android自定义滤镜,【Android】自定义View那点事(三)ColorFilter篇
前言
前面學(xué)習(xí)Xfermode的使用,我們可以自定義各種不同樣式的View,本節(jié)我們學(xué)習(xí)關(guān)于顏色處理相關(guān)的內(nèi)容。現(xiàn)在很多圖片處理軟件都具有濾鏡功能,選擇不同風(fēng)格濾鏡可以改變圖片色彩呈現(xiàn)不同風(fēng)格。Android開發(fā)文檔中提供了相應(yīng)的API供開發(fā)者使用,這樣我們自己可以實(shí)現(xiàn)圖片濾鏡效果。這節(jié)我們主要講ColorMatrixColorFilter,ColorMatrixColorFilter通過(guò)ColorMatrix設(shè)置4*5的矩陣變換RGBA參數(shù)調(diào)整顏色。
色彩科普
在開始如何調(diào)整圖片顏色之前,我們先了解一下關(guān)于色彩方面的知識(shí)。Ps:理論知識(shí)來(lái)源于度娘
色相
色相是色彩的首要特征,是區(qū)別各種不同色彩的最準(zhǔn)確的標(biāo)準(zhǔn)。事實(shí)上任何黑白灰以外的顏色都有色相的屬性,而色相也就是由原色、間色和復(fù)色來(lái)構(gòu)成的。色相,色彩可呈現(xiàn)出來(lái)的質(zhì)地面貌。自然界中各個(gè)不同的色相是無(wú)限豐富的,如紫紅、銀灰、橙黃等。色相即各類色彩的相貌稱謂。
色調(diào)
色調(diào)指的是一幅畫中畫面色彩的總體傾向,是大的色彩效果。這種在不同顏色的物體上,籠罩著某一種色彩,使不同顏色的物體都帶有同一色彩傾向,這樣的色彩現(xiàn)象就是色調(diào)。
灰度
灰度使用黑色調(diào)表示物體,即用黑色為基準(zhǔn)色,不同的飽和度的黑色來(lái)顯示圖像。 每個(gè)灰度對(duì)象都具有從 0%(白色)到100%(黑色)的亮度值。使用黑白或灰度掃描儀生成的圖像通常以灰度顯示。
對(duì)比度
對(duì)比度指的是一幅圖像中明暗區(qū)域最亮的白和最暗的黑之間不同亮度層級(jí)的測(cè)量,差異范圍越大代表對(duì)比越大,差異范圍越小代表對(duì)比越小,好的對(duì)比率120:1就可容易地顯示生動(dòng)、豐富的色彩,當(dāng)對(duì)比率高達(dá)300:1時(shí),便可支持各階的顏色。但對(duì)比率遭受和亮度相同的困境,現(xiàn)今尚無(wú)一套有效又公正的標(biāo)準(zhǔn)來(lái)衡量對(duì)比率,所以最好的辨識(shí)方式還是依靠使用者眼睛。
飽和度
飽和度可定義為彩度除以明度,與彩度同樣表征彩色偏離同亮度灰色的程度。注意,與彩度完全不是同一個(gè)概念。但由于其和彩度決定的是出現(xiàn)在人眼里的同一個(gè)效果,所以才會(huì)出現(xiàn)視彩度與飽和度為同一概念的情況。
主角ColorMatrix
ColorMatrix通過(guò)設(shè)置4*5的矩陣數(shù)值改變圖片的顏色和透明度。我們來(lái)看看官方文檔的描述。No picture,say the JJ,來(lái)上圖。
Paste_Image.png
可以看到4*5矩陣每一行的運(yùn)算結(jié)果分別代表RGBA的最終的數(shù)值,以及它們?nèi)≈捣秶?-255之間。而每一行最后一個(gè)數(shù)值代表偏移量,例如想讓R增加100偏移量,則將矩陣數(shù)組第四個(gè)數(shù)值設(shè)置為100。
ColorMatrix的reset()方法可以看到,顏色矩陣RGBA的初始情況。
Paste_Image.png
美圖濾鏡效果
原圖
Paste_Image.png
|1,0,0,0,0|
|0,1,0,0,0|
|0,0,1,0,0|
|0,0,0,1,0|
泛黃矩陣
Paste_Image.png
|1,0,0,0,100|
|0,1,0,0,100|
|0,0,1,0,0|
|0,0,0,1,0|
偏紅矩陣
Paste_Image.png
|2,0,0,0,0|
|0,1,0,0,0|
|0,0,1,0,0|
|0,0,0,1,0|
底片矩陣
Paste_Image.png
|-1,0,0,0,255|
|0,-1,0,0,255|
|0,0,-1,0,255|
|0,0,0,1,0|
主要代碼
開發(fā)流程簡(jiǎn)介
1.獲取圖片資源draweBitmap
2.canvasBitmap獲取draweBitmap用于創(chuàng)建畫布canvas的大小
3.ColorMatrix設(shè)置顏色矩陣,ColorMatrixColorFilter加載ColorMatrix,paint設(shè)置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);
}
}
設(shè)置顏色矩陣Dialog
public class ColorMatrixDialog extends Dialog {
RecyclerView recyclerView;
List 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{
@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;
}
}
}
補(bǔ)充內(nèi)容
除了使用顏色矩陣改變,在官方文檔中還可以看到ColorMatrix另外幾個(gè)方法
Paste_Image.png
Paste_Image.png
Paste_Image.png
這三個(gè)方法分別設(shè)置飽和度、亮度、色相。
演示代碼
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);
}
效果展示
620019632-5815ffd94819e_articlex.gif
總結(jié)
以上是生活随笔為你收集整理的android自定义滤镜,【Android】自定义View那点事(三)ColorFilter篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 名人堂内存灯:三招教你如何轻松关闭
- 下一篇: 选购x99内存,三大注意事项
