1、zlib库和png库的源码获取

(1)zlib库源码下载网址:http://www.zlib.net/;
(2)libpng库源码下载网址:ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng16/;
(3)如果想直接要源码,可以私信我,源码和下面的移植过程是对应的;

2、libpng库的移植步骤

(1)首先要编译zlib库,因为libpng库是依赖zlib库;
(2)将编译得到的zlib库和头文件存放路径导出到环境变量,这样在编译libpng库时可以直接使用;
(3)编译libpng库,得到动态库和头文件,并移植到自己的工程环境中;
(4)根据libpng库源码中的example.c示例代码,编写png图片的编解码函数;

3、zlib库的编译

解压源码:
	tar -zxvf zlib-1.2.8.tar.gz

导出交叉编译工具链:
	export CC=arm-linux-gcc

配置源码,生成Makefile:
	./configure -shared --prefix=/opt/pngDecode

	-shared:生成动态库
	--prefix:安装路径

编译和安装:
	make && make install

(1)解压源码:tar -zxvf zlib-1.2.8.tar.gz;
(2)导出交叉编译工具链:export CC=arm-linux-gcc;
(3)配置zlib库:./configure -shared --prefix=/opt/pngDecode;
(4)经过第三步会得到Makefile文件,执行命令:make && make install;
(5)在/opt/pngDecode目录下会生成include和lib文件夹,里面是zlib库的头文件和动态库;

4、libpng库源码编译

解压源码:
	tar -zxvf libpng-1.6.6.tar.gz

第一步:
	export LDFLAGS="-L/opt/pngDecode/lib"
	export CFLAGS="-I/opt/pngDecode/include"
	export CPPFLAGS="-I/opt/pngDecode/include"

第二步:
	./configure --host=arm-linux --enable-shared --enable-static --prefix=/opt/jpgDecode
	
	--host:指定目标平台
	--enable-shared:生成动态库
	--enable-static:生成静态库
	--prefix:指定安装目录,将来产物就存放在此路径

第三步:
	make && make install

(1)首先将zlib库的头文件和动态库路径导出到环境变量中,供libpng库的编译使用;
(2)调用configure文件配置libpng源码,生成Makefile文件;
(3)调用Makefile文件编译源码和安装zlib库;

5、png解码库的移植

(1)将编译得到的include目录下的头文件,和lib目录下动态库添加到你的代码工程中,并且动态库还需要部署到可执行程序的运行环境中;
(2)参考libpng源码中的example.c示例代码,编写调用png解码库去编解码png图片的函数;
(3)在实际编写png解码函数后会发现,还需要pngstruct.h和pnginfo.h,都在libpng库的源码中,拷贝过去即可;

6、png解码库的使用示例

// 结构体用来封装一个图片的各种信息
typedef struct pic_info
{
	char *pathname;			// 图片在文件系统中的路径名+文件名
	unsigned int width;		// 图片分辨率之宽
	unsigned int height;	// 图片分辨率之高
	unsigned int bpp;		// 图片bpp
	char *pData;			// 指向图片有效数据存储的buf数据
}pic_info;

// 函数功能: 判断一个图片文件是不是png图片
// 函数参数: path是图片文件的pathname
// 返回值:   如果是png则返回0,不是则非0
int is_png(const char *path)
{
	FILE *fp = NULL;
	char buf[PNG_BYTES_TO_CHECK] = {0};	

	/* Open the prospective PNG file. */   
	if ((fp = fopen(path, "rb")) == NULL)		
		return -1;	

	/* Read in some of the signature bytes */	
	if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK)	   
		return -1; 

//	printf("%d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]);
	/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.		
	Return nonzero (true) if they match */	 
	return(png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
}

/*
 * 函数功能: 解码png图片,并将解码出来的RGB数据存储
 * 函数参数: pPic,记录源png图片,解码出来的图片宽高、图片数据缓冲区等信息
 * 返回值  : 成功解码则返回0,失败则返回-1
 */
 
int png_analyze(struct pic_info *pPic)
{
	FILE *fp = NULL;
	png_structp png_ptr;   
	png_infop info_ptr;
	int color_type;
	png_bytep* row_pointers;
	unsigned long len = 0;
	int pos = 0;
	int i = 0, j = 0;

	if ((fp = fopen(pPic->pathname, "rb")) == NULL) 
	{	 
		fprintf(stderr, "can't open %s\n", pPic->pathname);    
		return -1;	
	}

	// 第1步: 相关数据结构实例化
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (png_ptr == 0)
	{
		fclose(fp);
		return -1;
	}

	info_ptr = png_create_info_struct(png_ptr);
  	if (info_ptr == 0)
  	{
   		png_destroy_read_struct(&png_ptr, 0, 0);
   		fclose(fp);
   		return -1;
  	}

	// 第2步: 设置错误处理函数
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, 0);
		fclose(fp);
		return -1;
	}

	// 第3步: 将要解码的png图片的文件指针和png解码器绑定起来
	png_init_io(png_ptr, fp);

	// 第4步: 读取png图片信息
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA, 0);

	// 第5步: 相关图片信息打印出来看一看
	color_type = info_ptr->color_type;
	debug("color_type = %d\n", color_type);

	pPic->width = info_ptr->width;
	pPic->height = info_ptr->height;
	pPic->bpp = info_ptr->pixel_depth;
	len = info_ptr->width * info_ptr->height * info_ptr->pixel_depth / 8;
	debug("width = %u, height = %u, bpp = %u\n", pPic->width, pPic->height, pPic->bpp);

	// 第6步: 读取真正的图像信息
	row_pointers = png_get_rows(png_ptr,info_ptr);

	// 只处理RGB24位真彩色图片,其他格式的图片不管
	// 第7步: 图像数据移动到我们自己的buf中
	if(color_type == PNG_COLOR_TYPE_RGB)
  	{
   		//memcpy(pPic->pData, row_pointers, len);
		for(i=0; i<pPic->height; i++)
		{
			for(j=0; j<3*pPic->width; j+=3)
			{
				pPic->pData[pos++] = row_pointers[i][j+0];		
				pPic->pData[pos++] = row_pointers[i][j+1];		
				pPic->pData[pos++] = row_pointers[i][j+2];		
			}
		}
  	}

	// 第8步: 收尾处理
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
	// close file
	fclose(fp);
	
	return 0;
}

7、参考资源

《朱友鹏——嵌入式核心课程》