Android 使用ColorMatrix改變圖片顏色

小呂-ICE發表於2015-10-17

ColorMatrix的顏色矩陣介紹

  • 顏色矩陣M是一個5*4的矩陣,在Android中,顏色矩陣M是以一維陣列m=[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]的方式進行儲存的。如下圖1:

圖1 顏色矩陣M
圖1 顏色矩陣M

他通過RGBA四個通道來直接操作對應顏色,達到修改影像的效果。

  • 第一行決定紅色 R
  • 第二行決定綠色 G
  • 第三行決定藍色 B
  • 第四行決定了透明度 A
  • 第五列是顏色的偏移量

原圖的RGBA的ColorMatrix顏色矩陣陣列為:

[ 1, 0, 0, 0, 0,
  0, 1, 0, 0, 0,
  0, 0, 1, 0, 0,
  0, 0, 0, 1, 0]
  • 在一張圖片中,影像的RGBA(紅色、綠色、藍色、透明度)值決定了該圖片所呈現出來的顏色效果。而影像的RGBA值則儲存在一個5*1的顏色分量矩陣C中,由顏色分量矩陣C可以控制影像的顏色效果。顏色分量矩陣C 如圖2所示:
    顏色分量矩陣C
    圖2 顏色分量矩陣C

  • 要想改變一張圖片的顏色效果,只需要改變影像的顏色分量矩陣即可。通過顏色矩陣可以很方便的修改影像的顏色分量矩陣。假設修改後的影像顏色分量矩陣為C1,則有如圖3所示的顏色分量矩陣計算公式:
    這裡寫圖片描述
    圖3 顏色分量矩陣計算公式

通常,改變顏色分量時可以通過修改第5列的顏色偏移量來實現,如圖4所示的顏色矩陣M1,通過計算後可以得知該顏色矩陣的作用是使影像的紅色分量和綠色分量均增加100,這樣的效果就是圖片泛黃(因為紅色與綠色混合後得到黃色)。
顏色矩陣M1
圖4 顏色矩陣M1

除此之外,也可以通過直接對顏色值乘以某一系數而達到改變顏色分量的目的。如圖5所示的顏色矩陣M2,將綠色分量放大了2倍,這樣的效果就是圖片泛綠色。
顏色矩陣M2
圖5 顏色矩陣M2

————以上內容收集於網路:http://www.android100.org/html/201406/05/19490.html———-


使用ColorMatrix改變圖片顏色的步驟

  • 通過Bitmap.createBitmap()方法獲得一個空白的Bitmap物件。
  • 使用Bitmap物件建立畫布Canvas, 然後建立畫筆Paint。
  • 定義ColorMatrix,並指定RGBA矩陣。
  • 使用ColorMatrix建立一個ColorMatrixColorFilter物件, 作為畫筆的濾鏡 paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix))。
  • 使用Canvas.drawBitmap()方法把原圖使用定義的Paint畫到空白的Bitmap物件上即可獲得改變RGBA值後的影像。

影像顏色處理例項

  • 首先準備一張用來修改顏色的黑色原始圖片 btn_pause.png 如下:
    這裡寫圖片描述

  • 佈局檔案 colormatrix_activity.xml 內容如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="R" />

    <SeekBar
        android:id="@+id/sb_red"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="0" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="G" />

    <SeekBar
        android:id="@+id/sb_green"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="0" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="B" />

    <SeekBar
        android:id="@+id/sb_blue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="0" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A" />

    <SeekBar
        android:id="@+id/sb_alpha"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="255" />

    <ImageView
        android:id="@+id/iv_color_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/btn_pause" />

</LinearLayout>
  • 介面程式碼 ColorMatrixActivity.java
/**
 * Created by lvzhengbin on 15/10/15.
 */
public class ColorMatrixActivity extends ActionBarActivity {

    private SeekBar sb_red, sb_green, sb_blue, sb_alpha;
    private ImageView iv_show;
    private Bitmap afterBitmap;
    private Paint paint;
    private Canvas canvas;
    private Bitmap baseBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.colormatrix_activity);
        initView();
    }

    private void initView() {
        iv_show = (ImageView) findViewById(R.id.iv_color_show);
        sb_red = (SeekBar) findViewById(R.id.sb_red);
        sb_green = (SeekBar) findViewById(R.id.sb_green);
        sb_blue = (SeekBar) findViewById(R.id.sb_blue);
        sb_alpha = (SeekBar) findViewById(R.id.sb_alpha);

        sb_red.setOnSeekBarChangeListener(seekBarChange);
        sb_green.setOnSeekBarChangeListener(seekBarChange);
        sb_blue.setOnSeekBarChangeListener(seekBarChange);
        sb_alpha.setOnSeekBarChangeListener(seekBarChange);

        baseBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.btn_pause);
        // 1.獲取一個與baseBitmap大小一致的可編輯的空圖片
        afterBitmap = Bitmap.createBitmap(baseBitmap.getWidth(),
                baseBitmap.getHeight(), baseBitmap.getConfig());
        // 2.使用Bitmap物件建立畫布Canvas, 然後建立畫筆Paint。
        canvas = new Canvas(afterBitmap);
        paint = new Paint();
    }

    private SeekBar.OnSeekBarChangeListener seekBarChange = new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if(seekBar.getId() == R.id.sb_alpha){
                iv_show.getDrawable().setAlpha(sb_alpha.getProgress());

            }else{
                float progressR = sb_red.getProgress();
                float progressG = sb_green.getProgress();
                float progressB = sb_blue.getProgress();
                // 根據SeekBar定義RGBA的矩陣, 通過修改矩陣第五列顏色的偏移量改變圖片的顏色
                float[] src = new float[]{
                        1, 0, 0, 0, progressR,
                        0, 1, 0, 0, progressG,
                        0, 0, 1, 0, progressB,
                        0, 0, 0, 1, 0};

                // 3.定義ColorMatrix,並指定RGBA矩陣
                ColorMatrix colorMatrix = new ColorMatrix();
                colorMatrix.set(src);
                // 4.使用ColorMatrix建立一個ColorMatrixColorFilter物件, 作為畫筆的濾鏡, 設定Paint的顏色
                paint.setColorFilter(new ColorMatrixColorFilter(src));
                // 5.通過指定了RGBA矩陣的Paint把原圖畫到空白圖片上
                canvas.drawBitmap(baseBitmap, new Matrix(), paint);
                iv_show.setImageBitmap(afterBitmap);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
        }
    };
}
  • 我們可以通過SeekBar調節RGB的值來修改圖片的顏色來達到不同的效果,執行效果如下:
    這裡寫圖片描述

相關文章