From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001
From: 单军华
Date: Wed, 11 Jul 2018 10:47:42 +0800
Subject: [PATCH] 首次上传
---
screendisplay/Pods/TZImagePickerController/TZImagePickerController/TZImagePickerController/TZImageManager.m | 1203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,203 insertions(+), 0 deletions(-)
diff --git a/screendisplay/Pods/TZImagePickerController/TZImagePickerController/TZImagePickerController/TZImageManager.m b/screendisplay/Pods/TZImagePickerController/TZImagePickerController/TZImagePickerController/TZImageManager.m
new file mode 100755
index 0000000..ab18648
--- /dev/null
+++ b/screendisplay/Pods/TZImagePickerController/TZImagePickerController/TZImagePickerController/TZImageManager.m
@@ -0,0 +1,1203 @@
+//
+// TZImageManager.m
+// TZImagePickerController
+//
+// Created by ������ on 16/1/4.
+// Copyright �� 2016��� ������. All rights reserved.
+//
+
+#import "TZImageManager.h"
+#import <AssetsLibrary/AssetsLibrary.h>
+#import "TZAssetModel.h"
+#import "TZImagePickerController.h"
+
+@interface TZImageManager ()
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+@property (nonatomic, strong) ALAssetsLibrary *assetLibrary;
+@end
+
+@implementation TZImageManager
+
+CGSize AssetGridThumbnailSize;
+CGFloat TZScreenWidth;
+CGFloat TZScreenScale;
+
+static TZImageManager *manager;
+static dispatch_once_t onceToken;
+
++ (instancetype)manager {
+ dispatch_once(&onceToken, ^{
+ manager = [[self alloc] init];
+ if (iOS8Later) {
+ // manager.cachingImageManager = [[PHCachingImageManager alloc] init];
+ // manager.cachingImageManager.allowsCachingHighQualityImages = YES;
+ }
+
+ [manager configTZScreenWidth];
+ });
+ return manager;
+}
+
++ (void)deallocManager {
+ onceToken = 0;
+ manager = nil;
+}
+
+- (void)setPhotoWidth:(CGFloat)photoWidth {
+ _photoWidth = photoWidth;
+ TZScreenWidth = photoWidth / 2;
+}
+
+- (void)setColumnNumber:(NSInteger)columnNumber {
+ [self configTZScreenWidth];
+
+ _columnNumber = columnNumber;
+ CGFloat margin = 4;
+ CGFloat itemWH = (TZScreenWidth - 2 * margin - 4) / columnNumber - margin;
+ AssetGridThumbnailSize = CGSizeMake(itemWH * TZScreenScale, itemWH * TZScreenScale);
+}
+
+- (void)configTZScreenWidth {
+ TZScreenWidth = [UIScreen mainScreen].bounds.size.width;
+ // ���������������������scale���plus���������������3.0������������������������������������������������2.0
+ TZScreenScale = 2.0;
+ if (TZScreenWidth > 700) {
+ TZScreenScale = 1.5;
+ }
+}
+
+- (ALAssetsLibrary *)assetLibrary {
+ if (_assetLibrary == nil) _assetLibrary = [[ALAssetsLibrary alloc] init];
+ return _assetLibrary;
+}
+
+/// Return YES if Authorized ������YES���������������������
+- (BOOL)authorizationStatusAuthorized {
+ NSInteger status = [self.class authorizationStatus];
+ if (status == 0) {
+ /**
+ * ������������������AuthorizationStatus == AuthorizationStatusNotDetermined���������������������������������������������alertView���������������������������������������������������������������������������������������������������������������������������������alertView
+ */
+ [self requestAuthorizationWithCompletion:nil];
+ }
+
+ return status == 3;
+}
+
++ (NSInteger)authorizationStatus {
+ if (iOS8Later) {
+ return [PHPhotoLibrary authorizationStatus];
+ } else {
+ return [ALAssetsLibrary authorizationStatus];
+ }
+ return NO;
+}
+
+- (void)requestAuthorizationWithCompletion:(void (^)(void))completion {
+ void (^callCompletionBlock)(void) = ^(){
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (completion) {
+ completion();
+ }
+ });
+ };
+
+ if (iOS8Later) {
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
+ callCompletionBlock();
+ }];
+ });
+ } else {
+ [self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
+ callCompletionBlock();
+ } failureBlock:^(NSError *error) {
+ callCompletionBlock();
+ }];
+ }
+}
+
+#pragma mark - Get Album
+
+/// Get Album ������������/������������
+- (void)getCameraRollAlbum:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(TZAlbumModel *model))completion {
+ __block TZAlbumModel *model;
+ if (iOS8Later) {
+ PHFetchOptions *option = [[PHFetchOptions alloc] init];
+ if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
+ if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
+ PHAssetMediaTypeVideo];
+ // option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]];
+ if (!self.sortAscendingByModificationDate) {
+ option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]];
+ }
+ PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
+ for (PHAssetCollection *collection in smartAlbums) {
+ // ������������PHCollectionList���������������������������
+ if (![collection isKindOfClass:[PHAssetCollection class]]) continue;
+ // ���������������
+ if (collection.estimatedAssetCount <= 0) continue;
+ if ([self isCameraRollAlbum:collection]) {
+ PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
+ model = [self modelWithResult:fetchResult name:collection.localizedTitle isCameraRoll:YES needFetchAssets:needFetchAssets];
+ if (completion) completion(model);
+ break;
+ }
+ }
+ } else {
+ [self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
+ if ([group numberOfAssets] < 1) return;
+ if ([self isCameraRollAlbum:group]) {
+ NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
+ model = [self modelWithResult:group name:name isCameraRoll:YES needFetchAssets:needFetchAssets];
+ if (completion) completion(model);
+ *stop = YES;
+ }
+ } failureBlock:nil];
+ }
+}
+
+- (void)getAllAlbums:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage needFetchAssets:(BOOL)needFetchAssets completion:(void (^)(NSArray<TZAlbumModel *> *))completion{
+ NSMutableArray *albumArr = [NSMutableArray array];
+ if (iOS8Later) {
+ PHFetchOptions *option = [[PHFetchOptions alloc] init];
+ if (!allowPickingVideo) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
+ if (!allowPickingImage) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld",
+ PHAssetMediaTypeVideo];
+ // option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"modificationDate" ascending:self.sortAscendingByModificationDate]];
+ if (!self.sortAscendingByModificationDate) {
+ option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:self.sortAscendingByModificationDate]];
+ }
+ // ��������������� 1.6.10������������..
+ PHFetchResult *myPhotoStreamAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumMyPhotoStream options:nil];
+ PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
+ PHFetchResult *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
+ PHFetchResult *syncedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumSyncedAlbum options:nil];
+ PHFetchResult *sharedAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumCloudShared options:nil];
+ NSArray *allAlbums = @[myPhotoStreamAlbum,smartAlbums,topLevelUserCollections,syncedAlbums,sharedAlbums];
+ for (PHFetchResult *fetchResult in allAlbums) {
+ for (PHAssetCollection *collection in fetchResult) {
+ // ������������PHCollectionList���������������������������
+ if (![collection isKindOfClass:[PHAssetCollection class]]) continue;
+ // ���������������
+ if (collection.estimatedAssetCount <= 0) continue;
+ PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
+ if (fetchResult.count < 1) continue;
+
+ if ([self.pickerDelegate respondsToSelector:@selector(isAlbumCanSelect:result:)]) {
+ if (![self.pickerDelegate isAlbumCanSelect:collection.localizedTitle result:fetchResult]) {
+ continue;
+ }
+ }
+
+ if (collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumAllHidden) continue;
+ if (collection.assetCollectionSubtype == 1000000201) continue; //������������������������
+ if ([self isCameraRollAlbum:collection]) {
+ [albumArr insertObject:[self modelWithResult:fetchResult name:collection.localizedTitle isCameraRoll:YES needFetchAssets:needFetchAssets] atIndex:0];
+ } else {
+ [albumArr addObject:[self modelWithResult:fetchResult name:collection.localizedTitle isCameraRoll:NO needFetchAssets:needFetchAssets]];
+ }
+ }
+ }
+ if (completion && albumArr.count > 0) completion(albumArr);
+ } else {
+ [self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
+ if (group == nil) {
+ if (completion && albumArr.count > 0) completion(albumArr);
+ }
+ if ([group numberOfAssets] < 1) return;
+ NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
+
+ if ([self.pickerDelegate respondsToSelector:@selector(isAlbumCanSelect:result:)]) {
+ if (![self.pickerDelegate isAlbumCanSelect:name result:group]) {
+ return;
+ }
+ }
+
+ if ([self isCameraRollAlbum:group]) {
+ [albumArr insertObject:[self modelWithResult:group name:name isCameraRoll:YES needFetchAssets:needFetchAssets] atIndex:0];
+ } else if ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == ALAssetsGroupPhotoStream) {
+ if (albumArr.count) {
+ [albumArr insertObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets] atIndex:1];
+ } else {
+ [albumArr addObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets]];
+ }
+ } else {
+ [albumArr addObject:[self modelWithResult:group name:name isCameraRoll:NO needFetchAssets:needFetchAssets]];
+ }
+ } failureBlock:nil];
+ }
+}
+
+#pragma mark - Get Assets
+
+/// Get Assets ������������������
+- (void)getAssetsFromFetchResult:(id)result completion:(void (^)(NSArray<TZAssetModel *> *))completion {
+ TZImagePickerConfig *config = [TZImagePickerConfig sharedInstance];
+ return [self getAssetsFromFetchResult:result allowPickingVideo:config.allowPickingVideo allowPickingImage:config.allowPickingImage completion:completion];
+}
+
+- (void)getAssetsFromFetchResult:(id)result allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(NSArray<TZAssetModel *> *))completion {
+ NSMutableArray *photoArr = [NSMutableArray array];
+ if ([result isKindOfClass:[PHFetchResult class]]) {
+ PHFetchResult *fetchResult = (PHFetchResult *)result;
+ [fetchResult enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+ TZAssetModel *model = [self assetModelWithAsset:obj allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
+ if (model) {
+ [photoArr addObject:model];
+ }
+ }];
+ if (completion) completion(photoArr);
+ } else if ([result isKindOfClass:[ALAssetsGroup class]]) {
+ ALAssetsGroup *group = (ALAssetsGroup *)result;
+ if (allowPickingImage && allowPickingVideo) {
+ [group setAssetsFilter:[ALAssetsFilter allAssets]];
+ } else if (allowPickingVideo) {
+ [group setAssetsFilter:[ALAssetsFilter allVideos]];
+ } else if (allowPickingImage) {
+ [group setAssetsFilter:[ALAssetsFilter allPhotos]];
+ }
+ ALAssetsGroupEnumerationResultsBlock resultBlock = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
+ if (result == nil) {
+ if (completion) completion(photoArr);
+ }
+ TZAssetModel *model = [self assetModelWithAsset:result allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
+ if (model) {
+ [photoArr addObject:model];
+ }
+ };
+ if (self.sortAscendingByModificationDate) {
+ [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
+ if (resultBlock) { resultBlock(result,index,stop); }
+ }];
+ } else {
+ [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
+ if (resultBlock) { resultBlock(result,index,stop); }
+ }];
+ }
+ }
+}
+
+/// Get asset at index ���������������index���������������
+/// if index beyond bounds, return nil in callback ������������������, ������������������ nil
+- (void)getAssetFromFetchResult:(id)result atIndex:(NSInteger)index allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage completion:(void (^)(TZAssetModel *))completion {
+ if ([result isKindOfClass:[PHFetchResult class]]) {
+ PHFetchResult *fetchResult = (PHFetchResult *)result;
+ PHAsset *asset;
+ @try {
+ asset = fetchResult[index];
+ }
+ @catch (NSException* e) {
+ if (completion) completion(nil);
+ return;
+ }
+ TZAssetModel *model = [self assetModelWithAsset:asset allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
+ if (completion) completion(model);
+ } else if ([result isKindOfClass:[ALAssetsGroup class]]) {
+ ALAssetsGroup *group = (ALAssetsGroup *)result;
+ if (allowPickingImage && allowPickingVideo) {
+ [group setAssetsFilter:[ALAssetsFilter allAssets]];
+ } else if (allowPickingVideo) {
+ [group setAssetsFilter:[ALAssetsFilter allVideos]];
+ } else if (allowPickingImage) {
+ [group setAssetsFilter:[ALAssetsFilter allPhotos]];
+ }
+ NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
+ @try {
+ [group enumerateAssetsAtIndexes:indexSet options:NSEnumerationConcurrent usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
+ if (!result) return;
+ TZAssetModel *model = [self assetModelWithAsset:result allowPickingVideo:allowPickingVideo allowPickingImage:allowPickingImage];
+ if (completion) completion(model);
+ }];
+ }
+ @catch (NSException* e) {
+ if (completion) completion(nil);
+ }
+ }
+}
+
+- (TZAssetModel *)assetModelWithAsset:(id)asset allowPickingVideo:(BOOL)allowPickingVideo allowPickingImage:(BOOL)allowPickingImage {
+ BOOL canSelect = YES;
+ if ([self.pickerDelegate respondsToSelector:@selector(isAssetCanSelect:)]) {
+ canSelect = [self.pickerDelegate isAssetCanSelect:asset];
+ }
+ if (!canSelect) return nil;
+
+ TZAssetModel *model;
+ TZAssetModelMediaType type = [self getAssetType:asset];
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ if (!allowPickingVideo && type == TZAssetModelMediaTypeVideo) return nil;
+ if (!allowPickingImage && type == TZAssetModelMediaTypePhoto) return nil;
+ if (!allowPickingImage && type == TZAssetModelMediaTypePhotoGif) return nil;
+
+ PHAsset *phAsset = (PHAsset *)asset;
+ if (self.hideWhenCanNotSelect) {
+ // ���������������������������������������
+ if (![self isPhotoSelectableWithAsset:phAsset]) {
+ return nil;
+ }
+ }
+ NSString *timeLength = type == TZAssetModelMediaTypeVideo ? [NSString stringWithFormat:@"%0.0f",phAsset.duration] : @"";
+ timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
+ model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
+ } else {
+ if (!allowPickingVideo){
+ model = [TZAssetModel modelWithAsset:asset type:type];
+ return model;
+ }
+ /// Allow picking video
+ if (type == TZAssetModelMediaTypeVideo) {
+ NSTimeInterval duration = [[asset valueForProperty:ALAssetPropertyDuration] doubleValue];
+ NSString *timeLength = [NSString stringWithFormat:@"%0.0f",duration];
+ timeLength = [self getNewTimeFromDurationSecond:timeLength.integerValue];
+ model = [TZAssetModel modelWithAsset:asset type:type timeLength:timeLength];
+ } else {
+ if (self.hideWhenCanNotSelect) {
+ // ���������������������������������������
+ if (![self isPhotoSelectableWithAsset:asset]) {
+ return nil;
+ }
+ }
+ model = [TZAssetModel modelWithAsset:asset type:type];
+ }
+ }
+ return model;
+}
+
+- (TZAssetModelMediaType)getAssetType:(id)asset {
+ TZAssetModelMediaType type = TZAssetModelMediaTypePhoto;
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ PHAsset *phAsset = (PHAsset *)asset;
+ if (phAsset.mediaType == PHAssetMediaTypeVideo) type = TZAssetModelMediaTypeVideo;
+ else if (phAsset.mediaType == PHAssetMediaTypeAudio) type = TZAssetModelMediaTypeAudio;
+ else if (phAsset.mediaType == PHAssetMediaTypeImage) {
+ if (iOS9_1Later) {
+ // if (asset.mediaSubtypes == PHAssetMediaSubtypePhotoLive) type = TZAssetModelMediaTypeLivePhoto;
+ }
+ // Gif
+ if ([[phAsset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
+ type = TZAssetModelMediaTypePhotoGif;
+ }
+ }
+ } else {
+ if ([[asset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo]) {
+ type = TZAssetModelMediaTypeVideo;
+ }
+ }
+ return type;
+}
+
+- (NSString *)getNewTimeFromDurationSecond:(NSInteger)duration {
+ NSString *newTime;
+ if (duration < 10) {
+ newTime = [NSString stringWithFormat:@"0:0%zd",duration];
+ } else if (duration < 60) {
+ newTime = [NSString stringWithFormat:@"0:%zd",duration];
+ } else {
+ NSInteger min = duration / 60;
+ NSInteger sec = duration - (min * 60);
+ if (sec < 10) {
+ newTime = [NSString stringWithFormat:@"%zd:0%zd",min,sec];
+ } else {
+ newTime = [NSString stringWithFormat:@"%zd:%zd",min,sec];
+ }
+ }
+ return newTime;
+}
+
+/// Get photo bytes ���������������������������
+- (void)getPhotosBytesWithArray:(NSArray *)photos completion:(void (^)(NSString *totalBytes))completion {
+ if (!photos || !photos.count) {
+ if (completion) completion(@"0B");
+ return;
+ }
+ __block NSInteger dataLength = 0;
+ __block NSInteger assetCount = 0;
+ for (NSInteger i = 0; i < photos.count; i++) {
+ TZAssetModel *model = photos[i];
+ if ([model.asset isKindOfClass:[PHAsset class]]) {
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
+ options.resizeMode = PHImageRequestOptionsResizeModeFast;
+ options.networkAccessAllowed = YES;
+ [[PHImageManager defaultManager] requestImageDataForAsset:model.asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
+ if (model.type != TZAssetModelMediaTypeVideo) dataLength += imageData.length;
+ assetCount ++;
+ if (assetCount >= photos.count) {
+ NSString *bytes = [self getBytesFromDataLength:dataLength];
+ if (completion) completion(bytes);
+ }
+ }];
+ } else if ([model.asset isKindOfClass:[ALAsset class]]) {
+ ALAssetRepresentation *representation = [model.asset defaultRepresentation];
+ if (model.type != TZAssetModelMediaTypeVideo) dataLength += (NSInteger)representation.size;
+ if (i >= photos.count - 1) {
+ NSString *bytes = [self getBytesFromDataLength:dataLength];
+ if (completion) completion(bytes);
+ }
+ }
+ }
+}
+
+- (NSString *)getBytesFromDataLength:(NSInteger)dataLength {
+ NSString *bytes;
+ if (dataLength >= 0.1 * (1024 * 1024)) {
+ bytes = [NSString stringWithFormat:@"%0.1fM",dataLength/1024/1024.0];
+ } else if (dataLength >= 1024) {
+ bytes = [NSString stringWithFormat:@"%0.0fK",dataLength/1024.0];
+ } else {
+ bytes = [NSString stringWithFormat:@"%zdB",dataLength];
+ }
+ return bytes;
+}
+
+#pragma mark - Get Photo
+
+/// Get photo ������������������
+- (int32_t)getPhotoWithAsset:(id)asset completion:(void (^)(UIImage *, NSDictionary *, BOOL isDegraded))completion {
+ CGFloat fullScreenWidth = TZScreenWidth;
+ if (fullScreenWidth > _photoPreviewMaxWidth) {
+ fullScreenWidth = _photoPreviewMaxWidth;
+ }
+ return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion progressHandler:nil networkAccessAllowed:YES];
+}
+
+- (int32_t)getPhotoWithAsset:(id)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
+ return [self getPhotoWithAsset:asset photoWidth:photoWidth completion:completion progressHandler:nil networkAccessAllowed:YES];
+}
+
+- (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 {
+ CGFloat fullScreenWidth = TZScreenWidth;
+ if (fullScreenWidth > _photoPreviewMaxWidth) {
+ fullScreenWidth = _photoPreviewMaxWidth;
+ }
+ return [self getPhotoWithAsset:asset photoWidth:fullScreenWidth completion:completion progressHandler:progressHandler networkAccessAllowed:networkAccessAllowed];
+}
+
+- (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 {
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
+ options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (progressHandler) {
+ progressHandler(progress, error, stop, info);
+ }
+ });
+ };
+ options.networkAccessAllowed = YES;
+ options.resizeMode = PHImageRequestOptionsResizeModeFast;
+ int32_t imageRequestID = [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
+ if (completion) completion(imageData,dataUTI,orientation,info);
+ }];
+ return imageRequestID;
+ } else if ([asset isKindOfClass:[ALAsset class]]) {
+ ALAsset *alAsset = (ALAsset *)asset;
+ dispatch_async(dispatch_get_global_queue(0,0), ^{
+ ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
+ CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
+ UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (completion) completion(UIImageJPEGRepresentation(fullScrennImage, 0.83), nil, UIImageOrientationUp, nil);
+ });
+ });
+ }
+ return 0;
+}
+
+- (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 {
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ CGSize imageSize;
+ if (photoWidth < TZScreenWidth && photoWidth < _photoPreviewMaxWidth) {
+ imageSize = AssetGridThumbnailSize;
+ } else {
+ PHAsset *phAsset = (PHAsset *)asset;
+ CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight;
+ CGFloat pixelWidth = photoWidth * TZScreenScale * 1.5;
+ // ������������
+ if (aspectRatio > 1.8) {
+ pixelWidth = pixelWidth * aspectRatio;
+ }
+ // ������������
+ if (aspectRatio < 0.2) {
+ pixelWidth = pixelWidth * 0.5;
+ }
+ CGFloat pixelHeight = pixelWidth / aspectRatio;
+ imageSize = CGSizeMake(pixelWidth, pixelHeight);
+ }
+
+ __block UIImage *image;
+ // ������������������������������������������������������
+ // ���������������������������hsjcom���������github������https://github.com/hsjcom ������������
+ PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
+ option.resizeMode = PHImageRequestOptionsResizeModeFast;
+ int32_t imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
+ if (result) {
+ image = result;
+ }
+ BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
+ if (downloadFinined && result) {
+ result = [self fixOrientation:result];
+ if (completion) completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
+ }
+ // Download image from iCloud / ���iCloud������������
+ if ([info objectForKey:PHImageResultIsInCloudKey] && !result && networkAccessAllowed) {
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
+ options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (progressHandler) {
+ progressHandler(progress, error, stop, info);
+ }
+ });
+ };
+ options.networkAccessAllowed = YES;
+ options.resizeMode = PHImageRequestOptionsResizeModeFast;
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
+ UIImage *resultImage = [UIImage imageWithData:imageData scale:0.1];
+ resultImage = [self scaleImage:resultImage toSize:imageSize];
+ if (!resultImage) {
+ resultImage = image;
+ }
+ resultImage = [self fixOrientation:resultImage];
+ if (completion) completion(resultImage,info,NO);
+ }];
+ }
+ }];
+ return imageRequestID;
+ } else if ([asset isKindOfClass:[ALAsset class]]) {
+ ALAsset *alAsset = (ALAsset *)asset;
+ dispatch_async(dispatch_get_global_queue(0,0), ^{
+ CGImageRef thumbnailImageRef = alAsset.thumbnail;
+ UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnailImageRef scale:2.0 orientation:UIImageOrientationUp];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (completion) completion(thumbnailImage,nil,YES);
+
+ if (photoWidth == TZScreenWidth || photoWidth == self->_photoPreviewMaxWidth) {
+ dispatch_async(dispatch_get_global_queue(0,0), ^{
+ ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
+ CGImageRef fullScrennImageRef = [assetRep fullScreenImage];
+ UIImage *fullScrennImage = [UIImage imageWithCGImage:fullScrennImageRef scale:2.0 orientation:UIImageOrientationUp];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (completion) completion(fullScrennImage,nil,NO);
+ });
+ });
+ }
+ });
+ });
+ }
+ return 0;
+}
+
+/// Get postImage / ���������������
+- (void)getPostImageWithAlbumModel:(TZAlbumModel *)model completion:(void (^)(UIImage *))completion {
+ if (iOS8Later) {
+ id asset = [model.result lastObject];
+ if (!self.sortAscendingByModificationDate) {
+ asset = [model.result firstObject];
+ }
+ [[TZImageManager manager] getPhotoWithAsset:asset photoWidth:80 completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
+ if (completion) completion(photo);
+ }];
+ } else {
+ ALAssetsGroup *group = model.result;
+ UIImage *postImage = [UIImage imageWithCGImage:group.posterImage];
+ if (completion) completion(postImage);
+ }
+}
+
+/// Get Original Photo / ������������
+- (void)getOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *photo,NSDictionary *info))completion {
+ [self getOriginalPhotoWithAsset:asset newCompletion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
+ if (completion) {
+ completion(photo,info);
+ }
+ }];
+}
+
+- (void)getOriginalPhotoWithAsset:(id)asset newCompletion:(void (^)(UIImage *photo,NSDictionary *info,BOOL isDegraded))completion {
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ PHImageRequestOptions *option = [[PHImageRequestOptions alloc]init];
+ option.networkAccessAllowed = YES;
+ option.resizeMode = PHImageRequestOptionsResizeModeFast;
+ [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage *result, NSDictionary *info) {
+ BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
+ if (downloadFinined && result) {
+ result = [self fixOrientation:result];
+ BOOL isDegraded = [[info objectForKey:PHImageResultIsDegradedKey] boolValue];
+ if (completion) completion(result,info,isDegraded);
+ }
+ }];
+ } else if ([asset isKindOfClass:[ALAsset class]]) {
+ ALAsset *alAsset = (ALAsset *)asset;
+ ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
+
+ dispatch_async(dispatch_get_global_queue(0,0), ^{
+ CGImageRef originalImageRef = [assetRep fullResolutionImage];
+ UIImage *originalImage = [UIImage imageWithCGImage:originalImageRef scale:1.0 orientation:UIImageOrientationUp];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (completion) completion(originalImage,nil,NO);
+ });
+ });
+ }
+}
+
+- (void)getOriginalPhotoDataWithAsset:(id)asset completion:(void (^)(NSData *data,NSDictionary *info,BOOL isDegraded))completion {
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
+ option.networkAccessAllowed = YES;
+ if ([[asset valueForKey:@"filename"] hasSuffix:@"GIF"]) {
+ // if version isn't PHImageRequestOptionsVersionOriginal, the gif may cann't play
+ option.version = PHImageRequestOptionsVersionOriginal;
+ }
+ option.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:option resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
+ BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
+ if (downloadFinined && imageData) {
+ if (completion) completion(imageData,info,NO);
+ }
+ }];
+ } else if ([asset isKindOfClass:[ALAsset class]]) {
+ ALAsset *alAsset = (ALAsset *)asset;
+ ALAssetRepresentation *assetRep = [alAsset defaultRepresentation];
+ Byte *imageBuffer = (Byte *)malloc(assetRep.size);
+ NSUInteger bufferSize = [assetRep getBytes:imageBuffer fromOffset:0.0 length:assetRep.size error:nil];
+ NSData *imageData = [NSData dataWithBytesNoCopy:imageBuffer length:bufferSize freeWhenDone:YES];
+ if (completion) completion(imageData,nil,NO);
+ }
+}
+
+#pragma mark - Save photo
+
+- (void)savePhotoWithImage:(UIImage *)image completion:(void (^)(NSError *error))completion {
+ [self savePhotoWithImage:image location:nil completion:completion];
+}
+
+- (void)savePhotoWithImage:(UIImage *)image location:(CLLocation *)location completion:(void (^)(NSError *error))completion {
+ if (iOS8Later) {
+ [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
+ if (iOS9Later) {
+ NSData *data = UIImageJPEGRepresentation(image, 0.9);
+ PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
+ options.shouldMoveFile = YES;
+ PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
+ [request addResourceWithType:PHAssetResourceTypePhoto data:data options:options];
+ if (location) {
+ request.location = location;
+ }
+ request.creationDate = [NSDate date];
+ } else {
+ PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
+ if (location) {
+ request.location = location;
+ }
+ request.creationDate = [NSDate date];
+ }
+ } completionHandler:^(BOOL success, NSError *error) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (success && completion) {
+ completion(nil);
+ } else if (error) {
+ NSLog(@"������������������:%@",error.localizedDescription);
+ if (completion) {
+ completion(error);
+ }
+ }
+ });
+ }];
+ } else {
+ [self.assetLibrary writeImageToSavedPhotosAlbum:image.CGImage orientation:[self orientationFromImage:image] completionBlock:^(NSURL *assetURL, NSError *error) {
+ if (error) {
+ NSLog(@"������������������:%@",error.localizedDescription);
+ if (completion) {
+ completion(error);
+ }
+ } else {
+ // ������������0.5���������������������������������������������
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ if (completion) {
+ completion(nil);
+ }
+ });
+ }
+ }];
+ }
+}
+
+#pragma mark - Save video
+
+- (void)saveVideoWithUrl:(NSURL *)url completion:(void (^)(NSError *error))completion {
+ [self saveVideoWithUrl:url location:nil completion:completion];
+}
+
+- (void)saveVideoWithUrl:(NSURL *)url location:(CLLocation *)location completion:(void (^)(NSError *error))completion {
+ if (iOS8Later) {
+ [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
+ if (iOS9Later) {
+ PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
+ options.shouldMoveFile = YES;
+ PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
+ [request addResourceWithType:PHAssetResourceTypeVideo fileURL:url options:options];
+ if (location) {
+ request.location = location;
+ }
+ request.creationDate = [NSDate date];
+ } else {
+ PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];
+ if (location) {
+ request.location = location;
+ }
+ request.creationDate = [NSDate date];
+ }
+ } completionHandler:^(BOOL success, NSError *error) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (success && completion) {
+ completion(nil);
+ } else if (error) {
+ NSLog(@"������������������:%@",error.localizedDescription);
+ if (completion) {
+ completion(error);
+ }
+ }
+ });
+ }];
+ } else {
+ [self.assetLibrary writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError *error) {
+ if (error) {
+ NSLog(@"������������������:%@",error.localizedDescription);
+ if (completion) {
+ completion(error);
+ }
+ } else {
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ if (completion) {
+ completion(nil);
+ }
+ });
+ }
+ }];
+ }
+}
+
+#pragma mark - Get Video
+
+/// Get Video / ������������
+- (void)getVideoWithAsset:(id)asset completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
+ [self getVideoWithAsset:asset progressHandler:nil completion:completion];
+}
+
+- (void)getVideoWithAsset:(id)asset progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler completion:(void (^)(AVPlayerItem *, NSDictionary *))completion {
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ PHVideoRequestOptions *option = [[PHVideoRequestOptions alloc] init];
+ option.networkAccessAllowed = YES;
+ option.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (progressHandler) {
+ progressHandler(progress, error, stop, info);
+ }
+ });
+ };
+ [[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:option resultHandler:^(AVPlayerItem *playerItem, NSDictionary *info) {
+ if (completion) completion(playerItem,info);
+ }];
+ } else if ([asset isKindOfClass:[ALAsset class]]) {
+ ALAsset *alAsset = (ALAsset *)asset;
+ ALAssetRepresentation *defaultRepresentation = [alAsset defaultRepresentation];
+ NSString *uti = [defaultRepresentation UTI];
+ NSURL *videoURL = [[asset valueForProperty:ALAssetPropertyURLs] valueForKey:uti];
+ AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:videoURL];
+ if (completion && playerItem) completion(playerItem,nil);
+ }
+}
+
+#pragma mark - Export video
+
+/// Export Video / ������������
+- (void)getVideoOutputPathWithAsset:(id)asset success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
+ [self getVideoOutputPathWithAsset:asset presetName:AVAssetExportPreset640x480 success:success failure:failure];
+}
+
+- (void)getVideoOutputPathWithAsset:(id)asset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
+ if ([asset isKindOfClass:[PHAsset class]]) {
+ PHVideoRequestOptions* options = [[PHVideoRequestOptions alloc] init];
+ options.version = PHVideoRequestOptionsVersionOriginal;
+ options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
+ options.networkAccessAllowed = YES;
+ [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset* avasset, AVAudioMix* audioMix, NSDictionary* info){
+ // NSLog(@"Info:\n%@",info);
+ AVURLAsset *videoAsset = (AVURLAsset*)avasset;
+ // NSLog(@"AVAsset URL: %@",myAsset.URL);
+ [self startExportVideoWithVideoAsset:videoAsset presetName:presetName success:success failure:failure];
+ }];
+ } else if ([asset isKindOfClass:[ALAsset class]]) {
+ NSURL *videoURL =[asset valueForProperty:ALAssetPropertyAssetURL]; // ALAssetPropertyURLs
+ AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
+ [self startExportVideoWithVideoAsset:videoAsset presetName:presetName success:success failure:failure];
+ }
+}
+
+/// Deprecated, Use -getVideoOutputPathWithAsset:failure:success:
+- (void)getVideoOutputPathWithAsset:(id)asset completion:(void (^)(NSString *outputPath))completion {
+ [self getVideoOutputPathWithAsset:asset success:completion failure:nil];
+}
+
+- (void)startExportVideoWithVideoAsset:(AVURLAsset *)videoAsset presetName:(NSString *)presetName success:(void (^)(NSString *outputPath))success failure:(void (^)(NSString *errorMessage, NSError *error))failure {
+ // Find compatible presets by video asset.
+ NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
+
+ // Begin to compress video
+ // Now we just compress to low resolution if it supports
+ // If you need to upload to the server, but server does't support to upload by streaming,
+ // You can compress the resolution to lower. Or you can support more higher resolution.
+ if ([presets containsObject:presetName]) {
+ AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:presetName];
+
+ NSDateFormatter *formater = [[NSDateFormatter alloc] init];
+ [formater setDateFormat:@"yyyy-MM-dd-HH:mm:ss-SSS"];
+ NSString *outputPath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/output-%@.mp4", [formater stringFromDate:[NSDate date]]];
+ // NSLog(@"video outputPath = %@",outputPath);
+ session.outputURL = [NSURL fileURLWithPath:outputPath];
+
+ // Optimize for network use.
+ session.shouldOptimizeForNetworkUse = true;
+
+ NSArray *supportedTypeArray = session.supportedFileTypes;
+ if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
+ session.outputFileType = AVFileTypeMPEG4;
+ } else if (supportedTypeArray.count == 0) {
+ if (failure) {
+ failure(@"���������������������������������", nil);
+ }
+ NSLog(@"No supported file types ������������������������������");
+ return;
+ } else {
+ session.outputFileType = [supportedTypeArray objectAtIndex:0];
+ }
+
+ if (![[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"]]) {
+ [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingFormat:@"/tmp"] withIntermediateDirectories:YES attributes:nil error:nil];
+ }
+
+ AVMutableVideoComposition *videoComposition = [self fixedCompositionWithAsset:videoAsset];
+ if (videoComposition.renderSize.width) {
+ // ������������������
+ session.videoComposition = videoComposition;
+ }
+
+ // Begin to export video to the output path asynchronously.
+ [session exportAsynchronouslyWithCompletionHandler:^(void) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ switch (session.status) {
+ case AVAssetExportSessionStatusUnknown: {
+ NSLog(@"AVAssetExportSessionStatusUnknown");
+ } break;
+ case AVAssetExportSessionStatusWaiting: {
+ NSLog(@"AVAssetExportSessionStatusWaiting");
+ } break;
+ case AVAssetExportSessionStatusExporting: {
+ NSLog(@"AVAssetExportSessionStatusExporting");
+ } break;
+ case AVAssetExportSessionStatusCompleted: {
+ NSLog(@"AVAssetExportSessionStatusCompleted");
+ if (success) {
+ success(outputPath);
+ }
+ } break;
+ case AVAssetExportSessionStatusFailed: {
+ NSLog(@"AVAssetExportSessionStatusFailed");
+ if (failure) {
+ failure(@"������������������", session.error);
+ }
+ } break;
+ case AVAssetExportSessionStatusCancelled: {
+ NSLog(@"AVAssetExportSessionStatusCancelled");
+ if (failure) {
+ failure(@"������������������������", nil);
+ }
+ } break;
+ default: break;
+ }
+ });
+ }];
+ } else {
+ if (failure) {
+ NSString *errorMessage = [NSString stringWithFormat:@"������������������������������:%@", presetName];
+ failure(errorMessage, nil);
+ }
+ }
+}
+
+/// Judge is a assets array contain the asset ������������assets������������������������asset
+- (BOOL)isAssetsArray:(NSArray *)assets containAsset:(id)asset {
+ if (iOS8Later) {
+ return [assets containsObject:asset];
+ } else {
+ NSMutableArray *selectedAssetUrls = [NSMutableArray array];
+ for (ALAsset *asset_item in assets) {
+ [selectedAssetUrls addObject:[asset_item valueForProperty:ALAssetPropertyURLs]];
+ }
+ return [selectedAssetUrls containsObject:[asset valueForProperty:ALAssetPropertyURLs]];
+ }
+}
+
+- (BOOL)isCameraRollAlbum:(id)metadata {
+ if ([metadata isKindOfClass:[PHAssetCollection class]]) {
+ NSString *versionStr = [[UIDevice currentDevice].systemVersion stringByReplacingOccurrencesOfString:@"." withString:@""];
+ if (versionStr.length <= 1) {
+ versionStr = [versionStr stringByAppendingString:@"00"];
+ } else if (versionStr.length <= 2) {
+ versionStr = [versionStr stringByAppendingString:@"0"];
+ }
+ CGFloat version = versionStr.floatValue;
+ // ������������8.0.0 ~ 8.0.2������������������������������������������������������
+ if (version >= 800 && version <= 802) {
+ return ((PHAssetCollection *)metadata).assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumRecentlyAdded;
+ } else {
+ return ((PHAssetCollection *)metadata).assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumUserLibrary;
+ }
+ }
+ if ([metadata isKindOfClass:[ALAssetsGroup class]]) {
+ ALAssetsGroup *group = metadata;
+ return ([[group valueForProperty:ALAssetsGroupPropertyType] intValue] == ALAssetsGroupSavedPhotos);
+ }
+
+ return NO;
+}
+
+- (NSString *)getAssetIdentifier:(id)asset {
+ if (iOS8Later) {
+ PHAsset *phAsset = (PHAsset *)asset;
+ return phAsset.localIdentifier;
+ } else {
+ ALAsset *alAsset = (ALAsset *)asset;
+ NSURL *assetUrl = [alAsset valueForProperty:ALAssetPropertyAssetURL];
+ return assetUrl.absoluteString;
+ }
+}
+
+/// ������������������������������������������
+- (BOOL)isPhotoSelectableWithAsset:(id)asset {
+ CGSize photoSize = [self photoSizeWithAsset:asset];
+ if (self.minPhotoWidthSelectable > photoSize.width || self.minPhotoHeightSelectable > photoSize.height) {
+ return NO;
+ }
+ return YES;
+}
+
+- (CGSize)photoSizeWithAsset:(id)asset {
+ if (iOS8Later) {
+ PHAsset *phAsset = (PHAsset *)asset;
+ return CGSizeMake(phAsset.pixelWidth, phAsset.pixelHeight);
+ } else {
+ ALAsset *alAsset = (ALAsset *)asset;
+ return alAsset.defaultRepresentation.dimensions;
+ }
+}
+
+#pragma mark - Private Method
+
+- (TZAlbumModel *)modelWithResult:(id)result name:(NSString *)name isCameraRoll:(BOOL)isCameraRoll needFetchAssets:(BOOL)needFetchAssets {
+ TZAlbumModel *model = [[TZAlbumModel alloc] init];
+ [model setResult:result needFetchAssets:needFetchAssets];
+ model.name = name;
+ model.isCameraRoll = isCameraRoll;
+ if ([result isKindOfClass:[PHFetchResult class]]) {
+ PHFetchResult *fetchResult = (PHFetchResult *)result;
+ model.count = fetchResult.count;
+ } else if ([result isKindOfClass:[ALAssetsGroup class]]) {
+ ALAssetsGroup *group = (ALAssetsGroup *)result;
+ model.count = [group numberOfAssets];
+ }
+ return model;
+}
+
+/// ������������������������
+- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)size {
+ if (image.size.width > size.width) {
+ UIGraphicsBeginImageContext(size);
+ [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
+ UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return newImage;
+
+ /* ������������������������https://mp.weixin.qq.com/s/CiqMlEIp1Ir2EJSDGgMooQ
+ CGFloat maxPixelSize = MAX(size.width, size.height);
+ CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)UIImageJPEGRepresentation(image, 0.9), nil);
+ NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue,
+ (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelSize]
+ };
+ CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
+ UIImage *newImage = [UIImage imageWithCGImage:imageRef scale:2 orientation:image.imageOrientation];
+ CGImageRelease(imageRef);
+ CFRelease(sourceRef);
+ return newImage;
+ */
+ } else {
+ return image;
+ }
+}
+
+- (ALAssetOrientation)orientationFromImage:(UIImage *)image {
+ NSInteger orientation = image.imageOrientation;
+ return orientation;
+}
+
+/// ������������������������������������
+- (AVMutableVideoComposition *)fixedCompositionWithAsset:(AVAsset *)videoAsset {
+ AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
+ // ������������
+ int degrees = [self degressFromVideoFileWithAsset:videoAsset];
+ if (degrees != 0) {
+ CGAffineTransform translateToCenter;
+ CGAffineTransform mixedTransform;
+ videoComposition.frameDuration = CMTimeMake(1, 30);
+
+ NSArray *tracks = [videoAsset tracksWithMediaType:AVMediaTypeVideo];
+ AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
+
+ AVMutableVideoCompositionInstruction *roateInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
+ roateInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]);
+ AVMutableVideoCompositionLayerInstruction *roateLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
+
+ if (degrees == 90) {
+ // ���������������90��
+ translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.height, 0.0);
+ mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2);
+ videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
+ [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
+ } else if(degrees == 180){
+ // ���������������180��
+ translateToCenter = CGAffineTransformMakeTranslation(videoTrack.naturalSize.width, videoTrack.naturalSize.height);
+ mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI);
+ videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.width,videoTrack.naturalSize.height);
+ [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
+ } else if(degrees == 270){
+ // ���������������270��
+ translateToCenter = CGAffineTransformMakeTranslation(0.0, videoTrack.naturalSize.width);
+ mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0);
+ videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.height,videoTrack.naturalSize.width);
+ [roateLayerInstruction setTransform:mixedTransform atTime:kCMTimeZero];
+ }
+
+ roateInstruction.layerInstructions = @[roateLayerInstruction];
+ // ������������������������
+ videoComposition.instructions = @[roateInstruction];
+ }
+ return videoComposition;
+}
+
+/// ������������������
+- (int)degressFromVideoFileWithAsset:(AVAsset *)asset {
+ int degress = 0;
+ NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
+ if([tracks count] > 0) {
+ AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
+ CGAffineTransform t = videoTrack.preferredTransform;
+ if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0){
+ // Portrait
+ degress = 90;
+ } else if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0){
+ // PortraitUpsideDown
+ degress = 270;
+ } else if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0){
+ // LandscapeRight
+ degress = 0;
+ } else if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0){
+ // LandscapeLeft
+ degress = 180;
+ }
+ }
+ return degress;
+}
+
+/// ������������������
+- (UIImage *)fixOrientation:(UIImage *)aImage {
+ if (!self.shouldFixOrientation) return aImage;
+
+ // No-op if the orientation is already correct
+ if (aImage.imageOrientation == UIImageOrientationUp)
+ return aImage;
+
+ // We need to calculate the proper transformation to make the image upright.
+ // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
+ CGAffineTransform transform = CGAffineTransformIdentity;
+
+ switch (aImage.imageOrientation) {
+ case UIImageOrientationDown:
+ case UIImageOrientationDownMirrored:
+ transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
+ transform = CGAffineTransformRotate(transform, M_PI);
+ break;
+
+ case UIImageOrientationLeft:
+ case UIImageOrientationLeftMirrored:
+ transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
+ transform = CGAffineTransformRotate(transform, M_PI_2);
+ break;
+
+ case UIImageOrientationRight:
+ case UIImageOrientationRightMirrored:
+ transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
+ transform = CGAffineTransformRotate(transform, -M_PI_2);
+ break;
+ default:
+ break;
+ }
+
+ switch (aImage.imageOrientation) {
+ case UIImageOrientationUpMirrored:
+ case UIImageOrientationDownMirrored:
+ transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
+ transform = CGAffineTransformScale(transform, -1, 1);
+ break;
+
+ case UIImageOrientationLeftMirrored:
+ case UIImageOrientationRightMirrored:
+ transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
+ transform = CGAffineTransformScale(transform, -1, 1);
+ break;
+ default:
+ break;
+ }
+
+ // Now we draw the underlying CGImage into a new context, applying the transform
+ // calculated above.
+ CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
+ CGImageGetBitsPerComponent(aImage.CGImage), 0,
+ CGImageGetColorSpace(aImage.CGImage),
+ CGImageGetBitmapInfo(aImage.CGImage));
+ CGContextConcatCTM(ctx, transform);
+ switch (aImage.imageOrientation) {
+ case UIImageOrientationLeft:
+ case UIImageOrientationLeftMirrored:
+ case UIImageOrientationRight:
+ case UIImageOrientationRightMirrored:
+ // Grr...
+ CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
+ break;
+
+ default:
+ CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
+ break;
+ }
+
+ // And now we just create a new UIImage from the drawing context
+ CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
+ UIImage *img = [UIImage imageWithCGImage:cgimg];
+ CGContextRelease(ctx);
+ CGImageRelease(cgimg);
+ return img;
+}
+
+#pragma clang diagnostic pop
+
+@end
+
+
+//@implementation TZSortDescriptor
+//
+//- (id)reversedSortDescriptor {
+// return [NSNumber numberWithBool:![TZImageManager manager].sortAscendingByModificationDate];
+//}
+//
+//@end
--
Gitblit v1.8.0