一、图片裁剪
//拖动手势
- (void)handlePanGes:(PanGesRec *)panGes { CGPoint translation = [panGes translationInView:self.imgView.superview]; CGPoint movePoint = panGes.movedPoint; //判断开始滑动时的滑动对象:top、bottom、left、right if (panGes.state == GR_BEGIN) { //再次开始移动,shaView整体高亮 [UIView animateWithDuration:0.5 animations:^{ self.shaView.isSetShadow = NO; }]; if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.leftEdge+SHORT_LINE_LENGTH MaxX:self.clipAreaLayer.rightEdge-SHORT_LINE_LENGTH MinY:self.clipAreaLayer.topEdge-PANGR_OFFET MaxY:self.clipAreaLayer.topEdge+PANGR_OFFET]) { self.acGeView = CLIP_AREA_TOP; } else if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.leftEdge+SHORT_LINE_LENGTH MaxX:self.clipAreaLayer.rightEdge-SHORT_LINE_LENGTH MinY:self.clipAreaLayer.bottomEdge-PANGR_OFFET MaxY:self.clipAreaLayer.bottomEdge+PANGR_OFFET]) { self.acGeView = CLIP_AREA_BOTTOM; } else if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.leftEdge-PANGR_OFFET MaxX:self.clipAreaLayer.leftEdge+PANGR_OFFET MinY:self.clipAreaLayer.topEdge+SHORT_LINE_LENGTH MaxY:self.clipAreaLayer.bottomEdge-SHORT_LINE_LENGTH]) { self.acGeView = CLIP_AREA_LEFT; } else if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.rightEdge-PANGR_OFFET MaxX:self.clipAreaLayer.rightEdge+PANGR_OFFET MinY:self.clipAreaLayer.topEdge+SHORT_LINE_LENGTH MaxY:self.clipAreaLayer.bottomEdge-SHORT_LINE_LENGTH]) { self.acGeView = CLIP_AREA_RIGHT; } else if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.leftEdge-PANGR_OFFET MaxX:self.clipAreaLayer.leftEdge+PANGR_OFFET MinY:self.clipAreaLayer.topEdge MaxY:self.clipAreaLayer.topEdge+SHORT_LINE_LENGTH] || [self judgeGesRecInViewWithMinX:self.clipAreaLayer.leftEdge MaxX:self.clipAreaLayer.leftEdge+SHORT_LINE_LENGTH MinY:self.clipAreaLayer.topEdge-PANGR_OFFET MaxY:self.clipAreaLayer.topEdge+PANGR_OFFET]){ self.acGeView = CLIP_AREA_LT; } else if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.leftEdge-PANGR_OFFET MaxX:self.clipAreaLayer.leftEdge+PANGR_OFFET MinY:self.clipAreaLayer.bottomEdge-SHORT_LINE_LENGTH MaxY:self.clipAreaLayer.bottomEdge] || [self judgeGesRecInViewWithMinX:self.clipAreaLayer.leftEdge MaxX:self.clipAreaLayer.leftEdge+SHORT_LINE_LENGTH MinY:self.clipAreaLayer.bottomEdge-PANGR_OFFET MaxY:self.clipAreaLayer.bottomEdge+PANGR_OFFET]){ self.acGeView = CLIP_AREA_LB; } else if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.rightEdge-PANGR_OFFET MaxX:self.clipAreaLayer.rightEdge+PANGR_OFFET MinY:self.clipAreaLayer.topEdge MaxY:self.clipAreaLayer.topEdge+SHORT_LINE_LENGTH] || [self judgeGesRecInViewWithMinX:self.clipAreaLayer.rightEdge-SHORT_LINE_LENGTH MaxX:self.clipAreaLayer.rightEdge MinY:self.clipAreaLayer.topEdge-PANGR_OFFET MaxY:self.clipAreaLayer.topEdge+PANGR_OFFET]){ self.acGeView = CLIP_AREA_RT; } else if ([self judgeGesRecInViewWithMinX:self.clipAreaLayer.rightEdge-PANGR_OFFET MaxX:self.clipAreaLayer.rightEdge+PANGR_OFFET MinY:self.clipAreaLayer.bottomEdge-SHORT_LINE_LENGTH MaxY:self.clipAreaLayer.bottomEdge] || [self judgeGesRecInViewWithMinX:self.clipAreaLayer.rightEdge-SHORT_LINE_LENGTH MaxX:self.clipAreaLayer.rightEdge MinY:self.clipAreaLayer.bottomEdge-PANGR_OFFET MaxY:self.clipAreaLayer.bottomEdge+PANGR_OFFET]){ self.acGeView = CLIP_AREA_RB; } else { self.acGeView = IMAGE_VIEW; [self.imgView setCenter:CGPointMake(self.imgView.center.x+translation.x, self.imgView.center.y+translation.y)]; [panGes setTranslation:CGPointZero inView:self.imgView.superview]; } } //滑动过程中位置改变 CGFloat offsetX = 0; CGFloat offsetY = 0; if (panGes.state == GR_CHANGED) { switch (self.acGeView) { case CLIP_AREA_TOP: { offsetY = movePoint.y-self.clipAreaLayer.topEdge; if (offsetY >=0 && self.clipAreaHeight >= CLIP_AREA_MIN_WH) { self.clipAreaHeight -= fabs(offsetY); self.clipAreaLayer.topEdge += fabs(offsetY); } else if(offsetY < 0 && self.clipAreaLayer.topEdge >= CLIP_VIEW_TOP_MIN) { self.clipAreaHeight += fabs(offsetY); self.clipAreaLayer.topEdge -= fabs(offsetY); [self scaleImgForTop]; } } break; case CLIP_AREA_BOTTOM: { offsetY = movePoint.y-self.clipAreaLayer.bottomEdge; if (offsetY >= 0 && self.clipAreaLayer.bottomEdge <= SCREEN_HEIGHT-CLIP_VIEW_BOTTOM_MAX) { self.clipAreaHeight += fabs(offsetY); self.clipAreaLayer.bottomEdge += fabs(offsetY); [self scaleImgForBottom]; } else if (offsetY < 0 && self.clipAreaHeight >= CLIP_AREA_MIN_WH){ self.clipAreaHeight -= fabs(offsetY); self.clipAreaLayer.bottomEdge -= fabs(offsetY); } } break; case CLIP_AREA_LEFT: { offsetX = movePoint.x-self.clipAreaLayer.leftEdge; if (offsetX >= 0 && self.clipAreaWidth >= CLIP_AREA_MIN_WH) { self.clipAreaWidth -= fabs(offsetX); self.clipAreaLayer.leftEdge += fabs(offsetX); }else if (offsetX < 0 && self.clipAreaLayer.leftEdge >= CLIP_VIEW_LR_MIN){ self.clipAreaWidth += fabs(offsetX); self.clipAreaLayer.leftEdge -= fabs(offsetX); } } break; case CLIP_AREA_RIGHT: { offsetX = movePoint.x-self.clipAreaLayer.rightEdge; if (offsetX >= 0 && self.clipAreaLayer.rightEdge <= SCREEN_WIDTH-CLIP_VIEW_LR_MIN) { self.clipAreaWidth += fabs(offsetX); self.clipAreaLayer.rightEdge += fabs(offsetX); } else if (offsetX < 0 && self.clipAreaWidth >= CLIP_AREA_MIN_WH){ self.clipAreaWidth -= fabs(offsetX); self.clipAreaLayer.rightEdge -= fabs(offsetX); } } break; case CLIP_AREA_LT: { offsetX = movePoint.x-self.clipAreaLayer.leftEdge; offsetY = movePoint.y-self.clipAreaLayer.topEdge; if (offsetX >= 0 && offsetY >= 0 && self.clipAreaWidth >= CLIP_AREA_MIN_WH && self.clipAreaHeight >= CLIP_AREA_MIN_WH) { self.clipAreaWidth -= fabs(offsetX); self.clipAreaHeight -= fabs(offsetY); self.clipAreaLayer.leftEdge += fabs(offsetX); self.clipAreaLayer.topEdge += fabs(offsetY); }else if (offsetX < 0 && offsetY < 0 && self.clipAreaLayer.leftEdge >= CLIP_VIEW_LR_MIN && self.clipAreaLayer.topEdge >= CLIP_VIEW_TOP_MIN){ self.clipAreaWidth += fabs(offsetX); self.clipAreaHeight += fabs(offsetY); self.clipAreaLayer.leftEdge -= fabs(offsetX); self.clipAreaLayer.topEdge -= fabs(offsetY); [self scaleImgForTop]; } } break; case CLIP_AREA_LB: { offsetX = movePoint.x-self.clipAreaLayer.leftEdge; offsetY = movePoint.y-self.clipAreaLayer.bottomEdge; if (offsetX >= 0 && offsetY <= 0 && self.clipAreaWidth >= CLIP_AREA_MIN_WH && self.clipAreaHeight >= CLIP_AREA_MIN_WH) { self.clipAreaWidth -= fabs(offsetX); self.clipAreaHeight -= fabs(offsetY); self.clipAreaLayer.leftEdge += fabs(offsetX); self.clipAreaLayer.bottomEdge -= fabs(offsetY); }else if (offsetX < 0 && offsetY > 0 && self.clipAreaLayer.leftEdge >= CLIP_VIEW_LR_MIN && self.clipAreaLayer.bottomEdge <= SCREEN_HEIGHT-CLIP_VIEW_BOTTOM_MAX){ self.clipAreaWidth += fabs(offsetX); self.clipAreaHeight += fabs(offsetY); self.clipAreaLayer.leftEdge -= fabs(offsetX); self.clipAreaLayer.bottomEdge += fabs(offsetY); [self scaleImgForBottom]; } } break; case CLIP_AREA_RT: { offsetX = movePoint.x-self.clipAreaLayer.rightEdge; offsetY = movePoint.y-self.clipAreaLayer.topEdge; if (offsetX <= 0 && offsetY >= 0 && self.clipAreaWidth >= CLIP_AREA_MIN_WH && self.clipAreaHeight >= CLIP_AREA_MIN_WH) { self.clipAreaWidth -= fabs(offsetX); self.clipAreaHeight -= fabs(offsetY); self.clipAreaLayer.rightEdge -= fabs(offsetX); self.clipAreaLayer.topEdge += fabs(offsetY); }else if (offsetX > 0 && offsetY < 0 && self.clipAreaLayer.rightEdge <= SCREEN_WIDTH-CLIP_VIEW_LR_MIN && self.clipAreaLayer.topEdge >= CLIP_VIEW_TOP_MIN){ self.clipAreaWidth += fabs(offsetX); self.clipAreaHeight += fabs(offsetY); self.clipAreaLayer.rightEdge += fabs(offsetX); self.clipAreaLayer.topEdge -= fabs(offsetY); [self scaleImgForTop]; } } break; case CLIP_AREA_RB: { offsetX = movePoint.x-self.clipAreaLayer.rightEdge; offsetY = movePoint.y-self.clipAreaLayer.bottomEdge; if (offsetX <= 0 && offsetY <= 0 && self.clipAreaWidth >= CLIP_AREA_MIN_WH && self.clipAreaHeight >= CLIP_AREA_MIN_WH) { self.clipAreaWidth -= fabs(offsetX); self.clipAreaHeight -= fabs(offsetY); self.clipAreaLayer.rightEdge -= fabs(offsetX); self.clipAreaLayer.bottomEdge -= fabs(offsetY); }else if (offsetX > 0 && offsetY > 0 && self.clipAreaLayer.rightEdge <= SCREEN_WIDTH-CLIP_VIEW_LR_MIN && self.clipAreaLayer.bottomEdge <= SCREEN_HEIGHT-CLIP_VIEW_BOTTOM_MAX){ self.clipAreaWidth += fabs(offsetX); self.clipAreaHeight += fabs(offsetY); self.clipAreaLayer.rightEdge += fabs(offsetX); self.clipAreaLayer.bottomEdge += fabs(offsetY); [self scaleImgForBottom]; } } break; case IMAGE_VIEW: { [self.imgView setCenter:CGPointMake(self.imgView.center.x + translation.x, self.imgView.center.y+translation.y)]; [panGes setTranslation:CGPointZero inView:self.imgView.superview]; } break; default: break; } if (self.acGeView != IMAGE_VIEW) { [self setUpClipLayer:NO]; } } if (panGes.state == GR_ENDED) { if (self.acGeView == IMAGE_VIEW) { //修正imgView位置————必须铺满clipAreaLayer [UIView animateWithDuration:0.5 animations:^{ if (CGRectGetMinY(self.imgView.frame)>self.clipAreaLayer.topEdge) { self.imgView.frame = CGRectMake(CGRectGetMinX(self.imgView.frame), self.clipAreaLayer.topEdge, CGRectGetWidth(self.imgView.frame), CGRectGetHeight(self.imgView.frame)); } if (CGRectGetMaxY(self.imgView.frame)<self.clipAreaLayer.bottomEdge) { self.imgView.frame = CGRectMake(CGRectGetMinX(self.imgView.frame), self.clipAreaLayer.bottomEdge-CGRectGetHeight(self.imgView.frame), CGRectGetWidth(self.imgView.frame), CGRectGetHeight(self.imgView.frame)); } if (CGRectGetMinX(self.imgView.frame)>self.clipAreaLayer.leftEdge) { self.imgView.frame = CGRectMake(self.clipAreaLayer.leftEdge, CGRectGetMinY(self.imgView.frame), CGRectGetWidth(self.imgView.frame), CGRectGetHeight(self.imgView.frame)); } if (CGRectGetMaxX(self.imgView.frame)<self.clipAreaLayer.rightEdge) { self.imgView.frame = CGRectMake(self.clipAreaLayer.rightEdge-CGRectGetWidth(self.imgView.frame), CGRectGetMinY(self.imgView.frame), CGRectGetWidth(self.imgView.frame), CGRectGetHeight(self.imgView.frame)); } }]; }else{ /* 思路:滑动结束后位置修正 1.clipAreaLayer的移动后会回到中心点和宽都固定的位置; 2.clipAreaLayer的缩放:宽固定——如果高度超过最大值——固定高度为最大值——再确定宽度; 3.imgView的缩放:根据clipAreaLayer的缩放比例来确定宽高; 4.imgView的位置:以clipAreaLayer为基准并根据缩放前的上边和左边的相对位置的缩放量,来确定; */ [NSThread sleepForTimeInterval:0.3]; // [self animationForPosition];//移动动画效果——待解决 [UIView animateWithDuration:ANI_DURA animations:^{ //修正裁剪框之前的参照数据 CGFloat preDrawClipTop = self.clipAreaLayer.topEdge; CGFloat preDrawClipLeft = self.clipAreaLayer.leftEdge; //修正裁剪框 CGFloat scale = [self drawClipArea]; //设置imgView————不能单纯靠裁剪框的位置偏移量来定位,要考虑到缩放 CGFloat imgViewX = 0; CGFloat imgViewY = 0; CGFloat imgWidth = CGRectGetWidth(self.imgView.frame)*scale; CGFloat imgHeight = CGRectGetHeight(self.imgView.frame)*scale; CGFloat offsetX = fabs(CGRectGetMinX(self.imgView.frame)-preDrawClipLeft); CGFloat offsetY = fabs(CGRectGetMinY(self.imgView.frame)-preDrawClipTop); imgViewX = self.clipAreaLayer.leftEdge-offsetX*scale; imgViewY = self.clipAreaLayer.topEdge-offsetY*scale; self.imgView.frame = CGRectMake(imgViewX, imgViewY, imgWidth, imgHeight); }]; //记录每次修复后的位置 self.preClipAreaFrame = CGRectMake(self.clipAreaLayer.leftEdge, self.clipAreaLayer.topEdge, self.clipAreaWidth, self.clipAreaHeight); } //滑动后,超出clipAreaLayer的图片设置为透明 [self configShadowArea]; } }
//捏合手势
- (void)handlePinGes:(UIPinchGestureRecognizer *)pinGes { CGPoint pinchCenter = [pinGes locationInView:self.imgView.superview]; if (pinGes.state == UIGestureRecognizerStateBegan || pinGes.state == UIGestureRecognizerStateChanged) { [UIView animateWithDuration:0.5 animations:^{ self.shaView.isSetShadow = NO; }]; //CGAffineTransformScale方法90度旋转有问题 // self.imgView.transform=CGAffineTransformScale(self.imgView.transform, pinGes.scale, pinGes.scale); // pinGes.scale = 1; CGFloat scale = pinGes.scale; CGFloat distanceX = self.imgView.frame.origin.x - pinchCenter.x; CGFloat distanceY = self.imgView.frame.origin.y - pinchCenter.y; CGFloat scaledDistanceX = distanceX * scale; CGFloat scaledDistanceY = distanceY * scale; CGRect newFrame = CGRectMake(self.imgView.frame.origin.x + scaledDistanceX - distanceX, self.imgView.frame.origin.y + scaledDistanceY - distanceY, self.imgView.frame.size.width * scale, self.imgView.frame.size.height * scale); self.imgView.frame = newFrame; pinGes.scale = 1; } // if (pinGes.state == UIGestureRecognizerStateEnded) { //不能过小 if (CGRectGetMinY(self.imgView.frame)>self.clipAreaLayer.topEdge || CGRectGetMaxY(self.imgView.frame)<self.clipAreaLayer.bottomEdge || CGRectGetMinX(self.imgView.frame)>self.clipAreaLayer.leftEdge || CGRectGetMaxX(self.imgView.frame)<self.clipAreaLayer.rightEdge) { self.imgView.frame = CGRectMake(self.clipAreaLayer.leftEdge, self.clipAreaLayer.topEdge, self.clipAreaWidth, self.clipAreaHeight); } //不能过大 CGFloat scaleNum = 10; CGFloat originalImgViewWidth = CGRectGetWidth(_originalImgViewFrame); if (CGRectGetWidth(self.imgView.frame)/originalImgViewWidth>scaleNum) { self.imgView.frame = _originalImgViewFrame; CGFloat distanceX = self.imgView.frame.origin.x - pinchCenter.x; CGFloat distanceY = self.imgView.frame.origin.y - pinchCenter.y; CGFloat scaledDistanceX = distanceX * scaleNum; CGFloat scaledDistanceY = distanceY * scaleNum; CGRect newFrame = CGRectMake(self.imgView.frame.origin.x + scaledDistanceX - distanceX, self.imgView.frame.origin.y + scaledDistanceY - distanceY, self.imgView.frame.size.width * scaleNum, self.imgView.frame.size.height * scaleNum); self.imgView.frame = newFrame; pinGes.scale = 1; } // NSLog(@"self.imgView.frame-----scale------%@", NSStringFromCGRect(self.imgView.frame)); // } //缩放完后,需要点击一下图片才会执行该if语句————如何自动执行,待解决 if (pinGes.state == UIGestureRecognizerStateEnded) { [self configShadowArea]; } // self.resetBtn.hidden = NO; }
//旋转
case 301://旋转90度——顺时针 { _rorateNum++; [UIView animateWithDuration:0.5 animations:^{ self.shaView.isSetShadow = NO; }]; self.clipAreaLayer.hidden = YES; CGFloat dura = 1.0f; //旋转前:记录imgView与clipAreaLayer左边和底边的距离 CGFloat preRoOffsetX = fabs(CGRectGetMaxY(self.imgView.frame)-self.clipAreaLayer.bottomEdge); CGFloat preRoOffsetY = fabs(CGRectGetMinX(self.imgView.frame)-self.clipAreaLayer.leftEdge); //旋转 [UIView animateWithDuration:dura animations:^{ CGAffineTransform trans = CGAffineTransformMakeRotation(_valueOffset); self.imgView.transform = trans; }]; _valueOffset += M_PI_2; if (_rorateNum == kRotateNumMax) { _valueOffset = M_PI_2; _rorateNum = 0; } //切换坐标——imgView的frame自动修正 [self changeXYWithRotation:_valueOffset]; UIImage *agerImage = [self getRotatedImg]; self.targetImg = agerImage; CGFloat temp = self.clipAreaWidth; self.clipAreaWidth = self.clipAreaHeight; self.clipAreaHeight = temp; CGFloat scale = [self drawClipArea]; // [self setUpClipLayer:YES]; //旋转后:调整imgView的位置——左变上,底变左 self.imgView.frame = CGRectMake(self.clipAreaLayer.leftEdge-preRoOffsetX, self.clipAreaLayer.topEdge-preRoOffsetY, CGRectGetWidth(self.imgView.frame), CGRectGetHeight(self.imgView.frame)); //缩放 CABasicAnimation *baAniScale = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; baAniScale.beginTime = dura; baAniScale.duration = dura; baAniScale.fromValue = @1; baAniScale.toValue = @(scale); [self.imgView.layer addAnimation:baAniScale forKey:nil]; //缩放后调整imgView的位置 CGFloat imgViewX = 0; CGFloat imgViewY = 0; CGFloat imgWidth = CGRectGetWidth(self.imgView.frame)*scale; CGFloat imgHeight = CGRectGetHeight(self.imgView.frame)*scale; imgViewX = self.clipAreaLayer.leftEdge-preRoOffsetX*scale; imgViewY = self.clipAreaLayer.topEdge-preRoOffsetY*scale; //修正imgView位置 self.imgView.frame = CGRectMake(imgViewX, imgViewY, imgWidth, imgHeight); //修正clipAreaLayer位置 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.clipAreaLayer.hidden = NO; }); [self configShadowArea]; }
//裁剪
//要的是实际图片的大小 - (UIImage *)clipDownOriginalImg { CGFloat imageScale = MIN(self.imgView.frame.size.width/self.targetImg.size.width, self.imgView.frame.size.height/self.targetImg.size.height); CGFloat clipX = (self.clipAreaLayer.leftEdge - self.imgView.frame.origin.x)/imageScale; CGFloat clipY = (self.clipAreaLayer.topEdge - self.imgView.frame.origin.y)/imageScale; CGFloat clipWidth = self.clipAreaWidth/imageScale; CGFloat clipHeight = self.clipAreaHeight/imageScale; CGRect clipImgRect = CGRectMake(clipX, clipY, clipWidth, clipHeight); CGImageRef sourceImageRef = [self.targetImg CGImage]; CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, clipImgRect); UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; CGImageRelease(newImageRef); return newImage; }
二、滤镜——主要用到GPUImage框架
- (void)colorImg:(UIImage *)img { [self.filter forceProcessingAtSize:img.size]; self.staticPicture.image = img; if (self.outPutImgArr.count > 0) { [self.outPutImgArr removeAllObjects]; } //图片太多,内存爆增,系统会自动杀掉app // [self.outPutImgArr addObject:img]; // NSArray *paramArr = @[@"0.1", @"0.2", @"0.3", @"0.4", @"0.5", @"0.6", @"0.7", @"0.8", @"0.9", @"1.0"]; NSArray *paramArr = @[@"0.3", @"0.5", @"0.7", @"0.9", @"1.0"]; dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_async(queue, ^{ dispatch_apply(paramArr.count, queue, ^(size_t index) { NSString *paramStr = paramArr[index]; [self.filter setIntensity: paramStr.floatValue]; [self.staticPicture processImage]; [self.outPutImgArr addObject:[self.filter imageFromCurrentlyProcessedOutput]]; // NSLog(@"memoryUsage------%lld", [self memoryUsage]); dispatch_async(dispatch_get_main_queue(), ^{ [self reloadData]; }); }); // NSLog(@"-------Done1"); }); // NSLog(@"-------Done2"); }