1

I am trying to load a byte array into a bitmap. I already tried to downscale the image so it will be smaller but I still get an OutOfMemory error. How can I make sure that people don't get an OutOfMemory error here?

The code I am using to create the bitmap:

private void rotatePicture(int rotation, byte[] data, ImageView photoImageView) {
    BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inSampleSize = 2; // Power of 2
    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
...

The stacktrace:

09-15 11:09:28.182  11831-11831/com.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.OutOfMemoryError
            at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
            at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:522)
            at com.app.SquareCamera.EditSavePhotoFragment.rotatePicture(EditSavePhotoFragment.java:85)
            at com.app.SquareCamera.EditSavePhotoFragment.onViewCreated(EditSavePhotoFragment.java:72)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:973)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:740)
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
            at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:458)
            at android.os.Handler.handleCallback(Handler.java:730)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:176)
            at android.app.ActivityThread.main(ActivityThread.java:5419)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
            at dalvik.system.NativeStart.main(Native Method)

Edit:

I now tried to use the examples from http://developer.android.com/training/displaying-bitmaps/load-bitmap.html using the following code. But I still get an OutOfMemory error on return BitmapFactory.decodeByteArray(data, 0, data.length, options); in the decodeSampledBitmapFromByteArray method.

private void rotatePicture(int rotation, byte[] data, ImageView photoImageView) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeByteArray(data, 0, data.length, options);
    int imageHeight = options.outHeight;
    int imageWidth = options.outWidth;

    Bitmap bitmap = decodeSampledBitmapFromByteArray(data, imageWidth, imageHeight);
    ...
}


public static Bitmap decodeSampledBitmapFromByteArray(byte[] data,
                                                     int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeByteArray(data, 0, data.length, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
4
  • I'd recommend reading this, if you haven't dont so already: developer.android.com/training/displaying-bitmaps/… Commented Sep 15, 2015 at 9:16
  • Please see my edit to the post, I tried that but I am still getting an error. Commented Sep 15, 2015 at 9:28
  • downsample the BitmapFactory. Options Commented Sep 15, 2015 at 10:02
  • may be it needs large heap, try to write in AndroidManifest.xml android:largeHeap="true" Commented Sep 15, 2015 at 10:06

2 Answers 2

1

you try to downsample the image to its current size not to a smaller size

int imageHeight = options.outHeight;
int imageWidth = options.outWidth;

Bitmap bitmap = decodeSampledBitmapFromByteArray(data, imageWidth, imageHeight);
...

if you change to something like this

int imageHeight = options.outHeight;
int imageWidth = options.outWidth;

// calculate maxHeight and maxWidth from screen resolution

while ((imageHeight > maxHeight) || (imageWidth > maxWidth)) {
   imageHeight /= 2; imageWidth /= 2;
}

Bitmap bitmap = decodeSampledBitmapFromByteArray(data, imageWidth, imageHeight);
Sign up to request clarification or add additional context in comments.

Comments

0

hi please use below function according to your need

public static byte[] getByteOfImage(String p_fileName) throws Exception
    {
        Bitmap m_bitmap = null;
        byte[] m_bitmapdata1 = null;
        try
        {
            m_bitmap = decodeFile(new File(p_fileName), 100, 100);
        }
        catch (Throwable m_throwable)
        {

        }

        ByteArrayOutputStream m_bos = new ByteArrayOutputStream();
        m_bitmap.compress(Bitmap.CompressFormat.JPEG, 90, m_bos);
        m_bitmapdata1 = m_bos.toByteArray();
        m_bitmap.recycle();


        return m_bitmapdata1;
    }




 public static Bitmap decodeFile(File file, int width, int height)
    {
        try
        {
            //Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(file), null, o);
            int scale = 1;

            //The new size we want to scale to
            final int REQUIRED_WIDTH = width;
            final int REQUIRED_HIGHT = height;



            //Find the correct scale value. It should be the power of 2.
            while (o.outWidth / scale / 2 >= REQUIRED_WIDTH && o.outHeight / scale / 2 >= REQUIRED_HIGHT)
            {
                scale *= 2;
            }

            //Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeStream(new FileInputStream(file), null, o2);
        }
        catch (FileNotFoundException e)
        {

        }
        return null;
    }

3 Comments

I already have the byte array. The way I am getting the byte array is: byte[] data = getArguments().getByteArray(BITMAP_KEY);
Try to reduce bitmap creation steps . May be in your code multiple times bitmap create so bcoz of this reason it will throw OOM Exception
I am getting the data originally from the onPictureTaken method of the camera. I am not making other bitmaps before I am making my current bitmap.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.