最近學習了android中的圖片顏色的處理,現在來總結一下。android中存在三種方式來調整圖片的顏色,來達到不同的效果。分別是:利用色光三原色來調整圖片顏色,利用顏色矩陣來調整圖片顏色,利用調整每一個像素點來調整圖片顏色。顯然調整顏色的方式是越來越細致的。那么在這一篇文章中,就總結一下通過色光三原色來調整圖片的顏色。
一、基礎知識
首先說一下基礎的顏色知識。android中采取的顏色模型是RGBA模型。即R代表紅色,G代表綠色,B代表藍色,A代表透明度。而通過改變一張圖片的三原色的色相,飽和度,亮度就可以改變一張圖片的顏色。
所謂色相,就是指具體的顏色,比如說紅色,黃色等就是一種具體的顏色。而飽和度就是指顏色的純度,值從0%到100%。亮度就是指顏色相對的明暗程度。只要改變這三個值,就可以實現不同的顏色效果。
android中是通過ColorMatrix類來改變色光三原色的,從這個類就可以看出其實本質還是通過改變顏色矩陣來改變顏色的,只不過封裝的好。所以顏色矩陣實現不同的顏色是基本的原理,在下一篇的文章中會講到。下面就看一看要用到的方法,代碼如下:
1 //實例化處理色相的顏色矩陣 2 ColorMatrix hugeMatrix = new ColorMatrix(); 3 hugeMatrix.setRotate(0, huge);//0表示紅色 4 hugeMatrix.setRotate(1, huge);//1表示設置綠色 5 hugeMatrix.setRotate(2, huge);//2表示藍色 6 7 //實例化處理飽和度的矩陣 8 ColorMatrix satMatrix = new ColorMatrix(); 9 //查看該方法的源碼發現,只設置一個值方法內部就直接改變了每一個三原色的飽和度 10 satMatrix.setSaturation(saturation); 11 12 //實例化處理亮度的矩陣 13 ColorMatrix lumMatrix = new ColorMatrix(); 14 //參數從左到右依次為紅色亮度,綠色,藍色,透明度(1表示完全不透明) 15 lumMatrix.setScale(lum, lum, lum, 1);
上面的代碼注釋很明白了,需要說明的事huge,saturation,lum都是float類型的值,為0-255之間。有了這些基礎知識,我們就可以改變一張圖片的顏色了。
或許你還是很糊塗,雖然通過上面的代碼,你知道怎么設置色光三原色的色相,飽和度和亮度,但是你還不知道怎么將設置好的顏色替換掉已有圖片的顏色。那么就接着看下面的代碼,下面的代碼是一個實現圖片顏色變化的工具類,該工具類中的靜態方法實現了將一張圖片變換顏色效果。具體思路就是傳入一張圖片,由於android不允許在已有的bitmap上操作,所以我們要新建一個bitmap,然后用設置好的顏色來設置畫筆,接着用畫筆畫出一張和原來圖片一樣大小的bitmap,只是顏色變成了我們設置的顏色了而已,然后將該圖片返回。好了,我們來看這個工具類的具體代碼,注釋很詳細,你應該能看得懂。如下:
1 /* 2 * 用來處理圖片顏色的工具類 3 */ 4 public class ImageHelper { 5 6 /** 7 * 該方法根據色光三原色,改變圖片顏色 8 * @param bmp 原圖片 9 * @param huge 色相 10 * @param saturation 飽和度 11 * @param lum 亮度 12 * @return 13 */ 14 public static Bitmap ImageUtil(Bitmap bmp,float huge,float saturation,float lum){ 15 //注意,android不允許在原有的bitmap上操作,因此我們必須重畫一個btimap來保存我們所做的操作並返回 16 //第三個參數為制定顏色模式,通常會使用bitmap的最高處理方式 17 Bitmap btp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888); 18 19 Canvas canvas = new Canvas(btp);//實例化一塊畫布 20 Paint mPaint = new Paint();//實例化一支畫筆 21 mPaint.setStrokeWidth(Paint.ANTI_ALIAS_FLAG);//設置為抗鋸齒 22 23 //實例化處理色相的顏色矩陣 24 ColorMatrix hugeMatrix = new ColorMatrix(); 25 hugeMatrix.setRotate(0, huge);//0表示紅色 26 hugeMatrix.setRotate(1, huge);//1表示設置綠色 27 hugeMatrix.setRotate(2, huge);//2表示藍色 28 29 //實例化處理飽和度的矩陣 30 ColorMatrix satMatrix = new ColorMatrix(); 31 //查看該方法的源碼發現,只設置一個值方法內部就直接改變了每一個三原色的飽和度 32 satMatrix.setSaturation(saturation); 33 34 //實例化處理亮度的矩陣 35 ColorMatrix lumMatrix = new ColorMatrix(); 36 //參數從左到右依次為紅色亮度,綠色,藍色,透明度(1表示完全不透明) 37 lumMatrix.setScale(lum, lum, lum, 1); 38 39 //再實例化一個顏色矩陣將上面的顏色設定都柔和再一起 40 ColorMatrix imageMatrix = new ColorMatrix(); 41 imageMatrix.postConcat(hugeMatrix); 42 imageMatrix.postConcat(satMatrix); 43 imageMatrix.postConcat(lumMatrix); 44 45 //將調好的顏色設置給畫筆 46 mPaint.setColorFilter(new ColorMatrixColorFilter(imageMatrix)); 47 //然后我們用調整好的顏色畫筆將原來的圖片bmp畫到新的bitmap上 48 canvas.drawBitmap(bmp, 0, 0, mPaint); 49 50 return btp; 51 52 } 53 }
有了這個工具類,我們就可以真的為一張圖片來變化其顏色了。下面我們來實戰一下吧。
二、實戰演示圖片顏色變化
我們廢話少說,直接來寫代碼。新建項目”圖像處理“,首先編寫它的activity_main.xml。代碼很簡單,無非就是給按鈕注冊一個點擊事件。我就不解釋了,如下:
1 <RelativeLayout 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:gravity="center"> 6 7 <TextView 8 android:id="@+id/txt_img" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:text="圖像實驗" 12 android:textSize="30sp" 13 android:gravity="center" 14 android:background="#cc00ff"/> 15 <Button 16 android:id="@+id/bnt_imgcolor1" 17 android:layout_width="match_parent" 18 android:layout_height="wrap_content" 19 android:text="調整三原色" 20 android:textSize="30sp" 21 android:gravity="center" 22 android:layout_below="@id/txt_img" 23 android:onClick="preferenceClick" 24 /> 25 <Button 26 android:id="@+id/bnt_imgcolor2" 27 android:layout_width="match_parent" 28 android:layout_height="wrap_content" 29 android:text="調整顏色矩陣" 30 android:textSize="30sp" 31 android:gravity="center" 32 android:layout_below="@id/bnt_imgcolor1" 33 android:onClick="matrixClick" 34 /> 35 <Button 36 android:id="@+id/bnt_imgcolor3" 37 android:layout_width="match_parent" 38 android:layout_height="wrap_content" 39 android:text="調整色素" 40 android:textSize="30sp" 41 android:gravity="center" 42 android:layout_below="@id/bnt_imgcolor2" 43 android:onClick="pxClick" 44 /> 45 46 </RelativeLayout>
你會發現有三個按鈕,在這里,我們只實現第一個按鈕”調整三原色“。其他兩個按鈕的實現,也就是顏色矩陣和像素點改變圖片效果我們放在后面的兩篇文章中講解。
然后我們再新建一個color1.xml,是用來顯示圖片用的,在這里需要一張圖片,讀者可以自行設定為自己的圖片即可。代碼如下:
1 <RelativeLayout 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 > 6 <ImageView 7 android:id="@+id/img" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:src="@drawable/test1"> 11 </ImageView> 12 <SeekBar 13 android:id="@+id/sbr_huge" 14 android:layout_width="match_parent" 15 android:layout_height="wrap_content" 16 android:layout_below="@id/img"/> 17 <SeekBar 18 android:id="@+id/sbr_sat" 19 android:layout_width="match_parent" 20 android:layout_height="wrap_content" 21 android:layout_marginTop="30dp" 22 android:layout_below="@id/sbr_huge"/> 23 <SeekBar 24 android:id="@+id/sbr_lum" 25 android:layout_width="match_parent" 26 android:layout_height="wrap_content" 27 android:layout_marginTop="30dp" 28 android:layout_below="@id/sbr_sat"/> 29 30 31 </RelativeLayout>
好了,然后我們再新建一個活動”ColorAdjustActivity“,用來將這個布局顯示出來,注意不要忘記注冊這個活動哦!代碼如下:
1 package com.fuly.image; 2 3 import android.app.Activity; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.os.Bundle; 7 import android.widget.ImageView; 8 import android.widget.SeekBar; 9 10 public class ColorAdjustActivity extends Activity implements SeekBar.OnSeekBarChangeListener{ 11 12 private ImageView img; 13 private SeekBar sbrHuge; 14 private SeekBar sbrSat; 15 private SeekBar sbrLum; 16 17 private static final int MAX_VALUE = 255; 18 private static final int MIDDLE_VALUE = 127; 19 20 private float huge;//色相 21 private float sat;//飽和度 22 private float lum;//亮度 23 24 private Bitmap priBmp;//原始圖片 25 26 27 protected void onCreate(Bundle savedInstanceState) { 28 super.onCreate(savedInstanceState); 29 setContentView(R.layout.color1); 30 31 img = (ImageView) findViewById(R.id.img); 32 sbrHuge = (SeekBar) findViewById(R.id.sbr_huge); 33 sbrSat = (SeekBar) findViewById(R.id.sbr_sat); 34 sbrLum = (SeekBar) findViewById(R.id.sbr_lum); 35 36 priBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test1); 37 38 //注冊監聽器 39 sbrHuge.setOnSeekBarChangeListener(this); 40 sbrSat.setOnSeekBarChangeListener(this); 41 sbrLum.setOnSeekBarChangeListener(this); 42 43 sbrHuge.setMax(MAX_VALUE);//設定最大范圍 44 sbrSat.setMax(MAX_VALUE); 45 sbrLum.setMax(MAX_VALUE); 46 47 sbrHuge.setProgress(MIDDLE_VALUE);//設定初始停留位置 48 sbrSat.setProgress(MIDDLE_VALUE);//設定初始停留位置 49 sbrLum.setProgress(MIDDLE_VALUE);//設定初始停留位置 50 } 51 52 53 54 /** 55 * 在該方法中我們監聽每一個seekBar的狀態改變 56 * @param seekBar 我們點擊的seekBar控件 57 * @param progress 當前點擊位置的值 58 * @param fromUser 59 */ 60 public void onProgressChanged(SeekBar seekBar, int progress, 61 boolean fromUser) { 62 63 switch(seekBar.getId()){ 64 65 case R.id.sbr_huge: 66 //獲得色相的計算公式 67 huge = (progress - MIDDLE_VALUE) * 1.0F / MIDDLE_VALUE * 180; 68 break; 69 case R.id.sbr_sat: 70 //獲得飽和度的計算公式 71 sat = progress*1.0f/MIDDLE_VALUE; 72 break; 73 case R.id.sbr_lum: 74 //獲得亮度的計算公式 75 lum = progress*1.0f/MIDDLE_VALUE; 76 break; 77 } 78 Bitmap bt = ImageHelper.ImageUtil(priBmp, huge, sat, lum); 79 80 img.setImageBitmap(bt);//注意這一步,就實現了圖片效果的改變 81 } 82 83 84 85 /** 86 * 該方法在用戶剛剛點擊seeBar時被調用,一般在這里可以禁止用戶對 87 * seeBar的操作 88 */ 89 public void onStartTrackingTouch(SeekBar seekBar) { 90 91 92 } 93 94 95 96 /** 97 * 該方法在用戶完成seeBar的操作時會被調用,一般來說,如果用戶禁用了seekBar, 98 * 則可能會在這個方法里重新啟用seekBar 99 * 100 */ 101 public void onStopTrackingTouch(SeekBar seekBar) { 102 103 104 } 105 106 }
上面的代碼注釋很清晰了,我就不多解釋了。發現了沒有,在78行,我們調用了處理圖片顏色的工具類。所以我們要把這個工具類編寫出來,其實就是上面基礎知識的那個工具類。新建類”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 }
代碼就不用我多解釋了吧。最后別忘記在MainActivity中實現活動的跳轉,即點擊”調整三原色“按鈕,跳到圖片顯示界面。代碼如下:
1 package com.fuly.image; 2 3 import android.os.Bundle; 4 import android.view.View; 5 import android.app.Activity; 6 import android.content.Intent; 7 8 public class MainActivity extends Activity { 9 10 11 12 protected void onCreate(Bundle savedInstanceState) { 13 super.onCreate(savedInstanceState); 14 setContentView(R.layout.activity_main); 15 } 16 17 /* 18 * btn1的點擊事件 19 */ 20 public void preferenceClick(View view){ 21 22 Intent intent = new Intent(this,ColorAdjustActivity.class); 23 startActivity(intent); 24 25 26 }
好了,一切代碼都完成了。我們趕緊運行,看看效果吧。左邊為原圖,右邊為滑動seekBar時調整的效果。
滑動seekBar可以有不同的效果。如果你覺得還不過癮,沒關系。可以看我的下一篇文章《利用顏色矩陣實現圖片效果》。但是請注意,在本篇實戰中的代碼要保存,因為在下一節中,我們仍舊要在這個基礎上寫代碼。
對了,還需要總結一下,在設置色相,飽和度和亮度時,我們用到了三個公式,即下面的代碼:
//獲得色相的計算公式 huge = (progress - MIDDLE_VALUE) * 1.0F / MIDDLE_VALUE * 180; //獲得飽和度的計算公式 sat = progress*1.0f/MIDDLE_VALUE; //獲得亮度的計算公式 um = progress*1.0f/MIDDLE_VALUE;
其中progress是一個float的數值(0~255),MIDDLE_VALUE的值是127。這三個公式希望能記住,這是前輩們根據經驗得到的。