Commit 3d2d8760 authored by banchichen's avatar banchichen

正式加入裁剪功能

parent c046af73
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "TZImagePickerController" s.name = "TZImagePickerController"
s.version = "1.7.1" s.version = "1.7.2"
s.summary = "A clone of UIImagePickerController, support picking multiple photos、original photo and video" s.summary = "A clone of UIImagePickerController, support picking multiple photos、original photo and video"
s.homepage = "https://github.com/banchichen/TZImagePickerController" s.homepage = "https://github.com/banchichen/TZImagePickerController"
s.license = "MIT" s.license = "MIT"
s.author = { "banchichen" => "tanzhenios@foxmail.com" } s.author = { "banchichen" => "tanzhenios@foxmail.com" }
s.platform = :ios s.platform = :ios
s.ios.deployment_target = "6.0" s.ios.deployment_target = "6.0"
s.source = { :git => "https://github.com/banchichen/TZImagePickerController.git", :tag => "1.7.1" } s.source = { :git => "https://github.com/banchichen/TZImagePickerController.git", :tag => "1.7.2" }
s.requires_arc = true s.requires_arc = true
s.resources = "TZImagePickerController/TZImagePickerController/*.{png,xib,nib,bundle}" s.resources = "TZImagePickerController/TZImagePickerController/*.{png,xib,nib,bundle}"
s.source_files = "TZImagePickerController/TZImagePickerController/*.{h,m}" s.source_files = "TZImagePickerController/TZImagePickerController/*.{h,m}"
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
6D32B9BD1CD83640005CE1E0 /* LxGridViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */; }; 6D32B9BD1CD83640005CE1E0 /* LxGridViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D32B9BC1CD83640005CE1E0 /* LxGridViewFlowLayout.m */; };
6D5358CD1D64600F00928CC6 /* NSBundle+TZImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */; }; 6D5358CD1D64600F00928CC6 /* NSBundle+TZImagePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */; };
6DC358661CC8BAFD00898D29 /* TZImagePickerController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */; }; 6DC358661CC8BAFD00898D29 /* TZImagePickerController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */; };
6DC84D0A1DF5358500A107A9 /* TZImageCropManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DC84D091DF5358500A107A9 /* TZImageCropManager.m */; };
900E65811C2BB8D5003D9A9E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65801C2BB8D5003D9A9E /* main.m */; }; 900E65811C2BB8D5003D9A9E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65801C2BB8D5003D9A9E /* main.m */; };
900E65841C2BB8D5003D9A9E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65831C2BB8D5003D9A9E /* AppDelegate.m */; }; 900E65841C2BB8D5003D9A9E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65831C2BB8D5003D9A9E /* AppDelegate.m */; };
900E65871C2BB8D5003D9A9E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65861C2BB8D5003D9A9E /* ViewController.m */; }; 900E65871C2BB8D5003D9A9E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E65861C2BB8D5003D9A9E /* ViewController.m */; };
...@@ -55,6 +56,8 @@ ...@@ -55,6 +56,8 @@
6D5358CB1D64600F00928CC6 /* NSBundle+TZImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+TZImagePicker.h"; sourceTree = "<group>"; }; 6D5358CB1D64600F00928CC6 /* NSBundle+TZImagePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+TZImagePicker.h"; sourceTree = "<group>"; };
6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+TZImagePicker.m"; sourceTree = "<group>"; }; 6D5358CC1D64600F00928CC6 /* NSBundle+TZImagePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+TZImagePicker.m"; sourceTree = "<group>"; };
6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TZImagePickerController.bundle; sourceTree = "<group>"; }; 6DC358651CC8BAFD00898D29 /* TZImagePickerController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TZImagePickerController.bundle; sourceTree = "<group>"; };
6DC84D081DF5358500A107A9 /* TZImageCropManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZImageCropManager.h; sourceTree = "<group>"; };
6DC84D091DF5358500A107A9 /* TZImageCropManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZImageCropManager.m; sourceTree = "<group>"; };
900E657C1C2BB8D5003D9A9E /* TZImagePickerController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TZImagePickerController.app; sourceTree = BUILT_PRODUCTS_DIR; }; 900E657C1C2BB8D5003D9A9E /* TZImagePickerController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TZImagePickerController.app; sourceTree = BUILT_PRODUCTS_DIR; };
900E65801C2BB8D5003D9A9E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; 900E65801C2BB8D5003D9A9E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
900E65821C2BB8D5003D9A9E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; 900E65821C2BB8D5003D9A9E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
...@@ -196,8 +199,6 @@ ...@@ -196,8 +199,6 @@
900EEFF51C2BBF7600EA709B /* TZImagePickerController */ = { 900EEFF51C2BBF7600EA709B /* TZImagePickerController */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
90CE84AC1C3A89EF003D0779 /* TZImageManager.h */,
90CE84AD1C3A89EF003D0779 /* TZImageManager.m */,
900EEFF61C2BBF9500EA709B /* TZImagePickerController.h */, 900EEFF61C2BBF9500EA709B /* TZImagePickerController.h */,
900EEFF71C2BBF9500EA709B /* TZImagePickerController.m */, 900EEFF71C2BBF9500EA709B /* TZImagePickerController.m */,
900EEFFC1C2BD58B00EA709B /* TZPhotoPickerController.h */, 900EEFFC1C2BD58B00EA709B /* TZPhotoPickerController.h */,
...@@ -212,6 +213,10 @@ ...@@ -212,6 +213,10 @@
900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */, 900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */,
90CE84B51C3BABB6003D0779 /* TZVideoPlayerController.h */, 90CE84B51C3BABB6003D0779 /* TZVideoPlayerController.h */,
90CE84B61C3BABB6003D0779 /* TZVideoPlayerController.m */, 90CE84B61C3BABB6003D0779 /* TZVideoPlayerController.m */,
90CE84AC1C3A89EF003D0779 /* TZImageManager.h */,
90CE84AD1C3A89EF003D0779 /* TZImageManager.m */,
6DC84D081DF5358500A107A9 /* TZImageCropManager.h */,
6DC84D091DF5358500A107A9 /* TZImageCropManager.m */,
90EBF5D41C2E298000CB9BCC /* UIView+Layout.h */, 90EBF5D41C2E298000CB9BCC /* UIView+Layout.h */,
90EBF5D51C2E298000CB9BCC /* UIView+Layout.m */, 90EBF5D51C2E298000CB9BCC /* UIView+Layout.m */,
6D5358CB1D64600F00928CC6 /* NSBundle+TZImagePicker.h */, 6D5358CB1D64600F00928CC6 /* NSBundle+TZImagePicker.h */,
...@@ -368,6 +373,7 @@ ...@@ -368,6 +373,7 @@
900EF0121C2C107400EA709B /* TZPhotoPreviewController.m in Sources */, 900EF0121C2C107400EA709B /* TZPhotoPreviewController.m in Sources */,
6D5358CD1D64600F00928CC6 /* NSBundle+TZImagePicker.m in Sources */, 6D5358CD1D64600F00928CC6 /* NSBundle+TZImagePicker.m in Sources */,
900EEFF81C2BBF9500EA709B /* TZImagePickerController.m in Sources */, 900EEFF81C2BBF9500EA709B /* TZImagePickerController.m in Sources */,
6DC84D0A1DF5358500A107A9 /* TZImageCropManager.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
......
//
// TZImageCropManager.h
// TZImagePickerController
//
// Created by 谭真 on 2016/12/5.
// Copyright © 2016年 谭真. All rights reserved.
// 图片裁剪管理类
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TZImageCropManager : NSObject
/// 裁剪框背景的处理
+ (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView;
/*
1.7.2 为了解决多位同学对于图片裁剪的需求,我这两天有空便在研究图片裁剪
幸好有tuyou的PhotoTweaks库做参考,裁剪的功能实现起来简单许多
该方法和其内部引用的方法基本来自于tuyou的PhotoTweaks库,我做了稍许删减和修改
感谢tuyou同学在github开源了优秀的裁剪库PhotoTweaks,表示感谢
PhotoTweaks库的github链接:https://github.com/itouch2/PhotoTweaks
*/
/// 获得裁剪后的图片
+ (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView;
@end
//
// TZImageCropManager.m
// TZImagePickerController
//
// Created by 谭真 on 2016/12/5.
// Copyright © 2016年 谭真. All rights reserved.
//
#import "TZImageCropManager.h"
#import "UIView+Layout.h"
@implementation TZImageCropManager
/// 裁剪框背景的处理
+ (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView {
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGMutablePathRef path = CGPathCreateMutable();
// Left side of _cropBgView
CGPathAddRect(path, nil, CGRectMake(0, 0, cropRect.origin.x, containerView.tz_height));
// Right side of _cropBgView
CGPathAddRect(path, nil, CGRectMake(CGRectGetMaxX(cropRect), 0, view.tz_width - cropRect.origin.x - cropRect.size.width, containerView.tz_height));
// Top side of _cropBgView
CGPathAddRect(path, nil, CGRectMake(0, 0, view.tz_width, cropRect.origin.y));
// Bottom side _cropBgView
CGPathAddRect(path, nil, CGRectMake(0, CGRectGetMaxY(cropRect), view.tz_width, containerView.tz_height - cropRect.origin.y + cropRect.size.height));
maskLayer.path = path;
view.layer.mask = maskLayer;
CGPathRelease(path);
}
/// 获得裁剪后的图片
+ (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView {
CGAffineTransform transform = CGAffineTransformIdentity;
// 平移的处理
CGRect imageViewRect = [imageView convertRect:imageView.bounds toView:containerView];
CGPoint point = CGPointMake(imageViewRect.origin.x + imageViewRect.size.width / 2, imageViewRect.origin.y + imageViewRect.size.height / 2);
CGFloat xMargin = containerView.tz_width - CGRectGetMaxX(rect) - rect.origin.x;
CGPoint zeroPoint = CGPointMake((CGRectGetWidth(containerView.frame) - xMargin) / 2, containerView.center.y);
CGPoint translation = CGPointMake(point.x - zeroPoint.x, point.y - zeroPoint.y);
transform = CGAffineTransformTranslate(transform, translation.x, translation.y);
// 缩放的处理
transform = CGAffineTransformScale(transform, zoomScale, zoomScale);
CGImageRef imageRef = [self newTransformedImage:transform
sourceImage:imageView.image.CGImage
sourceSize:imageView.image.size
outputWidth:imageView.image.size.width
cropSize:rect.size
imageViewSize:imageView.frame.size];
UIImage *cropedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return cropedImage;
}
+ (CGImageRef)newTransformedImage:(CGAffineTransform)transform sourceImage:(CGImageRef)sourceImage sourceSize:(CGSize)sourceSize outputWidth:(CGFloat)outputWidth cropSize:(CGSize)cropSize imageViewSize:(CGSize)imageViewSize {
CGImageRef source = [self newScaledImage:sourceImage toSize:sourceSize];
CGFloat aspect = cropSize.height/cropSize.width;
CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect);
CGContextRef context = CGBitmapContextCreate(NULL, outputSize.width, outputSize.height, CGImageGetBitsPerComponent(source), 0, CGImageGetColorSpace(source), CGImageGetBitmapInfo(source));
CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height));
CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width / cropSize.width, outputSize.height / cropSize.height);
uiCoords = CGAffineTransformTranslate(uiCoords, cropSize.width/2.0, cropSize.height / 2.0);
uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0);
CGContextConcatCTM(context, uiCoords);
CGContextConcatCTM(context, transform);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2, -imageViewSize.height/2.0, imageViewSize.width, imageViewSize.height), source);
CGImageRef resultRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGImageRelease(source);
return resultRef;
}
+ (CGImageRef)newScaledImage:(CGImageRef)source toSize:(CGSize)size {
CGSize srcSize = size;
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(rgbColorSpace);
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextTranslateCTM(context, size.width/2, size.height/2);
CGContextDrawImage(context, CGRectMake(-srcSize.width/2, -srcSize.height/2, srcSize.width, srcSize.height), source);
CGImageRef resultRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
return resultRef;
}
@end
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// //
// Created by 谭真 on 16/1/4. // Created by 谭真 on 16/1/4.
// Copyright © 2016年 谭真. All rights reserved. // Copyright © 2016年 谭真. All rights reserved.
// // 图片资源获取管理类
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// //
// Created by 谭真 on 15/12/24. // Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved. // Copyright © 2015年 谭真. All rights reserved.
// version 1.7.2 - 2016.12.2 // version 1.7.2 - 2016.12.5
/* /*
经过测试,比起xib的方式,把TZAssetCell改用纯代码的方式来写,滑动帧数明显提高了(约提高10帧左右) 经过测试,比起xib的方式,把TZAssetCell改用纯代码的方式来写,滑动帧数明显提高了(约提高10帧左右)
...@@ -97,6 +97,7 @@ ...@@ -97,6 +97,7 @@
@property (nonatomic, assign) BOOL showSelectBtn; ///< 在单选模式下,照片列表页中,显示选择按钮,默认为NO @property (nonatomic, assign) BOOL showSelectBtn; ///< 在单选模式下,照片列表页中,显示选择按钮,默认为NO
@property (nonatomic, assign) BOOL allowCrop; ///< 允许裁剪,默认为YES,showSelectBtn为NO才生效 @property (nonatomic, assign) BOOL allowCrop; ///< 允许裁剪,默认为YES,showSelectBtn为NO才生效
@property (nonatomic, assign) CGRect cropRect; ///< 裁剪框的尺寸 @property (nonatomic, assign) CGRect cropRect; ///< 裁剪框的尺寸
@property (nonatomic, copy) void (^cropViewSettingBlock)(UIView *cropView); ///< 自定义裁剪框的其他属性
- (void)showAlertWithTitle:(NSString *)title; - (void)showAlertWithTitle:(NSString *)title;
- (void)showProgressHUD; - (void)showProgressHUD;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// //
// Created by 谭真 on 15/12/24. // Created by 谭真 on 15/12/24.
// Copyright © 2015年 谭真. All rights reserved. // Copyright © 2015年 谭真. All rights reserved.
// version 1.7.2 - 2016.12.2 // version 1.7.2 - 2016.12.5
#import "TZImagePickerController.h" #import "TZImagePickerController.h"
#import "TZPhotoPickerController.h" #import "TZPhotoPickerController.h"
...@@ -278,6 +278,7 @@ ...@@ -278,6 +278,7 @@
_maxImagesCount = maxImagesCount; _maxImagesCount = maxImagesCount;
if (maxImagesCount > 1) { if (maxImagesCount > 1) {
_showSelectBtn = YES; _showSelectBtn = YES;
_allowCrop = NO;
} }
} }
...@@ -290,7 +291,7 @@ ...@@ -290,7 +291,7 @@
} }
- (void)setAllowCrop:(BOOL)allowCrop { - (void)setAllowCrop:(BOOL)allowCrop {
_allowCrop = allowCrop; _allowCrop = _maxImagesCount > 1 ? NO : allowCrop;
if (allowCrop) { // 允许裁剪的时候,不能选原图 if (allowCrop) { // 允许裁剪的时候,不能选原图
self.allowPickingOriginalPhoto = NO; self.allowPickingOriginalPhoto = NO;
} }
...@@ -300,8 +301,8 @@ ...@@ -300,8 +301,8 @@
if (_cropRect.size.width > 0) { if (_cropRect.size.width > 0) {
return _cropRect; return _cropRect;
} }
CGFloat cropViewWH = self.view.tz_width - 2; CGFloat cropViewWH = self.view.tz_width;
return CGRectMake(1, (self.view.tz_height - self.view.tz_width) / 2, cropViewWH, cropViewWH); return CGRectMake(0, (self.view.tz_height - self.view.tz_width) / 2, cropViewWH, cropViewWH);
} }
- (void)setTimeout:(NSInteger)timeout { - (void)setTimeout:(NSInteger)timeout {
......
...@@ -91,20 +91,43 @@ ...@@ -91,20 +91,43 @@
_imageContainerView.tz_height = self.tz_height; _imageContainerView.tz_height = self.tz_height;
} }
CGFloat contentSizeH = MAX(_imageContainerView.tz_height, self.tz_height); CGFloat contentSizeH = MAX(_imageContainerView.tz_height, self.tz_height);
if (_allowCrop) {
_scrollView.contentSize = CGSizeMake(self.scrollView.tz_width, contentSizeH);
} else {
_scrollView.contentSize = CGSizeMake(self.scrollView.tz_width, contentSizeH); _scrollView.contentSize = CGSizeMake(self.scrollView.tz_width, contentSizeH);
}
[_scrollView scrollRectToVisible:self.bounds animated:NO]; [_scrollView scrollRectToVisible:self.bounds animated:NO];
_scrollView.alwaysBounceVertical = _imageContainerView.tz_height <= self.tz_height ? NO : YES; _scrollView.alwaysBounceVertical = _imageContainerView.tz_height <= self.tz_height ? NO : YES;
_imageView.frame = _imageContainerView.bounds; _imageView.frame = _imageContainerView.bounds;
[self refreshScrollViewContentSize];
}
- (void)setAllowCrop:(BOOL)allowCrop {
_allowCrop = allowCrop;
_scrollView.maximumZoomScale = allowCrop ? 4.0 : 2.5;
}
- (void)refreshScrollViewContentSize {
if (_allowCrop) {
// 1.7.2 如果允许裁剪,需要让图片的任意部分都能在裁剪框内,于是对_scrollView做了如下处理:
// 1.让contentSize增大(裁剪框右下角的图片部分)
CGFloat contentWidthAdd = self.scrollView.tz_width - CGRectGetMaxX(_cropRect);
CGFloat contentHeightAdd = (MIN(_imageContainerView.tz_height, self.tz_height) - self.cropRect.size.height) / 2;
CGFloat newSizeW = self.scrollView.contentSize.width + contentWidthAdd;
CGFloat newSizeH = MAX(self.scrollView.contentSize.height, self.tz_height) + contentHeightAdd;
_scrollView.contentSize = CGSizeMake(newSizeW, newSizeH);
_scrollView.alwaysBounceVertical = YES;
// 2.让scrollView新增滑动区域(裁剪框左上角的图片部分)
if (contentHeightAdd > 0) {
_scrollView.contentInset = UIEdgeInsetsMake(contentHeightAdd, _cropRect.origin.x, 0, 0);
} else {
_scrollView.contentInset = UIEdgeInsetsZero;
}
}
} }
#pragma mark - UITapGestureRecognizer Event #pragma mark - UITapGestureRecognizer Event
- (void)doubleTap:(UITapGestureRecognizer *)tap { - (void)doubleTap:(UITapGestureRecognizer *)tap {
if (_scrollView.zoomScale > 1.0) { if (_scrollView.zoomScale > 1.0) {
_scrollView.contentInset = UIEdgeInsetsZero;
[_scrollView setZoomScale:1.0 animated:YES]; [_scrollView setZoomScale:1.0 animated:YES];
} else { } else {
CGPoint touchPoint = [tap locationInView:self.imageView]; CGPoint touchPoint = [tap locationInView:self.imageView];
...@@ -127,14 +150,24 @@ ...@@ -127,14 +150,24 @@
return _imageContainerView; return _imageContainerView;
} }
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
scrollView.contentInset = UIEdgeInsetsZero;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView { - (void)scrollViewDidZoom:(UIScrollView *)scrollView {
CGFloat offsetX = (scrollView.tz_width > scrollView.contentSize.width) ? (scrollView.tz_width - scrollView.contentSize.width) * 0.5 : 0.0; [self refreshImageContainerViewCenter];
CGFloat offsetY = (scrollView.tz_height > scrollView.contentSize.height) ? (scrollView.tz_height - scrollView.contentSize.height) * 0.5 : 0.0;
self.imageContainerView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, scrollView.contentSize.height * 0.5 + offsetY);
} }
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale { - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
[self refreshScrollViewContentSize];
}
#pragma mark - Private
- (void)refreshImageContainerViewCenter {
CGFloat offsetX = (_scrollView.tz_width > _scrollView.contentSize.width) ? ((_scrollView.tz_width - _scrollView.contentSize.width) * 0.5) : 0.0;
CGFloat offsetY = (_scrollView.tz_height > _scrollView.contentSize.height) ? ((_scrollView.tz_height - _scrollView.contentSize.height) * 0.5) : 0.0;
self.imageContainerView.center = CGPointMake(_scrollView.contentSize.width * 0.5 + offsetX, _scrollView.contentSize.height * 0.5 + offsetY);
} }
@end @end
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
#import "UIView+Layout.h" #import "UIView+Layout.h"
#import "TZImagePickerController.h" #import "TZImagePickerController.h"
#import "TZImageManager.h" #import "TZImageManager.h"
#import "TZImageCropManager.h"
@interface TZPhotoPreviewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UIScrollViewDelegate> { @interface TZPhotoPreviewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UIScrollViewDelegate> {
UICollectionView *_collectionView; UICollectionView *_collectionView;
BOOL _isHideNaviBar;
NSArray *_photosTemp; NSArray *_photosTemp;
NSArray *_assetsTemp; NSArray *_assetsTemp;
...@@ -29,9 +29,10 @@ ...@@ -29,9 +29,10 @@
UILabel *_numberLable; UILabel *_numberLable;
UIButton *_originalPhotoButton; UIButton *_originalPhotoButton;
UILabel *_originalPhotoLable; UILabel *_originalPhotoLable;
UIView *_cropView;
} }
@property (nonatomic, assign) BOOL isHideNaviBar;
@property (nonatomic, strong) UIView *cropBgView;
@property (nonatomic, strong) UIView *cropView;
@end @end
@implementation TZPhotoPreviewController @implementation TZPhotoPreviewController
...@@ -46,8 +47,8 @@ ...@@ -46,8 +47,8 @@
self.isSelectOriginalPhoto = _tzImagePickerVc.isSelectOriginalPhoto; self.isSelectOriginalPhoto = _tzImagePickerVc.isSelectOriginalPhoto;
} }
[self configCollectionView]; [self configCollectionView];
[self configCustomNaviBar];
[self configCropView]; [self configCropView];
[self configCustomNaviBar];
[self configBottomToolBar]; [self configBottomToolBar];
self.view.clipsToBounds = YES; self.view.clipsToBounds = YES;
} }
...@@ -181,33 +182,26 @@ ...@@ -181,33 +182,26 @@
- (void)configCropView { - (void)configCropView {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
if (!_tzImagePickerVc.showSelectBtn && _tzImagePickerVc.allowCrop) { if (!_tzImagePickerVc.showSelectBtn && _tzImagePickerVc.allowCrop) {
_cropBgView = [UIView new];
_cropBgView.userInteractionEnabled = NO;
static CGFloat rgb = 34 / 255.0;
_cropBgView.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0];
_cropBgView.alpha = 0.5;
_cropBgView.frame = self.view.bounds;
[self.view addSubview:_cropBgView];
[TZImageCropManager overlayClippingWithView:_cropBgView cropRect:_tzImagePickerVc.cropRect containerView:self.view];
_cropView = [UIView new]; _cropView = [UIView new];
_cropView.userInteractionEnabled = NO; _cropView.userInteractionEnabled = NO;
static CGFloat rgb = 34 / 255.0; _cropView.backgroundColor = [UIColor clearColor];
_cropView.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0]; _cropView.frame = _tzImagePickerVc.cropRect;
_cropView.alpha = 0.5; _cropView.layer.borderColor = [UIColor whiteColor].CGColor;
_cropView.frame = self.view.bounds; _cropView.layer.borderWidth = 1.0;
[self.view addSubview:_cropView]; [self.view addSubview:_cropView];
if (_tzImagePickerVc.cropViewSettingBlock) {
[self overlayClipping]; _tzImagePickerVc.cropViewSettingBlock(_cropView);
}
} }
}
- (void)overlayClipping {
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGMutablePathRef path = CGPathCreateMutable();
// Left side of _cropView
CGPathAddRect(path, nil, CGRectMake(0, 0, _tzImagePickerVc.cropRect.origin.x, _cropView.tz_height));
// Right side of _cropView
CGPathAddRect(path, nil, CGRectMake(CGRectGetMaxX(_tzImagePickerVc.cropRect), 0, _cropView.tz_width - _tzImagePickerVc.cropRect.origin.x - _tzImagePickerVc.cropRect.size.width, _cropView.tz_height));
// Top side of _cropView
CGPathAddRect(path, nil, CGRectMake(0, 0, _cropView.tz_width, _tzImagePickerVc.cropRect.origin.y));
// Bottom side _cropView
CGPathAddRect(path, nil, CGRectMake(0, CGRectGetMaxY(_tzImagePickerVc.cropRect), _cropView.tz_width, _cropView.tz_height - _tzImagePickerVc.cropRect.origin.y + _tzImagePickerVc.cropRect.size.height));
maskLayer.path = path;
_cropView.layer.mask = maskLayer;
CGPathRelease(path);
} }
#pragma mark - Click Event #pragma mark - Click Event
...@@ -292,7 +286,7 @@ ...@@ -292,7 +286,7 @@
if (_tzImagePickerVc.allowCrop) { // 裁剪状态 if (_tzImagePickerVc.allowCrop) { // 裁剪状态
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:_currentIndex inSection:0]; NSIndexPath *indexPath = [NSIndexPath indexPathForItem:_currentIndex inSection:0];
TZPhotoPreviewCell *cell = (TZPhotoPreviewCell *)[_collectionView cellForItemAtIndexPath:indexPath]; TZPhotoPreviewCell *cell = (TZPhotoPreviewCell *)[_collectionView cellForItemAtIndexPath:indexPath];
UIImage *cropedImage = [self cropImageView:cell.imageView toRect:_tzImagePickerVc.cropRect zoomScale:cell.scrollView.zoomScale]; UIImage *cropedImage = [TZImageCropManager cropImageView:cell.imageView toRect:_tzImagePickerVc.cropRect zoomScale:cell.scrollView.zoomScale containerView:self.view];
if (self.doneButtonClickBlockCropMode) { if (self.doneButtonClickBlockCropMode) {
TZAssetModel *model = _models[_currentIndex]; TZAssetModel *model = _models[_currentIndex];
self.doneButtonClickBlockCropMode(cropedImage,model.asset); self.doneButtonClickBlockCropMode(cropedImage,model.asset);
...@@ -347,15 +341,15 @@ ...@@ -347,15 +341,15 @@
TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController; TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
cell.cropRect = _tzImagePickerVc.cropRect; cell.cropRect = _tzImagePickerVc.cropRect;
cell.allowCrop = _tzImagePickerVc.allowCrop; cell.allowCrop = _tzImagePickerVc.allowCrop;
__weak typeof(self) weakSelf = self;
if (!cell.singleTapGestureBlock) { if (!cell.singleTapGestureBlock) {
__block BOOL _weakIsHideNaviBar = _isHideNaviBar;
__weak typeof(_naviBar) weakNaviBar = _naviBar; __weak typeof(_naviBar) weakNaviBar = _naviBar;
__weak typeof(_toolBar) weakToolBar = _toolBar; __weak typeof(_toolBar) weakToolBar = _toolBar;
cell.singleTapGestureBlock = ^(){ cell.singleTapGestureBlock = ^(){
// show or hide naviBar / 显示或隐藏导航栏 // show or hide naviBar / 显示或隐藏导航栏
_weakIsHideNaviBar = !_weakIsHideNaviBar; weakSelf.isHideNaviBar = !weakSelf.isHideNaviBar;
weakNaviBar.hidden = _weakIsHideNaviBar; weakNaviBar.hidden = weakSelf.isHideNaviBar;
weakToolBar.hidden = _weakIsHideNaviBar; weakToolBar.hidden = weakSelf.isHideNaviBar;
}; };
} }
return cell; return cell;
...@@ -422,61 +416,4 @@ ...@@ -422,61 +416,4 @@
}]; }];
} }
#pragma mark - Crop
- (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale {
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, zoomScale, zoomScale);
CGImageRef imageRef = [self newTransformedImage:transform
sourceImage:imageView.image.CGImage
sourceSize:imageView.image.size
outputWidth:imageView.image.size.width
cropSize:rect.size
imageViewSize:imageView.frame.size];
UIImage *cropedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return cropedImage;
}
- (CGImageRef)newTransformedImage:(CGAffineTransform)transform sourceImage:(CGImageRef)sourceImage sourceSize:(CGSize)sourceSize outputWidth:(CGFloat)outputWidth cropSize:(CGSize)cropSize imageViewSize:(CGSize)imageViewSize {
CGImageRef source = [self newScaledImage:sourceImage toSize:sourceSize];
CGFloat aspect = cropSize.height/cropSize.width;
CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect);
CGContextRef context = CGBitmapContextCreate(NULL, outputSize.width, outputSize.height, CGImageGetBitsPerComponent(source), 0, CGImageGetColorSpace(source), CGImageGetBitmapInfo(source));
CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height));
CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width / cropSize.width, outputSize.height / cropSize.height);
uiCoords = CGAffineTransformTranslate(uiCoords, cropSize.width/2.0, cropSize.height / 2.0);
uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0);
CGContextConcatCTM(context, uiCoords);
CGContextConcatCTM(context, transform);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2.0, -imageViewSize.height/2.0, imageViewSize.width, imageViewSize.height), source);
CGImageRef resultRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGImageRelease(source);
return resultRef;
}
- (CGImageRef)newScaledImage:(CGImageRef)source toSize:(CGSize)size {
CGSize srcSize = size;
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(rgbColorSpace);
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextTranslateCTM(context, size.width/2, size.height/2);
CGContextDrawImage(context, CGRectMake(-srcSize.width/2, -srcSize.height/2, srcSize.width, srcSize.height), source);
CGImageRef resultRef = CGBitmapContextCreateImage(context);
CGContextRelease(context);
return resultRef;
}
@end @end
...@@ -231,8 +231,12 @@ ...@@ -231,8 +231,12 @@
/// 5. 单选模式,maxImagesCount为1时才生效 /// 5. 单选模式,maxImagesCount为1时才生效
imagePickerVc.showSelectBtn = NO; imagePickerVc.showSelectBtn = NO;
imagePickerVc.allowCrop = YES; imagePickerVc.allowCrop = YES;
NSInteger cropWH = self.view.tz_width - 40; // NSInteger cropWH = self.view.tz_width - 150;
imagePickerVc.cropRect = CGRectMake(20, (self.view.tz_height - cropWH) / 2 + 50, cropWH, cropWH - 100); // imagePickerVc.cropRect = CGRectMake(20, (self.view.tz_height - cropWH) / 2 + 50, cropWH, cropWH - 100);
[imagePickerVc setCropViewSettingBlock:^(UIView *cropView) {
cropView.layer.borderColor = [UIColor redColor].CGColor;
cropView.layer.borderWidth = 2.0;
}];
#pragma mark - 到这里为止 #pragma mark - 到这里为止
// You can get the photos by block, the same as by delegate. // You can get the photos by block, the same as by delegate.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment