`
hzy3774
  • 浏览: 985474 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

PNG格式学习以及使用libpng解析

 
阅读更多

  便携式网络图形(Portable Network Graphics,PNG)是一种无损压缩位图图形格式,支持索引、灰度RGB三种颜色方案以及Alpha通道等特性。PNG的开发目标是改善并取代GIF作为适合网络传输的格式而不需专利许可,所以被广泛应用于互联网及其他方面上。

详细结构可以参照维基百科:http://zh.wikipedia.org/wiki/PNG

     最常用的libpng库提供了解析png所需要的方法,不需要详细掌握png的文件结构,就可以调用相关函数获取png图片基本信息和解压后的图像数据以便后续使用。

libpng官方网站:http://libmng.com/pub/png/libpng.html

依赖库zlib官方网站:http://www.zlib.net/

使用libpng常用两个结构体:

 

/* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
 *
 * png_struct is the cache of information used while reading or writing a single
 * PNG file.  One of these is always required, although the simplified API
 * (below) hides the creation and destruction of it.
 */
typedef struct png_struct_def png_struct;
typedef const png_struct * png_const_structp;
typedef png_struct * png_structp;
typedef png_struct * * png_structpp;

/* png_info contains information read from or to be written to a PNG file.  One
 * or more of these must exist while reading or creating a PNG file.  The
 * information is not used by libpng during read but is used to control what
 * gets written when a PNG file is created.  "png_get_" function calls read
 * information during read and "png_set_" functions calls write information
 * when creating a PNG.
 * been moved into a separate header file that is not accessible to
 * applications.  Read libpng-manual.txt or libpng.3 for more info.
 */
typedef struct png_info_def png_info;
typedef png_info * png_infop;
typedef const png_info * png_const_infop;
typedef png_info * * png_infopp;

 png_info结构体中包含一些图片的相关信息:尺寸,位深等:

 

   /* The following are necessary for every PNG file */
   png_uint_32 width;  /* width of image in pixels (from IHDR) */
   png_uint_32 height; /* height of image in pixels (from IHDR) */
   png_uint_32 valid;  /* valid chunk data (see PNG_INFO_ below) */
   png_size_t rowbytes; /* bytes needed to hold an untransformed row */
   png_colorp palette;      /* array of color values (valid & PNG_INFO_PLTE) */
   png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
   png_uint_16 num_trans;   /* number of transparent palette color (tRNS) */
   png_byte bit_depth;      /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
   png_byte color_type;     /* see PNG_COLOR_TYPE_ below (from IHDR) */
   /* The following three should have been named *_method not *_type */
   png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
   png_byte filter_type;    /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
   png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */

   /* The following are set by png_set_IHDR, called from the application on
    * write, but the are never actually used by the write code.
    */
   png_byte channels;       /* number of data channels per pixel (1, 2, 3, 4) */
   png_byte pixel_depth;    /* number of bits per pixel */
   png_byte spare_byte;     /* to align the data, and for future use */

 下面是最简单的使用libpng读取并用opengl显示图片的代码:

 

/*
 * pngtest.c
 *
 *  Created on: 2014-10-27
 *      Author: HZY
 */

#include <stdio.h>
#include <stdlib.h>

#include "png.h"
#include "zlib.h"

#include "GL/freeglut.h"

unsigned char* buffer = NULL;
png_uint_32 width, height, color_type;

//获取每一行所用的字节数,需要凑足4的倍数
int getRowBytes(int width){
	//刚好是4的倍数
	if((width * 3) % 4 == 0){
		return width * 3;
	}else{
		return ((width * 3) / 4 + 1) * 4;
	}
}

//显示图片
void myDisplay() {
	glClear(GL_COLOR_BUFFER_BIT);
	//图片是否有透明度
	if (color_type == PNG_COLOR_TYPE_RGB) {
		glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
	} else if (color_type == PNG_COLOR_TYPE_RGBA) {
		glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
	}
	glFlush();
}

int main(int c, char** v) {
	png_structp png_ptr;
	png_infop info_ptr;
	int bit_depth;
	FILE *fp;

	printf("lpng[%s], zlib[%s]\n", PNG_LIBPNG_VER_STRING, ZLIB_VERSION);

	if ((fp = fopen("testrgb.png", "rb")) == NULL) {
		return EXIT_FAILURE;
	}
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL)
	{
		fclose(fp);
		return EXIT_FAILURE;
	}
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		fclose(fp);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return EXIT_FAILURE;
	}
	if (setjmp(png_jmpbuf(png_ptr))) {
		/* Free all of the memory associated with the png_ptr and info_ptr */
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(fp);
		/* If we get here, we had a problem reading the file */
		return EXIT_FAILURE;
	}
	/* Set up the input control if you are using standard C streams */
	png_init_io(png_ptr, fp);
	//读取png文件
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
	//获取png图片相关信息
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
			NULL, NULL, NULL);
	printf("width[%d], height[%d], bit_depth[%d], color_type[%d]\n",
			width, height, bit_depth, color_type);

	//获得所有png数据
	png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);
	//计算buffer大小
	unsigned int bufSize = 0;
	if (color_type == PNG_COLOR_TYPE_RGB) {
		bufSize = getRowBytes(width) * height;
	} else if (color_type == PNG_COLOR_TYPE_RGBA) {
		bufSize = width * height * 4;
	} else{
		return EXIT_FAILURE;
	}
	//申请堆空间
	buffer = (unsigned char*) malloc(bufSize);
	int i;
	for (i = 0; i < height; i++) {
		//拷贝每行的数据到buffer,
		//opengl原点在下方,拷贝时要倒置一下
		if(color_type == PNG_COLOR_TYPE_RGB){
			memcpy(buffer + getRowBytes(width) * i, row_pointers[height - i - 1], width * 3);
		}else if(color_type == PNG_COLOR_TYPE_RGBA){
			memcpy(buffer + i * width * 4, row_pointers[height - i - 1], width * 4);
		}
	}
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
	fclose(fp);

	glutInit(&c, v);
	glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(width, height);
	glutCreateWindow("hello png");
	glutDisplayFunc(&myDisplay);
	glutMainLoop();
	return 0;
}

 效果如图:



       
能显示RGB图片和RGBA的图片,代码里做了判断,用到了libpng,zlib,freeglut。在eclipse中cdt用mingw编译通过。

      所有源码在附件中。

 

  • 大小: 141.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics