iOS 深度好文

IOS获取相册图片,并通过空心圆遮罩剪裁

2020-04-23  本文已影响0人  xiaoming12

IOS开发获取相册图片,并给图片编辑页面加上空心圆遮罩

先放效果图

IMG_1953.png

1、获取图片,使用UIImagePickerController,sourcetype图片来源(UIImagePickerControllerSourceTypePhotoLibrary图库包含一些自己添加的图片,UIImagePickerControllerSourceTypeCamera相机,UIImagePickerControllerSourceTypeSavedPhotosAlbum相册)。

  UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
     imagePickerController.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
//     imagePickerController.allowsEditing = true; 如果为true,会跳转到系统给的编辑页面,这里我们选择自定义编辑页面
     imagePickerController.delegate = self;
     [self presentViewController:imagePickerController animated:true completion:nil];

选取完图片后在imagePickerController的代理方法里面收到回调信息,图片的信息都保存在返回的info字典里面。
其中UIImagePickerControllerOriginalImage关键字表示原图,UIImagePickerControllerReferenceURL表示原图的URL,可以通过Photos/Photos.h库中的PHAsset实例获取。

//选取图片后的代理回调
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
    UIImage *originImage = info[@"UIImagePickerControllerOriginalImage"];
    NSLog(@"info=%@",info);
   //跳转自定义编辑页面
    ImagePickerCropViewController *vc = [[ImagePickerCropViewController alloc] init];
    vc.originImage = originImage;
    [picker pushViewController:vc animated:true];
    [vc maskCircleImage:^(UIImage *image) {
        NSLog(@"获取到编辑后的图片");
    }];
   // 或者是通过Photos/Photos.h库PHAsset获取
  //NSURL *imageAssetUrl = [info     objectForKey:UIImagePickerControllerReferenceURL];
//    PHFetchResult*result = [PHAsset   fetchAssetsWithALAssetURLs:@[imageAssetUrl] options:nil];
//    PHAsset *asset = [result firstObject];
//    PHImageRequestOptions *phImageRequestOptions =   [[PHImageRequestOptions alloc] init];
//    [[PHImageManager defaultManager] requestImageDataForAsset:asset   options:phImageRequestOptions resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
//        //imageData
//    }];

这样图片获取完成.
2、自定义编辑页面缩放图片,拿到图片后缩放,让图片的宽高最小值刚好等于中间的空心圆直径大小

 //缩放比例,把宽和高的最小值缩放到圆的直径大小,让图片看起来在圆内
    CGFloat scale = 1.0f;
    CGFloat minFloat = self.originImage.size.width<self.originImage.size.height?self.originImage.size.width:self.originImage.size.height;
    scale = minFloat/(CircleRadius*2);
    self.cropImageView.frame = CGRectMake(0, 0, self.originImage.size.width/scale, self.originImage.size.height/scale);

然后将图片放在scrollview里面,利用scrollview的缩放功能进行缩放,记得让图片居于scrollview的contentsize可滑动范围的中间, 然后设置scrollview的contentofset偏移,让图片居于self.view的中间

//创建scroll用于缩放和滑动查看图片
    UIScrollView *scroll = [[UIScrollView alloc]initWithFrame:frame];
    scroll.bounces = YES;
    
    //滑动范围就是scrollview的大小加上图片比圆多出来的部分
    CGFloat contentSizeWidth = scroll.frame.size.width+(_cropImageView.frame.size.width-CircleRadius*2);
    CGFloat contentSizeHeight = scroll.frame.size.height+(_cropImageView.frame.size.height-CircleRadius*2);
    
    //设置scrollview的滑动范围
    scroll.contentSize = CGSizeMake(contentSizeWidth,contentSizeHeight);

    //设置图片在scrollview的滑动范围中心显示
    self.cropImageView.center = CGPointMake(scroll.contentSize.width/2.0, scroll.contentSize.height/2.0);
    //设置scrollview的偏移让图片刚好在view的中间
    scroll.contentOffset = CGPointMake((_cropImageView.frame.size.width-CircleRadius*2)/2.0, (_cropImageView.frame.size.height-CircleRadius*2)/2.0);
    scroll.delegate=self;
    
    //设置最大伸缩比例
    scroll.maximumZoomScale=2.0;
   //设置最小伸缩比例
    scroll.minimumZoomScale=1;
    [self.view addSubview:scroll];
    [scroll addSubview:self.cropImageView];

记得在scrollViewDidEndZooming代理方法里面让scrollview的contentsize滑动范围适应图片大小,否则会出现缩放完,scrollview无法滑动的情况。
3、添加遮罩,使用贝塞尔曲线画一个圆形路径,然后将路径添加到layer上面,填充规则选择kCAFillRuleEvenOdd。

填充规则kCAFillRuleEvenOdd,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部,记得计算的时候加上外部的rect边框。
填充规则kCAFillRuleNonZero,从0开始计数,路径顺时针穿过射线则计数加1,逆时针穿过射线则计数减1,
结果为0则是外部,看你绘制路径的时候选择顺时针还是逆时针,计算的时候记得包含rect的边框[UIBezierPath bezierPathWithRect:rect]。

 //
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect];
    
    CGFloat x = rect.size.width/2.0;
    CGFloat y = rect.size.height/2.0;
    CGFloat radius = CircleRadius;
    //用贝塞尔曲线画圆,clockwise选择顺时针
    UIBezierPath *cycle = [UIBezierPath bezierPathWithArcCenter:CGPointMake(x, y)
                                                         radius:radius
                                                     startAngle:0.0
                                                       endAngle:2*M_PI
                                                      clockwise:1];
    //添加圆的路径
    [path appendPath:cycle];
    
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.path = [path CGPath];
    
    /*1、填充规则kCAFillRuleEvenOdd,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部,记得包含rect边框[UIBezierPath bezierPathWithRect:rect]
     2、填充规则 kCAFillRuleNonZero,从0开始计数,路径顺时针穿过射线则计数加1,逆时针穿过射线则计数减1,
     结果为0则是外部,看你绘制路径的时候选择顺时针还是逆时针记得包含rect的边框[UIBezierPath bezierPathWithRect:rect]*/
    maskLayer.fillRule = kCAFillRuleEvenOdd;
    maskLayer.fillColor = [UIColor blackColor].CGColor;
    maskLayer.opacity = .5;//半透明填充

以上就是基本实现,总结一下过程,通过UIImagePickerController设置代理拿到图片或者图片的URL,然后进入到自定义的编辑页面,通过scrollview进行图片的缩放,通过贝塞尔曲线画圆形路径,然后用layer添加路径并填充完成遮罩,记得最后添加layer。

git下载地址

自定义剪裁页面参考:
IOS开发-自定义裁剪框并保存在相册

上一篇下一篇

猜你喜欢

热点阅读