123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958 |
- //
- // ZLImageEditTool.m
- // ZLPhotoBrowser
- //
- // Created by long on 2018/5/5.
- // Copyright © 2018年 long. All rights reserved.
- //
- #import "ZLImageEditTool.h"
- #import "ZLPhotoConfiguration.h"
- #import "ZLFilterItem.h"
- #import "ZLClipItem.h"
- #import "ZLFilterTool.h"
- #import "UIImage+ZLPhotoBrowser.h"
- #import "UIButton+EnlargeTouchArea.h"
- #import "ZLBrushBoardImageView.h"
- #import "ZLDrawItem.h"
- @interface ZLImageEditTool ()
- {
- NSInteger _layoutCount;
-
- ZLImageEditType _type;
- ZLPhotoConfiguration *_configuration;
- ZLImageEditType _selectToolType;
-
- //计算imageView尺寸时是否交换宽高(旋转图片90°及270°时候值为YES)
- BOOL _exchangeImageWH;
- //是否正在旋转图片
- BOOL _isRotatingImage;
-
- ZLClippingCircle *_ltView;
- ZLClippingCircle *_lbView;
- ZLClippingCircle *_rtView;
- ZLClippingCircle *_rbView;
-
- CGSize _originSize;
- }
- @property (nonatomic, strong) ZLBrushBoardImageView *imageView;
- @property (nonatomic, strong) UIButton *cancelBtn;
- @property (nonatomic, strong) UIButton *doneBtn;
- @property (nonatomic, strong) UIView *bottomView;
- @property (nonatomic, strong) UIButton *filterBtn;
- @property (nonatomic, strong) UIButton *drawBtn;
- @property (nonatomic, strong) UIButton *revokeBtn;
- @property (nonatomic, strong) UIButton *rotateBtn;
- @property (nonatomic, strong) UIButton *clipBtn;
- @property (nonatomic, strong) UIButton *rotateRatioBtn;
- @property (nonatomic, strong) UIScrollView *clipMenu;
- @property (nonatomic, strong) UIScrollView *filterMenu;
- @property (nonatomic, strong) UIScrollView *drawMenu;
- @property (nonatomic, strong) ZLGridLayar *gridLayer;
- @property (nonatomic, strong) ZLClipItem *selectClipItem;
- @property (nonatomic, strong) ZLClipRatio *selectClipRatio;
- @property (nonatomic, assign) CGRect clippingRect;
- @property (nonatomic, strong) ZLFilterItem *selectFilterItem;
- @property (nonatomic, strong) ZLDrawItem *selectDrawItem;
- @end
- @implementation ZLImageEditTool
- - (void)dealloc
- {
- [[GPUImageContext sharedImageProcessingContext].framebufferCache purgeAllUnassignedFramebuffers];
- // NSLog(@"---- %s", __FUNCTION__);
- }
- - (instancetype)initWithFrame:(CGRect)frame
- {
- return [self initWithEditType:ZLImageEditTypeDraw |
- ZLImageEditTypeMosaic |
- ZLImageEditTypeFilter |
- ZLImageEditTypeClip |
- ZLImageEditTypeRotate
- image:nil
- configuration:nil];
- }
- - (instancetype)initWithCoder:(NSCoder *)coder
- {
- return [self initWithEditType:ZLImageEditTypeDraw |
- ZLImageEditTypeMosaic |
- ZLImageEditTypeFilter |
- ZLImageEditTypeClip |
- ZLImageEditTypeRotate
- image:nil
- configuration:nil];
- }
- - (instancetype)initWithEditType:(ZLImageEditType)type image:(UIImage *)image configuration:(ZLPhotoConfiguration *)configuration
- {
- if (self = [super initWithFrame:[UIScreen mainScreen].bounds]) {
- _type = type;
- _configuration = configuration;
- self.editImage = image;
- [self setupUI];
- }
- return self;
- }
- - (void)setEditImage:(UIImage *)editImage
- {
- _editImage = editImage;
- _originSize = editImage.size;
- _imageView.image = editImage;
- _layoutCount = 0;
- [self setNeedsLayout];
- }
- - (void)layoutSubviews
- {
- [super layoutSubviews];
-
- _layoutCount++;
-
- UIEdgeInsets inset = UIEdgeInsetsZero;
- if (@available(iOS 11, *)) {
- inset = self.superview.safeAreaInsets;
- }
-
- self.cancelBtn.frame = CGRectMake(15+inset.left, inset.top+10, GetMatchValue(GetLocalLanguageTextValue(ZLPhotoBrowserCancelText), 15, YES, 30), 30);
- CGFloat doneBtnW = GetMatchValue(GetLocalLanguageTextValue(ZLPhotoBrowserDoneText), 15, YES, 30);
- self.doneBtn.frame = CGRectMake(kViewWidth-doneBtnW-inset.right-15, inset.top+10, doneBtnW, 30);
-
- [self setImageViewFrame:_layoutCount != 1];
- if (_selectToolType & ZLImageEditTypeClip) {
- self.gridLayer.frame = self.imageView.bounds;
- [self clippingRatioDidChange];
- }
-
- self.bottomView.frame = CGRectMake(0, kViewHeight-44-inset.bottom, kViewWidth, 44);
- NSInteger toolCount = [self toolCount];
- CGFloat disW = kViewWidth/(toolCount+1);
-
- CGFloat bx = disW;
- CGFloat bottomBtnW = 40;
- if (_type & ZLImageEditTypeFilter) {
- self.filterBtn.frame = CGRectMake(bx-bottomBtnW/2, 2, bottomBtnW, bottomBtnW);
- bx += disW;
- }
- if (_type & ZLImageEditTypeDraw) {
- self.drawBtn.frame = CGRectMake(bx-bottomBtnW/2, 2, bottomBtnW, bottomBtnW);
- bx += disW;
- }
- if (_type & ZLImageEditTypeRotate) {
- self.rotateBtn.frame = CGRectMake(bx-bottomBtnW/2, 2, bottomBtnW, bottomBtnW);
- bx += disW;
- }
- if (_type & ZLImageEditTypeClip) {
- self.clipBtn.frame = CGRectMake(bx-bottomBtnW/2, 2, bottomBtnW, bottomBtnW);
- bx += disW;
- }
-
- CGFloat menuMaxY = CGRectGetMinY(self.bottomView.frame);
-
- _filterMenu.frame = CGRectMake(inset.left, menuMaxY-80, kViewWidth-inset.left-inset.right, 80);
- _drawMenu.frame = CGRectMake(inset.left+30, menuMaxY-40, kViewWidth-inset.left-inset.right-30-60, 40);
- _revokeBtn.frame = CGRectMake(kViewWidth-60-inset.right, menuMaxY-40, 40, 40);
-
- BOOL hideClipRatioView = _configuration.hideClipRatiosToolBar ?: [self shouldHideClipRatioView];
-
- if (hideClipRatioView) {
- _rotateRatioBtn.hidden = YES;
- _clipMenu.hidden = YES;
- } else {
- _rotateRatioBtn.superview.frame = CGRectMake(kViewWidth-70-inset.right, menuMaxY-80, 70, 80);
- _clipMenu.frame = CGRectMake(inset.left, menuMaxY-80, kViewWidth-70-inset.left-inset.right, 80);
- }
- }
- - (void)setImageViewFrame:(BOOL)animate
- {
- if (!_editImage) return;
-
- UIEdgeInsets inset = UIEdgeInsetsZero;
- if (@available(iOS 11, *)) {
- inset = self.superview.safeAreaInsets;
- }
-
- BOOL showMenu = NO;
- if (_selectToolType & ZLImageEditTypeClip) {
- showMenu = ![self shouldHideClipRatioView];
- } else if (_selectToolType & (ZLImageEditTypeFilter | ZLImageEditTypeDraw)) {
- showMenu = YES;
- }
-
- //隐藏时 底部工具条高44,间距设置4即可,不隐藏时,比例view高度80,则为128
- CGFloat flag = showMenu ? 128 : 48;
-
- CGFloat diffXMarigin = showMenu ? 40 : 20;
- CGFloat w = kViewWidth-diffXMarigin-inset.left-inset.right;
- CGFloat maxH = kViewHeight-flag-inset.bottom-inset.top-50;
-
- CGFloat imgW = _exchangeImageWH ? _originSize.height : _originSize.width;
- CGFloat imgH = _exchangeImageWH ? _originSize.width : _originSize.height;
-
- CGFloat h = w * imgH / imgW;
- if (h > maxH) {
- h = maxH;
- w = h * imgW / imgH;
- }
- CGRect frame = CGRectMake((kViewWidth-w)/2, (kViewHeight-h-flag+40)/2, w, h);
-
- if (animate && !_isRotatingImage) {
- [UIView animateWithDuration:0.2 animations:^{
- _imageView.frame = frame;
- }];
- } else {
- _imageView.frame = frame;
- }
- }
- //当裁剪比例只有 custom 或者 1:1 的时候隐藏比例视图
- - (BOOL)shouldHideClipRatioView
- {
- if (_configuration.clipRatios.count <= 1) {
- NSInteger value1 = [_configuration.clipRatios.firstObject[ClippingRatioValue1] integerValue];
- NSInteger value2 = [_configuration.clipRatios.firstObject[ClippingRatioValue2] integerValue];
- if ((value1==0 && value2==0) || (value1==1 && value2==1)) {
- return YES;
- }
- }
- return NO;
- }
- - (void)setupUI
- {
- self.cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- self.cancelBtn.titleLabel.font = [UIFont systemFontOfSize:15];
- [self.cancelBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
- [self.cancelBtn setTitle:GetLocalLanguageTextValue(ZLPhotoBrowserCancelText) forState:UIControlStateNormal];
- [self.cancelBtn addTarget:self action:@selector(cancelBtn_click) forControlEvents:UIControlEventTouchUpInside];
- [self.cancelBtn setEnlargeEdgeWithTop:0 right:10 bottom:10 left:0];
- [self addSubview:self.cancelBtn];
-
- self.doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [self.doneBtn setTitle:GetLocalLanguageTextValue(ZLPhotoBrowserDoneText) forState:UIControlStateNormal];
- [self.doneBtn setTitleColor:_configuration.bottomBtnsNormalTitleColor forState:UIControlStateNormal];
- self.doneBtn.titleLabel.font = [UIFont systemFontOfSize:15];
- self.doneBtn.layer.masksToBounds = YES;
- self.doneBtn.layer.cornerRadius = 3.0f;
- [self.doneBtn addTarget:self action:@selector(btnDone_click) forControlEvents:UIControlEventTouchUpInside];
- [self.doneBtn setEnlargeEdgeWithTop:0 right:0 bottom:10 left:10];
- [self addSubview:_doneBtn];
-
- //imageView
- self.imageView = [[ZLBrushBoardImageView alloc] init];
- self.imageView.image = _editImage;
- self.imageView.contentMode = UIViewContentModeScaleAspectFit;
- [self addSubview:self.imageView];
-
-
- UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGridView:)];
- self.imageView.userInteractionEnabled = YES;
- [self.imageView addGestureRecognizer:panGesture];
-
- //下方视图
- self.bottomView = [[UIView alloc] init];
- [self addSubview:self.bottomView];
-
- {
- if (_type & ZLImageEditTypeClip) {
- self.clipBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [self.clipBtn setImage:GetImageWithName(@"zl_clip") forState:UIControlStateNormal];
- [self.clipBtn addTarget:self action:@selector(clipBtn_click) forControlEvents:UIControlEventTouchUpInside];
- [self.bottomView addSubview:self.clipBtn];
- }
-
- if (_type & ZLImageEditTypeRotate) {
- self.rotateBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [self.rotateBtn setImage:GetImageWithName(@"zl_rotateimage") forState:UIControlStateNormal];
- [self.rotateBtn addTarget:self action:@selector(rotateImageBtn_click) forControlEvents:UIControlEventTouchUpInside];
- [self.bottomView addSubview:self.rotateBtn];
- }
-
- if (_type & ZLImageEditTypeFilter) {
- self.filterBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [self.filterBtn setImage:GetImageWithName(@"zl_filter") forState:UIControlStateNormal];
- [self.filterBtn addTarget:self action:@selector(filterBtn_click) forControlEvents:UIControlEventTouchUpInside];
- [self.bottomView addSubview:self.filterBtn];
- }
-
- if (_type & ZLImageEditTypeDraw) {
- self.drawBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [self.drawBtn setImage:GetImageWithName(@"zl_draw") forState:UIControlStateNormal];
- [self.drawBtn addTarget:self action:@selector(drawBtn_click) forControlEvents:UIControlEventTouchUpInside];
- [self.bottomView addSubview:self.drawBtn];
- }
- }
-
- [self sendSubviewToBack:self.imageView];
- }
- - (ZLClippingCircle*)clippingCircleWithTag:(NSInteger)tag
- {
- ZLClippingCircle *view = [[ZLClippingCircle alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
- view.backgroundColor = [UIColor clearColor];
- view.bgColor = [UIColor whiteColor];
- view.tag = tag;
-
- UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panCircleView:)];
- [view addGestureRecognizer:panGesture];
-
- [self addSubview:view];
-
- return view;
- }
- - (NSInteger)toolCount
- {
- NSArray *arr = @[@(ZLImageEditTypeClip), @(ZLImageEditTypeRotate), @(ZLImageEditTypeFilter), @(ZLImageEditTypeDraw), @(ZLImageEditTypeMosaic)];
- NSInteger count = 0;
- for (NSNumber *num in arr) {
- if (_type & num.integerValue) {
- count++;
- }
- }
- return count;
- }
- #pragma mark - menu
- - (void)setupFilterMenu
- {
- if (_filterMenu) return;
-
- //这只是初始坐标,实际坐标在viewdidlayoutsubviews里面布局
- _filterMenu = [[UIScrollView alloc] initWithFrame:CGRectZero];
- _filterMenu.backgroundColor = [UIColor clearColor];
- _filterMenu.showsHorizontalScrollIndicator = NO;
- _filterMenu.clipsToBounds = NO;
- [self addSubview:_filterMenu];
-
- CGFloat W = 70;
- CGFloat H = 80;
- CGFloat x = 0;
-
- CGSize imgSize = self.editImage.size;
- CGFloat maxW = MIN(imgSize.width, imgSize.height);
- UIImage *iconImage = [self scaleImage:self.editImage toSize:CGSizeMake(W * imgSize.width/maxW, W * imgSize.height/maxW)];
-
- for (int i = ZLFilterTypeOriginal; i <= ZLFilterTypeColorInvert; i++) {
- ZLFilterItem *item = [[ZLFilterItem alloc] initWithFrame:CGRectMake(x, 0, W, H) Image:iconImage filterType:i target:self action:@selector(tapFilter:)];
- [_filterMenu addSubview:item];
-
- if (!self.selectFilterItem) {
- self.selectFilterItem = item;
- }
- x += W;
- }
- _filterMenu.contentSize = CGSizeMake(MAX(x, _filterMenu.frame.size.width+1), 0);
- }
- - (void)setupDrawMenu
- {
- if (_drawMenu) return;
-
- //这只是初始坐标,实际坐标在viewdidlayoutsubviews里面布局
- _drawMenu = [[UIScrollView alloc] initWithFrame:CGRectZero];
- _drawMenu.backgroundColor = [UIColor clearColor];
- _drawMenu.showsHorizontalScrollIndicator = NO;
- _drawMenu.clipsToBounds = NO;
- [self addSubview:_drawMenu];
-
- self.revokeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [self.revokeBtn setImage:GetImageWithName(@"zl_revoke") forState:UIControlStateNormal];
- [self.revokeBtn addTarget:self action:@selector(revokeBtn_click) forControlEvents:UIControlEventTouchUpInside];
- [self addSubview:self.revokeBtn];
-
- CGFloat W = 40;
- CGFloat H = 40;
- CGFloat x = 0;
-
- for (int i = ZLDrawItemColorTypeWhite; i <= ZLDrawItemColorTypePurple; i++) {
- ZLDrawItem *item = [[ZLDrawItem alloc] initWithFrame:CGRectMake(x, 0, W, H) colorType:i target:self action:@selector(tapDrawColor:)];
- [_drawMenu addSubview:item];
-
- if (!self.selectDrawItem) {
- self.selectDrawItem = item;
- }
- x += W;
- }
- _drawMenu.contentSize = CGSizeMake(MAX(x, _drawMenu.frame.size.width+1), 0);
- }
- - (void)setupClipMenu
- {
- if (_clipMenu) return;
-
- self.gridLayer = [[ZLGridLayar alloc] init];
- self.gridLayer.bgColor = [[UIColor blackColor] colorWithAlphaComponent:.5];
- self.gridLayer.gridColor = [UIColor whiteColor];
- [self.imageView.layer addSublayer:self.gridLayer];
-
- _ltView = [self clippingCircleWithTag:0];
- _lbView = [self clippingCircleWithTag:1];
- _rtView = [self clippingCircleWithTag:2];
- _rbView = [self clippingCircleWithTag:3];
-
- //这只是初始坐标,实际坐标在viewdidlayoutsubviews里面布局
- _clipMenu = [[UIScrollView alloc] initWithFrame:CGRectZero];
- _clipMenu.backgroundColor = [UIColor clearColor];
- _clipMenu.showsHorizontalScrollIndicator = NO;
- _clipMenu.clipsToBounds = NO;
- [self addSubview:_clipMenu];
-
- //旋转按钮
- UIView *view = [[UIView alloc] init];
- view.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:.8];
- view.hidden = YES;
- [self addSubview:view];
- _rotateRatioBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- _rotateRatioBtn.frame = CGRectMake(15, 20, 40, 40);
- _rotateRatioBtn.imageView.contentMode = UIViewContentModeScaleAspectFit;
- [_rotateRatioBtn setBackgroundImage:GetImageWithName(@"zl_btn_rotate") forState:UIControlStateNormal];
- [_rotateRatioBtn addTarget:self action:@selector(rotateRadioBtn_click) forControlEvents:UIControlEventTouchUpInside];
- [view addSubview:_rotateRatioBtn];
-
- CGFloat W = 70;
- CGFloat H = 80;
- CGFloat x = 0;
-
- CGSize imgSize = self.editImage.size;
- CGFloat maxW = MIN(imgSize.width, imgSize.height);
- UIImage *iconImage = [self scaleImage:self.editImage toSize:CGSizeMake(W * imgSize.width/maxW, W * imgSize.height/maxW)];
-
- //如需要其他比例,请按照格式自行设置
- for(NSDictionary *info in _configuration.clipRatios){
- CGFloat val1 = [info[@"value1"] floatValue];
- CGFloat val2 = [info[@"value2"] floatValue];
-
- ZLClipRatio *ratio = [[ZLClipRatio alloc] initWithValue1:val1 value2:val2];
- ratio.titleFormat = info[@"titleFormat"];
-
- ratio.isLandscape = val1 > val2;
-
- ZLClipItem *item = [[ZLClipItem alloc] initWithFrame:CGRectMake(x, 0, W, H) image:iconImage target:self action:@selector(tapRadio:)];
- item.ratio = ratio;
- [item refreshViews];
-
- [_clipMenu addSubview:item];
- x += W;
-
- if (!self.selectClipItem){
- self.selectClipItem = item;
- }
- }
-
- _clipMenu.contentSize = CGSizeMake(MAX(x, _clipMenu.frame.size.width+1), 0);
- }
- #pragma mark - btn action
- - (void)cancelBtn_click
- {
- if (self.cancelEditBlock) {
- self.cancelEditBlock();
- }
- }
- - (void)btnDone_click
- {
- UIImage *image = [self clipImage];
-
- if (self.doneEditBlock) {
- self.doneEditBlock(image);
- }
- }
- - (void)clipBtn_click
- {
- [self switchTool:ZLImageEditTypeClip];
- }
- - (void)rotateImageBtn_click
- {
- if (_isRotatingImage) {
- //旋转过程中不接受再次旋转
- return;
- }
- _isRotatingImage = YES;
-
- _editImage = [_editImage rotate:UIImageOrientationLeft];
- UIImage *newImage = [_imageView.image rotate:UIImageOrientationLeft];
-
- _exchangeImageWH = !_exchangeImageWH;
-
- [self switchCircleAndGridLayerShowStatus:NO];
-
- [UIView animateWithDuration:0.25 animations:^{
- _imageView.transform = CGAffineTransformMakeRotation(-M_PI_2);
- } completion:^(BOOL finished) {
- _imageView.image = newImage;
- [self setImageViewFrame:NO];
- _imageView.transform = CGAffineTransformIdentity;
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- _isRotatingImage = NO;
- });
- }];
-
- [self.class cancelPreviousPerformRequestsWithTarget:self selector:@selector(showCircleAndGrid) object:nil];
- if (_selectToolType & ZLImageEditTypeClip) {
- [self performSelector:@selector(showCircleAndGrid) withObject:nil afterDelay:0.5];
- }
- }
- - (void)showCircleAndGrid
- {
- [self switchCircleAndGridLayerShowStatus:YES];
- }
- - (void)rotateRadioBtn_click
- {
- for (ZLClipItem *item in _clipMenu.subviews){
- if([item isKindOfClass:[ZLClipItem class]]){
- [item changeOrientation];
- }
- }
-
- if (self.selectClipRatio.ratio != 0 &&
- self.selectClipRatio.ratio != 1){
- [self clippingRatioDidChange];
- }
- }
- - (void)filterBtn_click
- {
- [self switchTool:ZLImageEditTypeFilter];
- }
- - (void)drawBtn_click
- {
- [self switchTool:ZLImageEditTypeDraw];
- }
- - (void)switchTool:(ZLImageEditType)type
- {
- if (_selectToolType & type) {
- _selectToolType = 0;
- } else {
- _selectToolType = type;
- }
-
- if (!self.editImage) return;
-
- switch (_selectToolType) {
- case ZLImageEditTypeClip:
- [self setupClipMenu];
- break;
- case ZLImageEditTypeFilter:
- [self setupFilterMenu];
- break;
- case ZLImageEditTypeDraw:
- [self setupDrawMenu];
- break;
- default:
- break;
- }
-
- [self setNeedsLayout];
-
- if (_selectToolType == 0) {
- _filterMenu.hidden = YES;
- _clipMenu.hidden = YES;
- _rotateRatioBtn.superview.hidden = YES;
- [self switchBtnStatus:nil];
- [self switchCircleAndGridLayerShowStatus:NO];
- return;
- }
- if (_selectToolType & ZLImageEditTypeFilter) {
- _filterMenu.hidden = NO;
- _drawMenu.hidden = YES;
- _clipMenu.hidden = YES;
- _rotateRatioBtn.superview.hidden = YES;
- self.imageView.drawEnable = NO;
- [self switchCircleAndGridLayerShowStatus:NO];
- [self switchBtnStatus:self.filterBtn];
- } else if (_selectToolType & ZLImageEditTypeDraw) {
- _filterMenu.hidden = YES;
- _drawMenu.hidden = NO;
- _clipMenu.hidden = YES;
- _rotateRatioBtn.superview.hidden = YES;
- self.imageView.drawEnable = YES;
- [self switchCircleAndGridLayerShowStatus:NO];
- [self switchBtnStatus:self.drawBtn];
- } else if (_selectToolType & ZLImageEditTypeClip) {
- _filterMenu.hidden = YES;
- _drawMenu.hidden = YES;
- _clipMenu.hidden = NO;
- _rotateRatioBtn.superview.hidden = NO;
- self.imageView.drawEnable = NO;
- [self switchCircleAndGridLayerShowStatus:YES];
- [self switchBtnStatus:self.clipBtn];
- }
- }
- - (void)switchBtnStatus:(UIButton *)btn
- {
- UIButton *b = [UIButton new];
- NSArray *arr = @[self.filterBtn?: b, self.drawBtn?: b, self.rotateBtn?: b, self.clipBtn?: b];
- for (UIButton *b in arr) {
- if (b == btn) {
- [b setBackgroundColor:[UIColor colorWithWhite:1 alpha:.15]];
- } else {
- [b setBackgroundColor:[UIColor clearColor]];
- }
- }
- }
- - (void)switchCircleAndGridLayerShowStatus:(BOOL)show
- {
- if (!show) {
- self.clippingRect = CGRectZero;
- }
-
- _gridLayer.hidden = !show;
- _ltView.hidden = !show;
- _lbView.hidden = !show;
- _rtView.hidden = !show;
- _rbView.hidden = !show;
- }
- #pragma mark - 滤镜
- - (void)tapFilter:(UITapGestureRecognizer *)sender
- {
- ZLFilterItem *item = (ZLFilterItem *)sender.view;
- if (self.selectFilterItem == item) return;
-
- self.selectFilterItem = item;
-
- //加滤镜
- self.imageView.image = [ZLFilterTool filterImage:_editImage filterType:item.filterType];
- }
- - (void)setSelectFilterItem:(ZLFilterItem *)selectFilterItem
- {
- if (selectFilterItem != _selectFilterItem) {
- _selectFilterItem.backgroundColor = [UIColor clearColor];
- _selectFilterItem = selectFilterItem;
- _selectFilterItem.backgroundColor = [UIColor colorWithWhite:1 alpha:.15];
- }
- }
- #pragma mark - draw
- - (void)tapDrawColor:(UITapGestureRecognizer *)sender
- {
- ZLDrawItem *item = (ZLDrawItem *)sender.view;
- if (self.selectDrawItem == item) return;
-
- self.selectDrawItem = item;
- }
- - (void)setSelectDrawItem:(ZLDrawItem *)selectDrawItem
- {
- if (selectDrawItem != _selectDrawItem) {
- _selectDrawItem.selected = NO;
- _selectDrawItem = selectDrawItem;
- _selectDrawItem.selected = YES;
- self.imageView.drawColor = _selectDrawItem.color;
- }
- }
- - (void)revokeBtn_click
- {
- [self.imageView revoke];
- }
- #pragma mark - 裁剪
- - (void)tapRadio:(UITapGestureRecognizer *)sender
- {
- ZLClipItem *item = (ZLClipItem *)sender.view;
-
- self.selectClipItem = item;
- }
- - (void)setSelectClipItem:(ZLClipItem *)selectClipItem
- {
- if (selectClipItem != _selectClipItem){
- _selectClipItem.backgroundColor = [UIColor clearColor];
- _selectClipItem = selectClipItem;
- _selectClipItem.backgroundColor = [UIColor colorWithWhite:1 alpha:.15];
-
- if(selectClipItem.ratio.ratio==0){
- self.selectClipRatio = nil;
- } else {
- self.selectClipRatio = selectClipItem.ratio;
- }
- }
- }
- - (void)setSelectClipRatio:(ZLClipRatio *)selectClipRatio
- {
- if(selectClipRatio != _selectClipRatio){
- _selectClipRatio = selectClipRatio;
- [self clippingRatioDidChange];
- }
- }
- - (void)clippingRatioDidChange
- {
- CGRect rect = _imageView.bounds;
- if (self.selectClipRatio) {
- CGFloat H = rect.size.width * self.selectClipRatio.ratio;
- if (H <= rect.size.height) {
- rect.size.height = H;
- } else {
- rect.size.width *= rect.size.height / H;
- }
- rect.origin.x = (_imageView.bounds.size.width - rect.size.width) / 2;
- rect.origin.y = (_imageView.bounds.size.height - rect.size.height) / 2;
- }
- [self setClippingRect:rect animated:YES];
- }
- - (void)setClippingRect:(CGRect)clippingRect animated:(BOOL)animated
- {
- if (animated) {
- [UIView animateWithDuration:0.2 animations:^{
- _ltView.center = [self convertPoint:CGPointMake(clippingRect.origin.x, clippingRect.origin.y) fromView:_imageView];
- _lbView.center = [self convertPoint:CGPointMake(clippingRect.origin.x, clippingRect.origin.y+clippingRect.size.height) fromView:_imageView];
- _rtView.center = [self convertPoint:CGPointMake(clippingRect.origin.x+clippingRect.size.width, clippingRect.origin.y) fromView:_imageView];
- _rbView.center = [self convertPoint:CGPointMake(clippingRect.origin.x+clippingRect.size.width, clippingRect.origin.y+clippingRect.size.height) fromView:_imageView];
- }
- ];
- CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"clippingRect"];
- animation.duration = 0.2;
- animation.fromValue = [NSValue valueWithCGRect:_clippingRect];
- animation.toValue = [NSValue valueWithCGRect:clippingRect];
- [_gridLayer addAnimation:animation forKey:nil];
- _gridLayer.clippingRect = clippingRect;
- _clippingRect = clippingRect;
- [_gridLayer setNeedsDisplay];
- } else {
- self.clippingRect = clippingRect;
- }
- }
- - (void)setClippingRect:(CGRect)clippingRect
- {
- _clippingRect = clippingRect;
-
- _ltView.center = [self convertPoint:CGPointMake(_clippingRect.origin.x, _clippingRect.origin.y) fromView:_imageView];
- _lbView.center = [self convertPoint:CGPointMake(_clippingRect.origin.x, _clippingRect.origin.y+_clippingRect.size.height) fromView:_imageView];
- _rtView.center = [self convertPoint:CGPointMake(_clippingRect.origin.x+_clippingRect.size.width, _clippingRect.origin.y) fromView:_imageView];
- _rbView.center = [self convertPoint:CGPointMake(_clippingRect.origin.x+_clippingRect.size.width, _clippingRect.origin.y+_clippingRect.size.height) fromView:_imageView];
-
- _gridLayer.clippingRect = clippingRect;
- [_gridLayer setNeedsDisplay];
- }
- #pragma mark - 拖动
- - (void)panCircleView:(UIPanGestureRecognizer*)sender
- {
- CGPoint point = [sender locationInView:_imageView];
- CGPoint dp = [sender translationInView:_imageView];
-
- CGRect rct = self.clippingRect;
-
- const CGFloat W = _imageView.frame.size.width;
- const CGFloat H = _imageView.frame.size.height;
- CGFloat minX = 0;
- CGFloat minY = 0;
- CGFloat maxX = W;
- CGFloat maxY = H;
-
- CGFloat ratio = (sender.view.tag == 1 || sender.view.tag==2) ? -self.selectClipRatio.ratio : self.selectClipRatio.ratio;
-
- switch (sender.view.tag) {
- case 0: // upper left
- {
- maxX = MAX((rct.origin.x + rct.size.width) - 0.1 * W, 0.1 * W);
- maxY = MAX((rct.origin.y + rct.size.height) - 0.1 * H, 0.1 * H);
-
- if (ratio!=0) {
- CGFloat y0 = rct.origin.y - ratio * rct.origin.x;
- CGFloat x0 = -y0 / ratio;
- minX = MAX(x0, 0);
- minY = MAX(y0, 0);
-
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
-
- if(-dp.x*ratio + dp.y > 0){ point.x = (point.y - y0) / ratio; }
- else{ point.y = point.x * ratio + y0; }
- } else {
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
- }
-
- rct.size.width = rct.size.width - (point.x - rct.origin.x);
- rct.size.height = rct.size.height - (point.y - rct.origin.y);
- rct.origin.x = point.x;
- rct.origin.y = point.y;
- break;
- }
- case 1: // lower left
- {
- maxX = MAX((rct.origin.x + rct.size.width) - 0.1 * W, 0.1 * W);
- minY = MAX(rct.origin.y + 0.1 * H, 0.1 * H);
-
- if (ratio!=0) {
- CGFloat y0 = (rct.origin.y + rct.size.height) - ratio* rct.origin.x ;
- CGFloat xh = (H - y0) / ratio;
- minX = MAX(xh, 0);
- maxY = MIN(y0, H);
-
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
-
- if(-dp.x*ratio + dp.y < 0){ point.x = (point.y - y0) / ratio; }
- else{ point.y = point.x * ratio + y0; }
- } else {
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
- }
-
- rct.size.width = rct.size.width - (point.x - rct.origin.x);
- rct.size.height = point.y - rct.origin.y;
- rct.origin.x = point.x;
- break;
- }
- case 2: // upper right
- {
- minX = MAX(rct.origin.x + 0.1 * W, 0.1 * W);
- maxY = MAX((rct.origin.y + rct.size.height) - 0.1 * H, 0.1 * H);
-
- if (ratio!=0) {
- CGFloat y0 = rct.origin.y - ratio * (rct.origin.x + rct.size.width);
- CGFloat yw = ratio * W + y0;
- CGFloat x0 = -y0 / ratio;
- maxX = MIN(x0, W);
- minY = MAX(yw, 0);
-
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
-
- if(-dp.x*ratio + dp.y > 0){ point.x = (point.y - y0) / ratio; }
- else{ point.y = point.x * ratio + y0; }
- } else {
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
- }
-
- rct.size.width = point.x - rct.origin.x;
- rct.size.height = rct.size.height - (point.y - rct.origin.y);
- rct.origin.y = point.y;
- break;
- }
- case 3: // lower right
- {
- minX = MAX(rct.origin.x + 0.1 * W, 0.1 * W);
- minY = MAX(rct.origin.y + 0.1 * H, 0.1 * H);
-
- if (ratio!=0) {
- CGFloat y0 = (rct.origin.y + rct.size.height) - ratio * (rct.origin.x + rct.size.width);
- CGFloat yw = ratio * W + y0;
- CGFloat xh = (H - y0) / ratio;
- maxX = MIN(xh, W);
- maxY = MIN(yw, H);
-
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
-
- if(-dp.x*ratio + dp.y < 0){ point.x = (point.y - y0) / ratio; }
- else{ point.y = point.x * ratio + y0; }
- } else {
- point.x = MAX(minX, MIN(point.x, maxX));
- point.y = MAX(minY, MIN(point.y, maxY));
- }
-
- rct.size.width = point.x - rct.origin.x;
- rct.size.height = point.y - rct.origin.y;
- break;
- }
- default:
- break;
- }
- self.clippingRect = rct;
- }
- - (void)panGridView:(UIPanGestureRecognizer*)sender
- {
- if (_selectToolType != ZLImageEditTypeClip) {
- return;
- }
-
- static BOOL dragging = NO;
- static CGRect initialRect;
-
- if (sender.state==UIGestureRecognizerStateBegan) {
- CGPoint point = [sender locationInView:_imageView];
- dragging = CGRectContainsPoint(_clippingRect, point);
- initialRect = self.clippingRect;
- } else if(dragging) {
- CGPoint point = [sender translationInView:_imageView];
- CGFloat left = MIN(MAX(initialRect.origin.x + point.x, 0), _imageView.frame.size.width-initialRect.size.width);
- CGFloat top = MIN(MAX(initialRect.origin.y + point.y, 0), _imageView.frame.size.height-initialRect.size.height);
-
- CGRect rct = self.clippingRect;
- rct.origin.x = left;
- rct.origin.y = top;
- self.clippingRect = rct;
- }
- }
- #pragma mark - 裁剪
- - (UIImage *)clipImage
- {
- CGFloat zoomScale = _imageView.bounds.size.width / _imageView.image.size.width;
- CGRect rct = CGRectEqualToRect(self.clippingRect, CGRectZero) ? _imageView.bounds : self.clippingRect;
- rct.size.width /= zoomScale;
- rct.size.height /= zoomScale;
- rct.origin.x /= zoomScale;
- rct.origin.y /= zoomScale;
-
- CGPoint origin = CGPointMake(-rct.origin.x, -rct.origin.y);
- UIImage *img = nil;
-
- UIGraphicsBeginImageContextWithOptions(rct.size, NO, _imageView.image.scale);
- [_imageView.image drawAtPoint:origin];
- img = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
-
- return img;
- }
- - (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size
- {
- NSData *data = UIImageJPEGRepresentation(image, 1.0);
- return [self scaledlmageWithData:data withSize:size scale:1.0 orientation:image.imageOrientation];
- }
- - (UIImage *)scaledlmageWithData:(NSData *)data withSize:(CGSize)size scale:(CGFloat)scale orientation:(UIImageOrientation)orientation {
- CGFloat maxPixelSize = MAX(size.width, size.height);
- CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil);
- NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue,
- (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize]};
- CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
- UIImage *resultlmage = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
- CGImageRelease(imageRef);
- CFRelease(sourceRef);
- return resultlmage;
- }
- @end
|