zoukankan      html  css  js  c++  java
  • BitmapFactory: inSampleSize 的一些思考

    一. BitmapFactory.Options 中inSampleSize的取值问题

    关于inSampleSize的取值问题Google已经给出了一个推荐的算法:(https://developer.android.com/topic/performance/graphics/load-bitmap)

    public static int calculateInSampleSize(
                BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
    
        if (height > reqHeight || width > reqWidth) {
    
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
    
            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) >= reqHeight
                    && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }
    
        return inSampleSize;
    }

    实际测试下还好,基本可以满足不OOM的需求,但是隐隐觉得当inSampleSize的值很大的时候,图片的压缩质量会不会太严重?比如说App内中的相册功能,采用这个算法放大的时候,图片会不会变得很不清楚?一时也没有找到特别好的压缩算法。

    二. 图片的放置问题

    按照Google给出的示例代码,使用inSampleSize前要先把 options.inJustDecodeBounds = true; 设置成true:

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
            int reqWidth, int reqHeight) {
    
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
    
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    然后再计算出inSampleSize,最后再进行decode,个人觉得这段代码还是有缺陷,拿我的手机来说吧,分辨率是1440*2560, 需要显示的ImageView宽度是1440*810,需要加载的图片是1920*1080,通过上面Google的算法,算出inSampleSize的值为1,我把图片放置到xxxhdpi和xxhdpi的时候图片可以正常显示,但是我把图片放到mdpi和raw文件夹下的时候,程序一运行就Crash了,因为inSampleSize的默认值就是1,等于没有做任何处理,但是系统在加载时却会对图片再进行放大,一旦需要申请的字节数过多,系统就直接Crash了:

    java.lang.RuntimeException: Canvas: trying to draw too large(132710400bytes) bitmap.

    所以我觉得为了保险起见,最好在上面的代码中加上这么一句: options.inScaled = false; 

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
            int reqWidth, int reqHeight) {
    
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
    
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
       options.inScaled = false;
    return BitmapFactory.decodeResource(res, resId, options); }

    保证不管我放置在任何文件夹,图片都不会被缩放。

  • 相关阅读:
    将Python 程序打包成 .exe格式入门
    浅论各种调试接口(SWD、JTAG、Jlink、Ulink、STlink)的区别
    用pyinstaller打包python程序,解决打包时的错误:Cannot find existing PyQt5 plugin directories
    win10下 anaconda 环境下python2和python3版本转换
    zsh: command not found: conda的一种解决方法
    mac-os安装autojump
    六环外的商业
    浮躁的社会没错,错的是缺少一颗平静的心
    一张图看懂STM32芯片型号的命名规则
    OpenOCD的概念,安装和使用
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/11120590.html
Copyright © 2011-2022 走看看