2012-10-11 44 views
5

我試圖從InputStream調整一個圖像的大小,所以我使用Strange out of memory issue while loading an image to a Bitmap object中的代碼,但我不知道爲什麼此代碼總是返回Drawable而沒有圖像。從InputStream調整位圖的大小

這一個效果很好:

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

這一個不工作:

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

爲什麼一個選項會影響其他?如果我使用兩個不同的InputStream和Options,它的可能性如何?

編輯

解決方案:

private Drawable decodeFile(InputStream in){ 
    try { 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     byte[] buffer = new byte[1024]; 
     int len; 
     while ((len = in.read(buffer)) > -1) { 
      baos.write(buffer, 0, len); 
     } 
     baos.flush(); 
     InputStream is1 = new ByteArrayInputStream(baos.toByteArray()); 
     InputStream is2 = new ByteArrayInputStream(baos.toByteArray()); 

     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(is1,null,o); 

     final int IMAGE_MAX_SIZE=90; 

     System.out.println("h:" + o.outHeight + " w:" + o.outWidth); 
     int scale = 1; 
     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.inSampleSize=scale; 
     return new BitmapDrawable(BitmapFactory.decodeStream(is2, null, o2)); 
    } catch (Exception e) { 
     return null; 
    } 
} 

回答

7

其實你有兩個不同的BufferedInputStream,但他們內部使用唯一的一個InputStream對象,因爲BufferedInputStream只是InputStream的包裝。

因此,您不能只在同一個流上調用兩次BitmapFactory.decodeStream方法,它肯定會失敗,因爲它第二次不會從流的開始處開始解碼。如果支持或重新打開它,您需要重置您的流。

+0

明白..但我收到來自HttpURLConnection這個流,我該怎麼做? – kavain

+0

你是對的,我沒有兩個InputStreams,只有一個像你說的,我學習如何重複InputStream在這裏:http://stackoverflow.com/questions/5923817/how-to-clone-an-inputstream非常感謝你許多。 – kavain

+2

你意識到你正在調整位圖的內存改進權嗎?但是,該鏈接將使您在內存中保存整個Bitmap的後備字節數組兩次......我只會重新打開FileInputStream或您正在使用的任何內容。 – HandlerExploit

1

這是我的代碼,效果很好,我希望這將有助於

//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); 

而且我相信你不需要2的InputStream。

+1

這項工作只適用於文件..但謝謝。 – kavain