一、View转换为Bitmap

        在Android中所有的控件都是View的直接子类或者间接子类,通过它们可以组成丰富的UI界面。在窗口显示的时候Android会把这些控件都加载到内存中,形成一个以ViewRoot为根节点的控件树,然后由根节点开始逐级把控件绘制到屏幕上。

可以通过调用控件的setDrawingCacheEnabled(true)方法,开启绘图缓存功能,在绘制View的时候把图像缓存起来,然后通过getDrawingCache()方法获取这个缓存的Bitmap。需要注意的是,当不再使用这个Bitmap时,需要调用destroyDrawingCache()方法,释放Bitmap资源。由于在绘制View到屏幕时缓存图像会降低控件绘制的效率,因此只会在需要使用View的图像缓存的时候才调用setDrawingCacheEnabled(true)方法开启图像缓存功能,当不再使用图像缓存时需要调用setDrawingCacheEnabled(false)  关闭图像缓存功能。

这种方法在支持拖拽类型的应用中经常见到,在Android系统的Launcher应用中也使用了这种方法,当用户拖拽应用的快捷图标时,获取到控件对应的Bitmap,然后操作这个Bitmap随着手指移动。

下面通过一段代码来说明如何获取View对应的Bitmap。在代码中使用了两个ImageView并给它们都设置了显示的图片资源,然后把第一个ImageView对应的bitmap显示到第二个ImageView中。由于在Activity的onCreate方法中调用这个方法,当执行Activity的onCreate方法时,控件还没有准备好,所以需要使用Handler进行延迟操作,Java代码如下:

[java] view plaincopy

 
  1. //View转换为Bitmap
  2. public void getDrawingCache(final ImageView sourceImageView, final ImageView destImageView) {
  3. new Handler().postDelayed(new Runnable() {
  4. @Override
  5. public void run() {
  6. // TODO Auto-generated method stub
  7. //开启bitmap缓存
  8. sourceImageView.setDrawingCacheEnabled(true);
  9. //获取bitmap缓存
  10. Bitmap mBitmap = sourceImageView.getDrawingCache();
  11. //显示 bitmap
  12. destImageView.setImageBitmap(mBitmap);
  13. //                                Bitmap mBitmap = sourceImageView.getDrawingCache();
  14. //                                Drawable drawable = (Drawable) new BitmapDrawable(mBitmap);
  15. //                                destImageView.setImageDrawable(drawable);
  16. new Handler().postDelayed(new Runnable() {
  17. @Override
  18. public void run() {
  19. // TODO Auto-generated method stub
  20. //不再显示bitmap缓存
  21. //destImageView.setImageBitmap(null);
  22. destImageView.setImageResource(R.drawable.pet);
  23. //使用这句话而不是用上一句话是错误的,空指针调用
  24. //destImageView.setBackgroundDrawable(null);
  25. //关闭bitmap缓存
  26. sourceImageView.setDrawingCacheEnabled(false);
  27. //释放bitmap缓存资源
  28. sourceImageView.destroyDrawingCache();
  29. }
  30. }, DELAY_TIME);
  31. }
  32. }, DELAY_TIME);
  33. }
[java] view plaincopy

 
  1. mImageView1.setImageResource(R.drawable.android);
  2. mImageView2.setImageResource(R.drawable.pet);
  3. getDrawingCache(mImageView1, mImageView2);
运行效果如下:

 

Demo运行效果图1

 

Demo运行效果图2

二、图片圆角处理

在Android中可以很容通过图像叠加的规则为图片添加圆角效果。正常情况下,在已有的图像上绘图时将会在其上面添加一层新的图形。如果绘图时使用的Paint是完全不透明的,那么它将完全遮挡住下面的图像,如果Paint是部分透明的,那么它将会对重叠部分图像的颜色叠加处理。通过PorterDuffXfermode规则可以设置绘制图像时的叠加规则。PorterDuffXfermode是非常强大的转换模式,使用它可以设置图像叠加的Porter-Duff规则,来控制Paint如何与Canvas上已有的图像进行叠加。下面列举了常用的12条Porter-Duff规则及其表示的含义:

PorterDuff.Mode.CLEAR 清除画布上图像
        PorterDuff.Mode.SRC 显示上层图像
        PorterDuff.Mode.DST 显示下层图像
        PorterDuff.Mode.SRC_OVER上下层图像都显示,下层居上显示
        PorterDuff.Mode.DST_OVER 上下层都显示,下层居上显示
        PorterDuff.Mode.SRC_IN 取两层图像交集部分,只显示上层图像
        PorterDuff.Mode.DST_IN 取两层图像交集部分,只显示下层图像
        PorterDuff.Mode.SRC_OUT 取上层图像非交集部分
        PorterDuff.Mode.DST_OUT 取下层图像非交集部分
        PorterDuff.Mode.SRC_ATOP 取下层图像非交集部分与上层图像交集部分
        PorterDuff.Mode.DST_ATOP 取上层图像非交集部分与下层图像交集部分
        PorterDuff.Mode.XOR 取两层图像的非交集部分

下面使用PorterDuff.Mode.SRC_IN规则来给图片添加圆角效果,主要的思路是先绘制一个圆角矩形,然后在上面绘制图像,取图像与圆角矩形的交集部分,只保留图像。Java代码如下:

[java] view plaincopy

 
  1. //图片圆角处理
  2. public Bitmap getRoundedBitmap() {
  3. Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.frame);
  4. //创建新的位图
  5. Bitmap bgBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888);
  6. //把创建的位图作为画板
  7. Canvas mCanvas = new Canvas(bgBitmap);
  8. Paint mPaint = new Paint();
  9. Rect mRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
  10. RectF mRectF = new RectF(mRect);
  11. //设置圆角半径为20
  12. float roundPx = 15;
  13. mPaint.setAntiAlias(true);
  14. //先绘制圆角矩形
  15. mCanvas.drawRoundRect(mRectF, roundPx, roundPx, mPaint);
  16. //设置图像的叠加模式
  17. mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  18. //绘制图像
  19. mCanvas.drawBitmap(mBitmap, mRect, mRect, mPaint);
  20. return bgBitmap;
  21. }

效果如下图所示:

 

图片圆角处理

三、图片灰化处理

在Android中可以通过ColorMatrix类实现图像处理软件中的滤镜效果,通过ColorMatrix类可以对位图中的每个像素进行变换处理,达到特殊的滤镜效果,下面通过一个例子来介绍如何通过ColorMatrix对图像进行灰化处理,Java代码如下:

[java] view plaincopy

 
  1. //图片灰化处理
  2. public Bitmap getGrayBitmap() {
  3. Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android);
  4. Bitmap mGrayBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888);
  5. Canvas mCanvas = new Canvas(mGrayBitmap);
  6. Paint mPaint = new Paint();
  7. //创建颜色变换矩阵
  8. ColorMatrix mColorMatrix = new ColorMatrix();
  9. //设置灰度影响范围
  10. mColorMatrix.setSaturation(0);
  11. //创建颜色过滤矩阵
  12. ColorMatrixColorFilter mColorFilter = new ColorMatrixColorFilter(mColorMatrix);
  13. //设置画笔的颜色过滤矩阵
  14. mPaint.setColorFilter(mColorFilter);
  15. //使用处理后的画笔绘制图像
  16. mCanvas.drawBitmap(mBitmap, 0, 0, mPaint);
  17. return mGrayBitmap;
  18. }

效果如下图所示:

 

图片灰化处理

四、提取图像Alpha位图

Android中的ARGB_8888类型的位图由Alpha(透明度)、Red(红)、Green(绿)、Blue(蓝)四部分组成,其中Alpha部分也就是常说的Alpha通道,它控制图像的透明度。在Android中Bitmap类提供了extractAlpha()方法,可以把位图中的Alpha部分提取出来作为一个新的位图,然后与填充颜色后的Paint结合重新绘制一个新图像。下面通过一个例子来说明Bitmap类的extractAlpha()方法的使用,Java代码如下:

[java] view plaincopy

 
  1. //提取图像Alpha位图
  2. public Bitmap getAlphaBitmap() {
  3. BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.enemy_infantry_ninja);
  4. Bitmap mBitmap = mBitmapDrawable.getBitmap();
  5. //BitmapDrawable的getIntrinsicWidth()方法,Bitmap的getWidth()方法
  6. //注意这两个方法的区别
  7. //Bitmap mAlphaBitmap = Bitmap.createBitmap(mBitmapDrawable.getIntrinsicWidth(), mBitmapDrawable.getIntrinsicHeight(), Config.ARGB_8888);
  8. Bitmap mAlphaBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888);
  9. Canvas mCanvas = new Canvas(mAlphaBitmap);
  10. Paint mPaint = new Paint();
  11. mPaint.setColor(Color.BLUE);
  12. //从原位图中提取只包含alpha的位图
  13. Bitmap alphaBitmap = mBitmap.extractAlpha();
  14. //在画布上(mAlphaBitmap)绘制alpha位图
  15. mCanvas.drawBitmap(alphaBitmap, 0, 0, mPaint);
  16. return mAlphaBitmap;
  17. }

提取图像Alpha位图

其中最后一幅图片是把原图片四个边距缩小两个dp,然后与Alpha位图一起绘制的结果,读者可以参考本章Demo中的getStrokeBitmap()方法。

五、图像变换

Android开发框架提供了一个坐标变换矩阵Matrix类,它可以与Bitmap类的createBitmap方法结合使用,对图像进行缩放、旋转、扭曲等变换处理。图像变换操作就是对坐标变换矩阵进行矩阵乘法运算,Matrix类中提供了一些简便的方法如preScale、postScale、preRotate、postRotate、preSkrew、postSkrew、preTranslate、postTranslate等封装了矩阵的运算,它们与Bitmap类的createBitmap方法结合使用可以很容易地对图像进行缩放、旋转、扭曲、平移操作。

1)图像缩放

使用Matrix类preScale或者postScale可以对图像进行缩放操作,它的两个参数分别为x和y坐标缩放比例,下面使用preScale对图像进行放大0.75倍,Java代码如下:

//getScaleBitmap
    public Bitmap getScaleBitmap() {
            BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.pet);
            Bitmap mBitmap = mBitmapDrawable.getBitmap();
            int width = mBitmap.getWidth();
            int height = mBitmap.getHeight();
            
            Matrix matrix = new Matrix();
            matrix.preScale(0.75f, 0.75f);
            Bitmap mScaleBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
            
            return mScaleBitmap;
    }

效果如下图所示:

 


图像缩放

2)图片旋转

使用Matrix类preRotate或者postRotate可以对图像进行旋转操作,它只有一个参数表示旋转的角度,下面使用preRotate对图像顺时针旋转30度,Java代码如下:

[java] view plaincopy

 
  1. //getRotatedBitmap
  2. public Bitmap getRotatedBitmap() {
  3. BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.pet);
  4. Bitmap mBitmap = mBitmapDrawable.getBitmap();
  5. int width = mBitmap.getWidth();
  6. int height = mBitmap.getHeight();
  7. Matrix matrix = new Matrix();
  8. matrix.preRotate(45);
  9. Bitmap mRotateBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
  10. return mRotateBitmap;
  11. }

效果如下图所示:

 


图片旋转

3)图像倾斜

使用Matrix类preSkew或者postSkew可以对图像进行倾斜操作,它的两个参数分别为x和y坐标倾斜度,下面使用preSkew对图像进行倾斜变换,Java代码如下:

[java] view plaincopy

 
  1. //getScrewBitmap
  2. public Bitmap getScrewBitmap() {
  3. BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.pet);
  4. Bitmap mBitmap = mBitmapDrawable.getBitmap();
  5. int width = mBitmap.getWidth();
  6. int height = mBitmap.getHeight();
  7. Matrix matrix = new Matrix();
  8. matrix.preSkew(1.0f, 0.15f);
  9. Bitmap mScrewBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
  10. return mScrewBitmap;
  11. }

效果如下图所示:

 


图像倾斜

4)图像倒影

为图像添加倒影效果之后,图像看起来会有立体感,更有真实感,在Android中使用Matrix类可以很容易实现图像的倒影效果。主要是Matrix的preScale方法的使用,给它设置负数缩放比例,图像就会进行反转。然后通过设置Shader添加渐变效果。Java代码如下:

[java] view plaincopy

 
  1. //getReflectedBitmap
  2. private Bitmap getReflectedBitmap() {
  3. BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.pet);
  4. Bitmap mBitmap = mBitmapDrawable.getBitmap();
  5. int width = mBitmap.getWidth();
  6. int height = mBitmap.getHeight();
  7. Matrix matrix = new Matrix();
  8. // 图片缩放,x轴变为原来的1倍,y轴为-1倍,实现图片的反转
  9. matrix.preScale(1, -1);
  10. //创建反转后的图片Bitmap对象,图片高是原图的一半。
  11. //Bitmap mInverseBitmap = Bitmap.createBitmap(mBitmap, 0, height/2, width, height/2, matrix, false);
  12. //创建标准的Bitmap对象,宽和原图一致,高是原图的1.5倍。
  13. //注意两种createBitmap的不同
  14. //Bitmap mReflectedBitmap = Bitmap.createBitmap(width, height*3/2, Config.ARGB_8888);
  15. Bitmap mInverseBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, false);
  16. Bitmap mReflectedBitmap = Bitmap.createBitmap(width, height*2, Config.ARGB_8888);
  17. // 把新建的位图作为画板
  18. Canvas mCanvas = new Canvas(mReflectedBitmap);
  19. //绘制图片
  20. mCanvas.drawBitmap(mBitmap, 0, 0, null);
  21. mCanvas.drawBitmap(mInverseBitmap, 0, height, null);
  22. //添加倒影的渐变效果
  23. Paint mPaint = new Paint();
  24. Shader mShader = new LinearGradient(0, height, 0, mReflectedBitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.MIRROR);
  25. mPaint.setShader(mShader);
  26. //设置叠加模式
  27. mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
  28. //绘制遮罩效果
  29. mCanvas.drawRect(0, height, width, mReflectedBitmap.getHeight(), mPaint);
  30. return mReflectedBitmap;
  31. }

效果如下图所示:

 


图像倒影

5)图像剪切

如果只需要图像的一部分,就必须对图像进行剪切处理,在原图像上选择一个剪切区域,使用PorterDuffXfermode图像叠加规则,就可以把指定的图像区域剪切下来,下面通过三个步骤来说明如果对图像进行剪切操作。

第一步,创建一个新位图作为画板,然后把原图像画到新位图上面,Java代码如下:

[java] view plaincopy

 
  1. BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable(
  2. R.drawable.beauty);
  3. Bitmap bitmap = bd.getBitmap();
  4. int w = bitmap.getWidth();
  5. int h = bitmap.getHeight();
  6. Bitmap bm = Bitmap.createBitmap(w, h, Config.ARGB_8888);
  7. Canvas canvas = new Canvas(bm);
  8. Paint mPaint = new Paint();
  9. mPaint.setAntiAlias(true);
  10. mPaint.setStyle(Style.STROKE);
  11. canvas.drawBitmap(bitmap, 0, 0, mPaint);

效果如下图所示:

 


第一步效果图

第二步,绘制一个剪切区域,比如要剪切人物的脸部区域,需要在指定的位置绘制一个圆角矩形区域,代码中的坐标是在调试中获得,在其他分辨率下会有所不同,Java代码如下:

[java] view plaincopy

 
  1. int deltX = 76;
  2. int deltY = 98;
  3. DashPathEffect dashStyle = new DashPathEffect(new float[] { 10, 5,        5, 5 }, 2);//创建虚线边框样式
  4. RectF faceRect = new RectF(0, 0, 88, 106);
  5. float [] faceCornerii = new float[] {30,30,30,30,75,75,75,75};
  6. Paint mPaint = new Paint();//创建画笔
  7. mPaint.setColor(0xFF6F8DD5);
  8. mPaint.setStrokeWidth(6);
  9. mPaint.setPathEffect(dashStyle);
  10. Path clip = new Path();//创建路径
  11. clip.reset();
  12. clip.addRoundRect(faceRect, faceCornerii, Direction.CW);//添加圆角矩形路径
  13. canvas.save();//保存画布
  14. canvas.translate(deltX, deltY);
  15. canvas.clipPath(clip, Region.Op.DIFFERENCE);
  16. canvas.drawColor(0xDF222222);
  17. canvas.drawPath(clip, mPaint);//绘制路径
  18. canvas.restore();

效果如下图所示:

 


第二步效果

第三步,从原图像上获取指定区域的图像,并绘制到屏幕上,java代码如下:

[java] view plaincopy

 
  1. Rect srcRect = new Rect(0, 0, 88, 106);
  2. srcRect.offset(deltX, deltY);
  3. PaintFlagsDrawFilter dfd = new PaintFlagsDrawFilter(Paint.ANTI_ALIAS_FLAG,
  4. Paint.FILTER_BITMAP_FLAG);
  5. canvas.setDrawFilter(dfd);
  6. canvas.clipPath(clip);//使用路径剪切画布
  7. canvas.drawBitmap(bitmap, srcRect, faceRect, mPaint);

效果如下图所示:

 

第三部效果图

6)图像合成

如果要为图片添加水印,或者把几张小图片拼接成大图片时,就需要利用图像合成的方法,在前面实例代码中已经使用了这种方法,就是创建新位图作为画板,然后在对应的位置上绘制其他图像

Android bitmap图片处理的更多相关文章

  1. Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据

    Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据 2014-06-11 10:45:14   阅读375次 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何 ...

  2. android bitmap compress(图片压缩)

    android bitmap compress android的照相功能随着手机硬件的发展,变得越来越强大,能够找出很高分辨率的图片. 有些场景中,需要照相并且上传到服务,但是由于图片的大小太大,那么 ...

  3. Android性能优化系列之Bitmap图片优化

    https://blog.csdn.net/u012124438/article/details/66087785 在Android开发过程中,Bitmap往往会给开发者带来一些困扰,因为对Bitma ...

  4. Android—将Bitmap图片保存到SD卡目录下或者指定目录

    直接上代码就不废话啦 一:保存到SD卡下 File file = new File(Environment.getExternalStorageDirectory(), System.currentT ...

  5. Android开发之常用必备工具类图片bitmap转成字符串string与String字符串转换为bitmap图片格式

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...

  6. [翻译]开发文档:android Bitmap的高效使用

    内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...

  7. Android Bitmap 和 ByteArray的互相转换

    Android Bitmap 和 ByteArray的互相转换 移动平台图像处理,需要将图像传给native处理,如何传递?将bitmap转换成一个 byte[] 方便传递也方便cpp代码直接处理图像 ...

  8. Android压缩图片到100K以下并保持不失真的高效方法

    前言:目前一般手机的相机都能达到800万像素,像我的Galaxy Nexus才500万像素,拍摄的照片也有1.5M左右.这么大的照片上传到服务器,不仅浪费流量,同时还浪费时间. 在开发Android企 ...

  9. Android 实现图片画画板

    本文主要讲述了Android 实现图片画画板 设计项目布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk ...

随机推荐

  1. 什么XSS攻击?PHP防止XSS攻击函数

    什么XSS攻击?PHP防止XSS攻击函数 发布时间: 2013-05-14 浏览次数:22325 分类: PHP教程 XSS 全称为 Cross Site Scripting,用户在表单中有意或无意输 ...

  2. 程序集“xxx"中的类型"xxx"的方法“XXXX”没有实现

    通过反射调用一个类库时出现这样的报错,检查了一下类中已经实现了此方法,实现的方法如下: public partial class LogList : DockContent, ILogForm { p ...

  3. golang中设置Host Header的小Tips

    前言 笔者最近时间一直在学习和写Ruby和Go,尤其是Go,作为云计算时代的标准语言,写起来还是相当有感觉的,难过其会越来越火. 不过写的过程中,也遇到了一些小问题,本文就是分享关于go语言设置 HT ...

  4. 下一代hadoop

    1,hadoop 2.0 产生背景2,hadoop 2.0 基本构成3,HDFS 2.04 YARN5 MapReduce On YARN6 Hadoop 2.0初体验7 总结 1,hadoop 2. ...

  5. The Perfect Stall

    poj1274:http://poj.org/problem?id=1274 题意:有n个奶牛和m个谷仓,现在每个奶牛有自己喜欢去的谷仓,并且它们只会去自己喜欢的谷仓吃东西,问最多有多少奶牛能够吃到东 ...

  6. c++调用ffmpeg

    在自己编译好ffmpeg库后,已经迫不及待的想尝试用vs2010来调用ffmpeg,在开始调用的时候遇到了些问题,但还是解决了. 配置vs 1.右键工程-属性,在然后选择 配置属性 -> C/C ...

  7. Qt 窗体的模态与非模态(setWindowFlags(Qt::WindowStaysOnTopHint);比较有用,还有Qt::WA_DeleteOnClose)

    概念 模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在.又有叫法是称为模式对话框,无模式对话框等. 1. 模态窗体 ...

  8. (转载)JavaScript中定义变量

    (转载)http://blog.163.com/xuxiaoqianhz@126/blog/static/165190577201061594421870/ JavaScript中定义变量有两种方式: ...

  9. gcc编译器参数使用及解决

    gcc -c CStringAndPointer.c -o CStringAndPointer.o 执行时出现问题: ./CStringAndPointer.o bash: ./CStringAndP ...

  10. Jdk5.0新特性

    增强for循环:foreach语句,foreach简化了迭代器. 格式:// 增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器 for( 元素类型 变量名 : Colle ...