当前位置: 首页 > 工具软件 > LodePNG > 使用案例 >

单片机系统:使用lodepng解码png图片

华恩
2023-12-01

1.使用lodepng解码,源代码为。使用最少2个文件就能完成png的解码。不像libpng + Zlib需要许多文件,并且有很多关联头文件。
lodepng-master为原始代码
https://lodev.org/lodepng/

也有github主页https://github.com/lvandeve/lodepng

2.png_examples是配合NXP RT1170 SDK,仿照jpeg_example的例子,主要是借助从这个示例,可以从从SD卡文件系统直接读取.png文件

2.1修改loadpng.c中对文件的操作,使用fatfs API操作图片文件,比如f_open,而不是fopen

2.2仿照example_sdl.c调用以下函数完成对png的解码,解码成8888的格式
  lodepng_decode32_file(&image, &width, &height, filename);
  获取png图片的高度和宽度

2.3 在framebuff的中间位置,将获取到的rgba数据显示到屏上。
     因为大部分显示driver不含有alpha blending功能,所以a透明度数据被综合到r,b,g数据中
     并且最终按照b,g,r的顺序填入framebuffer
     如果显示驱动定义的格式为ARGB8888,这种情况直接按序填入framebuffer即可。

    /*plot the pixels of the PNG file*/
    for(y = 0; y + jump - 1 < h; y += jump)
    {
        bufp = pBuffStart + y * row_stride;
        
        for(x = 0; x + jump - 1 < w; x += jump) 
        {
          /*get RGBA components*/
          r = image[4 * y * w + 4 * x + 0]; /*red*/
          g = image[4 * y * w + 4 * x + 1]; /*green*/
          b = image[4 * y * w + 4 * x + 2]; /*blue*/
          a = image[4 * y * w + 4 * x + 3]; /*alpha*/
        
          /*make translucency visible by placing checkerboard pattern behind image*/

          //处理透明情况
          checkerColor = 191 + 64 * (((x / 16) % 2) == ((y / 16) % 2));
          r = (a * r + (255 - a) * checkerColor) / 255;
          g = (a * g + (255 - a) * checkerColor) / 255;
          b = (a * b + (255 - a) * checkerColor) / 255;

        
          /*give the color value to the pixel of the screenbuffer*/
          //bufp = (Uint32 *)scr->pixels + (y * scr->pitch / 4) / jump + (x / jump);
          //*bufp = 65536 * r + 256 * g + b;
          *bufp++ = b;
          *bufp++ = g;
          *bufp++ = r;
        }
2.4 以上即可解码png格式图片,loadpng还支持生成png格式图片,或者将png格式图片转成bmp图片等。
当然现在lodepng的实现需要filesystem接口来操作图片。
LODEPNG_COMPILE_DISK定义后,可以使用lodepng_decode_file来直接解码图片文件
对于单片机系统,也有一些情况下需要将png图片作为bin文件存放。这时候要先手动把文件数据读取到buffer中
再调用unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize)
传入in,w,h,insize,colortype, bitdepth等参数转换为out输出

lodepng_decode32_file只需传入文件名,colortype, bitdepth即可,会自动调用文件系统读取文件大小。通过lodepng_load_file获得文件大小,并且将文件读取到一个动态malloc分配的buffer中
而lodepng_decode32的insize参数需要自行通过文件获取,并将该文件读取到buffer中。或者文件大小在编译时指定。比如在远程下载一个png文件的时候,将下载大小保存起来,作为下次解码png的参数。

2.5 接上问题:如何在IAR中不使用文件系统直接使用一个png文件
2.5.1:首先需要在IAR中link一张png图片,并将其与代码段link在一起,4字节对齐,指定其symbol为symbol_snowy
Link: extra option
--image_input=$PROJ_DIR$/../snowy.png,symbol_snowy,.text,4
--keep=symbol_snowy
在代码中如下应用该png文件对应的buffer
extern unsigned char symbol_snowy[];

 

例程是针对于NXP i.MXRT系列做的一个范例,在IAR工程中采用两种方式解码并显示png图片。

1.第一种,000.png放于sd卡上,通过fatfs读取该文件,并使用lodepng_decode_file解码

2.第二种,直接将一张png图片编译在工程中,直接将该文件使用lodepng_decode32解码

 

补充:

通过定义一些NO_COMPILE选项,可以屏蔽掉不需要的功能,加快编译速度

#define LODEPNG_NO_COMPILE_DISK   不需要文件系统,而采用裸数据解码
#define LODEPNG_NO_COMPILE_ENCODER 不需要编码png图片

lodepng_decode32可以解出RBGA 4种数据,输出out buffer也是每4个字节为一个像素

lodepng_decode24可以解出RGB3种数据,输出out buffer每3个字节为一个像素

          /*get RGBA components*/
          r = image[3 * y * w + 3 * x + 0]; /*red*/
          g = image[3 * y * w + 3 * x + 1]; /*green*/
          b = image[3 * y * w + 3 * x + 2]; /*blue*/
          a = 255; /*no alpha,不透明*/
        
          /*make translucency visible by placing checkerboard pattern behind image*/

          //处理透明情况
          checkerColor = 191 + 64 * (((x / 16) % 2) == ((y / 16) % 2));
          r = (a * r + (255 - a) * checkerColor) / 255;
          g = (a * g + (255 - a) * checkerColor) / 255;
          b = (a * b + (255 - a) * checkerColor) / 255;

        
          /*give the color value to the pixel of the screenbuffer*/
          //bufp = (Uint32 *)scr->pixels + (y * scr->pitch / 4) / jump + (x / jump);
          //*bufp = 65536 * r + 256 * g + b;
          *bufp++ = b;
          *bufp++ = g;
          *bufp++ = r;

当然前者需要更多的heap资源,虽然png相比jpeg为无损压缩,且数据压缩率也可以,但是解码的时候需要大量的RAM,小单片机还是慎用,情愿用SPI Flash空间存储bmp文件换取珍贵的RAM资源

 类似资料: