你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 图形图象处理与游戏编程
利用C++类实现PNG图像读写及显示(二)
 

2  文件头数据块的结构

名称

字节数

说明

Width (宽度)

4

图像宽度(单位:像素,0为无效值)

Height (长度)

4

图像高度(单位:像素,0为无效值)

Bit depth (图像深度)

1

索引彩色图像:1248
灰度图像:1248
16
真彩色图像:816

Color type (颜色类型)

1

0:灰度图像,
2
:真彩色图像
3
:索引彩色图像
4
:带
α通道数据的灰度图像

6:带α通道数据的真彩色图像

Compression method (压缩方法)

1

显示所用压缩方法,国际标准中只定义了一种方法(method 0)

Filter method (滤波器方法)

1

滤波器方法

Interlace method (隔行扫描方法)

1

0:非隔行扫描;1 Adam7(Adam M. Costello开发的7遍隔行扫描方法

三、PNG类设计

这一小节我们设计一个名为MyPNG的类,主要功能包括(1)将一幅PNG图像文件读入内存,对应函数为PngLoadImage (const char *pstrFileName);(2)将内存中的图像数据保存为PNG图像,对应函数为PngSaveImage (const char *pstrFileName);(3)显示PNG图像,对应函数为Draw( CDC *pDC, int nX = 0, int nY = 0, int nWidth = -1, int nHeight = -1 )。通常,Window应用程序中的其他格式的图像显示可通过显示其对应位图实现。由于PNG图像数据的存放格式与位图格式不同,因此为了显示PNG图像,需要将PNG图像数据转换成对应的位图格式数据,类中的成员函数PngToBitmap()就是实现这个功能。此外,显示位图像素数据时,需要知道位图文件信息,因此要将PNG图像的信息(如宽度、高度等)转换成相应位图文件信息,实现该功能的类成员函数为FillBitmapInfo()。于是,可得到MyPNG类的头文件定义:

#ifndef _PNG_INC_

#define _PNG_INC_

#include "png.h"  //声明libpng库函数、png相关的结构体等信息的头文件

class MyPNG

{

public:

        MyPNG();

  ~MyPNG();  

  bool PngToBitmap();     //Png数据区转换到bitmap数据区

   bool FillBitmapInfo();

  BOOL Draw( CDC *pDC, int nX = 0, int nY = 0, int nWidth = -1, int nHeight = -1 ); //显示位图

   BOOL PngLoadImage (const char *pstrFileName);  //载入PNG

   BOOL PngSaveImage (const char *pstrFileName);  //pPixelBuffer的数据保存PNG

public:

  png_structp png_ptr;    //libpng定义的结构体指针,存放用于读/png图像的信息

  png_infop info_ptr;     // libpng定义的结构体指针,存放png文件信息

png_byte  *pbImage; //存放次序是R-G-B

//PNG图像数据,该数据存放规则与位图相反(第一个像素在左下角,自下而上,从左到右),即第一个像素在左上角(自上而下,从左到右存放)

    int  cxImgSize, cyImgSize; //图像宽度、高度

    int  cImgChannels;       //颜色通道

//图像深度,索引彩色图像:1248;灰度图像:124816;真彩色图像:816

    int  iBitDepth;

int  iColorType;   //颜色类型,0 --灰度图像,2--真彩色图像,3--索引彩色图像,4--α通道数据的灰度图像

               //6--α通道数据的真彩色图像

    png_color   bkgColor;      //背景颜色

BITMAPINFO m_bmi;      //位图文件信息

  BYTE   *pPixelBuffer;   //存放PNG的位图数据缓存区

    WORD  wImgRowBytes;   //每行的字节数

};

#endif

下面是类成员函数的详细定义。类的构造函数用来初始化成员变量信息,析构函数的作用是释放内存空间。

MyPNG::MyPNG()

{ png_ptr=NULL; info_ptr=NULL;  pbImage=NULL; pPixelBuffer=NULL;

     bkgColor.red=127; bkgColor.green=127; bkgColor.blue=127;   cxImgSize=0; cyImgSize=0; wImgRowBytes=0;

}

MyPNG::~MyPNG()

{ if (pbImage!=NULL) free(pbImage); if (png_ptr!=NULL) free(png_ptr);

     if (info_ptr!=NULL) free(info_ptr);    if (pPixelBuffer!=NULL) delete pPixelBuffer;

}

成员函数PngLoadImage从路径pstrFileName读入PNG图像,并将PNG图像数据转换成位图数据,设置位图信息。如果执行函数成功,返回TRUE,失败则返回FALSE。函数中使用了一个例外处理的宏定义,Try{} Catch(){};其详细定义在另外一个头文件cexcept.h (libpng例程visupng有该文件定义),这里不再列举。

BOOL MyPNG::PngLoadImage (const char *pstrFileName)

{   FILE  *pfFile;  png_byte  pbSig[8];

    double  dGamma;   int  i;

    png_color_16   *pBackground;  png_uint_32  ulChannels, ulRowBytes;

    static png_byte  **ppbRowPointers = NULL;

    if (!pstrFileName)  {pbImage=NULL;  return FALSE; } //文件名指针为空则返回

    if (!(pfFile = fopen(pstrFileName, "rb")))  { pbImage=NULL; return FALSE; } //打开PNG文件

    fread(pbSig, 1, 8, pfFile); //读取8PNG文件署名

    if (!png_check_sig(pbSig, 8))  {  pbImage=NULL; return FALSE;  } //检查PNG文件署名

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,

         (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); //创建结构体信息

    if (!png_ptr) {pbImage=NULL; return FALSE;} //创建失败,返回

    info_ptr = png_create_info_struct(png_ptr); //创建结构体

//创建失败,释放已创建信息,返回false

  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089