12

我正在开发一个显示从 Flickr 下载的照片的 Android 应用程序。我从字节数组中获取位图对象,然后从相关的 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 对象的变体,但都没有成功。我的应用中显示的图片与原始网址中的图片的区别大致如下:

图像不好,请参见左上角的像素化 http://homepages.inf.ed.ac.uk/s0677975/bad.jpg

好图,这是预期的结果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);
        }
    }
}

我在这里疯了吗?最好的,迈克尔。

4

3 回答 3

4

好的,我终于明白了:看来我的移动网络会进行图像压缩以节省带宽。

因此,从我的手机下载的图片质量低于从我的计算机下载的同一张图片。

这对我的应用程序来说很糟糕,但我认为我对此无能为力。叹。

再次感谢您的意见!

最好的,迈克尔。

于 2010-02-02T16:28:55.623 回答
3

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

JPEG 图像压缩为 8x8(或 16x16)图块。您所描述的“像素化”实际上是在这些图块中,这表明“坏”图像是一个比另一个压缩得更积极的 JPEG。

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

于 2010-02-02T12:14:03.410 回答
1

某些版本的 Android 在 Bitmap 类中存在错误,并且通过某些操作将 Bitmap 转换为 RGB_565。这将体现在与您图片上的伪像相似的伪像中。这也可以解释蓝天的条带。另外,请记住,android 会在加载甚至编译资源文件时尝试通过将它们转换为 rgb_565 来“优化”图像。看看: http ://android.nakatome.net/2010/04/bitmap-basics.html

于 2012-01-29T22:51:56.397 回答