Android 常见滤镜的实现,怀旧,底片,浮雕,ColorMatrix

来源:互联网 发布:淘宝账户管理在哪里 编辑:程序博客网 时间:2024/04/27 22:58

目前市场上很多种美图软件,都会带有一个滤镜效果,在android中提供了一个类ColorMatrix来调整一张图片的颜色。

android中颜色由四个参数组成ARGB ,分别代表透明度,红色,绿色,和蓝色,即矩阵

[a,r,g,b] //将这个矩阵命名为mColor
代表一个像素。ColorMatrix 实际上是一个4*5的矩阵,[ a, b, c, d, e,  f, g, h, i, j,  k, l, m, n, o,  p, q, r, s, t ]  //给这个矩阵命名为mColorMatrix[1 , 0 , 0 , 0 , 0, 0 , 1 , 0 , 0 , 0, 0 , 0 , 1 , 0 , 0, 0 , 0 , 0 , 1 , 0,] //给这个矩阵命名为mUnitColorMatrix [1 , 0 , 0 , mTranslateAlpha , 0,  0 , 1 , 0 , mTranslateRed , 0,  0 , 0 , 1 , mTranslateGreen , 0,  0 , 0 , 0 , mTranslateBlue , 0,]  //给这个矩阵命名为mTranslateColorMatrix [aScale , 0 , 0 , 0 , 0,  0 , rScale , 0 , 0 , 0,  0 , 0 , gScale , 0 , 0,  0 , 0 , 0 , bScale , 0,]  //给这个矩阵命名为mScaleColorMatrix

用mColorMatrix 和mColor矩阵相乘,得到一个新的颜色矩阵

mColorMatrix * mColor = [a1 , r1 , g1 , b1];/** * a1 = a*R + b*G + c*B + d*A + e; * g1 = f*R + g*G + h*B + i*A + j; * b1 = k*R + l*G + m*B + n*A + o; * a1 = p*R + q*G + r*B + s*A + t; */mUnitColorMatrix * mColor = [a , r , g , b]//单位矩阵乘以原来的矩阵得到相同的颜色mTranslateColorMatrix * mColor = [a+ mTranslateAlpha , r + mTranslateRed ,g + mTranslateGreen,b + mTranslateBlue ]//色差偏移矩阵得到新的颜色效果mScaleColorMatrix* mColor = [a*aScale  , r*rScale  ,g*gScale ,b*bScale  ]//色差偏移矩阵得到新的颜色效果

这里可以总结一下mColorMatrix中几个重要的参数的作用
a,g,m,s分别对颜色的比例的放大缩小,这里要注意一点,android中bitmap中的config参数中最高像素占位为Bitmap.Config.ARGB_8888,即ARGB分别占8位。所以结果的最大值为255。

d,i,n,s分别控制颜色的偏移。同样最大值不超过255.

市场上几个特定的滤镜效果,实则是用一个特殊的ColorMatrix 乘以 每个像素点的颜色,或者将对满足一定条件的像素点乘以某些特定的矩阵。

下面笔者从大神那儿拿来了三个效果的ColorMatrix
底片效果矩阵:这里写图片描述

浮雕效果:这里写图片描述

package com.example.androidtest;import android.R.integer;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.ColorMatrix;import android.graphics.ColorMatrixColorFilter;import android.graphics.Paint;import android.os.Bundle;import android.text.InputType;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.GridLayout;import android.widget.ImageView;public class ColorMatrixActivity2 extends Activity{private GridLayout mGridLayout;private int mWith,mHeight;private EditText[] ets = new EditText[20];private float[] colorMatrix = new float[20];private Button btn1;private Bitmap bitmap;private ImageView mImageView;private int width,height;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.colormatrix_2);bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test1);width = bitmap.getWidth();height = bitmap.getHeight();mGridLayout = (GridLayout) findViewById(R.id.ets);mImageView = (ImageView) findViewById(R.id.ivBeauty);mGridLayout.post(new Runnable() {@Overridepublic void run() {mWith = mGridLayout.getWidth() / 5;mHeight = mGridLayout.getHeight() / 4;addEts();initMatrix();}});btn1 = (Button) findViewById(R.id.btn1);btn1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {getMatrix();setBitmap();}});findViewById(R.id.btn2).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {setOldBitmap();}});findViewById(R.id.btn3).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {setInvertImage();}});findViewById(R.id.btn4).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {setEmbossImage();}});findViewById(R.id.btn5).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {initMatrix();setBitmap();}});}private void addEts(){for (int i = 0; i < 20; i++) {EditText et = new EditText(ColorMatrixActivity2.this);et.setInputType(InputType.TYPE_CLASS_NUMBER);ets[i] = et;mGridLayout.addView(et, mWith, mHeight);}}private void initMatrix(){for (int i = 0; i < 20; i++) {if (i % 6 == 0) {ets[i].setText(1+"");colorMatrix[i] = 1.0f;}else {ets[i].setText(0+"");colorMatrix[i] = 0.0f;}}}private void getMatrix(){for (int i = 0; i < 20; i++) {colorMatrix[i] = Float.valueOf(ets[i].getText().toString());}}private void setBitmap(){Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bmp);Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);ColorMatrix matrix = new ColorMatrix(colorMatrix);paint.setColorFilter(new ColorMatrixColorFilter(matrix));canvas.drawBitmap(bitmap, 0, 0, paint);mImageView.setImageBitmap(bmp);}private void setOldBitmap(){Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);int[] oldPixs = new int[width*height];int[] newPixs = new int[width*height];bitmap.getPixels(oldPixs, 0, width, 0, 0, width, height);int color;int r,g,b;int r1,g1,b1,a;for (int i = 0; i < oldPixs.length; i++) {color = oldPixs[i];r = Color.red(color);g = Color.green(color);b = Color.blue(color);a = Color.alpha(color);r1 = (int) (0.393*r+0.769*g + 0.189*b);g1 = (int) (0.349*r + 0.686*g + 0.168*b);b1 = (int) (0.272*r + 0.534*g + 0.131*b);r1 = r1 > 255 ? 255:r1;g1 = g1 > 255 ? 255:g1;b1 = b1 > 255 ? 255:b1;newPixs[i] = Color.argb(a, r1, g1, b1);}bmp.setPixels(newPixs, 0, width, 0, 0, width, height);mImageView.setImageBitmap(bmp);}private void setInvertImage(){Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);int[] oldPixs = new int[width*height];int[] newPixs = new int[width*height];bitmap.getPixels(oldPixs, 0, width, 0, 0, width, height);int color;int r,g,b;int r1,g1,b1,a;for (int i = 0; i < oldPixs.length; i++) {color = oldPixs[i];r = Color.red(color);g = Color.green(color);b = Color.blue(color);a = Color.alpha(color);r1 = 255 - r;g1 = 255 - g;b1 = 255 - b;newPixs[i] = Color.argb(a, r1, g1, b1);}bmp.setPixels(newPixs, 0, width, 0, 0, width, height);mImageView.setImageBitmap(bmp);}private void setEmbossImage(){Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);int[] oldPixs = new int[width*height];int[] newPixs = new int[width*height];bitmap.getPixels(oldPixs, 0, width, 0, 0, width, height);int color,oldColor;int r,g,b;int r0,g0,b0,a0;int r1,g1,b1,a;for (int i = 1; i < oldPixs.length; i++) {oldColor = oldPixs[i-1];r0 = Color.red(oldColor);g0 = Color.green(oldColor);b0 = Color.blue(oldColor);a0 = Color.alpha(oldColor);color = oldPixs[i];r = Color.red(color);g = Color.green(color);b = Color.blue(color);a = Color.alpha(color);r1 = r0 - r + 127;if (r1<0) {r1 = 0;}else if(r1>255){r1 = 255;}g1 = g0 - g + 127;if (g1<0) {g1 = 0;}else if(g1>255){g1 = 255;}b1 = b0 - b + 127;if (b1<0) {b1 = 0;}else if(b1>255){b1 = 255;}newPixs[i] = Color.argb(a, r1, g1, b1);}bmp.setPixels(newPixs, 0, width, 0, 0, width, height);mImageView.setImageBitmap(bmp);}}

下面是布局文件

<?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:gravity="center"    android:orientation="vertical" >    <ImageView         android:id="@+id/ivBeauty"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="@drawable/test1"/>    <GridLayout         android:id="@+id/ets"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:rowCount="4"        android:layout_weight="2"        android:columnCount="5"></GridLayout>    <LinearLayout         android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">        <Button             android:id="@+id/btn1"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="设置"/>        <Button             android:id="@+id/btn2"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="老照片"/>    </LinearLayout>    <LinearLayout         android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">        <Button             android:id="@+id/btn3"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="底片效果"/>        <Button             android:id="@+id/btn4"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="浮雕效果"/>    </LinearLayout>    <Button         android:id="@+id/btn5"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="还原"/></LinearLayout>

效果图
老照片

底片效果

浮雕效果

1 0