本文翻譯自蘋果官方文檔:原文地址
圖形上下文(Graphics Context)
圖形上下文指的是繪圖的地點(diǎn)阳柔,它包含了繪圖系統(tǒng)需要實(shí)現(xiàn)后續(xù)繪圖操作需要的參數(shù)和指定設(shè)備的所有信息。圖形上下文定義了基本的繪圖特性磷雇,如:顏色种远、裁剪區(qū)域盆耽、線的寬度和樣式轰绵、字體信息莹桅、復(fù)合選項(xiàng)等等昌执。
你能夠使用Quartz提供的上下文創(chuàng)建函數(shù)或者由 OS X 以及 iOS 提供的更高級(jí)的函數(shù)來(lái)得到一個(gè)圖形上下文。Quartz為很多不同種類的圖形上下文(如诈泼,bitmap懂拾、PDF)提供了很多函數(shù);你可以用這些來(lái)創(chuàng)建自定義的內(nèi)容铐达。
本章中岖赋,我們將教會(huì)你如何創(chuàng)建各式各樣的圖形上下文(針對(duì)不同的繪圖地點(diǎn))。在代碼中圖形上下文用一個(gè)類型為CGContextRef的數(shù)據(jù)代替瓮孙,這個(gè)數(shù)據(jù)是閉源的唐断。在你獲取到圖形上下文之后选脊,你可以使用Quartz提供的函數(shù)來(lái)進(jìn)行繪制、變換等操作脸甘。
iOS中繪制到頁(yè)面的圖形上下文(Drawing to a View Graphics Context in iOS)
在iOS的一個(gè)APP中,如果你想將內(nèi)容繪制到屏幕恳啥,你需要?jiǎng)?chuàng)建一個(gè)UIView對(duì)象并實(shí)現(xiàn)它的drawRect:方法。當(dāng)View可見并且內(nèi)容需要更新時(shí)丹诀,View的drawRect:將會(huì)被調(diào)用角寸。在調(diào)用drawRect:方法之前,這View對(duì)象自動(dòng)注冊(cè)了它的繪圖環(huán)境忿墅,以方便你能夠快速的繪制扁藕。這個(gè)UIView在注冊(cè)的過(guò)程中,創(chuàng)建了一個(gè)針對(duì)當(dāng)前繪圖環(huán)境的圖形上下文(CGContextRef類型)疚脐。你能夠在drawRect:方法中用使用UIGraphicsGetCurrentContext來(lái)獲取這個(gè)圖形上下文亿柑。
UIKit與Quartz使用著不同的坐標(biāo)系;在UIKit中棍弄,坐標(biāo)系的原點(diǎn)在左上角望薄,y軸正半軸向下延伸;而在Quartz中原點(diǎn)在左下角呼畸,y軸正半軸向上延伸痕支。UIView對(duì)象修改了當(dāng)前圖形上下文的CTM,使得坐標(biāo)系能夠與UIKit匹配蛮原。
UIView詳細(xì)的描述在View Programming Guide for iOS卧须。
在 Mac OS X 中創(chuàng)建一個(gè)窗口圖形上下文(Window Graphics Context)
當(dāng)你在 Mac OS X 中繪制時(shí),你需要?jiǎng)?chuàng)建一個(gè)適合你正在使用框架的圖形上下文儒陨。Quartz 2D 本身沒(méi)有提供函數(shù)來(lái)獲取一個(gè)窗口圖形上下文花嘶。但是,你可以使用Cocoa 框架來(lái)獲取一個(gè)在Cocoa中創(chuàng)建的窗口上下文蹦漠。
你在drawRect:中使用如下代碼來(lái)獲取上下文:
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
currentContext方法返回了一個(gè)屬于當(dāng)前線程的NSGraphicsContext實(shí)例椭员。graphicsPort 方法返回一個(gè)低級(jí)、指定平臺(tái)的圖形上下文笛园,它是一個(gè)Quartz圖形上下文(CGContextRef)隘击,不要被這個(gè)方法的名字弄混淆了,它是有歷史原因的研铆。想要了解更多可以看:NSGraphicsContext Class Reference埋同。
在你獲取到這個(gè)圖形上下文之后,你可以調(diào)用任何Quartz提供的繪圖方法蚜印。你還可以混合使用Quartz 2D 和 Cocoa 繪圖方法莺禁。圖 2-1 展示了一個(gè)在Cocoa View 上的繪制,它是由兩個(gè)部分重疊的矩形構(gòu)成的窄赋,一個(gè)完全不透明的紅色矩形和一個(gè)半透明的藍(lán)色矩形哟冬。你可以在顏色和色域中了解更多楼熄。你能透過(guò)顏色看到多少內(nèi)容是 Quartz 2D 的一個(gè)特征。
想要完成 圖 2-1 繪制的浩峡,首先在Xcode中創(chuàng)建一個(gè)Cocoa應(yīng)用程序工程可岂;然后在Interface Builder中拖拽一個(gè)自定義的View到window并子類化它;接著翰灾,在相關(guān)的子類實(shí)現(xiàn)中寫下如 列表 2-1 中的代碼缕粹。在這個(gè)例子中,這個(gè)view的類叫做MyQuartzView纸淮。該view的drawRect:方法包含了所有的Quartz繪圖代碼平斩。在列表下面有詳細(xì)的解釋。
注意:NSView的drawRect:方法在每次需要被繪制的時(shí)候都會(huì)自動(dòng)調(diào)用咽块。想了解更多關(guān)于重寫drawRect:方法的信息绘面,請(qǐng)見:NSView Class Reference。
列表 2-1 在窗口圖形上下文繪制
@implementation MyQuartzView
- (id)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
return self;
}
- (void)drawRect:(NSRect)rect
{
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort]; // 1
// ********** Your drawing code here ********** // 2
CGContextSetRGBFillColor (myContext, 1, 0, 0, 1);// 3
CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100 ));// 4
CGContextSetRGBFillColor (myContext, 0, 0, 1, .5);// 5
CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200));// 6
}
@end
下面解釋這些代碼做了什么:
- 獲取view的圖形上下文侈沪。
- 你需要把繪圖的代碼寫到這個(gè)地方揭璃。接下來(lái)的4行使用了 Quartz 2D 的函數(shù)。
- 將填充色設(shè)置為一個(gè)完全不透明的紅色亭罪。關(guān)于顏色和alpha(設(shè)置透明度)瘦馍,詳見:顏色和色域。
- 填充了一個(gè)矩形应役,這個(gè)矩形原點(diǎn)在(0,0)情组,寬度為200,高度為100扛吞。關(guān)于繪制矩形的更多內(nèi)容見:路徑(Paths)呻惕。
- 設(shè)置一個(gè)半透明的藍(lán)色為填充色荆责。
- 填充了一個(gè)原點(diǎn)在(0滥比,0),寬度為100做院,高度為200的矩形盲泛。
創(chuàng)建一個(gè)PDF圖形上下文(PDF Graphics Context)
當(dāng)你創(chuàng)建一個(gè)PDF圖形上下文并繪制時(shí),Quartz將你的繪制記錄成一系列的繪圖指令键耕,并將其寫入到一個(gè)文件寺滚。你需要為這個(gè)PDF文件指定一個(gè)輸出位置和默認(rèn)的媒體盒(定義這個(gè)頁(yè)(Page)邊界的矩形)。圖 2-2 展示了用PDF預(yù)覽將使用 PDF Graphics Context 繪制的結(jié)果打開的情形屈雄。
Quartz 2D 的API 提供了兩種函數(shù)來(lái)創(chuàng)建一個(gè)PDF圖形上下文:
- CGPDFContextCreateWithURL,當(dāng)你想為輸出的PDF文件指定一個(gè)路徑時(shí)(CoreFoundation URL)。列表 2-2 展示了如何用這個(gè)函數(shù)創(chuàng)建PDF圖形上下文雀扶。
- CGPDFContextCreate,當(dāng)你想把PDF輸出送到一個(gè)消費(fèi)者(Consumer)處理的時(shí)候(可以在Quartz 2D的數(shù)據(jù)管理中查看更多)奶赔。列表 2-3 展示了如何用這個(gè)函數(shù)創(chuàng)建PDF圖形上下文。
對(duì)于每個(gè)標(biāo)注了數(shù)字的代碼行杠氢,都會(huì)有詳細(xì)的解釋站刑。
iOS 注意:在iOS中的PDF圖形上下文使用了Quartz提供的默認(rèn)坐標(biāo),并沒(méi)有應(yīng)用一個(gè)變換去適配UIKit的坐標(biāo)鼻百。如果你的應(yīng)用程序計(jì)劃在PDF圖形上下文和UIView提供的圖形上下文之間共享繪制代碼绞旅,你的應(yīng)用應(yīng)當(dāng)修改PDF圖形上下文的CTM從而修改坐標(biāo)系。詳見:Quartz 2D Coordinate Systems温艇。
列表 2-2 調(diào)用CGPDFContextCreateWithURL來(lái)創(chuàng)建PDF圖形上下文
CGContextRef MyPDFContextCreate (const CGRect *inMediaBox,
CFStringRef path)
{
CGContextRef myOutContext = NULL;
CFURLRef url;
url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, false); // 1
if (url != NULL) {
myOutContext = CGPDFContextCreateWithURL (url,
inMediaBox,
NULL); // 2
CFRelease(url);// 3
}
return myOutContext;// 4
}
代碼解釋:
- 調(diào)用了 Core Foundation 的函數(shù)來(lái)用CFString創(chuàng)建一個(gè)CFURL對(duì)象因悲,這個(gè)對(duì)象稍后會(huì)被用于MyPDFContextCreate函數(shù)。對(duì)于CFURLCreateWithFileSystemPath勺爱,你傳入第一個(gè)參數(shù)為NULL時(shí)使用默認(rèn)的分配器(allocator)囤捻;同時(shí)你需要指定路徑的樣式,在這個(gè)例子中是一個(gè)POSIX-style的路徑名邻寿。
- 調(diào)用Quartz 2D 的函數(shù)來(lái)創(chuàng)建PDF圖形上下文蝎土,會(huì)使用到剛剛創(chuàng)建的路徑和一個(gè)指示PDF頁(yè)(Page)大小的矩形,這個(gè)矩形在調(diào)用MyPDFContextCreate時(shí)由外部傳入绣否,他表示了默認(rèn)的PDF邊界大小誊涯。
- 釋放CFURL對(duì)象。
- 返回創(chuàng)建的PDF圖形上下文對(duì)象蒜撮。調(diào)用者在不使用的時(shí)候必須釋放這個(gè)圖形上下文暴构。
列表 2-3 調(diào)用CGPDFContextCreate來(lái)創(chuàng)建PDF圖形上下文
CGContextRef MyPDFContextCreate (const CGRect *inMediaBox,
CFStringRef path)
{
CGContextRef myOutContext = NULL;
CFURLRef url;
CGDataConsumerRef dataConsumer;
url = CFURLCreateWithFileSystemPath (NULL,
path,
kCFURLPOSIXPathStyle,
false); // 1
if (url != NULL)
{
dataConsumer = CGDataConsumerCreateWithURL (url);// 2
if (dataConsumer != NULL)
{
myOutContext = CGPDFContextCreate (dataConsumer,
inMediaBox,
NULL); // 3
CGDataConsumerRelease (dataConsumer);// 4
}
CFRelease(url);// 5
}
return myOutContext;// 6
}
代碼解釋:
- 調(diào)用了 Core Foundation 的函數(shù)來(lái)用CFString創(chuàng)建一個(gè)CFURL對(duì)象,這個(gè)對(duì)象稍后會(huì)被用于MyPDFContextCreate函數(shù)段磨。對(duì)于CFURLCreateWithFileSystemPath取逾,你傳入第一個(gè)參數(shù)為NULL時(shí)使用默認(rèn)的分配器(allocator);同時(shí)你需要指定路徑的樣式苹支,在這個(gè)例子中是一個(gè)POSIX-style的路徑名砾隅。
- 使用CFURL對(duì)象,創(chuàng)建了一個(gè)Quartz data consumer 對(duì)象债蜜。如果你不想使用CFURL對(duì)象(例如你想要放置的輸出數(shù)據(jù)不能指定CFURL對(duì)象時(shí))晴埂,你可以利用一系列的回掉函數(shù)(callback functions)創(chuàng)建一個(gè)data consumer來(lái)代替CFURL。詳見: Quart 2D 中的數(shù)據(jù)管理寻定。
- 調(diào)用Quartz 2D的函數(shù)來(lái)創(chuàng)建PDF圖形上下文儒洛。
- 釋放data cunsumer。
- 釋放CFURL對(duì)象狼速。
- 返回創(chuàng)建的PDF圖形上下文對(duì)象琅锻。調(diào)用者在不使用的時(shí)候必須釋放這個(gè)圖形上下文。
列表 2-4 展示了MyPDFContextCreate 的使用和繪制。
列表 2-4 在PDF圖形上下文中繪制
CGRect mediaBox;// 1
mediaBox = CGRectMake (0, 0, myPageWidth, myPageHeight);// 2
myPDFContext = MyPDFContextCreate (&mediaBox, CFSTR("test.pdf"));// 3
CFStringRef myKeys[1];// 4
CFTypeRef myValues[1];
myKeys[0] = kCGPDFContextMediaBox;
myValues[0] = (CFTypeRef) CFDataCreate(NULL,(const UInt8 *)&mediaBox, sizeof (CGRect));
CFDictionaryRef pageDictionary = CFDictionaryCreate(NULL, (const void **) myKeys,
(const void **) myValues, 1,
&kCFTypeDictionaryKeyCallBacks,
& kCFTypeDictionaryValueCallBacks);
CGPDFContextBeginPage(myPDFContext, &pageDictionary);// 5
// ********** Your drawing code here **********// 6
CGContextSetRGBFillColor (myPDFContext, 1, 0, 0, 1);
CGContextFillRect (myPDFContext, CGRectMake (0, 0, 200, 100 ));
CGContextSetRGBFillColor (myPDFContext, 0, 0, 1, .5);
CGContextFillRect (myPDFContext, CGRectMake (0, 0, 100, 200 ));
CGPDFContextEndPage(myPDFContext);// 7
CFRelease(pageDictionary);// 8
CFRelease(myValues[0]);
CGContextRelease(myPDFContext);
代碼解釋:
- 聲明用來(lái)定義PDF的media box 的矩形恼蓬。
- 設(shè)置矩形的原點(diǎn)沫浆、寬度和高度。
- 調(diào)用函數(shù)MyPDFContextCreate(列表 2-3)獲取一個(gè)PDF圖形上下文滚秩,并傳入正確的 media box 和路徑专执。CFSTR可以將一個(gè)字符串轉(zhuǎn)換成CFStringRef類型。
- 設(shè)置page的選項(xiàng)郁油。在這個(gè)例子中本股,只有media box 是指定了值的。你不需要傳入相同的矩形來(lái)設(shè)置PDF圖形上下文桐腌。因?yàn)閙edia box 取代了你傳入設(shè)置PDF圖形上下文的矩形拄显。
- 開始一個(gè)page的信號(hào)。這個(gè)方法用于面向頁(yè)面的繪圖案站,即PDF繪圖躬审。
- 調(diào)用Quartz 2D的繪圖函數(shù)。你可以替換接下來(lái)的這四行蟆盐,來(lái)畫你想畫的東西承边。
- PDF page結(jié)束的信號(hào)。
- 在選項(xiàng)字典和PDF圖形上下文不使用時(shí)釋放它們石挂。
你能夠在PDF中寫下任意的內(nèi)容(對(duì)于你的應(yīng)用來(lái)說(shuō)合適的內(nèi)容)博助。如:圖片、文字痹愚、基于路徑的繪圖富岳、鏈接、編碼等等拯腮。更多信息請(qǐng)見:PDF文檔的創(chuàng)建窖式、預(yù)覽和轉(zhuǎn)換。
創(chuàng)建一個(gè)位圖圖形上下文(Bitmap Graphics Context)
位圖圖形上下文接收一個(gè)指向內(nèi)存的指針动壤,這片指向的區(qū)域中包含了位圖(bitmap)萝喘。當(dāng)你在位圖圖形上下文中繪制時(shí),這些字節(jié)流會(huì)得到更新狼电,當(dāng)你釋放這個(gè)圖形上下文時(shí)蜒灰,你就在你指定的像素格式下完全更新了這個(gè)bitmap。
注意:位圖圖形上下文有時(shí)候也被用來(lái)做離屏繪制肩碟。在你決定這么做之前,看看:核心圖形圖層繪畫(Core Graphics Layer Drawing)凸椿。CGLayer 對(duì)象(CCGLayerRef)針對(duì)離屏繪制有特定的優(yōu)化削祈,因?yàn)樵诳赡艿臅r(shí)候它將緩存 video card 上的涂層。
iOS 注意:iOS中的應(yīng)用程序應(yīng)當(dāng)使用UIGraphicsBeginImageContextWithOptions方法而不是這里描述的Quartz低級(jí)方法來(lái)獲取圖形上下文。如果你的應(yīng)用程序使用Quartz提供的API創(chuàng)建了一個(gè)離屏的bitmap髓抑,那么這么位圖圖形上下文會(huì)使用Quartz默認(rèn)的坐標(biāo)系咙崎。作為對(duì)比,如果你使用 UIGraphicsBeginImageContextWithOptions 來(lái)創(chuàng)建圖形上下文吨拍,那么UIKit會(huì)對(duì)其(位圖圖形上下文)使用與從UIView獲取圖形上下文相同的變換褪猛。這就允許你使用相同的坐標(biāo)系來(lái)繪制。雖然你的應(yīng)用程序能夠人為地來(lái)完成這些補(bǔ)償羹饰,但是在實(shí)際中伊滋,這樣做沒(méi)有任何好處。
你可以使用CGBitmapContextCreate函數(shù)來(lái)創(chuàng)建一個(gè)位圖圖形上下文队秩,這個(gè)函數(shù)接收下列的參數(shù):
- 數(shù)據(jù)(data)笑旺。提供一個(gè)指向內(nèi)存的指針,指向的這個(gè)地方是你想要存放繪圖渲染的地方馍资;這塊內(nèi)存的大小至少要有(bytesPerRow*height)字節(jié)筒主。
- 寬度(width)。指定位圖的像素寬度(單位是像素)鸟蟹。
- 高度(height)乌妙。指定位圖圖像的高度(單位是像素)。
- 組成部分的位數(shù)(bitsPerComponent)建钥。指定每一個(gè)像素中組件的位數(shù)(bits冠胯,二進(jìn)制位)。例如:對(duì)于32位格式的RGB色域锦针,你需要為每一個(gè)部分指定8位荠察。見:本章中的表“支持的像素格式”。
- 每行的字節(jié)數(shù)(bytesPerRow)奈搜。指定內(nèi)存中位圖每一行的字節(jié)數(shù)悉盆。
注意:當(dāng)你創(chuàng)建一個(gè)位圖圖形上下文后,如果你確保數(shù)據(jù)(data)和每行的字節(jié)數(shù)(bitsPerCompoent)是16為對(duì)齊的馋吗,那么你將獲得最佳的性能焕盟。
- 色域(colorspace)。位圖圖形上下文所使用的色域宏粤,你可以提供灰階(Gray)脚翘、RGB、CMYK或者NULL這些色域值給位圖圖形上下文绍哎。更多關(guān)于色域和顏色管理的細(xì)節(jié)来农,見:Color Management Overview。更多關(guān)于顏色創(chuàng)建的信息見:顏色和色域崇堰。更多支持的色域見:位圖圖像和圖像遮罩沃于。
- 位圖信息(bitmapInfo)涩咖。位圖的布局信息,通常用一個(gè)CGBitmapInfo的常量來(lái)表示繁莹。這個(gè)信息指明了位圖是否包含alpha檩互、alpha值在一個(gè)像素中的位置、alpha值是否是預(yù)相乘的(premultiplied)以及顏色的組成到底是浮點(diǎn)還是整數(shù)值等等咨演。想要知道這些常量是什么闸昨、什么時(shí)候使用、Quartz支持的位圖圖形上下文和圖片的像素格式等信息薄风,查看:位圖圖像和圖像遮罩章節(jié)的色域和位圖布局饵较。
列表 2-5 展示了如何創(chuàng)建一個(gè)位圖圖形上下文。當(dāng)你在位圖圖形上下文中繪制時(shí)村刨,Quartz記錄你的繪圖操作告抄,并將其轉(zhuǎn)換數(shù)據(jù)存放到指定的內(nèi)存區(qū)域中。
列表 2-5 創(chuàng)建一個(gè)位圖圖形上下文
CGContextRef MyCreateBitmapContext (int pixelsWide,
int pixelsHigh)
{
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
int bitmapByteCount;
int bitmapBytesPerRow;
bitmapBytesPerRow = (pixelsWide * 4);// 1
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);// 2
bitmapData = calloc( bitmapByteCount, sizeof(uint8_t) );// 3
if (bitmapData == NULL)
{
fprintf (stderr, "Memory not allocated!");
return NULL;
}
context = CGBitmapContextCreate (bitmapData,// 4
pixelsWide,
pixelsHigh,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
if (context== NULL)
{
free (bitmapData);// 5
fprintf (stderr, "Context not created!");
return NULL;
}
CGColorSpaceRelease( colorSpace );// 6
return context;// 7
}
代碼解釋:
- 聲明代表每行有多少字節(jié)的變量嵌牺。在這個(gè)例子中bitmap中的一個(gè)像素由4個(gè)字節(jié)表示打洼,8位的紅、綠逆粹、藍(lán)和alpha募疮。
- 創(chuàng)建了一個(gè)普通的RGB色域,當(dāng)然你也可以創(chuàng)建其他的色域如CMYK僻弹。在顏色和色域中你能了解到普通的(generic)色域是依賴于設(shè)備的阿浓。
- 調(diào)用calloc函數(shù)來(lái)創(chuàng)建一個(gè)用于存儲(chǔ)bitmap數(shù)據(jù)的內(nèi)存塊。在這個(gè)例子中創(chuàng)建了一個(gè)32位的bitmap(32位表示一個(gè)像素蹋绽,每個(gè)像素都包含8位的紅芭毙、綠、藍(lán)和aplha值)卸耘。不難看出每一個(gè)像素占用了4個(gè)字節(jié)(1個(gè)字節(jié)8位)退敦。在 Mac OS 10.6 和 iOS 4 以及之后的版本中,你可以將bitmap data 傳為NULL蚣抗,此時(shí)Quartz將自動(dòng)為你分配bitmap的存儲(chǔ)空間侈百。
- 調(diào)用方法創(chuàng)建一個(gè)位圖圖形上下文,傳入相應(yīng)的參數(shù)翰铡。常量kCGImageAlphaPremultipliedLast指明了alpha值被存儲(chǔ)在每個(gè)像素的最后一個(gè)字節(jié)钝域,同時(shí)它也指明了其中的顏色早已經(jīng)與alpha值相乘過(guò)了。關(guān)于alpha值的預(yù)乘(premultiplied alpha)見:The Alpha Value锭魔。
- 如果上下文沒(méi)有創(chuàng)建成功例证,釋放申請(qǐng)的用來(lái)存放 bitmap data 數(shù)據(jù)的內(nèi)存。
- 釋放色域赂毯。
- 返回創(chuàng)建好的位圖圖形上下文战虏。使用者需要釋放這個(gè)圖形上下文拣宰。
列表 2-6 使用先前創(chuàng)建的MyCreateBitmapContext函數(shù)來(lái)創(chuàng)建一個(gè)位圖圖形上下文党涕,然后使用這個(gè)圖形上下文創(chuàng)建了一個(gè)CGImage對(duì)象烦感,接著將這個(gè)圖片繪制到了一個(gè)窗口圖形上下文上。
圖 2-3 展示了繪制到窗口上的這個(gè)圖片膛堤。
列表 2-6 在位圖圖形上下文上繪制
CGRect myBoundingBox;// 1
myBoundingBox = CGRectMake (0, 0, myWidth, myHeight);// 2
myBitmapContext = MyCreateBitmapContext (400, 300);// 3
// ********** Your drawing code here ********** // 4
CGContextSetRGBFillColor (myBitmapContext, 1, 0, 0, 1);
CGContextFillRect (myBitmapContext, CGRectMake (0, 0, 200, 100 ));
CGContextSetRGBFillColor (myBitmapContext, 0, 0, 1, .5);
CGContextFillRect (myBitmapContext, CGRectMake (0, 0, 100, 200 ));
myImage = CGBitmapContextCreateImage (myBitmapContext);// 5
CGContextDrawImage(myContext, myBoundingBox, myImage);// 6
char *bitmapData = CGBitmapContextGetData(myBitmapContext); // 7
CGContextRelease (myBitmapContext);// 8
if (bitmapData) free(bitmapData); // 9
CGImageRelease(myImage);//10
代碼解釋:
- 聲明了一個(gè)定義了原點(diǎn)和尺寸的變量box手趣,這個(gè)變量將被用于繪制由位圖圖形上下文產(chǎn)生的圖片。
- 設(shè)置這個(gè)box的原點(diǎn)和寬高肥荔。
- 調(diào)用自定義的函數(shù)MyCreateBitmapContext(列表 2-5)來(lái)創(chuàng)建了一個(gè)寬為400px高為300px的像素绿渣。你使用任意尺寸來(lái)創(chuàng)建位圖圖形上下文。
- 調(diào)用Quartz 2D的函數(shù)來(lái)在這個(gè)位圖圖形上下文中繪制燕耿。你能夠自由替換下面4行繪制代碼中符。
- 從位圖圖形上下文中創(chuàng)建了一個(gè)Quartz 2D 圖片(CGImageRef)。
- 將這個(gè)圖片繪制到box指定的窗口圖形上下文中誉帅,這個(gè)有邊界的box指示的坐標(biāo)和尺寸是在用戶空間下的(user space)淀散。例子中沒(méi)有展示如何創(chuàng)建窗口圖形上下文,可以看本章中的在 Mac OS X 中創(chuàng)建一個(gè)窗口圖形上下文蚜锨。
- 獲取和這個(gè)位圖圖形上下文關(guān)聯(lián)的 bitmap data 指針档插。
- 釋放位圖圖形上下文。
- 如果bitmap data 存在則釋放它亚再。
- 在不使用的時(shí)候釋放圖片郭膛。
支持的像素格式(Supported Pixel Formats)
表 2-1 概括了位圖圖形上下文支持的像素格式氛悬、相關(guān)的色域(color space)则剃、Mac OS X中的可用性。像素格式由每個(gè)像素的位數(shù)(bits per pixel -- bpp)和每個(gè)部分的位數(shù)(bits per component -- bpc)表示如捅。表中同樣包含了與像素格式關(guān)聯(lián)的位圖信息常量(bitmap information constant)棍现。想要了解每一個(gè)常量代表什么可以查看:CGImage Reference。
表 2-1 位圖圖形上下文支持的像素格式
色域(Color Space) | 像素格式和位圖信息常量(Pixel format and bitmap information constant) | 可用性 |
---|---|---|
NULL | 8 bpp, 8 bpc, kCGImageAlphaOnly | Mac OS X, iOS |
Gray | 8 bpp, 8 bpc, kCGImageAlphaNone | Mac OS X, iOS |
Gray | 8 bpp, 8 bpc, kCGImageAlphaOnly | Mac OS X, iOS |
Gray | 16 bpp, 16 bpc, kCGImageAlphaNone | Mac OS X |
Gray | 32 bpp, 32 bpc, kCGImageAlphaNone | kCGBitmapFloatComponents | Mac OS X |
RGB | 16 bpp, 5 bpc, kCGImageAlphaNoneSkipFirst | Mac OS X, iOS |
RGB | 32 bpp, 8 bpc, kCGImageAlphaNoneSkipFirst | Mac OS X, iOS |
RGB | 32 bpp, 8 bpc, kCGImageAlphaNoneSkipLast | Mac OS X, iOS |
RGB | 32 bpp, 8 bpc, kCGImageAlphaPremultipliedFirst | Mac OS X, iOS |
RGB | 32 bpp, 8 bpc, kCGImageAlphaPremultipliedLast | Mac OS X, iOS |
RGB | 64 bpp, 16 bpc, kCGImageAlphaPremultipliedLast | Mac OS X |
RGB | 64 bpp, 16 bpc, kCGImageAlphaNoneSkipLast | Mac OS X |
RGB | 128 bpp, 32 bpc, kCGImageAlphaNoneSkipLast | kCGBitmapFloatComponents | Mac OS X |
RGB | 128 bpp, 32 bpc, kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents | Mac OS X |
CMYK | 32 bpp, 8 bpc, kCGImageAlphaNone | Mac OS X |
CMYK | 64 bpp, 16 bpc, kCGImageAlphaNone | Mac OS X |
CMYK | 128 bpp, 32 bpc, kCGImageAlphaNone | kCGBitmapFloatComponents | Mac OS X |
抗鋸齒(Anti-Aliasing)
位圖圖形上下文支持抗鋸齒伪朽≈嵩郏抗鋸齒是對(duì)繪制文字或者圖形時(shí)邊緣出現(xiàn)鋸齒狀情況的糾正。當(dāng)位圖的分辨率大大低于人眼的分辨率時(shí)烈涮,就會(huì)出現(xiàn)鋸齒朴肺。為了使繪制的內(nèi)容變得光滑,Quartz對(duì)包裹在對(duì)應(yīng)圖形形狀外的像素使用了不同的顏色坚洽。通過(guò)這樣的混色方式戈稿,這些形狀看起來(lái)就光滑了一些。你能夠從 圖 2-4 中看出來(lái)抗鋸齒的效果讶舰。同樣鞍盗,你可以在繪制特殊的位圖圖形上下文時(shí)關(guān)閉抗鋸齒(通過(guò)CGContextSetShouldAntialias方法)需了。這個(gè)抗鋸齒設(shè)置是圖形狀態(tài)的(graphics state)一部分。
你同樣也能夠使用CGContextSetAllowsAntialiasing方法針對(duì)一個(gè)特殊的圖形上下文設(shè)置其是否抗鋸齒般甲。當(dāng)函數(shù)的參數(shù)傳入true時(shí)則允許抗鋸齒肋乍。這個(gè)設(shè)置不屬于圖形狀態(tài)(graphics state)。只有當(dāng)圖形狀態(tài)和當(dāng)前上下文中的抗鋸齒都設(shè)置為true時(shí)敷存,Quartz才會(huì)進(jìn)行抗鋸齒操作墓造。
獲取打印使用的圖形上下文
在 Mac OS X 中的Cocoa應(yīng)用程序通過(guò)自定義的NSView子類來(lái)實(shí)現(xiàn)打印。想要打印一個(gè)view锚烦,直接調(diào)用它的print:方法觅闽;隨后,這個(gè)view創(chuàng)建了一個(gè)針對(duì)打印的圖形上下文并調(diào)用它的drawRect:方法涮俄。對(duì)于繪制到屏幕和打印機(jī)蛉拙,你的程序使用了相同的繪圖代碼。同樣也可自定義drawRect:方法彻亲,圖片這樣對(duì)于打印機(jī)的調(diào)用是不同于屏幕的(原文:It can also customize the drawRect: call to an image to the printer that is different from the one sent to the screen.)孕锄。
對(duì)于更多在Cocoa中打印的資料,請(qǐng)查看:Printing Programming Guide for Mac睹栖。