2012-10-11 25 views
5

Estoy tratando de cambiar el tamaño de una imagen de InputStream, así que uso el código en Strange out of memory issue while loading an image to a Bitmap object pero no sé por qué este código siempre devuelve Drawable sin imagen.Cambio de tamaño del mapa de bits de InputStream

Esta funciona así:

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

Ésta no funciona:

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

por qué una opción afecta a la otra? ¿Cómo es posible si uso dos InputStream y opciones diferentes?

EDITAR

Solución:

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

Respuesta

7

realidad que tienen dos diferentes BufferedInputStream pero utilizan internamente el único objeto porque InputStreamBufferedInputStream no es más que un contenedor para InputStream.

Así que no puedes simplemente llamar dos veces al método BitmapFactory.decodeStream en la misma transmisión, definitivamente fallará porque la segunda vez no comenzará la decodificación desde el comienzo de la transmisión. Debes restablecer tu transmisión si es compatible o volver a abrirla.

+0

entiendo ... pero recibo esta transmisión de HttpURLConnection, ¿cómo puedo hacer eso? – kavain

+0

Tienes razón, no tengo dos InputStreams, solo uno como dices, y aprendo cómo duplicar InputStream aquí: http://stackoverflow.com/questions/5923817/how-to-clone-an-inputstream muchas gracias mucho. – kavain

+2

¿Se da cuenta de que está cambiando el tamaño del mapa de bits para mejorar la memoria, verdad? Pero ese enlace hará que retenga dos veces toda la matriz de bytes de respaldo de Bitmap en la memoria ... Solo volvería a abrir FileInputStream o lo que sea que esté usando nuevamente. – HandlerExploit

1

este es mi código que funciona bien, espero que esto ayudará

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

Y Me creer que no necesita 2 InputStream.

+1

esto funciona solo para archivos ... pero gracias. – kavain

Cuestiones relacionadas