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图片的处理的更多相关文章
- Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据
Android中如何将Bitmap byte裸数据转换成Bitmap图片int数据 2014-06-11 10:45:14 阅读375次 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何 ...
- Android—将Bitmap图片保存到SD卡目录下或者指定目录
直接上代码就不废话啦 一:保存到SD卡下 File file = new File(Environment.getExternalStorageDirectory(), System.currentT ...
- Bitmap 图片格式并用 C++ 读写 Bitmap
转自 Bitmap 图片格式并用 C++ 读写 Bitmap 1.Bitmap 图片格式 每部分的具体内容就不展开了.要说的有两点: (1)调色板不是必须的,可有可无,有没有调色板可以通过位图文件头的 ...
- BitMap 图片格式与Base64Image格式互转方法
BitMap 图片格式与Base64Image格式互转方法 /// <summary> /// 图片转为base64编码的字符串 /// </summary> /// < ...
- Android开发之常用必备工具类图片bitmap转成字符串string与String字符串转换为bitmap图片格式
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- android 通过uri获取bitmap图片并压缩
很多人在调用图库选择图片时会在onActivityResult中用Media.getBitmap来获取返回的图片,如下: Uri mImageCaptureUri = data.getData(); ...
- android开发 两张bitmap图片合成一张图片
场景:对android4.4解码gif(解码文章见前面一篇)后的图片进行每帧处理,android4.3 解码出来的每帧都很完整,但是到android4.4版本就不完整了,每帧都是在第一帧的基础上把被改 ...
- Android bitmap图片处理
一.View转换为Bitmap 在Android中所有的控件都是View的直接子类或者间接子类,通过它们可以组成丰富的UI界面.在窗口显示的时候Android会把这些控件都加载到内存中 ...
- android中对Bitmap图片设置任意角为圆角
http://blog.csdn.net/l448288137/article/details/48276681 最近项目开发中使用到了圆角图片,网上找到的圆角图片控件大多比较死板,只可以全圆角.其中 ...
- Android性能优化系列之Bitmap图片优化
https://blog.csdn.net/u012124438/article/details/66087785 在Android开发过程中,Bitmap往往会给开发者带来一些困扰,因为对Bitma ...
随机推荐
- DFT/FFT/NTT
在Seal库和HElib库中都用到了NTT技术,用于加快多项式计算,而NTT又是FFT的优化,FFT又来自于DFT,现在具体学习一下这三个技术! 基础概念 名词区分 1.DFT:离散傅立叶变换 2.F ...
- SQL从零到迅速精通【表连接查询】
看了这些表连接,个人感觉'左外连接'.'右外连接'和'全外连接'应用好就可以了. 1.外连接 (1)LEFT JOIN(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录. 在student ...
- mysql常用索引
1.索引 在关系数据库中,索引是一种单独的.物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单.索引的作用相当 ...
- Dapr集成之GRPC 接口
Dapr 为本地调用实现 HTTP 和 gRPC API . 通常大家第一时间想到的是通过 gRPC 调用 Dapr,更重要的一点是Dapr 也可以通过 gRPC 与应用程序通信. 要做到这一点,原理 ...
- QQ聊天记录快速迁移
QQ聊天记录快速迁移 在工作中大家经常会用到QQ来沟通,但是很多时候在其它设备上登录QQ就无法查看到之前的聊天记录和图片,这是因为电脑上的QQ聊天记录一般都是保存在电脑本地硬盘里,所以我们在换设备登录 ...
- 当.Net撞上BI可视化,这3种“套路”你必须知道
最近葡萄在做技术支持,又遇到了客户给我们出的新问题. 事情是这样的. 这次客户使用的是.Net项目,直接做BI大屏过于复杂,所以想直接集成使用BI数据可视化分析大屏. 所以,这次我们就从--Wyn出发 ...
- LGP7167题解
考试的一道题,因为某些原因sb了常数翻了好几倍/px 首先我们发现,一个水池的水只会向它下边第一个直径比它大的水池流. 我们把这些流动的关系连边,很容易发现是一棵树. 问水最后会到哪个水池相当于在问最 ...
- dedecms 5.7 任意前台用户修改漏洞
一. 启动环境 1.双击运行桌面phpstudy.exe软件 2.点击启动按钮,启动服务器环境 二.代码审计 1.双击启动桌面Seay源代码审计系统软件 2.点击新建项目按钮,弹出对画框中选择(C:\ ...
- 《前端运维》二、Nginx--3静态资源服务、跨域与其他
一.静态资源服务 首先,静态资源一般是指客户端发送请求到Web服务器,web服务器从内存中取得相应的文件,返回给客户端,客户端解析并渲染出来.动态资源呢,则是由客户端发起请求,先交由web容器,web ...
- 为什么要从Web form过渡到MVC中
可以说,在未来几年中,Web form的使用会逐渐减少,而取而代之的就是MVC.可能你不会同意我的观点,那么我就试着阐述一下我的观点,如果你还是不能接受,那么请你反驳我. 学习一个新语言或者是新架构是 ...