Android:BitmapFactory.decodeByteArray 提供像素化位图 [英] Android: BitmapFactory.decodeByteArray gives pixelated bitmap

查看:61
本文介绍了Android:BitmapFactory.decodeByteArray 提供像素化位图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 Android 应用程序,该应用程序显示从 Flickr 下载的照片.我从字节数组中获取位图对象,依次从相关的 Flickr URL 中读取,如下所示:

I am working on an Android app that displays photos which are downloaded from Flickr. I obtain a bitmap object from a byte array, which in turn is read from the relevant Flickr URL, as follows:

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 方法中将位图绘制到画布上:

I then draw the bitmap onto a canvas in the onDraw method of a View object:

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint); 

问题是生成的图片像素化了,我不知道为什么;我尝试了许多 opt 和paint 对象的变体,但都没有运气.我的应用中显示的图片与原始网址中的图片的区别大致如下所示:

The problem is that the resulting picture is pixelated and I can't figure out why; I have tried a number of variations of the opt and paint objects with no luck. The difference between the picture displayed in my app and the picture at the original URL is roughly demonstrated by the following:

糟糕的图像,请参阅 http://homepages 左上角的像素化.inf.ed.ac.uk/s0677975/bad.jpg

好图,这是预期的结果 http://homepages.inf.ed.ac.uk/s0677975/good.jpg

看例如在左上角的云彩处查看差异.

Look e.g. at the clouds in the top-left corner to see the difference.

请注意,从项目资源加载并以类似方式绘制的 JPEG 图片显示效果很好,即没有像素化.

Note that JPEG pictures which are loaded from the project resources and drawn in a similar way display just fine, i.e. have no pixelation.

谁能告诉我为什么会这样?

Can anybody give me a hint as to why this is happening?

再详细说一下,字节数组是从Flickr获取的,如下;这是基于 Romain Guy 的 Photostream 应用程序中的代码:

To elaborate a little, the byte array is obtained from Flickr as follows; this is based on code from the Photostream app by Romain Guy:

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 group 上发布了这个问题的一个变体.

PS: I also posted a variant of this question on the android.developer Google group.

非常感谢您的建议——现在我真的很困惑!我按照你的建议做了,发现直接从下载的字节数组产生的图像确实是像素化的.但是,这是从完全相同的 URL 下载的,在我的计算机上访问时,该 URL 没有像素化.这是相应的 Flickr 网址:

Thanks a lot for your suggestion -- now I am really puzzled! I did as you suggested and found that the image resulting directly from the downloaded byte array is indeed pixelated. However, this is downloaded from exactly the same URL which, when accessed on my computer, is NOT pixelated. Here is the corresponding Flickr URL:

http://farm3.static.flickr.com/2678/4315351421_54e8cdb8e

更奇怪的是,当我在模拟器而不是手机(HTC Hero)上运行相同的应用程序时,没有像素化.

Even stranger, when I run the same app in the simulator rather than on my phone (a HTC Hero), there is no pixelation.

这怎么可能?

以下是我用于从 URL 加载位图的代码——它基于 Romain Guy 的 Photostream 应用程序,并且结合了 Will 将原始字节数组写入文件的建议:

Below is the code I use for loading a bitmap from a URL -- it is based on the Photostream app by Romain Guy, and it incorporates Will's suggestion to write the raw byte array to file:

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

我会在这里发疯吗?最好的,迈克尔.

Am I going crazy here? Best, Michael.

推荐答案

将从 URL 获取的原始字节写入 /sdcard/tmp.jpg,并在您的 PC 上查看.

Write the raw bytes fetched from the URL to /sdcard/tmp.jpg, and view on your PC.

JPEG 图像以 8x8(或 16x16)图块压缩.您描述的像素化"实际上是在这些图块中,这表明坏"图像是比其他图像压缩得更积极的 JPEG.

JPEG images are compressed in 8x8 (or 16x16) tiles. The 'pixelation' as you describe it is actually in these tiles, suggesting that the 'bad' image is a JPEG that is more aggressively compressed than the other.

所以我预计实际问题是正在下载的图像是一个非常低质量的版本,例如一种用于缩略图/预览用例.

So I'd anticipate that the actual issue is that the image being downloaded is a very low-quality version, e.g. one intended for thumbnailing/preview use-cases.

这篇关于Android:BitmapFactory.decodeByteArray 提供像素化位图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆