图片裁剪/滤镜渲染
一、图片裁剪
//拖动手势
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | - ( 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]; } } |
//捏合手势
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | - ( 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; } |
//旋转
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 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]; } |
//裁剪
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //要的是实际图片的大小 - (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框架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | - ( 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"); } |
三、效果图
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用