R - red G - Green B - Blue A - Alphajava
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0, hue);//紅
hueMatrix.setRotate(1, hue);//綠
hueMatrix.setRotate(2, hue);//藍
正常值:hue = 0.0f
經常使用取值範圍:hue ∈ (-180.0f, 180.0f)
複製代碼
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
正常值:saturation = 1.0f
經常使用取值範圍:saturation ∈ (0.0f, 2.0f)
複製代碼
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum, lum, lum, 1);
正常值:lum = 1.0f
經常使用取值範圍:lum ∈ (0.0f, 2.0f)
複製代碼
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(hueMatrix);
imageMatrix.postConcat(saturationMatrix);
imageMatrix.postConcat(lumMatrix);
複製代碼
Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
canvas.drawBitmap(bitmap, 0, 0, paint);
imageView.setImageBitmap(bmp);
複製代碼
{1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0}
複製代碼
{a, b, c, d, e, {R {aR + bR + cR + dR + e, {R1
f, g, h, i, j, G fG + gG + hG + iG + j, G1
k, l, m, n, o, x B = kB + lB + mB + nB + o, = B1
p, q, r, s, t} A pA + qA + rA + sA + t} A1}
1}
第一行控制R
第二行控制G
第三行控制B
第四行控制A
第五列:顏色的偏移量
複製代碼
public static Bitmap handleImageMatrix(Bitmap bitmap, float[] matrixValues) {
Bitmap bmp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColorFilter(new ColorMatrixColorFilter(matrixValues));
canvas.drawBitmap(bitmap, 0, 0, paint);
return bmp;
}
複製代碼
這裏對每個像素點進行處理
ABC:表明三個挨着的像素點
-
底片效果算法:
B.r = 255 - B.r;
B.g = 255 - B.g;
B.b = 255 - B.b;
-
老照片效果算法:
newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
newG = (int) (0.249 * pixR + 0.686 * pixG + 0.168 * pixB);
newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
-
浮雕效果算法:
B.r = C.r - B.r + 127;
B.g = C.g - B.g + 127;
B.b = C.b - B.b + 127;
複製代碼
/**
* 限制argb取值範圍
*
* @param value
* @return
*/
public static int limit(int value) {
if (value > 255) {
return 255;
} else if (value < 0) {
return 0;
}
return value;
}
複製代碼
/**
* 底片
*
* @param bitmap
* @return
*/
public static Bitmap handleImagePix(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int r, g, b, a;
int[] imgPixels = new int[width * height];
int[] newImgPixels = new int[width * height];
bitmap.getPixels(imgPixels, 0, width, 0, 0, width, height);
for (int i = 0; i < imgPixels.length; i++) {
r = Color.red(imgPixels[i]);
g = Color.green(imgPixels[i]);
b = Color.blue(imgPixels[i]);
a = Color.alpha(imgPixels[i]);
r = limit(255 - r);
g = limit(255 - g);
b = limit(255 - b);
newImgPixels[i] = Color.argb(a, r, g, b);
}
Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
newBitmap.setPixels(newImgPixels, 0, width, 0, 0, width, height);
return newBitmap;
}
複製代碼
/**
* 懷舊
*
* @param bitmap
* @return
*/
public static Bitmap handleImagePix2(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int r, g, b, a, newR, newG, newB;
int[] imgPixels = new int[width * height];
int[] newImgPixels = new int[width * height];
bitmap.getPixels(imgPixels, 0, width, 0, 0, width, height);
for (int i = 0; i < imgPixels.length; i++) {
r = Color.red(imgPixels[i]);
g = Color.green(imgPixels[i]);
b = Color.blue(imgPixels[i]);
a = Color.alpha(imgPixels[i]);
newR = limit((int) (0.393 * r + 0.769 * g + 0.189 * b));
newG = limit((int) (0.249 * r + 0.686 * g + 0.168 * b));
newB = limit((int) (0.272 * r + 0.534 * g + 0.131 * b));
newImgPixels[i] = Color.argb(a, newR, newG, newB);
}
Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
newBitmap.setPixels(newImgPixels, 0, width, 0, 0, width, height);
return newBitmap;
}
複製代碼
/**
* 浮雕
*
* @param bitmap
* @return
*/
public static Bitmap handleImagePix3(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int r, g, b, a, cr, cg, cb;
int[] imgPixels = new int[width * height];
int[] newImgPixels = new int[width * height];
bitmap.getPixels(imgPixels, 0, width, 0, 0, width, height);
for (int i = 0; i < imgPixels.length - 1; i++) {
r = Color.red(imgPixels[i]);
g = Color.green(imgPixels[i]);
b = Color.blue(imgPixels[i]);
a = Color.alpha(imgPixels[i]);
cr = Color.red(imgPixels[i + 1]);
cg = Color.green(imgPixels[i + 1]);
cb = Color.blue(imgPixels[i + 1]);
r = limit(cr - r + 127);
g = limit(cg - g + 127);
b = limit(cb - b + 127);
newImgPixels[i] = Color.argb(a, r, g, b);
}
Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
newBitmap.setPixels(newImgPixels, 0, width, 0, 0, width, height);
return newBitmap;
}
複製代碼
{a, b, c, X a * X + b * Y + c X′
d, e, f, x Y = d * X + e * Y + f = Y′
g, h, i} 1 g * X + h * Y + i 1′
複製代碼
{1, 0, 0,
0, 1, 0,
0, 0, 1}
複製代碼
△x:表示x軸方向平移量
△y:表示y軸方向平移量
{1, 0, △x, x1 x1 + △x
0, 1, △y, x y1 = y1 + △y
0, 0, 1} 1 1
複製代碼
P點座標(x1, y1),鏈接座標中心O,與x軸造成夾角α
r = OP
則以下等式成立
x1 = r * cosα
y1 = r * sinα
-
-
當以O爲中心,r爲軸,旋轉θ角度,此時P點旋轉後坐標爲(x₂, y₂)
則以下等式成立
x2 = r * cos(α + θ) = r * cosα * cosθ - r * sinα * sinθ = x1 * cosθ - y1 * sinθ
y2 = r * sin(α + θ) = r * sinα * cosθ + r * cosα * sinθ = y1 * cosθ + x1 * sinθ
-
-
將上邊等式轉換成矩陣表示
{cosθ, -sinθ, 0, x1 x1 * cosθ - y1 * sinθ x2
sinθ, cosθ, 0, x y1 = y1 * cosθ + x1 * sinθ = y2
0, 0, 1} 1 1 1
複製代碼
P點座標:(x1, y1),x方向縮放k₁,y方向縮放k₂,
那麼新P點座標(x₂, y₂)知足如下等式:
x2 = x1 * k1
y2 = y1 * k2
-
-
將上邊等式轉換成矩陣表示
{k1, 0, 0, x1 x1 * k1 x2
0, k2, 0, x y1 = y1 * k2 = y2
0, 0, 1} 1 1 1
複製代碼
變換公式:
x2 = x1 + y1 * k1
y2 = y1 + x1 * k2
-
-
將上邊等式轉換成矩陣表示
{1, k1, 0, x1 x1 + y1 * k1 x2
k2, 1, 0, x y1 = y1 + x1 * k2 = y2
0, 0, 1} 1 1 1
複製代碼
{a, b, c,
d, e, f,
g, h, i}
-
-
經過上邊變換得出:
a,e:控制縮放
c,f:控制平移
b,d:控制錯切
複製代碼
效果與代碼 算法
public class ImageMatrixView extends View{
private Bitmap bitmap;
private Matrix matrix;
public ImageMatrixView(Context context) {
super(context);
init();
}
public ImageMatrixView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ImageMatrixView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
matrix = new Matrix();
float[] translateF = new float[]{
1, 0, 140,
0, 1, 140,
0, 0, 1
};
matrix.setValues(translateF);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(ImageHelper.handleImagePix2(bitmap), 0, 0, null);
canvas.drawBitmap(bitmap, matrix, null);
}
}
複製代碼
安卓中提供的一些矩陣變換API接口canvas
縮放:matrix.setScale()
旋轉:matrix.setRotate()
平移:matrix.setTranslate()
錯切:matrix.setSkew()
矩陣組合:matrix.post...
複製代碼
Xfermode 數組
畫布上先畫上去的爲Dst,後畫上去的爲Src。這裏經過SrcIn實現圖片圓角。bash
public class RoundRectView extends View {
private Bitmap outBitmap;
private Matrix matrix;
public RoundRectView(Context context) {
super(context);
init();
}
public RoundRectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundRectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setLayerType(LAYER_TYPE_SOFTWARE, null);//關閉硬件加速
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.b);
outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outBitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//Dst
canvas.drawRoundRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), 100, 100, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//設置風格
//Src
canvas.drawBitmap(bitmap, 0, 0, paint);
matrix = new Matrix();//將圖片縮小一倍
matrix.setScale(0.5f, 0.5f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(outBitmap, matrix, null);
}
}
複製代碼
public class RoundRectView extends View {
private Bitmap outBitmap;
private Matrix matrix;
public RoundRectView(Context context) {
super(context);
init();
}
public RoundRectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundRectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
matrix = new Matrix();//將圖片縮小
matrix.setScale(0.7f, 0.7f);
matrix.postTranslate(100f, 0f);
setLayerType(LAYER_TYPE_SOFTWARE, null);//關閉硬件加速
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.b);
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.mask);
outBitmap = Bitmap.createBitmap(bitmap2.getWidth(), bitmap2.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outBitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawBitmap(bitmap2, matrix, null);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, 0, 0, paint);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(outBitmap, matrix, null);
}
}
複製代碼
線性漸變 環形漸變 掃描漸變 組合漸變ide
簡單的實現一下倒影效果post
public class ReflectView extends View {
private Bitmap srcBitmap;
private Bitmap refBitmap;
private Paint paint;
public ReflectView(Context context) {
super(context);
init();
}
public ReflectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ReflectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
//1.原圖片
srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.e);
//2.建立倒影圖
Matrix matrix = new Matrix();//經過矩陣變換:y軸對摺
matrix.setScale(1, -1);
refBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
//3.設置畫筆漸變
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//線性漸變
paint.setShader(new LinearGradient(0, srcBitmap.getHeight(), 0, srcBitmap.getHeight() * 1.4f,
0xDD000000, 0x10000000,
Shader.TileMode.CLAMP));
//4.設置混合模式
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(srcBitmap, 0, 0, null);
canvas.drawBitmap(refBitmap, 0, srcBitmap.getHeight(), null);
canvas.drawRect(0, srcBitmap.getHeight(), srcBitmap.getWidth(), srcBitmap.getHeight() * 2, paint);
}
}
複製代碼
public class BitmapShaderView extends View {
private Bitmap bitmap;
private Paint paint;
private BitmapShader bitmapShader;
public BitmapShaderView(Context context) {
super(context);
init();
}
public BitmapShaderView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public BitmapShaderView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.d);
bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(bitmapShader);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(700, 400, 400, paint);
}
}
複製代碼
public class MeshView extends View {
private int WIDTH = 200;//橫向網格
private int HEIGHT = 200;//縱向網格
private int COUNT = (WIDTH + 1) * (HEIGHT + 1);//全部點的數量
private float[] orig = new float[COUNT * 2];//保存全部點的座標,原始座標
private float[] verts = new float[COUNT * 2];//保存全部點的座標,變換後的座標
private Bitmap bitmap;
private float k = 1;//變化偏移量
public MeshView(Context context) {
super(context);
init();
}
public MeshView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public MeshView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.f);
float width = bitmap.getWidth();
float height = bitmap.getHeight();
int index = 0;
//將全部點的座標點保存到orig,verts。
//A(x1,y1),B(x2,y2),C(x3,y3)是挨着的三點,保存在數組中的方式爲:[x1,y1,x2,y2,x3,y3]
for (int i = 0; i < HEIGHT + 1; i++) {
float fy = height * i / HEIGHT;
for (int j = 0; j < WIDTH + 1; j++) {
orig[index * 2] = verts[index * 2] = width * j / WIDTH;
orig[index * 2 + 1] = verts[index * 2 + 1] = fy + 100;
index ++;
}
}
}
@Override
protected void onDraw(Canvas canvas) {
int index = 0;
//波浪,x座標不變,y座標改變
for (int i = 0; i < HEIGHT + 1; i++) {
for (int j = 0; j < WIDTH + 1; j++) {
float offsetY = (float) Math.sin((float)j / WIDTH * 2 * Math.PI + k * 2 * Math.PI);
verts[index * 2 + 1] = orig[index * 2 + 1] + offsetY * 80;
index ++;
}
}
k += 0.1f;
canvas.drawBitmapMesh(bitmap, WIDTH, HEIGHT, verts, 0, null, 0, null);
invalidate();
}
}
複製代碼
學習路徑: Android圖像處理-打造美圖秀秀從它開始: http://www.imooc.com/learn/302 Android圖像處理-變"換"莫測的圖像: http://www.imooc.com/learn/343學習