CoreGraphics with Swift

概述

Core Graphics Framework是一套基于C的API框架外永,使用了Quartz作為繪圖引擎。它提供了低級別谭跨、輕量級鹃答、高保真度的2D渲染乎澄。該框架可以用于基于路徑的繪圖、變換测摔、顏色管理置济、脫屏渲染,模板锋八、漸變浙于、遮蔽、圖像數(shù)據(jù)管理挟纱、圖像的創(chuàng)建羞酗、遮罩以及PDF文檔的創(chuàng)建、顯示和分析紊服。Quartz 2DCore Graphics Framework的一部分檀轨。能實現(xiàn)以下的功能

  1. 畫圖
  2. 在程序中提供圖形編輯
  3. 生成或者展示位圖
  4. 和PDF文檔工作

Painter Model

一個畫圖模型就是將CALayer上的內(nèi)容渲染到畫布上胸竞,

Graphics context

一個GraphicsContext對象是一個數(shù)據(jù)類型,封裝了Quartz圖像到設(shè)備的信息参萄,總共有5種類型的context:

  1. 窗口
  2. PDF
  3. 位圖
  4. 打印
  5. 反鋸齒
    這些類型主要是包括:繪制參數(shù)卫枝,設(shè)備相關(guān)信息。

圖形API

OpenGL ES是跨平臺的圖形API讹挎,屬于OpenGL的一個簡化版本剃盾。QuartZ 2D是蘋果公司開發(fā)的一套API.OpenGL ES是應(yīng)用程序編程接口,該接口描述了方法淤袜、結(jié)構(gòu)、函數(shù)應(yīng)具有的行為以及應(yīng)該如何被使用的語義衰伯。也就是說它只定義了一套規(guī)范铡羡,具體的實現(xiàn)由設(shè)備制造商根據(jù)規(guī)范去做.

Core Graphics API所有的操作都在一個上下文中進(jìn)行

獲取當(dāng)前context的方法

調(diào)用UIGraphicsBeginImageContextWithOptions函數(shù)就可獲得用來處理圖片的圖形上下文。利用該上下文意鲸,你就可以在其上進(jìn)行繪圖烦周,并生成圖片。調(diào)用UIGraphicsGetImageFromCurrentImageContext函數(shù)可從當(dāng)前上下文中獲取一個UIImage對象怎顾。記住在你所有的繪圖操作后別忘了調(diào)用UIGraphicsEndImageContext函數(shù)關(guān)閉圖形上下文读慎。UIViewCALayer中的渲染方法(比如drawRectdispaly)中,默認(rèn)就是當(dāng)前的context上實現(xiàn)的槐雾,當(dāng)需要在其他的方法上去對layer上進(jìn)行的渲染的時候夭委,需要獲取當(dāng)前的山下文,通過func UIGraphicsGetCurrentContext() -> CGContext?獲取當(dāng)前的上下文募强。

繪圖形式

用Core Graphics之前需要指定一個用于繪圖的圖形上下文(CGContextRef)株灸,這個圖形上下文會在每個繪圖函數(shù)中都會被用到。用UIKit使用的時候自定義UIView,實現(xiàn)drawRect方法時擎值,系統(tǒng)會自動的生成一個CGContextRef慌烧。總共有6種的繪圖方式鸠儿。

  1. 在UIView的子類方法drawRect:

        func drawRect(_ aRect: NSRect) { 
    
             var p = UIBezierPath(UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0,100,100)) 
    
             UIColor.blueColor().setFill() 
    
             p.fill()
    
          } 
    
    
  2. 使用Core Graphics,在drawRect中實現(xiàn)

    func drawRect(_ aRect: NSRect) {

     let con = UIGraphicsGetCurrentContext()
    
     CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100))
    
     CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor)
    
     CGContextFillPath(con);  
    

    }

  3. CALayer的drawLayer上實現(xiàn) 屹蚊。 view調(diào)用setNeedsDisplay,或者view.layer調(diào)用display进每。和1相似

  4. 和2相似,CALayerdrawLayer上實現(xiàn) 通過提供的上下文

  5. UIGraphicsBeginImageContextWithOptions實現(xiàn)

     UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0); 
     let p = UIBezierPath(bezierPathWithOvalInRect:CGRectMake(0,0,100,100)) 
     UIColor.blueColor().setFill() 
     p.fill()
     let  im = UIGraphicsGetImageFromCurrentImageContext()
     UIGraphicsEndImageContext()
    
  6. 使用 UIGraphicsBeginImageContextWithOptions基于Core Graphics實現(xiàn)

     UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0); 
    
     let con = UIGraphicsGetCurrentContext(); 
    
     CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100)); 
    
     CGContextSetFillColorWithColor(con, UIColor.blueColor().CGColor); 
    
     CGContextFillPath(con); 
    
     let im = UIGraphicsGetImageFromCurrentImageContext(); 
    
     UIGraphicsEndImageContext();
    

Quartz2D的數(shù)據(jù)類型

下面列出了Quartz 2D包含的數(shù)據(jù)類型:
CGPathRef:用于向量圖汹粤,可創(chuàng)建路徑,并進(jìn)行填充或描畫(stroke)
CGImageRef:用于表示bitmap圖像和基于采樣數(shù)據(jù)的bitmap圖像遮罩田晚。
CGLayerRef:用于表示可用于重復(fù)繪制(如背景)和幕后(offscreen)繪制的繪畫層
CGPatternRef:用于重繪圖
CGShadingRef玄括、CGGradientRef:用于繪制漸變
CGFunctionRef:用于定義回調(diào)函數(shù),該函數(shù)包含一個隨機的浮點值參數(shù)肉瓦。當(dāng)為陰影創(chuàng)建漸變時使用該類型
CGColorRef, CGColorSpaceRef:用于告訴Quartz如何解釋顏色
CGImageSourceRef,CGImageDestinationRef:用于在Quartz中移入移出數(shù)據(jù)
CGFontRef:用于繪制文本
CGPDFDictionaryRef, CGPDFObjectRef, CGPDFPageRef, CGPDFStream, CGPDFStringRef, CGPDFArrayRef:用于訪問PDF的元數(shù)據(jù)
CGPDFScannerRef, CGPDFContentStreamRef:用于解析PDF元數(shù)據(jù)
CGPSConverterRef:用于將PostScript轉(zhuǎn)化成PDF遭京。在iOS中不能使用胃惜。

CGPath路徑的組成

  1. 線:實線,虛線--->通過CGPathAddLines(_:_:_:_:)等方法
  2. 點:通過moveToPoint(_:)等方法哪雕。
  3. 淮场:CGContextAddArc(_:_:_:_:_:_:_:)CGContextAddArcToPoint(_:_:_:_:_:_:)等方法添加弧線
  4. 曲線:可以通過貝塞爾曲線獲取CGContextAddArcToPoint(_:_:_:_:_:_:),或者自己定義一個貝塞爾曲線
  5. 最后可以選擇閉合曲線CGContextClosePath(_:)

路徑的創(chuàng)建

具體步驟是:

  1. 通過 UIGraphicsGetCurrentContext獲取上下文,如果是在UIView和CALayer的渲染方法中斯嚎,可以不用獲取
  2. 在開始繪制路徑前利虫,調(diào)用函數(shù)CGContextBeginPath,用CGContextBeginPath來標(biāo)記Quartz,因為context一個時間只能有一個path被使用堡僻,如果不使用的話糠惫,會丟棄之前的path
  3. 進(jìn)行線和點的繪制,CGContextMoveToPoint CGContextAddLineToPoint
  4. 通過CGContextAddPath(_:_:)將路線加到上下文上

繪制路徑

路徑的繪制包括填充和描邊钉疫,在繪制前可以先設(shè)置繪制屬性硼讽,包括線寬,顏色等牲阁。

描邊

描邊的屬性包括:線寬固阁,連接點,是否為虛線城菊。以下是一些常用的描邊函數(shù)

描邊函數(shù)

填充

  1. 填充區(qū)域:填充當(dāng)前路徑時备燃,Quartz將路徑包含的每個子路徑都看作是閉合的。然后凌唬,使用這些閉合路徑并計算填充的像素并齐。但是如果路徑是由幾個重疊的部分組成或者路徑包含多個子路徑,則需一定的規(guī)則來定義填充區(qū)域(具體參考官方文檔)
  2. 填充模式:Quartz默認(rèn)使用普通混合模式(normal blend mode)客税,也就是多種顏色重疊的時候冀膝,繪制模式。

路徑剪裁

繪制時霎挟,Quartz只渲染裁剪區(qū)內(nèi)的路徑窝剖,裁剪區(qū)域內(nèi)的閉合路徑是可見的;而在區(qū)域外的部分是不可見的酥夭。

顏色與顏色空間

顏色空間是指一個設(shè)備所能表示的顏色赐纱,通過以下方法

  1. func deviceRGBColorSpace() -> NSColorSpace
  2. func deviceCMYKColorSpace() -> NSColorSpace
    顏色空間有許多種,常用有RGB熬北,CMY疙描,HSB,CMYK,BGR等.alpha表示存在的對象與新對象如何混合。
    CGContextSetAlpha可以指定全局alpha讶隐。

變化

在繪圖空間上起胰,分為用戶空間和設(shè)備空間。context是作用在用戶空間的巫延,然后通過CTM(current transformation matrix)映射到設(shè)備空間效五。CTM有三種操作包括平移CGContextTranslateCTM(_:_:_:)地消,旋轉(zhuǎn)
CGContextRotateCTM(_:_:),縮放CGContextScaleCTM(_:_:_:)。從用戶空間到設(shè)備空間的映射空間可以通過
CGContextGetUserSpaceToDeviceSpaceTransform(_:)獲取到畏妖。

模式

模式(Pattern)是繪制操作的一個序列脉执,這些繪制操作可以重復(fù)地繪制到一個圖形上下文上。當(dāng)用模式的時候戒劫,`Quartz將Page分割成模式單元格的集合半夷,其中每個單元格的大小不是模式圖片的大小,并使用我們提供的回調(diào)函數(shù)來繪制這些單元格迅细。模式單元格之間可以設(shè)置間距巫橄,并且在模式單元格上被繪制

陰影(Shadow)

陰影包括陰影偏移(iOS和MacOS的坐標(biāo)不一樣),通過CGContextSetShadow(_:_:_:)CGContextSetShadowWithColor(_:_:_:_:)設(shè)置陰影茵典。
具體的步驟如下:

  1. 保存圖形狀態(tài)CGContextSaveGState(_:)
  2. 調(diào)用CGContextSetShadow(_:_:_:)
  3. 使用陰影繪制對象
  4. 恢復(fù)圖形狀態(tài)

漸變

漸變對象主要是兩個CGShadingRefCGGradientRef,CGGradientRef對象是對CGShadingRef的封裝湘换,區(qū)別是不需要提供漸變計算函數(shù),只需要提供顏色和位置素組就好

CGGradientRef的創(chuàng)建和使用

使用過程:

  1. 創(chuàng)建CGGradientRef對象敬尺,提供一個顏色空間,以及兩個以上的位置和顏色數(shù)組
  2. 調(diào)用CGContextDrawLinearGradient(_:_:_:_:_:)或者CGContextDrawRadialGradient(_:_:_:_:_:_:_:)
  3. 釋放內(nèi)存

使用CGGradient對象

一個CGGradient對象是一個漸變的抽象定義—它簡單地指定了顏色值和位置贴浙,但沒有指定幾何形狀砂吞。我們可以在軸向和徑向幾何形狀中使用這個對象。作為一個抽象定義崎溃,CGGradient對象可能比CGShading對象更容易重用蜻直。沒有將幾何形狀存儲在CGGradient對象中,這樣允許我們使用相同的顏色方案來繪制不同的幾何圖形袁串,而不需要為多個圖形創(chuàng)建多個CGGradient對象概而。

因為Quartz為我們計算漸變,使用一個CGGradient對象來創(chuàng)建和繪制一個漸變則更直接囱修,只需要以下幾步:

創(chuàng)建一個CGGradient對象赎瑰,提供一個顏色空間,一個飽含兩個或更多顏色組件的數(shù)組破镰,一個包含兩個或多個位置的數(shù)組餐曼,和兩個數(shù)組中元素的個數(shù)。
調(diào)用CGContextDrawLinearGradient或CGContextDrawRadialGradient函數(shù)并提供一個上下文鲜漩、一個CGGradient對象源譬、繪制選項和開始結(jié)束幾何圖形來繪制漸變。
當(dāng)不再需要時釋放CGGradient對象孕似。

let locations = 2;
let locations[2] = { 0.0, 1.0 };
let components[8] = { 1.0, 0.5, 0.4, 1.0, 0.8, 0.8, 0.3, 1.0 }
let myColorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
let myGradient = CGGradientCreateWithColorComponents (myColorspace, components,locations, num_locations);
// myStartPoint, myEndPoint起始點和終點
CGContextDrawLinearGradient (myContext, myGradient, myStartPoint, myEndPoint, 0)

CGShadingRef的創(chuàng)建和使用

CGShadingRef分為創(chuàng)建和使用

CGShadingRef的創(chuàng)建

  1. 獲取顏色空間(CGColorSpace
  2. 設(shè)置起始點和終點
  3. 起始半徑和終止半徑
  4. CGFunctionCreate這個是關(guān)鍵:需要保證繪制到特低點的顏色值
  5. 一個bool值踩娘,指定是否用純色來繪制起始點和終點的擴展區(qū)(可選值)

CGShadingRef的使用

  1. 設(shè)置CGFunction對象計算顏色值 : 也就是計算每一個位置的顏色
  2. 創(chuàng)建CGShadingRef對象
  3. 裁剪上下文
  4. 使用CGShading對象:CGFunctionEvaluate的重寫
  5. 釋放對象

透明

Quartz為每一個上下文維護(hù)一個透明層棧,繪制透明層的步驟如下

  1. 調(diào)用CGContextBeginTransparencyLayer(_:_:)方法表明開始繪制透明
  2. 在透明層中繪制需要的組合對象
  3. 調(diào)用CGContextEndTransparencyLayer(_:)后,透明才會被繪制上去

CGImageRef類型

CGImageRef是CGGraphics 的一種重要的數(shù)據(jù)類型喉祭,主要處理的是位圖與圖像的遮罩养渴。創(chuàng)建一個位圖(CGImageRef)時雷绢,Quartz使用以下信息:

  1. 位圖數(shù)據(jù)源:可以是一個Quartz數(shù)據(jù)提供者或者是一個Quartz圖像源。
  2. 可選的解碼數(shù)組厚脉。(Decode Array)
  3. 插值設(shè)置:這是一個布爾值习寸,指定Quartz在重置圖像大小時是否使用插值算法。
  4. 渲染意圖:指定如何映射位于圖形上下文中的目標(biāo)顏色空間中的顏色傻工。該值在圖像遮罩中不需要霞溪。
  5. 圖像尺寸
  6. 像素格式,包括每個分量中的位數(shù)中捆,每個像素的位數(shù)和每行中的字節(jié)數(shù)鸯匹。

如何創(chuàng)建

創(chuàng)建一個位圖對象主要有以下幾種方法:

  1. 依賴于圖像的數(shù)據(jù)源
  2. 常用CGImageCreate來創(chuàng)建一個我吐
  3. 從PNG,JPEG創(chuàng)建一個CGImage對象,主要通過:CGImageSourceCreateWithURL(_:_:)泄伪,CGImageSourceCreateImageAtIndex(_:_:_:)
  4. 從位圖上下文獲取CGImage對象殴蓬。調(diào)用CGBitmapContextCreateImage(_:)
  5. 從一個已存在圖像中創(chuàng)建子圖像CGImageCreateWithImageInRect(_:_:)

遮罩

一個位圖圖像遮罩定義了如何轉(zhuǎn)換顏色,而不是使用哪些顏色蟋滴。函數(shù)CGImageCreateWithMask通過將圖像遮罩使用到一個圖像上的方式來創(chuàng)建一個圖像染厅。

總結(jié)

首先CoreGraphics是Quartz的一部分,這部分大多數(shù)是C語言結(jié)構(gòu)的津函,Swift和OC的使用上沒有太大區(qū)別肖粮。而在獲取到了上下文后,關(guān)鍵的是如何去確定Path尔苦,貝塞爾曲線等等涩馆,這部分也可以通過專門的工具,在這推薦一個好的軟件PaintCode允坚,能直接導(dǎo)出Swift代碼和OC代碼魂那。具體可以參考用Sketch和PaintCode快速得到繪制代碼。let's Swift

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末稠项,一起剝皮案震驚了整個濱河市涯雅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌展运,老刑警劉巖斩芭,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異乐疆,居然都是意外死亡划乖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門挤土,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琴庵,“玉大人,你說我怎么就攤上這事∶缘睿” “怎么了儿礼?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長庆寺。 經(jīng)常有香客問我蚊夫,道長,這世上最難降的妖魔是什么懦尝? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任知纷,我火速辦了婚禮,結(jié)果婚禮上陵霉,老公的妹妹穿的比我還像新娘琅轧。我一直安慰自己,他們只是感情好踊挠,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布乍桂。 她就那樣靜靜地躺著,像睡著了一般效床。 火紅的嫁衣襯著肌膚如雪睹酌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天剩檀,我揣著相機與錄音憋沿,去河邊找鬼。 笑死谨朝,一個胖子當(dāng)著我的面吹牛卤妒,可吹牛的內(nèi)容都是我干的甥绿。 我是一名探鬼主播字币,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼共缕!你這毒婦竟也來了洗出?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤图谷,失蹤者是張志新(化名)和其女友劉穎翩活,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體便贵,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡菠镇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了承璃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片利耍。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出隘梨,到底是詐尸還是另有隱情程癌,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布轴猎,位于F島的核電站嵌莉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捻脖。R本人自食惡果不足惜锐峭,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望郎仆。 院中可真熱鬧只祠,春花似錦、人聲如沸扰肌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曙旭。三九已至盗舰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桂躏,已是汗流浹背钻趋。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留剂习,地道東北人蛮位。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像鳞绕,于是被迫代替她去往敵國和親失仁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容