Android對于圖片的處理以故,最常使用到的數(shù)據(jù)結(jié)構(gòu)是位圖——Bitmap,它包含了一張圖片所有的數(shù)據(jù)裆操。整個圖片都是由點陣和顏色值組成的怒详,所謂點陣就是一個包含像素的矩陣,每一個元素對應(yīng)著圖片的一個像素踪区。而顏色值——ARGB昆烁,分別對應(yīng)著透明度、紅缎岗、綠静尼、藍這四個通道分量,他們共同決定了每個像素點顯示的顏色。上圖顯示的就是色光三原色鼠渺。
色彩矩陣分析
在Android中蜗元,系統(tǒng)使用一個顏色矩陣——ColorMatrix,來處理圖像的色彩效果系冗。對于圖像的每個像素點奕扣,都有一個顏色分量矩陣用來保存顏色的RGBA值(下圖矩陣C),Android中的顏色矩陣是一個 4x5 的數(shù)字矩陣掌敬,它用來對圖片的色彩進行處理(下圖矩陣A)惯豆。 如下:
如果我們想要改變一張圖像的色彩顯示效果,在Android系統(tǒng)中奔害,我們會用矩陣的乘法運算來修改顏色分量矩陣的值楷兽。上面矩陣A就是一個 4x5 的顏色矩陣。在Android中华临,它會以一維數(shù)組的形式來存儲[a,b,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]芯杀,而C則是一個顏色矩陣分量。在處理圖像時雅潭,使用矩陣乘法運算AC來處理顏色分量矩陣揭厚,如下:
利用線性代數(shù)知識可知:
R1 = aR + bG + cB + dA + e;
G1 = fR + gG + hB + iA + j;
B1 = kR + lG + mB + nA + o;
A1 = pR + qG + rB + sA + t;
從這個公式可以發(fā)現(xiàn),矩陣A中:
- 第一行的 abcde 用來決定新的顏色值中的R——紅色
- 第二行的 fghij 用來決定新的顏色值中的G——綠色
- 第三行的 klmno 用來決定新的顏色值中的B——藍色
- 第四行的 pqrst 用來決定新的顏色值中的A——透明度
- 矩陣A中第五列——ejot 值分別用來決定每個分量中的 offset 扶供,即偏移量
這樣劃分好后筛圆,這些值的作用就比較明確了。
初始顏色矩陣
接下來椿浓,我們重新看一下矩陣變換的計算公式太援,以R分量為例,
R1 = aR + bG + cB + dA + e;
如果令 a=1扳碍,b提岔、c、d笋敞、e都等于0碱蒙,則有 R1=R 。同理對第二液样、三振亮、四巧还、行進行操作鞭莽,可以構(gòu)造出一個矩陣,如下:
把這個矩陣代入公式 R=AC麸祷,根據(jù)矩陣乘法運算法則澎怒,可得R1=R,G1=G,B1=B喷面,A1=A星瘾。即不會對原有顏色進行任何修改,所以這個矩陣通常被用來作為初始顏色矩陣惧辈。
改變顏色值
那么琳状,當我們想要改變顏色值的時候,通常有兩種方法盒齿。
- 改變顏色的 offset(偏移量)的值念逞;
- 改變對應(yīng) RGBA 值的系數(shù)。
1.改變偏移量
從前面的分析中可知边翁,改變顏色的偏移量就是改變顏色矩陣的第五列的值翎承,其他保持初始矩陣的值即可。如下示例:
上面的操作中改變了 R符匾、G 對應(yīng)的顏色偏移量叨咖,那么結(jié)果就是圖像的紅色和綠色分量增加了100,即整體色調(diào)偏黃顯示啊胶。
看看下面的對比圖就一目了然了:
2.改變顏色系數(shù)
如下操作:
改變 G 分量對應(yīng)的系數(shù) g 的值甸各,增加到2倍,這樣在矩陣運算后焰坪,圖像會整體色調(diào)偏綠顯示痴晦。
請看下面的對比圖:
通過前面的分析,我們知道調(diào)整顏色矩陣可以改變圖像的色彩效果琳彩,圖像的色彩處理很大程度上就是在尋找處理圖像的顏色矩陣誊酌。
下面,我們著手寫一個demo露乏,模擬一個 4x5 的顏色矩陣來體驗一下上面對顏色矩陣的分析碧浊。
先來看看效果圖:
關(guān)鍵代碼是將 4x5 矩陣轉(zhuǎn)換成一維數(shù)組,然后再將這一維數(shù)組設(shè)置到ColorMatrix類里去瘟仿,請看代碼:
//將矩陣設(shè)置到圖像
private void setImageMatrix() {
Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(mColorMatrix);//將一維數(shù)組設(shè)置到ColorMatrix
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap, 0, 0, paint);
iv_photo.setImageBitmap(bmp);
}
這個demo里面的代碼比較簡單箱锐,我在這里就全部貼出來了,先上xml布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.deeson.mycolormatrix.MainActivity"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_photo"
android:layout_width="300dp"
android:layout_height="0dp"
android:layout_weight="3"
android:layout_gravity="center_horizontal"/>
<GridLayout
android:id="@+id/matrix_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4"
android:columnCount="5"
android:rowCount="4">
</GridLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_change"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="change"/>
<Button
android:id="@+id/btn_reset"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="reset"/>
</LinearLayout>
</LinearLayout>
在 MainActivity 類這里有一個地方要注意的就是劳较,我們無法在 onCreate() 方法中獲得 4x5 矩陣視圖的寬高值驹止,所以通過 View 的 post() 方法,在視圖創(chuàng)建完畢后獲得其寬高值观蜗。如下:
matrixLayout.post(new Runnable() {
@Override
public void run() {
mEtWidth = matrixLayout.getWidth() / 5;
mEtHeight = matrixLayout.getHeight() / 4;
addEts();
initMatrix();
}
});
接下來是 MainActivity 類的全部代碼臊恋,也沒有幾行,相信大家都能看得明白墓捻,如下:
package com.example.deeson.mycolormatrix;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.InputType;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridLayout;
import android.widget.ImageView;
/**
* @author Deeson
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Bitmap bitmap;
ImageView iv_photo;
GridLayout matrixLayout;
//每個edittext的寬高
int mEtWidth;
int mEtHeight;
//保存20個edittext
EditText[] mEts = new EditText[20];
//一維數(shù)組保存20個矩陣值
float[] mColorMatrix = new float[20];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.iv_model);
iv_photo = (ImageView) findViewById(R.id.iv_photo);
matrixLayout = (GridLayout) findViewById(R.id.matrix_layout);
Button btn_change = (Button) findViewById(R.id.btn_change);
Button btn_reset = (Button) findViewById(R.id.btn_reset);
btn_change.setOnClickListener(this);
btn_reset.setOnClickListener(this);
iv_photo.setImageBitmap(bitmap);
//我們無法在onCreate()方法中獲得視圖的寬高值抖仅,所以通過View的post()方法,在視圖創(chuàng)建完畢后獲得其寬高值
matrixLayout.post(new Runnable() {
@Override
public void run() {
mEtWidth = matrixLayout.getWidth() / 5;
mEtHeight = matrixLayout.getHeight() / 4;
addEts();
initMatrix();
}
});
}
//動態(tài)添加edittext
private void addEts() {
for (int i = 0; i < 20; i++) {
EditText et = new EditText(this);
et.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
mEts[i] = et;
matrixLayout.addView(et, mEtWidth, mEtHeight);
}
}
//初始化顏色矩陣
private void initMatrix() {
for (int i = 0; i < 20; i++) {
if (i % 6 == 0) {
mEts[i].setText(String.valueOf(1));
} else {
mEts[i].setText(String.valueOf(0));
}
}
}
//獲取矩陣值
private void getMatrix() {
for (int i = 0; i < 20; i++) {
String matrix = mEts[i].getText().toString();
boolean isNone = null == matrix || "".equals(matrix);
mColorMatrix[i] = isNone ? 0.0f : Float.valueOf(matrix);
if (isNone) {
mEts[i].setText("0");
}
}
}
//將矩陣設(shè)置到圖像
private void setImageMatrix() {
Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(mColorMatrix);//將一維數(shù)組設(shè)置到ColorMatrix
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap, 0, 0, paint);
iv_photo.setImageBitmap(bmp);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_change:
//作用矩陣效果
break;
case R.id.btn_reset:
//重置矩陣效果
initMatrix();
break;
}
//作用矩陣效果
getMatrix();
setImageMatrix();
}
}
MyColorMatrixDemo 下載地址
至此,我們可以通過 MyColorMatrixDemo 來對圖像的色彩特效進行精確地修改撤卢。
在了解了Android的顏色矩陣之后环凿,我們知道可以通過修改顏色矩陣的值來改變圖像的色彩顯示效果。接下來放吩,我們看看Android系統(tǒng)給我們提供的快速修改圖像色彩特效的API智听。
圖像的色光屬性
在色彩處理中,通常使用以下三個角度來描述一個圖像渡紫。
- 色調(diào)——物體傳播的顏色
- 飽和度——顏色的純度瞭稼,從0(灰)到100%(飽和)來進行描述
- 亮度——顏色的相對明暗程度
在Android 的 ColorMatrix 顏色矩陣中也封裝了一些 API 來快速調(diào)整上面這三個顏色參數(shù),而不用每次都去計算矩陣的值腻惠。
下面我們來看看如何調(diào)用這些API:
詳情可參考這個文檔 https://developer.android.com/reference/android/graphics/ColorMatrix.html
- 色調(diào)
Android系統(tǒng)提供了 setRotate(int axis, float degrees)方法來修改顏色的色調(diào)环肘。第一個參數(shù),用0集灌、1悔雹、2分別代表紅、綠欣喧、藍三個顏色通道腌零,第二個參數(shù)就是要修改的值,如下:
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0,hue0);
hueMatrix.setRotate(1,hue1);
hueMatrix.setRotate(2,hue2);
Android系統(tǒng)的 setRotate(int axis, float degrees) 方法其實就是對色彩的旋轉(zhuǎn)運算唆阿。RGB色是如何旋轉(zhuǎn)的呢益涧,首先用R、G驯鳖、B三色建立三維坐標系闲询,如下:
這里,我們可以把一個色彩值看成三維空間里的一個點浅辙,色彩值的三個分量可以看成該點對應(yīng)的坐標(三維坐標)扭弧。我們先不考慮,在三個維度綜合情況下是怎么旋轉(zhuǎn)的记舆,我們先看看鸽捻,在某個軸做為Z軸,在另兩個軸形成的平面上旋轉(zhuǎn)的情況泽腮。假如御蒲,我們現(xiàn)在需要圍繞藍色軸進行旋轉(zhuǎn),我們對著藍色箭頭觀察由紅色和綠色構(gòu)造的平面诊赊。然后順時針旋轉(zhuǎn) α 度厚满。 如下圖所示:
在圖中,我們可以看到豪筝,在旋轉(zhuǎn)后痰滋,原 R 在 R 軸的分量變?yōu)椋篟*cosα兄世,且原G分量在旋轉(zhuǎn)后在 R 軸上也有了分量掂碱,所以我們要加上這部分分量,因此最終的結(jié)果為 R’=R*cosα + G*sinα绞旅,同理严望,在計算 G’ 時多艇,因為 R 的分量落在了負軸上,所以我們要減去這部分像吻,故 G’=G*cosα - R*sinα峻黍;
回憶之前講過的矩陣乘法運算法則,下圖:
![][01]
R1 = aR + bG + cB + dA + e;
G1 = fR + gG + hB + iA + j;
B1 = kR + lG + mB + nA + o;
A1 = pR + qG + rB + sA + t;
我們可以計算出圍繞藍色分量軸順時針旋轉(zhuǎn) α 度的顏色矩陣如下:
同理拨匆,我們可以得出圍繞紅色分量軸順時針旋轉(zhuǎn) α 度的顏色矩陣:
圍繞綠色分量軸順時針旋轉(zhuǎn) α 度的顏色矩陣:
通過上面的分析姆涩,我們可以知道,當圍繞紅色分量軸進行色彩旋轉(zhuǎn)時惭每,由于當前紅色分量軸的色彩是不變的骨饿,而僅利用三角函數(shù)來動態(tài)的變更綠色和藍色的顏色值。這種改變就叫做色相調(diào)節(jié)台腥。當圍繞紅色分量軸旋轉(zhuǎn)時宏赘,是對圖片就行紅色色相的調(diào)節(jié);同理黎侈,當圍繞藍色分量軸旋轉(zhuǎn)時察署,就是對圖片就行藍色色相調(diào)節(jié);當然峻汉,當圍繞綠色分量軸旋轉(zhuǎn)時贴汪,就是對圖片進行綠色色相的調(diào)節(jié).
下面是Android系統(tǒng)對色調(diào)修改的源碼,我們可以看得到休吠,源碼對第二個參數(shù)進行轉(zhuǎn)換成弧度嘶是,即對紅、綠蛛碌、藍三個顏色通道分別進行旋轉(zhuǎn)聂喇,那我們在第二個參數(shù)中傳入我們平時用的度數(shù)即可。通過對源碼的閱讀蔚携,我們也知道希太,第二個參數(shù)最終被設(shè)置的數(shù)值范圍為 [-1,1] ,然后再設(shè)置到顏色矩陣中酝蜒。即我們在第二個參數(shù)傳入[-180誊辉,180]范圍的值(一個最小周期)即可。
另外亡脑,相信大家都可以看得出來堕澄,系統(tǒng)對存儲顏色矩陣的一維數(shù)組元素的值的修改正好符合上面的分析邀跃。
/**
* Set the rotation on a color axis by the specified values.
* <p>
* <code>axis=0</code> correspond to a rotation around the RED color
* <code>axis=1</code> correspond to a rotation around the GREEN color
* <code>axis=2</code> correspond to a rotation around the BLUE color
* </p>
*/
public void setRotate(int axis, float degrees) {
reset();
double radians = degrees * Math.PI / 180d;
float cosine = (float) Math.cos(radians);
float sine = (float) Math.sin(radians);
switch (axis) {
// Rotation around the red color
case 0:
mArray[6] = mArray[12] = cosine;
mArray[7] = sine;
mArray[11] = -sine;
break;
// Rotation around the green color
case 1:
mArray[0] = mArray[12] = cosine;
mArray[2] = -sine;
mArray[10] = sine;
break;
// Rotation around the blue color
case 2:
mArray[0] = mArray[6] = cosine;
mArray[1] = sine;
mArray[5] = -sine;
break;
default:
throw new RuntimeException();
}
}
- 飽和度
Android系統(tǒng)提供了 setSaturation(float sat) 方法來修改顏色的飽和度。參數(shù) float sat:表示把當前色彩飽和度放大的倍數(shù)蛙紫。取值為0表示完全無色彩拍屑,即灰度圖像(黑白圖像);取值為1時坑傅,表示色彩不變動僵驰;當取值大于1時,顯示色彩過度飽和 如下:
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
同樣貼出修改飽和度值的源碼唁毒,通過源碼我們可以看到系統(tǒng)是通過改變顏色矩陣中對角線上系數(shù)的比例來改變飽和度蒜茴。
/**
* Set the matrix to affect the saturation of colors.
*
* @param sat A value of 0 maps the color to gray-scale. 1 is identity.
*/
public void setSaturation(float sat) {
reset();
float[] m = mArray;
final float invSat = 1 - sat;
final float R = 0.213f * invSat;
final float G = 0.715f * invSat;
final float B = 0.072f * invSat;
m[0] = R + sat; m[1] = G; m[2] = B;
m[5] = R; m[6] = G + sat; m[7] = B;
m[10] = R; m[11] = G; m[12] = B + sat;
}
- 亮度
當三原色以相同比例進行混合時,就會顯示出白色浆西。Android系統(tǒng)正是利用這個原理對圖像進行亮度的改變粉私。如下:
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum,lum,lum,1);
同樣貼出修改亮度值的源碼,當亮度為 0 時近零,圖像就變成全黑了。通過對源碼的閱讀秒赤,我們可以知道猪瞬, 系統(tǒng)將顏色矩陣置為初始初始顏色矩陣,再將紅痊项、綠、藍训枢、透明度四個分量通道對應(yīng)的系數(shù)修改成我們傳入的值。
/**
* Set this colormatrix to scale by the specified values.
*/
public void setScale(float rScale, float gScale, float bScale,
float aScale) {
final float[] a = mArray;
for (int i = 19; i > 0; --i) {
a[i] = 0;
}
a[0] = rScale;
a[6] = gScale;
a[12] = bScale;
a[18] = aScale;
}
當然恒界,除了單獨使用上面的三種方法來進行顏色效果的處理之外睦刃,Android系統(tǒng)還封裝了矩陣的乘法運算。它提供了 postConcat(ColorMatrix postmatrix) 方法來將矩陣的作用效果混合十酣,從而疊加處理效果涩拙。如下:
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(hueMatrix);
imageMatrix.postConcat(saturationMatrix);
imageMatrix.postConcat(lumMatrix);
下面际长,通過一個demo來給大家看看,修改色調(diào)兴泥、飽和度工育、亮度的效果。
首先我們看看效果圖郁轻,如下:
這里的 demo 通過滑動三個 SeekBar 來改變不同的值翅娶,并將這些數(shù)值作用到對應(yīng)色調(diào)文留、飽和度好唯、亮度的顏色矩陣中,最后通過 ColorMatrix 的 postConcat() 方法來混合這三個被修改的顏色矩陣的顯示效果燥翅。
關(guān)鍵設(shè)置圖像矩陣的代碼如下:
public static Bitmap handleImageEffect(Bitmap oriBmp, Bitmap bmp, float hue, float saturation, float lum) {
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0, hue);
hueMatrix.setRotate(1, hue);
hueMatrix.setRotate(2, hue);
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum, lum, lum, 1);
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(hueMatrix);
imageMatrix.postConcat(saturationMatrix);
imageMatrix.postConcat(lumMatrix);
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
canvas.drawBitmap(oriBmp, 0, 0, paint);
return bmp;
}
這里需要注意的是骑篙,Android系統(tǒng)不允許直接修改原圖,類似 Photoshop 中的鎖定森书,必須通過原圖創(chuàng)建一個同樣大小的 Bitmap 靶端,并將原圖繪制到該 Bitmap 中,以一個副本的形式來修改圖像凛膏。
在設(shè)置好需要處理的顏色矩陣后杨名,通過使用 Paint 類的 setColorFilter() 方法,將通過 imageMatrix 構(gòu)造的 ColorMatrixColorFilter 對象傳遞進去猖毫,并使用這個畫筆來繪制原來的圖像台谍,從而將顏色矩陣作用到圖像中。
接下來我們看看這個demo的xml代碼吁断,很簡單趁蕊,一個 ImageView ,三個 SeekBar 仔役,如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.deeson.mycolor.MainActivity"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_photo"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:src="@drawable/iv_model0"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginLeft="5dp"
android:textColor="@android:color/black"
android:text="色調(diào)"
/>
<SeekBar
android:id="@+id/seekbarHue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="200"
android:progress="100"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
android:textColor="@android:color/black"
android:text="飽和度"
/>
<SeekBar
android:id="@+id/seekbarSaturation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="200"
android:progress="100"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
android:textColor="@android:color/black"
android:text="亮度"
/>
<SeekBar
android:id="@+id/seekbarLum"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="200"
android:progress="100"/>
</LinearLayout>
然后是 MainActivity 類的代碼掷伙,就是獲取三個 SeekBar 的值,如下:
package com.example.deeson.mycolor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.SeekBar;
/**
* @author Deeson
*/
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
ImageView iv_photo;
float mHue = 0.0f;
float mSaturation = 1f;
float mLum = 1f;
float MID_VALUE;
Bitmap oriBitmap,newBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_photo = (ImageView) findViewById(R.id.iv_photo);
SeekBar barHue = (SeekBar) findViewById(R.id.seekbarHue);
SeekBar barSaturation = (SeekBar) findViewById(R.id.seekbarSaturation);
SeekBar barLum = (SeekBar) findViewById(R.id.seekbarLum);
MID_VALUE = barHue.getMax() * 1.0F / 2;
oriBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.iv_model0);
//Android系統(tǒng)不允許直接修改原圖
newBitmap = Bitmap.createBitmap(oriBitmap.getWidth(), oriBitmap.getHeight(), Bitmap.Config.ARGB_8888);
barHue.setOnSeekBarChangeListener(this);
barSaturation.setOnSeekBarChangeListener(this);
barLum.setOnSeekBarChangeListener(this);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
switch (seekBar.getId()) {
case R.id.seekbarHue:
mHue = (progress - MID_VALUE) * 1.0F / MID_VALUE * 180;
break;
case R.id.seekbarSaturation:
mSaturation = progress * 1.0F / MID_VALUE;
break;
case R.id.seekbarLum:
mLum = progress * 1.0F / MID_VALUE;
break;
}
iv_photo.setImageBitmap(ImageHelper.handleImageEffect(oriBitmap,newBitmap, mHue, mSaturation, mLum));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
MyColorDemo 源碼下載
寫到這里又兵,我們差不多就可以自己實現(xiàn)一個圖像美顏處理的APP任柜。當然這只是一個整體的思路,中間還有很多的細節(jié)需要去完善沛厨。我們現(xiàn)在都知道改變顏色矩陣的系數(shù)就能達到一種意想不到的圖片風(fēng)格宙地,比如什么xx色調(diào),xx濾鏡等等俄烁。無非是每種色調(diào)的顏色矩陣的系數(shù)不一樣而已绸栅。
一些常用的圖像處理效果的顏色矩陣
灰度效果
圖像反轉(zhuǎn)
懷舊效果
去色效果
高飽和度
色彩反色
這里是紅綠反色,另外紅藍页屠、藍綠反色原理一樣粹胯,就是把顏色初始矩陣中對應(yīng)顏色通道的值交換處理蓖柔,如下:
后續(xù)
學(xué)習(xí)資料
《Android群英傳》