不規則截圖的實現

效果如下圖:

wps_clip_image-561  wps_clip_image-492 

 

首先,在工程Bundle中加入測試用的圖片文件,比如“meteoralp.jpg”。

image

 

首先,我們需要把圖片展示在界面上。很簡單的操作,唯一需要注意的是由於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];
}

 

圖片就顯示出來了:

wps_clip_image-2157

 

接下來繪製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,運行後第一個圖的效果就出來了:

wps_clip_image-561

 

接下來完成第二個圖的效果。第二個圖是這樣完成的,我們不僅需要加入第一個圖繪製的菱形,同時還要把最外層的邊框加入到Path中。後者可以通過CGContextGetClipBoundingBox函數直接得到。

接下來需要講一下Even-Odd規則,這個規則其實在諸多平臺的繪圖框架中都有使用,都也是用在填充或者Clip操作中的。

沒有在Apple的文檔中找到圖,倒是在W3C的SVG標準說明中找到一個不錯的解釋圖:

image

(引用自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);

 

運行結果:

wps_clip_image-492

 

更新

如果你只需要從原圖片中截圖一個矩形區域,那麼可以直接用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];
}

 

結果:

wps_clip_image-29406

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章