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

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

[复制链接]
baiyongbin2009 发布时间:2015-1-15 14:34
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第14章      PNG图片显示
1 }5 ^: m2 V! C1 u1 j# B
    本期主要讲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
9 S3 y$ w  r: U+ V7 d8 [
14.1.1      PNG格式图标转换
    某些情况下,将PNG文件作为C文件添加到项目中非常有用。对此,可完全按照前面介绍的“JPEG文件支持”下的相同方式来执行。此外,位图转换器能够加载PNG文件并将它们转换为C位图文件。下面举一个例子,跟大家演示下:比如我们要转换如下的PNG图标:

) k" o/ ]/ E4 |, F0 m, I2 G1 t
14.2.png
l  打开软件加载上面的图片
14.3.jpg
* F/ N; v* ~5 r# K
l  加载后点击Convert即可,点击后没有任何现象,直接去图片所在的文件夹找即可
7 G8 N; ~4 j$ s6 L% v0 c
14.4.jpg
实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)9 s8 T+ S4 Y' k' w2 b& e
  2. {   
    9 S: y0 J# n7 {1 \; J+ ]
  3.     GUI_Init();
    - W8 P2 K8 }# p7 d
  4.      GUI_PNG_Draw(_acmusic, sizeof(_acmusic), 20, 20);
    / c  e6 p% x$ S. q- g$ M
  5.     while(1)5 m8 Z" M2 y( u- i' m  N
  6.     {$ G& H: F* T$ m8 Z4 `' p, M6 j  M
  7.         GUI_Delay(100);
    & B  g! ^$ Q- w  i! q* O! m) r
  8.     }
    1 N/ N/ i, `; s  m) K- a/ K3 f
  9. }
复制代码
    由于在Bin2C的小工具是来自MDK安装目录中,这个工具只是评估板,无法实现PNG图标的透明色效果。模拟器实际的显示效果如下:
14.5.png
. ^5 F7 r  l6 E0 \
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
( Y, K7 F1 h% ~+ a

) E7 D6 q& `. E5 S9 [( x4 c
赞 收藏 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. /* 申请一块内存空间 并且将其清零 */
    & D. I2 \. H9 r% ^
  2. hMem = GUI_ALLOC_AllocZero(100000);, D0 m0 u0 h5 W# g& m* K  N
  3. /* 将申请到内存的句柄转换成指针类型 */& @; N; C" w& Z3 t
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);
      H, T( H% M+ ~* b+ O
  5. /* 释放申请的动态内存  */9 Q! V9 \) \: M/ s. d2 l# `6 f
  6. GUI_ALLOC_Free(hMem);
复制代码
    这里还用上面的图片作为显示对象。先把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*
    / z# T2 Y' ]9 ?0 P7 ^; Y- I: R
  2. *********************************************************************************************************
    $ ~; S& \% E! \. t$ ?
  3. *    函 数 名: _ShowPNG# S6 Q0 f' q8 C! D% ^) Q
  4. *    功能说明: 显示GIF片' o1 v- F8 F" t$ ~/ o/ n
  5. *    形    参:sFilename   要显示的图片名字* \  p/ Y  U) |; m, H; c
  6. *              usPOSX     显示位置X' _: N! K6 W4 @7 q. B
  7. *              usPOSY     显示位置Y8 X* `% I  `5 F/ o9 v! M5 v6 F/ m
  8. *    返 回 值: 无
    ) j* E2 P' z) u1 p, Y2 V& v
  9. *********************************************************************************************************
    : T. z4 q7 F% y1 O1 Q  r6 I
  10. */0 C, c/ Z6 F6 u, Q2 r$ [+ j: Y4 q
  11. static void _ShowPNG(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)' Z& g5 r5 F5 t! A1 E3 f9 C
  12. {
    ) ?3 [' t, M' n9 U
  13.      GUI_HMEM hMem;
    0 l9 d) ]- @+ _0 S$ n( @' F
  14.      char *_acBuffer2;; u9 P& ?( f! g) y6 U8 m! Z2 g$ r

  15. 9 e  S( N' l, n1 F3 [
  16.      /* 申请一块内存空间 并且将其清零 */
    / S- s9 [4 v& r* A9 X
  17.     hMem = GUI_ALLOC_AllocZero(500000);: z# J7 f2 @3 Z. {3 H. w6 I
  18.      /* 将申请到内存的句柄转换成指针类型 */
    ; o* U# `9 q0 z/ ^9 j2 D
  19.      _acBuffer2 = GUI_ALLOC_h2p(hMem);
    8 X& S) b; i0 i

  20. * Q6 M0 T1 {$ |& s- ?2 H+ X
  21.     . a+ E% l4 ?  V
  22.      /* 打开文件 */        
    . i1 C- w: W0 u3 m7 v! w/ ?: h
  23.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
      [$ S' P! a- S
  24.      if (result != FR_OK)
    + N  p; |1 \7 x, m$ g9 t
  25.      {  O1 O$ g/ m6 [) V
  26.          return;
    9 c& A8 [' d- c& K1 F9 ?
  27.      }# l- _- Z3 M2 \6 M

  28. ( O" C: D- X% t6 Z3 H" o; _8 w
  29.      result = f_read(&file, _acBuffer2, file.fsize, &bw);
    % N8 E0 h; `- ~
  30.      if (result != FR_OK)
    / N9 D0 ^% O1 j# M
  31.      {/ J. t0 f' R9 D
  32.          return;
    # M8 I; e; R+ D3 y( `
  33.      }- _; V; Y: R6 Q% G& p

  34. # [  \1 o$ d9 b
  35.      GUI_PNG_Draw(_acBuffer2, file.fsize, usPOSX, usPOSY);+ _( f8 g4 }+ n
  36.      GUI_ALLOC_Free(hMem);
    , W$ l3 A5 l. Y# D$ X
  37.      f_close(&file);1 u4 J: b7 B; m
  38. }
复制代码
l  主函数
  1. /*- ]8 ], p% D! [
  2. *********************************************************************************************************
    0 y5 V; @+ i1 ?+ _
  3. *    函 数 名: MainTask
    " V6 `7 @/ R  X* b# e5 q
  4. *    功能说明: GUI主函数2 C; Z" Y9 B3 C0 q5 `: e* [& D
  5. *    形    参:无4 r  G) c8 D; Q
  6. *    返 回 值: 无/ T; s5 z3 m5 y. v
  7. *********************************************************************************************************- o6 p$ A7 ~6 P6 Y9 T$ ^
  8. */+ a+ [' L( f( ]( ~
  9. void MainTask(void)
    1 K$ v, U2 x0 X2 f7 [! j
  10. {   4 U7 d& }6 L' H7 \
  11.      GUI_Init();# o( A( g1 d  |  d1 o( R. l* \% {
  12.      GUI_SetBkColor(GUI_BLUE);% b6 M6 ?# j) Y% |- ^
  13.      GUI_Clear();
    2 a7 a- x! Z- j+ q# D/ j7 U
  14.     2 v7 y4 ?& @6 F) K6 a( D
  15.     /* 绘制已加载到存储器的PNG文件 */' E% c( j6 G! p' m* V- u
  16.      _ShowPNG("1.png", 0, 0);
    ; C8 G/ E1 {6 l- d" \
  17.      _ShowPNG("2.png", 100, 0);
      S* F2 z& k0 o0 v: \" k0 v
  18.    
    $ ?" ]0 ~) {6 ]; s- x2 }
  19.      while(1)
    + r+ s9 j8 @: Z8 L2 K* \
  20.      {                 
    . R7 T: C# s6 y. h6 }" N
  21.          GUI_Delay(100);3 X9 u) a& c# k1 p
  22.      }
    / Y  \  Q: h, Q9 A7 G# U
  23. 7 g9 r) S, |# k, Z: A) @% B
  24. }
复制代码
实际显示效果如下:
14.7.png
2 V  g/ y% K# S* a
    编译,链接工程的时候会出现大量如下的警告:

5 U- e4 b7 s; ?* U: ?, S0 |
    14.8.jpg
    这个是由于使用的PNG库和现在STemWin5.22版本不匹配造成的,PNG的库是用5.18版本的,最新的5.22版本官方还没有更新。
' {& o% M0 g2 L. N$ I
baiyongbin2009 回答时间:2015-1-15 14:38:58
14.3  绘制无需加载到存储器的PNG图片
    绘制无需加载到存储器的PNG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于PNG比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. /*: m" m7 l' d' b
  2. ********************************************************************************3 u7 t( y9 a( g( z4 d$ W
  3. *
    9 `9 ^5 y! y& T; |: E2 _
  4. *       _GetData2 T0 p! b8 t) v4 C0 X0 i5 z: w: U
  5. *# R, W0 ?- X+ {) E7 x
  6. * Purpose:
    0 s+ |( Y; `) {& f
  7. *   This routine is called by GUI_GIF_DrawEx(). The routine is responsible
    $ z: o1 Q! {( L
  8. *   for setting the data pointer to a valid data location with at least
    $ j' X8 K9 K1 i: E% D
  9. *   one valid byte.
    ) X/ S# d2 n9 B  x7 {0 `
  10. *5 `5 j2 N- W; _
  11. * Parameters:- g7 a1 [, r1 p- h
  12. *   p           - Pointer to application defined data.
    & u- ?) `9 A! r2 b4 W9 w
  13. *   NumBytesReq - Number of bytes requested.) {7 }* D: B% S& z
  14. *   ppData      - Pointer to data pointer. This pointer should be set to
    $ L) l0 D1 M& c. P1 s: q1 w* W
  15. *                 a valid location.6 M' G% \- z; l, ?
  16. *   StartOfFile - If this flag is 1, the data pointer should be set to the6 w' `7 b9 H( I7 ]" |; J
  17. *                 beginning of the data stream., Y0 O0 J6 g, s) Y
  18. *& Z% B! q0 o3 s& K$ V" n
  19. * Return value:" m# M3 s2 I+ ~% r# u
  20. *   Number of data bytes available./ m) M6 z# x$ U) g+ m
  21. *********************************************************************************
    ! `, O: Y! {/ w
  22. */$ U9 }6 C$ |' c& {" H0 N
  23.   u$ e# b- S, E( Y
  24. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) {( C3 `9 ?  U6 |8 P
  25.      static int FileAddress = 0;9 t1 m5 Z5 z1 q# C
  26.      FIL *file;
    6 ?* y# Q( y' d4 i0 Z1 R/ K
  27.      DWORD    NumBytesRead;9 E4 B$ A6 ?# a
  28.      U8     * pData;5 P+ X, I' i- ]: E# S8 }
  29. 1 Y+ @5 ^3 m% ?' q
  30.      pData  = (U8 *)*ppData;# G/ t8 c- ?3 `8 G# W
  31.      file = (FIL *)p;
    : Z) Y6 |( [! B* o$ n* m9 u, q
  32.      //
    2 B; W$ L- g, d) o
  33.      // Set file pointer to the required position* R( k7 x% q/ g0 B& m1 F
  34.      /// u9 ]3 j( \! J% Y$ b3 \+ a
  35.      if(Off == 1) FileAddress = 0;
    ; }: [1 T2 o7 u5 X
  36.      else FileAddress = Off;
    1 a0 q$ I! L0 v
  37.      result =f_lseek(file, FileAddress);
    $ K: j; k8 E: C: M* Y
  38.      //
    ) Q' o. t5 D' D+ C+ e  m
  39.      // Read data into buffer0 J7 ^. O0 `# |. b6 N& p
  40.      //4 g& z& d' `( W2 H. j
  41.      result = f_read(file, pData, NumBytesReq, &NumBytesRead);! _1 f8 Q/ h+ V# `4 O$ M" b

  42. 5 i8 V5 K6 u& o4 k& l
  43.      //
    : g/ K$ D' j- n- b6 m% l# N8 s' t
  44.      // Return number of available bytes
    , P* Q# u9 b1 t& d
  45.      //# e# l' G( s$ ~9 u' M3 B
  46.      return NumBytesRead;
    5 N  x. P$ {7 f, [5 n! J! d

  47. - ~$ t6 [5 M; W% Y
  48. }
    % N5 C" j3 O. E; R5 d
  49. /*
    . Z# ?/ s. ^- ^6 C# b
  50. *********************************************************************************************************
    * K5 J4 d6 {* j4 V0 W& d, ~! T
  51. *    函 数 名: _ShowPNG8 `3 {+ ^9 E* O' k( d3 [
  52. *    功能说明: 显示PNG图片
    + _, Q# ]. R+ W$ O& H$ S# Z! [& N/ o# U
  53. *    形    参:sFilename 要显示的图片名字; M0 N' C: h: F" D6 d4 l" T
  54. *             usPOSX    显示位置X0 x+ N; p7 ~. G; r. R
  55. *             usPOSY    显示位置Y
    / I, D  @( ^" Y8 v0 M7 L7 A
  56. *    返 回 值: 无% X: s. h2 c0 V3 S
  57. *********************************************************************************************************1 c' E3 f3 J7 i  y  G+ @5 K( L. \7 D
  58. */
    8 c6 X; d. h! K) a. D# D
  59. static void _ShowPNGEx(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)
    " Z: Y! Z5 m% M4 k
  60. {   
    # z4 `9 n4 b% c! b
  61. + w  W2 a. T+ l" O
  62.      /* 打开文件 */        . k( u5 g+ ~' ?0 y+ r4 E0 N* x# a% _
  63.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);
    5 K8 D. T  |5 c( T5 y( w$ k
  64.      if (result != FR_OK)
      D3 T) ]% y7 Z- V
  65.      {
    ( e( {& I7 w, _" i4 d% v' i
  66.          return;) C9 h' @/ v0 ^# y9 L/ x9 p7 V
  67.      }# \7 ^! T8 y) F% H! t4 l( s" I* }# i: l
  68.     + D" P' {5 A5 C" r" V0 j
  69.      GUI_PNG_DrawEx(_GetData, &file, usPOSX, usPOSY);
    ; j9 ?6 G/ ^. i, X- L( S6 V; l% ?
  70. # i4 g0 R- v( U( m
  71.      f_close(&file);
    ! V* o' S+ u1 e5 V
  72. }
复制代码
l  主函数
  1. /*0 R7 X: ^: |7 w
  2. *********************************************************************************************************
    ; G) h, R5 U7 X
  3. *    函 数 名: MainTask  S, \. F" B, D( }
  4. *    功能说明: GUI主函数
    - M& U9 K+ |+ V; u* a# W8 R# k
  5. *    形    参:无8 |% X1 Y5 b7 [
  6. *    返 回 值: 无9 Y6 v& }: [: A  d
  7. *********************************************************************************************************
    8 F4 I" q: e" `
  8. */: K7 N  r( b% P) e
  9. void MainTask(void)
    , J( `( N9 _2 u0 ]( m& g, }
  10. {   ( U2 S  n4 N# F2 s: }3 q! U# L9 A% n
  11.      GUI_Init();- y% k* C  {  }! ?) W! H8 Y
  12.      GUI_SetBkColor(GUI_BLUE);5 k" g, I7 |/ v, o7 I
  13.      GUI_Clear();5 ^- R% D& Y: z) z
  14.    
    6 O6 W( k8 T4 }0 b/ m% I* h5 F
  15.      /* 绘制无需加载到存储器的PNG文件 */
    & m2 c* j2 {2 k# ~) U
  16.      _ShowPNGEx("3.png", 0, 100);; l$ `; F) d( _% b; M/ Z
  17.      _ShowPNGEx("4.png", 100,100);
    $ P) k& w  r- o7 D5 u: ~# H
  18.     : c! T3 L- u. O1 R6 i- V, K! W
  19.      while(1)
    . p2 F( l  ]6 g3 @5 \( `
  20.      {                 & U& y1 w' `( L
  21.          GUI_Delay(100);+ d, @1 j, V  W5 N7 _3 J
  22.      }
    ! X7 E" l7 e+ v* N) `

  23. 0 I8 Q# H! g+ [2 U& J6 b
  24. }
复制代码
实际显示效果如下:
14.9.png

- |" X: J  J7 v/ g0 y14.4  实验总结; h7 q+ c* f  N. g1 ?+ M; D' }/ W
    有兴趣的可以了解一下PNG压缩方面的知识。如果只是API应用的话,这部分知识还是比较容易学会的。PNG图标用到的地方还是比较多的。1 a; K6 q8 U' O" L' k/ Z' J

; y+ I$ h( f9 i/ c: ?! `
蔚飞 回答时间: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 手机版