iOS UIImage与绘图,裁剪,图像上下文


比如需要给图片加上水印,绘制对图片进行裁剪和处理,都是绘图中对图片的特定操作。

绘图图片

UIImage类

UIImage类中提供了创建UIImage对象的方法,这其中既有类方法(class method),也有实例方法(instance method),最常用的有如下几个方法:

imageNamed: 类方法,从main bundle中读取图片文件。通常情况下图片放置在工程的Assets.xcassets文件夹中,只要提供文件名即可创建UIImage对象;

+(nullable UIImage *)imageNamed:(NSString *)name;

imageWithContentOfFile: 类方法,从工程文件中读取图片,传入一个图片路径参数,最终得到一个UIImage对象;

+(nullable UIImage *)imageWithContentsOfFile:(NSString *)path;

imageWithData: 类方法,从一个NSData对象中加载图片;

+(nullable UIImage *)imageWithData:(NSData *)data;

initWithContentsOfFile:实例方法,与imageWithContentOfFile类似,需要传入图片的路径。

-(nullable instancetype)initWithContentsOfFile:(NSString *)path;

下方的示例代码中演示了创建UIImage对象的常用方法。

UIImage *image1 = [UIImage imageNamed:@"logo"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"99ios" ofType:@"png"];
UIImage *image2 = [UIImage imageWithContentsOfFile:path];

绘图方法

在UIImage类中提供了2个主要的绘图方法,可以把图片绘制到绘图上下文中(有些类似于绘画结束后盖印章,只需一盖就可以把一个完整的印章图形显示在纸面上,这个和用笔画画有些区别):

drawAtPoint: 以图片的左上角为锚点,显示在制定的Point位置,图片不做压缩处理,显示原始大小;

-(void)drawAtPoint:(CGPoint)point;

drawInRect: 把图片装在一个矩形区域内显示,图片有可能会放大/缩小或者拉伸/压缩。

-(void)drawInRect:(CGRect)rect; 

使用

后绘制的图会把先绘制的盖住。
创建一个名为MainView的类,继承自UIView,在StoryBoard中,修改主控制器View的类型为MainView。
在这里插入图片描述

//  MainView.m
//  UIImage与绘图
//
//  Created by  on 2019/7/22.
//  Copyright © 2019 Shae. All rights reserved.
//

#import "MainView.h"

@implementation MainView

- (void)drawRect:(CGRect)rect{
    UIImage *image1=[UIImage imageNamed:@"1"];
    NSString *path=[[NSBundle mainBundle] pathForResource: @"2"ofType:@"jpg"];
    UIImage *imgae2=[UIImage imageWithContentsOfFile:path];
    
    //先绘制image1
    [image1  drawAtPoint:CGPointZero];
    
    //绘制imgae2
    [imgae2 drawInRect:CGRectMake(0, 250, 100, 100)];
}

@end

在这里插入图片描述

添加水印

在类似新浪微博的应用中,上传的图片都会自动添加水印watermark,水印的添加也是通过绘图的方式实现的,即首先在画布上画上图片,然后再添加上水印签名。
对UIImage对象的修改和加工,经常会使用到UIGraphics类中提供的函数。对UIImage对象进行修改,通常会采取如下步骤:

  • 调用UIGraphicsBeginImageContext方法,开启一个空白的图像上下文,图像上下文包含了绘图的参数和属性,就是一个画布,一个绘图环境;
UIKIT_EXTERN void     UIGraphicsBeginImageContext(CGSize size);
UIKIT_EXTERN void     UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale);
  • 绘制该上下文中的内容,例如添加图片,添加文字等;
  • 根据最新的图像上下文中的内容,调用UIGraphicsGetImageFromCurrentImageContext函数,得到一个图像合成后的UIImage对象;
UIKIT_EXTERN UIImage* __null_unspecified UIGraphicsGetImageFromCurrentImageContext(void);
  • 调用UIGraphicsEndImageContext函数,关闭上下文,以节省内存。
UIKIT_EXTERN void     UIGraphicsEndImageContext(void); 

使用

分类的方式为UIImage添加水印的函数

分类.h

//
//  UIImage+MYImage.h
//  UIImage与绘图
//
//  Created by  on 2019/7/22.
//  Copyright © 2019 Shae. All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (MYImage)
+(UIImage *) image:(UIImage *)image addWaterMarkWithString:(NSString *)string;
@end

NS_ASSUME_NONNULL_END

分类.m

//
//  UIImage+MYImage.m
//  UIImage与绘图
//
//  Created by  on 2019/7/22.
//  Copyright © 2019 Shae. All rights reserved.
//

#import "UIImage+MYImage.h"

@implementation UIImage (MYImage)
+ (UIImage *)image:(UIImage *)image addWaterMarkWithString:(NSString *)string{
    //开启一个图形上下文
    UIGraphicsBeginImageContext(image.size);
    //绘制上下文:1.绘制图片
    [image drawAtPoint:CGPointMake(0, 20)];
    //绘制上下文:2.添加文字到上下文
    NSDictionary *dict=@{NSFontAttributeName:[UIFont systemFontOfSize:80.0],
                         NSForegroundColorAttributeName:[UIColor blackColor]
                         };
    [string drawAtPoint:CGPointMake(60, 60) withAttributes:dict];
    //从图形上下文中获取合成的图片
    UIImage *watermarkImage=UIGraphicsGetImageFromCurrentImageContext();
    //关闭上下文
    UIGraphicsEndImageContext();
    return watermarkImage;
    
}
@end

使用分类

-(void)addWaterMark{
    UIImage *image1=[UIImage imageNamed:@"1"];
    UIImage *imageWater =[UIImage image:image1 addWaterMarkWithString:@"Shae"];
    UIImageView *imageView=[[UIImageView alloc]initWithImage:imageWater];
    imageView.frame=CGRectMake(0, 0, 1025, 576);
    [self addSubview:imageView];
}

在这里插入图片描述

代码1:

https://github.com/ShaeZhuJiu/UIImgaeAndDraw_1.git

裁剪圆形图片

比如把一个方形图片裁剪成圆形,比如个人头像。

使用绘图的方式裁剪

当使用绘图的方式对图片进行裁剪时,主要的思路就是裁剪出来一个圆形的图形上下文,相当于得到了一张圆形的画布,然后在这个圆形的画布上绘画,自然得到了一张圆形的图片。

下面的示例代码实现了对一个正方形的图片进行裁剪,最终得到一个圆形的图片。

-(UIImage *)clipImageView:(UIImage *)image{
    //开启上下文
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);
    //  获取路径
    UIBezierPath *path=[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //裁剪圆形
    [path addClip];
    //n把图片塞进上下文
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //保存新图片
    UIImage *newImage=UIGraphicsGetImageFromCurrentImageContext();
    //关闭上下文
    UIGraphicsEndImageContext();
    return  newImage;
    
}
//
//  ViewController.m
//  UIImageLipe
//
//  Created by 谢鑫 on 2019/7/23.
//  Copyright © 2019 Shae. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *clipImageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    UIImage *image=[UIImage imageNamed:@"2"];
    UIImage *newImage=[self clipImageView:image];
    _clipImageView.image=newImage;
   
}

在这里插入图片描述
设置背景颜色clearColor,可以图片没占的地方为透明。

headImage.backgroundColor=[UIColor clearColor];

在这里插入图片描述
在这里插入图片描述

/// 对图片生成圆角,可用于button等的背景图片
/// @param OriginalImage 原图,可用纯色图片
/// @param sizeToFit 大小
/// @param radius 圆角弧度
+ (UIImage *)OriginalImage:(UIImage *)OriginalImage WithRoundedCornersAndSize:(CGSize)sizeToFit andCornerRadius:(CGFloat)radius
{
CGRect rect = (CGRect){0.f, 0.f, sizeToFit};
UIGraphicsBeginImageContextWithOptions(sizeToFit, NO, UIScreen.mainScreen.scale);
CGContextAddPath(UIGraphicsGetCurrentContext(),
[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:4].CGPath);
CGContextClip(UIGraphicsGetCurrentContext());
[OriginalImage drawInRect:rect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

其他方法

在实际的开发过程中,还有一种更加常用并且简便的方法,能够实现对图片控件的裁剪,即修改UIView的layer属性。

UIView类中有一个CALayer类型的属性–layer,通过对layer的修改,也可以达到对图片的裁剪效果。

CALayer类中有两个常用的属性,cornerRadius和masksToBounds属性

以上方法只适用于一个界面只有几个按钮,如果是大量的按钮,如UITableViewCell上那么就会出现卡顿,造成这个原因就是离屏渲染。

@property CGFloat cornerRadius;//圆角半径
@property BOOL masksToBounds; //是否裁剪
-(void)clipImageView2{
UIImage *image=[UIImage imageNamed:@"2"];
_clipImageView.image=image;
_clipImageView.layer.cornerRadius=_clipImageView.bounds.size.width*0.5;
_clipImageView.layer.masksToBounds=YES;
}

在这里插入图片描述

截屏

在游戏应用中,通常会提供截屏的功能,用来记录辉煌的游戏记录。UIKit框架中,也提供了简单高效的截屏方法,以及保存截屏文件的方法,供开发者直接调用。
通常情况下,在应用中添加截屏功能需要有如下两个步骤:

第一步,获取当前屏幕截屏图片。在UIView类中,提供了drawViewHierarchyInRect: afterScreenUpdates方法,利用该方法可以实现对任何View视图的截取图像操作。在使用之前,需要提前准备绘图上下文。

- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates ;

第二步,保存图片到本地相册。在UIImagePickerController类中,封装了一个专门用于保存图片到相册的函数UIImageWriteToSavedPhotosAlbum。通过该函数可以把UIImage图片对象存放到手机相册中。

UIKIT_EXTERN void UIImageWriteToSavedPhotosAlbum(UIImage *image, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo) ;

使用

-(void)myScreenShot{
    //开启一个图形上下文
    UIGraphicsBeginImageContext(self.view.bounds.size);
    //截屏
    if([self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES]){
        NSLog(@"Successfully draw the screenshot.");
    }else{
         NSLog(@"Failed to draw the screenshot.");
    }
    //获取当前d上下文
    UIImage *screenShot= UIGraphicsGetImageFromCurrentImageContext();
    //关闭上下文
    UIGraphicsEndImageContext();
    //保存到相册
    UIImageWriteToSavedPhotosAlbum(screenShot, self, nil, nil);
}

保存图片报错 权限Crash问题:

在这里插入图片描述
解决:
1.在项目中找到info.plist文件,右键点击以 Source Code形式打开
2.添加报错信息中的键值对,这里以 PhotoLibrary 作为例子

<key>NSPhotoLibraryAddUsageDescription</key>
    <string>此 App 需要您的同意才能读取媒体资料库</string>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

绘制纯色图片

/// 生成纯色图片
/// @param color  [UIColor redColor]
/// @param rect CGRectMake(0, 0, _editBtn.frame.size.width, _editBtn.frame.size.height)],必须0,0开始
+ (UIImage *)createImageWithColor:(UIColor *)color frame:(CGRect)rect
{
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

代码2

https://github.com/ShaeZhuJiu/UIImageClip.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值