高級(jí)UI---LSN-4-1-Paint(濾鏡,顏色通道,矩陣運(yùn)算)

前言

在之前的幾次課當(dāng)中我們已經(jīng)詳細(xì)了解到整個(gè)android程序,從啟動(dòng)再到繪制的整體流程,從這中間我們又牽扯出了Canvas繪制圖形的畫板和我們的Paint控制色彩樣式的畫筆,那么之前基礎(chǔ)篇我們就不進(jìn)行詳細(xì)的解釋,那些API在之前的基礎(chǔ)篇已經(jīng)公布出來,我也注釋的非常詳細(xì),今天我門來了解Paint高級(jí)篇真正需要了解的濾鏡

濾鏡

1.濾鏡效果

image.png

從上圖我們可以看到 四張濾鏡效果圖像,其色彩的顯示效果各不一樣,也就是說所謂濾鏡其實(shí)只不過是對(duì)于原本圖像色彩進(jìn)行調(diào)整
那么需要對(duì)圖像的色彩進(jìn)行調(diào)整操作,我們會(huì)需要知道幾個(gè)概念,那就是我們的圖像構(gòu)成,顏色通道,顏色模式以及顏色舉證

2.圖像構(gòu)成

在具體講濾鏡之前,今天我們先來系統(tǒng)化真正認(rèn)識(shí)一下在我們計(jì)算機(jī)當(dāng)中我們的圖像到底是什么,我們都知道在計(jì)算機(jī)體系當(dāng)中我們的圖像有各種各樣的格式,比如jpg,png,gif等等...
那么我們同樣也知道我們計(jì)算機(jī)當(dāng)中的圖像文件其實(shí)實(shí)際也就是一個(gè)二進(jìn)制的字節(jié)碼文件,那么這個(gè)圖像本質(zhì)上來說是一個(gè)二進(jìn)制文件,然后我們的cpg,gpu對(duì)二進(jìn)制文件進(jìn)行識(shí)別再顯示到我們的屏幕上,那么我們現(xiàn)在需要關(guān)注的是,這些文件當(dāng)中他到底保存的是什么?
其實(shí)一個(gè)圖像文件當(dāng)中,他保存的數(shù)據(jù)總體分為兩塊
1.圖像的信息
2.圖像的數(shù)據(jù)
后者好理解,我們可以理解為圖像具體的那些像素點(diǎn)的數(shù)據(jù),
那么前者其實(shí)我們可以理解為,是一組信息,這組信息的作用是讓我們的cpg,gpu在顯示圖像的時(shí)候,基于我門設(shè)定的這組信息的規(guī)則不同,那么顯示的效果不一樣,
以一種格式(PNG)為例,我在網(wǎng)上扒出了對(duì)于這個(gè)圖像的結(jié)構(gòu)的解釋(粗略看一下就好)

    PNG的文件結(jié)構(gòu)
    
    對(duì)于一個(gè)PNG文件來說,其文件頭總是由位固定的字節(jié)來描述的:

    十進(jìn)制數(shù)    137 80 78 71 13 10 26 10
    十六進(jìn)制數(shù)   89 50 4E 47 0D 0A 1A 0A
    其中第一個(gè)字節(jié)0x89超出了ASCII字符的范圍,這是為了避免某些軟件將                PNG文件當(dāng)做文本文件來處理。文件中剩余的部分由3個(gè)以上的PNG的數(shù)據(jù)塊(Chunk)按照特定的順序組成,因此,一個(gè)標(biāo)準(zhǔn)的PNG文件結(jié)構(gòu)應(yīng)該如下:

    PNG文件標(biāo)志 PNG數(shù)據(jù)塊  ……  PNG數(shù)據(jù)塊
    PNG數(shù)據(jù)塊(Chunk)

    PNG定義了兩種類型的數(shù)據(jù)塊,一種是稱為關(guān)鍵數(shù)據(jù)塊(critical chunk),這是標(biāo)準(zhǔn)的數(shù)據(jù)塊,另一種叫做輔助數(shù)據(jù)塊(ancillary chunks),這是可選的數(shù)據(jù)塊。關(guān)鍵數(shù)據(jù)塊定義了4個(gè)標(biāo)準(zhǔn)數(shù)據(jù)塊,每個(gè)PNG文件都必須包含它們,PNG讀寫軟件也都必須要支持這些數(shù)據(jù)塊。雖然PNG文件規(guī)范沒有要求PNG編譯碼器對(duì)可選數(shù)據(jù)塊進(jìn)行編碼和譯碼,但規(guī)范提倡支持可選數(shù)據(jù)塊。

    下表就是PNG中數(shù)據(jù)塊的類別,其中,關(guān)鍵數(shù)據(jù)塊部分我們使用深色背景加以區(qū)分。


    為了簡(jiǎn)單起見,我們假設(shè)在我們使用的PNG文件中,這4個(gè)數(shù)據(jù)塊按以上先后順序進(jìn)行存儲(chǔ),并且都只出現(xiàn)一次。

    數(shù)據(jù)塊結(jié)構(gòu)

    PNG文件中,每個(gè)數(shù)據(jù)塊由4個(gè)部分組成,如下:

    名稱  字節(jié)數(shù) 說明
    Length (長(zhǎng)度) 4字節(jié) 指定數(shù)據(jù)塊中數(shù)據(jù)域的長(zhǎng)度,其長(zhǎng)度不超過(231-1)字節(jié)
    Chunk Type Code (數(shù)據(jù)塊類型碼)    4字節(jié) 數(shù)據(jù)塊類型碼由ASCII字母(A-Z和a-z)組成
    Chunk Data (數(shù)據(jù)塊數(shù)據(jù))  可變長(zhǎng)度    存儲(chǔ)按照Chunk Type Code指定的數(shù)據(jù)
    CRC (循環(huán)冗余檢測(cè))    4字節(jié) 存儲(chǔ)用來檢測(cè)是否有錯(cuò)誤的循環(huán)冗余碼

從上面這一段解釋當(dāng)中我門可以看出,其實(shí)所謂的各個(gè)圖像格式只不過是發(fā)布的標(biāo)準(zhǔn)不一樣,那么們cpu解析的規(guī)則也不一致,同時(shí)一張圖片里面包含了多個(gè)數(shù)據(jù)塊,如下圖

image.png

這是我打開的一張jpg圖的數(shù)據(jù),這時(shí)我門看到的是16進(jìn)制的數(shù)據(jù),盡管我們不知道這些數(shù)據(jù)是什么,那么此時(shí)我們結(jié)合上述所說,假定第一行的數(shù)據(jù)是這個(gè)jpg的標(biāo)志,第2-8行可能記錄的是解析規(guī)則等等信息類似,后面的為數(shù)據(jù),那么這樣去看待一張圖形,我們就能大致明白一個(gè)意思, 標(biāo)志+圖像信息+數(shù)據(jù)--》最終構(gòu)成一張完整的圖像,圖像根據(jù)數(shù)據(jù)和所為的解析規(guī)則計(jì)算顯示出來的
那么對(duì)于今天的濾鏡,我門需要了解到圖像當(dāng)中比較重要的兩個(gè)信息顏色通道,顏色模式

3.顏色通道,顏色模式

顏色通道:保存圖像顏色信息的通道稱為顏色通道。這句話是顏色通道的基本定義,我門可以理解為記錄色彩信息的那一段數(shù)據(jù),
每個(gè)圖像都有一個(gè)或者多個(gè)顏色通道,圖像中默認(rèn)的顏色通道信息取決于顏色模式

顏色模式:顏色模式我門可以理解為將某種顏色表現(xiàn)為數(shù)字形式的模型,或者說是一種記錄圖像顏色的方式。分為:RGB模式、CMYK模式、HSB模式、Lab顏色模式、位圖模式、灰度模式、索引顏色模式、雙色調(diào)模式和多通道模式等。
其實(shí)實(shí)際上我們就認(rèn)為,現(xiàn)在我要顯示的色彩這個(gè)時(shí)候是用數(shù)字表示,最經(jīng)典的RGB模式我們可以理解為R(255) G(0) B(0)當(dāng)前這個(gè)像素,顯示,在識(shí)別的時(shí)候?yàn)榧t色,他由紅 綠 藍(lán) 三種色彩進(jìn)行混合,顯示出我們要的顏色其程度數(shù)值是0-255的范圍

總結(jié):也就是說,其實(shí)圖像的顯示,每個(gè)點(diǎn)都是由模式所決定的色彩數(shù)值混合形成我們想要的顏色,那么我們的濾鏡效果實(shí)現(xiàn),其實(shí)實(shí)際上就是去對(duì)于顏色通道進(jìn)行過濾操作,在其原本的模式數(shù)值上面進(jìn)行操作,達(dá)到更改圖像色彩效果的目的,這就是我們所為的濾鏡

4.顏色矩陣

在android當(dāng)中,他所采用的顏色模式是RGBA模式,也就是在紅綠藍(lán)的基礎(chǔ)上加入了Alpha透明度的概念,那么也就是他現(xiàn)在是一個(gè)四通道的模式
在Android當(dāng)中當(dāng)android將圖像信息獲取出來時(shí)候,當(dāng)前圖像的顏色通道信息他用的是一個(gè)矩陣在進(jìn)行保存

用一個(gè)數(shù)組來表示的話就是


image.png
image.png

上面這里看到的是一個(gè)四通道形式的表示方式,我門會(huì)發(fā)現(xiàn)在
1-1
2-2
3-3
4-4
的位置都是一個(gè)1的數(shù)值,那么幾個(gè)數(shù)值我們把他理解為顏色的系數(shù),1為原本數(shù)值不動(dòng),若0.5那么當(dāng)前對(duì)應(yīng)的rgba四個(gè)選項(xiàng)按比例處理
如果想要更改為半透明的,那么,當(dāng)前a的值改為0.5就OK了紅色翻一倍就改為2

但是如果在這種情況下


image.png

這個(gè)四介矩陣做不到,在android當(dāng)中真正的表現(xiàn)方式他應(yīng)用了一個(gè)4*5的矩陣


image.png

最后方加入一列,作為所為的亞元坐標(biāo),其實(shí)也就是分量值
那么下面這個(gè)顏色的矩陣如果想要將我們的顏色值達(dá)到上訴效果,第二行的100表示在之前的顏色基礎(chǔ)上增加100個(gè)綠色數(shù)值

那么這種是我們最為簡(jiǎn)單的理解,
而真正的他當(dāng)中的實(shí)現(xiàn)實(shí)際上是采用矩陣的計(jì)算

4.矩陣運(yùn)算


image.png
image.png

矩陣的運(yùn)算規(guī)則是矩陣A的一行乘以矩陣C的一列作為矩陣R的一行,
C矩陣是圖片中包含的ARGB信息,R矩陣是用顏色矩陣應(yīng)用于C之后的新的顏色分量,運(yùn)算結(jié)果如下:

R' = aR + bG + cB + dA + e;
G' = fR + gG + hB + iA + j;
B' = kR + lG + mB + nA + o;
A' = pR + qG + rB + sA + t;

顏色矩陣并不是看上去那么深?yuàn)W,其實(shí)需要使用的參數(shù)很少,而且很有規(guī)律第一行決定紅色第二行決定綠色
第三行決定藍(lán)色,第四行決定了透明度,第五列是顏色的偏移量。下面是一個(gè)實(shí)際中使用的顏色矩陣。


image

如果把這個(gè)矩陣作用于各顏色分量的話,R=A*C,計(jì)算后會(huì)發(fā)現(xiàn),各個(gè)顏色分量實(shí)際上沒有任何的改變(R'=R G'=G B'=B A'=A)。


image

圖1.5所示矩陣計(jì)算后會(huì)發(fā)現(xiàn)紅色分量增加100,綠色分量增加100,
這樣的效果就是圖片偏黃,因?yàn)榧t色和綠色混合后得到黃色,黃色增加了100,圖片當(dāng)然就偏黃了。


image

改變各顏色分量不僅可以通過修改第5列的顏色偏移量也可如上面矩陣所示將對(duì)應(yīng)的顏色值乘以一個(gè)倍數(shù),直接放大。
上圖1.6是將綠色分量乘以2變?yōu)樵瓉淼?倍。至此已經(jīng)明白了如何通過顏色矩陣來改變各顏色分量。

5.濾鏡實(shí)現(xiàn)

那么在對(duì)于的實(shí)現(xiàn)上面android的使用非常簡(jiǎn)單,只需要依賴于一個(gè)API就好

  // 顏色通道過濾
    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            1, 0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,1,0,
    });
  paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));

那么下面是我的demo代碼,大家可以去試試效果

 protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    setLayerType(View.LAYER_TYPE_SOFTWARE,null);


    RectF rectF = new RectF(0,100,bitmap.getWidth(),bitmap.getHeight());
    paint.reset();
    paint.setColor(Color.RED);
   
    canvas.drawBitmap(bitmap,null, rectF,paint);
    // 平移運(yùn)算---加法
    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            1, 0,0,0,0,
            0,1,0,0,100,
            0,0,1,0,0,
            0,0,0,1,0,
    });*/

    // 反相效果 -- 底片效果
   /* ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            -1, 0,0,0,255,
            0,-1,0,0,255,
            0,0,-1,0,255,
            0,0,0,1,0,
    });*/
    // 縮放運(yùn)算---乘法 -- 顏色增強(qiáng)
    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            1.2f, 0,0,0,0,
            0,1.2f,0,0,0,
            0,0,1.2f,0,0,
            0,0,0,1.2f,0,
    });*/

    // 黑白照片
    // 去色原理:只要把R G B 三通道的色彩信息設(shè)置成一樣,那么圖像就會(huì)變成灰色,
    // 同時(shí)為了保證圖像亮度不變,同一個(gè)通道里的R+G+B =1
    //
    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            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,
    });*/

    // 發(fā)色效果---(比如紅色和綠色交換)
    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            0,1,0,0,0,
            1, 0,0,0,0,
            0,0,1,0,0,
            0,0,0,1,0,
    });*/
    // 復(fù)古效果
    /*ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            1/2f,1/2f,1/2f,0,0,
            1/3f, 1/3f,1/3f,0,0,
            1/4f,1/4f,1/4f,0,0,
            0,0,0,1,0,
    });*/
    // 顏色通道過濾
   ColorMatrix colorMartrix = new ColorMatrix(new float[]{
            1, 0,0,0,0,
            0,0,0,0,0,
            0,0,0,0,0,
            0,0,0,1,0,
    });
    
    RectF rectF2 = new RectF(600,100,600 + bitmap.getWidth(),bitmap.getHeight());
    paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
   
    
    canvas.drawBitmap(bitmap,null, rectF2,paint);
}

那么關(guān)于濾鏡其他的反轉(zhuǎn),光影等效果課上講,大家可以試試這里最基礎(chǔ)的一些操作

著作:Kerwin Barry
郵箱:kerwin0210@sina.com
原創(chuàng)博客,轉(zhuǎn)載請(qǐng)注明出處.....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容