在Bit中将Bitmap转换为带有灰度值的单通道字节数组?

时间:2013-06-09 17:50:07

标签: android bitmap

我正在尝试将带有ARGB_8888格式的位图转换为单个通道 需要在应用程序的本机部分中使用的字节数组。

我使用

进行了一些健全性检查
int pixel = bitmap.getPixel(x,y);
 int redValue = Color.red(pixel);
 int blueValue = Color.blue(pixel);
 int greenValue = Color.green(pixel);
 int alphaValue = Color.alpha(pixel);

似乎格式实际上是RGBA而不是ARGB。

我使用以下代码来完成此任务

public static byte[] bitmapToByteArray(Bitmap bm) {
        // Create the buffer with the correct size
        int iBytes = bm.getWidth() * bm.getHeight() ;
        byte[] res = new byte[iBytes];
        Bitmap.Config format = bm.getConfig();
        if (format == Bitmap.Config.ARGB_8888)
        {
            ByteBuffer buffer = ByteBuffer.allocate(iBytes*4);
            // Log.e("DBG", buffer.remaining()+""); -- Returns a correct number based on dimensions
            // Copy to buffer and then into byte array
            bm.copyPixelsToBuffer(buffer);
            byte[] arr = buffer.array();
            for(int i=0;i<iBytes;i++)
            {
                int A,R,G,B;
                R=(int)(arr[i*4+0]) & 0xff;
                G=(int)(arr[i*4+1]) & 0xff;
                B=(int)(arr[i*4+2]) & 0xff;
                //A=arr[i*4+3];
                byte r = (byte)(0.2989 * R + 0.5870 * G + 0.1140 * B) ;
                res[i] = r;
            }
        }
        if (format == Bitmap.Config.RGB_565)
        {
            ByteBuffer buffer = ByteBuffer.allocate(iBytes*2);
            // Log.e("DBG", buffer.remaining()+""); -- Returns a correct number based on dimensions
            // Copy to buffer and then into byte array
            bm.copyPixelsToBuffer(buffer);
            byte[] arr = buffer.array();
            for(int i=0;i<iBytes;i++)
            {
                float A,R,G,B;
                R = ((arr[i*2+0] & 0xF8) );
                G = ((arr[i*2+0] & 0x7) << 5) + ((arr[i*2+1] & 0xE0) >> 5);
                B = ((arr[i*2+1] & 0x1F) << 3 );
                byte r = (byte)(0.2989 * R + 0.5870 * G + 0.1140 * B) ;
                res[i] = r;
            }
        }
        // Log.e("DBG", buffer.remaining()+""); -- Returns 0
        return res;
    }
}

出于调试原因,正在将字节数组发送到远程服务器。 当我在服务器中重建位图时,我得到的图像都是像素化的并且在灰度级中具有奇怪的值。 知道我做错了什么吗? 任何评论将不胜感激。 感谢

1 个答案:

答案 0 :(得分:0)

O.K,找到了问题的根源,并找到了一个不同且不易出错的解决方案。

1)像素化的暗图像是由于输入图像是RGB565格式的事实,并且恢复RGB被弄乱了......请参阅我现在使用的以下本机代码来查看差异:

> void MYJNI::ConvertRGBToGRAY(unsigned char in[], unsigned char
> out[],int w,int h,int type)
>     {
>       int sz = w*h;
>       char msg[300];
>       sprintf(msg,"width = %u height = %u sz = %u",w,h,sz);
>     #if defined(__ANDROID__) || defined(ANDROID)
>       __android_log_write(ANDROID_LOG_INFO,"MOBLINK", msg);
>     #endif
>       if (type == 0) //RGBA
>       {
>           for(int i=0;i<sz;i++)
>           {
>               float A,R,G,B;
>               R=in[i*4+0];
>               G=in[i*4+1];
>               B=in[i*4+2];
>               //A=arr[i*4+3];
>               unsigned char ir = 0.2989 * R + 0.5870 * G + 0.1140 * B;
>               out[i] = ir;
>           }
>       }
>       else if(type == 1) //RGB565
>       {
>           uint16_t *parr = (uint16_t*)in;
>           for(int i=0;i<sz;i++)
>           {
>               float A,R,G,B;
>               R = ((parr[i] & 0xF800)>> 11) *8;
>               G = ((parr[i] & 0x07e0)>> 5) *4;
>               B = ((parr[i] & 0x001F)>> 0) *8;
>               
>               unsigned char ir = 0.2989 * R + 0.5870 * G + 0.1140 * B;
>               out[i] = ir;
>           }
>       }
>     } 

我使用原生函数,因为基于java的方式太慢了。