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

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

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

+ `* V' r; d3 B4 H
    本期主要讲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

, U+ [( F7 Z. p- d14.1.1      PNG格式图标转换
    某些情况下,将PNG文件作为C文件添加到项目中非常有用。对此,可完全按照前面介绍的“JPEG文件支持”下的相同方式来执行。此外,位图转换器能够加载PNG文件并将它们转换为C位图文件。下面举一个例子,跟大家演示下:比如我们要转换如下的PNG图标:
5 l/ v4 y8 d$ p0 _5 k
14.2.png
l  打开软件加载上面的图片
14.3.jpg
7 _9 c0 }: T) L  v. ^. B: ]0 ]
l  加载后点击Convert即可,点击后没有任何现象,直接去图片所在的文件夹找即可

" f% B) i0 B4 G
14.4.jpg
实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)# e4 o1 j) g" h6 k+ f* x) K
  2. {   * s: e# o2 y( {; r% c. b
  3.     GUI_Init();
    9 y  x4 B- |) s/ h3 h
  4.      GUI_PNG_Draw(_acmusic, sizeof(_acmusic), 20, 20);& K* l: N/ y8 N" r
  5.     while(1)
    , Y! j0 p7 [8 a8 J7 ]5 o; H
  6.     {
    , i/ y" L  K) _* R# m- C# V# h
  7.         GUI_Delay(100);: S' E2 e; x, N. R5 u, k- i
  8.     }+ u8 ?4 I; \) W3 W
  9. }
复制代码
    由于在Bin2C的小工具是来自MDK安装目录中,这个工具只是评估板,无法实现PNG图标的透明色效果。模拟器实际的显示效果如下:
14.5.png

3 P" p8 {) C( {7 X" q) I% ~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

7 [2 V2 \4 q2 V' C1 c2 D# G
: U) M7 Y. F7 S7 v4 N; Y3 C% F( f
收藏 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. /* 申请一块内存空间 并且将其清零 */5 ~* U- A3 A# m- S3 h
  2. hMem = GUI_ALLOC_AllocZero(100000);
    - ~! j' L. y# H# z
  3. /* 将申请到内存的句柄转换成指针类型 */
    : C1 O$ d: v, h1 ]) \4 Y
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);
    $ j7 S9 {. K7 u3 Q6 S+ S
  5. /* 释放申请的动态内存  */
    : ]" S$ S1 S- Z$ w
  6. GUI_ALLOC_Free(hMem);
复制代码
    这里还用上面的图片作为显示对象。先把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*( ~) `2 j/ ]0 u% t/ v$ f6 u; O
  2. *********************************************************************************************************
    - T) J/ ^) E) ]( j
  3. *    函 数 名: _ShowPNG
    * f' G! v( d. t' k7 p  e
  4. *    功能说明: 显示GIF片
    ! V5 q. v, z4 }0 m
  5. *    形    参:sFilename   要显示的图片名字
    6 c6 P3 Q+ h4 ]/ `% h* C
  6. *              usPOSX     显示位置X
    # U! J& a4 L3 t1 `- S' U; R8 S. C
  7. *              usPOSY     显示位置Y1 q' @4 x) g% Z. F+ h" k5 G# x
  8. *    返 回 值: 无1 S' a1 ~& t1 J  K7 `
  9. *********************************************************************************************************
    5 V; K7 u0 j9 Q* [' h/ f, l) D
  10. */
    2 Q# j) g* U3 a; M- U7 }! Y, O' Z
  11. static void _ShowPNG(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY), [  w) Z9 M8 v8 x
  12. {
    / a$ B4 A0 k# C) I/ E9 e- M6 j
  13.      GUI_HMEM hMem;
    ! h2 N$ l4 W: ]8 L$ I) S# w4 `9 ]
  14.      char *_acBuffer2;/ K% X" Y, r7 x8 `7 _

  15. ; R3 M7 q1 q9 _! X+ j8 N
  16.      /* 申请一块内存空间 并且将其清零 */* u9 j8 D9 W( I9 `0 T9 q' N5 {, N, Q
  17.     hMem = GUI_ALLOC_AllocZero(500000);
      q8 D6 |0 ~! L" l: {
  18.      /* 将申请到内存的句柄转换成指针类型 */; A2 ?$ O1 e; Q- k& h
  19.      _acBuffer2 = GUI_ALLOC_h2p(hMem);2 W- ~. V6 u# @* q

  20. ( F& P. G( p2 C& k: n
  21.     2 }3 l8 j  P5 I) i; z& Z; b
  22.      /* 打开文件 */        % ?( l7 E# P$ Y; s$ T
  23.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    . W! V+ N# K# O8 ~: A; [0 v  Q
  24.      if (result != FR_OK)
    7 V2 p8 a# g0 B9 T0 \
  25.      {: |  J7 A6 {  j9 X" t1 h
  26.          return;
    7 K/ g/ e# }6 i
  27.      }
    ( f7 v. R) b6 b% h3 }% Q" e( Q

  28. ' r. ]. c5 S7 D- _3 s  N! c: |& p
  29.      result = f_read(&file, _acBuffer2, file.fsize, &bw);% S. S* H4 C" g  e( g& B% p8 }9 W
  30.      if (result != FR_OK)
    / j8 B/ v$ [4 t- y* M; z
  31.      {
    3 g* w* U. a. I9 v1 N8 U) q2 g
  32.          return;
    2 {: o' {6 j  F: x
  33.      }, L& O, C6 m* T

  34. + C: J- K% t0 F7 Z. Y
  35.      GUI_PNG_Draw(_acBuffer2, file.fsize, usPOSX, usPOSY);7 z. z! v, q0 l4 p8 h3 u3 _
  36.      GUI_ALLOC_Free(hMem);
    ' }, r9 U1 H, Z1 V$ O
  37.      f_close(&file);0 Q- K7 D- [$ k+ l, X
  38. }
复制代码
l  主函数
  1. /*' Z7 S, o/ w9 F3 V( u3 R) V' {+ M
  2. *********************************************************************************************************
    5 F+ S' n; p4 ?
  3. *    函 数 名: MainTask
    6 M* F9 u: l7 `7 r
  4. *    功能说明: GUI主函数
    * `3 [) t9 x$ ^9 W4 o
  5. *    形    参:无3 I3 z3 H% V. G% X5 z
  6. *    返 回 值: 无5 H( g  r0 c" w, Q; }9 }
  7. *********************************************************************************************************
    3 }! Z7 r7 K$ z9 g
  8. */7 V. ]2 f3 s, K; J, w
  9. void MainTask(void)4 m2 O' B! K5 `. H- H9 y4 }  R
  10. {   
      q  ~1 k9 \1 }+ i, P% R
  11.      GUI_Init();
    7 v% l( c$ }9 B# o5 ^7 a% k- p
  12.      GUI_SetBkColor(GUI_BLUE);
    3 Y: {9 `4 \' C  ]; `/ D* ?- M/ \
  13.      GUI_Clear();2 r* h2 M5 `+ X' a
  14.     ) Z, }. @" |6 C- i: U+ k3 {- y* E
  15.     /* 绘制已加载到存储器的PNG文件 */
    1 R  D/ `: t6 A0 F" w' s
  16.      _ShowPNG("1.png", 0, 0);
    - Q$ Q% ?' a" N1 F+ W: L
  17.      _ShowPNG("2.png", 100, 0);. h" `( G8 L, J0 ]; _+ \( o
  18.    
    5 A6 ]7 n- k% c+ k' B) a* s
  19.      while(1)
    . _: `% {) Z$ I4 E% ]
  20.      {                 ! C: U; Y& G. C8 H( @& s4 _, A
  21.          GUI_Delay(100);; q" ^/ \# m- T
  22.      }
    5 W3 Q6 {* L3 y- F# ~0 W; U
  23. - w$ D$ A( ?7 p: i. [
  24. }
复制代码
实际显示效果如下:
14.7.png

  l* t/ {5 L, q) `! q' I
    编译,链接工程的时候会出现大量如下的警告:

' R, ]1 L; @- ]: C7 x6 Y) g
    14.8.jpg
    这个是由于使用的PNG库和现在STemWin5.22版本不匹配造成的,PNG的库是用5.18版本的,最新的5.22版本官方还没有更新。
' B8 D$ o$ P9 @$ E  F
baiyongbin2009 回答时间:2015-1-15 14:38:58
14.3  绘制无需加载到存储器的PNG图片
    绘制无需加载到存储器的PNG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于PNG比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. /*
    8 ]2 I) u. Z! }( O
  2. ********************************************************************************
    1 A- B: O3 L6 C7 `2 x. X
  3. *
    " g9 R, k# v$ j
  4. *       _GetData
    9 F  K0 L. M) \6 ]  k7 b" V
  5. *
    6 M$ F( w% U9 b+ ]: J( D
  6. * Purpose:+ Y7 S# ?6 Y; @1 @3 z  R
  7. *   This routine is called by GUI_GIF_DrawEx(). The routine is responsible
    2 q, y- U9 Y9 e+ d* S
  8. *   for setting the data pointer to a valid data location with at least
    3 @- @1 B% N1 ~' H
  9. *   one valid byte.
    " M1 A4 T( {. A# {& n/ W
  10. *
    & T" f/ j: N- Y( F3 ^( O8 M
  11. * Parameters:
    $ Z  I' v0 Q4 d* H. B. j  X- W7 U, G
  12. *   p           - Pointer to application defined data.! b; w  x# E3 M
  13. *   NumBytesReq - Number of bytes requested.) O" ~1 R' @: m3 y/ k+ i
  14. *   ppData      - Pointer to data pointer. This pointer should be set to) l! O& _2 l- J* m0 D" ?
  15. *                 a valid location.
    6 Y' i! r" b( H9 p8 y" a' [
  16. *   StartOfFile - If this flag is 1, the data pointer should be set to the
    1 o5 t( n6 Q* Y: E3 f  F  J% G0 A, G
  17. *                 beginning of the data stream./ ?4 l9 r. d. N
  18. *
    / U" y* V1 a* f
  19. * Return value:
    4 u# d- g& d9 x8 r' i
  20. *   Number of data bytes available.( o: a; Y, ?3 m& B( r" d
  21. *********************************************************************************" `% }4 S7 d5 x/ m0 B7 u+ `% H) W
  22. */
    ( X6 g9 f5 [" b# W1 n' s0 B$ x

  23. ) g0 O) k# @: u* t1 D
  24. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) {
    , x! B3 ]% `1 x
  25.      static int FileAddress = 0;
    ! k+ }6 x5 Z5 c7 N# f
  26.      FIL *file;
    & A5 p( u! H* b6 p: N# E  H9 g
  27.      DWORD    NumBytesRead;4 u- \% A2 @" h- o
  28.      U8     * pData;2 B: Q+ o% p& |! x6 [

  29. 8 q1 j) p2 a/ }" A! ^; p0 {0 W& S
  30.      pData  = (U8 *)*ppData;
    " C. E" o8 L) a% ~' L: l
  31.      file = (FIL *)p;
    / H# |: D9 Z; U6 N; a+ [
  32.      //+ j+ n  E  d9 @! C! P, N
  33.      // Set file pointer to the required position9 T, m7 O- X* H' S% h% n# R
  34.      //4 |- }  u" w( L# [! M
  35.      if(Off == 1) FileAddress = 0;) ?1 J2 D: r4 t2 p  G2 h" E
  36.      else FileAddress = Off;' E" S4 o7 O# u2 \9 t. J
  37.      result =f_lseek(file, FileAddress);# L9 h+ j  L6 U9 N% m' Y# y0 l
  38.      //
    - M, R$ B3 g0 S2 a: h' ?/ c
  39.      // Read data into buffer* ~! \4 t) R3 U- s
  40.      //# n" J: E+ s( v( ~
  41.      result = f_read(file, pData, NumBytesReq, &NumBytesRead);# e. K* M# B$ t( h) r5 A
  42. , r; q, ]: Y# f8 Z, P' t  L" W, t
  43.      //) S* _+ m) O# R( T; x% ?
  44.      // Return number of available bytes7 B3 o* X7 E8 d0 B8 W8 N
  45.      //6 M- s6 E* x' p: r$ Z
  46.      return NumBytesRead;
    ( x  W% N6 h6 X' O  H
  47. 2 @6 D2 H. j! X, ?6 s; L. K5 v$ I
  48. }4 e1 c3 G8 A( M" A
  49. /*4 O$ U% J2 V& U' L+ q; m; p
  50. *********************************************************************************************************
    6 M4 X$ ?# C: T5 g& j
  51. *    函 数 名: _ShowPNG
    * }% v3 m* ?0 v, B! v
  52. *    功能说明: 显示PNG图片+ D) z8 @) p6 E' I' [- ]) W
  53. *    形    参:sFilename 要显示的图片名字9 n, z$ X- y8 ~/ ^' D3 C
  54. *             usPOSX    显示位置X5 v4 z+ q' A7 m% f4 J9 G5 C1 C
  55. *             usPOSY    显示位置Y0 M  h8 C5 x1 j' W. F# G
  56. *    返 回 值: 无
    7 j- ~- x  l2 P3 t' u6 S
  57. *********************************************************************************************************
    ( b( l. m: d% H0 @% q  c
  58. */
    9 P$ w) j( ^: Q' \$ X
  59. static void _ShowPNGEx(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)" c- {8 B2 ~4 v1 n
  60. {   
    & Z: b( s/ d1 t9 l/ P% b- B6 f

  61. % A% w6 ^" M; W) |5 v# o  q
  62.      /* 打开文件 */        
    5 h0 {1 G2 c% `* R/ @( X! X
  63.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    + |, g, I7 e/ Z
  64.      if (result != FR_OK)
    8 P. T& W" `, |" M
  65.      {7 S( Z0 Z% ^6 B" O
  66.          return;
    0 b# Z( Y1 [, p, O9 O% K
  67.      }+ Q9 F% h/ @3 {, i# L7 L+ u6 f* E
  68.    
    8 P& Q; @! A" k' D0 d9 D) e- X
  69.      GUI_PNG_DrawEx(_GetData, &file, usPOSX, usPOSY);
    : A! g' a/ @! d7 ?$ }( s9 D
  70. ( U- F" m, q+ o7 {: s- U
  71.      f_close(&file);3 g+ i6 X" {9 w% l- |
  72. }
复制代码
l  主函数
  1. /*
    ; @. U% q* \7 L9 A3 \
  2. *********************************************************************************************************
    ' m. p! i& O: L. B9 M% R$ y
  3. *    函 数 名: MainTask8 B8 t/ _# l* z8 q$ l9 _
  4. *    功能说明: GUI主函数
    $ E- E( O# D2 J( L! N2 K
  5. *    形    参:无) W2 Y& c1 }" s$ U2 R. L
  6. *    返 回 值: 无
    : p) {' j/ l* j: P
  7. *********************************************************************************************************
    " M: i9 t7 h; ?! F% L$ B  ]
  8. */
    0 Y% G. `" O* v
  9. void MainTask(void)4 X6 p$ K* z$ w1 K2 J" W" G6 o
  10. {   ) N- [2 T+ }& f, Q. ?
  11.      GUI_Init();  j- N- V% V: N6 K5 l1 ~
  12.      GUI_SetBkColor(GUI_BLUE);) l4 v9 v1 l; d3 }6 K
  13.      GUI_Clear();
    3 s" U+ G8 u! z+ s
  14.     * f" A: {/ F) C) h$ u1 a/ i
  15.      /* 绘制无需加载到存储器的PNG文件 */. I/ M  v! m2 @' g$ Q/ i
  16.      _ShowPNGEx("3.png", 0, 100);
    . h: J, q1 ]% B. [: y$ ?
  17.      _ShowPNGEx("4.png", 100,100);
    . I) G5 L$ U3 [$ {4 M( z
  18.    
    1 _, J: T4 w1 }
  19.      while(1)
    2 f& p5 _8 }* f$ j
  20.      {                 : r" D9 J# o0 e: \$ F% ], q7 M
  21.          GUI_Delay(100);: n) ^. e3 e/ w! J+ p/ E
  22.      }
    , V/ W7 I: J8 y2 c
  23. 5 A- d1 i; o2 I+ Y  k2 D+ s" j
  24. }
复制代码
实际显示效果如下:
14.9.png
! u6 N) `5 ]+ K; G+ a
14.4  实验总结5 x) H& y5 }4 i, w: Y2 s
    有兴趣的可以了解一下PNG压缩方面的知识。如果只是API应用的话,这部分知识还是比较容易学会的。PNG图标用到的地方还是比较多的。- v6 h/ z3 P7 e# O3 R, s: h

) `" m) Z3 ?# G% p3 y, D
蔚飞 回答时间: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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版