利用顏色矩陣實現圖片效果


      在上一篇文章中,我們學習利用色光三原色調整圖片顏色的方法。這一篇文章的代碼將在上一篇的基礎上繼續書寫。如果你還沒讀過,可以點擊下面的鏈接:

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 )

         好了,我們運行程序,點擊第二個按鈕,實現的效果如下:

                                

    點擊按鈕,跳轉后為第一張效果,然后設置值並點擊”改變“是第二張的效果,然后點擊恢復是第三張效果。

 

     這樣子,是不是很直觀啊。不知道用顏色矩陣來處理圖片顏色你掌握了沒有。下面我們就來實現最后一個按鈕”調整色素“,即通過調整色素來實現顏色的改變。在下面的這篇文章中,我們將實現負片效果,浮雕效果,老照片效果,有意思吧,快來學習吧。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM