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

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

[复制链接]
baiyongbin2009 发布时间:2015-1-15 14:34
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第14章      PNG图片显示
- |. D3 L' `* J
    本期主要讲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
6 c7 K+ a# d# N7 z
14.1.1      PNG格式图标转换
    某些情况下,将PNG文件作为C文件添加到项目中非常有用。对此,可完全按照前面介绍的“JPEG文件支持”下的相同方式来执行。此外,位图转换器能够加载PNG文件并将它们转换为C位图文件。下面举一个例子,跟大家演示下:比如我们要转换如下的PNG图标:
4 m6 J9 P/ j, N5 I. r+ T' |9 r
14.2.png
l  打开软件加载上面的图片
14.3.jpg
; x" E: ~0 U' A, D; A& X
l  加载后点击Convert即可,点击后没有任何现象,直接去图片所在的文件夹找即可

/ Q$ R2 c2 w$ s- e, D" C
14.4.jpg
实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)7 ~( i' l7 q& m3 L* _
  2. {   
    2 ]* i* k7 O; E
  3.     GUI_Init();
    * b) V/ [0 M" Z1 ?( B; c
  4.      GUI_PNG_Draw(_acmusic, sizeof(_acmusic), 20, 20);5 T0 B& ]5 Z4 x# v7 a+ `
  5.     while(1)$ }0 o$ Z% c( ~  Q- s. R8 X; [
  6.     {
    7 `0 s# j5 _0 p) V4 T3 }6 E% P0 d
  7.         GUI_Delay(100);5 P& [. |4 w. V' c2 M0 l
  8.     }1 q$ C: v; f0 A! T% o/ Y6 E
  9. }
复制代码
    由于在Bin2C的小工具是来自MDK安装目录中,这个工具只是评估板,无法实现PNG图标的透明色效果。模拟器实际的显示效果如下:
14.5.png
: [. h  Q3 H  H! E
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
& A8 O# e: H$ ?: v' i5 F9 q% y

+ h7 e+ {4 w5 b  G9 A# x; l5 n: Y
收藏 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. /* 申请一块内存空间 并且将其清零 */$ P+ w6 ^3 ~6 X3 r2 V+ r9 p
  2. hMem = GUI_ALLOC_AllocZero(100000);
    8 y3 ?; P- u& M$ Z" C
  3. /* 将申请到内存的句柄转换成指针类型 */9 C- u( c; i. I& `
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);2 G- S  j$ ]: L
  5. /* 释放申请的动态内存  */
    & t  ]  o: V! j
  6. GUI_ALLOC_Free(hMem);
复制代码
    这里还用上面的图片作为显示对象。先把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*
    ; t5 A* Q7 w6 ~; A# ^% @
  2. *********************************************************************************************************
    " f: B& C. x9 ^
  3. *    函 数 名: _ShowPNG; U$ m* d+ `$ V, Q7 F0 Q
  4. *    功能说明: 显示GIF片
    $ Z* G' T) W  q. N' o
  5. *    形    参:sFilename   要显示的图片名字. J4 f7 A0 {- I9 \, a( W- |
  6. *              usPOSX     显示位置X/ M9 J0 b# P7 B% L
  7. *              usPOSY     显示位置Y
    ) g1 T9 W; G2 i2 O' S. h
  8. *    返 回 值: 无! y- p) m9 l( ]8 D- k8 k
  9. *********************************************************************************************************
    * w  l) A9 p0 w- t3 P
  10. */; z' p2 u: m% |: a$ R8 }0 y, f5 @
  11. static void _ShowPNG(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)6 S, G* U$ X' T, c1 [
  12. {2 [/ ?6 t7 e( t: C& A1 L
  13.      GUI_HMEM hMem;
    6 t( a% D: c; `8 |  G( x
  14.      char *_acBuffer2;
    ' m" Q$ e5 t9 @! @9 g' B5 ^

  15. + g  n. K- f3 A% q, g/ W% a* j' v
  16.      /* 申请一块内存空间 并且将其清零 */' x$ A/ P+ [/ n8 p$ D0 o
  17.     hMem = GUI_ALLOC_AllocZero(500000);& t. y  V3 W; T3 E5 ^3 @( P
  18.      /* 将申请到内存的句柄转换成指针类型 */
    : l5 A4 `+ P  O+ s* D' w
  19.      _acBuffer2 = GUI_ALLOC_h2p(hMem);
    9 w/ f6 J/ M7 W' v4 s+ y3 R' F4 r
  20. 5 G# p$ ^+ B* r% [7 e$ @8 F
  21.    
    0 l+ ~5 v7 K6 }% t
  22.      /* 打开文件 */        ' j0 E9 s& [: A7 f- f
  23.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    , b5 S6 E# P' M4 w2 o) i
  24.      if (result != FR_OK)( p1 B6 r5 Z! B' [+ T, [( A0 b6 l; f
  25.      {
    / ]$ }2 B& K' Z# F  s0 q- z9 J
  26.          return;: R0 H! N4 m1 |' B
  27.      }
    * }: |0 _6 p7 Q3 R% ~$ h! J
  28.   ]/ w- z1 p4 E( i( V! w
  29.      result = f_read(&file, _acBuffer2, file.fsize, &bw);
    * C6 O7 {. C/ @! X. Y
  30.      if (result != FR_OK)
    / u( X. }' ~# N
  31.      {
    & L) `3 I3 y- M& |5 G
  32.          return;; Y" ]1 h4 w" F6 H! Q3 v- _
  33.      }0 b2 I2 @! V7 X
  34. " h* S- S( L  y# T' F
  35.      GUI_PNG_Draw(_acBuffer2, file.fsize, usPOSX, usPOSY);
    3 s0 O0 @* X7 Y/ G: }6 r& |
  36.      GUI_ALLOC_Free(hMem);
    0 G7 f: v" o0 e* w, `: }
  37.      f_close(&file);' c1 u+ N. l- x3 S
  38. }
复制代码
l  主函数
  1. /*( I& k, k' \, ^5 k
  2. *********************************************************************************************************
    % E' y4 P+ n/ l) j2 t9 O/ z( s
  3. *    函 数 名: MainTask
    0 V8 O9 u. x$ _% Z
  4. *    功能说明: GUI主函数
    # @; `, L5 i+ \- ~; t: h) O
  5. *    形    参:无7 c! q4 I9 u3 B+ B: k) x( U
  6. *    返 回 值: 无
    ( n+ f. ^4 J" u4 a5 L5 Z
  7. *********************************************************************************************************
    " S. m# Y7 S& }, i- g, s) \' T
  8. */: [( Q% t6 f2 H0 B( m0 r% \
  9. void MainTask(void)- J& y9 r, I! m( K/ i
  10. {   
    . N- Z" m% r; `* c0 ^
  11.      GUI_Init();
    ) F! w9 a( ?5 _) E) ^" w+ h  o8 n
  12.      GUI_SetBkColor(GUI_BLUE);
    6 ]. @7 n2 a+ U3 h
  13.      GUI_Clear();6 |0 e# y  q6 {0 w
  14.     ! H# ^; l6 B/ B, |, U' j# u, Y% |
  15.     /* 绘制已加载到存储器的PNG文件 */  G1 s9 F) [% J( g
  16.      _ShowPNG("1.png", 0, 0);3 i# p- @8 _. A" _
  17.      _ShowPNG("2.png", 100, 0);4 t' \( ?8 O& w7 V2 Q3 y( h' A
  18.     - C, \& R' f9 e  J
  19.      while(1)
    3 L+ P0 T( o2 i! f; i  _8 o( Q
  20.      {                 
    " m+ H/ l2 L, V& g# l" y
  21.          GUI_Delay(100);$ L2 T# ]; {, B, {9 A
  22.      }4 ~& `; O3 L, w: v# {' n

  23. 1 |# k* V/ |) ~7 u$ h! Y. F9 |& |6 ]# r
  24. }
复制代码
实际显示效果如下:
14.7.png

- C! ?: E, D" P  z+ Z8 ~
    编译,链接工程的时候会出现大量如下的警告:
4 E0 Z( J" d2 h- m. F
    14.8.jpg
    这个是由于使用的PNG库和现在STemWin5.22版本不匹配造成的,PNG的库是用5.18版本的,最新的5.22版本官方还没有更新。

0 p/ S5 m5 @+ E1 x# E" O- W
baiyongbin2009 回答时间:2015-1-15 14:38:58
14.3  绘制无需加载到存储器的PNG图片
    绘制无需加载到存储器的PNG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于PNG比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. /*
    ( n  H4 b% N. ]' D, g/ C$ ~" W
  2. ********************************************************************************
    * D$ m& ?$ ~$ `! R7 C
  3. *1 h" X. ?: C8 {. w$ A2 C' n
  4. *       _GetData
    8 A4 T7 W$ S- E" |( \( ?
  5. *! `* u9 j& u2 M! t8 i9 h
  6. * Purpose:
    ) Y9 `+ C) `$ y) v+ H: p$ W
  7. *   This routine is called by GUI_GIF_DrawEx(). The routine is responsible9 ?6 N& p7 V- s6 E: i, R0 s
  8. *   for setting the data pointer to a valid data location with at least8 G3 Z, D, E. K5 H* j
  9. *   one valid byte.
    - d0 J) ^1 ?7 |9 W
  10. *
    % E% N$ d, {* C1 u0 M, o
  11. * Parameters:
    / d/ W& v9 X3 v+ |* V
  12. *   p           - Pointer to application defined data.
    ( U! q- J7 z! X+ o
  13. *   NumBytesReq - Number of bytes requested.
    7 F4 Y% F$ K* \% \+ n5 y" G
  14. *   ppData      - Pointer to data pointer. This pointer should be set to
      R3 Z. d$ T- k0 a7 f( g6 R
  15. *                 a valid location.
    0 T9 A# p* j+ S" |5 k- B1 n
  16. *   StartOfFile - If this flag is 1, the data pointer should be set to the. f- Y+ O  K' T: M" V# o
  17. *                 beginning of the data stream.% m, I) P) y8 {9 q# \7 s
  18. *7 }- Q* B" S8 T* p
  19. * Return value:
    3 N" n+ f3 [% t0 A% J
  20. *   Number of data bytes available.
    : f6 D  z; Y1 L7 m) J9 `2 T1 {
  21. *********************************************************************************/ H- C' w( Y0 W  q4 e
  22. */
    3 d  m9 X5 L. O; g
  23. & u1 Q! s# \$ `$ O4 q7 ?
  24. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) {
    ! A$ O* z1 p# {$ E4 O
  25.      static int FileAddress = 0;- [; U" a* x/ x
  26.      FIL *file;0 z) W" Q7 W5 Q) I5 ?# H* g7 K0 a! W8 Z
  27.      DWORD    NumBytesRead;* H" H- a6 H$ R) a$ H( C4 y# y1 i/ S
  28.      U8     * pData;
    & x5 d' m$ C2 Q7 d5 a5 s: s3 K. z* X$ y" u

  29. 4 V- d) o; C7 V0 g0 W3 f& T
  30.      pData  = (U8 *)*ppData;' u5 n7 G, d" {" u! N
  31.      file = (FIL *)p;
    5 {% o" g* Q, B  q9 q$ [5 ]7 v2 @
  32.      //3 G8 o" X" E! `' R' q! p
  33.      // Set file pointer to the required position
    $ Y0 t8 ~+ O2 H  J& X
  34.      //
    $ n( A3 ^' g8 D0 M  r: Z
  35.      if(Off == 1) FileAddress = 0;+ A) x  }9 P$ p6 ?
  36.      else FileAddress = Off;
    7 \+ l) ^. x" L
  37.      result =f_lseek(file, FileAddress);
    ; x; ]3 E+ J, t. M& U
  38.      //. l+ c$ t3 N1 S: v; O: Z
  39.      // Read data into buffer
    # t& K* R) A6 a2 e
  40.      //
    2 S8 }5 _6 m# ]- w
  41.      result = f_read(file, pData, NumBytesReq, &NumBytesRead);2 q0 _4 T7 u9 s2 }) v; z

  42. 8 V: G: p$ e* N: `
  43.      //
    , V' X1 B3 ~! e& t+ D% ^0 ^# G
  44.      // Return number of available bytes
    . \. r% E' Q/ r
  45.      //' N- Z+ ^1 \( U) R4 I; x3 Y* j; j3 d
  46.      return NumBytesRead;
    5 E; h. a3 Q9 H; B
  47. + d( D3 U4 P- b/ ]! S9 x3 u2 [8 b6 s
  48. }' v& L3 T9 F/ g0 j# d3 t
  49. /*4 r+ p3 g7 z9 I# ]
  50. *********************************************************************************************************- k$ w/ ^( _0 [" A- \& y1 S1 k/ }
  51. *    函 数 名: _ShowPNG
    7 j0 n4 b; v9 f: a4 \
  52. *    功能说明: 显示PNG图片
    0 ?2 z0 A8 v# _9 E# _
  53. *    形    参:sFilename 要显示的图片名字
    / \) `$ x  g# L! W& {% Q3 Y6 ]3 |# B
  54. *             usPOSX    显示位置X  m; I( {0 ]: U
  55. *             usPOSY    显示位置Y
    . o/ |  V* g' K* @
  56. *    返 回 值: 无
    6 z2 T2 I9 c+ X
  57. *********************************************************************************************************
      o# g6 k3 {: i
  58. */
    ; ]1 _% ]7 x! {5 E) V
  59. static void _ShowPNGEx(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)
    $ ]+ T! e' W, l8 Z$ q! A& U( q
  60. {   
    ( x& L$ w. y+ Z

  61. : h1 [9 ]2 m" p- o
  62.      /* 打开文件 */        3 T8 a3 @1 E" c! m- p' i+ b
  63.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    ; Q5 b0 ]. V' H  D+ Q
  64.      if (result != FR_OK)8 m, A& `' M$ B. c+ z/ ~& A& \# ^: P
  65.      {/ w, e  _5 ]: z" u0 O+ t- M0 c' d
  66.          return;
    & n# N. \& Q4 z7 p$ m: x, M, @/ H4 V
  67.      }
    , p& k5 Q1 r3 x) G
  68.    
      x" D3 J" ^) j. w) O* S$ o) t6 @
  69.      GUI_PNG_DrawEx(_GetData, &file, usPOSX, usPOSY);3 B" q4 o" ^+ v& q4 G- D" {1 a* N
  70. 4 O3 w" A+ M/ {+ p. p) m) G
  71.      f_close(&file);
    : a: Z1 K3 o; T; d2 A1 O
  72. }
复制代码
l  主函数
  1. /*1 M$ U: Z& Q% j, q: H7 Z# q
  2. *********************************************************************************************************/ y! e: f" {/ B6 [+ k" g
  3. *    函 数 名: MainTask( f' x# P0 q: s1 a4 q
  4. *    功能说明: GUI主函数0 H1 f1 `0 Q; Z
  5. *    形    参:无
    0 g3 i8 M5 B8 {  J: P( X
  6. *    返 回 值: 无" H1 v8 D6 y$ @
  7. *********************************************************************************************************
      k" q4 l3 q6 C) Q
  8. */
    6 p0 Z" y' e2 j( h4 f: Q
  9. void MainTask(void)
    ! Q1 H# M4 \7 }# V/ y
  10. {   ' d( U+ G0 _: T& q) `" d
  11.      GUI_Init();
    # x5 s4 d5 z# {  J; v
  12.      GUI_SetBkColor(GUI_BLUE);0 [' c- E( L9 `7 {: V: U# i0 e  z
  13.      GUI_Clear();
    6 {& Q/ H( f$ {
  14.    
    0 [1 w( j6 R' b. i7 o) i- A
  15.      /* 绘制无需加载到存储器的PNG文件 */
    3 ?8 L2 o& V$ p8 E3 }" b
  16.      _ShowPNGEx("3.png", 0, 100);
    7 H1 F% |# @  H( ?. [
  17.      _ShowPNGEx("4.png", 100,100);
    $ j2 c6 |* J" h+ x- P
  18.     ! v! c, ]0 s: s& M. v2 ^1 O6 S
  19.      while(1)
    * ~: {  j1 r' B
  20.      {                 
    / E+ z4 |3 K; h5 O: H  Z
  21.          GUI_Delay(100);1 k/ a9 y0 f9 f1 }1 j
  22.      }4 W2 @3 g" d$ S. a
  23. ) k9 M8 F& s9 y7 r* n) R( v
  24. }
复制代码
实际显示效果如下:
14.9.png

- d! P% x! I* s0 M- q14.4  实验总结6 p; _. t. P' d. K) G
    有兴趣的可以了解一下PNG压缩方面的知识。如果只是API应用的话,这部分知识还是比较容易学会的。PNG图标用到的地方还是比较多的。
# z* }  n3 }% t! Q1 `
8 y  V$ v  L7 T$ ^
蔚飞 回答时间:2015-1-15 14:41:59
我是来赚金币的,你信不?
wyxy163@126.com 回答时间:2015-1-16 08:07:30
提示: 作者被禁止或删除 内容自动屏蔽
xiaoyustm32 回答时间:2016-9-12 22:42:30
谢谢分享,但是可以不用emWin吗

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版