Search code examples
androidimagebitmapscaledecode

Trying to scale an image and return a bitmap from android gallery


I am currently pulling an image from the android gallery, which returns a uri to an activity for preview, then gets sent up to Parse database.

Images being sent up were far too big so I implemented the methods found in the android developer documentation

Here's what I'm working with

Uri selectedImage = data.getData();
            InputStream imageStream = getContentResolver().openInputStream(selectedImage);

            imageBitmap = getBitmapFromReturnedImage(imageStream, 800, 800);

//                ByteArrayOutputStream stream = new ByteArrayOutputStream();
// LINE 2                imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
//                byte[] byteArray = stream.toByteArray();
//
//                parseFile = new ParseFile("location_image.jpg", byteArray);

            mImage.setImageBitmap(imageBitmap);



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;
}

public static Bitmap getBitmapFromReturnedImage(InputStream inputStream, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(inputStream, null, options);

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(inputStream, null, options);
}

The commented "LINE 2", when that section isn't commented, returns a null pointer exception, which blows my mind. With that section commented, the imageview simply looks to be empty when I run the app.

Any clue what's going on?


Solution

  • You need to seek back to the start of the InputStream after reading the bounds before calling decodeStream for a second time, otherwise you will end up with an invalid Bitmap. The easiest way is just to close the stream and open it again.

    Try this code (note function is no longer static to allow calling getContentResolver() and you have pass in a Uri not an InputStream):

    public Bitmap getBitmapFromReturnedImage(Uri selectedImage, int reqWidth, int reqHeight) throws IOException {
    
        InputStream inputStream = getContentResolver().openInputStream(selectedImage);
    
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(inputStream, null, options);
    
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
        // close the input stream
        inputStream.close();
    
        // reopen the input stream
        inputStream = getContentResolver().openInputStream(selectedImage);      
    
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeStream(inputStream, null, options);
    }
    

    call like this

    Uri selectedImage = data.getData();
    imageBitmap = getBitmapFromReturnedImage(selectedImage, 800, 800);