国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

iOS繪畫(huà)學(xué)習(xí)(1)

2019-11-14 20:29:18
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  本文翻譯自:《iOS 7編程》 Matt Neuburg 著,OREILLY出版。

 

 

  很多UIView的子類(lèi),例如UIButton或者UIlabel,都知道如何繪制自己;不過(guò)遲早,你都會(huì)想繪制一些自己想要的效果。你可以通過(guò)一些已有的類(lèi)在代碼中繪制一幅圖片,然后在自己的界面上展示出來(lái),例如UIImageVIew和UIButton。單純一個(gè)UIView就是只與繪制有關(guān),它給你了很大的空間來(lái)繪畫(huà);你的代碼決定了這個(gè)視圖怎么繪制自己,最終怎么在你界面上展示。

  UIImage和UIImageView

  iOS系統(tǒng)支持很多標(biāo)準(zhǔn)的圖片格式:TIFF、JPEG、GIF、PNG等。當(dāng)一張圖片被包含在我們的app 包內(nèi),iOS系統(tǒng)特別地,會(huì)對(duì)PNG文件提供更加友好的支持,不只是因?yàn)橄到y(tǒng)會(huì)對(duì)它進(jìn)行壓縮處理,還有在不同分辨率下的對(duì)圖片的選取和展示都做了很多工作,所以我們應(yīng)該優(yōu)先選擇PNG格式圖片。我們可以通過(guò)  imageNamed: 這個(gè)UIImage類(lèi)提供的方法獲取app包內(nèi)的圖片,這個(gè)方法會(huì)從兩個(gè)地方尋找指定的圖片:

  app包頂級(jí)目錄

    系統(tǒng)會(huì)通過(guò)提供的圖片名字,名字是大小寫(xiě)敏感的,以及包括圖片的類(lèi)型,在app包中尋找。如果沒(méi)有提供類(lèi)型,默認(rèn)是png格式。

  Asset catalog 資源目錄

    它會(huì)通過(guò)提供的名字,在這個(gè)資源目錄中尋找匹配的圖片集。如果名字帶有文件后綴,就不會(huì)在這里查找,以便舊代  碼中,如果把圖片移動(dòng)到這個(gè)目錄仍然能夠正常工作。這個(gè)目錄的查找優(yōu)先級(jí)比上面的查找高,也就意味著,如果在這個(gè)  資源目錄下找到了匹配的圖片,方法就會(huì)返回,而不會(huì)再去app包頂級(jí)目錄中查找。

 


 

  可調(diào)整大小的Images

  可以通過(guò)向一個(gè)UIImage發(fā)送  resizableImageWithCapInsets:resizingMode: 消息,來(lái)把圖片轉(zhuǎn)換成可調(diào)整大小的圖片。capInsets參數(shù)是一個(gè)UIEdgeInsets類(lèi)型的結(jié)構(gòu)體,由四個(gè)浮點(diǎn)型數(shù)字組成:top,left,bottom,right。它們代表著從圖片邊緣向內(nèi)的距離。在一個(gè)比圖片要大的上下文中,可調(diào)整大小的Image有兩種工作模式,通過(guò) resizingMode: value: 指定

  UIImageResizingModeTile

    在上面capInsets 指定的內(nèi)部矩形區(qū)域會(huì)平鋪在內(nèi)部,每一個(gè)邊緣由對(duì)應(yīng)邊的矩形區(qū)域平鋪而成,而外面的四個(gè)角落的矩形不變。

  UIImageResizingModeStretch

    內(nèi)部的矩形會(huì)被拉伸一次來(lái)填充內(nèi)部,每個(gè)邊緣由對(duì)應(yīng)變的矩形區(qū)域拉伸而成,而外面的四個(gè)角落的矩形不變。

  例如:假設(shè)  self.iv  是一個(gè)有固定長(zhǎng)寬的UIImageView,contentMode是UIViewContentModeScaleToFill。

(1)設(shè)置capInsets 為 UIEdgeInsetsZero

   UIImage* mars = [UIImage imageNamed:@"Mars"];  UIImage* marsTiled = [mars resizableImageWithCapInsets: UIEdgeInsetsZero                                                          resizingMode: UIImageResizingModeTile];  self.iv.image = marsTiled;

  

(2)

 UIImage* marsTiled = [mars resizableImageWithCapInsets:                          UIEdgeInsetsMake(mars.size.height/4.0,                                           mars.size.width/4.0,                                           mars.size.height/4.0,                                           mars.size.width/4.0)                          resizingMode: UIImageResizingModeTile];

  

(3)常用的拉伸策略是把幾乎是原始圖片的一半作為capinset,僅僅在中間留出1到2像素來(lái)填充整個(gè)內(nèi)部。

UIImage* marsTiled = [mars resizableImageWithCapInsets:                          UIEdgeInsetsMake(mars.size.height/2.0 - 1,                                           mars.size.width/2.0 - 1,                                           mars.size.height/2.0 - 1,                                           mars.size.width/2.0 - 1)                          resizingMode: UIImageResizingModeStretch];

  

 

在最新的Xcode5 中,我們可以不用代碼來(lái)配置一個(gè)可調(diào)整大小的圖片,僅僅通過(guò)Xcode5提供的一個(gè) asset catalogs 功能,而不用多次編寫(xiě)同樣的代碼,這個(gè)功能僅在ios7.0以上版本可用。

 


 

  圖片的渲染模式

  在ios應(yīng)用界面的很多地方,會(huì)自動(dòng)把圖片當(dāng)作透明遮罩,也稱(chēng)為模板。這樣意味著會(huì)忽略圖片的顏色,僅僅保留每個(gè)像素對(duì)應(yīng)的透明度(alpha)。在屏幕上顯示的圖片就是單一的色調(diào)與圖片透明度合成在一起的效果。例如標(biāo)簽欄按鈕的圖片或者在工具欄中類(lèi)型為UIBarButtonItemSylePlain的按鈕的圖片,都是這種模式。
  在最新的ios7系統(tǒng)中,圖片類(lèi)添加了一個(gè)新的屬性:renderingMode,表示圖片渲染模式。這個(gè)屬性是只讀的。為了改變圖片這個(gè)屬性,我們可以通過(guò)已有的圖片以不同的渲染模式生成新的圖片,調(diào)用這個(gè)方法:imageWithRendingMode:。渲染模式有三種,分別為:UIImageRenderingModeAlwaysOriginal,
UIImageRenderingModeAutomatic,
UIImageRenderingModeAlwaysTemplate 。
UIImageRenderingModeAutomatic
 
 
默認(rèn)是UIImageRenderingModeAutomatic模式,也就是除了在上面所說(shuō)的地方使用透明模板模式外,其他地方都是原樣顯示圖片。有了這個(gè)渲染屬性,我們可以強(qiáng)制圖片按照通常的方式繪制,即使在一個(gè)通常用透明模板模式渲染圖片的上下文中也可以,反之亦然。蘋(píng)果公司希望iOS7應(yīng)用在整個(gè)界面中使用更多的透明模板模式。下面是ios7系統(tǒng)設(shè)置應(yīng)用中的例子:
 
 
  
  為了方便實(shí)現(xiàn)這種效果,iOS7給UIView添加了一個(gè)tintColor的屬性,用來(lái)給圖片包含的任意模板著色。而且,這個(gè)屬性默認(rèn)是從視圖層次結(jié)構(gòu)中繼承下來(lái)的,貫穿整個(gè)應(yīng)用,從UIWindow開(kāi)始。此外,給你的應(yīng)用主窗口分配一個(gè)tint color可能是你對(duì)主窗口為數(shù)不多的改變之一,否則你的應(yīng)用將會(huì)采用系統(tǒng)的藍(lán)色色調(diào)顏色(如果你使用storyboard故事板,可以在File inspector 文件檢查器中修改這個(gè)tint color)。也可以為獨(dú)立的視圖設(shè)置它們自己的tint color,它們的子視圖會(huì)繼承該tint color。下面就是在一個(gè)窗口的tint color 為 紅色的 應(yīng)用中,兩種同樣的圖片不同的展示,一個(gè)是通常的渲染模式,另外一個(gè)是模板模式:
 
 

  圖形上下文
   UIImageView會(huì)為你繪制一張圖片,并處理好所有的細(xì)節(jié),很多情況下,這就是你所需要的。即使那樣,你可能也會(huì)想直接用代碼來(lái)繪制一些自己想要的東西,這時(shí),你需要一個(gè)圖形上下文。
  一個(gè)圖形上下文通常來(lái)說(shuō)就是你能夠繪制的一塊區(qū)域。相反地,你只能通過(guò)一個(gè)圖形上下文來(lái)在代碼中進(jìn)行繪制。有多種方式來(lái)獲得一個(gè)圖形上下文,這里將介紹兩種,這兩種目前在我遇到的各種情況下用得最多:
  自己創(chuàng)建一個(gè)圖片上下文
    UIGraphicsBeginImageContextWithOptions 函數(shù)生成一個(gè)適合用作圖片的圖形上下文。然后你可以在這個(gè)圖形上下文中生成圖片。當(dāng)你完成了繪制,你可以調(diào)用UIGraphicsGetImageFromCurrentImageContext 來(lái)把當(dāng)前的圖形上下文轉(zhuǎn)換成一個(gè)UImage,最后調(diào)用UIGraphicsEndImageContext來(lái)釋放這個(gè)上下文?,F(xiàn)在,你擁有了一個(gè)可以顯示在你的界面中或者在其他上下文中繪制的或者是保存為一個(gè)文件的UIImage對(duì)象了。
  Cocoa給你一個(gè)圖形上下文
    你可以子類(lèi)化UIView,并實(shí)現(xiàn)drawRect:方法。在你實(shí)現(xiàn)的這個(gè)drawRect:方法被調(diào)用時(shí),Cocoa已經(jīng)為你創(chuàng)建了一個(gè)圖形上下文,并叫你立刻使用它來(lái)繪制;不管你繪制什么,都會(huì)在UIView中顯示出來(lái)。(這種情況的一個(gè)輕微的變種就是,你子類(lèi)化CALayer,并實(shí)現(xiàn)drawInContext:方法,或者給layer圖層委托一些對(duì)象,并實(shí)現(xiàn)drawLayer:inContext:方法,以后會(huì)再次討論這個(gè))。
  在任何給定的時(shí)刻,一個(gè)圖形上下文要么是當(dāng)前的圖形上下文,要么不是:
  * UIGraphicsBeginImageContextWithOptions  不僅創(chuàng)建一個(gè)圖片上下文,同時(shí)也會(huì)把這個(gè)上下文設(shè)置為當(dāng)前的圖形上下文。
  * 當(dāng)drawRect:方法被調(diào)用時(shí),UIView正在繪制的上下文就已經(jīng)是當(dāng)前的圖形上下文了。
  * 以一個(gè)上下文為參數(shù)的回調(diào),不會(huì)使任何的上下文為當(dāng)前的圖形上下文,相反,這個(gè)參數(shù)僅僅是一個(gè)圖形上下文的引用。
  
  讓初學(xué)者困惑的是有兩個(gè)單獨(dú)的工具集來(lái)繪制,它們?cè)诶L制時(shí)對(duì)圖形上下文使用了不同的參數(shù):
 
  UIKit
    很多Objective-C類(lèi)知道如何繪制它們自己,包括UIImage,NSString(繪制文本),UIBezierPath(繪制圖形)和UIColor。這些類(lèi)中有些提供  了方便的方法和有限的功能;另一些則是功能非常強(qiáng)大。很多情況下,UIKit將是你所需要的全部。
 
    通過(guò)UIKit,你只能在當(dāng)前的圖形上下文中繪制。所以如果你是在使用UIGraphicsBeginImageContextWithOptions 或者drawRect:的情況下,那么你就可以直接使用UIKit提供的方便的方法;里面提供了一個(gè)當(dāng)前的上下文,也是你想繪制的那個(gè)上下文。如果你已經(jīng)持有了一個(gè)上下文參數(shù),另一方面,你也想使用UIKit的方便方法,你將需要把這個(gè)上下文轉(zhuǎn)變?yōu)楫?dāng)前的上下文,通過(guò)調(diào)用 UIGraphicsPushContext(記得在最后還原上下文,調(diào)用UIGraphicsPopContext)。
 
  Core Graphics
    這個(gè)是完整的繪圖API。Core Graphics 通常稱(chēng)為Quartz,或者Quartz2D,是構(gòu)成所有iOS繪畫(huà)的繪畫(huà)系統(tǒng) ----UIKit的繪畫(huà)就是構(gòu)建在它之上的-----所以是包含了大量C函數(shù)的底層框架。這個(gè)小節(jié)將讓你熟悉它的原理。為了獲取更全面的信息,你可以學(xué)習(xí)蘋(píng)果的Quartz 2D編程指南(Apple's Quartz 2D PRogramming Guide)。
 
    為了使用Core Graphics,你必須指定一個(gè)圖形上下文來(lái)進(jìn)行繪制,確切地說(shuō),是在每個(gè)函數(shù)調(diào)用中。但是在UIGraphicsBeginContextWithOptions或者drawRect:方法中,你沒(méi)有一個(gè)上下文的引用;為了能夠使用Core Graphics,你需要拿到這個(gè)引用。由于這個(gè)你想用來(lái)繪制的上下文就是當(dāng)前的上下文,你可以調(diào)用 UIGraphicsGetCurrentContext來(lái)獲得所需的引用。
 
  所以現(xiàn)在我們有兩套工具集,對(duì)應(yīng)的兩種上下文又提供了三種方式,所以我們一共有六種方式繪畫(huà)。下面我將一一說(shuō)明這六種!你不需要擔(dān)心實(shí)際的這些繪畫(huà)命令,僅僅專(zhuān)注于怎么指定上下文以及我們是在使用UIKit還是Core Graphics。首先我將通過(guò)子類(lèi)化UIView,并實(shí)現(xiàn)drawRect:方法來(lái)繪制一個(gè)藍(lán)色圓形;使用UIKit已經(jīng)為我提供的當(dāng)前上下文來(lái)繪制:
  
- (void) drawRect: (CGRect) rect {        UIBezierPath* p =            [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)];        [[UIColor blueColor] setFill];        [p fill];}

  現(xiàn)在我用Core Graphics 實(shí)現(xiàn)同樣的效果;這樣需要我首先拿到一個(gè)當(dāng)前上下文的引用:

- (void) drawRect: (CGRect) rect {        CGContextRef con = UIGraphicsGetCurrentContext();        CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));        CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);        CGContextFillPath(con);}

  接下來(lái),我會(huì)在UIView子類(lèi)中實(shí)現(xiàn) drawLayer:inContext:。這種情況下,我們手中的上下文引用并不是當(dāng)前上下文,所以我需要用UIKit把它轉(zhuǎn)換成當(dāng)前上下文:

- (void)drawLayer:(CALayer*)lay inContext:(CGContextRef)con {        UIGraphicsPushContext(con);        UIBezierPath* p =            [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)];        [[UIColor blueColor] setFill];        [p fill];        UIGraphicsPopContext();}

   為了在drawLayer:inContext:中使用Core Graphics,我僅僅需要簡(jiǎn)單地保留一個(gè)我持有的上下文即可:

- (void)drawLayer:(CALayer*)lay inContext:(CGContextRef)con {        CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));        CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);        CGContextFillPath(con);}

  最后,為了完整性,讓我們創(chuàng)建一個(gè)藍(lán)色圓形的UIImage對(duì)象。我們可以在任何時(shí)間(我們不需要等待某些特定方法被調(diào)用)以及在任何類(lèi)(我們不需要在UIView的子類(lèi))中創(chuàng)建。創(chuàng)建的UIImage你可以在任何地方正常使用,例如,你可以把它放到一個(gè)可見(jiàn)的UIImageView中當(dāng)做圖片展示,或者你可以把它保存在一個(gè)文件中,或者你可以在其他的繪制中使用(下一節(jié)介紹)。

 

首先,我使用UIKit繪制我的圖片:

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0);    UIBezierPath* p =        [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,100,100)];    [[UIColor blueColor] setFill];    [p fill];    UIImage* im = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    // im is the blue circle image, do something with it here ...

下面是使用Core Graphics實(shí)現(xiàn)的:

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100,100), NO, 0); CGContextRef con = UIGraphicsGetCurrentContext();CGContextAddEllipseInRect(con, CGRectMake(0,0,100,100));CGContextSetFillColorWithColor(con, [UIColor blueColor].CGColor);CGContextFillPath(con);UIImage* im = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();// im is the blue circle image, do something with it here ...

你可能會(huì)對(duì)UIGraphicsBeginImageContextWithOptions這個(gè)方法的參數(shù)感到疑惑,其實(shí)第一個(gè)參數(shù)顯然是將要?jiǎng)?chuàng)建的圖片的大小。第二個(gè)參數(shù)表明這個(gè)圖片是否是不透明的,如果我在上面的方法中傳遞YES而是不是NO,我的圖片將會(huì)有一個(gè)黑色背景,而我不想要這種效果。第三個(gè)參數(shù)指定圖片的縮放比例,傳遞0是告訴系統(tǒng)根據(jù)當(dāng)前屏幕的尺寸為我自動(dòng)設(shè)置壓縮比例,這樣我的圖片就會(huì)在單分辨率和雙分辨率屏幕下都能完美顯示。

 

你不必完全使用UIKit或者Core Graphics,相反地,你可以混合UIKit 調(diào)用和Core Graphics調(diào)用來(lái)操作同樣的圖形上下文。它們僅僅只是表示兩種不同的方式對(duì)同樣的圖形上下文通信而已。


 

  CGImage繪畫(huà)

  UIImage在Core Graphics中的版本是CGImage(實(shí)際上是CGImageRef)。它們可以很容易地互相轉(zhuǎn)換:UIImage有一個(gè)CGImage的屬性,可以訪問(wèn)它的Quartz 的圖片數(shù)據(jù),你也可以把CGImage 轉(zhuǎn)換成UIImage,使用imageWithCGImage:或者initWithCGImage:(在實(shí)戰(zhàn)中,你會(huì)更偏向使用更加可配置性的姐妹方法:imageWithCGImage:scale:orientation: 以及 initWithCGImage:scale:orientation:)。

  一個(gè)CGImage可以讓你從一個(gè)原始圖片的一個(gè)矩形區(qū)域中創(chuàng)建一個(gè)新的圖片,而UIImage是做不到的。(一個(gè)CGImage還有其他強(qiáng)大的功能而UIImage沒(méi)有的,例如你可以將圖片的遮罩應(yīng)用到CGImage中)。我將會(huì)通過(guò)分隔一張火星圖片為兩半,并分開(kāi)單獨(dú)繪制每一邊。

 

注意,我們現(xiàn)在是在CFTypeRef范圍下操作,必須自動(dòng)管理好內(nèi)容:

    UIImage* mars = [UIImage imageNamed:@"Mars"];    // extract each half as a CGImage    CGSize sz = mars.size;    CGImageRef marsLeft = CGImageCreateWithImageInRect([mars CGImage],                           CGRectMake(0,0,sz.width/2.0,sz.height));    CGImageRef marsRight = CGImageCreateWithImageInRect([mars CGImage],                            CGRectMake(sz.width/2.0,0,sz.width/2.0,sz.height));    // draw each CGImage into an image context    UIGraphicsBeginImageContextWithOptions(        CGSizeMake(sz.width*1.5, sz.height), NO, 0);    CGContextRef con = UIGraphicsGetCurrentContext();    CGContextDrawImage(con,                       CGRectMake(0,0,sz.width/2.0,sz.height), marsLeft);    CGContextDrawImage(con,                       CGRectMake(sz.width,0,sz.width/2.0,sz.height), marsRight);    UIImage* im = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    CGImageRelease(marsLeft); CGImageRelease(marsRight)

但是這里的例子有個(gè)問(wèn)題:繪制的東西上下顛倒了! 它不是被旋轉(zhuǎn)了,而是從上到下映射,或者用專(zhuān)業(yè)的術(shù)語(yǔ),翻轉(zhuǎn)。這種想象會(huì)發(fā)生在你創(chuàng)建了一個(gè)CGImage,然后通過(guò)CGContextDrawImage繪制時(shí),是由于源和目標(biāo)上下文的本地坐標(biāo)系統(tǒng)不匹配。

有多種的方式補(bǔ)償這種不同坐標(biāo)系統(tǒng)之間的不匹配。其中一種就是把CGImage繪制成一個(gè)中間的UIImage,然后從UIImage中獲取CGImage,下面展示一個(gè)通用的函數(shù)來(lái)實(shí)現(xiàn)這種轉(zhuǎn)換:

//  Utility for flipping an image drawingCGImageRef flip (CGImageRef im) {    CGSize sz = CGSizeMake(CGImageGetWidth(im), CGImageGetHeight(im));    UIGraphicsBeginImageContextWithOptions(sz, NO, 0);    CGContextDrawImage(UIGraphicsGetCurrentContext(),                       CGRectMake(0, 0, sz.width, sz.height), im);    CGImageRef result = [UIGraphicsGetImageFromCurrentImageContext() CGImage];    UIGraphicsEndImageContext();    return result;}

我們可以使用這個(gè)工具函數(shù)來(lái)修復(fù)我們上面例子中調(diào)用CGContextDrawImage產(chǎn)生的問(wèn)題,讓它們正確畫(huà)出火星的一半。

CGContextDrawImage(con, CGRectMake(0,0,sz.width/2.0,sz.height),                       flip(marsLeft));CGContextDrawImage(con, CGRectMake(sz.width,0,sz.width/2.0,sz.height),                       flip(marsRight));

但是,我們?nèi)匀挥幸粋€(gè)問(wèn)題:在雙分辨率設(shè)備上,如果我們的圖片有一個(gè)雙分辨率的版本(@2x.png),這個(gè)繪制就會(huì)出錯(cuò)。原因就是我們使用 imageNamed:來(lái)獲取原始的火星圖片,這樣就會(huì)返回一個(gè)為了適配雙分辨率而設(shè)置自己的縮放比例來(lái)產(chǎn)生雙倍分辨率的圖片。但是CGImage沒(méi)有scale屬性,同時(shí)對(duì)這張圖片為原始分辨率兩倍一無(wú)所知!因此,我們?cè)陔p分辨率設(shè)備上,我們通過(guò)調(diào)用 [mars  CGImage]獲得到的火星CGImage圖片,是火星圖片大小的兩倍,那么我們所有的計(jì)算都是錯(cuò)的。

所以,為了在CGImage提取想要的片,我們必須把所有適當(dāng)?shù)闹党艘钥s放比例scale,或者以CGImage的尺寸來(lái)描述大小。下面是我們?cè)趩畏制梁碗p分屏都正確繪制的一個(gè)代碼版本,并且補(bǔ)償了翻轉(zhuǎn)效果:

    UIImage* mars = [UIImage imageNamed:@"Mars"];    CGSize sz = mars.size;    // Derive CGImage and use its dimensions to extract its halves    CGImageRef marsCG = [mars CGImage];    CGSize szCG = CGSizeMake(CGImageGetWidth(marsCG),          CGImageGetHeight(marsCG));    CGImageRef marsLeft =        CGImageCreateWithImageInRect(            marsCG, CGRectMake(0,0,szCG.width/2.0,szCG.height));    CGImageRef marsRight =        CGImageCreateWithImageInRect(            marsCG, CGRectMake(szCG.width/2.0,0,szCG.width/2.0,szCG.height));    UIGraphicsBeginImageContextWithOptions(        CGSizeMake(sz.width*1.5, sz.height), NO, 0);    // The rest is as before, calling flip() to compensate for flipping    CGContextRef con = UIGraphicsGetCurrentContext();    CGContextDrawImage(con, CGRectMake(0,0,sz.width/2.0,sz.height),                       flip(marsLeft));    CGContextDrawImage(con, CGRectMake(sz.width,0,sz.width/2.0,sz.height),                       flip(marsRight));    UIImage* im = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    CGImageRelease(marsLeft); CGImageRelease(marsRight);

另一種方案就是:在UIImage里面包裝一個(gè)CGImage,繪制這個(gè)UIImage。UIImage可以通過(guò)調(diào)用 imageWithCGImage:scale:orientation:來(lái)實(shí)現(xiàn)這種方式,補(bǔ)償縮放帶來(lái)的影響。此外,通過(guò)繪制一個(gè)UIImage,而不是一個(gè)的CGImage,我們避免了翻轉(zhuǎn)問(wèn)題。下面是一種同時(shí)處理翻轉(zhuǎn)和縮放的方法(沒(méi)有調(diào)用我們上面的公用類(lèi)):

    UIImage* mars = [UIImage imageNamed:@"Mars"];    CGSize sz = mars.size;    // Derive CGImage and use its dimensions to extract its halves    CGImageRef marsCG = [mars CGImage];    CGSize szCG = CGSizeMake(CGImageGetWidth(marsCG),              CGImageGetHeight(marsCG));    CGImageRef marsLeft =        CGImageCreateWithImageInRect(            marsCG, CGRectMake(0,0,szCG.width/2.0,szCG.height));    CGImageRef marsRight =        CGImageCreateWithImageInRect(            marsCG, CGRectMake(szCG.width/2.0,0,szCG.width/2.0,szCG.height));    UIGraphicsBeginImageContextWithOptions(        CGSizeMake(sz.width*1.5, sz.height), NO, 0);    [[UIImage imageWithCGImage:marsLeft                         scale:mars.scale                   orientation:UIImageOrientationUp]     drawAtPoint:CGPointMake(0,0)];    [[UIImage imageWithCGImage:marsRight                         scale:mars.scale                   orientation:UIImageOrientationUp]     drawAtPoint:CGPointMake(sz.width,0)];    UIImage* im = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    CGImageRelease(marsLeft); CGImageRelease(marsRight);

是的,另一種方案解決翻轉(zhuǎn),就是在繪制CGImage之前,對(duì)圖形上下文進(jìn)行線性轉(zhuǎn)換,有效地翻轉(zhuǎn)圖形上下文中內(nèi)部的坐標(biāo)系統(tǒng)。這種方式很簡(jiǎn)潔,但是當(dāng)有其他的線性轉(zhuǎn)換時(shí)會(huì)變得難以理解。我會(huì)在下面的章節(jié)中談?wù)摳鄨D形上下文轉(zhuǎn)換的內(nèi)容。

 

    為什么會(huì)發(fā)生翻轉(zhuǎn)??

Core Graphics 會(huì)意外發(fā)生翻轉(zhuǎn)的歷史,來(lái)源于OS X世界,OS X 里的坐標(biāo)系統(tǒng)的原點(diǎn)默認(rèn)是在左下角,正Y方向是向上的,而在iOS中,坐標(biāo)原點(diǎn)默認(rèn)在左上角,正Y方向是向下的。在大多數(shù)的繪畫(huà)中沒(méi)有問(wèn)題,因?yàn)閳D形上下文的坐標(biāo)系統(tǒng)會(huì)自動(dòng)適應(yīng)的。另外,在iOS的Core Graphics框架中的上下文繪畫(huà)時(shí),上下文的坐標(biāo)系統(tǒng)原點(diǎn)是左上角,我們都知道,但是,創(chuàng)建和繪制CGImage在兩個(gè)坐標(biāo)系統(tǒng)之間,互不匹配。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 历史| 汝城县| 章丘市| 三门峡市| 无为县| 蒙阴县| 辽宁省| 兰州市| 深泽县| 巴东县| 区。| 岱山县| 兴仁县| 米泉市| 景德镇市| 福建省| 遂溪县| 勐海县| 长顺县| 西乌| 毕节市| 郴州市| 鄂托克旗| 台南市| 周至县| 新津县| 团风县| 交口县| 当雄县| 德阳市| 婺源县| 乡城县| 神农架林区| 阿巴嘎旗| 蒙山县| 丁青县| 龙胜| 西贡区| 秦安县| 桐梓县| 祁阳县|