
CoreGraphics是"藝名",學名是Quartz 2D,是二維圖形繪制引擎,支持 iOS 和 OS X。
Quartz 2D的API使用簡單,提供了很多強大的特性,如:透明層,基于路徑繪圖,離屏渲染,先進的色彩管理,防鋸齒渲染,以及PDF文件的創(chuàng)建、展示和解析。
關(guān)于CG,工作用到的并不是非常多,但是作為開發(fā)者們耳熟能詳?shù)目蚣?、其?yōu)秀的特性,奈何不了手癢癢。一直關(guān)于CG限于閱讀博客、官文(官方文檔),但“紙上得來終覺淺,絕知此事要躬行”啊。
此文是對于官文的總結(jié)和應(yīng)用。
簡介
哪些場景下會用到CoreGraphics
1.繪制圖形。
2.需要提供圖像編輯功能。
3.創(chuàng)建或者展示bitmap圖片。
4.與PDF相關(guān)的操作。
概覽
Page(畫布)
Quartz 2D在圖像中使用了繪畫者模型(painter’s model)。在繪畫者模型中,簡單說,當前的圖層A,在上面添加圖層B,A被B遮蓋的地方將不會顯示出來,而只顯示A未被覆蓋的地方和B層。
Page可以是一張紙(如果輸出設(shè)備是打印機),也可以是虛擬的紙張(如果輸出設(shè)備是PDF文件),還可以是bitmap圖像。這根據(jù)實際使用的graphics context而定。
Graphics Context(圖形上下文)
Graphics Context 是一種不透明數(shù)據(jù)類型,它封裝了Quartz繪制圖像到輸出設(shè)備上所用到的信息,輸出設(shè)備可以是PDF文件,bitmap內(nèi)存或者顯示器。同一張圖片可以通過指定不同的Context,即可輸出到不同的設(shè)備上。
Quartz提供了以下幾種類型的Graphics Context,詳細的介紹將在后續(xù)章節(jié)說明:
- Bitmap Graphics Context
- PDF Graphics Context
- Window Graphics Context
- Layer Context
- Post Graphics Context
其他的圖形上下文
除了上面幾種Context,Quartz還提供下面這些上下文,他們都以CG開頭,Quartz 2D在這些context上創(chuàng)建對象操作對象,從而獲得某一特定的輸出(大白話這么說,根據(jù)你要創(chuàng)建的東西不一樣,可以是路徑、圖片、layer等等,而創(chuàng)建不同的context,從而輸出你要的結(jié)果,比如一張美美的圖片啦)。
常用的
- CGPathRef:用于向量圖,可創(chuàng)建路徑,并進行填充或描畫(stroke)
- CGImageRef:用于表示bitmap圖像和基于采樣數(shù)據(jù)的bitmap圖像遮罩。
- CGLayerRef:用于表示可用于重復(fù)繪制(如背景)和幕后(offscreen)繪制的繪畫層
- CGPatternRef:用于重繪圖
- CGShadingRef、CGGradientRef:用于繪制漸變
不常用的 詳細說明鏈接
- CGFunctionRef; CGColorRef, CGColorSpaceRef; CGImageSourceRef,CGImageDestinationRef; CGFontRef; CGPDFDictionaryRef, CGPDFObjectRef, CGPDFPageRef; CGPDFStream, CGPDFStringRef, and CGPDFArrayRef;
CGPDFScannerRef, CGPDFContentStreamRef;
CGPSConverterRef;
Quartz 2D 坐標系統(tǒng)
在iOS 3.2以后的版本,當創(chuàng)建一個繪圖上下文時,UIKit對上下文進行了額外的修改以匹配UIKit坐標習慣。但,patterns和shadows(不被CTM影響)單獨進行調(diào)整以匹配UIKit坐標系統(tǒng)。因為需要理解在哪種上下文中進行繪制,并調(diào)整行為以匹配上下文的預(yù)期。
內(nèi)存管理
通常,以”Create”或“Copy”單詞的函數(shù)獲取一個對象,當使用完后必須釋放,否則將導(dǎo)致內(nèi)存泄露。如果不是用上面的兩種“關(guān)鍵字”定義的,你將不會擁有對象的引用,不需要釋放它。
如果你對一個對象沒有擁有權(quán)卻想要引用它,你必須retain它,并在不需要的時候手動釋放它,相應(yīng)的方法。
例如:創(chuàng)建了一個CGColorspace對象,則使用函數(shù)CGColorSpaceRetain和CGColorSpaceRelease來retain和release對象。同樣,可以使用Core Foundation的CFRetain和CFRelease,但是注意不能傳遞NULL值給這些函數(shù)。
圖形上下文(Graphics Contexts)
獲取上下文的方式有:Quartz提供的創(chuàng)建函數(shù)、Mac OS X框架或IOS的UIKit框架提供的函數(shù)。Quartz提供了多種Graphics Context的創(chuàng)建函數(shù),包括bitmap和PDF。
iOS,在View Graphics Context繪制
在iOS應(yīng)用中,視圖顯示在屏幕上及它的內(nèi)容需要更新時會調(diào)用被調(diào)用drawRect:方法。你只需要實現(xiàn)drawRect:方法,并在其中獲取上下文(視圖對象會配置一個上下文給你),繪制你想要的圖像。
調(diào)用UIGraphicsGetCurrentContext獲取當前的上下文。
樣例代碼
CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(context, 1, 0, 0.5, 1); CGContextFillRect(context, CGRectMake (0, 0, 250, 150));
在Mac OS X中創(chuàng)建一個窗口Graphics Context
內(nèi)容不多,關(guān)于Mac開發(fā),不多占用篇幅了,見參考文檔吧。
創(chuàng)建 PDF Graphics Context
Quartz2D API 提供了兩個函數(shù)來創(chuàng)建 PDF Graphics Context。
CGPDFContextCreateWithURL。當你需要用 Core Foundation URL 指定 PDF 輸出的位置時使用該函數(shù)。
CGPDFContextCreate 當需要將pdf輸出發(fā)送給數(shù)據(jù)用戶時使用該方法。
創(chuàng)建 Bitmap Graphics Context
一個位圖Graphics Context接受一個指向內(nèi)存緩存(包含位圖存儲空間)的指針,當我們繪制一個位圖Graphics Context時,該緩存被更新。在釋放Graphics Context后,我們將得到一個我們指定像素格式的全新的位圖。
注:位圖Graphics Context有時用于后臺繪制。CGLayer對象優(yōu)化了后臺繪制,因為Quartz在顯卡上緩存了層。
UIGraphicsBeginImageContext([UIScreen mainScreen].bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1, 0.5, 0.5, 1);
CGContextFillRect(context, CGRectMake (0, 0, 100, 150));
->接下來,獲取圖片
UIImage *imageOne = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
<->或者
CGImageRef myImage = CGBitmapContextCreateImage(context);
CGContextDrawImage(context, CGRectMake(0, 0, 300, 300), myImage);
char *bitmapData = CGBitmapContextGetData(context);
CGContextRelease (context);
if (bitmapData) free(bitmapData);
CGImageRelease(myImage);
支持的像素格式
位圖 Graphics Context支持的像素格式,相關(guān)的顏色空間及像素格式支持的Mac OS X最早版本。像素格式用bpp(每像素的位數(shù))和bpc(每個組件的位數(shù))來表示,詳細格式表格。
iOS 共支持 8 種像素格式。
- Null 8 bpp, 8 bpc, kCGImageAlphaOnly
- Gray 8 bpp, 8 bpc, kCGImageAlphaNone
- Gray 8 bpp, 8 bpc, kCGImageAlphaOnly
- RGB 16 bpp, 5 bpc, kCGImageAlphaNoneSkipFirst
- RGB 32 bpp, 8 bpc, kCGImageAlphaNoneSkipFirst
- RGB 32 bpp, 8 bpc, kCGImageAlphaNoneSkipLast
- RGB 32 bpp, 8 bpc, kCGImageAlphaPremultipliedFirst
- RGB 32 bpp, 8 bpc, kCGImageAlphaPremultipliedLast
反鋸齒
位圖 Graphics Context支持反鋸齒,當位圖的分辯率明顯低于人眼的分辯率時就會產(chǎn)生鋸齒。使形狀看起來更平滑。
我們可以通過調(diào)用CGContextSetShouldAntialias來關(guān)閉位圖Graphics Context的反鋸齒效果。反鋸齒設(shè)置是圖形狀態(tài)的一部分。
可以調(diào)用函數(shù)CGContextSetAllowsAntialiasing來控制一個特定Graphics Context是否支持反鋸齒;
CGContextRef context1 =UIGraphicsGetCurrentContext();
CGContextSetShouldAntialias(context1, YES);
CGContextSetAllowsAntialiasing(context1, YES);
顏色與顏色空間
什么是顏色與顏色空間
Quartz中的顏色是用一組值來表示。而顏色空間用于解析這些顏色信息。例如,下表列出了在全亮度下藍色值在不同顏色空間下的值。如果不知道顏色空間及顏色空間所能接受的值,我們沒有辦法知道一組值所表示的顏色。
| Values(值) | Color Space(顏色空間) | Components(組件) |
|---|---|---|
| 240 degrees 100% 100% | HSB | Hue, saturation, britness |
| 0, 0, 1 | RGB | Red, green, blue |
| 1, 1, 0, 0 | CMYK | Cyan ,magenta, yellow, black |
| 1, 0, 0 | BGR | Blue, green, red |
alpha值(透明度)
使用 CGContextSetAlpha(context, 0.2) 設(shè)置透明度。
使用 CGContextClearRect 清除上下文的 alpha 通道。
創(chuàng)建設(shè)備依賴顏色空間
創(chuàng)建設(shè)備依賴灰度顏色空間。
CGColorSpaceCreateDeviceGray()
創(chuàng)建設(shè)備依賴RGB顏色空間。
CGColorSpaceCreateDeviceRGB()
創(chuàng)建設(shè)備依賴CMYK顏色空間。
CGColorSpaceCreateDeviceCMYK()
設(shè)置顏色空間。
CGContextSetFillColorSpace(context, colorSpace) 或 CGContextSetStrokeColorSpace(context, colorSpace)
樣例代碼:
//Device RGB. 設(shè)置設(shè)備依賴RGB顏色空間并設(shè)置顏色值。
CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
//Device CMYK. 設(shè)置設(shè)備依賴CMYK顏色空間并設(shè)置顏色值。
CGContextSetCMYKStrokeColor(context, 1, 0, 0, 0, 1);
CGContextSetCMYKFillColor(context, 1, 0, 0, 0, 1);
//Device Gray.設(shè)置設(shè)備依賴灰度顏色空間并設(shè)置顏色值。
CGContextSetGrayStrokeColor(context, 0.5, 1);
CGContextSetGrayFillColor(context, 0.5, 1);
//使用 CGColor 設(shè)置顏色值并使用 CGColor 指定的顏色空間。
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat colors[4] = {1.0, 0.0, 0.0, 1.0};
CGColorRef color = CGColorCreate(colorSpace, colors);
CGContextSetStrokeColorWithColor(context, color);
CGContextSetFillColorWithColor(context, color);
調(diào)用如下函數(shù)來便捷的設(shè)置顏色值并使用正在使用的顏色空間。
CGContextSetStrokeColor(context, colors);
CGContextSetFillColor(context, colors);
設(shè)置和創(chuàng)建顏色
通過如下函數(shù)設(shè)置和創(chuàng)建顏色。
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor));
設(shè)置再現(xiàn)意圖(Rending Intent)
每個設(shè)備都有固定的可復(fù)制的顏色范圍(gamut),這是設(shè)備的物理性質(zhì)決定的。當圖像從一個顏色空間向另一個顏色空間轉(zhuǎn)換時,有些源設(shè)備顏色空間中呈現(xiàn)的顏色,不能在目標設(shè)備顏色空間中復(fù)制出來,這些不能復(fù)制的顏色叫色域外(out-of-gamut)顏色。比如 RGB 顏色空間比 CMYK 的顏色空間要大,有些在顯示器上能顯示的顏色不能在打印機上同樣打印出來。因為我們不能在目標設(shè)備顏色空間中復(fù)制出色域外顏色,我們必須用一些其他顏色來替代他們。顏色空間轉(zhuǎn)換時顏色替換調(diào)整的規(guī)則就是再現(xiàn)意圖。你也可以查閱這里關(guān)于“再現(xiàn)意圖”(Rendering intent 和 Understanding rendering intents: Which one and why?
再現(xiàn)意圖用于指定如何將源顏色空間的顏色映射到圖形上下文的目標顏色空間的顏色范圍內(nèi)。
如果不顯式的指定再現(xiàn)意圖,Quartz 使用“相對色度再現(xiàn)意圖”應(yīng)用于所有繪制(不包含位圖圖像)。
對于位圖圖像,Quartz默認使用“感知再現(xiàn)意圖”。
調(diào)用 CGContextSetRenderingIntent(context, kCGRenderingIntentDefault) 來設(shè)置再現(xiàn)意圖。
再現(xiàn)意圖共有以下 5 種。
typedef CF_ENUM (int32_t, CGColorRenderingIntent) {
kCGRenderingIntentDefault,//默認
kCGRenderingIntentAbsoluteColorimetric,//絕對色度再現(xiàn)意圖
kCGRenderingIntentRelativeColorimetric,//相對色度再現(xiàn)意圖
kCGRenderingIntentPerceptual,//感知再現(xiàn)意圖
kCGRenderingIntentSaturation//飽和度再現(xiàn)意圖
};
詳細查看官文文檔 。
這是CoreGraphic第一篇,基礎(chǔ)概念篇,接下來會進入實戰(zhàn)階段,如果你感興趣,來個?和關(guān)注。我們下期見。