2016-11-15 105 views
0

Im無法獲取像素數據。從字節數組中獲取像素值

我的程序需要屏幕截圖,每個循環都會存儲前一屏幕截圖。

我的目標是在當前屏幕截圖和舊屏幕之間的像素級進行比較。

伊夫運行這段代碼,它告訴我的截圖是什麼格式: System.out.println(image.getType());

這樣做的輸出(我的程序)爲1意味着它的一個BufferedImage.TYPE_INT_RGB

。據我讀的類型確定像素值在字節數組中的順序。

我使用此代碼到我的緩衝的圖像轉換爲字節陣列(使用awt.Robot類,創建緩衝的圖像):

public byte[] convertToByteArray(BufferedImage img){ 
     byte[] imageInByte = null; 
     try { 



      // convert BufferedImage to byte array 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      ImageIO.write(img, "png", baos); 
      baos.flush(); 
      imageInByte = baos.toByteArray(); 
      baos.close(); 

     } catch (IOException ex) { 
      Logger.getLogger(OverlayWindow.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return imageInByte; 
} 

最後我使用的比較方法來檢查字節數組。目前僅打印陣列的顏色值:

final byte[] pixels = convertToByteArray(image); 
    final int pixelLength = 3; 
     for (int pixel = 0, row = 0, col = 0; pixel < 1; pixel += pixelLength) { 
     int argb = 0; 
     argb += -16777216; // 255 alpha 
     argb += ((int) pixels[pixel] & 0xff); // blue 
     argb += (((int) pixels[pixel + 1] & 0xff) << 8); // green 
     argb += (((int) pixels[pixel + 2] & 0xff) << 16); // red 


     int r = (argb >> 16) & 0xff, g = (argb >> 8)& 0xff, b = argb & 0xff; 
     System.out.println("R = " + r); 
     System.out.println("G = " + g); 
     System.out.println("B = " + b); 

     col++; 
     if (col == width) { 
      col = 0; 
      row++; 
     } 




    } 

我這個代碼的問題是,即使我把純色的截屏,像素值是所有的地方。我希望每個像素具有相同的顏色值。

-Edit-

我爲了性能的原因避免使用getRGB。每次調用getRGB的兩個大圖像迭代在我的應用程序中都是非常昂貴的。

+0

我們不會知道會發生什麼 - 你有一個完整的運行程序,所有的細節你做? – gpasch

+0

首先,「像素」並不是真正的像素值,它是壓縮PNG文件的字節......所以這不會起作用。其次,如果您已經將像素值作爲獨立的R,G和B樣本(您的代碼假定),爲什麼試圖將它們打包成32位ARGB格式並再次打開它們?我首先建議使用'int argb = image.getRGB(x,y);',然後像你已經做的那樣分裂成R,G和B.然後從那裏進行優化,如果速度不夠快... – haraldK

+0

我更新了我的問題。所以字節數組是問題所在?我嘗試使用這個來獲取字節數組最初:'((DataBufferByte)bufferedImage.getData()。getDataBuffer())。getData();'當我嘗試運行它時拋出以下錯誤:'java.lang.ClassCastException :java.awt.image.DataBufferInt不能轉換爲java.awt.image.DataBufferByte',那麼爲像素比較獲取字節數組的方法是什麼? – user3712476

回答

2

訪問一個BufferedImage中的像素值的最簡單方法是使用光柵:

BufferedImage image = ... 
for (int y=0 ; y < image.getHeight() ; y++) 
    for (int x=0 ; x < image.getWidth() ; x++) 
     for (int c=0 ; c < image.getRaster().getNumBands() ; c++) 
      final int value = image.getRaster().getSample(x, y, c) ; // Returns the value of the channel C of the pixel (x,y) 

光柵將採取編碼的照顧你,使它訪問的像素值的最簡單方法。但是,最快的方法是使用DataBuffer,但是必須管理所有的編碼。

/* This method takes a BufferedImage encoded with TYPE_INT_ARGB and copies the pixel values into an image encoded with TYPE_4BYTE_ABGR.*/ 
public static void IntToByte(BufferedImage source, BufferedImage result) 
    { 
    final byte[] bb = ((DataBufferByte)result.getRaster().getDataBuffer()).getData() ; 
    final int[] ib = ((DataBufferInt)source.getRaster().getDataBuffer()).getData() ; 

    switch (source.getType()) 
     { 
     case BufferedImage.TYPE_INT_ARGB : 
      for (int i=0, b=0 ; i < ib.length ; i++, b+=4) 
       { 
       int p = ib[i] ; 
       bb[b] = (byte)((p & 0xFF000000) >> 24) ; 
       bb[b+3] = (byte)((p & 0xFF0000) >> 16) ; 
       bb[b+2] = (byte)((p & 0xFF00) >> 8) ; 
       bb[b+1] = (byte)(p & 0xFF) ; 
       } 
      break ; 
     // Many other case to manage... 
     } 
    } 
+0

是'BufferedImage.TYPE_INT_RGB'與'BufferedImage.TYPE_INT_ARGB'相同的格式類型嗎?我也不需要編碼到另一個圖像,但我可以看到你展示如何獲得像素值,我唯一的問題是((DataBufferByte)result.getRaster()。getDataBuffer())。getData()'throws一個例外:'java.lang.ClassCastException:java.awt.image.DataBufferInt不能轉換爲java.awt.image.DataBufferByte' – user3712476

+0

BufferedImage。TYPE_INT_RGB和BufferedImage.TYPE_INT_ARGB是一個整數的相同編碼,它只是存在或不存在的Alpha通道。 – FiReTiTi

+0

異常是因爲您想將DataBufferInt轉換爲DataBufferByte。所以你試圖通過將它轉換爲字節來訪問一個用int編碼的圖像。正如我所說的,當使用DataBuffer時,你必須管理所有的編碼。 – FiReTiTi

相關問題