android - 如何在不首先读取整个图像的情况下就地缩放流式位图?

标签 android bitmap streaming scale

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

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

最佳答案

此方法将从图像中读取 header 信息以确定其大小,然后读取图像并将其缩放到所需的大小,而无需为完整的原始大小的图像分配内存。

它还使用 BitmapFactory.Options.inPurgeable ,这似乎是一个记录稀疏但可取的选项,可以在使用大量位图时防止 OoM 异常。 更新:不再使用 inPurgeable,参见 this note来自罗曼

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

/**
 * 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 ) {}
    }

}

关于android - 如何在不首先读取整个图像的情况下就地缩放流式位图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7051025/

相关文章:

android - 服务器如何处理来自多个客户端的 Web 服务请求

c# - 创建位图时的相对路径

android - 如何从相机拍摄的照片制作缩略图?

android - H.264 实时流,NAL 单位的时间戳?

Python请求在上传请求正文时读取响应

java - 实现发送短信的代码?

android - Android 浏览器支持多少 HTML5?

android - sns 自动将端点注册到主题

Android - 将字符串转换为字节 []

java - 使用 StAX 解混——如果元素之间没有空格,它会跳过这些元素