Android bitmap圖片處理

1、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

 

[java]  view plain copy
 
 
  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.     }  

[java]  view plain copy
 
 
  1. mImageView1.setImageResource(R.drawable.android);  
  2.         mImageView2.setImageResource(R.drawable.pet);  
  3.         getDrawingCache(mImageView1, mImageView2);  

運行效果以下:

 

Demo運行效果圖1



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代碼以下:緩存

 

[java]  view plain copy
 
 
  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. }  

效果以下圖所示:

 

 

 

圖片圓角處理框架



3、圖片灰化處理

        在Android中能夠經過ColorMatrix類實現圖像處理軟件中的濾鏡效果,經過ColorMatrix類能夠對位圖中的每一個像素進行變換處理,達到特殊的濾鏡效果,下面經過一個例子來介紹如何經過ColorMatrix對圖像進行灰化處理,Java代碼以下:

 

[java]  view plain copy
 
 
  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.     }  

 效果以下圖所示:

 

 

圖片灰化處理ide



4、提取圖像Alpha位圖

        Android中的ARGB_8888類型的位圖由Alpha(透明度)、Red(紅)、Green(綠)、Blue(藍)四部分組成,其中Alpha部分也就是常說的Alpha通道,它控制圖像的透明度。在Android中Bitmap類提供了extractAlpha()方法,能夠把位圖中的Alpha部分提取出來做爲一個新的位圖,而後與填充顏色後的Paint結合從新繪製一個新圖像。下面經過一個例子來講明Bitmap類的extractAlpha()方法的使用,Java代碼以下:

 

[java]  view plain copy
 
 
  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位圖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

 

 


圖像縮放.net

2)圖片旋轉

        使用Matrix類preRotate或者postRotate能夠對圖像進行旋轉操做,它只有一個參數表示旋轉的角度,下面使用preRotate對圖像順時針旋轉30度,Java代碼以下:

 

[java]  view plain copy
 
 
  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代碼以下:

 

[java]  view plain copy
 
 
  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代碼以下:

 

[java]  view plain copy
 
 
  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代碼以下:
[java]  view plain copy
 
 
  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 plain copy
 
 
  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 plain copy
 
 
  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)圖像合成

        若是要爲圖片添加水印,或者把幾張小圖片拼接成大圖片時,就須要利用圖像合成的方法,在前面實例代碼中已經使用了這種方法,就是建立新位圖做爲畫板,而後在對應的位置上繪製其餘圖像

相關文章
相關標籤/搜索