Android Bitmap 常见的几个操作:缩放,裁剪,旋转,偏移

Android Bitmap 相关操作

常见的几个操作:缩放,裁剪,旋转,偏移

    

很多操作需要 Matrix 来支持;Matrix 通过矩阵来处理位图,计算出各个像素点的位置,从而把bitmap显示出来。
matrix里有一个3x3的矩阵,用于图像处理:

MSCALE_X MSKEW_X  MTRANS_X
MSKEW_Y  MSCALE_Y MTRANS_Y
MPERSP_0 MPERSP_1 MPERSP_2

根据变量名能猜出具体的用途:
缩放X 偏移X 平移X
偏移Y 缩放Y 平移Y
透视0 透视1 透视2

matrix的操作有set,pre和post;set能够直接设置矩阵中的数值;pre类似于矩阵左乘;post类似与矩阵中的右乘

原bitmap经过计算后,会重新生成一张bitmap

代码片段:

    /**
     * 根据给定的宽和高进行拉伸
     *
     * @param origin    原图
     * @param newWidth  新图的宽
     * @param newHeight 新图的高
     * @return new Bitmap
     */
    private Bitmap scaleBitmap(Bitmap origin, int newWidth, int newHeight) {
        if (origin == null) {
            return null;
        }
        int height = origin.getHeight();
        int width = origin.getWidth();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);// 使用后乘
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (!origin.isRecycled()) {
            origin.recycle();
        }
        return newBM;
    }

    /**
     * 按比例缩放图片
     *
     * @param origin 原图
     * @param ratio  比例
     * @return 新的bitmap
     */
    private Bitmap scaleBitmap(Bitmap origin, float ratio) {
        if (origin == null) {
            return null;
        }
        int width = origin.getWidth();
        int height = origin.getHeight();
        Matrix matrix = new Matrix();
        matrix.preScale(ratio, ratio);
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (newBM.equals(origin)) {
            return newBM;
        }
        origin.recycle();
        return newBM;
    }

    /**
     * 裁剪
     *
     * @param bitmap 原图
     * @return 裁剪后的图像
     */
    private Bitmap cropBitmap(Bitmap bitmap) {
        int w = bitmap.getWidth(); // 得到图片的宽,高
        int h = bitmap.getHeight();
        int cropWidth = w >= h ? h : w;// 裁切后所取的正方形区域边长
        cropWidth /= 2;
        int cropHeight = (int) (cropWidth / 1.2);
        return Bitmap.createBitmap(bitmap, w / 3, 0, cropWidth, cropHeight, null, false);
    }

    /**
     * 选择变换
     *
     * @param origin 原图
     * @param alpha  旋转角度,可正可负
     * @return 旋转后的图片
     */
    private Bitmap rotateBitmap(Bitmap origin, float alpha) {
        if (origin == null) {
            return null;
        }
        int width = origin.getWidth();
        int height = origin.getHeight();
        Matrix matrix = new Matrix();
        matrix.setRotate(alpha);
        // 围绕原地进行旋转
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (newBM.equals(origin)) {
            return newBM;
        }
        origin.recycle();
        return newBM;
    }

    /**
     * 偏移效果
     * @param origin 原图
     * @return 偏移后的bitmap
     */
    private Bitmap skewBitmap(Bitmap origin) {
        if (origin == null) {
            return null;
        }
        int width = origin.getWidth();
        int height = origin.getHeight();
        Matrix matrix = new Matrix();
        matrix.postSkew(-0.6f, -0.3f);
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (newBM.equals(origin)) {
            return newBM;
        }
        origin.recycle();
        return newBM;
    }

按钮的操作定义:

    @Override
    public void onClick(View v) {
        Bitmap originBM = BitmapFactory.decodeResource(getResources(),
                R.drawable.littleboygreen_x128);
        switch (v.getId()) {
            case R.id.btn1: {// 按尺寸缩放
                effectTextView.setText(R.string.scale);
                Bitmap nBM = scaleBitmap(originBM, 100, 72);
                effectView.setImageBitmap(nBM);
                break;
            }
            case R.id.btn2: {// 按比例缩放,每次点击缩放比例都会不同
                effectTextView.setText(R.string.scale_ratio);
                if (ratio < 3) {
                    ratio += 0.05f;
                } else {
                    ratio = 0.1f;
                }
                Bitmap nBM = scaleBitmap(originBM, ratio);
                effectView.setImageBitmap(nBM);
                break;
            }
            case R.id.btn3: {// 裁剪
                effectTextView.setText("剪个头");
                Bitmap cropBitmap = cropBitmap(originBM);
                effectView.setImageBitmap(cropBitmap);
                break;
            }
            case R.id.btn4: {// 顺时针旋转效果;每次点击更新旋转角度
                if (alpha < 345) {
                    alpha += 15;
                } else {
                    alpha = 0;
                }
                effectTextView.setText("旋转");
                Bitmap rotateBitmap = rotateBitmap(originBM, alpha);
                effectView.setImageBitmap(rotateBitmap);
                break;
            }
            case R.id.btn5: {// 逆时针旋转效果;每次点击更新旋转角度
                if (beta > 15) {
                    beta -= 15;
                } else {
                    beta = 360;
                }
                effectTextView.setText("旋转");
                Bitmap rotateBitmap = rotateBitmap(originBM, beta);
                effectView.setImageBitmap(rotateBitmap);
                break;
            }
            case R.id.btn6: {// 偏移效果;偏移量在方法中
                Bitmap skewBM = skewBitmap(originBM);
                effectView.setImageBitmap(skewBM);
                break;
            }
        }
    }

遇到的问题

Matrix matrix = new Matrix();
matrix.preScale(ratio, ratio);// 当 ratio=1,下面的 newBM 将会等价于 origin
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
if (!origin.isRecycled()) {
origin.recycle();
}

log如下,当ratio=1时,新bitmap和旧的bitmap同一地址

11-27 05:27:16.086 16723-16723/? D/rust: originBitmap = [email protected]
11-27 05:27:16.086 16723-16723/? D/rust: newBitmap = [email protected]

时间: 2024-10-12 04:45:04

Android Bitmap 常见的几个操作:缩放,裁剪,旋转,偏移的相关文章

Android Bitmap 加载与像素操作

Android Bitmap 加载与像素操作 一:加载与像素读写 在Android SDK中,图像的像素读写可以通过getPixel与setPixel两个Bitmap的API实现.Bitmap API读取像素的代码如下: int pixel = bitmap.getPixel(col, row);// ARGB int red = Color.red(pixel); // same as (pixel >> 16) &0xff int green = Color.green(pixel

Qt on Android: Qt Quick 事件处理之捏拉缩放与旋转

上一篇<Qt on Android: Qt Quick事件处理之鼠标.键盘.定时器>我们介绍了常见的鼠标.键盘.定时器的处理,鼠标.键盘都是电脑上我们最常使用的事件,这节我们来介绍 Android 智能手机上的一个非常重要的手势:捏拉手势.捏拉手势最早在苹果手机上得到应用,苹果还曾经尝试为此操作申请专利,借以钳制三星在美国的手机和平板销售.这些我们且不管它,咱们只说在 Qt Quick 中如何处理捏拉手势. 广而告之:我正在参加 CSDN 博文大赛,请给我的参赛文章<Qt on Andr

Android单点触控技术,对图片进行平移,缩放,旋转操作

相信大家使用多点对图片进行缩放,平移的操作很熟悉了,大部分大图的浏览都具有此功能,有些app还可以对图片进行旋转操作,QQ的大图浏览就可以对图片进行旋转操作,大家都知道对图片进行缩放,平移,旋转等操作可以使用Matrix来实现,Matrix就是一个3X3的矩阵,对图片的处理可分为四个基础变换操作,Translate(平移变换).Rotate(旋转变换.Scale (缩放变换).Skew(错切变换),如果大家对Matrix不太了解的话可以看看这篇文章(点击查看),作者对每一种Matrix的变换写的

Android处理Bitmap使其能够不失真等比缩放裁剪后显示在ImageView上

Android开发过程中,我们有时需要动态得显示一些图片,并且这些图片的大小差距会十分大,如果需求并不是需要图片完整显示,但是需要不失真,并且要图片中间部分的情况下,我们需要做一系列处理,因为这个时候ImageView的各种scale type都不适用.具体步骤详见下面代码,大家也可以直接拷过去作为工具类使用 1 /** 2 * 获取正确缩放裁剪适应IamgeView的Bitmap 3 * @param imageView 4 * @param bitmap 5 * @return 6 */ 7

Android Bitmap 开源图片框架分析(精华三)

主要介绍这三个框架,都挺有名的,其他的框架估计也差不多了 Android-Universal-Image-Loaderhttps://github.com/nostra13/Android-Universal-Image-Loader ImageLoaderhttps://github.com/novoda/ImageLoader Volley(综合框架,包含图片部分)https://github.com/mcxiaoke/android-volley 扯淡时间,可以跳过这段这些开源框架的源码还

Android Bitmap面面观

转自android程序员:http://mp.weixin.qq.com/s?__biz=MzA4MjU5NTY0NA==&mid=404530070&idx=1&sn=e2580b69d6ec73dabf8160216aa6702a&scene=23&srcid=#rd 开通赞赏后的第一篇文章,仍然由大家熟悉的冯建同学投稿,他的这几篇文章可以说风格类似,都是某一个专题的详细整理,这次轮到Bitmap了.点击这里可以快速访问他的上一篇投稿: 你应该知道的那些Andr

[Android] 使用Matrix矩阵类对图像进行缩放、旋转、对比度、亮度处理

    前一篇文章讲述了Android拍照.截图.保存并显示在ImageView控件中,该篇文章继续讲述Android图像处理技术,主要操作包括:通过打开相册里的图片,使用Matrix对图像进行缩放.旋转.移动.对比度.亮度.饱和度操作,希望对大家有所帮助. 一. 显示打开图片     首先,设置activity_main.xml布局如下所示: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android

Android bitmap图片处理

一.View转换为Bitmap 在Android中所有的控件都是View的直接子类或者间接子类,通过它们可以组成丰富的UI界面.在窗口显示的时候Android会把这些控件都加载到内存中,形成一个以ViewRoot为根节点的控件树,然后由根节点开始逐级把控件绘制到屏幕上. 可以通过调用控件的setDrawingCacheEnabled(true)方法,开启绘图缓存功能,在绘制View的时候把图像缓存起来,然后通过getDrawingCache()方法获取这个缓存的Bitmap.需要注意的是,当不再

Android Bitmap 加载多张图片的缓存处理(精华二)

一般少量图片是很少出现OOM异常的,除非单张图片过~大~ 那么就可以用教程一里面的方法了通常应用场景是listview列表加载多张图片,为了提高效率一般要缓存一部分图片,这样方便再次查看时能快速显示~不用重新下载图片但是手机内存是很有限的~当缓存的图片越来越多,即使单张图片不是很大,不过数量太多时仍然会出现OOM的情况了~本篇则是讨论多张图片的处理问题 -----------------------------------------------------------------------