GifLib 基础示例
源码位置: samples/media/giflib 查看源码
功能说明
演示如何使用 GifLib 库解析 GIF 文件。本示例展示了如何从内存中读取 GIF 数据、解析 GIF 文件结构、获取 GIF 信息和图像帧信息,以及解析扩展块(如图形控制扩展块)。
GifLib 是一个用于操作 GIF 文件的 C 语言库,支持读取 GIF 文件并将其转换为 RGB 位图,也支持将 RGB 位图写入为 GIF 文件。
硬件连接
无需外部连接,GifLib 为纯软件 GIF 处理库。
示例内容
定义内置的测试 GIF 数据(1x1 像素的简单 GIF,包含黑白两色)
实现自定义内存读取函数
memory_read_func使用
DGifOpen()打开 GIF 文件(使用自定义读取函数从内存读取)使用
DGifSlurp()解析整个 GIF 文件内容打印 GIF 基本信息:
逻辑屏幕宽度和高度
颜色分辨率
背景色索引
图像总数
全局调色板信息(颜色数、BitsPerPixel、颜色值)
遍历所有图像帧,打印每帧信息:
图像位置(左上角坐标)
图像宽度和高度
交错标志
局部调色板信息
扩展块信息(功能码、大小)
图形控制扩展块详细信息(处理方式、用户输入、透明度、延迟时间)
使用
DGifCloseFile()关闭 GIF 文件
编译
重要提示:在编译前,请先确认您使用的开发板型号。SDK 目前支持以下开发板:
arcs_evb - ARCS EVB 评估板
arcs_mini - ARCS Mini 开发板
根据您的开发板型号,选择对应的编译命令:
在示例目录下执行编译:
# 使用 arcs_evb 开发板
./build.sh -C -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -DBOARD=arcs_mini
Note
如果在 SDK 根目录执行,需要指定示例路径:
# 使用 arcs_evb 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_mini
Note
确保已安装对应的工具链。
烧录
编译完成后,使用 SDK tools 目录下的 cskburn 工具烧录固件:
./tools/burn/cskburn -s /dev/ttyUSB0 -b 3000000 0x0 build/arcs.bin -C arcs
Note
烧录参数说明:
-s /dev/ttyUSB0:串口设备路径,需要根据实际情况修改 - Linux 系统:通常是/dev/ttyUSB0或/dev/ttyACM0- 可通过ls /dev/tty*命令查看可用串口设备 - 不同开发板或 USB 转串口芯片可能使用不同的设备名-b 3000000:烧录波特率(3Mbps)0x0:烧录起始地址build/arcs.bin:编译生成的固件路径-C arcs:芯片类型
注意事项:
确保开发板已正确连接到电脑
如果无法识别串口设备,请检查 USB 连接线是否正常,或尝试其他 USB 端口
预期输出
********Arcs SDK 0.1.0 @ v0.0.23.temp.docs-96-gf56c5084660d********
Running on hart-id: 1
I/elog [1034:42:44.159 1 elog_async] EasyLogger V2.2.99 is initialize success.
[I][sample] 正在打开GIF数据
[I][sample] 正在解析GIF数据
[I][sample] GIF信息
[I][sample] 宽度: 1
[I][sample] 高度: 1
[I][sample] 颜色分辨率: 1
[I][sample] 背景色索引: 0
[I][sample] 图像总数: 1
[I][sample] 全局调色板
[I][sample] 颜色数: 2
[I][sample] BitsPerPixel: 1
[I][sample] 颜色#0: RGB(0, 0, 0)
[I][sample] 颜色#1: RGB(255, 255, 255)
[I][sample] GIF包含 1 个图像
[I][sample] 图像 #0
[I][sample] 帧信息
[I][sample] 左上角: (0, 0)
[I][sample] 宽度: 1
[I][sample] 高度: 1
[I][sample] 交错: 否
[I][sample] 无局部调色板
[I][sample] GifLib sample completed successfully
说明:
输出开头包含系统启动信息和日志系统初始化信息
示例使用内置的 1x1 像素 GIF 数据,包含黑白两色
GIF 信息包括逻辑屏幕尺寸、颜色分辨率、背景色、图像数量和调色板信息
图像帧信息包括位置、尺寸、交错标志和调色板信息
如果 GIF 包含图形控制扩展块,会显示处理方式、透明度、延迟时间等信息
核心 API
API |
说明 |
|---|---|
|
打开 GIF 文件(支持自定义读取函数) |
|
解析整个 GIF 文件内容到内存 |
|
关闭 GIF 文件并释放资源 |
|
将错误代码转换为错误描述字符串 |
关键代码
// 自定义内存读取函数
typedef struct {
const unsigned char *data;
size_t size;
size_t pos;
} MemoryBuffer;
int memory_read_func(GifFileType *gif, GifByteType *buf, int len) {
MemoryBuffer *buffer = (MemoryBuffer *)gif->UserData;
if (buffer->pos >= buffer->size) {
return 0;
}
int remaining = buffer->size - buffer->pos;
int read_size = (remaining < len) ? remaining : len;
memcpy(buf, buffer->data + buffer->pos, read_size);
buffer->pos += read_size;
return read_size;
}
// 打开 GIF 文件
MemoryBuffer buffer = {
.data = sample_gif,
.size = sizeof(sample_gif),
.pos = 0
};
int error = 0;
GifFileType *gif = DGifOpen(&buffer, memory_read_func, &error);
if (!gif) {
LOGI("无法打开GIF: %s", GifErrorString(error));
return 1;
}
// 解析 GIF 内容
if (DGifSlurp(gif) != GIF_OK) {
LOGI("无法读取GIF内容: %s", GifErrorString(gif->Error));
DGifCloseFile(gif, &error);
return 1;
}
// 访问 GIF 信息
LOGI("宽度: %d", gif->SWidth);
LOGI("高度: %d", gif->SHeight);
LOGI("图像总数: %d", gif->ImageCount);
// 访问全局调色板
if (gif->SColorMap) {
LOGI("颜色数: %d", gif->SColorMap->ColorCount);
for (int i = 0; i < gif->SColorMap->ColorCount; i++) {
GifColorType color = gif->SColorMap->Colors[i];
LOGI("颜色#%d: RGB(%d, %d, %d)", i, color.Red, color.Green, color.Blue);
}
}
// 遍历所有图像帧
for (int i = 0; i < gif->ImageCount; i++) {
SavedImage *image = &gif->SavedImages[i];
LOGI("图像 #%d", i);
LOGI(" 宽度: %d", image->ImageDesc.Width);
LOGI(" 高度: %d", image->ImageDesc.Height);
// 访问扩展块
for (int j = 0; j < image->ExtensionBlockCount; j++) {
ExtensionBlock *ext = &image->ExtensionBlocks[j];
if (ext->Function == GRAPHICS_EXT_FUNC_CODE) {
// 解析图形控制扩展块
int delay = ext->Bytes[1] | (ext->Bytes[2] << 8);
LOGI(" 延迟时间: %d/100秒", delay);
}
}
}
// 关闭 GIF 文件
if (DGifCloseFile(gif, &error) != GIF_OK) {
LOGI("关闭GIF文件时出错: %s", GifErrorString(error));
return 1;
}
GIF 数据结构说明
GifFileType 结构
GIF 文件的主要结构,包含以下重要字段:
SWidth,SHeight: 逻辑屏幕宽度和高度SColorResolution: 颜色分辨率(位数)SBackGroundColor: 背景色索引ImageCount: 图像帧数量SColorMap: 全局调色板指针SavedImages: 保存的图像数组
SavedImage 结构
每个图像帧的信息:
ImageDesc: 图像描述符(位置、尺寸、交错标志等)RasterBits: 图像像素数据ExtensionBlocks: 扩展块数组ExtensionBlockCount: 扩展块数量
扩展块类型
GRAPHICS_EXT_FUNC_CODE: 图形控制扩展块,包含处理方式、透明度、延迟时间等信息COMMENT_EXT_FUNC_CODE: 注释扩展块PLAIN_TEXT_EXT_FUNC_CODE: 纯文本扩展块APPLICATION_EXT_FUNC_CODE: 应用程序扩展块
配置说明
必需配置
CONFIG_SDK_MODULE_GIFLIB=y: 启用 GifLib 模块
可选配置
CONFIG_MEM_CONFIG=y: 启用内存配置(如果需要)
注意事项
内存读取函数: 使用
DGifOpen()时,可以提供自定义读取函数从内存、网络或其他数据源读取 GIF 数据,而不是从文件系统读取错误处理: 所有 GifLib API 在失败时会设置错误代码,使用
GifErrorString()可以获取可读的错误描述资源管理: 使用
DGifOpen()打开 GIF 后,必须使用DGifCloseFile()关闭并释放资源DGifSlurp 使用:
DGifSlurp()会将整个 GIF 文件解析到内存中,适合处理较小的 GIF 文件;对于大文件,可能需要使用流式读取方式调色板访问: 图像可以使用全局调色板(
gif->SColorMap)或局部调色板(image->ImageDesc.ColorMap),访问前应检查指针是否为 NULL扩展块解析: 扩展块的数据格式取决于功能码,图形控制扩展块(
GRAPHICS_EXT_FUNC_CODE)的格式是固定的,其他扩展块格式可能不同像素数据:
SavedImage->RasterBits包含解码后的像素数据,每个像素是一个索引值,需要通过调色板转换为 RGB 颜色交错图像: 如果
ImageDesc.Interlace为真,图像是交错存储的,需要按照 GIF 规范的交错顺序进行解码