iOS - 图形上下文使用

实现圆形图片的裁切有多种方法,可以直接设置layer.cornerRadius,但这样会造成离屏渲染,耗费内存。在此不详述离屏渲染,想看的戳进去吧:iOS离屏渲染研究

先来个简单例子:实现圆形图片的裁切

- (UIImage *)circleImage:(UIImage *)image {

    if (!image) return nil;

    // 开始上下文,下面不使用时一定要关闭,从上下文栈中移除
    UIGraphicsBeginImageContextWithOptions(image.size, NO
                                           ,[UIScreen mainScreen].scale);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // 添加镶边
    CGContextSetLineWidth(context, 1);
    CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);

    //裁切
    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
    CGContextAddEllipseInRect(context, rect);
    CGContextClip(context);

    // 在圆区内画出image原图
    [image drawInRect:rect];

    // 围绕当前路径画一条线,镶边线,注意在调用strokePath之前必须先添加线,fillPath也一样要先添加线才可操作
    CGContextAddEllipseInRect(context, rect);
    CGContextStrokePath(context); 

    //从上下文环境中获取切好的图片
    UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();

    // 使用了beginImgacontext需要关闭上下文 并从上下文栈中移除
    UIGraphicsEndImageContext();

    return newImg;

}

调用方式如:

    UIImage *image = [UIImage imageNamed:@"welcome.png"];

    UIImageView *imagView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 30, 120, 120)];
    imagView.image = [self circleImage:image];
    [self.view addSubview:imagView];

一直对上下文操作视图感到好奇,这下便查看部分文档资料,简单翻译了下,如有不合理欢迎指正:

UIGraphicsGetCurrentContext()
 返回:
    当前的图形上下文   

描述: 
    默认情况下当前的图形上下文为nil,首先调用到它的是drawRect:方法,
    视图控件将一个有效的上下文压到一个栈中,使其成为当前上下文, 如果你不使用一个控件对象来进行绘画, 
    那么你便需要手动将一个有效的上下文压到栈中通过使用UIGraphicsPushContext函数   

 这个方法可能从你app的任何线程中调用。

 UIGraphicsPushContext(ctx):
使一个特殊的上下文成为当前的上下文    

描述: 你可以使用这个功能去保存之前的图形上下文状态,并且使一个上下文成为当前的上下文,
使用这个方法需要配对使用UIGraphicsPopContext方法 这个方法可能从你的app的任何线程中调用

 UIGraphicsPopContext(ctx):
  从上下文栈中移除当前的上下文,恢复使用之前的上下文

 UIGraphicsBeginImageContext(size)
 创建一个基于位图的图形上下文,并使之成为当前的上下文

parameters:  
     size: 新位图上下文的尺寸,这个代表了通过        UIGraphicsGetImageFromCurrentImageContext方法返回的图片的尺寸    

 描述: 
     这个方法相当于调用了UIGraphicsBeginImageContextWithOptions方法, 
     并且opaque参数设置为NO,并且一个scale参数为1.0 这个方法可能从你的app的任何线程中调用

 UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)
 创建一个基于位图的图形上下文同时附带有相应的选择

parameters:
    size: 新的位图上下文的尺寸(以点来作为量算单位)。 
    这展现在在UIGraphicsGetImageFromCurrentImageContext函数返回的图片的尺寸。 
    为了得到位图的的像素尺寸,你必须以宽度和高度乘以scale参数。

    opaque: 一个BOOL值的标志标志着位图是否为半透明。如果你知道位图是完全的不透明, 
    赋值YES去忽略掉alpha通道并且优化位图的存储空间。 
    赋值为NO意味着位图必须要包含alpha通道去掌握着部分的透明像素。

    scale: 这个scale元素去应用到位图中,如果你将其设置为0.0f, 
    那么就会以系统设备屏幕尺寸的的scale作为标准。

讨论:
    你可以使用这个方法去配置绘画环境提交到位图中。 
    这个位图是ARGB32-bit整型像素格式使用主byte次序。如果opaque参数设置为YES, 
    这个alpha通道被忽略并且被认为是完全不透明(kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrer32Host)。 
    不然每一个像素使用premultipledARGB格式(kCGImageAlphaPremultipledFirst | kCGBitmapByteOrder32Host).

这个环境同时使用了默认的UIKit视图的坐标系统,它的原点是在左上角, 
正轴是原点向下及向右。这个提供到的scale因为同样应用到坐标系统及得到的结果图片。 
这个绘画环境会被立刻push到图形上下文。

当 当前上下文是通过这个方法生成的,你便可以调用UIGraphicsGetImageFromCurrentImageContext 
函数去取回基于当前上下文的图片对象。当你不再改正上下文你必须去调用UIGraphicsEndImageContext方法去清理位图绘画环境并且从上下文栈中移除。 
你不应该使用UIGraphicsPopContext函数去从栈上移除上下文。

在大多数其他情况,这个图形上下文创建与其他一样,你可以改变上下文通过 
push或pop其他图形上下文,你一样可以通过UIGraphicsGetCurrentContext函数。

这个函数可以被任何线程的app调用

 UIGraphicsGetImageFromCurrentImageContext
返回一个基于当前位图上下文中的内容

Return Value:
    一个图片对象包含当前图片上下文中的内容

讨论:
    你只能在一个位图上下文为当前上下文时才能调用这个方法。 
    如果当前上下文为nil或者不是通过调用UIGraphicsBeginImageContext来调用的,那么这个函数便返回nil.

这个函数可以被app的任何线程调用。

 UIGraphicsEndImageContext
从上下文栈顶部移除当前的位图上下文


注: 你可以使用这个方法来清理通过UIGraphicsBeginImageContext函数创建的上下文并且可以移除在栈顶部并基于位图的上下文。 
如果当前上下文不是通过UIGraphicsBeginImageContext函数创建,那么这个方法什么都不会去做。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值