关于png的一个谜题,png 转ico
这一篇我们只研究一个问题。
如果要显示感知上(视觉上)的“半灰色”,在一张SRGB的PNG图片里存储的值应该是多少呢?是0.5的alpha值吗?
假如你是一个对PNG和图像感知以及alpha的绝对专家,这就是你需要的所有信息。对于这个问题,确保你能达成以下共识:
1、在屏幕上感知为半灰色的值是(187,187,187),而不是(128,128,128)。下面我们会使用JohnHabel文章中的图片
翻译:袁笠凯(°Sinmere) 审校:王成林(麦克斯韦的麦斯威尔)
这一篇我们只研究一个问题。
如果要显示感知上(视觉上)的“半灰色”,在一张SRGB的PNG图片里存储的值应该是多少呢?是0.5的alpha值吗?
假如你是一个对PNG和图像感知以及alpha的绝对专家,这就是你需要的所有信息。对于这个问题,确保你能达成以下共识:
1、在屏幕上感知为半灰色的值是(187,187,187),而不是(128,128,128)。下面我们会使用JohnHabel文章中的图片来证实这一点。
2、PNG的颜色是存储在sRGB空间的。鲜少会有gamma = 1.0的PNG格式会被使用。
3、alpha值是线性的。PNG规范指出,“gamma值对alpha采样值没有影响,alpha采样在不透明时一直会是线性的。”
4、PNG的alpha值总是不关联的,它们不会与其颜色值进行预乘。如果以黑色为底色显示sRGB的PNG颜色时,你必须用未关联Alpha的颜色值来相乘。
那么,你要在PNG图片中存储什么信息才能使用alpha0.5的值来显示半灰色呢?这里会有一些提示,而答案在下面的图片下面。
水平纯黑线和纯白线相结合构成半灰色,即187代表的颜色,这是在sRGB空间的效果:
John Hable的图片
提示#1:alpha值为1.0(完全不透明)的半灰色存储在PNG中为(187,187,187,255)。
提示#2:如果PNG可以存储一个预乘颜色,答案是(187,187,187,128)。
提示#3:如果把一个预乘颜色转换成一个独立的颜色,只需用它的alpha值除以这个颜色
这就是,我希望我知道你和答案只有一步之遥。
答案是(255,255,255,128),由麦克·查克(网名friedlinguini)在我的文章评论区提出 - 见下方的评论。我的答案是明显不对的,当然我会解释为什么是这个答案。
PNG说明书提到,“这种计算应使用亮度样本(而不是gamma编码的样本)”。因此,要显示的sRGB编码的PNG,必须做到以下几点:
1.转换sRGB色彩为线性空间。对于(255,255,255,128),这是(1.0,1.0,1.0)。
2.现在乘以alpha,得到一个线性预乘值。乘以(128/255) - > 0.5得到了(0.5,0.5,0.5)。
3.转换此值回sRGB空间然后显示。得到(187,187,187)要显示的颜色。
我觉得使用sRGB值和alpha值的PNG是通过简单地将sRGB值和其中存储的alpha值相乘显示的。错误!至少,在规范中是这样。我的思路为何如此疯狂?因为我测试的每一个查看器和浏览器都告诉我PNG就是这样显示的。
所以,我很高兴地发现在PNG的的世界并没有崩溃;它只是没有人正确地实现它。如果你确实知道一些软件,程序会显示此图像正确(您的浏览器没有),让我知道-这将是我的事情应该如何工作的例子。
更新:事实上Jim Blinn早在18年前就认识到了这个问题。他的文章“A Ghost in a Snowstorm”(在书中收集的Notation, Notation,Notation,这篇文章大部分可以在这里 找到)讲到正确的方式(线性化),以及各种对alpha和sRGB进行编码引起的错误。感谢肖恩·巴雷特指出来。
我的结论依旧不变:如果你想尝试有趣的谜题并且你靠近大城市,看看The Puzzled Pint,一个很棒且免费的社会性解谜活动,每月都会举行。
回顾记录,这是我原来错误的答案:
答案是(373,373,373,128)。要正确显示此RGBA,你乘以alpha(除以255,因为128值代表0.5),以获得(187,187,187)。
简单点说这是sRGB的PNG格式存在的重大缺陷:你不能在PNG 8位存储中存储373。16位也没用:PNG格式存储其值的范围为[0.0,1.0]的分数。
没有线性化或过滤或运算顺序或任何其他事涉及,只是一个简单的问题。不幸的是,PNG失败。
错误答案包括:
·(187,187,187,128) - 如果PNG有一个预乘模式,这个答案就没问题。然并没有这种模式,所以颜色值将与0.5相乘得到的(94,94,94)来显示。也就是说,如果你有一个封闭的系统而且没有其他人会用你的PNG,这是个不错的储存数据的方式。
·(187,187,187,255) - 这会显示正确,但不保留alpha值。
·(255,255,255,128) - 这给了你(128,128,128)的颜色的显示值,Hable的图像显示不是一个视觉认知的半灰色。如果你使用PNG伽马块,并设置伽玛值1.0,这是可行的。几乎没有人使会用这种伽玛设置(它会导致带状化,除非您使用16位)而且它基本不被大多数工具所支持。
·(255,255,255,187) - 你用sRPG校正alpha违背了PNG规范。实际上这个将会显示正确的(187,187,187)。如果你使用alpha将其它图片合成为这张图片,这个错误的alpha不可行。
·同样是(255,255,255,187) - 你决定“记住”alpha值是经过sRGB校正的,并在其他地方使用它之前将它校正回来。如果你想打破规范,最好存储一个预乘的颜色,就像第一个错误答案。这种修正是令人困惑的。
·同样是(255,255,255,128)您存储正确的alpha值,但你需要在应用alpha值之前你首先要把存储的颜色从sRGB转换到线性空间,然后再将颜色转换回sRGB进行显示。这个可行,但它违背了光照和alpha理论,它是纠结的,耗性能的,超级混乱的,而不是如何实现PNG的显示,也不是如何去读这篇规范,按照我的理解。最好只存储一个预乘颜色。
我希望我的结论是错误的,但我看不到任何一个在PNG规范中除解决方案以外的新板块。我更希望看到的是添加存储预乘值的板块。
在此期间,如果你想解决难题,而且你是在一个大城市附近,看The Puzzled Pint,,一个每个月都有免费益智社会事件的网站。
附录
扎普安德森和我在Facebook上对这个谜题讨论很多,在这非常感谢他。他更倾向于(255,255,255,128)的答案,“在后面”应用alpha。为了说明白,下面是PNG通常的分析方法(我认为这遵循该规范,但我很乐意被证明是错误,因为即使没有浏览器或浏览器据我所知能正确地实现它,PNG依旧能正常工作):
想要以SRGB显示PNG的RGBA:你用RGB颜色乘以alpha值(表示小数)。
以SRGB显示PNG的RGBA的那个“在后面应用alpha”的方法:您sRGB数字转换存储称一个线性值,然后应用alpha,然后你转换这种线性值到sRGB空间显示。
我很喜欢这一点,就像它令人费解,使PNG工作(我真的不希望看到PNG失败)。这种解决方案的问题是,我不认为任何人都不会这样做; 浏览器当然不会这样做。
扎普指出另外一件有趣的事情,这个有趣的网页。它指向这个更多相关页面。我的观点是,我不应该讨论187灰色作为感知平均灰度; 128灰色确实看起来视觉上更容易接受(这就是为什么通常伽玛校正是有道理的,即人类的感知与显示器之间为非线性关系-我忘了)。这实际上没有改变以上任何内容,“半覆盖像素”的例子还是应该得到187。这一点可以通过平均为187的全黑和全白直线交替出现来确定。
关于JPG BMP GIF PNG图片失真的问题
BMP是原始的无压缩的位图格式,是没有质量损失的,当然与此相对应它的文件体积也越大,不过也正由于它的格式简单,出现的也很早,所以基本上所有图像软件都可以支持这种格式。至于png是无损压缩格式的一种,在需要无损的保持原来的图像数据,但是又不想用bmp那么大的空间来存储的时候,png是一个不错的选择,另外png后来发展出来一种无损的动画格式apng,不过它的标准在各个浏览器下支持的也不一样。jpg是用途最广的有损压缩格式,也就是说使用这种格式,图像质量是有损失的,好处就是可以人为的控制jpg的压缩率,从而可以在图像质量与图像大小之间取得一个均衡。
gif是用途比较多的动画格式,不过它的单帧的色彩被限制在256色,这也就是为什么你将其它图片或者视频转成gif,颜色失真通常就比较大的原因。
png文件是什么格式?
png是一种采用无损压缩算法的位图格式。
png其设计目的是试图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。PNG使用从LZ77派生的无损数据压缩算法,一般应用于JAVA程序、网页或S60程序中,原因是它压缩比高,生成文件体积小。
PNG同时还支持真彩和灰度级图像的Alpha通道透明度。最高支持24位真彩色图像以及8位灰度图像。支持Alpha通道的透明/半透明特性。支持图像亮度的Gamma校准信息。支持存储附加文本信息,以保留图像名称、作者、版权、创作时间、注释等信息。
PNG图片与其他格式图片对比:
一、PNG与 GIF
1、一般情况下将静态GIF图像无损转换为PNG后可以压缩率会略为提高(前提是同样采用8位索引模式)。
2、PNG可提供更大颜色深度的支持,包括24位(8位3通道)和48位(16位3通道)真彩色。加入α通道后可进一步支持每像素64位的表示。
3、超过8位色深的PNG图像转换为GIF时,图像质量会由于分色(颜色数减少)而下降。
4、GIF原生支持动态图像,PNG只能通过非标准实现,在PNG的基础上另有发展出支持动画的APNG和MNG格式,但普及度不高。PNG在IE6等旧浏览器上的支持较差。
二、PNG 与JPEG
1、JPEG可以对照片(或类似)图像生成更小的文件,这是由于JPEG采用了一种针对照片图像的特定有损编码方法,这种编码适用于低对比,图像颜色过渡平滑,噪声多,且结构不规则的情况下。
如果在这种情况下用PNG代替JPEG,文件尺寸增大很多,而图像质量的提高有限。相应的,如果保存文本,线条或类似的边缘清晰,有大块相同颜色区域的图像,PNG格式的压缩效果就要比JPEG好很多,并且不会出现JPEG那样的高对比度区域的图像有损。如果图像既有清晰边缘,又有照片图像的特点,就在在这两种格式之间权衡一下了。JPEG不支持透明度。
2、由于JPEG是有损压缩,会产生迭代有损,在重复压缩和解码的过程中会不断丢失信息使图像质量下降。由于PNG是无损的,保存将要被编辑的图像来说更加合适。
虽然PNG压缩照片图像也有效,但有专门针对照片图像设计的无损压缩格式,比如无损JPEG2000,Adobe DNG等。总的来说这些格式都不能做到适用所有图像。对于将要发布的图像可以保存成JPEG,用JPEG编码一次不会造成明显的图像有损。
三、PNG vs JPEG-LS
JPEG-LS是一个“几乎”无损压缩格式,相对于上面提到的有损JPEG压缩,它的知名度不高。它可以直接和PNG相比较,使用一组标准的测试图像。在Waterloo Repertoire ColorSet(一组标准测试图像)下,JPEG-LS通常表现要比PNG好10%-15%,但其中有一些图像PNG表现明显更好一些,大约50%-75%。所以,如果这两种格式都支持而且对图像文件大小很敏感的话,可以用这两种格式都试试,和图像数据本身有比较大关系。
四、PNG与TIFF
TIFF是一个相当多方案结合的格式。它被广泛用作专业图像编辑软件之间图像交换的中间格式,因此它不断支持更多应用程序所需的功能,而对应用程序不关心的图像操作部分支持不多。这也意味着许多应用程序只能识别TIFF的一个子集,而产生更多的潜在混淆之处。
TIFF使用的最通用的无损压缩算法是LZW。这种算法--GIF中也在使用,直到2003年一直在专利保护之中。有一种TIFF变种使用与PNG相同的压缩算法,但是没有被许多专利程序所支持。TIFF也提供了一种特殊的无损压缩算法,类似CCITTGroup IV,可以对二值图像(比如传真或黑白文本)比PNG有更好的压缩效果。 PNG只支持非自左乘α,而TIFF也支持联合(自左乘)α。
PNG规范中不包含嵌入式EXIF(可交换图像文件格式)图像数据的标准,比如数码像机拍得的图像。而TIFF,JPEG 2000, DNG都支持EXIF。
文章评论