2012-10-11 15 views
5

Próbuję zmienić rozmiar jednego obrazu z InputStream, więc używam kodu w Strange out of memory issue while loading an image to a Bitmap object, ale nie wiem, dlaczego ten kod zawsze zwraca Drawable bez obrazu.Zmiana rozmiaru bitmapy z InputStream

Ten działa dobrze:

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

Ten jeden nie działa:

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

dlaczego jedna opcja wpływa na innych? jak to możliwe, jeśli używam dwóch różnych metod InputStream i Options?

EDIT

Rozwiązanie:

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

Odpowiedz

7

Właściwie masz dwa różne BufferedInputStream, ale używają one wewnętrznie jedynego obiektu InputStream, ponieważ BufferedInputStream jest tylko opakowaniem dla InputStream.

Więc nie można po prostu wywołać dwukrotnej metody BitmapFactory.decodeStream na tym samym strumieniu, to na pewno się nie powiedzie, ponieważ za drugim razem nie rozpocznie dekodowania od początku strumienia. Musisz zresetować strumień, jeśli jest obsługiwany lub ponownie go otworzyć.

+0

rozumiem .. ale otrzymuję ten strumień z HttpURLConnection, jak mogę to zrobić? – kavain

+0

Masz rację, nie mam dwóch InputStreams, tylko jeden taki jak powiedziałeś, i dowiaduję się, jak zduplikowany InputStream tutaj: http://stackoverflow.com/questions/5923817/how-to-clone-an-inputstream thank you very dużo. – kavain

+2

Zdajesz sobie sprawę, że zmieniasz rozmiar bitmapy dla ulepszeń pamięci, prawda? Ale ten link sprawi, że w pamięci dwukrotnie przytrzymasz całą bajtową szufladę Bitmapy w pamięci ... Chciałbym ponownie otworzyć FileInputStream lub cokolwiek innego, czego używasz ponownie. – HandlerExploit

1

to jest mój kod, który działa dobrze, mam nadzieję, że to pomoże

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

I belive nie trzeba 2 InputStream.

+1

to działa tylko dla plików .. ale dzięki. – kavain