diff --git a/README.md b/README.md index 5123429c6..f1e537630 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,16 @@ buildscript { } ``` +- Add the following to your `build.gradle`'s repositories section. (project build.gradle) +```gradle +allprojects { + repositories { + jcenter() + maven { url "https://jitpack.io" } + } +} +``` + - Add `useSupportLibrary` (app build.gradle) ```gradle diff --git a/android/build.gradle b/android/build.gradle index 0d0a68f9b..4692afaa9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -16,6 +16,6 @@ android { dependencies { compile 'com.facebook.react:react-native:+' - compile 'com.yalantis:ucrop:2.2.0-native' + compile 'com.github.yalantis:ucrop:2.2.1-native' compile 'id.zelory:compressor:2.1.0' } diff --git a/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java b/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java index 3ab8296f1..0fa986a78 100644 --- a/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java +++ b/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java @@ -678,8 +678,11 @@ private void croppingResult(Activity activity, final int requestCode, final int final Uri resultUri = UCrop.getOutput(data); if (resultUri != null) { try { + WritableMap result = getSelection(activity, resultUri, false); + result.putMap("cropRect", PickerModule.getCroppedRectMap(data)); + resultCollector.setWaitCount(1); - resultCollector.notifySuccess(getSelection(activity, resultUri, false)); + resultCollector.notifySuccess(result); } catch (Exception ex) { resultCollector.notifyProblem(E_NO_IMAGE_DATA_FOUND, ex.getMessage()); } @@ -729,4 +732,16 @@ private File createImageFile() throws IOException { return image; } + + private static WritableMap getCroppedRectMap(Intent data) { + final int DEFAULT_VALUE = -1; + final WritableMap map = new WritableNativeMap(); + + map.putInt("x", data.getIntExtra(UCrop.EXTRA_OUTPUT_OFFSET_X, DEFAULT_VALUE)); + map.putInt("y", data.getIntExtra(UCrop.EXTRA_OUTPUT_OFFSET_Y, DEFAULT_VALUE)); + map.putInt("width", data.getIntExtra(UCrop.EXTRA_OUTPUT_IMAGE_WIDTH, DEFAULT_VALUE)); + map.putInt("height", data.getIntExtra(UCrop.EXTRA_OUTPUT_IMAGE_HEIGHT, DEFAULT_VALUE)); + + return map; + } } diff --git a/index.d.ts b/index.d.ts index 94b33ea23..811093ca2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -33,6 +33,14 @@ declare module "react-native-image-crop-picker" { height: number; mime: string; exif: null | object; + cropRect: null | CropRect + } + + export interface CropRect { + x: number; + y: number; + width: number; + height: number; } export function openPicker(options: Options): Promise; diff --git a/ios/ImageCropPicker.m b/ios/ImageCropPicker.m index a602e2d69..375254127 100644 --- a/ios/ImageCropPicker.m +++ b/ios/ImageCropPicker.m @@ -67,7 +67,7 @@ - (instancetype)init }; self.compression = [[Compression alloc] init]; } - + return self; } @@ -79,11 +79,11 @@ + (BOOL)requiresMainQueueSetup { if ([[self.options objectForKey:@"waitAnimationEnd"] boolValue]) { return completion; } - + if (completion != nil) { completion(); } - + return nil; } @@ -106,7 +106,7 @@ - (void)checkCameraPermissions:(void(^)(BOOL granted))callback - (void) setConfiguration:(NSDictionary *)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { - + self.resolve = resolve; self.reject = reject; self.options = [NSMutableDictionary dictionaryWithDictionary:self.defaultOptions]; @@ -120,17 +120,17 @@ - (UIViewController*) getRootVC { while (root.presentedViewController != nil) { root = root.presentedViewController; } - + return root; } RCT_EXPORT_METHOD(openCamera:(NSDictionary *)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - + [self setConfiguration:options resolver:resolve rejecter:reject]; self.currentSelectionMode = CAMERA; - + #if TARGET_IPHONE_SIMULATOR self.reject(ERROR_PICKER_CANNOT_RUN_CAMERA_ON_SIMULATOR_KEY, ERROR_PICKER_CANNOT_RUN_CAMERA_ON_SIMULATOR_MSG, nil); return; @@ -140,7 +140,7 @@ - (UIViewController*) getRootVC { self.reject(ERROR_PICKER_NO_CAMERA_PERMISSION_KEY, ERROR_PICKER_NO_CAMERA_PERMISSION_MSG, nil); return; } - + UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; picker.allowsEditing = NO; @@ -148,7 +148,7 @@ - (UIViewController*) getRootVC { if ([[self.options objectForKey:@"useFrontCamera"] boolValue]) { picker.cameraDevice = UIImagePickerControllerCameraDeviceFront; } - + dispatch_async(dispatch_get_main_queue(), ^{ [[self getRootVC] presentViewController:picker animated:YES completion:nil]; }); @@ -163,12 +163,12 @@ - (void)viewDidLoad { - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *chosenImage = [info objectForKey:UIImagePickerControllerOriginalImage]; UIImage *chosenImageT = [chosenImage fixOrientation]; - + NSDictionary *exif; if([[self.options objectForKey:@"includeExif"] boolValue]) { exif = [info objectForKey:UIImagePickerControllerMediaMetadata]; } - + [self processSingleImagePick:chosenImageT withExif:exif withViewController:picker withSourceURL:self.croppingFile[@"sourceURL"] withLocalIdentifier:self.croppingFile[@"localIdentifier"] withFilename:self.croppingFile[@"filename"] withCreationDate:self.croppingFile[@"creationDate"] withModificationDate:self.croppingFile[@"modificationDate"]]; } @@ -181,38 +181,38 @@ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { - (NSString*) getTmpDirectory { NSString *TMP_DIRECTORY = @"react-native-image-crop-picker/"; NSString *tmpFullPath = [NSTemporaryDirectory() stringByAppendingString:TMP_DIRECTORY]; - + BOOL isDir; BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:tmpFullPath isDirectory:&isDir]; if (!exists) { [[NSFileManager defaultManager] createDirectoryAtPath: tmpFullPath withIntermediateDirectories:YES attributes:nil error:nil]; } - + return tmpFullPath; } - (BOOL)cleanTmpDirectory { NSString* tmpDirectoryPath = [self getTmpDirectory]; NSArray* tmpDirectory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpDirectoryPath error:NULL]; - + for (NSString *file in tmpDirectory) { BOOL deleted = [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@%@", tmpDirectoryPath, file] error:NULL]; - + if (!deleted) { return NO; } } - + return YES; } RCT_EXPORT_METHOD(cleanSingle:(NSString *) path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - + BOOL deleted = [[NSFileManager defaultManager] removeItemAtPath:path error:NULL]; - + if (!deleted) { reject(ERROR_CLEANUP_ERROR_KEY, ERROR_CLEANUP_ERROR_MSG, nil); } else { @@ -232,16 +232,16 @@ - (BOOL)cleanTmpDirectory { RCT_EXPORT_METHOD(openPicker:(NSDictionary *)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - + [self setConfiguration:options resolver:resolve rejecter:reject]; self.currentSelectionMode = PICKER; - + [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { if (status != PHAuthorizationStatusAuthorized) { self.reject(ERROR_PICKER_UNAUTHORIZED_KEY, ERROR_PICKER_UNAUTHORIZED_MSG, nil); return; } - + dispatch_async(dispatch_get_main_queue(), ^{ // init picker QBImagePickerController *imagePickerController = @@ -251,7 +251,7 @@ - (BOOL)cleanTmpDirectory { imagePickerController.minimumNumberOfSelection = abs([[self.options objectForKey:@"minFiles"] intValue]); imagePickerController.maximumNumberOfSelection = abs([[self.options objectForKey:@"maxFiles"] intValue]); imagePickerController.showsNumberOfSelectedAssets = [[self.options objectForKey:@"showsSelectedCount"] boolValue]; - + if ([self.options objectForKey:@"smartAlbums"] != nil) { NSDictionary *smartAlbums = @{ @"UserLibrary" : @(PHAssetCollectionSubtypeSmartAlbumUserLibrary), @@ -268,12 +268,12 @@ - (BOOL)cleanTmpDirectory { } imagePickerController.assetCollectionSubtypes = albumsToShow; } - + if ([[self.options objectForKey:@"cropping"] boolValue]) { imagePickerController.mediaType = QBImagePickerMediaTypeImage; } else { NSString *mediaType = [self.options objectForKey:@"mediaType"]; - + if ([mediaType isEqualToString:@"any"]) { imagePickerController.mediaType = QBImagePickerMediaTypeAny; } else if ([mediaType isEqualToString:@"photo"]) { @@ -281,9 +281,9 @@ - (BOOL)cleanTmpDirectory { } else { imagePickerController.mediaType = QBImagePickerMediaTypeVideo; } - + } - + [[self getRootVC] presentViewController:imagePickerController animated:YES completion:nil]; }); }]; @@ -292,12 +292,12 @@ - (BOOL)cleanTmpDirectory { RCT_EXPORT_METHOD(openCropper:(NSDictionary *)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - + [self setConfiguration:options resolver:resolve rejecter:reject]; self.currentSelectionMode = CROPPING; - + NSString *path = [options objectForKey:@"path"]; - + [self.bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:path] callback:^(NSError *error, UIImage *image) { if (error) { self.reject(ERROR_CROPPER_IMAGE_NOT_FOUND_KEY, ERROR_CROPPER_IMAGE_NOT_FOUND_MSG, nil); @@ -319,7 +319,7 @@ - (void)startCropping:(UIImage *)image { imageCropVC.delegate = self; [imageCropVC setModalPresentationStyle:UIModalPresentationCustom]; [imageCropVC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve]; - + dispatch_async(dispatch_get_main_queue(), ^{ [[self getRootVC] presentViewController:imageCropVC animated:YES completion:nil]; }); @@ -328,18 +328,18 @@ - (void)startCropping:(UIImage *)image { - (void)showActivityIndicator:(void (^)(UIActivityIndicatorView*, UIView*))handler { dispatch_async(dispatch_get_main_queue(), ^{ UIView *mainView = [[self getRootVC] view]; - + // create overlay UIView *loadingView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; loadingView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]; loadingView.clipsToBounds = YES; - + // create loading spinner UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; activityView.frame = CGRectMake(65, 40, activityView.bounds.size.width, activityView.bounds.size.height); activityView.center = loadingView.center; [loadingView addSubview:activityView]; - + // create message UILabel *loadingLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 115, 130, 22)]; loadingLabel.backgroundColor = [UIColor clearColor]; @@ -352,11 +352,11 @@ - (void)showActivityIndicator:(void (^)(UIActivityIndicatorView*, UIView*))handl loadingLabel.text = [self.options objectForKey:@"loadingLabelText"]; [loadingLabel setFont:[UIFont boldSystemFontOfSize:18]]; [loadingView addSubview:loadingLabel]; - + // show all [mainView addSubview:loadingView]; [activityView startAnimating]; - + handler(activityView, loadingView); }); } @@ -366,30 +366,30 @@ - (void) getVideoAsset:(PHAsset*)forAsset completion:(void (^)(NSDictionary* ima PHImageManager *manager = [PHImageManager defaultManager]; PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init]; options.version = PHVideoRequestOptionsVersionOriginal; - + [manager requestAVAssetForVideo:forAsset options:options resultHandler:^(AVAsset * asset, AVAudioMix * audioMix, NSDictionary *info) { NSURL *sourceURL = [(AVURLAsset *)asset URL]; - + // create temp file NSString *tmpDirFullPath = [self getTmpDirectory]; NSString *filePath = [tmpDirFullPath stringByAppendingString:[[NSUUID UUID] UUIDString]]; filePath = [filePath stringByAppendingString:@".mp4"]; NSURL *outputURL = [NSURL fileURLWithPath:filePath]; - + [self.compression compressVideo:sourceURL outputURL:outputURL withOptions:self.options handler:^(AVAssetExportSession *exportSession) { if (exportSession.status == AVAssetExportSessionStatusCompleted) { AVAsset *compressedAsset = [AVAsset assetWithURL:outputURL]; AVAssetTrack *track = [[compressedAsset tracksWithMediaType:AVMediaTypeVideo] firstObject]; - + NSNumber *fileSizeValue = nil; [outputURL getResourceValue:&fileSizeValue forKey:NSURLFileSizeKey error:nil]; - + completion([self createAttachmentResponse:[outputURL absoluteString] withExif:nil withSourceURL:[sourceURL absoluteString] @@ -400,6 +400,7 @@ - (void) getVideoAsset:(PHAsset*)forAsset completion:(void (^)(NSDictionary* ima withMime:@"video/mp4" withSize:fileSizeValue withData:nil + withRect:CGRectNull withCreationDate:forAsset.creationDate withModificationDate:forAsset.modificationDate ]); @@ -410,8 +411,7 @@ - (void) getVideoAsset:(PHAsset*)forAsset completion:(void (^)(NSDictionary* ima }]; } -- (NSDictionary*) createAttachmentResponse:(NSString*)filePath withExif:(NSDictionary*) exif withSourceURL:(NSString*)sourceURL withLocalIdentifier:(NSString*)localIdentifier withFilename:(NSString*)filename withWidth:(NSNumber*)width withHeight:(NSNumber*)height withMime:(NSString*)mime withSize:(NSNumber*)size withData:(NSString*)data withCreationDate:(NSDate*)creationDate withModificationDate:(NSDate*)modificationDate -{ +- (NSDictionary*) createAttachmentResponse:(NSString*)filePath withExif:(NSDictionary*) exif withSourceURL:(NSString*)sourceURL withLocalIdentifier:(NSString*)localIdentifier withFilename:(NSString*)filename withWidth:(NSNumber*)width withHeight:(NSNumber*)height withMime:(NSString*)mime withSize:(NSNumber*)size withData:(NSString*)data withRect:(CGRect)cropRect withCreationDate:(NSDate*)creationDate withModificationDate:(NSDate*)modificationDate { return @{ @"path": filePath, @"sourceURL": (sourceURL) ? sourceURL : [NSNull null], @@ -423,6 +423,7 @@ - (NSDictionary*) createAttachmentResponse:(NSString*)filePath withExif:(NSDicti @"size": size, @"data": (data) ? data : [NSNull null], @"exif": (exif) ? exif : [NSNull null], + @"cropRect": CGRectIsNull(cropRect) ? [NSNull null] : [ImageCropPicker cgRectToDictionary:cropRect], @"creationDate:": (creationDate) ? [NSString stringWithFormat:@"%.0f", [creationDate timeIntervalSince1970]] : [NSNull null], @"modificationDate": (modificationDate) ? [NSString stringWithFormat:@"%.0f", [modificationDate timeIntervalSince1970]] : [NSNull null], }; @@ -431,26 +432,26 @@ - (NSDictionary*) createAttachmentResponse:(NSString*)filePath withExif:(NSDicti - (void)qb_imagePickerController: (QBImagePickerController *)imagePickerController didFinishPickingAssets:(NSArray *)assets { - + PHImageManager *manager = [PHImageManager defaultManager]; PHImageRequestOptions* options = [[PHImageRequestOptions alloc] init]; options.synchronous = NO; options.networkAccessAllowed = YES; - + if ([[[self options] objectForKey:@"multiple"] boolValue]) { NSMutableArray *selections = [[NSMutableArray alloc] init]; - + [self showActivityIndicator:^(UIActivityIndicatorView *indicatorView, UIView *overlayView) { NSLock *lock = [[NSLock alloc] init]; __block int processed = 0; - + for (PHAsset *phAsset in assets) { - + if (phAsset.mediaType == PHAssetMediaTypeVideo) { [self getVideoAsset:phAsset completion:^(NSDictionary* video) { dispatch_async(dispatch_get_main_queue(), ^{ [lock lock]; - + if (video == nil) { [indicatorView stopAnimating]; [overlayView removeFromSuperview]; @@ -459,11 +460,11 @@ - (void)qb_imagePickerController: }]]; return; } - + [selections addObject:video]; processed++; [lock unlock]; - + if (processed == [assets count]) { [indicatorView stopAnimating]; [overlayView removeFromSuperview]; @@ -479,18 +480,18 @@ - (void)qb_imagePickerController: requestImageDataForAsset:phAsset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { - + NSURL *sourceURL = [info objectForKey:@"PHImageFileURLKey"]; - + dispatch_async(dispatch_get_main_queue(), ^{ [lock lock]; @autoreleasepool { UIImage *imgT = [UIImage imageWithData:imageData]; UIImage *imageT = [imgT fixOrientation]; - + ImageResult *imageResult = [self.compression compressImage:imageT withOptions:self.options]; NSString *filePath = [self persistFile:imageResult.data]; - + if (filePath == nil) { [indicatorView stopAnimating]; [overlayView removeFromSuperview]; @@ -499,12 +500,12 @@ - (void)qb_imagePickerController: }]]; return; } - + NSDictionary* exif = nil; if([[self.options objectForKey:@"includeExif"] boolValue]) { exif = [[CIImage imageWithData:imageData] properties]; } - + [selections addObject:[self createAttachmentResponse:filePath withExif: exif withSourceURL:[sourceURL absoluteString] @@ -515,15 +516,16 @@ - (void)qb_imagePickerController: withMime:imageResult.mime withSize:[NSNumber numberWithUnsignedInteger:imageResult.data.length] withData:[[self.options objectForKey:@"includeBase64"] boolValue] ? [imageResult.data base64EncodedStringWithOptions:0]: nil + withRect:CGRectNull withCreationDate:phAsset.creationDate withModificationDate:phAsset.modificationDate ]]; } processed++; [lock unlock]; - + if (processed == [assets count]) { - + [indicatorView stopAnimating]; [overlayView removeFromSuperview]; [imagePickerController dismissViewControllerAnimated:YES completion:[self waitAnimationEnd:^{ @@ -538,7 +540,7 @@ - (void)qb_imagePickerController: }]; } else { PHAsset *phAsset = [assets objectAtIndex:0]; - + [self showActivityIndicator:^(UIActivityIndicatorView *indicatorView, UIView *overlayView) { if (phAsset.mediaType == PHAssetMediaTypeVideo) { [self getVideoAsset:phAsset completion:^(NSDictionary* video) { @@ -566,11 +568,11 @@ - (void)qb_imagePickerController: if([[self.options objectForKey:@"includeExif"] boolValue]) { exif = [[CIImage imageWithData:imageData] properties]; } - + dispatch_async(dispatch_get_main_queue(), ^{ [indicatorView stopAnimating]; [overlayView removeFromSuperview]; - + [self processSingleImagePick:[UIImage imageWithData:imageData] withExif: exif withViewController:imagePickerController @@ -596,16 +598,16 @@ - (void)qb_imagePickerControllerDidCancel:(QBImagePickerController *)imagePicker // this method will take care of attaching image metadata, and sending image to cropping controller // or to user directly - (void) processSingleImagePick:(UIImage*)image withExif:(NSDictionary*) exif withViewController:(UIViewController*)viewController withSourceURL:(NSString*)sourceURL withLocalIdentifier:(NSString*)localIdentifier withFilename:(NSString*)filename withCreationDate:(NSDate*)creationDate withModificationDate:(NSDate*)modificationDate { - + if (image == nil) { [viewController dismissViewControllerAnimated:YES completion:[self waitAnimationEnd:^{ self.reject(ERROR_PICKER_NO_DATA_KEY, ERROR_PICKER_NO_DATA_MSG, nil); }]]; return; } - + NSLog(@"id: %@ filename: %@", localIdentifier, filename); - + if ([[[self options] objectForKey:@"cropping"] boolValue]) { self.croppingFile = [[NSMutableDictionary alloc] init]; self.croppingFile[@"sourceURL"] = sourceURL; @@ -614,7 +616,7 @@ - (void) processSingleImagePick:(UIImage*)image withExif:(NSDictionary*) exif wi self.croppingFile[@"creationDate"] = creationDate; self.croppingFile[@"modifcationDate"] = modificationDate; NSLog(@"CroppingFile %@", self.croppingFile); - + [self startCropping:image]; } else { ImageResult *imageResult = [self.compression compressImage:image withOptions:self.options]; @@ -625,7 +627,7 @@ - (void) processSingleImagePick:(UIImage*)image withExif:(NSDictionary*) exif wi }]]; return; } - + // Wait for viewController to dismiss before resolving, or we lose the ability to display // Alert.alert in the .then() handler. [viewController dismissViewControllerAnimated:YES completion:[self waitAnimationEnd:^{ @@ -638,9 +640,11 @@ - (void) processSingleImagePick:(UIImage*)image withExif:(NSDictionary*) exif wi withHeight:imageResult.height withMime:imageResult.mime withSize:[NSNumber numberWithUnsignedInteger:imageResult.data.length] - withData:[[self.options objectForKey:@"includeBase64"] boolValue] ? [imageResult.data base64EncodedStringWithOptions:0] : nil + withData:[[self.options objectForKey:@"includeBase64"] boolValue] ? [imageResult.data base64EncodedStringWithOptions:0] : nil + withRect:CGRectNull withCreationDate:creationDate - withModificationDate:modificationDate]); + withModificationDate:modificationDate + ]); }]]; } } @@ -653,14 +657,14 @@ - (CGRect)imageCropViewControllerCustomMaskRect: CGSize maskSize = CGSizeMake( [[self.options objectForKey:@"width"] intValue], [[self.options objectForKey:@"height"] intValue]); - + CGFloat viewWidth = CGRectGetWidth(controller.view.frame); CGFloat viewHeight = CGRectGetHeight(controller.view.frame); - + CGRect maskRect = CGRectMake((viewWidth - maskSize.width) * 0.5f, (viewHeight - maskSize.height) * 0.5f, maskSize.width, maskSize.height); - + return maskRect; } @@ -670,13 +674,13 @@ - (CGRect) scaleRect:(RSKImageCropViewController *)controller { CGRect rect = controller.maskRect; CGFloat viewWidth = CGRectGetWidth(controller.view.frame); CGFloat viewHeight = CGRectGetHeight(controller.view.frame); - + double scaleFactor = fmin(viewWidth / rect.size.width, viewHeight / rect.size.height); rect.size.width *= scaleFactor; rect.size.height *= scaleFactor; rect.origin.x = (viewWidth - rect.size.width) / 2; rect.origin.y = (viewHeight - rect.size.height) / 2; - + return rect; } @@ -732,13 +736,13 @@ - (void) dismissCropper:(RSKImageCropViewController*)controller selectionDone:(B - (void)imageCropViewController:(RSKImageCropViewController *)controller didCropImage:(UIImage *)croppedImage usingCropRect:(CGRect)cropRect { - + // we have correct rect, but not correct dimensions // so resize image CGSize resizedImageSize = CGSizeMake([[[self options] objectForKey:@"width"] intValue], [[[self options] objectForKey:@"height"] intValue]); UIImage *resizedImage = [croppedImage resizedImageToFitInSize:resizedImageSize scaleIfSmaller:YES]; ImageResult *imageResult = [self.compression compressImage:resizedImage withOptions:self.options]; - + NSString *filePath = [self persistFile:imageResult.data]; if (filePath == nil) { [self dismissCropper:controller selectionDone:YES completion:[self waitAnimationEnd:^{ @@ -746,12 +750,12 @@ - (void)imageCropViewController:(RSKImageCropViewController *)controller }]]; return; } - + NSDictionary* exif = nil; if([[self.options objectForKey:@"includeExif"] boolValue]) { exif = [[CIImage imageWithData:imageResult.data] properties]; } - + [self dismissCropper:controller selectionDone:YES completion:[self waitAnimationEnd:^{ self.resolve([self createAttachmentResponse:filePath withExif: exif @@ -763,8 +767,10 @@ - (void)imageCropViewController:(RSKImageCropViewController *)controller withMime:imageResult.mime withSize:[NSNumber numberWithUnsignedInteger:imageResult.data.length] withData:[[self.options objectForKey:@"includeBase64"] boolValue] ? [imageResult.data base64EncodedStringWithOptions:0] : nil + withRect:cropRect withCreationDate:self.croppingFile[@"creationDate"] - withModificationDate:self.croppingFile[@"modificationDate"]]); + withModificationDate:self.croppingFile[@"modificationDate"] + ]); }]]; } @@ -775,13 +781,13 @@ - (NSString*) persistFile:(NSData*)data { NSString *tmpDirFullPath = [self getTmpDirectory]; NSString *filePath = [tmpDirFullPath stringByAppendingString:[[NSUUID UUID] UUIDString]]; filePath = [filePath stringByAppendingString:@".jpg"]; - + // save cropped file BOOL status = [data writeToFile:filePath atomically:YES]; if (!status) { return nil; } - + return filePath; } @@ -794,4 +800,15 @@ - (void)imageCropViewController:(RSKImageCropViewController *)controller [self imageCropViewController:controller didCropImage:croppedImage usingCropRect:cropRect]; } -@end + + ++ (NSDictionary *)cgRectToDictionary:(CGRect)rect { + return @{ + @"x": [NSNumber numberWithFloat: rect.origin.x], + @"y": [NSNumber numberWithFloat: rect.origin.y], + @"width": [NSNumber numberWithFloat: CGRectGetWidth(rect)], + @"height": [NSNumber numberWithFloat: CGRectGetHeight(rect)] + }; +} + +@end \ No newline at end of file