我想加載(並解碼)PNG圖像並將它們轉換爲Java中的一維數組。我明顯可以用ImageIO.read()來做這件事,然後將這些像素複製到數組中,但是這消耗了兩倍的內存(柵格+最終數組),它涉及的處理時間比我想要的要多。在java中將PNG圖像快速加載到數組中
我應該怎麼辦?最壞的情況是我可以自己實現PNG規範,但這似乎是一個相當複雜的任務。理想情況下,我想要一個可以「插入」的PNG實現。不太理想,但仍然可以很容易理解(不像com.sun代碼)PNG閱讀器,我可以(並且將被允許)修改。
我想加載(並解碼)PNG圖像並將它們轉換爲Java中的一維數組。我明顯可以用ImageIO.read()來做這件事,然後將這些像素複製到數組中,但是這消耗了兩倍的內存(柵格+最終數組),它涉及的處理時間比我想要的要多。在java中將PNG圖像快速加載到數組中
我應該怎麼辦?最壞的情況是我可以自己實現PNG規範,但這似乎是一個相當複雜的任務。理想情況下,我想要一個可以「插入」的PNG實現。不太理想,但仍然可以很容易理解(不像com.sun代碼)PNG閱讀器,我可以(並且將被允許)修改。
如果你想要做的是得到的像素數據作爲一個數組,那麼你可以使用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。)
+1我喜歡詳細的案例和警告...... – eee 2010-10-12 11:06:30
爲什麼你想要一個一維數組?什麼是更大的目的?
關於這一點,取決於任何建議。
通常可以解碼PNG到一個內存訪問的位圖(ImageIO.read()
返回BufferedImage
,而這恰恰是),只是直接...訪問其像素,(使用BufferedImage.getRaster().getDataBuffer()
)一維數組。
只有當他想要來自PNG文件的原始字節而不是*解碼的*圖像數據時,這纔有意義。 – uckelman 2010-10-12 10:49:54
哪個*是*我想要的(我修改了這個問題)。 – 2010-10-12 10:53:24
數組有什麼類型?字節[]?在這種情況下,我看不到你應該如何「複製像素」到陣列中。如果它是一個字節數組,爲什麼不將PNG文件內容加載到數組中? – aioobe 2010-10-12 09:50:38
@aioobe:據推測,他想要在數組中存儲解碼的圖像數據,而不是PNG文件中的實際字節。 – uckelman 2010-10-12 10:34:48
是的,我想要解碼的圖像數據。 – 2010-10-12 10:51:26