cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From shaz...@apache.org
Subject cordova-plugin-camera git commit: CB-7937 - Re-factor iOS Camera plugin so that it is testable (closes #52)
Date Fri, 09 Jan 2015 23:39:56 GMT
Repository: cordova-plugin-camera
Updated Branches:
  refs/heads/master 3ab650bdc -> 35c653d24


CB-7937 - Re-factor iOS Camera plugin so that it is testable (closes #52)

Signed-off-by: Shazron Abdullah <shazron@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/35c653d2
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/35c653d2
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/35c653d2

Branch: refs/heads/master
Commit: 35c653d24d3961655b3dcbb4c032942736754a92
Parents: 3ab650b
Author: Shazron Abdullah <shazron@apache.org>
Authored: Wed Nov 5 12:19:42 2014 -0800
Committer: Shazron Abdullah <shazron@apache.org>
Committed: Fri Jan 9 15:39:29 2015 -0800

----------------------------------------------------------------------
 plugin.xml                             |   2 +
 src/ios/CDVCamera.h                    |  42 +-
 src/ios/CDVCamera.m                    | 811 +++++++++++++---------------
 src/ios/UIImage+CropScaleOrientation.h |  28 +
 src/ios/UIImage+CropScaleOrientation.m | 170 ++++++
 5 files changed, 592 insertions(+), 461 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/35c653d2/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index d84c44d..2844e1f 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -133,6 +133,8 @@
             <clobbers target="CameraPopoverHandle" />
          </js-module>
 
+         <header-file src="src/ios/UIImage+CropScaleOrientation.h" />
+         <source-file src="src/ios/UIImage+CropScaleOrientation.m" />
          <header-file src="src/ios/CDVCamera.h" />
          <source-file src="src/ios/CDVCamera.m" />
          <header-file src="src/ios/CDVJpegHeaderWriter.h" />

http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/35c653d2/src/ios/CDVCamera.h
----------------------------------------------------------------------
diff --git a/src/ios/CDVCamera.h b/src/ios/CDVCamera.h
index c2a71ac..231e9f6 100644
--- a/src/ios/CDVCamera.h
+++ b/src/ios/CDVCamera.h
@@ -42,22 +42,39 @@ enum CDVMediaType {
 };
 typedef NSUInteger CDVMediaType;
 
+@interface CDVPictureOptions : NSObject
+
+@property (strong) NSNumber* quality;
+@property (assign) CDVDestinationType destinationType;
+@property (assign) UIImagePickerControllerSourceType sourceType;
+@property (assign) CGSize targetSize;
+@property (assign) CDVEncodingType encodingType;
+@property (assign) CDVMediaType mediaType;
+@property (assign) BOOL allowsEditing;
+@property (assign) BOOL correctOrientation;
+@property (assign) BOOL saveToPhotoAlbum;
+@property (strong) NSDictionary* popoverOptions;
+@property (assign) UIImagePickerControllerCameraDevice cameraDirection;
+
+@property (assign) BOOL popoverSupported;
+@property (assign) BOOL usesGeolocation;
+@property (assign) BOOL cropToSize;
+
++ (instancetype) createFromTakePictureArguments:(NSArray*)arguments;
+
+@end
+
 @interface CDVCameraPicker : UIImagePickerController
-{}
 
-@property (assign) NSInteger quality;
+@property (strong) CDVPictureOptions* pictureOptions;
+
 @property (copy)   NSString* callbackId;
 @property (copy)   NSString* postUrl;
-@property (nonatomic) enum CDVDestinationType returnType;
-@property (nonatomic) enum CDVEncodingType encodingType;
-@property (strong) UIPopoverController* popoverController;
-@property (assign) CGSize targetSize;
-@property (assign) bool correctOrientation;
-@property (assign) bool saveToPhotoAlbum;
-@property (assign) bool cropToSize;
+@property (strong) UIPopoverController* pickerPopoverController;
+@property (assign) BOOL cropToSize;
 @property (strong) UIView* webView;
-@property (assign) BOOL popoverSupported;
-@property (assign) BOOL usesGeolocation;
+
++ (instancetype) createFromPictureOptions:(CDVPictureOptions*)options;
 
 @end
 
@@ -92,9 +109,6 @@ typedef NSUInteger CDVMediaType;
 - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
 - (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker;
 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
-- (UIImage*)imageByScalingAndCroppingForSize:(UIImage*)anImage toSize:(CGSize)targetSize;
-- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)anImage toSize:(CGSize)frameSize;
-- (UIImage*)imageCorrectedForCaptureOrientation:(UIImage*)anImage;
 
 - (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation;
 - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/35c653d2/src/ios/CDVCamera.m
----------------------------------------------------------------------
diff --git a/src/ios/CDVCamera.m b/src/ios/CDVCamera.m
index 301187a..857c9b1 100644
--- a/src/ios/CDVCamera.m
+++ b/src/ios/CDVCamera.m
@@ -19,6 +19,7 @@
 
 #import "CDVCamera.h"
 #import "CDVJpegHeaderWriter.h"
+#import "UIImage+CropScaleOrientation.h"
 #import <Cordova/NSArray+Comparisons.h>
 #import <Cordova/NSData+Base64.h>
 #import <Cordova/NSDictionary+Extensions.h>
@@ -34,6 +35,40 @@
 
 static NSSet* org_apache_cordova_validArrowDirections;
 
+@implementation CDVPictureOptions
+
++ (instancetype) createFromTakePictureArguments:(NSArray*)arguments
+{
+    CDVPictureOptions* pictureOptions = [[CDVPictureOptions alloc] init];
+
+    pictureOptions.quality = [arguments objectAtIndex:0 withDefault:@(50)];
+    pictureOptions.destinationType = [[arguments objectAtIndex:1 withDefault:@(DestinationTypeFileUri)] unsignedIntegerValue];
+    pictureOptions.sourceType = [[arguments objectAtIndex:2 withDefault:@(UIImagePickerControllerSourceTypeCamera)] unsignedIntegerValue];
+    
+    NSNumber* targetWidth = [arguments objectAtIndex:3 withDefault:nil];
+    NSNumber* targetHeight = [arguments objectAtIndex:4 withDefault:nil];
+    pictureOptions.targetSize = CGSizeMake(0, 0);
+    if ((targetWidth != nil) && (targetHeight != nil)) {
+        pictureOptions.targetSize = CGSizeMake([targetWidth floatValue], [targetHeight floatValue]);
+    }
+
+    pictureOptions.encodingType = [[arguments objectAtIndex:5 withDefault:@(EncodingTypeJPEG)] unsignedIntegerValue];
+    pictureOptions.mediaType = [[arguments objectAtIndex:6 withDefault:@(MediaTypePicture)] unsignedIntegerValue];
+    pictureOptions.allowsEditing = [[arguments objectAtIndex:7 withDefault:@(NO)] boolValue];
+    pictureOptions.correctOrientation = [[arguments objectAtIndex:8 withDefault:@(NO)] boolValue];
+    pictureOptions.saveToPhotoAlbum = [[arguments objectAtIndex:9 withDefault:@(NO)] boolValue];
+    pictureOptions.popoverOptions = [arguments objectAtIndex:10 withDefault:nil];
+    pictureOptions.cameraDirection = [[arguments objectAtIndex:11 withDefault:@(UIImagePickerControllerCameraDeviceRear)] unsignedIntegerValue];
+    
+    pictureOptions.popoverSupported = NO;
+    pictureOptions.usesGeolocation = NO;
+    
+    return pictureOptions;
+}
+
+@end
+
+
 @interface CDVCamera ()
 
 @property (readwrite, assign) BOOL hasPendingOperation;
@@ -49,7 +84,6 @@ static NSSet* org_apache_cordova_validArrowDirections;
 
 @synthesize hasPendingOperation, pickerController, locationManager;
 
-
 - (BOOL)usesGeolocation
 {
     id useGeo = [self.commandDelegate.settings objectForKey:[@"CameraUsesGeolocation" lowercaseString]];
@@ -62,106 +96,55 @@ static NSSet* org_apache_cordova_validArrowDirections;
            (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
 }
 
-/*  takePicture arguments:
- * INDEX   ARGUMENT
- *  0       quality
- *  1       destination type
- *  2       source type
- *  3       targetWidth
- *  4       targetHeight
- *  5       encodingType
- *  6       mediaType
- *  7       allowsEdit
- *  8       correctOrientation
- *  9       saveToPhotoAlbum
- *  10      popoverOptions
- *  11      cameraDirection
- */
 - (void)takePicture:(CDVInvokedUrlCommand*)command
 {
-    NSString* callbackId = command.callbackId;
-    NSArray* arguments = command.arguments;
-
     self.hasPendingOperation = YES;
+    
+    __weak CDVCamera* weakSelf = self;
 
-    NSString* sourceTypeString = [arguments objectAtIndex:2];
-    UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; // default
-    if (sourceTypeString != nil) {
-        sourceType = (UIImagePickerControllerSourceType)[sourceTypeString intValue];
-    }
-
-    bool hasCamera = [UIImagePickerController isSourceTypeAvailable:sourceType];
-    if (!hasCamera) {
-        NSLog(@"Camera.getPicture: source type %lu not available.", (unsigned long)sourceType);
-        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no camera available"];
-        [self.commandDelegate sendPluginResult:result callbackId:callbackId];
-        return;
-    }
-
-    bool allowEdit = [[arguments objectAtIndex:7] boolValue];
-    NSNumber* targetWidth = [arguments objectAtIndex:3];
-    NSNumber* targetHeight = [arguments objectAtIndex:4];
-    NSNumber* mediaValue = [arguments objectAtIndex:6];
-    CDVMediaType mediaType = (mediaValue) ? [mediaValue intValue] : MediaTypePicture;
-
-    CGSize targetSize = CGSizeMake(0, 0);
-    if ((targetWidth != nil) && (targetHeight != nil)) {
-        targetSize = CGSizeMake([targetWidth floatValue], [targetHeight floatValue]);
-    }
-
-    // If a popover is already open, close it; we only want one at a time.
-    if (([[self pickerController] popoverController] != nil) && [[[self pickerController] popoverController] isPopoverVisible]) {
-        [[[self pickerController] popoverController] dismissPopoverAnimated:YES];
-        [[[self pickerController] popoverController] setDelegate:nil];
-        [[self pickerController] setPopoverController:nil];
-    }
-
-    CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
-    self.pickerController = cameraPicker;
-
-    cameraPicker.delegate = self;
-    cameraPicker.sourceType = sourceType;
-    cameraPicker.allowsEditing = allowEdit; // THIS IS ALL IT TAKES FOR CROPPING - jm
-    cameraPicker.callbackId = callbackId;
-    cameraPicker.targetSize = targetSize;
-    cameraPicker.cropToSize = NO;
-    // we need to capture this state for memory warnings that dealloc this object
-    cameraPicker.webView = self.webView;
-    cameraPicker.popoverSupported = [self popoverSupported];
-    cameraPicker.usesGeolocation = [self usesGeolocation];
-
-    cameraPicker.correctOrientation = [[arguments objectAtIndex:8] boolValue];
-    cameraPicker.saveToPhotoAlbum = [[arguments objectAtIndex:9] boolValue];
-
-    cameraPicker.encodingType = ([arguments objectAtIndex:5]) ? [[arguments objectAtIndex:5] intValue] : EncodingTypeJPEG;
-
-    cameraPicker.quality = ([arguments objectAtIndex:0]) ? [[arguments objectAtIndex:0] intValue] : 50;
-    cameraPicker.returnType = ([arguments objectAtIndex:1]) ? [[arguments objectAtIndex:1] intValue] : DestinationTypeFileUri;
-
-    if (sourceType == UIImagePickerControllerSourceTypeCamera) {
-        // We only allow taking pictures (no video) in this API.
-        cameraPicker.mediaTypes = [NSArray arrayWithObjects:(NSString*)kUTTypeImage, nil];
-
-        // We can only set the camera device if we're actually using the camera.
-        NSNumber* cameraDirection = [command argumentAtIndex:11 withDefault:[NSNumber numberWithInteger:UIImagePickerControllerCameraDeviceRear]];
-        cameraPicker.cameraDevice = (UIImagePickerControllerCameraDevice)[cameraDirection intValue];
-    } else if (mediaType == MediaTypeAll) {
-        cameraPicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType];
-    } else {
-        NSArray* mediaArray = [NSArray arrayWithObjects:(NSString*)(mediaType == MediaTypeVideo ? kUTTypeMovie : kUTTypeImage), nil];
-        cameraPicker.mediaTypes = mediaArray;
-    }
+    [self.commandDelegate runInBackground:^{
+        
+        CDVPictureOptions* pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command.arguments];
+        pictureOptions.popoverSupported = [self popoverSupported];
+        pictureOptions.usesGeolocation = [self usesGeolocation];
+        pictureOptions.cropToSize = NO;
+        
+        BOOL hasCamera = [UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType];
+        if (!hasCamera) {
+            NSLog(@"Camera.getPicture: source type %lu not available.", (unsigned long)pictureOptions.sourceType);
+            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No camera available"];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+            return;
+        }
+        
+        // If a popover is already open, close it; we only want one at a time.
+        if (([[weakSelf pickerController] pickerPopoverController] != nil) && [[[weakSelf pickerController] pickerPopoverController] isPopoverVisible]) {
+            [[[weakSelf pickerController] pickerPopoverController] dismissPopoverAnimated:YES];
+            [[[weakSelf pickerController] pickerPopoverController] setDelegate:nil];
+            [[weakSelf pickerController] setPickerPopoverController:nil];
+        }
+        
+        CDVCameraPicker* cameraPicker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
+        weakSelf.pickerController = cameraPicker;
+        
+        cameraPicker.delegate = weakSelf;
+        cameraPicker.callbackId = command.callbackId;
+        // we need to capture this state for memory warnings that dealloc this object
+        cameraPicker.webView = weakSelf.webView;
+        
+        if ([weakSelf popoverSupported] && (pictureOptions.sourceType != UIImagePickerControllerSourceTypeCamera)) {
+            if (cameraPicker.pickerPopoverController == nil) {
+                cameraPicker.pickerPopoverController = [[NSClassFromString(@"UIPopoverController") alloc] initWithContentViewController:cameraPicker];
+            }
+            [weakSelf displayPopover:pictureOptions.popoverOptions];
+            weakSelf.hasPendingOperation = NO;
 
-    if ([self popoverSupported] && (sourceType != UIImagePickerControllerSourceTypeCamera)) {
-        if (cameraPicker.popoverController == nil) {
-            cameraPicker.popoverController = [[NSClassFromString(@"UIPopoverController")alloc] initWithContentViewController:cameraPicker];
+        } else {
+            [weakSelf.viewController presentViewController:cameraPicker animated:YES completion:^{
+                weakSelf.hasPendingOperation = NO;
+            }];
         }
-        NSDictionary* options = [command.arguments objectAtIndex:10 withDefault:nil];
-        [self displayPopover:options];
-    } else {
-        [self.viewController presentViewController:cameraPicker animated:YES completion:nil];
-    }
-    self.hasPendingOperation = NO;
+    }];
 }
 
 - (void)repositionPopover:(CDVInvokedUrlCommand*)command
@@ -190,8 +173,8 @@ static NSSet* org_apache_cordova_validArrowDirections;
         }
     }
 
-    [[[self pickerController] popoverController] setDelegate:self];
-    [[[self pickerController] popoverController] presentPopoverFromRect:CGRectMake(x, y, width, height)
+    [[[self pickerController] pickerPopoverController] setDelegate:self];
+    [[[self pickerController] pickerPopoverController] presentPopoverFromRect:CGRectMake(x, y, width, height)
                                                                  inView:[self.webView superview]
                                                permittedArrowDirections:arrowDirection
                                                                animated:YES];
@@ -200,9 +183,9 @@ static NSSet* org_apache_cordova_validArrowDirections;
 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
 {
     if([navigationController isKindOfClass:[UIImagePickerController class]]){
-        UIImagePickerController * cameraPicker = (UIImagePickerController*)navigationController;
+        UIImagePickerController* cameraPicker = (UIImagePickerController*)navigationController;
         
-        if(![cameraPicker.mediaTypes containsObject:(NSString*) kUTTypeImage]){
+        if(![cameraPicker.mediaTypes containsObject:(NSString*)kUTTypeImage]){
             [viewController.navigationItem setTitle:NSLocalizedString(@"Videos title", nil)];
         }
     }
@@ -245,13 +228,12 @@ static NSSet* org_apache_cordova_validArrowDirections;
 
 - (void)popoverControllerDidDismissPopover:(id)popoverController
 {
-    // [ self imagePickerControllerDidCancel:self.pickerController ];	'
     UIPopoverController* pc = (UIPopoverController*)popoverController;
 
     [pc dismissPopoverAnimated:YES];
     pc.delegate = nil;
-    if (self.pickerController && self.pickerController.callbackId && self.pickerController.popoverController) {
-        self.pickerController.popoverController = nil;
+    if (self.pickerController && self.pickerController.callbackId && self.pickerController.pickerPopoverController) {
+        self.pickerController.pickerPopoverController = nil;
         NSString* callbackId = self.pickerController.callbackId;
         CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"];   // error callback expects string ATM
         [self.commandDelegate sendPluginResult:result callbackId:callbackId];
@@ -259,299 +241,218 @@ static NSSet* org_apache_cordova_validArrowDirections;
     self.hasPendingOperation = NO;
 }
 
-- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
+- (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPictureOptions*)options
 {
-    CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
-
-    if (cameraPicker.popoverSupported && (cameraPicker.popoverController != nil)) {
-        [cameraPicker.popoverController dismissPopoverAnimated:YES];
-        cameraPicker.popoverController.delegate = nil;
-        cameraPicker.popoverController = nil;
-    } else {
-        [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-    }
-
-    CDVPluginResult* result = nil;
-
-    NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
-    // IMAGE TYPE
-    if ([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
-        if (cameraPicker.returnType == DestinationTypeNativeUri) {
-            NSString* nativeUri = [(NSURL*)[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
-            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
-        } else {
-            // get the image
-            UIImage* image = nil;
-            if (cameraPicker.allowsEditing && [info objectForKey:UIImagePickerControllerEditedImage]) {
-                image = [info objectForKey:UIImagePickerControllerEditedImage];
-            } else {
-                image = [info objectForKey:UIImagePickerControllerOriginalImage];
-            }
-
-            if (cameraPicker.correctOrientation) {
-                image = [self imageCorrectedForCaptureOrientation:image];
-            }
-
-            UIImage* scaledImage = nil;
-
-            if ((cameraPicker.targetSize.width > 0) && (cameraPicker.targetSize.height > 0)) {
-                // if cropToSize, resize image and crop to target size, otherwise resize to fit target without cropping
-                if (cameraPicker.cropToSize) {
-                    scaledImage = [self imageByScalingAndCroppingForSize:image toSize:cameraPicker.targetSize];
-                } else {
-                    scaledImage = [self imageByScalingNotCroppingForSize:image toSize:cameraPicker.targetSize];
-                }
-            }
-
-            NSData* data = nil;
-            // returnedImage is the image that is returned to caller and (optionally) saved to photo album
-            UIImage* returnedImage = (scaledImage == nil ? image : scaledImage);
-
-            if (cameraPicker.encodingType == EncodingTypePNG) {
-                data = UIImagePNGRepresentation(returnedImage);
-            } else if ((cameraPicker.allowsEditing==false) && (cameraPicker.targetSize.width <= 0) && (cameraPicker.targetSize.height <= 0) && (cameraPicker.correctOrientation==false)){
+    NSData* data = nil;
+    
+    switch (options.encodingType) {
+        case EncodingTypePNG:
+            data = UIImagePNGRepresentation(image);
+            break;
+        case EncodingTypeJPEG:
+        {
+            if ((options.allowsEditing == NO) && (options.targetSize.width <= 0) && (options.targetSize.height <= 0) && (options.correctOrientation == NO)){
                 // use image unedited as requested , don't resize
-                data = UIImageJPEGRepresentation(returnedImage, 1.0);
+                data = UIImageJPEGRepresentation(image, 1.0);
             } else {
-                data = UIImageJPEGRepresentation(returnedImage, cameraPicker.quality / 100.0f);
-                
-                if (cameraPicker.usesGeolocation) {
-                    NSDictionary *controllerMetadata = [info objectForKey:@"UIImagePickerControllerMediaMetadata"];
+                if (options.usesGeolocation) {
+                    NSDictionary* controllerMetadata = [info objectForKey:@"UIImagePickerControllerMediaMetadata"];
                     if (controllerMetadata) {
                         self.data = data;
                         self.metadata = [[NSMutableDictionary alloc] init];
                         
-                        NSMutableDictionary *EXIFDictionary = [[controllerMetadata objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy];
-                        if (EXIFDictionary)	[self.metadata setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary];
+                        NSMutableDictionary* EXIFDictionary = [[controllerMetadata objectForKey:(NSString*)kCGImagePropertyExifDictionary]mutableCopy];
+                        if (EXIFDictionary)	{
+                            [self.metadata setObject:EXIFDictionary forKey:(NSString*)kCGImagePropertyExifDictionary];
+                        }
                         
                         if (IsAtLeastiOSVersion(@"8.0")) {
                             [[self locationManager] performSelector:NSSelectorFromString(@"requestWhenInUseAuthorization") withObject:nil afterDelay:0];
                         }
                         [[self locationManager] startUpdatingLocation];
-                        return;
                     }
-                }
-            }
-            
-            if (cameraPicker.saveToPhotoAlbum) {
-                ALAssetsLibrary *library = [ALAssetsLibrary new];
-                [library writeImageToSavedPhotosAlbum:returnedImage.CGImage orientation:(ALAssetOrientation)(returnedImage.imageOrientation) completionBlock:nil];
-            }
-
-            if (cameraPicker.returnType == DestinationTypeFileUri) {
-                // write to temp directory and return URI
-                // get the temp directory path
-                NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
-                NSError* err = nil;
-                NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by apple (vs [NSFileManager defaultManager]) to be threadsafe
-                // generate unique file name
-                NSString* filePath;
-
-                int i = 1;
-                do {
-                    filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, cameraPicker.encodingType == EncodingTypePNG ? @"png":@"jpg"];
-                } while ([fileMgr fileExistsAtPath:filePath]);
-
-                // save file
-                if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
-                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
                 } else {
-                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
+                    data = UIImageJPEGRepresentation(image, [options.quality floatValue] / 100.0f);
                 }
-            } else {
-                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[data base64EncodedString]];
             }
         }
-    }
-    // NOT IMAGE TYPE (MOVIE)
-    else {
-        NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
-        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
-    }
-
-    if (result) {
-        [self.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
-    }
-
-    self.hasPendingOperation = NO;
-    self.pickerController = nil;
+            break;
+        default:
+            break;
+    };
+    
+    return data;
 }
 
-// older api calls newer didFinishPickingMediaWithInfo
-- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo
+- (NSString*)tempFilePath:(NSString*)extension
 {
-    NSDictionary* imageInfo = [NSDictionary dictionaryWithObject:image forKey:UIImagePickerControllerOriginalImage];
-
-    [self imagePickerController:picker didFinishPickingMediaWithInfo:imageInfo];
+    NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
+    NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by Apple (vs [NSFileManager defaultManager]) to be threadsafe
+    NSString* filePath;
+    
+    // generate unique file name
+    int i = 1;
+    do {
+        filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, extension];
+    } while ([fileMgr fileExistsAtPath:filePath]);
+    
+    return filePath;
 }
 
-- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
+- (UIImage*)retrieveImage:(NSDictionary*)info options:(CDVPictureOptions*)options
 {
-    CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
-
-    [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
-
-    CDVPluginResult* result;
-    if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusAuthorized) {
-        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"];   // error callback expects string ATM
+    // get the image
+    UIImage* image = nil;
+    if (options.allowsEditing && [info objectForKey:UIImagePickerControllerEditedImage]) {
+        image = [info objectForKey:UIImagePickerControllerEditedImage];
     } else {
-        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"];   // error callback expects string ATM
+        image = [info objectForKey:UIImagePickerControllerOriginalImage];
     }
     
-    [self.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
-
-    self.hasPendingOperation = NO;
-    self.pickerController = nil;
-}
-
-- (UIImage*)imageByScalingAndCroppingForSize:(UIImage*)anImage toSize:(CGSize)targetSize
-{
-    UIImage* sourceImage = anImage;
-    UIImage* newImage = nil;
-    CGSize imageSize = sourceImage.size;
-    CGFloat width = imageSize.width;
-    CGFloat height = imageSize.height;
-    CGFloat targetWidth = targetSize.width;
-    CGFloat targetHeight = targetSize.height;
-    CGFloat scaleFactor = 0.0;
-    CGFloat scaledWidth = targetWidth;
-    CGFloat scaledHeight = targetHeight;
-    CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
-
-    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
-        CGFloat widthFactor = targetWidth / width;
-        CGFloat heightFactor = targetHeight / height;
-
-        if (widthFactor > heightFactor) {
-            scaleFactor = widthFactor; // scale to fit height
+    if (options.correctOrientation) {
+        image = [image imageCorrectedForCaptureOrientation];
+    }
+    
+    UIImage* scaledImage = nil;
+    
+    if ((options.targetSize.width > 0) && (options.targetSize.height > 0)) {
+        // if cropToSize, resize image and crop to target size, otherwise resize to fit target without cropping
+        if (options.cropToSize) {
+            scaledImage = [image imageByScalingAndCroppingForSize:options.targetSize];
         } else {
-            scaleFactor = heightFactor; // scale to fit width
+            scaledImage = [image imageByScalingNotCroppingForSize:options.targetSize];
         }
-        scaledWidth = width * scaleFactor;
-        scaledHeight = height * scaleFactor;
-
-        // center the image
-        if (widthFactor > heightFactor) {
-            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
-        } else if (widthFactor < heightFactor) {
-            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
-        }
-    }
-
-    UIGraphicsBeginImageContext(targetSize); // this will crop
-
-    CGRect thumbnailRect = CGRectZero;
-    thumbnailRect.origin = thumbnailPoint;
-    thumbnailRect.size.width = scaledWidth;
-    thumbnailRect.size.height = scaledHeight;
-
-    [sourceImage drawInRect:thumbnailRect];
-
-    newImage = UIGraphicsGetImageFromCurrentImageContext();
-    if (newImage == nil) {
-        NSLog(@"could not scale image");
     }
-
-    // pop the context to get back to the default
-    UIGraphicsEndImageContext();
-    return newImage;
+    
+    return (scaledImage == nil ? image : scaledImage);
 }
 
-- (UIImage*)imageCorrectedForCaptureOrientation:(UIImage*)anImage
+- (CDVPluginResult*)resultForImage:(CDVPictureOptions*)options info:(NSDictionary*)info
 {
-    float rotation_radians = 0;
-    bool perpendicular = false;
-
-    switch ([anImage imageOrientation]) {
-        case UIImageOrientationUp :
-            rotation_radians = 0.0;
-            break;
+    CDVPluginResult* result = nil;
+    BOOL saveToPhotoAlbum = options.saveToPhotoAlbum;
+    UIImage* image = nil;
 
-        case UIImageOrientationDown:
-            rotation_radians = M_PI; // don't be scared of radians, if you're reading this, you're good at math
+    switch (options.destinationType) {
+        case DestinationTypeNativeUri:
+        {
+            NSString* nativeUri = [(NSURL*)[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
+            saveToPhotoAlbum = NO;
+        }
             break;
-
-        case UIImageOrientationRight:
-            rotation_radians = M_PI_2;
-            perpendicular = true;
+        case DestinationTypeFileUri:
+        {
+            image = [self retrieveImage:info options:options];
+            NSData* data = [self processImage:image info:info options:options];
+            if (data) {
+                
+                NSString* extension = options.encodingType == EncodingTypePNG? @"png" : @"jpg";
+                NSString* filePath = [self tempFilePath:extension];
+                NSError* err = nil;
+                
+                // save file
+                if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
+                } else {
+                    result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
+                }
+            }
+        }
             break;
-
-        case UIImageOrientationLeft:
-            rotation_radians = -M_PI_2;
-            perpendicular = true;
+        case DestinationTypeDataUrl:
+        {
+            image = [self retrieveImage:info options:options];
+            NSData* data = [self processImage:image info:info options:options];
+            
+            if (data)  {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[data base64EncodedString]];
+            }
+        }
             break;
-
         default:
             break;
+    };
+    
+    if (saveToPhotoAlbum && image) {
+        ALAssetsLibrary* library = [ALAssetsLibrary new];
+        [library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:nil];
     }
+    
+    return result;
+}
 
-    UIGraphicsBeginImageContext(CGSizeMake(anImage.size.width, anImage.size.height));
-    CGContextRef context = UIGraphicsGetCurrentContext();
-
-    // Rotate around the center point
-    CGContextTranslateCTM(context, anImage.size.width / 2, anImage.size.height / 2);
-    CGContextRotateCTM(context, rotation_radians);
-
-    CGContextScaleCTM(context, 1.0, -1.0);
-    float width = perpendicular ? anImage.size.height : anImage.size.width;
-    float height = perpendicular ? anImage.size.width : anImage.size.height;
-    CGContextDrawImage(context, CGRectMake(-width / 2, -height / 2, width, height), [anImage CGImage]);
-
-    // Move the origin back since the rotation might've change it (if its 90 degrees)
-    if (perpendicular) {
-        CGContextTranslateCTM(context, -anImage.size.height / 2, -anImage.size.width / 2);
-    }
-
-    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-    return newImage;
+- (CDVPluginResult*)resultForVideo:(NSDictionary*)info
+{
+    NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
 }
 
-- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)anImage toSize:(CGSize)frameSize
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
 {
-    UIImage* sourceImage = anImage;
-    UIImage* newImage = nil;
-    CGSize imageSize = sourceImage.size;
-    CGFloat width = imageSize.width;
-    CGFloat height = imageSize.height;
-    CGFloat targetWidth = frameSize.width;
-    CGFloat targetHeight = frameSize.height;
-    CGFloat scaleFactor = 0.0;
-    CGSize scaledSize = frameSize;
-
-    if (CGSizeEqualToSize(imageSize, frameSize) == NO) {
-        CGFloat widthFactor = targetWidth / width;
-        CGFloat heightFactor = targetHeight / height;
-
-        // opposite comparison to imageByScalingAndCroppingForSize in order to contain the image within the given bounds
-        if (widthFactor > heightFactor) {
-            scaleFactor = heightFactor; // scale to fit height
-        } else {
-            scaleFactor = widthFactor; // scale to fit width
+    __weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
+    __weak CDVCamera* weakSelf = self;
+    
+    dispatch_block_t invoke = ^(void) {
+        __block CDVPluginResult* result = nil;
+        
+        NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
+        if ([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
+            result = [self resultForImage:cameraPicker.pictureOptions info:info];
+        }
+        else {
+            result = [self resultForVideo:info];
         }
-        scaledSize = CGSizeMake(MIN(width * scaleFactor, targetWidth), MIN(height * scaleFactor, targetHeight));
+        
+        if (result) {
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
+            weakSelf.hasPendingOperation = NO;
+            weakSelf.pickerController = nil;
+        }
+    };
+    
+    if (cameraPicker.pictureOptions.popoverSupported && (cameraPicker.pickerPopoverController != nil)) {
+        [cameraPicker.pickerPopoverController dismissPopoverAnimated:YES];
+        cameraPicker.pickerPopoverController.delegate = nil;
+        cameraPicker.pickerPopoverController = nil;
+        invoke();
+    } else {
+        [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:invoke];
     }
+}
 
-    // If the pixels are floats, it causes a white line in iOS8 and probably other versions too
-    scaledSize.width = (int)scaledSize.width;
-    scaledSize.height = (int)scaledSize.height;
-    
-    UIGraphicsBeginImageContext(scaledSize); // this will resize
+// older api calls newer didFinishPickingMediaWithInfo
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo
+{
+    NSDictionary* imageInfo = [NSDictionary dictionaryWithObject:image forKey:UIImagePickerControllerOriginalImage];
 
-    [sourceImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)];
+    [self imagePickerController:picker didFinishPickingMediaWithInfo:imageInfo];
+}
 
-    newImage = UIGraphicsGetImageFromCurrentImageContext();
-    if (newImage == nil) {
-        NSLog(@"could not scale image");
-    }
+- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
+{
+    __weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
+    __weak CDVCamera* weakSelf = self;
+    
+    dispatch_block_t invoke = ^ (void) {
+        CDVPluginResult* result;
+        if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusAuthorized) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"];
+        } else {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"];
+        }
+        
+        [weakSelf.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
+        
+        weakSelf.hasPendingOperation = NO;
+        weakSelf.pickerController = nil;
+    };
 
-    // pop the context to get back to the default
-    UIGraphicsEndImageContext();
-    return newImage;
+    [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:invoke];
 }
 
-- (CLLocationManager *)locationManager {
-    
+- (CLLocationManager*)locationManager
+{
 	if (locationManager != nil) {
 		return locationManager;
 	}
@@ -565,70 +466,76 @@ static NSSet* org_apache_cordova_validArrowDirections;
 
 - (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation
 {
-	if (locationManager != nil) {
-		[self.locationManager stopUpdatingLocation];
-		self.locationManager = nil;
-        
-		NSMutableDictionary *GPSDictionary = [[NSMutableDictionary dictionary] init];
-        
-		CLLocationDegrees latitude  = newLocation.coordinate.latitude;
-		CLLocationDegrees longitude = newLocation.coordinate.longitude;
-        
-		// latitude
-		if (latitude < 0.0) {
-			latitude = latitude * -1.0f;
-			[GPSDictionary setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
-		} else {
-			[GPSDictionary setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
-		}
-		[GPSDictionary setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString*)kCGImagePropertyGPSLatitude];
-        
-		// longitude
-		if (longitude < 0.0) {
-			longitude = longitude * -1.0f;
-			[GPSDictionary setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
-		}
-		else {
-			[GPSDictionary setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
-		}
-		[GPSDictionary setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString*)kCGImagePropertyGPSLongitude];
-        
-		// altitude
-        CGFloat altitude = newLocation.altitude;
-        if (!isnan(altitude)){
-			if (altitude < 0) {
-				altitude = -altitude;
-				[GPSDictionary setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
-			} else {
-				[GPSDictionary setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
-			}
-			[GPSDictionary setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude];
+    if (locationManager == nil) {
+        return;
+    }
+    
+    [self.locationManager stopUpdatingLocation];
+    self.locationManager = nil;
+    
+    NSMutableDictionary *GPSDictionary = [[NSMutableDictionary dictionary] init];
+    
+    CLLocationDegrees latitude  = newLocation.coordinate.latitude;
+    CLLocationDegrees longitude = newLocation.coordinate.longitude;
+    
+    // latitude
+    if (latitude < 0.0) {
+        latitude = latitude * -1.0f;
+        [GPSDictionary setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
+    } else {
+        [GPSDictionary setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
+    }
+    [GPSDictionary setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString*)kCGImagePropertyGPSLatitude];
+    
+    // longitude
+    if (longitude < 0.0) {
+        longitude = longitude * -1.0f;
+        [GPSDictionary setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
+    }
+    else {
+        [GPSDictionary setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
+    }
+    [GPSDictionary setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString*)kCGImagePropertyGPSLongitude];
+    
+    // altitude
+    CGFloat altitude = newLocation.altitude;
+    if (!isnan(altitude)){
+        if (altitude < 0) {
+            altitude = -altitude;
+            [GPSDictionary setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
+        } else {
+            [GPSDictionary setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
         }
-        
-        // Time and date
-        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
-        [formatter setDateFormat:@"HH:mm:ss.SSSSSS"];
-        [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
-        [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp];
-        [formatter setDateFormat:@"yyyy:MM:dd"];
-        [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp];
-        
-		[self.metadata setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
- 		[self imagePickerControllerReturnImageResult];
-	}
+        [GPSDictionary setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude];
+    }
+    
+    // Time and date
+    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+    [formatter setDateFormat:@"HH:mm:ss.SSSSSS"];
+    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
+    [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp];
+    [formatter setDateFormat:@"yyyy:MM:dd"];
+    [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp];
+    
+    [self.metadata setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
+    [self imagePickerControllerReturnImageResult];
 }
 
-- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
-	if (locationManager != nil) {
-		[self.locationManager stopUpdatingLocation];
-		self.locationManager = nil;
-        
-		[self imagePickerControllerReturnImageResult];
-	}
+- (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error
+{
+    if (locationManager == nil) {
+        return;
+    }
+
+    [self.locationManager stopUpdatingLocation];
+    self.locationManager = nil;
+    
+    [self imagePickerControllerReturnImageResult];
 }
 
 - (void)imagePickerControllerReturnImageResult
 {
+    CDVPictureOptions* options = self.pickerController.pictureOptions;
     CDVPluginResult* result = nil;
     
     if (self.metadata) {
@@ -643,39 +550,31 @@ static NSSet* org_apache_cordova_validArrowDirections;
         CFRelease(destinationImage);
     }
     
-    if (self.pickerController.saveToPhotoAlbum) {
-        ALAssetsLibrary *library = [ALAssetsLibrary new];
-        [library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
-    }
-    
-    if (self.pickerController.returnType == DestinationTypeFileUri) {
-        // write to temp directory and return URI
-        // get the temp directory path
-        NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
-        NSError* err = nil;
-        NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by apple (vs [NSFileManager defaultManager]) to be threadsafe
-        // generate unique file name
-        NSString* filePath;
-        
-        int i = 1;
-        do {
-            filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, self.pickerController.encodingType == EncodingTypePNG ? @"png":@"jpg"];
-        } while ([fileMgr fileExistsAtPath:filePath]);
-        
-        // save file
-        if (![self.data writeToFile:filePath options:NSAtomicWrite error:&err]) {
-            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
+    switch (options.destinationType) {
+        case DestinationTypeFileUri:
+        {
+            NSError* err = nil;
+            NSString* extension = self.pickerController.pictureOptions.encodingType == EncodingTypePNG ? @"png":@"jpg";
+            NSString* filePath = [self tempFilePath:extension];
+            
+            // save file
+            if (![self.data writeToFile:filePath options:NSAtomicWrite error:&err]) {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
+            }
+            else {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
+            }
         }
-        else {
-            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
+            break;
+        case DestinationTypeDataUrl:
+        {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[self.data base64EncodedString]];
         }
-    }
-    else {
-        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[self.data base64EncodedString]];
-    }
-    if (result) {
-        [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
-    }
+            break;
+        case DestinationTypeNativeUri:
+        default:
+            break;
+    };
     
     if (result) {
         [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
@@ -685,33 +584,29 @@ static NSSet* org_apache_cordova_validArrowDirections;
     self.pickerController = nil;
     self.data = nil;
     self.metadata = nil;
+    
+    if (options.saveToPhotoAlbum) {
+        ALAssetsLibrary *library = [ALAssetsLibrary new];
+        [library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
+    }
 }
 
 @end
 
 @implementation CDVCameraPicker
 
-@synthesize quality, postUrl;
-@synthesize returnType;
-@synthesize callbackId;
-@synthesize popoverController;
-@synthesize targetSize;
-@synthesize correctOrientation;
-@synthesize saveToPhotoAlbum;
-@synthesize encodingType;
-@synthesize cropToSize;
-@synthesize webView;
-@synthesize popoverSupported;
-
-- (BOOL)prefersStatusBarHidden {
+- (BOOL)prefersStatusBarHidden
+{
     return YES;
 }
 
-- (UIViewController*)childViewControllerForStatusBarHidden {
+- (UIViewController*)childViewControllerForStatusBarHidden
+{
     return nil;
 }
     
-- (void)viewWillAppear:(BOOL)animated {
+- (void)viewWillAppear:(BOOL)animated
+{
     SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
     if ([self respondsToSelector:sel]) {
         [self performSelector:sel withObject:nil afterDelay:0];
@@ -720,4 +615,26 @@ static NSSet* org_apache_cordova_validArrowDirections;
     [super viewWillAppear:animated];
 }
 
++ (instancetype) createFromPictureOptions:(CDVPictureOptions*)pictureOptions;
+{
+    CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
+    cameraPicker.pictureOptions = pictureOptions;
+    cameraPicker.sourceType = pictureOptions.sourceType;
+    cameraPicker.allowsEditing = pictureOptions.allowsEditing;
+    
+    if (cameraPicker.sourceType == UIImagePickerControllerSourceTypeCamera) {
+        // We only allow taking pictures (no video) in this API.
+        cameraPicker.mediaTypes = @[(NSString*)kUTTypeImage];
+        // We can only set the camera device if we're actually using the camera.
+        cameraPicker.cameraDevice = pictureOptions.cameraDirection;
+    } else if (pictureOptions.mediaType == MediaTypeAll) {
+        cameraPicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:cameraPicker.sourceType];
+    } else {
+        NSArray* mediaArray = @[(NSString*)(pictureOptions.mediaType == MediaTypeVideo ? kUTTypeMovie : kUTTypeImage)];
+        cameraPicker.mediaTypes = mediaArray;
+    }
+    
+    return cameraPicker;
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/35c653d2/src/ios/UIImage+CropScaleOrientation.h
----------------------------------------------------------------------
diff --git a/src/ios/UIImage+CropScaleOrientation.h b/src/ios/UIImage+CropScaleOrientation.h
new file mode 100644
index 0000000..0f7fca5
--- /dev/null
+++ b/src/ios/UIImage+CropScaleOrientation.h
@@ -0,0 +1,28 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface UIImage (CropScaleOrientation)
+
+- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize;
+- (UIImage*)imageCorrectedForCaptureOrientation;
+- (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize;
+
+@end
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/35c653d2/src/ios/UIImage+CropScaleOrientation.m
----------------------------------------------------------------------
diff --git a/src/ios/UIImage+CropScaleOrientation.m b/src/ios/UIImage+CropScaleOrientation.m
new file mode 100644
index 0000000..3ab3ad5
--- /dev/null
+++ b/src/ios/UIImage+CropScaleOrientation.m
@@ -0,0 +1,170 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "UIImage+CropScaleOrientation.h"
+
+@implementation UIImage (CropScaleOrientation)
+
+- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
+{
+    UIImage* sourceImage = self;
+    UIImage* newImage = nil;
+    CGSize imageSize = sourceImage.size;
+    CGFloat width = imageSize.width;
+    CGFloat height = imageSize.height;
+    CGFloat targetWidth = targetSize.width;
+    CGFloat targetHeight = targetSize.height;
+    CGFloat scaleFactor = 0.0;
+    CGFloat scaledWidth = targetWidth;
+    CGFloat scaledHeight = targetHeight;
+    CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
+    
+    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
+        CGFloat widthFactor = targetWidth / width;
+        CGFloat heightFactor = targetHeight / height;
+        
+        if (widthFactor > heightFactor) {
+            scaleFactor = widthFactor; // scale to fit height
+        } else {
+            scaleFactor = heightFactor; // scale to fit width
+        }
+        scaledWidth = width * scaleFactor;
+        scaledHeight = height * scaleFactor;
+        
+        // center the image
+        if (widthFactor > heightFactor) {
+            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
+        } else if (widthFactor < heightFactor) {
+            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
+        }
+    }
+    
+    UIGraphicsBeginImageContext(targetSize); // this will crop
+    
+    CGRect thumbnailRect = CGRectZero;
+    thumbnailRect.origin = thumbnailPoint;
+    thumbnailRect.size.width = scaledWidth;
+    thumbnailRect.size.height = scaledHeight;
+    
+    [sourceImage drawInRect:thumbnailRect];
+    
+    newImage = UIGraphicsGetImageFromCurrentImageContext();
+    if (newImage == nil) {
+        NSLog(@"could not scale image");
+    }
+    
+    // pop the context to get back to the default
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+- (UIImage*)imageCorrectedForCaptureOrientation
+{
+    float rotation_radians = 0;
+    bool perpendicular = false;
+    
+    switch ([self imageOrientation]) {
+        case UIImageOrientationUp :
+            rotation_radians = 0.0;
+            break;
+            
+        case UIImageOrientationDown:
+            rotation_radians = M_PI; // don't be scared of radians, if you're reading this, you're good at math
+            break;
+            
+        case UIImageOrientationRight:
+            rotation_radians = M_PI_2;
+            perpendicular = true;
+            break;
+            
+        case UIImageOrientationLeft:
+            rotation_radians = -M_PI_2;
+            perpendicular = true;
+            break;
+            
+        default:
+            break;
+    }
+    
+    UIGraphicsBeginImageContext(CGSizeMake(self.size.width, self.size.height));
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    // Rotate around the center point
+    CGContextTranslateCTM(context, self.size.width / 2, self.size.height / 2);
+    CGContextRotateCTM(context, rotation_radians);
+    
+    CGContextScaleCTM(context, 1.0, -1.0);
+    float width = perpendicular ? self.size.height : self.size.width;
+    float height = perpendicular ? self.size.width : self.size.height;
+    CGContextDrawImage(context, CGRectMake(-width / 2, -height / 2, width, height), [self CGImage]);
+    
+    // Move the origin back since the rotation might've change it (if its 90 degrees)
+    if (perpendicular) {
+        CGContextTranslateCTM(context, -self.size.height / 2, -self.size.width / 2);
+    }
+    
+    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+- (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize
+{
+    UIImage* sourceImage = self;
+    UIImage* newImage = nil;
+    CGSize imageSize = sourceImage.size;
+    CGFloat width = imageSize.width;
+    CGFloat height = imageSize.height;
+    CGFloat targetWidth = targetSize.width;
+    CGFloat targetHeight = targetSize.height;
+    CGFloat scaleFactor = 0.0;
+    CGSize scaledSize = targetSize;
+    
+    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
+        CGFloat widthFactor = targetWidth / width;
+        CGFloat heightFactor = targetHeight / height;
+        
+        // opposite comparison to imageByScalingAndCroppingForSize in order to contain the image within the given bounds
+        if (widthFactor > heightFactor) {
+            scaleFactor = heightFactor; // scale to fit height
+        } else {
+            scaleFactor = widthFactor; // scale to fit width
+        }
+        scaledSize = CGSizeMake(MIN(width * scaleFactor, targetWidth), MIN(height * scaleFactor, targetHeight));
+    }
+    
+    // If the pixels are floats, it causes a white line in iOS8 and probably other versions too
+    scaledSize.width = (int)scaledSize.width;
+    scaledSize.height = (int)scaledSize.height;
+    
+    UIGraphicsBeginImageContext(scaledSize); // this will resize
+    
+    [sourceImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)];
+    
+    newImage = UIGraphicsGetImageFromCurrentImageContext();
+    if (newImage == nil) {
+        NSLog(@"could not scale image");
+    }
+    
+    // pop the context to get back to the default
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+@end


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


Mime
View raw message