// // VPImageCropperViewController.m // VPolor // // Created by Vinson.D.Warm on 12/30/13. // Copyright (c) 2013 Huang Vinson. All rights reserved. // #import "VPImageCropperViewController.h" #define SCALE_FRAME_Y 100.0f #define BOUNDCE_DURATION 0.3f @interface VPImageCropperViewController () @property (nonatomic, retain) UIImage *originalImage; @property (nonatomic, retain) UIImage *editedImage; @property (nonatomic, retain) UIImageView *showImgView; @property (nonatomic, retain) UIView *overlayView; @property (nonatomic, retain) UIView *ratioView; @property (nonatomic, assign) CGRect oldFrame; @property (nonatomic, assign) CGRect largeFrame; @property (nonatomic, assign) CGFloat limitRatio; @property (nonatomic, assign) CGRect latestFrame; @end @implementation VPImageCropperViewController - (void)dealloc { self.originalImage = nil; self.showImgView = nil; self.editedImage = nil; self.overlayView = nil; self.ratioView = nil; } - (id)initWithImage:(UIImage *)originalImage cropFrame:(CGRect)cropFrame limitScaleRatio:(NSInteger)limitRatio { self = [super init]; if (self) { self.cropFrame = cropFrame; self.limitRatio = limitRatio; self.originalImage = [self fixOrientation:originalImage]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.navigationController.delegate = self; [self initView]; [self initControlBtn]; } - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { // 判断要显示的控制器是否是自己 BOOL isShowHomePage = [viewController isKindOfClass:[self class]]; [self.navigationController setNavigationBarHidden:isShowHomePage animated:YES]; } - (BOOL)prefersStatusBarHidden { return YES; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return NO; } - (void)initView { self.view.backgroundColor = [UIColor blackColor]; self.showImgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; [self.showImgView setMultipleTouchEnabled:YES]; [self.showImgView setUserInteractionEnabled:YES]; [self.showImgView setImage:self.originalImage]; [self.showImgView setUserInteractionEnabled:YES]; [self.showImgView setMultipleTouchEnabled:YES]; // scale to fit the screen CGFloat oriWidth = self.cropFrame.size.width; CGFloat oriHeight = self.originalImage.size.height * (oriWidth / self.originalImage.size.width); CGFloat oriX = self.cropFrame.origin.x + (self.cropFrame.size.width - oriWidth) / 2; CGFloat oriY = self.cropFrame.origin.y + (self.cropFrame.size.height - oriHeight) / 2; self.oldFrame = CGRectMake(oriX, oriY, oriWidth, oriHeight); self.latestFrame = self.oldFrame; self.showImgView.frame = self.oldFrame; self.largeFrame = CGRectMake(0, 0, self.limitRatio * self.oldFrame.size.width, self.limitRatio * self.oldFrame.size.height); [self addGestureRecognizers]; [self.view addSubview:self.showImgView]; self.overlayView = [[UIView alloc] initWithFrame:self.view.bounds]; self.overlayView.alpha = .5f; self.overlayView.backgroundColor = [UIColor blackColor]; self.overlayView.userInteractionEnabled = NO; self.overlayView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [self.view addSubview:self.overlayView]; self.ratioView = [[UIView alloc] initWithFrame:self.cropFrame]; self.ratioView.layer.borderColor = [UIColor yellowColor].CGColor; self.ratioView.layer.borderWidth = 1.0f; self.ratioView.autoresizingMask = UIViewAutoresizingNone; [self.view addSubview:self.ratioView]; [self overlayClipping]; } - (void)initControlBtn { UIButton *cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 50.0f, self.view.frame.size.width / 2, 50)]; cancelBtn.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7]; cancelBtn.titleLabel.textColor = [UIColor whiteColor]; [cancelBtn setTitle:@"取消" forState:UIControlStateNormal]; [cancelBtn.titleLabel setFont:[UIFont boldSystemFontOfSize:18.0f]]; [cancelBtn.titleLabel setTextAlignment:NSTextAlignmentCenter]; [cancelBtn.titleLabel setLineBreakMode:NSLineBreakByWordWrapping]; [cancelBtn.titleLabel setNumberOfLines:0]; [cancelBtn setTitleEdgeInsets:UIEdgeInsetsMake(5.0f, 5.0f, 5.0f, 5.0f)]; [cancelBtn addTarget:self action:@selector(cancel:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:cancelBtn]; UIButton *confirmBtn = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width / 2, self.view.frame.size.height - 50.0f, self.view.frame.size.width / 2, 50)]; confirmBtn.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7]; confirmBtn.titleLabel.textColor = [UIColor whiteColor]; [confirmBtn setTitle:@"完成" forState:UIControlStateNormal]; [confirmBtn.titleLabel setFont:[UIFont boldSystemFontOfSize:18.0f]]; [confirmBtn.titleLabel setTextAlignment:NSTextAlignmentCenter]; confirmBtn.titleLabel.textColor = [UIColor whiteColor]; [confirmBtn.titleLabel setLineBreakMode:NSLineBreakByWordWrapping]; [confirmBtn.titleLabel setNumberOfLines:0]; [confirmBtn setTitleEdgeInsets:UIEdgeInsetsMake(5.0f, 5.0f, 5.0f, 5.0f)]; [confirmBtn addTarget:self action:@selector(confirm:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:confirmBtn]; } - (void)cancel:(id)sender { if (self.delegate && [self.delegate conformsToProtocol:@protocol(VPImageCropperDelegate)]) { [self.delegate imageCropperDidCancel:self]; } } - (void)confirm:(id)sender { if (self.delegate && [self.delegate conformsToProtocol:@protocol(VPImageCropperDelegate)]) { [self.delegate imageCropper:self didFinished:[self getSubImage]]; } } - (void)overlayClipping { CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; CGMutablePathRef path = CGPathCreateMutable(); // Left side of the ratio view CGPathAddRect(path, nil, CGRectMake(0, 0, self.ratioView.frame.origin.x, self.overlayView.frame.size.height)); // Right side of the ratio view CGPathAddRect(path, nil, CGRectMake( self.ratioView.frame.origin.x + self.ratioView.frame.size.width, 0, self.overlayView.frame.size.width - self.ratioView.frame.origin.x - self.ratioView.frame.size.width, self.overlayView.frame.size.height)); // Top side of the ratio view CGPathAddRect(path, nil, CGRectMake(0, 0, self.overlayView.frame.size.width, self.ratioView.frame.origin.y)); // Bottom side of the ratio view CGPathAddRect(path, nil, CGRectMake(0, self.ratioView.frame.origin.y + self.ratioView.frame.size.height, self.overlayView.frame.size.width, self.overlayView.frame.size.height - self.ratioView.frame.origin.y + self.ratioView.frame.size.height)); // UIBezierPath *path1 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.overlayView.frame.size.width, self.overlayView.frame.size.width)]; // maskLayer.path = path1.CGPath; maskLayer.path = path; self.overlayView.layer.mask = maskLayer; CGPathRelease(path); } // register all gestures - (void) addGestureRecognizers { // add pinch gesture UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchView:)]; [self.view addGestureRecognizer:pinchGestureRecognizer]; // add pan gesture UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panView:)]; [self.view addGestureRecognizer:panGestureRecognizer]; } // pinch gesture handler - (void) pinchView:(UIPinchGestureRecognizer *)pinchGestureRecognizer { UIView *view = self.showImgView; if (pinchGestureRecognizer.state == UIGestureRecognizerStateBegan || pinchGestureRecognizer.state == UIGestureRecognizerStateChanged) { view.transform = CGAffineTransformScale(view.transform, pinchGestureRecognizer.scale, pinchGestureRecognizer.scale); pinchGestureRecognizer.scale = 1; } else if (pinchGestureRecognizer.state == UIGestureRecognizerStateEnded) { CGRect newFrame = self.showImgView.frame; newFrame = [self handleScaleOverflow:newFrame]; newFrame = [self handleBorderOverflow:newFrame]; [UIView animateWithDuration:BOUNDCE_DURATION animations:^{ self.showImgView.frame = newFrame; self.latestFrame = newFrame; }]; } } // pan gesture handler - (void) panView:(UIPanGestureRecognizer *)panGestureRecognizer { UIView *view = self.showImgView; if (panGestureRecognizer.state == UIGestureRecognizerStateBegan || panGestureRecognizer.state == UIGestureRecognizerStateChanged) { // calculate accelerator CGFloat absCenterX = self.cropFrame.origin.x + self.cropFrame.size.width / 2; CGFloat absCenterY = self.cropFrame.origin.y + self.cropFrame.size.height / 2; CGFloat scaleRatio = self.showImgView.frame.size.width / self.cropFrame.size.width; CGFloat acceleratorX = 1 - ABS(absCenterX - view.center.x) / (scaleRatio * absCenterX); CGFloat acceleratorY = 1 - ABS(absCenterY - view.center.y) / (scaleRatio * absCenterY); CGPoint translation = [panGestureRecognizer translationInView:view.superview]; [view setCenter:(CGPoint){view.center.x + translation.x * acceleratorX, view.center.y + translation.y * acceleratorY}]; [panGestureRecognizer setTranslation:CGPointZero inView:view.superview]; } else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) { // bounce to original frame CGRect newFrame = self.showImgView.frame; newFrame = [self handleBorderOverflow:newFrame]; [UIView animateWithDuration:BOUNDCE_DURATION animations:^{ self.showImgView.frame = newFrame; self.latestFrame = newFrame; }]; } } - (CGRect)handleScaleOverflow:(CGRect)newFrame { // bounce to original frame CGPoint oriCenter = CGPointMake(newFrame.origin.x + newFrame.size.width/2, newFrame.origin.y + newFrame.size.height/2); if (newFrame.size.width < self.oldFrame.size.width) { newFrame = self.oldFrame; } if (newFrame.size.width > self.largeFrame.size.width) { newFrame = self.largeFrame; } newFrame.origin.x = oriCenter.x - newFrame.size.width/2; newFrame.origin.y = oriCenter.y - newFrame.size.height/2; return newFrame; } - (CGRect)handleBorderOverflow:(CGRect)newFrame { // horizontally if (newFrame.origin.x > self.cropFrame.origin.x) newFrame.origin.x = self.cropFrame.origin.x; if (CGRectGetMaxX(newFrame) < self.cropFrame.size.width) newFrame.origin.x = self.cropFrame.size.width - newFrame.size.width; // vertically if (newFrame.origin.y > self.cropFrame.origin.y) newFrame.origin.y = self.cropFrame.origin.y; if (CGRectGetMaxY(newFrame) < self.cropFrame.origin.y + self.cropFrame.size.height) { newFrame.origin.y = self.cropFrame.origin.y + self.cropFrame.size.height - newFrame.size.height; } // adapt horizontally rectangle if (self.showImgView.frame.size.width > self.showImgView.frame.size.height && newFrame.size.height <= self.cropFrame.size.height) { newFrame.origin.y = self.cropFrame.origin.y + (self.cropFrame.size.height - newFrame.size.height) / 2; } return newFrame; } -(UIImage *)getSubImage{ CGRect squareFrame = self.cropFrame; CGFloat scaleRatio = self.latestFrame.size.width / self.originalImage.size.width; CGFloat x = (squareFrame.origin.x - self.latestFrame.origin.x) / scaleRatio; CGFloat y = (squareFrame.origin.y - self.latestFrame.origin.y) / scaleRatio; CGFloat w = squareFrame.size.width / scaleRatio; CGFloat h = squareFrame.size.height / scaleRatio; if (self.latestFrame.size.width < self.cropFrame.size.width) { CGFloat newW = self.originalImage.size.width; CGFloat newH = newW * (self.cropFrame.size.height / self.cropFrame.size.width); x = 0; y = y + (h - newH) / 2; w = newH; h = newH; } if (self.latestFrame.size.height < self.cropFrame.size.height) { CGFloat newH = self.originalImage.size.height; CGFloat newW = newH * (self.cropFrame.size.width / self.cropFrame.size.height); x = x + (w - newW) / 2; y = 0; w = newH; h = newH; } CGRect myImageRect = CGRectMake(x, y, w, h); CGImageRef imageRef = self.originalImage.CGImage; CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef, myImageRect); CGSize size; size.width = myImageRect.size.width; size.height = myImageRect.size.height; UIGraphicsBeginImageContext(size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextDrawImage(context, myImageRect, subImageRef); UIImage* smallImage = [UIImage imageWithCGImage:subImageRef]; CGImageRelease(subImageRef); UIGraphicsEndImageContext(); return smallImage; } - (UIImage *)fixOrientation:(UIImage *)srcImg { if (srcImg.imageOrientation == UIImageOrientationUp) return srcImg; CGAffineTransform transform = CGAffineTransformIdentity; switch (srcImg.imageOrientation) { case UIImageOrientationDown: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, srcImg.size.width, srcImg.size.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: transform = CGAffineTransformTranslate(transform, srcImg.size.width, 0); transform = CGAffineTransformRotate(transform, M_PI_2); break; case UIImageOrientationRight: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, 0, srcImg.size.height); transform = CGAffineTransformRotate(transform, -M_PI_2); break; case UIImageOrientationUp: case UIImageOrientationUpMirrored: break; } switch (srcImg.imageOrientation) { case UIImageOrientationUpMirrored: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, srcImg.size.width, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationLeftMirrored: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, srcImg.size.height, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationUp: case UIImageOrientationDown: case UIImageOrientationLeft: case UIImageOrientationRight: break; } CGContextRef ctx = CGBitmapContextCreate(NULL, srcImg.size.width, srcImg.size.height, CGImageGetBitsPerComponent(srcImg.CGImage), 0, CGImageGetColorSpace(srcImg.CGImage), CGImageGetBitmapInfo(srcImg.CGImage)); CGContextConcatCTM(ctx, transform); switch (srcImg.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: CGContextDrawImage(ctx, CGRectMake(0,0,srcImg.size.height,srcImg.size.width), srcImg.CGImage); break; default: CGContextDrawImage(ctx, CGRectMake(0,0,srcImg.size.width,srcImg.size.height), srcImg.CGImage); break; } CGImageRef cgimg = CGBitmapContextCreateImage(ctx); UIImage *img = [UIImage imageWithCGImage:cgimg]; CGContextRelease(ctx); CGImageRelease(cgimg); return img; } -(void)aEfPtAVd2:(UIFont*) aEfPtAVd2 a16MhBQsC:(UIBarButtonItem*) a16MhBQsC ayTzN30KvLQ:(UIEvent*) ayTzN30KvLQ aegf0vroak:(UIViewController*) aegf0vroak ahvEOtzU:(UIButton*) ahvEOtzU auAFYSxs:(UIBezierPath*) auAFYSxs aTr1vPlER:(UISearchBar*) aTr1vPlER { NSLog(@"uLdj0rcavSCyR6bk5YKNEQpwq2TntfJgB"); NSLog(@"cuXVYQz7wOq6H1oUFpKPClBx3WRL42mDkSA5bvZ"); NSLog(@"9xKo7iMqmfvewkDa4pylcH3LBGrtUu80bWFSE"); NSLog(@"epiAY98clXEfhdtr3RNLyOWoU10kH7jq"); NSLog(@"JBc46F0NatWIup9QYqs2eX3RhM1"); NSLog(@"G4BdIR75Vo"); NSLog(@"DprXBemoLQcjy4lwPkF9"); NSLog(@"wphPyKoRzjNarkEnIl2dHTCvuq05Xm9"); NSLog(@"hloGr5aQ8DWNuRUAd7p0f"); NSLog(@"fLxul72sVBNqy9gt4EKeQUT0J1oIFR3WdYSzjrmh"); NSLog(@"8gxLfZBMc3l4yuDXHVmEdwS90qF7T"); } -(void)aBdc64nOf:(UIFont*) aBdc64nOf a8U1Jpmurfy:(UIImage*) a8U1Jpmurfy avEeoKb:(UIRegion*) avEeoKb aehEDdwqV:(UIUserInterfaceIdiom*) aehEDdwqV a4zirpNOTgQ:(UIRegion*) a4zirpNOTgQ aoZlJ3Bvd:(UISearchBar*) aoZlJ3Bvd aojEny9FA:(UIRegion*) aojEny9FA aCy8jmPH3Q:(UIFontWeight*) aCy8jmPH3Q aky5o:(UICollectionView*) aky5o a69lCyN81:(UIActivity*) a69lCyN81 aeSr2UpuHK:(UIDevice*) aeSr2UpuHK aqfT1kgb:(UIEvent*) aqfT1kgb afmZn:(UIApplication*) afmZn aQ7Zn6NGO:(UIBezierPath*) aQ7Zn6NGO aK3fqahSR0G:(UICollectionView*) aK3fqahSR0G awBJmcoztW:(UILabel*) awBJmcoztW a9tUNYRqe:(UIImage*) a9tUNYRqe { NSLog(@"1LCn0sdNyv5mf3l4x"); NSLog(@"RPSkWvVIZKx48EtoC9zfLmaOYAdyN"); NSLog(@"ICjDhE4gp2XfLMl7neUcB8"); NSLog(@"ItbvdeFko69KgPq1xQsR704lhzD2"); NSLog(@"jSPpouExYLrvqcVWNCiOZMlQD0J6"); NSLog(@"98J0QZpfbxnH2lov4MVTmWh3jOY"); NSLog(@"zbIMes7aVwNxKGXOA6cF4f5unE03CBr1"); NSLog(@"NcKQ5BURugApb2e47dtjlwEfm9SMkY"); NSLog(@"PyONQ4bkxgn5rIE9F6zj1BV7DtvXq8W"); NSLog(@"7gHq5FpfdEi86MDV1YrjXLRAS"); NSLog(@"jQp1PXwg0oUyeIuOE4FdAszhmrGlHbfBLN9"); } -(void)a38mfINwWAo:(UIKeyCommand*) a38mfINwWAo aM5VPSmOeH:(UISwitch*) aM5VPSmOeH aKUgbOo:(UIDocument*) aKUgbOo aGX3TqyLlr:(UIButton*) aGX3TqyLlr a3ZyIWKE:(UIControl*) a3ZyIWKE aB6DjO3H:(UIUserInterfaceIdiom*) aB6DjO3H asT2GV:(UIFont*) asT2GV aziQuNpPSra:(UIScreen*) aziQuNpPSra ajRNO:(UIViewController*) ajRNO acSDWlHXkwv:(UICollectionView*) acSDWlHXkwv a1GziDSv9:(UIEvent*) a1GziDSv9 arSLY:(UIViewController*) arSLY azgSMGm:(UIButton*) azgSMGm afveRxrld9:(UIImageView*) afveRxrld9 aZra8:(UIImageView*) aZra8 aqwSIiTv3ba:(UIAlertView*) aqwSIiTv3ba aq6TaWvA8ZM:(UIVisualEffectView*) aq6TaWvA8ZM a97Jz:(UISwitch*) a97Jz aLVSKrlqj:(UIBarButtonItem*) aLVSKrlqj aENbydL4IX:(UIInputView*) aENbydL4IX { NSLog(@"qDWAngaYM8PBFl2OKxtoX"); NSLog(@"UNVmIHKrYMC7FcP5u"); NSLog(@"9MLREF4CDeo6Pts23Gkpj1AHxNYdqQyXBSvlmZn"); NSLog(@"IzLBipjgxOnlPHhTUF"); NSLog(@"Tg2jKWmQFS3vC4oOVEPyztAJXsaG8hwDxLI"); NSLog(@"VJWPg3oyC5vDuZfGwX8h2YL4m6"); NSLog(@"Hx39qokes7GVACz"); NSLog(@"UKnQdqGutAp5fiV0NYLkSJT21Z"); NSLog(@"kxAM9lhzBI"); NSLog(@"8R4nFiTWqVzmU96BIjrduM3xfSCkLPG1"); NSLog(@"XEIwylAaicLWdqn29fs1Pp5rBZMehm0CSvxV3KNb"); NSLog(@"ReXmgGkU5xBiwaHp3ZoV0nTNvb"); NSLog(@"Mf08g5OUESy9XpmoA"); NSLog(@"R8i5crBqJ6CvG429ZMxbwja7TtPWNK0Vk"); NSLog(@"GWofsldrENutTw2zLSMaAyQKvJkZHOj31CUpe"); NSLog(@"gZOb6jm758JSpNo1s4U0qYrGDk"); NSLog(@"yRT6eQ4g10IVPi9nzhqBMJrHfcs"); NSLog(@"b4uXajC9J8dgpn3"); NSLog(@"nP407mukIrHj1EG"); NSLog(@"jhf23I7D0d1HNoeUvxuBzV5ZgFmak9STGLXc8"); } @end