BitmapFactory.decodeStream always returns null and

2019-01-17 19:18发布

问题:

test image here: http://images.plurk.com/tn_4134189_bf54fe8e270ce41240d534b5133884ee.gif

I've tried several solutions found on the internet but there is no working solution.

I'm using the following snippet code:

Url imageUrl = new Url("http://images.plurk.com/tn_4134189_bf54fe8e270ce41240d534b5133884ee.gif");
Bitmap image = BitmapFactory.decodeStream(imageUrl.openStream());

Always getting this log:

DEBUG/skia(1441): --- decoder->decode returned false

Any help? Thanks.

EDIT:

Those images failed to be decoded are also can not be shown on a WebView. But can see if open in a Browser.

回答1:

Try this as a temporary workaround:

First add the following class:

  public static class PlurkInputStream extends FilterInputStream {

    protected PlurkInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read(byte[] buffer, int offset, int count)
        throws IOException {
        int ret = super.read(buffer, offset, count);
        for ( int i = 2; i < buffer.length; i++ ) {
            if ( buffer[i - 2] == 0x2c && buffer[i - 1] == 0x05
                && buffer[i] == 0 ) {
                buffer[i - 1] = 0;
            }
        }
        return ret;
    }

}

Then wrap your original stream with PlurkInputStream:

Bitmap bitmap = BitmapFactory.decodeStream(new PlurkInputStream(originalInputStream));

Let me know if this helps you.

EDIT:

Sorry please try the following version instead:

        for ( int i = 6; i < buffer.length - 4; i++ ) {
            if ( buffer[i] == 0x2c ) {
                if ( buffer[i + 2] == 0 && buffer[i + 1] > 0
                    && buffer[i + 1] <= 48 ) {
                    buffer[i + 1] = 0;
                }
                if ( buffer[i + 4] == 0 && buffer[i + 3] > 0
                    && buffer[i + 3] <= 48 ) {
                    buffer[i + 3] = 0;
                }
            }
        }

Note that this is not efficient code nor is this a full/correct solution. It will work for most cases, but not all.



回答2:

I had the same problem, partially was fixed by this class:

static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
    super(inputStream);
}

@Override
public long skip(long n) throws IOException {
    long totalBytesSkipped = 0L;
    while (totalBytesSkipped < n) {
        long bytesSkipped = in.skip(n - totalBytesSkipped);
        if (bytesSkipped == 0L) {
              int byte = read();
              if (byte < 0) {
                  break;  // we reached EOF
              } else {
                  bytesSkipped = 1; // we read one byte
              }
       }
        totalBytesSkipped += bytesSkipped;
    }
    return totalBytesSkipped;
}

}

And:

InputStream in = null;
    try {
        in = new java.net.URL(imageUrl).openStream();
        } catch (MalformedURLException e) {
        e.printStackTrace();
        } catch (IOException e) {
        e.printStackTrace();
        }
Bitmap image = BitmapFactory.decodeStream(new FlushedInputStream(in));

It helped in most cases, but this is not universal solution. For more refer to this bugreport.

Best luck!



回答3:

I tried all the solutions but did not solved my problem. After some tests, the problem of skia decoder failing happened a lot when the internet connection is not stable. For me, forcing to redownload the image solved the problem.

The problem also presented more when the image is of large size.

Using a loop will required me at most 2 retries and the image will be downloaded correctly.

Bitmap bmp = null;
int retries = 0;
while(bmp == null){
    if (retries == 2){
        break;
    }
    bmp = GetBmpFromURL(String imageURL);
    Log.d(TAG,"Retry...");
    retries++;
}


回答4:

This should work:

URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
connection.disconnect();
input.close();

myBitmap contains your image.



回答5:

this is due to a bug in the InputStream class in Android. You can find a valid workaround and a description of the bug here http://code.google.com/p/android/issues/detail?id=6066



回答6:

For memory reasons, you must be implements BitmapFactory options like this:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; // might try 8 also

The main download bitmap function maybe like this:

Bitmap downloadBitmap(String url) {

    final HttpClient client = AndroidHttpClient.newInstance("Android");
    final HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse response = client.execute(getRequest);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != HttpStatus.SC_OK) {
            if(DEBUG)Log.w("ImageDownloader", "Error " + statusCode +
                    " while retrieving bitmap from " + url);
            return null;
        }

        final HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream inputStream = null;
            try {

                inputStream = entity.getContent();
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 4; // might try 8 also
                return BitmapFactory.decodeStream(new FlushedInputStream(inputStream),null,options);

            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                entity.consumeContent();
            }
        }
    } catch (IOException e) {
        getRequest.abort();
        if(DEBUG)Log.w(TAG, "I/O error while retrieving bitmap from " + url, e);
    } catch (IllegalStateException e) {
        getRequest.abort();
        if(DEBUG)Log.w(TAG, "Incorrect URL: " + url);
    } catch (Exception e) {
        getRequest.abort();
        if(DEBUG)Log.w(TAG, "Error while retrieving bitmap from " + url, e);
    } finally {
        if ((client instanceof AndroidHttpClient)) {
            ((AndroidHttpClient) client).close();
        }
    }
    return null;
}

And maybe you must be implements AsyncTask like this: http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html



回答7:

For me the problem is with type of color of image: your image are in color=CYMK not in RGB



回答8:

Maybe this is not your case but it could be if you are trying to decode images with CMYK colorspace, instead of RGB colorspace. CMYK images, like this one, are not supported by Android, and will not be displayed even in the Android web browser. Read more about this here:

Unable to load JPEG-image with BitmapFactory.decodeFile. Returns null



回答9:

Try this:

HttpGet httpRequest = new HttpGet(url);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);
InputStream is = bufferedHttpEntity.getContent();
Drawable d = Drawable.createFromStream(is, "");
//or bitmap
//Bitmap b = BitmapFactory.decodeStream(is);