设为首页 加入收藏

TOP

使用 libpng 配合 GDI 完成对 png 图片的解析与显示(一)
2014-11-24 02:56:06 来源: 作者: 【 】 浏览:3
Tags:使用 libpng 配合 GDI 完成 png 图片 解析 显示

第一步: 使用 libpng 完成对 png 图像的解析


推荐阅读:


在这之前, 我们先做个假设:


1. 所使用的图片确实为 png 格式


做假设目的是为了减少演示代码的复杂度, 因为代码中没有对传入的图片是否为png进行检测, 进行过多的错误处理这不符合演示代码的书写习惯。


开始进行图片得读取:


long ReadPngData( const char *szPath, int *pnWidth, int *pnHeight, unsigned char **cbData )
{
FILE *fp = NULL;
long file_size = 0, pos = 0, mPos = 0;
int color_type = 0, x = 0, y = 0, block_size = 0;


png_infop info_ptr;
png_structp png_ptr;
png_bytep *row_point = NULL;


fp = fopen( szPath, "rb" );
if( !fp ) return FILE_ERROR; //文件打开错误则返回 FILE_ERROR


png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); //创建png读取结构
info_ptr = png_create_info_struct(png_ptr); //png 文件信息结构
png_init_io(png_ptr, fp); //初始化文件 I\O
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); //读取png文件

*pnWidth = png_get_image_width( png_ptr, info_ptr ); //获得图片宽度
*pnHeight = png_get_image_height( png_ptr, info_ptr ); //获得图片高度
color_type = png_get_color_type( png_ptr, info_ptr ); //获得图片颜色类型
file_size = (*pnWidth) * (*pnHeight) * 4; //计算需要存储RGB(A)数据所需的内存大小
*cbData = (unsigned char *)malloc(file_size); //申请所需的内存, 并将传入的 cbData 指针指向申请的这块内容


row_point = png_get_rows( png_ptr, info_ptr ); //读取RGB(A)数据


block_size = color_type == 6 4 : 3; //根据是否具有a通道判断每次所要读取的数据大小, 具有Alpha通道的每次读4字节, 否则读3字节


//将读取到的RGB(A)数据按规定格式读到申请的内存中
for( x = 0; x < *pnHeight; x++ )
for( y = 0; y < *pnWidth*block_size; y+=block_size )
{
(*cbData)[pos++] = row_point[x][y + 2]; //B
(*cbData)[pos++] = row_point[x][y + 1]; //G
(*cbData)[pos++] = row_point[x][y + 0]; //R
(*cbData)[pos++] = row_point[x][y + 3]; //Alpha
}


png_destroy_read_struct(&png_ptr, &info_ptr, 0);
fclose( fp );


return file_size;
}


上面我们定义了一个 ReadPngData 的函数, 看一下这个函数的参数:


long ReadPngData(
const char *szFileName, //png文件路径
int *pnWidth, //指针类型, 用于传出图片宽度
int *pnHeight, //指针类型, 用于传出图片高度
unsigned char **cbData //二级指针, 用于指向所申请的用于存储RGB(A)的内存地址
)


在代码中, 还根据获得的色彩类型对每次需要读取的字节数做了简单的判断


block_size = color_type == 6 4 : 3; //根据是否具有a通道判断每次所要读取的数据大小, 具有Alpha通道的每次读4字节, 否则读3字节


该语句使用了问号表达式代替了 if..else 进行判断, 减少了代码的行数。


接下来就是使用两个 for 循环完成对RGB(A)数据的读取工作, 在这里, 你也可以通过不同的 RGB(A) 之间的运算, 将图像呈现出不同的显示效果。


现在, cbData指针指向的内存中就是我们所需的 RGB(A) 数据了, 有了这份数据, 就可以完成显示。该函数已被封装为 .h 头文件, 使用可以直接调用, 完成的封装代码如下: gdipng.h


- gdipng.h


#pragma once


//////////////////////////////////////////////////////////////////////////


#include
#include "png.h"


//////////////////////////////////////////////////////////////////////////


#define FILE_ERROR -1


//////////////////////////////////////////////////////////////////////////


long ReadPngData( const char *szFileName, int *pnWidth, int *pnHeight, unsigned char **cbData );


//////////////////////////////////////////////////////////////////////////


long ReadPngData( const char *szPath, int *pnWidth, int *pnHeight, unsigned char **cbData )
{
FILE *fp = NULL;
long file_size = 0, pos = 0, mPos = 0;
int color_type = 0, x = 0, y = 0, block_size = 0;


png_infop info_ptr;
png_structp png_ptr;
png_bytep *row_point = NULL;


fp = fopen( szPath, "rb" );
if( !fp ) return FILE_ERROR; //文件打开错误则返回 FILE_ERROR


png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); //创建png读取结构
info_ptr = png_c

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇VC6 下 libpng 库的编译与初步使用 下一篇C++矩阵处理工具——Eigen

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Sphinx : 高性能SQL (2025-12-24 10:18:11)
·Pandas 性能优化 - (2025-12-24 10:18:08)
·MySQL 索引 - 菜鸟教 (2025-12-24 10:18:06)
·Shell 基本运算符 - (2025-12-24 09:52:56)
·Shell 函数 | 菜鸟教 (2025-12-24 09:52:54)