16

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

Community
  • 1
  • 1
btalb
  • 6,937
  • 11
  • 36
  • 44
  • i think problem is not bitmap problem in layout. – Zala Janaksinh Dec 07 '12 at 07:24
  • The problem is (as one of the reference question shows), compression is obviously slow in comparison to just copying the pixels. I can understand the benefits, but when working with small icon images it seems to be unnecessary overhead. Is decodeByteArray just the wrong function call given that the image is not 'encoded'/compressed when put into the array? – btalb Dec 08 '12 at 00:17
  • Sending a Bitmap in a `Bundle` of data is a real bad idea, and would be a real bad implementation. Also, the data size of a `Bundle` is `1 MB` as stated by Dianne Hackborn (Android framework engineer). – kaderud Dec 07 '12 at 14:05
  • The scope of this work is using limited size icons, but yes you do have a valid point. In my implementation, I think I will rethink (maybe use temp files and a path in the bundle). Can you provide a link to this information you have given? My searching returned different answers as to the max size. – btalb Dec 08 '12 at 00:18
  • See this discussion https://groups.google.com/d/msg/android-developers/KKEyW6XdDvg/wgetULOJq3QJ – kaderud Dec 08 '12 at 00:30

3 Answers3

52

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.

Dipak Keshariya
  • 22,193
  • 18
  • 76
  • 128
  • 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](http://stackoverflow.com/questions/10770263/decodebytearray-and-copypixelstobuffer-not-working-skimagedecoderfactory-retu) which physically paints the pixels from the byte array to a bitmap canvas – btalb Dec 08 '12 at 05:42
  • You are simply superb dipkaaaa ;-) – Hardik Joshi Oct 02 '15 at 06:45
  • @Prince. it's dipakkk – Abhi Apr 18 '16 at 10:18
  • @spongeBob Oh ok Bobbbbb. – Hardik Joshi Apr 18 '16 at 10:48
  • You should mention bmp.recycle() on your bitmap after compression! – Yurets Oct 04 '19 at 07:27
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();
}
Nermeen
  • 15,883
  • 5
  • 59
  • 72
0

try this:

  bmBef = BitmapFactory.decodeFile("/mnt/sdcard/Debug/001.png", bmo);
  ByteArrayOutputStream baos= new ByteArrayOutputStream();
  bmBef .compress(Bitmap.CompressFormat.PNG, 100, baos);
  byte[] byteArray = baos.toByteArray();
G M Ramesh
  • 3,420
  • 9
  • 37
  • 53