12

copyPixelsToBufferおよびcopyPixelsFromBufferメソッドを使用して、Android で ARGB_8888 形式のビットマップの生データにアクセスしようとしています。ただし、これらの呼び出しを呼び出すと、常にアルファ チャネルが RGB チャネルに適用されるようです。byte[] または類似の生データが必要です (JNI を通過するため; はい、Android 2.2 の bitmap.h について知っていますが、それを使用することはできません)。

以下にサンプルを示します。

    // Create 1x1 Bitmap with alpha channel, 8 bits per channel
    Bitmap one = Bitmap.createBitmap(1,1,Bitmap.Config.ARGB_8888);
    one.setPixel(0,0,0xef234567);
    Log.v("?","hasAlpha() = "+Boolean.toString(one.hasAlpha()));
    Log.v("?","pixel before = "+Integer.toHexString(one.getPixel(0,0)));

    // Copy Bitmap to buffer
    byte[] store = new byte[4];
    ByteBuffer buffer  = ByteBuffer.wrap(store);
    one.copyPixelsToBuffer(buffer);

    // Change value of the pixel
    int value=buffer.getInt(0);
    Log.v("?", "value before = "+Integer.toHexString(value));
    value = (value >> 8) | 0xffffff00;
    buffer.putInt(0, value);
    value=buffer.getInt(0);
    Log.v("?", "value after = "+Integer.toHexString(value));

    // Copy buffer back to Bitmap
    buffer.position(0);
    one.copyPixelsFromBuffer(buffer);
    Log.v("?","pixel after = "+Integer.toHexString(one.getPixel(0,0)));

次にログが表示されます

hasAlpha() = true
pixel before = ef234567
value before = 214161ef
value after = ffffff61
pixel after = 619e9e9e

argb チャネルの順序が異なることは理解しています。それはいいです。しかし、私はすべてのコピーにアルファチャンネルを適用したくありません(それはそれがしているようです)。

これはどのようcopyPixelsToBuffercopyPixelsFromBuffer動作するはずですか?バイト[]で生データを取得する方法はありますか?

以下の回答に応じて追加されました:

buffer.order(ByteOrder.nativeOrder());の前に置くとcopyPixelsToBuffer結果が変わりますが、それでも私が望む方法ではありません:

pixel before = ef234567
value before = ef614121
value after = ffffff41
pixel after = ff41ffff

基本的に同じ問題に悩まされているようです (それぞれにアルファが適用されますcopyPixelsFrom/ToBuffer)。

4

4 に答える 4

3

Bitmap のデータにアクセスする 1 つの方法は、getPixels() メソッドを使用することです。以下に、argbデータからグレースケール画像を取得し、バイト配列からビットマップに戻すために使用した例を示します(もちろん、RGBが必要な場合は、3xバイトを予約してすべて保存します...):

/*Free to use licence by Sami Varjo (but nice if you retain this line)*/

public final class BitmapConverter {

    private BitmapConverter(){};

   /**
    * Get grayscale data from argb image to byte array
    */
   public static byte[] ARGB2Gray(Bitmap img)
   {

       int width = img.getWidth();
       int height = img.getHeight();

       int[] pixels = new int[height*width];
       byte grayIm[] = new byte[height*width];

       img.getPixels(pixels,0,width,0,0,width,height);

       int pixel=0;
       int count=width*height;

       while(count-->0){
           int inVal = pixels[pixel];

           //Get the pixel channel values from int 
           double r = (double)( (inVal & 0x00ff0000)>>16 );
           double g = (double)( (inVal & 0x0000ff00)>>8  );
           double b = (double)(  inVal & 0x000000ff)      ;

           grayIm[pixel++] = (byte)( 0.2989*r + 0.5870*g + 0.1140*b );
       }

       return grayIm;
   }

   /**
    * Create a gray scale bitmap from byte array
    */
   public static Bitmap gray2ARGB(byte[] data, int width, int height)
   {
       int count = height*width;
       int[] outPix = new int[count];
       int pixel=0;
       while(count-->0){
           int val = data[pixel] & 0xff; //convert byte to unsigned
           outPix[pixel++] = 0xff000000 | val << 16 | val << 8 | val ;
       }

       Bitmap out =  Bitmap.createBitmap(outPix,0,width,width, height, Bitmap.Config.ARGB_8888);
       return out;
   }

}
于 2014-10-23T15:50:18.353 に答える
1

私の推測では、これは使用しているByteBufferのバイト順序に関係している可能性があります。ByteBufferはデフォルトでビッグエンディアンを使用します。バッファにエンディアンを設定します

buffer.order(ByteOrder.nativeOrder());

それが役立つかどうかを確認してください。

さらに、copyPixelsFromBuffer / copyPixelsToBufferは、ピクセルデータを変更しません。それらは生でコピーされます。

于 2011-02-15T23:17:12.393 に答える