头像裁剪功能的实现

UIImage+CTFCrop.h

@interface UIImage (CTFCrop)
- (UIImage *)resizeImageWithSize:(CGSize)newSize;
- (UIImage *)ovalClip;
@end

 

UIImage+CTFCrop.m

@implementation UIImage (CTFCrop)

- (UIImage *)resizeImageWithSize:(CGSize)newSize {
    CGFloat newWidth = newSize.width;
    CGFloat newHeight = newSize.height;
    float width  = self.size.width;
    float height = self.size.height;
    if (width != newWidth || height != newHeight) {
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(newWidth, newHeight), YES, [UIScreen mainScreen].scale);
        [self drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
        
        UIImage *resized = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return resized;
    }
    return self;
}

- (UIImage *)ovalClip {

    CGSize size = self.size;
    UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
    [path addClip];
    [self drawAtPoint:CGPointZero];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}

@end

 

CTFCropImageVC.h

typedef void(^CropedImageBlock)(UIImage *cropedImage);

@protocol CropImageDelegate <NSObject>
- (void)cropImageDidFinishedWithImage:(UIImage *)image;
@end

@interface CTFCropImageVC : BaseViewController
@property (nonatomic, weak) id <CropImageDelegate> delegate;
@property (nonatomic, assign) BOOL ovalClip;//圆形裁剪,默认开启;
- (instancetype)initWithImage:(UIImage *)originalImage delegate:(id)delegate;
@property (nonatomic, copy) CropedImageBlock cropedImageBlock;
@end

 

CTFCropImageVC.m

#import "UIImage+CTFCrop.h"
#import "AppDelegate.h"

@interface CTFCropImageVC () <UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIImage *originalImage;
@end

@implementation CTFCropImageVC

- (instancetype)initWithImage:(UIImage *)originalImage delegate:(id)delegate {
    if (self = [super init]) {
        self.originalImage = originalImage;
        self.delegate = delegate;
        self.ovalClip = YES;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.isHiddenNavBar = YES;
    self.view.backgroundColor = [UIColor blackColor];
    self.automaticallyAdjustsScrollViewInsets = NO;
    
    CGFloat top_height = 168;
    CGFloat width_cropView = kScreen_Width - 39 - 39;
    CGFloat height_cropView = kScreen_Width - 39 - 39;
    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(39, top_height, width_cropView, height_cropView)];
    self.scrollView.bouncesZoom = YES;
    self.scrollView.minimumZoomScale = 1;
    self.scrollView.maximumZoomScale = 3;
    self.scrollView.zoomScale = 1;
    self.scrollView.delegate = self;
    self.scrollView.layer.masksToBounds = NO;
    self.scrollView.showsHorizontalScrollIndicator = NO;
    self.scrollView.showsVerticalScrollIndicator = NO;
    self.scrollView.layer.borderWidth = 1.5;
    self.scrollView.layer.borderColor = [UIColor whiteColor].CGColor;
      if (self.ovalClip) {
        self.scrollView.layer.cornerRadius = width_cropView/2.0;
    }
    
    self.view.layer.masksToBounds = YES;
    if (self.originalImage) {
        self.imageView = [[UIImageView alloc] initWithImage:self.originalImage];
        
        CGFloat img_width = 0.f;
        CGFloat img_height = 0.f;
        CGFloat img_x= 0.f;
        CGFloat img_y= 0.f;
        
        if (self.originalImage.size.height > self.originalImage.size.width) {//高度 大于 宽度
            
            img_width = width_cropView;
            img_height = self.originalImage.size.height * (img_width/self.originalImage.size.width);
            img_x= 0.f;
            img_y= (img_height - height_cropView)/2.0;
            
        }else if (self.originalImage.size.height < self.originalImage.size.width) {//宽度 大于 高度
            
            img_height = height_cropView;
            img_width = self.originalImage.size.width * (img_height/self.originalImage.size.height);
            img_x= (img_width - width_cropView)/2.0;
            img_y= 0.f;
            
        }else {//正方形
            
            img_height = height_cropView;
            img_width = width_cropView;
            img_x= 0.f;
            img_y= 0.f;
        }
        
        self.imageView.frame = CGRectMake(0, 0, img_width, img_height);
        self.imageView.userInteractionEnabled = YES;
        [self.scrollView addSubview:self.imageView];
        self.scrollView.contentSize = CGSizeMake(img_width, img_height);
        self.scrollView.contentOffset = CGPointMake(img_x, img_y);
        [self.view addSubview:self.scrollView];
    }
    [self userInterface];
    
    //
    UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
    [cancelBtn addTarget:self action:@selector(cancelBtnAction) forControlEvents:UIControlEventTouchUpInside];
    [cancelBtn setTitleColor:UIColorFromHEX(0xFFFFFF) forState:UIControlStateNormal];
    cancelBtn.titleLabel.font = [UIFont systemFontOfSize:18];
    cancelBtn.backgroundColor = [UIColor clearColor];
    [self.view addSubview:cancelBtn];
    [cancelBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(self.view.mas_left).offset(76);
        make.bottom.mas_equalTo(self.view.mas_bottom).offset(-36);
    }];
    
    //
    UIButton *sureBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [sureBtn setTitle:@"确定" forState:UIControlStateNormal];
    [sureBtn addTarget:self action:@selector(sureBtnAction) forControlEvents:UIControlEventTouchUpInside];
    [sureBtn setTitleColor:UIColorFromHEX(0xFFFFFF) forState:UIControlStateNormal];
    sureBtn.titleLabel.font = [UIFont systemFontOfSize:18];
    sureBtn.layer.masksToBounds = YES;
    sureBtn.layer.backgroundColor = UIColorFromHEX(0xFF6885).CGColor;
    sureBtn.layer.cornerRadius = 20;
    [self.view addSubview:sureBtn];
    [sureBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.mas_equalTo(self.view.mas_right).offset(-55);
        make.bottom.mas_equalTo(self.view.mas_bottom).offset(-28);
        make.size.mas_equalTo(CGSizeMake(74, 40));
    }];
}

- (void)cancelBtnAction {
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)sureBtnAction {
    UIImage *cropImage = [self cropImage];
    if (self.cropedImageBlock) {
        self.cropedImageBlock(cropImage);
    }
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)userInterface {
    
    CGRect cropframe = self.scrollView.frame;
    UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.view.bounds cornerRadius:0];
    UIBezierPath * cropPath = [UIBezierPath bezierPathWithRoundedRect:cropframe cornerRadius:0];
    if (self.ovalClip) {
        cropPath = [UIBezierPath bezierPathWithOvalInRect:cropframe];
    }
    [path appendPath:cropPath];
    
    CAShapeLayer * layer = [[CAShapeLayer alloc] init];
    layer.fillColor = [UIColor colorWithRed:.0 green:.0 blue:.0 alpha:0.5].CGColor;
    //填充规则
    layer.fillRule = kCAFillRuleEvenOdd;
    layer.path = path.CGPath;
    [self.view.layer addSublayer:layer];
}

#pragma mark -- UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return self.imageView;
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    //调整位置
    [self centerContent];
}

- (void)centerContent {
    
    CGRect imageViewFrame = self.imageView.frame;
    
    CGRect scrollBounds = CGRectMake(0, 0, kScreen_Width - 39 - 39, kScreen_Width - 39 - 39);
    if (imageViewFrame.size.height > scrollBounds.size.height) {
        imageViewFrame.origin.y = 0.0f;
    }else {
        imageViewFrame.origin.y = (scrollBounds.size.height - imageViewFrame.size.height) / 2.0;
    }
    if (imageViewFrame.size.width < scrollBounds.size.width) {
        imageViewFrame.origin.x = (scrollBounds.size.width - imageViewFrame.size.width) /2.0;
    }else {
        imageViewFrame.origin.x = 0.0f;
    }
    self.imageView.frame = imageViewFrame;
}

- (UIImage *)cropImage {
    
    CGPoint offset = self.scrollView.contentOffset;
    CGFloat zoom = self.imageView.frame.size.width / self.originalImage.size.width;
    CGFloat width_scroll = self.scrollView.frame.size.width;
    CGFloat height_scroll = self.scrollView.frame.size.height;
    
    CGRect rec = CGRectMake(fabs(offset.x)/zoom, fabs(offset.y)/zoom, width_scroll/zoom, height_scroll/zoom);
    
    UIImage * image = [self cropImage:self.originalImage toRect:rec];
    
    return image;
}

- (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect {

    CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) {
        return deg / 180.0f * (CGFloat) M_PI;
    };

    CGAffineTransform rectTransform;
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
            break;
        case UIImageOrientationRight:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
            break;
        case UIImageOrientationDown:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
            break;
        default:
            rectTransform = CGAffineTransformIdentity;
    };

    // adjust the transformation scale based on the image scale
    rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);
    // apply the transformation to the rect to create a new, shifted rect
    CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform);
    // use the rect to crop the image
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare);
    // create a new UIImage and set the scale and orientation appropriately
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
    // memory cleanup
    CGImageRelease(imageRef);
    
    return result;
}

@end

 

上一篇:UIView设置背景色值


下一篇:2020 — iOS 面试败北感悟