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

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

[复制链接]
baiyongbin2009 发布时间:2015-1-15 14:34
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第14章      PNG图片显示
# @3 d. o- M4 [6 K) {: x
    本期主要讲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
8 Z% p3 Z; t8 o* n* k8 R' p. j6 V
14.1.1      PNG格式图标转换
    某些情况下,将PNG文件作为C文件添加到项目中非常有用。对此,可完全按照前面介绍的“JPEG文件支持”下的相同方式来执行。此外,位图转换器能够加载PNG文件并将它们转换为C位图文件。下面举一个例子,跟大家演示下:比如我们要转换如下的PNG图标:
. L5 K3 m, U2 z" ~
14.2.png
l  打开软件加载上面的图片
14.3.jpg
* p1 `; n  F. s# a& v% u( I
l  加载后点击Convert即可,点击后没有任何现象,直接去图片所在的文件夹找即可

/ D+ p1 l3 R$ m$ P3 i) b% S8 V
14.4.jpg
实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)
    2 f* f5 }0 v0 i) Z4 `- |( k
  2. {   
    " ~  H. {- S4 P8 n0 h/ N
  3.     GUI_Init();
    : h8 \) B# v( ~$ |& H. m
  4.      GUI_PNG_Draw(_acmusic, sizeof(_acmusic), 20, 20);; H1 ^7 f$ O0 j3 F
  5.     while(1)
    ( V' M2 h" q! Z( N
  6.     {
    + V$ ]) n7 b: D
  7.         GUI_Delay(100);
    , n' {' @4 M7 R( R
  8.     }& m4 I: C' q0 I3 B
  9. }
复制代码
    由于在Bin2C的小工具是来自MDK安装目录中,这个工具只是评估板,无法实现PNG图标的透明色效果。模拟器实际的显示效果如下:
14.5.png

5 f6 E" P  k$ A$ q$ ]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
: F* s( [6 H" P. F6 c% I
' K5 `# R4 h+ y0 X/ r
收藏 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. /* 申请一块内存空间 并且将其清零 */6 Q) T3 m; o0 _" T
  2. hMem = GUI_ALLOC_AllocZero(100000);) S2 N8 d# M7 k* a! Y% C. _) d7 j6 x" D
  3. /* 将申请到内存的句柄转换成指针类型 */
    3 J! y9 |. o1 ?( C  _, J
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);
    . T, O# B: K9 G4 t7 l4 {' Z
  5. /* 释放申请的动态内存  */3 {8 X' [" m3 c8 L6 i5 P9 S% d
  6. GUI_ALLOC_Free(hMem);
复制代码
    这里还用上面的图片作为显示对象。先把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*
    " |3 x& z2 i" ]( W
  2. *********************************************************************************************************+ q4 b. P1 V1 z! N
  3. *    函 数 名: _ShowPNG! H+ O) g0 P& y4 ]
  4. *    功能说明: 显示GIF片
    + z6 Z- ~$ x2 g+ H  ~( f! O
  5. *    形    参:sFilename   要显示的图片名字
    3 }; T+ u7 e, J8 v
  6. *              usPOSX     显示位置X
    & e# I7 W% K. ?" b
  7. *              usPOSY     显示位置Y
    8 Z/ w0 j* v" z# q
  8. *    返 回 值: 无/ V5 A; V0 ]! E8 w( O* k
  9. *********************************************************************************************************1 ^* r  z- T! o" A1 A. Q
  10. */1 u6 j9 j( ?; q$ k" g
  11. static void _ShowPNG(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)6 f+ t$ V" o9 E! A' o! Y( f4 m
  12. {
    3 ^# ~% l+ |$ {0 X
  13.      GUI_HMEM hMem;7 q, @  D8 \) V  k& D
  14.      char *_acBuffer2;8 z7 X) W7 @4 }6 B( |+ x
  15. . H/ H$ V, _, E8 J! h# A$ |, J
  16.      /* 申请一块内存空间 并且将其清零 */
    , m: X; b3 S1 T" z9 p! @- |
  17.     hMem = GUI_ALLOC_AllocZero(500000);. C2 S0 s. E6 u# i7 x
  18.      /* 将申请到内存的句柄转换成指针类型 */
    . _9 t1 S) C' u) c8 \' }2 V( f
  19.      _acBuffer2 = GUI_ALLOC_h2p(hMem);
    " H0 T. b0 P! k$ A6 i9 U9 t

  20. 5 s( n0 i" i6 e% y. i' W
  21.    
    5 }3 f0 V: {& f) k8 Q
  22.      /* 打开文件 */        
    ' h& M5 z3 z3 V; S( {
  23.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    5 P2 V, M$ I! w
  24.      if (result != FR_OK)8 W# _. k1 f  ^% `! h3 g
  25.      {
    ! M" J1 Y& |) T% q" E$ d
  26.          return;
    : i- @/ e) s- d( q1 ^" o- R8 p
  27.      }
    3 w- [# c' r0 a
  28. 7 a) q5 u' k$ O  m0 ^
  29.      result = f_read(&file, _acBuffer2, file.fsize, &bw);
    1 y! _- c  z; M' H5 J
  30.      if (result != FR_OK)5 g1 ~; t& L0 S/ x3 H6 x
  31.      {
    & o/ ^0 j5 u& b5 }& p
  32.          return;
    ! e* ?1 V6 L, B1 W
  33.      }
    - n2 z% [  O8 b% a7 Q

  34. ) Z# g% m0 i# Y/ b
  35.      GUI_PNG_Draw(_acBuffer2, file.fsize, usPOSX, usPOSY);% J* n. W7 f7 ]3 N4 I8 S7 v: D
  36.      GUI_ALLOC_Free(hMem);0 f* K! s! j, i6 r
  37.      f_close(&file);
    2 ^" n3 A7 Q) ]& u. C
  38. }
复制代码
l  主函数
  1. /*5 Y. i  A: h* [( x% a% @+ x3 {
  2. *********************************************************************************************************9 f% F' T3 [( ^5 E2 @: k. t" [5 B
  3. *    函 数 名: MainTask7 |) i8 j4 B8 r8 n' Z3 [
  4. *    功能说明: GUI主函数) X3 i  a# O) j, n8 H$ t
  5. *    形    参:无
    9 ]4 |" u. S, e- K- C3 k+ z7 Z) k, q
  6. *    返 回 值: 无
    - }; x7 [: B1 L4 ]# i
  7. *********************************************************************************************************
    0 X( f( p  {- B$ H: w' J
  8. */$ Z8 v# l8 F' q4 l3 |: T& X2 m
  9. void MainTask(void)
    * g2 Y* F2 \1 x6 p. K+ c+ i
  10. {   
      V' i5 z! Y8 Q. v$ U+ B# R
  11.      GUI_Init();' b  M( J5 u3 y0 c9 E) B
  12.      GUI_SetBkColor(GUI_BLUE);
    1 O! Y7 L) _- O9 Y! d& u$ v
  13.      GUI_Clear();
    $ ?7 n  z8 N7 h8 }& r6 v
  14.     7 m2 n& E$ Q5 l' g) I' U
  15.     /* 绘制已加载到存储器的PNG文件 */% }7 s; h* n' X+ `
  16.      _ShowPNG("1.png", 0, 0);
    : y( D$ B* \. S: P7 ^6 P7 h) W7 X
  17.      _ShowPNG("2.png", 100, 0);
    / D3 z  t+ P' f9 N" O
  18.     ( m3 d/ E" j" g$ w: E2 k( c$ H
  19.      while(1)5 I/ T1 a" R  ^$ e( l# k
  20.      {                 * G; l" ]! B5 ^% D
  21.          GUI_Delay(100);1 q, q, `% z2 m
  22.      }7 d* d3 B3 t  Y) `

  23. , a/ X( W4 w$ A9 V2 n1 d
  24. }
复制代码
实际显示效果如下:
14.7.png
; }) a$ K( T6 z- O- k) }# t
    编译,链接工程的时候会出现大量如下的警告:

( q" K% e' |& n8 y
    14.8.jpg
    这个是由于使用的PNG库和现在STemWin5.22版本不匹配造成的,PNG的库是用5.18版本的,最新的5.22版本官方还没有更新。

, n) }' P0 }: g( v0 r
baiyongbin2009 回答时间:2015-1-15 14:38:58
14.3  绘制无需加载到存储器的PNG图片
    绘制无需加载到存储器的PNG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于PNG比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. /*! D% z6 L8 J3 B, v, K
  2. ********************************************************************************$ |0 W5 m7 u: [% k
  3. *7 t8 S6 s  c% c; Q7 k
  4. *       _GetData1 s( o9 ^% I/ Q8 Q
  5. *
    . s  e- T& E& H/ Y/ J' B# d
  6. * Purpose:
    ( V; E# ]" t4 o
  7. *   This routine is called by GUI_GIF_DrawEx(). The routine is responsible& }' y" D( c3 _% b% I
  8. *   for setting the data pointer to a valid data location with at least
    # [! n1 q$ ~" H/ B7 j- |2 n: V
  9. *   one valid byte.' ]" d' G; H. _% R  T  z
  10. *' b; ~0 K' \2 F8 S
  11. * Parameters:( o+ R2 ^- m, b( K. X. t
  12. *   p           - Pointer to application defined data.# Q; }& R" e/ E, X3 [
  13. *   NumBytesReq - Number of bytes requested.
    6 }( A( n, b( d& ^/ G" v9 \
  14. *   ppData      - Pointer to data pointer. This pointer should be set to
    8 w) Z; W& q8 A! {6 p, ?  F3 Z
  15. *                 a valid location.$ }' M/ G3 n+ A' q
  16. *   StartOfFile - If this flag is 1, the data pointer should be set to the
    1 K, f1 ^! ?; h1 S* T( y5 P
  17. *                 beginning of the data stream.( S  g4 T& j5 I2 O, C" W
  18. *
    . V/ Y( N: ~5 q6 s
  19. * Return value:
    6 W- l8 u# u0 |& T( o
  20. *   Number of data bytes available.
    % \2 j# t# H8 s' M& G( V
  21. *********************************************************************************: q- U8 g# G$ _) [# L" W" D8 \
  22. *// [/ @' J$ m4 I$ f5 s! Y9 B
  23. , d/ s4 y& E' J+ I1 N) k1 E$ ^
  24. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) {
    * ]# L* `9 I! F5 L/ E4 g, A
  25.      static int FileAddress = 0;
    ' U6 z8 \; |8 L" @: N
  26.      FIL *file;( R: F+ J# ^0 C2 q* |: b' m
  27.      DWORD    NumBytesRead;
    2 j2 `& L) J3 F5 {3 x6 ?& u
  28.      U8     * pData;! ], e, S, E' k6 b# Z/ X: r

  29. - z1 F( q5 {9 |1 T+ A4 H
  30.      pData  = (U8 *)*ppData;
    # `3 Z' W2 O2 m% ]
  31.      file = (FIL *)p;% a) J5 [; o1 ?0 P9 n( v& W8 ]* k1 W
  32.      //
    # ^# D; f; ^% d; {* J
  33.      // Set file pointer to the required position8 r3 r4 _2 V* \3 r: v& i& {6 K8 l
  34.      //
    9 C) R% T' S- U
  35.      if(Off == 1) FileAddress = 0;
    ) a2 p9 s+ Y6 Y/ U9 t) C6 |; e  l% N- n
  36.      else FileAddress = Off;
    4 P5 g8 W1 B. C+ Y0 c3 [7 r+ G+ M
  37.      result =f_lseek(file, FileAddress);
    ; l  K4 h, t$ z, t, ^4 K! J
  38.      //1 _  ?9 v9 \- {6 b% p
  39.      // Read data into buffer
    . I3 l1 V6 @) V+ N) F4 D2 y4 r- s% `
  40.      //: _/ ]5 V9 s, p
  41.      result = f_read(file, pData, NumBytesReq, &NumBytesRead);
    ( S7 F  T. ?& q* I7 k

  42. 3 c$ {/ h1 T2 n
  43.      //
      D5 y. f, d8 J$ d) v
  44.      // Return number of available bytes: G; V( {. m5 p9 X
  45.      //
      Y' m; X" F* ~6 t: q( d% B0 ^
  46.      return NumBytesRead;0 i0 r( X4 n" R$ [

  47. 0 H3 L* A4 r) }( p
  48. }
    ) }6 K! _- n5 w8 U0 K
  49. /** p1 X* j- w3 U+ V3 r' s, u
  50. *********************************************************************************************************6 E' F7 Q* X$ Y6 E# ^
  51. *    函 数 名: _ShowPNG
    , e5 e; X  l# Y( R) r# O2 j% P. ~
  52. *    功能说明: 显示PNG图片7 G* C3 l' v* t. R
  53. *    形    参:sFilename 要显示的图片名字1 [) ?  {: G1 l. L( {$ u1 H
  54. *             usPOSX    显示位置X3 [: G+ e1 `) `
  55. *             usPOSY    显示位置Y" J$ Y7 e* r7 ]" t
  56. *    返 回 值: 无
    ; E; ?% P5 X$ U& y4 |
  57. *********************************************************************************************************
    5 j9 u+ r+ W2 {5 T
  58. */
    - W% V1 a& d# g  J3 k4 z0 C
  59. static void _ShowPNGEx(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)% Q" @' @8 t# }8 X  R
  60. {   
      h  j4 T5 G" j+ a1 U& h
  61. - P- N1 w! D2 o# `  b
  62.      /* 打开文件 */        
    3 {: |; @1 f, R2 u# q" C) x
  63.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    6 u( E9 X- j' ]5 M
  64.      if (result != FR_OK)
    8 n/ W* B0 g/ W2 V3 o
  65.      {
    ! s0 {- o" i. P, g) l: b
  66.          return;
    % Q) X  _  D5 i2 ~9 ~4 Q
  67.      }0 Y0 ^" S' v1 V6 ?
  68.    
    & _* S$ M. F3 o3 H9 ^
  69.      GUI_PNG_DrawEx(_GetData, &file, usPOSX, usPOSY);
    0 l: \. L- m' }1 C/ u

  70. 9 s  }- M6 \% D0 y
  71.      f_close(&file);
    ) Z) q3 T0 l: S4 C
  72. }
复制代码
l  主函数
  1. /*6 y% G+ f- u0 U2 T
  2. *********************************************************************************************************
    : r: g7 }$ c7 j6 C
  3. *    函 数 名: MainTask/ x" R7 D5 q* I. X
  4. *    功能说明: GUI主函数
    , Y& ?! ?$ v4 V$ A  f5 L) J5 M
  5. *    形    参:无0 o6 e* r1 Z9 C$ h- `% I
  6. *    返 回 值: 无, k7 k! U6 n' y) }, i4 i* {
  7. *********************************************************************************************************
    ; C7 \) ^3 y" H9 j5 \
  8. */  G. r5 O* X' V6 B) s
  9. void MainTask(void)
    + V+ I# ?9 m7 q6 K. Z% a
  10. {   / n! N7 ~9 ~% n* _: \
  11.      GUI_Init();
    # q. K2 U% Q: z+ N
  12.      GUI_SetBkColor(GUI_BLUE);
    ' {2 K1 h/ o" k  f/ \  s
  13.      GUI_Clear();
    & ]4 v3 |4 [7 L$ _. Y- q
  14.    
    . Q8 ~! o, X2 r! A: _; P' ?3 b
  15.      /* 绘制无需加载到存储器的PNG文件 */3 e; I) R* @& r" a* D# `  k
  16.      _ShowPNGEx("3.png", 0, 100);
    7 P' Z: Q5 c/ ?3 E
  17.      _ShowPNGEx("4.png", 100,100);
    ) r; d, Y: ~& I7 Y" D# K
  18.    
    4 l2 s! [& t) s- C! B: I# v
  19.      while(1)
    + E0 M3 P0 G- A/ q% n7 \; F
  20.      {                 
    ! \1 w  q4 y4 e! W# o& S
  21.          GUI_Delay(100);
    8 A" \+ F& W6 f# U0 T% h9 s+ e
  22.      }
    # z3 Q& ~: n# w0 b/ ^' Z! i
  23. " _& j% [' d- Y0 p5 ?1 x& I
  24. }
复制代码
实际显示效果如下:
14.9.png

  k' L- P# \$ \* K) K% o' z) M14.4  实验总结
7 i& s& _& R6 W* P8 Z
    有兴趣的可以了解一下PNG压缩方面的知识。如果只是API应用的话,这部分知识还是比较容易学会的。PNG图标用到的地方还是比较多的。5 i7 \4 h  ]+ f$ q. M9 R; W
0 u2 J8 {+ U& A: O- T+ F
蔚飞 回答时间: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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版