#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, ¤t_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 } }