您的位置:首页 > 移动开发 > Android开发

android使用inSampleSize、inScaled、inDensity、inTargetDensity对图片进行缩放

2017-07-06 12:43 1591 查看
 


android使用inSampleSize、inScaled、inDensity、inTargetDensity对图片进行缩放

标签: androidBitmapBitmapFactory.OptioninSampleSizeinScaled
2015-05-04 23:27 4764人阅读 评论(3) 收藏 举报


 分类:

android(72) 

 inScaled inTargetDensity Bitmap inDensity

版权声明:本文为博主原创文章,未经博主允许不得转载。

一般来说,在Android中对图片进行缩放,我们使用以下的代码:

[java] view
plain copy

public Bitmap resizeImage(Bitmap bitmap, int w, int h) {  

    Bitmap BitmapOrg = bitmap;  

    int width = BitmapOrg.getWidth();  

    int height = BitmapOrg.getHeight();  

    int newWidth = w;  

    int newHeight = h;  

  

    float scaleWidth = ((float) newWidth) / width;  

    float scaleHeight = ((float) newHeight) / height;  

  

    Matrix matrix = new Matrix();  

    matrix.postScale(scaleWidth, scaleHeight);  

    Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg, 0, 0, width,  

            height, matrix, true);  

    return resizedBitmap;  

}  

上面这段代码也是一般对图片的进行缩放的方式,不会出什么问题,但是有两个小问题:

1、我们先要从磁盘上先将图片加载到内存,然后才能对图片进行缩放,在移动设备上对内存的要求比较高,这在一定程度上降级了性能。

2、我们使用Bitmap.createBitmap这个方法进行缩放,使用的是Java层面的方法来缩放,我们知道Java层面对图片,视频等进行处理是有性能损失的。

如果只有一两张图片,用上面的方法进行缩放是没有问题的,如果是大量的图片或者是图片很大,就会出现明显降低性能,甚至出现OOM的异常,OOM的异常是必须要处理的。

下面给出优化方案,优化我们也是基于上面两点问题给出的。一次性从磁盘上读取并缩放,而且这个缩放实在Native层,能够显著提高效率,代码如下:

[java] view
plain copy

@Override  

protected void onCreate(Bundle savedInstanceState) {  

    super.onCreate(savedInstanceState);  

    setContentView(R.layout.activity_main);  

    try {  

        BitmapFactory.Options options = new BitmapFactory.Options();  

        options.inJustDecodeBounds = true;  

        BitmapFactory.decodeStream(getAssets().open("g_b090.jpg"), null, options);  

          

        int targetDensity = getResources().getDisplayMetrics().densityDpi;  

          

        DisplayMetrics dm = new DisplayMetrics();  

        getWindowManager().getDefaultDisplay().getMetrics(dm);  

          

        int x = dm.widthPixels;  

        int y = dm.heightPixels;  

        options.inSampleSize = calculateInSampleSize(options, x, y);  

          

        double xSScale = ((double)options.outWidth) / ((double)x);    

        double ySScale = ((double)options.outHeight) / ((double)y);  

          

        double startScale = xSScale > ySScale ? xSScale : ySScale;    

          

        options.inScaled = true;  

        options.inDensity = (int) (targetDensity*startScale);  

        options.inTargetDensity = targetDensity;  

        options.inJustDecodeBounds = false;  

        Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("g_b090.jpg"), null, options);  

      

    } catch (IOException e) {  

        e.printStackTrace();  

    }  

}  

其中calculateInSampleSize方法如下

[java] view
plain copy

public 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;  

    }  

这段代码是google给出的,我们无需对它进行修改,在上面这段代码中我们使用BitmapFactory.Options的inScaled,inDensity,inTargetDensity来变相对图片进行缩放,但是这有一个局限,就是只能对图片进行等比例的放大或者缩小,不能按任意大小进行缩放,不过这还是适用大部分的情况,因为很少有对图片进行任意的缩放,因为那样会使图片变形。大家有什么问题或者有什么错误,请给我留言,大家一起讨论!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: