简体   繁体   中英

byte array to bitmap returns null

I have a small program that takes a Chair.jpg and converts it a bitmap. The reason for this is to change the color type of the pixels to the format of BGR_888 (which I got from this stack overflow post .)

However the bitmap is null. I believe it is because of this reason D/skia: --- Failed to create image decoder with message 'unimplemented' . Looking on online, it maybe because I need to compress this? Im not sure. Can someone help me understand?

public class MainActivity extends AppCompatActivity {

    TextView textView;
    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.imageView);
        textView = findViewById(R.id.textView);

        Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.chair);
        imageView.setImageBitmap(b);

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

        Log.d("bitmap height", String.valueOf(height));
        Log.d("bitmap width", String.valueOf(width));
        Bitmap.Config config = b.getConfig();
        Log.d("b color format", String.valueOf(config));

        byte[] newImage = getImagePixels(b);
        Log.d("getImagePixels Result", String.valueOf(newImage));

        boolean b2 = isNewBitmapNull(newImage);
        Log.d("is my new bitmap null:",String.valueOf(b2));


    }

    /// <summary>
    /// function getImagePixels
    /// Purpose: Given the bitmap image return the converted 4 byte ARGB to 3 byte BGR
    /// </summary>
    /// <param name="image"> Bitmap image object </param>

    public byte[] getImagePixels(Bitmap image) {
        // calculate how many bytes our image consists of
        int bytes = image.getByteCount();
        // Create a new buffer
        ByteBuffer buffer = ByteBuffer.allocate(bytes);
        // Move the byte data to the buffer
        image.copyPixelsToBuffer(buffer);

        // Get the underlying array containing the data.
        byte[] temp = buffer.array();

        // Allocate for 3 byte BGR
        byte[] pixels = new byte[(temp.length / 4) * 3];

        // Copy pixels into place
        for (int i = 0; i < (temp.length / 4); i++) {
            pixels[i * 3] = temp[i * 4 + 3];     // B
            pixels[i * 3 + 1] = temp[i * 4 + 2]; // G
            pixels[i * 3 + 2] = temp[i * 4 + 1]; // R

            // Alpha is discarded
        }
        Log.d("check if it is array", String.valueOf(pixels.getClass().isArray()));
        Log.d("array object type", String.valueOf(pixels.getClass()));
        Log.d("array length", String.valueOf(pixels.length));
        return pixels;
    }

    public static byte[] convertBitmapToByteArrayUncompressed(Bitmap bitmap){
        ByteBuffer byteBuffer = ByteBuffer.allocate(bitmap.getByteCount());
        bitmap.copyPixelsToBuffer(byteBuffer);
        byteBuffer.rewind();
        return byteBuffer.array();
    }

    /// <summary>
    /// function copyPixelsToBitmap
    /// Purpose: Given the pixel data return a bitmap of size [?,?],PixelFormat=24BGR
    /// </summary>
    /// <param name="pixels"> Byte array with pixel data </param>
    public Bitmap copyPixelsToBitmap(byte[] pixels){
        //Here create the Bitmap to the know height, width and format
        Bitmap bmp = BitmapFactory.decodeByteArray(pixels, 0, pixels.length);

        //Return the bitmap
        return bmp;
    }

    /// <summary>
    /// function isNewBitmapNull
    /// Purpose: Given the pixel data return T/F is the bitmap was created
    /// </summary>
    /// <param name="pixels"> Byte array with pixel data </param>
    public boolean isNewBitmapNull(byte[] pixels){
        //BitmapFactory.Options options = new BitmapFactory.Options();
        //options.inMutable = true;
        Bitmap bmp = BitmapFactory.decodeByteArray(pixels, 0, pixels.length);
        if (bmp == null)
            return true;


        return false;
    }
}

For the isNewBitMapNull method, I have also tried adding the BitMapFactory options but still get a null bitmap:

//BitmapFactory.Options options = new BitmapFactory.Options();
//options.inMutable = true;
Bitmap bmp = BitmapFactory.decodeByteArray(pixels, 0, pixels.length, options);

Here is the output:

D/bitmap height: 1260 
D/bitmap width: 1260
D/b color format: ARGB_8888
D/check if it is array: true
D/array object type: class [B
D/array length: 4762800
D/getImagePixels Result: [B@5a36e09
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/is my new bitmap null:: true

It seems that you are trying to create a bitmap that has 3 bytes per pixel, but it is not possible in Android since Bitmap supports 1, 2, 4 or 8 bytes per pixel .

That is why you need to create a new bitmap with the pixel format that is supported. But using BitmapFactory.decodeByteArray doesn't work because it creates a bitmap from compressed image data, such as data that is stored in.jpg file. But you have array of raw pixel values (uncompressed).

While compressing the image and then reading it using decodeByteArray is an option, you will need to implement compression of BGR_888 yourself or use a 3rd party library. The simpler way is to convert BGR_888 back to ARGB_8888 and create a bitmap from this data:

val temp = IntArray(width * height)

for (i in 0 until width * height) {
    val red = pixels[i * 3 + 2].toInt() and 0xff
    val green = pixels[i * 3 + 1].toInt() and 0xff
    val blue = pixels[i * 3].toInt() and 0xff
    temp[i] = Color.rgb(red, green, blue)
}
return Bitmap.createBitmap(temp, width, height, Bitmap.Config.ARGB_8888)

Java version:

int[] temp = new int[width * height];

for (int i = 0; i < width * height; ++i) {
    int red = (int)pixels[i * 3 + 2] & 0xff;
    int green = (int)pixels[i * 3 + 1] & 0xff;
    int blue = (int)pixels[i * 3] & 0xff;
    temp[i] = Color.rgb(red, green, blue);
}
return Bitmap.createBitmap(temp, width, height, Bitmap.Config.ARGB_8888);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM