在Java中将PNG图像快速加载到数组中

时间:2010-10-12 09:31:24

标签: java performance png javax.imageio

我想加载(和解码)PNG图像并将它们转换为Java中的一维数组。我显然可以使用ImageIO.read()然后将像素复制到数组中,但这会消耗两倍的内存(栅格+最终数组),并且它会占用比我想要的更多的处理时间。

我应该怎么做?最坏的情况我可以自己实现PNG规范,但这似乎是一个相当复杂的任务。理想情况下,我想要一个可以“插入”的PNG实现。不太理想但仍然很好将是一个易于理解(不像com.sun代码)PNG阅读器,我可以(并将被允许)修改。

3 个答案:

答案 0 :(得分:8)

如果您要做的是将像素数据作为数组获取,那么您可以使用ImageIO.read()获取BufferedImage,然后使用BufferedImage.getRaster().getDataBuffer()获取DataBuffer 1}}。从那里,您需要检查您拥有的BufferedImage类型,以确定如何投射DataBuffer。例如。如果您有TYPE_INT_RGB图片,那么您应该转换为DataBufferInt,然后您可以调用DataBufferInt.getData()来检索包含数据的int[]。你通过这种方式获得的不是副本 - 它是支持BufferedImage的实际数组。

然而,所有这一切都有一个很大的警告:ImageIO.read()通常不会为您提供所需的图像类型。例如,你会经常得到TYPE_CUSTOM,除了复制到你真正想要的图像类型之外你不能做任何有用的事情。

所以,如果您有幸ImageIO.read()为您提供图像,那么您只能通过ImageIO.read()获取图像数据,而无需再制作第二份副本以您想要的格式。如果您想查看ImageIO中可用的类型,可以致电ImageIO.getImageReaders()以获取Iterator所有声称能够阅读您的信息流的读者,然后您可以使用ImageReader.getImageTypes(0)来获取读者可以阅读的Iterator图像类型。您可能找到一个能够以这种方式为您提供所需图像类型的阅读器,但请不要屏住呼吸。

除非您的图像很大,否则复制它们实际上非常快。但是,如果您的图像 很大,则可能不得不求助于使用BufferedImage.getRGB()一次一行地将原始图像数据写入磁盘(但要进行压缩,请使用{ {1}}),让原始图像被垃圾收集,创建所需类型的新GZIPOutputStream,最后从磁盘读回行,使用BufferedImage将它们写入新图像。 (几天前我写了一些东西来做这件事,因此我的想法中的细节相当新鲜.LGPL的来源是here。)

答案 1 :(得分:3)

你为什么想要一维数组?更大的目的是什么?

这取决于任何建议。

您通常可以将PNG解码为内存可访问的位图,(ImageIO.read()返回BufferedImage,这正是如此)并直接访问其像素...作为一维数组(使用BufferedImage.getRaster().getDataBuffer())。

答案 2 :(得分:0)