Android: Bitmap to Byte Array and back: SkImageDecoder::Factory returned null

70,815

Solution 1

You are passing Bitmap into Intent and get bitmap in next activity from bundle, but the problem is if your Bitmap/Image size is big at that time the image is not load in next activity.

Use below 2 Solutions to solve this issue.

1) First Convert Image into Byte Array and then pass into Intent and in next activity get byte array from Bundle and Convert into Image(Bitmap) and set into ImageView.

Convert Bitmap to Byte Array:-

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();

Pass byte array into intent:-

Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("picture", byteArray);
startActivity(intent);

Get Byte Array from Bundle and Convert into Bitmap Image:-

Bundle extras = getIntent().getExtras();
byte[] byteArray = extras.getByteArray("picture");

Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
ImageView image = (ImageView) findViewById(R.id.imageView1);

image.setImageBitmap(bmp);

2) First Save image into SDCard and in next activity set this image into ImageView.

Solution 2

The following method works perfectly with me, give it a try..

public byte[] convertBitmapToByteArray(Context context, Bitmap bitmap) {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(bitmap.getWidth() * bitmap.getHeight());
    bitmap.compress(CompressFormat.PNG, 100, buffer);
    return buffer.toByteArray();
}
Share:
70,815
btalb
Author by

btalb

Updated on February 26, 2020

Comments

  • btalb
    btalb about 4 years

    The goal is to convert a Bitmap to a byte [], pass it between activities in a Bundle of data, then reconvert it back to a Bitmap at a later stage for display in an Imageview.

    The issue is that whenever I try this, I just get a null bitmap and the non-descriptive, unhelpful log output:

    12-07 17:01:33.282: D/skia(2971): --- SkImageDecoder::Factory returned null

    I have looked at the following solutions:

    Solution supplies the bitmap to byte[] code used

    Highlighted that copyPixelsToBuffer() is essential over .compress

    (Especially seeing as it is not necessary in this case).

    I have run up the following test case which definitely narrows down the problem to the converting and restoring code. Based on my debugging, there is correct decoding, the byte array is the correct size and full, Bitmap configs are forced to be the same, decodeByteArray is just failing:

    package com.example.debug;
    
    import java.nio.ByteBuffer;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.Bitmap.Config;
    import android.graphics.BitmapFactory;
    import android.util.Log;
    import android.view.Menu;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    
    public class MainActivity extends Activity {
        RelativeLayout rl = null;
        RelativeLayout.LayoutParams rlp = null;
    
        ImageView ivBef = null;
        ImageView ivAft = null;
    
        Bitmap bmBef = null;
        Bitmap bmAft = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // TEST
            BitmapFactory.Options bmo = new BitmapFactory.Options();
            bmo.inPreferredConfig = Config.ARGB_8888;
    
            bmBef = BitmapFactory.decodeFile("/mnt/sdcard/Debug/001.png", bmo);
            byte[] b = bitmapToByteArray(bmBef);
            bmAft = BitmapFactory.decodeByteArray(b, 0, b.length, bmo);
    
            LinearLayout ll = new LinearLayout(this);
    
            ivBef = new ImageView(this);
            ivBef.setImageBitmap(bmBef);
    
            ivAft = new ImageView(this);
            ivAft.setImageBitmap(bmAft);
    
            ll.addView(ivBef);
            ll.addView(ivAft);
    
            setContentView(ll);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.activity_main, menu);
            return true;
        }
    
        public static byte[] bitmapToByteArray(Bitmap bm) {
            // Create the buffer with the correct size
            int iBytes = bm.getWidth() * bm.getHeight() * 4;
            ByteBuffer buffer = ByteBuffer.allocate(iBytes);
    
            // Log.e("DBG", buffer.remaining()+""); -- Returns a correct number based on dimensions
            // Copy to buffer and then into byte array
            bm.copyPixelsToBuffer(buffer);
            // Log.e("DBG", buffer.remaining()+""); -- Returns 0
            return buffer.array();
        }
    
    }
    

    The before Imageview correctly displays the image, the after ImageView shows nothing (as you would expect with a null bitmap

  • btalb
    btalb over 11 years
    I have marked this answer as correct as it works. Essentially, the problem here it seems that if I want to just copy the pixels into a byte[] and transfer them, without the unnecessary overhead of compression, then decodeByteArray is the wrong function call. It seems there is no correct function call for creating a bitmap from a byte array of pixels, the only option is that here which physically paints the pixels from the byte array to a bitmap canvas
  • Hardik Joshi
    Hardik Joshi over 8 years
    You are simply superb dipkaaaa ;-)
  • Abhi
    Abhi about 8 years
    @Prince. it's dipakkk
  • Hardik Joshi
    Hardik Joshi about 8 years
    @spongeBob Oh ok Bobbbbb.
  • Yurets
    Yurets over 4 years
    You should mention bmp.recycle() on your bitmap after compression!