2012-10-11 19 views
5

Tôi đang cố định lại kích thước một hình ảnh từ InputStream, vì vậy tôi sử dụng mã trong Strange out of memory issue while loading an image to a Bitmap object nhưng tôi không biết tại sao mã này luôn trả về Bản vẽ không có hình ảnh.Thay đổi kích thước bitmap từ InputStream

Cái này hoạt động tốt:

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

Cái này không hoạt động:

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

lý do tại sao một lựa chọn ảnh hưởng đến người khác? làm thế nào nó có thể nếu tôi sử dụng hai InputStream và Options khác nhau?

EDIT

Giải pháp:

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

Trả lời

7

Thực tế bạn có hai khác nhau BufferedInputStream nhưng họ sử dụng nội bộ chỉ một đối tượng InputStreamBufferedInputStream chỉ là một trình bao bọc cho InputStream.

Vì vậy, bạn không thể chỉ gọi hai lần BitmapFactory.decodeStream phương pháp trên cùng một luồng, nó chắc chắn sẽ thất bại vì lần thứ hai nó sẽ không bắt đầu giải mã từ đầu luồng. Bạn cần đặt lại luồng của mình nếu nó được hỗ trợ hoặc mở lại.

+0

hiểu .. nhưng tôi nhận luồng này từ HttpURLConnection, làm cách nào tôi có thể làm điều đó? – kavain

+0

Bạn nói đúng, tôi không có hai InputStream, giống như bạn đã nói và tôi tìm hiểu cách InputStream trùng lặp ở đây: http://stackoverflow.com/questions/5923817/how-to-clone-an-inputstream cảm ơn bạn rất nhiều nhiều. – kavain

+2

Bạn nhận ra rằng bạn đang thay đổi kích thước Bitmap để cải thiện bộ nhớ phải không? Nhưng liên kết đó sẽ khiến bạn giữ toàn bộ mảng byte sao lưu của Bitmap trong bộ nhớ hai lần ... Tôi sẽ chỉ mở lại FileInputStream hoặc bất kỳ thứ gì bạn đang sử dụng lại. – HandlerExploit

1

đây là mã của tôi hoạt động tốt, tôi hy vọng điều này sẽ giúp

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

Và tôi tin bạn không cần phải 2 InputStream.

+1

tác phẩm này chỉ dành cho tệp .. nhưng cảm ơn. – kavain