图片处理

头文件


#import <UIKit/UIKit.h>

@class CropImageViewController;

typedef void(^CropedImageCallBack)(UIImage *cropImage,CropImageViewController *viewController);

@interface CropImageViewController : UIViewController
@property (assign, nonatomic) CGSize cropSize;
@property (assign, nonatomic, getter=isFixCropSize) BOOL fixCropSize;
- (instancetype)initWithOriginImage:(UIImage *)originImage callBack:(CropedImageCallBack)callBack;
@end

执行文件


typedef NS_ENUM(NSUInteger, ActionViewTag) {
    OriginViewTag = 111,
    CropViewTag
};

static CGPoint PreviousTapPoint = (CGPoint){0,0};
static CGAffineTransform PreviousAffineTransform = (CGAffineTransform){1,0,0,1,0,0};
static const CGFloat kGenerateButtonHeight = 40;
static const UIEdgeInsets kCropButtonEdgeInsets = (UIEdgeInsets){20,20,30,20};
static const UIEdgeInsets kOriginImageBackgroundViewEdgeInsets = {30,20,20,20};
static const CGSize kCropViewDefaultSize = (CGSize){200,200};
@interface CropImageViewController () <UIGestureRecognizerDelegate>
@property (copy, nonatomic) CropedImageCallBack callBack;
@property (strong, nonatomic) UIImage *originImage;
@property (strong, nonatomic, readonly) UIImage *generateCropImage;
@property (strong, nonatomic) UIView *originImageBoardView;
@property (strong, nonatomic) UIImageView *originImageView;
@property (strong, nonatomic) UIView *cropView;
@property (strong, nonatomic) UIButton *cropButton;
@property (strong, nonatomic) UIButton *cancelButton;
@end

@implementationCropImageViewController

- (instancetype)initWithOriginImage:(UIImage *)originImage callBack:(CropedImageCallBack)callBack {
    assert(originImage && callBack);
    if(self = [super init]) {
        self.callBack = callBack;
        self.originImage = originImage;
    }
    return self;
}

- (instancetype)init {
    NSAssert(0, @"use initWithOriginImage:callBack: instead");
    return nil;
}

#pragma mark bind gesture recognizer

- (void)bindGestureAction {
    UIPinchGestureRecognizer *pinchOriginGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureAction:)];
    UIPanGestureRecognizer *panOriginGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)];
    panOriginGestureRecognizer.maximumNumberOfTouches = 1;
    UIRotationGestureRecognizer *rotationOriginGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationGestureAction:)];
    pinchOriginGestureRecognizer.delegate = panOriginGestureRecognizer.delegate = rotationOriginGestureRecognizer.delegate = self;
    [self.originImageBoardView addGestureRecognizer:pinchOriginGestureRecognizer];
    [self.originImageBoardView addGestureRecognizer:panOriginGestureRecognizer];
    [self.originImageBoardView addGestureRecognizer:rotationOriginGestureRecognizer];
    UIPinchGestureRecognizer *pinchCropGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureAction:)];
    UIPanGestureRecognizer *panCropGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)];
    panOriginGestureRecognizer.maximumNumberOfTouches = 1;
    [self.cropView addGestureRecognizer:panCropGestureRecognizer];
    if(self.isFixCropSize) {
        return;
    }
    [self.cropView addGestureRecognizer:pinchCropGestureRecognizer];
    
}

#pragma mark relayout subviews

- (void)generateSubViews {
    self.view.backgroundColor = [UIColor whiteColor];
    CGRect windowFrame = [[UIScreen mainScreen] bounds];
//    generate origin imageview background view;
    
    self.originImageBoardView = [[UIView alloc] initWithFrame:CGRectMake(kOriginImageBackgroundViewEdgeInsets.left, kOriginImageBackgroundViewEdgeInsets.top, CGRectGetWidth(windowFrame) - (kCropButtonEdgeInsets.left + kCropButtonEdgeInsets.right), CGRectGetHeight(windowFrame) - (kOriginImageBackgroundViewEdgeInsets.top + kOriginImageBackgroundViewEdgeInsets.bottom) - (kGenerateButtonHeight + kCropButtonEdgeInsets.top + kCropButtonEdgeInsets.bottom))];
    self.originImageBoardView.layer.borderColor = [UIColor grayColor].CGColor;
    self.originImageBoardView.layer.borderWidth = .8;

    self.originImageBoardView.tag = OriginViewTag;
    self.originImageBoardView.clipsToBounds = YES;
    [self.view addSubview:self.originImageBoardView];
    
//    generate origin imageview
    
    self.originImageView = [[UIImageView alloc] initWithFrame:self.originImageBoardView.bounds];
    self.originImageView.image = self.originImage;
//    self.originImageView.contentMode = UIViewContentModeCenter;
    [self.originImageBoardView addSubview:self.originImageView];
    
//    generate crop view
    self.cropView = [[UIView alloc] init];
    self.cropView.center = CGPointMake(CGRectGetWidth(self.originImageBoardView.frame) / 2 + kOriginImageBackgroundViewEdgeInsets.left, CGRectGetHeight(self.originImageBoardView.frame) / 2 + kOriginImageBackgroundViewEdgeInsets.top);
    if(CGSizeEqualToSize(self.cropSize, CGSizeZero)) {
        self.cropView.bounds = CGRectMake(0, 0, kCropViewDefaultSize.width, kCropViewDefaultSize.height);
    }
    else {
        self.cropView.bounds = CGRectMake(0, 0, self.cropSize.width, self.cropSize.height);
    }
    self.cropView.tag = CropViewTag;
    self.cropView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:.3];
    [self.view addSubview:self.cropView];
    
//    generate crop button;
    self.cropButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.cropButton.frame = CGRectMake(kCropButtonEdgeInsets.left,CGRectGetMaxY(self.originImageBoardView.frame) + kCropButtonEdgeInsets.top,(CGRectGetWidth(windowFrame) - (kCropButtonEdgeInsets.left * 2 + kCropButtonEdgeInsets.right)) / 2,kGenerateButtonHeight);
    [self.cropButton setTitle:@"截取" forState:UIControlStateNormal];
    [self.cropButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    self.cropButton.backgroundColor = [UIColor orangeColor];
    [self.cropButton addTarget:self action:@selector(cropAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.cropButton];
    CGRect cropButtonFrame = self.cropButton.frame;
    self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
    cropButtonFrame.origin.x = CGRectGetMaxX(cropButtonFrame) + kCropButtonEdgeInsets.left;
    self.cancelButton.frame = cropButtonFrame;
    [self.cancelButton setTitle:@"取消" forState:UIControlStateNormal];
    [self.cancelButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    self.cancelButton.backgroundColor = [UIColor orangeColor];
    [self.cancelButton addTarget:self action:@selector(cancelAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.cancelButton];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self generateSubViews];
    [self bindGestureAction];
}

#pragma mark gesture recognizer action

- (void)pinchGestureAction:(UIPinchGestureRecognizer *)gestureRecognizer {
    
    UIView *gestureView = gestureRecognizer.view;
    if(gestureView.tag == OriginViewTag) {
        gestureView = self.originImageView;
    }
    CGAffineTransform affineTransform = CGAffineTransformScale(gestureView.transform,gestureRecognizer.scale, gestureRecognizer.scale);
    
    gestureView.transform = affineTransform;
    gestureRecognizer.scale = 1;
    if(gestureRecognizer.view.tag == OriginViewTag) {
        return;
    }
    if(!CGRectContainsRect(self.originImageBoardView.frame, gestureView.frame)) {
        gestureView.transform = PreviousAffineTransform;
        return;
    }
    PreviousAffineTransform = gestureView.transform;
}

- (void)panGestureAction:(UIPanGestureRecognizer *)gestureRecognizer {
    UIView *gestureView = gestureRecognizer.view,
    *gestureViewSuperView = gestureView.superview;
    BOOL needPaddingDistance = NO;
    if(gestureView.tag == OriginViewTag) {
        gestureView = self.originImageView;
        needPaddingDistance = NO;
    }
    else if (gestureView.tag == CropViewTag) {
        needPaddingDistance = YES;
        gestureViewSuperView = self.originImageBoardView;
    }
    CGPoint touchPoint = [gestureRecognizer locationInView:gestureView.superview];
    
    if(gestureRecognizer.state == UIGestureRecognizerStateChanged) {
        CGPoint centerPoint = CGPointMake(gestureView.center.x + touchPoint.x - PreviousTapPoint.x, gestureView.center.y + touchPoint.y - PreviousTapPoint.y);
        if(needPaddingDistance) {
            CGFloat w = CGRectGetWidth(gestureView.frame),
            h = CGRectGetHeight(gestureView.frame);
            CGRect tempFrame = CGRectMake(centerPoint.x - w / 2, centerPoint.y - h / 2, w, h);
            if(!CGRectContainsRect(gestureViewSuperView.frame, tempFrame)) {
                return;
            }
        }
        gestureView.center = centerPoint;
    }
    PreviousTapPoint = touchPoint;
    [gestureRecognizer setTranslation:CGPointZero inView:gestureView.superview];
}

- (void)rotationGestureAction:(UIRotationGestureRecognizer *)gestureRecognizer {
    UIView *gestureView = gestureRecognizer.view;
    if(gestureView.tag == OriginViewTag) {
        gestureView = self.originImageView;
    }
    if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        PreviousTapPoint = gestureView.center;
    }
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan || gestureRecognizer.state == UIGestureRecognizerStateChanged) {
        gestureView.transform = CGAffineTransformRotate(gestureView.transform, gestureRecognizer.rotation);
        gestureView.center = PreviousTapPoint;
        [gestureRecognizer setRotation:0];
    }
}

- (UIImage *)generateCropImage {
    UIGraphicsBeginImageContext(self.originImageBoardView.bounds.size); //currentView 当前的view
    [self.originImageBoardView.layer renderInContext:UIGraphicsGetCurrentContext()];
    
    UIImage *originFullImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    CGImageRef imageRef = originFullImage.CGImage;
    CGImageRef imagePartRef = CGImageCreateWithImageInRect(imageRef, self.cropView.frame);
    UIImage *cropImage = [UIImage imageWithCGImage:imagePartRef];
    CGImageRelease(imagePartRef);
    return cropImage;
}

- (void)cancelAction {
    if(self.callBack) {
        self.callBack(nil,self);
    }
}

- (void)cropAction {
    if(self.callBack) {
        self.callBack(self.generateCropImage,self);
    }
}

#pragma mark UIGestureRecognizerDelegate

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}
@end

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

推荐阅读更多精彩内容