编辑:这是Android版本中的一个错误< 4.3 Kitkat。它涉及Android中的libjpeg库,它不能处理缺少EOF / EOI位的JPEG,或者显然没有它不喜欢的元数据/ EXIF数据。 https://code.google.com/p/android/issues/detail?id=9064
原始问题:
在我的应用中加载图片时出现问题。
我的端点发送JSON
,其中包含BASE64
编码图像。根据REST调用,这些图像可以是PNG
或JPG
。某些JPG
文件遇到的问题是它们最后缺少EOF
位。 PNG
文件有效,有些JPG
文件可以正常工作,但不幸的是,这些带有问题的JPG
文件存在于Oracle DB中(存储为BLOB
)。我无法控制数据库。
我一直在浏览谷歌的错误: https://code.google.com/p/android/issues/detail?id=9064 和这里: https://code.google.com/p/android/issues/detail?id=57502
还可以看到使用自定义ICC配置文件进行编码CYMK
的问题。
以标准方式解码图像会返回false
:
byte[] imageAsBytes = Base64.decode(base64ImageString, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
根据上面的错误报告,Android中内置的JPG解析器应该受到指责。
我试图找出我的设备的解决方法,该方法停留在4.2.2
上。我对此操作系统版本没有其他选择。
我认为尝试使用像Universal Image Loader
这样的图像加载器库可能是一个好主意,但它要求我将图像存储在本地,或存储在URL上。当我从REST服务器获取BASE64
中的数据时,我无法使用它。一个选项是支持decodeByteArray
扩展BaseImageDecoder
的自定义类,如底部开发人员所述:https://github.com/nostra13/Android-Universal-Image-Loader/issues/209
在这里,我被卡住了。我已经有了一个自定义图像解码器来尝试处理JPG文件中缺少EOF
标记的问题,但我不知道如何编辑它以添加对decodeByteArray
的支持。
这是我的CustomImageDecoder
:
public class CustomImageDecoder extends BaseImageDecoder {
public CustomImageDecoder(boolean loggingEnabled) {
super(loggingEnabled);
}
@Override
protected InputStream getImageStream(ImageDecodingInfo decodingInfo) throws IOException {
InputStream stream = decodingInfo.getDownloader()
.getStream(decodingInfo.getImageUri(), decodingInfo.getExtraForDownloader());
return stream == null ? null : new JpegClosedInputStream(stream);
}
private class JpegClosedInputStream extends InputStream {
private static final int JPEG_EOI_1 = 0xFF;
private static final int JPEG_EOI_2 = 0xD9;
private final InputStream inputStream;
private int bytesPastEnd;
private JpegClosedInputStream(final InputStream iInputStream) {
inputStream = iInputStream;
bytesPastEnd = 0;
}
@Override
public int read() throws IOException {
int buffer = inputStream.read();
if (buffer == -1) {
if (bytesPastEnd > 0) {
buffer = JPEG_EOI_2;
} else {
++bytesPastEnd;
buffer = JPEG_EOI_1;
}
}
return buffer;
}
}
}
顺便说一句,使用上面的自定义类,我试图像这样加载我的字节数组:
byte[] bytes = Base64.decode(formattedB64String, Base64.NO_WRAP);
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
String imageId = "stream://" + is.hashCode();
...
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(imageId, userImage, options);
我收到此错误:
ImageLoader: Image can't be decoded [stream://1097215584_656x383]
Universal Image loader不允许stream://
架构,因此我创建了一个允许它的自定义BaseImageDownloader
类:
public class StreamImageDownloader extends BaseImageDownloader {
private static final String SCHEME_STREAM = "stream";
private static final String STREAM_URI_PREFIX = SCHEME_STREAM + "://";
public StreamImageDownloader(Context context) {
super(context);
}
@Override
protected InputStream getStreamFromOtherSource(String imageUri, Object extra) throws IOException {
if (imageUri.startsWith(STREAM_URI_PREFIX)) {
return (InputStream) extra;
} else {
return super.getStreamFromOtherSource(imageUri, extra);
}
}
}
因此,如果有人可以帮助我创建一个更好的CustomImageDecoder
来处理BASE64
编码的字符串,或者byte[]
包含一个图像,那么我可以使用decodeByteArray
,我会不胜感激!
谢谢。
答案 0 :(得分:1)
UnversalImageLoader
使用以下方案解码文件
"h t t p ://site.com/image.png" // from Web
"file:///mnt/sdcard/image.png" // from SD card
"file:///mnt/sdcard/video.mp4" // from SD card (video thumbnail)
"content://media/external/images/media/13" // from content provider
"content://media/external/video/media/13" // from content provider (video thumbnail)
"assets://image.png" // from assets
"drawable://" + R.drawable.img // from drawables (non-9patch images)
您的方案是stream://
希望有所帮助。
答案 1 :(得分:0)
关闭这个: 这里的问题实际上是Android< 4.3中的一个错误,其中Android无法显示未正确关闭的图像(缺少结束字节)或包含某些元数据,这些元数据由于某种原因而无法实现。喜欢。但是,我不确定这是什么元数据。我的问题是JPEG没有正确终止。
无论如何,该错误已在Android 4.3中修复。