在上一篇文章中,我们学习利用色光三原色调整图片颜色的方法。这一篇文章的代码将在上一篇的基础上继续书写。如果你还没读过,可以点击下面的链接:

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 )

         好了,我们运行程序,点击第二个按钮,实现的效果如下:

                                

    点击按钮,跳转后为第一张效果,然后设置值并点击”改变“是第二张的效果,然后点击恢复是第三张效果。

 

     这样子,是不是很直观啊。不知道用颜色矩阵来处理图片颜色你掌握了没有。下面我们就来实现最后一个按钮”调整色素“,即通过调整色素来实现颜色的改变。在下面的这篇文章中,我们将实现负片效果,浮雕效果,老照片效果,有意思吧,快来学习吧。

 

posted on 2015-10-15 21:09  fuly  阅读(5193)  评论(1编辑  收藏  举报