|
|
#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
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|