mirror of
https://github.com/apache/cordova-plugin-camera.git
synced 2025-03-16 14:01:04 +08:00
CB-7937 - Re-factor iOS Camera plugin so that it is testable (closes #52)
Signed-off-by: Shazron Abdullah <shazron@apache.org>
This commit is contained in:
parent
3ab650bdc9
commit
35c653d24d
@ -133,6 +133,8 @@
|
|||||||
<clobbers target="CameraPopoverHandle" />
|
<clobbers target="CameraPopoverHandle" />
|
||||||
</js-module>
|
</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" />
|
<header-file src="src/ios/CDVCamera.h" />
|
||||||
<source-file src="src/ios/CDVCamera.m" />
|
<source-file src="src/ios/CDVCamera.m" />
|
||||||
<header-file src="src/ios/CDVJpegHeaderWriter.h" />
|
<header-file src="src/ios/CDVJpegHeaderWriter.h" />
|
||||||
|
@ -42,22 +42,39 @@ enum CDVMediaType {
|
|||||||
};
|
};
|
||||||
typedef NSUInteger CDVMediaType;
|
typedef NSUInteger CDVMediaType;
|
||||||
|
|
||||||
@interface CDVCameraPicker : UIImagePickerController
|
@interface CDVPictureOptions : NSObject
|
||||||
{}
|
|
||||||
|
|
||||||
@property (assign) NSInteger quality;
|
@property (strong) NSNumber* quality;
|
||||||
@property (copy) NSString* callbackId;
|
@property (assign) CDVDestinationType destinationType;
|
||||||
@property (copy) NSString* postUrl;
|
@property (assign) UIImagePickerControllerSourceType sourceType;
|
||||||
@property (nonatomic) enum CDVDestinationType returnType;
|
|
||||||
@property (nonatomic) enum CDVEncodingType encodingType;
|
|
||||||
@property (strong) UIPopoverController* popoverController;
|
|
||||||
@property (assign) CGSize targetSize;
|
@property (assign) CGSize targetSize;
|
||||||
@property (assign) bool correctOrientation;
|
@property (assign) CDVEncodingType encodingType;
|
||||||
@property (assign) bool saveToPhotoAlbum;
|
@property (assign) CDVMediaType mediaType;
|
||||||
@property (assign) bool cropToSize;
|
@property (assign) BOOL allowsEditing;
|
||||||
@property (strong) UIView* webView;
|
@property (assign) BOOL correctOrientation;
|
||||||
|
@property (assign) BOOL saveToPhotoAlbum;
|
||||||
|
@property (strong) NSDictionary* popoverOptions;
|
||||||
|
@property (assign) UIImagePickerControllerCameraDevice cameraDirection;
|
||||||
|
|
||||||
@property (assign) BOOL popoverSupported;
|
@property (assign) BOOL popoverSupported;
|
||||||
@property (assign) BOOL usesGeolocation;
|
@property (assign) BOOL usesGeolocation;
|
||||||
|
@property (assign) BOOL cropToSize;
|
||||||
|
|
||||||
|
+ (instancetype) createFromTakePictureArguments:(NSArray*)arguments;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface CDVCameraPicker : UIImagePickerController
|
||||||
|
|
||||||
|
@property (strong) CDVPictureOptions* pictureOptions;
|
||||||
|
|
||||||
|
@property (copy) NSString* callbackId;
|
||||||
|
@property (copy) NSString* postUrl;
|
||||||
|
@property (strong) UIPopoverController* pickerPopoverController;
|
||||||
|
@property (assign) BOOL cropToSize;
|
||||||
|
@property (strong) UIView* webView;
|
||||||
|
|
||||||
|
+ (instancetype) createFromPictureOptions:(CDVPictureOptions*)options;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@ -92,9 +109,6 @@ typedef NSUInteger CDVMediaType;
|
|||||||
- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
|
- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
|
||||||
- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker;
|
- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker;
|
||||||
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
|
- (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 didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation;
|
||||||
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
|
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#import "CDVCamera.h"
|
#import "CDVCamera.h"
|
||||||
#import "CDVJpegHeaderWriter.h"
|
#import "CDVJpegHeaderWriter.h"
|
||||||
|
#import "UIImage+CropScaleOrientation.h"
|
||||||
#import <Cordova/NSArray+Comparisons.h>
|
#import <Cordova/NSArray+Comparisons.h>
|
||||||
#import <Cordova/NSData+Base64.h>
|
#import <Cordova/NSData+Base64.h>
|
||||||
#import <Cordova/NSDictionary+Extensions.h>
|
#import <Cordova/NSDictionary+Extensions.h>
|
||||||
@ -34,6 +35,40 @@
|
|||||||
|
|
||||||
static NSSet* org_apache_cordova_validArrowDirections;
|
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 ()
|
@interface CDVCamera ()
|
||||||
|
|
||||||
@property (readwrite, assign) BOOL hasPendingOperation;
|
@property (readwrite, assign) BOOL hasPendingOperation;
|
||||||
@ -49,7 +84,6 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
|
|
||||||
@synthesize hasPendingOperation, pickerController, locationManager;
|
@synthesize hasPendingOperation, pickerController, locationManager;
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)usesGeolocation
|
- (BOOL)usesGeolocation
|
||||||
{
|
{
|
||||||
id useGeo = [self.commandDelegate.settings objectForKey:[@"CameraUsesGeolocation" lowercaseString]];
|
id useGeo = [self.commandDelegate.settings objectForKey:[@"CameraUsesGeolocation" lowercaseString]];
|
||||||
@ -62,106 +96,55 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
|
(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
|
- (void)takePicture:(CDVInvokedUrlCommand*)command
|
||||||
{
|
{
|
||||||
NSString* callbackId = command.callbackId;
|
|
||||||
NSArray* arguments = command.arguments;
|
|
||||||
|
|
||||||
self.hasPendingOperation = YES;
|
self.hasPendingOperation = YES;
|
||||||
|
|
||||||
|
__weak CDVCamera* weakSelf = self;
|
||||||
|
|
||||||
NSString* sourceTypeString = [arguments objectAtIndex:2];
|
[self.commandDelegate runInBackground:^{
|
||||||
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; // default
|
|
||||||
if (sourceTypeString != nil) {
|
CDVPictureOptions* pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command.arguments];
|
||||||
sourceType = (UIImagePickerControllerSourceType)[sourceTypeString intValue];
|
pictureOptions.popoverSupported = [self popoverSupported];
|
||||||
}
|
pictureOptions.usesGeolocation = [self usesGeolocation];
|
||||||
|
pictureOptions.cropToSize = NO;
|
||||||
bool hasCamera = [UIImagePickerController isSourceTypeAvailable:sourceType];
|
|
||||||
if (!hasCamera) {
|
BOOL hasCamera = [UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType];
|
||||||
NSLog(@"Camera.getPicture: source type %lu not available.", (unsigned long)sourceType);
|
if (!hasCamera) {
|
||||||
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no camera available"];
|
NSLog(@"Camera.getPicture: source type %lu not available.", (unsigned long)pictureOptions.sourceType);
|
||||||
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No camera available"];
|
||||||
return;
|
[weakSelf.commandDelegate sendPluginResult:result callbackId:command.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([self popoverSupported] && (sourceType != UIImagePickerControllerSourceTypeCamera)) {
|
|
||||||
if (cameraPicker.popoverController == nil) {
|
|
||||||
cameraPicker.popoverController = [[NSClassFromString(@"UIPopoverController")alloc] initWithContentViewController:cameraPicker];
|
|
||||||
}
|
}
|
||||||
NSDictionary* options = [command.arguments objectAtIndex:10 withDefault:nil];
|
|
||||||
[self displayPopover:options];
|
// If a popover is already open, close it; we only want one at a time.
|
||||||
} else {
|
if (([[weakSelf pickerController] pickerPopoverController] != nil) && [[[weakSelf pickerController] pickerPopoverController] isPopoverVisible]) {
|
||||||
[self.viewController presentViewController:cameraPicker animated:YES completion:nil];
|
[[[weakSelf pickerController] pickerPopoverController] dismissPopoverAnimated:YES];
|
||||||
}
|
[[[weakSelf pickerController] pickerPopoverController] setDelegate:nil];
|
||||||
self.hasPendingOperation = NO;
|
[[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;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
[weakSelf.viewController presentViewController:cameraPicker animated:YES completion:^{
|
||||||
|
weakSelf.hasPendingOperation = NO;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)repositionPopover:(CDVInvokedUrlCommand*)command
|
- (void)repositionPopover:(CDVInvokedUrlCommand*)command
|
||||||
@ -190,8 +173,8 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[[self pickerController] popoverController] setDelegate:self];
|
[[[self pickerController] pickerPopoverController] setDelegate:self];
|
||||||
[[[self pickerController] popoverController] presentPopoverFromRect:CGRectMake(x, y, width, height)
|
[[[self pickerController] pickerPopoverController] presentPopoverFromRect:CGRectMake(x, y, width, height)
|
||||||
inView:[self.webView superview]
|
inView:[self.webView superview]
|
||||||
permittedArrowDirections:arrowDirection
|
permittedArrowDirections:arrowDirection
|
||||||
animated:YES];
|
animated:YES];
|
||||||
@ -200,9 +183,9 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||||
{
|
{
|
||||||
if([navigationController isKindOfClass:[UIImagePickerController class]]){
|
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)];
|
[viewController.navigationItem setTitle:NSLocalizedString(@"Videos title", nil)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,13 +228,12 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
|
|
||||||
- (void)popoverControllerDidDismissPopover:(id)popoverController
|
- (void)popoverControllerDidDismissPopover:(id)popoverController
|
||||||
{
|
{
|
||||||
// [ self imagePickerControllerDidCancel:self.pickerController ]; '
|
|
||||||
UIPopoverController* pc = (UIPopoverController*)popoverController;
|
UIPopoverController* pc = (UIPopoverController*)popoverController;
|
||||||
|
|
||||||
[pc dismissPopoverAnimated:YES];
|
[pc dismissPopoverAnimated:YES];
|
||||||
pc.delegate = nil;
|
pc.delegate = nil;
|
||||||
if (self.pickerController && self.pickerController.callbackId && self.pickerController.popoverController) {
|
if (self.pickerController && self.pickerController.callbackId && self.pickerController.pickerPopoverController) {
|
||||||
self.pickerController.popoverController = nil;
|
self.pickerController.pickerPopoverController = nil;
|
||||||
NSString* callbackId = self.pickerController.callbackId;
|
NSString* callbackId = self.pickerController.callbackId;
|
||||||
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"]; // error callback expects string ATM
|
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"]; // error callback expects string ATM
|
||||||
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
|
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
|
||||||
@ -259,122 +241,184 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
self.hasPendingOperation = NO;
|
self.hasPendingOperation = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
|
- (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPictureOptions*)options
|
||||||
{
|
{
|
||||||
CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
|
NSData* data = nil;
|
||||||
|
|
||||||
if (cameraPicker.popoverSupported && (cameraPicker.popoverController != nil)) {
|
switch (options.encodingType) {
|
||||||
[cameraPicker.popoverController dismissPopoverAnimated:YES];
|
case EncodingTypePNG:
|
||||||
cameraPicker.popoverController.delegate = nil;
|
data = UIImagePNGRepresentation(image);
|
||||||
cameraPicker.popoverController = nil;
|
break;
|
||||||
} else {
|
case EncodingTypeJPEG:
|
||||||
[[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
|
{
|
||||||
}
|
if ((options.allowsEditing == NO) && (options.targetSize.width <= 0) && (options.targetSize.height <= 0) && (options.correctOrientation == NO)){
|
||||||
|
|
||||||
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)){
|
|
||||||
// use image unedited as requested , don't resize
|
// use image unedited as requested , don't resize
|
||||||
data = UIImageJPEGRepresentation(returnedImage, 1.0);
|
data = UIImageJPEGRepresentation(image, 1.0);
|
||||||
} else {
|
} else {
|
||||||
data = UIImageJPEGRepresentation(returnedImage, cameraPicker.quality / 100.0f);
|
if (options.usesGeolocation) {
|
||||||
|
NSDictionary* controllerMetadata = [info objectForKey:@"UIImagePickerControllerMediaMetadata"];
|
||||||
if (cameraPicker.usesGeolocation) {
|
|
||||||
NSDictionary *controllerMetadata = [info objectForKey:@"UIImagePickerControllerMediaMetadata"];
|
|
||||||
if (controllerMetadata) {
|
if (controllerMetadata) {
|
||||||
self.data = data;
|
self.data = data;
|
||||||
self.metadata = [[NSMutableDictionary alloc] init];
|
self.metadata = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
NSMutableDictionary *EXIFDictionary = [[controllerMetadata objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy];
|
NSMutableDictionary* EXIFDictionary = [[controllerMetadata objectForKey:(NSString*)kCGImagePropertyExifDictionary]mutableCopy];
|
||||||
if (EXIFDictionary) [self.metadata setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary];
|
if (EXIFDictionary) {
|
||||||
|
[self.metadata setObject:EXIFDictionary forKey:(NSString*)kCGImagePropertyExifDictionary];
|
||||||
|
}
|
||||||
|
|
||||||
if (IsAtLeastiOSVersion(@"8.0")) {
|
if (IsAtLeastiOSVersion(@"8.0")) {
|
||||||
[[self locationManager] performSelector:NSSelectorFromString(@"requestWhenInUseAuthorization") withObject:nil afterDelay:0];
|
[[self locationManager] performSelector:NSSelectorFromString(@"requestWhenInUseAuthorization") withObject:nil afterDelay:0];
|
||||||
}
|
}
|
||||||
[[self locationManager] startUpdatingLocation];
|
[[self locationManager] startUpdatingLocation];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
data = UIImageJPEGRepresentation(image, [options.quality floatValue] / 100.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (cameraPicker.saveToPhotoAlbum) {
|
break;
|
||||||
ALAssetsLibrary *library = [ALAssetsLibrary new];
|
default:
|
||||||
[library writeImageToSavedPhotosAlbum:returnedImage.CGImage orientation:(ALAssetOrientation)(returnedImage.imageOrientation) completionBlock:nil];
|
break;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
if (cameraPicker.returnType == DestinationTypeFileUri) {
|
- (NSString*)tempFilePath:(NSString*)extension
|
||||||
// write to temp directory and return URI
|
{
|
||||||
// get the temp directory path
|
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImage*)retrieveImage:(NSDictionary*)info options:(CDVPictureOptions*)options
|
||||||
|
{
|
||||||
|
// get the image
|
||||||
|
UIImage* image = nil;
|
||||||
|
if (options.allowsEditing && [info objectForKey:UIImagePickerControllerEditedImage]) {
|
||||||
|
image = [info objectForKey:UIImagePickerControllerEditedImage];
|
||||||
|
} else {
|
||||||
|
image = [info objectForKey:UIImagePickerControllerOriginalImage];
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
scaledImage = [image imageByScalingNotCroppingForSize:options.targetSize];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (scaledImage == nil ? image : scaledImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CDVPluginResult*)resultForImage:(CDVPictureOptions*)options info:(NSDictionary*)info
|
||||||
|
{
|
||||||
|
CDVPluginResult* result = nil;
|
||||||
|
BOOL saveToPhotoAlbum = options.saveToPhotoAlbum;
|
||||||
|
UIImage* image = nil;
|
||||||
|
|
||||||
|
switch (options.destinationType) {
|
||||||
|
case DestinationTypeNativeUri:
|
||||||
|
{
|
||||||
|
NSString* nativeUri = [(NSURL*)[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
|
||||||
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
|
||||||
|
saveToPhotoAlbum = NO;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
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;
|
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
|
// save file
|
||||||
if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
|
if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
|
||||||
} else {
|
} else {
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
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]];
|
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];
|
||||||
}
|
}
|
||||||
// NOT IMAGE TYPE (MOVIE)
|
|
||||||
else {
|
return result;
|
||||||
NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
|
}
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result) {
|
- (CDVPluginResult*)resultForVideo:(NSDictionary*)info
|
||||||
[self.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
|
{
|
||||||
}
|
NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
|
||||||
|
return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
|
||||||
|
}
|
||||||
|
|
||||||
self.hasPendingOperation = NO;
|
- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
|
||||||
self.pickerController = nil;
|
{
|
||||||
|
__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];
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// older api calls newer didFinishPickingMediaWithInfo
|
// older api calls newer didFinishPickingMediaWithInfo
|
||||||
@ -387,171 +431,28 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
|
|
||||||
- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
|
- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
|
||||||
{
|
{
|
||||||
CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
|
__weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
|
||||||
|
__weak CDVCamera* weakSelf = self;
|
||||||
[[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
|
|
||||||
} else {
|
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"]; // error callback expects string ATM
|
|
||||||
}
|
|
||||||
|
|
||||||
[self.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
|
dispatch_block_t invoke = ^ (void) {
|
||||||
|
CDVPluginResult* result;
|
||||||
self.hasPendingOperation = NO;
|
if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusAuthorized) {
|
||||||
self.pickerController = nil;
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"];
|
||||||
}
|
|
||||||
|
|
||||||
- (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
|
|
||||||
} else {
|
} else {
|
||||||
scaleFactor = heightFactor; // scale to fit width
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"];
|
||||||
}
|
}
|
||||||
scaledWidth = width * scaleFactor;
|
|
||||||
scaledHeight = height * scaleFactor;
|
[weakSelf.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
|
||||||
|
|
||||||
|
weakSelf.hasPendingOperation = NO;
|
||||||
|
weakSelf.pickerController = nil;
|
||||||
|
};
|
||||||
|
|
||||||
// center the image
|
[[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:invoke];
|
||||||
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:(UIImage*)anImage
|
- (CLLocationManager*)locationManager
|
||||||
{
|
{
|
||||||
float rotation_radians = 0;
|
|
||||||
bool perpendicular = false;
|
|
||||||
|
|
||||||
switch ([anImage 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(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)anImage toSize:(CGSize)frameSize
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CLLocationManager *)locationManager {
|
|
||||||
|
|
||||||
if (locationManager != nil) {
|
if (locationManager != nil) {
|
||||||
return locationManager;
|
return locationManager;
|
||||||
}
|
}
|
||||||
@ -565,70 +466,76 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
|
|
||||||
- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation
|
- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation
|
||||||
{
|
{
|
||||||
if (locationManager != nil) {
|
if (locationManager == nil) {
|
||||||
[self.locationManager stopUpdatingLocation];
|
return;
|
||||||
self.locationManager = nil;
|
}
|
||||||
|
|
||||||
NSMutableDictionary *GPSDictionary = [[NSMutableDictionary dictionary] init];
|
[self.locationManager stopUpdatingLocation];
|
||||||
|
self.locationManager = nil;
|
||||||
CLLocationDegrees latitude = newLocation.coordinate.latitude;
|
|
||||||
CLLocationDegrees longitude = newLocation.coordinate.longitude;
|
NSMutableDictionary *GPSDictionary = [[NSMutableDictionary dictionary] init];
|
||||||
|
|
||||||
// latitude
|
CLLocationDegrees latitude = newLocation.coordinate.latitude;
|
||||||
if (latitude < 0.0) {
|
CLLocationDegrees longitude = newLocation.coordinate.longitude;
|
||||||
latitude = latitude * -1.0f;
|
|
||||||
[GPSDictionary setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
|
// latitude
|
||||||
} else {
|
if (latitude < 0.0) {
|
||||||
[GPSDictionary setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
|
latitude = latitude * -1.0f;
|
||||||
}
|
[GPSDictionary setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
|
||||||
[GPSDictionary setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString*)kCGImagePropertyGPSLatitude];
|
} else {
|
||||||
|
[GPSDictionary setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
|
||||||
// longitude
|
}
|
||||||
if (longitude < 0.0) {
|
[GPSDictionary setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString*)kCGImagePropertyGPSLatitude];
|
||||||
longitude = longitude * -1.0f;
|
|
||||||
[GPSDictionary setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
|
// longitude
|
||||||
}
|
if (longitude < 0.0) {
|
||||||
else {
|
longitude = longitude * -1.0f;
|
||||||
[GPSDictionary setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
|
[GPSDictionary setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
|
||||||
}
|
}
|
||||||
[GPSDictionary setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString*)kCGImagePropertyGPSLongitude];
|
else {
|
||||||
|
[GPSDictionary setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
|
||||||
// altitude
|
}
|
||||||
CGFloat altitude = newLocation.altitude;
|
[GPSDictionary setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString*)kCGImagePropertyGPSLongitude];
|
||||||
if (!isnan(altitude)){
|
|
||||||
if (altitude < 0) {
|
// altitude
|
||||||
altitude = -altitude;
|
CGFloat altitude = newLocation.altitude;
|
||||||
[GPSDictionary setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
|
if (!isnan(altitude)){
|
||||||
} else {
|
if (altitude < 0) {
|
||||||
[GPSDictionary setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
|
altitude = -altitude;
|
||||||
}
|
[GPSDictionary setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
|
||||||
[GPSDictionary setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude];
|
} else {
|
||||||
|
[GPSDictionary setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
|
||||||
}
|
}
|
||||||
|
[GPSDictionary setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude];
|
||||||
// Time and date
|
}
|
||||||
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
|
||||||
[formatter setDateFormat:@"HH:mm:ss.SSSSSS"];
|
// Time and date
|
||||||
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
|
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
||||||
[GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp];
|
[formatter setDateFormat:@"HH:mm:ss.SSSSSS"];
|
||||||
[formatter setDateFormat:@"yyyy:MM:dd"];
|
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
|
||||||
[GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp];
|
[GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp];
|
||||||
|
[formatter setDateFormat:@"yyyy:MM:dd"];
|
||||||
[self.metadata setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
|
[GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp];
|
||||||
[self imagePickerControllerReturnImageResult];
|
|
||||||
}
|
[self.metadata setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
|
||||||
|
[self imagePickerControllerReturnImageResult];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
|
- (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error
|
||||||
if (locationManager != nil) {
|
{
|
||||||
[self.locationManager stopUpdatingLocation];
|
if (locationManager == nil) {
|
||||||
self.locationManager = nil;
|
return;
|
||||||
|
}
|
||||||
[self imagePickerControllerReturnImageResult];
|
|
||||||
}
|
[self.locationManager stopUpdatingLocation];
|
||||||
|
self.locationManager = nil;
|
||||||
|
|
||||||
|
[self imagePickerControllerReturnImageResult];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)imagePickerControllerReturnImageResult
|
- (void)imagePickerControllerReturnImageResult
|
||||||
{
|
{
|
||||||
|
CDVPictureOptions* options = self.pickerController.pictureOptions;
|
||||||
CDVPluginResult* result = nil;
|
CDVPluginResult* result = nil;
|
||||||
|
|
||||||
if (self.metadata) {
|
if (self.metadata) {
|
||||||
@ -643,39 +550,31 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
CFRelease(destinationImage);
|
CFRelease(destinationImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.pickerController.saveToPhotoAlbum) {
|
switch (options.destinationType) {
|
||||||
ALAssetsLibrary *library = [ALAssetsLibrary new];
|
case DestinationTypeFileUri:
|
||||||
[library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
|
{
|
||||||
}
|
NSError* err = nil;
|
||||||
|
NSString* extension = self.pickerController.pictureOptions.encodingType == EncodingTypePNG ? @"png":@"jpg";
|
||||||
if (self.pickerController.returnType == DestinationTypeFileUri) {
|
NSString* filePath = [self tempFilePath:extension];
|
||||||
// write to temp directory and return URI
|
|
||||||
// get the temp directory path
|
// save file
|
||||||
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
|
if (![self.data writeToFile:filePath options:NSAtomicWrite error:&err]) {
|
||||||
NSError* err = nil;
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
|
||||||
NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by apple (vs [NSFileManager defaultManager]) to be threadsafe
|
}
|
||||||
// generate unique file name
|
else {
|
||||||
NSString* filePath;
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
|
||||||
|
}
|
||||||
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]];
|
|
||||||
}
|
}
|
||||||
else {
|
break;
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
|
case DestinationTypeDataUrl:
|
||||||
|
{
|
||||||
|
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[self.data base64EncodedString]];
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else {
|
case DestinationTypeNativeUri:
|
||||||
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[self.data base64EncodedString]];
|
default:
|
||||||
}
|
break;
|
||||||
if (result) {
|
};
|
||||||
[self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
[self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
|
[self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
|
||||||
@ -685,33 +584,29 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
self.pickerController = nil;
|
self.pickerController = nil;
|
||||||
self.data = nil;
|
self.data = nil;
|
||||||
self.metadata = nil;
|
self.metadata = nil;
|
||||||
|
|
||||||
|
if (options.saveToPhotoAlbum) {
|
||||||
|
ALAssetsLibrary *library = [ALAssetsLibrary new];
|
||||||
|
[library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation CDVCameraPicker
|
@implementation CDVCameraPicker
|
||||||
|
|
||||||
@synthesize quality, postUrl;
|
- (BOOL)prefersStatusBarHidden
|
||||||
@synthesize returnType;
|
{
|
||||||
@synthesize callbackId;
|
|
||||||
@synthesize popoverController;
|
|
||||||
@synthesize targetSize;
|
|
||||||
@synthesize correctOrientation;
|
|
||||||
@synthesize saveToPhotoAlbum;
|
|
||||||
@synthesize encodingType;
|
|
||||||
@synthesize cropToSize;
|
|
||||||
@synthesize webView;
|
|
||||||
@synthesize popoverSupported;
|
|
||||||
|
|
||||||
- (BOOL)prefersStatusBarHidden {
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIViewController*)childViewControllerForStatusBarHidden {
|
- (UIViewController*)childViewControllerForStatusBarHidden
|
||||||
|
{
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated
|
||||||
|
{
|
||||||
SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
|
SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
|
||||||
if ([self respondsToSelector:sel]) {
|
if ([self respondsToSelector:sel]) {
|
||||||
[self performSelector:sel withObject:nil afterDelay:0];
|
[self performSelector:sel withObject:nil afterDelay:0];
|
||||||
@ -720,4 +615,26 @@ static NSSet* org_apache_cordova_validArrowDirections;
|
|||||||
[super viewWillAppear:animated];
|
[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
|
@end
|
||||||
|
28
src/ios/UIImage+CropScaleOrientation.h
Normal file
28
src/ios/UIImage+CropScaleOrientation.h
Normal file
@ -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
|
170
src/ios/UIImage+CropScaleOrientation.m
Normal file
170
src/ios/UIImage+CropScaleOrientation.m
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user