iOS繪圖和打印編程指導(dǎo)(四)-繪制和創(chuàng)建圖片

大多數(shù)情況下, 通常直接使用標(biāo)準(zhǔn)的view來展示image, 不過, 有兩中情況需要做些額外的工作:

  • 如果你將image作為自定義view的部分展示. 你需要在drawRect:中將image繪制到view中.
  • 如果你想離屏(延遲顯示, 或者保存到文件)渲染image, 那么必須創(chuàng)建一個bitmap上下文環(huán)境.

繪制image


為了獲得最大的性能,如果可以使用UIImageView類顯示圖像的需要,則應(yīng)該使用此圖像對象來初始化UIImageView對象。但是,如果需要顯式繪制圖像,則可以存儲圖像并在視圖的drawRect:方法中使用它。
下面的示例演示如何從應(yīng)用程序包中加載圖像。

NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"myImage" ofType:@"png"];
UIImage *myImageObj = [[UIImage alloc] initWithContentsOfFile:imagePath];
 
// Store the image into a property of type UIImage *
// for use later in the class's drawRect: method.
self.anImage = myImageObj;

要在視圖的drawRect:方法中顯式地繪制結(jié)果圖像,可以使用UIImage中可用的任何繪圖方法。這些方法允許您指定在視圖中要繪制圖像的位置,因此不需要在繪制之前創(chuàng)建和應(yīng)用單獨的轉(zhuǎn)換。
下面的代碼片段在視圖中的點(10, 10)繪制上方加載的圖像。

- (void)drawRect:(CGRect)rect {
    ...
 
    // Draw the image.
    [self.anImage drawAtPoint:CGPointMake(10, 10)];
}

重要: 如果你使用CGContextDrawImage函數(shù)來直接繪制bitmap圖像, 那么圖像會在y軸方向翻轉(zhuǎn)了. 因為CoreGraphic中的坐標(biāo)系是LLO型的, 想繪制正常的圖像, 那么你需要對Graphic context做變換, 前面內(nèi)容已經(jīng)講過.

使用Bitmap圖像上下文創(chuàng)建新的image


多數(shù)情況下, 你是將內(nèi)容繪制到屏幕上以便顯示. 但是有時候需要將一些內(nèi)容繪制到屏幕外緩沖區(qū). 例如, 你可能希望創(chuàng)建一個現(xiàn)有圖像的縮略圖, 然后繪制到緩沖區(qū)以便將其保存到文件等. 為了支持這些需求, 你可以創(chuàng)建一個bitmap圖像上下文, 使用UIKit或Core Graphic框架對其進(jìn)行繪制, 然后從上下文中獲取圖像對象.
在UIKit中, 步驟如下:

  1. 調(diào)用UIGraphicsBeginImageContextWithOptions來創(chuàng)建一個bitmap圖像上下文然后push進(jìn)Graphic堆棧.
    • 第一個參數(shù)size, 傳一個CGSize來確定繪圖區(qū)域大小
    • 第二個參數(shù)opaque, 如果你的image包含透明的部分,傳NO; 否則, 傳YES, 這樣性能也能提升
    • 第三參數(shù)scale, 傳0.0, 如果比bitmap已經(jīng)適配屏幕, 也可按需傳入其他值.

舉個例子, 下面的代碼片段創(chuàng)建一個200x200像素的bitmap(像素量有scale*點數(shù))

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100.0,100.0), NO, 2.0);

注意:你平常應(yīng)該避免使用名稱類似UIGraphicsBeginImageContext的函數(shù)(除了作為向后兼容性的回退之外), 因為它總是創(chuàng)建scale為1.0的像素, 如果底層設(shè)備具有高分辨率屏幕, 使用上面的函數(shù)創(chuàng)建的圖像看起來可能不會那么平滑.

  1. 使用UIKit或者Core Graphic的繪圖方式將圖像繪制到新創(chuàng)建的圖形上下文中
  2. 調(diào)用UIGraphicsGetImageFromCurrentImageContext函數(shù)來創(chuàng)建和返回一個你繪制的UIImage對象. 你可以繼續(xù)繪制內(nèi)容然后調(diào)用該方法獲取新的圖片
  3. 調(diào)用UIGraphicsEndImageContext函數(shù)pop出當(dāng)前bitmap圖形上下文.

代碼4-1中的方法從網(wǎng)上下載一張圖片然后將其繪制到上下文, 縮小APP icon的圖片大小. 從bitmap數(shù)據(jù)中獲取UIImage對象, 然后賦值給一個變量. 要注意bitmap(函數(shù)UIGraphicsBeginImageContextWithOptions的第一個參數(shù))中的size和繪制內(nèi)容(imageRect的size)的size要相符. 如果內(nèi)容的size要比bitmap大, 一部分內(nèi)容將被裁剪掉

代碼清單4-1 將縮小的圖像繪制到位圖上下文并獲得結(jié)果圖像

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
    if (image != nil && image.size.width != kAppIconHeight && image.size.height != kAppIconHeight) {
        CGRect imageRect = CGRectMake(0.0, 0.0, kAppIconHeight, kAppIconHeight);
        UIGraphicsBeginImageContextWithOptions(itemSize, NO, [UIScreen mainScreen].scale);
        [image drawInRect:imageRect];
        self.appRecord.appIcon = UIGraphicsGetImageFromCurrentImageContext();  // UIImage returned.
        UIGraphicsEndImageContext();
    } else {
        self.appRecord.appIcon = image;
    }
    self.activeDownload = nil;
    [image release];
    self.imageConnection = nil;
    [delegate appImageDidLoad:self.indexPathInTableView];
}

您還可以調(diào)用Core Graphics函數(shù)來繪制生成的位圖圖像的內(nèi)容;清單3-2中的代碼片段給出了一個示例,該代碼片段繪制了PDF頁面的縮放圖像。注意,代碼在調(diào)用CGContextDrawPDFPage之前翻轉(zhuǎn)圖形上下文,以使繪制的圖像與UIKit的默認(rèn)坐標(biāo)系統(tǒng)對齊。

代碼清單3-2 使用Core Graphic函數(shù)往bitmap上下文中繪制內(nèi)容

// Other code precedes...
CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
pdfScale = self.frame.size.width/pageRect.size.width;
pageRect.size = CGSizeMake(pageRect.size.width * pdfScale, pageRect.size.height * pdfScale);
UIGraphicsBeginImageContextWithOptions(pageRect.size, YES, pdfScale);
CGContextRef context = UIGraphicsGetCurrentContext();
 
// First fill the background with white.
CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);
CGContextFillRect(context,pageRect);
CGContextSaveGState(context);
 
// Flip the context so that the PDF page is rendered right side up
CGContextTranslateCTM(context, 0.0, pageRect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
 
// Scale the context so that the PDF page is rendered at the
// correct size for the zoom level.
CGContextScaleCTM(context, pdfScale,pdfScale);
CGContextDrawPDFPage(context, page);
CGContextRestoreGState(context);
UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
backgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage];
 
// Other code follows...

如果你喜歡全用Core Graphic來繪制內(nèi)容, 那么你可以使用CGBitmapContextCreate函數(shù)來創(chuàng)建上下文, 并將圖像內(nèi)容會知道上下文中. 完成繪圖后, 調(diào)用CGBitmapContextCreateImage函數(shù)來獲取CGImageRef對象. 使用直接使用Core Graphic來繪制圖像, 也可以創(chuàng)建UIImage對象. 最后調(diào)用CGContextRelease函數(shù)來釋放上文對象.

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

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

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