• 利用颜色矩阵实现图片效果


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

    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 )

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

                                    

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

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

  • 相关阅读:
    jQuery过滤器 过滤器
    查询总结
    ado.net
    禅修程序员十诫
    Asp.net中Bind()和Eval()的区别
    什么是好代码?
    12 个有效的提高编程技能的方法
    Visual Studio各种版本之间的转换工具
    程序员的培养
    session和cookie的区别和联系!
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4883681.html
Copyright © 2020-2023  润新知