美文网首页iOS 深度好文
IOS获取相册图片,并通过空心圆遮罩剪裁

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

作者: xiaoming12 | 来源:发表于2020-04-23 16:51 被阅读0次

    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开发-自定义裁剪框并保存在相册

    相关文章

      网友评论

        本文标题:IOS获取相册图片,并通过空心圆遮罩剪裁

        本文链接:https://www.haomeiwen.com/subject/ehxaihtx.html