BitmapFactory.decodeStream总是返回null,skia解码器显示解码返回false。

3

这里是测试图片:

http://images.plurk.com/tn_4134189_bf54fe8e270ce41240d534b5133884ee.gif

我尝试了互联网上找到的几种方法,但都没有可行解决方案。

我正在使用以下代码片段:

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

始终会看到这个日志:
DEBUG/skia(1441): --- decoder->decode returned false

需要帮助吗? 谢谢。

编辑:

这些无法被解码的图像也无法在WebView中显示。但是如果在浏览器中打开,则可以查看。

9个回答

4

我遇到了同样的问题,这个类部分地解决了我的问题:

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

}

并且:

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

它在大多数情况下有所帮助,但这不是普遍解决方案。更多信息请参考此错误报告

祝好运!


4

尝试使用以下临时解决方法:

首先添加以下类:

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

}

接下来,您需要使用PlurkInputStream来包装原始数据流:

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

请告诉我这是否有帮助。

编辑:

对不起,请尝试使用以下版本:

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

请注意,这不是高效的代码,也不是完整/正确的解决方案。它可以适用于大多数情况,但并非全部。

感谢您的帮助,但仍然得到相同的结果。10-28 18:36:03.970: DEBUG/skia(14676): --- 解码器->解码返回false 10-28 18:36:03.970: ERROR: 图像为空。http://images.plurk.com/tn_5606289_30342c409d2a5a5cd747e064721464c4.gif - shiami
我很好奇你为什么要重写这个方法? - shiami
Android Skia解码器对gif图像进行所谓的TopLeft检查,并且不处理超出画布边界的图像。通过覆盖读取方法,我们将绘制偏移量相对于画布的值替换为零,并欺骗Skia解码器接受gif文件进行进一步解码。您可以查看Android Skia源代码,并根据GIF89a规范对图像进行bvi检查。 - Wu-Man
顺便提一下,您可能需要确保仅针对来自images.plurk.com的图像使用PlurkInputStream包装器。 - Wu-Man
1
@Wu-Man,你说的“Btw,你可能要确保只使用PlurkInputStream包装器来处理来自images.plurk.com的图像。”是什么意思?“完整/正确的解决方案”版本是什么? - user123321
显示剩余2条评论

1

我尝试了所有的解决方案,但都没有解决我的问题。经过一些测试,当网络连接不稳定时,skia解码器失败的问题经常发生。对我来说,强制重新下载图像可以解决这个问题。

当图像大小较大时,问题也更加明显。

使用循环将需要我最多尝试2次,然后图像将被正确下载。

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

0

试试这个:

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

0

这应该可以工作:

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 包含了你的图片。


谢谢,但还是不行。它总是返回 null。另一张测试图片:http://images.plurk.com/tn_5018722_bf926743319e0ed15ccbab52a114900a.gif - shiami

0

出于内存原因,您必须像这样实现BitmapFactory选项:

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

主要的下载位图函数可能是这样的:
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;
}

也许你需要像这样实现AsyncTask: http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html


0
对我来说,问题在于图像的颜色类型:您的图像是CYMK颜色而不是RGB。

0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接