iOS裁剪UIImage部分不规则区域

效果如下图:

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,如下代码:

//原始UIImage
UIImage *srcImg = [UIImage imageNamed:@"meteoralp.jpg"];
//创建CGImageRef并从一个矩形中截取源UIImage的一部分
CGImageRef cgimg = CGImageCreateWithImageInRect(srcImg.CGImage, CGRectInset(CGRectMake(0, 0, srcImg.size.width * srcImg.scale, srcImg.size.height * srcImg.scale), 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


有任何疑问,可以到Coldfunction来提问.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值