From 9da1ca5f8a55c3f546f27c9d414412e500b2ec4f Mon Sep 17 00:00:00 2001 From: Victor Rodriguez Date: Tue, 8 Dec 2020 09:02:23 +0100 Subject: [PATCH 1/6] export videos to tmp path when selected --- src/ios/GMImagePicker/GMFetchItem.h | 1 + src/ios/GMImagePicker/GMFetchItem.m | 3 +- src/ios/GMImagePicker/GMGridViewController.m | 31 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/ios/GMImagePicker/GMFetchItem.h b/src/ios/GMImagePicker/GMFetchItem.h index e8ead2d8..1eadc943 100644 --- a/src/ios/GMImagePicker/GMFetchItem.h +++ b/src/ios/GMImagePicker/GMFetchItem.h @@ -18,6 +18,7 @@ @property (nonatomic, assign) double percent; @property (nonatomic, strong) NSString * image_fullsize; @property (nonatomic, strong) NSString * image_thumb; +@property (nonatomic, strong) NSString * video; @property (nonatomic, assign) bool be_saving_img_thumb; diff --git a/src/ios/GMImagePicker/GMFetchItem.m b/src/ios/GMImagePicker/GMFetchItem.m index 30442be0..14a20118 100644 --- a/src/ios/GMImagePicker/GMFetchItem.m +++ b/src/ios/GMImagePicker/GMFetchItem.m @@ -10,7 +10,7 @@ @implementation GMFetchItem -@synthesize be_progressed, be_finished, percent, image_fullsize, image_thumb, be_saving_img, be_saving_img_thumb; +@synthesize be_progressed, be_finished, percent, image_fullsize, video, image_thumb, be_saving_img, be_saving_img_thumb; - (id)init{ @@ -22,6 +22,7 @@ - (id)init{ image_thumb = nil; image_fullsize = nil; + video = nil; be_saving_img = false; be_saving_img_thumb; diff --git a/src/ios/GMImagePicker/GMGridViewController.m b/src/ios/GMImagePicker/GMGridViewController.m index 6636eb72..39ac52fc 100755 --- a/src/ios/GMImagePicker/GMGridViewController.m +++ b/src/ios/GMImagePicker/GMGridViewController.m @@ -19,6 +19,7 @@ #define CDV_PHOTO_PREFIX @"cdv_photo_" #define CDV_THUMB_PREFIX @"cdv_thumb_" +#define CDV_VIDEO_PREFIX @"cdv_video_" //Helper methods @@ -556,6 +557,10 @@ - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPa //GMFetchItem * fetch_item = [dic_asset_fetches objectForKey:[ NSNumber numberWithLong:indexPath.item ]]; GMFetchItem * fetch_item = [dic_asset_fetches objectForKey:asset]; + if (asset.mediaType==PHAssetMediaTypeVideo){ + [self exportVideoAsset:asset andIndex:indexPath.item andFetchAsset:fetch_item]; + } + [self.picker selectAsset:asset]; [self.picker selectFetchItem:fetch_item]; @@ -766,5 +771,31 @@ - (NSArray *)assetsAtIndexPaths:(NSArray *)indexPaths return assets; } +#pragma mark - VideAssets +-(void)exportVideoAsset:(PHAsset *)asset andIndex:(int)index andFetchAsset:(GMFetchItem *)fetchItem{ + // if video + if (asset.mediaType==2){ + + UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Preparing video" + message:@"Please wait..." + preferredStyle:UIAlertControllerStyleAlert]; + [self presentViewController:alert animated:YES completion:nil]; + + [self.imageManager requestExportSessionForVideo:asset options:nil exportPreset:@"AVAssetExportPresetPassthrough" resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) { + NSString *filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_VIDEO_PREFIX, index, @"mov"]; + exportSession.outputURL = [NSURL fileURLWithPath:filePath]; + exportSession.outputFileType = AVFileTypeMPEG4; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [exportSession exportAsynchronouslyWithCompletionHandler:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + fetchItem.video = filePath; + [alert dismissViewControllerAnimated:YES completion:^{}]; + }); + }]; + }); + }]; + } +} + @end From 7c5e9f43d3c602c62a00b1029eb7e69871f27b87 Mon Sep 17 00:00:00 2001 From: Victor Rodriguez Date: Tue, 8 Dec 2020 09:04:03 +0100 Subject: [PATCH 2/6] remove extra if test --- src/ios/GMImagePicker/GMGridViewController.m | 38 +++++++++----------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/ios/GMImagePicker/GMGridViewController.m b/src/ios/GMImagePicker/GMGridViewController.m index 39ac52fc..0bdde9c0 100755 --- a/src/ios/GMImagePicker/GMGridViewController.m +++ b/src/ios/GMImagePicker/GMGridViewController.m @@ -771,30 +771,26 @@ - (NSArray *)assetsAtIndexPaths:(NSArray *)indexPaths return assets; } -#pragma mark - VideAssets +#pragma mark - VideoAssets -(void)exportVideoAsset:(PHAsset *)asset andIndex:(int)index andFetchAsset:(GMFetchItem *)fetchItem{ - // if video - if (asset.mediaType==2){ - - UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Preparing video" - message:@"Please wait..." - preferredStyle:UIAlertControllerStyleAlert]; - [self presentViewController:alert animated:YES completion:nil]; - - [self.imageManager requestExportSessionForVideo:asset options:nil exportPreset:@"AVAssetExportPresetPassthrough" resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) { - NSString *filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_VIDEO_PREFIX, index, @"mov"]; - exportSession.outputURL = [NSURL fileURLWithPath:filePath]; - exportSession.outputFileType = AVFileTypeMPEG4; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [exportSession exportAsynchronouslyWithCompletionHandler:^{ - dispatch_async(dispatch_get_main_queue(), ^{ - fetchItem.video = filePath; - [alert dismissViewControllerAnimated:YES completion:^{}]; - }); - }]; + UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Preparing video" + message:@"Please wait..." + preferredStyle:UIAlertControllerStyleAlert]; + [self presentViewController:alert animated:YES completion:nil]; + + [self.imageManager requestExportSessionForVideo:asset options:nil exportPreset:@"AVAssetExportPresetPassthrough" resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) { + NSString *filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_VIDEO_PREFIX, index, @"mov"]; + exportSession.outputURL = [NSURL fileURLWithPath:filePath]; + exportSession.outputFileType = AVFileTypeMPEG4; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [exportSession exportAsynchronouslyWithCompletionHandler:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + fetchItem.video = filePath; + [alert dismissViewControllerAnimated:YES completion:^{}]; }); }]; - } + }); + }]; } From 3f6c33b24a7a6489fa15f15e16d1da40c1502e99 Mon Sep 17 00:00:00 2001 From: Victor Rodriguez Date: Tue, 8 Dec 2020 09:27:55 +0100 Subject: [PATCH 3/6] return video path for video media --- src/ios/SOSPicker.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ios/SOSPicker.m b/src/ios/SOSPicker.m index 0e2e00e7..afbb75b5 100644 --- a/src/ios/SOSPicker.m +++ b/src/ios/SOSPicker.m @@ -195,6 +195,11 @@ - (void)assetsPickerController:(GMImagePickerController *)picker didFinishPickin continue; } + if (item.video!=nil){ + [result_all addObject:item.video]; + continue; + } + do { filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, @"jpg"]; } while ([fileMgr fileExistsAtPath:filePath]); From b33648bf58f4d919d30de55c8e09568205260ee0 Mon Sep 17 00:00:00 2001 From: Victor Rodriguez Date: Tue, 8 Dec 2020 18:51:46 +0100 Subject: [PATCH 4/6] JSON Metadata --- src/ios/GMImagePicker/GMFetchItem.h | 2 +- src/ios/GMImagePicker/GMFetchItem.m | 4 +- src/ios/GMImagePicker/GMGridViewController.h | 1 + src/ios/GMImagePicker/GMGridViewController.m | 35 ++++++++++-- src/ios/PHAsset+Meta.h | 51 ++++++++++++++++++ src/ios/PHAsset+Meta.m | 57 ++++++++++++++++++++ src/ios/SOSPicker.m | 6 ++- 7 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 src/ios/PHAsset+Meta.h create mode 100644 src/ios/PHAsset+Meta.m diff --git a/src/ios/GMImagePicker/GMFetchItem.h b/src/ios/GMImagePicker/GMFetchItem.h index 1eadc943..c5904279 100644 --- a/src/ios/GMImagePicker/GMFetchItem.h +++ b/src/ios/GMImagePicker/GMFetchItem.h @@ -19,7 +19,7 @@ @property (nonatomic, strong) NSString * image_fullsize; @property (nonatomic, strong) NSString * image_thumb; @property (nonatomic, strong) NSString * video; - +@property (nonatomic, strong) NSString * metadataJSON; @property (nonatomic, assign) bool be_saving_img_thumb; @property (nonatomic, assign) bool be_saving_img; diff --git a/src/ios/GMImagePicker/GMFetchItem.m b/src/ios/GMImagePicker/GMFetchItem.m index 14a20118..3376a268 100644 --- a/src/ios/GMImagePicker/GMFetchItem.m +++ b/src/ios/GMImagePicker/GMFetchItem.m @@ -10,7 +10,7 @@ @implementation GMFetchItem -@synthesize be_progressed, be_finished, percent, image_fullsize, video, image_thumb, be_saving_img, be_saving_img_thumb; +@synthesize be_progressed, be_finished, percent, image_fullsize, video, image_thumb, be_saving_img, be_saving_img_thumb, metadataJSON; - (id)init{ @@ -27,6 +27,8 @@ - (id)init{ be_saving_img = false; be_saving_img_thumb; + metadataJSON = nil; + return self; } diff --git a/src/ios/GMImagePicker/GMGridViewController.h b/src/ios/GMImagePicker/GMGridViewController.h index e9930a15..180e62f3 100755 --- a/src/ios/GMImagePicker/GMGridViewController.h +++ b/src/ios/GMImagePicker/GMGridViewController.h @@ -9,6 +9,7 @@ #import "GMImagePickerController.h" #import "UIImage+fixOrientation.h" +#import "PHAsset+Meta.h" #import diff --git a/src/ios/GMImagePicker/GMGridViewController.m b/src/ios/GMImagePicker/GMGridViewController.m index 0bdde9c0..09d71531 100755 --- a/src/ios/GMImagePicker/GMGridViewController.m +++ b/src/ios/GMImagePicker/GMGridViewController.m @@ -395,7 +395,6 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell if ( fetch_item.be_saving_img_thumb==false && fetch_item.image_thumb == nil && result!= nil ) { fetch_item.be_saving_img_thumb = true; - NSString * filePath; do { filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_THUMB_PREFIX, doc_thumbCount++, @"jpg"]; @@ -512,12 +511,42 @@ - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtInde UIImage *imageToDisplay = result.fixOrientation; // UIImage+fixOrientation extension NSLog(@"corrected orientation: %ld",(UIImageOrientation)imageToDisplay.imageOrientation); - + NSData * imageData = UIImageJPEGRepresentation(imageToDisplay, 0.2f ); // setting compression to a low value (high compression) impact performance, but not actual img quality - if ( ![ UIImageJPEGRepresentation(imageToDisplay, 0.2f ) writeToFile:filePath atomically:YES ] ) { + if ( ![ imageData writeToFile:filePath atomically:YES ] ) { return; } + [asset requestMetadataWithCompletionBlock:^(NSDictionary * _Nonnull metadata) { + //fetch_item.metadata = metadata; + + NSError *error; + NSData *jsonData; + NSMutableDictionary * fetchMeta = [NSMutableDictionary new]; + @try { + jsonData = [NSJSONSerialization dataWithJSONObject:[metadata objectForKey:@"{GPS}"] options:0 error:&error]; + [fetchMeta setObject:[metadata objectForKey:@"{GPS}"] forKey:@"gps"]; + } @catch (NSException *exception) { + NSLog(@"ERROR - %@", exception); + } + + @try { + jsonData = [NSJSONSerialization dataWithJSONObject:[metadata objectForKey:@"{Exif}"] options:0 error:&error]; + [fetchMeta setObject:[metadata objectForKey:@"{Exif}"] forKey:@"exif"]; + } @catch (NSException *exception) { + NSLog(@"ERROR - %@", exception); + } + [fetchMeta setValue:filePath forKey:@"image_fullsize"]; + + NSDictionary *fetchMetaResult = [NSDictionary dictionaryWithDictionary:fetchMeta]; + + + jsonData = [NSJSONSerialization dataWithJSONObject:fetchMetaResult options:0 error:&error]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + fetch_item.metadataJSON = jsonString; + + }]; + fetch_item.image_fullsize = filePath; fetch_item.be_saving_img = false; diff --git a/src/ios/PHAsset+Meta.h b/src/ios/PHAsset+Meta.h new file mode 100644 index 00000000..546d2141 --- /dev/null +++ b/src/ios/PHAsset+Meta.h @@ -0,0 +1,51 @@ +// +// PHAsset+Meta.h +// CordovaPlugins +// +// Created by Alexander on 11/19/15. +// Copyright © 2015 Kentdome, LLC. All rights reserved. +// + +#import +@import Photos; + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^PHAssetStringBlock)(NSString *string); +typedef void (^PHAssetBoolBlock)(BOOL success); +typedef void (^PHAssetMetadataBlock)(NSDictionary *metadata); + +@interface PHAsset (Meta) + +-(void)setMetadata:(NSDictionary *)metadata; + +/*! + @method requestUniformTypeWithCompletionBlock + @description Get system-declared uniform type identifiers of an asset (com.compuserve.gif, public.png, etc) + @param completionBlock This block is passed a string. This parameter may be nil. + */ +-(void)requestUniformTypeWithCompletionBlock:(PHAssetStringBlock)completionBlock; + +/*! + @method requestMetadataWithOptions:options:completionBlock + @description Get metadata dictionary of an asset (contains sub-dictionaries EXIF, GPS etc) + @param options An PHContentEditingInputRequestOptions to specify options of a PHAsset object (networkAccessAllowed, progressHandler) + @param completionBlock This block is passed a dictionary of metadata properties. This parameter may be nil. + */ +-(void)requestMetadataWithOptions:(PHContentEditingInputRequestOptions*)options completionBlock:(PHAssetMetadataBlock)completionBlock; + + +/*! + @method requestMetadataWithCompletionBlock + @description Get metadata dictionary of an asset (contains sub-dictionaries EXIF, GPS etc) + @param completionBlock This block is passed a dictionary of metadata properties. This parameter may be nil. + */ +-(void)requestMetadataWithCompletionBlock:(PHAssetMetadataBlock)completionBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/PHAsset+Meta.m b/src/ios/PHAsset+Meta.m new file mode 100644 index 00000000..6cb871bb --- /dev/null +++ b/src/ios/PHAsset+Meta.m @@ -0,0 +1,57 @@ +// +// PHAsset+Meta.m +// PHAssetTest +// +// Created by Alexander on 11/19/15. +// Copyright © 2015 Kentdome, LLC. All rights reserved. +// + +#import "PHAsset+Meta.h" + +@implementation PHAsset (Meta) + +-(void)requestUniformTypeWithCompletionBlock:(PHAssetStringBlock)completionBlock{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + PHImageRequestOptions *options = [[PHImageRequestOptions alloc]init]; + options.networkAccessAllowed = YES; + PHImageManager *manager = [[PHImageManager alloc] init]; + [manager requestImageDataForAsset:self options:options resultHandler: + ^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(dataUTI); + }); + }]; + }); +} + + +-(void)requestMetadataWithOptions:(PHContentEditingInputRequestOptions*)options completionBlock:(PHAssetMetadataBlock)completionBlock{ + if(self.mediaType == PHAssetMediaTypeImage){ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) { + CIImage *image = [CIImage imageWithContentsOfURL:contentEditingInput.fullSizeImageURL]; + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(image.properties); + }); + }]; + + }); + } +} + + +-(void)requestMetadataWithCompletionBlock:(PHAssetMetadataBlock)completionBlock{ + PHImageRequestOptions *options = [PHImageRequestOptions new]; + options.networkAccessAllowed = YES; + options.synchronous = YES; + options.version = PHImageRequestOptionsVersionOriginal; + PHImageManager *manager = [[PHImageManager alloc] init]; + [manager requestImageDataForAsset:self options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info){ + CIImage *image = [CIImage imageWithData:imageData]; + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(image.properties); + }); + }]; +} + +@end diff --git a/src/ios/SOSPicker.m b/src/ios/SOSPicker.m index afbb75b5..efb14c5f 100644 --- a/src/ios/SOSPicker.m +++ b/src/ios/SOSPicker.m @@ -16,7 +16,8 @@ typedef enum : NSUInteger { FILE_URI = 0, - BASE64_STRING = 1 + BASE64_STRING = 1, + METADATA_JSON = 2 } SOSPickerOutputType; @interface SOSPicker () @@ -213,7 +214,8 @@ - (void)assetsPickerController:(GMImagePickerController *)picker didFinishPickin } else { if (self.quality == 100) { // no scaling, no downsampling, this is the fastest option - [result_all addObject:item.image_fullsize]; + //[result_all addObject:item.image_fullsize]; + [result_all addObject:item.metadataJSON]; } else { // resample first UIImage* image = [UIImage imageNamed:item.image_fullsize]; From 5c3bc1ed88c833dcde1229fecd057a2705e710d7 Mon Sep 17 00:00:00 2001 From: Victor Rodriguez Date: Tue, 8 Dec 2020 18:58:08 +0100 Subject: [PATCH 5/6] plugin.xml --- plugin.xml | 3 +++ src/ios/{ => GMImagePicker}/PHAsset+Meta.h | 0 src/ios/{ => GMImagePicker}/PHAsset+Meta.m | 0 3 files changed, 3 insertions(+) rename src/ios/{ => GMImagePicker}/PHAsset+Meta.h (100%) rename src/ios/{ => GMImagePicker}/PHAsset+Meta.m (100%) diff --git a/plugin.xml b/plugin.xml index f44c2414..89813080 100644 --- a/plugin.xml +++ b/plugin.xml @@ -66,6 +66,9 @@ + + + diff --git a/src/ios/PHAsset+Meta.h b/src/ios/GMImagePicker/PHAsset+Meta.h similarity index 100% rename from src/ios/PHAsset+Meta.h rename to src/ios/GMImagePicker/PHAsset+Meta.h diff --git a/src/ios/PHAsset+Meta.m b/src/ios/GMImagePicker/PHAsset+Meta.m similarity index 100% rename from src/ios/PHAsset+Meta.m rename to src/ios/GMImagePicker/PHAsset+Meta.m From 19135caa1e49ffd11c028e2d12832e1b8055da20 Mon Sep 17 00:00:00 2001 From: Victor Rodriguez Date: Sat, 12 Dec 2020 00:12:49 +0100 Subject: [PATCH 6/6] fix output image quality --- src/ios/GMImagePicker/GMGridViewController.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ios/GMImagePicker/GMGridViewController.m b/src/ios/GMImagePicker/GMGridViewController.m index 09d71531..0ba890f1 100755 --- a/src/ios/GMImagePicker/GMGridViewController.m +++ b/src/ios/GMImagePicker/GMGridViewController.m @@ -511,8 +511,8 @@ - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtInde UIImage *imageToDisplay = result.fixOrientation; // UIImage+fixOrientation extension NSLog(@"corrected orientation: %ld",(UIImageOrientation)imageToDisplay.imageOrientation); - NSData * imageData = UIImageJPEGRepresentation(imageToDisplay, 0.2f ); - // setting compression to a low value (high compression) impact performance, but not actual img quality + NSData * imageData = UIImageJPEGRepresentation(imageToDisplay, 1.0f ); + // setting compression to a 1.0 => keep original quality if ( ![ imageData writeToFile:filePath atomically:YES ] ) { return; }