1.作安卓的大多應該對顏色不太敏感,畢竟咱是敲代碼的,顏色有設計師呢。
2.不過做爲一名在大學被顏色薰(陶)過四年的人,對顏色多少仍是挺親切的(雖然當時挺討厭的)
3.記念也好,記錄也罷,爲它寫篇總結也理所應當
4.若是你以爲並不須要瞭解關於顏色的知識,那你能夠將本文當作一篇科普文(出去跟人家吹吹牛仍是夠用的)react
有個叫牛頓的人拿一塊三棱鏡將太陽光折射出了彩色產生色散現象:
----色散現象說明光在介質中的速度v=c/n(或折射率n)隨光的頻率f而變,從而:證實了光具備波動性
複製代碼
光的色散 | 光的色散圖示 |
---|---|
問:若是把全部非黑的顏料混合,會獲得什麼?----感受一團糟,應該是黑色吧
問:若是把全部非白的光混合,會獲得什麼?----感受愈來愈亮,應該是白色吧
複製代碼
從一開始,這個問題就困擾着我,也將一直困擾這我...
若是說[肉眼所見到的光線,是由波長範圍很窄的電磁波產生的,不一樣波長的電磁波表現爲不一樣的顏色],
那光的疊加也就是波的疊加,貌似有個[波動方程]吧...只能這樣說服本身:
光色疊加是減色模式:會越來約"淡"
顏料色疊加是加色模式:會越來約"濃"
複製代碼
安卓敲代碼的多少都用過
#ffff00
表示黃色吧,這是RGB的一種表現形式
你也能夠用"R:255,G:255,B:0"來表示黃色,其實二者是一個意思,只不過是10進制和16進制的轉化android
RGB的位數:git
RGB還有位數的區別,也就是一個顏色佔幾位,通常是8位,
也就是用1個字節表示一種顏色(一個字節8位)
1個字節(8位)每種顏色有0~255共256種中顏色,三色共表達:256*256*256=16,777,216種顏色
因此RGB並不能表明全部顏色,它只是一個子集,天然界的顏色是無窮的。人類只能模擬
16位是2個字節表明一種顏色,每種顏色有0~65535共65536中顏色,
三色共表達:65536*65536*65536=279213318656種顏色
複製代碼
即在RGB的基礎上添加添加透明度
顏色通道的概念(本身的理解,僅供參考):程序員
大學那會學ps,動不動紅色通道,Alpha通道的,搞得雲裏霧裏,如今想一想
拿ARGB_8888(八位)來講,就至關有四道牆,每道牆上有256扇門分別標上0~255數字
第一道牆叫Alpha(透明度)牆,第二道牆叫R(紅)牆,第二道牆叫G(綠)牆,第二道牆叫B(藍)牆
如今你要從這四道牆的門走到終點,每次進門拿着門牌號,當你走到終點時,門牌號加起來就是顏色
那門,就是通道,若是進紅色的0門(俗稱:紅色通道關閉),從表現上來看最終顏色不帶紅色,以下下圖
複製代碼
爲何編程裏用
int
做爲顏色?github
衆所周知:一個int佔4個字節,也就是4*8個位,恰好用來盛放ARGB_8888。
複製代碼
做爲程序員對CMYK瞭解估計很少,畢竟都在屏幕上,是ARGB的的天下
對於打印使用CMYK,符號是%,以不一樣顏色的百分比調色,理論上只應該有CMY就好了
但實際黑色(K)的要比其餘三色更容易生產,用三張一百塊合成爲一張十塊錢估計沒人會這麼作
至於爲何叫K...也許是RGB先出來的,而後不能叫B,只能叫K了
複製代碼
看到值就能想到大概的顏色編程
顏色有三個維度屬性:色相、明度和飽和度
HSV模型對應於:
圓柱座標系中的一個圓錐形子集,圓錐的頂面對應於V=1。
它包含RGB模型中的R=1,G=1,B=1三個面,所表明的顏色較亮。
色彩H由繞V軸的旋轉角給定。紅色對應於角度0°,綠色對應於角度120°,藍色對應於角度240°。
在HSV顏色模型中,每一種顏色和它的補色相差180°。飽和度S取值從0到1,因此圓錐頂面的半徑爲1。
複製代碼
RGB:R:255 G:255 B:0 #ffff00
CMYK:C:10% M:0 Y:83% K:0
HSV:H:60° S:100% V:100%
複製代碼
好了,科普結束,下面進入正題canvas
顏色使用場景:
1.基本使用:背景、陰影、文字顏色
2.基於Color建立的Bitmap以及疊合模式:Xfermode
3.paint中的着色、顏色過濾器 4.ColorMatrix的使用數組
可見只有無參數構造能夠用bash
int blue = Color.BLUE;//第一種獲取藍色方法
blue = Color.parseColor("#0000FF");//第二種獲取藍色方法
blue = Color.rgb(0, 0, 255);//第三種獲取藍色方法
blue = Color.argb(255, 0, 0, 255);//第四種獲取藍色方法
blue = Color.HSVToColor(new float[]{240.0f, 1.0f, 1.0f});//第五種獲取藍色方法
blue = 0xff0000FF;//第六種獲取藍色方法
//(吐槽:怎麼有種孔乙己說茴香豆的茴字有多少種寫法同樣...,看哪一個順手就用哪一個吧)
float[] hsv = {0, 0, 0};//hsv數組
Color.RGBToHSV(0, 0, 255, hsv);//將RGB轉爲hsv
Log.e(TAG, "onDraw: " + hsv[0]+","+hsv[1]+","+hsv[2]);
//onDraw: 240.0,1.01.0
複製代碼
其實Color的自己並無太多的知識點,畢竟就是一個int而已,難點在於顏色的拼合與變換微信
什麼是位圖,前面講過顏色是按位存儲的,ARGB_8888每種顏色佔8位
相信你們都知道一張jpg或png放大後會是一個個小格子,稱爲一個像素(px),並且一個小格子是一種顏色
也就是一張jpg或png圖片就是不少顏色的合集,而這些合集信息都被封裝到了Bitmap類中
你可使用Bitmap獲取任意像素點,並修改它,對與某像素點而言,顏色信息是其主要的部分
咱們通常使用Bitmap是都是用BitmapFactory來decode資源,因此並未設計太多Bitmap的操做,以至認爲Bitmap=圖片
Bitmap實際是一個封裝圖片像素信息的類,它能顯示出來是由於View及手機的硬件
注意區別bitmapCanvas和View中OnDraw中Canvas的區別:
這裏:bitmapCanvas是負責在位圖(Bitmap)上繪製,讓位圖記錄像素點位信息的
OnDraw中Canvas是用來在View上繪製,顯示在屏幕上的。
打個不恰當的比方:
你是bitmapCanvas,負責畫一張圖(Bitmap),你畫完後不能直接交給印刷人員(View)去印
須要交給審稿員(OnDraw中canvas),通過他容許才能給印刷人員
/**
* 建立一個Bitmap
*
* @param color 背景色
* @return bitmap
*/
private Bitmap createBitmap(int color) {
//建立一個ARGB_8888,寬高200的bitmap
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
//使用Bitmap建立一個canvas畫板,畫板上的一切都會保留在bitmap上
Canvas bitmapCanvas = new Canvas(bitmap);
//接下來就是在畫板上操做
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(color);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
bitmapCanvas.drawRect(rect, p);
p.setColor(Color.GRAY);
p.setStrokeWidth(3);
bitmapCanvas.drawLine(0, 0, 200, 200, p);
bitmapCanvas.drawLine(200, 0, 0, 200, p);
return bitmap;
}
複製代碼
OnDraw中使用Bitmap,使用Bitmap,使用Bitmap...
//審稿人統一,印刷到View上
canvas.drawBitmap(mBitmap, 100, 100, mMainPaint);
複製代碼
終於寫到這裏了,總算與Xfermode相遇了,最喜歡分析不少的狀況,這裏有18種模式,想一想都激動...。
作開發的,咱們應該知道src和dst吧src是源,dst是目標,在react裏就有src的源文件,和dest的輸出文件
圖片疊合顧名思義,必須有兩個圖片才行,這裏原圖src用藍色正方形,目標dst用綠色圓形
/**
* 建立源圖片
*
* @return bitmap
*/
private Bitmap createSrcBitmap() {
//建立一個ARGB_8888,寬高200的bitmap
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
//使用Bitmap建立一個canvas畫板,畫板上的一切都會保留在bitmap上
Canvas bitmapCanvas = new Canvas(bitmap);
//接下來就是在畫板上操做
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(0x882045F3);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
bitmapCanvas.drawRect(rect, p);
return bitmap;
}
/**
* 建立目標
*
* @return bitmap
*/
private Bitmap createDstBitmap() {
//建立一個ARGB_8888,寬高200的bitmap
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
//使用Bitmap建立一個canvas畫板,畫板上的一切都會保留在bitmap上
Canvas bitmapCanvas = new Canvas(bitmap);
//接下來就是在畫板上操做
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(0xff43F41D);
bitmapCanvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getHeight() / 2,p);
return bitmap;
}
複製代碼
別怕,別怕,一幅圖展現一下:
public enum Mode {
CLEAR (0),
SRC (1),
DST (2),
SRC_OVER (3),
DST_OVER (4),
SRC_IN (5),
DST_IN (6),
SRC_OUT (7),
DST_OUT (8),
SRC_ATOP (9),
DST_ATOP (10),
XOR (11),
DARKEN (16),
LIGHTEN (17),
MULTIPLY (13),
SCREEN (14),
ADD (12),
OVERLAY (15);
Mode(int nativeInt) {
this.nativeInt = nativeInt;
}
public final int nativeInt;
}
複製代碼
注意:測試了一下,開不開硬件加速對這東西有影響,下面在無有硬件加速:
android:hardwareAccelerated="false"
mMainPaint.setXfermode(XXX);放置的順序也很重要,在下面的是疊合的源
網上有一組圖,不過沒有透明度,我對源(藍色)加了88的透明度,顯示的更清楚些
注意:看正方形框裏的內容,看正方形框裏的內容,看正方形框裏的內容!由於它是被疊合的對象
private void init() {
mMainPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mMainPaint.setStyle(Paint.Style.FILL);
mMainPaint.setStrokeCap(Paint.Cap.ROUND);
src = createSrcBitmap();
dst = createDstBitmap();
//背景圖層的筆
mLayerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLayerPaint.setStyle(Paint.Style.FILL);
mLayerPaint.setFilterBitmap(false);
//文字的筆
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextSize(45);
Typeface typeface = Typeface.create(Typeface.MONOSPACE, Typeface.BOLD);
mTextPaint.setTypeface(typeface);
mTextPaint.setColor(0xffF98D1F);
//虛線畫筆
mDashPaint = new Paint();
mDashPaint.setStrokeWidth(3);
mDashPaint.setColor(Color.RED);
mDashPaint.setStyle(Paint.Style.STROKE);
//設置虛線效果new float[]{可見長度, 不可見長度},偏移值
mDashPaint.setPathEffect(new DashPathEffect(new float[]{10, 5}, 0));
mModes = new PorterDuffXfermode[]{
new PorterDuffXfermode(PorterDuff.Mode.CLEAR),//0
new PorterDuffXfermode(PorterDuff.Mode.SRC),//1
new PorterDuffXfermode(PorterDuff.Mode.DST),//2
new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),//3
new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),//4
new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),//5
new PorterDuffXfermode(PorterDuff.Mode.DST_IN),//6
new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),//7
new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),//8
new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),//9
new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),//10
new PorterDuffXfermode(PorterDuff.Mode.XOR),//11
new PorterDuffXfermode(PorterDuff.Mode.DARKEN),//12
new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),//13
new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),//14
new PorterDuffXfermode(PorterDuff.Mode.SCREEN),//15
new PorterDuffXfermode(PorterDuff.Mode.ADD),//16
new PorterDuffXfermode(PorterDuff.Mode.OVERLAY),//17
};
mModeText = new String[]{"CLEAR", "SRC", "DST", "SRC_OVER", "DST_OVER", "SRC_IN",
"DST_IN", "SRC_OUT", "DST_OUT", "SRC_ATOP", "DST_ATOP", "XOR", "DARKEN",
"LIGHTEN", "MULTIPLY", "SCREEN", "ADD", "OVERLAY"
};
}
複製代碼
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//建立一個圖層,在圖層上演示圖形混合後的效果
int sc = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
sc = canvas.saveLayer(new RectF(0, 0, 2500, 2500), mLayerPaint);
}
for (int i = 0; i < 18; i++) {
int line = i % 6;
int row = i / 6;
canvas.drawBitmap(dst, 350 * line, row * 350, mMainPaint);//目標圖象
mMainPaint.setXfermode(mModes[i]);//設置對源的疊合模式
canvas.drawBitmap(src, 100 + 350 * line, 100 + row * 350, mMainPaint);
//輔助信息
canvas.drawText(mModeText[i],100 + 350 * line, 300 + row * 350,mTextPaint);
canvas.drawCircle(100 + 350 * line, 100 + row * 350, 100, mDashPaint);
canvas.drawRect(100 + 350 * line, 100 + row * 350, 100 + 200 + 350 * line, 100 + 200 + row * 350, mDashPaint);
}
canvas.restoreToCount(sc);
}
複製代碼
一個很簡單的類,有5個子類:
漸變模式:
Shader.TileMode.
[MIRROR
|CLAMP
|REPEAT
] (圖中很形象,就不解釋了)
int colorStart = Color.parseColor("#84F125");
int colorEnd = Color.parseColor("#5825F1");
canvas.save();
canvas.translate(mCoo.x, mCoo.y);
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new LinearGradient(
-200, 0, 200, 0,
colorStart, colorEnd,
Shader.TileMode.MIRROR
));
canvas.drawRect(-400,-200,400,-100,mRedPaint);
canvas.translate(0, 150);
mRedPaint.setShader(
new LinearGradient(
-100, 0, 100, 0,
colorStart, colorEnd,
Shader.TileMode.CLAMP
));
canvas.drawRect(-400,-200,400,-100,mRedPaint);
canvas.translate(0, 150);
mRedPaint.setShader(
new LinearGradient(
-100, 0, 100, 0,
colorStart, colorEnd,
Shader.TileMode.REPEAT
));
canvas.drawRect(-400,-200,400,-100,mRedPaint);
複製代碼
int[] colors = new int[]{
Color.parseColor("#F60C0C"),//紅
Color.parseColor("#F3B913"),//橙
Color.parseColor("#E7F716"),//黃
Color.parseColor("#3DF30B"),//綠
Color.parseColor("#0DF6EF"),//青
Color.parseColor("#0829FB"),//藍
Color.parseColor("#B709F4"),//紫
};
float[] pos = new float[]{
1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
};
canvas.translate(0, 150);
mRedPaint.setShader(
new LinearGradient(
-300, 0, 300, 0,
colors, pos,
Shader.TileMode.CLAMP
));
canvas.drawRect(-400, -200, 400, -100, mRedPaint);
複製代碼
canvas.translate(mCoo.x, mCoo.y);
int colorStart = Color.parseColor("#84F125");
int colorEnd = Color.parseColor("#5825F1");
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new RadialGradient(
0,0,50,
colorStart, colorEnd,
Shader.TileMode.MIRROR
));
canvas.drawCircle(0, 0, 150, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setShader(
new RadialGradient(
0,0,50,
colorStart, colorEnd,
Shader.TileMode.CLAMP
));
canvas.drawCircle(0, 0, 150, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setShader(
new RadialGradient(
0,0,50,
colorStart, colorEnd,
Shader.TileMode.REPEAT
));
canvas.drawCircle(0, 0, 150, mRedPaint);
複製代碼
RadialGradient(漸變中心,漸變半徑,漸變模式,顏色數組,位置百分點數組0~1,漸變模式)
int[] colors = new int[]{
Color.parseColor("#F60C0C"),//紅
Color.parseColor("#F3B913"),//橙
Color.parseColor("#E7F716"),//黃
Color.parseColor("#3DF30B"),//綠
Color.parseColor("#0DF6EF"),//青
Color.parseColor("#0829FB"),//藍
Color.parseColor("#B709F4"),//紫
};
float[] pos = new float[]{
1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
};
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new RadialGradient(
0, 0, 200,
colors, pos,
Shader.TileMode.CLAMP
));
canvas.drawCircle(0, 0, 250, mRedPaint);
複製代碼
這個要比上面的簡單一點,沒有漸變的模式 雙色掃描漸變:SweepGradient(中心點x,y,顏色1,顏色2) 多色掃描漸變:SweepGradient(中心點x,y,顏色數組,位置百分點數組0~1)
int colorStart = Color.parseColor("#84F125");
int colorEnd = Color.parseColor("#5825F1");
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setShader(
new SweepGradient(0, 0, colorStart, colorEnd));
canvas.drawCircle(0, 0, 150, mRedPaint);
canvas.translate(400, 0);
int[] colors = new int[]{
Color.parseColor("#F60C0C"),//紅
Color.parseColor("#F3B913"),//橙
Color.parseColor("#E7F716"),//黃
Color.parseColor("#3DF30B"),//綠
Color.parseColor("#0DF6EF"),//青
Color.parseColor("#0829FB"),//藍
Color.parseColor("#B709F4"),//紫
};
float[] pos = new float[]{
1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1
};
mRedPaint.setShader(
new SweepGradient(0, 0, colors, pos));
canvas.drawCircle(0, 0, 150, mRedPaint);
複製代碼
用圖片的全部像素點做爲畫筆的顏色
//加載圖片,生成圖片着色器
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.menu_bg);
BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
mRedPaint.setShader(bs);
mRedPaint.setTextSize(150);
mRedPaint.setStrokeWidth(10);
mRedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawText("張風捷特烈", 0, 500, mRedPaint);
複製代碼
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mRedPaint.setShader(bs);
mRedPaint.setStyle(Paint.Style.FILL);
Path path = CommonPath.nStarPath(8, 500, 250);
canvas.drawPath(path, mRedPaint);
複製代碼
還有一個ComposeShader比較複雜,之後有需求會專門寫一篇
Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setColorFilter(new LightingColorFilter(
Color.parseColor("#F00000"),//紅
Color.parseColor("#0000ff")//藍
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new LightingColorFilter(
Color.parseColor("#FF0000"),//紅
Color.parseColor("#00ff00")//綠
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new LightingColorFilter(
Color.parseColor("#FF0000"),//紅
Color.parseColor("#000000")//黑
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.restore();
複製代碼
下面分析一下紅藍配的結果:打開LightingColorFilter源碼:
/**
* Create a colorfilter that multiplies the RGB channels by one color,
* and then adds a second color. The alpha components of the mul and add
* arguments are ignored.
建立一個顏色過濾器:用mul顏色乘以RGB通道的顏色,再加上add顏色,mul和add的透明度將被忽略
*/
public LightingColorFilter(@ColorInt int mul, @ColorInt int add) {
mMul = mul;
mAdd = add;
}
//看了沒什麼感受,又是native的方法,往上一看,有註釋
* Given a source color RGB, the resulting R'G'B' color is computed thusly: * R' = R * colorMultiply.R + colorAdd.R
* G' = G * colorMultiply.G + colorAdd.G * B' = B * colorMultiply.B + colorAdd.B
複製代碼
這下明白了,就是顏色變換嘛----草稿紙準備好,要演算了:
注意:當相乘數大於255時,便會溢出,至關於8位容不下那麼多數,後面再進來,前面的就被推出來了
這裏爲了區別,特地用#F00000來測試,結果有一點點誤差,畢竟兩次選點的點位可能有誤差
活了這麼大,第一次對顏色進行乘法和加法,對於一張圖片,加上綠色就是對每一個像素點進行這樣的運算
PorterDuff.Mode是否是很熟悉,看上面的疊加模式吧
Bitmap mainBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.menu_bg);
mRedPaint.setStyle(Paint.Style.FILL);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"), PorterDuff.Mode.DARKEN));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"),PorterDuff.Mode.LIGHTEN
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"),PorterDuff.Mode.SCREEN
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
canvas.translate(350, 0);
mRedPaint.setColorFilter(new PorterDuffColorFilter(
Color.parseColor("#0000ff"),PorterDuff.Mode.OVERLAY
));
canvas.drawBitmap(mainBitmap, 0, 0, mRedPaint);
複製代碼
它是有一個5*4的矩陣對某個顏色進行運算,是否是有種衆星捧月的但覺,沒錯,20個數,是否是很開心
顏色ARBG佔了int的四個字節,因此不多是負數,至於如何處理負數,要看ColorMatrix的處理
測試了一下,應該是0,ARGB都沒了
設爲1後,結果[-R,-G,-B,A],黑色,符合預期:
因爲只有G、B不通,因此顯示是不一樣的紅色
-1,0,0,0,0
0,-1,0,0,0
0,0,-1,0,255
0,0,0,1,0
複製代碼
-1,0,0,0,255
0,-1,0,0,255
0,0,-1,0,255
0,0,0,1,0
複製代碼
//只要把RGB三通道的色彩信息設置成同樣:即:R=G=B,
//爲了保證圖像亮度不變,同一個通道中的R+G+B=1
0.3086, 0.6094, 0.0820, 0, 0
0.3086, 0.6094, 0.0820, 0, 0
0.3086, 0.6094, 0.0820, 0, 0
0 , 0 , 0 , 1, 0
複製代碼
(R-1)*X + 1, G*X , B*X , 0, 0,
R*X , (G-1)*X + 1, B*X , 0, 0,
R*X , G*X , (B-1)*X + 1, 0, 0,
0 , 0 , 0 , 1, 0
R=0.3086,G=0.6094,B=0.0820
複製代碼
/**
* 飽和度調節
* @param R 紅色保留比
* @param G 綠色保留比
* @param B 藍色保留比
* @param X 值越小越飽和----0爲原圖
* @return
*/
private float[] colorM(float R, float G, float B, float X) {
float[] array= new float[]{
(R - 1) * X + 1, G * X, B * X, 0, 0,
R * X, (G - 1) * X + 1, B * X, 0, 0,
R * X, G * X, (B - 1) * X + 1, 0, 0,
0, 0, 0, 1, 0
};
return array;
}
複製代碼
X,0,0,0,128*(1-X) R X*R+128*(1-X)
0,X,0,0,128*(1-X) * G G*R+128*(1-X)
0,0,X,0,128*(1-X) B = B*R+128*(1-X)
0,0,0,1,0 A A
1
複製代碼
private float[] colorM(float X) {
float[] array = new float[]{
X, 0, 0, 0, 128 * (1 - X),
0, X, 0, 0, 128 * (1 - X),
0, 0, X, 0, 128 * (1 - X),
0, 0, 0, 1, 0
};
return array;
}
複製代碼
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;
}
複製代碼
mCmx.setSaturation(folat );
複製代碼
終於寫完了,完結散花。
項目源碼 | 日期 | 備註 |
---|---|---|
V0.1--無 | 2018-11-10 | Android關於Color你所知道的和不知道的一切 |
筆名 | 微信 | 愛好 | |
---|---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 | 語言 |
個人github | 個人簡書 | 個人CSDN | 我的網站 |
1----本文由張風捷特烈原創,轉載請註明 2----歡迎廣大編程愛好者共同交流 3----我的能力有限,若有不正之處歡迎你們批評指證,一定虛心改正 4----看到這裏,我在此感謝你的喜歡與支持