Bitmap图片的处理

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

效果如下图所示:

第三部效果图

时间: 2024-10-14 22:18:43

Bitmap图片的处理的相关文章

从本地或者网络读取图片,并转换为Bitmap图片

在做android项目时,我们经常需要从本地或者网络读取图片,并转换为Bitmap图片,以便使用,下面是读取本地图片并转换的方法: Java代码   /** * 得到本地或者网络上的bitmap url - 网络或者本地图片的绝对路径,比如: * * A.网络路径: url="http://blog.foreverlove.us/girl2.png" ; * * B.本地路径:url="file://mnt/sdcard/photo/image.png"; * * 

如何在ListView 里面加载Bitmap图片?

写了一个Application类,里面都是Bitmap图片,还有一些文字,文字可以直接在ListView里显示,但是图片需要怎么显示呢? private Mycuncu app;  app = (Mycuncu) getApplication(); for (int i = 0;i<app.getBmpSize();i++){ Map<String,Object> map = new HashMap<String,Object>(); map.put("Vendin

Android中bitmap图片透明度的处理(以撕美女衣服为例)

原理介绍:将两种不同效果的图片放在相同的位置,改变上面的图片的透明度,就能实现了. 布局文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_h

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

直接上代码就不废话啦 一:保存到SD卡下 [java] view plain copy File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis()+".jpg"); try { out = new FileOutputStream(file); btImage.compress(Bitmap.CompressFormat.JPEG, 90, out); System

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

在Android开发过程中,Bitmap往往会给开发者带来一些困扰,因为对Bitmap操作不慎,就容易造成OOM(Java.lang.OutofMemoryError - 内存溢出),本篇博客,我们将一起探讨Bitmap的性能优化. 为什么Bitmap会导致OOM? 1.每个机型在编译ROM时都设置了一个应用堆内存VM值上限dalvik.vm.heapgrowthlimit,用来限定每个应用可用的最大内存,超出这个最大值将会报OOM.这个阀值,一般根据手机屏幕dpi大小递增,dpi越小的手机,每

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

2014-06-11 10:45:14   阅读375次 我们在JNI中处理得到的BMP图片Raw数据,我们应该如何转换为Bitmap呢? 由于得到的数据是unsigned char *类型的数据,而对于Bitmap的类来说,其类方法里面: 1 2 public static Bitmap createBitmap(int colors[], int offset, int stride,             int width, int height, Config config) 要求传

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

场景:对android4.4解码gif(解码文章见前面一篇)后的图片进行每帧处理,android4.3 解码出来的每帧都很完整,但是到android4.4版本就不完整了,每帧都是在第一帧的基础上把被改变的显示出来了,所以需要再次合成每帧 如图效果: 合成后: 代码直接看: /** * 将2张图片合成 * @param downBitmap 底部图片 * @param upBitmap 置顶的图片 * @return */ public static Bitmap compoundBitmap(B

Android bitmap图片处理

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

【Android实战】Bitmap图片的截屏、模糊处理、传递、使用

项目中遇到了这样一个需求: 当某个条件满足时就截取当前屏幕.并跳转到另外一个页面,同一时候将这个截屏图片作为下一个页面的背景图片,同一时候背景图片须要模糊处理 接下来就一步一步解决这个问题: 1.截取无状态栏的当前屏幕图片.请參考takeScreenShot方法 2.使图片高斯模糊的方法请參考blurBitmap方法 注意:RenderScript是Android在API 11之后增加的,用于高效的图片处理,包含模糊.混合.矩阵卷积计算等 public class ScreenShotUtil