Java中的BufferedImage类包含一个getType()
方法,该方法返回一个与BufferedImage常量类型变量相关的整数,该变量描述了有关图像编码方式的一些信息(您可以查看BufferedImage source确定哪个数字对应于什么常量类型变量)。例如,如果它返回与BufferedImage.TYPE_3BYTE_BGR
对应的整数,那么这意味着BufferedImage是一个8位RGB图像,没有alpha,蓝色,绿色和黄色各自用3位表示。
其中一些图像类型似乎与特定格式的某些属性相关联。例如,TYPE_BYTE_INDEXED
表示它是从“256色6/6/6颜色立方体调色板”创建的。这听起来很像GIF图像,它是由256种颜色创建的。
好奇,我在硬盘上扫描了数百张照片,并使用ImageIO.read(File file)
将每张照片转换为BufferedImage,然后在其上调用BufferedImage.getType()
。我确定只有少数BufferedImage类型是从某些图像类型生成的。结果如下:
JPG: TYPE_3BYTE_BGR,TYPE_BYTE_GRAY
PNG: TYPE_3BYTE_BGR,TYPE_BYTE_GRAY,TYPE_4BYTE_BGRA
GIF: TYPE_BYTE_INDEXED
虽然看起来JPG和PNG共享了一些类似的BufferedImage常量类型,但我的测试中只有一个PNG导致TYPE_4BYTE_BGRA
,而每个GIF都产生TYPE_BYTE_INDEXED
。
我对图像格式不太熟悉,而且我的样本量并不是那么大。所以我想我会问:假设图像格式正确,某些图像类型是否总是导致具有某些常量类型的BufferedImages?要提供具体示例,格式正确的GIF图像是否始终与TYPE_BYTE_INDEXED
对应?或者所有格式正确的图像是否可以与所有BufferedImage常量类型相对应?
答案 0 :(得分:7)
[Do]某些图像类型总是导致
BufferedImage
具有某些常量类型?
与in your other question一样; 不,BufferedImage
类型和文件格式之间没有直接关系。
或者所有格式正确的图像是否可以与所有
BufferedImage
常量类型对应?
基本上,是的。当然,如果转换为灰色,彩色图像会丢失信息, 如果每个样本转换为8位等,每个样本16位图像将失去精度
但是,不同的文件格式有不同的存储像素和颜色的方式,通常某种BufferedImage
类型更接近地表示文件格式中使用的“布局”。
让我们使用您的GIF示例:
GIF的存储“布局”(在应用LZW压缩之前)通常最接近TYPE_BYTE_INDEXED
的存储“布局”,因此这通常是用Java做的“最便宜”的转换。对于最多16种颜色的GIF,TYPE_BYTE_BINARY
也可以正常工作。如果没有透明色,则GIF始终可以解码为TYPE_4BYTE_ABGR
或TYPE_INT_ARGB
(甚至TYPE_3BYTE_BGR
或TYPE_INT_RGB
。
换句话说,图像的类型取决于解码器,在某些情况下(例如the ImageIO
API)用户。
总结一下,您发现的是,默认情况下,ImageIO的GIF插件(GIFImageReader
)会将超过16种颜色的GIF解码为TYPE_BYTE_INDEXED
。使用不同的解码器/框架可能会产生不同的结果。
一些可能启发好奇读者的历史:
未建模以对应图像格式的BufferedImage
的类型。它们被建模为对应于显示硬件。具有与显示硬件相同的像素布局的图像总是更快地显示。其他布局首先需要经过某种转换。现在,现代显示硬件非常快,这当然不是一个问题,但在“古代”时代,这很重要。
顺便提一下,许多“古老”图像格式是临时创建的,或者是在特定显示硬件上运行的特定应用程序。因此,显示硬件的像素布局通常以文件格式使用。同样,因为不需要转换,这是最快/最简单的实现。
所以,是的,有一种关系。这不是直接的“给定A => B”关系,而是“给定A 和 C => B”。