利用C++类实现PNG图像读写及显示
一j誉
摘要:运用libpng库函数,设计了一个可读写PNG格式图像的c++类.同时,在
VC++6.0开发平台下,设计出一个基于多文档结构的图像浏览器,实现PNG格式图像的
读写及显示.
关键词:PNG;图像格式;C++;类
一
,前言
PNG是一种可携式网络图像格式,其名称来源于非官方的
“PNG’SNotGIF”,是一种位图文件(Bitmapfile)存储格式,读
成”ping”.设计PNG时,保留了GIF的众多特性,如(1)
使用彩查表(也称调板)可支持256种颜的彩图
像;(2)流式读/写性能(Streamability);(3)逐次逼近显示
(Progressivedisplay);(4)透明性(Transparency);(5)使用
无损压缩等.同时,也增加了一些GIF文件格式所不具备的特
性,如(1)每个像素为48位的真彩图像;(2)每个像素为
l6位的灰度图像;(3)可为灰度图和真彩图添加通道;
(4)添加图像的信息;(5)使用循环冗余码(Cyclicredun—
dancycode,CRC)检测损害的文件;(6)加快图像显示的逐次
逼近显示方式;(7)标准的读/写工具包等.目前,PNG已
成为国际互网络联盟(WorldWideWebConsortium,W3C)推荐的
标准[2],是互联网中常用的图像格式之一,常见的绘图软件
和浏览器均支持PNG图像浏览(其中IE4.0以上版本均支持
PNG).本文利用提供的libpng库
【3】,设计一个可读写PNG图像的C++类,同时利用
VC++6.0开发平台,通过PNG图像浏览器的实例设计,说
明PNG类的使用方法.
二,PNG文件结构
PNG图像由一个8字节的PNG文件署名(PNGfilesigna-
ture)域和按照特定结构组织的3个以上的数据块(Chunk)组
成.PNG文件署名域是用来识别该文件是不是PNG文件,如
果用十进制数表示,该域的值依此是137,80,78,71,13,10,
26,l0,(对应的十六进制数为89,50,4e,47,Od,0a,
1a,0a).PNG数据块由表1所示的4个域构成【2].根据类
型的不同,PNG数据块又可分为两种:一种是关键数据块
(Criticalchunk),这是标准的数据块,另一种叫做辅助数据块
(Ancillarychunks),是可选的数据块.其中,关键数据块又定
义了4个标准数据块,分别为(1)文件头数据块IHDR
(Headerchunk);(2)调板数据块PLTE(Palettechunk);
(3)图像数据块IDAT(Imagedatachunk);(4)图像结束数据
IEND(Imagetrailerchunk).由于篇幅限制,这里只介绍与编程
设计最为密切的文件头数据块结构,具体见表2.
表1PNG数据块的结构
名称字节数说明
指定数据块中数据域的长度,其长
Length(长度)4度
不超过(2~1)字节
ChunkTypeCode数据块类型码由ASCII字母(A-Z
(数据块类型码)4和a—z)组成
ChunkData(数据块可变长度存储按照ChunkTypeCode指定的
数据)数据
CRC(循环冗余检存储用来检测是否有错误的循环4
测)冗余码
表2文件头数据块的结构
名称字节数说明
Width(宽度)4图象宽度(单位:像素,0为无效值)
Height(长度)4图象高度(单位:像素,0为无效值)
索引彩图象:1,2,4或8Bi
tdepth
l灰度图象:1,2,4,8或16
(图象深度)真彩图象
:8或16
O:灰度图象,
2:真彩图象
Colortype
l3:索引彩图象(颜类型
)4
:带a通道数据的灰度图象
6:带a通道数据的真彩图象
Compressionmethod显示所用压缩方法,国际标准中只定义
getsavefilenamef压缩方法)l了一种方法(method0)
Filtermeth0d
1滤波器方法
(滤波器方法)
Interlacemeth0d0:非隔行扫描:1:Adam7(由Adam
(隔行扫描方法)1M.Costello开发的7遍隔行扫描方法
{tt…i∞』t_’tMt -I
实用第一/智慧密集
三,PNG类设计
设计一个名为MyPNG的类,图像,对应函数为Draw(CDC
pDC,intnX=0,intnY=0,intnWidth=一1,intnHeight=
一
1).通常,Window应用程序中的其他格式的图像显示可通
过显示其对应位图实现.由于PNG图像数据的存放格式与位
图格式不同,因此为了显示PNG图像,需要将PNG图像数据
转换成对应的位图格式数据,类中的成员函数PngToBitmap()
就是实现这个功能.此外,显示位图像素数据时,需要知道位
图文件信息,因此要将PNG’图像的信息(如宽度,高度等)转
换成相应位图文件信息,实现该功能的类成员函数为Fil1.
Bitmaplnfo().于是,可得到MyPNG类的头文件定义:
#ifndefNGJNC一
#defineNG/NC一
#includepng.h
//声明libpng库函数,png相关的结构体等信息的头文件
classMyPNG
{
public:
MyPNG():
~
MyPNG():
boolPngToBitmap()://将Png数据区转换到bitmap数据区
boolFillBitmaplnfo():
BO0LDraw(CDCpDC,intnX=0,intnY=0,intnWidth
=一
1,intnHeight=一1)://显示位图
BOOLPngLoadlmage(constcharpstrFileName):
f,载7\,PNG
BOOLPngSavelmage(constcharpstrFileName):
//将pPixelBuffer的数据保存PNG
public:
png_structppngjotr;
//libpng定义的结构体指针.存放用于读/写png图像的信息
pngjnfopinfojotr;
//libpng定义的结构体指针,存放png文件信息
png_bytepblmage;//存放次序是R—G—B
//PNG图像数据.该数据存放规则与位图相反(第一个像素
//在左下角,自下而上.从左到右),即第一个像素在左上角
//(自上而下,从左到右存放)
intcxlmgSize,cylmgSize;//图像宽度,高度
intclmgChannels;//颜通道图像深度,索引彩图像:
//1,2,4或8:灰度图像:1,2,4,8或16:真彩图像:8或16
intiBitDepth;
intiColorType;//颜类型,O一一灰度图像,2一一真彩图
//象,3一一索引彩图像,4一一带ot通道数据的灰度图像
//6一一带通道数据的真彩图像
png_colorbkgColor;//背景颜
BITMAPlNFOm-bmi;//位图文件信息
BYTEpPixelBuffer;//存放PNG的位图数据缓存区
WORDwlmgRowBytes;//每行的字节数
):
#endif
下面是类成员函数的详细定义.类的构造函数用来初始化
7
:
2
_∥
:
皇-
2
_
00
I翟
9~
撼
7
西与维自;;i
成员变量信息,析构函数的作用是释放内存空间.
MyPNG::MyPNG()
{pngJotr=NULL;infojotr=NULL;pblmage=NULL;
pPixelBuffer=NULL;
d==127;bkgCotor.blue=
127;cxlmgSize=O:cylmgSize=O:wlmgRowBytes=0:
)
MyPNG::~MyPNG()
{if(pblmage!=NULL)free{pblmage):
if(png_ptr!=NULL)free(png_ptr)
.f(infojotd=NULL)free(infojotr):
If(pPixelBuffer!=NULL)deletepPixelBuffer;
)
成员函数PngLoadImage从路径pstrFileName读入PNG图
像,并将PNG图像数据转换成位图数据,设置位图信息.如
果执行函数成功,返回TRUE,失败则返回FALSE.函数中使
用了一个例外处理的宏定义,Try{}Catch(){};其详细定义在
另外一个头文件cexcept.h(1ibpng例程visupng有该文件定
义),这里不再列举.
BOOLMyPNG::PngLoadlmage(constcharpstrFileName)
(FILEpfFile;png_bytepbSig【8】:
doubledGamma:inti:
png._color._
l6pBackground;png_uint_
32ulChannels,ul—
RowBytes;
staticpng_byte%plsbRowPointers=NULL;
if(fpstrFileName)(pblmage=NULL;returnFALSE;)
//文件名指针为空则返回
if(i(pfFile=fopen(pstrFileName,rb))){pblmage=
NULL;returnFALSE;)//打开PNG文件
fread(pbSig,1,8,pfFile)://读取8位PNG文件署名
iff!png_check_sig{pbSig,8)){pblmage=NULL;return
FALSE;)//检查PNG文件署名
pngjotr=png_create_read._struct
(PNG_LIBPNG_VERSTRING,NULL.
(png_errorjotr)png_cexcept_error,(png_errorjotr)NULL):
//创建结构体信息
if(!png_ptr){pblmage=NULL;returnFALSE;)
//创建失败,返回
infod3tr=png_createinfostruct(pngjotr)//创建结构体
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论