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

【安富莱STemWin教程】第14章 PNG图片显示

[复制链接]
baiyongbin2009 发布时间:2015-1-15 14:34
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第14章      PNG图片显示

    本期主要讲STemWin支持的PNG图片的显示,官方支持的主要有两种显示方法,一种是从外部存储器读取数据到内部存储器,然后来显示图片,这种的显示速度要快些,另一种方法是直接从外部存储器读取数据并显示,这种办法的好处就是不要大的RAM需求,每次读取一些数据显示一次,坏处就是显示速度比较的慢。
    这里将2MB的外部SRAM做为emWin的动态内存,PNG的图片显示相当耗费RAM。
    有一点在这里提前得和大家说明,对于PNG的库,STemWin里面是不带的,需要自己添加,从SEGGER的官网下载,这个库是来自libpng,官网www.libpng.org
    14. 1  PNG图片支持
    14. 2 绘制已经加载到存储器的PNG图片
    14. 3 绘制无须加载到存储器的PNG图片
    14. 4 实验总结
14.1  PNG图片支持
    PNG(可移植的网络图形)格式是一种图像格式,它利用非专利的数据压缩方法提供无损的数据压缩和Alpha混合。PNG 1.0版规范于1996年发布。到2003年末,PNG成为国际标准(ISO/IEC15948)。
    emWin对PNG支持的实施基于来自GlennRanders-Pehrson、Guy Eric Schalnat和Andreas Dilger的“libpng”库,该库可在www.libpng.org下免费获得。emWin对该库的使用符合GUI\PNG\png.h中的版权通知,通知中允许使用该库,而没有任何限制。
    图形库首先对图形信息进行解码。如果必须绘制图像,解码流程将花费相当长的时间。如果在窗口管
理器经常调用的callback例程中使用PNG文件,则解码流程可能花费相当长的时间。通过使用存储设备可缩短计算时间。最好的方法是先将图像绘制到存储设备中。在这种情况下,将只进行一次解压缩。
    从SEGGER官网下载的png如下,这里我们使用最新的5.18版本:
14.1.png

14.1.1      PNG格式图标转换
    某些情况下,将PNG文件作为C文件添加到项目中非常有用。对此,可完全按照前面介绍的“JPEG文件支持”下的相同方式来执行。此外,位图转换器能够加载PNG文件并将它们转换为C位图文件。下面举一个例子,跟大家演示下:比如我们要转换如下的PNG图标:

14.2.png
l  打开软件加载上面的图片
14.3.jpg

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

14.4.jpg
实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)
  2. {   
  3.     GUI_Init();
  4.      GUI_PNG_Draw(_acmusic, sizeof(_acmusic), 20, 20);
  5.     while(1)
  6.     {
  7.         GUI_Delay(100);
  8.     }
  9. }
复制代码
    由于在Bin2C的小工具是来自MDK安装目录中,这个工具只是评估板,无法实现PNG图标的透明色效果。模拟器实际的显示效果如下:
14.5.png

14.1.2      PNG存储器方式显示
    为了区分上面将图片转换为C文件进行显示,这里将PNG图片存入到外部SD卡等存储器中进行加载显示。
    首先要注意PNG需要的动态内存大小。PNG解压缩大约需要21 Kb RAM用于与图像大小无关的解压缩和依赖大小的字节量。RAM要求可按以下方式计算:
        大约RAM要求= (X-Size + 1)* Y大小* 4 + 21Kbytes
    当前STemWin支持的PNG图片 API函数如下:
14.6.png


收藏 2 评论5 发布时间:2015-1-15 14:34

举报

5个回答
baiyongbin2009 回答时间:2015-1-15 14:36:36
14.2  绘制已经加载到存储器的PNG图片
    将图片加载到存储器后进行显示比较的耗内存,所以这里就使用开发板外置的2MB SRAM做STemWin的动态内存空间,并通过相应的API函数申请动态内存来加载SD卡等外部存储器中的PNG图片。申请和释放STemWin动态内存的方法如下:
  1. /* 申请一块内存空间 并且将其清零 */
  2. hMem = GUI_ALLOC_AllocZero(100000);
  3. /* 将申请到内存的句柄转换成指针类型 */
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);
  5. /* 释放申请的动态内存  */
  6. GUI_ALLOC_Free(hMem);
复制代码
    这里还用上面的图片作为显示对象。先把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: _ShowPNG
  4. *    功能说明: 显示GIF片
  5. *    形    参:sFilename   要显示的图片名字
  6. *              usPOSX     显示位置X
  7. *              usPOSY     显示位置Y
  8. *    返 回 值: 无
  9. *********************************************************************************************************
  10. */
  11. static void _ShowPNG(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)
  12. {
  13.      GUI_HMEM hMem;
  14.      char *_acBuffer2;

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

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

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

  31.      GUI_PNG_Draw(_acBuffer2, file.fsize, usPOSX, usPOSY);
  32.      GUI_ALLOC_Free(hMem);
  33.      f_close(&file);
  34. }
复制代码
l  主函数
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: MainTask
  4. *    功能说明: GUI主函数
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void MainTask(void)
  10. {   
  11.      GUI_Init();
  12.      GUI_SetBkColor(GUI_BLUE);
  13.      GUI_Clear();
  14.    
  15.     /* 绘制已加载到存储器的PNG文件 */
  16.      _ShowPNG("1.png", 0, 0);
  17.      _ShowPNG("2.png", 100, 0);
  18.    
  19.      while(1)
  20.      {                 
  21.          GUI_Delay(100);
  22.      }

  23. }
复制代码
实际显示效果如下:
14.7.png

    编译,链接工程的时候会出现大量如下的警告:

    14.8.jpg
    这个是由于使用的PNG库和现在STemWin5.22版本不匹配造成的,PNG的库是用5.18版本的,最新的5.22版本官方还没有更新。

baiyongbin2009 回答时间:2015-1-15 14:38:58
14.3  绘制无需加载到存储器的PNG图片
    绘制无需加载到存储器的PNG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于PNG比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. /*
  2. ********************************************************************************
  3. *
  4. *       _GetData
  5. *
  6. * Purpose:
  7. *   This routine is called by GUI_GIF_DrawEx(). The routine is responsible
  8. *   for setting the data pointer to a valid data location with at least
  9. *   one valid byte.
  10. *
  11. * Parameters:
  12. *   p           - Pointer to application defined data.
  13. *   NumBytesReq - Number of bytes requested.
  14. *   ppData      - Pointer to data pointer. This pointer should be set to
  15. *                 a valid location.
  16. *   StartOfFile - If this flag is 1, the data pointer should be set to the
  17. *                 beginning of the data stream.
  18. *
  19. * Return value:
  20. *   Number of data bytes available.
  21. *********************************************************************************
  22. */

  23. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) {
  24.      static int FileAddress = 0;
  25.      FIL *file;
  26.      DWORD    NumBytesRead;
  27.      U8     * pData;

  28.      pData  = (U8 *)*ppData;
  29.      file = (FIL *)p;
  30.      //
  31.      // Set file pointer to the required position
  32.      //
  33.      if(Off == 1) FileAddress = 0;
  34.      else FileAddress = Off;
  35.      result =f_lseek(file, FileAddress);
  36.      //
  37.      // Read data into buffer
  38.      //
  39.      result = f_read(file, pData, NumBytesReq, &NumBytesRead);

  40.      //
  41.      // Return number of available bytes
  42.      //
  43.      return NumBytesRead;

  44. }
  45. /*
  46. *********************************************************************************************************
  47. *    函 数 名: _ShowPNG
  48. *    功能说明: 显示PNG图片
  49. *    形    参:sFilename 要显示的图片名字
  50. *             usPOSX    显示位置X
  51. *             usPOSY    显示位置Y
  52. *    返 回 值: 无
  53. *********************************************************************************************************
  54. */
  55. static void _ShowPNGEx(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)
  56. {   

  57.      /* 打开文件 */        
  58.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
  59.      if (result != FR_OK)
  60.      {
  61.          return;
  62.      }
  63.    
  64.      GUI_PNG_DrawEx(_GetData, &file, usPOSX, usPOSY);

  65.      f_close(&file);
  66. }
复制代码
l  主函数
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: MainTask
  4. *    功能说明: GUI主函数
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void MainTask(void)
  10. {   
  11.      GUI_Init();
  12.      GUI_SetBkColor(GUI_BLUE);
  13.      GUI_Clear();
  14.    
  15.      /* 绘制无需加载到存储器的PNG文件 */
  16.      _ShowPNGEx("3.png", 0, 100);
  17.      _ShowPNGEx("4.png", 100,100);
  18.    
  19.      while(1)
  20.      {                 
  21.          GUI_Delay(100);
  22.      }

  23. }
复制代码
实际显示效果如下:
14.9.png

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

weifei-373748 回答时间:2015-1-15 14:41:59
我是来赚金币的,你信不?
数码小叶 回答时间:2015-1-16 08:07:30
谢谢分享,学习学习
xiaoyustm32 回答时间:2016-9-12 22:42:30
谢谢分享,但是可以不用emWin吗

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

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