效果如下圖:
首先,在工程Bundle中加入測試用的圖片文件,比如“meteoralp.jpg”。
首先,我們需要把圖片展示在界面上。很簡單的操作,唯一需要注意的是由於CGContextDrawImage會使用Quartz內以左下角爲(0,0)點的座標系,所以需要使用CGContextTranslateCTM函數和CGContextScaleCTM函數把以左下角爲0點的座標系轉化成左上角形式的座標系。
ViewController中的代碼:
//ViewController中的viewDidLoad方法 - (void)viewDidLoad { //從Bundle中讀取圖片 UIImage *srcImg = [UIImage imageNamed:@"meteoralp.jpg"]; CGFloat width = srcImg.size.width; CGFloat height = srcImg.size.height; //開始繪製圖片 UIGraphicsBeginImageContext(srcImg.size); CGContextRef gc = UIGraphicsGetCurrentContext(); //座標系轉換 //因爲CGContextDrawImage會使用Quartz內的以左下角爲(0,0)的座標系 CGContextTranslateCTM(gc, 0, height); CGContextScaleCTM(gc, 1, -1); CGContextDrawImage(gc, CGRectMake(0, 0, width, height), [srcImg CGImage]); //結束繪畫 UIImage *destImg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //創建UIImageView並顯示在界面上 UIImageView *imgView = [[UIImageView alloc] initWithImage:destImg]; [self.view addSubview:imgView]; }
圖片就顯示出來了:
接下來繪製Clip區域。使用Quartz中的Path創建操作去繪製一個菱形邊框,最後使用CGContextClip函數把當前Path作爲Clip區域。
把下面代碼插入到上方“開始繪製圖片”和“座標系轉化”之間。因爲如果在畫完圖後在設置Clip區域那就沒有任何意義了。
//繪製Clip區域 CGContextMoveToPoint(gc, width/2, 0); CGContextAddLineToPoint(gc, width, height/2); CGContextAddLineToPoint(gc, width/2, height); CGContextAddLineToPoint(gc, 0, height/2); CGContextClosePath(gc); CGContextClip(gc);
OK,運行後第一個圖的效果就出來了:
接下來完成第二個圖的效果。第二個圖是這樣完成的,我們不僅需要加入第一個圖繪製的菱形,同時還要把最外層的邊框加入到Path中。後者可以通過CGContextGetClipBoundingBox函數直接得到。
接下來需要講一下Even-Odd規則,這個規則其實在諸多平臺的繪圖框架中都有使用,都也是用在填充或者Clip操作中的。
沒有在Apple的文檔中找到圖,倒是在W3C的SVG標準說明中找到一個不錯的解釋圖:
(引用自http://www.w3.org/TR/SVG/painting.html)
可以看到,所謂Even odd規則就是被偶數條線包圍的區域會被填充。
所以,有了外面的大邊框,被菱形分割的四個小角就是被偶數條線所包圍,Clip會生效。注意使用CGContextEOClip函數來做Even odd模式的Clip操作。
修改上面的“繪製Clip區域”代碼如下:
//繪製Clip區域 CGContextMoveToPoint(gc, width/2, 0); CGContextAddLineToPoint(gc, width, height/2); CGContextAddLineToPoint(gc, width/2, height); CGContextAddLineToPoint(gc, 0, height/2); CGContextClosePath(gc); //加入矩形邊框並調用CGContextEOClip函數 CGContextAddRect(gc, CGContextGetClipBoundingBox(gc)); CGContextEOClip(gc);
運行結果:
更新
如果你只需要從原圖片中截圖一個矩形區域,那麼可以直接用CGImageRef,如下代碼:
- (void)viewWillAppear:(BOOL)animated { //原始UIImage UIImage *srcImg = [UIImage imageNamed:@"meteoralp.jpg"]; //創建CGImageRef並從一個矩形中截取源UIImage的一部分 CGImageRef cgimg = CGImageCreateWithImageInRect(srcImg.CGImage, CGRectInset(CGRectMake(0, 0, srcImg.size.width, srcImg.size.height), 20, 100)); UIImage *destImg = [UIImage imageWithCGImage:cgimg]; //注意釋放CGImageRef,因爲創建方法包含Create CGImageRelease(cgimg); //創建UIImageView並顯示在界面上 UIImageView *imgView = [[UIImageView alloc] initWithImage:destImg]; [self.view addSubview:imgView]; }
結果: