在上一篇文章中,咱們學習了經過顏色矩陣的變換來實現圖片不一樣顏色效果。沒讀過的朋友能夠點擊下面的連接:html
http://www.cnblogs.com/fuly550871915/p/4883681.htmlandroid
在本篇中,咱們將實現更加好玩的效果,好比老照片效果,浮雕效果等。canvas
1、基礎知識數組
其實每一張圖片的一個像素點就是一個顏色值,它包含四個份量,分別是:紅,綠,藍,透明度。試想若是咱們可以遍歷一張圖片的每個像素點,而後提取出這四個份量,作相應的計算操做,而後再返回,是否是就實現顏色的改變。沒錯,經過像素點來改變顏色就是這個原理。app
好比咱們常見的底片的效果,它是遍歷圖片全部的像素點後,對每個像素點(好比B點)作了下面的計算的:工具
那麼你可能會問,這個公式是怎麼獲得呢?這是研究圖像處理的專家給出的,只要這樣子處理像素點,就會獲得一個底片效果。咱們沒必要管這個。也就是說只要咱們知道公式,就能夠實現不一樣的有意思的效果。順便再說兩種效果的公式吧。佈局
老照片的效果計算公式:post
浮雕效果(注意是前一個像素減去後一個像素再加上127,再賦給前一個):學習
好了,就介紹這幾種效果吧。你或許還有疑問,怎麼遍歷像素點,並取出份量呢?其實Bitmp類和Colro類已經給咱們提供了這樣子的方法。咱們看下面的設置底片效果的方法,註釋寫的很詳細,你想知道的都在註釋中。以下:this
1 /** 2 * 將圖片轉換爲負片 3 * @param bitmap 原來圖片 4 * @return 新圖片 5 */ 6 public static Bitmap ImgaeToNegative(Bitmap bitmap){ 7 //其實咱們得到寬和高就是圖片像素的寬和高 8 //它們的乘積就是總共一張圖片擁有的像素點數 9 int width = bitmap.getWidth(); 10 int height = bitmap.getHeight(); 11 12 Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 13 14 int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組 15 int[] newPx = new int[width*height];//用來存儲新的像素點的數組 16 int color;//用來存儲原來顏色值 17 int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度 18 19 //該方法用來將圖片的像素寫入到oldPx中,咱們這樣子設置,就會獲取所有的像素點 20 //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0 21 //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標 22 //第五個參數表示讀取的長度,第六個表示讀取的高度 23 bitmap.getPixels(oldPx, 0, width, 0, 0, width, height); 24 //下面用循環來處理每個像素點 25 for(int i =0;i<width*height;i++){ 26 27 color = oldPx[i];//獲取一個原來的像素點 28 r = Color.red(color);//獲取紅色份量,下同 29 g = Color.green(color); 30 b = Color.blue(color); 31 a = Color.alpha(color); 32 33 //下面計算生成新的顏色份量 34 r = 255 -r; 35 g = 255 - g; 36 b = 255 - b; 37 38 //下面主要保證r g b 的值都必須在0~255以內 39 if(r>255){ 40 r = 255; 41 }else if(r<0){ 42 r = 0; 43 } 44 if(g>255){ 45 g = 255; 46 }else if(g<0){ 47 g = 0; 48 } 49 if(b>255){ 50 b = 255; 51 }else if(b<0){ 52 b = 0; 53 } 54 55 //下面合成新的像素點,並添加到newPx中 56 color = Color.argb(a, r, g, b); 57 newPx[i] = color; 58 } 59 60 //而後重要的一步,爲bmp設置新顏色了,該方法中的參數意義與getPixels中的同樣 61 //無非是將newPx寫入到bmp中 62 bmp.setPixels(newPx, 0, width, 0, 0, width, height); 63 return bmp; 64 }
從上面的代碼中,你學會了如何遍歷一個圖片的像素點以及如何取出顏色份量和合成新的顏色。其餘的將圖片變爲老照片和浮雕,都是相似的方法。就很少講了。那麼咱們能夠直接進入實戰了。
2、實戰
好了,咱們仍舊在上一篇文章的基礎上寫代碼,下面實現第三個按鈕」調整色素「。首先編寫color.3xml,用來顯示調整後的圖片,以下:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 <LinearLayout 8 android:layout_width="match_parent" 9 android:layout_height="0dp" 10 android:layout_weight="1" 11 android:orientation="horizontal"> 12 <ImageView 13 android:id="@+id/img1" 14 android:layout_width="0dp" 15 android:layout_height="match_parent" 16 android:layout_weight="1"/> 17 <ImageView 18 android:id="@+id/img2" 19 android:layout_width="0dp" 20 android:layout_height="match_parent" 21 android:layout_weight="1"/> 22 23 </LinearLayout> 24 25 <LinearLayout 26 android:layout_width="match_parent" 27 android:layout_height="0dp" 28 android:layout_weight="1" 29 android:orientation="horizontal"> 30 <ImageView 31 android:id="@+id/img3" 32 android:layout_width="0dp" 33 android:layout_height="match_parent" 34 android:layout_weight="1"/> 35 <ImageView 36 android:id="@+id/img4" 37 android:layout_width="0dp" 38 android:layout_height="match_parent" 39 android:layout_weight="1"/> 40 41 42 </LinearLayout> 43 44 45 46 47 </LinearLayout>
在這個佈局中,咱們放置了四個ImageView,用來顯示原圖,底片,老照片以及浮雕效果。
而後要擴充咱們的ImageHelper工具類了,將底片,老照片和浮雕實現的方法添加進去。代碼以下,註釋很詳細,建議仔細研讀。
1 package com.fuly.image; 2 3 import android.graphics.Bitmap; 4 import android.graphics.Canvas; 5 import android.graphics.Color; 6 import android.graphics.ColorMatrix; 7 import android.graphics.ColorMatrixColorFilter; 8 import android.graphics.Paint; 9 10 /* 11 * 用來處理圖片顏色的工具類 12 */ 13 public class ImageHelper { 14 15 /** 16 * 該方法根據色光三原色,改變圖片顏色 17 * @param bmp 原圖片 18 * @param huge 色相 19 * @param saturation 飽和度 20 * @param lum 亮度 21 * @return 22 */ 23 public static Bitmap ImageUtil(Bitmap bmp,float huge,float saturation,float lum){ 24 //注意,android不容許在原有的bitmap上操做,所以咱們必須重畫一個btimap來保存咱們所作的操做並返回 25 //第三個參數爲制定顏色模式,一般會使用bitmap的最高處理方式 26 Bitmap btp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888); 27 28 Canvas canvas = new Canvas(btp);//實例化一塊畫布 29 Paint mPaint = new Paint();//實例化一支畫筆 30 mPaint.setStrokeWidth(Paint.ANTI_ALIAS_FLAG);//設置爲抗鋸齒 31 32 //實例化處理色相的顏色矩陣 33 ColorMatrix hugeMatrix = new ColorMatrix(); 34 hugeMatrix.setRotate(0, huge);//0表示紅色 35 hugeMatrix.setRotate(1, huge);//1表示設置綠色 36 hugeMatrix.setRotate(2, huge);//2表示藍色 37 38 //實例化處理飽和度的矩陣 39 ColorMatrix satMatrix = new ColorMatrix(); 40 //查看該方法的源碼發現,只設置一個值方法內部就直接改變了每個三原色的飽和度 41 satMatrix.setSaturation(saturation); 42 43 //實例化處理亮度的矩陣 44 ColorMatrix lumMatrix = new ColorMatrix(); 45 //參數從左到右依次爲紅色亮度,綠色,藍色,透明度(1表示徹底不透明) 46 lumMatrix.setScale(lum, lum, lum, 1); 47 48 //再實例化一個顏色矩陣將上面的顏色設定都柔和再一塊兒 49 ColorMatrix imageMatrix = new ColorMatrix(); 50 imageMatrix.postConcat(hugeMatrix); 51 imageMatrix.postConcat(satMatrix); 52 imageMatrix.postConcat(lumMatrix); 53 54 //將調好的顏色設置給畫筆 55 mPaint.setColorFilter(new ColorMatrixColorFilter(imageMatrix)); 56 //而後咱們用調整好的顏色畫筆將原來的圖片bmp畫到新的bitmap上 57 canvas.drawBitmap(bmp, 0, 0, mPaint); 58 59 return btp; 60 61 } 62 /** 63 * 將圖片轉換爲負片 64 * @param bitmap 原來圖片 65 * @return 新圖片 66 */ 67 public static Bitmap ImgaeToNegative(Bitmap bitmap){ 68 //其實咱們得到寬和高就是圖片像素的寬和高 69 //它們的乘積就是總共一張圖片擁有的像素點數 70 int width = bitmap.getWidth(); 71 int height = bitmap.getHeight(); 72 73 Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 74 75 int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組 76 int[] newPx = new int[width*height];//用來存儲新的像素點的數組 77 int color;//用來存儲原來顏色值 78 int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度 79 80 //該方法用來將圖片的像素寫入到oldPx中,咱們這樣子設置,就會獲取所有的像素點 81 //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0 82 //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標 83 //第五個參數表示讀取的長度,第六個表示讀取的高度 84 bitmap.getPixels(oldPx, 0, width, 0, 0, width, height); 85 //下面用循環來處理每個像素點 86 for(int i =0;i<width*height;i++){ 87 88 color = oldPx[i];//獲取一個原來的像素點 89 r = Color.red(color);//獲取紅色份量,下同 90 g = Color.green(color); 91 b = Color.blue(color); 92 a = Color.alpha(color); 93 94 //下面計算生成新的顏色份量 95 r = 255 -r; 96 g = 255 - g; 97 b = 255 - b; 98 99 //下面主要保證r g b 的值都必須在0~255以內 100 if(r>255){ 101 r = 255; 102 }else if(r<0){ 103 r = 0; 104 } 105 if(g>255){ 106 g = 255; 107 }else if(g<0){ 108 g = 0; 109 } 110 if(b>255){ 111 b = 255; 112 }else if(b<0){ 113 b = 0; 114 } 115 116 //下面合成新的像素點,並添加到newPx中 117 color = Color.argb(a, r, g, b); 118 newPx[i] = color; 119 } 120 121 //而後重要的一步,爲bmp設置新顏色了,該方法中的參數意義與getPixels中的同樣 122 //無非是將newPx寫入到bmp中 123 bmp.setPixels(newPx, 0, width, 0, 0, width, height); 124 return bmp; 125 } 126 /** 127 * 將圖片變成老照片 128 * @param bitmap 原來的圖片 129 * @return 新圖片(即老照片) 130 */ 131 public static Bitmap ImgaeToOld(Bitmap bitmap){ 132 133 int width = bitmap.getWidth(); 134 int height = bitmap.getHeight(); 135 136 Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 137 138 int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組 139 int[] newPx = new int[width*height];//用來存儲新的像素點的數組 140 int color;//用來存儲原來顏色值 141 int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度 142 143 //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0 144 //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標 145 //第五個參數表示讀取的長度,第六個表示讀取的高度 146 bitmap.getPixels(oldPx, 0, width, 0, 0, width, height); 147 148 for(int i =0;i<width*height;i++){ 149 150 color = oldPx[i];//獲取一個原來的像素點 151 r = Color.red(color);//獲取紅色份量,下同 152 g = Color.green(color); 153 b = Color.blue(color); 154 a = Color.alpha(color); 155 156 //下面計算生成新的顏色份量 157 r = (int)(0.393*r+0.769*g+0.189*b); 158 g = (int)(0.349*r+0.686*g+0.168*b); 159 b = (int)(0.272*r+0.534*g+0.131*b); 160 161 //下面主要保證r g b 的值都必須在0~255以內 162 if(r>255){ 163 r = 255; 164 }else if(r<0){ 165 r = 0; 166 } 167 if(g>255){ 168 g = 255; 169 }else if(g<0){ 170 g = 0; 171 } 172 if(b>255){ 173 b = 255; 174 }else if(b<0){ 175 b = 0; 176 } 177 178 //下面合成新的像素點,並添加到newPx中 179 color = Color.argb(a, r, g, b); 180 newPx[i] = color; 181 } 182 183 //而後重要的一步,爲bmp設置新顏色了 184 bmp.setPixels(newPx, 0, width, 0, 0, width, height); 185 return bmp; 186 } 187 /** 188 * 將圖片變成浮雕 189 * @param bitmap 舊照片 190 * @return 新照片 191 */ 192 public static Bitmap ImgaeToRelief(Bitmap bitmap){ 193 194 int width = bitmap.getWidth(); 195 int height = bitmap.getHeight(); 196 197 Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 198 199 int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組 200 int[] newPx = new int[width*height];//用來存儲新的像素點的數組 201 int color;//用來存儲前一個顏色值 202 int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度 203 int color1;//用來存儲後一個顏色值 204 int r1,g1,b1,a1; 205 206 //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0 207 //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標 208 //第五個參數表示讀取的長度,第六個表示讀取的高度 209 bitmap.getPixels(oldPx, 0, width, 0, 0, width, height); 210 //注意是從1開始循環 211 for(int i =1;i<width*height;i++){ 212 213 color = oldPx[i-1];//獲取前一個像素點 214 r = Color.red(color);//獲取紅色份量,下同 215 g = Color.green(color); 216 b = Color.blue(color); 217 a = Color.alpha(color); 218 219 color1 = oldPx[i];//獲取後一個像素點 220 r1 = Color.red(color1);//獲取紅色份量,下同 221 g1 = Color.green(color1); 222 b1 = Color.blue(color1); 223 a1 = Color.alpha(color1); 224 225 //下面計算生成新的顏色份量,注意浮雕是前一個像素減去後一個像素再加上127,賦給前一個 226 r = r - r1 + 127; 227 g = g - g1 + 127; 228 b = b - b1 +127; 229 230 //下面主要保證r g b 的值都必須在0~255以內 231 if(r>255){ 232 r = 255; 233 }else if(r<0){ 234 r = 0; 235 } 236 if(g>255){ 237 g = 255; 238 }else if(g<0){ 239 g = 0; 240 } 241 if(b>255){ 242 b = 255; 243 }else if(b<0){ 244 b = 0; 245 } 246 247 //下面合成新的像素點,並添加到newPx中 248 color = Color.argb(a, r, g, b); 249 newPx[i] = color; 250 } 251 252 //而後重要的一步,爲bmp設置新顏色了 253 bmp.setPixels(newPx, 0, width, 0, 0, width, height); 254 return bmp; 255 } 256 257 }
好了,咱們全部的工具方法都有了,下面就編寫」PxActivity「用來顯示這些效果吧。代碼以下:
1 package com.fuly.image; 2 3 import android.app.Activity; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.graphics.drawable.BitmapDrawable; 7 import android.os.Bundle; 8 import android.widget.ImageView; 9 10 public class PxActivity extends Activity{ 11 12 private ImageView img1; 13 private ImageView img2; 14 private ImageView img3; 15 private ImageView img4; 16 17 protected void onCreate(Bundle savedInstanceState) { 18 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.color3); 21 img1 = (ImageView) findViewById(R.id.img1); 22 img2 = (ImageView) findViewById(R.id.img2); 23 img3 = (ImageView) findViewById(R.id.img3); 24 img4 = (ImageView) findViewById(R.id.img4); 25 26 Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.test2); 27 28 29 img1.setImageBitmap(bmp); 30 img2.setImageBitmap(ImageHelper.ImgaeToNegative(bmp)); 31 img3.setImageBitmap(ImageHelper.ImgaeToOld(bmp)); 32 img4.setImageBitmap(ImageHelper.ImgaeToRelief(bmp)); 33 } 34 35 }
代碼很簡單,無非就是調用咱們的工具類設置圖片而已。下面別忘記給這個活動註冊,而後給MainActivity中的按鈕註冊監聽,代碼以下:
1 package com.fuly.image; 2 3 import android.os.Bundle; 4 import android.view.View; 5 import android.widget.Button; 6 import android.app.Activity; 7 import android.content.Intent; 8 9 public class MainActivity extends Activity { 10 11 private Button btn1; 12 13 14 protected void onCreate(Bundle savedInstanceState) { 15 super.onCreate(savedInstanceState); 16 setContentView(R.layout.activity_main); 17 18 btn1 = (Button) findViewById(R.id.bnt_imgcolor1); 19 20 } 21 22 /* 23 * btn1的點擊事件 24 */ 25 public void preferenceClick(View view){ 26 27 Intent intent = new Intent(this,ColorAdjustActivity.class); 28 startActivity(intent); 29 30 31 } 32 /* 33 * btn2的點擊事件 34 */ 35 public void matrixClick(View view){ 36 37 Intent intent = new Intent(this,ColorMatrixActivity.class); 38 startActivity(intent); 39 40 } 41 /* 42 * btn3的點擊事件 43 */ 44 public void pxClick(View view){ 45 46 Intent intent = new Intent(this,PxActivity.class); 47 startActivity(intent); 48 49 } 50 51 52 }
好了,全部代碼都完成了,運行程序,點擊」調整色素「按鈕,效果圖以下:
其實這個三個按鈕均可以用了,咱們能夠爲所欲爲的實驗,看看效果了。至此,android中的圖像顏色處理就完結了,但願學習的的都能掌握。共同窗習,一塊兒進步!!