路徑(Paths)—— Quartz 2D編程指導翻譯 第4篇

本文翻譯自蘋果官方文檔:原文地址

路徑(Paths)

一個路徑定義了一個或者多個形狀或子路徑。一個子路徑可以包含:直線、曲線,或者兩者都包含;它們可以閉合也可以不閉合。一個子路徑可以是簡單的形狀,例如:一條線、一個圓、一個矩形、一個星星或者更復雜的形狀(如山的輪廓、涂鴉等)。圖 3-1 展示了你能夠創建的一些路徑。左上角的直線是虛線,同樣,它也可以是實線。中上方的彎彎曲曲的路徑是由若干的曲線構成的,它是一個開放的路徑。右上方的同心圓做了填充,沒有做描邊。加州(加利福利亞)是由若干曲線和直線構成的閉合路徑,這個路徑既做了填充又做了描邊。下面的星星說明了填充路徑的兩個選項,你將在本章后面閱讀。

圖 3-1 Quartz 支持的基于路徑的繪畫

在本章中,你將會學到如何創建路徑、描邊和填充路徑、影響路徑顯示的參數。

路徑的創建和路徑的繪制(Painting)

路徑的創建和路徑的繪制是兩個不相關的任務。首先,你需要創建一個路徑;當你想渲染一個路徑時,你請求Quartz繪制它。正如 圖 3-1 所示,你能夠選擇對路徑進行描邊,也能夠選擇對路徑填充,還可以既對路徑做填充又對路徑做描邊。同樣,你也可以使用路徑來限制其他對象的繪制(在路徑創建的bounds之內),也即是,裁剪區域(clipping area)。

圖 3-2 展示了繪制的一個路徑。該路徑包含兩個子路徑,左邊的子路徑是一個矩形,右邊的子路徑是一個由曲線和直線構成的路徑;這兩個子路徑都進行描邊和填充。

圖 3-2 包含兩個子路徑的路徑

圖 3-3 展示了獨立繪制的多個路徑。每一個路徑都包含一個隨機創建的曲線,有些做了填充,有些做了描邊。這些路徑是在一個裁剪區域中進行繪制的。

圖 3-3 裁剪區域內的繪制

構建塊(The Building Blocks)

子路徑由線、弧、和曲線構成。Quartz同樣提供了方便的方法來添加矩形、橢圓。點也同樣是基本的構建塊,因為點定義了圖形的起點和終點。

點(Points)

點是用戶空間坐標系下的坐標(x,y的值)。你可以使用函數CGContextMoveToPoint來指定一個新路徑的起始位置。Quartz對當前的點保持了記錄,當前點(Current Point)就是創建路徑的最后一個位置。例如當你調用CGContextMoveToPoint來把位置設置到(10,10),當前點的位置也就變成了(10,10)。接著,如果你在水平方向上繪制了50個單位長度后,當前點就變成了(60,10)。線、弧、曲線總是從當前點開始繪制的。

大多數情況下,可以通過傳入兩個浮點類型的值,來指定點的位置;有些函數則要求傳入CGPoint類型的值來指定位置。

線(Lines)

一條線是由它的終點定義的,它的起點始終是當前點(current point)。當你創建一條線時,你僅僅需要只指定它的終點。使用函數CGContextAddLineToPoint來追加一條線到子路徑。

同樣,你也可以通過函數CGContextAddLines來添加一系列相關聯的線。在這個函數中,你需要傳入一個數組,數組中的第一個點必須是第一條線的起點,接下來的點就依次是終點。Quartz在第一個點的地方開始了一個新的子路徑,它們是由線段連起來的點。

?。ˋrcs)

弧是圓的一部分。Quartz 提供了創建弧的兩種方法。CGContentAddArc方法能夠創建一個屬于指定圓的某部分的弧。因此,你需要在方法中指定圓心、半徑、弧度。如果你想創建一個完整的圓,你只需要指定弧度為2π。圖 3-4 展示了獨立繪制的多個路徑,每個路徑都是隨機創造的圓,有些描邊、有些填充。

圖 3-4 隨機創造的圓

當你想使矩形擁有圓角的時候,通常可以使用CGContextAddArcToPoint方法(當然這個方法也不局限于給矩形做圓角)。Quartz 使用你提供的兩個終點,結合當前點來創造兩條切線(實際上就是兩條直線,第一條是:經過當前點和第一個終點的直線;第二條是:經過依次指定的兩個終點的直線);同樣,你還需要指定一個圓弧的半徑。之所以叫這兩條線為切線,是因為,最終的圓弧都將與兩條切線相切,且半徑等于指定的半徑。 如圖 3-5 所示 紅色部分就是實際繪制的部分。

圖 3-5 由兩條切線和半徑定義弧

ps:大家可能會對這個方法不是很好理解。經過查閱官方的詳細API介紹得知:兩個切點(弧和切線的交點),分別為弧的起點和終點;如果弧的起點不是當前點(current point),那么繪制出的結果中會額外添加一條由當前點到弧起點的線段。使用該方法之后,弧終點就變成了當前上下文的起點。官方API詳細描述

曲線(Curves)

二階和三階貝塞爾曲線都是代數曲線,可以用來描述任意數量的有趣的曲線形狀。對起點和終點以及控制點(一個或多個)使用一個多項式計算出了這些曲線上的每個點。這是定義矢量圖的基本方法。使用一個多項式來保存這些點的信息,比起使用數組來說顯得十分精簡,而且它的優點是,你可以在任何情況下重新創建這些曲線。

圖 3-6 展示了大量的隨機獨立繪制的曲線,有些填充,有些描邊。

圖 3-6 獨立的隨機曲線

對于描述二階和三階貝塞爾曲線的多項式以及如何從這些多項式中創造曲線在大多數的數學相關書籍中都可以看得到,本篇文章就不進行討論了。

使用CGContextAddCurevToPoint方法,用你指定的控制點(control points)和終點(endpoint)從當前點追加一個三階貝塞爾曲線。圖 3-7 展示了由這些因素創建的貝塞爾曲線。控制點的位置決定了曲線的幾何形狀,如果控制點都在起點和終點的上方,那么曲線的拱是向上的,反之,如果控制點都在起點和終點的下方,那么拱朝下。

圖 3-7 使用2個控制點創建的三階貝塞爾曲線

你可以使用CGContextAddQuadCurveToPoint方法、你指定的終點和一個控制點來為當前點添加一個二階貝塞爾曲線。圖 3-8 展示了對于相同的起點和終點,不同的控制點對曲線的影響。控制點決定了曲線拱的方向,你不能夠使用二階的貝塞爾曲線來創造任意你想愛那個創造的形狀,但是你可以使用三階貝塞爾曲線來實現他,因為二階貝塞爾曲線僅僅使用了一個控制點;例如,你不可能用一個單一的控制點來創建一個交叉曲線(For example, it’s not possible to create a crossover using a single control point.)。

圖 3-8 二階貝塞爾曲線
關閉一個子路徑(Closing a Subpath)

在應用程序中,使用CGContextClosePath來關閉當前的子路徑。這個函數會添加一條從當前點到起點的線段,然后關閉這個子路徑。當直線、圓弧、曲線在起點結束時,并沒有關閉這個子路徑,你必須通過調用CGContextClosePath來關閉它。

當你的應用程序關閉子路徑時,有些Quartz函數會處理他們,這些函數為每一個關閉了的子路徑從當前點到起點的線段。

在關閉一個子路徑之后,應用程序的其添加路徑操作,如:添加直線、圓弧、曲線等都會視為一個新的子路徑,這個子路徑的起點就是你剛剛關閉的子路徑的起點。

橢圓(Ellipses)

一個橢圓看起來就像是一個被壓扁了的圓。通過指定兩個焦點,然后在找出到到兩個焦點之和為一個你指定值的所有點,它們所構成的曲線就是橢圓。圖 3-9 展示了隨機繪制、填充或描邊的橢圓。

圖 3-9 獨立繪制的橢圓

使用CGContextAddEllipseInRect方法來為當前的路徑添加一個橢圓。該方法中指定的矩形描述了橢圓的邊界。Quartz使用一系列恰當的貝塞爾曲線來表示這個橢圓,橢圓的中心和你指定的矩形的中心是相同的,如果矩形是正方形,那么得到的橢圓就是圓;如果不是正方形,那么它定義了橢圓的主軸和副軸。

使用該方法添加到路徑的橢圓,以一個move-to操作開始,close-subpath操作結束。并且它是順時針繪制的。

矩形(Rectangles)

你可以使用CGContextAddRect添加一個矩形到當前的路徑,在這個方法中,你需要指定一個帶有起點和寬高的矩形。

這種方法添加的矩形,以move-to操作開始,close-subpath操作結束,但是與橢圓不同的是,它是逆時針繪制的。

同樣的你也可以通過CGContextAddRects來為當前路徑添加多個矩形。圖 3-10 展示了隨機繪制、填充或描邊的矩形。

圖 3-10 獨立繪制的矩形

創建一個路徑(Creating a Path)

當你想在一個圖形上下文中創建一個路徑時;首先,你要使用CGContextBeginPath給Quartz發送一個開啟的路徑的信號;接著,調用CGContextMoveToPoint來為你的第一個形狀或者路徑指定一個起始點;在你指定了這個點之后,你就可以添加直線、圓弧、以及曲線,你需要記?。?/p>

  • 在開始一個新路徑之前調用CGContextBeginPath。
  • 線、圓弧、曲線都是從當前點開始繪制的。一個空的路徑沒有當前點;你必須調用CGContextMoveToPoint或者一個包含該做法的函數,來為你的第一個形狀或者子路徑設置起始點。
  • 當你想要關閉一個路徑的子路徑時,調用CGContextClosePath來實現它,該方法會添加一個當前點到起始點的線段。即是你沒有指定一個起點,隨后的其他路徑操作,都會開始一個新的子路徑。
  • 當你在繪制弧時,Quartz會額外添加一條由當前點到起始點的線段。
  • 在添加矩形和橢圓時,Quartz會默認添加一個新的關閉的子路徑。
  • 如果你想看見你路徑,你必對它們進行須填充或者描邊。詳見文中的:繪制一個路徑。

當你繪制完一個路徑后,圖形上下文中就不再包含該路徑的信息。在某些情況下,特別是在該路徑表達的場景很復雜時,你可能想重用該路徑;也正是出于這個原因,Quartz提供了兩種數據類型來創建可以重用的路徑:CGPathRefCGMutablePathRef。調用CGPathMutableCreate來創建一個可以修改的CGPath對象,你能夠為其添加直線、圓弧、曲線以及矩形。Quartz提供了很多平行的在文中構建塊討論的方法。這些方式被用于對CGPath操作(而不是圖形上下文)。這些方法是:

  • CGPathCreateMutable,代替 CGContextBeginPath
  • CGPathMoveToPoint,代替 CGContextMoveToPoint
  • CGPathAddLineToPoint,代替 CGContextAddLineToPoint
  • CGPathAddCurveToPoint,代替 CGContextAddCurveToPoint
  • CGPathAddEllipseInRect,代替 CGContextAddEllipseInRect
  • CGPathAddArc,代替 CGContextAddArc
  • CGPathAddRect,代替 CGContextAddRect
  • CGPathCloseSubpath,代替 CGContextClosePath

如果想要了解完整的函數列表,去查看 Quartz 2D Reference Collection文檔。

當你想為當前路徑添加一個Path時,調用CGContextAddPath,這個路徑的狀態在被繪制之前都會存在與圖形上下文。你可以調用CGContextAddPath來再一次添加之前的路徑。

你可以通過CGContextReplacePathWithStrokedPath方法來替換圖形上下文中的路徑(用一個原路徑的描邊來替換)。

繪制一個路徑(Painting a Path)

你可以對當前路徑進行,描邊、填充、或者兩者都。描邊就是對路徑使用一條線在外邊緣繪制,填充則是填充路徑內部的內容。Quartz為填充、描邊或者兩者都實現提供了函數。描邊線的特征以及填充的顏色、計算方式,都是屬于當前圖形狀態的一部分(詳見:圖形狀態)。

影響描邊的參數

可以通過 表 3-1 中的參數來控制描邊的樣式。這些參數是圖形狀態的一部分,這也就意味著,一旦你設置了這些參數的值后,它將會影響接下來的描邊,直到你為其設置了新的值。

表 3-1 影響描邊的參數

參數 設置參數的函數
Line width CGcontextSetLineWidth
Line join CGContextSetLineJoin
Line cap CGContextSetLineCap
Miter limit CGContextSetMiterLimit
Line dash pattern CGContextSetLineDash
Stroke color space CGContextSetStrokeColorSpace
Stroke color CGContextSetStrokeColor、CGContextSetStrokeColorWithColor
Stroke pattern CGContextSetStrokePattern
  • line width 表示線的總寬度,它的單位是在用戶空間內的單位。線橫跨路徑,在路徑的兩側各占總寬度的一半。
  • line join 指定了Quartz如何處理兩條教誨的線段。Quartz支持的line join 樣式在 表3-2 中描述,默認的值是 miter join。

表 3-2 Line join styles

樣式(Style) 展示(Appearance) 描述(Description)
Miter join
Quartz擴展兩條線段的外邊緣,直到它們組成一個角度,就像相框一樣。如果線段組成的角度太尖銳了,就會使用bevel join 的樣式來連接;如果miter除以線寬大于miter limit的話,我們就判定它太尖銳
Round join
Quartz使用一個直徑為線寬(line width)的半圓連接外緣,半圓內部的區域是被填充的。
Bevel join
Quartz finishes the two segments with butt caps. The resulting notch beyond the ends of the segments is filled with a triangle.
  • line cap 指明了CGContextStrokePath函數繪制線終點的方式。Quartz 支持的 line cap 樣式都列在 表 3-3 中,默認的樣式是 butt cup。

表 3-3 Line cap 的樣式

樣式(Style) 展示(Appearance) 描述(Description)
Butt cap
Quartz 對于描邊的端點直接切斷,沒有任何的補充填充
Round cap
Quartz 在兩條邊緣(上下邊緣)線段交匯的地方繪制一個直徑為line width 的圓,圓內部的區域是被填充的。
Projecting square cap
Quartz 在兩端擴展一半 line width 的長度的矩形。

在一個關閉的子路徑中,它把起始點看做是一個連接(junction),因此起點的渲染會使用設置的line-join值。作為對比,如果你僅僅是手動添加一條線段到起始點,那么對于path的兩端都會使用設置的line-cap值來展示。

  • line dash pattern 允許你沿著描邊的路徑來繪制虛線。你可以通過傳入CGContextSetLineDash方法的dash數組和phase參數來控制虛線的大小和位置。
void CGContextSetLineDash (
    CGContextRef ctx,
    CGFloat phase,
    const CGFloat lengths[],
    size_t count
);

參數lengths指明了虛線的繪制部分和空白部分,它們是間接交替的{繪制、空白、繪制、空白}。參數phase指定了繪制虛線開始的起點,如lengths為{50,10}時表示50的繪制和10的空白互相交替,如果指定了phase為40,那么繪制和空白的交替為:(50-40)、10、50、10、50、10、...

圖 3-11 一些虛線的繪制

圖 3-11 一些虛線的繪制

描邊的色域決定了顏色將被如何解析,你可以指定一個CGColorRef類型的數據(同時包含了色域和顏色值)。更多設置顏色見:顏色和色域。

路徑描邊的函數(Functions for Stroking a Path)

表 3-4 展示了Quartz提供的對當前路徑進行描邊的函數,有些是對矩形和橢圓進行描邊的快捷方法。

表 3-4 描邊的方法(函數)

函數(Function) 描述(Description)
CGContextStrokePath 對當前路徑進行描邊
CGContextStrokeRect 對指定的矩形進行描邊
CGContextStrokeRectWithWidth 使用指定的寬度對指定的矩形進行描邊
CGContextStrokeEllipseInRect 對指定矩形的內接橢圓進行描邊
CGContextStrokeLineSegments 對一系列線段進行描邊
CGContextDrawPath 如果你傳入了kCGPathStroke參數,則會對當前路徑進描邊,如果你想即填充又描邊見本章:路徑的填充

函數CGContextStrokeLineSegments等價與下面的代碼:

CGContextBeginPath (context);
for (k = 0; k < count; k += 2) {
    CGContextMoveToPoint(context, s[k].x, s[k].y);
    CGContextAddLineToPoint(context, s[k+1].x, s[k+1].y);
}
CGContextStrokePath(context);

當你調用CGContextStrokeLineSegments時,你需要指定成對的點的數組,每一對值都包含了線段的起點和終點。例如,數組中的第一個點是第一條線段的起點,第二個點是第一條線段的終點,第三個點是第二條線段的起點,以此類推。

路徑的填充(Filling a Path)

當你填充當前路徑時,Quartz把路徑中的每一個子路徑都視作關閉的路徑。然后用這些關閉的路徑來計算需要填充的像素。Quartz有兩種可以使用的方法來計算填充區域。簡單的路徑,例如橢圓、矩形有一個完美定義(well-defined)的區域。但是,如果你的路徑包含重疊的線段或者包含多個路徑,例如 圖 3-12 展示的同心圓,你有兩種方式來決定填充區域。

默認的填充規則叫做:非零繞數規則(nonzero winding number rule)。想要知道一個確定的點是否會被繪制,從這個點和一個超出路徑邊界的點畫一條線,以count=0開始計數,如果路徑從左到右穿過這條線,那么count增加1,如果路徑從右到左穿過,count減1。如果照這樣計算出的結果為0,那么該點就不會被繪制,否則則會繪制。因此路徑的繪制方向會影響最終的填充結果。圖 3-12 展示了兩組同心圓使用非零繞數規則的不同結果,當圓在使用同一方向繪制時,兩個圓都進行了填充;當兩個圓以不同的方向繪制時,內部的小圓沒有被填充。

你也可以選擇:奇偶法則(even-odd rule)。想要知道一個確定的點是否會被繪制,從這個點和一個超出路徑邊界的點畫一條線,以count=0開始計數,如果有路徑穿過這根線,那么count增加1。如果最終得到的結果為偶數,那么這個點就不會進行繪制,反之,結果為奇數時,該點會進行繪制。正如 圖3-12 所示,路徑的方向并不會影響填充的結果。

圖 3-12 對同心圓使用不同的填充規則

表 3-5 列舉了Quartz提供的填充當前路徑的函數,有些是用于快速填充矩形和橢圓的。

表 3-5 路徑填充的函數

函數(Function) 描述(Description)
CGContextEOFillPath 對當前路徑使用奇偶法則進行填充
CGContextFillPath 對當前路徑使用非零繞數規則進行填充
CGContextFillRect 填充一個指定的矩形
CGContextFillRects 填充多個指定的矩形
CGContextFillEllipseInRect 填充一個指定矩形的內接橢圓
CGContextDrawPath 如果你傳入了:kCGPathFill(非零繞如規則)或者kCGPathEOFill(奇偶法則),那么就會進行填充。如果你傳入的參數是:kCGPathFillStroke或者kCGPathEOFillStroke,那么既會進行填充也會進行描邊

設置混色模式(Setting Blend Modes)

混色模式(Blend Modes)用于指示Quartz如何在一個背景上進行繪制。Quartz使用普通混色模式作為默認的模式,它遵循下列的表達式:

result = (alpha * foreground) + (1 - alpha) *background

顏色和色域中詳細描述了一個顏色alpha值的含義,alpha指明了顏色的不透明度。當alpha值等于1時,這個顏色完全不透明。對于完全不透明的顏色來說,當你繪制的時候使用普通混色模式,你繪制的任何內容會完全遮蓋背景色。

你可以通過調用CGContextSetBlendMode方法,并傳入恰當的參數,設置混色模式來完成許多效果。需要記住的是混色模式圖形狀態(Graphics state)的一部分,因此,如果你在設置之前調用了CGContextSaveGState,那么你可以在使用之后調用CGContextRestoreGState來還原之前的混色模式

本部分剩下的內容展示了在 圖3-14 上繪制 圖3-13 的矩形。在每一個案例中(圖3-15 到 圖3-30),背景矩形(圖3-14)都使用了普通混色模式進行繪制;然后使用CGContextSetBlendMode來設置混色模式;最后繪制前景矩形(圖3-13)。

圖 3-13 前景矩形

圖 3-13 前景矩形

圖 3-14 背景矩形

圖 3-14 背景矩形

你也可以使用混色模式來復合兩張圖片,或者在當前圖形上下文中復合一張圖片。對圖片使用混色模式展示了更多關于圖片的復合和效果。
本文會引用百度百科對混合模式(多數人譯為混合模式)的講解。

普通混色模式(Normal Blend Mode)

普通混色模式是默認的模式,調用函數CGContextSetBlendMode并傳入kCGBlendModeNormal參數來將混色模式設置為默認值。圖3-15展示了使用普通混色模式將 圖3-13 繪制到 圖3-14上的結果。

圖 3-15 使用普通混色模式繪制矩形
正片疊底模式(Multiply Blend Mode)

正片疊底模式會將前景和背景色的取樣相乘,然后得到一個顏色比兩者都暗的結果。圖 3-16 展示了使用正片疊底的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeMultiply常量來使用該模式。

圖 3-16 正片疊底效果展示

百度百科解釋:

公式:C=(A*B)/255 (文中C為結果顏色、A為背景色、B為前景色)

此模式就象是將兩副透明的圖像重疊夾在一起放在一張發光的桌子上。

將兩個顏色的像素值相乘,然后除以255得到的結果就是最終色的像素值。通常執行正片疊底模式后的顏色比原來兩種顏色都深。任何顏色和黑色正片疊底得到的仍然是黑色,任何顏色和白色執行正片疊底則保持原來的顏色不變,而與其他顏色執行此模式會產生暗室中以此種顏色照明的效果。

在MuItiply模式 中應用較淡的顏色對圖像的最終像素顏色沒有影響。 MuItiply模式模擬陰影是很捧的?,F實 中的陰影從來也不會描繪出比源材料(陰影)或背景(獲得陰影的區域)更淡的顏色或色調的 特征。用戶將在本章中使用MuItiply模式在恢復的圖像中對Lee加入一個下拉陰影。在RGB模式下,每一個像素點的色階范圍是0-255,純黑色的色階值是0,純白色的色階值是255。

濾色模式(Screen Blend Mode)

濾色模式將兩個顏色的補色樣本相乘,得到了最低亮度為兩者中最亮者的顏色為結果。圖 3-17 展示了使用該模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeScreen常量來使用該模式。

圖 3-17 濾色模式效果

百度百科解釋:

公式:

作用結果和正片疊底剛好相反,它是將兩個顏色的互補色的像素值相乘,然后除以255得到的最終色的像素值。通常執行濾色模式后的顏色都較淺。任何顏色和黑色執行濾色,原色不受影響;任何顏色和白色執行濾色得到的是白色;而與其他顏色執行濾色會產生漂白的效果。

此屏幕模式對于在圖像中創建霓虹輝光效果是有用的。如果在層上圍繞背景對象的邊緣涂了白色(或任何淡顏色),然后指定層Screen模式,通過調節層的opacity設置就能 獲得飽滿或稀薄的輝光效果。

(附:在Screen和Multipy運算中的重點是----兩幅圖做Screen運算會加強亮的部分;做Multipy運算則會加強兩幅圖中暗的部分)

疊加模式(Overlay Blend Mode)

疊加模式會根據背景色來使用正片疊加濾色模式。它保留了原背景色的高光和陰影部分。圖 3-18 展示了使用該模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeOverlay常量來使用該模式。

圖 3-18 使用疊加模式的效果

百度百科解釋:

公式:當A<=128時,

當A>128時,

在保留底色明暗變化的基礎上使用“正片疊底”或“濾色”模式,繪圖的顏色被疊加到底色上,但保留底色的高光和陰影部分。底色的顏色沒有被取代,而是和繪圖色混合來體現原圖的亮部和暗部。使用此模式可使底色的圖像的飽和度及對比度得到相應的提高,使圖像看起來更加鮮亮。

這種模式以一種非藝術邏輯的方式把放置或應用到一個層上的顏色同背景色進行混 合,然而,卻能得到有趣的效果。背景圖像中的純黑色或純白色區域無法在Overlay模式下 顯示層上的Overlay著色或圖像區域。背景區域上落在黑色和白色之間的亮度值同Overlay 材料的顏色混合在一起,產生最終的合成顏色。為了使背景圖像看上去好像是同設計或文本 一起拍攝的,Overlay可用來在背景圖像上畫上一個設計或文本。

變暗模式(Darken Blend Mode)

選擇兩種顏色中數值較小的顏色分量,作為新的分量來組成混合后的顏色。因此混合之后的顏色會看起來暗一些。圖 3-19 展示了該模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeDarken常量來使用該模式。

圖 3-19 使用變暗模式的效果

百度百科解釋:

公式:C=Min(A,B)

與Lighten相反,將兩個圖像中更暗的那個被選來作為結果。

用于查找各顏色通道內的顏色信息,并按照像素對比底色和繪圖色,那個更暗,便以這種顏色作為此圖像最終的顏色,也就是取兩個顏色中的暗色作為最終色。亮于底色的顏色被替換,暗于底色的顏色保持不變。

變亮模式(Lighten Blend Mode)

選擇兩種顏色中數值較大的顏色分量,作為新的分量來組成混合后的顏色。因此混合之后的顏色會看起來亮一些。圖 3-20 展示了該模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeLighten常量來使用該模式。

圖 3-19 使用變暗模式的效果

百度百科解釋:

公式:C=Max(A,B)

與Darken相反,取兩個像素中更亮的作為結果。

查看每個通道的顏色信息,并按照像素對比兩個顏色,那個更亮,便以這種顏色作為此像素最終的顏色,也就是取兩個顏色中的亮色作為最終色。繪圖色中亮于底色的顏色被保留,暗于底色的顏色被替換。

顏色減淡模式(Color Dodge Blend Mode)

指定變亮背景色的樣本來影響前景色。如果前景色值為黑色,那么不會產生任何效果。圖 3-21 展示了使用該模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeColorDodge常量來使用該模式。

圖 3-21 使用顏色減淡模式的效果

百度百科解釋:

公式:

查看每個通道的顏色信息,通過降低“對比度”使底色的顏色變亮來反映繪圖色,和黑色混合沒變化。

除了指定在這個模式的層上邊緣區域更尖銳,以及在這個模式下著色的筆畫之外, Color Dodge模式類似于Screen模式創建的效果。另外,不管何時定義color Dodge模式混合 前景與背景像素,背景圖像上的暗區域都將會消失。

顏色加深模式(Color Burn Blend Mode)

指定變暗背景色的樣本來影響前景色。如果前景色值為白色,那么不會產生任何效果。圖 3-22 展示了使用該模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeColorBurn常量來使用該模式。

圖 3-22 顏色加深模式效果

百度百科解釋:

公式:

查看每個通道的顏色信息,通過增加“對比度”使底色的顏色變暗來反映繪圖色,和白色混合沒變化。

除了背景上的較淡區域消失,且圖像區域呈現尖銳的邊緣特性之外,這種Color Burn模式創建的效果類似于由MuItiply模式創建的效果。

柔光模式(Soft Light Blend Mode)

根據要混合的前景色,來變暗或者變亮的顏色。如果前景色比50%灰度要亮,那么背景色會變亮,類似于減淡(dodging);如果前景色比50%灰度要深,那么背景色會變暗,類似于加深(burning);如果前景色等于50%灰度,那么背景色不會產生改變。如果前景色為純黑或者純白色,那么背景色僅僅是會變得更暗或更亮,但是,當底色也為純黑或者純白時,不會產生這樣的效果。圖 3-23 展示了柔光模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeSoftLight常量來使用該模式。

圖 3-23 柔光模式效果

百度百科解釋:

公式:

當B<=128時,

當B>128時,

根據繪圖色的明暗程度來決定最終色是變亮還是變暗,當繪圖色比50%的灰要亮時,則底色圖像變亮。當繪圖色比50%的灰要暗時,則底色圖像就變暗。如果繪圖色有純黑色或純白色,最終色不是黑色或白色,而是稍微變暗或變亮。如果底色是純白色或純黑色,不產生任何效果。此效果與發散的聚光燈照在圖像上相似。

強光模式(Hard Light Blend Mode)

根據前景色來選擇正片疊底(multiply)或者濾色(screen);如果前景色大于50%的灰度,那么背景色就會變得更亮,類似于濾色(screening);反之,如果前景色比50%灰度小,那么背景色就會變暗,類似于正片疊底(multiply);如果前景色的灰度值等于50%,那么前景色不會改變。純黑或者純白的前景色會產生純黑或者純白的結果。圖 3-24 展示了強光模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeHardLight常量來使用該模式。

圖 3-24 強光模式效果

百度百科解釋:

公式:

當B<=128時,

;

當B>128時,

。

根據繪圖色來決定是執行“正片疊底”還是“濾色”模式。當繪圖色比50%的灰要亮時,則底色變亮,就執行“濾色”模式一樣,這對增加圖像的高光非常有幫助;當繪圖色比50%的灰要暗時,則底色變暗,就執行“正片疊底”模式一樣,可增加圖像的暗部。當繪圖色是純白色或黑色時得到的是純白色和黑色。此效果與耀眼的聚光燈照在圖像上相似。像亮則更亮,暗則更暗。

這種模式實質上同Soft Light模式是一樣的。它的效果要比Soft Light模式更強烈一些,同Overlay一樣,這種模式 也可以在背景對象的表面模擬圖案或文本。

差值模式(Difference Blend Mode)

將前景色和背景色的分量差值作為新的顏色,如果前景色是黑色,那么,不會對背景色產生任何效果。 圖 3-25 展示了差值模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeDifference常量來使用該模式。

圖 3-25 差值模式效果

百度百科解釋:

公式:C=|A-B|

查看每個通道中的顏色信息,比較底色和繪圖色,用較亮的像素點的像素值減去較暗的像素點的像素值。與白色混合將使底色反相;與黑色混合則不產生變化。

排除模式(Exclusion Blend Mode)

該模式產生的效果和差值模式類似,只是沒有那么明顯。前景色為純白時,背景色會變成它的反相;前景色為黑色時,不會對背景色產生影響。圖 3-26 展示了排除模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeExclusion常量來使用該模式。

圖 3-26 排除模式的效果

百度百科介紹:

公式:

可生成和差值模式相似的效果,但比差值模式生成的顏色對比度較小,因而顏色較柔和。與白色混合將使底色反相;與黑色混合則不產生變化。

色相模式(Hue Blend Mode)

使用背景色的亮度和飽和度以及前景色的色相來創建最終的顏色。圖 3-27 展示了色相模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeHue常量來使用該模式。

圖 3-27 色相模式效果
飽和度模式(Saturation Blend Mode)

使用背景色的亮度和色相以及前景色的飽和度來創建最終的顏色。對于沒有飽和度的背景區域(即是純灰區域),不會產生影響。圖 3-28 展示了使用飽和度模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeSaturation常量來使用該模式。

圖 3-28 飽和度模式效果
顏色模式(Color Blend Mode)

該模式使用背景圖的亮度和前景圖的色相和飽和度來創造新的繪制結果。這種模式保護了圖片中的灰階,你可以使用這種模式為黑白圖像或者彩色圖像著色。圖 3-29 展示了使用顏色模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeColor常量來使用該模式。

圖 2-29 顏色模式效果
亮度模式(Luminosity Blend Mode)

該模式使用背景色的色相和飽和度以及前景色的亮度來創建新的結果。這個模式產生的效果與顏色模式相反。 圖 3-30 展示了使用亮度模式的效果。調用CGContextSetBlendMode函數時,傳入kCGBlendModeLuminosity常量來使用該模式。

圖 3-30 使用亮度模式的效果

路徑的裁剪(Clipping to a Path)

路徑的當前裁剪區域就像是一個遮罩(mask)一樣,允許你隔離你不想繪制的區域。例如,如果你僅僅是想展示一個很大位圖的一小部分,你就可以通過設置裁剪區域來實現。

進行繪制的時候,Quartz僅僅繪制了裁剪區域內的內容。繪制后,在裁剪區域內的關閉路徑內可見,在裁剪區域外的關閉路徑不可見。

當圖形上下文剛剛初始化的時候,裁剪區域包含了整個上下文區域(如,一個PDF的media box)。在設置好當前路徑之后,你調用一個裁剪的函數(而不是繪圖函數)來設置裁剪區域。裁剪函數使當前路徑的填充區域和存在的裁剪區域相交,也就是說,你可以通過它來縮小圖片的可見區域,但是你不能增加原本的可見區域。

裁剪區域是圖形狀態的一部分,因此你可以保存在添加裁剪區域之前的狀態,以便于裁剪之后進行恢復。

清單 3-1 展示了設置一個圓形的裁剪區域的代碼;這些代碼使得繪畫被裁剪,就像圖 3-3 那樣。(另一個例子在漸變章節的裁剪上下文中)

清單 3-1 設置一個圓形的裁剪區域

CGContextBeginPath (context);
CGContextAddArc (context, w/2, h/2, ((w>h) ? h : w)/2, 0, 2*PI, 0);
CGContextClosePath (context);
CGContextClip (context);

表 3-6 裁剪圖形上下文的函數

函數(Function) 描述(Description)
CGContextClip 使用非零繞數規則來計算當前路徑和裁剪路徑的相交區域,并將其作為新的裁剪區域。
CGContextEOClip 使用奇偶法則來計算當前路徑和裁剪路徑的相交區域,并將其作為新的裁剪區域。
CGContextClipToRect 使用指定矩形和當前裁剪區域的相交區域作為新的裁剪區域。
CGContextClipToRects 與指定單個矩形相同,指定多個矩形。
CGContextClipToMask 在你指定的矩形中增加一個遮罩來和當前的裁剪區域相交,之后的一系列操作都會被裁剪(詳見: Masking an Image by Clipping the Context)。

上一章:圖形上下文(Graphics Context)
下一章:顏色與色域 (Color and Color Spaces)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容