5

I trying to resize one image from InputStream, so I use the code in Strange out of memory issue while loading an image to a Bitmap object but I don't know why this code always return Drawable without image.

This one works well:

private Drawable decodeFile(InputStream f){
    try {
        InputStream in2 = new BufferedInputStream(f);
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=2;
        return new BitmapDrawable(BitmapFactory.decodeStream(in2, null, o2));
    } catch (Exception e) {
        return null;
    }
}

This one does not work:

private Drawable decodeFile(InputStream f){
    try {
        InputStream in1 = new BufferedInputStream(f);
        InputStream in2 = new BufferedInputStream(f);
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(in1,null,o);

        //The new size we want to scale to
        final int IMAGE_MAX_SIZE=90;

        //Find the correct scale value. It should be the power of 2.
        int scale = 2;
        if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
            scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / 
               (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inJustDecodeBounds = false;
        o2.inSampleSize=scale;
        return new BitmapDrawable(BitmapFactory.decodeStream(in2, null, o2));
    } catch (Exception e) {
        return null;
    }
}

why one option affect the other? how its possible if I use two different InputStream and Options?

jww
  • 97,681
  • 90
  • 411
  • 885
kavain
  • 451
  • 2
  • 8
  • 20
  • Possible duplicate of [Resize a large bitmap file to scaled output file on Android](https://stackoverflow.com/q/3331527/608639) – jww Sep 02 '18 at 15:46

2 Answers2

8

Actually you have two different BufferedInputStream but they internally use the only one InputStream object because BufferedInputStream is only a wrapper for InputStream.

So you can't just call two times BitmapFactory.decodeStream method on the same stream, it will definitely fail because the second time it wouldn't start decoding from the beginning of the stream. You need to reset your stream if it is supported or reopen it.

Andrei Mankevich
  • 2,253
  • 16
  • 15
  • understand.. but I receive this stream from HttpURLConnection, how can I do that? – kavain Oct 11 '12 at 17:44
  • You are right, I haven't two InputStreams, just one like you said, and I learn how duplicate InputStream here: http://stackoverflow.com/questions/5923817/how-to-clone-an-inputstream thank you very much. – kavain Oct 11 '12 at 18:04
  • 2
    You realize you are resizing the Bitmap for memory improvements right? But that link will make you hold the entire Bitmap's backing byte array in memory twice... I would just reopen the FileInputStream or whatever you are using again. – HandlerExploit Oct 11 '12 at 18:39
  • @andrei-mankevich Such InputStreams (that do not support mark/reset) can be simply wrapped into BufferedInputStream – Sachin Gupta Mar 31 '16 at 10:09
1

this is my code that works well, I hope this will help

//Decode image size
    BitmapFactory.Options optionsIn = new BitmapFactory.Options();
    optionsIn.inJustDecodeBounds = true; // the trick is HERE, avoiding memory leaks
    BitmapFactory.decodeFile(filePath, optionsIn);

    BitmapFactory.Options optionsOut = new BitmapFactory.Options();
    int requiredWidth = ECameraConfig.getEntryById(Preferences.I_CAMERA_IMAGE_RESOLUTION.get()).getyAxe();
    float bitmapWidth = optionsIn.outWidth;
    int scale = Math.round(bitmapWidth / requiredWidth);
    optionsOut.inSampleSize = scale;
    optionsOut.inPurgeable = true;//avoiding memory leaks
    return BitmapFactory.decodeFile(filePath, optionsOut);

And I belive you dont need 2 InputStream.

Roman Nazarevych
  • 7,513
  • 4
  • 62
  • 67