在上一篇文章中,我們學習利用色光三原色調整圖片顏色的方法。這一篇文章的代碼將在上一篇的基礎上繼續書寫。如果你還沒讀過,可以點擊下面的鏈接:
http://www.cnblogs.com/fuly550871915/p/4883422.html
在本篇中,我們繼續學習圖片顏色的變換方法,利用顏色矩陣將更加細致的調整圖片顏色。其實顏色矩陣變換是圖片顏色變化的基礎原理。在下面我們將詳細說一說。
一、基礎知識
在用色光三原色來變換圖片顏色中,涉及到一個類ColorMatrix,也就是顏色矩陣的意思。而android中圖像顏色處理的原理就是用一個4*5的數值矩陣來與圖片中每一個像素點相乘,即與每一個顏色值相乘從而得到新的顏色的。我們看下面的一張圖片
這張圖片說的就是顏色處理的原理。其中的矩陣A就是我們的顏色矩陣,是一個數值矩陣,每一個值都在0—255之間。而C是一個5*1的向量,即時圖片上的每一個像素點(也就是顏色值)。當A*C時,由線性代數的知識,就得到一個新的4*1的向量。仔細觀察右邊的計算公式,新的向量的四個元素其實就是新的顏色分量值:紅,綠,藍,透明度。至於原始的向量是5*1,最后一個元素為什么是1,這這只是android設置的一個偏移量而已,不用管它。那么我怎么改變顏色呢?其實我們要做的很簡單,就是設定顏色矩陣A的每一個值即可。那么當A的初始化值我多少呢,即A怎么設置,可以將圖片還原為以前的顏色呢(或者說是不會改變顏色)。學過線代就會知道,其實很簡單,只要能夠保證C的值變即可。那么A應該設置為,如下:
好了,基本基礎知識你都知道了。也許你還是很困惑,怎么使用顏色矩陣呢?其實思路跟利用色光三元色改變圖片效果的方法是一樣的。我們通過ColorMatrxi的set方法,將一個長度為20的數值數組傳給它,就可以實現顏色矩陣A的設定了。然后同樣,利用這個設定好的顏色矩陣來設置畫筆,最后用畫筆根據我們原來的圖片畫一張只改變了顏色的圖片即可。我們來看具體的一個實現方法吧,代碼如下,注釋很詳細,我就不多解釋了。
1 /* 2 * 用來根據顏色矩陣處理圖片的顏色 3 */ 4 private void setImage(){ 5 Bitmap bmp = Bitmap.createBitmap(priBmp.getWidth(), priBmp.getHeight(), Bitmap.Config.ARGB_8888); 6 Canvas canvas = new Canvas(bmp); 7 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//抗鋸齒設置 8 9 ColorMatrix colorMatrix = new ColorMatrix(); 10 colorMatrix.set(mColorMatrix);//注意這一步是核心,將顏色矩陣設置為我們的顏色矩陣 11 //根據顏色矩陣獲得一支這樣的畫筆 12 paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); 13 //然后利用設置好的顏色畫筆將原圖畫到新的bmp上 14 canvas.drawBitmap(priBmp, 0, 0, paint); 15 16 img.setImageBitmap(bmp);//注意這一步,我們將圖片顯示在ImageView上了 17 }
需要說明的是,其中img是一個ImageView,priBmp是原來的Bitmap圖片,mColorMatrxi是一個長度為20的數值數組。其實上面的代碼就是截取我們下面的實戰里面的,所以你看不到它們的初始化。那么下面我們快快進入實戰吧。
二、實戰
我們的實戰代碼在上一篇用三原色改變顏色效果的基礎上繼續編寫。在上一篇中我們再MainActivity中顯示了三個按鈕,現在我們就來實現第二個按鈕”調整顏色矩陣“。首先編寫color2.xml用來顯示利用顏色矩陣調整的圖片。這里面用到了一個Gridlayout布局,相信大家都不陌生吧,我就不多說了。代碼如下:
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 <ImageView 7 android:id="@+id/img_color" 8 android:layout_width="match_parent" 9 android:layout_height="0dp" 10 android:layout_weight="2"/> 11 <GridLayout 12 android:id="@+id/glay" 13 android:layout_width="match_parent" 14 android:layout_height="0dp" 15 android:layout_weight="3" 16 android:columnCount="5" 17 android:rowCount="4" ></GridLayout> 18 19 <LinearLayout 20 android:layout_width="match_parent" 21 android:layout_height="wrap_content" 22 android:orientation="horizontal"> 23 <Button 24 android:id="@+id/btn_change" 25 android:layout_width="0dp" 26 android:layout_height="wrap_content" 27 android:layout_weight="1" 28 android:onClick="btnChange" 29 android:text="改變"/> 30 <Button 31 android:id="@+id/btn_ret" 32 android:layout_width="0dp" 33 android:layout_height="wrap_content" 34 android:layout_weight="1" 35 android:onClick="btnRet" 36 android:text="恢復"/> 37 </LinearLayout> 38 39 40 41 42 </LinearLayout>
我們發現在這個布局中,上放置了一個ImageView用來顯示圖片,下面是一個4*5的GridLayout,其實就是來設置顏色矩陣的,對應於顏色矩陣4*5。最下面是兩個按鈕,一個”改變“按鈕,用來改變顏色,一個”恢復“按鈕,用來恢復圖片顏色。
然后,再新建”ColorMatrixActivity“,用來顯示我們這個布局,處理相應的邏輯。注釋很詳細了,如下:
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.Canvas; 7 import android.graphics.ColorMatrix; 8 import android.graphics.ColorMatrixColorFilter; 9 import android.graphics.Paint; 10 import android.os.Bundle; 11 import android.view.View; 12 import android.widget.EditText; 13 import android.widget.GridLayout; 14 import android.widget.ImageView; 15 16 public class ColorMatrixActivity extends Activity{ 17 18 private ImageView img; 19 private GridLayout mGrid; 20 private Bitmap priBmp; 21 22 private int mEtWidth;//每一個小編輯框的寬度 23 private int mEtHeight;//每一個小編輯框的高度 24 25 private EditText[] mEts = new EditText[20];//用來存儲編輯框 26 private float[] mColorMatrix = new float[20];//用來存儲編輯框中的值 27 28 29 30 31 protected void onCreate(Bundle savedInstanceState) { 32 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.color2); 35 priBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test1); 36 37 img = (ImageView) findViewById(R.id.img_color); 38 mGrid = (GridLayout) findViewById(R.id.glay); 39 img.setImageBitmap(priBmp); 40 41 //當mGrid被畫出來之后就會調用這個方法 42 mGrid.post(new Runnable(){ 43 44 public void run() { 45 46 mEtWidth = mGrid.getWidth()/5; 47 mEtHeight = mGrid.getHeight()/4; 48 49 initGrid(); 50 initMatrix(); 51 } 52 53 }); 54 } 55 /* 56 * 初始化mGrid,將小的編輯框添加進去 57 */ 58 private void initGrid(){ 59 60 for(int i=0;i<20;i++){ 61 EditText et = new EditText(this); 62 mGrid.addView(et,mEtWidth,mEtHeight); 63 64 mEts[i] = et; 65 66 } 67 } 68 /* 69 * 初始化矩陣,即mGrid中的那些小編輯框 70 */ 71 private void initMatrix(){ 72 73 for(int i=0;i<20;i++){ 74 if(i%6 == 0){ 75 mEts[i].setText(String.valueOf(1)); 76 }else{ 77 mEts[i].setText(String.valueOf(0)); 78 } 79 } 80 } 81 /* 82 * 用來獲取編輯框中的值 83 */ 84 private void getMatrix(){ 85 for(int i=0;i<20;i++){ 86 mColorMatrix[i]=Float.valueOf(mEts[i].getText().toString()); 87 } 88 } 89 /* 90 * 用來根據顏色矩陣處理圖片的顏色 91 */ 92 private void setImage(){ 93 Bitmap bmp = Bitmap.createBitmap(priBmp.getWidth(), priBmp.getHeight(), Bitmap.Config.ARGB_8888); 94 Canvas canvas = new Canvas(bmp); 95 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//抗鋸齒設置 96 97 ColorMatrix colorMatrix = new ColorMatrix(); 98 colorMatrix.set(mColorMatrix);//注意這一步是核心,將顏色矩陣設置為我們的顏色矩陣 99 //根據顏色矩陣獲得一支這樣的畫筆 100 paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); 101 //然后利用設置好的顏色畫筆將原圖畫到新的bmp上 102 canvas.drawBitmap(priBmp, 0, 0, paint); 103 104 img.setImageBitmap(bmp);//注意這一步,我們將圖片顯示在ImageView上了 105 } 106 107 /** 108 * 改變按鈕的監聽事件 109 */ 110 public void btnChange(View view){ 111 112 getMatrix(); 113 setImage(); 114 } 115 /* 116 * 恢復按鈕的監聽事件 117 */ 118 public void btnRet(View view){ 119 initMatrix(); 120 getMatrix(); 121 setImage(); 122 123 } 124 }
在這里,我們可以看到將顏色矩陣初始化為了只包含1和0的矩陣,就是前面我們所講的用來恢復圖片顏色的矩陣。后面的那個setImage方法就是之前我們所貼出來的改變顏色的那個方法。代碼邏輯很簡單,不多說了。
最后不要忘記注冊這個活動,還要修改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 )
好了,我們運行程序,點擊第二個按鈕,實現的效果如下:
點擊按鈕,跳轉后為第一張效果,然后設置值並點擊”改變“是第二張的效果,然后點擊恢復是第三張效果。
這樣子,是不是很直觀啊。不知道用顏色矩陣來處理圖片顏色你掌握了沒有。下面我們就來實現最后一個按鈕”調整色素“,即通過調整色素來實現顏色的改變。在下面的這篇文章中,我們將實現負片效果,浮雕效果,老照片效果,有意思吧,快來學習吧。