outofmemoryerror example ejemplo bitmaps android bitmap android-image

example - bitmaps android



decodeStream devuelve null (3)

Estoy tratando de adoptar el tutorial de cambio de tamaño de mapa de bits : la única diferencia es que uso decodeStream en lugar de decodeResource. Es extraño, pero decodeStream, sin ninguna manipulación, me da un obj de mapa de bits, pero cuando paso por decodeSampleMitmapFromStream devuelve nulo por alguna razón. ¿Cómo lo arreglo?

Aquí está el código que uso:

protected Handler _onPromoBlocksLoad = new Handler() { @Override public void dispatchMessage(Message msg) { PromoBlocksContainer c = (PromoBlocksContainer) _promoBlocksFactory.getResponse(); HttpRequest request = new HttpRequest(c.getPromoBlocks().get(0).getSmallThumbnail()); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; InputStream stream; ImageView v = (ImageView) findViewById(R.id.banner); try { stream = request.getStream(); //v.setImageBitmap(BitmapFactory.decodeStream(stream)); Works fine Bitmap img = decodeSampledBitmapFromStream(stream, v.getWidth(), v.getHeight()); v.setImageBitmap(img); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }; public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { if (width > height) { inSampleSize = Math.round((float)height / (float)reqHeight); } else { inSampleSize = Math.round((float)width / (float)reqWidth); } } return inSampleSize; } public static Bitmap decodeSampledBitmapFromStream(InputStream res, int reqWidth, int reqHeight) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(res, null, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; Bitmap img = BitmapFactory.decodeStream(res, null, options); // Gives null return img; }


Debido a que el objeto InputStream solo puede consumirse una vez, debe hacer una copia profunda de un objeto InputStream cuando desee cambiar el tamaño del mapa de bits desde InputStream de HttpUrlConnection, de lo contrario, decodeStream devolverá null. Aquí hay una posible solución:

HttpURLConnection urlConnection = null; InputStream in = null; InputStream in2 = null; try { final URL imgUrl = new URL(url); urlConnection = (HttpURLConnection) imgUrl.openConnection(); in = urlConnection.getInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream(); copy(in,out); in2 = new ByteArrayInputStream(out.toByteArray()); // resize the bitmap bitmap = decodeSampledBitmapFromInputStream(in,in2); } catch (Exception e) { Log.e(TAG, "Error in down and process Bitmap - " + e); } finally { if (urlConnection != null) { urlConnection.disconnect(); } try { if (in != null) { in.close(); } if (in2 != null){ in2.close(); } } catch (final IOException e) { Log.e(TAG, "Error in when close the inputstream." + e); } } }

El código fuente de la copia de Método es el siguiente:

public static int copy(InputStream input, OutputStream output) throws IOException{ byte[] buffer = new byte[IO_BUFFER_SIZE]; int count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; }

El código fuente de Method decodeSampledBitmapFromInputStream es el siguiente:

public static Bitmap decodeSampledBitmapFromInputStream(InputStream in, InputStream copyOfin, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeStream(copyOfin, null, options); }


El problema es que una vez que haya utilizado un InputStream desde una HttpUrlConnection, no podrá rebobinar y utilizar el mismo InputStream nuevamente . Por lo tanto, debe crear un nuevo InputStream para el muestreo real de la imagen. De lo contrario, debemos abortar la solicitud http.

request.abort();


Hay algunos problemas en las respuestas del segundo piso. Debido a que en el Método de copy() , se ha utilizado la decodeSampledBitmapFromInputStream(in,copyOfIn) de decodeSampledBitmapFromInputStream(in,copyOfIn) , por lo que en el método de decodeSampledBitmapFromInputStream(in,copyOfIn) , no podemos capturar el valor de options.outWidth .

Aquí hice algunas correcciones; podemos convertirnos entre byte[] y inputstream Entonces, podemos convertir inputstream a byte[] , Esto puede usarse varias veces.

Código de la siguiente manera:

HttpURLConnection connection = null; InputStream inputStream = null; InputStream copyiInputStream1 = null; InputStream copyiInputStream2 = null; Bitmap bitmap = null; try { URL url=new URL(imageUrl); connection=(HttpURLConnection) url.openConnection(); connection.setConnectTimeout(8000);//设置连接超时 inputStream = connection.getInputStream(); byte[] data = InputStreamTOByte(inputStream); try { copyiInputStream1 = byteTOInputStream(data); copyiInputStream2 = byteTOInputStream(data); } catch (Exception e) { e.printStackTrace(); } bitmap = decodeSampledBitmapFromInputStream(copyiInputStream1,copyiInputStream2); /** * 将InputStream转换成byte数组 * @param in InputStream * @return byte[] * @throws IOException */ public byte[] InputStreamTOByte(InputStream in) throws IOException{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] data = new byte[1024*16]; int count = -1; while((count = in.read(data,0,1024*16)) != -1) outStream.write(data, 0, count); data = null; return outStream.toByteArray(); } /** * 将byte数组转换成InputStream * @param in * @return * @throws Exception */ public InputStream byteTOInputStream(byte[] in) throws Exception{ ByteArrayInputStream is = new ByteArrayInputStream(in); return is; }