mirror of
https://github.com/apache/cordova-plugin-camera.git
synced 2025-02-23 23:02:53 +08:00
CB-13661: Remove deprecated platforms
This commit is contained in:
parent
1f86358156
commit
7fad5d5786
92
README.md
92
README.md
@ -179,14 +179,10 @@ than `DATA_URL`.
|
|||||||
__Supported Platforms__
|
__Supported Platforms__
|
||||||
|
|
||||||
- Android
|
- Android
|
||||||
- BlackBerry
|
|
||||||
- Browser
|
- Browser
|
||||||
- Firefox
|
|
||||||
- FireOS
|
|
||||||
- iOS
|
- iOS
|
||||||
- Windows
|
- Windows
|
||||||
- WP8
|
- OSX
|
||||||
- Ubuntu
|
|
||||||
|
|
||||||
More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
|
More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
|
||||||
|
|
||||||
@ -469,12 +465,6 @@ Take a photo and retrieve it as a Base64-encoded image:
|
|||||||
|
|
||||||
<preference name="CameraUsesGeolocation" value="false" />
|
<preference name="CameraUsesGeolocation" value="false" />
|
||||||
|
|
||||||
#### Amazon Fire OS Quirks <a name="camera-getPicture-quirks"></a>
|
|
||||||
|
|
||||||
Amazon Fire OS uses intents to launch the camera activity on the device to capture
|
|
||||||
images, and on phones with low memory, the Cordova activity may be killed. In this
|
|
||||||
scenario, the image may not appear when the Cordova activity is restored.
|
|
||||||
|
|
||||||
#### Android Quirks
|
#### Android Quirks
|
||||||
|
|
||||||
Android uses intents to launch the camera activity on the device to capture
|
Android uses intents to launch the camera activity on the device to capture
|
||||||
@ -490,10 +480,6 @@ successful.
|
|||||||
|
|
||||||
Can only return photos as Base64-encoded image.
|
Can only return photos as Base64-encoded image.
|
||||||
|
|
||||||
#### Firefox OS Quirks
|
|
||||||
|
|
||||||
Camera plugin is currently implemented using [Web Activities][web_activities].
|
|
||||||
|
|
||||||
#### iOS Quirks
|
#### iOS Quirks
|
||||||
|
|
||||||
Including a JavaScript `alert()` in either of the callback functions
|
Including a JavaScript `alert()` in either of the callback functions
|
||||||
@ -505,11 +491,6 @@ displays:
|
|||||||
// do your thing here!
|
// do your thing here!
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
#### Windows Phone 7 Quirks
|
|
||||||
|
|
||||||
Invoking the native camera application while the device is connected
|
|
||||||
via Zune does not work, and triggers an error callback.
|
|
||||||
|
|
||||||
#### Windows quirks
|
#### Windows quirks
|
||||||
|
|
||||||
On Windows Phone 8.1 using `SAVEDPHOTOALBUM` or `PHOTOLIBRARY` as a source type causes application to suspend until file picker returns the selected image and
|
On Windows Phone 8.1 using `SAVEDPHOTOALBUM` or `PHOTOLIBRARY` as a source type causes application to suspend until file picker returns the selected image and
|
||||||
@ -520,22 +501,6 @@ To avoid this we suggest using SPA pattern or call `camera.getPicture` only from
|
|||||||
|
|
||||||
More information about Windows Phone 8.1 picker APIs is here: [How to continue your Windows Phone app after calling a file picker](https://msdn.microsoft.com/en-us/library/windows/apps/dn720490.aspx)
|
More information about Windows Phone 8.1 picker APIs is here: [How to continue your Windows Phone app after calling a file picker](https://msdn.microsoft.com/en-us/library/windows/apps/dn720490.aspx)
|
||||||
|
|
||||||
#### Tizen Quirks
|
|
||||||
|
|
||||||
Tizen only supports a `destinationType` of
|
|
||||||
`Camera.DestinationType.FILE_URI` and a `sourceType` of
|
|
||||||
`Camera.PictureSourceType.PHOTOLIBRARY`.
|
|
||||||
|
|
||||||
|
|
||||||
## `CameraOptions` Errata <a name="CameraOptions-quirks"></a>
|
|
||||||
|
|
||||||
#### Amazon Fire OS Quirks
|
|
||||||
|
|
||||||
- Any `cameraDirection` value results in a back-facing photo.
|
|
||||||
|
|
||||||
- Ignores the `allowEdit` parameter.
|
|
||||||
|
|
||||||
- `Camera.PictureSourceType.PHOTOLIBRARY` and `Camera.PictureSourceType.SAVEDPHOTOALBUM` both display the same photo album.
|
|
||||||
|
|
||||||
#### Android Quirks
|
#### Android Quirks
|
||||||
|
|
||||||
@ -547,38 +512,6 @@ Tizen only supports a `destinationType` of
|
|||||||
|
|
||||||
- Ignores the `encodingType` parameter if the image is unedited (i.e. `quality` is 100, `correctOrientation` is false, and no `targetHeight` or `targetWidth` are specified). The `CAMERA` source will always return the JPEG file given by the native camera and the `PHOTOLIBRARY` and `SAVEDPHOTOALBUM` sources will return the selected file in its existing encoding.
|
- Ignores the `encodingType` parameter if the image is unedited (i.e. `quality` is 100, `correctOrientation` is false, and no `targetHeight` or `targetWidth` are specified). The `CAMERA` source will always return the JPEG file given by the native camera and the `PHOTOLIBRARY` and `SAVEDPHOTOALBUM` sources will return the selected file in its existing encoding.
|
||||||
|
|
||||||
#### BlackBerry 10 Quirks
|
|
||||||
|
|
||||||
- Ignores the `quality` parameter.
|
|
||||||
|
|
||||||
- Ignores the `allowEdit` parameter.
|
|
||||||
|
|
||||||
- `Camera.MediaType` is not supported.
|
|
||||||
|
|
||||||
- Ignores the `correctOrientation` parameter.
|
|
||||||
|
|
||||||
- Ignores the `cameraDirection` parameter.
|
|
||||||
|
|
||||||
#### Firefox OS Quirks
|
|
||||||
|
|
||||||
- Ignores the `quality` parameter.
|
|
||||||
|
|
||||||
- `Camera.DestinationType` is ignored and equals `1` (image file URI)
|
|
||||||
|
|
||||||
- Ignores the `allowEdit` parameter.
|
|
||||||
|
|
||||||
- Ignores the `PictureSourceType` parameter (user chooses it in a dialog window)
|
|
||||||
|
|
||||||
- Ignores the `encodingType`
|
|
||||||
|
|
||||||
- Ignores the `targetWidth` and `targetHeight`
|
|
||||||
|
|
||||||
- `Camera.MediaType` is not supported.
|
|
||||||
|
|
||||||
- Ignores the `correctOrientation` parameter.
|
|
||||||
|
|
||||||
- Ignores the `cameraDirection` parameter.
|
|
||||||
|
|
||||||
#### iOS Quirks
|
#### iOS Quirks
|
||||||
|
|
||||||
- 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.
|
- 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.
|
||||||
@ -587,29 +520,6 @@ Tizen only supports a `destinationType` of
|
|||||||
|
|
||||||
- When using `destinationType.NATIVE_URI` and `sourceType.PHOTOLIBRARY` or `sourceType.SAVEDPHOTOALBUM`, all editing options are ignored and link is returned to original picture.
|
- When using `destinationType.NATIVE_URI` and `sourceType.PHOTOLIBRARY` or `sourceType.SAVEDPHOTOALBUM`, all editing options are ignored and link is returned to original picture.
|
||||||
|
|
||||||
#### Tizen Quirks
|
|
||||||
|
|
||||||
- options not supported
|
|
||||||
|
|
||||||
- always returns a FILE URI
|
|
||||||
|
|
||||||
#### Windows Phone 7 and 8 Quirks
|
|
||||||
|
|
||||||
- Ignores the `allowEdit` parameter.
|
|
||||||
|
|
||||||
- Ignores the `correctOrientation` parameter.
|
|
||||||
|
|
||||||
- Ignores the `cameraDirection` parameter.
|
|
||||||
|
|
||||||
- Ignores the `saveToPhotoAlbum` parameter. IMPORTANT: All images taken with the WP8/8 Cordova camera API are always copied to the phone's camera roll. Depending on the user's settings, this could also mean the image is auto-uploaded to their OneDrive. This could potentially mean the image is available to a wider audience than your app intended. If this is a blocker for your application, you will need to implement the CameraCaptureTask as [documented on MSDN][msdn_wp8_docs]. You may also comment or up-vote the related issue in the [issue tracker][wp8_bug].
|
|
||||||
|
|
||||||
- Ignores the `mediaType` property of `cameraOptions` as the Windows Phone SDK does not provide a way to choose videos from PHOTOLIBRARY.
|
|
||||||
|
|
||||||
[android_lifecycle]: http://cordova.apache.org/docs/en/dev/guide/platforms/android/lifecycle.html
|
|
||||||
[web_activities]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
|
|
||||||
[wp8_bug]: https://issues.apache.org/jira/browse/CB-2083
|
|
||||||
[msdn_wp8_docs]: http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx
|
|
||||||
|
|
||||||
## Sample: Take Pictures, Select Pictures from the Picture Library, and Get Thumbnails <a name="sample"></a>
|
## Sample: Take Pictures, Select Pictures from the Picture Library, and Get Thumbnails <a name="sample"></a>
|
||||||
|
|
||||||
The Camera plugin allows you to do things like open the device's Camera app and take a picture, or open the file picker and select one. The code snippets in this section demonstrate different tasks including:
|
The Camera plugin allows you to do things like open the device's Camera app and take a picture, or open the file picker and select one. The code snippets in this section demonstrate different tasks including:
|
||||||
|
16
package.json
16
package.json
@ -1,20 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "cordova-plugin-camera",
|
"name": "cordova-plugin-camera",
|
||||||
"version": "3.0.1-dev",
|
"version": "4.0.0-dev",
|
||||||
"description": "Cordova Camera Plugin",
|
"description": "Cordova Camera Plugin",
|
||||||
"types": "./types/index.d.ts",
|
"types": "./types/index.d.ts",
|
||||||
"cordova": {
|
"cordova": {
|
||||||
"id": "cordova-plugin-camera",
|
"id": "cordova-plugin-camera",
|
||||||
"platforms": [
|
"platforms": [
|
||||||
"firefoxos",
|
|
||||||
"android",
|
"android",
|
||||||
"amazon-fireos",
|
|
||||||
"ubuntu",
|
|
||||||
"ios",
|
"ios",
|
||||||
"blackberry10",
|
|
||||||
"wp7",
|
|
||||||
"wp8",
|
|
||||||
"windows8",
|
|
||||||
"browser",
|
"browser",
|
||||||
"windows",
|
"windows",
|
||||||
"osx"
|
"osx"
|
||||||
@ -31,15 +24,8 @@
|
|||||||
"cordova",
|
"cordova",
|
||||||
"camera",
|
"camera",
|
||||||
"ecosystem:cordova",
|
"ecosystem:cordova",
|
||||||
"cordova-firefoxos",
|
|
||||||
"cordova-android",
|
"cordova-android",
|
||||||
"cordova-amazon-fireos",
|
|
||||||
"cordova-ubuntu",
|
|
||||||
"cordova-ios",
|
"cordova-ios",
|
||||||
"cordova-blackberry10",
|
|
||||||
"cordova-wp7",
|
|
||||||
"cordova-wp8",
|
|
||||||
"cordova-windows8",
|
|
||||||
"cordova-browser",
|
"cordova-browser",
|
||||||
"cordova-windows",
|
"cordova-windows",
|
||||||
"cordova-osx"
|
"cordova-osx"
|
||||||
|
130
plugin.xml
130
plugin.xml
@ -22,7 +22,7 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:rim="http://www.blackberry.com/ns/widgets"
|
xmlns:rim="http://www.blackberry.com/ns/widgets"
|
||||||
id="cordova-plugin-camera"
|
id="cordova-plugin-camera"
|
||||||
version="3.0.1-dev">
|
version="4.0.0-dev">
|
||||||
<name>Camera</name>
|
<name>Camera</name>
|
||||||
<description>Cordova Camera Plugin</description>
|
<description>Cordova Camera Plugin</description>
|
||||||
<license>Apache 2.0</license>
|
<license>Apache 2.0</license>
|
||||||
@ -48,19 +48,6 @@
|
|||||||
<clobbers target="navigator.camera" />
|
<clobbers target="navigator.camera" />
|
||||||
</js-module>
|
</js-module>
|
||||||
|
|
||||||
<!-- firefoxos -->
|
|
||||||
<platform name="firefoxos">
|
|
||||||
<config-file target="config.xml" parent="/*">
|
|
||||||
<feature name="Camera">
|
|
||||||
<param name="firefoxos-package" value="Camera" />
|
|
||||||
</feature>
|
|
||||||
</config-file>
|
|
||||||
|
|
||||||
<js-module src="src/firefoxos/CameraProxy.js" name="CameraProxy">
|
|
||||||
<runs />
|
|
||||||
</js-module>
|
|
||||||
</platform>
|
|
||||||
|
|
||||||
<!-- android -->
|
<!-- android -->
|
||||||
<platform name="android">
|
<platform name="android">
|
||||||
<config-file target="res/xml/config.xml" parent="/*">
|
<config-file target="res/xml/config.xml" parent="/*">
|
||||||
@ -97,48 +84,6 @@
|
|||||||
|
|
||||||
</platform>
|
</platform>
|
||||||
|
|
||||||
<!-- amazon-fireos -->
|
|
||||||
<platform name="amazon-fireos">
|
|
||||||
<config-file target="res/xml/config.xml" parent="/*">
|
|
||||||
<feature name="Camera">
|
|
||||||
<param name="android-package" value="org.apache.cordova.camera.CameraLauncher"/>
|
|
||||||
</feature>
|
|
||||||
</config-file>
|
|
||||||
<config-file target="AndroidManifest.xml" parent="/*">
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
</config-file>
|
|
||||||
|
|
||||||
<source-file src="src/android/CameraLauncher.java" target-dir="src/org/apache/cordova/camera" />
|
|
||||||
<source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/camera" />
|
|
||||||
<source-file src="src/android/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
|
|
||||||
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
|
||||||
<clobbers target="CameraPopoverHandle" />
|
|
||||||
</js-module>
|
|
||||||
|
|
||||||
</platform>
|
|
||||||
|
|
||||||
<!-- ubuntu -->
|
|
||||||
<platform name="ubuntu">
|
|
||||||
<config-file target="config.xml" parent="/*">
|
|
||||||
<feature name="Camera">
|
|
||||||
<param policy_group="camera" policy_version="1" />
|
|
||||||
</feature>
|
|
||||||
</config-file>
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
|
||||||
<clobbers target="CameraPopoverHandle" />
|
|
||||||
</js-module>
|
|
||||||
<header-file src="src/ubuntu/camera.h" />
|
|
||||||
<source-file src="src/ubuntu/camera.cpp" />
|
|
||||||
|
|
||||||
<resource-file src="src/ubuntu/back.png" />
|
|
||||||
<resource-file src="src/ubuntu/CaptureWidget.qml" />
|
|
||||||
<resource-file src="src/ubuntu/shoot.png" />
|
|
||||||
<resource-file src="src/ubuntu/toolbar-left.png" />
|
|
||||||
<resource-file src="src/ubuntu/toolbar-middle.png" />
|
|
||||||
<resource-file src="src/ubuntu/toolbar-right.png" />
|
|
||||||
</platform>
|
|
||||||
|
|
||||||
<!-- ios -->
|
<!-- ios -->
|
||||||
<platform name="ios">
|
<platform name="ios">
|
||||||
<config-file target="config.xml" parent="/*">
|
<config-file target="config.xml" parent="/*">
|
||||||
@ -169,79 +114,6 @@
|
|||||||
|
|
||||||
</platform>
|
</platform>
|
||||||
|
|
||||||
<!-- blackberry10 -->
|
|
||||||
<platform name="blackberry10">
|
|
||||||
<source-file src="src/blackberry10/index.js" target-dir="Camera" />
|
|
||||||
<config-file target="www/config.xml" parent="/widget">
|
|
||||||
<feature name="Camera" value="Camera"/>
|
|
||||||
</config-file>
|
|
||||||
<config-file target="www/config.xml" parent="/widget/rim:permissions">
|
|
||||||
<rim:permit>access_shared</rim:permit>
|
|
||||||
<rim:permit>use_camera</rim:permit>
|
|
||||||
</config-file>
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
|
||||||
<clobbers target="CameraPopoverHandle" />
|
|
||||||
</js-module>
|
|
||||||
<asset src="www/blackberry10/assets" target="chrome" />
|
|
||||||
</platform>
|
|
||||||
|
|
||||||
<!-- wp7 -->
|
|
||||||
<platform name="wp7">
|
|
||||||
<config-file target="config.xml" parent="/*">
|
|
||||||
<feature name="Camera">
|
|
||||||
<param name="wp-package" value="Camera"/>
|
|
||||||
</feature>
|
|
||||||
</config-file>
|
|
||||||
|
|
||||||
<config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
|
|
||||||
<Capability Name="ID_CAP_ISV_CAMERA" />
|
|
||||||
<Capability Name="ID_CAP_MEDIALIB" />
|
|
||||||
</config-file>
|
|
||||||
|
|
||||||
<source-file src="src/wp/Camera.cs" />
|
|
||||||
|
|
||||||
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
|
||||||
<clobbers target="CameraPopoverHandle" />
|
|
||||||
</js-module>
|
|
||||||
</platform>
|
|
||||||
|
|
||||||
<!-- wp8 -->
|
|
||||||
<platform name="wp8">
|
|
||||||
<config-file target="config.xml" parent="/*">
|
|
||||||
<feature name="Camera">
|
|
||||||
<param name="wp-package" value="Camera"/>
|
|
||||||
</feature>
|
|
||||||
</config-file>
|
|
||||||
|
|
||||||
<config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
|
|
||||||
<Capability Name="ID_CAP_ISV_CAMERA" />
|
|
||||||
<Capability Name="ID_CAP_MEDIALIB_PHOTO"/>
|
|
||||||
</config-file>
|
|
||||||
|
|
||||||
<source-file src="src/wp/Camera.cs" />
|
|
||||||
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
|
||||||
<clobbers target="CameraPopoverHandle" />
|
|
||||||
</js-module>
|
|
||||||
</platform>
|
|
||||||
|
|
||||||
<!-- windows8 -->
|
|
||||||
<platform name="windows8">
|
|
||||||
|
|
||||||
<config-file target="package.appxmanifest" parent="/Package/Capabilities">
|
|
||||||
<Capability Name="picturesLibrary" />
|
|
||||||
<DeviceCapability Name="webcam" />
|
|
||||||
</config-file>
|
|
||||||
<js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
|
|
||||||
<clobbers target="CameraPopoverHandle" />
|
|
||||||
</js-module>
|
|
||||||
<js-module src="src/windows/CameraProxy.js" name="CameraProxy">
|
|
||||||
<runs />
|
|
||||||
</js-module>
|
|
||||||
|
|
||||||
</platform>
|
|
||||||
|
|
||||||
<!-- browser -->
|
<!-- browser -->
|
||||||
<platform name="browser">
|
<platform name="browser">
|
||||||
<config-file target="config.xml" parent="/*">
|
<config-file target="config.xml" parent="/*">
|
||||||
|
@ -1,227 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* globals qnx, FileError, PluginResult */
|
|
||||||
|
|
||||||
var PictureSourceType = {
|
|
||||||
PHOTOLIBRARY: 0, // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
|
|
||||||
CAMERA: 1, // Take picture from camera
|
|
||||||
SAVEDPHOTOALBUM: 2 // Choose image from picture library (same as PHOTOLIBRARY for Android)
|
|
||||||
};
|
|
||||||
var DestinationType = {
|
|
||||||
DATA_URL: 0, // Return base64 encoded string
|
|
||||||
FILE_URI: 1, // Return file uri (content://media/external/images/media/2 for Android)
|
|
||||||
NATIVE_URI: 2 // Return native uri (eg. asset-library://... for iOS)
|
|
||||||
};
|
|
||||||
var savePath = window.qnx.webplatform.getApplication().getEnv('HOME').replace('/data', '') + '/shared/camera/';
|
|
||||||
var invokeAvailable = true;
|
|
||||||
|
|
||||||
// check for camera card - it isn't currently availble in work perimeter
|
|
||||||
window.qnx.webplatform.getApplication().invocation.queryTargets(
|
|
||||||
{
|
|
||||||
type: 'image/jpeg',
|
|
||||||
action: 'bb.action.CAPTURE',
|
|
||||||
target_type: 'CARD'
|
|
||||||
},
|
|
||||||
function (error, targets) {
|
|
||||||
invokeAvailable = !error && targets && targets instanceof Array &&
|
|
||||||
targets.filter(function (t) { return t.default === 'sys.camera.card'; }).length > 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// open a webview with getUserMedia camera card implementation when camera card not available
|
|
||||||
function showCameraDialog (done, cancel, fail) {
|
|
||||||
var wv = qnx.webplatform.createWebView(function () {
|
|
||||||
wv.url = 'local:///chrome/camera.html';
|
|
||||||
wv.allowQnxObject = true;
|
|
||||||
wv.allowRpc = true;
|
|
||||||
wv.zOrder = 1;
|
|
||||||
wv.setGeometry(0, 0, screen.width, screen.height); /* eslint no-undef : 0 */
|
|
||||||
wv.backgroundColor = 0x00000000;
|
|
||||||
wv.active = true;
|
|
||||||
wv.visible = true;
|
|
||||||
wv.on('UserMediaRequest', function (evt, args) {
|
|
||||||
wv.allowUserMedia(JSON.parse(args).id, 'CAMERA_UNIT_REAR');
|
|
||||||
});
|
|
||||||
wv.on('JavaScriptCallback', function (evt, data) {
|
|
||||||
var args = JSON.parse(data).args;
|
|
||||||
if (args[0] === 'cordova-plugin-camera') {
|
|
||||||
if (args[1] === 'cancel') {
|
|
||||||
cancel('User canceled');
|
|
||||||
} else if (args[1] === 'error') {
|
|
||||||
fail(args[2]);
|
|
||||||
} else {
|
|
||||||
saveImage(args[1], done, fail);
|
|
||||||
}
|
|
||||||
wv.un('JavaScriptCallback', arguments.callee); /* eslint no-caller : 0 */
|
|
||||||
wv.visible = false;
|
|
||||||
wv.destroy();
|
|
||||||
qnx.webplatform.getApplication().unlockRotation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
wv.on('Destroyed', function () {
|
|
||||||
wv.delete();
|
|
||||||
});
|
|
||||||
qnx.webplatform.getApplication().lockRotation();
|
|
||||||
qnx.webplatform.getController().dispatchEvent('webview.initialized', [wv]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// create unique name for saved file (same pattern as BB10 camera app)
|
|
||||||
function imgName () {
|
|
||||||
var date = new Date();
|
|
||||||
var pad = function (n) { return n < 10 ? '0' + n : n; };
|
|
||||||
return 'IMG_' + date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + '_' +
|
|
||||||
pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds()) + '.png';
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert dataURI to Blob
|
|
||||||
function dataURItoBlob (dataURI) {
|
|
||||||
var byteString = atob(dataURI.split(',')[1]);
|
|
||||||
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
|
||||||
var arrayBuffer = new ArrayBuffer(byteString.length);
|
|
||||||
var ia = new Uint8Array(arrayBuffer);
|
|
||||||
var i;
|
|
||||||
for (i = 0; i < byteString.length; i++) {
|
|
||||||
ia[i] = byteString.charCodeAt(i);
|
|
||||||
}
|
|
||||||
return new Blob([new DataView(arrayBuffer)], { type: mimeString });
|
|
||||||
}
|
|
||||||
|
|
||||||
// save dataURI to file system and call success with path
|
|
||||||
function saveImage (data, success, fail) {
|
|
||||||
var name = savePath + imgName();
|
|
||||||
require('lib/webview').setSandbox(false);
|
|
||||||
window.webkitRequestFileSystem(window.PERSISTENT, 0, function (fs) {
|
|
||||||
fs.root.getFile(name, { create: true }, function (entry) {
|
|
||||||
entry.createWriter(function (writer) {
|
|
||||||
writer.onwriteend = function () {
|
|
||||||
success(name);
|
|
||||||
};
|
|
||||||
writer.onerror = fail;
|
|
||||||
writer.write(dataURItoBlob(data));
|
|
||||||
});
|
|
||||||
}, fail);
|
|
||||||
}, fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeBase64 (filePath, callback) {
|
|
||||||
var sandbox = window.qnx.webplatform.getController().setFileSystemSandbox; // save original sandbox value
|
|
||||||
var errorHandler = function (err) {
|
|
||||||
var msg = 'An error occured: ';
|
|
||||||
|
|
||||||
switch (err.code) {
|
|
||||||
case FileError.NOT_FOUND_ERR:
|
|
||||||
msg += 'File or directory not found';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FileError.NOT_READABLE_ERR:
|
|
||||||
msg += 'File or directory not readable';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FileError.PATH_EXISTS_ERR:
|
|
||||||
msg += 'File or directory already exists';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FileError.TYPE_MISMATCH_ERR:
|
|
||||||
msg += 'Invalid file type';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
msg += 'Unknown Error';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set it back to original value
|
|
||||||
window.qnx.webplatform.getController().setFileSystemSandbox = sandbox;
|
|
||||||
callback(msg);
|
|
||||||
};
|
|
||||||
var gotFile = function (fileEntry) {
|
|
||||||
fileEntry.file(function (file) {
|
|
||||||
var reader = new FileReader();
|
|
||||||
|
|
||||||
reader.onloadend = function (e) {
|
|
||||||
// set it back to original value
|
|
||||||
window.qnx.webplatform.getController().setFileSystemSandbox = sandbox;
|
|
||||||
callback(this.result);
|
|
||||||
};
|
|
||||||
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
}, errorHandler);
|
|
||||||
};
|
|
||||||
var onInitFs = function (fs) {
|
|
||||||
window.qnx.webplatform.getController().setFileSystemSandbox = false;
|
|
||||||
fs.root.getFile(filePath, {create: false}, gotFile, errorHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.webkitRequestFileSystem(window.TEMPORARY, 10 * 1024 * 1024, onInitFs, errorHandler); // set size to 10MB max
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
takePicture: function (success, fail, args, env) {
|
|
||||||
var destinationType = JSON.parse(decodeURIComponent(args[1]));
|
|
||||||
var sourceType = JSON.parse(decodeURIComponent(args[2]));
|
|
||||||
var result = new PluginResult(args, env);
|
|
||||||
var done = function (data) {
|
|
||||||
if (destinationType === DestinationType.FILE_URI) {
|
|
||||||
data = 'file://' + data;
|
|
||||||
result.callbackOk(data, false);
|
|
||||||
} else {
|
|
||||||
encodeBase64(data, function (data) {
|
|
||||||
if (/^data:/.test(data)) {
|
|
||||||
data = data.slice(data.indexOf(',') + 1);
|
|
||||||
result.callbackOk(data, false);
|
|
||||||
} else {
|
|
||||||
result.callbackError(data, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var cancel = function (reason) {
|
|
||||||
result.callbackError(reason, false);
|
|
||||||
};
|
|
||||||
var invoked = function (error) {
|
|
||||||
if (error) {
|
|
||||||
result.callbackError(error, false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (sourceType) {
|
|
||||||
case PictureSourceType.CAMERA:
|
|
||||||
if (invokeAvailable) {
|
|
||||||
window.qnx.webplatform.getApplication().cards.camera.open('photo', done, cancel, invoked);
|
|
||||||
} else {
|
|
||||||
showCameraDialog(done, cancel, fail);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PictureSourceType.PHOTOLIBRARY:
|
|
||||||
case PictureSourceType.SAVEDPHOTOALBUM:
|
|
||||||
window.qnx.webplatform.getApplication().cards.filePicker.open({
|
|
||||||
mode: 'Picker',
|
|
||||||
type: ['picture']
|
|
||||||
}, done, cancel, invoked);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.noResult(true);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* globals MozActivity */
|
|
||||||
|
|
||||||
function takePicture (success, error, opts) {
|
|
||||||
var pick = new MozActivity({
|
|
||||||
name: 'pick',
|
|
||||||
data: {
|
|
||||||
type: ['image/*']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
pick.onerror = error || function () {};
|
|
||||||
|
|
||||||
pick.onsuccess = function () {
|
|
||||||
// image is returned as Blob in this.result.blob
|
|
||||||
// we need to call success with url or base64 encoded image
|
|
||||||
if (opts && opts.destinationType === 0) {
|
|
||||||
// TODO: base64
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!opts || !opts.destinationType || opts.destinationType > 0) {
|
|
||||||
// url
|
|
||||||
return success(window.URL.createObjectURL(this.result.blob));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
takePicture: takePicture,
|
|
||||||
cleanup: function () {}
|
|
||||||
};
|
|
||||||
|
|
||||||
require('cordova/exec/proxy').add('Camera', module.exports);
|
|
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Copyright 2013 Canonical Ltd.
|
|
||||||
*
|
|
||||||
* 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 QtQuick 2.0
|
|
||||||
import QtMultimedia 5.0
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
property string shootImagePath: "shoot.png"
|
|
||||||
function isSuffix(str, suffix) {
|
|
||||||
return String(str).substr(String(str).length - suffix.length) == suffix
|
|
||||||
}
|
|
||||||
|
|
||||||
id: ui
|
|
||||||
color: "#252423"
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Camera {
|
|
||||||
objectName: "camera"
|
|
||||||
id: camera
|
|
||||||
onError: {
|
|
||||||
console.log(errorString);
|
|
||||||
}
|
|
||||||
videoRecorder.audioBitRate: 128000
|
|
||||||
imageCapture {
|
|
||||||
onImageSaved: {
|
|
||||||
root.exec("Camera", "onImageSaved", [path]);
|
|
||||||
ui.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VideoOutput {
|
|
||||||
id: output
|
|
||||||
source: camera
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
width: parent.width
|
|
||||||
height: shootButton.height
|
|
||||||
BorderImage {
|
|
||||||
id: leftBackground
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: middle.left
|
|
||||||
anchors.topMargin: units.dp(2)
|
|
||||||
anchors.bottomMargin: units.dp(2)
|
|
||||||
source: "toolbar-left.png"
|
|
||||||
Image {
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: parent.iconSpacing
|
|
||||||
source: "back.png"
|
|
||||||
width: units.gu(6)
|
|
||||||
height: units.gu(5)
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
root.exec("Camera", "cancel");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BorderImage {
|
|
||||||
id: middle
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
height: shootButton.height + units.gu(1)
|
|
||||||
width: shootButton.width
|
|
||||||
source: "toolbar-middle.png"
|
|
||||||
Image {
|
|
||||||
id: shootButton
|
|
||||||
width: units.gu(8)
|
|
||||||
height: width
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
source: shootImagePath
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
camera.imageCapture.captureToLocation(ui.parent.plugin('Camera').generateLocation("jpg"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BorderImage {
|
|
||||||
id: rightBackground
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: middle.right
|
|
||||||
anchors.topMargin: units.dp(2)
|
|
||||||
anchors.bottomMargin: units.dp(2)
|
|
||||||
source: "toolbar-right.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "camera.h"
|
|
||||||
#include <cordova.h>
|
|
||||||
|
|
||||||
#include <QCameraViewfinder>
|
|
||||||
#include <QCameraImageCapture>
|
|
||||||
#include <QGraphicsObject>
|
|
||||||
#include <QCloseEvent>
|
|
||||||
#include <QQuickItem>
|
|
||||||
|
|
||||||
const char code[] = "\
|
|
||||||
var component, object; \
|
|
||||||
function createObject() { \
|
|
||||||
component = Qt.createComponent(%1); \
|
|
||||||
if (component.status == Component.Ready) \
|
|
||||||
finishCreation(); \
|
|
||||||
else \
|
|
||||||
component.statusChanged.connect(finishCreation); \
|
|
||||||
} \
|
|
||||||
function finishCreation() { \
|
|
||||||
CordovaWrapper.global.cameraPluginWidget = component.createObject(root, \
|
|
||||||
{root: root, cordova: cordova}); \
|
|
||||||
} \
|
|
||||||
createObject()";
|
|
||||||
|
|
||||||
|
|
||||||
Camera::Camera(Cordova *cordova):
|
|
||||||
CPlugin(cordova),
|
|
||||||
_lastScId(0),
|
|
||||||
_lastEcId(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Camera::preprocessImage(QString &path) {
|
|
||||||
bool convertToPNG = (*_options.find("encodingType")).toInt() == Camera::PNG;
|
|
||||||
int quality = (*_options.find("quality")).toInt();
|
|
||||||
int width = (*_options.find("targetWidth")).toInt();
|
|
||||||
int height = (*_options.find("targetHeight")).toInt();
|
|
||||||
|
|
||||||
QImage image(path);
|
|
||||||
if (width <= 0)
|
|
||||||
width = image.width();
|
|
||||||
if (height <= 0)
|
|
||||||
height = image.height();
|
|
||||||
image = image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
||||||
|
|
||||||
QFile oldImage(path);
|
|
||||||
QTemporaryFile newImage;
|
|
||||||
|
|
||||||
const char *type;
|
|
||||||
if (convertToPNG) {
|
|
||||||
path = generateLocation("png");
|
|
||||||
type = "png";
|
|
||||||
} else {
|
|
||||||
path = generateLocation("jpg");
|
|
||||||
type = "jpg";
|
|
||||||
}
|
|
||||||
|
|
||||||
image.save(path, type, quality);
|
|
||||||
|
|
||||||
oldImage.remove();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::onImageSaved(QString path) {
|
|
||||||
bool dataURL = _options.find("destinationType")->toInt() == Camera::DATA_URL;
|
|
||||||
|
|
||||||
QString cbParams;
|
|
||||||
if (preprocessImage(path)) {
|
|
||||||
QString absolutePath = QFileInfo(path).absoluteFilePath();
|
|
||||||
if (dataURL) {
|
|
||||||
QFile image(absolutePath);
|
|
||||||
image.open(QIODevice::ReadOnly);
|
|
||||||
QByteArray content = image.readAll().toBase64();
|
|
||||||
cbParams = QString("\"%1\"").arg(content.data());
|
|
||||||
image.remove();
|
|
||||||
} else {
|
|
||||||
cbParams = CordovaInternal::format(QString("file://localhost") + absolutePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->callback(_lastScId, cbParams);
|
|
||||||
|
|
||||||
_lastEcId = _lastScId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
|
|
||||||
int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &/*popoverOptions*/, int/*cameraDirection*/) {
|
|
||||||
if (_camera.isNull()) {
|
|
||||||
_camera = QSharedPointer<QCamera>(new QCamera());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((_lastScId || _lastEcId) && (_lastScId != scId && _lastEcId != ecId)) || !_camera->isAvailable() || _camera->lockStatus() != QCamera::Unlocked) {
|
|
||||||
this->cb(_lastEcId, "Device is busy");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_options.clear();
|
|
||||||
_options.insert("quality", quality);
|
|
||||||
_options.insert("destinationType", destinationType);
|
|
||||||
_options.insert("targetWidth", targetWidth);
|
|
||||||
_options.insert("targetHeight", targetHeight);
|
|
||||||
_options.insert("encodingType", encodingType);
|
|
||||||
|
|
||||||
_lastScId = scId;
|
|
||||||
_lastEcId = ecId;
|
|
||||||
|
|
||||||
QString path = m_cordova->get_app_dir() + "/../qml/CaptureWidget.qml";
|
|
||||||
|
|
||||||
// TODO: relative url
|
|
||||||
QString qml = QString(code).arg(CordovaInternal::format(path));
|
|
||||||
m_cordova->execQML(qml);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::cancel() {
|
|
||||||
m_cordova->execQML("CordovaWrapper.global.cameraPluginWidget.destroy()");
|
|
||||||
this->cb(_lastEcId, "canceled");
|
|
||||||
|
|
||||||
_lastEcId = _lastScId = 0;
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CAMERA_H
|
|
||||||
#define CAMERA_H
|
|
||||||
|
|
||||||
#include <cplugin.h>
|
|
||||||
|
|
||||||
#include <QtCore>
|
|
||||||
#include <QQuickView>
|
|
||||||
#include <QCamera>
|
|
||||||
#include <QtMultimediaWidgets/QCameraViewfinder>
|
|
||||||
#include <QCameraImageCapture>
|
|
||||||
|
|
||||||
class Camera: public CPlugin {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit Camera(Cordova *cordova);
|
|
||||||
|
|
||||||
virtual const QString fullName() override {
|
|
||||||
return Camera::fullID();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const QString shortName() override {
|
|
||||||
return "Camera";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const QString fullID() {
|
|
||||||
return "Camera";
|
|
||||||
}
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
|
|
||||||
int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &popoverOptions, int cameraDirection);
|
|
||||||
void cancel();
|
|
||||||
|
|
||||||
void onImageSaved(QString path);
|
|
||||||
|
|
||||||
QString generateLocation(const QString &extension) {
|
|
||||||
int i = 1;
|
|
||||||
for (;;++i) {
|
|
||||||
QString path = QString("%1/.local/share/%2/persistent/%3.%4").arg(QDir::homePath())
|
|
||||||
.arg(QCoreApplication::applicationName()).arg(i).arg(extension);
|
|
||||||
|
|
||||||
if (!QFileInfo(path).exists())
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
bool preprocessImage(QString &path);
|
|
||||||
|
|
||||||
int _lastScId;
|
|
||||||
int _lastEcId;
|
|
||||||
QSharedPointer<QCamera> _camera;
|
|
||||||
|
|
||||||
QVariantMap _options;
|
|
||||||
protected:
|
|
||||||
enum DestinationType {
|
|
||||||
DATA_URL = 0,
|
|
||||||
FILE_URI = 1
|
|
||||||
};
|
|
||||||
enum EncodingType {
|
|
||||||
JPEG = 0,
|
|
||||||
PNG = 1
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CAMERA_H
|
|
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
534
src/wp/Camera.cs
534
src/wp/Camera.cs
@ -1,534 +0,0 @@
|
|||||||
/*
|
|
||||||
Licensed 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Net;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Ink;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Animation;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.Phone.Tasks;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.IO;
|
|
||||||
using System.IO.IsolatedStorage;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using Microsoft.Phone;
|
|
||||||
using Microsoft.Xna.Framework.Media;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace WPCordovaClassLib.Cordova.Commands
|
|
||||||
{
|
|
||||||
public class Camera : BaseCommand
|
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Return base64 encoded string
|
|
||||||
/// </summary>
|
|
||||||
private const int DATA_URL = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Return file uri
|
|
||||||
/// </summary>
|
|
||||||
private const int FILE_URI = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Return native uri
|
|
||||||
/// </summary>
|
|
||||||
private const int NATIVE_URI = 2;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Choose image from picture library
|
|
||||||
/// </summary>
|
|
||||||
private const int PHOTOLIBRARY = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Take picture from camera
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
private const int CAMERA = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Choose image from picture library
|
|
||||||
/// </summary>
|
|
||||||
private const int SAVEDPHOTOALBUM = 2;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Take a picture of type JPEG
|
|
||||||
/// </summary>
|
|
||||||
private const int JPEG = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Take a picture of type PNG
|
|
||||||
/// </summary>
|
|
||||||
private const int PNG = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Folder to store captured images
|
|
||||||
/// </summary>
|
|
||||||
private const string isoFolder = "CapturedImagesCache";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents captureImage action options.
|
|
||||||
/// </summary>
|
|
||||||
[DataContract]
|
|
||||||
public class CameraOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Source to getPicture from.
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "sourceType")]
|
|
||||||
public int PictureSourceType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Format of image that returned from getPicture.
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "destinationType")]
|
|
||||||
public int DestinationType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Quality of saved image
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "quality")]
|
|
||||||
public int Quality { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Controls whether or not the image is also added to the device photo album.
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "saveToPhotoAlbum")]
|
|
||||||
public bool SaveToPhotoAlbum { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ignored
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "correctOrientation")]
|
|
||||||
public bool CorrectOrientation { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Ignored
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "allowEdit")]
|
|
||||||
public bool AllowEdit { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Height in pixels to scale image
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "encodingType")]
|
|
||||||
public int EncodingType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Height in pixels to scale image
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "mediaType")]
|
|
||||||
public int MediaType { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Height in pixels to scale image
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "targetHeight")]
|
|
||||||
public int TargetHeight { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Width in pixels to scale image
|
|
||||||
/// </summary>
|
|
||||||
[DataMember(IsRequired = false, Name = "targetWidth")]
|
|
||||||
public int TargetWidth { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates options object with default parameters
|
|
||||||
/// </summary>
|
|
||||||
public CameraOptions()
|
|
||||||
{
|
|
||||||
this.SetDefaultValues(new StreamingContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes default values for class fields.
|
|
||||||
/// Implemented in separate method because default constructor is not invoked during deserialization.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context"></param>
|
|
||||||
[OnDeserializing()]
|
|
||||||
public void SetDefaultValues(StreamingContext context)
|
|
||||||
{
|
|
||||||
PictureSourceType = CAMERA;
|
|
||||||
DestinationType = FILE_URI;
|
|
||||||
Quality = 80;
|
|
||||||
TargetHeight = -1;
|
|
||||||
TargetWidth = -1;
|
|
||||||
SaveToPhotoAlbum = false;
|
|
||||||
CorrectOrientation = true;
|
|
||||||
AllowEdit = false;
|
|
||||||
MediaType = -1;
|
|
||||||
EncodingType = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Camera options
|
|
||||||
/// </summary>
|
|
||||||
CameraOptions cameraOptions;
|
|
||||||
|
|
||||||
public void takePicture(string options)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
|
|
||||||
// ["quality", "destinationType", "sourceType", "targetWidth", "targetHeight", "encodingType",
|
|
||||||
// "mediaType", "allowEdit", "correctOrientation", "saveToPhotoAlbum" ]
|
|
||||||
cameraOptions = new CameraOptions();
|
|
||||||
cameraOptions.Quality = int.Parse(args[0]);
|
|
||||||
cameraOptions.DestinationType = int.Parse(args[1]);
|
|
||||||
cameraOptions.PictureSourceType = int.Parse(args[2]);
|
|
||||||
cameraOptions.TargetWidth = int.Parse(args[3]);
|
|
||||||
cameraOptions.TargetHeight = int.Parse(args[4]);
|
|
||||||
cameraOptions.EncodingType = int.Parse(args[5]);
|
|
||||||
cameraOptions.MediaType = int.Parse(args[6]);
|
|
||||||
cameraOptions.AllowEdit = bool.Parse(args[7]);
|
|
||||||
cameraOptions.CorrectOrientation = bool.Parse(args[8]);
|
|
||||||
cameraOptions.SaveToPhotoAlbum = bool.Parse(args[9]);
|
|
||||||
|
|
||||||
// a very large number will force the other value to be the bound
|
|
||||||
if (cameraOptions.TargetWidth > -1 && cameraOptions.TargetHeight == -1)
|
|
||||||
{
|
|
||||||
cameraOptions.TargetHeight = 100000;
|
|
||||||
}
|
|
||||||
else if (cameraOptions.TargetHeight > -1 && cameraOptions.TargetWidth == -1)
|
|
||||||
{
|
|
||||||
cameraOptions.TargetWidth = 100000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Api supports FILE_URI, DATA_URL, NATIVE_URI destination types.
|
|
||||||
// Treat all other destination types as an error.
|
|
||||||
switch (cameraOptions.DestinationType)
|
|
||||||
{
|
|
||||||
case Camera.FILE_URI:
|
|
||||||
case Camera.DATA_URL:
|
|
||||||
case Camera.NATIVE_URI:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Incorrect option: destinationType"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChooserBase<PhotoResult> chooserTask = null;
|
|
||||||
if (cameraOptions.PictureSourceType == CAMERA)
|
|
||||||
{
|
|
||||||
chooserTask = new CameraCaptureTask();
|
|
||||||
}
|
|
||||||
else if ((cameraOptions.PictureSourceType == PHOTOLIBRARY) || (cameraOptions.PictureSourceType == SAVEDPHOTOALBUM))
|
|
||||||
{
|
|
||||||
chooserTask = new PhotoChooserTask();
|
|
||||||
}
|
|
||||||
// if chooserTask is still null, then PictureSourceType was invalid
|
|
||||||
if (chooserTask != null)
|
|
||||||
{
|
|
||||||
chooserTask.Completed += onTaskCompleted;
|
|
||||||
chooserTask.Show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.WriteLine("Unrecognized PictureSourceType :: " + cameraOptions.PictureSourceType.ToString());
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onTaskCompleted(object sender, PhotoResult e)
|
|
||||||
{
|
|
||||||
var task = sender as ChooserBase<PhotoResult>;
|
|
||||||
if (task != null)
|
|
||||||
{
|
|
||||||
task.Completed -= onTaskCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Error != null)
|
|
||||||
{
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (e.TaskResult)
|
|
||||||
{
|
|
||||||
case TaskResult.OK:
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string imagePathOrContent = string.Empty;
|
|
||||||
|
|
||||||
// Save image back to media library
|
|
||||||
// only save to photoalbum if it didn't come from there ...
|
|
||||||
if (cameraOptions.PictureSourceType == CAMERA && cameraOptions.SaveToPhotoAlbum)
|
|
||||||
{
|
|
||||||
MediaLibrary library = new MediaLibrary();
|
|
||||||
Picture pict = library.SavePicture(e.OriginalFileName, e.ChosenPhoto); // to save to photo-roll ...
|
|
||||||
}
|
|
||||||
|
|
||||||
int newAngle = 0;
|
|
||||||
// There's bug in Windows Phone 8.1 causing Seek on a DssPhotoStream not working properly.
|
|
||||||
// https://connect.microsoft.com/VisualStudio/feedback/details/783252
|
|
||||||
// But a mis-oriented file is better than nothing, so try and catch.
|
|
||||||
try {
|
|
||||||
int orient = ImageExifHelper.getImageOrientationFromStream(e.ChosenPhoto);
|
|
||||||
switch (orient) {
|
|
||||||
case ImageExifOrientation.LandscapeLeft:
|
|
||||||
newAngle = 90;
|
|
||||||
break;
|
|
||||||
case ImageExifOrientation.PortraitUpsideDown:
|
|
||||||
newAngle = 180;
|
|
||||||
break;
|
|
||||||
case ImageExifOrientation.LandscapeRight:
|
|
||||||
newAngle = 270;
|
|
||||||
break;
|
|
||||||
case ImageExifOrientation.Portrait:
|
|
||||||
default: break; // 0 default already set
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
Debug.WriteLine("Error fetching orientation from Exif");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newAngle != 0)
|
|
||||||
{
|
|
||||||
using (Stream rotImageStream = ImageExifHelper.RotateStream(e.ChosenPhoto, newAngle))
|
|
||||||
{
|
|
||||||
// we should reset stream position after saving stream to media library
|
|
||||||
rotImageStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
if (cameraOptions.DestinationType == DATA_URL)
|
|
||||||
{
|
|
||||||
imagePathOrContent = GetImageContent(rotImageStream);
|
|
||||||
}
|
|
||||||
else // FILE_URL or NATIVE_URI (both use the same resultant uri format)
|
|
||||||
{
|
|
||||||
imagePathOrContent = SaveImageToLocalStorage(rotImageStream, Path.GetFileName(e.OriginalFileName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // no need to reorient
|
|
||||||
{
|
|
||||||
if (cameraOptions.DestinationType == DATA_URL)
|
|
||||||
{
|
|
||||||
imagePathOrContent = GetImageContent(e.ChosenPhoto);
|
|
||||||
}
|
|
||||||
else // FILE_URL or NATIVE_URI (both use the same resultant uri format)
|
|
||||||
{
|
|
||||||
imagePathOrContent = SaveImageToLocalStorage(e.ChosenPhoto, Path.GetFileName(e.OriginalFileName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.OK, imagePathOrContent));
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Error retrieving image."));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TaskResult.Cancel:
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection cancelled."));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection did not complete!"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns image content in a form of base64 string
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">Image stream</param>
|
|
||||||
/// <returns>Base64 representation of the image</returns>
|
|
||||||
private string GetImageContent(Stream stream)
|
|
||||||
{
|
|
||||||
byte[] imageContent = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Resize photo and convert to JPEG
|
|
||||||
imageContent = ResizePhoto(stream);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
stream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Convert.ToBase64String(imageContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resize image
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">Image stream</param>
|
|
||||||
/// <returns>resized image</returns>
|
|
||||||
private byte[] ResizePhoto(Stream stream)
|
|
||||||
{
|
|
||||||
//output
|
|
||||||
byte[] resizedFile;
|
|
||||||
|
|
||||||
BitmapImage objBitmap = new BitmapImage();
|
|
||||||
objBitmap.SetSource(stream);
|
|
||||||
objBitmap.CreateOptions = BitmapCreateOptions.None;
|
|
||||||
|
|
||||||
WriteableBitmap objWB = new WriteableBitmap(objBitmap);
|
|
||||||
objBitmap.UriSource = null;
|
|
||||||
|
|
||||||
// Calculate resultant image size
|
|
||||||
int width, height;
|
|
||||||
if (cameraOptions.TargetWidth >= 0 && cameraOptions.TargetHeight >= 0)
|
|
||||||
{
|
|
||||||
// Keep proportionally
|
|
||||||
double ratio = Math.Min(
|
|
||||||
(double)cameraOptions.TargetWidth / objWB.PixelWidth,
|
|
||||||
(double)cameraOptions.TargetHeight / objWB.PixelHeight);
|
|
||||||
width = Convert.ToInt32(ratio * objWB.PixelWidth);
|
|
||||||
height = Convert.ToInt32(ratio * objWB.PixelHeight);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = objWB.PixelWidth;
|
|
||||||
height = objWB.PixelHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Hold the result stream
|
|
||||||
using (MemoryStream objBitmapStreamResized = new MemoryStream())
|
|
||||||
{
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// resize the photo with user defined TargetWidth & TargetHeight
|
|
||||||
Extensions.SaveJpeg(objWB, objBitmapStreamResized, width, height, 0, cameraOptions.Quality);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
//Dispose bitmaps immediately, they are memory expensive
|
|
||||||
DisposeImage(objBitmap);
|
|
||||||
DisposeImage(objWB);
|
|
||||||
GC.Collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Convert the resized stream to a byte array.
|
|
||||||
int streamLength = (int)objBitmapStreamResized.Length;
|
|
||||||
resizedFile = new Byte[streamLength]; //-1
|
|
||||||
objBitmapStreamResized.Position = 0;
|
|
||||||
|
|
||||||
//for some reason we have to set Position to zero, but we don't have to earlier when we get the bytes from the chosen photo...
|
|
||||||
objBitmapStreamResized.Read(resizedFile, 0, streamLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resizedFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Util: Dispose a bitmap resource
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="image">BitmapSource subclass to dispose</param>
|
|
||||||
private void DisposeImage(BitmapSource image)
|
|
||||||
{
|
|
||||||
if (image != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var ms = new MemoryStream(new byte[] { 0x0 }))
|
|
||||||
{
|
|
||||||
image.SetSource(ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Saves captured image in isolated storage
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="imageFileName">image file name</param>
|
|
||||||
/// <returns>Image path</returns>
|
|
||||||
private string SaveImageToLocalStorage(Stream stream, string imageFileName)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (stream == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("imageBytes");
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
|
|
||||||
|
|
||||||
if (!isoFile.DirectoryExists(isoFolder))
|
|
||||||
{
|
|
||||||
isoFile.CreateDirectory(isoFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
string filePath = System.IO.Path.Combine("///" + isoFolder + "/", imageFileName);
|
|
||||||
|
|
||||||
using (IsolatedStorageFileStream outputStream = isoFile.CreateFile(filePath))
|
|
||||||
{
|
|
||||||
BitmapImage objBitmap = new BitmapImage();
|
|
||||||
objBitmap.SetSource(stream);
|
|
||||||
objBitmap.CreateOptions = BitmapCreateOptions.None;
|
|
||||||
|
|
||||||
WriteableBitmap objWB = new WriteableBitmap(objBitmap);
|
|
||||||
objBitmap.UriSource = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
//use photo's actual width & height if user doesn't provide width & height
|
|
||||||
if (cameraOptions.TargetWidth < 0 && cameraOptions.TargetHeight < 0)
|
|
||||||
{
|
|
||||||
objWB.SaveJpeg(outputStream, objWB.PixelWidth, objWB.PixelHeight, 0, cameraOptions.Quality);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Resize
|
|
||||||
//Keep proportionally
|
|
||||||
double ratio = Math.Min((double)cameraOptions.TargetWidth / objWB.PixelWidth, (double)cameraOptions.TargetHeight / objWB.PixelHeight);
|
|
||||||
int width = Convert.ToInt32(ratio * objWB.PixelWidth);
|
|
||||||
int height = Convert.ToInt32(ratio * objWB.PixelHeight);
|
|
||||||
|
|
||||||
// resize the photo with user defined TargetWidth & TargetHeight
|
|
||||||
objWB.SaveJpeg(outputStream, width, height, 0, cameraOptions.Quality);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
//Dispose bitmaps immediately, they are memory expensive
|
|
||||||
DisposeImage(objBitmap);
|
|
||||||
DisposeImage(objWB);
|
|
||||||
GC.Collect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Uri(filePath, UriKind.Relative).ToString();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
//TODO: log or do something else
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
stream.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
<!--
|
|
||||||
Licensed 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.
|
|
||||||
-->
|
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script src="camera.js" type="text/javascript"></script>
|
|
||||||
<script>
|
|
||||||
var meta = document.createElement("meta");
|
|
||||||
meta.setAttribute('name','viewport');
|
|
||||||
meta.setAttribute('content','initial-scale='+ (1/window.devicePixelRatio) + ',user-scalable=no');
|
|
||||||
document.getElementsByTagName('head')[0].appendChild(meta);
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<style type="text/css">
|
|
||||||
body {
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
.action-bar {
|
|
||||||
position: fixed;
|
|
||||||
left: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
height: 100px;
|
|
||||||
width: 100%;
|
|
||||||
background-image: linear-gradient(rgb(41, 41, 41), rgb(32, 32, 32));
|
|
||||||
}
|
|
||||||
.action-bar-back {
|
|
||||||
width: 78px;
|
|
||||||
height: 100px;
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
.action-bar-divider {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0px;
|
|
||||||
left: 78px;
|
|
||||||
width: 28px;
|
|
||||||
height: 100px;
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAABkCAYAAACVfFA4AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3ggLDiUo1ElOKAAABHdJREFUaN612ktvE1cUB/Bz7bGdGcePJk1i4tA0DomCRJUQEGphAa3KQwGpUHWFYMEiIBZdtKgfADbdsekXaFW1XZUuQAiFh0BRi+iqap2EJrUSJSjg2I7Hk3GmdmwPi5Z4ziQEx57/XeXKUn6255w558y1ICKTUOvKverfpkl0/ahwEXKZ1c/iLhlERAQDu85etcrkX3mGBbPhPiIhXnkUyPyNBfO+1upGEIUyU1iQXG52LSd/HRNY0BIwPiNbfR8Iq+3CN5brZ5KiJrBgLrCT7cPpKSxYlPyWgBE0e/d7AQMHDh0nEhavVOSx5DRodA6zm6WSX8SC2dYBFjCvEh4GrsjtbB9MT2BB0+Vh++nx2wIG7jp2liW8VNQ23oAc/To79lavH5nkV+ewoBrqsVak9Rs2DCx4Q6xCfDbUKcHA/R+dsnydRKJSputfXyvDwHSgl1cIPbl51XLs+rXvYQnfnJ3BgprSyfah1AQWrLh9ZI2YxKNfBAzs//A0a2/da/nXdx5OgHpkH9sr2jwWVFv6eIVIT2HBVV8Lq/DB9CQWZP/GrNDTJw8FDIydHGUB4zXStb61OvOvY5BXiOUEFlSb3+EVYouAcQQsSTKrEHP3fxQwsP/gCdYSukqF7YRXHS1hlLeE8v8zIAzMtu62tYTTWDAvt7HrF0jFsaApJBahM7+NCRjYe+wcS3hPIbfde9I2W8LIEK8Q2QQWVEMxFjDB1CQWLHoCrEIs3P1OwMD/WkKLV16rp67UvpYCu1jCN+kvsKC9JfQvT2NBXdnB9rUkfEMgawkF0ez4TQEDe4+c4S1hMV9vM1Jjw7RjH3vapGwyAzoKqm/1sSmp+Q0VvmHQ8IVZwn85MuSFguwpYaVMX31+eQ0Gdo9cZDOgdzXdSAdbQ0sYGeQBk5nBgiuBnSxggqm/sGDJrbCAmX/0s4CBvQdPsIR3rRmNTiFvagmtM6BJsraABXMtA+xYwJ96igVXlTZbhZjAgqZLYl9p4vf7Agb2fHyOPyU0VCdG1y3yr3Mvr/A1toR1g1qwh+39S3EsWPTylnDxwQ8CBg7bW0LbsYDj4FKQt4Q+/TkW1Nre4+dIqSksqPt5SxhMxbFgxW09FhA09/iOgIGxw2fY9XMXdSefWW0yUkeHWYTK6iwW1MJ9tC6aJvlrnAHrBo0m/pTwxtVRFxQk6+8KKmU69P4BEwZ2j4w23BJuC1Q7hnjC284BHQd128FxczKOBcuSwhL+2fgNAQNjHxznLWHJIKfWpqDRxY8FmnILWFCzPSV0IuG3BPPK2yzho//OYUESHjYl/fHgloCB3UfPs4T3GMvk5NoA5iODvEJk/sGCWijGK8RSHAvaW8LnD38SUJDFTrlITi8GRj/5gr3oW1nEglo7bwnlOmfAmkFdiVjv1xRI/okFTclrHQFp/smYgIHvHv6U/5awoBFirYOr0WH2gpydxYK5cD+vEA4n/Aaw0BRiCZ+8962AgrwlLBFquYiIuk5ess2ASRgoERHp7XtIUGUdlTPTVACBLwEignyX5voIbgAAAABJRU5ErkJggg==);
|
|
||||||
}
|
|
||||||
.action-bar-back-button {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 35px;
|
|
||||||
left: 34px;
|
|
||||||
width: 18px;
|
|
||||||
height: 28px;
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAcCAYAAABsxO8nAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3ggLDh43ZfOs5QAAAvdJREFUOMuVlU9LMm0Uh6+ZRguUKaNoWbs0QVIMCb9CqQtb1UdI2lS0dBNhn6D2EVQQLaM2UZpTUknRwm3UooI2lTZ/9H42b/M+g2k+A/fmPjcXF+f8OAMg/vVEIhFRLBbF4+Oj0DRNjI2NCem/YsdfJBJhf38fWZbtu4eHBzoGSZJELBZjZ2cHSZKa6nKnkKmpKQ4ODgAQQjhOpVL53UiWZaanp9nY2EDX9ab6+/s76XS6vVFXVxepVIrNzc0fIU9PTySTSSqVCkoriKIozM7OksvlqNVqjpoQwoa8vb217pHL5SKTybC+vk61WnX0o9FocH9/TyKRsCFAs5Hb7SaTybC8vMzn56ej1mg0uL29ZWZmhnq93npqHo+HhYUFlpaW+Pj4sC0ALMuiUCiQTqebIA4jr9dLNptlbm7OYSJJEqZpcnx8zPz8fOuIAEJVVdbW1kilUo7GSpJErVbj8PCQxcXF9lnz+XxidXWVRCLRNJ1qtcr29ja5XO7X0MorKyskk8kmiCzLHB0ddQQBkF9eXnh9fUWSpKboK4rCwMBAR6CuYrGYdbvdBAIBuru77SkJIQiFQoyMjKBpGtVqtT0IyF5cXKAoCuFwGEX5P1qWZeH3+xkeHiafz/P19dUeBFAqlejr68Pv9+NyuWwz0zQJBAKoqkq5XG7qZRMI4OzsDFVVCQQCuFwu+5FhGExMTKCqKtfX1z/CHCCAQqGA1+tlfHzcHgCArutEo1E8Hg+lUgnDMNqDAM7PzxkcHMTv9yPLsg0zDINoNIosy9zd3TlWy48ggJOTE/r7+wkGg47Vapom8XgcRVG4ubmxzVqCAE5PT+nt7SUcDtNoNOx7XdeZnJwE4OrqCsuy2oMA8vk8Q0NDBINBxzYwDINYLMb3xH8FfZv5fD5CoZAN+s5ZPB5H07TOQEII8vk8qqoSjUaxLMu2M02T5+fnzn5HAPV6nVwux+7uLm63277v6emhXC53ZvT3qr28vMTn8zE6OgrA3t4eW1tb/AH4Zo+8fEoEngAAAABJRU5ErkJggg==);
|
|
||||||
}
|
|
||||||
.camera-cross-hairs {
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
-webkit-transform: translate(-50%, -147px);
|
|
||||||
width: 194px;
|
|
||||||
height: 195px;
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAQAAAB6tAYfAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfeCAsPDxicOdibAAACbElEQVR42u3a7U7aYBgG4Oet0yZLTMx2bDu5nYo7nSUmzi34DUSe/bA0UHSDbpS5Xpc/sECNuW/a5yV5I4CI8toL03y31R94ipMy7gj/PKmNp7/lWSx27PEuzkZaxFWe7viJL3EdH8ovS5hnRkTu+K9UcVzGehX0u/WsXxNVt4LcuYLoccb/ok9WGRHzfKWEWS56xvkw2hLue1a3WKuh9L+wluqRD+bH7BdA6Q7qr59mOW1/LBr3Wdky5VlenK9dCattjv2TPdwwXy5oqu4iSQX7VpfsjPVq7OubQ1i8VMLFefndF2j24i7b1O/z6LWJzT4Wtp28K5EcnhKUgBKUgBKUgBKUgBKUgBKUgBKUgBKUgBLeSglP7eFMIgPo5t3Zd2TDyzCWe4/q1X1HPz5HREykM5BJyBsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWhfn05zl95TEMC5zmrO8bPIuzw+zfD44LgIawjxzJe8qIuI2MzIyFnHnWhjATS6avG+zLaFqXz6W0ACO2t9OYj1/DkYJSkAJSkAJSkAJSkAJSkAJSkAJSkAJSkAJb6WE6y+COIzbiGh3WzxmaQ5P7LfYu4dc3oDq4nb0j8yA5ni50yWbHUjsz2bCTQmTlakwVcMeraZ73TyWzftUiYiMjO2Gw1O8H/kUuc+jrd6XUZpsY20ixGrSy+HceXoLN/FxpEVc5elO71+9ydTlxbT73oiq0e5hneei55l1eWVQ1z2jHO8Qyb9QwcZqqS6TPuve8a74e5wz2fiwl22m+C6tjnu9IyngTfsJ8D+4z5r15Y4AAAAASUVORK5CYII=);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<body>
|
|
||||||
<div id="camera">
|
|
||||||
<video id="v"></video>
|
|
||||||
<div class="camera-cross-hairs"></div>
|
|
||||||
</div>
|
|
||||||
<canvas id="c" style="display: none;"></canvas>
|
|
||||||
<div class="action-bar">
|
|
||||||
<div id="back" class="action-bar-back">
|
|
||||||
<div class="action-bar-back-button"></div>
|
|
||||||
</div>
|
|
||||||
<div class="action-bar-divider"></div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
document.getElementById('back').onclick = function () {
|
|
||||||
window.qnx.callExtensionMethod('cordova-plugin-camera', 'cancel');
|
|
||||||
};
|
|
||||||
window.navigator.webkitGetUserMedia(
|
|
||||||
{ video: true },
|
|
||||||
function (stream) {
|
|
||||||
var video = document.getElementById('v');
|
|
||||||
var canvas = document.getElementById('c');
|
|
||||||
var camera = document.getElementById('camera');
|
|
||||||
video.autoplay = true;
|
|
||||||
video.width = window.innerWidth;
|
|
||||||
video.height = window.innerHeight - 100;
|
|
||||||
video.src = window.webkitURL.createObjectURL(stream);
|
|
||||||
camera.onclick = function () {
|
|
||||||
canvas.width = video.videoWidth;
|
|
||||||
canvas.height = video.videoHeight;
|
|
||||||
canvas.getContext('2d').drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
|
|
||||||
window.qnx.callExtensionMethod('cordova-plugin-camera', canvas.toDataURL('img/png'));
|
|
||||||
};
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
window.qnx.callExtensionMethod('cordova-plugin-camera', 'error', 'getUserMedia failed');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
Loading…
Reference in New Issue
Block a user