Commit e69396e3194e1955a4342113964d82795bbf1ec9

Authored by 梁星国
1 parent 506347e9

提交创建

Showing 71 changed files with 74 additions and 4767 deletions

Too many changes to show.

To preserve performance only 71 of 109 files are displayed.

.gitignore 0 → 100644
  1 +# OS X
  2 +.DS_Store
  3 +
  4 +# Xcode
  5 +build/
  6 +Products/
  7 +*.pbxuser
  8 +!default.pbxuser
  9 +*.mode1v3
  10 +!default.mode1v3
  11 +*.mode2v3
  12 +!default.mode2v3
  13 +*.perspectivev3
  14 +!default.perspectivev3
  15 +xcuserdata/
  16 +*.xccheckout
  17 +profile
  18 +*.moved-aside
  19 +DerivedData
  20 +*.hmap
  21 +*.ipa
  22 +
  23 +# Bundler
  24 +.bundle
  25 +
  26 +# Add this line if you want to avoid checking in source code from Carthage dependencies.
  27 +# Carthage/Checkouts
  28 +
  29 +Carthage/Build
  30 +
  31 +# We recommend against adding the Pods directory to your .gitignore. However
  32 +# you should judge for yourself, the pros and cons are mentioned at:
  33 +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
  34 +#
  35 +# Note: if you ignore the Pods directory, make sure to uncomment
  36 +# `pod install` in .travis.yml
  37 +#
  38 +# Pods/
... ...
CNLiveImagePickerController.podspec
1 1 #
2   -# Be sure to run `pod spec lint CNLiveImagePickerController.podspec' to ensure this is a
3   -# valid spec and to remove all comments including this before submitting the spec.
  2 +# Be sure to run `pod lib lint CNLiveImagePickerController.podspec' to ensure this is a
  3 +# valid spec before submitting.
4 4 #
5   -# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
6   -# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
  5 +# Any lines starting with a # are optional, but their use is encouraged
  6 +# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
7 7 #
8 8  
9 9 Pod::Spec.new do |s|
10   -
11   -#
12   - # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
13   - #
14   - # These will help people to find your library, and whilst it
15   - # can feel like a chore to fill in it's definitely to your advantage. The
16   - # summary should be tweet-length, and the description more in depth.
17   - #
18   -
19   - s.name = "CNLiveImagePickerController" # 项目名称
20   - s.version = "0.0.2" # 版本号 与 你仓库的 标签号 对应
21   - s.summary = "相册选择基于TZImagePickerController" # 项目简介
22   -
23   - # This description is used to generate tags and improve search results.
24   - # * Think: What does it do? Why did you write it? What is the focus?
25   - # * Try to keep it short, snappy and to the point.
26   - # * Write the description between the DESC delimiters below.
27   - # * Finally, don't worry about the indent, CocoaPods strips it!
28   - s.description = <<-DESC
29   - 1.相册选择图片,视频
30   - 2.更改了相册适配问题
31   - DESC
32   -
33   - s.homepage = "http://bj.gitlab.cnlive.com/ios-team/CNLiveImagePickerController"
34   -
35   - # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
36   -
37   -
38   - # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
39   - #
40   - # Licensing your code is important. See http://choosealicense.com for more info.
41   - # CocoaPods will detect a license file if there is a named LICENSE*
42   - # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
43   - #
44   -
45   - s.license = "MIT" # 开源证书
46   - # s.license = { :type => "MIT", :file => "FILE_LICENSE" }
47   -
48   -
49   - # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
50   - #
51   - # Specify the authors of the library, with email addresses. Email addresses
52   - # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
53   - # accepts just a name if you'd rather not provide an email address.
54   - #
55   - # Specify a social_media_url where others can refer to, for example a twitter
56   - # profile URL.
57   - #
58   -
59   - s.author = { "梁星国" => "liangxingguo@cnlive.com" }
60   - # Or just: s.author = "梁星国"
61   - # s.authors = { "梁星国" => "jyyjkt@qq.com" }
62   - # s.social_media_url = "http://twitter.com/梁星国"
63   -
64   - # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
65   - #
66   - # If this Pod runs only on iOS or OS X, then specify the platform and
67   - # the deployment target. You can optionally include the target after the platform.
68   - #
69   -
70   - # s.platform = :ios
71   - s.platform = :ios, "9.0"
72   -
73   - # When using multiple platforms
74   - # s.ios.deployment_target = "5.0"
75   - # s.osx.deployment_target = "10.7"
76   - # s.watchos.deployment_target = "2.0"
77   - # s.tvos.deployment_target = "9.0"
78   -
79   -
80   - # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
81   - #
82   - # Specify the location from where the source should be retrieved.
83   - # Supports git, hg, bzr, svn and HTTP.
84   - #
85   -
86   - s.source = { :git => "http://bj.gitlab.cnlive.com/ios-team/CNLiveImagePickerController.git", :tag => "#{s.version}" } #你的仓库地址
87   -
88   -
89   - # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
90   - #
91   - # CocoaPods is smart about how it includes source code. For source files
92   - # giving a folder will include any swift, h, m, mm, c & cpp files.
93   - # For header files it will include any header in the folder.
94   - # Not including the public_header_files will make all headers public.
95   - #
96   -
97   - s.source_files = "CNLiveImagePickerController/*"
98   - s.exclude_files = "Classes/Exclude"
99   -
100   - # s.public_header_files = "Classes/**/*.h"
101   -
102   -
103   - # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
104   - #
105   - # A list of resources included with the Pod. These are copied into the
106   - # target bundle with a build phase script. Anything else will be cleaned.
107   - # You can preserve files from being cleaned, please don't preserve
108   - # non-essential files like tests, examples and documentation.
109   - #
110   -
111   - # s.resource = "icon.png"
112   - # s.resources = "Resources/*.png"
113   -
114   - # s.preserve_paths = "FilesToSave", "MoreFilesToSave"
115   -
116   -
117   - # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
118   - #
119   - # Link your library with frameworks, or libraries. Libraries do not include
120   - # the lib prefix of their name.
121   - #
122   -
123   - # s.framework = "SomeFramework"
124   - s.frameworks = "UIKit", "Foundation" #支持的框架
125   -
126   - # s.library = "iconv"
127   - # s.libraries = "iconv", "xml2"
128   -
129   -
130   - # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
131   - #
132   - # If your library depends on compiler flags you can set them in the xcconfig hash
133   - # where they will only apply to your library. If you depend on other Podspecs
134   - # you can include multiple dependencies to ensure it works.
135   -
136   - s.requires_arc = true
137   -
138   - # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
139   - # s.dependency "JSONKit", "~> 1.4"
140   -
  10 + s.name = 'CNLiveImagePickerController'
  11 + s.version = '0.1.0'
  12 + s.summary = 'A short description of CNLiveImagePickerController.'
  13 +
  14 +# This description is used to generate tags and improve search results.
  15 +# * Think: What does it do? Why did you write it? What is the focus?
  16 +# * Try to keep it short, snappy and to the point.
  17 +# * Write the description between the DESC delimiters below.
  18 +# * Finally, don't worry about the indent, CocoaPods strips it!
  19 +
  20 + s.description = <<-DESC
  21 +TODO: Add long description of the pod here.
  22 + DESC
  23 +
  24 + s.homepage = 'https://github.com/jyyjkt/CNLiveImagePickerController'
  25 + # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  26 + s.license = { :type => 'MIT', :file => 'LICENSE' }
  27 + s.author = { 'jyyjkt' => 'jyyjkt@qq.com' }
  28 + s.source = { :git => 'https://github.com/jyyjkt/CNLiveImagePickerController.git', :tag => s.version.to_s }
  29 + # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
  30 +
  31 + s.ios.deployment_target = '8.0'
  32 +
  33 + s.source_files = 'CNLiveImagePickerController/Classes/**/*'
  34 +
  35 + # s.resource_bundles = {
  36 + # 'CNLiveImagePickerController' => ['CNLiveImagePickerController/Assets/*.png']
  37 + # }
  38 +
  39 + # s.public_header_files = 'Pod/Classes/**/*.h'
  40 + # s.frameworks = 'UIKit', 'MapKit'
  41 + # s.dependency 'AFNetworking', '~> 2.3'
141 42 end
... ...
CNLiveImagePickerController/Assets/.gitkeep 0 → 100644
CNLiveImagePickerController/CNEditVideoController.h deleted 100755 → 0
1   -//
2   -// ZLEditVideoController.h
3   -// ZLPhotoBrowser
4   -//
5   -// Created by long on 2017/9/15.
6   -// Copyright © 2017年 long. All rights reserved.
7   -//
8   -
9   -#import <UIKit/UIKit.h>
10   -
11   -@class TZAssetModel;
12   -
13   -@interface CNEditVideoController : UIViewController
14   -
15   -@property (nonatomic, strong) TZAssetModel *model;
16   -
17   -@property (nonatomic, strong) NSMutableArray *models; ///< All photo models / 所有图片模型数组
18   -@property (nonatomic, strong) NSMutableArray *photos; ///< All photos / 所有图片数组
19   -@property (nonatomic, assign) NSInteger currentIndex;
20   -@property (nonatomic, assign) BOOL isCropImage;
21   -
22   -/// Return the new selected photos / 返回最新的选中图片数组
23   -@property (nonatomic, copy) void (^backButtonEditClickBlock)(BOOL isSelectOriginalPhoto);
24   -@property (nonatomic, copy) void (^doneButtonEditClickBlock)(BOOL isSelectOriginalPhoto);
25   -
26   -
27   -@end
CNLiveImagePickerController/CNEditVideoController.m deleted 100755 → 0
1   -//
2   -// ZLEditVideoController.m
3   -// ZLPhotoBrowser
4   -//
5   -// Created by long on 2017/9/15.
6   -// Copyright © 2017年 long. All rights reserved.
7   -//
8   -
9   -#import "CNEditVideoController.h"
10   -#import <AVFoundation/AVFoundation.h>
11   -#import "TZAssetModel.h"
12   -#import <objc/runtime.h>
13   -#import <AssetsLibrary/AssetsLibrary.h>
14   -#import "TZImagePickerController.h"
15   -#import "TZPhotoPreviewCell.h"
16   -#import "TZImageCropManager.h"
17   -
18   -#define kItemWidth kItemHeight * 2/3
19   -#define kItemHeight 50
20   -#define kAPPName @"网++"
21   -
22   -#pragma mark - 显示帧数的CNEditFrameView
23   -
24   -@interface CNEditVideoCell : UICollectionViewCell
25   -
26   -@property (nonatomic, strong) UIImageView *imageView;
27   -
28   -@end
29   -
30   -@implementation CNEditVideoCell
31   -
32   -- (UIImageView *)imageView
33   -{
34   - if (!_imageView) {
35   - _imageView = [[UIImageView alloc] init];
36   - _imageView.frame = self.bounds;
37   - _imageView.contentMode = UIViewContentModeScaleAspectFill;
38   - _imageView.clipsToBounds = YES;
39   - [self.contentView addSubview:_imageView];
40   - }
41   - return _imageView;
42   -}
43   -
44   -@end
45   -
46   -#pragma mark - 协议编辑帧数协议CNEditFrameViewDelegate
47   -@protocol CNEditFrameViewDelegate <NSObject>
48   -
49   -- (void)editViewValidRectChanged;//有效范围更变
50   -
51   -- (void)editViewValidRectEndChanged;//有效范围更变结束
52   -
53   -@end
54   -
55   -#pragma mark - 编辑时视图CNEditFrameView
56   -@interface CNEditFrameView : UIView
57   -{
58   - UIImageView *_leftView;//左视图
59   - UIImageView *_rightView;//有视图
60   -}
61   -
62   -@property (nonatomic, assign) CGRect validRect;
63   -@property (nonatomic, weak) id<CNEditFrameViewDelegate> delegate;
64   -
65   -@end
66   -
67   -@implementation CNEditFrameView
68   -
69   -- (instancetype)init
70   -{
71   - self = [super init];
72   - if (self) {
73   - [self setupUI];
74   - }
75   - return self;
76   -}
77   -
78   -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
79   -{
80   - //扩大下有效范围
81   - CGRect left = _leftView.frame;
82   - left.origin.x -= kItemWidth/2;
83   - left.size.width += kItemWidth/2;
84   - CGRect right = _rightView.frame;
85   - right.size.width += kItemWidth/2;
86   -
87   - if (CGRectContainsPoint(left, point)) {
88   - return _leftView;
89   - }
90   - if (CGRectContainsPoint(right, point)) {
91   - return _rightView;
92   - }
93   - return nil;
94   -}
95   -
96   -- (void)setupUI
97   -{
98   - self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:.5];
99   - self.layer.borderWidth = 2;
100   - self.layer.borderColor = [UIColor clearColor].CGColor;
101   -
102   - _leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"video_edit_left"]];
103   - _leftView.userInteractionEnabled = YES;
104   - _leftView.tag = 0;
105   - UIPanGestureRecognizer *lg = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
106   - [_leftView addGestureRecognizer:lg];
107   - [self addSubview:_leftView];
108   -
109   - _rightView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"video_edit_right"]];
110   - _rightView.userInteractionEnabled = YES;
111   - _rightView.tag = 1;
112   - UIPanGestureRecognizer *rg = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
113   - [_rightView addGestureRecognizer:rg];
114   - [self addSubview:_rightView];
115   -}
116   -
117   -- (void)panAction:(UIGestureRecognizer *)pan //滑动收拾实现
118   -{
119   - self.layer.borderColor = [[UIColor whiteColor] colorWithAlphaComponent:.4].CGColor;
120   - CGPoint point = [pan locationInView:self];
121   -
122   - CGRect rct = self.validRect;
123   -
124   - const CGFloat W = self.frame.size.width;
125   - CGFloat minX = 0;
126   - CGFloat maxX = W;
127   -
128   - switch (pan.view.tag) {
129   - case 0: {
130   - //left视图响应
131   - maxX = rct.origin.x + rct.size.width - kItemWidth;
132   -
133   - point.x = MAX(minX, MIN(point.x, maxX));
134   - point.y = 0;
135   -
136   - rct.size.width -= (point.x - rct.origin.x);
137   - rct.origin.x = point.x;
138   - }
139   - break;
140   -
141   - case 1:
142   - {
143   - //right视图响应
144   - minX = rct.origin.x + kItemWidth/2;
145   - maxX = W - kItemWidth/2;
146   -
147   - point.x = MAX(minX, MIN(point.x, maxX));
148   - point.y = 0;
149   -
150   - rct.size.width = (point.x - rct.origin.x + kItemWidth/2);
151   - }
152   - break;
153   - }
154   -
155   - switch (pan.state) {
156   - case UIGestureRecognizerStateBegan:
157   - case UIGestureRecognizerStateChanged:
158   - if (self.delegate && [self.delegate respondsToSelector:@selector(editViewValidRectChanged)]) {
159   - [self.delegate editViewValidRectChanged];//滑动响应实现
160   - }
161   - break;
162   -
163   - case UIGestureRecognizerStateEnded:
164   - case UIGestureRecognizerStateCancelled:
165   - self.layer.borderColor = [UIColor clearColor].CGColor;
166   - if (self.delegate && [self.delegate respondsToSelector:@selector(editViewValidRectEndChanged)]) {
167   - [self.delegate editViewValidRectEndChanged];//滑动结束响应实现
168   - }
169   - break;
170   -
171   - default:
172   - break;
173   - }
174   -
175   -
176   - self.validRect = rct;
177   -}
178   -
179   -- (void)setValidRect:(CGRect)validRect//根据范围
180   -{
181   - _validRect = validRect;
182   - _leftView.frame = CGRectMake(validRect.origin.x - kItemWidth/4, 0, kItemWidth/2, kItemHeight);
183   - _rightView.frame = CGRectMake(validRect.origin.x+validRect.size.width-kItemWidth/4, 0, kItemWidth/2, kItemHeight);
184   -
185   - [self setNeedsDisplay];
186   -}
187   -
188   -- (void)drawRect:(CGRect)rect
189   -{
190   - CGContextRef context = UIGraphicsGetCurrentContext();
191   -
192   - CGContextClearRect(context, self.validRect);
193   -
194   - CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
195   - CGContextSetLineWidth(context, 4.0);
196   -
197   - CGPoint topPoints[2];
198   - topPoints[0] = CGPointMake(self.validRect.origin.x, 0);
199   - topPoints[1] = CGPointMake(self.validRect.origin.x+self.validRect.size.width, 0);
200   -
201   - CGPoint bottomPoints[2];
202   - bottomPoints[0] = CGPointMake(self.validRect.origin.x, kItemHeight);
203   - bottomPoints[1] = CGPointMake(self.validRect.origin.x+self.validRect.size.width, kItemHeight);
204   -
205   - CGContextAddLines(context, topPoints, 2);
206   - CGContextAddLines(context, bottomPoints, 2);
207   -
208   - CGContextDrawPath(context, kCGPathStroke);
209   -}
210   -
211   -@end
212   -
213   -
214   -#pragma mark - 编辑视频控制器CNEditVideoController
215   -@interface CNEditVideoController () <UIScrollViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate, CNEditFrameViewDelegate>
216   -{
217   - UIView *_bottomView;
218   - UIButton *_cancelBtn;
219   - UIButton *_doneBtn;
220   -
221   - NSTimer *_timer;
222   -
223   - //下方collectionview偏移量
224   - CGFloat _offsetX;
225   - BOOL _orientationChanged;
226   -
227   - UIView *_indicatorLine;
228   -
229   - AVAsset *_avAsset;
230   -
231   - NSTimeInterval _interval;
232   -
233   - NSInteger _measureCount;
234   - NSOperationQueue *_queue;
235   - NSMutableDictionary<NSString *, UIImage *> *_imageCache;
236   - NSMutableDictionary<NSString *, NSBlockOperation *> *_opCache;
237   -}
238   -
239   -@property (nonatomic, strong) AVPlayerLayer *playerLayer;
240   -@property (nonatomic, strong) UICollectionView *collectionView;
241   -@property (nonatomic, strong) CNEditFrameView *editView;
242   -@property (nonatomic, strong) AVAssetImageGenerator *generator;
243   -
244   -@end
245   -
246   -@implementation CNEditVideoController
247   -
248   -- (void)dealloc
249   -{
250   - [_queue cancelAllOperations];
251   - [self stopTimer];
252   - [[NSNotificationCenter defaultCenter] removeObserver:self];
253   -// NSLog(@"---- %s", __FUNCTION__);
254   -}
255   -
256   -- (AVAssetImageGenerator *)generator
257   -{
258   - if (!_generator) {
259   - _generator = [[AVAssetImageGenerator alloc] initWithAsset:_avAsset];
260   - _generator.maximumSize = CGSizeMake(kItemWidth*4, kItemHeight*4);
261   - _generator.appliesPreferredTrackTransform = YES;
262   - _generator.requestedTimeToleranceBefore = kCMTimeZero;
263   - _generator.requestedTimeToleranceAfter = kCMTimeZero;
264   - _generator.apertureMode = AVAssetImageGeneratorApertureModeProductionAperture;
265   - }
266   - return _generator;
267   -}
268   -
269   -- (void)viewDidLoad {
270   - [super viewDidLoad];
271   - [self setupUI];
272   - [self analysisAssetImages];
273   -
274   - _queue = [[NSOperationQueue alloc] init];
275   - _queue.maxConcurrentOperationCount = 3;
276   -
277   - _imageCache = [NSMutableDictionary dictionary];
278   - _opCache = [NSMutableDictionary dictionary];
279   -
280   - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationChanged:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
281   - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appResignActive) name:UIApplicationWillResignActiveNotification object:nil];
282   - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
283   -}
284   -
285   -- (void)viewWillAppear:(BOOL)animated
286   -{
287   - [super viewWillAppear:animated];
288   - [UIApplication sharedApplication].statusBarHidden = YES;
289   - self.navigationController.navigationBar.hidden = YES;
290   -}
291   -
292   -- (void)viewWillDisappear:(BOOL)animated
293   -{
294   - [super viewWillDisappear:animated];
295   - self.navigationController.navigationBar.hidden = NO;
296   -}
297   -
298   -- (void)viewDidLayoutSubviews
299   -{
300   - [super viewDidLayoutSubviews];
301   -
302   - UIEdgeInsets inset = UIEdgeInsetsZero;
303   - if (@available(iOS 11, *)) {
304   - inset = self.view.safeAreaInsets;
305   - }
306   -
307   - self.playerLayer.frame = CGRectMake(15, inset.top>0?inset.top:30, [UIScreen mainScreen].bounds.size.width-30, [UIScreen mainScreen].bounds.size.height-160-inset.bottom);
308   -
309   - self.editView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width-kItemWidth*10)/2, [UIScreen mainScreen].bounds.size.height-100-inset.bottom, kItemWidth*10, kItemHeight);
310   - self.editView.validRect = self.editView.bounds;
311   - self.collectionView.frame = CGRectMake(inset.left, [UIScreen mainScreen].bounds.size.height-100-inset.bottom, [UIScreen mainScreen].bounds.size.width-inset.left-inset.right, kItemHeight);
312   -
313   - CGFloat leftOffset = (([UIScreen mainScreen].bounds.size.width-kItemWidth*10)/2-inset.left);
314   - CGFloat rightOffset = (([UIScreen mainScreen].bounds.size.width-kItemWidth*10)/2-inset.right);
315   - [self.collectionView setContentInset:UIEdgeInsetsMake(0, leftOffset, 0, rightOffset)];
316   - [self.collectionView setContentOffset:CGPointMake(_offsetX-leftOffset, 0)];
317   -
318   - CGFloat bottomViewH = 44;
319   - CGFloat bottomBtnH = 30;
320   - _bottomView.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height-bottomViewH-inset.bottom, [UIScreen mainScreen].bounds.size.width, kItemHeight);
321   - _cancelBtn.frame = CGRectMake(10+inset.left, 7, 60, bottomBtnH);
322   - _doneBtn.frame = CGRectMake([UIScreen mainScreen].bounds.size.width-70-inset.right, 7, 60, bottomBtnH);
323   -
324   - [self.playerLayer setBackgroundColor:[UIColor clearColor].CGColor];
325   -}
326   -
327   -#pragma mark - notifies
328   -//设备旋转
329   -- (void)deviceOrientationChanged:(NSNotification *)notify
330   -{
331   - _offsetX = self.collectionView.contentOffset.x + self.collectionView.contentInset.left;
332   - _orientationChanged = YES;
333   -}
334   -
335   -- (void)appResignActive
336   -{
337   - [self stopTimer];
338   -}
339   -
340   -- (void)appBecomeActive
341   -{
342   - [self startTimer];
343   -}
344   -
345   -- (void)setupUI
346   -{
347   - //禁用返回手势
348   - if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
349   - self.navigationController.interactivePopGestureRecognizer.delegate = nil;
350   - self.navigationController.interactivePopGestureRecognizer.enabled = NO;
351   - }
352   -
353   - self.view.backgroundColor = [UIColor blackColor];
354   -
355   - self.playerLayer = [[AVPlayerLayer alloc] init];
356   - [self.view.layer addSublayer:self.playerLayer];
357   -
358   - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
359   - layout.itemSize = CGSizeMake(kItemWidth, kItemHeight);
360   - layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
361   - layout.minimumInteritemSpacing = 0;
362   - layout.minimumLineSpacing = 0;
363   -
364   - self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
365   - self.collectionView.delegate = self;
366   - self.collectionView.dataSource = self;
367   - self.collectionView.backgroundColor = [UIColor clearColor];
368   - self.collectionView.showsHorizontalScrollIndicator = NO;
369   - [self.collectionView registerClass:CNEditVideoCell.class forCellWithReuseIdentifier:@"CNEditVideoCell"];
370   -
371   - [self.view addSubview:self.collectionView];
372   -
373   - [self creatBottomView];
374   -
375   - self.editView = [[CNEditFrameView alloc] init];
376   - self.editView.delegate = self;
377   - [self.view addSubview:self.editView];
378   -
379   - _indicatorLine = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2, kItemHeight)];
380   -// _indicatorLine.backgroundColor = [RGBOF(0x0BBE06) colorWithAlphaComponent:.7];
381   -}
382   -
383   -- (void)creatBottomView
384   -{
385   - //下方视图
386   - _bottomView = [[UIView alloc] init];
387   - _bottomView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:.7];
388   - [self.view addSubview:_bottomView];
389   -
390   - _cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
391   - _cancelBtn.titleLabel.font = [UIFont systemFontOfSize:15];
392   - [_cancelBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
393   - [_cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
394   - [_cancelBtn addTarget:self action:@selector(cancelBtn_click) forControlEvents:UIControlEventTouchUpInside];
395   - [_bottomView addSubview:_cancelBtn];
396   -
397   - _doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
398   - [_doneBtn setTitle:@"完成" forState:UIControlStateNormal];
399   - [_doneBtn setBackgroundColor:[UIColor clearColor]];
400   -// [_doneBtn setTitleColor:RGBOF(0x0BBE06) forState:UIControlStateNormal];
401   - _doneBtn.titleLabel.font = [UIFont systemFontOfSize:15];
402   - _doneBtn.layer.masksToBounds = YES;
403   - _doneBtn.layer.cornerRadius = 3.0f;
404   - [_doneBtn addTarget:self action:@selector(btnDone_click) forControlEvents:UIControlEventTouchUpInside];
405   - [_bottomView addSubview:_doneBtn];
406   -}
407   -
408   -#pragma mark - 解析视频每一帧图片
409   -- (void)analysisAssetImages
410   -{
411   - NSTimeInterval duration = 0.0;
412   - if ([self.model.asset isKindOfClass:[PHAsset class]]) {
413   - PHAsset *asset = self.model.asset;
414   - duration = asset.duration;
415   - }else if([self.model.asset isKindOfClass:[ALAsset class]]){
416   - duration = [[self.model.asset valueForProperty:ALAssetPropertyDuration] doubleValue];
417   - }
418   -
419   - TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
420   - _interval = _tzImagePickerVc.maxEditVideoTime/10.0;
421   - _measureCount = (NSInteger)(duration / _interval);
422   - ///播放视频的
423   - if ([self.model.asset isKindOfClass:[PHAsset class]]) {//PHAsset
424   - __weak typeof(self) weakSelf = self;
425   - [[PHCachingImageManager defaultManager] requestPlayerItemForVideo:self.model.asset options:nil resultHandler:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
426   - dispatch_async(dispatch_get_main_queue(), ^{
427   - __strong typeof(weakSelf) strongSelf = weakSelf;
428   - if (!playerItem) return;
429   - AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
430   - strongSelf.playerLayer.player = player;
431   - [strongSelf startTimer];
432   - });
433   -
434   - }];
435   -
436   - ///截取视频帧数
437   - PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
438   - options.version = PHVideoRequestOptionsVersionOriginal;
439   - options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
440   - options.networkAccessAllowed = YES;
441   - [[PHImageManager defaultManager] requestAVAssetForVideo:self.model.asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
442   - __strong typeof(weakSelf) strongSelf = weakSelf;
443   - strongSelf->_avAsset = asset;
444   - dispatch_async(dispatch_get_main_queue(), ^{
445   - [strongSelf.collectionView reloadData];
446   - });
447   - }];
448   -
449   - }else if([self.model.asset isKindOfClass:[ALAsset class]]){//ALAsset
450   - ///播放视频的
451   - ALAsset *alAsset = (ALAsset *)self.model.asset;
452   - ALAssetRepresentation *defaultRepresentation = [alAsset defaultRepresentation];
453   - NSString *uti = [defaultRepresentation UTI];
454   - NSURL *videoURL = [[alAsset valueForProperty:ALAssetPropertyURLs] valueForKey:uti];
455   - AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:videoURL];
456   - AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
457   - self.playerLayer.player = player;
458   - [self startTimer];
459   -
460   - ///截取视频帧数
461   - NSURL *videoURL_al =[self.model.asset valueForProperty:ALAssetPropertyAssetURL]; // ALAssetPropertyURLs
462   - AVAsset *videoAsset = [AVURLAsset assetWithURL:videoURL];
463   - _avAsset = videoAsset ;
464   - [self.collectionView reloadData];
465   -
466   - }
467   -
468   -}
469   -
470   -#pragma mark - action
471   -- (void)cancelBtn_click
472   -{
473   - [self stopTimer];
474   -
475   - if (self.backButtonEditClickBlock) {
476   - TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
477   - self.backButtonEditClickBlock(_tzImagePickerVc.isSelectOriginalPhoto);
478   - }
479   - UIViewController *vc = [self.navigationController popViewControllerAnimated:NO];
480   - if (!vc) {
481   - [self dismissViewControllerAnimated:YES completion:nil];
482   - }
483   -}
484   -
485   -- (void)btnDone_click
486   -{
487   - [self stopTimer];
488   -
489   - TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
490   - [_tzImagePickerVc showProgressHUD];
491   -
492   - [self exportEditVideoForAsset:_avAsset range:[self getTimeRange] complete:^(BOOL isSuc, id asset) {
493   - [_tzImagePickerVc hideProgressHUD];
494   - if (isSuc) {
495   - TZAssetModel *editModel = [TZAssetModel modelWithAsset:asset type:TZAssetModelMediaTypeVideo];
496   -
497   - // 如果没有选中过照片 点击确定时选中当前预览的照片
498   - if (_tzImagePickerVc.selectedModels.count == 0 && _tzImagePickerVc.minImagesCount <= 0) {
499   - [_tzImagePickerVc addSelectedModel:editModel];
500   - }
501   -
502   - if (self.doneButtonEditClickBlock) {
503   - self.doneButtonEditClickBlock(_tzImagePickerVc.isSelectOriginalPhoto);
504   - }
505   - [_tzImagePickerVc hideProgressHUD];
506   - }else{
507   - [_tzImagePickerVc showAlertWithTitle:@"编辑失败"];
508   - }
509   -
510   - }];
511   -}
512   -#pragma mark - 截取视频
513   -
514   -- (void)exportEditVideoForAsset:(AVAsset *)asset range:(CMTimeRange)range complete:(void (^)(BOOL, id))complete
515   -{
516   - [self export:asset range:range presetName:AVAssetExportPresetPassthrough renderSize:CGSizeZero imageSize:CGSizeZero effectImage:nil birthRate:0 velocity:0 complete:^(NSString *exportFilePath, NSError *error) {
517   - if (!error) {
518   - [self saveVideoToAblum:[NSURL fileURLWithPath:exportFilePath] completion:^(BOOL isSuc, id asset) {
519   - dispatch_async(dispatch_get_main_queue(), ^{
520   - if (complete) complete(isSuc, asset);
521   - });
522   - }];
523   - } else {
524   - dispatch_async(dispatch_get_main_queue(), ^{
525   - if (complete) complete(NO, nil);
526   - });
527   - }
528   - }];
529   -}
530   -
531   -///保存视频到相册
532   -- (void)saveVideoToAblum:(NSURL *)url completion:(void (^)(BOOL, id))completion
533   -{
534   - if (iOS8Later) {
535   - PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
536   - if (status == PHAuthorizationStatusDenied) {
537   - if (completion) completion(NO, nil);
538   - } else if (status == PHAuthorizationStatusRestricted) {
539   - if (completion) completion(NO, nil);
540   - } else {
541   - __block PHObjectPlaceholder *placeholderAsset=nil;
542   - [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
543   - PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
544   - placeholderAsset = newAssetRequest.placeholderForCreatedAsset;
545   - } completionHandler:^(BOOL success, NSError * _Nullable error) {
546   - if (!success) {
547   - if (completion) completion(NO, nil);
548   - return;
549   - }
550   - PHAsset *asset = [self getAssetFromlocalIdentifier:placeholderAsset.localIdentifier];
551   - PHAssetCollection *desCollection = [self getDestinationCollection];
552   - if (!desCollection) completion(NO, nil);
553   -
554   - [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
555   - [[PHAssetCollectionChangeRequest changeRequestForAssetCollection:desCollection] addAssets:@[asset]];
556   - } completionHandler:^(BOOL success, NSError * _Nullable error) {
557   - if (completion) completion(success, asset);
558   - }];
559   - }];
560   - }
561   - }else{
562   -
563   - ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
564   - [assetLibrary writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error) {
565   - if (error) {
566   - NSLog(@"保存视频出错:%@",error.localizedDescription);
567   - if (completion) {
568   - completion(NO,nil);
569   - }
570   - } else {
571   - [assetLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
572   - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
573   - if (completion) {
574   - completion(YES,asset);
575   - }
576   - });
577   - } failureBlock:^(NSError *error) {
578   -
579   - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
580   - if (completion) {
581   - completion(NO,nil);
582   - }
583   - });
584   -
585   - }];
586   - }
587   - }];
588   -
589   - }
590   -
591   -}
592   -
593   -- (PHAsset *)getAssetFromlocalIdentifier:(NSString *)localIdentifier{
594   - if(localIdentifier == nil){
595   - NSLog(@"Cannot get asset from localID because it is nil");
596   - return nil;
597   - }
598   - PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
599   - if(result.count){
600   - return result[0];
601   - }
602   - return nil;
603   -}
604   -
605   -//获取自定义相册
606   -- (PHAssetCollection *)getDestinationCollection
607   -{
608   - //找是否已经创建自定义相册
609   - PHFetchResult<PHAssetCollection *> *collectionResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
610   - for (PHAssetCollection *collection in collectionResult) {
611   - if ([collection.localizedTitle isEqualToString:kAPPName]) {
612   - return collection;
613   - }
614   - }
615   - //新建自定义相册
616   - __block NSString *collectionId = nil;
617   - NSError *error = nil;
618   - [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
619   - collectionId = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:kAPPName].placeholderForCreatedAssetCollection.localIdentifier;
620   - } error:&error];
621   - if (error) {
622   - return nil;
623   - }
624   - return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[collectionId] options:nil].lastObject;
625   -}
626   -
627   -- (void)export:(AVAsset *)asset range:(CMTimeRange)range presetName:(NSString *)presetName renderSize:(CGSize)renderSize imageSize:(CGSize)imageSize effectImage:(UIImage *)effectImage birthRate:(NSInteger)birthRate velocity:(CGFloat)velocity complete:(void (^)(NSString *exportFilePath, NSError *error))complete
628   -{
629   - NSString *exportFilePath = [self getVideoExportFilePath];
630   -
631   - AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:presetName];
632   -
633   - NSURL *exportFileUrl = [NSURL fileURLWithPath:exportFilePath];
634   -
635   - exportSession.outputURL = exportFileUrl;
636   - exportSession.outputFileType = AVFileTypeMPEG4;
637   - exportSession.timeRange = range;
638   - // exportSession.shouldOptimizeForNetworkUse = YES;
639   - if (!CGSizeEqualToSize(renderSize, CGSizeZero)) {
640   - AVMutableVideoComposition *com = [self getVideoComposition:asset renderSize:renderSize imageSize:imageSize effectImage:effectImage birthRate:birthRate velocity:velocity];
641   - if (!com) {
642   - if (complete) {
643   - complete(nil, [NSError errorWithDomain:@"视频裁剪导出失败" code:-1 userInfo:@{@"message": @"视频对象格式可能有错误,没有检测到视频通道"}]);
644   - }
645   - return;
646   - }
647   - exportSession.videoComposition = com;
648   - }
649   -
650   - [exportSession exportAsynchronouslyWithCompletionHandler:^{
651   - BOOL suc = NO;
652   - switch ([exportSession status]) {
653   - case AVAssetExportSessionStatusFailed:
654   - NSLog(@"Export failed: %@", [[exportSession error] localizedDescription]);
655   - break;
656   - case AVAssetExportSessionStatusCancelled:
657   - NSLog(@"Export canceled");
658   - break;
659   -
660   - case AVAssetExportSessionStatusCompleted:{
661   - NSLog(@"Export completed");
662   - suc = YES;
663   - }
664   - break;
665   -
666   - default:
667   - NSLog(@"Export other");
668   - break;
669   - }
670   -
671   - if (complete) {
672   - complete(suc?exportFilePath:nil, suc?nil:exportSession.error);
673   - if (!suc) {
674   - [exportSession cancelExport];
675   - }
676   - }
677   - }];
678   -}
679   -
680   -- (NSString *)getVideoExportFilePath
681   -{
682   - NSString *format = @"mp4";
683   -
684   - NSString *exportFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [self getUniqueStrByUUID], format]];
685   -
686   - return exportFilePath;
687   -}
688   -
689   -- (NSString *)getUniqueStrByUUID
690   -{
691   - CFUUIDRef uuidObj = CFUUIDCreate(nil);//create a new UUID
692   -
693   - //get the string representation of the UUID
694   - CFStringRef uuidString = CFUUIDCreateString(nil, uuidObj);
695   -
696   - NSString *str = [NSString stringWithString:(__bridge NSString *)uuidString];
697   -
698   - CFRelease(uuidObj);
699   - CFRelease(uuidString);
700   -
701   - return [str lowercaseString];
702   -}
703   -
704   -
705   -- (AVMutableVideoComposition *)getVideoComposition:(AVAsset *)asset renderSize:(CGSize)renderSize imageSize:(CGSize)imageSize effectImage:(UIImage *)effectImage birthRate:(NSInteger)birthRate velocity:(CGFloat)velocity
706   -{
707   - AVMutableComposition *composition = [AVMutableComposition composition];
708   - //视频通道
709   - AVMutableCompositionTrack *assetVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
710   - //音频通道
711   - AVMutableCompositionTrack *assetAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
712   -
713   - NSError *error = nil;
714   - //裁剪时长
715   - CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
716   -
717   - AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;//视频
718   - AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;//音频
719   -
720   - if (!videoTrack) {
721   - return nil;
722   - }
723   - [assetVideoTrack insertTimeRange:timeRange ofTrack:videoTrack atTime:kCMTimeZero error:&error];
724   - NSLog(@"%@", error);
725   - if (audioTrack) {
726   - [assetAudioTrack insertTimeRange:timeRange ofTrack:audioTrack atTime:kCMTimeZero error:&error];
727   - NSLog(@"%@", error);
728   - }
729   -
730   - if (error) {
731   - return nil;
732   - }
733   -
734   - AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
735   - instruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration);
736   -
737   - //处理视频旋转
738   - AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:assetVideoTrack];
739   - [layerInstruction setOpacity:0.0 atTime:assetVideoTrack.timeRange.duration];
740   - //视频旋转,获取视频旋转角度,然后旋转对应角度,保持视频方向正确
741   - CGFloat degree = [self getVideoDegree:videoTrack];
742   - CGSize naturalSize = assetVideoTrack.naturalSize;
743   -
744   - CGAffineTransform mixedTransform = CGAffineTransformIdentity;
745   - //处理renderSize,不能大于视频宽高
746   - CGFloat videoWidth = (degree==0 || degree==M_PI) ? naturalSize.width : naturalSize.height;
747   - CGFloat videoHeight = (degree==0 || degree==M_PI) ? naturalSize.height : naturalSize.width;
748   - CGSize cropSize = CGSizeMake(MIN(videoWidth, renderSize.width), MIN(videoHeight, renderSize.height));
749   - CGFloat x, y;
750   - if (degree == M_PI_2) {
751   - //顺时针 90°
752   - CGAffineTransform t = CGAffineTransformMakeTranslation(naturalSize.height,.0);
753   - CGAffineTransform t1 = CGAffineTransformRotate(t, M_PI_2);
754   - //x为正向下 y为正向左
755   - x = -(videoHeight-cropSize.height)/2;
756   - y = (videoWidth-cropSize.width)/2;
757   - mixedTransform = CGAffineTransformTranslate(t1, x, y);
758   - } else if (degree == M_PI) {
759   - //顺时针 180°
760   - CGAffineTransform t = CGAffineTransformMakeTranslation(naturalSize.width, naturalSize.height);
761   - CGAffineTransform t1 = CGAffineTransformRotate(t, M_PI);
762   - //x为正向左 y为正向上
763   - x = (videoWidth-cropSize.width)/2;
764   - y = (videoHeight-cropSize.height)/2;
765   - mixedTransform = CGAffineTransformTranslate(t1, x, y);
766   - } else if (degree == (M_PI_2 * 3)) {
767   - //顺时针 270°
768   - CGAffineTransform t = CGAffineTransformMakeTranslation(.0, naturalSize.width);
769   - CGAffineTransform t1 = CGAffineTransformRotate(t, M_PI_2*3);
770   - //x为正向上 y为正向右
771   - x = (videoHeight-cropSize.height)/2;
772   - y = -(videoWidth-cropSize.width)/2;
773   - mixedTransform = CGAffineTransformTranslate(t1, x, y);
774   - } else {
775   - //x为正向右 y为正向下
776   - x = -(videoWidth-cropSize.width)/2;
777   - y = -(videoHeight-cropSize.height)/2;
778   - mixedTransform = CGAffineTransformMakeTranslation(x, y);
779   - }
780   -
781   - [layerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
782   -
783   - //管理所有需要处理的视频
784   - AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
785   - videoComposition.frameDuration = CMTimeMake(1, 30);
786   - videoComposition.renderScale = 1;
787   - videoComposition.renderSize = cropSize;
788   -
789   - instruction.layerInstructions = @[layerInstruction];
790   - videoComposition.instructions = @[instruction];
791   -
792   - return videoComposition;
793   -}
794   -
795   -- (CGFloat)getVideoDegree:(AVAssetTrack *)videoTrack
796   -{
797   - CGAffineTransform tf = videoTrack.preferredTransform;
798   -
799   - CGFloat degree = 0;
800   - if (tf.b == 1.0 && tf.c == -1.0) {
801   - degree = M_PI_2;
802   - } else if (tf.a == -1.0 && tf.d == -1.0) {
803   - degree = M_PI;
804   - } else if (tf.b == -1.0 && tf.c == 1.0) {
805   - degree = M_PI_2 * 3;
806   - }
807   - return degree;
808   -}
809   -
810   -
811   -
812   -#pragma mark - timer
813   -- (void)startTimer
814   -{
815   - [self stopTimer];
816   -
817   - CGFloat duration = _interval * self.editView.validRect.size.width / (kItemWidth);
818   - _timer = [NSTimer scheduledTimerWithTimeInterval:duration target:self selector:@selector(playPartVideo:) userInfo:nil repeats:YES];
819   - [_timer fire];
820   - [[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
821   -
822   - _indicatorLine.frame = CGRectMake(self.editView.validRect.origin.x, 0, 4, kItemHeight);
823   - [self.editView addSubview:_indicatorLine];
824   - [UIView animateWithDuration:duration delay:.0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear animations:^{
825   - _indicatorLine.frame = CGRectMake(CGRectGetMaxX(self.editView.validRect)-2, 0, 2, kItemHeight);
826   - } completion:nil];
827   -}
828   -
829   -- (void)stopTimer
830   -{
831   - [_timer invalidate];
832   - _timer = nil;
833   - [_indicatorLine removeFromSuperview];
834   - [self.playerLayer.player pause];
835   -}
836   -
837   -- (CMTime)getStartTime
838   -{
839   - CGRect rect = [self.collectionView convertRect:self.editView.validRect fromView:self.editView];
840   - CGFloat s = MAX(0, _interval * rect.origin.x / (kItemWidth));
841   - return CMTimeMakeWithSeconds(s, self.playerLayer.player.currentTime.timescale);
842   -}
843   -
844   -- (CMTimeRange)getTimeRange
845   -{
846   - CMTime start = [self getStartTime];
847   - CGFloat d = _interval * self.editView.validRect.size.width / (kItemWidth);
848   - CMTime duration = CMTimeMakeWithSeconds(d, self.playerLayer.player.currentTime.timescale);
849   - return CMTimeRangeMake(start, duration);
850   -}
851   -
852   -- (void)playPartVideo:(NSTimer *)timer
853   -{
854   - [self.playerLayer.player play];
855   - [self.playerLayer.player seekToTime:[self getStartTime] toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
856   -}
857   -
858   -#pragma mark - edit view delegate
859   -- (void)editViewValidRectChanged
860   -{
861   - [self stopTimer];
862   - [self.playerLayer.player seekToTime:[self getStartTime] toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
863   -}
864   -
865   -- (void)editViewValidRectEndChanged
866   -{
867   - [self startTimer];
868   -}
869   -
870   -#pragma mark - scroll view delegate
871   -- (void)scrollViewDidScroll:(UIScrollView *)scrollView
872   -{
873   - if (!self.playerLayer.player || _orientationChanged) {
874   - _orientationChanged = NO;
875   - return;
876   - }
877   - [self stopTimer];
878   - [self.playerLayer.player seekToTime:[self getStartTime] toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
879   -}
880   -
881   -- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
882   -{
883   - if (!decelerate) {
884   - [self startTimer];
885   - }
886   -}
887   -
888   -- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
889   -{
890   - [self startTimer];
891   -}
892   -
893   -#pragma mark - collection view data sources
894   -- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
895   -{
896   - return _measureCount;
897   -}
898   -
899   -- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
900   -{
901   - CNEditVideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CNEditVideoCell" forIndexPath:indexPath];
902   -
903   - UIImage *image = _imageCache[@(indexPath.row).stringValue];
904   - if (image) {
905   - cell.imageView.image = image;
906   - }
907   -
908   - return cell;
909   -}
910   -
911   -static const char _CNOperationCellKey;
912   -- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
913   -{
914   - if (!_avAsset) return;
915   -
916   - if (_imageCache[@(indexPath.row).stringValue] || _opCache[@(indexPath.row).stringValue]) {
917   - return;
918   - }
919   -
920   - NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
921   - NSInteger row = indexPath.row;
922   - NSInteger i = row * _interval;
923   -
924   - CMTime time = CMTimeMake((i+0.35) * _avAsset.duration.timescale, _avAsset.duration.timescale);
925   -
926   - NSError *error = nil;
927   - CGImageRef cgImg = [self.generator copyCGImageAtTime:time actualTime:NULL error:&error];
928   - if (!error && cgImg) {
929   - UIImage *image = [UIImage imageWithCGImage:cgImg];
930   - CGImageRelease(cgImg);
931   -
932   - [_imageCache setValue:image forKey:@(row).stringValue];
933   -
934   - dispatch_async(dispatch_get_main_queue(), ^{
935   -
936   - NSIndexPath *nowIndexPath = [collectionView indexPathForCell:cell];
937   - if (row == nowIndexPath.row) {
938   - [(CNEditVideoCell *)cell imageView].image = image;
939   - } else {
940   - UIImage *cacheImage = _imageCache[@(nowIndexPath.row).stringValue];
941   - if (cacheImage) {
942   - [(CNEditVideoCell *)cell imageView].image = cacheImage;
943   - }
944   - }
945   - });
946   - [_opCache removeObjectForKey:@(row).stringValue];
947   - }
948   - objc_removeAssociatedObjects(cell);
949   - }];
950   - [_queue addOperation:op];
951   - [_opCache setValue:op forKey:@(indexPath.row).stringValue];
952   -
953   - objc_setAssociatedObject(cell, &_CNOperationCellKey, op, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
954   -}
955   -
956   -- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
957   -{
958   - NSBlockOperation *op = objc_getAssociatedObject(cell, &_CNOperationCellKey);
959   - if (op) {
960   - [op cancel];
961   - objc_removeAssociatedObjects(cell);
962   - [_opCache removeObjectForKey:@(indexPath.row).stringValue];
963   - }
964   -}
965   -
966   -- (void)didReceiveMemoryWarning {
967   - [super didReceiveMemoryWarning];
968   - // Dispose of any resources that can be recreated.
969   -}
970   -
971   -/*
972   -#pragma mark - Navigation
973   -
974   -// In a storyboard-based application, you will often want to do a little preparation before navigation
975   -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
976   - // Get the new view controller using [segue destinationViewController].
977   - // Pass the selected object to the new view controller.
978   -}
979   -*/
980   -
981   -@end
CNLiveImagePickerController/CNImagePickerCommonDefine.h deleted 100644 → 0
1   -//
2   -// CNImagePickerCommonDefine.h
3   -// CNLiveImagePickerControllerExample
4   -//
5   -// Created by 梁星国 on 2018/10/25.
6   -// Copyright © 2018年 梁星国. All rights reserved.
7   -//
8   -
9   -#ifndef CNImagePickerCommonDefine_h
10   -#define CNImagePickerCommonDefine_h
11   -
12   -
13   -////////////////////////////////////////////////////////
14   -//////////// Color
15   -////////////////////////////////////////////////////////
16   -
17   -#define IP_RGBOF(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \
18   -green:((float)((rgbValue & 0xFF00) >> 8))/255.0 \
19   -blue:((float)(rgbValue & 0xFF))/255.0 \
20   -alpha:1.0]
21   -
22   -#define IP_RGBA_OF(rgbValue) [UIColor colorWithRed:((float)(((rgbValue) & 0xFF000000) >> 24))/255.0 \
23   -green:((float)(((rgbValue) & 0x00FF0000) >> 16))/255.0 \
24   -blue:((float)(rgbValue & 0x0000FF00) >> 8)/255.0 \
25   -alpha:((float)(rgbValue & 0x000000FF))/255.0]
26   -
27   -#define IP_RGBAOF(v, a) [UIColor colorWithRed:((float)(((v) & 0xFF0000) >> 16))/255.0 \
28   -green:((float)(((v) & 0x00FF00) >> 8))/255.0 \
29   -blue:((float)(v & 0x0000FF))/255.0 \
30   -alpha:a]
31   -
32   -
33   -////////////////////////////////////////////////////////
34   -//////////// 发送图片,视频限制
35   -////////////////////////////////////////////////////////
36   -#define kFriendsCircle_limit_photo 20*1024.0*1024.0 //朋友圈限制图片20M
37   -#define kFirendsCircle_limit_video 30*1024.0*1024.0 //朋友圈限制视频30M
38   -#define kTarentoComment_limit_photo 10*1024.0*1024.0 //达人评论10M
39   -#define kSweepCode_limit_phoho 10*1024.0*1024.0 //扫码10M限制
40   -#define kChat_limit_photo 20*1024.0*1024.0 //聊天限制图片20M
41   -#define kChat_limit_video 20*1024.0*1024.0 //聊天限制视频20M
42   -
43   -#define kChat_limit_video_length 5*60 //聊天限制视频5分钟
44   -#define kFriendsCircle_limit_video_maxEdit 5*60 //朋友圈限制视频5分钟
45   -#define kFriendsCircle_limit_video_max 10*60 //朋友圈限制最大视频编辑10分钟
46   -
47   -
48   -
49   -////////////////////////////////////////////////////////
50   -//////////// SCreen
51   -////////////////////////////////////////////////////////
52   -#define kIPScreenWidth ([UIScreen mainScreen].bounds.size.width > [UIScreen mainScreen].bounds.size.height ? [UIScreen mainScreen].bounds.size.height : [UIScreen mainScreen].bounds.size.width)
53   -#define kIPScreenHeight ([UIScreen mainScreen].bounds.size.width > [UIScreen mainScreen].bounds.size.height ? [UIScreen mainScreen].bounds.size.width : [UIScreen mainScreen].bounds.size.height)
54   -
55   -
56   -//判断iPHoneXr
57   -#define IP_Device_Is_iPhoneXS_XR ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(828, 1792), [[UIScreen mainScreen] currentMode].size) : NO)
58   -
59   -//判断iPHoneX、iPHoneXs
60   -#define IP_Device_Is_iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
61   -#define IP_Device_Is_iPhoneXS ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
62   -
63   -//判断iPhoneXs Max
64   -#define IP_Device_Is_iPhoneXS_MAX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2688), [[UIScreen mainScreen] currentMode].size) : NO)
65   -
66   -#define IP_IS_IPhoneX_All (CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(375, 812)) ||CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(812, 375)) ||CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(414, 896)) ||CGSizeEqualToSize([UIScreen mainScreen].bounds.size, CGSizeMake(896, 414)))
67   -
68   -
69   -#define kIPStatusHeight (int)[UIApplication sharedApplication].statusBarFrame.size.height //x44 非x20
70   -#define kIPNavigationBarHeight ((int)[UIApplication sharedApplication].statusBarFrame.size.height+44) //x88 非x64
71   -#define kIPVerticalNaviBarHeight ((IP_IS_IPhoneX_All > 0) ? 88 : 44)
72   -#define kIPVerticalTabBarTotalHeight ((IP_IS_IPhoneX_All > 0) ? 83 : 49)
73   -#define kIPVerticalBottomSafeHeight ((IP_IS_IPhoneX_All > 0) ? 34 : 0)
74   -#define kIPVerticalStatusHeight ((IP_IS_IPhoneX_All > 0) ? 44 : 20)
75   -#define kIPVerticalTopHeight ((IP_IS_IPhoneX_All > 0) ? 24 : 0)
76   -#define kIPHorizontalTopNaviBarHeight 32
77   -#define kIPHorizontalBottomHeight ((IP_IS_IPhoneX_All > 0) ? 21 : 0)
78   -#define kIPHorizontalLeftHeight ((IP_IS_IPhoneX_All > 0) ? 44 : 0)
79   -#define kIPHorizontalRightHeight ((IP_IS_IPhoneX_All > 0) ? 44 : 0)
80   -#define kIPHorizontalTopHeight ((IP_IS_IPhoneX_All > 0) ? 24 : 0)
81   -
82   -#endif /* CNImagePickerCommonDefine_h */
CNLiveImagePickerController/CNImagePickerController.h deleted 100644 → 0
1   -//
2   -// CNTZImagePickerControllerViewController.h
3   -// CNLiveNetAdd
4   -//
5   -// Created by 梁星国 on 2018/8/22.
6   -// Copyright © 2018年 cnlive. All rights reserved.
7   -//
8   -
9   -#import "TZImagePickerController.h"
10   -
11   -@interface CNImagePickerController : TZImagePickerController
12   -
13   -/**
14   - 配置
15   - */
16   -- (void)configTZImagePicker;
17   -
18   -@end
CNLiveImagePickerController/CNImagePickerController.m deleted 100644 → 0
1   -//
2   -// CNTZImagePickerControllerViewController.m
3   -// CNLiveNetAdd
4   -//
5   -// Created by 梁星国 on 2018/8/22.
6   -// Copyright © 2018年 cnlive. All rights reserved.
7   -//
8   -
9   -#import "CNImagePickerController.h"
10   -#import "CNImagePickerCommonDefine.h"
11   -#import "UIImage+CNImagePicker.h"
12   -
13   -@interface CNImagePickerController ()
14   -
15   -@end
16   -
17   -@implementation CNImagePickerController
18   -
19   -- (void)viewDidLoad {
20   - [super viewDidLoad];
21   -
22   -}
23   -
24   -/**
25   - 配置 详情看TZImagePickerController
26   - */
27   -- (void)configTZImagePicker{
28   -
29   -#pragma mark - 五类个性化设置,这些参数都可以不传,此时会走默认设置
30   - // 1.设置目前已经选中的图片数组
31   - self.allowTakePicture = NO; // 在内部显示拍照按钮
32   - self.allowTakeVideo = NO;// 在内部拍摄按钮
33   - self.videoMaximumDuration = 10; // 视频最大拍摄时间
34   - [self setUiImagePickerControllerSettingBlock:^(UIImagePickerController *imagePickerController) {
35   - imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;//拍摄分辨率
36   - }];
37   - self.iconThemeColor = IP_RGBOF(0x00BBE06);// 主体颜色
38   - self.showPhotoCannotSelectLayer = YES;//达到上限是否有浮层
39   - self.cannotSelectLayerColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8];//设置达到上限的浮层
40   -
41   - self.photoDefImage = [UIImage imageNamedFromMyBundle:@"photo_cell_normal"];
42   - self.photoSelImage = [UIImage ip_imageWithColor:IP_RGBOF(0x0BBE06) size:CGSizeMake(22, 22) radius:11];
43   - self.photoOriginDefImage = [UIImage imageNamedFromMyBundle:@"photo_original_nor"];
44   -
45   - // 3. 设置是否可以选择视频/图片/原图/gif
46   - self.allowPickingVideo = YES;// 显示视频
47   - self.allowPickingImage = YES;// 显示图片
48   - self.allowPickingOriginalPhoto = YES; //显示原图
49   - self.allowPickingGif = NO;// 显示GIF
50   - self.allowPickingMultipleVideo = YES; // 是否可以多选视频
51   -
52   - // 4. 照片排列按修改时间升序
53   - self.sortAscendingByModificationDate = YES;
54   -
55   - // imagePickerVc.minImagesCount = 3;
56   - // imagePickerVc.alwaysEnableDoneBtn = YES;
57   -
58   - // imagePickerVc.minPhotoWidthSelectable = 3000;
59   - // imagePickerVc.minPhotoHeightSelectable = 2000;
60   -
61   - /// 5. Single selection mode, valid when maxImagesCount = 1
62   - /// 5. 单选模式,maxImagesCount为1时才生效
63   - self.showSelectBtn = NO;
64   - self.allowCrop = NO;
65   - self.needCircleCrop = NO;
66   - // 设置横屏下的裁剪尺寸
67   - // imagePickerVc.cropRectLandscape = CGRectMake((self.view.tz_height - widthHeight) / 2, left, widthHeight, widthHeight);
68   - /*
69   - [imagePickerVc setCropViewSettingBlock:^(UIView *cropView) {
70   - cropView.layer.borderColor = [UIColor redColor].CGColor;
71   - cropView.layer.borderWidth = 2.0;
72   - }];*/
73   -
74   - //imagePickerVc.allowPreview = NO;
75   - // 自定义导航栏上的返回按钮
76   - /*
77   - [imagePickerVc setNavLeftBarButtonSettingBlock:^(UIButton *leftButton){
78   - [leftButton setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
79   - [leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, -10, 0, 20)];
80   - }];
81   - imagePickerVc.delegate = self;
82   - */
83   -
84   - self.statusBarStyle = UIStatusBarStyleDefault;//状态栏黑色
85   -
86   - self.showSelectedIndex = YES; // 设置是否显示图片序号
87   -
88   - self.naviBgColor = IP_RGBOF(0xFFFFFF);//导航栏颜色
89   - self.naviTitleColor = IP_RGBOF(0x282828);//相册title
90   - self.naviTitleFont = [UIFont systemFontOfSize:18];//title文字大小
91   - [self setNavLeftBarButtonSettingBlock:^(UIButton *leftButton) {//设置返回按钮图标
92   - [leftButton setImage:[UIImage imageNamedFromMyBundle:@"photoback"] forState:UIControlStateNormal];//返回按钮图片
93   - [leftButton setTitle:@"返回" forState:UIControlStateNormal];//设置文字大小
94   - [leftButton setTitleColor:IP_RGBOF(0x282828) forState:UIControlStateNormal];//设置文字颜色
95   - leftButton.titleLabel.font = [UIFont systemFontOfSize:15];//设置文字大小
96   - leftButton.imageEdgeInsets = UIEdgeInsetsMake(0, -7, 0, +7);//设置图片边缘
97   - }];
98   - self.barItemTextColor = IP_RGBOF(0x282828);//设置barItem文字颜色
99   - self.barItemTextFont = [UIFont systemFontOfSize:15];
100   -
101   - // 设置首选语言 / Set preferred language
102   - // imagePickerVc.preferredLanguage = @"zh-Hans";
103   -
104   - // 设置languageBundle以使用其它语言 / Set languageBundle to use other language
105   - // imagePickerVc.languageBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"tz-ru" ofType:@"lproj"]];
106   -
107   - /// 【自定义各页面/组件的样式】在界面初始化/组件setModel完成后调用,允许外界修改样式等
108   - //相册
109   - [self setPhotoPickerPageUIConfigBlock:^(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine) {
110   -
111   - //底部栏
112   - [bottomToolBar setBackgroundColor:IP_RGBOF(0xFFFFFF)];
113   -
114   - //预览
115   - previewButton.titleLabel.font = [UIFont systemFontOfSize:16];
116   - [previewButton setTitleColor:IP_RGBOF(0xB3B3B3) forState:UIControlStateDisabled];//禁用
117   - [previewButton setTitleColor:IP_RGBOF(0x000000) forState:UIControlStateNormal];//默认
118   -
119   - //原图按钮
120   - [originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_normal"] forState:UIControlStateDisabled];//禁用
121   - [originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_normal"] forState:UIControlStateNormal];//默认
122   - [originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_select"] forState:UIControlStateSelected];//选中
123   - originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:16];
124   - [originalPhotoButton setTitleColor:IP_RGBOF(0xB3B3B3) forState:UIControlStateDisabled];
125   - [originalPhotoButton setTitleColor:IP_RGBOF(0x000000) forState:UIControlStateNormal];
126   -
127   - //原图文字提示
128   - originalPhotoLabel.font = [UIFont systemFontOfSize:16];
129   - originalPhotoLabel.textColor = IP_RGBOF(0xB3B3B3);
130   - originalPhotoLabel.hidden = YES;
131   -
132   - //选中提示
133   - numberImageView = [UIImageView new];
134   - numberLabel = [UILabel new];
135   -
136   - //完成按钮
137   - doneButton.titleLabel.font = [UIFont systemFontOfSize:13];
138   - [doneButton setTitle:@"完成" forState:UIControlStateDisabled];
139   - [doneButton setTitleColor:IP_RGBAOF(0xFFFFFF, 0.5) forState:UIControlStateDisabled];
140   - [doneButton setTitleColor:IP_RGBOF(0xFFFFFF) forState:UIControlStateNormal];
141   -
142   - //颜色绘制成图片
143   - UIImage *dis_image = [UIImage ip_imageWithColor:IP_RGBAOF(0x0BBE06, 0.5)];
144   - [doneButton setBackgroundImage:dis_image forState:UIControlStateDisabled];
145   - UIImage *nor_image = [UIImage ip_imageWithColor:IP_RGBOF(0x0BBE06)];
146   - [doneButton setBackgroundImage:nor_image forState:UIControlStateNormal];
147   - doneButton.layer.masksToBounds = YES;
148   - doneButton.layer.cornerRadius = 5;
149   -
150   - //分割线
151   - [divideLine setBackgroundColor:IP_RGBOF(0xDEDEDE)];
152   -
153   - }];
154   -
155   - //图片预览
156   - [self setPhotoPreviewPageUIConfigBlock:^(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel) {
157   -
158   - //返回按钮
159   - [backButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_back"] forState:UIControlStateNormal];
160   - //选择按钮
161   - [selectButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_nor"] forState:UIControlStateNormal];
162   - [selectButton setImage:[UIImage ip_imageWithColor:IP_RGBOF(0x0BBE06) size:CGSizeMake(28, 28) radius:14] forState:UIControlStateSelected];
163   - [selectButton setTitle:@"" forState:UIControlStateDisabled];
164   -
165   - //原图按钮
166   - [originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_normal"] forState:UIControlStateDisabled];//禁用
167   - [originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_normal"] forState:UIControlStateNormal];//默认
168   - [originalPhotoButton setImage:[UIImage imageNamedFromMyBundle:@"photo_original_select"] forState:UIControlStateSelected];//选中
169   - originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:16];
170   - [originalPhotoButton setTitleColor:IP_RGBOF(0xB3B3B3) forState:UIControlStateDisabled];
171   - [originalPhotoButton setTitleColor:IP_RGBAOF(0xFFFFFF, 0.7) forState:UIControlStateNormal];
172   - //原图内容隐藏
173   - originalPhotoLabel.hidden = YES;
174   -
175   - //完成按钮
176   - doneButton.titleLabel.font = [UIFont systemFontOfSize:13];
177   - [doneButton setTitle:@"完成" forState:UIControlStateDisabled];
178   - [doneButton setTitleColor:IP_RGBOF(0xFFFFFF) forState:UIControlStateDisabled];
179   - [doneButton setTitleColor:IP_RGBOF(0xFFFFFF) forState:UIControlStateNormal];
180   -
181   - //颜色绘制成图片
182   - UIImage *dis_image = [UIImage ip_imageWithColor:IP_RGBAOF(0x0BBE06, 0.5)];
183   - [doneButton setBackgroundImage:dis_image forState:UIControlStateSelected];
184   - UIImage *nor_image = [UIImage ip_imageWithColor:IP_RGBOF(0x0BBE06)];
185   - [doneButton setBackgroundImage:nor_image forState:UIControlStateNormal];
186   - doneButton.layer.masksToBounds = YES;
187   - doneButton.layer.cornerRadius = 5;
188   - }];
189   -
190   - //视频预览
191   - [self setVideoPreviewPageUIConfigBlock:^(UIButton *playButton, UIView *toolBar, UIButton *doneButton) {
192   -
193   - //完成按钮
194   - doneButton.titleLabel.font = [UIFont systemFontOfSize:13];
195   - [doneButton setTitle:@"完成" forState:UIControlStateDisabled];
196   - [doneButton setTitleColor:IP_RGBOF(0xFFFFFF) forState:UIControlStateDisabled];
197   - [doneButton setTitleColor:IP_RGBOF(0xFFFFFF) forState:UIControlStateNormal];
198   -
199   - //颜色绘制成图片
200   - UIImage *dis_image = [UIImage ip_imageWithColor:IP_RGBAOF(0x0BBE06, 0.5)];
201   - [doneButton setBackgroundImage:dis_image forState:UIControlStateSelected];
202   - UIImage *nor_image = [UIImage ip_imageWithColor:IP_RGBOF(0x0BBE06)];
203   - [doneButton setBackgroundImage:nor_image forState:UIControlStateNormal];
204   - doneButton.layer.masksToBounds = YES;
205   - doneButton.layer.cornerRadius = 5;
206   -
207   - }];
208   -
209   - //gif预览
210   - [self setGifPreviewPageUIConfigBlock:^(UIView *toolBar, UIButton *doneButton) {
211   -
212   - //完成按钮
213   - doneButton.titleLabel.font = [UIFont systemFontOfSize:13];
214   - [doneButton setTitle:@"完成" forState:UIControlStateDisabled];
215   - [doneButton setTitleColor:IP_RGBOF(0xFFFFFF) forState:UIControlStateDisabled];
216   - [doneButton setTitleColor:IP_RGBOF(0xFFFFFF) forState:UIControlStateNormal];
217   -
218   - //颜色绘制成图片
219   - UIImage *dis_image = [UIImage ip_imageWithColor:IP_RGBAOF(0x0BBE06, 0.5)];
220   - [doneButton setBackgroundImage:dis_image forState:UIControlStateSelected];
221   - UIImage *nor_image = [UIImage ip_imageWithColor:IP_RGBOF(0x0BBE06)];
222   - [doneButton setBackgroundImage:nor_image forState:UIControlStateNormal];
223   - doneButton.layer.masksToBounds = YES;
224   - doneButton.layer.cornerRadius = 5;
225   -
226   - }];
227   - //相册cell
228   - [self setAssetCellDidSetModelBlock:^(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView) {
229   -
230   -
231   - }];
232   - //相簿
233   - [self setAlbumCellDidSetModelBlock:^(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel) {
234   - [posterImageView setBackgroundColor:[UIColor blueColor]];
235   - [posterImageView setBackgroundColor:[UIColor blueColor]];
236   -
237   - }];
238   -
239   -
240   - /// 【自定义各页面/组件的frame】在界面viewDidLayoutSubviews/组件layoutSubviews后调用,允许外界修改frame等
241   - //相册
242   - [self setPhotoPickerPageDidLayoutSubviewsBlock:^(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine) {
243   -
244   - CGRect frame = bottomToolBar.frame;
245   - doneButton.frame = CGRectMake(frame.size.width - 60 - 13, frame.size.height /2 - 15 - (kIPVerticalBottomSafeHeight /2), 60, 30);
246   -
247   - CGRect originalPhotoLabelFrame = originalPhotoLabel.frame;
248   - CGFloat originalX = (bottomToolBar.frame.size.width - originalPhotoLabelFrame.size.width) /2;
249   - CGFloat originalY = originalPhotoLabelFrame.origin.y;
250   - originalPhotoButton.frame = CGRectMake(originalX, originalY, originalPhotoLabelFrame.size.width, originalPhotoLabelFrame.size.height);
251   -
252   -
253   - }];
254   - //图片预览
255   - [self setPhotoPreviewPageDidLayoutSubviewsBlock:^(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel) {
256   -
257   - CGRect frame = toolBar.frame;
258   - doneButton.frame = CGRectMake(frame.size.width - 60 - 13, frame.size.height /2 - 15 - (kIPVerticalBottomSafeHeight /2), 60, 30);
259   -
260   - }];
261   - //视频预览
262   - [self setVideoPreviewPageDidLayoutSubviewsBlock:^(UIButton *playButton, UIView *toolBar, UIButton *doneButton) {
263   -
264   - CGRect frame = toolBar.frame;
265   - doneButton.frame = CGRectMake(frame.size.width - 60 - 13, frame.size.height /2 - 15 - (kIPVerticalBottomSafeHeight /2), 60, 30);
266   -
267   - }];
268   - //gif预览
269   - [self setGifPreviewPageDidLayoutSubviewsBlock:^(UIView *toolBar, UIButton *doneButton) {
270   -
271   - CGRect frame = toolBar.frame;
272   - doneButton.frame = CGRectMake(frame.size.width - 60 - 13, frame.size.height /2 - 15 - (kIPVerticalBottomSafeHeight /2), 60, 30);
273   -
274   - }];
275   - //相册cell
276   -
277   - [self setAssetCellDidLayoutSubviewsBlock:^(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView) {
278   - }];
279   - //相簿
280   - [self setAlbumCellDidLayoutSubviewsBlock:^(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel) {
281   -
282   - }];
283   -
284   - //设置图片个数
285   - self.photoNumberIconImage = [UIImage new];
286   -
287   -}
288   -
289   -- (void)didReceiveMemoryWarning {
290   - [super didReceiveMemoryWarning];
291   - // Dispose of any resources that can be recreated.
292   -}
293   -
294   -
295   -@end
CNLiveImagePickerController/CNImagePickerManager.h deleted 100644 → 0
1   -//
2   -// CNImagePickerManager.h
3   -// CNLiveNetAdd
4   -//
5   -// Created by 梁星国 on 2018/10/8.
6   -// Copyright © 2018年 cnlive. All rights reserved.
7   -//
8   -
9   -#import <UIKit/UIKit.h>
10   -#import <Foundation/Foundation.h>
11   -#import "CNImagePickerController.h"
12   -
13   -
14   -typedef void (^didFinishPickingPhotosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto);//选着图片返回
15   -
16   -//typedef void (^failureBlock)(NSMutableArray* errorArray, NSError *error);//失败数组,错误
17   -
18   -typedef NS_ENUM(NSUInteger, CNImagePickerEnterType) {
19   - CNImagePickerEnterTypeFriendsCircle = 0,//朋友圈
20   - CNImagePickerEnterTypeComment = 1,//评论
21   - CNImagePickerEnterTypeSweepCode = 2,//扫码
22   - CNImagePickerEnterTypeChat = 3,//聊天
23   - CNImagePickerEnterTypeOther = 4,//其他
24   - CNImagePickerEnterTypeWitness = 5, //目击者
25   -
26   -};
27   -@interface CNImagePickerManager : NSObject
28   -
29   -
30   -
31   -/**
32   - 打开相册选择图片
33   -
34   - @param maxImagesCount 最大图片
35   - @param columnNumber 列个数
36   - @param delegate 代理(UIViewController<TZImagePickerControllerDelegate>)
37   - @param pushPhotoPickerVc 是否跳转到相册
38   - @param isSelectOriginalPhoto 是否原图
39   - @param selectedAssets 选择图片
40   - @param enterType 进入方式
41   - @param pickingPhotosHandle 选择结束回调
42   - */
43   -+ (void)ImagePickerWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id<TZImagePickerControllerDelegate>)delegate pushPhotoPickerVc:(BOOL)pushPhotoPickerVc isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto selectedAssets:(NSMutableArray *)selectedAssets enterType:(CNImagePickerEnterType )enterType pickingPhotosHandle:(didFinishPickingPhotosHandle) pickingPhotosHandle;
44   -
45   -/**
46   - 预览图片
47   -
48   - @param maxImagesCount 最大限制
49   - @param delegate 代理(UIViewController<TZImagePickerControllerDelegate>)
50   - @param selectedAssets 选中Assets
51   - @param selectedPhotos 选中Photos
52   - @param index 选中第几个
53   - @param isSelectOriginalPhoto 是否原图
54   - @param enterType 进入方式
55   - @param pickingPhotosHandle 回调参数
56   - */
57   -+ (void)ImagePickerWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id<TZImagePickerControllerDelegate>)delegate selectedAssets:(NSMutableArray *)selectedAssets selectedPhotos:(NSMutableArray *)selectedPhotos index:(NSInteger)index isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto enterType:(CNImagePickerEnterType )enterType pickingPhotosHandle:(didFinishPickingPhotosHandle) pickingPhotosHandle;
58   -
59   -
60   -/**
61   - 预览单个视频
62   -
63   - @param selectedAsset 选择视频
64   - @param delegate 代理(UIViewController<TZImagePickerControllerDelegate>)
65   - */
66   -+ (void)ImagePickerWithSelectedAsset:(id)selectedAsset delegate:(id<TZImagePickerControllerDelegate>)delegate;
67   -
68   -
69   -/**
70   - 保存图片
71   -
72   - @param delegate 代理(UIViewController<TZImagePickerControllerDelegate>)
73   - @param image 图片
74   - @param location 地点
75   - @param success 成功
76   - @param failure 失败
77   -
78   - */
79   -+(void)ImageManagerSavePhotoWithDelegate:(id<TZImagePickerControllerDelegate>)delegate image:(UIImage *)image location:(CLLocation *)location success:(void (^)(TZAssetModel *assetModel))success failure:(void (^)(NSError *error))failure;
80   -
81   -
82   -/**
83   - 判断Asset类型
84   -
85   - @param asset asset
86   - @return 返回类型
87   - */
88   -+ (TZAssetModelMediaType)getAssetType:(id)asset;
89   -
90   -
91   -@end
92   -
CNLiveImagePickerController/CNImagePickerManager.m deleted 100644 → 0
1   -//
2   -// CNImagePickerManager.m
3   -// CNLiveNetAdd
4   -//
5   -// Created by 梁星国 on 2018/10/8.
6   -// Copyright © 2018年 cnlive. All rights reserved.
7   -//
8   -
9   -#import "CNImagePickerManager.h"
10   -#import <AssetsLibrary/AssetsLibrary.h>
11   -#import "CNImagePickerCommonDefine.h"
12   -
13   -@implementation CNImagePickerManager
14   -
15   -/// 打开相册选择图片
16   -+ (void)ImagePickerWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id<TZImagePickerControllerDelegate>)delegate pushPhotoPickerVc:(BOOL)pushPhotoPickerVc isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto selectedAssets:(NSMutableArray *)selectedAssets enterType:(CNImagePickerEnterType )enterType pickingPhotosHandle:(didFinishPickingPhotosHandle) pickingPhotosHandle{
17   -
18   - if (![delegate isKindOfClass:[UIViewController class]]) {
19   - return;
20   - }
21   - UIViewController *vc = (UIViewController *)delegate;
22   -
23   - CNImagePickerController *imagePickerVc = [[CNImagePickerController alloc] initWithMaxImagesCount:maxImagesCount columnNumber:columnNumber delegate:delegate pushPhotoPickerVc:pushPhotoPickerVc];
24   - [imagePickerVc configTZImagePicker];//基本配置
25   - //特殊配置
26   - switch (enterType) {
27   - case CNImagePickerEnterTypeFriendsCircle:
28   - imagePickerVc.maxEditVideoTime = kFriendsCircle_limit_video_maxEdit;//编辑长度
29   - imagePickerVc.maxVideoDuration = kFriendsCircle_limit_video_max;//编辑视频最大长度
30   - // 3. 设置是否可以混选选择视频/图片/原图
31   - imagePickerVc.allowPickingMultipleVideo = NO;
32   - break;
33   - case CNImagePickerEnterTypeComment:
34   -
35   - break;
36   - case CNImagePickerEnterTypeSweepCode:
37   -
38   - break;
39   - case CNImagePickerEnterTypeChat:
40   - imagePickerVc.maxEditVideoTime = kFriendsCircle_limit_video_maxEdit;//编辑长度
41   - imagePickerVc.maxVideoDuration = kChat_limit_video_length;//编辑视频最大长度
42   -
43   - break;
44   - case CNImagePickerEnterTypeWitness:
45   - imagePickerVc.allowPickingImage = NO;// 显示图片
46   - imagePickerVc.allowPickingMultipleVideo = NO;
47   - imagePickerVc.maxEditVideoTime = kFriendsCircle_limit_video_maxEdit;//编辑长度
48   - imagePickerVc.maxVideoDuration = kFriendsCircle_limit_video_max;//编辑视频最大长度
49   - break;
50   - default://其他
51   - break;
52   - }
53   -
54   - imagePickerVc.isSelectOriginalPhoto = isSelectOriginalPhoto;//是否选择原图
55   - // 1.设置目前已经选中的图片数组
56   - imagePickerVc.selectedAssets = selectedAssets; // 目前已经选中的图片数组
57   - /// 5. Single selection mode, valid when maxImagesCount = 1
58   - /// 5. 单选模式,maxImagesCount为1时才生效
59   - // 设置竖屏下的裁剪尺寸
60   - NSInteger left = 30;
61   - NSInteger widthHeight = vc.view.frame.size.width - 2 * left;
62   - NSInteger top = (vc.view.frame.size.height - widthHeight) / 2;
63   - imagePickerVc.cropRect = CGRectMake(left, top, widthHeight, widthHeight);
64   - // 你可以通过block或者代理,来得到用户选择的照片.
65   - [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
66   - // 回调参数
67   - !pickingPhotosHandle ? : pickingPhotosHandle(photos, assets, isSelectOriginalPhoto);
68   -
69   - }];
70   -
71   - [vc presentViewController:imagePickerVc animated:YES completion:nil];
72   -}
73   -
74   -/// 预览图片
75   -+ (void)ImagePickerWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id<TZImagePickerControllerDelegate>)delegate selectedAssets:(NSMutableArray *)selectedAssets selectedPhotos:(NSMutableArray *)selectedPhotos index:(NSInteger)index isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto enterType:(CNImagePickerEnterType )enterType pickingPhotosHandle:(didFinishPickingPhotosHandle) pickingPhotosHandle {
76   -
77   - if (![delegate isKindOfClass:[UIViewController class]]) {
78   - return;
79   - }
80   - UIViewController *vc = (UIViewController *)delegate;
81   -
82   - CNImagePickerController *imagePickerVc = [[CNImagePickerController alloc] initWithSelectedAssets:selectedAssets selectedPhotos:selectedPhotos index:index];
83   - [imagePickerVc configTZImagePicker];//基本配置
84   - //特殊配置
85   - switch (enterType) {
86   - case CNImagePickerEnterTypeFriendsCircle:
87   - imagePickerVc.allowPickingGif = NO;
88   - imagePickerVc.allowPickingOriginalPhoto = YES;
89   - imagePickerVc.allowPickingMultipleVideo = NO;
90   - break;
91   - case CNImagePickerEnterTypeComment:
92   -#pragma mark - TODO:根据不同设置
93   - break;
94   - case CNImagePickerEnterTypeSweepCode:
95   -
96   - break;
97   - case CNImagePickerEnterTypeChat:
98   -
99   - break;
100   - case CNImagePickerEnterTypeOther:
101   - break;
102   - default://其他
103   - break;
104   - }
105   -
106   - imagePickerVc.maxImagesCount = maxImagesCount;
107   - imagePickerVc.isSelectOriginalPhoto = isSelectOriginalPhoto;
108   -
109   - [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
110   - // 回调参数
111   - !pickingPhotosHandle ? : pickingPhotosHandle(photos, assets, isSelectOriginalPhoto);
112   -
113   - }];
114   - [vc presentViewController:imagePickerVc animated:YES completion:nil];
115   -
116   -}
117   -
118   -/// 预览单个视频
119   -+ (void)ImagePickerWithSelectedAsset:(id)selectedAsset delegate:(id<TZImagePickerControllerDelegate>)delegate {
120   -
121   - if (![delegate isKindOfClass:[UIViewController class]]) {
122   - return;
123   - }
124   - UIViewController *vc = (UIViewController *)delegate;
125   -
126   - TZVideoPlayerController *videoVC = [[TZVideoPlayerController alloc] init];
127   - TZAssetModel *model = [TZAssetModel modelWithAsset:selectedAsset type:TZAssetModelMediaTypeVideo timeLength:@""];
128   - videoVC.isOther = YES;//(LXG)相册外进入
129   - videoVC.model = model;
130   - [vc presentViewController:videoVC animated:YES completion:nil];
131   -
132   -}
133   -
134   -/// 返回类型
135   -+ (TZAssetModelMediaType)getAssetType:(id)asset {
136   -
137   - TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
138   - if ([asset isKindOfClass:[PHAsset class]]) {
139   - PHAsset *phAsset = (PHAsset *)asset;
140   - if (phAsset.mediaType == PHAssetMediaTypeVideo) type = TZAssetModelMediaTypeVideo;
141   - else if (phAsset.mediaType == PHAssetMediaTypeAudio) type = TZAssetModelMediaTypeAudio;
142   - else if (phAsset.mediaType == PHAssetMediaTypeImage) {
143   - if (iOS9_1Later) {
144   - if (@available(iOS 9.1, *)) {
145   - if (phAsset.mediaSubtypes == PHAssetMediaSubtypePhotoLive)
146   - {
147   - type = TZAssetModelMediaTypeLivePhoto;
148   - }
149   - } else {
150   - // Fallback on earlier versions
151   - }
152   - }
153   - // Gif
154   - if ([[phAsset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
155   - type = TZAssetModelMediaTypePhotoGif;
156   - }
157   - }
158   - } else {
159   - if ([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
160   - type = TZAssetModelMediaTypeVideo;
161   - }
162   - }
163   - return type;
164   -}
165   -
166   -
167   -+(void)ImageManagerSavePhotoWithDelegate:(id<TZImagePickerControllerDelegate>)delegate image:(UIImage *)image location:(CLLocation *)location success:(void (^)(TZAssetModel *assetModel))success failure:(void (^)(NSError *error))failure {
168   -
169   - TZImagePickerController *tzImagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:delegate];
170   - tzImagePickerVc.sortAscendingByModificationDate = YES;
171   -
172   - [tzImagePickerVc showProgressHUD];
173   - // save photo and get asset / 保存图片,获取到asset
174   - [[TZImageManager manager] savePhotoWithImage:image location:location completion:^(NSError *error){
175   -
176   - if (error) {
177   - [tzImagePickerVc hideProgressHUD];
178   - failure(error);
179   - NSLog(@"图片保存失败 %@",error);
180   - } else {
181   -
182   - [[TZImageManager manager] getCameraRollAlbum:NO allowPickingImage:YES needFetchAssets:YES completion:^(TZAlbumModel *model) {
183   - [[TZImageManager manager] getAssetsFromFetchResult:model.result allowPickingVideo:NO allowPickingImage:YES completion:^(NSArray<TZAssetModel *> *models) {
184   - [tzImagePickerVc hideProgressHUD];
185   - TZAssetModel *assetModel = [models firstObject];
186   - if (tzImagePickerVc.sortAscendingByModificationDate) {
187   - assetModel = [models lastObject];
188   - }
189   - success(assetModel);
190   - }];
191   -
192   - }];
193   - }
194   - }];
195   -
196   -}
197   -
198   -
199   -
200   -
201   -
202   -
203   -
204   -
205   -
206   -@end
CNLiveImagePickerController/Classes/.gitkeep 0 → 100644
CNLiveImagePickerController/Classes/ReplaceMe.m 0 → 100644
CNLiveImagePickerController/NSBundle+TZImagePicker.h deleted 100755 → 0
1   -//
2   -// NSBundle+TZImagePicker.h
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 16/08/18.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -//
8   -
9   -#import <UIKit/UIKit.h>
10   -
11   -@interface NSBundle (TZImagePicker)
12   -
13   -+ (NSBundle *)tz_imagePickerBundle;
14   -
15   -+ (NSString *)tz_localizedStringForKey:(NSString *)key value:(NSString *)value;
16   -+ (NSString *)tz_localizedStringForKey:(NSString *)key;
17   -
18   -@end
19   -
CNLiveImagePickerController/NSBundle+TZImagePicker.m deleted 100755 → 0
1   -//
2   -// NSBundle+TZImagePicker.m
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 16/08/18.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -//
8   -
9   -#import "NSBundle+TZImagePicker.h"
10   -#import "TZImagePickerController.h"
11   -
12   -@implementation NSBundle (TZImagePicker)
13   -
14   -+ (NSBundle *)tz_imagePickerBundle {
15   - NSBundle *bundle = [NSBundle bundleForClass:[TZImagePickerController class]];
16   - NSURL *url = [bundle URLForResource:@"TZImagePickerController" withExtension:@"bundle"];
17   - bundle = [NSBundle bundleWithURL:url];
18   - return bundle;
19   -}
20   -
21   -+ (NSString *)tz_localizedStringForKey:(NSString *)key {
22   - return [self tz_localizedStringForKey:key value:@""];
23   -}
24   -
25   -+ (NSString *)tz_localizedStringForKey:(NSString *)key value:(NSString *)value {
26   - NSBundle *bundle = [TZImagePickerConfig sharedInstance].languageBundle;
27   - NSString *value1 = [bundle localizedStringForKey:key value:value table:nil];
28   - return value1;
29   -}
30   -
31   -@end
CNLiveImagePickerController/TZAssetCell.h deleted 100755 → 0
1   -//
2   -// TZAssetCell.h
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 15/12/24.
6   -// Copyright © 2015年 谭真. All rights reserved.
7   -//
8   -
9   -#import <UIKit/UIKit.h>
10   -#import <Photos/Photos.h>
11   -
12   -typedef enum : NSUInteger {
13   - TZAssetCellTypePhoto = 0,
14   - TZAssetCellTypeLivePhoto,
15   - TZAssetCellTypePhotoGif,
16   - TZAssetCellTypeVideo,
17   - TZAssetCellTypeAudio,
18   -} TZAssetCellType;
19   -
20   -@class TZAssetModel;
21   -@interface TZAssetCell : UICollectionViewCell
22   -@property (weak, nonatomic) UIButton *selectPhotoButton;
23   -@property (weak, nonatomic) UIButton *cannotSelectLayerButton;
24   -@property (nonatomic, strong) TZAssetModel *model;
25   -@property (assign, nonatomic) NSInteger index;
26   -@property (nonatomic, copy) void (^didSelectPhotoBlock)(BOOL);
27   -@property (nonatomic, assign) TZAssetCellType type;
28   -@property (nonatomic, assign) BOOL allowPickingGif;
29   -@property (nonatomic, assign) BOOL allowPickingMultipleVideo;
30   -@property (nonatomic, copy) NSString *representedAssetIdentifier;
31   -@property (nonatomic, assign) int32_t imageRequestID;
32   -
33   -@property (nonatomic, strong) UIImage *photoSelImage;
34   -@property (nonatomic, strong) UIImage *photoDefImage;
35   -
36   -@property (nonatomic, assign) BOOL showSelectBtn;
37   -@property (assign, nonatomic) BOOL allowPreview;
38   -@property (assign, nonatomic) BOOL useCachedImage;
39   -
40   -@property (nonatomic, copy) void (^assetCellDidSetModelBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView);
41   -@property (nonatomic, copy) void (^assetCellDidLayoutSubviewsBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView);
42   -@end
43   -
44   -
45   -@class TZAlbumModel;
46   -@interface TZAlbumCell : UITableViewCell
47   -@property (nonatomic, strong) TZAlbumModel *model;
48   -@property (weak, nonatomic) UIButton *selectedCountButton;
49   -
50   -@property (nonatomic, copy) void (^albumCellDidSetModelBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel);
51   -@property (nonatomic, copy) void (^albumCellDidLayoutSubviewsBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel);
52   -@end
53   -
54   -
55   -@interface TZAssetCameraCell : UICollectionViewCell
56   -@property (nonatomic, strong) UIImageView *imageView;
57   -@end
CNLiveImagePickerController/TZAssetCell.m deleted 100755 → 0
1   -//
2   -// TZAssetCell.m
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 15/12/24.
6   -// Copyright © 2015年 谭真. All rights reserved.
7   -//
8   -
9   -#import "TZAssetCell.h"
10   -#import "TZAssetModel.h"
11   -#import "UIView+Layout.h"
12   -#import "TZImageManager.h"
13   -#import "TZImagePickerController.h"
14   -#import "TZProgressView.h"
15   -
16   -@interface TZAssetCell ()
17   -@property (weak, nonatomic) UIImageView *imageView; // The photo / 照片
18   -@property (weak, nonatomic) UIImageView *selectImageView;
19   -@property (weak, nonatomic) UILabel *indexLabel;
20   -@property (weak, nonatomic) UIView *bottomView;
21   -@property (weak, nonatomic) UILabel *timeLength;
22   -@property (strong, nonatomic) UITapGestureRecognizer *tapGesture;
23   -
24   -@property (nonatomic, weak) UIImageView *videoImgView;
25   -@property (nonatomic, strong) TZProgressView *progressView;
26   -@property (nonatomic, assign) int32_t bigImageRequestID;
27   -@end
28   -
29   -@implementation TZAssetCell
30   -
31   -- (void)setModel:(TZAssetModel *)model {
32   - _model = model;
33   - if (iOS8Later) {
34   - self.representedAssetIdentifier = [[TZImageManager manager] getAssetIdentifier:model.asset];
35   - }
36   - if (self.useCachedImage && model.cachedImage) {
37   - self.imageView.image = model.cachedImage;
38   - } else {
39   - self.model.cachedImage = nil;
40   - int32_t imageRequestID = [[TZImageManager manager] getPhotoWithAsset:model.asset photoWidth:self.tz_width completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
41   - // Set the cell's thumbnail image if it's still showing the same asset.
42   - if (!iOS8Later) {
43   - self.imageView.image = photo;
44   - self.model.cachedImage = photo;
45   - [self hideProgressView];
46   - return;
47   - }
48   - if ([self.representedAssetIdentifier isEqualToString:[[TZImageManager manager] getAssetIdentifier:model.asset]]) {
49   - self.imageView.image = photo;
50   - self.model.cachedImage = photo;
51   - } else {
52   - // NSLog(@"this cell is showing other asset");
53   - [[PHImageManager defaultManager] cancelImageRequest:self.imageRequestID];
54   - }
55   - if (!isDegraded) {
56   - [self hideProgressView];
57   - self.imageRequestID = 0;
58   - }
59   - } progressHandler:nil networkAccessAllowed:NO];
60   - if (imageRequestID && self.imageRequestID && imageRequestID != self.imageRequestID) {
61   - [[PHImageManager defaultManager] cancelImageRequest:self.imageRequestID];
62   - // NSLog(@"cancelImageRequest %d",self.imageRequestID);
63   - }
64   - self.imageRequestID = imageRequestID;
65   - }
66   - self.selectPhotoButton.selected = model.isSelected;
67   - self.selectImageView.image = self.selectPhotoButton.isSelected ? self.photoSelImage : self.photoDefImage;
68   - self.indexLabel.hidden = !self.selectPhotoButton.isSelected;
69   -
70   - self.type = (NSInteger)model.type;
71   - // 让宽度/高度小于 最小可选照片尺寸 的图片不能选中
72   - if (![[TZImageManager manager] isPhotoSelectableWithAsset:model.asset]) {
73   - if (_selectImageView.hidden == NO) {
74   - self.selectPhotoButton.hidden = YES;
75   - _selectImageView.hidden = YES;
76   - }
77   - }
78   - // 如果用户选中了该图片,提前获取一下大图
79   - if (model.isSelected) {
80   - [self requestBigImage];
81   - } else {
82   - [self cancelBigImageRequest];
83   - }
84   - if (model.needOscillatoryAnimation) {
85   - [UIView showOscillatoryAnimationWithLayer:self.selectImageView.layer type:TZOscillatoryAnimationToBigger];
86   - }
87   - model.needOscillatoryAnimation = NO;
88   - [self setNeedsLayout];
89   -
90   - if (self.assetCellDidSetModelBlock) {
91   - self.assetCellDidSetModelBlock(self, _imageView, _selectImageView, _indexLabel, _bottomView, _timeLength, _videoImgView);
92   - }
93   -}
94   -
95   -- (void)setIndex:(NSInteger)index {
96   - _index = index;
97   - self.indexLabel.text = [NSString stringWithFormat:@"%zd", index];
98   - [self.contentView bringSubviewToFront:self.indexLabel];
99   -}
100   -
101   -- (void)setShowSelectBtn:(BOOL)showSelectBtn {
102   - _showSelectBtn = showSelectBtn;
103   - BOOL selectable = [[TZImageManager manager] isPhotoSelectableWithAsset:self.model.asset];
104   - if (!self.selectPhotoButton.hidden) {
105   - self.selectPhotoButton.hidden = !showSelectBtn || !selectable;
106   - }
107   - if (!self.selectImageView.hidden) {
108   - self.selectImageView.hidden = !showSelectBtn || !selectable;
109   - }
110   -}
111   -
112   -- (void)setType:(TZAssetCellType)type {
113   - _type = type;
114   - if (type == TZAssetCellTypePhoto || type == TZAssetCellTypeLivePhoto || (type == TZAssetCellTypePhotoGif && !self.allowPickingGif) || self.allowPickingMultipleVideo) {
115   - _selectImageView.hidden = NO;
116   - _selectPhotoButton.hidden = NO;
117   - _bottomView.hidden = YES;
118   - } else { // Video of Gif
119   - _selectImageView.hidden = YES;
120   - _selectPhotoButton.hidden = YES;
121   - }
122   -
123   - if (type == TZAssetCellTypeVideo) {
124   - self.bottomView.hidden = NO;
125   - self.timeLength.text = _model.timeLength;
126   - self.videoImgView.hidden = NO;
127   - _timeLength.tz_left = self.videoImgView.tz_right;
128   - _timeLength.textAlignment = NSTextAlignmentRight;
129   - } else if (type == TZAssetCellTypePhotoGif && self.allowPickingGif) {
130   - self.bottomView.hidden = NO;
131   - self.timeLength.text = @"GIF";
132   - self.videoImgView.hidden = YES;
133   - _timeLength.tz_left = 5;
134   - _timeLength.textAlignment = NSTextAlignmentLeft;
135   - }
136   -}
137   -
138   -- (void)setAllowPreview:(BOOL)allowPreview {
139   - _allowPreview = allowPreview;
140   - if (allowPreview) {
141   - _imageView.userInteractionEnabled = NO;
142   - _tapGesture.enabled = NO;
143   - } else {
144   - _imageView.userInteractionEnabled = YES;
145   - _tapGesture.enabled = YES;
146   - }
147   -}
148   -
149   -- (void)selectPhotoButtonClick:(UIButton *)sender {
150   - if (self.didSelectPhotoBlock) {
151   - self.didSelectPhotoBlock(sender.isSelected);
152   - }
153   - self.selectImageView.image = sender.isSelected ? self.photoSelImage : self.photoDefImage;
154   - if (sender.isSelected) {
155   - if (![TZImagePickerConfig sharedInstance].showSelectedIndex && ![TZImagePickerConfig sharedInstance].showPhotoCannotSelectLayer) {
156   - [UIView showOscillatoryAnimationWithLayer:_selectImageView.layer type:TZOscillatoryAnimationToBigger];
157   - }
158   - // 用户选中了该图片,提前获取一下大图
159   - [self requestBigImage];
160   - } else { // 取消选中,取消大图的获取
161   - [self cancelBigImageRequest];
162   - }
163   -}
164   -
165   -/// 只在单选状态且allowPreview为NO时会有该事件
166   -- (void)didTapImageView {
167   - if (self.didSelectPhotoBlock) {
168   - self.didSelectPhotoBlock(NO);
169   - }
170   -}
171   -
172   -- (void)hideProgressView {
173   - if (_progressView) {
174   - self.progressView.hidden = YES;
175   - self.imageView.alpha = 1.0;
176   - }
177   -}
178   -
179   -- (void)requestBigImage {
180   - if (_bigImageRequestID) {
181   - [[PHImageManager defaultManager] cancelImageRequest:_bigImageRequestID];
182   - }
183   -
184   - _bigImageRequestID = [[TZImageManager manager] requestImageDataForAsset:_model.asset completion:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
185   - [self hideProgressView];
186   - } progressHandler:^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
187   - if (self.model.isSelected) {
188   - progress = progress > 0.02 ? progress : 0.02;;
189   - self.progressView.progress = progress;
190   - self.progressView.hidden = NO;
191   - self.imageView.alpha = 0.4;
192   - if (progress >= 1) {
193   - [self hideProgressView];
194   - }
195   - } else {
196   - *stop = YES;
197   - [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
198   - [self cancelBigImageRequest];
199   - }
200   - }];
201   -}
202   -
203   -- (void)cancelBigImageRequest {
204   - if (_bigImageRequestID) {
205   - [[PHImageManager defaultManager] cancelImageRequest:_bigImageRequestID];
206   - }
207   - [self hideProgressView];
208   -}
209   -
210   -#pragma mark - Lazy load
211   -
212   -- (UIButton *)selectPhotoButton {
213   - if (_selectPhotoButton == nil) {
214   - UIButton *selectPhotoButton = [[UIButton alloc] init];
215   - [selectPhotoButton addTarget:self action:@selector(selectPhotoButtonClick:) forControlEvents:UIControlEventTouchUpInside];
216   - [self.contentView addSubview:selectPhotoButton];
217   - _selectPhotoButton = selectPhotoButton;
218   - }
219   - return _selectPhotoButton;
220   -}
221   -
222   -- (UIImageView *)imageView {
223   - if (_imageView == nil) {
224   - UIImageView *imageView = [[UIImageView alloc] init];
225   - imageView.contentMode = UIViewContentModeScaleAspectFill;
226   - imageView.clipsToBounds = YES;
227   - [self.contentView addSubview:imageView];
228   - _imageView = imageView;
229   -
230   - _tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapImageView)];
231   - [_imageView addGestureRecognizer:_tapGesture];
232   - }
233   - return _imageView;
234   -}
235   -
236   -- (UIImageView *)selectImageView {
237   - if (_selectImageView == nil) {
238   - UIImageView *selectImageView = [[UIImageView alloc] init];
239   - selectImageView.contentMode = UIViewContentModeCenter;
240   - selectImageView.clipsToBounds = YES;
241   - [self.contentView addSubview:selectImageView];
242   - _selectImageView = selectImageView;
243   - }
244   - return _selectImageView;
245   -}
246   -
247   -- (UIView *)bottomView {
248   - if (_bottomView == nil) {
249   - UIView *bottomView = [[UIView alloc] init];
250   - static NSInteger rgb = 0;
251   - bottomView.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.8];
252   - [self.contentView addSubview:bottomView];
253   - _bottomView = bottomView;
254   - }
255   - return _bottomView;
256   -}
257   -
258   -- (UIButton *)cannotSelectLayerButton {
259   - if (_cannotSelectLayerButton == nil) {
260   - UIButton *cannotSelectLayerButton = [[UIButton alloc] init];
261   - [self.contentView addSubview:cannotSelectLayerButton];
262   - _cannotSelectLayerButton = cannotSelectLayerButton;
263   - }
264   - return _cannotSelectLayerButton;
265   -}
266   -
267   -- (UIImageView *)videoImgView {
268   - if (_videoImgView == nil) {
269   - UIImageView *videoImgView = [[UIImageView alloc] init];
270   - [videoImgView setImage:[UIImage imageNamedFromMyBundle:@"VideoSendIcon"]];
271   - [self.bottomView addSubview:videoImgView];
272   - _videoImgView = videoImgView;
273   - }
274   - return _videoImgView;
275   -}
276   -
277   -- (UILabel *)timeLength {
278   - if (_timeLength == nil) {
279   - UILabel *timeLength = [[UILabel alloc] init];
280   - timeLength.font = [UIFont boldSystemFontOfSize:11];
281   - timeLength.textColor = [UIColor whiteColor];
282   - timeLength.textAlignment = NSTextAlignmentRight;
283   - [self.bottomView addSubview:timeLength];
284   - _timeLength = timeLength;
285   - }
286   - return _timeLength;
287   -}
288   -
289   -- (UILabel *)indexLabel {
290   - if (_indexLabel == nil) {
291   - UILabel *indexLabel = [[UILabel alloc] init];
292   - indexLabel.font = [UIFont systemFontOfSize:14];
293   - indexLabel.textColor = [UIColor whiteColor];
294   - indexLabel.textAlignment = NSTextAlignmentCenter;
295   - [self.contentView addSubview:indexLabel];
296   - _indexLabel = indexLabel;
297   - }
298   - return _indexLabel;
299   -}
300   -
301   -- (TZProgressView *)progressView {
302   - if (_progressView == nil) {
303   - _progressView = [[TZProgressView alloc] init];
304   - _progressView.hidden = YES;
305   - [self addSubview:_progressView];
306   - }
307   - return _progressView;
308   -}
309   -
310   -- (void)layoutSubviews {
311   - [super layoutSubviews];
312   - _cannotSelectLayerButton.frame = self.bounds;
313   - if (self.allowPreview) {
314   - _selectPhotoButton.frame = CGRectMake(self.tz_width - 44, 0, 44, 44);
315   - } else {
316   - _selectPhotoButton.frame = self.bounds;
317   - }
318   - _selectImageView.frame = CGRectMake(self.tz_width - 27, 3, 24, 24);
319   - if (_selectImageView.image.size.width <= 27) {
320   - _selectImageView.contentMode = UIViewContentModeCenter;
321   - } else {
322   - _selectImageView.contentMode = UIViewContentModeScaleAspectFit;
323   - }
324   - _indexLabel.frame = _selectImageView.frame;
325   - _imageView.frame = CGRectMake(0, 0, self.tz_width, self.tz_height);
326   -
327   - static CGFloat progressWH = 20;
328   - CGFloat progressXY = (self.tz_width - progressWH) / 2;
329   - _progressView.frame = CGRectMake(progressXY, progressXY, progressWH, progressWH);
330   -
331   - _bottomView.frame = CGRectMake(0, self.tz_height - 17, self.tz_width, 17);
332   - _videoImgView.frame = CGRectMake(8, 0, 17, 17);
333   - _timeLength.frame = CGRectMake(self.videoImgView.tz_right, 0, self.tz_width - self.videoImgView.tz_right - 5, 17);
334   -
335   - self.type = (NSInteger)self.model.type;
336   - self.showSelectBtn = self.showSelectBtn;
337   -
338   - [self.contentView bringSubviewToFront:_bottomView];
339   - [self.contentView bringSubviewToFront:_cannotSelectLayerButton];
340   - [self.contentView bringSubviewToFront:_selectPhotoButton];
341   - [self.contentView bringSubviewToFront:_selectImageView];
342   - [self.contentView bringSubviewToFront:_indexLabel];
343   -
344   - if (self.assetCellDidLayoutSubviewsBlock) {
345   - self.assetCellDidLayoutSubviewsBlock(self, _imageView, _selectImageView, _indexLabel, _bottomView, _timeLength, _videoImgView);
346   - }
347   -}
348   -
349   -@end
350   -
351   -@interface TZAlbumCell ()
352   -@property (weak, nonatomic) UIImageView *posterImageView;
353   -@property (weak, nonatomic) UILabel *titleLabel;
354   -@end
355   -
356   -@implementation TZAlbumCell
357   -
358   -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
359   - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
360   - self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
361   - return self;
362   -}
363   -
364   -- (void)setModel:(TZAlbumModel *)model {
365   - _model = model;
366   -
367   - NSMutableAttributedString *nameString = [[NSMutableAttributedString alloc] initWithString:model.name attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor blackColor]}];
368   - NSAttributedString *countString = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" (%zd)",model.count] attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor lightGrayColor]}];
369   - [nameString appendAttributedString:countString];
370   - self.titleLabel.attributedText = nameString;
371   - [[TZImageManager manager] getPostImageWithAlbumModel:model completion:^(UIImage *postImage) {
372   - self.posterImageView.image = postImage;
373   - }];
374   - if (model.selectedCount) {
375   - self.selectedCountButton.hidden = NO;
376   - [self.selectedCountButton setTitle:[NSString stringWithFormat:@"%zd",model.selectedCount] forState:UIControlStateNormal];
377   - } else {
378   - self.selectedCountButton.hidden = YES;
379   - }
380   -
381   - if (self.albumCellDidSetModelBlock) {
382   - self.albumCellDidSetModelBlock(self, _posterImageView, _titleLabel);
383   - }
384   -}
385   -
386   -/// For fitting iOS6
387   -- (void)layoutSubviews {
388   - if (iOS7Later) [super layoutSubviews];
389   - _selectedCountButton.frame = CGRectMake(self.tz_width - 24 - 30, 23, 24, 24);
390   - NSInteger titleHeight = ceil(self.titleLabel.font.lineHeight);
391   - self.titleLabel.frame = CGRectMake(80, (self.tz_height - titleHeight) / 2, self.tz_width - 80 - 50, titleHeight);
392   - self.posterImageView.frame = CGRectMake(0, 0, 70, 70);
393   -
394   - if (self.albumCellDidLayoutSubviewsBlock) {
395   - self.albumCellDidLayoutSubviewsBlock(self, _posterImageView, _titleLabel);
396   - }
397   -}
398   -
399   -- (void)layoutSublayersOfLayer:(CALayer *)layer {
400   - if (iOS7Later) [super layoutSublayersOfLayer:layer];
401   -}
402   -
403   -#pragma mark - Lazy load
404   -
405   -- (UIImageView *)posterImageView {
406   - if (_posterImageView == nil) {
407   - UIImageView *posterImageView = [[UIImageView alloc] init];
408   - posterImageView.contentMode = UIViewContentModeScaleAspectFill;
409   - posterImageView.clipsToBounds = YES;
410   - [self.contentView addSubview:posterImageView];
411   - _posterImageView = posterImageView;
412   - }
413   - return _posterImageView;
414   -}
415   -
416   -- (UILabel *)titleLabel {
417   - if (_titleLabel == nil) {
418   - UILabel *titleLabel = [[UILabel alloc] init];
419   - titleLabel.font = [UIFont boldSystemFontOfSize:17];
420   - titleLabel.textColor = [UIColor blackColor];
421   - titleLabel.textAlignment = NSTextAlignmentLeft;
422   - [self.contentView addSubview:titleLabel];
423   - _titleLabel = titleLabel;
424   - }
425   - return _titleLabel;
426   -}
427   -
428   -- (UIButton *)selectedCountButton {
429   - if (_selectedCountButton == nil) {
430   - UIButton *selectedCountButton = [[UIButton alloc] init];
431   - selectedCountButton.layer.cornerRadius = 12;
432   - selectedCountButton.clipsToBounds = YES;
433   - selectedCountButton.backgroundColor = [UIColor redColor];
434   - [selectedCountButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
435   - selectedCountButton.titleLabel.font = [UIFont systemFontOfSize:15];
436   - [self.contentView addSubview:selectedCountButton];
437   - _selectedCountButton = selectedCountButton;
438   - }
439   - return _selectedCountButton;
440   -}
441   -
442   -@end
443   -
444   -
445   -
446   -@implementation TZAssetCameraCell
447   -
448   -- (instancetype)initWithFrame:(CGRect)frame {
449   - self = [super initWithFrame:frame];
450   - if (self) {
451   - self.backgroundColor = [UIColor whiteColor];
452   - _imageView = [[UIImageView alloc] init];
453   - _imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500];
454   - _imageView.contentMode = UIViewContentModeScaleAspectFill;
455   - [self.contentView addSubview:_imageView];
456   - self.clipsToBounds = YES;
457   - }
458   - return self;
459   -}
460   -
461   -- (void)layoutSubviews {
462   - [super layoutSubviews];
463   - _imageView.frame = self.bounds;
464   -}
465   -
466   -@end
CNLiveImagePickerController/TZAssetModel.h deleted 100755 → 0
1   -//
2   -// TZAssetModel.h
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 15/12/24.
6   -// Copyright © 2015年 谭真. All rights reserved.
7   -//
8   -
9   -#import <Foundation/Foundation.h>
10   -#import <UIKit/UIKit.h>
11   -
12   -typedef enum : NSUInteger {
13   - TZAssetModelMediaTypePhoto = 0,
14   - TZAssetModelMediaTypeLivePhoto,
15   - TZAssetModelMediaTypePhotoGif,
16   - TZAssetModelMediaTypeVideo,
17   - TZAssetModelMediaTypeAudio
18   -} TZAssetModelMediaType;
19   -
20   -@class PHAsset;
21   -@interface TZAssetModel : NSObject
22   -
23   -@property (nonatomic, strong) id asset; ///< PHAsset or ALAsset
24   -@property (nonatomic, assign) BOOL isSelected; ///< The select status of a photo, default is No
25   -@property (nonatomic, assign) TZAssetModelMediaType type;
26   -@property (assign, nonatomic) BOOL needOscillatoryAnimation;
27   -@property (nonatomic, copy) NSString *timeLength;
28   -@property (strong, nonatomic) UIImage *cachedImage;
29   -
30   -/// Init a photo dataModel With a asset
31   -/// 用一个PHAsset/ALAsset实例,初始化一个照片模型
32   -+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type;
33   -+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength;
34   -
35   -@end
36   -
37   -
38   -@class PHFetchResult;
39   -@interface TZAlbumModel : NSObject
40   -
41   -@property (nonatomic, strong) NSString *name; ///< The album name
42   -@property (nonatomic, assign) NSInteger count; ///< Count of photos the album contain
43   -@property (nonatomic, strong) id result; ///< PHFetchResult<PHAsset> or ALAssetsGroup<ALAsset>
44   -
45   -@property (nonatomic, strong) NSArray *models;
46   -@property (nonatomic, strong) NSArray *selectedModels;
47   -@property (nonatomic, assign) NSUInteger selectedCount;
48   -
49   -@property (nonatomic, assign) BOOL isCameraRoll;
50   -
51   -- (void)setResult:(id)result needFetchAssets:(BOOL)needFetchAssets;
52   -
53   -@end
CNLiveImagePickerController/TZAssetModel.m deleted 100755 → 0
1   -//
2   -// TZAssetModel.m
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 15/12/24.
6   -// Copyright © 2015年 谭真. All rights reserved.
7   -//
8   -
9   -#import "TZAssetModel.h"
10   -#import "TZImageManager.h"
11   -
12   -@implementation TZAssetModel
13   -
14   -+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type{
15   - TZAssetModel *model = [[TZAssetModel alloc] init];
16   - model.asset = asset;
17   - model.isSelected = NO;
18   - model.type = type;
19   - return model;
20   -}
21   -
22   -+ (instancetype)modelWithAsset:(id)asset type:(TZAssetModelMediaType)type timeLength:(NSString *)timeLength {
23   - TZAssetModel *model = [self modelWithAsset:asset type:type];
24   - model.timeLength = timeLength;
25   - return model;
26   -}
27   -
28   -@end
29   -
30   -
31   -
32   -@implementation TZAlbumModel
33   -
34   -- (void)setResult:(id)result needFetchAssets:(BOOL)needFetchAssets {
35   - _result = result;
36   - if (needFetchAssets) {
37   - [[TZImageManager manager] getAssetsFromFetchResult:result completion:^(NSArray<TZAssetModel *> *models) {
38   - self->_models = models;
39   - if (self->_selectedModels) {
40   - [self checkSelectedModels];
41   - }
42   - }];
43   - }
44   -}
45   -
46   -- (void)setSelectedModels:(NSArray *)selectedModels {
47   - _selectedModels = selectedModels;
48   - if (_models) {
49   - [self checkSelectedModels];
50   - }
51   -}
52   -
53   -- (void)checkSelectedModels {
54   - self.selectedCount = 0;
55   - NSMutableArray *selectedAssets = [NSMutableArray array];
56   - for (TZAssetModel *model in _selectedModels) {
57   - [selectedAssets addObject:model.asset];
58   - }
59   - for (TZAssetModel *model in _models) {
60   - if ([[TZImageManager manager] isAssetsArray:selectedAssets containAsset:model.asset]) {
61   - self.selectedCount ++;
62   - }
63   - }
64   -}
65   -
66   -- (NSString *)name {
67   - if (_name) {
68   - return _name;
69   - }
70   - return @"";
71   -}
72   -
73   -@end
CNLiveImagePickerController/TZGifPhotoPreviewController.h deleted 100755 → 0
1   -//
2   -// TZGifPhotoPreviewController.h
3   -// TZImagePickerController
4   -//
5   -// Created by ttouch on 2016/12/13.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -//
8   -
9   -#import <UIKit/UIKit.h>
10   -
11   -@class TZAssetModel;
12   -@interface TZGifPhotoPreviewController : UIViewController
13   -
14   -@property (nonatomic, strong) TZAssetModel *model;
15   -
16   -@end
CNLiveImagePickerController/TZGifPhotoPreviewController.m deleted 100755 → 0
1   -//
2   -// TZGifPhotoPreviewController.m
3   -// TZImagePickerController
4   -//
5   -// Created by ttouch on 2016/12/13.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -//
8   -
9   -#import "TZGifPhotoPreviewController.h"
10   -#import "TZImagePickerController.h"
11   -#import "TZAssetModel.h"
12   -#import "UIView+Layout.h"
13   -#import "TZPhotoPreviewCell.h"
14   -#import "TZImageManager.h"
15   -
16   -#pragma clang diagnostic push
17   -#pragma clang diagnostic ignored "-Wdeprecated-declarations"
18   -
19   -@interface TZGifPhotoPreviewController () {
20   - UIView *_toolBar;
21   - UIButton *_doneButton;
22   - UIProgressView *_progress;
23   -
24   - TZPhotoPreviewView *_previewView;
25   -
26   - UIStatusBarStyle _originStatusBarStyle;
27   -}
28   -@end
29   -
30   -@implementation TZGifPhotoPreviewController
31   -
32   -- (void)viewDidLoad {
33   - [super viewDidLoad];
34   - self.view.backgroundColor = [UIColor blackColor];
35   - TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
36   - if (tzImagePickerVc) {
37   - self.navigationItem.title = [NSString stringWithFormat:@"GIF %@",tzImagePickerVc.previewBtnTitleStr];
38   - }
39   - [self configPreviewView];
40   - [self configBottomToolBar];
41   -}
42   -
43   -- (void)viewWillAppear:(BOOL)animated {
44   - [super viewWillAppear:animated];
45   - _originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
46   - [UIApplication sharedApplication].statusBarStyle = iOS7Later ? UIStatusBarStyleLightContent : UIStatusBarStyleBlackOpaque;
47   -}
48   -
49   -- (void)viewWillDisappear:(BOOL)animated {
50   - [super viewWillDisappear:animated];
51   - [UIApplication sharedApplication].statusBarStyle = _originStatusBarStyle;
52   -}
53   -
54   -- (void)configPreviewView {
55   - _previewView = [[TZPhotoPreviewView alloc] initWithFrame:CGRectZero];
56   - _previewView.model = self.model;
57   - __weak typeof(self) weakSelf = self;
58   - [_previewView setSingleTapGestureBlock:^{
59   - __strong typeof(weakSelf) strongSelf = weakSelf;
60   - [strongSelf signleTapAction];
61   - }];
62   - [self.view addSubview:_previewView];
63   -}
64   -
65   -- (void)configBottomToolBar {
66   - _toolBar = [[UIView alloc] initWithFrame:CGRectZero];
67   - CGFloat rgb = 34 / 255.0;
68   - _toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7];
69   -
70   - _doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
71   - _doneButton.titleLabel.font = [UIFont systemFontOfSize:16];
72   - [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside];
73   - TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
74   - if (tzImagePickerVc) {
75   - [_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal];
76   - [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
77   - } else {
78   - [_doneButton setTitle:[NSBundle tz_localizedStringForKey:@"Done"] forState:UIControlStateNormal];
79   - [_doneButton setTitleColor:[UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0] forState:UIControlStateNormal];
80   - }
81   - [_toolBar addSubview:_doneButton];
82   -
83   - UILabel *byteLabel = [[UILabel alloc] init];
84   - byteLabel.textColor = [UIColor whiteColor];
85   - byteLabel.font = [UIFont systemFontOfSize:13];
86   - byteLabel.frame = CGRectMake(10, 0, 100, 44);
87   - [[TZImageManager manager] getPhotosBytesWithArray:@[_model] completion:^(NSString *totalBytes) {
88   - byteLabel.text = totalBytes;
89   - }];
90   - [_toolBar addSubview:byteLabel];
91   -
92   - [self.view addSubview:_toolBar];
93   -
94   - if (tzImagePickerVc.gifPreviewPageUIConfigBlock) {
95   - tzImagePickerVc.gifPreviewPageUIConfigBlock(_toolBar, _doneButton);
96   - }
97   -}
98   -
99   -#pragma mark - Layout
100   -
101   -- (void)viewDidLayoutSubviews {
102   - [super viewDidLayoutSubviews];
103   -
104   - _previewView.frame = self.view.bounds;
105   - _previewView.scrollView.frame = self.view.bounds;
106   - CGFloat toolBarHeight = [TZCommonTools tz_isIPhoneX] ? 44 + (83 - 49) : 44;
107   - _toolBar.frame = CGRectMake(0, self.view.tz_height - toolBarHeight, self.view.tz_width, toolBarHeight);
108   - _doneButton.frame = CGRectMake(self.view.tz_width - 44 - 12, 0, 44, 44);
109   -
110   - TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
111   - if (tzImagePickerVc.gifPreviewPageDidLayoutSubviewsBlock) {
112   - tzImagePickerVc.gifPreviewPageDidLayoutSubviewsBlock(_toolBar, _doneButton);
113   - }
114   -}
115   -
116   -#pragma mark - Click Event
117   -
118   -- (void)signleTapAction {
119   - _toolBar.hidden = !_toolBar.isHidden;
120   - [self.navigationController setNavigationBarHidden:_toolBar.isHidden];
121   - TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
122   - if (iOS7Later) {
123   - if (_toolBar.isHidden) {
124   - [UIApplication sharedApplication].statusBarHidden = YES;
125   - } else if (tzImagePickerVc.needShowStatusBar) {
126   - [UIApplication sharedApplication].statusBarHidden = NO;
127   - }
128   - }
129   -}
130   -
131   -- (void)doneButtonClick {
132   - if (self.navigationController) {
133   - TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
134   - if (imagePickerVc.autoDismiss) {
135   - [self.navigationController dismissViewControllerAnimated:YES completion:^{
136   - [self callDelegateMethod];
137   - }];
138   - } else {
139   - [self callDelegateMethod];
140   - }
141   - } else {
142   - [self dismissViewControllerAnimated:YES completion:^{
143   - [self callDelegateMethod];
144   - }];
145   - }
146   -}
147   -
148   -- (void)callDelegateMethod {
149   - TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
150   - UIImage *animatedImage = _previewView.imageView.image;
151   - if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingGifImage:sourceAssets:)]) {
152   - [imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingGifImage:animatedImage sourceAssets:_model.asset];
153   - }
154   - if (imagePickerVc.didFinishPickingGifImageHandle) {
155   - imagePickerVc.didFinishPickingGifImageHandle(animatedImage,_model.asset);
156   - }
157   -}
158   -
159   -#pragma clang diagnostic pop
160   -
161   -@end
CNLiveImagePickerController/TZImageCropManager.h deleted 100755 → 0
1   -//
2   -// TZImageCropManager.h
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 2016/12/5.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -// 图片裁剪管理类
8   -
9   -#import <Foundation/Foundation.h>
10   -#import <UIKit/UIKit.h>
11   -
12   -@interface TZImageCropManager : NSObject
13   -
14   -/// 裁剪框背景的处理
15   -+ (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView needCircleCrop:(BOOL)needCircleCrop;
16   -
17   -/*
18   - 1.7.2 为了解决多位同学对于图片裁剪的需求,我这两天有空便在研究图片裁剪
19   - 幸好有tuyou的PhotoTweaks库做参考,裁剪的功能实现起来简单许多
20   - 该方法和其内部引用的方法基本来自于tuyou的PhotoTweaks库,我做了稍许删减和修改
21   - 感谢tuyou同学在github开源了优秀的裁剪库PhotoTweaks,表示感谢
22   - PhotoTweaks库的github链接:https://github.com/itouch2/PhotoTweaks
23   - */
24   -/// 获得裁剪后的图片
25   -+ (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView;
26   -
27   -/// 获取圆形图片
28   -+ (UIImage *)circularClipImage:(UIImage *)image;
29   -
30   -@end
31   -
32   -
33   -/// 该分类的代码来自SDWebImage:https://github.com/rs/SDWebImage
34   -/// 为了防止冲突,我将分类名字和方法名字做了修改
35   -@interface UIImage (TZGif)
36   -
37   -+ (UIImage *)sd_tz_animatedGIFWithData:(NSData *)data;
38   -
39   -@end
CNLiveImagePickerController/TZImageCropManager.m deleted 100755 → 0
1   -//
2   -// TZImageCropManager.m
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 2016/12/5.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -//
8   -
9   -#import "TZImageCropManager.h"
10   -#import "UIView+Layout.h"
11   -#import <ImageIO/ImageIO.h>
12   -#import "TZImageManager.h"
13   -#import "TZImagePickerController.h"
14   -
15   -@implementation TZImageCropManager
16   -
17   -/// 裁剪框背景的处理
18   -+ (void)overlayClippingWithView:(UIView *)view cropRect:(CGRect)cropRect containerView:(UIView *)containerView needCircleCrop:(BOOL)needCircleCrop {
19   - UIBezierPath *path= [UIBezierPath bezierPathWithRect:[UIScreen mainScreen].bounds];
20   - CAShapeLayer *layer = [CAShapeLayer layer];
21   - if (needCircleCrop) { // 圆形裁剪框
22   - [path appendPath:[UIBezierPath bezierPathWithArcCenter:containerView.center radius:cropRect.size.width / 2 startAngle:0 endAngle: 2 * M_PI clockwise:NO]];
23   - } else { // 矩形裁剪框
24   - [path appendPath:[UIBezierPath bezierPathWithRect:cropRect]];
25   - }
26   - layer.path = path.CGPath;
27   - layer.fillRule = kCAFillRuleEvenOdd;
28   - layer.fillColor = [[UIColor blackColor] CGColor];
29   - layer.opacity = 0.5;
30   - [view.layer addSublayer:layer];
31   -}
32   -
33   -/// 获得裁剪后的图片
34   -+ (UIImage *)cropImageView:(UIImageView *)imageView toRect:(CGRect)rect zoomScale:(double)zoomScale containerView:(UIView *)containerView {
35   - CGAffineTransform transform = CGAffineTransformIdentity;
36   - // 平移的处理
37   - CGRect imageViewRect = [imageView convertRect:imageView.bounds toView:containerView];
38   - CGPoint point = CGPointMake(imageViewRect.origin.x + imageViewRect.size.width / 2, imageViewRect.origin.y + imageViewRect.size.height / 2);
39   - CGFloat xMargin = containerView.tz_width - CGRectGetMaxX(rect) - rect.origin.x;
40   - CGPoint zeroPoint = CGPointMake((CGRectGetWidth(containerView.frame) - xMargin) / 2, containerView.center.y);
41   - CGPoint translation = CGPointMake(point.x - zeroPoint.x, point.y - zeroPoint.y);
42   - transform = CGAffineTransformTranslate(transform, translation.x, translation.y);
43   - // 缩放的处理
44   - transform = CGAffineTransformScale(transform, zoomScale, zoomScale);
45   -
46   - CGImageRef imageRef = [self newTransformedImage:transform
47   - sourceImage:imageView.image.CGImage
48   - sourceSize:imageView.image.size
49   - outputWidth:rect.size.width * [UIScreen mainScreen].scale
50   - cropSize:rect.size
51   - imageViewSize:imageView.frame.size];
52   - UIImage *cropedImage = [UIImage imageWithCGImage:imageRef];
53   - cropedImage = [[TZImageManager manager] fixOrientation:cropedImage];
54   - CGImageRelease(imageRef);
55   - return cropedImage;
56   -}
57   -
58   -+ (CGImageRef)newTransformedImage:(CGAffineTransform)transform sourceImage:(CGImageRef)sourceImage sourceSize:(CGSize)sourceSize outputWidth:(CGFloat)outputWidth cropSize:(CGSize)cropSize imageViewSize:(CGSize)imageViewSize {
59   - CGImageRef source = [self newScaledImage:sourceImage toSize:sourceSize];
60   -
61   - CGFloat aspect = cropSize.height/cropSize.width;
62   - CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect);
63   -
64   - CGContextRef context = CGBitmapContextCreate(NULL, outputSize.width, outputSize.height, CGImageGetBitsPerComponent(source), 0, CGImageGetColorSpace(source), CGImageGetBitmapInfo(source));
65   - CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
66   - CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height));
67   -
68   - CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width / cropSize.width, outputSize.height / cropSize.height);
69   - uiCoords = CGAffineTransformTranslate(uiCoords, cropSize.width/2.0, cropSize.height / 2.0);
70   - uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0);
71   - CGContextConcatCTM(context, uiCoords);
72   -
73   - CGContextConcatCTM(context, transform);
74   - CGContextScaleCTM(context, 1.0, -1.0);
75   -
76   - CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2, -imageViewSize.height/2.0, imageViewSize.width, imageViewSize.height), source);
77   - CGImageRef resultRef = CGBitmapContextCreateImage(context);
78   - CGContextRelease(context);
79   - CGImageRelease(source);
80   - return resultRef;
81   -}
82   -
83   -+ (CGImageRef)newScaledImage:(CGImageRef)source toSize:(CGSize)size {
84   - CGSize srcSize = size;
85   - CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
86   - CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, rgbColorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
87   - CGColorSpaceRelease(rgbColorSpace);
88   -
89   - CGContextSetInterpolationQuality(context, kCGInterpolationNone);
90   - CGContextTranslateCTM(context, size.width/2, size.height/2);
91   -
92   - CGContextDrawImage(context, CGRectMake(-srcSize.width/2, -srcSize.height/2, srcSize.width, srcSize.height), source);
93   -
94   - CGImageRef resultRef = CGBitmapContextCreateImage(context);
95   - CGContextRelease(context);
96   - return resultRef;
97   -}
98   -
99   -/// 获取圆形图片
100   -+ (UIImage *)circularClipImage:(UIImage *)image {
101   - UIGraphicsBeginImageContextWithOptions(image.size, NO, [UIScreen mainScreen].scale);
102   -
103   - CGContextRef ctx = UIGraphicsGetCurrentContext();
104   - CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
105   - CGContextAddEllipseInRect(ctx, rect);
106   - CGContextClip(ctx);
107   -
108   - [image drawInRect:rect];
109   - UIImage *circleImage = UIGraphicsGetImageFromCurrentImageContext();
110   -
111   - UIGraphicsEndImageContext();
112   - return circleImage;
113   -}
114   -
115   -@end
116   -
117   -
118   -@implementation UIImage (TZGif)
119   -
120   -+ (UIImage *)sd_tz_animatedGIFWithData:(NSData *)data {
121   - if (!data) {
122   - return nil;
123   - }
124   -
125   - CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
126   -
127   - size_t count = CGImageSourceGetCount(source);
128   -
129   - UIImage *animatedImage;
130   -
131   - if (count <= 1) {
132   - animatedImage = [[UIImage alloc] initWithData:data];
133   - }
134   - else {
135   - // images数组过大时内存会飙升,在这里限制下最大count
136   - NSInteger maxCount = [TZImagePickerConfig sharedInstance].gifPreviewMaxImagesCount ?: 200;
137   - NSInteger interval = MAX((count + maxCount / 2) / maxCount, 1);
138   -
139   - NSMutableArray *images = [NSMutableArray array];
140   -
141   - NSTimeInterval duration = 0.0f;
142   -
143   - for (size_t i = 0; i < count; i+=interval) {
144   - CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
145   - if (!image) {
146   - continue;
147   - }
148   -
149   - duration += [self sd_frameDurationAtIndex:i source:source] * MIN(interval, 3);
150   -
151   - [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
152   -
153   - CGImageRelease(image);
154   - }
155   -
156   - if (!duration) {
157   - duration = (1.0f / 10.0f) * count;
158   - }
159   -
160   - animatedImage = [UIImage animatedImageWithImages:images duration:duration];
161   - }
162   -
163   - CFRelease(source);
164   -
165   - return animatedImage;
166   -}
167   -
168   -+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
169   - float frameDuration = 0.1f;
170   - CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
171   - NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
172   - NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
173   -
174   - NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
175   - if (delayTimeUnclampedProp) {
176   - frameDuration = [delayTimeUnclampedProp floatValue];
177   - }
178   - else {
179   -
180   - NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
181   - if (delayTimeProp) {
182   - frameDuration = [delayTimeProp floatValue];
183   - }
184   - }
185   -
186   - // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
187   - // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
188   - // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
189   - // for more information.
190   -
191   - if (frameDuration < 0.011f) {
192   - frameDuration = 0.100f;
193   - }
194   -
195   - CFRelease(cfFrameProperties);
196   - return frameDuration;
197   -}
198   -
199   -@end
CNLiveImagePickerController/TZImageManager.h deleted 100755 → 0
1   -//
2   -// TZImageManager.h
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 16/1/4.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -// 图片资源获取管理类
8   -
9   -#import <Foundation/Foundation.h>
10   -#import <UIKit/UIKit.h>
11   -#import <AVFoundation/AVFoundation.h>
12   -#import <Photos/Photos.h>
13   -#import "TZAssetModel.h"
14   -
15   -@class TZAlbumModel,TZAssetModel;
16   -@protocol TZImagePickerControllerDelegate;
17   -@interface TZImageManager : NSObject
18   -
19   -@property (nonatomic, strong) PHCachingImageManager *cachingImageManager;
20   -
21   -+ (instancetype)manager NS_SWIFT_NAME(default());
22   -+ (void)deallocManager;
23   -
24   -@property (weak, nonatomic) id<TZImagePickerControllerDelegate> pickerDelegate;
25   -
26   -#pragma mark - ADD: 原有逻辑-会话id(LXG)
27   -
28   -/// 导出路径
29   -@property (nonatomic, copy) NSString *outputPath;
30   -
31   -@property (nonatomic, assign) BOOL shouldFixOrientation;
32   -
33   -/// Default is 600px / 默认600像素宽
34   -@property (nonatomic, assign) CGFloat photoPreviewMaxWidth;
35   -/// The pixel width of output image, Default is 828px / 导出图片的宽度,默认828像素宽
36   -@property (nonatomic, assign) CGFloat photoWidth;
37   -
38   -/// Default is 4, Use in photos collectionView in TZPhotoPickerController
39   -/// 默认4列, TZPhotoPickerController中的照片collectionView
40   -@property (nonatomic, assign) NSInteger columnNumber;
41   -
42   -/// Sort photos ascending by modificationDate,Default is YES
43   -/// 对照片排序,按修改时间升序,默认是YES。如果设置为NO,最新的照片会显示在最前面,内部的拍照按钮会排在第一个
44   -@property (nonatomic, assign) BOOL sortAscendingByModificationDate;
45   -
46   -/// Minimum selectable photo width, Default is 0
47   -/// 最小可选中的图片宽度,默认是0,小于这个宽度的图片不可选中
48   -@property (nonatomic, assign) NSInteger minPhotoWidthSelectable;
49   -@property (nonatomic, assign) NSInteger minPhotoHeightSelectable;
50   -@property (nonatomic, assign) BOOL hideWhenCanNotSelect;
51   -
52   -/// Return YES if Authorized 返回YES如果得到了授权
53   -- (BOOL)authorizationStatusAuthorized;
54   -+ (NSInteger)authorizationStatus;
55   -- (void)requestAuthorizationWithCompletion:(void (^)(void))completion;
56   -
57   -/// Get Album 获得相册/相册数组
58   -- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion;
59   -- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray<TZAlbumModel *> *models))completion;
60   -
61   -/// Get Assets 获得Asset数组
62   -- (void)getAssetsFromFetchResult:(id)result completion:(void (^)(NSArray<TZAssetModel *> *models))completion;
63   -- (void)getAssetsFromFetchResult:(id)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *models))completion;
64   -- (void)getAssetFromFetchResult:(id)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *model))completion;
65   -
66   -/// Get photo 获得照片
67   -- (void)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *postImage))completion;
68   -
69   -- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
70   -- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
71   -- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed;
72   -- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed;
73   -- (int32_t)requestImageDataForAsset:(id)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler;
74   -
75   -/// Get full Image 获取原图
76   -/// 如下两个方法completion一般会调多次,一般会先返回缩略图,再返回原图(详见方法内部使用的系统API的说明),如果info[PHImageResultIsDegradedKey] 为 YES,则表明当前返回的是缩略图,否则是原图。
77   -- (void)getOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion;
78   -- (void)getOriginalPhotoWithAsset:(id)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion;
79   -// 该方法中,completion只会走一次
80   -- (void)getOriginalPhotoDataWithAsset:(id)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion;
81   -- (void)getOriginalPhotoDataWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion;
82   -
83   -/// Save photo 保存照片
84   -- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(NSError *error))completion;
85   -- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(NSError *error))completion;
86   -
87   -/// Save video 保存视频
88   -- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(NSError *error))completion;
89   -- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(NSError *error))completion;
90   -
91   -/// Get video 获得视频
92   -- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem * playerItem, NSDictionary * info))completion;
93   -- (void)getVideoWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion;
94   -
95   -/// Export video 导出视频 presetName: 预设名字,默认值是AVAssetExportPreset640x480
96   -- (void)getVideoOutputPathWithAsset:(id)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure;
97   -- (void)getVideoOutputPathWithAsset:(id)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure;
98   -/// Deprecated, Use -getVideoOutputPathWithAsset:failure:success:
99   -- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion __attribute__((deprecated("Use -getVideoOutputPathWithAsset:failure:success:")));
100   -
101   -/// Get photo bytes 获得一组照片的大小
102   -- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion;
103   -
104   -/// Judge is a assets array contain the asset 判断一个assets数组是否包含这个asset
105   -- (BOOL)isAssetsArray:(NSArray *)assets containAsset:(id)asset;
106   -
107   -- (NSString *)getAssetIdentifier:(id)asset;
108   -- (BOOL)isCameraRollAlbum:(id)metadata;
109   -
110   -/// 检查照片大小是否满足最小要求
111   -- (BOOL)isPhotoSelectableWithAsset:(id)asset;
112   -- (CGSize)photoSizeWithAsset:(id)asset;
113   -
114   -/// 修正图片转向
115   -- (UIImage *)fixOrientation:(UIImage *)aImage;
116   -
117   -/// 获取asset的资源类型
118   -- (TZAssetModelMediaType)getAssetType:(id)asset;
119   -/// 缩放图片至新尺寸
120   -- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size;
121   -
122   -/// 判断asset是否是视频
123   -- (BOOL)isVideo:(id)asset;
124   -
125   -@end
126   -
127   -//@interface TZSortDescriptor : NSSortDescriptor
128   -//
129   -//@end
CNLiveImagePickerController/TZImageManager.m deleted 100755 → 0
1   -//
2   -// TZImageManager.m
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 16/1/4.
6   -// Copyright © 2016年 谭真. All rights reserved.
7   -//
8   -
9   -#import "TZImageManager.h"
10   -#import <AssetsLibrary/AssetsLibrary.h>
11   -#import "TZAssetModel.h"
12   -#import "TZImagePickerController.h"
13   -
14   -@interface TZImageManager ()
15   -#pragma clang diagnostic push
16   -#pragma clang diagnostic ignored "-Wdeprecated-declarations"
17   -@property (nonatomic, strong) ALAssetsLibrary *assetLibrary;
18   -@end
19   -
20   -@implementation TZImageManager
21   -
22   -CGSize AssetGridThumbnailSize;
23   -CGFloat TZScreenWidth;
24   -CGFloat TZScreenScale;
25   -
26   -static TZImageManager *manager;
27   -static dispatch_once_t onceToken;
28   -
29   -+ (instancetype)manager {
30   - dispatch_once(&onceToken, ^{
31   - manager = [[self alloc] init];
32   - if (iOS8Later) {
33   - // manager.cachingImageManager = [[PHCachingImageManager alloc] init];
34   - // manager.cachingImageManager.allowsCachingHighQualityImages = YES;
35   - }
36   -
37   - [manager configTZScreenWidth];
38   - });
39   - return manager;
40   -}
41   -
42   -+ (void)deallocManager {
43   - onceToken = 0;
44   - manager = nil;
45   -}
46   -
47   -- (void)setPhotoWidth:(CGFloat)photoWidth {
48   - _photoWidth = photoWidth;
49   - TZScreenWidth = photoWidth / 2;
50   -}
51   -
52   -- (void)setColumnNumber:(NSInteger)columnNumber {
53   - [self configTZScreenWidth];
54   -
55   - _columnNumber = columnNumber;
56   - CGFloat margin = 4;
57   - CGFloat itemWH = (TZScreenWidth - 2 * margin - 4) / columnNumber - margin;
58   - AssetGridThumbnailSize = CGSizeMake(itemWH * TZScreenScale, itemWH * TZScreenScale);
59   -}
60   -
61   -- (void)configTZScreenWidth {
62   - TZScreenWidth = [UIScreen mainScreen].bounds.size.width;
63   - // 测试发现,如果scale在plus真机上取到3.0,内存会增大特别多。故这里写死成2.0
64   - TZScreenScale = 2.0;
65   - if (TZScreenWidth > 700) {
66   - TZScreenScale = 1.5;
67   - }
68   -}
69   -
70   -- (ALAssetsLibrary *)assetLibrary {
71   - if (_assetLibrary == nil) _assetLibrary = [[ALAssetsLibrary alloc] init];
72   - return _assetLibrary;
73   -}
74   -
75   -/// Return YES if Authorized 返回YES如果得到了授权
76   -- (BOOL)authorizationStatusAuthorized {
77   - NSInteger status = [self.class authorizationStatus];
78   - if (status == 0) {
79   - /**
80   - * 当某些情况下AuthorizationStatus == AuthorizationStatusNotDetermined时,无法弹出系统首次使用的授权alertView,系统应用设置里亦没有相册的设置,此时将无法使用,故作以下操作,弹出系统首次使用的授权alertView
81   - */
82   - [self requestAuthorizationWithCompletion:nil];
83   - }
84   -
85   - return status == 3;
86   -}
87   -
88   -+ (NSInteger)authorizationStatus {
89   - if (iOS8Later) {
90   - return [PHPhotoLibrary authorizationStatus];
91   - } else {
92   - return [ALAssetsLibrary authorizationStatus];
93   - }
94   - return NO;
95   -}
96   -
97   -- (void)requestAuthorizationWithCompletion:(void (^)(void))completion {
98   - void (^callCompletionBlock)(void) = ^(){
99   - dispatch_async(dispatch_get_main_queue(), ^{
100   - if (completion) {
101   - completion();
102   - }
103   - });
104   - };
105   -
106   - if (iOS8Later) {
107   - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
108   - [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
109   - callCompletionBlock();
110   - }];
111   - });
112   - } else {
113   - [self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
114   - callCompletionBlock();
115   - } failureBlock:^(NSError *error) {
116   - callCompletionBlock();
117   - }];
118   - }
119   -}
120   -
121   -#pragma mark - Get Album
122   -
123   -/// Get Album 获得相册/相册数组
124   -- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion {
125   - __block TZAlbumModel *model;
126   - if (iOS8Later) {
127   - PHFetchOptions *option = [[PHFetchOptions alloc] init];
128   - if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
129   - if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
130   - PHAssetMediaTypeVideo];
131   - // option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]];
132   - if (!self.sortAscendingByModificationDate) {
133   - option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]];
134   - }
135   - PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
136   - for (PHAssetCollection *collection in smartAlbums) {
137   - // 有可能是PHCollectionList类的的对象,过滤掉
138   - if (![collection isKindOfClass:[PHAssetCollection class]]) continue;
139   - // 过滤空相册
140   - if (collection.estimatedAssetCount <= 0) continue;
141   - if ([self isCameraRollAlbum:collection]) {
142   - PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
143   - model = [self modelWithResult:fetchResult name:collection.localizedTitle isCameraRoll:YES needFetchAssets:needFetchAssets];
144   - if (completion) completion(model);
145   - break;
146   - }
147   - }
148   - } else {
149   - [self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
150   - if ([group numberOfAssets] < 1) return;
151   - if ([self isCameraRollAlbum:group]) {
152   - NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
153   - model = [self modelWithResult:group name:name isCameraRoll:YES needFetchAssets:needFetchAssets];
154   - if (completion) completion(model);
155   - *stop = YES;
156   - }
157   - } failureBlock:nil];
158   - }
159   -}
160   -
161   -- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray<TZAlbumModel *> *))completion{
162   - NSMutableArray *albumArr = [NSMutableArray array];
163   - if (iOS8Later) {
164   - PHFetchOptions *option = [[PHFetchOptions alloc] init];
165   - if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
166   - if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
167   - PHAssetMediaTypeVideo];
168   - // option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]];
169   - if (!self.sortAscendingByModificationDate) {
170   - option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]];
171   - }
172   - // 我的照片流 1.6.10重新加入..
173   - PHFetchResult *myPhotoStreamAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumMyPhotoStream options:nil];
174   - PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
175   - PHFetchResult *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
176   - PHFetchResult *syncedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumSyncedAlbum options:nil];
177   - PHFetchResult *sharedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumCloudShared options:nil];
178   - NSArray *allAlbums = @[myPhotoStreamAlbum,smartAlbums,topLevelUserCollections,syncedAlbums,sharedAlbums];
179   - for (PHFetchResult *fetchResult in allAlbums) {
180   - for (PHAssetCollection *collection in fetchResult) {
181   - // 有可能是PHCollectionList类的的对象,过滤掉
182   - if (![collection isKindOfClass:[PHAssetCollection class]]) continue;
183   - // 过滤空相册
184   - if (collection.estimatedAssetCount <= 0) continue;
185   - PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
186   - if (fetchResult.count < 1) continue;
187   -
188   - if ([self.pickerDelegate respondsToSelector:@selector(isAlbumCanSelect:result:)]) {
189   - if (![self.pickerDelegate isAlbumCanSelect:collection.localizedTitle result:fetchResult]) {
190   - continue;
191   - }
192   - }
193   -
194   - if (collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumAllHidden) continue;
195   - if (collection.assetCollectionSubtype == 1000000201) continue; //『最近删除』相册
196   - if ([self isCameraRollAlbum:collection]) {
197   - [albumArr insertObject:[self modelWithResult:fetchResult name:collection.localizedTitle isCameraRoll:YES needFetchAssets:needFetchAssets] atIndex:0];
198   - } else {
199   - [albumArr addObject:[self modelWithResult:fetchResult name:collection.localizedTitle isCameraRoll:NO needFetchAssets:needFetchAssets]];
200   - }
201   - }
202   - }
203   - if (completion && albumArr.count > 0) completion(albumArr);
204   - } else {
205   - [self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
206   - if (group == nil) {
207   - if (completion && albumArr.count > 0) completion(albumArr);
208   - }
209   - if ([group numberOfAssets] < 1) return;
210   - NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
211   -
212   - if ([self.pickerDelegate respondsToSelector:@selector(isAlbumCanSelect:result:)]) {
213   - if (![self.pickerDelegate isAlbumCanSelect:name result:group]) {
214   - return;
215   - }
216   - }
217   -
218   - if ([self isCameraRollAlbum:group]) {
219   - [albumArr insertObject:[self modelWithResult:group name:name isCameraRoll:YES needFetchAssets:needFetchAssets] atIndex:0];
220   - } else if ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == ALAssetsGroupPhotoStream) {
221   - if (albumArr.count) {
222   - [albumArr insertObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets] atIndex:1];
223   - } else {
224   - [albumArr addObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets]];
225   - }
226   - } else {
227   - [albumArr addObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets]];
228   - }
229   - } failureBlock:nil];
230   - }
231   -}
232   -
233   -#pragma mark - Get Assets
234   -
235   -/// Get Assets 获得照片数组
236   -- (void)getAssetsFromFetchResult:(id)result completion:(void (^)(NSArray<TZAssetModel *> *))completion {
237   - TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance];
238   - return [self getAssetsFromFetchResult:result allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage completion:completion];
239   -}
240   -
241   -- (void)getAssetsFromFetchResult:(id)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *))completion {
242   - NSMutableArray *photoArr = [NSMutableArray array];
243   - if ([result isKindOfClass:[PHFetchResult class]]) {
244   - PHFetchResult *fetchResult = (PHFetchResult *)result;
245   - [fetchResult enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
246   - TZAssetModel *model = [self assetModelWithAsset:obj allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
247   - if (model) {
248   - [photoArr addObject:model];
249   - }
250   - }];
251   - if (completion) completion(photoArr);
252   - } else if ([result isKindOfClass:[ALAssetsGroup class]]) {
253   - ALAssetsGroup *group = (ALAssetsGroup *)result;
254   - if (allowPickingImage && allowPickingVideo) {
255   - [group setAssetsFilter:[ALAssetsFilter allAssets]];
256   - } else if (allowPickingVideo) {
257   - [group setAssetsFilter:[ALAssetsFilter allVideos]];
258   - } else if (allowPickingImage) {
259   - [group setAssetsFilter:[ALAssetsFilter allPhotos]];
260   - }
261   - ALAssetsGroupEnumerationResultsBlock resultBlock = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
262   - if (result == nil) {
263   - if (completion) completion(photoArr);
264   - }
265   - TZAssetModel *model = [self assetModelWithAsset:result allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
266   - if (model) {
267   - [photoArr addObject:model];
268   - }
269   - };
270   - if (self.sortAscendingByModificationDate) {
271   - [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
272   - if (resultBlock) { resultBlock(result,index,stop); }
273   - }];
274   - } else {
275   - [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
276   - if (resultBlock) {resultBlock(result,index,stop); }
277   - }];
278   - }
279   - }
280   -}
281   -
282   -/// Get asset at index 获得下标为index的单个照片
283   -/// if index beyond bounds, return nil in callback 如果索引越界, 在回调中返回 nil
284   -- (void)getAssetFromFetchResult:(id)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *))completion {
285   - if ([result isKindOfClass:[PHFetchResult class]]) {
286   - PHFetchResult *fetchResult = (PHFetchResult *)result;
287   - PHAsset *asset;
288   - @try {
289   - asset = fetchResult[index];
290   - }
291   - @catch (NSException* e) {
292   - if (completion) completion(nil);
293   - return;
294   - }
295   - TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
296   - if (completion) completion(model);
297   - } else if ([result isKindOfClass:[ALAssetsGroup class]]) {
298   - ALAssetsGroup *group = (ALAssetsGroup *)result;
299   - if (allowPickingImage && allowPickingVideo) {
300   - [group setAssetsFilter:[ALAssetsFilter allAssets]];
301   - } else if (allowPickingVideo) {
302   - [group setAssetsFilter:[ALAssetsFilter allVideos]];
303   - } else if (allowPickingImage) {
304   - [group setAssetsFilter:[ALAssetsFilter allPhotos]];
305   - }
306   - NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
307   - @try {
308   - [group enumerateAssetsAtIndexes:indexSet options:NSEnumerationConcurrent usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
309   - if (!result) return;
310   - TZAssetModel *model = [self assetModelWithAsset:result allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
311   - if (completion) completion(model);
312   - }];
313   - }
314   - @catch (NSException* e) {
315   - if (completion) completion(nil);
316   - }
317   - }
318   -}
319   -
320   -- (TZAssetModel *)assetModelWithAsset:(id)asset allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage {
321   - BOOL canSelect = YES;
322   - if ([self.pickerDelegate respondsToSelector:@selector(isAssetCanSelect:)]) {
323   - canSelect = [self.pickerDelegate isAssetCanSelect:asset];
324   - }
325   - if (!canSelect) return nil;
326   -
327   - TZAssetModel *model;
328   - TZAssetModelMediaType type = [self getAssetType:asset];
329   - if ([asset isKindOfClass:[PHAsset class]]) {
330   - if (!allowPickingVideo && type == TZAssetModelMediaTypeVideo) return nil;
331   - if (!allowPickingImage && type == TZAssetModelMediaTypePhoto) return nil;
332   - if (!allowPickingImage && type == TZAssetModelMediaTypePhotoGif) return nil;
333   -
334   - PHAsset *phAsset = (PHAsset *)asset;
335   - if (self.hideWhenCanNotSelect) {
336   - // 过滤掉尺寸不满足要求的图片
337   - if (![self isPhotoSelectableWithAsset:phAsset]) {
338   - return nil;
339   - }
340   - }
341   - NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",phAsset.duration] : @"";
342   - timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
343   - model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
344   - } else {
345   - if (!allowPickingVideo){
346   - model = [TZAssetModel modelWithAsset:asset type:type];
347   - return model;
348   - }
349   - /// Allow picking video
350   - if (type == TZAssetModelMediaTypeVideo) {
351   - NSTimeInterval duration = [[asset valueForProperty:ALAssetPropertyDuration] doubleValue];
352   - NSString *timeLength = [NSString stringWithFormat:@"%0.0f",duration];
353   - timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
354   - model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
355   - } else {
356   - if (self.hideWhenCanNotSelect) {
357   - // 过滤掉尺寸不满足要求的图片
358   - if (![self isPhotoSelectableWithAsset:asset]) {
359   - return nil;
360   - }
361   - }
362   - model = [TZAssetModel modelWithAsset:asset type:type];
363   - }
364   - }
365   - return model;
366   -}
367   -
368   -- (TZAssetModelMediaType)getAssetType:(id)asset {
369   - TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
370   - if ([asset isKindOfClass:[PHAsset class]]) {
371   - PHAsset *phAsset = (PHAsset *)asset;
372   - if (phAsset.mediaType == PHAssetMediaTypeVideo) type = TZAssetModelMediaTypeVideo;
373   - else if (phAsset.mediaType == PHAssetMediaTypeAudio) type = TZAssetModelMediaTypeAudio;
374   - else if (phAsset.mediaType == PHAssetMediaTypeImage) {
375   - if (@available(iOS 9.1, *)) {
376   - // if (asset.mediaSubtypes == PHAssetMediaSubtypePhotoLive) type = TZAssetModelMediaTypeLivePhoto;
377   - }
378   - // Gif
379   - if ([[phAsset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
380   - type = TZAssetModelMediaTypePhotoGif;
381   - }
382   - }
383   - } else {
384   - if ([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
385   - type = TZAssetModelMediaTypeVideo;
386   - }
387   - }
388   - return type;
389   -}
390   -
391   -- (NSString *)getNewTimeFromDurationSecond:(NSInteger)duration {
392   - NSString *newTime;
393   - if (duration < 10) {
394   - newTime = [NSString stringWithFormat:@"0:0%zd",duration];
395   - } else if (duration < 60) {
396   - newTime = [NSString stringWithFormat:@"0:%zd",duration];
397   - } else {
398   - NSInteger min = duration / 60;
399   - NSInteger sec = duration - (min * 60);
400   - if (sec < 10) {
401   - newTime = [NSString stringWithFormat:@"%zd:0%zd",min,sec];
402   - } else {
403   - newTime = [NSString stringWithFormat:@"%zd:%zd",min,sec];
404   - }
405   - }
406   - return newTime;
407   -}
408   -
409   -/// Get photo bytes 获得一组照片的大小
410   -- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion {
411   - if (!photos || !photos.count) {
412   - if (completion) completion(@"0B");
413   - return;
414   - }
415   - __block NSInteger dataLength = 0;
416   - __block NSInteger assetCount = 0;
417   - for (NSInteger i = 0; i < photos.count; i++) {
418   - TZAssetModel *model = photos[i];
419   - if ([model.asset isKindOfClass:[PHAsset class]]) {
420   - PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
421   - options.resizeMode = PHImageRequestOptionsResizeModeFast;
422   - options.networkAccessAllowed = YES;
423   - if (model.type == TZAssetModelMediaTypePhotoGif) {
424   - options.version = PHImageRequestOptionsVersionOriginal;
425   - }
426   - [[PHImageManager defaultManager] requestImageDataForAsset:model.asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
427   - if (model.type != TZAssetModelMediaTypeVideo) dataLength += imageData.length;
428   - assetCount ++;
429   - if (assetCount >= photos.count) {
430   - NSString *bytes = [self getBytesFromDataLength:dataLength];
431   - if (completion) completion(bytes);
432   - }
433   - }];
434   - } else if ([model.asset isKindOfClass:[ALAsset class]]) {
435   - ALAssetRepresentation *representation = [model.asset defaultRepresentation];
436   - if (model.type != TZAssetModelMediaTypeVideo) dataLength += (NSInteger)representation.size;
437   - if (i >= photos.count - 1) {
438   - NSString *bytes = [self getBytesFromDataLength:dataLength];
439   - if (completion) completion(bytes);
440   - }
441   - }
442   - }
443   -}
444   -
445   -- (NSString *)getBytesFromDataLength:(NSInteger)dataLength {
446   - NSString *bytes;
447   - if (dataLength >= 0.1 * (1024 * 1024)) {
448   - bytes = [NSString stringWithFormat:@"%0.1fM",dataLength/1024/1024.0];
449   - } else if (dataLength >= 1024) {
450   - bytes = [NSString stringWithFormat:@"%0.0fK",dataLength/1024.0];
451   - } else {
452   - bytes = [NSString stringWithFormat:@"%zdB",dataLength];
453   - }
454   - return bytes;
455   -}
456   -
457   -#pragma mark - Get Photo
458   -
459   -/// Get photo 获得照片本身
460   -- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion {
461   - CGFloat fullScreenWidth = TZScreenWidth;
462   - if (fullScreenWidth > _photoPreviewMaxWidth) {
463   - fullScreenWidth = _photoPreviewMaxWidth;
464   - }
465   - return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion progressHandler:nil networkAccessAllowed:YES];
466   -}
467   -
468   -- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
469   - return [self getPhotoWithAsset:asset photoWidth:photoWidth completion:completion progressHandler:nil networkAccessAllowed:YES];
470   -}
471   -
472   -- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed {
473   - CGFloat fullScreenWidth = TZScreenWidth;
474   - if (fullScreenWidth > _photoPreviewMaxWidth) {
475   - fullScreenWidth = _photoPreviewMaxWidth;
476   - }
477   - return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion progressHandler:progressHandler networkAccessAllowed:networkAccessAllowed];
478   -}
479   -
480   -- (int32_t)requestImageDataForAsset:(id)asset completion:(void (^)(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler {
481   - if ([asset isKindOfClass:[PHAsset class]]) {
482   - PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
483   - options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
484   - dispatch_async(dispatch_get_main_queue(), ^{
485   - if (progressHandler) {
486   - progressHandler(progress, error, stop, info);
487   - }
488   - });
489   - };
490   - options.networkAccessAllowed = YES;
491   - options.resizeMode = PHImageRequestOptionsResizeModeFast;
492   - int32_t imageRequestID = [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
493   - if (completion) completion(imageData,dataUTI,orientation,info);
494   - }];
495   - return imageRequestID;
496   - } else if ([asset isKindOfClass:[ALAsset class]]) {
497   - ALAsset *alAsset = (ALAsset *)asset;
498   - dispatch_async(dispatch_get_global_queue(0,0), ^{
499   - ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
500   - CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
501   - UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
502   - dispatch_async(dispatch_get_main_queue(), ^{
503   - if (completion) completion(UIImageJPEGRepresentation(fullScrennImage, 0.83), nil, UIImageOrientationUp, nil);
504   - });
505   - });
506   - }
507   - return 0;
508   -}
509   -
510   -- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed {
511   - if ([asset isKindOfClass:[PHAsset class]]) {
512   - CGSize imageSize;
513   - if (photoWidth < TZScreenWidth && photoWidth < _photoPreviewMaxWidth) {
514   - imageSize = AssetGridThumbnailSize;
515   - } else {
516   - PHAsset *phAsset = (PHAsset *)asset;
517   - CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight;
518   - CGFloat pixelWidth = photoWidth * TZScreenScale * 1.5;
519   - // 超宽图片
520   - if (aspectRatio > 1.8) {
521   - pixelWidth = pixelWidth * aspectRatio;
522   - }
523   - // 超高图片
524   - if (aspectRatio < 0.2) {
525   - pixelWidth = pixelWidth * 0.5;
526   - }
527   - CGFloat pixelHeight = pixelWidth / aspectRatio;
528   - imageSize = CGSizeMake(pixelWidth, pixelHeight);
529   - }
530   -
531   - __block UIImage *image;
532   - // 修复获取图片时出现的瞬间内存过高问题
533   - // 下面两行代码,来自hsjcom,他的github是:https://github.com/hsjcom 表示感谢
534   - PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
535   - option.resizeMode = PHImageRequestOptionsResizeModeFast;
536   - int32_t imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
537   - if (result) {
538   - image = result;
539   - }
540   - BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
541   - if (downloadFinined && result) {
542   - result = [self fixOrientation:result];
543   - if (completion) completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
544   - }
545   - // Download image from iCloud / 从iCloud下载图片
546   - if ([info objectForKey:PHImageResultIsInCloudKey] && !result && networkAccessAllowed) {
547   - PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
548   - options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
549   - dispatch_async(dispatch_get_main_queue(), ^{
550   - if (progressHandler) {
551   - progressHandler(progress, error, stop, info);
552   - }
553   - });
554   - };
555   - options.networkAccessAllowed = YES;
556   - options.resizeMode = PHImageRequestOptionsResizeModeFast;
557   - [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
558   - UIImage *resultImage = [UIImage imageWithData:imageData scale:0.1];
559   - if (![TZImagePickerConfig sharedInstance].notScaleImage) {
560   - resultImage = [self scaleImage:resultImage toSize:imageSize];
561   - }
562   - if (!resultImage) {
563   - resultImage = image;
564   - }
565   - resultImage = [self fixOrientation:resultImage];
566   - if (completion) completion(resultImage,info,NO);
567   - }];
568   - }
569   - }];
570   - return imageRequestID;
571   - } else if ([asset isKindOfClass:[ALAsset class]]) {
572   - ALAsset *alAsset = (ALAsset *)asset;
573   - dispatch_async(dispatch_get_global_queue(0,0), ^{
574   - CGImageRef thumbnailImageRef = alAsset.thumbnail;
575   - UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnailImageRef scale:2.0 orientation:UIImageOrientationUp];
576   - dispatch_async(dispatch_get_main_queue(), ^{
577   - if (completion) completion(thumbnailImage,nil,YES);
578   -
579   - if (photoWidth == TZScreenWidth || photoWidth == self->_photoPreviewMaxWidth) {
580   - dispatch_async(dispatch_get_global_queue(0,0), ^{
581   - ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
582   - CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
583   - UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
584   -
585   - dispatch_async(dispatch_get_main_queue(), ^{
586   - if (completion) completion(fullScrennImage,nil,NO);
587   - });
588   - });
589   - }
590   - });
591   - });
592   - }
593   - return 0;
594   -}
595   -
596   -/// Get postImage / 获取封面图
597   -- (void)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *))completion {
598   - if (iOS8Later) {
599   - id asset = [model.result lastObject];
600   - if (!self.sortAscendingByModificationDate) {
601   - asset = [model.result firstObject];
602   - }
603   - [[TZImageManager manager] getPhotoWithAsset:asset photoWidth:80 completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
604   - if (completion) completion(photo);
605   - }];
606   - } else {
607   - ALAssetsGroup *group = model.result;
608   - UIImage *postImage = [UIImage imageWithCGImage:group.posterImage];
609   - if (completion) completion(postImage);
610   - }
611   -}
612   -
613   -/// Get Original Photo / 获取原图
614   -- (void)getOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion {
615   - [self getOriginalPhotoWithAsset:asset newCompletion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
616   - if (completion) {
617   - completion(photo,info);
618   - }
619   - }];
620   -}
621   -
622   -- (void)getOriginalPhotoWithAsset:(id)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
623   - if ([asset isKindOfClass:[PHAsset class]]) {
624   - PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init];
625   - option.networkAccessAllowed = YES;
626   - option.resizeMode = PHImageRequestOptionsResizeModeFast;
627   - [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage *result, NSDictionary *info) {
628   - BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
629   - if (downloadFinined && result) {
630   - result = [self fixOrientation:result];
631   - BOOL isDegraded = [[info objectForKey:PHImageResultIsDegradedKey] boolValue];
632   - if (completion) completion(result,info,isDegraded);
633   - }
634   - }];
635   - } else if ([asset isKindOfClass:[ALAsset class]]) {
636   - ALAsset *alAsset = (ALAsset *)asset;
637   - ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
638   -
639   - dispatch_async(dispatch_get_global_queue(0,0), ^{
640   - CGImageRef originalImageRef = [assetRep fullResolutionImage];
641   - UIImage *originalImage = [UIImage imageWithCGImage:originalImageRef scale:1.0 orientation:UIImageOrientationUp];
642   -
643   - dispatch_async(dispatch_get_main_queue(), ^{
644   - if (completion) completion(originalImage,nil,NO);
645   - });
646   - });
647   - }
648   -}
649   -
650   -- (void)getOriginalPhotoDataWithAsset:(id)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion {
651   - [self getOriginalPhotoDataWithAsset:asset progressHandler:nil completion:completion];
652   -}
653   -
654   -- (void)getOriginalPhotoDataWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion {
655   - if ([asset isKindOfClass:[PHAsset class]]) {
656   - PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
657   - option.networkAccessAllowed = YES;
658   - if ([[asset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
659   - // if version isn't PHImageRequestOptionsVersionOriginal, the gif may cann't play
660   - option.version = PHImageRequestOptionsVersionOriginal;
661   - }
662   - [option setProgressHandler:progressHandler];
663   - option.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
664   - [[PHImageManager defaultManager] requestImageDataForAsset:asset options:option resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
665   - BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
666   - if (downloadFinined && imageData) {
667   - if (completion) completion(imageData,info,NO);
668   - }
669   - }];
670   - } else if ([asset isKindOfClass:[ALAsset class]]) {
671   - ALAsset *alAsset = (ALAsset *)asset;
672   - ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
673   - Byte *imageBuffer = (Byte *)malloc(assetRep.size);
674   - NSUInteger bufferSize = [assetRep getBytes:imageBuffer fromOffset:0.0 length:assetRep.size error:nil];
675   - NSData *imageData = [NSData dataWithBytesNoCopy:imageBuffer length:bufferSize freeWhenDone:YES];
676   - if (completion) completion(imageData,nil,NO);
677   - }
678   -}
679   -
680   -#pragma mark - Save photo
681   -
682   -- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(NSError *error))completion {
683   - [self savePhotoWithImage:image location:nil completion:completion];
684   -}
685   -
686   -- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(NSError *error))completion {
687   - if (iOS8Later) {
688   - [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
689   - if (@available(iOS 9, *)) {
690   - NSData *data = UIImageJPEGRepresentation(image, 0.9);
691   - PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
692   - options.shouldMoveFile = YES;
693   - PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
694   - [request addResourceWithType:PHAssetResourceTypePhoto data:data options:options];
695   - if (location) {
696   - request.location = location;
697   - }
698   - request.creationDate = [NSDate date];
699   - } else {
700   - PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
701   - if (location) {
702   - request.location = location;
703   - }
704   - request.creationDate = [NSDate date];
705   - }
706   - } completionHandler:^(BOOL success, NSError *error) {
707   - dispatch_async(dispatch_get_main_queue(), ^{
708   - if (success && completion) {
709   - completion(nil);
710   - } else if (error) {
711   - NSLog(@"保存照片出错:%@",error.localizedDescription);
712   - if (completion) {
713   - completion(error);
714   - }
715   - }
716   - });
717   - }];
718   - } else {
719   - [self.assetLibrary writeImageToSavedPhotosAlbum:image.CGImage orientation:[self orientationFromImage:image] completionBlock:^(NSURL *assetURL, NSError *error) {
720   - if (error) {
721   - NSLog(@"保存图片失败:%@",error.localizedDescription);
722   - if (completion) {
723   - completion(error);
724   - }
725   - } else {
726   - // 多给系统0.5秒的时间,让系统去更新相册数据
727   - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
728   - if (completion) {
729   - completion(nil);
730   - }
731   - });
732   - }
733   - }];
734   - }
735   -}
736   -
737   -#pragma mark - Save video
738   -
739   -- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(NSError *error))completion {
740   - [self saveVideoWithUrl:url location:nil completion:completion];
741   -}
742   -
743   -- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(NSError *error))completion {
744   - if (iOS8Later) {
745   - [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
746   - if (@available(iOS 9, *)) {
747   - PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
748   - options.shouldMoveFile = YES;
749   - PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
750   - [request addResourceWithType:PHAssetResourceTypeVideo fileURL:url options:options];
751   - if (location) {
752   - request.location = location;
753   - }
754   - request.creationDate = [NSDate date];
755   - } else {
756   - PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
757   - if (location) {
758   - request.location = location;
759   - }
760   - request.creationDate = [NSDate date];
761   - }
762   - } completionHandler:^(BOOL success, NSError *error) {
763   - dispatch_async(dispatch_get_main_queue(), ^{
764   - if (success && completion) {
765   - completion(nil);
766   - } else if (error) {
767   - NSLog(@"保存视频出错:%@",error.localizedDescription);
768   - if (completion) {
769   - completion(error);
770   - }
771   - }
772   - });
773   - }];
774   - } else {
775   - [self.assetLibrary writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error) {
776   - if (error) {
777   - NSLog(@"保存视频出错:%@",error.localizedDescription);
778   - if (completion) {
779   - completion(error);
780   - }
781   - } else {
782   - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
783   - if (completion) {
784   - completion(nil);
785   - }
786   - });
787   - }
788   - }];
789   - }
790   -}
791   -
792   -#pragma mark - Get Video
793   -
794   -/// Get Video / 获取视频
795   -- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
796   - [self getVideoWithAsset:asset progressHandler:nil completion:completion];
797   -}
798   -
799   -- (void)getVideoWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
800   - if ([asset isKindOfClass:[PHAsset class]]) {
801   - PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];
802   - option.networkAccessAllowed = YES;
803   - option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
804   - dispatch_async(dispatch_get_main_queue(), ^{
805   - if (progressHandler) {
806   - progressHandler(progress, error, stop, info);
807   - }
808   - });
809   - };
810   - [[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:option resultHandler:^(AVPlayerItem *playerItem, NSDictionary *info) {
811   - if (completion) completion(playerItem,info);
812   - }];
813   - } else if ([asset isKindOfClass:[ALAsset class]]) {
814   - ALAsset *alAsset = (ALAsset *)asset;
815   - ALAssetRepresentation *defaultRepresentation = [alAsset defaultRepresentation];
816   - NSString *uti = [defaultRepresentation UTI];
817   - NSURL *videoURL = [[asset valueForProperty:ALAssetPropertyURLs] valueForKey:uti];
818   - AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:videoURL];
819   - if (completion && playerItem) completion(playerItem,nil);
820   - }
821   -}
822   -
823   -#pragma mark - Export video
824   -
825   -/// Export Video / 导出视频
826   -- (void)getVideoOutputPathWithAsset:(id)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
827   - [self getVideoOutputPathWithAsset:asset presetName:AVAssetExportPreset640x480 success:success failure:failure];
828   -}
829   -
830   -- (void)getVideoOutputPathWithAsset:(id)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
831   - if ([asset isKindOfClass:[PHAsset class]]) {
832   - PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
833   - options.version = PHVideoRequestOptionsVersionOriginal;
834   - options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
835   - options.networkAccessAllowed = YES;
836   - [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
837   - // NSLog(@"Info:\n%@",info);
838   - AVURLAsset *videoAsset = (AVURLAsset*)avasset;
839   - // NSLog(@"AVAsset URL: %@",myAsset.URL);
840   - [self startExportVideoWithVideoAsset:videoAsset presetName:presetName success:success failure:failure];
841   - }];
842   - } else if ([asset isKindOfClass:[ALAsset class]]) {
843   - NSURL *videoURL =[asset valueForProperty:ALAssetPropertyAssetURL]; // ALAssetPropertyURLs
844   - AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
845   - [self startExportVideoWithVideoAsset:videoAsset presetName:presetName success:success failure:failure];
846   - }
847   -}
848   -
849   -/// Deprecated, Use -getVideoOutputPathWithAsset:failure:success:
850   -- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion {
851   - [self getVideoOutputPathWithAsset:asset success:completion failure:nil];
852   -}
853   -
854   -- (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
855   - // Find compatible presets by video asset.
856   - NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
857   -
858   - // Begin to compress video
859   - // Now we just compress to low resolution if it supports
860   - // If you need to upload to the server, but server does't support to upload by streaming,
861   - // You can compress the resolution to lower. Or you can support more higher resolution.
862   - if ([presets containsObject:presetName]) {
863   - AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:presetName];
864   -
865   - NSDateFormatter *formater = [[NSDateFormatter alloc] init];
866   - [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
867   -#pragma mark - ADD: 原有逻辑-根据会话id取得path(LXG)
868   - NSString *outputPath = @"";
869   - if (self.outputPath.length <= 0) {
870   - outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
871   - }else {
872   - NSString *filaName = [NSString stringWithFormat:@"output-%@_fileType=videoType.mp4",[formater stringFromDate:[NSDate date]]];
873   - outputPath = [self.outputPath stringByAppendingString:filaName];
874   - }
875   -
876   - NSLog(@"video outputPath = %@",outputPath);
877   -
878   - session.outputURL = [NSURL fileURLWithPath:outputPath];
879   -
880   - // Optimize for network use.
881   - session.shouldOptimizeForNetworkUse = true;
882   -
883   - NSArray *supportedTypeArray = session.supportedFileTypes;
884   - if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
885   - session.outputFileType = AVFileTypeMPEG4;
886   - } else if (supportedTypeArray.count == 0) {
887   - if (failure) {
888   - failure(@"该视频类型暂不支持导出", nil);
889   - }
890   - NSLog(@"No supported file types 视频类型暂不支持导出");
891   - return;
892   - } else {
893   - session.outputFileType = [supportedTypeArray objectAtIndex:0];
894   - }
895   -
896   - if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"]]) {
897   - [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"] withIntermediateDirectories:YES attributes:nil error:nil];
898   - }
899   -
900   - if ([TZImagePickerConfig sharedInstance].needFixComposition) {
901   - AVMutableVideoComposition *videoComposition = [self fixedCompositionWithAsset:videoAsset];
902   - if (videoComposition.renderSize.width) {
903   - // 修正视频转向
904   - session.videoComposition = videoComposition;
905   - }
906   - }
907   -
908   - // Begin to export video to the output path asynchronously.
909   -#pragma mark - ADD: 原有逻辑-会话id置空(LXG)
910   - [session exportAsynchronouslyWithCompletionHandler:^(void) {
911   - dispatch_async(dispatch_get_main_queue(), ^{
912   -
913   - switch (session.status) {
914   - case AVAssetExportSessionStatusUnknown: {
915   - NSLog(@"AVAssetExportSessionStatusUnknown");
916   - } break;
917   - case AVAssetExportSessionStatusWaiting: {
918   - NSLog(@"AVAssetExportSessionStatusWaiting");
919   - } break;
920   - case AVAssetExportSessionStatusExporting: {
921   - NSLog(@"AVAssetExportSessionStatusExporting");
922   - } break;
923   - case AVAssetExportSessionStatusCompleted: {
924   - NSLog(@"AVAssetExportSessionStatusCompleted");
925   - if (success) {
926   - success(outputPath);
927   - }
928   - } break;
929   - case AVAssetExportSessionStatusFailed: {
930   - NSLog(@"AVAssetExportSessionStatusFailed");
931   - if (failure) {
932   - failure(@"视频导出失败", session.error);
933   - }
934   - } break;
935   - case AVAssetExportSessionStatusCancelled: {
936   - NSLog(@"AVAssetExportSessionStatusCancelled");
937   - if (failure) {
938   - failure(@"导出任务已被取消", nil);
939   - }
940   - } break;
941   - default:
942   - NSLog(@"未知错误");
943   - break;
944   - }
945   - });
946   - }];
947   - } else {
948   - if (failure) {
949   - NSString *errorMessage = [NSString stringWithFormat:@"当前设备不支持该预设:%@", presetName];
950   - failure(errorMessage, nil);
951   - }
952   - }
953   -}
954   -
955   -/// Judge is a assets array contain the asset 判断一个assets数组是否包含这个asset
956   -- (BOOL)isAssetsArray:(NSArray *)assets containAsset:(id)asset {
957   - if (iOS8Later) {
958   - return [assets containsObject:asset];
959   - } else {
960   - NSMutableArray *selectedAssetUrls = [NSMutableArray array];
961   - for (ALAsset *asset_item in assets) {
962   - [selectedAssetUrls addObject:[asset_item valueForProperty:ALAssetPropertyURLs]];
963   - }
964   - return [selectedAssetUrls containsObject:[asset valueForProperty:ALAssetPropertyURLs]];
965   - }
966   -}
967   -
968   -- (BOOL)isCameraRollAlbum:(id)metadata {
969   - if ([metadata isKindOfClass:[PHAssetCollection class]]) {
970   - NSString *versionStr = [[UIDevice currentDevice].systemVersion stringByReplacingOccurrencesOfString:@"." withString:@""];
971   - if (versionStr.length <= 1) {
972   - versionStr = [versionStr stringByAppendingString:@"00"];
973   - } else if (versionStr.length <= 2) {
974   - versionStr = [versionStr stringByAppendingString:@"0"];
975   - }
976   - CGFloat version = versionStr.floatValue;
977   - // 目前已知8.0.0 ~ 8.0.2系统,拍照后的图片会保存在最近添加中
978   - if (version >= 800 && version <= 802) {
979   - return ((PHAssetCollection *)metadata).assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumRecentlyAdded;
980   - } else {
981   - return ((PHAssetCollection *)metadata).assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumUserLibrary;
982   - }
983   - }
984   - if ([metadata isKindOfClass:[ALAssetsGroup class]]) {
985   - ALAssetsGroup *group = metadata;
986   - return ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == ALAssetsGroupSavedPhotos);
987   - }
988   -
989   - return NO;
990   -}
991   -
992   -- (NSString *)getAssetIdentifier:(id)asset {
993   - if (iOS8Later) {
994   - PHAsset *phAsset = (PHAsset *)asset;
995   - return phAsset.localIdentifier;
996   - } else {
997   - ALAsset *alAsset = (ALAsset *)asset;
998   - NSURL *assetUrl = [alAsset valueForProperty:ALAssetPropertyAssetURL];
999   - return assetUrl.absoluteString;
1000   - }
1001   -}
1002   -
1003   -/// 检查照片大小是否满足最小要求
1004   -- (BOOL)isPhotoSelectableWithAsset:(id)asset {
1005   - CGSize photoSize = [self photoSizeWithAsset:asset];
1006   - if (self.minPhotoWidthSelectable > photoSize.width || self.minPhotoHeightSelectable > photoSize.height) {
1007   - return NO;
1008   - }
1009   - return YES;
1010   -}
1011   -
1012   -- (CGSize)photoSizeWithAsset:(id)asset {
1013   - if (iOS8Later) {
1014   - PHAsset *phAsset = (PHAsset *)asset;
1015   - return CGSizeMake(phAsset.pixelWidth, phAsset.pixelHeight);
1016   - } else {
1017   - ALAsset *alAsset = (ALAsset *)asset;
1018   - return alAsset.defaultRepresentation.dimensions;
1019   - }
1020   -}
1021   -
1022   -#pragma mark - Private Method
1023   -
1024   -- (TZAlbumModel *)modelWithResult:(id)result name:(NSString *)name isCameraRoll:(BOOL)isCameraRoll needFetchAssets:(BOOL)needFetchAssets {
1025   - TZAlbumModel *model = [[TZAlbumModel alloc] init];
1026   - [model setResult:result needFetchAssets:needFetchAssets];
1027   - model.name = name;
1028   - model.isCameraRoll = isCameraRoll;
1029   - if ([result isKindOfClass:[PHFetchResult class]]) {
1030   - PHFetchResult *fetchResult = (PHFetchResult *)result;
1031   - model.count = fetchResult.count;
1032   - } else if ([result isKindOfClass:[ALAssetsGroup class]]) {
1033   - ALAssetsGroup *group = (ALAssetsGroup *)result;
1034   - model.count = [group numberOfAssets];
1035   - }
1036   - return model;
1037   -}
1038   -
1039   -/// 缩放图片至新尺寸
1040   -- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size {
1041   - if (image.size.width > size.width) {
1042   - UIGraphicsBeginImageContext(size);
1043   - [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
1044   - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
1045   - UIGraphicsEndImageContext();
1046   - return newImage;
1047   -
1048   - /* 好像不怎么管用:https://mp.weixin.qq.com/s/CiqMlEIp1Ir2EJSDGgMooQ
1049   - CGFloat maxPixelSize = MAX(size.width, size.height);
1050   - CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)UIImageJPEGRepresentation(image, 0.9), nil);
1051   - NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue,
1052   - (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize]
1053   - };
1054   - CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
1055   - UIImage *newImage = [UIImage imageWithCGImage:imageRef scale:2 orientation:image.imageOrientation];
1056   - CGImageRelease(imageRef);
1057   - CFRelease(sourceRef);
1058   - return newImage;
1059   - */
1060   - } else {
1061   - return image;
1062   - }
1063   -}
1064   -
1065   -/// 判断asset是否是视频
1066   -- (BOOL)isVideo:(id)asset {
1067   - if (iOS8Later) {
1068   - PHAsset *phAsset = asset;
1069   - return phAsset.mediaType == PHAssetMediaTypeVideo;
1070   - } else {
1071   - ALAsset *alAsset = asset;
1072   - NSString *alAssetType = [[alAsset valueForProperty:ALAssetPropertyType] stringValue];
1073   - return [alAssetType isEqualToString:ALAssetTypeVideo];
1074   - }
1075   -}
1076   -
1077   -- (ALAssetOrientation)orientationFromImage:(UIImage *)image {
1078   - NSInteger orientation = image.imageOrientation;
1079   - return orientation;
1080   -}
1081   -
1082   -/// 获取优化后的视频转向信息
1083   -- (AVMutableVideoComposition *)fixedCompositionWithAsset:(AVAsset *)videoAsset {
1084   - AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
1085   - // 视频转向
1086   - int degrees = [self degressFromVideoFileWithAsset:videoAsset];
1087   - if (degrees != 0) {
1088   - CGAffineTransform translateToCenter;
1089   - CGAffineTransform mixedTransform;
1090   - videoComposition.frameDuration = CMTimeMake(1, 30);
1091   -
1092   - NSArray *tracks = [videoAsset tracksWithMediaType:AVMediaTypeVideo];
1093   - AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
1094   -
1095   - AVMutableVideoCompositionInstruction *roateInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
1096   - roateInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]);
1097   - AVMutableVideoCompositionLayerInstruction *roateLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
1098   -
1099   - if (degrees == 90) {
1100   - // 顺时针旋转90°
1101   - translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.height, 0.0);
1102   - mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2);
1103   - videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
1104   - [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
1105   - } else if(degrees == 180){
1106   - // 顺时针旋转180°
1107   - translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.width, videoTrack.naturalSize.height);
1108   - mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI);
1109   - videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.width,videoTrack.naturalSize.height);
1110   - [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
1111   - } else if(degrees == 270){
1112   - // 顺时针旋转270°
1113   - translateToCenter = CGAffineTransformMakeTranslation(0.0, videoTrack.naturalSize.width);
1114   - mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0);
1115   - videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
1116   - [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
1117   - }
1118   -
1119   - roateInstruction.layerInstructions = @[roateLayerInstruction];
1120   - // 加入视频方向信息
1121   - videoComposition.instructions = @[roateInstruction];
1122   - }
1123   - return videoComposition;
1124   -}
1125   -
1126   -/// 获取视频角度
1127   -- (int)degressFromVideoFileWithAsset:(AVAsset *)asset {
1128   - int degress = 0;
1129   - NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
1130   - if([tracks count] > 0) {
1131   - AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
1132   - CGAffineTransform t = videoTrack.preferredTransform;
1133   - if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){
1134   - // Portrait
1135   - degress = 90;
1136   - } else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){
1137   - // PortraitUpsideDown
1138   - degress = 270;
1139   - } else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){
1140   - // LandscapeRight
1141   - degress = 0;
1142   - } else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){
1143   - // LandscapeLeft
1144   - degress = 180;
1145   - }
1146   - }
1147   - return degress;
1148   -}
1149   -
1150   -/// 修正图片转向
1151   -- (UIImage *)fixOrientation:(UIImage *)aImage {
1152   - if (!self.shouldFixOrientation) return aImage;
1153   -
1154   - // No-op if the orientation is already correct
1155   - if (aImage.imageOrientation == UIImageOrientationUp)
1156   - return aImage;
1157   -
1158   - // We need to calculate the proper transformation to make the image upright.
1159   - // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
1160   - CGAffineTransform transform = CGAffineTransformIdentity;
1161   -
1162   - switch (aImage.imageOrientation) {
1163   - case UIImageOrientationDown:
1164   - case UIImageOrientationDownMirrored:
1165   - transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
1166   - transform = CGAffineTransformRotate(transform, M_PI);
1167   - break;
1168   -
1169   - case UIImageOrientationLeft:
1170   - case UIImageOrientationLeftMirrored:
1171   - transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
1172   - transform = CGAffineTransformRotate(transform, M_PI_2);
1173   - break;
1174   -
1175   - case UIImageOrientationRight:
1176   - case UIImageOrientationRightMirrored:
1177   - transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
1178   - transform = CGAffineTransformRotate(transform, -M_PI_2);
1179   - break;
1180   - default:
1181   - break;
1182   - }
1183   -
1184   - switch (aImage.imageOrientation) {
1185   - case UIImageOrientationUpMirrored:
1186   - case UIImageOrientationDownMirrored:
1187   - transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
1188   - transform = CGAffineTransformScale(transform, -1, 1);
1189   - break;
1190   -
1191   - case UIImageOrientationLeftMirrored:
1192   - case UIImageOrientationRightMirrored:
1193   - transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
1194   - transform = CGAffineTransformScale(transform, -1, 1);
1195   - break;
1196   - default:
1197   - break;
1198   - }
1199   -
1200   - // Now we draw the underlying CGImage into a new context, applying the transform
1201   - // calculated above.
1202   - CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
1203   - CGImageGetBitsPerComponent(aImage.CGImage), 0,
1204   - CGImageGetColorSpace(aImage.CGImage),
1205   - CGImageGetBitmapInfo(aImage.CGImage));
1206   - CGContextConcatCTM(ctx, transform);
1207   - switch (aImage.imageOrientation) {
1208   - case UIImageOrientationLeft:
1209   - case UIImageOrientationLeftMirrored:
1210   - case UIImageOrientationRight:
1211   - case UIImageOrientationRightMirrored:
1212   - // Grr...
1213   - CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
1214   - break;
1215   -
1216   - default:
1217   - CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
1218   - break;
1219   - }
1220   -
1221   - // And now we just create a new UIImage from the drawing context
1222   - CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
1223   - UIImage *img = [UIImage imageWithCGImage:cgimg];
1224   - CGContextRelease(ctx);
1225   - CGImageRelease(cgimg);
1226   - return img;
1227   -}
1228   -
1229   -#pragma clang diagnostic pop
1230   -
1231   -@end
1232   -
1233   -
1234   -//@implementation TZSortDescriptor
1235   -//
1236   -//- (id)reversedSortDescriptor {
1237   -// return [NSNumber numberWithBool:![TZImageManager manager].sortAscendingByModificationDate];
1238   -//}
1239   -//
1240   -//@end
CNLiveImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlay@2x.png deleted 100755 → 0

3.56 KB

CNLiveImagePickerController/TZImagePickerController.bundle/MMVideoPreviewPlayHL@2x.png deleted 100755 → 0

3.56 KB

CNLiveImagePickerController/TZImagePickerController.bundle/Root.plist deleted 100755 → 0
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3   -<plist version="1.0">
4   -<dict>
5   - <key>StringsTable</key>
6   - <string>Root</string>
7   - <key>PreferenceSpecifiers</key>
8   - <array>
9   - <dict>
10   - <key>Type</key>
11   - <string>PSGroupSpecifier</string>
12   - <key>Title</key>
13   - <string>Group</string>
14   - </dict>
15   - <dict>
16   - <key>Type</key>
17   - <string>PSTextFieldSpecifier</string>
18   - <key>Title</key>
19   - <string>Name</string>
20   - <key>Key</key>
21   - <string>name_preference</string>
22   - <key>DefaultValue</key>
23   - <string></string>
24   - <key>IsSecure</key>
25   - <false/>
26   - <key>KeyboardType</key>
27   - <string>Alphabet</string>
28   - <key>AutocapitalizationType</key>
29   - <string>None</string>
30   - <key>AutocorrectionType</key>
31   - <string>No</string>
32   - </dict>
33   - <dict>
34   - <key>Type</key>
35   - <string>PSToggleSwitchSpecifier</string>
36   - <key>Title</key>
37   - <string>Enabled</string>
38   - <key>Key</key>
39   - <string>enabled_preference</string>
40   - <key>DefaultValue</key>
41   - <true/>
42   - </dict>
43   - <dict>
44   - <key>Type</key>
45   - <string>PSSliderSpecifier</string>
46   - <key>Key</key>
47   - <string>slider_preference</string>
48   - <key>DefaultValue</key>
49   - <real>0.5</real>
50   - <key>MinimumValue</key>
51   - <integer>0</integer>
52   - <key>MaximumValue</key>
53   - <integer>1</integer>
54   - <key>MinimumValueImage</key>
55   - <string></string>
56   - <key>MaximumValueImage</key>
57   - <string></string>
58   - </dict>
59   - </array>
60   -</dict>
61   -</plist>
CNLiveImagePickerController/TZImagePickerController.bundle/VideoSendIcon@2x.png deleted 100755 → 0

223 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/en.lproj/Localizable.strings deleted 100755 → 0
1 1 Binary files a/CNLiveImagePickerController/TZImagePickerController.bundle/en.lproj/Localizable.strings and /dev/null differ
... ...
CNLiveImagePickerController/TZImagePickerController.bundle/fb_quxiao@2x.png deleted 100755 → 0

1.16 KB

CNLiveImagePickerController/TZImagePickerController.bundle/navi_back@2x.png deleted 100755 → 0

116 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/ph_select@2x.png deleted 100755 → 0

1.31 KB

CNLiveImagePickerController/TZImagePickerController.bundle/ph_unselect@2x.png deleted 100755 → 0

902 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_cell_normal.png deleted 100644 → 0

641 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_cell_normal@2x.png deleted 100644 → 0

1.35 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_cell_normal@3x.png deleted 100644 → 0

2.57 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_def_photoPickerVc@2x.png deleted 100755 → 0

1.13 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_def_previewVc@2x.png deleted 100755 → 0

1.13 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_number_icon@2x.png deleted 100755 → 0

501 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_back.png deleted 100644 → 0

234 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_back@2x.png deleted 100644 → 0

384 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_back@3x.png deleted 100644 → 0

726 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_def@2x.png deleted 100755 → 0

1.56 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_nor.png deleted 100644 → 0

1.04 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_nor@2x.png deleted 100644 → 0

2.12 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_nor@3x.png deleted 100644 → 0

6.27 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_normal.png deleted 100644 → 0

453 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_normal@2x.png deleted 100644 → 0

902 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_normal@3x.png deleted 100644 → 0

1.77 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_sel@2x.png deleted 100755 → 0

620 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_select.png deleted 100644 → 0

713 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_select@2x.png deleted 100644 → 0

1.31 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_original_select@3x.png deleted 100644 → 0

3.56 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photo_sel_photoPickerVc@2x.png deleted 100755 → 0

1006 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/photo_sel_previewVc@2x.png deleted 100755 → 0

1.16 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photoback.png deleted 100644 → 0

1.01 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photoback@2x.png deleted 100644 → 0

1.16 KB

CNLiveImagePickerController/TZImagePickerController.bundle/photoback@3x.png deleted 100644 → 0

1.23 KB

CNLiveImagePickerController/TZImagePickerController.bundle/preview_number_icon@2x.png deleted 100755 → 0

501 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/preview_original_def@2x.png deleted 100755 → 0

392 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/takePicture80@2x.png deleted 100755 → 0

1.25 KB

CNLiveImagePickerController/TZImagePickerController.bundle/takePicture@2x.png deleted 100755 → 0

2.98 KB

CNLiveImagePickerController/TZImagePickerController.bundle/upload_selection1@2x.png deleted 100755 → 0

1.35 KB

CNLiveImagePickerController/TZImagePickerController.bundle/vi.lproj/Localizable.strings deleted 100755 → 0
1   -"OK" = "Xác nhận";
2   -"Back" = "Quay lại";
3   -"Done" = "Hoàn thành";
4   -"Sorry" = "Xin lỗi";
5   -"Cancel" = "Hủy";
6   -"Setting" = "Cài đặt";
7   -"Photos" = "Hình";
8   -"Videos" = "Clip";
9   -"Preview" = "Xem trước";
10   -"Full image" = "Hình gốc";
11   -"Processing..." = "Đang xử lý...";
12   -"Can not use camera" = "Máy chụp hình không khả dụng";
13   -"Synchronizing photos from iCloud" = "Đang đồng bộ hình ảnh từ ICloud";
14   -"Can not choose both video and photo" = "Trong lúc chọn hình ảnh không cùng lúc chọn video";
15   -"Can not choose both photo and GIF" = "Trong lúc chọn hình ảnh không cùng lúc chọn hình GIF";
16   -"Select the video when in multi state, we will handle the video as a photo" = "Chọn hình ảnh cùng video, video sẽ bị mặc nhận thành hình ảnh và gửi đi.";
17   -"Can not jump to the privacy settings page, please go to the settings page by self, thank you" = "Không thể chuyển tự động qua trang cài đặt riêng tư, bạn hãy thoát ra cà điều chỉnh lại, cám ơn bạn.";
18   -
19   -"Select a maximum of %zd photos" = "Bạn chỉ được chọn nhiều nhất %zd tấm hình";
20   -"Select a minimum of %zd photos" = "Chọn ít nhất %zd tấm hình";
21   -"Allow %@ to access your album in \"Settings -> Privacy -> Photos\"" = "Vui lòng tại mục iPhone \" Cài đặt – quyền riêng tư - Ảnh\" mở quyền cho phép %@ truy cập ảnh.";
22   -"Please allow %@ to access your camera in \"Settings -> Privacy -> Camera\"" = "Vui lòng tại mục iPhone \" Cài đặt – quyền riêng tư - Ảnh\" mở quyền cho phép %@ truy cập máy ảnh";
CNLiveImagePickerController/TZImagePickerController.bundle/video_edit_left@2x.png deleted 100644 → 0

203 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/video_edit_left@3x.png deleted 100644 → 0

514 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/video_edit_right@2x.png deleted 100644 → 0

208 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/video_edit_right@3x.png deleted 100644 → 0

502 Bytes

CNLiveImagePickerController/TZImagePickerController.bundle/zh-Hans.lproj/Localizable.strings deleted 100755 → 0
1 1 Binary files a/CNLiveImagePickerController/TZImagePickerController.bundle/zh-Hans.lproj/Localizable.strings and /dev/null differ
... ...
CNLiveImagePickerController/TZImagePickerController.bundle/zh-Hant.lproj/Localizable.strings deleted 100755 → 0
1 1 Binary files a/CNLiveImagePickerController/TZImagePickerController.bundle/zh-Hant.lproj/Localizable.strings and /dev/null differ
... ...
CNLiveImagePickerController/TZImagePickerController.h deleted 100755 → 0
1   -//
2   -// TZImagePickerController.h
3   -// TZImagePickerController
4   -//
5   -// Created by 谭真 on 15/12/24.
6   -// Copyright © 2015年 谭真. All rights reserved.
7   -// version 2.2.6 - 2018.08.21
8   -// 更多信息,请前往项目的github地址:https://github.com/banchichen/TZImagePickerController
9   -
10   -/*
11   - 经过测试,比起xib的方式,把TZAssetCell改用纯代码的方式来写,滑动帧数明显提高了(约提高10帧左右)
12   -
13   - 最初发现这个问题并修复的是@小鱼周凌宇同学,她的博客地址: http://zhoulingyu.com/
14   - 表示感谢~
15   -
16   - 原来xib确实会导致性能问题啊...大家也要注意了...
17   - */
18   -
19   -#import <UIKit/UIKit.h>
20   -#import "TZAssetModel.h"
21   -#import "NSBundle+TZImagePicker.h"
22   -#import "TZImageManager.h"
23   -#import "TZVideoPlayerController.h"
24   -#import "TZGifPhotoPreviewController.h"
25   -#import "TZLocationManager.h"
26   -#import "TZPhotoPreviewController.h"
27   -
28   -#define iOS7Later ([UIDevice currentDevice].systemVersion.floatValue >= 7.0f)
29   -#define iOS8Later ([UIDevice currentDevice].systemVersion.floatValue >= 8.0f)
30   -///
31   -#define iOS9Later ([UIDevice currentDevice].systemVersion.floatValue >= 9.0f)
32   -#define iOS9_1Later ([UIDevice currentDevice].systemVersion.floatValue >= 9.1f)
33   -
34   -@class TZAlbumCell, TZAssetCell;
35   -@protocol TZImagePickerControllerDelegate;
36   -@interface TZImagePickerController : UINavigationController
37   -
38   -#pragma mark -
39   -/// Use this init method / 用这个初始化方法
40   -- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount delegate:(id<TZImagePickerControllerDelegate>)delegate;
41   -- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id<TZImagePickerControllerDelegate>)delegate;
42   -- (instancetype)initWithMaxImagesCount:(NSInteger)maxImagesCount columnNumber:(NSInteger)columnNumber delegate:(id<TZImagePickerControllerDelegate>)delegate pushPhotoPickerVc:(BOOL)pushPhotoPickerVc;
43   -/// This init method just for previewing photos / 用这个初始化方法以预览图片
44   -- (instancetype)initWithSelectedAssets:(NSMutableArray *)selectedAssets selectedPhotos:(NSMutableArray *)selectedPhotos index:(NSInteger)index;
45   -/// This init method for crop photo / 用这个初始化方法以裁剪图片
46   -- (instancetype)initCropTypeWithAsset:(id)asset photo:(UIImage *)photo completion:(void (^)(UIImage *cropImage,id asset))completion;
47   -
48   -#pragma mark -
49   -
50   -#pragma mark - ADD:视频编辑(LXG)
51   -///**
52   -// 是否允许编辑视频,选择一张时候才允许编辑,默认NO
53   -// */
54   -//@property (nonatomic, assign) BOOL allowEditVideo;
55   -
56   -/**
57   - 编辑视频时最大裁剪时间,单位:秒,默认10s 且最低10s
58   -
59   - @discussion 当该参数为10s时,所选视频时长必须大于等于10s才允许进行编辑
60   - */
61   -@property (nonatomic, assign) NSInteger maxEditVideoTime;
62   -
63   -/**
64   - 允许选择视频的最大时长,单位:秒, 默认 120s
65   - */
66   -@property (nonatomic, assign) NSInteger maxVideoDuration;
67   -
68   -/// Default is 9 / 默认最大可选9张图片
69   -@property (nonatomic, assign) NSInteger maxImagesCount;
70   -
71   -/// The minimum count photos user must pick, Default is 0
72   -/// 最小照片必选张数,默认是0
73   -@property (nonatomic, assign) NSInteger minImagesCount;
74   -
75   -/// Always enale the done button, not require minimum 1 photo be picked
76   -/// 让完成按钮一直可以点击,无须最少选择一张图片
77   -@property (nonatomic, assign) BOOL alwaysEnableDoneBtn;
78   -
79   -/// Sort photos ascending by modificationDate,Default is YES
80   -/// 对照片排序,按修改时间升序,默认是YES。如果设置为NO,最新的照片会显示在最前面,内部的拍照按钮会排在第一个
81   -@property (nonatomic, assign) BOOL sortAscendingByModificationDate;
82   -
83   -/// The pixel width of output image, Default is 828px / 导出图片的宽度,默认828像素宽
84   -@property (nonatomic, assign) CGFloat photoWidth;
85   -
86   -/// Default is 600px / 默认600像素宽
87   -@property (nonatomic, assign) CGFloat photoPreviewMaxWidth;
88   -
89   -/// Default is 15, While fetching photo, HUD will dismiss automatic if timeout;
90   -/// 超时时间,默认为15秒,当取图片时间超过15秒还没有取成功时,会自动dismiss HUD;
91   -@property (nonatomic, assign) NSInteger timeout;
92   -
93   -/// Default is YES, if set NO, the original photo button will hide. user can't picking original photo.
94   -/// 默认为YES,如果设置为NO,原图按钮将隐藏,用户不能选择发送原图
95   -@property (nonatomic, assign) BOOL allowPickingOriginalPhoto;
96   -
97   -/// Default is YES, if set NO, user can't picking video.
98   -/// 默认为YES,如果设置为NO,用户将不能选择视频
99   -@property (nonatomic, assign) BOOL allowPickingVideo;
100   -/// Default is NO / 默认为NO,为YES时可以多选视频/gif/图片,和照片共享最大可选张数maxImagesCount的限制
101   -@property (nonatomic, assign) BOOL allowPickingMultipleVideo;
102   -
103   -/// Default is NO, if set YES, user can picking gif image.
104   -/// 默认为NO,如果设置为YES,用户可以选择gif图片
105   -@property (nonatomic, assign) BOOL allowPickingGif;
106   -
107   -/// Default is YES, if set NO, user can't picking image.
108   -/// 默认为YES,如果设置为NO,用户将不能选择发送图片
109   -@property (nonatomic, assign) BOOL allowPickingImage;
110   -
111   -/// Default is YES, if set NO, user can't take picture.
112   -/// 默认为YES,如果设置为NO, 用户将不能拍摄照片
113   -@property (nonatomic, assign) BOOL allowTakePicture;
114   -@property (nonatomic, assign) BOOL allowCameraLocation;
115   -
116   -/// Default is YES, if set NO, user can't take video.
117   -/// 默认为YES,如果设置为NO, 用户将不能拍摄视频
118   -@property(nonatomic, assign) BOOL allowTakeVideo;
119   -/// Default value is 10 minutes / 视频最大拍摄时间,默认是10分钟,单位是秒
120   -@property (assign, nonatomic) NSTimeInterval videoMaximumDuration;
121   -/// Customizing UIImagePickerController's other properties, such as videoQuality / 定制UIImagePickerController的其它属性,比如视频拍摄质量videoQuality
122   -@property (nonatomic, copy) void(^uiImagePickerControllerSettingBlock)(UIImagePickerController *imagePickerController);
123   -
124   -/// 首选语言,如果设置了就用该语言,不设则取当前系统语言。
125   -/// 由于目前只支持中文、繁体中文、英文、越南语。故该属性只支持zh-Hans、zh-Hant、en、vi四种值,其余值无效。
126   -@property (copy, nonatomic) NSString *preferredLanguage;
127   -
128   -/// 语言bundle,preferredLanguage变化时languageBundle会变化
129   -/// 可通过手动设置bundle,让选择器支持新的的语言(需要在设置preferredLanguage后设置languageBundle)。欢迎提交PR把语言文件提交上来~
130   -@property (strong, nonatomic) NSBundle *languageBundle;
131   -
132   -/// Default is YES, if set NO, user can't preview photo.
133   -/// 默认为YES,如果设置为NO,预览按钮将隐藏,用户将不能去预览照片
134   -@property (nonatomic, assign) BOOL allowPreview;
135   -
136   -/// Default is YES, if set NO, the picker don't dismiss itself.
137   -/// 默认为YES,如果设置为NO, 选择器将不会自己dismiss
138   -@property(nonatomic, assign) BOOL autoDismiss;
139   -
140   -/// Default is NO, if set YES, in the delegate method the photos and infos will be nil, only assets hava value.
141   -/// 默认为NO,如果设置为YES,代理方法里photos和infos会是nil,只返回assets
142   -@property (assign, nonatomic) BOOL onlyReturnAsset;
143   -
144   -/// Default is NO, if set YES, will show the image's selected index.
145   -/// 默认为NO,如果设置为YES,会显示照片的选中序号
146   -@property (assign, nonatomic) BOOL showSelectedIndex;
147   -
148   -/// Default is NO, if set YES, when selected photos's count up to maxImagesCount, other photo will show float layer what's color is cannotSelectLayerColor.
149   -/// 默认是NO,如果设置为YES,当照片选择张数达到maxImagesCount时,其它照片会显示颜色为cannotSelectLayerColor的浮层
150   -@property (assign, nonatomic) BOOL showPhotoCannotSelectLayer;
151   -/// Default is white color with 0.8 alpha;
152   -@property (strong, nonatomic) UIColor *cannotSelectLayerColor;
153   -
154   -/// Default is No, if set YES, the result photo will not be scaled to photoWidth pixel width. The photoWidth default is 828px
155   -/// 默认是NO,如果设置为YES,内部不会缩放图片到photoWidth像素宽
156   -@property (assign, nonatomic) BOOL notScaleImage;
157   -
158   -/// 默认是NO,如果设置为YES,导出视频时会修正转向(慎重设为YES,可能导致部分安卓下拍的视频导出失败)
159   -@property (assign, nonatomic) BOOL needFixComposition;
160   -
161   -/// The photos user have selected
162   -/// 用户选中过的图片数组
163   -@property (nonatomic, strong) NSMutableArray *selectedAssets;
164   -@property (nonatomic, strong) NSMutableArray<TZAssetModel *> *selectedModels;
165   -@property (nonatomic, strong) NSMutableArray *selectedAssetIds;
166   -- (void)addSelectedModel:(TZAssetModel *)model;
167   -- (void)removeSelectedModel:(TZAssetModel *)model;
168   -
169   -/// Minimum selectable photo width, Default is 0
170   -/// 最小可选中的图片宽度,默认是0,小于这个宽度的图片不可选中
171   -@property (nonatomic, assign) NSInteger minPhotoWidthSelectable;
172   -@property (nonatomic, assign) NSInteger minPhotoHeightSelectable;
173   -/// Hide the photo what can not be selected, Default is NO
174   -/// 隐藏不可以选中的图片,默认是NO,不推荐将其设置为YES
175   -@property (nonatomic, assign) BOOL hideWhenCanNotSelect;
176   -/// Deprecated, Use statusBarStyle (顶部statusBar 是否为系统默认的黑色,默认为NO)
177   -@property (nonatomic, assign) BOOL isStatusBarDefault __attribute__((deprecated("Use -statusBarStyle.")));
178   -/// statusBar的样式,默认为UIStatusBarStyleLightContent
179   -@property (assign, nonatomic) UIStatusBarStyle statusBarStyle;
180   -
181   -#pragma mark -
182   -/// Single selection mode, valid when maxImagesCount = 1
183   -/// 单选模式,maxImagesCount为1时才生效
184   -@property (nonatomic, assign) BOOL showSelectBtn; ///< 在单选模式下,照片列表页中,显示选择按钮,默认为NO
185   -@property (nonatomic, assign) BOOL allowCrop; ///< 允许裁剪,默认为YES,showSelectBtn为NO才生效
186   -@property (nonatomic, assign) CGRect cropRect; ///< 裁剪框的尺寸
187   -@property (nonatomic, assign) CGRect cropRectPortrait; ///< 裁剪框的尺寸(竖屏)
188   -@property (nonatomic, assign) CGRect cropRectLandscape; ///< 裁剪框的尺寸(横屏)
189   -@property (nonatomic, assign) BOOL needCircleCrop; ///< 需要圆形裁剪框
190   -@property (nonatomic, assign) NSInteger circleCropRadius; ///< 圆形裁剪框半径大小
191   -@property (nonatomic, copy) void (^cropViewSettingBlock)(UIView *cropView); ///< 自定义裁剪框的其他属性
192   -@property (nonatomic, copy) void (^navLeftBarButtonSettingBlock)(UIButton *leftButton); ///< 自定义返回按钮样式及其属性
193   -
194   -/// 【自定义各页面/组件的样式】在界面初始化/组件setModel完成后调用,允许外界修改样式等
195   -@property (nonatomic, copy) void (^photoPickerPageUIConfigBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine);
196   -@property (nonatomic, copy) void (^photoPreviewPageUIConfigBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel);
197   -@property (nonatomic, copy) void (^videoPreviewPageUIConfigBlock)(UIButton *playButton, UIView *toolBar, UIButton *doneButton);
198   -@property (nonatomic, copy) void (^gifPreviewPageUIConfigBlock)(UIView *toolBar, UIButton *doneButton);
199   -@property (nonatomic, copy) void (^assetCellDidSetModelBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView);
200   -@property (nonatomic, copy) void (^albumCellDidSetModelBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel);
201   -/// 【自定义各页面/组件的frame】在界面viewDidLayoutSubviews/组件layoutSubviews后调用,允许外界修改frame等
202   -@property (nonatomic, copy) void (^photoPickerPageDidLayoutSubviewsBlock)(UICollectionView *collectionView, UIView *bottomToolBar, UIButton *previewButton, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel, UIView *divideLine);
203   -@property (nonatomic, copy) void (^photoPreviewPageDidLayoutSubviewsBlock)(UICollectionView *collectionView, UIView *naviBar, UIButton *backButton, UIButton *selectButton, UILabel *indexLabel, UIView *toolBar, UIButton *originalPhotoButton, UILabel *originalPhotoLabel, UIButton *doneButton, UIImageView *numberImageView, UILabel *numberLabel);
204   -@property (nonatomic, copy) void (^videoPreviewPageDidLayoutSubviewsBlock)(UIButton *playButton, UIView *toolBar, UIButton *doneButton);
205   -@property (nonatomic, copy) void (^gifPreviewPageDidLayoutSubviewsBlock)(UIView *toolBar, UIButton *doneButton);
206   -@property (nonatomic, copy) void (^assetCellDidLayoutSubviewsBlock)(TZAssetCell *cell, UIImageView *imageView, UIImageView *selectImageView, UILabel *indexLabel, UIView *bottomView, UILabel *timeLength, UIImageView *videoImgView);
207   -@property (nonatomic, copy) void (^albumCellDidLayoutSubviewsBlock)(TZAlbumCell *cell, UIImageView *posterImageView, UILabel *titleLabel);
208   -
209   -#pragma mark -
210   -- (id)showAlertWithTitle:(NSString *)title;
211   -- (void)hideAlertView:(id)alertView;
212   -- (void)showProgressHUD;
213   -- (void)hideProgressHUD;
214   -@property (nonatomic, assign) BOOL isSelectOriginalPhoto;
215   -@property (assign, nonatomic) BOOL needShowStatusBar;
216   -
217   -#pragma mark -
218   -@property (nonatomic, copy) NSString *takePictureImageName __attribute__((deprecated("Use -takePictureImage.")));
219   -@property (nonatomic, copy) NSString *photoSelImageName __attribute__((deprecated("Use -photoSelImage.")));
220   -@property (nonatomic, copy) NSString *photoDefImageName __attribute__((deprecated("Use -photoDefImage.")));
221   -@property (nonatomic, copy) NSString *photoOriginSelImageName __attribute__((deprecated("Use -photoOriginSelImage.")));
222   -@property (nonatomic, copy) NSString *photoOriginDefImageName __attribute__((deprecated("Use -photoOriginDefImage.")));
223   -@property (nonatomic, copy) NSString *photoPreviewOriginDefImageName __attribute__((deprecated("Use -photoPreviewOriginDefImage.")));
224   -@property (nonatomic, copy) NSString *photoNumberIconImageName __attribute__((deprecated("Use -photoNumberIconImage.")));
225   -@property (nonatomic, strong) UIImage *takePictureImage;
226   -@property (nonatomic, strong) UIImage *photoSelImage;
227   -@property (nonatomic, strong) UIImage *photoDefImage;
228   -@property (nonatomic, strong) UIImage *photoOriginSelImage;
229   -@property (nonatomic, strong) UIImage *photoOriginDefImage;
230   -@property (nonatomic, strong) UIImage *photoPreviewOriginDefImage;
231   -@property (nonatomic, strong) UIImage *photoNumberIconImage;
232   -
233   -#pragma mark -
234   -/// Appearance / 外观颜色 + 按钮文字
235   -@property (nonatomic, strong) UIColor *oKButtonTitleColorNormal;
236   -@property (nonatomic, strong) UIColor *oKButtonTitleColorDisabled;
237   -@property (nonatomic, strong) UIColor *naviBgColor;
238   -@property (nonatomic, strong) UIColor *naviTitleColor;
239   -@property (nonatomic, strong) UIFont *naviTitleFont;
240   -@property (nonatomic, strong) UIColor *barItemTextColor;
241   -@property (nonatomic, strong) UIFont *barItemTextFont;
242   -@property (nonatomic, strong) UIColor *editBtnTitleColor;///LXG编辑按钮title颜色
243   -
244   -@property (nonatomic, copy) NSString *doneBtnTitleStr;
245   -@property (nonatomic, copy) NSString *cancelBtnTitleStr;
246   -@property (nonatomic, copy) NSString *previewBtnTitleStr;
247   -@property (nonatomic, copy) NSString *fullImageBtnTitleStr;
248   -@property (nonatomic, copy) NSString *settingBtnTitleStr;
249   -@property (nonatomic, copy) NSString *processHintStr;
250   -@property (nonatomic, copy) NSString *editBtnTitleStr;///LXG编辑按钮
251   -
252   -
253   -
254   -/// Icon theme color, default is green color like wechat, the value is r:31 g:185 b:34. Currently only support image selection icon when showSelectedIndex is YES. If you need it, please set it as soon as possible
255   -/// icon主题色,默认是微信的绿色,值是r:31 g:185 b:34。目前仅支持showSelectedIndex为YES时的图片选中icon。如需要,请尽早设置它。
256   -@property (strong, nonatomic) UIColor *iconThemeColor;
257   -
258   -#pragma mark -
259   -- (void)cancelButtonClick;
260   -
261   -// The picker should dismiss itself; when it dismissed these handle will be called.
262   -// You can also set autoDismiss to NO, then the picker don't dismiss itself.
263   -// If isOriginalPhoto is YES, user picked the original photo.
264   -// You can get original photo with asset, by the method [[TZImageManager manager] getOriginalPhotoWithAsset:completion:].
265   -// The UIImage Object in photos default width is 828px, you can set it by photoWidth property.
266   -// 这个照片选择器会自己dismiss,当选择器dismiss的时候,会执行下面的handle
267   -// 你也可以设置autoDismiss属性为NO,选择器就不会自己dismis了
268   -// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
269   -// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
270   -// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它
271   -@property (nonatomic, copy) void (^didFinishPickingPhotosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto);
272   -@property (nonatomic, copy) void (^didFinishPickingPhotosWithInfosHandle)(NSArray<UIImage *> *photos,NSArray *assets,BOOL isSelectOriginalPhoto,NSArray<NSDictionary *> *infos);
273   -@property (nonatomic, copy) void (^imagePickerControllerDidCancelHandle)(void);
274   -
275   -// If user picking a video, this handle will be called.
276   -// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
277   -// 如果用户选择了一个视频,下面的handle会被执行
278   -// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
279   -@property (nonatomic, copy) void (^didFinishPickingVideoHandle)(UIImage *coverImage,id asset);
280   -
281   -// If user picking a gif image, this callback will be called.
282   -// 如果用户选择了一个gif图片,下面的handle会被执行
283   -@property (nonatomic, copy) void (^didFinishPickingGifImageHandle)(UIImage *animatedImage,id sourceAssets);
284   -
285   -@property (nonatomic, weak) id<TZImagePickerControllerDelegate> pickerDelegate;
286   -
287   -@end
288   -
289   -
290   -@protocol TZImagePickerControllerDelegate <NSObject>
291   -@optional
292   -// The picker should dismiss itself; when it dismissed these handle will be called.
293   -// You can also set autoDismiss to NO, then the picker don't dismiss itself.
294   -// If isOriginalPhoto is YES, user picked the original photo.
295   -// You can get original photo with asset, by the method [[TZImageManager manager] getOriginalPhotoWithAsset:completion:].
296   -// The UIImage Object in photos default width is 828px, you can set it by photoWidth property.
297   -// 这个照片选择器会自己dismiss,当选择器dismiss的时候,会执行下面的handle
298   -// 你也可以设置autoDismiss属性为NO,选择器就不会自己dismis了
299   -// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
300   -// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
301   -// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它
302   -- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto;
303   -- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray<NSDictionary *> *)infos;
304   -//- (void)imagePickerControllerDidCancel:(TZImagePickerController *)picker __attribute__((deprecated("Use -tz_imagePickerControllerDidCancel:.")));
305   -- (void)tz_imagePickerControllerDidCancel:(TZImagePickerController *)picker;
306   -
307   -// If user picking a video, this callback will be called.
308   -// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
309   -// 如果用户选择了一个视频,下面的handle会被执行
310   -// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
311   -- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(id)asset;
312   -
313   -// If user picking a gif image, this callback will be called.
314   -// 如果用户选择了一个gif图片,下面的handle会被执行
315   -- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(id)asset;
316   -
317   -// Decide album show or not't
318   -// 决定相册显示与否 albumName:相册名字 result:相册原始数据
319   -- (BOOL)isAlbumCanSelect:(NSString *)albumName result:(id)result;
320   -
321   -// Decide asset show or not't
322   -// 决定照片显示与否
323   -- (BOOL)isAssetCanSelect:(id)asset;
324   -@end
325   -
326   -
327   -@interface TZAlbumPickerController : UIViewController
328   -@property (nonatomic, assign) NSInteger columnNumber;
329   -@property (assign, nonatomic) BOOL isFirstAppear;
330   -- (void)configTableView;
331   -@end
332   -
333   -
334   -@interface UIImage (MyBundle)
335   -+ (UIImage *)imageNamedFromMyBundle:(NSString *)name;
336   -@end
337   -
338   -
339   -@interface NSString (TzExtension)
340   -- (BOOL)tz_containsString:(NSString *)string;
341   -- (CGSize)tz_calculateSizeWithAttributes:(NSDictionary *)attributes maxSize:(CGSize)maxSize;
342   -@end
343   -
344   -
345   -@interface TZCommonTools : NSObject
346   -+ (BOOL)tz_isIPhoneX;
347   -+ (CGFloat)tz_statusBarHeight;
348   -// 获得Info.plist数据字典
349   -+ (NSDictionary *)tz_getInfoDictionary;
350   -@end
351   -
352   -
353   -@interface TZImagePickerConfig : NSObject
354   -+ (instancetype)sharedInstance;
355   -@property (copy, nonatomic) NSString *preferredLanguage;
356   -@property(nonatomic, assign) BOOL allowPickingImage;
357   -@property (nonatomic, assign) BOOL allowPickingVideo;
358   -@property (strong, nonatomic) NSBundle *languageBundle;
359   -/// 默认是200,如果一个GIF过大,里面图片个数可能超过1000,会导致内存飙升而崩溃
360   -@property (assign, nonatomic) NSInteger gifPreviewMaxImagesCount;
361   -@property (assign, nonatomic) BOOL showSelectedIndex;
362   -@property (assign, nonatomic) BOOL showPhotoCannotSelectLayer;
363   -@property (assign, nonatomic) BOOL notScaleImage;
364   -@property (assign, nonatomic) BOOL needFixComposition;
365   -@end