Search code examples
javaandroidbitmapscalebitmapfactory

Change the size of a bitmap in android to avoid OOM


I have been working on changing the size of the bitmap that I download from my server because I know that this is the issue with my OOM error I have been getting. I have tried the follow other examples and this one as well https://developer.android.com/training/displaying-bitmaps/load-bitmap.html but I cannot make heads or tails about how to use it and where to use it either. I want to scale my bitmaps down to screen resolution but can't seam to figure that out. Thank you for any help with this.

Also not that this is being done in a AsyncTask if that makes a difference.

Here is my code for setting up the bitmap:

public class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> {

BitmapFactory.Options options = new BitmapFactory.Options();

private final WeakReference<ImageView> imageViewReference;
Resources resources;

public ImageDownloaderTask(ImageView imageView) {
    imageViewReference = new WeakReference<ImageView>(imageView);
}


@Override
protected Bitmap doInBackground(String... params)
{
    return downloadBitmap(params[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
    if (isCancelled()) {
        bitmap = null;
        Log.d("HTTPS No go", bitmap.toString());
    }

    if (imageViewReference != null) {
        ImageView imageView = imageViewReference.get();
        if (imageView != null) {
            if (bitmap != null) {
                //Scale the bitmap to a smaller size
                imageView.setImageBitmap(bitmap);
            } else {
                Log.d("Downloading the image: ", "No Image found");
            }
        }

    }
}

//URL connection to download the image
private Bitmap downloadBitmap(String url) {

    HttpURLConnection urlConnection = null;
            try{
            URL uri = new URL(url);
            urlConnection = (HttpURLConnection) uri.openConnection();
            urlConnection.setRequestMethod("GET");
            int statusCode = urlConnection.getResponseCode();
            //check if the HTTP status code is equal to 200, which means that it is ok
            if (statusCode != 200) {
                return null;
            }

            InputStream inputStream = urlConnection.getInputStream();
            if (inputStream != null) {

                /*
                options.inJustDecodeBounds = true;
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
                int imageHeight = options.outHeight;
                int imageWidth = options.outWidth;
                String imageType = options.outMimeType;
                int sampleSize = calculateInSampleSize(options, imageWidth, imageHeight);
                */
                Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                return bitmap;
            }
            }catch (ProtocolException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } {}

    return null;
}

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

}

UPDATE:

This fixed it a bit. It allows me to log out just once but when I logout a second time it crashes with the good old OOM error.

InputStream inputStream = urlConnection.getInputStream();
            if (inputStream != null) {

                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize=1; //try to decrease decoded image

                Bitmap bitmap = BitmapFactory.decodeStream(inputStream , null, options);
                return bitmap;
            }
            }catch (ProtocolException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } {}

Solution

  • Thanks everyone that helped out. I found my issue was not the size of the downloading bitmap because I am resizing them automatically when i add them into my recycle view each time. It was caused by a gif I had playing on the Login Page which took just that much memory that it would kill the device once any other thing occupied the memory at all.

    I really appreciate everyone here and thank you. I thought myself that the issue was with the downloading of the image because that is what the usual culperat is.