Android群英傳知識點回顧——第六章:Android繪圖機制與處理技巧

來源:互聯網
上載者:User

標籤:map   主線程   mes   計算公式   渲染   drawtext   1.3   final   view   

  • 6.1 螢幕的尺寸資訊
    • 6.1.1 螢幕參數
    • 6.1.2 系統螢幕密度
    • 6.1.3 獨立像素密度dp
    • 6.1.4 單位轉換
  • 6.2 2D繪圖基礎
  • 6.3 Android XML繪圖
    • 6.3.1 Bitmap
    • 6.3.2 Shape
    • 6.3.3 Layer
    • 6.3.4 Selector
  • 6.4 Android繪圖技巧
    • 6.4.1 Canvas
    • 6.4.2 Layer圖層
  • 6.5 Android影像處理之色彩特效處理
    • 6.5.1 色彩矩陣分析
    • 6.5.2 Android顏色矩陣——ColorMatrix
    • 6.5.3 常用映像顏色矩陣處理效果
    • 6.5.4 像素點分析
    • 6.5.5 常用映像像素點處理效果
  • 6.6 Android影像處理之圖形特效處理
    • 6.6.1 Android變形矩陣——Matrix
    • 6.6.2 像素塊分析
  • 6.7 Android影像處理之畫筆特效處理
    • 6.7.1 PorterDuffXfermode
    • 6.7.2 Shader
    • 6.7.3 PathEffect
  • 6.8 View之孿生兄弟——SurfaceView
    • 6.8.1 SurfaceView與View的區別
    • 6.8.2 SurfaceView的使用
    • 6.8.3 SurfaceView執行個體

由於這一章比較難理解,所以大部分知識點都是摘抄原文的,如果是沒學習過線性代數的同學,那就難上加難了,不過克服它,是你進階進階工程師的必經之路,文章比較長,請耐心觀看

無知識點

  • 螢幕大小:螢幕對角線的長度,通常用寸來度量
  • 解析度:手機螢幕的像素點個數
  • PPI:每英吋像素,又稱DPI,由對角線像素點除以螢幕大小獲得

Android系統使用mdpi即密度值為160的螢幕作為標準,在這個螢幕上1px=1dp

ldpi:mdpi:hdpi:xhdpi:xxhdpi=3:4:6:8:12

這裡加0.5f的巧用目的是:四捨五入

dp==dip

系統提供了TypedValue類協助我們轉換

Paint作為一個重要的元素有以下方法:

  • setAntiAlias():設定畫筆的鋸齒效果
  • setColor():設定畫筆的顏色
  • setARGB():設定畫筆的A、R、G、B值
  • setAlpha():設定畫筆的Alpha值
  • setTextSize():設定字型的尺寸
  • setStyle():設定畫筆的風格(空心或實心)
  • setStrokeWidth():設定空心邊框的寬度

設定Paint的Style可以畫出空心或者實心的矩形:

  • paint.setStyle(Paint.Style.STROKE):空心效果
  • paint.setStyle(Paint.Style.FILL):實心效果

系統通過提供的Canvas對象來提供繪圖方法:

  • canvas.drawPoint(x, y, paint):繪製點
  • canvas.drawLine(startX, startY ,endX, endY, paint):繪製直線
  • canvas.drawLines(new float[]{startX1, startY1, endX1, endY1,……,startXn, startYn, endXn, endYn}, paint):繪製多條直線
  • canvas.drawRect(left, top, right, bottom, paint):繪製矩形
  • canvas.drawRoundRect(left, top, right, bottom, radiusX, radiusY, paint):繪製圓角矩形
  • canvas.drawCircle(circleX, circleY, radius, paint):繪製圓
  • canvas.drawOval(left, top, right, bottom, paint):繪製橢圓
  • canvas.drawText(text, startX, startY, paint):繪製文本
  • canvas.drawPosText(text, new float[]{X1,Y1,X2,Y2,……Xn,Yn}, paint):在指定位置繪製文本
  • Path path=new Path();
    path.moveTo(50, 50);
    path.lineTo(100, 100);
    path.lineTo(100, 300);
    path.lineTo(300, 50);
    canvas.drawPath(path, paint):繪製路徑

  • paint.setStyle(Paint.Style.STROKE);
    drawArc(left, top, right,bottom, startAngle, sweepAngle, true, paint):繪製扇形
  • paint.setStyle(Paint.Style.STROKE);
    drawArc(left, top, right,bottom, startAngle, sweepAngle, false, paint):繪製弧形
  • paint.setStyle(Paint.Style.FILL);
    drawArc(left, top, right,bottom, startAngle, sweepAngle, true, paint):繪製實心扇形
  • paint.setStyle(Paint.Style.FILL);
    drawArc(left, top, right,bottom, startAngle, sweepAngle, false, paint):繪製實心弧形

無知識點

通過這樣在XML中使用Bitmap就可以將圖片直接轉換成了Bitmap在程式中使用

通過Shape可以在XML中繪製各種形狀

下面通過漸層來實現的陰影製作效果

通過Layer會產生圖片依次疊加的效果

Selector的作用在於協助開發人員實現靜態繪圖中的事件反饋,通過給不同的事件設定不同的映像,從而在程式中根據使用者輸入,返回不同的效果

下面這個例子實現了一個具有點擊反饋效果的、圓角舉證Selector

無知識點

Canvas提供了以下幾種非常有用的方法:

  • Canvas.save():儲存畫布,將之前所有已繪製映像儲存起來,讓後續的操作就好像在一個新的圖層上操作一樣
  • Canvas.restore():在save()之後繪製的所有映像與save()之前的映像進行合并,可以理解為Photoshop中的合并圖層操作
  • Canvas.translate():畫布平移
  • Canvas.roate():畫布翻轉

通過一個執行個體——儀錶盤,來理解這幾個方法,將儀錶盤分為以下幾個元素:

  • 儀錶盤:外面的大圓盤
  • 刻度標記:包含四個長的刻度標記和其他短的刻度標記
  • 刻度值:包含長刻度標記對應的大的刻度值和其他小的刻度值
  • 指標:中間的指標,一粗一細兩根指標

儀錶盤……見經典代碼案例一

一張複雜的畫可以由很多個圖層疊加起來,形成一個複雜的映像,使用saveLayer()方法來建立一個圖層,圖層同樣是基於棧的結構進行管理的

Android通過調用saveLayer()方法,saveLayerAlpha()方法將一個圖層入棧,使用restore()方法、restoreToCount()方法將一個圖層出棧,仿照API Demos裡面的一個執行個體來使用Layer

  • 當透明度為127時,即半透明
  • 當透明度為255時,即完全不透明
  • 當透明度為0時,即完全透明

Bitmap圖片都是由點陣和顏色值組成的,所謂點陣就是一個包含像素的矩陣,每一個元素對應著圖片的一個像素。而顏色值——ARGB,分別對應透明度、紅、綠、藍這四個通道分量,它們共同決定了每個像素點顯示的顏色

在色彩處理中,我們通常用三個角度描述一張圖片:

  • 色調:物體傳播的顏色
  • 飽和度:顏色的純度,從0(灰)-100%(飽和)來進行描述
  • 亮度:顏色的相對明暗程度

而在Android中,系統會使用一個顏色矩陣——ColorMatrix,來處理這些色彩的效果,Android中的顏色矩陣是4X5的數字矩陣,他用來對顏色色彩進行處理,而對於每一個像素點,都有一個顏色分量矩陣來儲存ARGB值

根據前面對矩陣A、C的定義,通過矩陣乘法運演算法則,可以得到:

矩陣運算的乘法計算過程如下:

我們觀察顏色矩陣A

從這個公式可以發現

  • 第一行的abcde用來決定新的顏色值R——紅色
  • 第二行的fghij用來決定新的顏色值G——綠色
  • 第三行的kimno用來決定新的顏色值B——藍色
  • 第四行的pqrst用來決定新的顏色值A——透明度
  • 矩陣A中的第五列——ejot值分別用來決定每個分量中的offset,即位移量

通過一個小例子來講解:
首先重新看一下矩陣變換計算公式,以R分量為例,計算過程如下:

如果讓a=1,b,c,d,e都等於0,那麼計算的結果為R1=R,因此我們可以構建一個矩陣

如果把這個矩陣公式帶入R1=AC,那麼根據矩陣的乘法運演算法則,可以得到R1=R。因此,這個矩陣通常是用來作為初始的顏色矩陣來使用,他不會對原有顏色進行任何變化

那麼當我們要變換顏色值的時候,通常有兩種方法。一個是直接改變顏色的offset,即位移量的值來修改顏色的分量。另一種方法直接改變對應RGBA值的係數來調整顏色分量的值

從前面的分析中,可以知道要修改R1的值,只要將第五列的值進行修改即可。即改變顏色的位移量,其它值儲存初始矩陣的值,

在上面這個矩陣中,我們修改了R、G所對應的顏色位移量,那麼最後的處理結果就是映像的紅色、綠色分別增加了100。而我們知道,紅色混合綠色會得到黃色,所以最終的顏色處理結果就是讓整個圖片的色調偏黃色

如果修改顏色分量中的某個係數值,而其他只依然儲存初始矩陣的值,

在上面這個矩陣中,改變了G分量所對應的係數g,這樣在矩形運算後G分量會變成以前的兩倍,最終效果就是映像的色調更加偏綠

下面通過執行個體看看如何通過矩陣改變映像的色調、飽和度和亮度:

  • 色調:setRotate(int axis, float degree),第一個參數分別使用0、1、2代表Red、Green、Blue三種顏色,第二參數需要處理的值
  • 飽和度:setSaturation(float sat),參數代表設定飽和度的值
  • 亮度:setScale(float rscale,float gscale,float bscale,float ascale),參數分別是紅、綠、藍、透明度的亮度大小值

除了單獨使用上面三種方式來進行顏色效果處理之外,還提供了postConcat()方法來將矩陣的作用效果混合,從而疊加處理效果

通過SeekBar調節色調、飽和度、亮度……見經典代碼回顧案例二

類比4x5的顏色矩陣……見經典代碼回顧案例三

  • 灰色效果

  • 映像反轉

  • 懷舊效果

  • 去色效果

  • 高飽和度

在Android中,系統系統提供了Bitmap.getPixels()方法來幫我們提取整個Bitmap中的像素點,並儲存在一個數組中:

這幾個參數的具體含義如下:

  • pixels:接收位元影像顏色值的數組
  • offset:寫入到pixels[]中的第一個像素索引值
  • stride:pixels[]中的行間距
  • x:從位元影像中讀取的第一個像素的x座標值
  • y:從位元影像中讀取的第一個像素的y座標值
  • width:從每一行中讀取的像素寬度
  • height:讀取的行數

通常使用如下代碼:

接下來擷取每個像素具體的ARGB值:

接下來就是修改像素值,產生新的像素值

最後使用我們的新像素值

底片效果、老照片效果、浮雕效果……見經典代碼回顧案例四

無知識點

對於圖形變換,系統提供了3x3的舉證來處理:

與顏色矩陣一樣,計算方法通過矩陣乘法:

與顏色矩陣一樣,也有一個初始矩陣:

映像的變形處理包含以下四類基本變換:

  • Translate:平移變換
  • Rotate:旋轉變換
  • Scale:縮放變換
  • Skew:錯切變換

平移變換:即對每個像素點都進行平移變換,通過計算可以發現如下平移公式:

旋轉變換:通過以下三步驟完成以任意點為旋轉中心的旋轉變換

  • 將座標原點平移到O點
  • 使用前面講的以座標原點為中心的旋轉方法進行旋轉變換
  • 將座標原點還原

縮放變換:縮放變換的效果計算公式如下

錯切變換:錯切變換的效果計算公式如下

瞭解四種圖形變換矩陣,可以通過setValues()方法將一個一維數群組轉換為圖形變換矩陣:

Android中Matrix類也幫我們封裝好了幾個操作方法:

  • matrix.setRotate():旋轉變換
  • matrix.setTranslate():平移變換
  • matrix.setScale():縮放變換
  • matrix.setSkew():錯切變換
  • pre()和post():提供矩陣的前乘和後乘運算

舉個例子說明前乘和後乘的不同運算方式:

  • 先平移到(300, 100)
  • 再旋轉45度
  • 最後平移到(200, 200)

如果使用後乘運算,代碼如下:

如果使用前乘運算,代碼如下:

drawBitmapMesh()與操縱像素點來改變色彩的原理類似,只不過是把映像分成了一個個的小塊,然後通過改變每一個映像塊來修改整個映像:

參數分析:

  • bitmap:將要扭曲的映像
  • meshWidth:需要的橫向網格數目
  • meshHeight:需要的縱向網格數目
  • verts:網格交叉點的座標數組
  • vertOffset:verts數組中開始跳過的(X,Y)座標組的數目

飄動的旗子……見經典代碼回顧案例五

之前繪圖的時候也提到過畫筆的一些方法,這裡就不再介紹

PorterDuffXfermod設定的是兩個圖層交集地區的顯示方式,dst是先畫的圖形,而src是後畫的圖形

以一個圓角圖片為例子:

,由於圖片過大,只能看出一邊角

刮刮卡效果……見經典代碼回顧案例六

Shader又被稱為著色器。渲染器,它可以實現渲染,漸層等效果,Android中的Shader包括以下幾種:

  • BitmapShader:位元影像Shader
  • LinearGradient:線性Shader
  • RadialGradient:光束Shader
  • SweepGradient:梯形Shader
  • ComposeShader:混合Shader

其中BitmapShader有三種模式可以選擇:

  • CLAMP展開:展開的是圖片最後的那一個像素,不斷重複
  • REPEAT重複:橫向,縱向不斷重複
  • MIRROR鏡像:橫向不斷翻轉重複,縱向不斷翻轉重複

下面看下例子說明,圓形圖片:

下面把TileMode改為REPEAT:

使用LinearGradient:

結合前面的PorterDuffXfermode和剛學的LinearGradient,製作出倒影的片

倒影圖片效果……見經典代碼回顧案例七

先上一張直觀的圖:

Android提供的幾種繪製PathEffect方式:

  • 沒效果
  • CornerPathEffect:拐彎角變得圓滑
  • DiscretePathEffect:線段上會產生許多雜點
  • DashPathEffect:繪製虛線,用一個資料來設定各個點之間的間隔
  • PathDashPathEffect:繪製虛線,可以使用方形點虛線和圓形點虛線
  • ComposePathEffect:可任意組合兩種路徑(PathEffect)的特性

我們通過一個執行個體來認識這些效果:

每繪製一個Path,就將畫布平移,從而讓各種PathEffect依次繪製出來

無知識點

View的繪製重新整理間隔時間為16ms,如果在16ms內完成你所需要執行的所有操作,那麼在使用者視覺上,就不會產生卡頓的感覺,否則,就會出現卡頓,所以可以考慮使用SurfaceView來替代View的繪製

通常在Log會看到這樣的提示:

SurfaceView與View的主要區別:

  • View主要適用於主動更新的情況下,而surfaceVicw主要適用於被動更新,例如頻繁重新整理
  • View在主線程中對畫面進行重新整理,而surfaceView通常會通過一 個子線程來進行頁面的重新整理
  • View在繪製時沒有使用雙緩衝機制,而surfaceVicw在底層實現機制中就已經實現了雙緩衝機制

總結一句話就是,如果你的自訂View需要頻繁重新整理,或者重新整理資料處理量比較大,托福機經就可以考慮使用SurfaceView替代View

SurfaceView使用步驟:

  • 建立SurfaceView繼承自SurfaceView,並實現兩個介面——SurfaceHolder.Callback和Runnable
  • 初始化SurfacHolder對象,並註冊SurfaceHolder的回調方法
  • 通過SurfacHolder對象lockCanvas()方法獲得Canvas對象進行繪製,並通過unlockCanvasAndPost(mCanvas)方法對畫布內容進行提交

整個使用SurfaceView的模板代碼:

唯一注意的是,在繪製中將mHolder.unlockCanvasAndPost(mCanvas)方法放到finally代碼塊中,保證每次都能將內容提交

正弦曲線……見經典代碼回顧案例八
繪圖板……見經典代碼回顧案例九

布局檔案

Activity檔案

布局檔案

Activity檔案

關鍵點:將一個顏色矩陣傳入畫筆,然後畫出原始的圖在建立的圖上面

布局檔案

Activity檔案

工具類

本人也是懵逼,沒有搞懂這個例子

經典回顧源碼下載

github:https://github.com/CSDNHensen/QunYingZhuang

Android群英傳知識點回顧——第六章:Android繪圖機制與處理技巧

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.