【PNG overview】PNG专题!

来源:互联网 发布:人工智能 电话销售 编辑:程序博客网 时间:2024/04/29 18:05

这段时间因为工作原因开始接触PNG,遇到问题的时候,在网上搜索资料总是零零碎碎,而且有很多的说法根没就是人云亦云,信手拈来,根本没有经过详细的认证是否正确,这样的例子很多。我这里搜集了一些资料,希望不要犯下相同的错误,程序部除了说明出处的以外都是自己写的,希望对大家有点帮助。(索取代码信箱icebug@126.com ,代码公布网址 http://www.dingge.com/forum/ )

  因为想写的比较全面,所以分了很多的部分,以下是索引,前面的很浅显,后面的才是程序设计方面的内容

(转载请注明出处  http://www.dingge.com/forum/post.asp?action=edit&BoardID=43&replyID=37801&ID=8591&star=1

(一)什么是PNG
    1.PNG格式的概念
    2.PNG的图片文件格式特性
    3.PNG的比较
(二)PNG格式详细分析
    1.PNG格式总览
    2.PNG格式四大金刚
    3.PNG格式天兵天将
    4.PNG格式测试
(三)PNG格式的读写
     1.C语言读写
     2.MFC中Cimage类读,写,显示PNG
        3.MFC中CxImage读,写,显示PNG
        4.GDI+对PNG的应用
        5.PNG在D3D中的应用(dix 9.0c)
(四)PNG开放库
      1.未完成
      2.未完成........................


第一章  什么是PNG
    1.PNG格式的概念
   PNG全名Portable Network Graphics,字面上翻译过就是“可携性网络用图形”,这简单几个字已經明白定义了PNG的用途以及主要发展方向。1996年,PNG Group向W3C (World Wide Web Consortium)提出一种多媒体图形格式,重点在于改进现有JPG跟 GIF的缺点,并且提供更多新的概念与压缩模式,在提出后得到W3C的认可与推荐。在1st October, 1996,W3C正式发函公告,推荐PNG为最佳的图形格式,并且以“PNG Delivers Higher Quality Graphics for Web Page Design”这样高度推崇的文字来作为该文件的标头,看来PNG在1996年倒是相当风光。
   PNG要如何发音?基本上跟“ping”的发音相同,或者是你想念做“P-N-G”也可以。PNG的非官方名称为“PNG's Not GIF”,颇挑釁,但是这也反映出目前网络图形的现实状況。怎么说呢,话说网络最常用的图形格式GIF,其专利权属Unisys所有,早在1994年底,Unysis公司就宣布,要求有支持GIF软件的作者須缴交专利费。此举对于一向以免费开放架构为主流的网络生态,杀伤力非常大。这时不少人便开始反对Unisys的作风,并且共同开发另一种图形标准,希望能完全取代GIF,而PNG(PNG's Not GIF)也就孕育而生,从1996年起加入网络图形的阵营。(摘自CSDN)

   2.PNG的图片文件格式特性
  由于终极目标是为了取代GIF,因此PNG保留了大部分GIF的特性,像是Index Color、交举显示、透明区域、額外说明資訊等,都是GIF有的属性,而PNG在设定之初也保留了这样的原始功能。毕竟,想要取代对方,敌人会的招数自己还是得学学。
  除此之外,PNG还加入了不少GIF所沒有的新功能,包括储存全彩影像(24bit)、256级透明层次(Alpha Channel)、Gamma值信息、CRC Check、可定义的级层显示、压缩方式可以随时扩充等,都是相当棒的特性,乍看之下,比起GIF跟JPG真的进步不少。(摘自CSDN)

 

PNG文件格式保留GIF文件格式的下列特性:

使用彩色查找表或者叫做调色板可支持256种颜色的彩色图像。
流式读/写性能(streamability):图像文件格式允许连续读出和写入图像数据,这个特性很适合于在通信过程中生成和显示图像。
逐次逼近显示(progressive display):这种特性可使在通信链路上传输图像文件的同时就在终端上显示图像,把整个轮廓显示出来之后逐步显示图像的细节,也就是先用低分辨率显示图像,然后逐步提高它的分辨率。
透明性(transparency):这个性能可使图像中某些部分不显示出来,用来创建一些有特色的图像。
辅助信息(ancillary information):这个特性可用来在图像文件中存储一些文本注释信息。
独立于计算机软硬件环境。
使用无损压缩。
 
PNG文件格式中要增加下列GIF文件格式所没有的特性:

每个像素为48位的真彩色图像。
每个像素为16位的灰度图像。
可为灰度图和真彩色图添加α通道。
添加图像的γ信息。
使用循环冗余码(cyclic redundancy code,CRC)检测损害的文件。
加快图像显示的逐次逼近显示方式。
标准的读/写工具包。
可在一个文件中存储多幅图像。 (摘自pcadvance.cn)

PNG vs GIF 大对决
 

  口口声声要取代GIF,连PNG这个名字都摆明了就是要跟死要钱的GIF作对(PNG's Not GIF),那就得拿出真本事来,来能够让使用者信服。以下分别针对各种不同属性的图片文件,做一完整的测试,比较看看,PNG是否有取代GIF的实力。


  测试一:全彩Photo图片
 

  取样标准选用短景深的花卉摄影,主要目的在于,比较能够清楚了解图与压缩过后的解像能力。前景花卉的枝叶是否轮廓清晰,而后景朦胧的部分是否清楚展现其连续色级也是重点。红跟绿的对比配色,对于颜色数限制下的色彩展现,也有相当的测试性质。 GIF 16色 7.15k GIF 32色 9.63k GIF 64色 12.9k GIF 128色 15.6k 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 PNG 16色 9.51k PNG 16色12k PNG 16色15k PNG16色 16.5k   首先是GIF与PNG的比较。测试之后,非常无奈的发现,PhotoShop似乎没有对PNG以及GIF的压缩格式分别作最佳化。在抖色的色彩排列上,上下的比较可以很明显的看到,不论是GIF或是PNG,同一色彩数的抖色方式皆相同,也因此在画质上,两种格式完全没有差异。

  既然画质没有差异,那能够比较的只剩下图片文件大小。在全彩照片的测试中,GIF在每一个颜色数中都占尽上风,平均图片文件只要PNG的80%大小,在全彩复杂图形的压缩上保有一定的优势。PNG在这次的测试中占居第二。

  测试二:全彩Photo图片 --> 24bit图形
 


JPG 25-Q 5.97k JPG 50-Q 9.19k JPG 75- Q 18.9k JPG 100- Q 38.3k 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 图片点击可在新窗口打开查看 PNG 24bit 57.5k


  PNG在规格上可以压制24bit全彩图形,所以我们也增加了与JPG的比较测试。比较方式为,JPG采用分级段缩测试,分别由25、50、75到100,而PNG方面由于PhotoShop并未提供压缩比设定,在PNG规格上亦未标明24Bit图形的压缩品质如何控制,所以仅以一个样本来做比较。(PNG栏中的四张图皆为同一张,为了方便与上面四张JPG比较而复制四份)

  测试结果发现,JPG在50的压缩品质下已经相当接近原图,而在75的压缩品质下,几乎已是很难发现压缩失真的痕迹。JPG的压缩方式在压缩全彩图片上确实优秀,而且K 数非常小,9K的画质已是吓吓叫。反观PNG,目前的24bit图片效果似乎中看不重用,图形品质虽好,但是在文件大小上的劣势却相当明显。看来24bit的PNG图形应用,还有待大力改进。(摘自mysoo.net)  

PNG的背景透明

   接触PNG透明的做多的应该算是网页愕,毕竟PNG格式本来就是为网络开发的,不过非常不幸的是作为浏览器的老大微软IE却一直不支持PNG的透明(个人觉得这个很具有讽刺意味)。听说这是和曾经的一次IE支持PNG造成安全漏洞有原因,不过居然这么久了,微软还没有解决到这个问题,而是非常粗暴的堵上这个功能,大家看到下面的图片就是PNG格式的如果你是IE看的话肯定会有一个灰度的背景,如果你再用火狐或者非IE浏览器查看的话竟会发现是一张过渡非常精美的半透明图片。

图片点击可在新窗口打开查看图片点击可在新窗口打开查看图片点击可在新窗口打开查看

 

因为我个人不是网页设计,对这个研究不是很深入,因此,我在这里从网上摘抄一段代码,解决IE中无法显示PNG透明的问题。

Png透明图片在网页上用会出现灰底的问题,以前就碰到这问题了,没有去找解决方法, 今天在做一个页面的时候想到用PNG图片做背景, 找到了一个解决方法.
用一个样式来把这个图片加到table里去,以下是样式:

.pngbg{left:140px;  
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/login_bg.png',sizingMethod='scale');
background-image:none;
}
这个样式名随便取的


因为加了这个样式后,所以表格里的事件会无效, 所以必须在所用的table加上这句:style='position:relative'

 

还有一种方法是

把下面的代码放在head区就可以解决问题了。

<script type="text/javascript">
function correctPNG()
{
for(var i=0; i<document.images.length; i++)
{
var img = document.images[i]
var imgName = img.src.toUpperCase()
if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
{
var imgID = (img.id) ? "id='" + img.id + "' " : ""
var imgClass = (img.className) ? "class='" + img.className + "' " : ""
var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "
var imgStyle = "display:inline-block;" + img.style.cssText
if (img.align == "left") imgStyle = "float:left;" + imgStyle
if (img.align == "right") imgStyle = "float:right;" + imgStyle
if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle
var strNewHTML = "<span " + imgID + imgClass + imgTitle
+ " style=/"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
+ "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
+ "(src=/'" + img.src + "/', sizingMethod='scale');/"></span>"
img.outerHTML = strNewHTML
i = i-1
}
}
}
window.attachEvent("onload", correctPNG);
</script>
       还有一些朋友,在photoshop中生成PNG的时候,选择了索引方式保存,这样IE也会显示PNG的透明背景,不过这样的背景并不是半透明背景,而是关键色的,效果当然不是很理想,还有些朋友开始问我怎么用photoshop中生成PNG的问题了,我想这个并不是本文关心的话题,但是我还是给出几个链接方便大家。
(很抱歉的告诉大家,找了半天居然没有发现合适的文章,稍后我会写怎么生成PNG的图片)
 

第二章  PNG格式详细分析

1.PNG格式总览

国内系统介绍PNG格式的网站很少,查找了很多资料,发现主要是来自gameres上的一篇文章,其余的网站和个人博客基本上都是摘抄这个,后来有人做了一些修改,更加完善了。我开始分析PNG也是从这篇文章开始的,非常感谢这篇文章(点击查看原文)。以下是对PNG格式的一些分析。

PNG图像格式文件(或者称为数据流)由一个8字节的PNG文件署名(PNG file signature)域和按照特定结构组织的3个以上的数据块(chunk)组成。

PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块。虽然PNG文件规范没有要求PNG编译码器对可选数据块进行编码和译码,但规范提倡支持可选数据块。(摘自gameres)

图片点击可在新窗口打开查看


要讲解PNG格式,就不得不拿出一张经典的PNG格式测试图(上图来自PNG测试站点),以后的很多分析内容都会围绕着这张图展开,大家下载这张图到自己的电脑上,用图片点击可在新窗口打开查看UltraEdit-32这类软件打开,然后来分析PNG图片的结构(以下资料来自网络)

PNG企图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。流式网络图形格式(Portable Network Graphic Format,PNG)名称来源于非官方的“PNG's Not GIF”,是一种位图文件(bitmap file)存储格式,读成“ping”。PNG用来存储灰度图像时,灰度图像的深度可多到16位,存储彩色图像时,彩色图像的深度可多到48位,并且还可存储多到16位的α通道数据。PNG使用从LZ77派生的无损数据压缩算法。

PNG数据块(Chunk)
 

PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块。虽然PNG文件规范没有要求PNG编译码器对可选数据块进行编码和译码,但规范提倡支持可选数据块。

下表就是PNG中数据块的类别,其中,关键数据块部分我们使用深色背景加以区分。

PNG文件格式中的数据块
      
数据块符号
      
数据块名称
多数据块
可选否
位置限制
IHDR 文件头数据块 否 否 第一块 cHRM 基色和白色点数据块 否 是 在PLTE和IDAT之前 gAMA 图像γ数据块 否 是 在PLTE和IDAT之前 sBIT 样本有效位数据块 否 是 在PLTE和IDAT之前 PLTE 调色板数据块 否 是 在IDAT之前 bKGD 背景颜色数据块 否 是 在PLTE之后IDAT之前 hIST 图像直方图数据块 否 是 在PLTE之后IDAT之前 tRNS 图像透明数据块 否 是 在PLTE之后IDAT之前 oFFs (专用公共数据块) 否 是 在IDAT之前 pHYs 物理像素尺寸数据块 否 是 在IDAT之前 sCAL (专用公共数据块) 否 是 在IDAT之前 IDAT 图像数据块 是 否 与其他IDAT连续 tIME 图像最后修改时间数据块 否 是 无限制 tEXt 文本信息数据块 是 是 无限制 zTXt 压缩文本数据块 是 是 无限制 fRAc (专用公共数据块) 是 是 无限制 gIFg (专用公共数据块) 是 是 无限制 gIFt (专用公共数据块) 是 是 无限制 gIFx (专用公共数据块) 是 是 无限制 IEND 图像结束数据 否 否 最后一个数据块

为了简单起见,我们假设在我们使用的PNG文件中,这4个数据块按以上先后顺序进行存储,并且都只出现一次。

数据块结构
 

PNG文件中,每个数据块由4个部分组成,如下:

名称 字节数 说明 Length (长度) 4字节 指定数据块中数据域的长度,其长度不超过(231-1)字节 Chunk Type Code (数据块类型码) 4字节 数据块类型码由ASCII字母(A-Z和a-z)组成 Chunk Data (数据块数据) 可变长度 存储按照Chunk Type Code指定的数据 CRC (循环冗余检测) 4字节 存储用来检测是否有错误的循环冗余码

CRC(cyclic redundancy check)域中的值是对Chunk Type Code域和Chunk Data域中的数据进行计算得到的。CRC具体算法定义在ISO 3309和ITU-T V.42中,其值按下面的CRC码生成多项式进行计算:

x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1

下面,我们依次来了解一下各个关键数据块的结构吧。

2.PNG格式四大金刚

PNG必需的关键数据块主要是有四分组成,分别是IHDR,PLTE,IDAT,IEND ,其中PLTE 数据块只是和索引彩色图像有关的,如果是RGB格式的PNG,里面可以没有PLTE数据。这样来说其实PNG数据的主要分就是三部分IHDR,IDAT,IEND-----分别是文件头,数据部分和文件结尾。

IHDR
 

文件头数据块IHDR(header chunk):它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。

文件头数据块由13字节组成,它的格式如下表所示。

域的名称
字节数
说明
Width 4 bytes 图像宽度,以像素为单位 Height 4 bytes 图像高度,以像素为单位 Bit depth 1 byte 图像深度:
索引彩色图像:1,2,4或8
灰度图像:1,2,4,8或16
真彩色图像:8或16 ColorType 1 byte 颜色类型:
0:灰度图像, 1,2,4,8或16
2:真彩色图像,8或16
3:索引彩色图像,1,2,4或8
4:带α通道数据的灰度图像,8或16
6:带α通道数据的真彩色图像,8或16 Compression method 1 byte 压缩方法(LZ77派生算法) Filter method 1 byte 滤波器方法 Interlace method 1 byte 隔行扫描方法:
0:非隔行扫描
1: Adam7(由Adam M. Costello开发的7遍隔行扫描方法)

现在用图片点击可在新窗口打开查看UltraEdit-32打开上面的那张PNG格式测试图,我们开始分析它的数据结构。


图片点击可在新窗口打开查看[快车下载]:
图片点击可在新窗口打开查看

被红色选中的头8个字节即为PNG文件的标识,它说名了这个文件是一个PNG文件。
除了被红色选中的以外的白色部分,就是IHDR自身描述的数据块了

  • 00 00 00 0D 说明IHDR头块长为13
  • 49 48 44 52 IHDR标识
  • 00 00 01 00 图像的宽,256像素
  • 00 00 01 00 图像的高,256像素
  • 08 色深
  • 02 颜色类型,真彩色图像
  • 00 PNG Spec规定此处总为0(非0值为将来使用更好的压缩方法预留),表示使压缩方法(LZ77派生算法)
  • 00 同上
  • 00 非隔行扫描
  • 最后的4位数据是 CRC校验码  确保以上数据的完整性

    PLTE
     

    调色板数据块PLTE(palette chunk)包含有与索引彩色图像(indexed-color image)相关的彩色变换数据,它仅与索引彩色图像有关,而且要放在图像数据块(image data chunk)之前。

    PLTE数据块是定义图像的调色板信息,PLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成:

    颜色
          

    字节
          

    意义
          

    Red

    1 byte

    0 = 黑色, 255 = 红

    Green

    1 byte

    0 = 黑色, 255 = 绿色

    Blue

    1 byte

    0 = 黑色, 255 = 蓝色

    因此,调色板的长度应该是3的倍数,否则,这将是一个非法的调色板。

    对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数(如图像色深为4的时候,调色板中的颜色数不可以超过2^4=16),否则,这将导致PNG图像不合法。

    真彩色图像和带α通道数据的真彩色图像也可以有调色板数据块,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像。

    因为这张测试图片是真彩图像,所以没有PLTE数据块。

    IDAT
     

    图像数据块IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。

    IDAT存放着图像真正的数据信息,因此,如果能够了解IDAT的结构,我们就可以很方便的生成PNG图像。 


    图片点击可在新窗口打开查看[快车下载]:
    图片点击可在新窗口打开查看
    在这留白的部分就是我们的IDAT数据部分

  • 红色选中部分表示IDAT数据块的长度
  • 黄色部分49 44 41 54 IDAT标识
  • 78 DA…… 压缩的数据,LZ77派生压缩方法
  • 绿色部分是 CRC校验
     

    IEND
     

    图像结束数据IEND(image trailer chunk):它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。

    如果我们仔细观察PNG文件,我们会发现,文件的结尾12个字符看起来总应该是这样的:

    00 00 00 00 49 45 4E 44 AE 42 60 82

    不难明白,由于数据块结构的定义,IEND数据块的长度总是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82。

    至此,我们已经能够从一个PNG文件中识别出各个数据块了。由于PNG中规定除关键数据块外,其它的辅助数据块都为可选部分,因此,有了这个标准后,我们可以通过删除所有的辅助数据块来减少PNG文件的大小。(当然,需要注意的是,PNG格式可以保存图像中的层、文字等信息,一旦删除了这些辅助数据块后,图像将失去原来的可编辑性。)

    比如说下面这个图形数据,里面除了我们上面所提到的四块数据以外,还有很多的辅助数据

    图片点击可在新窗口打开查看

    3.PNG格式的天兵天将

    我们选择网上的一张图片作为讲解PNG辅助格式的图片素材图片点击可在新窗口打开查看,这个素材是8*8的,看起来很小,放大以后效果如下图,不过查看数据格式的时候还是要用图片点击可在新窗口打开查看UltraEdit-32打开图片点击可在新窗口打开查看
    图片点击可在新窗口打开查看

    主要的数据块我们就不讲了,现在看看辅助数据

    00000021~0000002F:
     

    图片点击可在新窗口打开查看
     

    可选数据块sBIT,颜色采样率,RGB都是256(2^8=256)

    00000030~00000062:
     

    图片点击可在新窗口打开查看
     

    这里是调色板信息

    • 00 00 00 27 说明调色板数据长为39字节,既13个颜色数
    • 50 4C 54 45 PLTE标识 (开始那张图片上面没有PLTE数据块,这张图片有)
    • FF FF 00 颜色0
    • FF ED 00 颜色1
    • …… ……
    • 09 00 B2 最后一个颜色,12
    • 5F F5 BB DD CRC校验

    00000063~000000C5:
     

    图片点击可在新窗口打开查看
     

    这部分包含了pHYs、tExt两种类型的数据块共3块,由于并不太重要,因此也不再详细描述了。

    4.PNG格式测试

    图片点击可在新窗口打开查看
    For the 21st century

    PNG Image Format

    Portable Network Graphics - PNG

    图片点击可在新窗口打开查看

    PNG 的压缩算法应该说是相当优秀的.他并不像JPEG images, PNG 采用的是无损压缩, 这样我们看到的图像就不会存在像素损失,也不会模糊. In some cases, filtering can compress the image data even more. Each horizontal line in an image can have one of five filter types associated with it. Whether specifying a filter helps in a particular case depends on the image content. In most cases the default setting is best ( adaptive filtering ).

    作为 PNG Development Group(PNG发展组)的一员, Paul Schmidt, 生成了一个 test image 包含pixels of all 16.7 million possible colors. 他是841:1的压缩比. 是一个非常棒的 24 bit PNG 图像.
    View a screenshot and more examples.

    PNG color depth

    真彩 24 bit images are one of fifteen color options in PNG format. Images can be created using color palettes(调色板) or 8 bit grayscale(灰阶). Pixel data with 8 bit values can index into palettes containing(包含) up to 256 colors, and with fewer colors pixel values can be 1, 2 or 4 bits. For specialist requirements PNG also offers 48 bit true color and 16 bit grayscale.

    PNG transparency(透明)

    PNG 2位透明格式试图取代 GIF透明 图像.这一点也是相当令人激动的 -- 可变透明, 这就是我们常常提到的"alpha transparency", "alpha-channel transparency"(alpha 透明;alpha 通道), or 简单的称之为 "mask channel". 它允许你在全透明不透明之间有254个阶可以选择.

    最近公布的PNG's 可变透明, 包含 WebTV and Microsoft Internet Explorer for Macs. 但是Pre-IE7 versions of Internet Explorer 例外, 但是背景透明还是有的.  IE6 for Windows支持 PNG's 单色透明. The image below shows some examples:

    1. 24 bit PNG with alpha transparency.
    2. 8 bit PNG with binary transparency.
    3. First example in pre-IE7 versions of Internet Explorer for Windows.
    4. 8 bit GIF with binary transparency.
    图片点击可在新窗口打开查看

    PNG interlaced images(交错图像)

    Interlaced GIF images display their data in 4 passes, each one filling in more detail from top to bottom. The first pass begins after 1/8 of the image has downloaded. PNG uses a more sophisticated scheme which begins rendering the image after only 1/64 of the data has arrived. PNG's 7 pass scheme, devised by Adam Costello, fills in increasing amounts of detail both horizontally and vertically. Interlacing increases the file size. You may find that with PNG's better compression fewer images will need interlacing. For exceptionally large image files thumbnail preview images are another option.

    Extra features

    PNG format allows all kinds of extra information to be stored inside image files. The two most potentially helpful features for web images are gamma correction and embedded text.

    Gamma correction is the ability to correct for differences in how computer systems interpret color values. Macintosh-generated images tend to look too dark on PCs, and PC-generated images tend to look too light on Macs. PNG format allows the gamma value of the computer which created an image to be embedded into the image file. Browsers and image software which support the feature can extract the gamma value and make a correction if the host computer uses a different gamma setting. Warning: There are some applications which don't implement it correctly. Don't rely on gamma correction to match image colors to HTML/CSS colors.

    The text feature makes it possible to add any text annotations you like -- a description of the image, the date of creation, copyright information, etc. Very few image editors offer this option, but the TweakPNG utility allows you to add text after the image has been created. It can also set the background color of a PNG alpha image. The default background color is gray in pre-IE7 versions of Internet Explorer for Windows.

    PNG - the background story

    In the late 1980's CompuServe introduced a new image format which became popular with internet users - Graphic Interchange Format, or GIF. It used a long-established compression algorithm, LZW, without realizing that LZW was subject to a patent filed by the Sperry corporation, which was later taken over by Unisys.

    In late 1994 Unisys dropped a bombshell by announcing that the company would start demanding royalties from all developers of GIF-supporting software. The announcement caused consternation among the internet community and ideas were passed around for a non-proprietary replacement. An informal internet working group was established by Thomas Boutell to devise an image format which would be even better than GIF. In October 1996, the World Wide Web Consortium adopted the new specification, Portable Network Graphics, as a recommended image format.

    By late 1997 both Netscape 4 and Internet Explorer 4 had arrived with basic support for PNG images. Support for the more advanced features followed. Now, binary transparency and interlacing are supported by all modern browsers, but pre-IE7 versions of Internet Explorer for Windows don't directly support PNG's most advanced feature, alpha-transparency. However, remedies are available using PHP or JavaScript:
    Internet Explorer and PNG transparency.

    图片点击可在新窗口打开查看

    The LZW patent in the United States expired in June 2003, and up to a year later in other countries. More information about patent controversies can be found at:

    • Burn All GIFs

    A comprehensive source of information about Portable Network Graphics format is maintained by one of the original members of the PNG working group, Greg Roelofs:

    • The PNG Home Site

    He is also the author of "PNG: The Definitive Guide". An online version is available at the site. Greg kindly provided examples of minimum-size PNG files to compare with the output of image converters reviewed on this site:
    Review of PNG image tools for MS Windows.

    图片点击可在新窗口打开查看

    By late 2003 the number of internet users with browsers dating back to 1997 or earlier was negligible. They would see image placeholders instead of the images.

    Animation

    Portable Network Graphics format was originally devised at a time when there was no browser support for GIF animation, so animation was not included in the specification. Later, a separate animation format was devised with a whole host of advanced features - Multiple-image Network Graphics, or MNG. As it turned out, however, the arrival of other animation technologies such as Macromedia Flash took attention away from MNG format. More information about MNG can be found at the PNG Home Site.

    The lack of sophistication in GIF animation can be annoying to users. Research into user reactions has shown that some users cover animations with one hand as they read the text on a page. Here's a tip: GIF animations can be frozen by pressing the ESC key in Internet Explorer or Firefox.

    Choosing an image format

    • For photos and scans JPEG will almost always be more compact than 24 bit PNG format.
    • For true color images containing text and sharp color transitions 24 bit PNG could turn out smaller, and will certainly provide the best quality. Ideal for maps, charts and diagrams with more than 256 colors.
    • If the quality is acceptable, converting true color images to a 8 bit palette can often produce a smaller file. Dither the colors if necessary.
    • For converting GIF images, use 8 bit PNG. With the right image tools only tiny GIF files remain smaller than a PNG equivalent (small icons, for example).
    • Use single-color transparency if alpha-channel transparency is not really necessary. It works in Internet Explorer and the file size will most likely be smaller.
    • There's a small overhead for PNG's versatility: the minimum file size is 67 bytes for an opaque single pixel.

    The official PNG specification

    A complete list of features can be found in the official PNG specification at the World Wide Web Consortium's website:

    • http://www.w3.org/TR/PNG/

  •  

    第三章  PNG格式的读写
        1.PNG格式C语言读写

          PNG格式读写离不开PNG库libpng 是一套免费的、公开源代码的程序库,支持对 PNG 图形文件的创建、读写等操作。可以到www.libpng.org 上下载源代码。libpng 使用 zlib 程序库作为压缩引擎,zlib 也是著名的 gzip (GNU zip) 所采用的压缩引擎。zlib 是通用的压缩库,提供了一套 in-memory 压缩和解压函数,并能检测解压出来的数据的完整性(integrity)。zlib 也支持读写 gzip (.gz) 格式的文件这些都是免费和公开的。在下载了pbglib,并且要下载zlib,如何才能加到代码中呢?以VC6.为例来说明。其他CBuild等编译器相信也一样的。

           比如我们从网上下载了一个lpng1210.zip和zlib-.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了!如果还有不明白的地方,在这里留言或者在百度上搜一下。

    下面将将到重点内容了。如何用pnglib实现对文件的读写?A simple libpng example program(http://zarb.org/~gc/html/libpng.html)

    以下就是写好的PNG读取和写入函数

    /*
     * Guillaume Cottenceau (gc at mandrakesoft.com)
     *
     * Copyright 2002 MandrakeSoft
     *
     * This software may be freely redistributed under the terms of the GNU
     * public license.
     *
     */

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdarg.h>

    #define PNG_DEBUG 3
    #include <png.h>

    void abort_(const char * s, ...)
    {
     va_list args;
     va_start(args, s);
     vfprintf(stderr, s, args);
     fprintf(stderr, "/n");
     va_end(args);
     abort();
    }

    int x, y;

    int width, height;
    png_byte color_type;
    png_byte bit_depth;

    png_structp png_ptr;
    png_infop info_ptr;
    int number_of_passes;
    png_bytep * row_pointers;

    void read_png_file(char* file_name)
    {
     char header[8]; // 8 is the maximum size that can be checked

     /* open file and test for it being a png */
     FILE *fp = fopen(file_name, "rb");
     if (!fp)
      abort_("[read_png_file] File %s could not be opened for reading", file_name);
     fread(header, 1, 8, fp);
     if (png_sig_cmp(header, 0, 8))
      abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);


     /* initialize stuff */
     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
     
     if (!png_ptr)
      abort_("[read_png_file] png_create_read_struct failed");

     info_ptr = png_create_info_struct(png_ptr);
     if (!info_ptr)
      abort_("[read_png_file] png_create_info_struct failed");

     if (setjmp(png_jmpbuf(png_ptr)))
      abort_("[read_png_file] Error during init_io");

     png_init_io(png_ptr, fp);
     png_set_sig_bytes(png_ptr, 8);

     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;

     number_of_passes = png_set_interlace_handling(png_ptr);
     png_read_update_info(png_ptr, info_ptr);


     /* read file */
     if (setjmp(png_jmpbuf(png_ptr)))
      abort_("[read_png_file] Error during read_image");

     row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
     for (y=0; y<height; y++)
      row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);

     png_read_image(png_ptr, row_pointers);

            fclose(fp);
    }

    写入PNG格式

    void write_png_file(char* file_name)
    {
     /* create file */
     FILE *fp = fopen(file_name, "wb");
     if (!fp)
      abort_("[write_png_file] File %s could not be opened for writing", file_name);


     /* initialize stuff */
     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
     
     if (!png_ptr)
      abort_("[write_png_file] png_create_write_struct failed");

     info_ptr = png_create_info_struct(png_ptr);
     if (!info_ptr)
      abort_("[write_png_file] png_create_info_struct failed");

     if (setjmp(png_jmpbuf(png_ptr)))
      abort_("[write_png_file] Error during init_io");

     png_init_io(png_ptr, fp);


     /* write header */
     if (setjmp(png_jmpbuf(png_ptr)))
      abort_("[write_png_file] Error during writing header");

     png_set_IHDR(png_ptr, info_ptr, width, height,
           bit_depth, color_type, PNG_INTERLACE_NONE,
           PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

     png_write_info(png_ptr, info_ptr);


     /* write bytes */
     if (setjmp(png_jmpbuf(png_ptr)))
      abort_("[write_png_file] Error during writing bytes");

     png_write_image(png_ptr, row_pointers);


     /* end write */
     if (setjmp(png_jmpbuf(png_ptr)))
      abort_("[write_png_file] Error during end of write");

     png_write_end(png_ptr, NULL);

            /* cleanup heap allocation */
     for (y=0; y<height; y++)
      free(row_pointers[y]);
     free(row_pointers);

            fclose(fp);
    }


    void process_file(void)
    {
     if (info_ptr->color_type != PNG_COLOR_TYPE_RGBA)
      abort_("[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (is %d)", info_ptr->color_type);

     for (y=0; y<height; y++) {
      png_byte* row = row_pointers[y];
      for (x=0; x<width; x++) {
       png_byte* ptr = &(row[x*4]);
       printf("Pixel at position [ %d - %d ] has the following RGBA values: %d - %d - %d - %d/n",
              x, y, ptr[0], ptr[1], ptr[2], ptr[3]);

       /* set red value to 0 and green value to the blue one */
       ptr[0] = 0;
       ptr[1] = ptr[2];
      }
     }

    }


    int main(int argc, char **argv)
    {
     if (argc != 3)
      abort_("Usage: program_name <file_in> <file_out>");

     read_png_file(argv[1]);
     process_file();
     write_png_file(argv[2]);

            return 0;
    }

     

              在读取PNG的时候要注意读取顺序和调色板等设置,这在你读取数据以后对它进行操作(修改,保存)都很重要,否则会出现花屏或者写入的文件无法正常读取的问题。

    2.MFC中Cimage类读,写,显示PNG

          PNG格式的图片在MFC中的读写要比C语言容易很多,既有现成的插件和库,也有很多的代码工程可以使用,但是如果自己需要写一个自己的处理FMC还是有一定难度的,可以说,如果要自己控制PNG的读写,上面C语言的读写PNG方法不可缺少。有的人可能就问了,为什么别人都写好的东西,我们还要去写自己的PNG读写程序呢?反复造车轮的设计可不是现在的设计思想。既然已经说到这里饿,那么我们就来看看现在主要的PNG处理库吧。

    3.MFC中CxImage读,写,显示PNG

    一。CxImage类库简介

    这只是翻译了CxImage开源项目主页上的部分简介及简单使用。

    CxImage类库是一个优秀的图像操作类库。它可以快捷地存取、显示、转换各种图像。有的读者可能说,有那么多优秀的图形库,如OpenIL,FreeImage,PaintLib等等,它们可谓是功能强大,齐全,没必要用其它的类库。但我要说,这些类库基本上没有免费的,使用这些类库,你要被这样那样的许可协议所束缚。在这点上,CxImage类库是完全免费的。另外,在使用上述类库时,你会遇到重重麻烦。因为它们大部分是平台无关的,且用C语言写成,有的还夹杂着基本的C++ wrapper和成堆德编译选项的声明需要你去处理。而CxImage类库在这方面做得很好。还有让我最看好的,就是作者完全公开了源代码。相对于那些封装好的图形库和GDI+来说,这一点使我们可以进一步学习各种编解码技术,而不再浮于各种技术的表面。

    CxImage是一个可以用于MFC的C++类,可以打开,保存,显示,转换各种格式的图像文件,比如BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K 等格式的文件。可以实现BMP<->JPG,PNG <>TIFF格式等等的转换。

    既可以实现图像文件的类型转换,也可以实现在内存图像数据的类型转换,并且使用很方便。

    它的作者是: Davide Pizzolato ,主页: http://www.xdp.it/

    首先,到http://www.codeproject.com/bitmap/CXImage.asp 下载它的源文件和Demo例子.

    注: 在Codeproject下载这个类,你得先注册一下,因为这个类可是含金量比较高的,下载量比较大的,当然你也会很高兴成为CodeProject的一名成员的,她不收你的费.授权:

    License

    The class CxImage is free; as for the TIFF, JPEG, PNG and ZLIB libraries : "If you use this source code in a product, acknowledgment is not required but would be appreciated."

    CxImage is open source and licensed under the zlib license . In a nutshell, this means that you can use the code however you wish, as long as you don't claim it as your own.

    由于很多人上codeproject的时候,老是上不去,所以,你也可以去这个类库的作者--Davide Pizzolato的主页去下载

    他的主页还有另外的源代码,有兴趣的也可以看看.

     

    二。编译CxImage类库

    作者已经提供了整个类库配置的工程文件CxImgLib.dsw (VC++6.0),只要打开它进行编译即可。需要大家注意的是:整个CxImage类库非常大。如果你只需要能处理其中的几种格式,编译该类库时,你可以在配置的头文件ximcfg.h 中找到一些编译开关选项来关闭一些图像库。JPG、PNG、TIFF中的每一个库,都会向最终程序增加约100KB的内容。而CxImage类库压缩后只有约60KB。所以,你需要谨慎挑选一些你真正需要的类库。

     

    图片点击可在新窗口打开查看 //类库配置文件:ximacfg.h
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_JPG 1
    图片点击可在新窗口打开查看
    //如果要实现bmp->jpg 则必须打开
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_BMP 1
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_GIF 1
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_JPG 1
    图片点击可在新窗口打开查看
    //以上为必须打开,下面的随便............
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_PNG 0//不使用它
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_MNG 0
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_ICO 1
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_TIF 0//
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_TGA 0//
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_PCX 0//
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_WBMP 0//
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_WMF 0//
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_J2K 0  // Beta, use JP2
    图片点击可在新窗口打开查看
    #define CXIMAGE_SUPPORT_JBG 0
    //.............


    其他的可以不打开

    编译该类库有好几个选择的工程,如下图所示:

    图片点击可在新窗口打开查看

     各工程的作用对应如下:

  • CxImage : cximage.lib - static library
  • CxImageCrtDll : cximagecrt.dll - DLL not using mfc
  • CxImageMfcDll : cximage.dll - DLL using mfc
  • Demo : demo.exe - program linked with cximage.lib and the C libraries
  • DemoDll : demodll.exe - program linked with cximagecrt.dll
  • j2k,jasper,jbig,jpeg,png,tiff,zlib : static C libraries

    编译这些工程需要耗费几分钟的时间(中间文件可达60MB)。

    三。在程序中应用CxImage类库进行图像类型转换

    在你的VC工程中使用这个类库,要对工程进行如下设置(Project Settings):

    |- C/C++
    |   |- Code Generation
    |   |   |- Use run-time library : Multithreaded DLL (must be the same for
    |   |   |  all the linked libraries)  //应该只要是多线程DLL即可,DEBUG的也行
    |   |   |- Struct member alignment : must be the same for all the linked libraries
    |   |- Precompiled headers : not using precompiled headers
    |   |- Preprocessor
    |       |- Additional Include Directories:  ../cximage(该处填CxImage里的.h和.cpp文件拷贝并导入工程后所在的文件夹,填写后在工程中include时编译器会查找该文件夹,故include的文件无需路径)
    |- Link
        |- General
            |- Object/library modules:  png.lib 
                                                           jpeg.lib 
                                                           zlib.lib 
                                                           tiff.lib 
                                                           jasper.lib 
                                                          cximage.lib  (把需要的lib文件从CxImage中拷贝到工程中的lib文件所在的目录)

    并且从CxImage中将xfile.h、ximacfg.h、ximadef.h、ximage.cpp、ximage.h、xiofile.h、xmemfile.cpp、xmemfile.h拷贝到工程文件夹下并将CxImage.h文件加入工程中即可。也可以设置vc6的"tools"中的"include"路径.

    下面介绍应用它进行图像类型转换的方式:

    1.从一种图像文件类型转换为另一种文件类型(convert from a format to another)

    图片点击可在新窗口打开查看 CxImage  image;   // 定义一个CxImage对象
    图片点击可在新窗口打开查看
    图片点击可在新窗口打开查看
    // 从bmp文件转换为jpg文件(bmp -> jpg)
    图片点击可在新窗口打开查看
    image.Load("image.bmp", CXIMAGE_FORMAT_BMP);   //先装载bmp文件,需要指定文件类型
    图片点击可在新窗口打开查看    
    // 判断加载的bmp文件是否存在。
    图片点击可在新窗口打开查看图片点击可在新窗口打开查看
    if (image.IsValid())......{
    图片点击可在新窗口打开查看       
    // Returns true if the image has 256 colors  and a linear grey scale palette.
    图片点击可在新窗口打开查看
        if(!image.IsGrayScale()) image.IncreaseBpp(24);   // param nbit: 4, 8, 24
    图片点击可在新窗口打开查看
        image.SetJpegQuality(99);                // 设置图像的压缩质量参数(从0到100,数值越大,质量越高)
    图片点击可在新窗口打开查看
        image.Save("image.jpg",CXIMAGE_FORMAT_JPG);          // 把压缩后的图像以jpg文件类型保存起来。
    图片点击可在新窗口打开查看
    }

    图片点击可在新窗口打开查看
    图片点击可在新窗口打开查看


    图片点击可在新窗口打开查看// 从png文件转换为tif文件(png -> tif)
    图片点击可在新窗口打开查看
    image.Load("image.png", CXIMAGE_FORMAT_PNG);
    图片点击可在新窗口打开查看图片点击可在新窗口打开查看
    if (image.IsValid())...{
    图片点击可在新窗口打开查看    image.Save(
    "image.tif",CXIMAGE_FORMAT_TIF);
    图片点击可在新窗口打开查看}


    2。加载程序资源图像(load an image resource)

    即从程序的资源图像中构建CxImage对象,有如下几种方式:

     

    图片点击可在新窗口打开查看// Load the resource IDR_PNG1 from the PNG resource type
    图片点击可在新窗口打开查看
    CxImage* newImage = new CxImage();
    图片点击可在新窗口打开查看newImage
    ->LoadResource(FindResource(NULL,MAKEINTRESOURCE(IDR_PNG1),
    图片点击可在新窗口打开查看                       
    "PNG"),CXIMAGE_FORMAT_PNG);

     

    或者

     

    图片点击可在新窗口打开查看//Load the resource IDR_JPG1 from DLL
    图片点击可在新窗口打开查看
    CxImage* newImage = new CxImage();
    图片点击可在新窗口打开查看HINSTANCE hdll
    =LoadLibrary("imagelib.dll");
    图片点击可在新窗口打开查看图片点击可在新窗口打开查看
    if (hdll)...{
    图片点击可在新窗口打开查看    HRSRC hres
    =FindResource(hdll,MAKEINTRESOURCE(IDR_JPG1),"JPG");
    图片点击可在新窗口打开查看    newImage
    ->LoadResource(hres,CXIMAGE_FORMAT_JPG,hdll);
    图片点击可在新窗口打开查看    FreeLibrary(hdll);
    图片点击可在新窗口打开查看}

     

    或者

     

    图片点击可在新窗口打开查看//Load a bitmap resource;
    图片点击可在新窗口打开查看
    HBITMAP bitmap = ::LoadBitmap(AfxGetInstanceHandle(),
    图片点击可在新窗口打开查看                              MAKEINTRESOURCE(IDB_BITMAP1)));
    图片点击可在新窗口打开查看CxImage 
    *newImage = new CxImage();
    图片点击可在新窗口打开查看newImage
    ->CreateFromHBITMAP(bitmap);

     

    3。在内存缓冲中的图像类型转换

    (1)把内存缓冲中的数据解码成一个Image对象(decode an image from memory)

    有如下几种方式:
    ------

    图片点击可在新窗口打开查看CxImage image((BYTE*)buffer,size,image_type);//把内存缓冲buffer中的数据构造成Image对象
    图片点击可在新窗口打开查看
    图片点击可在新窗口打开查看
    //或:
    图片点击可在新窗口打开查看

    图片点击可在新窗口打开查看CxMemFile memfile((BYTE
    *)buffer,size); // 显式使用CxMemFile对象
    图片点击可在新窗口打开查看
    CxImage image(&memfile,image_type);
    图片点击可在新窗口打开查看
    图片点击可在新窗口打开查看
    //或:
    图片点击可在新窗口打开查看

    图片点击可在新窗口打开查看CxMemFile memfile((BYTE
    *)buffer,size);
    图片点击可在新窗口打开查看CxImage
    * image = new CxImage();
    图片点击可在新窗口打开查看image
    ->Decode(&memfile,type);
    图片点击可在新窗口打开查看

     

    ============

    (2)把Image编码存放到内存缓冲中(encode an image in memory)

    --------

    图片点击可在新窗口打开查看long size=0;//得到图像大小
    图片点击可在新窗口打开查看
    BYTE* buffer=0;//存储图像数据的缓冲
    图片点击可在新窗口打开查看
    image.Encode(buffer,size,image_type);//把image对象中的图像以type类型数据copy到buffer
    图片点击可在新窗口打开查看
    ...
    图片点击可在新窗口打开查看free(buffer);
    图片点击可在新窗口打开查看
    图片点击可在新窗口打开查看或:
    图片点击可在新窗口打开查看
    图片点击可在新窗口打开查看CxMemFile memfile;            
    // 显式使用CxMemFile对象
    图片点击可在新窗口打开查看
    memfile.Open();
    图片点击可在新窗口打开查看image.Encode(
    &memfile,image_type);
    图片点击可在新窗口打开查看BYTE
    * buffer = memfile.GetBuffer();
    图片点击可在新窗口打开查看
    long size = memfile.Size();
    图片点击可在新窗口打开查看...
    图片点击可在新窗口打开查看free(buffer);
    图片点击可在新窗口打开查看
  • http://blog.csdn.net/sunshine1314/archive/2008/04/16/2295593.aspx

    原创粉丝点击