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

目前市场上很多种美图软件,都会带有一个滤镜效果,在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);
}
}

下面是布局文件

<?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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值