BitmapFactory.decodeStream 总是返回 null,skia 解码器显示解码返回 false
Posted
技术标签:
【中文标题】BitmapFactory.decodeStream 总是返回 null,skia 解码器显示解码返回 false【英文标题】:BitmapFactory.decodeStream always returns null and skia decoder shows decode returned false 【发布时间】:2010-09-27 10:11:51 【问题描述】:在这里测试图像: http://images.plurk.com/tn_4134189_bf54fe8e270ce41240d534b5133884ee.gif
我尝试了几种在互联网上找到的解决方案,但没有有效的解决方案。
我正在使用以下 sn-p 代码:
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
上显示。但可以查看是否在浏览器中打开。
【问题讨论】:
【参考方案1】:试试这个作为临时解决方法:
首先添加以下类:
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:调试/skia(14676):---解码器->解码返回假10-28 18:36:03.970:错误:图像为空。 images.plurk.com/… 我很好奇你为什么要重写这个方法? android skia 解码器对 gif 尺寸进行所谓的 TopLeft 检查,并且不处理超出画布边界的图像。通过覆盖 read 方法,我们将相对于画布的绘图偏移替换为零,并欺骗skia解码器接受gif文件以进行进一步解码。您可以查看适用于 Android 的 skia 源代码,并根据 GIF89a 规范对图像进行 bvi 检查。 顺便说一句,您可能需要确保仅对来自 images.plurk.com 的图像使用 PlurkInputStream 包装器。 @Wu-Man,“顺便说一句,您可能希望确保仅对来自 images.plurk.com 的图像使用 PlurkInputStream 包装器”是什么意思。什么是“完整/正确的解决方案”版本?【参考方案2】:我有同样的问题,部分被这个类解决了:
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));
它在大多数情况下都有帮助,但这不是通用的解决方案。 更多信息请参考bugreport。
祝你好运!
【讨论】:
【参考方案3】:我尝试了所有解决方案,但没有解决我的问题。经过一些测试,当互联网连接不稳定时,skia解码器失败的问题发生了很多。对我来说,强制重新下载图像解决了这个问题。
当图片尺寸较大时,问题也更加突出。
使用循环最多需要我重试 2 次,并且图像将被正确下载。
Bitmap bmp = null;
int retries = 0;
while(bmp == null)
if (retries == 2)
break;
bmp = GetBmpFromURL(String imageURL);
Log.d(TAG,"Retry...");
retries++;
【讨论】:
【参考方案4】:这应该可行:
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。另一张测试图:images.plurk.com/…【参考方案5】:这是由于 Android 中 InputStream 类中的错误造成的。 您可以在 http://code.google.com/p/android/issues/detail?id=6066 处找到有效的解决方法和错误描述
【讨论】:
【参考方案6】:出于内存原因,您必须像这样实现 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
【讨论】:
【参考方案7】:对我来说,问题在于图像的颜色类型:您的图像是 color=CYMK 而不是 RGB
【讨论】:
【参考方案8】:也许这不是您的情况,但如果您尝试使用 CMYK 颜色空间而不是 RGB 颜色空间解码图像,则可能是这种情况。 CMYK 图像,如this one,Android 不支持,即使在 Android 网络浏览器中也不会显示。阅读更多关于这个here:
Unable to load JPEG-image with BitmapFactory.decodeFile. Returns null
【讨论】:
【参考方案9】:试试这个:
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);
【讨论】:
以上是关于BitmapFactory.decodeStream 总是返回 null,skia 解码器显示解码返回 false的主要内容,如果未能解决你的问题,请参考以下文章