当前位置: 澳门新濠3559 > 编程 > 正文

澳门新濠3559、添加图片水印,图片擦除

时间:2019-09-14 13:32来源:编程
最近对图片的处理较多,就总结出一个UIImage分类(UIImage ZJIamge.h),以便之后使用。 此分类的功能有: 1、图片切圆2、给图片添加水印(水印可为文字或图片)3、截屏或者截取某个v

最近对图片的处理较多,就总结出一个UIImage分类(UIImage ZJIamge.h),以便之后使用。

此分类的功能有:

1、图片切圆2、给图片添加水印(水印可为文字或图片)3、截屏或者截取某个view的视图4、根据颜色生成图片5、图片的等比例缩放6、图片的自由拉伸

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

图片水印

  • 图片水印就是在图片的基础上绘制一些文字或logo,最终生成一张新的图片

  • 在viewDidLoad方法中生成图片水印的步骤:

    1. 加载图片

       UIImage *image = [UIImage imageNamed:@"小黄人"]; 
      
    • 手动获取上下文,之前的上下文都是在view的drawRect方法中获取的(跟View相关联的layer上下文),目前我们需要绘制图片到新的图片上,所以需要用到位图上下文

    • 怎样获取位图上下文呢?注意,位图上下文的获取方式跟layer上下文不一样,位图上下文需要我们手动创建

      // 开启一个位图上下文,注意位图上下文跟view无关联,所以不需要在drawRect.
      // size:位图上下文的尺寸(新图片的尺寸)
      // opaque: 不透明度 YES:不透明 NO:透明,通常我们一般都弄透明的上下文
      // scale:通常不需要缩放上下文,取值为0,表示不缩放
      UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
      
    • 绘制图片水印

      // 1.绘制原生的图片
      [image drawAtPoint:CGPointZero];
      
      // 2.给原生的图片添加文字
      NSString *str = @"水印文字";
      
      // 创建字典属性
      NSMutableDictionary *dict = [NSMutableDictionary dictionary];
      dict[NSForegroundColorAttributeName] = [UIColor redColor];
      dict[NSFontAttributeName] = [UIFont systemFontOfSize:20];
      
      [str drawAtPoint:CGPointMake(200, 528) withAttributes:dict];
      
  • 绘制贝瑟尔路径

     UIBezierPath *path =[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 300, 300)];
     [[UIColor redColor] set];
     [path stroke];
    
  • 底层实现

     // 1.获取上下文(位图上下文)
     CGContextRef ctx = UIGraphicsGetCurrentContext();
    
     // 2.描述路径
     CGContextMoveToPoint(ctx, 50, 50);
    
     CGContextAddLineToPoint(ctx, 200, 200);
    
     [[UIColor redColor] set];
    
     // 3.渲染上下文
     CGContextStrokePath(ctx);
    
  • 生成一张图片给我们,从上下文中获取图片,并将其显示到UIImageView上

     UIImage *imageWater = UIGraphicsGetImageFromCurrentImageContext();
     self.imageView.image = imageWater;
    
  • 关闭上下文

     UIGraphicsEndImageContext();
    

Quartz2D

简介

Quartz2D是二维(平面)的绘图引擎(经包装的函数库,方便开发者使用。也就是说苹果帮我们封装了一套绘图的函数库)

同时支持iOS和Mac系统开发,用Quartz2D写的同一份代码,既可以运行在iphone上又可以运行在mac上,可以跨平台开发。

Quartz 2D能完成的工作

绘制图形 : 线条三角形矩形圆弧等

绘制文字

绘制生成图片(图像)

读取生成PDF

截图裁剪图片

自定义UI控件

.....

Quartz2D在iOS开发中的价值

为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的UI控件 UILabel:显示文字 UIImageView:显示图片 UIButton:同时显示图片和文字(能点击) … …

利用UIKit框架提供的控件,拼拼凑凑,能搭建和现实一些简单、常见的UI界面,但是,有些UI界面极其复杂、而且比较个性化,用普通的UI控件无法实现,这时可以利用Quartz2D技术将控件内部的结构画出来,自定义控件的样子,iOS中大部分控件的内容都是通过Quartz2D画出来的,因此,Quartz2D在iOS开发中很重要的一个价值是:自定义view(自定义UI控件)

自定义View

图形上下文(Graphics Context):是一个CGContextRef类型的数据

图形上下文的作用

保存绘图信息、绘图状态 -决定绘制的输出目标(绘制到什么地方去?) (输出目标可以是PDF文件、Bitmap或者显示器的窗口上) 相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上

自定义view的步骤

新建一个类,继承自UIView

实现- (void)drawRect:(CGRect)rect方法,然后在这个方法中

取得跟当前view相关联的图形上下文

绘制相应的图形内容

利用图形上下文将绘制的所有内容渲染显示到view上面

drawRect:方法

实现drawRect:方法才能绘图到view,因为在drawRect:方法中才能取得跟view相关联的图形上下文,

drawRect:方法在调用时间 当view第一次显示到屏幕上时(被加到UIWindow上显示出来) 调用view的setNeedsDisplay或者setNeedsDisplayInRect:时

在drawRect:方法中取得上下文后,就可以绘制东西到view上

View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去了,View之所以能显示东西,完全是因为它内部的layer

示例1画直线

1> 获取图形上下文 CG:表示这个类在CoreGraphics框架里 Ref:引用 目前学的上下文都跟UIGraphics有关,想获取图形上下文,首先敲UIGraphics。

2> 拼接路径:一般开发中用贝塞尔路径,里面封装了很多东西,可以帮我画一些基本的线段,矩形,圆等等。 创建贝塞尔路径 起点:moveToPoint 终点:addLineToPoint

3> 把路径添加到上下文 CGPath转换:UIKit框架转CoreGraphics直接CGPath就能转

4> 把上下文渲染到视图,图形上下文本身不具备显示功能。 PPT画图分析为什么要这样做?首先获取图形上下文,然后描述路径,把路径添加到上下文,渲染到视图,图形上下文相当于一个内存缓存区,在内存里面操作是最快的,比直接在界面操作快多了。

在添加一根线 直接addLineToPoint,因为路径是拼接的,默认下一条线的起点是上一条线的终点。

画两跟不连接的线 1> 第二次画的时候,重新设置起点,然后画线。一个路径可以包含多条线段。 2> 新创建一个路径,添加到上下文。开发中建议使用这种,比较容易控制每根线。

设置绘图状态 线段怎么加粗。 绘图状态调用顺序:只要在渲染之前就好了,在渲染的时候才会去看绘图的最终状态。

// 1.获取跟当前view想关联的上下文// 以后只要根上下文有关,直接敲UIGraphics,一般都是以UIGraphics开头// CG:CoreGraphics Ref:引用CGContextRefctx =UIGraphicsGetCurrentContext();// 2.绘制内容,拼接路径,绘制的内容统称为路径// 在开发中一般使用贝塞尔路径,UIKit框架UIBezierPath*path = [UIBezierPathbezierPath];// 设置起点,移动到某个位置[path moveToPoint:CGPointMake(50,50)];// 添加一根线到某个点[path addLineToPoint:CGPointMake(200,200)];// 一根路径对象可以包含很多线段[path moveToPoint:CGPointMake(50,200)];// 默认下一根线的起点在上一根线的终点[path addLineToPoint:CGPointMake(100,200)];// 3.把路径添加到上下文,给上下文添加路径以CGContextCGContextAddPath(ctx, path.CGPath);// 开发中,如果线段不连接,最好使用一根线对应一个路径对象// 描述第二根线//    path = [UIBezierPath bezierPath];////    // 设置起点,移动到某个位置//    [path moveToPoint:CGPointMake(200, 200)];////    // 添加一根线到某个点//    [path addLineToPoint:CGPointMake(100, 200)];////    CGContextAddPath(ctx, path.CGPath);// 4.把上下文内容渲染到viewCGContextStrokePath(ctx);

示例2画圆形

//Center:圆心//radius:半径.//startAngle:开始角度//endAngle:结束角度//clockwise:CGPointcenter =CGPointMake(self.bounds.size.width*0.5,self.bounds.size.height*0.5);CGFloatradius =100;CGFloatstartA =0;//圆的0度角在圆的最右侧.CGFloatendA = -M_PI_2;UIBezierPath*path =  [UIBezierPathbezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];    [UIColorredColor] set];    [path stroke];

示例3画文字,常见属性

//我们要画的文字NSString*str =@"我们要画的文字";//开始绘制文字//   

思路:利用Quartz2D框架,开启图形上下文将图片绘制出来并处理之后,关闭图形上下文并生成一张新的图片即可。

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

图片裁剪

  • 图片裁剪是把正方形图片进行裁剪,并生成一张圆形的图片
  • 裁剪无边框的图片
- (void)clipImage
{
    // 0.加载图片
    UIImage *image = [UIImage imageNamed:@"阿狸头像"];

    // 1.开启位图上下文,跟图片尺寸一样大
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);

    // 2.设置圆形裁剪区域,正切与图片
    // 2.1创建圆形的路径
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];

    // 2.2把路径设置为裁剪区域
    [path addClip];

    // 3.绘制图片
    [image drawAtPoint:CGPointZero];

    // 4.从上下文中获取图片
    UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();

    // 5.关闭上下文
    UIGraphicsEndImageContext();

    _imageView.image = clipImage;
}
  • 裁剪有边框的图片,并将裁剪方法放到分类中去,以便他人的使用
  (UIImage *)imageWithClipImage:(UIImage *)image borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)color
{
    // 图片的宽度和高度
    CGFloat imageWH = image.size.width;

    // 设置圆环的宽度
    CGFloat border = borderWidth;

    // 圆形的宽度和高度
    CGFloat ovalWH = imageWH   2 * border;

    // 1.开启上下文
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(ovalWH, ovalWH), NO, 0);

    // 2.画大圆
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, ovalWH, ovalWH)];

    [color set];

    [path fill];

    // 3.设置裁剪区域
    UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(border, border, imageWH, imageWH)];
    [clipPath addClip];

    // 4.绘制图片
    [image drawAtPoint:CGPointMake(border, border)];

    // 5.获取图片
    UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();

    // 6.关闭上下文
    UIGraphicsEndImageContext();

    return clipImage;

}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // 图片裁剪:把正方形图片重新生产一张圆形的图片

    // 图片裁剪

    UIImage *image = [UIImage imageWithClipImage:[UIImage imageNamed:@"阿狸头像"] borderWidth:1 borderColor:[UIColor redColor]];

    _imageView.image = image;
}

AtPoint:画在哪个点上.//Attributes:文字的属性.颜色,字体大小...NSMutableDictionary*dict

[NSMutableDictionarydictionary]澳门新濠3559、添加图片水印,图片擦除。;//设置文字的颜色dict[NSForegroundColorAttributeName] = [UIColorredColor];//设置字体大小dict[NSFontAttributeName] =

1、图片切圆

/** 图片裁剪,适用于圆形头像之类 @param image 要切圆的图片 @param borderWidth 边框的宽度 @param color 边框的颜色 @return 切圆的图片 */  (UIImage *)imageWithClipImage:(UIImage *)image borderWidth:borderWidth borderColor:(UIColor *)color{ // 图片的宽度和高度 CGFloat imageWH = image.size.width; // 设置圆环的宽度 CGFloat border = borderWidth; // 圆形的宽度和高度 CGFloat ovalWH = imageWH   2 * border; // 1.开启上下文 UIGraphicsBeginImageContextWithOptions(CGSizeMake(ovalWH, ovalWH), NO, 0); // 2.画大圆 UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, ovalWH, ovalWH)]; [color set]; [path fill]; // 3.设置裁剪区域 UIBezierPath *clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(border, border, imageWH, imageWH)]; [clipPath addClip]; // 4.绘制图片 [image drawAtPoint:CGPointMake(border, border)]; // 5.获取图片 UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext(); // 6.关闭上下文 UIGraphicsEndImageContext(); return clipImage;}

屏幕截屏

  • 屏幕截屏的代码可以封装到分类当中
  (UIImage *)imageWithCaputureView:(UIView *)view
{
    // 开启位图上下文
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);

    // 获取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 把控件上的图层渲染到上下文,layer只能渲染,不能绘制
    [view.layer renderInContext:ctx];

    // 生成一张图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    // 关闭上下文
    UIGraphicsEndImageContext();

    return image;
}
  • 在viewDidLoad方法中调用分类,返回一个UIImage对象
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // 生成一张新的图片

    UIImage *image =  [UIImage imageWithCaputureView:self.view];

    // image转data
    // compressionQuality: 图片质量 1:最高质量

     NSData *data = UIImageJPEGRepresentation(image,1);

    [data writeToFile:@"/Users/xiaomage/Desktop/view.png" atomically:YES];

}

[UIFontsystemFontOfSize:50];//设置描边的颜色dict[NSStrokeColorAttributeName]

[UIColorblueColor];//设置描边的宽度dict[NSStrokeWidthAttributeName] = @1;NSShadow*shadow = [[NSShadowalloc] init];//设置阴影的偏移量shadow.shadowOffset=CGSizeMake(-10,10);//设置阴影的颜色shadow.shadowColor= [UIColorgreenColor];//设置阴影的模糊shadow.shadowBlurRadius=2;    dict[NSShadowAttributeName] = shadow;//drawAtPoint不会自动换行//    [str drawAtPoint:CGPointZero withAttributes:dict];//drawInRect它会自动的换行.[str drawInRect:self.boundswithAttributes:dict];

图形上下文的矩阵操作

形变操作,必须得要在添加路径之前进行

计时器

CADisplayLink

//在绘图当中, 我们一般使用CADisplayLink.因为他和setNeedsDisplay调用时机是一样的,都是当下一次屏幕刷新的时候调用.

2、给图片添加水印(水印可为文字和图片)

、添加文字水印

/** 根据文字生成水印图片 @param imageName 图片 @param str 水印文字 @param point 绘制水印文字的起始点 @param dict 水印文字的属性字典 @return 返回图片 */  (UIImage *)imageWithWaterMarkImage:(NSString *)imageName text:(NSString *)str textPoint:point textAttributes:(NSDictionary *)dict{ UIImage *image = [UIImage imageNamed:imageName]; UIGraphicsBeginImageContextWithOptions(image.size, NO, 0); //把图片画上去 [image drawAtPoint:CGPointZero]; //绘制文字到图片 [str drawAtPoint:point withAttributes:dict]; // 从上下文获取图片 UIImage *imageWater = UIGraphicsGetImageFromCurrentImageContext(); //关闭上下文 UIGraphicsEndImageContext(); return imageWater;}

、添加图片水印

/** 根据图片生成水印图片 @param image 图片 @param waterImage 水印图片 @param rect 水印图片的位置 @return 返回图片 */  (UIImage *)imageWithWaterMarkImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:rect{ //1.开启上下文 UIGraphicsBeginImageContextWithOptions(image.size, NO, 0); //2.绘制背景图片 [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; //绘制水印图片到当前上下文 [waterImage drawInRect:rect]; //3.从上下文中获取新图片 UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext(); //4.关闭图形上下文 UIGraphicsEndImageContext(); //返回图片 return newImage;}
1.开启图形上下文2.绘制图片- 使用drowInRect或者drawAtPoint绘制图片(区别在哪儿?你可以先想一想) drawInRect是以rect作为图片绘制的区域,图片是以填充的方式被绘制在当前区域图片的大小,rect的宽高比和原图片的宽高比不同时会造成图片的变形 drowAtPoint是以point作为图片绘制的起点,绘制的图片的大小依然是原图片的大小,不会使图片变形- 将layer渲染在当前上下文3.从当前上下文获取新的图片4.关闭上下文

图片截取

  • 在viewDidLoad方法中给控制器View添加一个pan手势
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // 给控制器的view添加一个pan手势
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];

    [self.view addGestureRecognizer:pan];
}
  • 在pan:方法中对手势进行处理
- (void)pan:(UIPanGestureRecognizer *)pan
{
    CGPoint endA = CGPointZero;

    if (pan.state == UIGestureRecognizerStateBegan) { // 一开始拖动的时候

        // 获取一开始触摸点
      _startP = [pan locationInView:self.view];

    }else if(pan.state == UIGestureRecognizerStateChanged){ // 一直拖动
        // 获取结束点
         endA = [pan locationInView:self.view];

        CGFloat w = endA.x - _startP.x;
        CGFloat h = endA.y - _startP.y;

        // 获取截取范围
        CGRect clipRect = CGRectMake(_startP.x, _startP.y, w, h);

        // 生成截屏的view
        self.clipView.frame = clipRect;

    }else if (pan.state == UIGestureRecognizerStateEnded){

        // 图片裁剪,生成一张新的图片

        // 开启上下文
        // 如果不透明,默认超出裁剪区域会变成黑色,通常都是透明
        UIGraphicsBeginImageContextWithOptions(_imageV.bounds.size, NO, 0);

        // 使用贝瑟尔路径,设置裁剪区域
       UIBezierPath *path =  [UIBezierPath bezierPathWithRect:_clipView.frame];

        [path addClip];

        // 获取上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();

        // 把控件上的内容渲染到上下文
        [_imageV.layer renderInContext:ctx];

        // 生成一张新的图片
        _imageV.image = UIGraphicsGetImageFromCurrentImageContext();

        // 关闭上下文
        UIGraphicsEndImageContext();

        // 先移除
        [_clipView removeFromSuperview];
        // 截取的view设置为nil
        _clipView = nil;

    }

    // 获取手指的偏移量
    // pan translationInView:(UIView *)
}
  • clipView的懒加载,仅当clipView为空的时候才去创建,否则直接返回
- (UIView *)clipView{
    if (_clipView == nil) {
        UIView *view = [[UIView alloc] init];
        _clipView = view;

        view.backgroundColor = [UIColor blackColor];
        view.alpha = 0.5;

        [self.view addSubview:view];
    }

    return _clipView;
}

//CADisplayLink//它是当每次屏幕刷新的时候就会调用定时器方法.(每一秒种刷新60次)CADisplayLink*link

[CADisplayLinkdisplayLinkWithTarget:selfselector:@selector(update)];//想让定时器工作,必须得要把它添加到主运行循环.[link addToRunLoop:[NSRunLoopmainRunLoop] forMode:NSDefaultRunLoopMode];

NSTimer

[NSTimerscheduledTimerWithTimeInterval:0.01target:selfselector:@selector(update) userInfo:nilrepeats:YES];

注意,在实际开发中视情况选择使用

常用的拼接函数

新建一个起点voidCGContextMoveToPoint(CGContextRefc,CGFloatx,CGFloaty)添加新的线段到某个点voidCGContextAddLineToPoint(CGContextRefc,CGFloatx,CGFloaty)添加一个矩形voidCGContextAddRect(CGContextRefc,CGRectrect)添加一个椭圆voidCGContextAddEllipseInRect(CGContextRefcontext,CGRectrect)添加一个圆弧voidCGContextAddArc(CGContextRefc,CGFloatx,CGFloaty,CGFloatradius,CGFloatstartAngle,CGFloatendAngle,intclockwise)

常用绘制的函数

Mode参数决定绘制的模式

voidCGContextDrawPath(CGContextRefc,CGPathDrawingModemode)绘制空心路径voidCGContextStrokePath(CGContextRefc)绘制实心路径voidCGContextFillPath(CGContextRefc)提示:一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的

矩阵操作

利用矩阵操作,能让绘制到上下文中的所有路径一起发生变化缩放voidCGContextScaleCTM(CGContextRefc,CGFloatsx,CGFloatsy)旋转voidCGContextRotateCTM(CGContextRefc,CGFloatangle)平移voidCGContextTranslateCTM(CGContextRefc,CGFloattx,CGFloatty)

图片水印技术

需求:在手机客户端app中需要用到水印技术,用户拍完照片后,可以在照片上打个水印,标识这个图片是属于哪个用户的

实现方式:利用Quartz2D,将水印(文字、LOGO)画到图片的右下角

核心代码

开启一个基于位图的图形上下文UIGraphicsBeginImageContextWithOptions(CGSizesize,BOOLopaque,CGFloatscale)从上下文中取得图片(UIImage)UIImage*UIGraphicsGetImageFromCurrentImageContext();结束基于位图的图形上下文UIGraphicsEndImageContext();

水印PPT简介

图片水印作用:防止他人盗取图片,加一些Logo,生成一张新的图片。

和绘图一样的生成新的图片,需要拿到上下文做事情,这里也需要拿到上下文,生成一个新的图片。

位图上下文,在这个上下文画东西,就能输出到新的图片上。

之前用的都是图层上下文,系统会自动创建,但是我们位图上下文,需要我们手动创建

总结:只要不和view有关系的上下文,都需要我们手动创建。

在哪获取图像上下文,viewDidLoad, 不需要拿到系统创建的图层上下文,没必要在drawRect方法里写,直接viewDidLoad就行了。

UIGraphicsBeginImageContextWithOptions:(CGSize size, BOOL opaque, CGFloat scale)创建一个位图上下文,而且这种方法得到的图片最清晰。解释参数(size:新图片尺寸 opaque: YES:不透明 NO:透明 scale:0.0 不伸缩)

绘制内容(图片,文字)

获取图片:把位图上下文的内容生成一个图片给你。

关闭上下文,不关闭一直占用着内存。

显示UIImageView上

保存图片,写到文件,UIImage不能写,需要转换成NSData二进制数据

UIImageJPEGRepresentation:可以设置图片质量

UIImagePNGRepresentation:把图片转换成png格式的二进制数据,png格式默认是最高清的。

写到桌面

图片裁剪

图片裁剪

PPT分析思路:先设置裁剪区域,把图片画上去,超出裁剪区域的自动裁剪掉。

加载旧图片,根据旧图片,获取上下文尺寸。

上下文的尺寸 = 新图片的尺寸

开启一个多大的上下文?:和图片尺寸一样大,避免压缩图片。如果比图片尺寸小,会压缩图片。

设置裁剪区域:正切于图片的圆

绘制旧图片

获取新图片

关闭上下文

//1.加载要裁剪的图片UIImage*image = [UIImageimageNamed:@"阿狸头像"];

//2.开启一个跟图片尺寸一样大的位图上下文UIGraphicsBeginImageContextWithOptions(image.size,NO,0);

//3.设置一个裁剪(宽度和高度都是等于原始图片的宽高)UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, image.size.width, image.size.height)];//把路径设置成裁剪区域[path addClip];

//4.把要裁剪的图片绘制到上下文当中.[image drawAtPoint:CGPointZero];

//5.从上下文当中生成一张新的图片UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

//6.关闭上下文.UIGraphicsEndImageContext();self.imageV.image= newImage;

带圆环裁剪:在裁剪的图片外边加个小圆环。

先画一个大圆,在设置裁剪区域,把图片画上去,超出裁剪区域的自动裁剪掉。

加载旧图片,根据旧图片,获取上下文尺寸。

确定圆环宽度 borderW

上下文的尺寸 = 新图片的尺寸

确定新的上下文尺寸: newImageW : oldImageW 2borderW newImageH : oldImageH 2borderW,

绘制大圆: 1.获取上下文 2.添加路径到上下文 3.设置大圆的颜色 = 圆环的颜色 4.渲染

设置裁剪区域,和图片尺寸一样大,只不过,x,y不一样,x=borderW,y=borderW.

绘制旧图片

获取新图片

关闭上下文

抽分类,3个参数,图片名称,圆环宽度,圆环颜色

可以创建给UIImage添加一个分类提供方法直接使用

//0.设置一个边框宽度//1.加载图片//2.开启一个位图上下文CGSizesize =CGSizeMake(image.size.width 2* boderW, image.size.height 2* boderW);UIGraphicsBeginImageContextWithOptions(size,NO,0);

//3.设置一个大圆的一个填充区域UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, size.width, size.height)];//设置边框的颜色[color set];    [path fill];

//4.设置一个小圆裁剪区域path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(boderW, boderW, image.size.width, image.size.height)];//把小圆设置成裁剪区域[path addClip];

//5.把原始图片绘制到上下文当中[image drawInRect:CGRectMake(boderW, boderW, image.size.width, image.size.height)];

//6.生成一张新的图片UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

//7.关闭上下文.UIGraphicsEndImageContext();returnnewImage;

图片截屏

屏幕截图:把屏幕的内容截屏生成一张新的图片

通常开发中,都是把控制器的内容截屏,生成新的图片

控制器根据view显示

view根据layer图层显示

把layer渲染到位图上下文

注意:图层只能用渲染,图片和文字可以用draw

渲染在新的图片

开启图片上下文,和视图一样的尺寸

写入桌面

抽分

//懒加载,当使用才创建,可以节省内存-(UIView*)cover{if(_cover ==nil) {//创建一个遮盖UIView*cover = [[UIViewalloc] init];        cover.backgroundColor= [UIColorblackColor];        cover.alpha=0.7;        _cover = cover;        [self.viewaddSubview:cover];    }return_cover;}

- (void)viewDidLoad {    [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.}

//当手指拖动的时候调用- (IBAction)pan:(UIPanGestureRecognizer*)pan {//获取当前手指所在的点CGPointcurP = [pan locationInView:self.imageV];//起点if(pan.state==UIGestureRecognizerStateBegan){//添加遮盖,设置遮盖的起点.self.startP= curP;    }elseif(pan.state==UIGestureRecognizerStateChanged){//移动,确定遮盖的尺寸//x轴偏移量CGFloatoffsetX = curP.x-self.startP.x;//Y 轴的偏移量CGFloatoffsetY = curP.y-self.startP.y;//改变遮盖的尺寸self.cover.frame=CGRectMake(self.startP.x,self.startP.y, offsetX, offsetY);    }else if(pan.state==UIGestureRecognizerStateEnded){//松开//做裁剪

//开启一个上下文.(跟图片一样大的上下文.)UIGraphicsBeginImageContextWithOptions(self.imageV.bounds.size,NO,0);

//在上下文当中设置一个裁剪区域(就是当前遮盖的frame)UIBezierPath*path = [UIBezierPathbezierPathWithRect:self.cover.frame];

//设置裁剪区域[path addClip];//把UIImageView当中的图片绘制到上下文当中.

//获取当前上下文CGContextRefctx =UIGraphicsGetCurrentContext();      [self.imageV.layerrenderInContext:ctx];

//生成一张新的图片.UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

//把位图上下文关闭掉UIGraphicsEndImageContext();

//把UIImageView当中的图片重新赋值self.imageV.image= newImage;//移除遮盖[self.coverremoveFromSuperview];    }}

手势解锁

分析界面有几个控件:背景:UIImageView 白色圆圈:按钮(点击他,会出现另外一种图片,按钮可以设置不同状态下的图片。)单独视图:(画线是有范围的,当超出view就不能画线了)

HMLoadView:自定义视图,在视图一创建的时候,就添加9个按钮。

在initWithCoder,initWithFrame方法添加按钮。

九宫格布局:

tolcol =3计算row,col 按钮的x,y跟col,row有关系,col = i % tolcol row = i / tolcol  计算边距 margin = (view.bounds.size.width- tolcol * btnW) / (tolcol 1)  btnX = margin (btnW margin) * col  btnY = (btnW margin) * row

圆的选中

点击按钮就为选中的图片怎么做?监听按钮点击。

不能addTarget: 不能及时显示选中图片。

监听touchBegin,判断点在不在按钮的frame上。

touchBegin不调用?原因:事件交给按钮处理,应该把事件交给解锁视图。让按钮不接收事件。

设置按钮不允许交互,2个用处:1.不接收事件 2.取消高亮效果 一举两得

遍历所有按钮,看触摸点在哪个按钮上,就选中谁,CGRectContainsPoint 传入的参数必须是同一个坐标系

实现touchMove方法:因为手指移动的时候,也需要判断点在不在按钮上。

抽方法,因为touchMove的方法里,也需要做同样的事情。

1>pointWithTouches根据touches集合取出触摸点2>buttonWithPoint根据触摸点,获取触摸按钮

圆的连线

被选中按钮之间都需要连线,还有一个多余的线

先把选中的按钮全部连线,因为多余的那根线是从最后一个按钮的圆心开始画,手指移动在哪就画哪。

搞个数组保存下所有选中按钮,在drawRect方法中遍历所有按钮,连线

UIBezierPath画线,不需要上下文。

需要多少个UIBezierPath对象?一个,路径都是连续的,不相连的,才需要创建新的UIBezierPath。

遍历数组,描述路径 1> 起点:第一个按钮的圆心 2> 添加一根线到其他按钮的圆心

设置路径的颜色和线宽

把所有路径都描述完就,渲染一次就够了。

[path stroke] 就能渲染到视图上了。

画多余的那根线,记住手指移动的位置。

setNeedDisplay 因为drawRect只会调用一次,需要每次手指移动的时候,都需要重绘。

touchBegin不调用setNeedDisplay,因为重绘也没用,只有起点。

lineJoinStyle:有尖尖的东西,线段连接样式的问题,设置为平的。

已经选中的按钮,不需要再次选中,和画线

手指抬起,取消所有选中按钮,并且清空数组,清空线条

drawRect判断下没有选中数组,不需要画线。

如何判断用户是否输入正确?给选中按钮绑定tag,遍历所有选中按钮,把tag拼接成一个字符串。

画板

分析控件:ToolBar(不需要管里面子控件的frame),画板view,自定义工具条(方便屏幕适配,能迅速固定里面子控件的位置)

自动布局,四个约束确定一个控件

蓝色按钮:左,右,下,高固定

橘色按钮:右,下固定,宽度和高度和蓝色按钮相等。

绿色按钮:右,下,宽度和高度和橘色按钮相等

绘图思路:先描述路径,在渲染,需要画很多线条,最好每个线条保存到一个路径里面。

绘图功能

touchBegin设置画线起点:开始触摸的点

创建UIBezierPath,贝塞尔路径才能设置起点

touchMove:手指移动到哪就画哪,addLine到移动的点

setNeedDisplay,路径描述完了,就渲染到视图就好了。

drawRect方法每次都会把之前的清掉,重新绘制

搞个数组保存上一次的,绘制多条线

设置线宽:每次滑动滑块,就改变下一次路径的宽度

监听滑块的值,把值传递给paintView,设置路径的线宽。

不能在drawRect写,会导致所有路径都是一个线宽,应该是每个路径都记录自己的线宽,而且线宽只需要设置一次,在路径一创建的时候就设置。

设置颜色:

自定义UIBezierPath,保存颜色,实现一条路径对应一个颜色 辅助功能:

清屏:清空所有路径数组

撤销:移除最后一条路径

橡皮擦:设置画笔为白色

保存:

1> 把画板内容截屏

2> 把图片保存到相册 UIImageWriteToSavedPhotosAlbum

3> 保存相册的回调方法不能乱写,必须按照规定 image:didFinishSavingWithError:contextInfo:

照片选择

1> 通常都是去相册里去照片

2> UIImagePickerController,就可以去手机相册了

3> 用Modal,没有导航控制器,不能push

4> 设置代理,获取图片

5> 把图片传递给paintView

6> 添加到路径,然后重绘。:画图片也需要顺序的

照片处理

1>搞一个和画板一样的透明view,里面搞个UIImageView来显示我们从照片库选择的图片,然后对UIImageView进行旋转,缩放等操作

2> UImageView不能放在layoutSubViews里面设置尺寸,因为要设置他的形变,默认会调用他父类的layoutSubViews,导致一些莫名其妙的原因

3> 在传图片的时候设置他的尺寸,和位置,让他和图片一样的尺寸,显示在中间

4> 长按操作:在长按结束的时候,做操作

1.默认高亮状态,先变浅在恢复,设置alpha

2.动画结束后,把自己截屏,传给控制器里,在交给paintView显示

3.需要移除父视图,使命完成了,而且不移除,不能绘制东西,永远添加到paintView上面

3、截屏或者截取某个view视图

/** 截屏或者截取某个view视图 @param captureView 要截取的view视图 @return 返回截图 */  (UIImage *)imageWithCaptureView:captureView{ //开启位图上下文 UIGraphicsBeginImageContextWithOptions(captureView.bounds.size, NO, 0); //获取上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); //把控件上的图层渲染到上下文 [captureView.layer renderInContext:ctx]; UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext(); //关闭上下文 UIGraphicsEndImageContext(); return screenImage; }

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

  (UIImage *)createImageColor:(UIColor *)color size: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;}

图片擦除

  • 需要用到手势操作
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];

    [self.view addGestureRecognizer:pan];
}
  • pan方法根据用户手指的位置进行图片擦除
- (void)pan:(UIPanGestureRecognizer *)pan
{
    // 获取当前点
    CGPoint curP = [pan locationInView:self.view];

    // 获取擦除的矩形范围
    CGFloat wh = 100;
    CGFloat x = curP.x - wh * 0.5;
    CGFloat y = curP.y - wh * 0.5;

    CGRect rect = CGRectMake(x, y, wh, wh);

    // 开启上下文
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 控件的layer渲染上去
    [_imageView.layer renderInContext:ctx];

    // 擦除图片
    CGContextClearRect(ctx, rect);

    // 生成一张图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    _imageView.image = image;

    // 关闭上下文
    UIGraphicsEndImageContext();

}

4、根据颜色生成图片

/** 根据颜色生成图片 @param color 颜色 @param size 图片的尺寸 @return 返回生成的图片 */  (UIImage *)imageWithColor:(UIColor *)color size:size{ CGRect rect = CGRectMake(0, 0, size.width, size.height); //开启位图上下文 UIGraphicsBeginImageContext(rect.size); //获取上下文 CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context,color.CGColor); CGContextFillRect(context, rect); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //关闭上下文 UIGraphicsEndImageContext(); return image;}

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

 这里我使用了drawInRect有兴趣的可以使用drowAtPoint,看看效果

  (UIImage *)scaleImage:(UIImage *)image sclae: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;}

手势解锁的界面布局

  • 首先,在awakeFromNib中创建9个按钮对象
// 加载完xib的时候调用
- (void)awakeFromNib
{
    // 创建9个按钮
    for ( int i = 0; i < 9; i  ) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];

        [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];

        [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];

        [self addSubview:btn];
    }
}
  • 然后,在layoutSubviews方法中对创建的按钮对象进行布局操作
// 为什么要在这个方法布局子控件,因为只要一调用这个方法,就表示父控件的尺寸确定
- (void)layoutSubviews
{
    [super layoutSubviews];

    NSUInteger count = self.subviews.count;
    int cols = 3;
    CGFloat x = 0;
    CGFloat y = 0;
    CGFloat w = 74;
    CGFloat h = 74;
    CGFloat margin = (self.bounds.size.width - cols * w) / (cols   1);

    CGFloat col = 0;
    CGFloat row = 0;
    for (NSUInteger i = 0; i < count; i  ) {
        UIButton *btn = self.subviews[i];
        // 获取当前按钮的列数
        col = i % cols;
        row = i / cols;
        x = margin   col * (margin   w);
        y = row * (margin   w);

        btn.frame = CGRectMake(x, y, w, h);

    }

}

5、图片的等比例缩放

/** 图片的等比例缩放 @param image 图片 @param defineWidth 要缩放到的宽度 @return 返回与原图片等宽高比的图片 */  (UIImage *)imageWithOriginImage:(UIImage *)image scaleToWidth:defineWidth{ CGSize imageSize = image.size; CGFloat width = imageSize.width; CGFloat height = imageSize.height; CGFloat targetWidth = defineWidth; CGFloat targetHeight = height / (width / targetWidth); CGSize size = CGSizeMake(targetWidth, targetHeight); UIGraphicsBeginImageContext; //size 为CGSize类型,即你所需要的图片尺寸 [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage;}

3.绘制水印

手势解锁的业务逻辑实现

  • 使用可变数组来存储已经选中的按钮
@property (nonatomic, strong) NSMutableArray *selectedsBtn;

// 重写get方法,对数组进行懒加载
- (NSMutableArray *)selectedsBtn
{
    if (_selectedsBtn == nil) {
        _selectedsBtn = [NSMutableArray array];
    }

    return _selectedsBtn;
}
  • 重写pan方法,对用户的手势进行判断,首先判断触摸点是否在按钮上,然后当用户手指离开屏幕时还原界面
- (IBAction)pan:(UIPanGestureRecognizer *)pan
{
    // 获取触摸点
    _curP = [pan locationInView:self];

    // 判断触摸点在不在按钮上
    for (UIButton *btn in self.subviews) {
        // 点在不在某个范围内,并且按钮没有被选中
        if (CGRectContainsPoint(btn.frame, _curP) && btn.selected == NO) {
            // 点在按钮上
            btn.selected = YES;

            // 保存到数组中
            [self.selectedsBtn addObject:btn];

        }

    }

    // 重绘
    [self setNeedsDisplay];


    if (pan.state == UIGestureRecognizerStateEnded) {

        // 创建可变字符串
        NSMutableString *strM = [NSMutableString string];
         // 保存输入密码
        for (UIButton *btn in self.selectedsBtn) {

            [strM appendFormat:@"%ld",btn.tag];

        }
        NSLog(@"%@",strM);

        // 还原界面

        // 取消所有按钮的选中
        [self.selectedsBtn makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];

        // 清除画线,把选中按钮清空
        [self.selectedsBtn removeAllObjects];
    }

}
  • 根据被选中按钮的数组,对界面进行重绘操作
// 只要调用这个方法,就会把之前绘制的东西全部清掉,重新绘制
- (void)drawRect:(CGRect)rect
{
    // 没有选中按钮,不需要连线
    if (self.selectedsBtn.count == 0) return;

    // 把所有选中按钮中心点连线
    UIBezierPath *path = [UIBezierPath bezierPath];

    NSUInteger count = self.selectedsBtn.count;
    // 把所有选中按钮之间都连好线
    for (int i = 0; i < count; i  ) {
        UIButton *btn = self.selectedsBtn[i];
        if (i == 0) {
            // 设置起点
            [path moveToPoint:btn.center];
        }else{
            [path addLineToPoint:btn.center];
        }

    }

    // 连线到手指的触摸点
    [path addLineToPoint:_curP];

    [[UIColor greenColor] set];
    path.lineWidth = 10;
    path.lineJoinStyle = kCGLineJoinRound;
    [path stroke];

}

6、图片的自由拉伸

 /** 根据图片名返回一张能够自由拉伸的图片 @param name 图片名 @param width 自由拉伸的宽度 @param height 自由拉伸的高度 @return 返回图片 */  (UIImage *)imageWithResizedImage:(NSString *)name capWidth:width capHeight:height{ UIImage *image = [UIImage imageNamed:name]; return [image stretchableImageWithLeftCapWidth:width topCapHeight:height];}
文字水印

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

  (UIImage *)waterAtImage:(UIImage *)image text:(NSString *)text point: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;}

画板

  • 根据数组中数据的类型,绘制图片和线条
// 绘制图形
// 只要调用drawRect方法就会把之前的内容全部清空
- (void)drawRect:(CGRect)rect
{
    for (DrawPath *path in self.paths) {

        if ([path isKindOfClass:[UIImage class]]) {
            // 绘制图片
            UIImage *image = (UIImage *)path;

            [image drawInRect:rect];
        }else{

            // 画线
            [path.pathColor set];

            [path stroke];
        }

    }
}
  • 选择照片,并实现代理方法,将选中的照片绘制到画板上
#pragma mark - 选择照片
- (IBAction)pickerPhoto:(id)sender {
    // 弹出系统的相册
    // 选择控制器(系统相册)
    UIImagePickerController *picekerVc = [[UIImagePickerController alloc] init];

    // 设置选择控制器的来源
    // UIImagePickerControllerSourceTypePhotoLibrary 相册集
    // UIImagePickerControllerSourceTypeSavedPhotosAlbum:照片库
    picekerVc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;

    // 设置代理
    picekerVc.delegate = self;

    // modal
    [self presentViewController:picekerVc animated:YES completion:nil];

}

#pragma mark - UIImagePickerControllerDelegate
// 当用户选择一张图片的时候调用
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // 获取选中的照片
    UIImage *image = info[UIImagePickerControllerOriginalImage];

    // 把选中的照片画到画板上

    _drawView.image = image;

    // dismiss
    [self dismissViewControllerAnimated:YES completion:nil];
}
  • 保存修改后的照片,相当于截屏操作
#pragma mark - 保存
- (IBAction)save:(id)sender {

    // 截屏
    // 开启上下文
    UIGraphicsBeginImageContextWithOptions(_drawView.bounds.size, NO, 0);

    // 获取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // 渲染图层
    [_drawView.layer renderInContext:ctx];

    // 获取上下文中的图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    // 关闭上下文
    UIGraphicsEndImageContext();

    // 保存画板的内容放入相册
    // image:写入的图片
    // completionTarget图片保存监听者
    // 注意:以后写入相册方法中,想要监听图片有没有保存完成,保存完成的方法不能随意乱写
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

}

// 监听保存完成,必须实现这个方法
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
     NSLog(@"保存图片成功");
}
图片水印
  (UIImage *)waterAtImage:(UIImage *)image waterImgae:(UIImage *)waterImage rect: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的操作

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

5.擦除

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

  (UIImage *)wipeView:view point:point size: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;}

澳门新濠3559 1擦除

6.图片裁剪

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

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

  (UIImage *)cutImage:(UIImage *)image imageViewSize:size clipRect: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.计算出自定义点所在的区域rect3.开始图形上下文,rect.size4.绘制path,机型剪裁5.绘图drawAtPoint,x:

  • rect.origin.x y: - rect.origin.y6.从图形上下文获取图片7.关闭图形上下文

    • (UIImage )cutImage:(UIImage )image imageViewSize: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 { [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;}

澳门新濠3559 2cutImage

编辑:编程 本文来源:澳门新濠3559、添加图片水印,图片擦除

关键词: 澳门新濠3559