1. 概念
色調/色相:物體傳遞的顏色
飽和度:顏色的純度,從0(灰)到100%(飽和)來進行描述
亮度/明度:顏色的相對明暗程度
2. 調整圖像小Demo
創建一個工具類,用來設置圖像的三種參數:
/**
*
* @param bm
* 圖像
* @param hue
* 色相
* @param saturation
* 飽和度
* @param lum
* 亮度
* @return
*/
public static Bitmap handleImageEffect(Bitmap bm, float hue, float saturation,
float lum) {
Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
// 設置抗鋸齒
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 調整色相
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0, hue);
hueMatrix.setRotate(1, hue);
hueMatrix.setRotate(2, hue);
// 飽和度
ColorMatrix satMatrix = new ColorMatrix();
satMatrix.setSaturation(saturation);
// 設置亮度
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum, lum, lum, 1);
// 將三種設置融合
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(hueMatrix);
imageMatrix.postConcat(satMatrix);
imageMatrix.postConcat(lumMatrix);
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
canvas.drawBitmap(bm, 0, 0, paint);
return bmp;
}
然後我們在佈局文件中創建一個ImageView和三個SeekBar用來調整參數,在Activity中實現OnSeekBarChangeListener接口:
private ImageView mImageView;
private SeekBar mSeekBarHue;
private SeekBar mSeekBarSat;
private SeekBar mSeekBarLum;
private static int MAX_VALUE = 255; // SeekBar刻度最大值
private static int MID_VALUE = 127; // SeekBar中間值
private float mHue; // 色調
private float mSat; // 飽和度
private float mLum; // 亮度
private Bitmap mBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_primarycolor);
initView();
}
private void initView() {
mImageView = (ImageView) findViewById(R.id.imageview);
mSeekBarHue = (SeekBar) findViewById(R.id.seekbar_hue);
mSeekBarSat = (SeekBar) findViewById(R.id.seekbar_sat);
mSeekBarLum = (SeekBar) findViewById(R.id.seekbar_lum);
// 設置SeekBar的最大值的刻度
mSeekBarHue.setMax(MAX_VALUE);
mSeekBarSat.setMax(MAX_VALUE);
mSeekBarLum.setMax(MAX_VALUE);
// 設置SeekBar初始值在中間
mSeekBarHue.setProgress(MID_VALUE);
mSeekBarSat.setProgress(MID_VALUE);
mSeekBarLum.setProgress(MID_VALUE);
mSeekBarHue.setOnSeekBarChangeListener(this);
mSeekBarSat.setOnSeekBarChangeListener(this);
mSeekBarLum.setOnSeekBarChangeListener(this);
mBitmap = BitmapFactory
.decodeResource(getResources(), R.drawable.test3);
mImageView.setImageBitmap(mBitmap);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
switch (seekBar.getId()) {
case R.id.seekbar_hue:
mHue = (progress - MID_VALUE) * 1.0F / MID_VALUE * 180;
break;
case R.id.seekbar_sat:
mSat = progress * 1.0F / MID_VALUE;
break;
case R.id.seekbar_lum:
mLum = progress * 1.0F / MID_VALUE;
break;
}
Bitmap bmp = ImageHelper.handleImageEffect(mBitmap, mHue, mSat, mLum);
mImageView.setImageBitmap(bmp);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
3. 顏色矩陣變換
原理:
新創建一個佈局:
<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"
android:orientation="vertical" >
<ImageView
android:id="@+id/imageview"
android:layout_width="300dp"
android:layout_height="0dp"
android:layout_gravity="center_horizontal"
android:layout_margin="20dp"
android:layout_weight="2" />
<GridLayout
android:id="@+id/group"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:columnCount="5"
android:rowCount="4" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="btnChange"
android:text="Change" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="btnReset"
android:text="Reset" />
</LinearLayout>
編寫Acitvity:
public class ColorMatrixActivity extends Activity {
private ImageView mImageView;
private GridLayout mGroup;
private Bitmap mBitmap;
private int mEditTextWidth, mEditTextHeight;
private EditText[] mEts = new EditText[20];
private float[] mColorMatrix = new float[20];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_colormatrix);
initView();
}
private void initView() {
mBitmap = BitmapFactory
.decodeResource(getResources(), R.drawable.test1);
mImageView = (ImageView) findViewById(R.id.imageview);
mGroup = (GridLayout) findViewById(R.id.group);
mImageView.setImageBitmap(mBitmap);
mGroup.post(new Runnable() {
@Override
public void run() {
// 初始化每一個EditText的寬和高
mEditTextWidth = mGroup.getWidth() / 5;
mEditTextHeight = mGroup.getHeight() / 4;
addEditText();
initMatrix();
}
});
}
/**
* 創建每一個EditText,並添加到數組中保存
*/
private void addEditText() {
for (int i = 0; i < 20; i++) {
EditText editText = new EditText(this);
mEts[i] = editText;
mGroup.addView(editText, mEditTextWidth, mEditTextHeight);
}
}
/**
* 初始化矩陣
*/
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));
}
}
}
/**
* 取得每一個EditText的值,賦給數組
*/
private void getMatrix() {
for (int i = 0; i < 20; i++) {
mColorMatrix[i] = Float.valueOf(mEts[i].getText().toString());
}
}
/**
* 將新的顏色矩陣設置到畫布上
*/
private void setImageMatrix() {
Bitmap bitmap = Bitmap.createBitmap(mBitmap.getWidth(),
mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.set(mColorMatrix);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(mBitmap, 0, 0, paint);
mImageView.setImageBitmap(bitmap);
}
/**
* 執行變化顏色矩陣
*
* @param v
*/
public void btnChange(View v) {
getMatrix();
setImageMatrix();
}
public void btnReset(View v) {
initMatrix();
getMatrix();
setImageMatrix();
}
}
4. 像素點分析
底片效果算法:
newR = 255 - oldR;
newG = 255 - oldG;
newB = 255 - oldB;
老照片效果:
newR = (int) (0.393 * oldR + 0.769 * oldG + 0.189 * oldB);
newG = (int) (0.349 * oldR + 0.686 * oldG + 0.168 * oldB);
newB = (int) (0.272 * oldR + 0534 * oldG + 0.131* oldB);
浮雕效果:
有ABC三點,求B點浮雕效果:
B.R = C.R - B.R + 127;
B.G = C.G - B.G + 127;
B.B = C.B - B.b + 127;
擴充ImageHelper工具類,編寫轉換成底片效果的方法:
/**
* 將圖片處理成底片效果
*
* @param bm
* @return
*/
public static Bitmap handlerImageNegative(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
// 使用寬乘以高的數組來保存所有的像素點
int[] oldPx = new int[width * height];
int[] newPx = new int[width * height];
int color;
int r, g, b, a; // 保存顏色中取出的分量
Bitmap bmp = Bitmap
.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bm.getPixels(oldPx, 0, width, 0, 0, width, height);
for (int i = 0; i < width * height; i++) {
color = oldPx[i];
// 取出每一個分量
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
r = 255 - r;
g = 255 - g;
b = 255 - b;
if (r > 255) {
r = 255;
} else if (r < 0) {
r = 0;
}
if (g > 255) {
g = 255;
} else if (g < 0) {
g = 0;
}
if (b > 255) {
b = 255;
} else if (b < 0) {
b = 0;
}
newPx[i] = Color.argb(a, r, g, b);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}
在Activity中寫相應代碼:
mImageView2.setImageBitmap(ImageHelper.handlerImageNegative(bitmap));
照片懷舊效果的處理:
/**
* 將圖片處理成懷舊效果
*
* @param bm
* @return
*/
public static Bitmap handlerImageOldPhoto(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
// 使用寬乘以高的數組來保存所有的像素點
int[] oldPx = new int[width * height];
int[] newPx = new int[width * height];
int color;
int r, g, b, a; // 保存顏色中取出的分量
Bitmap bmp = Bitmap
.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bm.getPixels(oldPx, 0, width, 0, 0, width, height);
for (int i = 0; i < width * height; i++) {
color = oldPx[i];
// 取出每一個分量
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
r = (int) (0.393 * r + 0.769 * g + 0.189 * b);
g = (int) (0.349 * r + 0.686 * g + 0.168 * b);
b = (int) (0.272 * r + 0534 * g + 0.131 * b);
if (r > 255) {
r = 255;
}
if (g > 255) {
g = 255;
}
if (b > 255) {
b = 255;
}
newPx[i] = Color.argb(a, r, g, b);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}
照片浮雕效果的處理:
/**
* 將圖片處理成浮雕效果
*
* @param bm
* @return
*/
public static Bitmap handlerImageRilievo(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
// 使用寬乘以高的數組來保存所有的像素點
int[] oldPx = new int[width * height];
int[] newPx = new int[width * height];
int color;
int r, g, b, a; // 保存顏色中取出的分量
int r1, g1, b1; // 保存顏色中取出的分量
int colorBefore; // 保存之前的像素值
Bitmap bmp = Bitmap
.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bm.getPixels(oldPx, 0, width, 0, 0, width, height);
for (int i = 1; i < width * height; i++) {
colorBefore = oldPx[i - 1];
r = Color.red(colorBefore);
g = Color.green(colorBefore);
b = Color.blue(colorBefore);
a = Color.alpha(colorBefore);
color = oldPx[i];
// 取出每一個分量
r1 = Color.red(color);
g1 = Color.green(color);
b1 = Color.blue(color);
r = r - r1 + 127;
g = g - g1 + 127;
b = b - b1 + 127;
if (r > 255) {
r = 255;
}
if (g > 255) {
g = 255;
}
if (b > 255) {
b = 255;
}
newPx[i] = Color.argb(a, r, g, b);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}