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

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

[复制链接]
baiyongbin2009 发布时间:2015-1-15 14:34
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第14章      PNG图片显示
6 O3 z4 U7 U9 _, m5 p% e
    本期主要讲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
) h1 u) p3 o# U: I! V1 e# [( n3 T+ [+ x6 T
14.1.1      PNG格式图标转换
    某些情况下,将PNG文件作为C文件添加到项目中非常有用。对此,可完全按照前面介绍的“JPEG文件支持”下的相同方式来执行。此外,位图转换器能够加载PNG文件并将它们转换为C位图文件。下面举一个例子,跟大家演示下:比如我们要转换如下的PNG图标:

3 a% W: ?, s% `( Q6 @/ E
14.2.png
l  打开软件加载上面的图片
14.3.jpg
, i" p5 _! A0 p" r/ Y
l  加载后点击Convert即可,点击后没有任何现象,直接去图片所在的文件夹找即可

! e) G" O6 I& Q9 n8 j
14.4.jpg
实际运行代码如下(图片数据就不贴出来了,看本期教程配套的例子)
  1. void MainTask(void)) ]( Q' K! Y; k+ `
  2. {   . `# f- \5 Q; N$ c
  3.     GUI_Init();
    7 f/ U' |. x9 C3 `, f0 v9 l1 I6 I  V
  4.      GUI_PNG_Draw(_acmusic, sizeof(_acmusic), 20, 20);) t9 s" Y. E+ q) J
  5.     while(1)
    ' g- [0 [4 U* W( l1 B0 a& a& T
  6.     {
    2 A8 z9 \5 w* w! W$ \4 n; {) L
  7.         GUI_Delay(100);/ R" k4 a6 I" z
  8.     }
    # ?; m% B0 T% |: h4 M
  9. }
复制代码
    由于在Bin2C的小工具是来自MDK安装目录中,这个工具只是评估板,无法实现PNG图标的透明色效果。模拟器实际的显示效果如下:
14.5.png
  J6 r" h- o# t; q  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
2 t. n0 {- L! M3 v; n% E; @$ i

4 X$ w$ b; E, E$ F+ o' K# |% x
收藏 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. /* 申请一块内存空间 并且将其清零 */' O" [8 G$ Q: O, f
  2. hMem = GUI_ALLOC_AllocZero(100000);& E6 l$ @# }4 {) ^/ w
  3. /* 将申请到内存的句柄转换成指针类型 */! ]5 Z' ^5 S. O: ?
  4. _acBuffer2 = GUI_ALLOC_h2p(hMem);
    0 R/ Y; w% E7 P2 B1 M
  5. /* 释放申请的动态内存  */
    8 j: z" F. E+ s/ F3 e7 u6 M
  6. GUI_ALLOC_Free(hMem);
复制代码
    这里还用上面的图片作为显示对象。先把这个图片放到SD卡中,然后通过程序把这个图片数据全部的加载到SRAM中,最后在屏上进行显示。这个工程的实现主要分为如下三个部分:
Ø  SRAM和SD卡及其文件系统的初始化
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  SRAM和SD卡及其文件系统的初始化,这部分函数与上面第11章的11.2小节一样。
l  图片的加载以及显示函数
  1. /*% X" Z' d. W9 x3 d( K' K( I
  2. *********************************************************************************************************; q7 Q8 q- q$ Z0 n6 g! d* b+ Q
  3. *    函 数 名: _ShowPNG
    * X0 F, c, Q8 M4 z$ g
  4. *    功能说明: 显示GIF片+ N/ O4 W" s- N  {
  5. *    形    参:sFilename   要显示的图片名字1 C6 K0 U0 ?8 b) [+ i4 d/ n
  6. *              usPOSX     显示位置X3 H9 m2 e2 p6 Z7 t6 _
  7. *              usPOSY     显示位置Y( ]' r: b2 K% n+ K& V, [1 Y
  8. *    返 回 值: 无$ I( Z, t+ O* Q. f- P
  9. *********************************************************************************************************
    6 z! z: a, n2 H, q" j
  10. */
    / d- I. D* d* R! ?! Y) Y
  11. static void _ShowPNG(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)) L, H# m& Y) P+ }2 a
  12. {
    9 O( b( q/ M3 S% [; H
  13.      GUI_HMEM hMem;
    % V2 c, t, h& y* _3 _9 C6 b6 L
  14.      char *_acBuffer2;
    4 u6 f, H* N7 n7 p/ R% ~4 G
  15. 4 h! c3 U% N1 g8 U7 a6 v3 @5 Y2 Z
  16.      /* 申请一块内存空间 并且将其清零 */% j! t8 W7 \, C$ j
  17.     hMem = GUI_ALLOC_AllocZero(500000);
    3 c+ Y8 J: ^; j: X3 x
  18.      /* 将申请到内存的句柄转换成指针类型 */
    , I2 F9 l0 u5 L) A2 q7 l
  19.      _acBuffer2 = GUI_ALLOC_h2p(hMem);
    $ ^+ ~& A- C! j% }. Z4 a
  20. ' S; {9 x. I/ }, |1 @7 }- z
  21.    
    % r0 V1 l5 O, r2 B. Y% N
  22.      /* 打开文件 */        
    - X3 N. N) q! o5 n5 v% l
  23.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);% ^! \% O- ~( Y; ~
  24.      if (result != FR_OK)) {* b4 |& b6 Q& a- K% @7 a
  25.      {
    ! z7 j. Z4 y. r. v6 t. v
  26.          return;
    + ~4 S4 z! k% Q, S
  27.      }4 V! @1 ]$ }9 O9 U8 H* K
  28. ( N2 g1 C7 e4 r7 J) W, O2 f5 C: b
  29.      result = f_read(&file, _acBuffer2, file.fsize, &bw);$ s& u" I5 `, G. ^* h
  30.      if (result != FR_OK)1 D7 o! y' V. @3 B( e' P
  31.      {
    ( T. C. ]  e- U6 x4 P7 E1 K
  32.          return;9 i% y; O4 H" Q% w1 |* l% Y3 s
  33.      }
    ! E" l/ x0 K" v8 X. H
  34. * V' p" S' B" C- K9 _% J
  35.      GUI_PNG_Draw(_acBuffer2, file.fsize, usPOSX, usPOSY);
    . E$ ], E! D  u- O. g. F8 x$ c
  36.      GUI_ALLOC_Free(hMem);
    % S# L$ d2 w; d  D/ G( n
  37.      f_close(&file);
    / R/ b4 r% S( k% F2 P
  38. }
复制代码
l  主函数
  1. /** T6 ]5 X4 B& a. Q
  2. *********************************************************************************************************
    1 w# ]" c0 Q8 \/ o1 ~0 B( q# D, A
  3. *    函 数 名: MainTask
    : b( S& A" r- q* N' a7 o
  4. *    功能说明: GUI主函数. a9 e* ~1 H5 p  N! e
  5. *    形    参:无  [- h/ c& v: |% K1 ]/ a
  6. *    返 回 值: 无1 A, x& f" f. L( K
  7. *********************************************************************************************************
    0 S3 l& i1 \& u+ C  B) p
  8. */& m! h8 ~' N4 s3 e/ G2 N" ?8 M; `
  9. void MainTask(void): k& E* ~0 b  ?, d4 p
  10. {   
    3 n( ^2 {5 c1 A: |( b, K& d% m) R* G
  11.      GUI_Init();
    7 Z3 b& K8 H* Q6 s1 h' z
  12.      GUI_SetBkColor(GUI_BLUE);
    9 O0 [2 S  y; K# t9 `% p5 n
  13.      GUI_Clear();
    , f, M$ k7 T: G+ U
  14.     5 K6 Q3 O' }$ K. t& g) D8 `7 t$ _& ~; r
  15.     /* 绘制已加载到存储器的PNG文件 */) W. ?& r2 F5 u0 V9 ~( t
  16.      _ShowPNG("1.png", 0, 0);
    * k" Y5 y4 m, O' e: K' p& c) v
  17.      _ShowPNG("2.png", 100, 0);/ l/ w5 m( ?( `* f
  18.     ) Q2 h7 {! [! i1 P1 j
  19.      while(1); t1 [, S' R. U5 C# X
  20.      {                 
    + {4 }6 ]: M. }2 i% [8 _1 U+ T
  21.          GUI_Delay(100);
    3 P, ^- N1 D" Y# @
  22.      }
    ( f- G# d! B0 r! {" D  s
  23. * s; I6 Y6 W2 c
  24. }
复制代码
实际显示效果如下:
14.7.png

9 R0 V" B5 m1 L* ~
    编译,链接工程的时候会出现大量如下的警告:
5 A) U8 s, H+ x3 y, V* m
    14.8.jpg
    这个是由于使用的PNG库和现在STemWin5.22版本不匹配造成的,PNG的库是用5.18版本的,最新的5.22版本官方还没有更新。
4 ~* o1 r! t8 c# B# O7 J
baiyongbin2009 回答时间:2015-1-15 14:38:58
14.3  绘制无需加载到存储器的PNG图片
    绘制无需加载到存储器的PNG图片方式可以有效的解决内部动态内存不够的情况,不过缺点也很明显,图片的显示速度很慢。这种方式一般是每次读取一行像素的数据,然后进行显示。这个工程的实现主要分为如下三个部分:
Ø  使用芯片内部的SRAM作为动态内存
Ø  图片的加载以及显示函数
Ø  主函数
    下面把这三部分详细的讲解下:
l  使用芯片外部的SRAM作为动态内存,这部分函数与上面第11章的11.2小节一样,由于PNG比较的消耗内存,这里和BMP不同也需要使用动态内存。
l  图片的加以及显示函数。
  1. /*
      z1 d6 {+ b9 a
  2. ********************************************************************************
    ! O. \1 S+ c4 Z
  3. *% c' u0 `0 Q; |7 O
  4. *       _GetData; w8 [  H3 _4 y: E5 J  z
  5. *4 f; m' n; z1 x: Z
  6. * Purpose:
      t8 T# W; q" ^) k" Q
  7. *   This routine is called by GUI_GIF_DrawEx(). The routine is responsible$ H6 }/ U  _7 X. `8 ~4 s3 H7 K; q
  8. *   for setting the data pointer to a valid data location with at least, F8 {, Z1 v# H2 |
  9. *   one valid byte.
    9 j+ p6 K. }, I4 T* D
  10. *- @, s5 u+ H/ v/ V8 z
  11. * Parameters:+ T6 u5 L2 A" K/ c& r: J
  12. *   p           - Pointer to application defined data.
    0 j( U% M, L3 |
  13. *   NumBytesReq - Number of bytes requested.0 ?6 s4 [, z0 [7 h, R9 Y- [
  14. *   ppData      - Pointer to data pointer. This pointer should be set to7 `$ Q7 [4 [5 }- }/ s* U7 g
  15. *                 a valid location.
    . P  g# W7 [: ?4 d% H! B
  16. *   StartOfFile - If this flag is 1, the data pointer should be set to the% T, C" J0 z7 ?; ^( j) l! `
  17. *                 beginning of the data stream.
    $ u! Q0 U2 f8 m
  18. */ _& N: D; ?: ?' u8 W
  19. * Return value:/ c; s: m2 {+ \* v" l
  20. *   Number of data bytes available.
    9 r' P5 i% f) K8 Z3 l- e
  21. *********************************************************************************1 B) q1 R. S+ _, s
  22. */
    - c2 }) _" I7 ^* @) C. Q  S1 Y

  23. ' ~; y2 a7 `9 _9 ^; R" D
  24. static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) {/ ~1 q" a, t/ V7 I/ s/ S* }: G2 V
  25.      static int FileAddress = 0;. {2 h& C6 {3 ^% O# d
  26.      FIL *file;
    3 \0 d/ p! K' s- E
  27.      DWORD    NumBytesRead;
    8 z9 `- E% [4 W; E% R5 b! c
  28.      U8     * pData;: a0 Z/ \% k, x0 J/ U5 j! H6 ~) z8 H

  29. 9 R/ O0 H/ V/ h9 }( @% E8 v
  30.      pData  = (U8 *)*ppData;. d+ ]" S( h* M2 m
  31.      file = (FIL *)p;2 m* Q9 h3 l1 Y4 D1 f7 d
  32.      //
    7 o9 C) A$ s- r) Z* d% z! U9 X
  33.      // Set file pointer to the required position
    $ r) V' R: z- J. v, g' a
  34.      //6 e3 J7 J- \4 z* ^% P, Z* F
  35.      if(Off == 1) FileAddress = 0;
    " G$ Z8 n7 w) `! ?) i( ?' u
  36.      else FileAddress = Off;9 r3 c) J/ k9 h" r- N8 J) K" w
  37.      result =f_lseek(file, FileAddress);
    9 ^! V# E: |: W% V
  38.      //
    5 b; L, e8 S3 n) J9 z- k, _
  39.      // Read data into buffer8 j9 F$ I+ v9 f2 }1 C$ v
  40.      //2 s# N3 ~/ W9 @3 n% I* y
  41.      result = f_read(file, pData, NumBytesReq, &NumBytesRead);8 Y1 O  }. E" y4 j- ?
  42. , \  T6 l& z8 ^+ V# ~$ H
  43.      //
    1 Z- {& h4 f# y9 k
  44.      // Return number of available bytes
    / ~3 n7 N7 k, _) D6 W
  45.      //! _7 L3 {& }# U7 W8 J% c
  46.      return NumBytesRead;
    + q+ Y5 B2 V6 Q2 Z. k( B

  47. ; u* _, s# _: f( }) h4 C6 L
  48. }0 d7 B9 F, q) o, s5 n' ]! l
  49. /*
    $ M9 _% G0 @. |5 m, A
  50. *********************************************************************************************************9 N+ K. m: d- K7 c$ i8 ?
  51. *    函 数 名: _ShowPNG2 {1 S- v+ i% k+ |
  52. *    功能说明: 显示PNG图片
    ( f; d; x; O6 l2 `2 z4 m1 c! B
  53. *    形    参:sFilename 要显示的图片名字. j( r# A' z- s- C2 d
  54. *             usPOSX    显示位置X  C; p$ k( G, b; A
  55. *             usPOSY    显示位置Y
    9 p1 C9 z/ C& V
  56. *    返 回 值: 无
    ! z4 q. a% V/ `0 Q9 ^  Z4 n; i
  57. *********************************************************************************************************
    4 }9 H, ]9 V: I" D( y( l& b  n- z
  58. */
    ; M% ^1 p' s7 T( Q7 D
  59. static void _ShowPNGEx(const char * sFilename, uint16_t usPOSX, uint16_t usPOSY)7 f$ a' \' O$ D$ t. ]9 M- @5 ^
  60. {   . W; [6 I/ r% E6 Y3 L
  61.   b0 e, _' c; u8 d8 V
  62.      /* 打开文件 */        - i  Q& g! l+ J* m" H# H
  63.      result = f_open(&file, sFilename, FA_OPEN_EXISTING | FA_READ | FA_OPEN_ALWAYS);% _5 B2 n$ q; L
  64.      if (result != FR_OK)
    8 z9 D$ C; C3 Y) l2 b" o
  65.      {; P. k9 F- V8 ?1 u
  66.          return;
    . \( ?% v+ ~8 M1 O+ z
  67.      }
    6 U5 \$ p- a% k3 S2 y5 K
  68.    
    7 O' b" ^# @$ O! L' G
  69.      GUI_PNG_DrawEx(_GetData, &file, usPOSX, usPOSY);
    & U5 y1 D8 o9 E

  70. " E& ?) v6 W# ?0 `7 e
  71.      f_close(&file);
    - e; E. y1 |6 l; P" u
  72. }
复制代码
l  主函数
  1. /*  z8 j% q4 u7 M$ i" k
  2. *********************************************************************************************************
    4 A9 c3 A: P6 x- }1 Y: o
  3. *    函 数 名: MainTask5 l* I' `0 }0 `' Q
  4. *    功能说明: GUI主函数
    . k. ~$ V4 \) _7 y* j& U0 I: I
  5. *    形    参:无% o, P4 b* j+ @" n
  6. *    返 回 值: 无
    4 |0 @/ |$ R$ w0 p6 u) v
  7. *********************************************************************************************************2 U% _$ D0 {7 S
  8. */: h5 w2 a5 Y& s5 u: i
  9. void MainTask(void)5 q6 u3 C4 e  n* @4 V
  10. {   
    + h' i* [5 A, o
  11.      GUI_Init();# B# E# A% R* }/ s- {2 y8 w: p
  12.      GUI_SetBkColor(GUI_BLUE);
      E9 }& l7 D8 q3 G# H# Y
  13.      GUI_Clear();
    7 C/ b! b( U. O2 f
  14.     ( L+ v0 e6 m! i! ~
  15.      /* 绘制无需加载到存储器的PNG文件 */
    $ n, s8 k7 H# u' ~( k; z
  16.      _ShowPNGEx("3.png", 0, 100);
    / z2 M, B/ I* Y% L7 M8 ?6 ]+ c
  17.      _ShowPNGEx("4.png", 100,100);
    # N) U8 q, J- \9 D0 c
  18.     9 T0 e( D) x! f) }% E
  19.      while(1)
    5 w: ?) q+ J) w1 ?5 ^% T& @: T6 v
  20.      {                 2 u% ?/ Y3 y( H: n, p
  21.          GUI_Delay(100);
    ! f. R3 [$ }# c
  22.      }( R+ u' k) k3 F1 M

  23. 0 y) o8 @8 i. U" {! J/ r7 f; S1 n
  24. }
复制代码
实际显示效果如下:
14.9.png
& k4 u9 k' S5 a
14.4  实验总结
6 Z3 i8 e5 _0 R+ |  b( |. C
    有兴趣的可以了解一下PNG压缩方面的知识。如果只是API应用的话,这部分知识还是比较容易学会的。PNG图标用到的地方还是比较多的。$ l$ g3 @9 \! l+ L
# J, T& D/ @3 |  S5 `+ v! Z& A0 z
蔚飞 回答时间: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 手机版