imx6 内核启动后使用giflib播放gif开机动画流程
1、giflib交叉编译
首先要下载giflib的源码:https://sourceforge.net/projects/giflib/files/
使用交叉编译器编译出arm端可执行文件,
source /opt/fsl-imx-fb/4.1.15-2.0.0/environment-setup-cortexa9hf-neon-poky-linux-gnueabi
make
make PREFIX=$PWD/_install install
完成后在会在源码路径下的_install目录里安装编译后程序。
llixx@linux:~/workspace/lgmg_gif/giflib-5.2.2/_install$ tree
.
├── bin
│ ├── gif2rgb
│ ├── gifbuild
│ ├── gifclrmp
│ ├── giffix
│ ├── giftext
│ └── giftool
├── include
│ └── gif_lib.h
├── lib
│ ├── libgif.a
│ ├── libgif.so -> libgif.so.7
│ ├── libgif.so.7 -> libgif.so.7.2.0
│ └── libgif.so.7.2.0
└── share
└── man
└── man1
├── gif2rgb.xml
├── gifbuild.xml
├── gifclrmp.xml
├── giffix.xml
├── giflib.xml
├── giftext.xml
└── giftool.xml
2、编写播放gif图代码
新建源码文件夹boot_animation,将上步骤生成的libgif.a静态库和gif_lib.h头文件拷贝到此目录,并新建一个boot_animation.c源文件,内容如下:
#include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/fb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "gif_lib.h" struct fb_var_screeninfo vinfo; int fb = -1; unsigned int* framebuffer = NULL; // 清空 framebuffer 并填充为背景色 void clear_framebuffer(unsigned int bg_color) { int total_pixels = vinfo.yres_virtual * vinfo.xres_virtual; for (int i = 0; i < total_pixels; i++) { framebuffer[i] = bg_color; } } // 打开 framebuffer 设备 int open_framebuffer(const char* fb_device) { fb = open(fb_device, O_RDWR); if (fb == -1) { perror("Error opening framebuffer device"); return -1; } if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo)) { perror("Error reading variable information"); close(fb); return -1; } framebuffer = mmap(NULL, vinfo.yres_virtual * vinfo.xres_virtual * vinfo.bits_per_pixel / 8, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); if (framebuffer == MAP_FAILED) { perror("Error mapping framebuffer to memory"); close(fb); return -1; } return 0; } // 关闭 framebuffer 设备 void close_framebuffer() { if (framebuffer) { munmap(framebuffer, vinfo.yres_virtual * vinfo.xres_virtual * vinfo.bits_per_pixel / 8); } if (fb != -1) { close(fb); } } // 显示单个帧到 framebuffer void display_frame(GifFileType* gif, int frame_index) { SavedImage* frame = &gif->SavedImages[frame_index]; ColorMapObject* cmap = frame->ImageDesc.ColorMap ? frame->ImageDesc.ColorMap : gif->SColorMap; if (!cmap) { fprintf(stderr, "No color map found\n"); return; } // 获取透明色索引 int transparent_index = -1; for (int ext = 0; ext < frame->ExtensionBlockCount; ext++) { if (frame->ExtensionBlocks[ext].Function == GRAPHICS_EXT_FUNC_CODE) { GraphicsControlBlock gcb; DGifExtensionToGCB(frame->ExtensionBlocks[ext].ByteCount, frame->ExtensionBlocks[ext].Bytes, &gcb); transparent_index = gcb.TransparentColor; break; } } int width = frame->ImageDesc.Width; int height = frame->ImageDesc.Height; int x_offset = frame->ImageDesc.Left; int y_offset = frame->ImageDesc.Top; unsigned char* raster = frame->RasterBits; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { unsigned char color_index = raster[y * width + x]; if (color_index == transparent_index || color_index >= cmap->ColorCount) { continue; } GifColorType color = cmap->Colors[color_index]; unsigned int pixel = (color.Red << 16) | (color.Green << 8) | color.Blue; int fb_x = x + x_offset; int fb_y = y + y_offset; if (fb_x < vinfo.xres_virtual && fb_y < vinfo.yres_virtual) { framebuffer[fb_y * vinfo.xres_virtual + fb_x] = pixel; } } } } // 播放 GIF 动画 void play_gif(const char* gif_file) { int error; GifFileType* gif = DGifOpenFileName(gif_file, &error); if (gif == NULL) { fprintf(stderr, "Error opening GIF file: %d\n", error); return; } if (DGifSlurp(gif) == GIF_ERROR) { fprintf(stderr, "Error reading GIF file: %d\n", gif->Error); DGifCloseFile(gif, &error); return; } int num_frames = gif->ImageCount; int delay_time = 41; // 默认延迟时间,单位为 1/100 秒 // 清空 framebuffer 为背景色(如黑色) clear_framebuffer(0x000000); // 黑色背景 while (1) { for (int i = 0; i < num_frames; i++) { display_frame(gif, i); usleep(delay_time * 1000); // 延时,单位为微秒 } } DGifCloseFile(gif, &error); } // 主程序 int main(int argc, char *argv[]) { // 确保提供了 GIF 文件路径作为命令行参数 if (argc < 2) { fprintf(stderr, "Usage: %s <path_to_gif_file>\n", argv[0]); return -1; } const char* gif_file = argv[1]; // 获取传入的 GIF 文件路径 // 打开 framebuffer 设备 if (open_framebuffer("/dev/fb0") == -1) { return -1; } // 播放 GIF 动画 play_gif(gif_file); // 关闭 framebuffer 设备 close_framebuffer(); return 0; }
编写Makefile文件,内容如下:
# 编译器和链接器设置 # CC = gcc CFLAGS = -Wall -g # 启用调试信息,可以去掉 -g 如果不需要调试符号 LDFLAGS = -L. # 指定静态库所在目录,这里是当前目录 LIBS = -lgif # 指定链接的库名,这里是 giflib # 源文件和目标文件 SRC = boot_animation.c OBJ = $(SRC:.c=.o) EXEC = boot_animation # 默认目标 all: $(EXEC) # 编译目标 $(EXEC): $(OBJ) $(CC) $(OBJ) -o $(EXEC) $(LDFLAGS) $(LIBS) # 编译源文件为目标文件 %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ # 清理目标 clean: rm -f $(OBJ) $(EXEC)
完成后make编译,生成boot_animation可执行程序,拷贝到目标版中运行可显示gif图片了。

浙公网安备 33010602011771号