2010-10-12 93 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