2010-10-12 75 views
3

我想加载(并解码)PNG图像并将它们转换为Java中的一维数组。我明显可以用ImageIO.read()来做这件事,然后将这些像素复制到数组中,但是这消耗了两倍的内存(栅格+最终数组),它涉及的处理时间比我想要的要多。在java中将PNG图像快速加载到数组中

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

+0

数组有什么类型?字节[]?在这种情况下,我看不到你应该如何“复制像素”到阵列中。如果它是一个字节数组,为什么不将PNG文件内容加载到数组中? – aioobe 2010-10-12 09:50:38

+2

@aioobe:据推测,他想要在数组中存储解码的图像数据,而不是PNG文件中的实际字节。 – uckelman 2010-10-12 10:34:48

+0

是的,我想要解码的图像数据。 – 2010-10-12 10:51:26

回答

8

如果你想要做的是得到的像素数据作为一个数组,那么你可以使用ImageIO.read()获得BufferedImage,然后使用BufferedImage.getRaster().getDataBuffer()得到DataBuffer。从那里,你需要检查你有什么类型的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()将原始图像数据一次写入磁盘一行(但要压缩,使用GZIPOutputStream),让原始图像被垃圾收集,创建所需类型的新BufferedImage,最后从磁盘读取行,使用BufferedImage.setRGB()将它们写入新映像。 (我前几天写了一些东西来做这件事,因此细节在我的脑海中是相当新鲜的,LGPL的源代码是here。)

+0

+1我喜欢详细的案例和警告...... – eee 2010-10-12 11:06:30

3

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

关于这一点,取决于任何建议。

通常可以解码PNG到一个内存访问的位图(ImageIO.read()返回BufferedImage,而这恰恰是),只是直接...访问其像素,(使用BufferedImage.getRaster().getDataBuffer())一维数组。

0
+0

只有当他想要来自PNG文件的原始字节而不是*解码的*图像数据时,这才有意义。 – uckelman 2010-10-12 10:49:54

+0

哪个*是*我想要的(我修改了这个问题)。 – 2010-10-12 10:53:24