BitmapFactory.decodeStream devolver null cuando se establecen las opciones

Tengo problemas con BitmapFactory.decodeStream(inputStream) . Al usarlo sin opciones, devolverá una imagen. Pero cuando lo uso con opciones como en .decodeStream(inputStream, null, options) nunca devuelve Bitmaps.

Lo que estoy tratando de hacer es downsample un mapa de bits antes de que realmente lo cargue para ahorrar memoria. He leído algunas buenas guías, pero ninguna utilizando. .decodeStream .

  • Manejo de mapas de bits grandes

  • Y aquí

  • Procesamiento de imágenes en Android

Funciona solo bien

 URL url = new URL(sUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); InputStream is = connection.getInputStream(); Bitmap img = BitmapFactory.decodeStream(is, null, options); 

No funciona

 InputStream is = connection.getInputStream(); Bitmap img = BitmapFactory.decodeStream(is, null, options); InputStream is = connection.getInputStream(); Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); Boolean scaleByHeight = Math.abs(options.outHeight - TARGET_HEIGHT) >= Math.abs(options.outWidth - TARGET_WIDTH); if (options.outHeight * options.outWidth * 2 >= 200*100*2){ // Load, scaling to smallest power of 2 that'll get it <= desired dimensions double sampleSize = scaleByHeight ? options.outHeight / TARGET_HEIGHT : options.outWidth / TARGET_WIDTH; options.inSampleSize = (int)Math.pow(2d, Math.floor( Math.log(sampleSize)/Math.log(2d))); } // Do the actual decoding options.inJustDecodeBounds = false; Bitmap img = BitmapFactory.decodeStream(is, null, options); 

El problema era que una vez que usted ha utilizado un InputStream de un HttpUrlConnection para buscar los metadatos de la imagen, usted no puede rebobinar y utilizar el mismo InputStream otra vez.

Por lo tanto, debe crear un nuevo InputStream para el muestreo real de la imagen.

  Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(is, null, options); Boolean scaleByHeight = Math.abs(options.outHeight - TARGET_HEIGHT) >= Math.abs(options.outWidth - TARGET_WIDTH); if(options.outHeight * options.outWidth * 2 >= 200*200*2){ // Load, scaling to smallest power of 2 that'll get it <= desired dimensions double sampleSize = scaleByHeight ? options.outHeight / TARGET_HEIGHT : options.outWidth / TARGET_WIDTH; options.inSampleSize = (int)Math.pow(2d, Math.floor( Math.log(sampleSize)/Math.log(2d))); } // Do the actual decoding options.inJustDecodeBounds = false; is.close(); is = getHTTPConnectionInputStream(sUrl); Bitmap img = BitmapFactory.decodeStream(is, null, options); is.close(); 

Intente encapsular InputStream con BufferedInputStream.

 InputStream is = new BufferedInputStream(conn.getInputStream()); is.mark(is.available()); // Do the bound decoding // inJustDecodeBounds =true is.reset(); // Do the actual decoding 

Creo que el problema es con la lógica de "calcular-escala-factor" porque el resto del código me parece correcto (asumiendo, por supuesto, que inputtream no es nulo).

Sería mejor si se puede factorizar toda la lógica de cálculo de tamaño de esta rutina en un método (llámelo calculateScaleFactor () o lo que sea) y probar ese método independientemente primero.

Algo como:

 // Get the stream InputStream is = mUrl.openStream(); // get the Image bounds BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds = true; bitmap = BitmapFactory.decodeStream(is,null,options); //get actual width x height of the image and calculate the scale factor options.inSampleSize = getScaleFactor(options.outWidth,options.outHeight, view.getWidth(),view.getHeight()); options.inJustDecodeBounds = false; bitmap=BitmapFactory.decodeStream(mUrl.openStream(),null,options); 

Y prueba getScaleFactor (…) independientemente.

También ayudará a rodear el código entero con el bloque try..catch {}, si no se hace ya.

Puede convertir el InputStream en una matriz de bytes y utilizar decodeByteArray (). Por ejemplo,

 public static Bitmap decodeSampledBitmapFromStream(InputStream inputStream, int reqWidth, int reqHeight) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { int n; byte[] buffer = new byte[1024]; while ((n = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, n); } return decodeSampledBitmapFromByteArray(outputStream.toByteArray(), reqWidth, reqHeight); } catch (IOException e) { e.printStackTrace(); } finally { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } public static Bitmap decodeSampledBitmapFromByteArray(byte[] data, int reqWidth, int reqHeight) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, 0, data.length, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; return BitmapFactory.decodeByteArray(data, 0, data.length, options); } private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { int width = options.outWidth; int height = options.outHeight; int inSampleSize = 1; if (width > reqWidth || height > reqHeight) { int halfWidth = width / 2; int halfHeight = height / 2; while (halfWidth / inSampleSize >= reqWidth && halfHeight / inSampleSize >= reqHeight) { inSampleSize *= 2; } } return inSampleSize; } 
  • Almacenar imagen de mapa de bits en tarjeta SD en Android
  • Android getPixels () posiblemente un error tonto?
  • BitmapFactory.decodeFile devuelve null
  • Google maps api v2 fuera de error de memoria
  • Guardar mapa de bits en la tarjeta SD
  • Botón para Android Sherlock ActionBar Up
  • ¿Es posible eliminar píxeles transparentes del mapa de bits en android
  • Android BitmapFactory.decodeFile intermitentemente devuelve null
  • Crear imagen desde la vista / pantalla en Android
  • Asignación de mapa de bits, utilizando BitmapFactory.Options.inBitmap arroja IllegalArgumentException
  • Android: hyperlink textview a una ubicación de mapa?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.