在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
- public void getDrawingCache(final ImageView sourceImageView, final ImageView destImageView) {
-
- new Handler().postDelayed(new Runnable() {
-
- @Override
- public void run() {
-
-
- sourceImageView.setDrawingCacheEnabled(true);
-
- Bitmap mBitmap = sourceImageView.getDrawingCache();
-
- destImageView.setImageBitmap(mBitmap);
-
-
- new Handler().postDelayed(new Runnable() {
-
- @Override
- public void run() {
-
-
-
- destImageView.setImageResource(R.drawable.pet);
-
-
-
-
-
- sourceImageView.setDrawingCacheEnabled(false);
-
- sourceImageView.destroyDrawingCache();
- }
- }, DELAY_TIME);
- }
- }, DELAY_TIME);
- }
- mImageView1.setImageResource(R.drawable.android);
- mImageView2.setImageResource(R.drawable.pet);
- getDrawingCache(mImageView1, mImageView2);
運行效果以下:
![](http://static.javashuo.com/static/loading.gif)
Demo運行效果圖1
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
android
Demo運行效果圖2canvas
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代碼以下:緩存
- public Bitmap getRoundedBitmap() {
- Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.frame);
-
- Bitmap bgBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888);
-
- Canvas mCanvas = new Canvas(bgBitmap);
-
- Paint mPaint = new Paint();
- Rect mRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
- RectF mRectF = new RectF(mRect);
-
- float roundPx = 15;
- mPaint.setAntiAlias(true);
-
- mCanvas.drawRoundRect(mRectF, roundPx, roundPx, mPaint);
-
-
- mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
-
- mCanvas.drawBitmap(mBitmap, mRect, mRect, mPaint);
-
- return bgBitmap;
- }
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
圖片圓角處理框架
3、圖片灰化處理
在Android中能夠經過ColorMatrix類實現圖像處理軟件中的濾鏡效果,經過ColorMatrix類能夠對位圖中的每一個像素進行變換處理,達到特殊的濾鏡效果,下面經過一個例子來介紹如何經過ColorMatrix對圖像進行灰化處理,Java代碼以下:
- public Bitmap getGrayBitmap() {
- Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android);
- Bitmap mGrayBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888);
- Canvas mCanvas = new Canvas(mGrayBitmap);
- Paint mPaint = new Paint();
-
-
- ColorMatrix mColorMatrix = new ColorMatrix();
-
- mColorMatrix.setSaturation(0);
-
- ColorMatrixColorFilter mColorFilter = new ColorMatrixColorFilter(mColorMatrix);
-
- mPaint.setColorFilter(mColorFilter);
-
- mCanvas.drawBitmap(mBitmap, 0, 0, mPaint);
-
- return mGrayBitmap;
- }
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖片灰化處理ide
4、提取圖像Alpha位圖
Android中的ARGB_8888類型的位圖由Alpha(透明度)、Red(紅)、Green(綠)、Blue(藍)四部分組成,其中Alpha部分也就是常說的Alpha通道,它控制圖像的透明度。在Android中Bitmap類提供了extractAlpha()方法,能夠把位圖中的Alpha部分提取出來做爲一個新的位圖,而後與填充顏色後的Paint結合從新繪製一個新圖像。下面經過一個例子來講明Bitmap類的extractAlpha()方法的使用,Java代碼以下:
- public Bitmap getAlphaBitmap() {
- BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.enemy_infantry_ninja);
- Bitmap mBitmap = mBitmapDrawable.getBitmap();
-
-
-
-
- Bitmap mAlphaBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Config.ARGB_8888);
-
- Canvas mCanvas = new Canvas(mAlphaBitmap);
- Paint mPaint = new Paint();
-
- mPaint.setColor(Color.BLUE);
-
- Bitmap alphaBitmap = mBitmap.extractAlpha();
-
- mCanvas.drawBitmap(alphaBitmap, 0, 0, mPaint);
-
- return mAlphaBitmap;
- }
![](http://static.javashuo.com/static/loading.gif)
提取圖像Alpha位圖post
其中最後一幅圖片是把原圖片四個邊距縮小兩個dp,而後與Alpha位圖一塊兒繪製的結果,讀者能夠參考本章Demo中的getStrokeBitmap()方法。
5、圖像變換
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;
}
效果以下圖所示:spa
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖像縮放.net
2)圖片旋轉
使用Matrix類preRotate或者postRotate能夠對圖像進行旋轉操做,它只有一個參數表示旋轉的角度,下面使用preRotate對圖像順時針旋轉30度,Java代碼以下:
- public Bitmap getRotatedBitmap() {
- 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.preRotate(45);
- Bitmap mRotateBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
-
- return mRotateBitmap;
- }
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖片旋轉指針
3)圖像傾斜
使用Matrix類preSkew或者postSkew能夠對圖像進行傾斜操做,它的兩個參數分別爲x和y座標傾斜度,下面使用preSkew對圖像進行傾斜變換,Java代碼以下:
- public Bitmap getScrewBitmap() {
- 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.preSkew(1.0f, 0.15f);
- Bitmap mScrewBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, true);
-
- return mScrewBitmap;
- }
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖像傾斜
4)圖像倒影
爲圖像添加倒影效果以後,圖像看起來會有立體感,更有真實感,在Android中使用Matrix類能夠很容易實現圖像的倒影效果。主要是Matrix的preScale方法的使用,給它設置負數縮放比例,圖像就會進行反轉。而後經過設置Shader添加漸變效果。Java代碼以下:
- private Bitmap getReflectedBitmap() {
- 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(1, -1);
-
-
-
-
-
-
-
- Bitmap mInverseBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, matrix, false);
- Bitmap mReflectedBitmap = Bitmap.createBitmap(width, height*2, Config.ARGB_8888);
-
-
- Canvas mCanvas = new Canvas(mReflectedBitmap);
-
- mCanvas.drawBitmap(mBitmap, 0, 0, null);
- mCanvas.drawBitmap(mInverseBitmap, 0, height, null);
-
-
- Paint mPaint = new Paint();
- Shader mShader = new LinearGradient(0, height, 0, mReflectedBitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.MIRROR);
- mPaint.setShader(mShader);
-
- mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
-
- mCanvas.drawRect(0, height, width, mReflectedBitmap.getHeight(), mPaint);
-
- return mReflectedBitmap;
- }
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
圖像倒影
5)圖像剪切
若是隻須要圖像的一部分,就必須對圖像進行剪切處理,在原圖像上選擇一個剪切區域,使用PorterDuffXfermode圖像疊加規則,就能夠把指定的圖像區域剪切下來,下面經過三個步驟來講明若是對圖像進行剪切操做。
第一步,建立一個新位圖做爲畫板,而後把原圖像畫到新位圖上面,Java代碼以下:
- BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable(
- R.drawable.beauty);
- Bitmap bitmap = bd.getBitmap();
- int w = bitmap.getWidth();
- int h = bitmap.getHeight();
- Bitmap bm = Bitmap.createBitmap(w, h, Config.ARGB_8888);
- Canvas canvas = new Canvas(bm);
- Paint mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setStyle(Style.STROKE);
- canvas.drawBitmap(bitmap, 0, 0, mPaint);
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
第一步效果圖
第二步,繪製一個剪切區域,好比要剪切人物的臉部區域,須要在指定的位置繪製一個圓角矩形區域,代碼中的座標是在調試中得到,在其餘分辨率下會有所不一樣,Java代碼以下:
- int deltX = 76;
- int deltY = 98;
- DashPathEffect dashStyle = new DashPathEffect(new float[] { 10, 5, 5, 5 }, 2);
- RectF faceRect = new RectF(0, 0, 88, 106);
- float [] faceCornerii = new float[] {30,30,30,30,75,75,75,75};
- Paint mPaint = new Paint();
- mPaint.setColor(0xFF6F8DD5);
- mPaint.setStrokeWidth(6);
- mPaint.setPathEffect(dashStyle);
- Path clip = new Path();
- clip.reset();
- clip.addRoundRect(faceRect, faceCornerii, Direction.CW);
- canvas.save();
- canvas.translate(deltX, deltY);
- canvas.clipPath(clip, Region.Op.DIFFERENCE);
- canvas.drawColor(0xDF222222);
- canvas.drawPath(clip, mPaint);
- canvas.restore();
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
第二步效果
第三步,從原圖像上獲取指定區域的圖像,並繪製到屏幕上,java代碼以下:
- Rect srcRect = new Rect(0, 0, 88, 106);
- srcRect.offset(deltX, deltY);
- PaintFlagsDrawFilter dfd = new PaintFlagsDrawFilter(Paint.ANTI_ALIAS_FLAG,
- Paint.FILTER_BITMAP_FLAG);
- canvas.setDrawFilter(dfd);
- canvas.clipPath(clip);
- canvas.drawBitmap(bitmap, srcRect, faceRect, mPaint);
效果以下圖所示:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
第三部效果圖
6)圖像合成
若是要爲圖片添加水印,或者把幾張小圖片拼接成大圖片時,就須要利用圖像合成的方法,在前面實例代碼中已經使用了這種方法,就是建立新位圖做爲畫板,而後在對應的位置上繪製其餘圖像