我想加载(和解码)PNG 图像并将它们转换为 Java 中的一维数组。我显然可以使用 ImageIO.read() 来执行此操作,然后将像素复制到数组中,但这会消耗两倍的内存(光栅 + 最终数组),并且它涉及的处理时间比我想要的要多。
我该怎么办?最坏的情况是我可以自己实现 PNG 规范,但这似乎是一项相当复杂的任务。理想情况下,我想要一个可以“插入”的 PNG 实现。不太理想但仍然很好的是一个易于理解的(与 com.sun 代码不同)PNG 阅读器,我可以(并且将被允许)修改。
我想加载(和解码)PNG 图像并将它们转换为 Java 中的一维数组。我显然可以使用 ImageIO.read() 来执行此操作,然后将像素复制到数组中,但这会消耗两倍的内存(光栅 + 最终数组),并且它涉及的处理时间比我想要的要多。
我该怎么办?最坏的情况是我可以自己实现 PNG 规范,但这似乎是一项相当复杂的任务。理想情况下,我想要一个可以“插入”的 PNG 实现。不太理想但仍然很好的是一个易于理解的(与 com.sun 代码不同)PNG 阅读器,我可以(并且将被允许)修改。
如果您要做的是将像素数据作为数组获取,那么您可以使用ImageIO.read()
获取 a BufferedImage
,然后使用BufferedImage.getRaster().getDataBuffer()
获取DataBuffer
. 从那里,您需要检查BufferedImage
您拥有的类型以确定如何投射DataBuffer
. 例如,如果你有一个TYPE_INT_RGB
图像,那么你应该转换为 aDataBufferInt
然后你可以调用DataBufferInt.getData()
来检索int[]
包含数据的那个。您以这种方式得到的不是副本——它是支持BufferedImage
.
然而,所有这一切都有一个很大的警告:ImageIO.read()
通常不会给你你想要的图像类型。例如,你会经常得到 TYPE_CUSTOM,除了复制到你真正想要的图像类型之外,你不能做任何有用的事情。
因此ImageIO.read()
,如果您足够幸运能够ImageIO.read()
以您想要的格式为您提供图像,您将只能通过不制作第二份副本来获取您的图像数据。如果您想检查可用的类型ImageIO
,您可以调用ImageIO.getImageReaders()
以获取Iterator
所有声称能够读取您的流的阅读器,然后您可以使用ImageReader.getImageTypes(0)
来获取Iterator
阅读器可以阅读的图像类型。您可能会找到一个阅读器,它会以这种方式为您提供所需的图像类型,但不要屏住呼吸。
除非您的图像很大,否则复制它们实际上非常快。但是,如果您的图像很大,您可能不得不求助于BufferedImage.getRGB()
将原始图像数据一次写入磁盘一行(但要压缩,使用 a GZIPOutputStream
),让原始图像被垃圾收集,创建一个新的BufferedImage
所需类型,最后从磁盘读回行,使用BufferedImage.setRGB()
. (几天前我写了一些东西来做这件事,因此细节在我脑海中相当新鲜。LGPL 的源代码在这里。)
为什么要一维数组?更大的目的是什么?
任何建议都取决于此。
您通常可以将 PNG 解码为内存可访问的位图(ImageIO.read()
返回 a BufferedImage
,正是这样),然后直接访问其像素......作为一维数组(使用BufferedImage.getRaster().getDataBuffer()
)。
阅读地使用Java()