Harshjags
Harshjags

Reputation: 163

Android BitmapFactory.Options.inSampleSize casuse application crash

We are working on a Android app that captures images and converts the same to Bitmap to be posted to a Rest service.

While creating the Bitmap we have BitmapFactory.Options.isSample Size configured to value of 4 and this works fine on all device except for HTC One. The image in HTC one is distorted.

When we change the value to 1 it shows a good image on HTC one but the application crashes on all other devices because of Memory issues.

The issue is related to Heap size available.

  1. What is the reason that HTC one shows a distorted image on HTC one.
  2. Why is application crashing on S3 which also has the same build version of 16 but crashes due to heap size unavailability.
  3. Why does all lower version phone like droid works fine for sample size of 4.
  4. Whats the best way to check available memory space for an app and use the available for working with BITMAP.

When we configure android:largeHeap in manifest file this seems to work but it does not seem to be a dependable solution.


I was able to find the size of the picture taken using camera parameters and then arrive at optimal sample size of bitmap. The below code solves issue. But is it right way of doing or should i need to compute sample size too instead of going with 1 and 4.

private Bitmap createImaegBitmap(byte[] data)
    {
        BitmapFactory.Options opt;

        opt = new BitmapFactory.Options();
        opt.inTempStorage = new byte[16 * 1024];
        Parameters parameters = ((ReceiptCollection)getApplication()).getParams();
        Size size = parameters.getPictureSize();

        int height11 = size.height;
        int width11 = size.width;
        float mb = (width11 * height11) / 1024000;

        if (mb > 4f)
            opt.inSampleSize = 4;
        else if (mb > 3f)
            opt.inSampleSize = 1;
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,opt);
        return bitmap;
    }

Upvotes: 3

Views: 8966

Answers (1)

Tobiel
Tobiel

Reputation: 1543

look:
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html

1: because... Direct FROM DOC: If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder uses a final value based on powers of 2, any other value will be rounded down to the nearest power of 2.

2:My guess is because not all the devices have the same memory available. 3: you need to calculate the sample size no just set a number...

2,3: all devices have different cameras resolution.

to work on this issue read this: http://developer.android.com/training/displaying-bitmaps/index.html

    public static Bitmap lessResolution(String filePath) {
    int reqHeight = 120;
    int reqWidth = 120;
    BitmapFactory.Options options = new BitmapFactory.Options();

    // First decode with inJustDecodeBounds=true to check dimensions
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filePath, options);

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeFile(filePath, options);
}

private static int calculateInSampleSize(BitmapFactory.Options options,
        int reqWidth, int reqHeight) {

    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

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

        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

Upvotes: 4

Related Questions