前言
前面学习Xfermode的使用,我们可以自定义各种不同样式的View,本节我们学习关于颜色处理相关的内容。现在很多图片处理软件都具有滤镜功能,选择不同风格滤镜可以改变图片色彩呈现不同风格。Android开发文档中提供了相应的API供开发者使用,这样我们自己可以实现图片滤镜效果。这节我们主要讲ColorMatrixColorFilter,ColorMatrixColorFilter通过ColorMatrix设置4*5的矩阵变换RGBA参数调整颜色。
色彩科普
在开始如何调整图片颜色之前,我们先了解一下关于色彩方面的知识。Ps:理论知识来源于度娘
- 色相
色相是色彩的首要特征,是区别各种不同色彩的最准确的标准。事实上任何黑白灰以外的颜色都有色相的属性,而色相也就是由原色、间色和复色来构成的。色相,色彩可呈现出来的质地面貌。自然界中各个不同的色相是无限丰富的,如紫红、银灰、橙黄等。色相即各类色彩的相貌称谓。
- 色调
色调指的是一幅画中画面色彩的总体倾向,是大的色彩效果。这种在不同颜色的物体上,笼罩着某一种色彩,使不同颜色的物体都带有同一色彩倾向,这样的色彩现象就是色调。
- 灰度
灰度使用黑色调表示物体,即用黑色为基准色,不同的饱和度的黑色来显示图像。 每个灰度对象都具有从 0%(白色)到100%(黑色)的亮度值。使用黑白或灰度扫描仪生成的图像通常以灰度显示。
- 对比度
对比度指的是一幅图像中明暗区域最亮的白和最暗的黑之间不同亮度层级的测量,差异范围越大代表对比越大,差异范围越小代表对比越小,好的对比率120:1就可容易地显示生动、丰富的色彩,当对比率高达300:1时,便可支持各阶的颜色。但对比率遭受和亮度相同的困境,现今尚无一套有效又公正的标准来衡量对比率,所以最好的辨识方式还是依靠使用者眼睛。
- 饱和度
饱和度可定义为彩度除以明度,与彩度同样表征彩色偏离同亮度灰色的程度。注意,与彩度完全不是同一个概念。但由于其和彩度决定的是出现在人眼里的同一个效果,所以才会出现视彩度与饱和度为同一概念的情况。
主角ColorMatrix
ColorMatrix通过设置4*5的矩阵数值改变图片的颜色和透明度。我们来看看官方文档的描述。No picture,say the JJ,来上图。
可以看到4*5矩阵每一行的运算结果分别代表RGBA的最终的数值,以及它们取值范围在0-255之间。而每一行最后一个数值代表偏移量,例如想让R增加100偏移量,则将矩阵数组第四个数值设置为100。
ColorMatrix的reset()方法可以看到,颜色矩阵RGBA的初始情况。
美图滤镜效果
- 原图
|1,0,0,0,0|
|0,1,0,0,0|
|0,0,1,0,0|
|0,0,0,1,0|
- 泛黄矩阵
|1,0,0,0,100|
|0,1,0,0,100|
|0,0,1,0,0|
|0,0,0,1,0|
- 偏红矩阵
|2,0,0,0,0|
|0,1,0,0,0|
|0,0,1,0,0|
|0,0,0,1,0|
- 底片矩阵
|-1,0,0,0,255|
|0,-1,0,0,255|
|0,0,-1,0,255|
|0,0,0,1,0|
主要代码
开发流程简介
1.获取图片资源draweBitmap
2.canvasBitmap获取draweBitmap用于创建画布canvas的大小
3.ColorMatrix设置颜色矩阵,ColorMatrixColorFilter加载ColorMatrix,paint设置ColorMatrixColorFilter
4.canvas使用paint绘制draweBitmap
5.imageView加载canvasBitmap
主视图部分
public class ColorFilterView extends LinearLayout{
ImageView imageView;
Button btnSetting;
Bitmap draweBitmap;
Bitmap canvasBitmap;
Canvas canvas;
Paint paint;
float[] ColorMatrixFloat = new float[20];
ColorMatrixDialog colorMatrixDialog;
public ColorFilterView(Context context) {
super(context);
initView(context);
}
public ColorFilterView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
private void initView(final Context context) {
this.setOrientation(VERTICAL);
imageView = new ImageView(context);
BitmapFactory.Options option = new BitmapFactory.Options();
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity)context).getWindow().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
draweBitmap = Utils.CompressImage(context, R.drawable.meizi,option,displayMetrics);
canvasBitmap = Bitmap.createBitmap(option.outWidth,option.outHeight, Bitmap.Config.ARGB_8888);
addView(imageView);
canvas = new Canvas(canvasBitmap);
paint = new Paint();
canvas.drawBitmap(draweBitmap,0,0,paint);
imageView.setImageBitmap(canvasBitmap);
btnSetting = new Button(context);
btnSetting.setText("MatrixSeeting");
btnSetting.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
colorMatrixDialog = new ColorMatrixDialog(context,ColorMatrixFloat);
colorMatrixDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
changeMatrix(ColorMatrixFloat);
}
});
colorMatrixDialog.show();
}
});
addView(btnSetting);
}
private void changeMatrix(float[] color){
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(color);
ColorMatrixColorFilter colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(colorMatrixColorFilter);
canvas.drawBitmap(draweBitmap,0,0,paint);
imageView.setImageBitmap(canvasBitmap);
}
}
设置颜色矩阵Dialog
public class ColorMatrixDialog extends Dialog {
RecyclerView recyclerView;
List<EditText> editTextList = new ArrayList<>();
float[] colors;
Button btnOk;
public ColorMatrixDialog(Context context,float[] colors) {
super(context);
init(context);
this.colors = colors;
}
public ColorMatrixDialog(Context context, int themeResId) {
super(context, themeResId);
init(context);
}
private void init(Context context){
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
recyclerView = new RecyclerView(context);
recyclerView.setLayoutManager(new GridLayoutManager(context,5));
recyclerView.setAdapter(new EditextAdapter());
linearLayout.addView(recyclerView);
btnOk = new Button(context);
btnOk.setText("OK");
btnOk.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int num = 0;
for(EditText editText : editTextList){
try {
String value = editText.getText().toString();
float floatValue = Float.valueOf(value);
colors[num] = floatValue;
}catch (NumberFormatException e){
e.printStackTrace();
}
num++;
}
dismiss();
}
});
linearLayout.addView(btnOk);
addContentView(linearLayout,new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
class EditextAdapter extends RecyclerView.Adapter<EditTextViewHolder>{
@Override
public EditTextViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
EditText editText = new EditText(parent.getContext());
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.weight = 1;
editText.setLayoutParams(layoutParams);
editText.setGravity(View.TEXT_ALIGNMENT_CENTER);
editText.setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_FLAG_DECIMAL|InputType.TYPE_NUMBER_FLAG_SIGNED);
editTextList.add(editText);
return new EditTextViewHolder(editText);
}
@Override
public void onBindViewHolder(EditTextViewHolder holder, int position) {
holder.editText.setText("0");
}
@Override
public int getItemCount() {
return 20;
}
}
class EditTextViewHolder extends RecyclerView.ViewHolder{
EditText editText;
public EditTextViewHolder(View itemView) {
super(itemView);
editText = (EditText)itemView;
}
}
}
补充内容
除了使用颜色矩阵改变,在官方文档中还可以看到ColorMatrix另外几个方法
这三个方法分别设置饱和度、亮度、色相。
- 演示代码
private void changeRGBA(){
float R = (rSeekBar.getProgress() -127) * 1.0f /127 * 180;
float G = gSeekBar.getProgress() * 1.0f / 127;
float B = bSeekBar.getProgress() * 1.0f / 127;
//色相
ColorMatrix colorMatrixRotate = new ColorMatrix();
colorMatrixRotate.setRotate(0,R);
colorMatrixRotate.setRotate(1,R);
colorMatrixRotate.setRotate(2,R);
//饱和度
ColorMatrix colorMatrixSaturation = new ColorMatrix();
colorMatrixSaturation.setSaturation(G);
//亮度
ColorMatrix colorMatrixScale = new ColorMatrix();
colorMatrixScale.setScale(B,B,B,1);
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.postConcat(colorMatrixRotate);
colorMatrix.postConcat(colorMatrixSaturation);
colorMatrix.postConcat(colorMatrixScale);
ColorMatrixColorFilter colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(colorMatrixColorFilter);
canvas.drawBitmap(draweBitmap,0,0,paint);
imageView.setImageBitmap(canvasBitmap);
}
- 效果展示