当设置选项时,BitmapFactory.decodeStream返回null

我有BitmapFactory.decodeStream(inputStream) 。 当没有选项使用它时,它会返回一个图像。 但是,当我在.decodeStream(inputStream, null, options)使用选项时.decodeStream(inputStream, null, options)它永远不会返回位图。

我想要做的是在我实际加载它来节省内存之前下取样一个位图。 我读过一些很好的指南,但没有使用.decodeStream

  • 处理大的位图

  • 和这里

  • Android中的image processing

工作只是罚款

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

不工作

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

问题是一旦你使用了一个来自HttpUrlConnection的InputStream来获取图像元数据,你就不能倒带并重​​新使用相同的InputStream。

因此您必须为图像的实际采样创build一个新的InputStream。

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

尝试用BufferedInputStream封装InputStream。

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

我认为问题在于“计算比例因子”逻辑,因为其余的代码看起来是正确的(当然假定inputstream不为空)。

如果你能把这个例程中的所有大小计算逻辑分解成一个方法(称之为calculateScaleFactor()或其他),并首先独立地testing这个方法,会更好。

就像是:

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

并独立testinggetScaleFactor(…)。

如果还没有完成,它也将有助于用try..catch {}块包围整个代码。

您可以将InputStream转换为一个字节数组,并使用decodeByteArray()。 例如,

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