2016-11-15 27 views
0

ピクセルデータの取得に問題があります。バイト配列からピクセル値を取得する

私のプログラムはスクリーンショットを取得します。ループするたびに前のスクリーンショットが保存されます。

私の目標は、現在のスクリーンショットと以前のスクリーンショットの間のピクセルレベルで比較を行うことです。

アイブ氏は私に語ったこのコードを実行したスクリーンショットはしているどのような形式: System.out.println(image.getType());

(私のプログラムのための)これの出力である1を意味し、そのIVEは、種類が読んだものから、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を呼び出す2つの大きな画像を反復することは、私のアプリケーションでは非常にコストがかかります。

+0

私たちは何が起こるか分からないでしょう - あなたはあなたがしているすべての詳細を備えた完全な実行プログラムを持っていますか? – gpasch

+0

まず、 'pixels'は実際にはピクセル値ではなく、圧縮された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のピクセル値にアクセスする最も簡単な方法は、Rasterを使用することです:

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_ARGB'と同じ書式設定の' BufferedImage.TYPE_INT_RGB'ですか?また、私は別のイメージにエンコードする必要はありませんが、私はあなたがピクセル値を取得する方法を表示することができます、これは私の唯一の問題は '((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は、1つのintへのエンコーディングと同じです。アルファチャンネルだけが存在します。 – FiReTiTi

+0

例外は、DataBufferIntをDataBufferByteにキャストしたいからです。だから、あなたはintでエンコードされたイメージにバイトにキャストすることでアクセスしようとします。私が言ったように、DataBufferを使用するときは、すべてのエンコーディングを管理する必要があります。 – FiReTiTi

関連する問題