2008-09-24 83 views
24

我使用以下代碼當前轉動的像素值(最初是用java.awt.image.PixelGrabber中對象創建)的陣列爲圖像對象:使用Java的ImageIO將像素數組轉換爲Image對象?

public Image getImageFromArray(int[] pixels, int width, int height) { 
    MemoryImageSource mis = new MemoryImageSource(width, height, pixels, 0, width); 
    Toolkit tk = Toolkit.getDefaultToolkit(); 
    return tk.createImage(mis); 
} 

是否有可能實現相同的結果使用ImageIO包中的類,所以我不必使用AWT Toolkit?

Toolkit.getDefaultToolkit()似乎不是100%可靠的,有時會拋出一個AWTError,而ImageIO類應該始終可用,這就是爲什麼我有興趣改變我的方法。

回答

23

您可以在不使用ImageIO的情況下創建圖像。只需使用匹配像素數組內容的圖像類型創建一個BufferedImage。

public static Image getImageFromArray(int[] pixels, int width, int height) { 
      BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 
      WritableRaster raster = (WritableRaster) image.getData(); 
      raster.setPixels(0,0,width,height,pixels); 
      return image; 
     } 

當使用PixelGrabber都會工作,不要忘記調用getImageFromArray之前提取來自像素陣列的RGBA信息。在PixelGrabber javadoc的handlepixelmethod中有一個例子。一旦你這樣做了,確保BufferedImage構造函數中的圖像類型爲BufferedImage.TYPE_INT_ARGB

+1

謝謝bcash,但是當我嘗試這個代碼時,我得到了一個java.lang.ArrayIndexOutOfBoundsException異常。有任何想法嗎? – 2008-09-24 02:53:40

+0

我認爲這很接近,我們可能需要克里斯的更多細節與細節?這看起來應該起作用......你的整數是什麼?他們是RGB? ARGB?某種打包格式? – 2008-09-24 04:37:39

+0

像素來自PixelGrabber,因此: int [] pixels = new int [width * height]; PixelGrabber pg = new PixelGrabber(img,0,0,width,height,pixels,0,width); pg.grabPixels(); – 2008-09-24 05:17:13

1

我已經使用java.awt.Robot抓取屏幕截圖(或屏幕的一部分)取得了很好的成功,但要使用ImageIO,您需要將其存儲在BufferedImage而不是內存中圖像源。然後你可以調用ImageIO的一個靜態方法並保存文件。嘗試類似:

// Capture whole screen 
Rectangle region = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); 
BufferedImage capturedImage = new Robot().createScreenCapture(region); 

// Save as PNG 
File imageFile = new File("capturedImage.png"); 
ImageIO.write(capturedImage, "png", imageFile); 
7

使用光柵即使我創建了BufferedImageTYPE_INT_ARGB,我也得到了ArrayIndexOutOfBoundsException。但是,使用setRGB(...)方法BufferedImage爲我工作。

3

BufferedImage.getData()上的JavaDoc表示:「一個柵格是拷貝的圖像數據。」

此代碼對我的作品,但我懷疑它的效率:

 // Получаем картинку из массива. 
     int[] pixels = new int[width*height]; 
      // Рисуем диагональ. 
      for (int j = 0; j < height; j++) { 
       for (int i = 0; i < width; i++) { 
        if (i == j) { 
         pixels[j*width + i] = Color.RED.getRGB(); 
        } 
        else { 
         pixels[j*width + i] = Color.BLUE.getRGB(); 
         //pixels[j*width + i] = 0x00000000; 
        } 
       } 
      } 

BufferedImage pixelImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
    pixelImage.setRGB(0, 0, width, height, pixels, 0, width); 
0

由於這是對SO標記ImageIO的最高投票的問題之一,我認爲還是有空間,更好的解決方案,即使這個問題很古老。 :-)

看看我在GitHub的開源imageio項目中的BufferedImageFactory.java類。

有了它,你可以簡單的寫:

BufferedImage image = new BufferedImageFactory(image).getBufferedImage(); 

另一個好處是,這種方法,因爲最壞的情況下,具有相同的性能(時間)作爲PixelGrabber基的例子已經在這個線。對於大多數常見情況(通常爲JPEG),速度大約快兩倍。無論如何,它使用較少的內存。

作爲一項附加功能,保留原始圖像的顏色模型和像素佈局,而不是使用默認顏色模型轉換爲int ARGB。這可能會節省更多的內存。

(PS:如果任何人有興趣,工廠還支持子採樣,感興趣區域和進度監聽器。:-)

0

我有同樣的問題,其他人試圖應用這個問題的正確答案,我的int數組實際上得到一個OutOfboundException,我修復它添加一個索引,因爲數組的長度必須是widht *高* 3在這之後我無法得到的圖像,所以我固定它的柵格設置到圖像

public static Image getImageFromArray(int[] pixels, int width, int height) { 
     BufferedImage image = new BufferedImage(width, height,  BufferedImage.TYPE_INT_ARGB); 
     WritableRaster raster = (WritableRaster) image.getData(); 
     raster.setPixels(0,0,width,height,pixels); 
     image.setData(raster); 
     return image; 
    } 

而且你可以看到圖像,如果u顯示它的標籤上JFrame上這樣

JFrame frame = new JFrame(); 
    frame.getContentPane().setLayout(new FlowLayout()); 
    frame.getContentPane().add(new JLabel(new ImageIcon(image))); 
    frame.pack(); 
    frame.setVisible(true); 

在imageIcon()上設置圖像。 最後的建議,您可以嘗試將Bufferedimage.TYPE_INT_ARGB更改爲與您從此類型中獲得數組的圖像相匹配的其他內容,這非常重要,因爲我有一個0和-1的數組,因此我使用了此類型BufferedImage.TYPE_3BYTE_BGR