你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【安富莱STemWin教程】第12章 JEPG图片显示

[复制链接]
baiyongbin2009 发布时间:2015-1-14 17:07
本帖最后由 baiyongbin2009 于 2015-1-14 17:10 编辑

特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第12章      JEPG图片显示

    本期主要讲emWin支持的JPEG图片的显示,官方支持的主要有两种显示方法,一种是从外部存储器读取数据到内部存储器后,再显示图片,这种的显示速度要快些。另一种方法是直接从外部存储器读取数据并显示,这种办法的好处就是不要大的RAM需求,每次读取一些数据显示一次,坏处就是显示速度比较的慢。
    由于官方提供的JPEG的显示方法比较耗RAM,这里将2MB的外部SRAM做为emWin的动态内存。
    12. 1  JPEG图片支持
    12. 2 绘制已经加载到存储器的JPEG图片
    12. 3 绘制无须加载到存储器的JPEG图片
    12. 4 实验总结

12.1  JPEG图片支持
    JPEG(读音为 “jay-peg”)是全彩和灰度图像的标准压缩方法。JPEG用于压缩 “真实世界”的景象、线条画、卡通,其他非现实图像并不是其强项。JPEG会有损耗,意指输出图像与输入图像并不完全相同。因此,如果您必须达到完全相同的输出位,则不能使用JPEG。不过,对于常见的照片图像,可以得到非常好的压缩级别,看不出变化。并且如果您能容忍低质量的图像,则可以实现相当高的压缩级别。
    这里有一点要特别的注意:出于法律原因,不得分发JPEG算术编码变体的代码。JPEG规范的算术编码选项似乎属于归IBM、AT&T和Mitsubishi所有的专利。因此,从法律上讲,如未获得一个或多个许可,则不能使用算术编码。因此,尚未包含对算术编码的支持。(由于算术编码相对于未获专利的Huffman模式仅具有限界收益,因此不太可能有太多实施支持它。)JPEG文件支持不包含提供标准中定义的层次式或无损流程。
12.1.1      JPEG格式图标转换
    某些情况下,将JPEG文件作为C文件添加到项目中非常有用。这时,首先需要将JPEG文件转换为C文件。使用emWin随附的工具Bin2C.exe可完成此任务。这个Bin2C.exe工具在STemWin软件包里面没有,需要到MDK安装目录里面找。下面我们下图JPEG格式的图片转换成C文件。
                12.1.jpg                
l  打开软件加载上面的图片
12.2.jpg

l  加载后点击Convert即可,点击后没有任何现象,直接去图片所在的文件夹找即可
12.3.jpg

    实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)
  2. {   
  3.    GUI_Init();
  4.    GUI_JPEG_Draw(_ac11, sizeof(_ac11), 0, 0);
  5.     while(1)
  6.     {
  7.        GUI_Delay(100);
  8.     }
  9. }
复制代码
    实际显示效果如下:
12..4.png

12.1.2      JPEG存储器方式显示
    为了区分上面将图片转换为C文件进行显示,这里将JPEG图片存入到外部SD卡等存储器中进行加载显示。
    首先要注意JPEG需要的动态内存大小,一般图片显示不出来往往是因为动态内存不够造成的。JPEG解压缩大约需要33 Kb RAM用于与图像大小无关的解压缩和依赖大小的字节量。RAM要求可按以下方式计算:
        App.大约RAM要求=图像的X大小* 80字节+ 33千字节
    依赖于X大小的量取决于JPEG文件的压缩类型。下表显示了部分示例:
12.5.png

    解压缩所需的存储器由emWin存储器管理系统动态分配。绘制JPEG图像后,将释放整个RAM。为了形象说明,下面举一个例子:比如要显示800*480的jpeg大约需要800*80 + 33k = 97k的内存,鉴于这种情况,这里把外部的2MB的SRAM做为动态内存, 使用前记得初始化SRAM,然后就是在GUIconf.c文件里面初始化一下。
    STemWin支持的JPEG函数如下:
12.6.png

收藏 评论10 发布时间:2015-1-14 17:07

举报

10个回答
baiyongbin2009 回答时间:2015-1-14 17:21:31
12.2  绘制已经加载到存储器的JPEG图片
    将图片加载到存储器后进行显示比较的耗内存,所以这里就使用开发板外置的2MB SRAM做STemWin的动态内存空间,并通过相应的API函数申请动态内存来加载SD卡等外部存储器中的JPEG图片。申请和释放STemWin动态内存的方法如下:
  1. /* 申请一块内存空间 并且将其清零 */
  2. hMem = GUI_ALLOC_AllocZero(100000);
  3. /* 将申请到内存的句柄转换成指针类型 */
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);
  5. /* 释放申请的动态内存  */
  6. GUI_ALLOC_Free(hMem);
复制代码
    比如我们要显示下面的JPEG格式的图片(800*480分辨率):
12.7.jpg

    就可以把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: _ShowJPG
  4. *    功能说明: 显示JPEG图片
  5. *    形    参:sFilename 要显示的图片名字
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. static void _ShowJPG(const char * sFilename)
  10. {
  11.      GUI_HMEM hMem;
  12.      char *_acBuffer2;

  13.      /* 申请一块内存空间 并且将其清零 */                                                               (1)
  14.     hMem = GUI_ALLOC_AllocZero(1024*512);
  15.      /* 将申请到内存的句柄转换成指针类型 */
  16.      _acBuffer2 = GUI_ALLOC_h2p(hMem);

  17.    
  18.      /* 打开文件 */        
  19.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
  20.      if (result != FR_OK)
  21.      {
  22.          return;
  23.      }

  24.      result = f_read(&file, _acBuffer2, file.fsize, &bw);
  25.      if (result != FR_OK)
  26.      {
  27.          return;
  28.      }

  29.      GUI_JPEG_GetInfo(_acBuffer2, file.fsize, &JpegInfo);(2)
  30.      GUI_JPEG_Draw(_acBuffer2, (3)
  31.                      file.fsize,
  32.                     0,
  33.                     0);

  34.      GUI_ALLOC_Free(hMem);
  35.      f_close(&file);
  36. }
复制代码
1.     申请一块动态内存,并将JPEG数据加载到动态内存中。
2.     利用已加载到存储器的jpeg文件的相关信息填充GUI_JPEG_INFO结构。
3.     将JPEG图片显示到屏上。
l  主函数
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: MainTask
  4. *    功能说明: GUI主函数
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void MainTask(void)
  10. {   
  11.      GUI_Init();

  12.      /* 设置皮肤函数 */
  13.      PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
  14.      FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX);
  15.      PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
  16.      BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX);
  17.      CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX);
  18.      DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX);
  19.      SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX);
  20.      SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX);
  21.      HEADER_SetDefaultSkin(HEADER_SKIN_FLEX);
  22.      RADIO_SetDefaultSkin(RADIO_SKIN_FLEX);

  23.      while(1)
  24.      {                 
  25.          _ShowJPG("2.jpg");
  26.      }

  27. }
复制代码
实际显示效果如下:
12.8.jpg

baiyongbin2009 回答时间:2015-1-14 17:23:47
12.3  绘制无需加载到存储器的JPEG图片
    绘制无需加载到存储器的JPEG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于jpeg比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. static char _acBuffer[0x2000];
  2. GUI_JPEG_INFO JpegInfo;

  3. /*
  4. *********************************************************************************************************
  5. *
  6. *       _GetData
  7. *
  8. * Purpose:
  9. *   This routine is called by GUI_JPEG_DrawEx(). The routine is responsible
  10. *   for setting the data pointer to a valid data location with at least
  11. *   one valid byte.
  12. *
  13. * Parameters:
  14. *   p           - Pointer to application defined data.
  15. *   NumBytesReq - Number of bytes requested.
  16. *   ppData      - Pointer to data pointer. This pointer should be set to
  17. *                 a valid location.
  18. *   StartOfFile - If this flag is 1, the data pointer should be set to the
  19. *                 beginning of the data stream.
  20. *
  21. * Return value:
  22. *   Number of data bytes available.
  23. *********************************************************************************************************
  24. */
  25. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off)
  26. {
  27.      static int FileAddress = 0;
  28.      UINT NumBytesRead;
  29.      FIL *PicFile;

  30.      PicFile = (FIL *)p;

  31.      /*
  32.      * Check buffer size
  33.      */
  34.      if (NumBytesReq > sizeof(_acBuffer)) {
  35.      NumBytesReq = sizeof(_acBuffer);
  36.      }


  37.      /*
  38.      * Set file pointer to the required position
  39.      */
  40.      if(Off == 1) FileAddress = 0;
  41.      else FileAddress = Off;
  42.      result =f_lseek(PicFile, FileAddress);


  43.      /*
  44.      * Read data into buffer
  45.      */
  46.      result = f_read(PicFile, _acBuffer, NumBytesReq, &NumBytesRead);

  47.      /*
  48.      * Set data pointer to the beginning of the buffer
  49.      */
  50.      *ppData = (const U8 *)_acBuffer;

  51.      /*
  52.      * Return number of available bytes
  53.      */
  54.      return NumBytesRead;
  55. }

  56. /*
  57. *********************************************************************************************************
  58. *    函 数 名: _ShowBMPEx
  59. *    功能说明: 显示BMP图片
  60. *    形    参:sFilename 要显示图片的名字
  61. *    返 回 值: 无
  62. *********************************************************************************************************
  63. */
  64. static void _ShowJPGEx(const char * sFilename)
  65. {   
  66.      OS_ERR err;
  67.      uint16_t i;

  68.      /* 打开文件 */        
  69.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
  70.      if (result != FR_OK)
  71.      {
  72.          return;
  73.      }
  74.    
  75.      GUI_JPEG_GetInfoEx(_GetData, &file, &JpegInfo);(1)
  76.      while(1)
  77.      {
  78.          /**********必要的时候,可以加上调度锁,防止刷图片的时候死机*************/
  79.          for(i = 100; i < 1000; i += 10)
  80.          {
  81.               OSSchedLock(&err);
  82.               GUI_JPEG_DrawScaledEx(_GetData, (2)
  83.                                      &file,
  84.                                        (LCD_GetXSize() - JpegInfo.XSize*i/100)/2,
  85.                                        (LCD_GetYSize() - JpegInfo.YSize*i/100)/2,
  86.                                        i,
  87.                                        100);
  88.               OSSchedUnlock(&err);
  89.               GUI_Delay(1000);  
  90.          }

  91.          GUI_Clear();
  92.          GUI_Delay(1);
  93.      }

  94. //   f_close(&file);
  95. }
复制代码
1.     获取JPEG图片的信息
2.     绘制带放缩比例的JPEG图片。
    实际显示效果如下,这个是放大后的:
12.9.png

12.4  实验总结
    有兴趣的可以了解一下JPEG压缩方面的知识。如果只是API应用的话,这部分知识还是比较容易学会的。

linlangxiyue 回答时间:2015-1-14 18:42:54
好详细。。学习了。。。
Veiko 回答时间:2015-1-14 19:38:27
很不错,顶一个
党国特派员 回答时间:2015-1-25 20:05:37
1.png
feel-376797 回答时间:2015-1-26 05:18:14

谢谢楼主分享
拼命三郎 回答时间:2015-1-26 08:04:29
stm32.jpg
Dylan疾风闪电 回答时间:2015-1-27 14:45:32
资料好多啊,学习学习
北斗光寒 回答时间:2015-1-27 19:21:43
貌似很给力的样子
wyxy163@126.com 回答时间:2015-1-28 15:10:07
提示: 作者被禁止或删除 内容自动屏蔽

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版