You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
6.6 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "ALLinclude.h"
#define GIF_MAX_FRAME_SIZE (80 * 160) // 假设每帧最大80x160像素
#define GIF_FRAME_COUNT 10 // 假设GIF有10帧
#define LZW_MAX_DICT_SIZE 4096 // LZW字典最大大小
#define SCREEN_WIDTH 80
#define SCREEN_HEIGHT 160
#define MAX_COLORS 64
#define LZW_DICT_SIZE 1024
#define RGB888_TO_RGB565(r, g, b) \
((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
// GIF全局色彩表的定义最多支持256种颜色每种颜色3字节RGB
uint8_t global_color_table[256][3];
// 每一帧的图像数据存放
uint8_t frame_buffer[GIF_MAX_FRAME_SIZE];
// GIF文件解析结构
typedef struct {
uint16_t width;
uint16_t height;
uint8_t global_color_table_flag;
uint8_t global_color_table_size;
uint8_t background_color_index;
uint8_t pixel_aspect_ratio;
const uint8_t *data; // 存储GIF的原始数据
uint32_t offset; // 当前解析的位置
} GIFFile;
// LZW解码字典结构
typedef struct {
uint16_t code_size;
uint16_t dictionary[LZW_MAX_DICT_SIZE][2]; // LZW字典
uint16_t next_code;
} LZWDecoder;
// 解析GIF的全局色彩表
void parseGlobalColorTable(const uint8_t* gif_data, uint16_t color_table_size) {
for (uint16_t i = 0; i < color_table_size; i++) {
global_color_table[i][0] = gif_data[i * 3];
global_color_table[i][1] = gif_data[i * 3 + 1];
global_color_table[i][2] = gif_data[i * 3 + 2];
#if DebugPrintEnable == 1
printf("Color %d: R=%d, G=%d, B=%d\n", i, global_color_table[i][0], global_color_table[i][1], global_color_table[i][2]); // Debug print
#endif
}
}
// 读取GIF的头部信息并初始化GIFFile结构体
void readGIFHeader(GIFFile* gif_file, const uint8_t *gif_address) {
const uint8_t* gif_data = gif_address;
gif_file->data = gif_data;
gif_file->width = gif_data[6] | (gif_data[7] << 8); // 解析宽度 (小端字节序)
gif_file->height = gif_data[8] | (gif_data[9] << 8); // 解析高度 (小端字节序)
#if DebugPrintEnable == 1
printf("GIF Header: Width = %d, Height = %d\n", gif_file->width, gif_file->height);
#endif
gif_file->global_color_table_flag = (gif_data[10] & 0x80) >> 7;
gif_file->global_color_table_size = 2 << (gif_data[10] & 0x07); // 获取色彩表大小
gif_file->background_color_index = gif_data[11];
gif_file->pixel_aspect_ratio = gif_data[12];
gif_file->offset = 13;
if (gif_file->global_color_table_flag) {
const uint8_t* color_table_data = gif_address + gif_file->offset;
parseGlobalColorTable(color_table_data, gif_file->global_color_table_size);
gif_file->offset += gif_file->global_color_table_size * 3;
}
}
// LZW解码函数
void LZWInit(LZWDecoder* decoder, const uint8_t* gif_data, uint32_t* offset) {
decoder->code_size = gif_data[*offset];
(*offset)++;
decoder->next_code = 258;
memset(decoder->dictionary, 0, sizeof(decoder->dictionary));
#if DebugPrintEnable == 1
printf("LZW Decoder Initialized: Code size = %d\n", decoder->code_size);
#endif
}
// 解码LZW数据并填充frame_buffer
void LZWDecode(LZWDecoder* decoder, const uint8_t* gif_data, uint32_t* offset, uint8_t* frame_buffer) {
uint32_t current_code = 0, previous_code = 0;
uint8_t stack[GIF_MAX_FRAME_SIZE];
uint32_t stack_pointer = 0;
uint16_t code_size = decoder->code_size;
#if DebugPrintEnable == 1
printf("Starting LZW decoding...\n"); // 调试输出,开始解码
#endif
// LZW解码循环
while (1) {
current_code = gif_data[*offset];
(*offset)++;
stack[stack_pointer++] = current_code;
#if DebugPrintEnable == 1
printf("LZW Decode: Read code = 0x%02X\n", current_code);
#endif
if (current_code == 0xFF) break; // Assuming 0xFF marks the end of frame data
}
// 填充frame_buffer
for (uint32_t i = 0; i < stack_pointer; i++) {
frame_buffer[i] = stack[i];
}
#if DebugPrintEnable == 1
printf("Frame decoded, %d bytes filled into frame_buffer\n", stack_pointer);
#endif
}
// 解码每一帧GIF并显示
void decodeFrame(GIFFile* gif_file, uint32_t* current_offset) {
const uint8_t* gif_data = gif_file->data;
LZWDecoder decoder;
#if DebugPrintEnable == 1
if (gif_file == NULL) {
printf("Error: gif_file is NULL\n");
return;
}
if (gif_data == NULL) {
printf("Error: gif_data in gif_file is NULL\n");
return;
}
if (current_offset == NULL) {
printf("Error: current_offset is NULL\n");
return;
}
// printf("Decoding frame, current_offset = %u\n", *current_offset);
#endif
LZWInit(&decoder, gif_data, current_offset);
#if DebugPrintEnable == 1
printf("Decoding frame, current_offset = %u\n", *current_offset);
#endif
LZWDecode(&decoder, gif_data, current_offset, frame_buffer);
#if DebugPrintEnable == 1
printf("Frame decoded, current_offset = %u\n", *current_offset);
printf("First 10 bytes of frame_buffer: ");
for (int i = 0; i < 10; i++) {
printf("0x%02X ", frame_buffer[i]);
}
printf("\n");
#endif
}
// 显示解码后的图像帧
// 显示解码后的图像帧
void displayFrame(uint8_t* frame_data, const GIFFile* gif_file) {
LCD_Clear(WHITE); // 清空屏幕
for (int i = 0; i < GIF_MAX_FRAME_SIZE; i++) {
uint8_t color_idx = frame_data[i];
// 确保颜色索引不越界
uint8_t r,g,b;
if (color_idx < gif_file->global_color_table_size) {
r = global_color_table[color_idx][0];
g = global_color_table[color_idx][1];
b = global_color_table[color_idx][2];
// 显示该像素
uint16_t color = RGB888_TO_RGB565(r, g, b);
LCDSetPointColor(i % SCREEN_WIDTH, i / SCREEN_WIDTH, color);
}
#if DebugPrintEnable == 1
if (i < 10) { // Only print the first few for brevity
printf("Pixel %d: ColorIdx = %d, RGB = (%d, %d, %d)\n", i, color_idx, r, g, b);
}
#endif
}
#if DebugPrintEnable == 1
printf("Frame displayed\n");
#endif
}
// 显示GIF动画
void gif_play(void) {
uint32_t gif_data_address = 0x08010000;
uint32_t current_offset = 0;
GIFFile gif_file;
readGIFHeader(&gif_file, (const uint8_t*)&Loading_map[0]);
#if DebugPrintEnable == 1
printf("Starting GIF play\n");
#endif
for (int frame = 0; frame < GIF_FRAME_COUNT; frame++) {
decodeFrame(&gif_file, &current_offset);
displayFrame(frame_buffer, &gif_file); // 传递 gif_file 给 displayFrame
vTaskDelay(25);
#if DebugPrintEnable == 1
printf("Frame %d displayed, waiting for next frame\n", frame + 1);
#endif
}
}