BitmapFactory.decodeStream returning null when options are set

前端 未结 4 415
北海茫月
北海茫月 2020-11-27 12:53

I\'m having issues with BitmapFactory.decodeStream(inputStream). When using it without options, it will return an image. But when I use it with options as in

相关标签:
4条回答
  • 2020-11-27 13:07

    The problem was that once you've used an InputStream from a HttpUrlConnection to fetch image metadata, you can't rewind and use the same InputStream again.

    Therefore you have to create a new InputStream for the actual sampling of the image.

      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();
    
    0 讨论(0)
  • I think the problem is with the "calculate-scale-factor" logic because rest of the code looks correct to me (assuming of course that inputstream is not null).

    It would be better if you can factor out all the size calculation logic from this routine into a method(call it calculateScaleFactor() or whatever) and test that method independently first.

    Something like:

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

    and test getScaleFactor(...) independently.

    It will also help to surround the entire code with try..catch{} block, if not done already.

    0 讨论(0)
  • 2020-11-27 13:30

    You can convert the InputStream to a byte array, and use the decodeByteArray(). For example,

    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;
    }
    
    0 讨论(0)
  • 2020-11-27 13:31

    Try wrap InputStream with BufferedInputStream.

    InputStream is = new BufferedInputStream(conn.getInputStream());
    is.mark(is.available());
    // Do the bound decoding
    // inJustDecodeBounds =true
    is.reset();  
    // Do the actual decoding
    
    0 讨论(0)
提交回复
热议问题