decodeStream returns null

2019-01-25 22:55发布

I'm trying to adopt bitmap resizing tutorial - the only difference is that I use decodeStream instead of decodeResource. It's strange but decodeStream, without any manipulations, gives me a bitmap obj, but when I go through decodeSampledBitmapFromStream it returns null for some reason. How do I fix it ?

Here's the code I use:

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

3条回答
放我归山
2楼-- · 2019-01-25 23:44

There are some problems in the replies of the second floor. Because in the Method of copy(), inputstream has been used,so in the method of decodeSampledBitmapFromInputStream(in,copyOfIn),we can not catch the value of options.outWidth.

Here I did some correction;We can convert each other between byte[] and inputstream So,we can convert inputstream to byte[], This can be used multiple times.

Code as follows:

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;  
}
查看更多
女痞
3楼-- · 2019-01-25 23:48

The problem was that once you've used an InputStream from a HttpUrlConnection, 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. Otherwise we have to abort the http request.

request.abort();
查看更多
贼婆χ
4楼-- · 2019-01-25 23:49

Because the InputStream Object can only be consumed once, you have to make a deep copy of an InputStream Object when you want to resize the bitmap from inputStream of HttpUrlConnection,otherwise decodeStream will returns null.Here is one possible solution:

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

the souce code of Method copy is as follows:

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

the souce code of Method decodeSampledBitmapFromInputStream is as follows:

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);
}
查看更多
登录 后发表回答