0

I am having an intermittent problem with capturing an image from the Camera activity, saving it to a smaller size, and uploading the saved image to my server.

If an image file is larger than a particular threshold (I use 2,000KB) I'm calling the following function to downsample it and save the smaller image:

private void downsampleLargePhoto(Uri uri, int fileSizeKB)
{
    int scaleFactor = (int) (fileSizeKB / fileSizeLimit);
    log("image is " + scaleFactor + " times too large");

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    try
    {           
        options.inJustDecodeBounds = false;
        options.inSampleSize = scaleFactor;
        Bitmap scaledBitmap = BitmapFactory.decodeStream(
                    getContentResolver().openInputStream(uri), null, options);
        log("scaled bitmap has size " + scaledBitmap.getWidth() + " x " + scaledBitmap.getHeight());

        String scaledFilename = uri.getPath();
        log("save scaled image to file " + scaledFilename);
        FileOutputStream out = new FileOutputStream(scaledFilename);
        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
        scaledBitmap.recycle();

        File image = new java.io.File(scaledFilename);
        int newFileSize = (int) image.length()/1000;
        log("scaled image file is size " + newFileSize + " KB");
    }
    catch(FileNotFoundException f)
    {
        log("FileNotFoundException: " + f);
    }
}

With very large images, however, my app crashes with an OutOfMemoryError on the line:

Bitmap scaledBitmap = BitmapFactory.decodeStream(
                    getContentResolver().openInputStream(uri), null, options);

What else can I do at this point to shrink an image?

TomBomb
  • 3,236
  • 5
  • 31
  • 40
  • this has been answered here before [1]: http://stackoverflow.com/questions/477572/strange-out-of-memory-issue-while-loading-an-image-to-a-bitmap-object/823966#823966 – thernav Mar 28 '13 at 19:13

1 Answers1

0

You haven't actually tried to use the API properly yet. You should be setting inJustDecodeBounds = true and then calling decodeStream(). Once you have the size that the decoded image would be you then choose an appropriate value for inSampleSize - which should be (a) a power of 2, and (b) has no relation to the compressed image file size - and then call decodeStream() a second time.

For choosing an appropriate inSampleSize value I usually refer to the screen size, i.e. if image largest edge more than twice as large as screen largest edge, set inSampleSize=2. Etc, etc.

Reuben Scratton
  • 38,595
  • 9
  • 77
  • 86