mirror of
https://gitee.com/shuto/cordova-plugin-camera.git
synced 2025-04-27 23:00:10 +08:00
258 lines
11 KiB
Objective-C
258 lines
11 KiB
Objective-C
/*
|
|
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 "CDVCamera.h"
|
|
|
|
|
|
@implementation CDVPictureOptions
|
|
|
|
+ (instancetype) createFromTakePictureArguments:(CDVInvokedUrlCommand*)command {
|
|
CDVPictureOptions *pictureOptions = [[CDVPictureOptions alloc] init];
|
|
|
|
pictureOptions.quality = [command argumentAtIndex:0 withDefault:@(50)];
|
|
pictureOptions.destinationType = [[command argumentAtIndex:1 withDefault:@(DestinationTypeFileUri)] unsignedIntegerValue];
|
|
pictureOptions.sourceType = [[command argumentAtIndex:2 withDefault:@(SourceTypeCamera)] unsignedIntegerValue];
|
|
|
|
NSNumber *targetWidth = [command argumentAtIndex:3 withDefault:nil];
|
|
NSNumber *targetHeight = [command argumentAtIndex:4 withDefault:nil];
|
|
pictureOptions.targetSize = CGSizeMake(0, 0);
|
|
if ((targetWidth != nil) && (targetHeight != nil)) {
|
|
pictureOptions.targetSize = CGSizeMake([targetWidth floatValue], [targetHeight floatValue]);
|
|
}
|
|
|
|
pictureOptions.encodingType = [[command argumentAtIndex:5 withDefault:@(EncodingTypeJPEG)] unsignedIntegerValue];
|
|
pictureOptions.mediaType = [[command argumentAtIndex:6 withDefault:@(MediaTypePicture)] unsignedIntegerValue];
|
|
pictureOptions.allowsEditing = [[command argumentAtIndex:7 withDefault:@(NO)] boolValue];
|
|
pictureOptions.correctOrientation = [[command argumentAtIndex:8 withDefault:@(NO)] boolValue];
|
|
pictureOptions.saveToPhotoAlbum = [[command argumentAtIndex:9 withDefault:@(NO)] boolValue];
|
|
|
|
return pictureOptions;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
// ======================================================================= //
|
|
|
|
|
|
@implementation CDVCamera
|
|
|
|
/*!
|
|
Static array that stores the temporary created files allowing to delete them when calling navigator.camera.cleanup(...)
|
|
*/
|
|
static NSMutableArray *cleanUpFiles;
|
|
|
|
+ (void)initialize {
|
|
cleanUpFiles = [NSMutableArray array];
|
|
}
|
|
|
|
- (void)takePicture:(CDVInvokedUrlCommand *)command {
|
|
CDVPictureOptions *pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
|
|
if (pictureOptions.sourceType == SourceTypeCamera) {
|
|
[self takePictureFromCamera:command withOptions:pictureOptions];
|
|
} else {
|
|
[self takePictureFromFile:command withOptions:pictureOptions];
|
|
}
|
|
}
|
|
|
|
- (void)cleanup:(CDVInvokedUrlCommand*)command {
|
|
[self.commandDelegate runInBackground:^{
|
|
if (cleanUpFiles.count > 0) {
|
|
for (int i=0; i<cleanUpFiles.count; i++) {
|
|
NSString *path = [cleanUpFiles objectAtIndex:i];
|
|
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
|
|
}
|
|
|
|
[cleanUpFiles removeAllObjects];
|
|
|
|
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}
|
|
}];
|
|
}
|
|
|
|
|
|
#pragma mark - Camera
|
|
|
|
/*!
|
|
Takes a picture from the iSight camera using the default OS dialog.
|
|
@see https://developer.apple.com/documentation/quartz/ikpicturetaker
|
|
*/
|
|
- (void)takePictureFromCamera:(CDVInvokedUrlCommand *)command withOptions:(CDVPictureOptions *)pictureOptions {
|
|
IKPictureTaker *pictureTaker = [IKPictureTaker pictureTaker];
|
|
[pictureTaker setValue:[NSNumber numberWithBool:YES] forKey:IKPictureTakerAllowsVideoCaptureKey];
|
|
[pictureTaker setValue:[NSNumber numberWithBool:NO] forKey:IKPictureTakerAllowsFileChoosingKey];
|
|
[pictureTaker setValue:[NSNumber numberWithBool:pictureOptions.allowsEditing] forKey:IKPictureTakerShowEffectsKey];
|
|
[pictureTaker setValue:[NSNumber numberWithBool:pictureOptions.allowsEditing] forKey:IKPictureTakerAllowsEditingKey];
|
|
|
|
NSDictionary *contextInfo = @{ @"command": command, @"pictureOptions" : pictureOptions};
|
|
[pictureTaker beginPictureTakerSheetForWindow:self.viewController.contentView.window withDelegate:self didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:) contextInfo:(void *)CFBridgingRetain(contextInfo)];
|
|
|
|
}
|
|
|
|
- (void)pictureTakerDidEnd:(IKPictureTaker *)pictureTaker returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
|
|
if (returnCode == NSOKButton) {
|
|
NSDictionary *contextInfoDictionary = (NSDictionary *)CFBridgingRelease(contextInfo);
|
|
CDVInvokedUrlCommand *command = [contextInfoDictionary valueForKey:@"command"];
|
|
CDVPictureOptions *pictureOptions = [contextInfoDictionary valueForKey:@"pictureOptions"];
|
|
|
|
[self returnImage:pictureTaker.outputImage command:command options:pictureOptions];
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark - File
|
|
|
|
/*!
|
|
Allows to select an image or video using the system native dialog.
|
|
*/
|
|
- (void)takePictureFromFile:(CDVInvokedUrlCommand *)command withOptions:(CDVPictureOptions *)pictureOptions {
|
|
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
|
openPanel.canChooseFiles = YES;
|
|
openPanel.canChooseDirectories = NO;
|
|
openPanel.canCreateDirectories = YES;
|
|
openPanel.allowsMultipleSelection = NO;
|
|
|
|
NSMutableArray *allowedTypes = [NSMutableArray array];
|
|
if (pictureOptions.mediaType == MediaTypePicture || pictureOptions.mediaType == MediaTypeAll) {
|
|
[allowedTypes addObjectsFromArray:[NSImage imageTypes]];
|
|
}
|
|
if (pictureOptions.mediaType == MediaTypeVideo || pictureOptions.mediaType == MediaTypeAll) {
|
|
[allowedTypes addObjectsFromArray:@[(NSString *)kUTTypeMovie]];
|
|
}
|
|
[openPanel setAllowedFileTypes:allowedTypes];
|
|
|
|
[openPanel beginSheetModalForWindow:self.viewController.contentView.window completionHandler:^(NSInteger result) {
|
|
if (result == NSOKButton) {
|
|
NSURL *fileURL = [openPanel.URLs objectAtIndex:0];
|
|
|
|
if ([self fileIsImage:fileURL]) {
|
|
NSImage *image = [[NSImage alloc] initWithContentsOfFile:fileURL.path];
|
|
[self returnImage:image command:command options:pictureOptions];
|
|
} else {
|
|
if (pictureOptions.destinationType == DestinationTypeDataUrl) {
|
|
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Camera.DestinationType.DATA_URL is only available with image files"];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
} else {
|
|
[self returnUri:fileURL.path command:command options:pictureOptions];
|
|
}
|
|
}
|
|
}
|
|
}];
|
|
}
|
|
|
|
|
|
#pragma mark - Common
|
|
|
|
/*!
|
|
Returns to JavaScript a URI.
|
|
Called when Camera.DestinationType.FILE_URI or Camera.DestinationType.NATIVE_URI.
|
|
*/
|
|
- (void)returnUri:(NSString *)path command:(CDVInvokedUrlCommand *)command options:(CDVPictureOptions *)pictureOptions {
|
|
NSString *protocol = (pictureOptions.destinationType == DestinationTypeFileUri) ? @"file://" : @"";
|
|
NSString *uri = [NSString stringWithFormat:@"%@%@", protocol, path];
|
|
|
|
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:uri];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
}
|
|
|
|
/*!
|
|
Returns to JavaScript a base64 encoded image.
|
|
Called when Camera.DestinationType.DATA_URL.
|
|
*/
|
|
- (void)returnImage:(NSImage *)image command:(CDVInvokedUrlCommand *)command options:(CDVPictureOptions *)pictureOptions {
|
|
[self.commandDelegate runInBackground:^{
|
|
NSData *processedImageData = [self processImage:image options:pictureOptions];
|
|
|
|
if (pictureOptions.destinationType == DestinationTypeDataUrl) {
|
|
CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[processedImageData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]];
|
|
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
|
|
} else {
|
|
NSString *tempFilePath = [self uniqueImageName:pictureOptions];
|
|
[processedImageData writeToFile:tempFilePath atomically:YES];
|
|
[cleanUpFiles addObject:tempFilePath];
|
|
[self returnUri:tempFilePath command:command options:pictureOptions];
|
|
}
|
|
}];
|
|
|
|
}
|
|
|
|
/*!
|
|
Top level method to apply the size and quality required changes to an image.
|
|
*/
|
|
- (NSData *)processImage:(NSImage *)image options:(CDVPictureOptions *)pictureOptions {
|
|
NSImage *sourceImage = image;
|
|
if (pictureOptions.targetSize.width > 0 && pictureOptions.targetSize.height > 0) {
|
|
sourceImage = [self resizeImage:sourceImage toSize:pictureOptions.targetSize];
|
|
}
|
|
|
|
CGImageRef cgRef = [sourceImage CGImageForProposedRect:NULL context:nil hints:nil];
|
|
NSBitmapImageRep *imageRepresentation = [[NSBitmapImageRep alloc] initWithCGImage:cgRef];
|
|
|
|
NSData *data = (pictureOptions.encodingType == EncodingTypeJPEG)
|
|
? [imageRepresentation representationUsingType:NSJPEGFileType properties:@{NSImageCompressionFactor: [NSNumber numberWithFloat:pictureOptions.quality.floatValue/100.f]}]
|
|
: [imageRepresentation representationUsingType:NSPNGFileType properties:@{NSImageCompressionFactor: @1.0}];
|
|
|
|
return data;
|
|
}
|
|
|
|
/*!
|
|
Auxiliar method to resize an image.
|
|
*/
|
|
- (NSImage *)resizeImage:(NSImage *)image toSize:(CGSize)newSize {
|
|
CGFloat aspectWidth = newSize.width / image.size.width;
|
|
CGFloat aspectHeight = newSize.height / image.size.height;
|
|
CGFloat aspectRatio = MIN(aspectWidth, aspectHeight);
|
|
|
|
CGSize scaledSize = NSMakeSize(image.size.width*aspectRatio, image.size.height*aspectRatio);
|
|
|
|
NSImage *smallImage = [[NSImage alloc] initWithSize: scaledSize];
|
|
[smallImage lockFocus];
|
|
[image setSize: scaledSize];
|
|
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
|
|
[image drawAtPoint:NSZeroPoint fromRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height) operation:NSCompositeCopy fraction:1.0];
|
|
[smallImage unlockFocus];
|
|
return smallImage;
|
|
}
|
|
|
|
/*!
|
|
Auxiliar method to know if a given file is an image or not.
|
|
*/
|
|
- (BOOL)fileIsImage:(NSURL *)fileURL {
|
|
NSString *type;
|
|
BOOL isImage = NO;
|
|
|
|
if ([fileURL getResourceValue:&type forKey:NSURLTypeIdentifierKey error:nil]) {
|
|
isImage = [[NSImage imageTypes] containsObject:type];
|
|
}
|
|
|
|
return isImage;
|
|
}
|
|
|
|
/*!
|
|
Auxiliar method that generates an unique filename for an image in the temporary directory.
|
|
*/
|
|
- (NSString *)uniqueImageName:(CDVPictureOptions *)pictureOptions {
|
|
NSString *tempDir = NSTemporaryDirectory();
|
|
NSString *guid = [[NSProcessInfo processInfo] globallyUniqueString] ;
|
|
NSString *extension = (pictureOptions.encodingType == EncodingTypeJPEG) ? @"jpeg" : @"png";
|
|
NSString *uniqueFileName = [NSString stringWithFormat:@"%@%@.%@", tempDir, guid, extension];
|
|
return uniqueFileName;
|
|
}
|
|
|
|
@end |