libpng 是一套免费的、公开源代码的程序库,支持对 PNG 图形文件的创建、读写等操作。可以下载源代码。libpng 使用 zlib 程序库作为压缩引擎,zlib 也是著名的 gzip (GNU zip) 所采用的压缩引擎。zlib 是通用的压缩库,提供了一套 in-memory 压缩和解压函数,并能检测解压出来的数据的完整性(integrity)。zlib 也支持读写 gzip (.gz) 格式的文件这些都是免费和公开的哦。在下载了pbglib,并且要下载zlib,如何才能加到代码中呢?以VC6.为例来说明。其他CBuild等编译器相信也一样的。比如我们从网上下载了一个lpng1210.zip和zlib-1.2.3.tar.tar。首先把他们解压。在lpng的目录中寻找 projects/visualc6/libpng.dsw。并在zlib中寻找zlib-1.2.3/projects/visualc6 /zlib.dsw。用vc打开libpng工程文件,把zlib的工程文件也添加进去。设置好在setting中设置好的zlib.lib和pbg.lib的输出路径,以及include路径(这个简单方法相信大家都明白吧)。运行后,就生成了两个静态库了。lib做好以后,就可以将lib加到我们要做的工程中去。在link中设置好,并将png.h和zlib.h都加进去。这样就可以正式的使用libpng了!
libpng 的详细介绍:请点这里
libpng 的下载地址:请点这里
下面到重点内容了。如何用pnglib实现对文件的读写? 现在让我们来试着写一段代码来读取PNG像素数据(from File or Stream),并把读取的数据存储到一个数组rgba中,用来生成OpenGl纹理
typedef struct {
u8* pixelData;
int imageWidth;
int imageHeight;
}ImageInfo;
typedef struct {
u8* data;
int size;
int offset;
}ImageSource;
//----------------------------------------------------------------------------------------------------------------
static void pngReaderCallback(png_structp png_ptr, png_bytep data, png_size_t length)
{
ImageSource* isource = (ImageSource*)png_get_io_ptr(png_ptr);
if(isource->offset + length <= isource->size)
{
memcpy(data, isource->data + isource->offset, length);
isource->offset += length;
}
else
{
png_error(png_ptr,"pngReaderCallback failed");
}
}
//----------------------------------------------------------------------------------------------------------------
ImageInfo* decodePNGFromStream(const u8* pixelData, const u32& dataSize)
{
png_structp png_ptr;
png_infop info_ptr;
int width, height, rowBytes;
png_byte color_type; //可以是PNG_COLOR_TYPE_RGB,PNG_COLOR_TYPE_PALETTE.......等
png_byte bit_depth;
png_colorp palette;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
if (!png_ptr)
{
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
TFC_DEBUG("ReadPngFile: Failed to create png_ptr");
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
TFC_DEBUG("ReadPngFile: Failed to create info_ptr");
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
TFC_DEBUG("ReadPngFile: Failed to read the PNG file");
}
ImageSource imgsource;
imgsource.data = (u8*)pixelData;
imgsource.size = dataSize;
imgsource.offset = 0;
//define our own callback function for I/O instead of reading from a file
png_set_read_fn(png_ptr,&imgsource, pngReaderCallback );
/* **************************************************
* The low-level read interface in libpng ()
* **************************************************
*/
png_read_info(png_ptr, info_ptr);
width = info_ptr->width;
height = info_ptr->height;
color_type = info_ptr->color_type;
bit_depth = info_ptr->bit_depth;
rowBytes = info_ptr->rowbytes;
palette= info_ptr->palette;