views:

201

answers:

4

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.

A: 

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.

Keenora Fluffball
Thanks but still not working. It always returns null. Another test image: http://images.plurk.com/tn_5018722_bf926743319e0ed15ccbab52a114900a.gif
shiami
A: 

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!

Patrick
I've tried this and also not working
shiami
A: 

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

yann.debonnel
I've read this, tried and failed.
shiami
+1  A: 

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.

Wu-Man
Thanks for helping but still get the same result. 10-28 18:36:03.970: DEBUG/skia(14676): --- decoder->decode returned false10-28 18:36:03.970: ERROR: image is null. http://images.plurk.com/tn_5606289_30342c409d2a5a5cd747e064721464c4.gif
shiami
I'm curious why you override the method to this?
shiami
Android skia decoder does a so-called TopLeft check on gif dimensions and does not handle images that go out of canvas bounds. By overriding the read method, we're replacing the drawing offset with respect to the canvas to zero and fooling the skia decoder to accept the gif file for further decoding. You can look into the skia source code for Android and do a bvi check on the images against the GIF89a spec.
Wu-Man
Btw, you might want to make sure that you use the PlurkInputStream wrapper only for images from images.plurk.com.
Wu-Man
Yes! It finally working now! Many thanks for sharing this trick and information. One more question, what is a bvi check? Sorry I'm not familiar with image formats.
shiami
bvi is just a binary file editor like vi. You can use it to edit the image file content, and verify the format against the GIF89a spec. That's how I did it anyway... :p
Wu-Man