`
hzy3774
  • 浏览: 993143 次
  • 性别: 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
分享到:
评论

相关推荐

    使用 Libpng 配合 GDI 完成对 png 图片的解析与显示

    在本文中,我们将深入探讨如何使用 Libpng 配合 GDI(Graphics Device Interface)来解析和显示PNG图像。PNG(Portable Network Graphics)是一种无损压缩的位图格式,广泛应用于网页设计、软件开发以及图像处理等...

    Qt:解决使用png图片时,报错libpng warning: iCCP: known incorrect sRGB profile的问题

    当一个PNG图像包含了一个与sRGB(标准红绿蓝)色彩空间不兼容的iCCP时,libpng库在解析时会发出警告,因为这可能导致颜色显示不准确。 出现“libpng warning: iCCP: known incorrect sRGB profile”错误的常见原因...

    图像解码之二——使用libpng解码png图片1

    对于文件读取,通常会使用 `fopen` 打开文件,然后通过 `png_init_io` 函数将文件指针关联到 libpng: 1: fp = fopen(filename, "rb"); 2: if (!fp) 3: { 4: printf("Can't open %s\n", filename); 5: return ...

    将png格式图片转换成YUV格式,C++

    1. **读取PNG图像**:使用libpng库,可以解析PNG文件的元数据,如宽度、高度、色彩类型等,并解码图像数据。libpng提供了一系列API,如`png_read_image()`,可以读取像素数据到内存缓冲区。 2. **颜色空间转换**:...

    MFC利用libpng源码库显示PNG图片

    - **加载PNG文件**:使用libpng提供的函数,如`png_create_read_struct`,`png_init_io`和`png_read_image`来读取PNG文件内容。 - **转换数据**:PNG图像数据通常以像素数组形式存在,需要将其转换为位图数据,...

    基于Qt的libpng使用

    在Qt中读取PNG图片,我们可以通过libpng库提供的函数来解析PNG文件,获取图像的像素数据。这些函数包括`png_create_read_struct`、`png_init_io`、`png_read_info`等,它们允许我们获取图像的宽度、高度、颜色类型等...

    libpng源码 png

    PNG(Portable Network Graphics)是一种广泛使用的无损压缩的位图图像格式,因其开源、免费、跨平台和良好的压缩效率而受到开发者的欢迎。`libpng`是官方支持的PNG库,用于读取、写入和处理PNG图像。在这个资源中,...

    libpng.lib+zlib.lib+zlib1d.dll+libpng15d.dll+png.h

    1. 加载PNG图像:使用libpng库解析PNG文件,解压缩数据并将其存储在内存中的适当数据结构。 2. 创建OpenGL纹理对象:在OpenGL上下文中创建一个新的纹理对象,并设置其属性。 3. 将图像数据上传到GPU:将内存中的PNG...

    利用libpng库读取png图片像素颜色索引值

    本文代码利用libpng库解码读取png图片,获取图片像素的颜色索引值,并将结果保存在opencv的Mat数据容器中。

    MFC利用png实现透明按钮的demo示例,可以直接加载PNG文件或先包含到程序资源中再加载 按钮的高亮与灰度图像都是自动生成

    4. **加载PNG到内存位图**:利用libpng解析出的像素数据,创建一个CBitmap对象,并将其绑定到兼容设备上下文。这个过程可能需要一些转换,因为MFC的CBitmap不直接支持Alpha通道,所以可能需要手动处理Alpha值。 5. ...

    libpng-1.6.6.tar_libpng_

    1. **PNG格式支持**:libpng提供读取和写入PNG图像文件的API,遵循PNG规范,确保正确解码和编码PNG数据流。 2. **错误处理**:库内包含丰富的错误检查和处理机制,以防止数据损坏或不完整时出现程序崩溃。 3. **内存...

    VC显示PNG格式图片

    2. **打开PNG文件**:使用`fopen`函数打开PNG文件,并通过libpng提供的`png_create_read_struct`和`png_create_info_struct`创建读取结构。 3. **设置错误处理回调**:libpng允许你定义错误处理函数,当出现错误时...

    libpng-1.6.26.tar.gz

    libpng,全称为“Library for Processing PNG”,是一个开源的PNG(Portable Network Graphics)图像处理库,广泛应用于各种软件和系统中,用于读取、写入和处理PNG格式的图像。libpng-1.6.26是该库的一个具体版本,...

    Google的libpng

    1. **读取PNG图像**:libpng库提供了读取PNG文件的函数,能够解析PNG文件头信息,包括图像的宽度、高度、颜色类型、位深度等,并将图像数据解压缩到内存中。 2. **写入PNG图像**:库还允许开发者创建新的PNG图像或...

    libpng-1.2.40.tar.gz.gz

    《深入解析libpng-1.2.40:PNG图像处理库的核心技术》 PNG(Portable Network Graphics)是一种无损压缩的位图格式,广泛应用于网页设计、软件开发以及数字图像处理等领域。libpng是PNG图像格式的开源库,它为...

    GL2libpng-android-显示PNG图片.rar

    这个项目提供了在Android应用中使用OpenGL ES显示PNG图片的一个实例,对于希望学习Android原生图形编程或者提升图形性能的开发者来说,是一个宝贵的参考资料。通过这种方式,开发者可以更高效地处理图像,为用户提供...

    OpenGL中使用png图标的方法

    在OpenGL编程中,通常我们...总结来说,不使用libpng在OpenGL中加载PNG图标涉及读取PNG文件格式、解压数据、创建和更新纹理对象,以及在场景中正确绘制。提供的代码文件可能展示了这样一种实现,值得进一步研究和学习。

    libpng.lib,zlib.lib,libpng16.dll

    libpng负责解析PNG文件格式,而zlib则处理图像数据的压缩和解压缩。 在开发过程中,确保这些库文件正确配置和可用至关重要。对于libpng.lib和zlib.lib这样的静态库,开发者需要在编译项目时链接这些库;对于libpng...

    libpng-1.2.56.tar.gz

    - **读取PNG图像**:libpng库提供了解析PNG文件结构的功能,包括解码PNG图像数据、恢复颜色空间信息、处理透明度等。 - **写入PNG图像**:库允许开发者创建新的PNG文件,设定图像的大小、颜色模式、透明度等属性,...

    libpng-1.6.35.tar.gz

    《深入解析libpng-1.6.35:PNG图像处理的核心库》 PNG(Portable Network Graphics)是一种无损、有损压缩的位图格式,广泛应用于网页设计、图形编程和数字图像处理领域。在PNG图像处理的背后,有一个至关重要的库...

Global site tag (gtag.js) - Google Analytics