如何在不先读取整个图像的情况下就地缩放流位图? [英] How do I scale a streaming bitmap in-place without reading the whole image first?

查看:14
本文介绍了如何在不先读取整个图像的情况下就地缩放流位图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个图像密集型的 Android 应用程序.我目前正在使用 Bitmap.createScaledBitmap() 将图像缩放到所需的大小.但是,这种方法要求我在内存中已经有原始位图,可以相当大.

I have an Android application that is very image intensive. I'm currently using Bitmap.createScaledBitmap() to scale the image to a desired size. However, this method requires that I already have the original bitmap in memory, which can be quite sizable.

如何在不先将整个内容写入本地内存或文件系统的情况下缩放我正在下载的位图?

How can I scale a bitmap that I'm downloading without first writing the entire thing out to local memory or file system?

推荐答案

这个方法会从图片中读取头信息来确定它的大小,然后读取图片并将其缩放到所需的大小,而不需要为图片分配内存完整的原始尺寸图像.

This method will read the header information from the image to determine its size, then read the image and scale it to the desired size in place without allocating memory for the full original sized image.

它还使用 BitmapFactory.Options.inPurgeable,这似乎是一个文档稀少但可取的选项,用于在使用大量位图时防止 OoM 异常.更新:不再使用 inPurgeable,参见 这篇笔记来自罗曼

It also uses BitmapFactory.Options.inPurgeable, which seems to be a sparsely documented but desirable option to prevent OoM exceptions when using lots of bitmaps. UPDATE: no longer uses inPurgeable, see this note from Romain

它的工作原理是在通过 InputStream 读取整个图像之前使用 BufferedInputStream 读取图像的标头信息.

It works by using a BufferedInputStream to read the header information for the image before reading the entire image in via the InputStream.

/**
 * Read the image from the stream and create a bitmap scaled to the desired
 * size.  Resulting bitmap will be at least as large as the 
 * desired minimum specified dimensions and will keep the image proportions 
 * correct during scaling.
 */
protected Bitmap createScaledBitmapFromStream( InputStream s, int minimumDesiredBitmapWith, int minimumDesiredBitmapHeight ) {

    final BufferedInputStream is = new BufferedInputStream(s, 32*1024);
    try {
        final Options decodeBitmapOptions = new Options();
        // For further memory savings, you may want to consider using this option
        // decodeBitmapOptions.inPreferredConfig = Config.RGB_565; // Uses 2-bytes instead of default 4 per pixel

        if( minimumDesiredBitmapWidth >0 && minimumDesiredBitmapHeight >0 ) {
            final Options decodeBoundsOptions = new Options();
            decodeBoundsOptions.inJustDecodeBounds = true;
            is.mark(32*1024); // 32k is probably overkill, but 8k is insufficient for some jpgs
            BitmapFactory.decodeStream(is,null,decodeBoundsOptions);
            is.reset();

            final int originalWidth = decodeBoundsOptions.outWidth;
            final int originalHeight = decodeBoundsOptions.outHeight;

            // inSampleSize prefers multiples of 2, but we prefer to prioritize memory savings
            decodeBitmapOptions.inSampleSize= Math.max(1,Math.min(originalWidth / minimumDesiredBitmapWidth, originalHeight / minimumDesiredBitmapHeight));

        }

        return BitmapFactory.decodeStream(is,null,decodeBitmapOptions);

    } catch( IOException e ) {
        throw new RuntimeException(e); // this shouldn't happen
    } finally {
        try {
            is.close();
        } catch( IOException ignored ) {}
    }

}

这篇关于如何在不先读取整个图像的情况下就地缩放流位图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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