Android 图片处理之固定视框中的等比例压缩

这是一篇比较简单的处理图片的应用文,我们先看一下具体的场景:

image

这里实现了上传图片的功能,图片限制在红色框框内且比例为4/3,标准的照片比例。但是如果用户上传了其他比例的图片,为了照顾观感肯定是要对图片进行一个等比压缩处理,最后的效果和ImageView中ScareType的FitCenter效果是一样的,也就是保持图片的比例,并且最大化的显示在时框中。

那么对于自定义View如何实现这一效果呢?首先分析一下图片是如何被处理的。

三种情况:

  • 比例小于视框

    也就是图片比较“高”,例如上图左边,是一张16比9的照片,9/16 < 3/4。

    显示高度 = 视框高度

  • 比例等于视框

    也就是4比3的图片,可以完美的贴合视框不留空白

    显示宽高 = 视框宽高

  • 比例大于视框

    也就是图片比较“宽”,例如上图右边,比例为1比1, 1 > 3/4

对于图片的处理就比较简单了,计算图片和视框的比例,按照比例进行缩放即可。

那么知道图片处理的判断情况以及处理方式后,接下来就是具体代码实现了:

//取得图片和图片所处空间的比例
float scaleBitmap = ((float) bitmap.getWidth()) / bitmap.getHeight();
float scaleView = ((float)getWidth()) / getHeight();

// 空间的大小 / bitmap 的大小 = bitmap 缩放的倍数
float scaleWidth = ((float) getWidth()) / bitmap.getWidth();
float scaleHeight = ((float) getHeight()) / bitmap.getHeight();

Matrix matrix = new Matrix();
//按照比例选择缩放参照
if (scaleBitmap < scaleView) {
    //比例小于视框时,全部按照图片高度和视框高度的比例进行缩放
    matrix.postScale(scaleHeight, scaleHeight);
}else {
    //比例大于视框时,全部按照图片宽度和视框宽度的比例进行缩放
    matrix.postScale(scaleWidth, scaleWidth);
}


//bitmap 缩放
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
//draw 上去
//canvas.drawBitmap(bitmap, 0, 0, paint);

//居中显示
canvas.drawBitmap(bitmap,
        (getWidth() - bitmap.getWidth()) / 2,
        (getHeight() - bitmap.getHeight()) / 2, paint);
canvas.restore();

这里要注意一个问题就是,Java中进行除法运算并获得带小数点的结果,需要将算式中的一个值转为float才可以取得。

在最后将bitmap画入画布时,也要记得计算一下位置,居中显示才算完整实现效果。

然后简单介绍一下Android中缩放图像生成缩略图的三种方式:

1、BitmapFactory和 BitmapFactory.Options

在设定好缩放值inSampleSize 后,通过BitmapFactory.decodeFile或者decode其他形式,生成缩放后的Bitmap位图。如果已经有Bitmap图了,可以转成File地址来实现。

而缩放值inSampleSize 可以直接设定具体倍数,比如2就是2分之一倍,或者通过计算原图宽高和设定的想达到的宽高得到比例。

其中很实用的一点是,在获取图片的宽高的时候,可以将inJustDecodeBounds设成true,此时bitmap不会加载到内存,而只是获取到图片的height和width,节省内存提高效率。

示例:

 //使用BitmapFactory.Options的inSampleSize参数来缩放  
            public static Drawable resizeImage2(String path,  
                        int width,int height)   
                {  
        BitmapFactory.Options options = new BitmapFactory.Options();  
        options.inJustDecodeBounds = true;//不加载bitmap到内存中  
        BitmapFactory.decodeFile(path,options);   
        int outWidth = options.outWidth;  
        int outHeight = options.outHeight;  
        options.inDither = false;  
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;  
        options.inSampleSize = 1;  
          
        if (outWidth != 0 && outHeight != 0 && width != 0 && height != 0)   
        {  
            int sampleSize=(outWidth/width+outHeight/height)/2;  
            Log.d(tag, "sampleSize = " + sampleSize);  
            options.inSampleSize = sampleSize;  
        }  
      
        options.inJustDecodeBounds = false;  
        return new BitmapDrawable(BitmapFactory.decodeFile(path, options));       
    }  

2、使用Bitmap加Matrix来缩放

首先要获得原bitmap,创建一个Matrix对象,包含想要达到的宽和高,最后在原Bitmap的基础上生成新图片。效率比较低。

示例:

    //使用Bitmap加Matrix来缩放  
    public static Drawable 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);    
        // if you want to rotate the Bitmap     
        // matrix.postRotate(45);     
        Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg, 0, 0, width,    
                                        height, matrix, true);    
        return new BitmapDrawable(resizedBitmap);    
    } 

3、Android自带的ThumbnailUtils

Android自带的处理方法,会结合第一种和第二种方法和一些其他算法对图片进行加工,效率会比第二种高一点,使用也比较方便,一行代码就可以了:

imView.setImageBitmap(ThumbnailUtils.extractThumbnail(bitmap,200,100));

关于图片压缩

最后在三种图片的处理方式中都发现了一个问题,也是以前我对图片处理的一个知识盲区:图片不仅在拉大的时候会模糊,在缩小的时候同样也可能模糊。一张照片,压缩10倍之后,其分辨率已经不足以看清细节,锯齿非常严重。所以这三种图片的压缩,是会降低显示效果的,如果需要尺寸减小画质不变,应该需要其他的算法来解决。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容

  • 一直以来Bitmap都是开发中很棘手的问题,这个问题就是传说中的OOM(java.lang.OutofMemory...
    M悇芐冋忆阅读 4,774评论 0 11
  • 目录介绍 01.如何计算Bitmap占用内存1.1 如何计算占用内存1.2 上面方法计算内存对吗1.3 一个像素占...
    杨充211阅读 4,175评论 1 9
  • 图片压缩就是为了避免我们内存溢出,所有要对一系列进行压缩二次采样等 1.什么是OOM?为什么会引起OOM? out...
    lay_wn阅读 960评论 0 1
  • 2021期待与你一起共事,点击查看岗位[https://www.jianshu.com/p/6f4d67fa406...
    闲庭阅读 16,628评论 0 75
  • 摘要:对android 上图片压缩,其实总结起来基本可以分为两类压缩:尺寸压缩和质量压缩, 尺寸压缩其实也可以理解...
    男爵是只猫丶阅读 8,780评论 2 14