Compare commits

..
9 changed files with 103 additions and 67 deletions
-13
View File
@@ -1,13 +0,0 @@
language: objective-c
git:
depth: 2
node_js:
- "0.10"
install:
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
- cd ..
- npm install -g cordova-paramedic
- npm install -g cordova
- npm install -g ios-sim
script:
- cordova-paramedic --platform ios --plugin ${TRAVIS_BUILD_DIR}
-4
View File
@@ -19,8 +19,6 @@
# cordova-plugin-camera
[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
This plugin defines a global `navigator.camera` object, which provides an API for taking pictures and for choosing images from
the system's image library.
@@ -293,8 +291,6 @@ with the Google Plus Photos application. Other crops may not work.
#### iOS Quirks
- Set `quality` below 50 to avoid memory errors on some devices.
- When using `destinationType.FILE_URI`, photos are saved in the application's temporary directory. The contents of the application's temporary directory is deleted when the application ends.
#### Tizen Quirks
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-camera",
"version": "1.2.0",
"version": "1.2.1-dev",
"description": "Cordova Camera Plugin",
"cordova": {
"id": "cordova-plugin-camera",
+1 -1
View File
@@ -22,7 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:rim="http://www.blackberry.com/ns/widgets"
id="cordova-plugin-camera"
version="1.2.0">
version="1.2.1-dev">
<name>Camera</name>
<description>Cordova Camera Plugin</description>
<license>Apache 2.0</license>
+8 -2
View File
@@ -379,7 +379,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
}
//We don't support PNG, so let's not pretend we do
exif.createInFile(getTempDirectoryPath() + "/.Pic.jpg");
exif.createInFile(sourcePath);
exif.readExifData();
rotate = exif.getOrientation();
@@ -442,7 +442,13 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
this.callbackContext.success(uri.toString());
} else {
bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString()));
if(croppedUri != null) {
bitmap = getScaledBitmap(FileHelper.stripFileProtocol(croppedUri.toString()));
}
else
{
bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString()));
}
if (rotate != 0 && this.correctOrientation) {
bitmap = getRotatedBitmap(rotate, bitmap, exif);
+18 -4
View File
@@ -20,7 +20,6 @@
#import "CDVCamera.h"
#import "CDVJpegHeaderWriter.h"
#import "UIImage+CropScaleOrientation.h"
#import <Cordova/NSData+Base64.h>
#import <ImageIO/CGImageProperties.h>
#import <AssetsLibrary/ALAssetRepresentation.h>
#import <AssetsLibrary/AssetsLibrary.h>
@@ -31,6 +30,10 @@
#import <MobileCoreServices/UTCoreTypes.h>
#import <objc/message.h>
#ifndef __CORDOVA_4_0_0
#import <Cordova/NSData+Base64.h>
#endif
#define CDV_PHOTO_PREFIX @"cdv_photo_"
static NSSet* org_apache_cordova_validArrowDirections;
@@ -38,9 +41,20 @@ static NSSet* org_apache_cordova_validArrowDirections;
static NSString* toBase64(NSData* data) {
SEL s1 = NSSelectorFromString(@"cdv_base64EncodedString");
SEL s2 = NSSelectorFromString(@"base64EncodedString");
SEL realSel = [data respondsToSelector:s1] ? s1 : s2;
NSString* (*func)(id, SEL) = (void *)[data methodForSelector:realSel];
return func(data, realSel);
SEL s3 = NSSelectorFromString(@"base64EncodedStringWithOptions:");
if ([data respondsToSelector:s1]) {
NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s1];
return func(data, s1);
} else if ([data respondsToSelector:s2]) {
NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s2];
return func(data, s2);
} else if ([data respondsToSelector:s3]) {
NSString* (*func)(id, SEL, NSUInteger) = (void *)[data methodForSelector:s3];
return func(data, s3, 0);
} else {
return nil;
}
}
@implementation CDVPictureOptions
+71 -38
View File
@@ -267,7 +267,12 @@ function takePictureFromFileWindows(successCallback, errorCallback, args) {
else {
var storageFolder = getAppData().localFolder;
file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
successCallback(URL.createObjectURL(storageFile));
if(destinationType == Camera.DestinationType.NATIVE_URI) {
successCallback("ms-appdata:///local/" + storageFile.name);
}
else {
successCallback(URL.createObjectURL(storageFile));
}
}, function () {
errorCallback("Can't access localStorage folder.");
});
@@ -307,6 +312,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
saveToPhotoAlbum = args[9],
cameraDirection = args[11],
capturePreview = null,
captureTakePhotoButton = null,
captureCancelButton = null,
capture = null,
captureSettings = null,
@@ -314,17 +320,24 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
sensor = null;
var createCameraUI = function () {
// Create fullscreen preview
capturePreview = document.createElement("video");
// create style for take and cancel buttons
var buttonStyle = "width:45%;padding: 10px 16px;font-size: 18px;line-height: 1.3333333;color: #333;background-color: #fff;border-color: #ccc; border: 1px solid transparent;border-radius: 6px; display: block; margin: 20px; z-index: 1000;border-color: #adadad;";
// Create fullscreen preview
// z-order style element for capturePreview and captureCancelButton elts
// is necessary to avoid overriding by another page elements, -1 sometimes is not enough
capturePreview.style.cssText = "position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 999";
capturePreview = document.createElement("video");
capturePreview.style.cssText = "position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 999;";
// Create capture button
captureTakePhotoButton = document.createElement("button");
captureTakePhotoButton.innerText = "Take";
captureTakePhotoButton.style.cssText = buttonStyle + "position: fixed; left: 0; bottom: 0; margin: 20px; z-index: 1000";
// Create cancel button
captureCancelButton = document.createElement("button");
captureCancelButton.innerText = "Cancel";
captureCancelButton.style.cssText = "position: fixed; right: 0; bottom: 0; display: block; margin: 20px; z-index: 1000";
captureCancelButton.style.cssText = buttonStyle + "position: fixed; right: 0; bottom: 0; margin: 20px; z-index: 1000";
capture = new CaptureNS.MediaCapture();
@@ -355,6 +368,22 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
return capture.initializeAsync(captureSettings);
}).then(function () {
// create focus control if available
var VideoDeviceController = capture.videoDeviceController;
var FocusControl = VideoDeviceController.focusControl;
if (FocusControl.supported == true) {
capturePreview.addEventListener('click', function () {
var preset = Windows.Media.Devices.FocusPreset.autoNormal;
FocusControl.setPresetAsync(preset).done(function () {
});
});
}
// msdn.microsoft.com/en-us/library/windows/apps/hh452807.aspx
capturePreview.msZoom = true;
capturePreview.src = URL.createObjectURL(capture);
@@ -365,10 +394,12 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
if (sensor !== null) {
sensor.addEventListener("orientationchanged", onOrientationChange);
}
capturePreview.addEventListener('click', captureAction);
// add click events to take and cancel buttons
captureTakePhotoButton.addEventListener('click', captureAction);
captureCancelButton.addEventListener('click', function () {
destroyCameraPreview();
errorCallback('Cancelled');
errorCallback('no image selected');
}, false);
// Change default orientation
@@ -388,8 +419,9 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
return;
}
// Insert preview frame and controls into page
// add elements to body
document.body.appendChild(capturePreview);
document.body.appendChild(captureTakePhotoButton);
document.body.appendChild(captureCancelButton);
if (aspectRatios.indexOf(DEFAULT_ASPECT_RATIO) > -1) {
@@ -410,7 +442,8 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
}
capturePreview.pause();
capturePreview.src = null;
[capturePreview, captureCancelButton].forEach(function(elem) {
// remove elements from wrapper
[capturePreview, captureTakePhotoButton, captureCancelButton].forEach(function (elem) {
if (elem /* && elem in document.body.childNodes */) {
document.body.removeChild(elem);
}
@@ -441,33 +474,33 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
var photoStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
var finalStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
capture.capturePhotoToStreamAsync(encodingProperties, photoStream)
.then(function() {
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(photoStream);
})
.then(function(dec) {
finalStream.size = 0; // BitmapEncoder requires the output stream to be empty
return Windows.Graphics.Imaging.BitmapEncoder.createForTranscodingAsync(finalStream, dec);
})
.then(function(enc) {
// We need to rotate the photo wrt sensor orientation
enc.bitmapTransform.rotation = orientationToRotation(sensor.getCurrentOrientation());
return enc.flushAsync();
})
.then(function() {
return tempCapturedFile.openAsync(Windows.Storage.FileAccessMode.readWrite);
})
.then(function(fileStream) {
return Windows.Storage.Streams.RandomAccessStream.copyAsync(finalStream, fileStream);
})
.done(function() {
photoStream.close();
finalStream.close();
complete(tempCapturedFile);
}, function() {
photoStream.close();
finalStream.close();
throw new Error("An error has occured while capturing the photo.");
});
.then(function() {
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(photoStream);
})
.then(function(dec) {
finalStream.size = 0; // BitmapEncoder requires the output stream to be empty
return Windows.Graphics.Imaging.BitmapEncoder.createForTranscodingAsync(finalStream, dec);
})
.then(function(enc) {
// We need to rotate the photo wrt sensor orientation
enc.bitmapTransform.rotation = orientationToRotation(sensor.getCurrentOrientation());
return enc.flushAsync();
})
.then(function() {
return tempCapturedFile.openAsync(Windows.Storage.FileAccessMode.readWrite);
})
.then(function(fileStream) {
return Windows.Storage.Streams.RandomAccessStream.copyAsync(finalStream, fileStream);
})
.done(function() {
photoStream.close();
finalStream.close();
complete(tempCapturedFile);
}, function() {
photoStream.close();
finalStream.close();
throw new Error("An error has occured while capturing the photo.");
});
});
})
.done(function(capturedFile) {
@@ -480,8 +513,8 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
saveToPhotoAlbum: saveToPhotoAlbum
}, successCallback, errorCallback);
}, function(err) {
destroyCameraPreview();
errorCallback(err);
destroyCameraPreview();
errorCallback(err);
});
};
@@ -476,7 +476,7 @@
pictureOptions.encodingType = EncodingTypePNG;
resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
XCTAssertEqualObjects([resultData base64EncodedString], [originalImageDataPNG base64EncodedString]);
XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataPNG base64EncodedStringWithOptions:0]);
// Original, JPEG, full quality
@@ -487,7 +487,7 @@
pictureOptions.encodingType = EncodingTypeJPEG;
resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
XCTAssertEqualObjects([resultData base64EncodedString], [originalImageDataJPEG base64EncodedString]);
XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataJPEG base64EncodedStringWithOptions:0]);
// Original, JPEG, with quality value
@@ -500,7 +500,7 @@
NSData* originalImageDataJPEGWithQuality = UIImageJPEGRepresentation(originalImage, [pictureOptions.quality floatValue]/ 100.f);
resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
XCTAssertEqualObjects([resultData base64EncodedString], [originalImageDataJPEGWithQuality base64EncodedString]);
XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataJPEGWithQuality base64EncodedStringWithOptions:0]);
// TODO: usesGeolocation is not tested
}
+1 -1
View File
@@ -22,7 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:rim="http://www.blackberry.com/ns/widgets"
id="cordova-plugin-camera-tests"
version="1.2.0">
version="1.2.1-dev">
<name>Cordova Camera Plugin Tests</name>
<license>Apache 2.0</license>