圖形上下文(Graphics Context)—— Quartz 2D編程指導(dǎo)翻譯 第3篇

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

圖形上下文(Graphics Context)

圖形上下文指的是繪圖的地點(diǎn),它包含了繪圖系統(tǒng)需要實(shí)現(xiàn)后續(xù)繪圖操作需要的參數(shù)和指定設(shè)備的所有信息。圖形上下文定義了基本的繪圖特性,如:顏色、裁剪區(qū)域、線的寬度和樣式、字體信息、復(fù)合選項(xiàng)等等。

你能夠使用Quartz提供的上下文創(chuàng)建函數(shù)或者由 OS X 以及 iOS 提供的更高級的函數(shù)來得到一個(gè)圖形上下文。Quartz為很多不同種類的圖形上下文(如,bitmap、PDF)提供了很多函數(shù);你可以用這些來創(chuàng)建自定義的內(nèi)容。

本章中,我們將教會(huì)你如何創(chuàng)建各式各樣的圖形上下文(針對不同的繪圖地點(diǎn))。在代碼中圖形上下文用一個(gè)類型為CGContextRef的數(shù)據(jù)代替,這個(gè)數(shù)據(jù)是閉源的。在你獲取到圖形上下文之后,你可以使用Quartz提供的函數(shù)來進(jìn)行繪制、變換等操作。

iOS中繪制到頁面的圖形上下文(Drawing to a View Graphics Context in iOS)

在iOS的一個(gè)APP中,如果你想將內(nèi)容繪制到屏幕,你需要?jiǎng)?chuàng)建一個(gè)UIView對象并實(shí)現(xiàn)它的drawRect:方法。當(dāng)View可見并且內(nèi)容需要更新時(shí),View的drawRect:將會(huì)被調(diào)用。在調(diào)用drawRect:方法之前,這View對象自動(dòng)注冊了它的繪圖環(huán)境,以方便你能夠快速的繪制。這個(gè)UIView在注冊的過程中,創(chuàng)建了一個(gè)針對當(dāng)前繪圖環(huán)境的圖形上下文(CGContextRef類型)。你能夠在drawRect:方法中用使用UIGraphicsGetCurrentContext來獲取這個(gè)圖形上下文。

UIKit與Quartz使用著不同的坐標(biāo)系;在UIKit中,坐標(biāo)系的原點(diǎn)在左上角,y軸正半軸向下延伸;而在Quartz中原點(diǎn)在左下角,y軸正半軸向上延伸。UIView對象修改了當(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 本身沒有提供函數(shù)來獲取一個(gè)窗口圖形上下文。但是,你可以使用Cocoa 框架來獲取一個(gè)在Cocoa中創(chuàng)建的窗口上下文。

你在drawRect:中使用如下代碼來獲取上下文:

CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];

currentContext方法返回了一個(gè)屬于當(dāng)前線程的NSGraphicsContext實(shí)例。graphicsPort 方法返回一個(gè)低級、指定平臺的圖形上下文,它是一個(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)色矩形。你可以在顏色和色域中了解更多。你能透過顏色看到多少內(nèi)容是 Quartz 2D 的一個(gè)特征。

圖 2-1 Cocoa框架中一個(gè)包含Quartz繪圖的View

想要完成 圖 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:方法的信息,請見: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

下面解釋這些代碼做了什么:

  1. 獲取view的圖形上下文。
  2. 你需要把繪圖的代碼寫到這個(gè)地方。接下來的4行使用了 Quartz 2D 的函數(shù)。
  3. 將填充色設(shè)置為一個(gè)完全不透明的紅色。關(guān)于顏色和alpha(設(shè)置透明度),詳見:顏色和色域。
  4. 填充了一個(gè)矩形,這個(gè)矩形原點(diǎn)在(0,0),寬度為200,高度為100。關(guān)于繪制矩形的更多內(nèi)容見:路徑(Paths)。
  5. 設(shè)置一個(gè)半透明的藍(lán)色為填充色。
  6. 填充了一個(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è)頁(Page)邊界的矩形)。圖 2-2 展示了用PDF預(yù)覽將使用 PDF Graphics Context 繪制的結(jié)果打開的情形。

圖 2-2 用 CGPDFContextCreateWithURL 創(chuàng)建的PDF文件

Quartz 2D 的API 提供了兩種函數(shù)來創(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圖形上下文。

對于每個(gè)標(biāo)注了數(shù)字的代碼行,都會(huì)有詳細(xì)的解釋。

iOS 注意:在iOS中的PDF圖形上下文使用了Quartz提供的默認(rèn)坐標(biāo),并沒有應(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來創(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
}

代碼解釋:

  1. 調(diào)用了 Core Foundation 的函數(shù)來用CFString創(chuàng)建一個(gè)CFURL對象,這個(gè)對象稍后會(huì)被用于MyPDFContextCreate函數(shù)。對于CFURLCreateWithFileSystemPath,你傳入第一個(gè)參數(shù)為NULL時(shí)使用默認(rèn)的分配器(allocator);同時(shí)你需要指定路徑的樣式,在這個(gè)例子中是一個(gè)POSIX-style的路徑名。
  2. 調(diào)用Quartz 2D 的函數(shù)來創(chuàng)建PDF圖形上下文,會(huì)使用到剛剛創(chuàng)建的路徑和一個(gè)指示PDF頁(Page)大小的矩形,這個(gè)矩形在調(diào)用MyPDFContextCreate時(shí)由外部傳入,他表示了默認(rèn)的PDF邊界大小。
  3. 釋放CFURL對象。
  4. 返回創(chuàng)建的PDF圖形上下文對象。調(diào)用者在不使用的時(shí)候必須釋放這個(gè)圖形上下文。

列表 2-3 調(diào)用CGPDFContextCreate來創(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
}

代碼解釋:

  1. 調(diào)用了 Core Foundation 的函數(shù)來用CFString創(chuàng)建一個(gè)CFURL對象,這個(gè)對象稍后會(huì)被用于MyPDFContextCreate函數(shù)。對于CFURLCreateWithFileSystemPath,你傳入第一個(gè)參數(shù)為NULL時(shí)使用默認(rèn)的分配器(allocator);同時(shí)你需要指定路徑的樣式,在這個(gè)例子中是一個(gè)POSIX-style的路徑名。
  2. 使用CFURL對象,創(chuàng)建了一個(gè)Quartz data consumer 對象。如果你不想使用CFURL對象(例如你想要放置的輸出數(shù)據(jù)不能指定CFURL對象時(shí)),你可以利用一系列的回掉函數(shù)(callback functions)創(chuàng)建一個(gè)data consumer來代替CFURL。詳見: Quart 2D 中的數(shù)據(jù)管理。
  3. 調(diào)用Quartz 2D的函數(shù)來創(chuàng)建PDF圖形上下文。
  4. 釋放data cunsumer。
  5. 釋放CFURL對象。
  6. 返回創(chuàng)建的PDF圖形上下文對象。調(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);

代碼解釋:

  1. 聲明用來定義PDF的media box 的矩形。
  2. 設(shè)置矩形的原點(diǎn)、寬度和高度。
  3. 調(diào)用函數(shù)MyPDFContextCreate(列表 2-3)獲取一個(gè)PDF圖形上下文,并傳入正確的 media box 和路徑。CFSTR可以將一個(gè)字符串轉(zhuǎn)換成CFStringRef類型。
  4. 設(shè)置page的選項(xiàng)。在這個(gè)例子中,只有media box 是指定了值的。你不需要傳入相同的矩形來設(shè)置PDF圖形上下文。因?yàn)閙edia box 取代了你傳入設(shè)置PDF圖形上下文的矩形。
  5. 開始一個(gè)page的信號。這個(gè)方法用于面向頁面的繪圖,即PDF繪圖。
  6. 調(diào)用Quartz 2D的繪圖函數(shù)。你可以替換接下來的這四行,來畫你想畫的東西。
  7. PDF page結(jié)束的信號。
  8. 在選項(xiàng)字典和PDF圖形上下文不使用時(shí)釋放它們。

你能夠在PDF中寫下任意的內(nèi)容(對于你的應(yīng)用來說合適的內(nèi)容)。如:圖片、文字、基于路徑的繪圖、鏈接、編碼等等。更多信息請見: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í)候也被用來做離屏繪制。在你決定這么做之前,看看:核心圖形圖層繪畫(Core Graphics Layer Drawing)。CGLayer 對象(CCGLayerRef)針對離屏繪制有特定的優(yōu)化,因?yàn)樵诳赡艿臅r(shí)候它將緩存 video card 上的涂層。

iOS 注意:iOS中的應(yīng)用程序應(yīng)當(dāng)使用UIGraphicsBeginImageContextWithOptions方法而不是這里描述的Quartz低級方法來獲取圖形上下文。如果你的應(yīng)用程序使用Quartz提供的API創(chuàng)建了一個(gè)離屏的bitmap,那么這么位圖圖形上下文會(huì)使用Quartz默認(rèn)的坐標(biāo)系。作為對比,如果你使用 UIGraphicsBeginImageContextWithOptions 來創(chuàng)建圖形上下文,那么UIKit會(huì)對其(位圖圖形上下文)使用與從UIView獲取圖形上下文相同的變換。這就允許你使用相同的坐標(biāo)系來繪制。雖然你的應(yīng)用程序能夠人為地來完成這些補(bǔ)償,但是在實(shí)際中,這樣做沒有任何好處。

你可以使用CGBitmapContextCreate函數(shù)來創(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)制位)。例如:對于32位格式的RGB色域,你需要為每一個(gè)部分指定8位。見:本章中的表“支持的像素格式”。
  • 每行的字節(jié)數(shù)(bytesPerRow)。指定內(nèi)存中位圖每一行的字節(jié)數(shù)。

注意:當(dāng)你創(chuàng)建一個(gè)位圖圖形上下文后,如果你確保數(shù)據(jù)(data)和每行的字節(jié)數(shù)(bitsPerCompoent)是16為對齊的,那么你將獲得最佳的性能。

  • 色域(colorspace)。位圖圖形上下文所使用的色域,你可以提供灰階(Gray)、RGB、CMYK或者NULL這些色域值給位圖圖形上下文。更多關(guān)于色域和顏色管理的細(xì)節(jié),見:Color Management Overview。更多關(guān)于顏色創(chuàng)建的信息見:顏色和色域。更多支持的色域見:位圖圖像和圖像遮罩。
  • 位圖信息(bitmapInfo)。位圖的布局信息,通常用一個(gè)CGBitmapInfo的常量來表示。這個(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
}

代碼解釋:

  1. 聲明代表每行有多少字節(jié)的變量。在這個(gè)例子中bitmap中的一個(gè)像素由4個(gè)字節(jié)表示,8位的紅、綠、藍(lán)和alpha。
  2. 創(chuàng)建了一個(gè)普通的RGB色域,當(dāng)然你也可以創(chuàng)建其他的色域如CMYK。在顏色和色域中你能了解到普通的(generic)色域是依賴于設(shè)備的。
  3. 調(diào)用calloc函數(shù)來創(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ǔ)空間。
  4. 調(diào)用方法創(chuàng)建一個(gè)位圖圖形上下文,傳入相應(yīng)的參數(shù)。常量kCGImageAlphaPremultipliedLast指明了alpha值被存儲(chǔ)在每個(gè)像素的最后一個(gè)字節(jié),同時(shí)它也指明了其中的顏色早已經(jīng)與alpha值相乘過了。關(guān)于alpha值的預(yù)乘(premultiplied alpha)見:The Alpha Value。
  5. 如果上下文沒有創(chuàng)建成功,釋放申請的用來存放 bitmap data 數(shù)據(jù)的內(nèi)存。
  6. 釋放色域。
  7. 返回創(chuàng)建好的位圖圖形上下文。使用者需要釋放這個(gè)圖形上下文。

列表 2-6 使用先前創(chuàng)建的MyCreateBitmapContext函數(shù)來創(chuàng)建一個(gè)位圖圖形上下文,然后使用這個(gè)圖形上下文創(chuàng)建了一個(gè)CGImage對象,接著將這個(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

代碼解釋:

  1. 聲明了一個(gè)定義了原點(diǎn)和尺寸的變量box,這個(gè)變量將被用于繪制由位圖圖形上下文產(chǎn)生的圖片。
  2. 設(shè)置這個(gè)box的原點(diǎn)和寬高。
  3. 調(diào)用自定義的函數(shù)MyCreateBitmapContext(列表 2-5)來創(chuàng)建了一個(gè)寬為400px高為300px的像素。你使用任意尺寸來創(chuàng)建位圖圖形上下文。
  4. 調(diào)用Quartz 2D的函數(shù)來在這個(gè)位圖圖形上下文中繪制。你能夠自由替換下面4行繪制代碼。
  5. 從位圖圖形上下文中創(chuàng)建了一個(gè)Quartz 2D 圖片(CGImageRef)。
  6. 將這個(gè)圖片繪制到box指定的窗口圖形上下文中,這個(gè)有邊界的box指示的坐標(biāo)和尺寸是在用戶空間下的(user space)。例子中沒有展示如何創(chuàng)建窗口圖形上下文,可以看本章中的在 Mac OS X 中創(chuàng)建一個(gè)窗口圖形上下文。
  7. 獲取和這個(gè)位圖圖形上下文關(guān)聯(lián)的 bitmap data 指針。
  8. 釋放位圖圖形上下文。
  9. 如果bitmap data 存在則釋放它。
  10. 在不使用的時(shí)候釋放圖片。
圖 2-3 由位圖圖形上下文產(chǎn)生的圖片,并將該圖片繪制到窗口圖形上下文

支持的像素格式(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)

位圖圖形上下文支持抗鋸齒??逛忼X是對繪制文字或者圖形時(shí)邊緣出現(xiàn)鋸齒狀情況的糾正。當(dāng)位圖的分辨率大大低于人眼的分辨率時(shí),就會(huì)出現(xiàn)鋸齒。為了使繪制的內(nèi)容變得光滑,Quartz對包裹在對應(yīng)圖形形狀外的像素使用了不同的顏色。通過這樣的混色方式,這些形狀看起來就光滑了一些。你能夠從 圖 2-4 中看出來抗鋸齒的效果。同樣,你可以在繪制特殊的位圖圖形上下文時(shí)關(guān)閉抗鋸齒(通過CGContextSetShouldAntialias方法)。這個(gè)抗鋸齒設(shè)置是圖形狀態(tài)的(graphics state)一部分。

你同樣也能夠使用CGContextSetAllowsAntialiasing方法針對一個(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)行抗鋸齒操作。

圖 2-4 抗鋸齒的使用與否對比

獲取打印使用的圖形上下文

在 Mac OS X 中的Cocoa應(yīng)用程序通過自定義的NSView子類來實(shí)現(xiàn)打印。想要打印一個(gè)view,直接調(diào)用它的print:方法;隨后,這個(gè)view創(chuàng)建了一個(gè)針對打印的圖形上下文并調(diào)用它的drawRect:方法。對于繪制到屏幕和打印機(jī),你的程序使用了相同的繪圖代碼。同樣也可自定義drawRect:方法,圖片這樣對于打印機(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.)。

對于更多在Cocoa中打印的資料,請查看:Printing Programming Guide for Mac。


上一章:Quartz 2D 概述
下一章:路徑(Paths)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容