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

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

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

$ W& E5 D  Z4 m9 Q- C  k1 Z9 N+ ^, |
    本期主要讲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
  d. J, N# ~' Y/ j0 E1 C' e
14.1.1      PNG格式图标转换
    某些情况下,将PNG文件作为C文件添加到项目中非常有用。对此,可完全按照前面介绍的“JPEG文件支持”下的相同方式来执行。此外,位图转换器能够加载PNG文件并将它们转换为C位图文件。下面举一个例子,跟大家演示下:比如我们要转换如下的PNG图标:
8 Q" A+ b( E8 `$ T9 t! ]4 K
14.2.png
l  打开软件加载上面的图片
14.3.jpg

4 A9 w; C. _. ], R, E
l  加载后点击Convert即可,点击后没有任何现象,直接去图片所在的文件夹找即可
$ i; Y2 S% g! y- f7 a7 ?0 ]
14.4.jpg
实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)
    + Z/ q6 l7 l3 Y: S. @/ }7 v, l
  2. {   - w/ x9 B/ w8 J6 u. n
  3.     GUI_Init();# o0 [/ T3 `* W) K( H( A) I* q
  4.      GUI_PNG_Draw(_acmusic, sizeof(_acmusic), 20, 20);" Y4 v& t' X6 g. R! I5 J3 A  T
  5.     while(1)
    * Q; i: N( x) O+ {
  6.     {7 \) c8 h" J* f7 d; D! _$ E
  7.         GUI_Delay(100);# o: G  C5 F( s: l" g9 l" d
  8.     }
    # \/ O% B, f8 W
  9. }
复制代码
    由于在Bin2C的小工具是来自MDK安装目录中,这个工具只是评估板,无法实现PNG图标的透明色效果。模拟器实际的显示效果如下:
14.5.png

% E+ ^% [* I8 m14.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
% ~, b% {9 X3 W# N9 ~9 D
+ C0 E0 a6 Z* s+ b5 k8 w
收藏 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. /* 申请一块内存空间 并且将其清零 */
    ' K; b, J. w  i0 Q/ U" ~
  2. hMem = GUI_ALLOC_AllocZero(100000);5 Y& |: L2 }# G: i1 h; ^
  3. /* 将申请到内存的句柄转换成指针类型 */" E2 J. [; _3 y3 f% y) c5 ~- n
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);  c; J  {% b# [, _* r+ Z
  5. /* 释放申请的动态内存  */+ d! G7 A& ~( ~! |* T5 w" x8 a
  6. GUI_ALLOC_Free(hMem);
复制代码
    这里还用上面的图片作为显示对象。先把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*, t  ^, N' n. @' n- h5 [
  2. ********************************************************************************************************** Q3 L3 M( Q; l- s# n8 r
  3. *    函 数 名: _ShowPNG
    8 g1 I, Z+ N  ?3 y: E$ l
  4. *    功能说明: 显示GIF片4 P8 @$ K: F( Q0 P- P5 X+ b
  5. *    形    参:sFilename   要显示的图片名字& U( `7 O' q& m7 @) `
  6. *              usPOSX     显示位置X4 \, W4 k4 v) v8 c8 W4 l
  7. *              usPOSY     显示位置Y
    ! }, @0 I( C& w. R) ?: X3 m
  8. *    返 回 值: 无
      ~0 T5 \. [+ x% j$ C5 D8 i
  9. *********************************************************************************************************% d* a) Z: I/ ^8 v
  10. */
    5 x& F: q% Y$ `" e$ V) O' E: E) k. _
  11. static void _ShowPNG(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)3 x/ ~! {1 f* y! N+ c: C
  12. {
    # q% w) H* t. t6 |$ q" d
  13.      GUI_HMEM hMem;8 Z4 a# X, B2 F/ a
  14.      char *_acBuffer2;( H0 a. c8 y5 j( g, Y) u. \

  15. 8 i% h' L# ^$ d3 T) r1 h7 n
  16.      /* 申请一块内存空间 并且将其清零 */
    0 ]' H/ |6 f# ^4 p4 S
  17.     hMem = GUI_ALLOC_AllocZero(500000);
    6 T% Z4 u) C# w$ P8 u
  18.      /* 将申请到内存的句柄转换成指针类型 */* [, z. ~. V; c( X) D/ `( ~/ b
  19.      _acBuffer2 = GUI_ALLOC_h2p(hMem);- J# J% @) l2 w- Z

  20. ( n# r) }+ k% ^2 k) a) c
  21.    
    # u) G; G) v: {5 y& I( F! h8 x
  22.      /* 打开文件 */        
    % m7 \( Z+ p8 o. N3 H. k. H. L
  23.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    ' ]& I5 P- X( C  |" f
  24.      if (result != FR_OK)
    * i  ~8 k/ E1 M2 o
  25.      {9 Z- {' i" _7 K( d$ G" \1 G
  26.          return;
    ' o: @# D3 R: @$ c, @
  27.      }
    * Q% `2 i: L7 T2 v9 @5 P

  28. 3 l9 c& J3 Q9 B- k7 N3 O- Y
  29.      result = f_read(&file, _acBuffer2, file.fsize, &bw);
    1 N) ]' r/ {  w7 Z% |5 J
  30.      if (result != FR_OK)) r% W: W: Q) Q  v; C3 p, ?
  31.      {# ^$ c9 H) G% P
  32.          return;
    / u7 M0 n  G. Z1 l) {. u
  33.      }
    2 |$ W, _6 I. h0 n5 H  m2 D, l! x
  34. ; s9 h8 |. A5 `- F9 b- m  U) h9 X) a
  35.      GUI_PNG_Draw(_acBuffer2, file.fsize, usPOSX, usPOSY);& R0 K( X1 H. H  k/ y5 e% K+ E& @
  36.      GUI_ALLOC_Free(hMem);; `1 I! L( z( {: q6 f2 `
  37.      f_close(&file);3 r% O! u& y' X
  38. }
复制代码
l  主函数
  1. /*
      x( ~9 I% U! P
  2. *********************************************************************************************************
    $ N7 J' U( x. n# [0 f8 c
  3. *    函 数 名: MainTask/ E" o  ^; T0 h! @8 o4 e7 L! ?6 b
  4. *    功能说明: GUI主函数
    2 I2 J! q7 b& w$ X6 J
  5. *    形    参:无4 M3 w9 w2 M% M1 E% O
  6. *    返 回 值: 无4 d4 Z5 ^1 f8 Q  S
  7. *********************************************************************************************************
    5 b$ F4 g8 p4 K& p4 p# }. H
  8. */" \! U9 }2 c5 f
  9. void MainTask(void)
    $ {0 l% m" `& e( b$ I
  10. {   
    ' D( ~1 C+ [: ~* U+ o7 B
  11.      GUI_Init();
    8 W1 Q3 Q" M, e6 Y2 O. J
  12.      GUI_SetBkColor(GUI_BLUE);: v0 x3 w4 N: V5 ~! D* W4 O; v
  13.      GUI_Clear();' T# L% M& X0 @' x7 B
  14.    
    , h4 A6 I4 D# ]" k+ ]2 m2 v2 [
  15.     /* 绘制已加载到存储器的PNG文件 */  K, Z" q6 O2 R" Y8 U/ @2 r% L
  16.      _ShowPNG("1.png", 0, 0);
    7 Y+ {0 H% L, E
  17.      _ShowPNG("2.png", 100, 0);2 D  v4 a4 h2 _% m' L& S
  18.     9 E4 a3 {5 b* u9 d, D4 m
  19.      while(1)+ {- d; L: w+ g% v7 m$ C2 S: F
  20.      {                 
    4 r& ~* Q8 e1 \( Y$ I! d; v! ]+ L7 L
  21.          GUI_Delay(100);
    ' r( h2 s% g" `. H3 [
  22.      }
    # e3 s' E# t; n1 ~5 b" m9 P6 |

  23. 3 `( J3 I7 L: [4 i; n
  24. }
复制代码
实际显示效果如下:
14.7.png

! }. y1 p0 M0 L6 a
    编译,链接工程的时候会出现大量如下的警告:
# j6 z3 e6 D$ v4 \, e
    14.8.jpg
    这个是由于使用的PNG库和现在STemWin5.22版本不匹配造成的,PNG的库是用5.18版本的,最新的5.22版本官方还没有更新。
7 m3 B8 Q& {! z, p5 H
baiyongbin2009 回答时间:2015-1-15 14:38:58
14.3  绘制无需加载到存储器的PNG图片
    绘制无需加载到存储器的PNG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于PNG比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. /*
    " E$ h; m9 O, s+ }" U3 t: t
  2. ********************************************************************************. R6 a+ X5 ?; O# F; w# o
  3. *" P2 B2 h! [0 m0 [. ^- z
  4. *       _GetData
    . J; E, D$ W8 t0 e$ f) R
  5. *
    $ J. G, V/ R+ r
  6. * Purpose:" z$ y- R' q$ ]5 q2 Y
  7. *   This routine is called by GUI_GIF_DrawEx(). The routine is responsible1 x9 D% j/ x; d& ^: V  w$ O
  8. *   for setting the data pointer to a valid data location with at least* |& f( T3 e# d+ F
  9. *   one valid byte.
    ' S* ]+ s3 g! Z# }) W- D
  10. *
    6 b" H+ j) G7 q( X9 D! r
  11. * Parameters:" e7 C% x* x8 _7 j! U. G
  12. *   p           - Pointer to application defined data.
    % [- W/ q" \  D8 O3 i1 s4 q  Y
  13. *   NumBytesReq - Number of bytes requested.
    8 N, s7 ^  l; |' h
  14. *   ppData      - Pointer to data pointer. This pointer should be set to
    $ V7 S6 y# f; \' u
  15. *                 a valid location.2 c4 J! j" W0 E* _! f# _4 a: ~
  16. *   StartOfFile - If this flag is 1, the data pointer should be set to the! `; e6 B0 m  C9 G, A0 S
  17. *                 beginning of the data stream.* G7 w1 o1 D* _. Z
  18. *
    ) W$ V! D0 ^# p3 w/ y- L
  19. * Return value:0 J+ c* u8 r' Z) z' [4 l+ y% j
  20. *   Number of data bytes available.
    1 A7 I% P8 y0 X$ Y$ Z& Z
  21. *********************************************************************************
    ( S: U# g: S' }/ J
  22. */
    3 w6 G" y* J6 Y5 R' D
  23. 3 s2 M8 D' x  M6 |; v
  24. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) {
    ( X! e1 ]0 }  E; E. u
  25.      static int FileAddress = 0;( ]6 v1 G% u2 f3 b- h
  26.      FIL *file;
    ' b  H# }; W! e+ H) V1 U& ]7 Q
  27.      DWORD    NumBytesRead;
    0 g) X) T' [+ v9 |9 |
  28.      U8     * pData;# I& E  s, ?5 L/ a. N$ T

  29. % A9 V, U) ~" v0 ^6 e
  30.      pData  = (U8 *)*ppData;
    # F( b; |: S) T4 G- I
  31.      file = (FIL *)p;. n" c& H6 T! _, Q! h
  32.      //4 e. l2 P- `' `
  33.      // Set file pointer to the required position
    + a' n) E8 ~1 g& Y. l
  34.      //1 ?' g9 v/ D, O% F2 Y' Q
  35.      if(Off == 1) FileAddress = 0;
    9 W' S$ {4 [: q) n4 @+ I
  36.      else FileAddress = Off;: g7 s: w; b; d
  37.      result =f_lseek(file, FileAddress);
    & r9 p0 D4 Q9 ]! t3 b. }/ }* V
  38.      //
    5 x& j2 g  P2 H9 e+ U* K1 C
  39.      // Read data into buffer
    ' I8 \( m! y. f4 Z0 e9 M% R% l
  40.      //9 v3 y9 Z5 |3 R  j4 S) x
  41.      result = f_read(file, pData, NumBytesReq, &NumBytesRead);
    3 i, S  K' _" ?' x& X1 C# e2 x" N; Q
  42. ; h0 i! K5 }9 t' S9 a2 y0 v" Q
  43.      //( a+ L. j0 w: @! B) S3 `
  44.      // Return number of available bytes
    , i. J' `- I9 Z4 J  N$ h
  45.      //" d( D+ N" L/ e; v" B( m# Q0 i
  46.      return NumBytesRead;. D1 z1 v& o' W1 h5 f9 i6 l2 o1 O0 K
  47. - n! |" ?3 ^( }  b: E: {
  48. }) Z4 C0 R+ _3 ^% u# U% h$ L2 z
  49. /*4 n( s4 i3 X9 F8 e( n
  50. ********************************************************************************************************** J; c9 J* j  O8 b5 m& [6 p8 x
  51. *    函 数 名: _ShowPNG3 U, j2 C: y3 V: p( ^9 b6 s
  52. *    功能说明: 显示PNG图片
    ; q$ O) V# L) o
  53. *    形    参:sFilename 要显示的图片名字% T2 F4 K3 V4 X& i1 }& e
  54. *             usPOSX    显示位置X2 Q' O" ~- y: X! q: a! S, l+ ~1 l
  55. *             usPOSY    显示位置Y7 O. w& c" k& K* Q# u+ H: E6 S9 b
  56. *    返 回 值: 无
    ( w# ]5 ~# \' V1 {* n
  57. *********************************************************************************************************( }/ d, p5 H) }* h* U& X
  58. */1 }8 R( Z7 a/ f' K4 ?0 b% m3 `; Q
  59. static void _ShowPNGEx(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)
    7 V# {  ?! n# y2 x# |2 e
  60. {   
    , H. H0 p$ L5 G
  61. 6 @% ~1 \7 [7 U  o  Z" g3 v( v( P
  62.      /* 打开文件 */        
    % \% v* O7 B" X2 t1 @4 h
  63.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    : A6 c' N, m. T* r- K+ G* k
  64.      if (result != FR_OK)
    7 x! F) r5 S4 r$ l( M
  65.      {2 {2 b/ L* J8 J- z$ W
  66.          return;( @) V4 \1 J( y$ ]4 p5 t) D
  67.      }
    ' ?1 [$ P- y9 m3 K: t5 O; w
  68.     1 b) b; I/ e* Q$ Y( F$ B* t
  69.      GUI_PNG_DrawEx(_GetData, &file, usPOSX, usPOSY);
    7 f3 X$ d& d* v0 W% v& H/ o7 m/ F

  70. 6 `9 {; C: p7 b, |) X# R+ E
  71.      f_close(&file);
    & N$ c! N3 [% _2 `- y; _
  72. }
复制代码
l  主函数
  1. /*+ A, @2 P- b: M* L/ n9 ]- R, |7 V
  2. *********************************************************************************************************
    3 X+ B! s8 n- X# G& a3 P
  3. *    函 数 名: MainTask9 G" c/ c  h. W: z
  4. *    功能说明: GUI主函数
    ( e/ M+ f; x2 J0 Z# R0 e0 o
  5. *    形    参:无
    " J8 Q3 [3 O& C6 S
  6. *    返 回 值: 无: K; E. ^8 \- `+ r4 h7 q) z; K
  7. *********************************************************************************************************% X4 v2 i! H4 }- F* m. J1 C3 z9 D2 m
  8. */
    - N: I2 I7 c$ r9 ?+ {
  9. void MainTask(void)" f2 D2 V, V- v
  10. {   
    " `' I2 n0 h( r
  11.      GUI_Init();, a0 Q" h1 p0 K
  12.      GUI_SetBkColor(GUI_BLUE);
    - n  M1 a3 t+ [& G( e7 B
  13.      GUI_Clear();
    0 B( T2 \/ Z& S' C1 {: a
  14.     . U, c: o; z. u" L+ T/ |  D
  15.      /* 绘制无需加载到存储器的PNG文件 */" }7 j: e5 Z2 L2 z
  16.      _ShowPNGEx("3.png", 0, 100);
    6 H) B  s+ A" |+ ]- w1 f
  17.      _ShowPNGEx("4.png", 100,100);
    . f7 p6 h  S8 u8 u" D
  18.     0 Q7 x& O+ O5 |. N! r% i- s- i2 Y
  19.      while(1)
    1 M6 j4 g2 G( Y' V& f' q( `
  20.      {                 
    5 D* S, t) H# i8 ]# v% W
  21.          GUI_Delay(100);  m9 w7 @2 u1 P& K$ |9 e1 w
  22.      }* O% {) G$ R; d

  23. ) V3 s1 I) Z( G% H9 A
  24. }
复制代码
实际显示效果如下:
14.9.png

5 ?$ \% f- n/ b( }/ n! n& c14.4  实验总结
9 d1 G' E" k% S* I- `3 s
    有兴趣的可以了解一下PNG压缩方面的知识。如果只是API应用的话,这部分知识还是比较容易学会的。PNG图标用到的地方还是比较多的。# U3 a8 g. w! f- p* O) k
$ p. t) J, _, e( x3 Q
蔚飞 回答时间: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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版