隔了一年多去看這篇文章,發(fā)現(xiàn)很多地方會有問題,比如7.0后拍照的問題,當(dāng)時用的6.0的系統(tǒng),所以7.0以上的系統(tǒng)一定會崩潰。還有就是加完濾鏡之后無法修改模糊效果。
源碼等可能暫時不維護(hù),存在不少問題。
1、效果展示
用ColorMatrix可以調(diào)節(jié)圖片顏色比例,做到濾鏡的效果。這里用ColorMatrix基本使用寫了一個小的APP,源碼地址:https://github.com/AxeChen/ColorFilter
先上一波效果圖:


利用安卓自帶的API即可完成一些簡單的圖片濾鏡,調(diào)整圖片的對比度亮度等屬性。
2、實現(xiàn)思路
主要思路:選擇相冊圖片或者拍照獲取圖片,然后通過修改ColorMatrix來實現(xiàn)各種不同的濾鏡效果或者通過修改BlurMaskFilter來實現(xiàn)邊框的虛化等效果。
3、主要技術(shù)
3.1、主要技術(shù)點
(1)顏色矩陣ColorMatrix的應(yīng)用(濾鏡,調(diào)整亮度等主要用到的技術(shù))。
(3)BlurMaskFilter邊框虛化。
(4)6.0相機相冊權(quán)限處理。
(5)Bitmap的一些處理:壓縮,生成新的bitmap等。
(6)其他的一些技術(shù)點:一些控件的簡單使用,例如(RecyclerView,Toobar)、分享圖片等。
3.2 顏色矩陣ColorMatrix
應(yīng)用ColorMatrix可以調(diào)節(jié)圖片顏色比例,實現(xiàn)一些濾鏡,調(diào)節(jié)圖片亮度、對比度等效果。
3.2.1 ColorMatrix簡單介紹
在Android中使用顏色矩陣ColorMatrix,來處理圖像的色彩效果。對于圖像的每個像素點,都有一個顏色矩陣A用來保存顏色的RGBA值。在處理圖像是將顏色矩陣和顏色矩陣分量C相乘。


在安卓中使用一個一維數(shù)組表示顏色矩陣:
public static final float[] src = {
1f, 0, 0, 0, 0,
0, 1f, 0, 0, 0,
0, 0, 1f, 0, 0,
0, 0, 0, 1f, 0,
};
如果對顏色矩陣基本知識有些難理解??梢圆患m結(jié)這些基本的知識,只抓住重點:只要改變顏色矩陣對應(yīng)的數(shù)組中元素的值,就可以改變圖片中顏色的比例!
對應(yīng)一維數(shù)組控制的顏色屬性:
第一行決定新的顏色值中的紅色R。
第二行決定新的顏色值中的綠色G。
第三行決定新的顏色值中的藍(lán)色B。
第四行決定新的顏色值中的透明度A。
第五列表示每個顏色的偏移量。
因此只要合理改變這個數(shù)組中不同元素的值就可以實現(xiàn)不同顏色效果了。
3.2.1 ColorMatrix使用
直接上關(guān)鍵代碼:
public class FilterImageView extends FilterView {
// ... 省略若干代碼
private Paint paint;
private ColorMatrixColorFilter colorMatrixColorFilter;
private ColorMatrix colorMatrix;
@Override
protected void onDraw(Canvas canvas) {
paint.reset();
paint.setAntiAlias(true);
if (colorMatrixColorFilter != null) {
paint.setColorFilter(colorMatrixColorFilter);
}
canvas.drawBitmap(bitmap, null, rectF, paint);
canvas.save();
}
@Override
public void setFloat(float[] floats) {
colorMatrix = new ColorMatrix();
colorMatrix.set(floats);
colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
invalidate();
}
// ... 省略若干代碼
}
代碼步驟:
1、初始化ColorMatrixColorFilter 和 ColorMatrix 。
2、在onDraw()方法中通過paint.setColorFilter()方法將ColorMatrixColorFilter設(shè)置給paint。
3通過 canvas.drawBitmap()將Bitmap畫出來即可。(不僅僅是drawBitmap只要drawXX方法中傳入了設(shè)置過ColorMatrixColorFilter的paint都可實現(xiàn)顏色改變的效果)。
3.2.2 修改顏色矩陣對應(yīng)的數(shù)組
改變顏色矩陣對應(yīng)的數(shù)組的數(shù)組元素值,可以展示不同的顏色效果。
一些簡單的修改:
1、改變顏色的偏移量的值(下面的r、g、b、a);
2、改變對應(yīng) RGBA(下面的R、G、B、A) 值的系數(shù)。
如下說明:
public static final float[] src = {
R, 0, 0, 0, r,
0, G, 0, 0, g,
0, 0, B, 0, b,
0, 0, 0, A, a,
};
以上:
R、G、B的值可以增大或者變小。
A的范圍為0f-1f(可以設(shè)置比1f更大,但是效果和1f是一樣的)
而偏移量r、g、b、a的范圍是0f-255f(可以設(shè)置比255f更大,但是效果和255f是一樣的)
改變R、G、B、A或者r、g、b、a的值都可以改變圖片的顏色的比例和透明度。
這些值越大,圖片中對應(yīng)顏色所占的比例就越大或者越不透明。
例如:
public static final float[] green = {
1f, 0, 0, 0, 0,
0, 1.2f, 0, 0, 0,
0, 0, 1f, 0, 0,
0, 0, 0, 1f, 0,
};
以上把G值調(diào)整成1.2f 。就能增加圖片中綠色的比例。

一些復(fù)雜的修改:
通過調(diào)節(jié)數(shù)組中多個元素來做出不同的效果。
例如灰度效果:
/**
* 灰度效果
*/
public static final float[] gray = {
0.213f, 0.715f, 0.072f, 0, 0,
0.213f, 0.715f, 0.072f, 0, 0,
0.213f, 0.715f, 0.072f, 0, 0,
0, 0, 0, 1, 0,
};

修改數(shù)組中多個元素的值來改變圖片中顏色的比例,從而達(dá)到灰度的效果。
3.2.2 調(diào)節(jié)亮度和對比度
ColorMatrix提供了多個方法來修改圖片,例如:
直接將R、G、B、A傳入,修改顏色所占比重:
public void setScale(float rScale, float gScale, float bScale,
float aScale)
調(diào)節(jié)圖片的對比度:
public void setSaturation(float sat)
顏色旋轉(zhuǎn)(可以做色調(diào)效果):
public void setRotate(int axis, float degrees)
修改對比度和亮度代碼如下:
// ... 省略若干代碼
private Paint paint;
private ColorMatrixColorFilter colorMatrixColorFilter;
private ColorMatrix colorMatrix;
@Override
protected void onDraw(Canvas canvas) {
paint.reset();
paint.setAntiAlias(true);
if (colorMatrixColorFilter != null) {
paint.setColorFilter(colorMatrixColorFilter);
}
canvas.drawBitmap(bitmap, null, rectF, paint);
canvas.save();
}
/**
* @param light 0f -2f
*/
public void changeLight(float light) {
colorMatrix = new ColorMatrix();
colorMatrix.setScale(light, light, light, 1f);
colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
invalidate();
}
/**
* @param saturaction 0f - 2f
*/
public void changeSaturation(float saturaction) {
colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(saturaction);
colorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
invalidate();
}
其中修改亮度的修改,就是將R、G、B三種顏色的比例不斷增大。

3.3 BlurMaskFilter虛化邊框

MaskFilter有兩個子類:
BlurMaskFilter :可實現(xiàn)模糊效果。
EmbossMaskFilter:可實現(xiàn)凸起效果。
這里用到了BlurMaskFilter 做虛化邊框的效果:
BlurMaskFilter 的構(gòu)造函數(shù):
public BlurMaskFilter(float radius, Blur style)
radius:模糊的寬度。
style:枚舉變量,提供不同的效果:
public enum Blur {
/**
* Blur inside and outside the original border.
*/
NORMAL(0),
/**
* Draw solid inside the border, blur outside.
*/
SOLID(1),
/**
* Draw nothing inside the border, blur outside.
*/
OUTER(2),
/**
* Blur inside the border, draw nothing outside.
*/
INNER(3);
Blur(int value) {
native_int = value;
}
final int native_int;
}
使用模糊效果會用到幾個關(guān)鍵類:BlurMaskFilter、Paint 、canvas。
代碼步驟:
1、初始化BlurMaskFilter。
2、然后通過paint.setMaskFilter()法將BlurMaskFilter設(shè)置給paint。
3、通過canvas.drawBitmap()方法即可實現(xiàn)圖片的模糊效果。(不僅僅是drawBitmap只要drawXX方法中傳入了設(shè)置過BlurMaskFilter的paint都可實現(xiàn)模糊效果)

不過BlurMaskFilter遇到幾個問題:
1、 虛化的顏色由背景由圖片的邊緣顏色決定的,如果圖片邊緣的顏色為白色,那么虛化部分的顏色是白色的。
2、 虛化寬度的最大值并沒有找到。這個類調(diào)用的是native的方法,我不知道怎么去處理。
3、保存圖片之后有點失真。
3.4 其他需要注意的問題
3.4.1、選擇相冊圖片和使用相機的6.0權(quán)限處理
第一步:AndroidManifest.xml文件中申明權(quán)限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
動態(tài)申請權(quán)限:
//申請相機權(quán)限
protected boolean requestCameraPermiss() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_CAMERA);
return false;
}
return true;
}
//申請讀取文件權(quán)限
protected boolean requestAlbumPermiss() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_CAMERA);
return false;
}
return true;
}
3.4.2、Bitmap的壓縮、生成新的bitmap等
3.4.2.1 生成新的Bitmap
如果需要通過一個Bitmap生成一個新的Bitmap,需要將Bitmap畫在一個新的Bitmap畫布上??创a注釋。
@Override
public Bitmap getChangeBitmap() {
//初始化一個Bitmap
Bitmap bitmapAltered = Bitmap.createBitmap((int) rectF.right, (int) rectF.bottom, bitmap.getConfig());
//將初始化的Bitmap當(dāng)作畫布
Canvas canvas = new Canvas(bitmapAltered);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColorFilter(colorMatrixColorFilter);
if (drawType == DRAW_TYPE_MASK) {
if (blurMaskFilter != null) {
paint.setMaskFilter(blurMaskFilter);
}
}
//將一個bitmap畫在畫布上(注:這里的bitmap是一個全局的變量,它就是一個普通的Bitmap)
canvas.drawBitmap(bitmap, null, rectF, paint);
//返回第一個Bitmap即可
return bitmapAltered;
}
3.4.2.2 圖片壓縮的方法:
防止圖片過大導(dǎo)致OOM,這里通過 BitmapFactory.Options 對圖片進(jìn)行壓縮之后再展示。
/**
* 讀取圖片,按照縮放比保持長寬比例返回bitmap對象
* <p>
*
* @param path 圖片全路徑
* @param scale 縮放比例(1到10, 為2時,長和寬均縮放至原來的2分之1,為3時縮放至3分之1,以此類推)
* @return Bitmap
*/
public synchronized static Bitmap readBitmap(String path, int scale) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
// 設(shè)置縮放比例
options.inSampleSize = scale;
// 設(shè)置為false,解析Bitmap對象加入到內(nèi)存中
options.inJustDecodeBounds = false;
// 設(shè)置內(nèi)存不足時,比bitmap對象可以被回收
options.inPurgeable = true;
options.inInputShareable = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
return bitmap;
} catch (Exception e) {
return null;
}
}
3.4.3、圖片的分享
這里通過安卓自帶的方法來做分享:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, imageUrl);
sendIntent.setType("image/");
startActivity(Intent.createChooser(sendIntent, "分享圖片"));

3.5、推薦的鏈接
colorMatrx :
http://www.itdecent.cn/p/9a44d04f39fc
http://www.itdecent.cn/p/a870fb9684d5
6.0權(quán)限:
http://www.itdecent.cn/p/5e05691d9c76
http://blog.csdn.net/yanzhenjie1003/article/details/52503533/
分享圖片:
http://www.itdecent.cn/p/f790833e669d
http://www.itdecent.cn/p/25c84ed9046d
源碼地址:https://github.com/AxeChen/ColorFilter
原創(chuàng)不易,如果大佬對這篇文章感興趣,還望點個贊,給點鼓勵!