OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11440|回复: 10

GIF解码

[复制链接]

3

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2012-9-11
在线时间
4 小时
发表于 2012-9-24 16:05:46 | 显示全部楼层 |阅读模式
STM32F103RB解码GIF实现了,消耗RAM大约15K。现在就是解码速度跟不上,就像放慢动作。有的会看到明显的刷屏现象。请问大家有什么好的解决办法?
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

26

主题

193

帖子

8

精华

金牌会员

Rank: 6Rank: 6

积分
1800
金钱
1800
注册时间
2012-8-23
在线时间
57 小时
发表于 2013-5-7 14:28:58 | 显示全部楼层

STM32+SD卡+znFAT实现的GIF文件解码
回复 支持 1 反对 0

使用道具 举报

20

主题

562

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
670
金钱
670
注册时间
2012-2-28
在线时间
0 小时
发表于 2012-9-24 16:27:19 | 显示全部楼层
程序代码消耗15K,这么大??GIF解码的代码有这么长吗??
努力,前进。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-9-24 23:03:24 | 显示全部楼层
不知道你的GIF解码是自己实现的还是移植别人的?
我移植了ucGUI的,速度还行,对那些黑白GIF速度很快,但是全彩的就比较慢,而且尺寸大的画更慢。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2012-9-11
在线时间
4 小时
 楼主| 发表于 2012-9-25 09:26:24 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
自己写的。前后两帧差别很大的就会看到明显的刷屏,前后两帧差不多的看不到刷屏但明显感觉慢,就像慢放。
这个是不是读SD卡(SPI方式,没用DAM)有一部分原因?
我感觉代码没什么好优化的了,就是可以把一些频繁调用的函数定义为内联函数。
不知道你们是怎么实现的?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-9-25 10:00:35 | 显示全部楼层
回复【4楼】TYZZD:
---------------------------------
自己写的啊,呵呵,那确实花了不少功夫哦。
我是直接移植ucGUI的。
我记得ucGUI的GIF解码有个特点,就是可以一次清除一行数据(如果这些数据都是一样的话),这样可以大幅提高速度。尤其对于那些单色gif,可以做到很快
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2012-9-11
在线时间
4 小时
 楼主| 发表于 2012-9-25 10:17:35 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
再请问一个问题keil RealView MDK 函数加上__inline和不加,编译后代码长度都一样,是不是编译器没做内联化处理?
谢谢!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-9-25 12:56:35 | 显示全部楼层
你调用inline函数不多吧,调用多几次试试。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

260

主题

809

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1896
金钱
1896
注册时间
2012-10-28
在线时间
357 小时
发表于 2014-11-2 21:28:02 | 显示全部楼层
回复【8楼】beyond696:
---------------------------------
你好,请问这个解码gif 的程序能否提供参考一下啊 ?、

我现在搞的gif 解码程序(是修改znFAT,我这个程序也是在网上找的,具体已经不记得是哪个论坛了),
显示只有图片的1/3显示基本正常,目前不知道是什么情况造成的,

有哪位大侠帮我看看啊 ??? 小弟不胜感激!!

部分程序如下:

#define USE_SD_CARD 1 //若需要支持SD卡显示GIF文件则需要将该宏定义为1
#define USE_SD_BUFFER  1 //若需要开辟SD卡读数据缓冲区则将该宏定义为1




/**************************************************************************************************************
 * 函数名:GLCD_DrawHLine()
 * 输入  :uint16_t Xpos, uint16_t Ypos, uint16_t Length 起点X和Y坐标及长度
 * 输出  :void
 * 描述  :画水平线
 * 调用  :外部调用  
 * 调试OK
 * LCD控制器:ILI9486
 *****************************************************************************************************************/
void LCD_DrawHLine(uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint16_t Color)
{
uint32_t i = 0;
LCD_SetCursor(Xpos, Xpos+Length, Ypos, Ypos+Length);
for(i = 0; i < Length; i++)
{
LCD_RAM = Color;
}
}


static uint8_t _ReadU8(void) {
  uint8_t Value;
  _Source.RemBytes -= 1;
  if (_Source.RemBytes < 0) {
    return 0;
  }

//  --------------------- 2014-11-02 ---------------------
#if USE_SD_CARD
#if USE_SD_BUFFER
  if(ReceiveDataNum<=0)
{
// br = znFAT_ReadData(&FileInfo,FileInfo.File_CurOffset,4096,SD_Buffer);   ??????
//   ReceiveDataNum += br;

// f_lseek(&pic_fsrc, pic_fsrc.fsize); // f_size(&pic_fsrc) ????????????????????????????
f_read(&pic_fsrc, SD_Buffer, 4096, &pic_br);

  ReceiveDataNum += pic_br;
  ReadDataNum = 0;
  }
  ReceiveDataNum--;//缓冲区剩下的数据字节数减1
  Value = SD_Buffer[ReadDataNum++]; //返回缓冲区的数据,同时将已读数据数加1 
#else
// znFAT_ReadData(&FileInfo,FileInfo.File_CurOffset,1,&Value);
f_read(&pic_fsrc, SD_Buffer, 1, &pic_br);
#endif
#else
  Value = *(_Source.pSrc++);
#endif

  return Value;
}

static uint16_t _ReadU16(void) {
  uint16_t Value;
  uint8_t Byte0, Byte1;
  Byte0 = _ReadU8();
  Byte1 = _ReadU8();
  Value = (Byte1 << 8) | Byte0;
  return Value;
}

static void _ReadBytes(uint8_t * pBuffer, int Len) {

UINT br = 0;

#if USE_SD_BUFFER
  int NeedDataNum;
#endif
  if (_Source.RemBytes < 0) {
    return;
  }
  if (_Source.RemBytes < Len) {
    Len = _Source.RemBytes;
    return;
  }
  _Source.RemBytes -= Len;
#if USE_SD_CARD
#if USE_SD_BUFFER
  if(ReceiveDataNum<Len){
   NeedDataNum = Len - ReceiveDataNum;
   for(;ReceiveDataNum>0;ReceiveDataNum--){
  *pBuffer++ = SD_Buffer[ReadDataNum++];
}

// br = znFAT_ReadData(&FileInfo,FileInfo.File_CurOffset,NeedDataNum,pBuffer); //????????????
// br = znFAT_ReadData(&FileInfo,FileInfo.File_CurOffset,4096,SD_Buffer);
// ReceiveDataNum += br;

// f_lseek(&pic_fsrc, pic_fsrc.fsize ); //f_size(&pic_fsrc) ?????????????????????
f_read(&pic_fsrc, pBuffer, NeedDataNum, &br);
f_read(&pic_fsrc, SD_Buffer, 4096, &br);

ReceiveDataNum += br;
ReadDataNum = 0;
  }else{
    for(;Len>0;Len--,ReceiveDataNum--){
*pBuffer++ = SD_Buffer[ReadDataNum++];
}
  }
#else
// znFAT_ReadData(&FileInfo,FileInfo.File_CurOffset,Len,pBuffer);

f_read(&pic_fsrc, pBuffer, Len, &br);
#endif  
#else
  memcpy(pBuffer, _Source.pSrc, Len);
  _Source.pSrc += Len;
#endif
}


static void _SkipBytes(int Len) {
  if (_Source.RemBytes < 0) {
    return;
  }
  if (_Source.RemBytes < Len) {
    Len = _Source.RemBytes;
    return;
  }
  _Source.RemBytes -= Len;
#if USE_SD_CARD
#if USE_SD_BUFFER
  if(ReceiveDataNum>=Len){
   ReceiveDataNum -= Len;
ReadDataNum += Len;
  }else{
// znFAT_Seek(&FileInfo,FileInfo.File_CurOffset + Len-ReceiveDataNum);
f_lseek(&pic_fsrc, pic_fsrc.fsize  + Len - ReceiveDataNum);
   ReceiveDataNum = 0;
ReadDataNum = 0;
  }
#else
// znFAT_Seek(&FileInfo,FileInfo.File_CurOffset + Len);

f_lseek(&pic_fsrc, pic_fsrc.fsize  + Len);
#endif
#else
  _Source.pSrc += Len;
#endif
}


static int _GetDataBlock(uint8_t * pBuffer) {
  uint8_t Count;
  Count = _ReadU8(); /* Read the length of the data block */
  if (Count) {
    if (pBuffer) {
      _ReadBytes(pBuffer, Count);
    } else {
#if USE_SD_CARD
#if USE_SD_BUFFER
  if(ReceiveDataNum>=Count){
   ReceiveDataNum -= Count;
ReadDataNum += Count;
  }else{
// znFAT_Seek(&FileInfo,FileInfo.File_CurOffset + Count-ReceiveDataNum);
f_lseek(&pic_fsrc, pic_fsrc.fsize + Count - ReceiveDataNum);
   ReceiveDataNum = 0;
ReadDataNum = 0;
  }
#else
// znFAT_Seek(&FileInfo,FileInfo.File_CurOffset + Count);

f_lseek(&pic_fsrc, pic_fsrc.fsize + Count);
#endif
#else
      _Source.pSrc += Count;
#endif
    }
  }
  return((int)Count);
}


 static int _DispGIFImage(IMAGE_DESCRIPTOR * pDescriptor, int x0, int y0, int Transparency, int Disposal) {
  int Codesize, Index, OldIndex, XPos, YPos, YCnt, ass, Interlace, XEnd;
  int Width, Height, NumColors, Cnt, BkColorIndex, ColorIndex,TransparencyCnt=0;
  const LCD_PIXELINDEX * pTrans;
  Width     = pDescriptor->XSize;
  Height    = pDescriptor->YSize;
  NumColors = pDescriptor->NumColors;
  XEnd      = Width + x0 - 1;
  BkColorIndex = BLACK;
pTrans = _aColorTable;//获取颜色索引表首地址
  Codesize  = _ReadU8();                 /* Read the LZW codesize */
  _InitLZW(Codesize);                    /* Initialize the LZW stack with the LZW codesize */
  Interlace = pDescriptor->Flags & 0x40; /* Evaluate if image is interlaced */
 
 
  if (Interlace){ //图像是交织排列的
  for (YCnt = 0, YPos = y0, ass = 0; YCnt < Height; YCnt++) {
    Cnt      = 0;
    OldIndex = -1;    
    for (XPos = x0; XPos <= XEnd; XPos++) {
      if (_LZWContext.sp > _LZWContext.aDecompBuffer) {
        Index = *--(_LZWContext.sp);
      } else {
        Index = _GetNextByte();
      }
      if (Index == -2) {
        return 0; // End code 
      }
      if ((Index < 0) || (Index >= NumColors)) {
        // If Index out of legal range stop decompressing 
        //while(1);
return 1; // Error 
      }
      // If current index equals old index increment counter 
      if ((Index == OldIndex) && (XPos <= XEnd)) {
        Cnt++;
      } else {
        if (Cnt) {
          if (OldIndex != Transparency) {
//             LCD_SetColorIndex(*(pTrans + OldIndex));
//             ARC_LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1);

LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1, *(pTrans + OldIndex));
          } else if (Disposal == 2) {
//             LCD_SetColorIndex(BkColorIndex);
//             ARC_LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1);

LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1, BkColorIndex);
          }
          Cnt = 0;
        } else {
          if (OldIndex >= 0) {
            if (OldIndex != Transparency) {
//               ARC_LCD_SetPixelIndex(XPos - 1, YPos, *(pTrans + OldIndex));

LCD_SetPoint(XPos - 1, YPos, *(pTrans + OldIndex));
            } else if (Disposal == 2) {
//               ARC_LCD_SetPixelIndex(XPos - 1, YPos, BkColorIndex);

LCD_SetPoint(XPos - 1, YPos, BkColorIndex);
            }
          }
        }
      }
      OldIndex = Index;
    }
    if ((OldIndex != Transparency) || (Disposal == 2)) {
      if (OldIndex != Transparency) {
        ColorIndex = *(pTrans + OldIndex);
      } else {
        ColorIndex = BkColorIndex;
      }
      if (Cnt) {
//         LCD_SetColorIndex(ColorIndex);
//         ARC_LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1);

LCD_DrawHLine(XPos - Cnt - 1, YPos, XPos - 1, ColorIndex);
      } else {
//         ARC_LCD_SetPixelIndex(XEnd, YPos, ColorIndex);

LCD_SetPoint(XEnd, YPos, ColorIndex);
      }
    }
    // Adjust YPos if image is interlaced 
    if (Interlace) {
      YPos += _aInterlaceOffset[Pass];
      if ((YPos - y0) >= Height) {
        ++Pass;
        YPos = _aInterlaceYPos[Pass] + y0;
      }
    } else {
      YPos++;
    }
  }
  }



else
{  //图像是连续排列
// ARC_LCD_SetDisplayWindow(x0,y0,XEnd,y0+Height-1);

LCD_SetCursor(x0, XEnd, y0, y0 + Height-1);

  for (YCnt = 0, YPos = y0, ass = 0; YCnt < Height; YCnt++) {
    Cnt      = 0;
    OldIndex = -1;    
    for (XPos = x0; XPos <= XEnd; XPos++) {
      if (_LZWContext.sp > _LZWContext.aDecompBuffer) {
        Index = *--(_LZWContext.sp);
      } else {
        Index = _GetNextByte();
      }
      if (Index == -2) {
        return 0; // End code 
      }
      if ((Index < 0) || (Index >= NumColors)) {
        // If Index out of legal range stop decompressing 
        //while(1); //有的GIF图片会进入到这里,从而不能显示图片,Index==-1,原因待定
return 1; // Error 
      }
if(Index>=0){
if (Index != Transparency){
if(TransparencyCnt){

/*
#if (MAX_X == 480) && (MAX_Y == 320)
// ARC_LCD_WriteReg(LCD_REG_4EH, YPos); //ssd1289/ssd1298 起始地址
// ARC_LCD_WriteReg(LCD_REG_4FH, XPos);

LCD_WriteIndex(0x2b); 
LCD_WriteData((u16)((319-YPos)>>8));  //起始地址
LCD_WriteData((u16)((319-YPos)&0x00FF));

LCD_WriteData((319-YPos)>>8); //结束地址
LCD_WriteData((319-YPos)&0x00FF);

LCD_WriteIndex(0x2a); 
LCD_WriteData(XPos>>8);   //起始地址
LCD_WriteData(XPos&0X00FF);

LCD_WriteData((XPos)>>8); //结束地址
LCD_WriteData((XPos)&0XFF);

#else
// ARC_LCD_WriteReg(LCD_REG_4EH, XPos);
// ARC_LCD_WriteReg(LCD_REG_4FH, YPos);

LCD_WriteIndex(0x2b); 
LCD_WriteData(YPos>>8);   //起始地址
LCD_WriteData(YPos&0X00FF);

LCD_WriteData((YPos)>>8); //结束地址
LCD_WriteData((YPos)&0XFF);

LCD_WriteIndex(0x2a); 
LCD_WriteData((u16)((XPos)>>8));    //起始地址
LCD_WriteData((u16)((XPos)&0x00FF));

LCD_WriteData((XPos)>>8); //结束地址
LCD_WriteData((XPos)&0x00FF);

#endif
TransparencyCnt = 0;
// LCD_REG = LCD_REG_22H; //ssd1289/ssd1298 LCD控制器使用的显示控制 命令
// LCD_WriteRAM_Start();
*/
}

LCD_RAM = *(pTrans + Index);
}else if (Disposal == 2){
if(TransparencyCnt){
/*

#if (MAX_X == 480) && (MAX_Y == 320)
// ARC_LCD_WriteReg(LCD_REG_4EH, YPos);
// ARC_LCD_WriteReg(LCD_REG_4FH, XPos);

LCD_WriteIndex(0x2b); 
LCD_WriteData((u16)((319-YPos)>>8));  //起始地址
LCD_WriteData((u16)((319-YPos)&0x00FF));

LCD_WriteData((319-YPos)>>8); //结束地址
LCD_WriteData((319-YPos)&0x00FF);

LCD_WriteIndex(0x2a); 
LCD_WriteData(XPos>>8);   //起始地址
LCD_WriteData(XPos&0X00FF);

LCD_WriteData((XPos)>>8); //结束地址
LCD_WriteData((XPos)&0XFF);
#else
// ARC_LCD_WriteReg(LCD_REG_4EH, XPos);
// ARC_LCD_WriteReg(LCD_REG_4FH, YPos);

LCD_WriteIndex(0x2b); 
LCD_WriteData(YPos>>8);   //起始地址
LCD_WriteData(YPos&0X00FF);

LCD_WriteData((YPos)>>8); //结束地址
LCD_WriteData((YPos)&0XFF);

LCD_WriteIndex(0x2a); 
LCD_WriteData((u16)((XPos)>>8));    //起始地址
LCD_WriteData((u16)((XPos)&0x00FF));

LCD_WriteData((XPos)>>8); //结束地址
LCD_WriteData((XPos)&0x00FF);
#endif
TransparencyCnt = 0;
// LCD_REG = LCD_REG_22H;
// LCD_WriteRAM_Start();
*/
}

LCD_RAM = BkColorIndex;
 }else{//颜色为透明色,也就是不需要在LCD的这个点输出颜色,但是内部地址需要递增
TransparencyCnt++;
}
}
}
YPos++;
}
  }

  return 0;
}
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
2
金钱
2
注册时间
2018-9-7
在线时间
0 小时
发表于 2018-9-7 17:34:31 | 显示全部楼层
103的,哪怕勇士fsmc也很难播放动画,速度太慢了,主频72M,spi才18M
回复 支持 反对

使用道具 举报

5

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2018-8-1
在线时间
52 小时
发表于 2019-9-16 15:37:26 | 显示全部楼层
hpdell 发表于 2014-11-2 21:28
回复【8楼】beyond696:
---------------------------------
你好,请问这个解码gif&nbsp;的程序能否提供参 ...

你好,这个问题解决了吗,程序能否提供下,不甚感激
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 20:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表