一、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代码如下:

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

 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
9 Paint mPaint = new Paint();
10 Rect mRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
11 RectF mRectF = new RectF(mRect);
12 //设置圆角半径为20
13 float roundPx = 15;
14 mPaint.setAntiAlias(true);
15 //先绘制圆角矩形
16 mCanvas.drawRoundRect(mRectF, roundPx, roundPx, mPaint);
17
18 //设置图像的叠加模式
19 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
20 //绘制图像
21 mCanvas.drawBitmap(mBitmap, mRect, mRect, mPaint);
22
23 return bgBitmap;
24 }

效果如下图所示:


图片圆角处理

三、图片灰化处理



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

 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 //创建颜色变换矩阵
9 ColorMatrix mColorMatrix = new ColorMatrix();
10 //设置灰度影响范围
11 mColorMatrix.setSaturation(0);
12 //创建颜色过滤矩阵
13 ColorMatrixColorFilter mColorFilter = new ColorMatrixColorFilter(mColorMatrix);
14 //设置画笔的颜色过滤矩阵
15 mPaint.setColorFilter(mColorFilter);
16 //使用处理后的画笔绘制图像
17 mCanvas.drawBitmap(mBitmap, 0, 0, mPaint);
18
19 return mGrayBitmap;
20 }

效果如下图所示:

图片灰化处理

四、提取图像Alpha位图



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

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

提取图像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代码如下:

 1 //getScaleBitmap
2 public Bitmap getScaleBitmap() {
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
8 Matrix matrix = new Matrix();
9 matrix.preScale(0.75f, 0.75f);
10 Bitmap mScaleBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
11
12 return mScaleBitmap;
13 }

效果如下图所示:

 



图像缩放

2)图片旋转



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

 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
8 Matrix matrix = new Matrix();
9 matrix.preRotate(45);
10 Bitmap mRotateBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
11
12 return mRotateBitmap;
13 }

效果如下图所示:

 



图片旋转

3)图像倾斜



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

 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
8 Matrix matrix = new Matrix();
9 matrix.preSkew(1.0f, 0.15f);
10 Bitmap mScrewBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
11
12 return mScrewBitmap;
13 }

效果如下图所示:

 



图像倾斜

4)图像倒影



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

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

效果如下图所示:

 



图像倒影

5)图像剪切



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



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

 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代码如下:

 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代码如下:

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

效果如下图所示:

 

第三部效果图

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图片保存到SD卡目录下或者指定目录

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

  3. Bitmap 图片格式并用 C++ 读写 Bitmap

    转自 Bitmap 图片格式并用 C++ 读写 Bitmap 1.Bitmap 图片格式 每部分的具体内容就不展开了.要说的有两点: (1)调色板不是必须的,可有可无,有没有调色板可以通过位图文件头的 ...

  4. BitMap 图片格式与Base64Image格式互转方法

    BitMap 图片格式与Base64Image格式互转方法 /// <summary> /// 图片转为base64编码的字符串 /// </summary> /// < ...

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

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

  6. android 通过uri获取bitmap图片并压缩

    很多人在调用图库选择图片时会在onActivityResult中用Media.getBitmap来获取返回的图片,如下: Uri mImageCaptureUri = data.getData(); ...

  7. android开发 两张bitmap图片合成一张图片

    场景:对android4.4解码gif(解码文章见前面一篇)后的图片进行每帧处理,android4.3 解码出来的每帧都很完整,但是到android4.4版本就不完整了,每帧都是在第一帧的基础上把被改 ...

  8. Android bitmap图片处理

    一.View转换为Bitmap         在Android中所有的控件都是View的直接子类或者间接子类,通过它们可以组成丰富的UI界面.在窗口显示的时候Android会把这些控件都加载到内存中 ...

  9. android中对Bitmap图片设置任意角为圆角

    http://blog.csdn.net/l448288137/article/details/48276681 最近项目开发中使用到了圆角图片,网上找到的圆角图片控件大多比较死板,只可以全圆角.其中 ...

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

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

随机推荐

  1. MM32F0140 UART1空闲中断接收

    目录: 1.MM32F0140简介 2.初始化MM32F0140 UART1空闲中断和NVIC中断 3.编写MM32F0140 UART1中断接收和空闲中断函数 4.编写MM32F0140 UART1 ...

  2. 解决github网站打不开的方法

    发现github最近经常抽风,之前发现打不开时就挂个梯子,最近梯子也都被封了,尝试了下改host发现效果挺好,方法如下(Mac电脑): 1.通过站长工具找出DNS地址:进入站长工具网站的域名解析网址: ...

  3. x86-7-页式管理(Paging)

    x86-7-页式管理(Paging) 页式管理是重中之重! 在段式管理下操作系统的运作出现了很多问题,因为段的长度不定,在分配内存时,可能会发生内存中的空闲区域小于要加载的段,或者空闲区域远远大于要加 ...

  4. Azure Container App(一)应用介绍

    一,引言 容器技术正日益成为打包.部署应用程序的第一选择.Azure 提供了许多使用容器的选项.例如,我们可以使用 Azure 容器注册表来存储和管理 Docker Images.Azure Cont ...

  5. MyBatis报错—Type handler was null on parameter mapping for property 'createTime'. It was either not specified and/or could not be found for the javaType (javax.xml.crypto.Data) : jdbcType (null) combina

    原因是:在创建实体类的时候吧date类型写成data导致类型不匹配 Type handler was null on parameter mapping for property 'createTim ...

  6. git中的文件操作

    现在我们的机器上有了一个 真实项目 的 Git 仓库,并从这个仓库中检出了所有文件的 工作副本. 通常,你会对这些文件做些修改,每当完成了一个阶段的目标,想要将记录下它时,就将它提交到仓库. git中 ...

  7. CentOS 7.5 安装配置tigervnc-server

    系统版本: [root@s10 ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) 1.安装 Gnome 包 [root@ ...

  8. python监控cpu 内存实现邮件微信报警

    # qianxiao996精心制作 #博客地址:https://blog.csdn.net/qq_36374896 import psutil, time,smtplib,socket import ...

  9. Java基础 (上)

    基础概念与常识 Java 语言有哪些特点? 简单易学: 面向对象(封装,继承,多态): 平台无关性( Java 虚拟机实现平台无关性): 支持多线程( C++ 语言没有内置的多线程机制,因此必须调用操 ...

  10. [WPF] 假装可变字体

    1. 可变字体 上图中的两个动画,一个文字直接变粗,一个渐渐变粗,我觉得后者会更有趣.但普通的字体可达不到这种效果,例如微软雅黑,无论怎么调整它的 FontWeight,实际上它也只有三种粗细: 这时 ...