目前市场上很多种美图软件,都会带有一个滤镜效果,在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;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.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() {
@Override
public void run() {
mWith = mGridLayout.getWidth() / 5;
mHeight = mGridLayout.getHeight() / 4;
addEts();
initMatrix();
}
});
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getMatrix();
setBitmap();
}
});
findViewById(R.id.btn2).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setOldBitmap();
}
});
findViewById(R.id.btn3).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setInvertImage();
}
});
findViewById(R.id.btn4).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setEmbossImage();
}
});
findViewById(R.id.btn5).setOnClickListener(new OnClickListener() {
@Override
public 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);
}
}
下面是布局文件
<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>