我是靠谱客的博主 专注铃铛,最近开发中收集的这篇文章主要介绍用fvb在Framebuffer中显示GIF动画fbv (v1.0b)、Framebuffer简介,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

用fvb在Framebuffer中显示GIF动画

  • fbv (v1.0b)、Framebuffer简介
    • fvb显示GIF为所有帧叠加的一张图像
    • 找找fvb不能正常显示GIF动画的问题
      • fbv显示图像文件的流程:
      • fbv读取GIF文件的过程:
    • 想想办法让GIF动画正常显示
      • 按照show_image()中的流程是行不通了
    • 为什么显示GIF动画过程,画面有些奇怪的小点点出现,还有残影???!!!

fbv (v1.0b)、Framebuffer简介

fbv是一个简单的图像文件显示程序,可以用来在Framebuffer中显示GIF、JPEG、PNG 和BMP文件图像。
Framebuffer,可看作显示屏像素点的抽象。

fvb显示GIF为所有帧叠加的一张图像

如果直接将下载编译后的fbv打开GIF文件,显示的是GIF文件所有帧叠加的一张图像,而非按照一帧一帧的图像显示为动画。

找找fvb不能正常显示GIF动画的问题

fbv显示图像文件的流程:

main.c中,定位到show_image(char * filename) ,看到显示图像文件时,都是分别调用

load = fh_gif_load;
load = fh_png_load;

等把图像文件的图像解析到image
unsigned char * image = NULL;
指针中,然后再链接到 struct image i 的 rgb ,
i.rgb = image;
接下来调用了fb_display
fb_display(i.rgb, i.alpha, i.width, i.height, x_pan, y_pan, x_offs, y_offs);
进行显示,然后就退出了。。。出了。。。了

也就是说,在fbv中一个图像文件只有一次显示到framebuffer的机会。

fbv读取GIF文件的过程:

看看fh_gif_load的内容,在gif.c中。fbv解析GIF文件用的是giflib

#include <gif_lib.h>
int fh_gif_load(char *name,unsigned char *buffer, unsigned char ** alpha, int x,int y)

使用giflib解析GIF我参考的是 https://blog.csdn.net/go_to_learn/article/details/8070742 ,跟fbv里的解析略有不同。
整个解析流程就是连续读取GIF文件,处理一遍,像素索引转换为RGB存到 传入的指针 buffer里,透明色则在申请到的一段内存进行保存,并将指针存到alpha地址指针中。

想想办法让GIF动画正常显示

按照show_image()中的流程是行不通了

#ifdef FBV_SUPPORT_GIF
if(fh_gif_id(filename))
if(fh_gif_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)
{
load = fh_gif_load;
goto identified;
}
#endif

那么加入自己的处理流程 gif_display(char * filename):

#ifdef FBV_SUPPORT_GIF
if(fh_gif_id(filename))
if(fh_gif_getsize(filename, &x_size, &y_size) == FH_ERROR_OK)
{
// load = fh_gif_load;
// goto identified;
gif_display(filename);
printf("exitn");
exit(0);
}
#endif

代码参考了上面提到的微博,处理GIF文件的过程:
case IMAGE_DESC_RECORD_TYPE中先读出一帧的颜色索引值,然后按照ColorMap解析成RGB像素,代码参照DumpScreen2RGBA(),注意微博中的DumpScreen2RGBA()中解析RGB的字节顺序可能是不对的。
接着是解析透明色alpha,参照DumpScreen2RGBA()修改一个:

static void GetAlpha(unsigned char * alpha_buffer , GifRowType * ScreenBuffer , int ScreenWidth, int ScreenHeight,int alphaColorIndex){
int i, j;
GifRowType GifRow;
static GifColorType *ColorMapEntry;
unsigned char *BufferP;
for (i = 0; i < ScreenHeight; i++) {
GifRow = ScreenBuffer[i];
BufferP = alpha_buffer + i * (ScreenWidth);
for (j = 0; j < ScreenWidth; j++) {
*BufferP++ = (alphaColorIndex ==GifRow[j])?0x00: 0xff;
}
}
}

读取完RGB ,alpha 数据后,将数据跟其他参数存到struct image im,再调用fb_display进行显示。
完成显示后继续处理下一帧。

case EXTENSION_RECORD_TYPE中主要处理的是透明色和延时


if(extcode==0xf9) //look image transparency in graph ctr extension
{
if(extension[1] & 1)
{
//透明色获取
transparency = extension[4];
}else{
transparency = -1;
}
if(extension[0] == 4){
unsigned long usec;
usec = (extension[3] << 8 | extension[2]) * 10*1000;
//延时处理
usleep(usec);
printf("Delay msec %d n",usec/1000);
}
}

按这么处理,理论上就可以正常显示GIF动画了。。。。吧

为什么显示GIF动画过程,画面有些奇怪的小点点出现,还有残影???!!!

为啥?我也只能靠猜,靠着printf打印信息出来判断。。。

还好,print还差个f,想到了:透明色处理可能有问题。

第一帧图像是没问题的。
如果把透明色去掉,GIF动画过程会出现越来越多的奇怪的点;残影则像是贴图错位。

来到fb_display.c,看看

void fb_display(unsigned char *rgbbuff, unsigned char * alpha,
int x_size, int y_size, int x_pan, int y_pan,
int x_offs, int y_offs){
...
/* blit buffer 2 fb */
fbbuff = convertRGB2FB(fh, rgbbuff, x_size * y_size, var.bits_per_pixel, &bp);
...
blit2FB(fh, fbbuff, alpha, x_size, y_size, x_stride, var.yres_virtual, x_pan, y_pan, x_offs, y_offs + var.yoffset, bp);
...
}

看看convertRGB2FB()代码,用来将RGB数据转换为framebuff要传输的像素格式数据。

看看blit2FB()代码,把转换后的像素数据填充到framebuff中,涉及到了透明色alpha的处理,那么就是它了。

没有透明色要处理的时候,把数据直接一行行的填进去:

for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp)
memcpy(fbptr, imptr, xc * cpp);

有透明色要处理的时候:


unsigned char * alphaptr;
int from, to, x;
alphaptr = alpha + (yp	* pic_xs + xp);
for(i = 0; i < yc; i++, fbptr += scr_xs * cpp, imptr += pic_xs * cpp, alphaptr += pic_xs)
{
for(x = 0; x<xc; x++)
{
int v;
from = to = -1;
for(v = x; v<xc; v++)
{
if(from == -1)
{
if(alphaptr[v] > 0x80) from = v;
}
else
{
if(alphaptr[v] < 0x80)
{
to = v;
break;
}
}
}
if(from == -1)
break;
if(to == -1) to = xc;
memcpy(fbptr + (from * cpp), imptr + (from * cpp), (to - from - 1) * cpp);
x += to - from - 1;
}
}

看着有点绕,就是按行处理,每行记录不透明的起始位置 from:
if(alphaptr[v] > 0x80) from = v;
和结束位置to:


if(alphaptr[v] < 0x80)
{
to = v;
break;
},
...
if(to == -1) to = xc;

然后用图像像素数据填充from to之间的framebuffer。

想想就能知道这么处理的问题了,就是每一行有多段透明,非透明存在,造成部分数据少填充。
解决的办法也简单,按像素处理,稍微会慢一点(就代码处理的感觉上。。。):

	if(alpha)
{
int w ,h ;
unsigned char * alphaptr;
int pos;
alphaptr = alpha + (yp	* pic_xs + xp);
printf("writing fbn");
for( h = 0 ; h< yc
; h++ ,fbptr += scr_xs * cpp, imptr += pic_xs * cpp,alphaptr+=pic_xs){
for(w = 0 ; w< xc ; w++){
if(alphaptr[w]>0x80){
memcpy(fbptr+w * cpp , imptr+w * cpp,cpp);
}
}
}
}

好了,终于正常显示GIF动画了。

最后

以上就是专注铃铛为你收集整理的用fvb在Framebuffer中显示GIF动画fbv (v1.0b)、Framebuffer简介的全部内容,希望文章能够帮你解决用fvb在Framebuffer中显示GIF动画fbv (v1.0b)、Framebuffer简介所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部