我正在开发一款Android应用,可以显示从Flickr下载的照片。我从字节数组中获取一个位图对象,然后从相关的Flickr URL中读取,如下所示:
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inDither = true;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt);
然后我将位图绘制到View对象的onDraw方法的画布上:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
问题是产生的图像是像素化的,我无法弄清楚原因;我尝试了一些opt和paint对象的变种而没有运气。我的应用程序中显示的图片与原始URL中的图片之间的差异大致由以下内容证明:
Bad image, see pixelation in top left corner http://homepages.inf.ed.ac.uk/s0677975/bad.jpg
Good picture, this is the expected result http://homepages.inf.ed.ac.uk/s0677975/good.jpg
看看,例如在左上角的云层中看到差异。
请注意,从项目资源加载并以类似方式绘制的JPEG图片显示得很好,即没有像素化。
有人能给我一个暗示为什么会这样吗?
详细说明一下,字节数组是从Flickr获得的,如下所示;这是基于Romain Guy的Photostream应用程序的代码:
InputStream in = new BufferedInputStream(url.openStream(), IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
PS:我还在android.developer Google小组上发布了这个问题的变体。
非常感谢你的建议 - 现在我真的很困惑!我按照你的建议做了,发现直接从下载的字节数组得到的图像确实是像素化的。但是,这是从完全相同的URL下载的,当在我的计算机上访问时,该URL不是像素化的。这是相应的Flickr URL:
http://farm3.static.flickr.com/2678/4315351421_54e8cdb8e5.jpg
更奇怪的是,当我在模拟器中而不是在我的手机(HTC Hero)上运行相同的应用程序时,没有像素化。
这究竟是怎么回事?
下面是我用来从URL加载位图的代码 - 它基于Romain Guy的Photostream应用程序,并且它结合了Will建议将原始字节数组写入文件:
Bitmap loadPhotoBitmap(URL url) {
Bitmap bitmap = null;
InputStream in = null;
BufferedOutputStream out = null;
try {
FileOutputStream fos = new FileOutputStream("/sdcard/photo-tmp.jpg");
BufferedOutputStream bfs = new BufferedOutputStream(fos);
in = new BufferedInputStream(url.openStream(),
IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
bfs.write(data, 0, data.length);
bfs.flush();
BitmapFactory.Options opt = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt);
} catch (IOException e) {
android.util.Log.e(LOG_TAG, "Could not load photo: " + this, e);
} finally {
closeStream(in);
closeStream(out)
closeStream(bfs);
}
return bitmap;
}
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
}
private static void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
android.util.Log.e(LOG_TAG, "Could not close stream", e);
}
}
}
我在这里疯了吗? 最好, 迈克尔。
答案 0 :(得分:4)
好的,所以我终于明白了:看来我的移动网络进行图像压缩以节省带宽。
因此,从我的手机下载的图片质量低于从我的电脑下载的相同图片。
这对我的应用程序来说真是太糟糕了,但我不认为我能做些什么。叹息。
再次感谢您的意见!
最佳, 迈克尔。
答案 1 :(得分:3)
将从URL获取的原始字节写入/sdcard/tmp.jpg
,并在PC上查看。
JPEG图像以8x8(或16x16)图块压缩。您描述的“像素化”实际上是在这些图块中,表明“坏图像”是比其他图像压缩得更积极的JPEG图像。
因此,我预计实际问题是所下载的图片质量非常低,例如一个用于缩略图/预览用例。
答案 2 :(得分:1)
某些版本的Android在Bitmap类中存在错误,并在某些操作时将Bitmap转换为RGB_565。这将表现在类似于您的图片上的文物中。这也可以解释蓝天的划分。 此外,请记住,android尝试"优化"图像通过加载甚至编译资源文件时将它们转换为rgb_565。看一眼: http://android.nakatome.net/2010/04/bitmap-basics.html