一种用于png图片处理的C/C++库lodepng的使用说明及踩坑记录

引言

前文说到,基于Alios系统的门禁只能处理JPG图片,由于历史遗留问题,服务器下发的人脸中有png格式的图片,开发人员需要将png图片进行解码处理成RGBA格式的图片,用于人脸识别,网上用的最多图片处理库为libjpg和libpng这些图片处理库过于复杂且移植后会扩大程序的大小,因此一款轻量级的png图片处理库的需求日益强烈。

lodepng介绍

LodePNG是一个集合了PNG图像解码器和编码器的代码文件,不依赖于诸如zlib和libpng的外部链接/库,提供方便友好的PNG编解码器调用方法。LodePNG主要是采用C(ISO C90)编写的,并提供了C++的接口。LodePNG的使用非常简单,只要在项目文件中包含lodepng.cpp和lodepng.h或者lodepng.c和lodepng.h就可以。

下载方式

1、登录官网http://lodev.org/lodepng/进行下载,并且官方给出的有例子便于学习。
在这里插入图片描述
2、登录github搜索lodepng,找到star最多的那一个就是,可以用git软件进行下载。

使用方法

在此给出自己写的一个例子供参考。应用时很简单,lodepng库提供的有直接读入文件的接口,lodepng_decode32_file() 这个接口可以直接将图片读入,并生成RGBA的格式图像,将其保存为RAW格式,可以使用imageJ软件进行查看。

#include <stdio.h>
#include "lodepng.h"

//#define filename "E:\\sun.png"

int main()
{
	FILE *fp;
	unsigned char *pBuffer;
	unsigned error;
	unsigned char * image;
    unsigned width, height;
	const char* filename =  "E:\\face\\2.png";
	const char* filename_new =  "E:\\png3.png";
	error =lodepng_decode32_file(&image, &width, &height, filename);
	//error =lodepng_decode24_file(&image, &width, &height, filename);//image内存的大小是多少
    if(error) printf("error %u: %s\n", error, lodepng_error_text(error));

	printf("error is %d,,width is %d ,height is %d\r\n",error,width,height);
	//lodepng_encode24_file(filename_new, image, width, height);
	//fp = fopen("E:\\face\\19_32.raw","w");//生成raw图片是这样生成的吗
	fp = fopen("E:\\face\\2_1211.raw","wb");//生成raw图片是这样生成的吗  //一定要用wb打开二进制
	//fwrite(image, width*height*3 , 1, fp);
	fwrite(image, width*height*4 , 1, fp);
	//fwrite(image, width*height*4 , 1, fp);
	fclose(fp);

   free(image);

	
	return 0;
}

解码前图片

解码后图片
在这里插入图片描述
本人是在Alios系统下进行开发,在此系统下没有fopen等函数,需要根据alios的文档说明将fopen函数改为aos_open函数,对win下的lodepng库进行改写,经过验证可以在alios系统下使用。

static long lodepng_filesize(const char* filename) {
#ifdef WIN32  //Added by sun
  FILE* file;
  long size;
  file = fopen(filename, "rb");
  if(!file) return -1;

  if(fseek(file, 0, SEEK_END) != 0) {
    fclose(file);
    return -1;
  }

  size = ftell(file);
  /* It may give LONG_MAX as directory size, this is invalid for us. */
  if(size == LONG_MAX) size = -1;

  fclose(file);
#else
    int file = -1;
    int ret = -1;
    struct aos_stat file_st;
    long size;

    file = aos_open(filename, O_RDWR);
    if (file < 0) {
      return -1;
    }
  /*
    if(aos_lseek(file, 0, SEEK_END) != 0) {
    aos_close(file);
    return -1;
  }
  */
    ret = aos_stat(filename, &file_st);
    if (!ret) {
    size = file_st.st_size;
}
#endif
  return size;
}

踩坑记录

说到这里又让我感觉到了嵌入式的特点,太需要经验了,总体来看其实就是移植一个库,移植过来调用调用就行了,但还是出现了很多问题。比如解码一张这样的图片
在这里插入图片描述
结果却是这样,只能大概判断出是错位了,想了好久准备使用16进制文件读取软件,如Hex Editor Neo来读取。
在这里插入图片描述
经过读取终于发现了问题,正确的RGBA是这样的
在这里插入图片描述但是转换出来的却是这样的,可以发现有明显的错位,当时我还没意识到错误在哪,技术领导看后说怎么多了换行符0d,0a,我这才发现问题。在网上进行搜索发现,fwrite实际写入文件的数据大小比参数指定的数值大一些字节,原因是:win下用文本方式读写文件,会在0A(换行)前加0D(回车)。发现自己用的fp = fopen(“E:\face\19_32.raw”,“w”);用的W参数进行打开的,w参数是以文本的方式打开,将w参数改为wb就可以了,一切都正常了,开始没有想到这个问题,我说为啥有的图片转换正常,有的不正常,原来是图片中出现0a的话会被添上0d,导致错误,如果图片中没有oa则正常。错误解决。
在这里插入图片描述

总结

通过这个任务学会了嵌入式系统中图片的处理,RGBA格式图片的buffer大小长4,png图片的大小不是,是因为png对图片进行了压缩,RGBA格式没有压缩。此外还学到了图片的位深,C语言IO函数,如fopen,fclose等知识以及如何申请内存等相关知识。此外任何一个任务都不能小看,比如这次任务看着简单,但是不做一遍根本不知道会产生什么问题。

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C/C++一种高效的编程语言,可以用来转换GIF格式文件为一帧一帧的图片。GIF文件是一种常用的动画格式,可以包含多张图片,每张图片称为一帧,以一定的时间间隔播放,形成动画效果。如果需要从GIF文件中提取每一帧的图片,可以通过C/C++实现以下的步骤: 1. 打开GIF文件并读取它的头部信息,包括图片的大小、分辨率、颜色等信息。 2. 解析GIF文件并获取它的每一帧图片的信息,包括图片的宽高、颜色等信息。 3. 将每一帧的图片数据提取出来,以便保存为单独的图片文件。 4. 将提取的图片数据进行解码和重新编码,将GIF格式的数据转换成一帧一帧独立的图片数据。 5. 将每一帧的图片数据保存成图片文件,一般采用常见的图片格式,如PNG、JPEG等。 以上步骤可以通过使用C/C++编程语言来实现。C/C++提供了丰富的图像处理和相关的API,例如OpenCV、libpng、libjpeg等,可以帮助我们实现GIF到一帧一帧的图片转换。通常情况下,我们可以通过编写相应的代码来完成GIF文件解析和转换过程,以便提取并保存每一帧的图片数据。这样就可以将GIF文件转换成单独的一帧一帧的图片数据,方便用于各种应用场景。 ### 回答2: 将C/C++语言和GIF文件转换为一帧一帧的图片通常需要使用GIF解码图像处理来实现。首先,需要使用GIF解码将GIF文件解码为一组连续的图像帧。解码过程可以使用现有的开源,例如GIFLIB或libnsgif。一旦解码完毕,此时就获得了一组表示每个帧的图像数据。 接下来,需要使用图像处理将所有这些图像数据转换为单独的图像文件。对于图像处理的选择,可以考虑使用OpenCV或ImageMagick等。可以遍历每一帧图像数据,将它们转换为独立的图像文件格式,例如JPEG或PNG格式。 其中需要注意的问题包括文件命名规则,帧率控制等。可以根据应用程序的需求和使用情况,来决定如何命名每个图像文件,并决定以何种方式将这些图像文件转换为动态图像。如果需要的话,也可以考虑使用其他来实现图像编码和解码,例如Boost或FFmpeg。 总之,C/C++与GIF文件转换为一帧一帧的图片是完全可行的。实现此类转换需要充分了解底层和方法,并考虑到预期的输出格式和文件类型。 ### 回答3: C/C语言可以实现将GIF动图转换成一帧一帧的静态图片。GIF动图是由多张图片组成的,每一帧持续一段时间,在C/C语言中可以通过读取GIF文件的方式获得每一帧的数据,并将其储存为一张静态图片文件。 首先,需要使用C/C语言的文件操作函数打开GIF文件,读取其中的每一帧数据。可以使用一些第三方,如GIFLIB,来帮助读取GIF文件。读取到每一帧数据后,可以使用图像处理(如FreeImage)将其转换为常见的图片格式,如JPEG、PNG等。转换后的静态图片可以储存在本地,在需要的时候进行调用。 另外,需要注意的是,由于GIF文件中可能会含有多种分辨率的图片,故在转换为静态图片时需要进行适当的缩放和剪裁,使得每一张静态图的尺寸都相同,以便后续使用。同时,还需要注意透明度的处理,以保留GIF文件中可能存在的透明部分。 总之,C/C语言实现GIF转换成一帧一帧的静态图片涉及到文件操作、图像处理等多方面的知识,需要较高的编程水平和经验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值