iOS实现动态区域裁剪图片--支持旋转、缩放、拖动手势

不多说,先上图:

裁剪图片.gif

源代码仓库
https://github.com/julyNineteen/DBCropImage

一个专门裁剪图片轻量级的轮子,简单易用,功能丰富(高自由度的参数设定、支持旋转和缩放、拖动),能满足绝大部分裁剪的需求。源代码公开,具体详细实现逻辑参数都在里面。非常支持自定义。
目前功能:
✅ 支持任意角度360度的旋转;
✅ 高自由度的参数设定,包括裁剪区域颜色大小、裁剪宽高比等;
✅支持固定或者可移动的裁剪框
✅ 支持固定或者可移动的裁剪框
✅ 裁剪算法公开,轻量级,非常适合自定义为适合自己的项目

使用非常简单,一个初始化方法搞定

       DBCropImageController *vc = [[DBCropImageController alloc] init];
        vc.lineColor = UIColor.whiteColor;//裁剪框线条眼色
        vc.isShowShaw = true;               //裁剪框线条是否显示阴影
        vc.lineWidth = 2;                        //裁剪框线条的宽度
        vc.isFixCropArea = false;       //是否固定裁剪框
        vc.widthHeightRate = 3/4.0;//设置宽高比例
        vc.cropAreaHeight = 50;      //设置最小裁剪高度
        vc.image = image;                 //传入裁剪图片
       //裁剪图片回调
        vc.clippedBlock = ^(UIImage * _Nonnull clippedImage) {
            CupedResultVC *ResultVC = [[CupedResultVC alloc] init];
            ResultVC.resultImage = clippedImage;
            ResultVC.modalPresentationStyle = 0;
            [self presentViewController:ResultVC animated:YES completion:nil];
        };
       //取消裁剪
        vc.cancelClipBlock = ^{
            [self dismissViewControllerAnimated:YES completion:nil];
        };
        vc.modalPresentationStyle = 0;
        [self presentViewController:vc animated:YES completion:nil];

核心裁剪逻辑实现在这里,代码注释非常详细,适合对图片裁剪领域的学习。

//操作UIKit上下文的操作方式是线程安全的,但你似乎无法在一个线程之外创建一个除了主程序,因为UIGraphicsBeginImageContextWithOptions“应该只在主程序中调用线程“,但仍然这样做的工作是完美的
- (UIImage *)clipImageWithSoucreImageView:(UIImageView *)imageView{
    
    CGRect foreCropRect = self.willCropRect;
    
    CGRect soucreRect = imageView.frame;
    
    UIImage *soucreImage = imageView.image;
    
    //缩放比例
    float zoomScale = [[imageView.layer valueForKeyPath:@"transform.scale.x"] floatValue];
   
    //计算 要裁剪图片的大小
    CGSize cropSize = CGSizeMake((foreCropRect.size.width)/zoomScale, (foreCropRect.size.height)/zoomScale);
    //计算 裁剪图片的原点
    CGPoint cropViewOrigin = CGPointMake((foreCropRect.origin.x - soucreRect.origin.x)/zoomScale,
                                            (foreCropRect.origin.y - soucreRect.origin.y)/zoomScale);
    
    //向上取整
    if((NSInteger)cropSize.width % 2 == 1)
    {
        cropSize.width = ceil(cropSize.width);
    }
    if((NSInteger)cropSize.height % 2 == 1)
    {
        cropSize.height = ceil(cropSize.height);
    }
    
    float _imageScale = soucreImage.size.width / self.cropAreaWidth;
    CGFloat imgRate = KScreenWidth/self.cropAreaWidth;
    //修正偏移量 得到最终的
    CGRect CropImageRect = CGRectMake((NSInteger)(cropViewOrigin.x)*_imageScale/imgRate ,(NSInteger)( cropViewOrigin.y)*_imageScale/imgRate, (NSInteger)(cropSize.width)*_imageScale/imgRate,(NSInteger)(cropSize.height)*_imageScale/imgRate);
   
    //旋转的角度 获取绕z轴 旋转的角度 -- 也就是当前平面旋转的角度
    float rotate = [[imageView.layer valueForKeyPath:@"transform.rotation.z"] floatValue];
    NSLog(@"旋转角度 == %f",rotate * 180/M_PI );
    //根据旋转的角度得到新的图片
    UIImage *rotInputImage = [soucreImage imageRotatedByRadians:rotate];
    
    CGImageRef tmp = CGImageCreateWithImageInRect([rotInputImage CGImage], CropImageRect);
    
    UIImage *resultImage = [UIImage imageWithCGImage:tmp scale:soucreImage.scale orientation:soucreImage.imageOrientation];
    
    if (!resultImage) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"您剪切的区域无效,请重新剪切" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
        [alert show];
        return nil;
    }
    
    CGRect imageRect = CGRectZero;
    imageRect.size = resultImage.size;
    
    UIBezierPath *cropedPath;
    //设置为YES 不透明,节省性能
    UIGraphicsBeginImageContextWithOptions(imageRect.size, YES,1);
    {
        //[[UIColor blackColor] setFill];
        UIRectFill(imageRect);
        [[UIColor whiteColor] setFill];
        //修改
        cropedPath = [UIBezierPath bezierPathWithRect:imageRect];
        [cropedPath fill];
    }
    UIImage *maskImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    //设置为YES 不透明,节省性能
    //1 裁剪尺寸原比例 设置为0或者UIScreen.mainScreen.scale 或随屏幕分辨率放大尺寸
    UIGraphicsBeginImageContextWithOptions(imageRect.size,YES,1);
    {
        CGContextClipToMask(UIGraphicsGetCurrentContext(), imageRect, maskImage.CGImage);
        [resultImage drawAtPoint:CGPointZero];
    }
    UIImage *maskResultImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return maskResultImage;
    
}

参考链接:
https://www.jianshu.com/p/73043c1d869a

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容