iOS绘图 - UIImage的一些简单操作

iOS绘图 - 基础篇中我们知道有一种获取上下文的方法是UIGraphicsBeginImageContextWithOptions,本文主要在图片类型上下文中对图片进行操作,具体实现的功能:
- 1.生成图片
- 2.绘制图片到视图
- 3.添加水印
- 4.截取屏幕或者相应view
- 5.图片擦除
- 6.图片裁剪

  • 具体的方法使用就在方法的介绍中解释吧,为了代码的复用,对上述方法进行了封装,放在UIImage的类别中,方便今后使用。

图片操作的基本步骤

1.开启图形上下文
2.绘制图片
- 使用drowInRect或者drawAtPoint绘制图片(区别在哪儿?你可以先想一想)
 drawInRect是以rect作为图片绘制的区域,图片是以填充的方式被绘制在当前区域图片的大小,rect的宽高比和原图片的宽高比不同时会造成图片的变形
 drowAtPoint是以point作为图片绘制的起点,绘制的图片的大小依然是原图片的大小,不会使图片变形
- 将layer渲染在当前上下文
3.从当前上下文获取新的图片
4.关闭上下文

1.生成图片,这里我们生成特定颜色的图片

+ (UIImage *)createImageColor:(UIColor *)color size:(CGSize)size {
    //开启图形上下文
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    //绘制颜色区域
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, size.width, size.height)];
    [color setFill];
    [path fill];
//    CGContextRef ctx = UIGraphicsGetCurrentContext();
//    CGContextSetFillColorWithColor(ctx, color.CGColor);
//    CGContextFillRect(ctx, CGRectMake(0, 0, size.width, size.height));
    //从图形上下文获取图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    //关闭图形上下文
    UIGraphicsEndImageContext();
    
    return newImage;
}

2.绘制图片,可以设置绘制的图片比例或者指定压缩后的图片的大小,可以当做压缩图片使用

 这里我使用了drawInRect有兴趣的可以使用drowAtPoint,看看效果
+ (UIImage *)scaleImage:(UIImage *)image sclae:(CGFloat)scale {
    //确定压缩后的size
    CGFloat scaleWidth = image.size.width * scale;
    CGFloat scaleHeight = image.size.height * scale;
    CGSize scaleSize = CGSizeMake(scaleWidth, scaleHeight);
    //开启图形上下文
    UIGraphicsBeginImageContext(scaleSize);
    //绘制图片
    [image drawInRect:CGRectMake(0, 0, scaleWidth, scaleHeight)];
    //从图形上下文获取图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    //关闭图形上下文
    UIGraphicsEndImageContext();
    return newImage;
}

3.绘制水印

文字水印

可能你在添加文字水印之后,显示文字字体并不是你设置的字体大小,这是因为画布的size是图片的size,绘制后的图片被添加到ImageView上时可能被压缩或者放大,文字也就会发生变化。

+ (UIImage *)waterAtImage:(UIImage *)image
                   text:(NSString *)text
                  point:(CGPoint)point
             attributes:(NSDictionary *)attributes {
    //开启图形上下文
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
    //绘制图片
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //添加文字
    [text drawAtPoint:point withAttributes:attributes];
    //获取图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    //关闭上下文
    UIGraphicsEndImageContext();
    return newImage;
}
图片水印
+ (UIImage *)waterAtImage:(UIImage *)image
             waterImgae:(UIImage *)waterImage
                   rect:(CGRect)rect {
    //开启图形上下文
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
    //绘制原图片
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.width)];
    //绘制水印
    [waterImage drawInRect:rect];
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

4.截屏

1.创建图形上下文
2.将view的layer渲染到图形上下文
3.从图形上下文得到图片
4.关闭图像上下文

//当然如果你只是需要某个view的快照,在iOS7之后你可以使用[view snapshotViewAfterScreenUpdates:NO];来获得,比如实现长按拖拽cell的操作

+ (void)cutView:(UIView *)view success:(void(^)(UIImage *image))success {
    //开启图形上下文
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
    //获取当前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //渲染
    [view.layer renderInContext:ctx];
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    success(newImage);
}

5.擦除

1.设置两张图片,上方为我们要擦除的图片,后方为需要展示的图片
2.设置擦除的区域的大小和位置

+ (UIImage *)wipeView:(UIView *)view
                point:(CGPoint)point
                 size:(CGSize)size {
    //开启图形上下文
    UIGraphicsBeginImageContext(view.bounds.size);
    //获取当前上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //渲染
    [view.layer renderInContext:ctx];
    //计算擦除的rect
    CGFloat clipX = point.x - size.width/2;
    CGFloat clipY = point.y - size.height/2;
    CGRect clipRect = CGRectMake(clipX, clipY, size.width, size.height);
    //将该区域设置为透明
    CGContextClearRect(ctx, clipRect);
    //获取新的图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    return newImage;
}
擦除

6.图片裁剪

矩形区域的裁剪,这里我们就利用drowAtPoint的特性去进行裁剪

1.假设一张图片的size是(600,600)
2.imageView的size是(300,300)
3.我们选择的裁剪区域是(10,10,150,150)
4.而我们为了能够保持原来图片的分辨率,在图片不拉伸的情况下在原图片上进行剪裁,所以实际我们在图片上的剪裁区域就是(20,20,300,300)
5.图片绘制在画布上的点就是(-20,-20),这样我们不需要进行裁剪就能获得我们想要得到的图片啦

+ (UIImage *)cutImage:(UIImage *)image
        imageViewSize:(CGSize)size
             clipRect:(CGRect)rect {
    //图片大小和实际显示大小的比例
    CGFloat scale_width = image.size.width/size.width;
    CGFloat scale_height = image.size.height/size.height;
    //实际剪切区域
    CGRect clipRect = CGRectMake(rect.origin.x * scale_width,
                                 rect.origin.y * scale_height,
                                 rect.size.width * scale_width,
                                 rect.size.height * scale_height);
    
    //开启图形上下文
    UIGraphicsBeginImageContext(clipRect.size);
    //画图
    [image drawAtPoint:CGPointMake(-clipRect.origin.x, -clipRect.origin.y)];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return newImage;
}
自定义点连线截图

1.将自定义点变换到在图片上的点
2.计算出自定义点所在的区域rect
3.开始图形上下文,rect.size
4.绘制path,机型剪裁
5.绘图drawAtPoint,x: - rect.origin.x y: - rect.origin.y
6.从图形上下文获取图片
7.关闭图形上下文

+ (UIImage *)cutImage:(UIImage *)image
        imageViewSize:(CGSize)size
           clipPoints:(NSArray *)points {
    //图片大小和实际显示大小的比例
    CGFloat scale_width = image.size.width/size.width;
    CGFloat scale_height = image.size.height/size.height;
    
    //处理剪裁的点
    NSArray *newPoints = [UIImage points:points scalex:scale_width scaleY:scale_height];
    
    //确定上下左右边缘的点
    //x升序数组
    NSArray *point_x = [newPoints sortedArrayUsingComparator:^NSComparisonResult(NSValue *obj1, NSValue *obj2) {
        CGPoint point1 = [obj1 CGPointValue];
        CGPoint point2 = [obj2 CGPointValue];
        return point1.x > point2.x;
    }];
    //y升序数组
    NSArray *point_y = [newPoints sortedArrayUsingComparator:^NSComparisonResult(NSValue *obj1, NSValue *obj2) {
        CGPoint point1 = [obj1 CGPointValue];
        CGPoint point2 = [obj2 CGPointValue];
        return point1.y > point2.y;
    }];
    
    //确定剪切的区域
    CGRect clipRect = CGRectMake([point_x.firstObject CGPointValue].x,
                                 [point_y.firstObject CGPointValue].y,
                                 [point_x.lastObject CGPointValue].x - [point_x.firstObject CGPointValue].x,
                                 [point_y.lastObject CGPointValue].y - [point_y.firstObject CGPointValue].y);
    //开启图形上下文
    UIGraphicsBeginImageContext(clipRect.size);
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    for (NSInteger i = 0; i < newPoints.count; i ++) {
        CGPoint point = [newPoints[i] CGPointValue];
        if (i == 0) {
            [path moveToPoint:point];
        } else {
            [path addLineToPoint:point];
        }
    }
    [path closePath];
    [path addClip];
    
    //画图
    [image drawAtPoint:CGPointMake(-clipRect.origin.x, -clipRect.origin.y)];
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    return newImage;
}
cutImage
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容