1. 程式人生 > >Android群英傳知識點回顧——第六章:Android繪圖機制與處理技巧

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

ride ets 常用 結合 管理 一個 sla 浮雕效果 調用


  • 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繪圖機制與處理技巧