一种用于png图片处理的C/C++库lodepng的使用说明及踩坑记录
Posted 爱小羊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一种用于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等知识以及如何申请内存等相关知识。此外任何一个任务都不能小看,比如这次任务看着简单,但是不做一遍根本不知道会产生什么问题。
以上是关于一种用于png图片处理的C/C++库lodepng的使用说明及踩坑记录的主要内容,如果未能解决你的问题,请参考以下文章