diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 7a4a3ea..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 8ec56a5..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache Cordova
-Copyright 2012 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index f84180e..dcda226 100644
--- a/README.md
+++ b/README.md
@@ -20,3 +20,5 @@
# org.apache.cordova.camera
Plugin documentation: [doc/index.md](doc/index.md)
+
+This is `dev` - the deprecated development branch of this plugin; development of this plugin has moved to the `master` branch
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
deleted file mode 100644
index 836bc27..0000000
--- a/RELEASENOTES.md
+++ /dev/null
@@ -1,82 +0,0 @@
-
-# Release Notes
-
-### 0.2.1 (Sept 5, 2013)
-* [CB-4656] Don't add line-breaks to base64-encoded images (Fixes type=DataURI)
-* [CB-4432] copyright notice change
-
-### 0.2.3 (Sept 25, 2013)
-* CB-4889 bumping&resetting version
-* CB-4889 forgot index.html
-* CB-4889 renaming core inside cameraProxy
-* [Windows8] commandProxy has moved
-* [Windows8] commandProxy has moved
-* added Camera API for FirefoxOS
-* Rename CHANGELOG.md -> RELEASENOTES.md
-* [CB-4823] Fix XCode 5 camera plugin warnings
-* Fix compiler warnings
-* [CB-4765] Move ExifHelper.java into Camera Plugin
-* [CB-4764] Remove reference to DirectoryManager from CameraLauncher
-* [CB-4763] Use a copy of FileHelper.java within camera-plugin.
-* [CB-4752] Incremented plugin version on dev branch.
-* CB-4633: We really should close cursors. It's just the right thing to do.
-* No longer causes a stack trace, but it doesn't cause the error to be called.
-* CB-4889 renaming org.apache.cordova.core.camera to org.apache.cordova.camera
-
- ### 0.2.4 (Oct 28, 2013)
-* CB-5128: added repo + issue tag to plugin.xml for camera plugin
-* CB-4958 - iOS - Camera plugin should not show the status bar
-* [CB-4919] updated plugin.xml for FxOS
-* [CB-4915] Incremented plugin version on dev branch.
-
-### 0.2.5 (Dec 4, 2013)
-* fix camera for firefox os
-* getPicture via web activities
-* [ubuntu] specify policy_group
-* add ubuntu platform
-* 1. User Agent detection now detects AmazonWebView. 2. Change to use amazon-fireos as the platform if user agent string contains 'cordova-amazon-fireos'
-* Added amazon-fireos platform.
-
-### 0.2.6 (Jan 02, 2014)
-* CB-5658 Add doc/index.md for Camera plugin
-* CB-2442 CB-2419 Use Windows.Storage.ApplicationData.current.localFolder, instead of writing to app package.
-* [BlackBerry10] Adding platform level permissions
-* CB-5599 Android: Catch and ignore OutOfMemoryError in getRotatedBitmap()
-
-### 0.2.7 (Feb 05, 2014)
-* CB-4919 firefox os quirks added and supported platforms list is updated
-* getPicture via web activities
-* Documented quirk for CB-5335 + CB-5206 for WP7+8
-* reference the correct firefoxos implementation
-* [BlackBerry10] Add permission to access_shared
-
-### 0.2.8 (Feb 26, 2014)
-* CB-1826 Catch OOM on gallery image resize
-
-### 0.2.9 (Apr 17, 2014)
-* CB-6460: Update license headers
-* CB-6422: [windows8] use cordova/exec/proxy
-* [WP8] When only targetWidth or targetHeight is provided, use it as the only bound
-* CB-4027, CB-5102, CB-2737, CB-2387: [WP] Fix camera issues, cropping, memory leaks
-* CB-6212: [iOS] fix warnings compiled under arm64 64-bit
-* [BlackBerry10] Add rim xml namespaces declaration
-* Add NOTICE file
diff --git a/doc/index.md b/doc/index.md
deleted file mode 100644
index edd881f..0000000
--- a/doc/index.md
+++ /dev/null
@@ -1,441 +0,0 @@
-
-
-# org.apache.cordova.camera
-
-This plugin provides an API for taking pictures and for choosing images from
-the system's image library.
-
- cordova plugin add org.apache.cordova.camera
-
-
-## navigator.camera.getPicture
-
-Takes a photo using the camera, or retrieves a photo from the device's
-image gallery. The image is passed to the success callback as a
-base64-encoded `String`, or as the URI for the image file. The method
-itself returns a `CameraPopoverHandle` object that can be used to
-reposition the file selection popover.
-
- navigator.camera.getPicture( cameraSuccess, cameraError, [ cameraOptions ] );
-
-### Description
-
-The `camera.getPicture` function opens the device's default camera
-application that allows users to snap pictures. This behavior occurs
-by default, when `Camera.sourceType` equals
-`Camera.PictureSourceType.CAMERA`. Once the user snaps the photo, the
-camera application closes and the application is restored.
-
-If `Camera.sourceType` is `Camera.PictureSourceType.PHOTOLIBRARY` or
-`Camera.PictureSourceType.SAVEDPHOTOALBUM`, then a dialog displays
-that allows users to select an existing image. The
-`camera.getPicture` function returns a `CameraPopoverHandle` object,
-which can be used to reposition the image selection dialog, for
-example, when the device orientation changes.
-
-The return value is sent to the `cameraSuccess` callback function, in
-one of the following formats, depending on the specified
-`cameraOptions`:
-
-- A `String` containing the base64-encoded photo image.
-
-- A `String` representing the image file location on local storage (default).
-
-You can do whatever you want with the encoded image or URI, for
-example:
-
-- Render the image in an `
` tag, as in the example below
-
-- Save the data locally (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
-
-- Post the data to a remote server
-
-__NOTE__: Photo resolution on newer devices is quite good. Photos
-selected from the device's gallery are not downscaled to a lower
-quality, even if a `quality` parameter is specified. To avoid common
-memory problems, set `Camera.destinationType` to `FILE_URI` rather
-than `DATA_URL`.
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Tizen
-- Windows Phone 7 and 8
-- Windows 8
-
-### Amazon Fire OS Quirks
-
-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 4.4 only*: Android 4.4 introduced a new [Storage Access Framework](https://developer.android.com/guide/topics/providers/document-provider.html) that makes it
-easier for users to browse and open documents across all of their preferred document storage providers.
-Cordova has not yet been fully integrated with this new Storage Access Framework. Because of this, the `getPicture()`
-method will not correctly return pictures when the user selects from the "Recent", "Drive", "Images", or "External
-Storage" folders when the `destinationType` is `FILE_URI`. However, the user will be able to correctly select any pictures
-if they go through the "Gallery" app first. Potential workarounds for this issue are documented on [this StackOverflow question](http://stackoverflow.com/questions/19834842/android-gallery-on-kitkat-returns-different-uri-for-intent-action-get-content/20177611). Please see [CB-5398](https://issues.apache.org/jira/browse/CB-5398) to track this issue.
-
-Android 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.
-
-### Firefox OS Quirks
-
-Camera plugin is currently implemented using [Web Activities](https://hacks.mozilla.org/2013/01/introducing-web-activities/).
-
-### iOS Quirks
-
-Including a JavaScript `alert()` in either of the callback functions
-can cause problems. Wrap the alert within a `setTimeout()` to allow
-the iOS image picker or popover to fully close before the alert
-displays:
-
- setTimeout(function() {
- // do your thing here!
- }, 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.
-
-### Tizen Quirks
-
-Tizen only supports a `destinationType` of
-`Camera.DestinationType.FILE_URI` and a `sourceType` of
-`Camera.PictureSourceType.PHOTOLIBRARY`.
-
-### Example
-
-Take a photo and retrieve it as a base64-encoded image:
-
- navigator.camera.getPicture(onSuccess, onFail, { quality: 50,
- destinationType: Camera.DestinationType.DATA_URL
- });
-
- function onSuccess(imageData) {
- var image = document.getElementById('myImage');
- image.src = "data:image/jpeg;base64," + imageData;
- }
-
- function onFail(message) {
- alert('Failed because: ' + message);
- }
-
-Take a photo and retrieve the image's file location:
-
- navigator.camera.getPicture(onSuccess, onFail, { quality: 50,
- destinationType: Camera.DestinationType.FILE_URI });
-
- function onSuccess(imageURI) {
- var image = document.getElementById('myImage');
- image.src = imageURI;
- }
-
- function onFail(message) {
- alert('Failed because: ' + message);
- }
-
-## CameraOptions
-
-Optional parameters to customize the camera settings.
-
- { quality : 75,
- destinationType : Camera.DestinationType.DATA_URL,
- sourceType : Camera.PictureSourceType.CAMERA,
- allowEdit : true,
- encodingType: Camera.EncodingType.JPEG,
- targetWidth: 100,
- targetHeight: 100,
- popoverOptions: CameraPopoverOptions,
- saveToPhotoAlbum: false };
-
-### Options
-
-- __quality__: Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. _(Number)_ (Note that information about the camera's resolution is unavailable.)
-
-- __destinationType__: Choose the format of the return value. Defined in `navigator.camera.DestinationType` _(Number)_
-
- Camera.DestinationType = {
- DATA_URL : 0, // Return image as base64-encoded string
- FILE_URI : 1, // Return image file URI
- NATIVE_URI : 2 // Return image native URI (e.g., assets-library:// on iOS or content:// on Android)
- };
-
-- __sourceType__: Set the source of the picture. Defined in `navigator.camera.PictureSourceType` _(Number)_
-
- Camera.PictureSourceType = {
- PHOTOLIBRARY : 0,
- CAMERA : 1,
- SAVEDPHOTOALBUM : 2
- };
-
-- __allowEdit__: Allow simple editing of image before selection. _(Boolean)_
-
-- __encodingType__: Choose the returned image file's encoding. Defined in `navigator.camera.EncodingType` _(Number)_
-
- Camera.EncodingType = {
- JPEG : 0, // Return JPEG encoded image
- PNG : 1 // Return PNG encoded image
- };
-
-- __targetWidth__: Width in pixels to scale image. Must be used with __targetHeight__. Aspect ratio remains constant. _(Number)_
-
-- __targetHeight__: Height in pixels to scale image. Must be used with __targetWidth__. Aspect ratio remains constant. _(Number)_
-
-- __mediaType__: Set the type of media to select from. Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`. Defined in `nagivator.camera.MediaType` _(Number)_
-
- Camera.MediaType = {
- PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
- VIDEO: 1, // allow selection of video only, WILL ALWAYS RETURN FILE_URI
- ALLMEDIA : 2 // allow selection from all media types
-};
-
-- __correctOrientation__: Rotate the image to correct for the orientation of the device during capture. _(Boolean)_
-
-- __saveToPhotoAlbum__: Save the image to the photo album on the device after capture. _(Boolean)_
-
-- __popoverOptions__: iOS-only options that specify popover location in iPad. Defined in `CameraPopoverOptions`.
-
-- __cameraDirection__: Choose the camera to use (front- or back-facing). Defined in `navigator.camera.Direction` _(Number)_
-
- Camera.Direction = {
- BACK : 0, // Use the back-facing camera
- FRONT : 1 // Use the front-facing camera
- };
-
-### Amazon Fire OSQuirks
-
-- 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
-
-- 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.
-
-### BlackBerry 10 Quirks
-
-- Ignores the `quality` parameter.
-
-- Ignores the `sourceType` 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
-
-- 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. You may delete the contents of this directory using the `navigator.fileMgr` APIs if storage space is a concern.
-
-### 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 `mediaType` property of `cameraOptions` as the Windows Phone SDK does not provide a way to choose videos from PHOTOLIBRARY.
-
-
-## CameraError
-
-onError callback function that provides an error message.
-
- function(message) {
- // Show a helpful message
- }
-
-### Parameters
-
-- __message__: The message is provided by the device's native code. _(String)_
-
-
-## cameraSuccess
-
-onSuccess callback function that provides the image data.
-
- function(imageData) {
- // Do something with the image
- }
-
-### Parameters
-
-- __imageData__: Base64 encoding of the image data, _or_ the image file URI, depending on `cameraOptions` in effect. _(String)_
-
-### Example
-
- // Show image
- //
- function cameraCallback(imageData) {
- var image = document.getElementById('myImage');
- image.src = "data:image/jpeg;base64," + imageData;
- }
-
-
-## CameraPopoverHandle
-
-A handle to the popover dialog created by `navigator.camera.getPicture`.
-
-### Methods
-
-- __setPosition__: Set the position of the popover.
-
-### Supported Platforms
-
-- iOS
-
-### setPosition
-
-Set the position of the popover.
-
-__Parameters__:
-
-- `cameraPopoverOptions`: the `CameraPopoverOptions` that specify the new position
-
-### Example
-
- var cameraPopoverHandle = navigator.camera.getPicture(onSuccess, onFail,
- { destinationType: Camera.DestinationType.FILE_URI,
- sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
- popoverOptions: new CameraPopoverOptions(300, 300, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY)
- });
-
- // Reposition the popover if the orientation changes.
- window.onorientationchange = function() {
- var cameraPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY);
- cameraPopoverHandle.setPosition(cameraPopoverOptions);
- }
-
-
-## CameraPopoverOptions
-
-iOS-only parameters that specify the anchor element location and arrow
-direction of the popover when selecting images from an iPad's library
-or album.
-
- { x : 0,
- y : 32,
- width : 320,
- height : 480,
- arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
- };
-
-### CameraPopoverOptions
-
-- __x__: x pixel coordinate of screen element onto which to anchor the popover. _(Number)_
-
-- __y__: y pixel coordinate of screen element onto which to anchor the popover. _(Number)_
-
-- __width__: width, in pixels, of the screen element onto which to anchor the popover. _(Number)_
-
-- __height__: height, in pixels, of the screen element onto which to anchor the popover. _(Number)_
-
-- __arrowDir__: Direction the arrow on the popover should point. Defined in `Camera.PopoverArrowDirection` _(Number)_
-
- Camera.PopoverArrowDirection = {
- ARROW_UP : 1, // matches iOS UIPopoverArrowDirection constants
- ARROW_DOWN : 2,
- ARROW_LEFT : 4,
- ARROW_RIGHT : 8,
- ARROW_ANY : 15
- };
-
-Note that the size of the popover may change to adjust to the
-direction of the arrow and orientation of the screen. Make sure to
-account for orientation changes when specifying the anchor element
-location.
-
-## navigator.camera.cleanup
-
-Removes intermediate photos taken by the camera from temporary
-storage.
-
- navigator.camera.cleanup( cameraSuccess, cameraError );
-
-### Description
-
-Removes intermediate image files that are kept in temporary storage
-after calling `camera.getPicture`. Applies only when the value of
-`Camera.sourceType` equals `Camera.PictureSourceType.CAMERA` and the
-`Camera.destinationType` equals `Camera.DestinationType.FILE_URI`.
-
-### Supported Platforms
-
-- iOS
-
-### Example
-
- navigator.camera.cleanup(onSuccess, onFail);
-
- function onSuccess() {
- console.log("Camera cleanup success.")
- }
-
- function onFail(message) {
- alert('Failed because: ' + message);
- }
-
diff --git a/plugin.xml b/plugin.xml
deleted file mode 100644
index a51f172..0000000
--- a/plugin.xml
+++ /dev/null
@@ -1,219 +0,0 @@
-
-
-
-
- Camera
- Cordova Camera Plugin
- Apache 2.0
- cordova,camera
- https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git
- https://issues.apache.org/jira/browse/CB/component/12320645
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- access_shared
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/android/CameraLauncher.java b/src/android/CameraLauncher.java
deleted file mode 100755
index 57878ab..0000000
--- a/src/android/CameraLauncher.java
+++ /dev/null
@@ -1,866 +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.
-*/
-package org.apache.cordova.camera;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.LOG;
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import android.app.Activity;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import android.graphics.Bitmap.CompressFormat;
-import android.media.MediaScannerConnection;
-import android.media.MediaScannerConnection.MediaScannerConnectionClient;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.util.Base64;
-import android.util.Log;
-
-/**
- * This class launches the camera view, allows the user to take a picture, closes the camera view,
- * and returns the captured image. When the camera view is closed, the screen displayed before
- * the camera view was shown is redisplayed.
- */
-public class CameraLauncher extends CordovaPlugin implements MediaScannerConnectionClient {
-
- private static final int DATA_URL = 0; // Return base64 encoded string
- private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
- private static final int NATIVE_URI = 2; // On Android, this is the same as FILE_URI
-
- private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
- private static final int CAMERA = 1; // Take picture from camera
- private static final int SAVEDPHOTOALBUM = 2; // Choose image from picture library (same as PHOTOLIBRARY for Android)
-
- private static final int PICTURE = 0; // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
- private static final int VIDEO = 1; // allow selection of video only, ONLY RETURNS URL
- private static final int ALLMEDIA = 2; // allow selection from all media types
-
- private static final int JPEG = 0; // Take a picture of type JPEG
- private static final int PNG = 1; // Take a picture of type PNG
- private static final String GET_PICTURE = "Get Picture";
- private static final String GET_VIDEO = "Get Video";
- private static final String GET_All = "Get All";
-
- private static final String LOG_TAG = "CameraLauncher";
-
- private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
- private int targetWidth; // desired width of the image
- private int targetHeight; // desired height of the image
- private Uri imageUri; // Uri of captured image
- private int encodingType; // Type of encoding to use
- private int mediaType; // What type of media to retrieve
- private boolean saveToPhotoAlbum; // Should the picture be saved to the device's photo album
- private boolean correctOrientation; // Should the pictures orientation be corrected
- private boolean orientationCorrected; // Has the picture's orientation been corrected
- //private boolean allowEdit; // Should we allow the user to crop the image. UNUSED.
-
- public CallbackContext callbackContext;
- private int numPics;
-
- private MediaScannerConnection conn; // Used to update gallery app with newly-written files
- private Uri scanMe; // Uri of image to be added to content store
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackContext The callback id used when calling back into JavaScript.
- * @return A PluginResult object with a status and message.
- */
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- this.callbackContext = callbackContext;
-
- if (action.equals("takePicture")) {
- int srcType = CAMERA;
- int destType = FILE_URI;
- this.saveToPhotoAlbum = false;
- this.targetHeight = 0;
- this.targetWidth = 0;
- this.encodingType = JPEG;
- this.mediaType = PICTURE;
- this.mQuality = 80;
-
- this.mQuality = args.getInt(0);
- destType = args.getInt(1);
- srcType = args.getInt(2);
- this.targetWidth = args.getInt(3);
- this.targetHeight = args.getInt(4);
- this.encodingType = args.getInt(5);
- this.mediaType = args.getInt(6);
- //this.allowEdit = args.getBoolean(7); // This field is unused.
- this.correctOrientation = args.getBoolean(8);
- this.saveToPhotoAlbum = args.getBoolean(9);
-
- // If the user specifies a 0 or smaller width/height
- // make it -1 so later comparisons succeed
- if (this.targetWidth < 1) {
- this.targetWidth = -1;
- }
- if (this.targetHeight < 1) {
- this.targetHeight = -1;
- }
-
- try {
- if (srcType == CAMERA) {
- this.takePicture(destType, encodingType);
- }
- else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
- this.getImage(srcType, destType);
- }
- }
- catch (IllegalArgumentException e)
- {
- callbackContext.error("Illegal Argument Exception");
- PluginResult r = new PluginResult(PluginResult.Status.ERROR);
- callbackContext.sendPluginResult(r);
- return true;
- }
-
- PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
- r.setKeepCallback(true);
- callbackContext.sendPluginResult(r);
-
- return true;
- }
- return false;
- }
-
- //--------------------------------------------------------------------------
- // LOCAL METHODS
- //--------------------------------------------------------------------------
-
- private String getTempDirectoryPath() {
- File cache = null;
-
- // SD Card Mounted
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
- "/Android/data/" + cordova.getActivity().getPackageName() + "/cache/");
- }
- // Use internal storage
- else {
- cache = cordova.getActivity().getCacheDir();
- }
-
- // Create the cache directory if it doesn't exist
- cache.mkdirs();
- return cache.getAbsolutePath();
- }
-
- /**
- * Take a picture with the camera.
- * When an image is captured or the camera view is cancelled, the result is returned
- * in CordovaActivity.onActivityResult, which forwards the result to this.onActivityResult.
- *
- * The image can either be returned as a base64 string or a URI that points to the file.
- * To display base64 string in an img tag, set the source to:
- * img.src="data:image/jpeg;base64,"+result;
- * or to display URI in an img tag
- * img.src=result;
- *
- * @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
- * @param returnType Set the type of image to return.
- */
- public void takePicture(int returnType, int encodingType) {
- // Save the number of images currently on disk for later
- this.numPics = queryImgDB(whichContentStore()).getCount();
-
- // Display camera
- Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
-
- // Specify file so that large image is captured and returned
- File photo = createCaptureFile(encodingType);
- intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
- this.imageUri = Uri.fromFile(photo);
-
- if (this.cordova != null) {
- this.cordova.startActivityForResult((CordovaPlugin) this, intent, (CAMERA + 1) * 16 + returnType + 1);
- }
-// else
-// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
- }
-
- /**
- * Create a file in the applications temporary directory based upon the supplied encoding.
- *
- * @param encodingType of the image to be taken
- * @return a File object pointing to the temporary picture
- */
- private File createCaptureFile(int encodingType) {
- File photo = null;
- if (encodingType == JPEG) {
- photo = new File(getTempDirectoryPath(), ".Pic.jpg");
- } else if (encodingType == PNG) {
- photo = new File(getTempDirectoryPath(), ".Pic.png");
- } else {
- throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
- }
- return photo;
- }
-
- /**
- * Get image from photo library.
- *
- * @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
- * @param srcType The album to get image from.
- * @param returnType Set the type of image to return.
- */
- // TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do!
- public void getImage(int srcType, int returnType) {
- Intent intent = new Intent();
- String title = GET_PICTURE;
- if (this.mediaType == PICTURE) {
- intent.setType("image/*");
- }
- else if (this.mediaType == VIDEO) {
- intent.setType("video/*");
- title = GET_VIDEO;
- }
- else if (this.mediaType == ALLMEDIA) {
- // I wanted to make the type 'image/*, video/*' but this does not work on all versions
- // of android so I had to go with the wildcard search.
- intent.setType("*/*");
- title = GET_All;
- }
-
- intent.setAction(Intent.ACTION_GET_CONTENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- if (this.cordova != null) {
- this.cordova.startActivityForResult((CordovaPlugin) this, Intent.createChooser(intent,
- new String(title)), (srcType + 1) * 16 + returnType + 1);
- }
- }
-
- /**
- * Applies all needed transformation to the image received from the camera.
- *
- * @param destType In which form should we return the image
- * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
- */
- private void processResultFromCamera(int destType, Intent intent) throws IOException {
- int rotate = 0;
-
- // Create an ExifHelper to save the exif data that is lost during compression
- ExifHelper exif = new ExifHelper();
- try {
- if (this.encodingType == JPEG) {
- exif.createInFile(getTempDirectoryPath() + "/.Pic.jpg");
- exif.readExifData();
- rotate = exif.getOrientation();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- Bitmap bitmap = null;
- Uri uri = null;
-
- // If sending base64 image back
- if (destType == DATA_URL) {
- bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString()));
- if (bitmap == null) {
- // Try to get the bitmap from intent.
- bitmap = (Bitmap)intent.getExtras().get("data");
- }
-
- // Double-check the bitmap.
- if (bitmap == null) {
- Log.d(LOG_TAG, "I either have a null image path or bitmap");
- this.failPicture("Unable to create bitmap!");
- return;
- }
-
- if (rotate != 0 && this.correctOrientation) {
- bitmap = getRotatedBitmap(rotate, bitmap, exif);
- }
-
- this.processPicture(bitmap);
- checkForDuplicateImage(DATA_URL);
- }
-
- // If sending filename back
- else if (destType == FILE_URI || destType == NATIVE_URI) {
- if (this.saveToPhotoAlbum) {
- Uri inputUri = getUriFromMediaStore();
- //Just because we have a media URI doesn't mean we have a real file, we need to make it
- uri = Uri.fromFile(new File(FileHelper.getRealPath(inputUri, this.cordova)));
- } else {
- uri = Uri.fromFile(new File(getTempDirectoryPath(), System.currentTimeMillis() + ".jpg"));
- }
-
- if (uri == null) {
- this.failPicture("Error capturing image - no media storage found.");
- }
-
- // If all this is true we shouldn't compress the image.
- if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
- !this.correctOrientation) {
- writeUncompressedImage(uri);
-
- this.callbackContext.success(uri.toString());
- } else {
- bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString()));
-
- if (rotate != 0 && this.correctOrientation) {
- bitmap = getRotatedBitmap(rotate, bitmap, exif);
- }
-
- // Add compressed version of captured image to returned media store Uri
- OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
- bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
- os.close();
-
- // Restore exif data to file
- if (this.encodingType == JPEG) {
- String exifPath;
- if (this.saveToPhotoAlbum) {
- exifPath = FileHelper.getRealPath(uri, this.cordova);
- } else {
- exifPath = uri.getPath();
- }
- exif.createOutFile(exifPath);
- exif.writeExifData();
- }
-
- }
- // Send Uri back to JavaScript for viewing image
- this.callbackContext.success(uri.toString());
- }
-
- this.cleanup(FILE_URI, this.imageUri, uri, bitmap);
- bitmap = null;
- }
-
- private String ouputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException {
- // Create an ExifHelper to save the exif data that is lost during compression
- String modifiedPath = getTempDirectoryPath() + "/modified.jpg";
-
- OutputStream os = new FileOutputStream(modifiedPath);
- bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
- os.close();
-
- // Some content: URIs do not map to file paths (e.g. picasa).
- String realPath = FileHelper.getRealPath(uri, this.cordova);
- ExifHelper exif = new ExifHelper();
- if (realPath != null && this.encodingType == JPEG) {
- try {
- exif.createInFile(realPath);
- exif.readExifData();
- if (this.correctOrientation && this.orientationCorrected) {
- exif.resetOrientation();
- }
- exif.createOutFile(modifiedPath);
- exif.writeExifData();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return modifiedPath;
- }
-
- /**
- * Applies all needed transformation to the image received from the gallery.
- *
- * @param destType In which form should we return the image
- * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
- */
- private void processResultFromGallery(int destType, Intent intent) {
- Uri uri = intent.getData();
- int rotate = 0;
-
- // If you ask for video or all media type you will automatically get back a file URI
- // and there will be no attempt to resize any returned data
- if (this.mediaType != PICTURE) {
- this.callbackContext.success(uri.toString());
- }
- else {
- // This is a special case to just return the path as no scaling,
- // rotating, nor compressing needs to be done
- if (this.targetHeight == -1 && this.targetWidth == -1 &&
- (destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation) {
- this.callbackContext.success(uri.toString());
- } else {
- String uriString = uri.toString();
- // Get the path to the image. Makes loading so much easier.
- String mimeType = FileHelper.getMimeType(uriString, this.cordova);
- // If we don't have a valid image so quit.
- if (!("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType))) {
- Log.d(LOG_TAG, "I either have a null image path or bitmap");
- this.failPicture("Unable to retrieve path to picture!");
- return;
- }
- Bitmap bitmap = null;
- try {
- bitmap = getScaledBitmap(uriString);
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (bitmap == null) {
- Log.d(LOG_TAG, "I either have a null image path or bitmap");
- this.failPicture("Unable to create bitmap!");
- return;
- }
-
- if (this.correctOrientation) {
- rotate = getImageOrientation(uri);
- if (rotate != 0) {
- Matrix matrix = new Matrix();
- matrix.setRotate(rotate);
- try {
- bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
- this.orientationCorrected = true;
- } catch (OutOfMemoryError oom) {
- this.orientationCorrected = false;
- }
- }
- }
-
- // If sending base64 image back
- if (destType == DATA_URL) {
- this.processPicture(bitmap);
- }
-
- // If sending filename back
- else if (destType == FILE_URI || destType == NATIVE_URI) {
- // Did we modify the image?
- if ( (this.targetHeight > 0 && this.targetWidth > 0) ||
- (this.correctOrientation && this.orientationCorrected) ) {
- try {
- String modifiedPath = this.ouputModifiedBitmap(bitmap, uri);
- // The modified image is cached by the app in order to get around this and not have to delete you
- // application cache I'm adding the current system time to the end of the file url.
- this.callbackContext.success("file://" + modifiedPath + "?" + System.currentTimeMillis());
- } catch (Exception e) {
- e.printStackTrace();
- this.failPicture("Error retrieving image.");
- }
- }
- else {
- this.callbackContext.success(uri.toString());
- }
- }
- if (bitmap != null) {
- bitmap.recycle();
- bitmap = null;
- }
- System.gc();
- }
- }
- }
-
- /**
- * Called when the camera view exits.
- *
- * @param requestCode The request code originally supplied to startActivityForResult(),
- * allowing you to identify who this result came from.
- * @param resultCode The integer result code returned by the child activity through its setResult().
- * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
- */
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
-
- // Get src and dest types from request code
- int srcType = (requestCode / 16) - 1;
- int destType = (requestCode % 16) - 1;
-
- // If CAMERA
- if (srcType == CAMERA) {
- // If image available
- if (resultCode == Activity.RESULT_OK) {
- try {
- this.processResultFromCamera(destType, intent);
- } catch (IOException e) {
- e.printStackTrace();
- this.failPicture("Error capturing image.");
- }
- }
-
- // If cancelled
- else if (resultCode == Activity.RESULT_CANCELED) {
- this.failPicture("Camera cancelled.");
- }
-
- // If something else
- else {
- this.failPicture("Did not complete!");
- }
- }
-
- // If retrieving photo from library
- else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
- if (resultCode == Activity.RESULT_OK) {
- this.processResultFromGallery(destType, intent);
- }
- else if (resultCode == Activity.RESULT_CANCELED) {
- this.failPicture("Selection cancelled.");
- }
- else {
- this.failPicture("Selection did not complete!");
- }
- }
- }
-
- private int getImageOrientation(Uri uri) {
- int rotate = 0;
- String[] cols = { MediaStore.Images.Media.ORIENTATION };
- try {
- Cursor cursor = cordova.getActivity().getContentResolver().query(uri,
- cols, null, null, null);
- if (cursor != null) {
- cursor.moveToPosition(0);
- rotate = cursor.getInt(0);
- cursor.close();
- }
- } catch (Exception e) {
- // You can get an IllegalArgumentException if ContentProvider doesn't support querying for orientation.
- }
- return rotate;
- }
-
- /**
- * Figure out if the bitmap should be rotated. For instance if the picture was taken in
- * portrait mode
- *
- * @param rotate
- * @param bitmap
- * @return rotated bitmap
- */
- private Bitmap getRotatedBitmap(int rotate, Bitmap bitmap, ExifHelper exif) {
- Matrix matrix = new Matrix();
- if (rotate == 180) {
- matrix.setRotate(rotate);
- } else {
- matrix.setRotate(rotate, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
- }
-
- try
- {
- bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
- exif.resetOrientation();
- }
- catch (OutOfMemoryError oom)
- {
- // You can run out of memory if the image is very large:
- // http://simonmacdonald.blogspot.ca/2012/07/change-to-camera-code-in-phonegap-190.html
- // If this happens, simply do not rotate the image and return it unmodified.
- // If you do not catch the OutOfMemoryError, the Android app crashes.
- }
-
- return bitmap;
- }
-
- /**
- * In the special case where the default width, height and quality are unchanged
- * we just write the file out to disk saving the expensive Bitmap.compress function.
- *
- * @param uri
- * @throws FileNotFoundException
- * @throws IOException
- */
- private void writeUncompressedImage(Uri uri) throws FileNotFoundException,
- IOException {
- FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(imageUri.toString()));
- OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
- byte[] buffer = new byte[4096];
- int len;
- while ((len = fis.read(buffer)) != -1) {
- os.write(buffer, 0, len);
- }
- os.flush();
- os.close();
- fis.close();
- }
-
- /**
- * Create entry in media store for image
- *
- * @return uri
- */
- private Uri getUriFromMediaStore() {
- ContentValues values = new ContentValues();
- values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
- Uri uri;
- try {
- uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
- } catch (UnsupportedOperationException e) {
- LOG.d(LOG_TAG, "Can't write to external media storage.");
- try {
- uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
- } catch (UnsupportedOperationException ex) {
- LOG.d(LOG_TAG, "Can't write to internal media storage.");
- return null;
- }
- }
- return uri;
- }
-
- /**
- * Return a scaled bitmap based on the target width and height
- *
- * @param imagePath
- * @return
- * @throws IOException
- */
- private Bitmap getScaledBitmap(String imageUrl) throws IOException {
- // If no new width or height were specified return the original bitmap
- if (this.targetWidth <= 0 && this.targetHeight <= 0) {
- return BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova));
- }
-
- // figure out the original width and height of the image
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova), null, options);
-
- //CB-2292: WTF? Why is the width null?
- if(options.outWidth == 0 || options.outHeight == 0)
- {
- return null;
- }
-
- // determine the correct aspect ratio
- int[] widthHeight = calculateAspectRatio(options.outWidth, options.outHeight);
-
- // Load in the smallest bitmap possible that is closest to the size we want
- options.inJustDecodeBounds = false;
- options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight);
- Bitmap unscaledBitmap = BitmapFactory.decodeStream(FileHelper.getInputStreamFromUriString(imageUrl, cordova), null, options);
- if (unscaledBitmap == null) {
- return null;
- }
-
- return Bitmap.createScaledBitmap(unscaledBitmap, widthHeight[0], widthHeight[1], true);
- }
-
- /**
- * Maintain the aspect ratio so the resulting image does not look smooshed
- *
- * @param origWidth
- * @param origHeight
- * @return
- */
- public int[] calculateAspectRatio(int origWidth, int origHeight) {
- int newWidth = this.targetWidth;
- int newHeight = this.targetHeight;
-
- // If no new width or height were specified return the original bitmap
- if (newWidth <= 0 && newHeight <= 0) {
- newWidth = origWidth;
- newHeight = origHeight;
- }
- // Only the width was specified
- else if (newWidth > 0 && newHeight <= 0) {
- newHeight = (newWidth * origHeight) / origWidth;
- }
- // only the height was specified
- else if (newWidth <= 0 && newHeight > 0) {
- newWidth = (newHeight * origWidth) / origHeight;
- }
- // If the user specified both a positive width and height
- // (potentially different aspect ratio) then the width or height is
- // scaled so that the image fits while maintaining aspect ratio.
- // Alternatively, the specified width and height could have been
- // kept and Bitmap.SCALE_TO_FIT specified when scaling, but this
- // would result in whitespace in the new image.
- else {
- double newRatio = newWidth / (double) newHeight;
- double origRatio = origWidth / (double) origHeight;
-
- if (origRatio > newRatio) {
- newHeight = (newWidth * origHeight) / origWidth;
- } else if (origRatio < newRatio) {
- newWidth = (newHeight * origWidth) / origHeight;
- }
- }
-
- int[] retval = new int[2];
- retval[0] = newWidth;
- retval[1] = newHeight;
- return retval;
- }
-
- /**
- * Figure out what ratio we can load our image into memory at while still being bigger than
- * our desired width and height
- *
- * @param srcWidth
- * @param srcHeight
- * @param dstWidth
- * @param dstHeight
- * @return
- */
- public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
- final float srcAspect = (float)srcWidth / (float)srcHeight;
- final float dstAspect = (float)dstWidth / (float)dstHeight;
-
- if (srcAspect > dstAspect) {
- return srcWidth / dstWidth;
- } else {
- return srcHeight / dstHeight;
- }
- }
-
- /**
- * Creates a cursor that can be used to determine how many images we have.
- *
- * @return a cursor
- */
- private Cursor queryImgDB(Uri contentStore) {
- return this.cordova.getActivity().getContentResolver().query(
- contentStore,
- new String[] { MediaStore.Images.Media._ID },
- null,
- null,
- null);
- }
-
- /**
- * Cleans up after picture taking. Checking for duplicates and that kind of stuff.
- * @param newImage
- */
- private void cleanup(int imageType, Uri oldImage, Uri newImage, Bitmap bitmap) {
- if (bitmap != null) {
- bitmap.recycle();
- }
-
- // Clean up initial camera-written image file.
- (new File(FileHelper.stripFileProtocol(oldImage.toString()))).delete();
-
- checkForDuplicateImage(imageType);
- // Scan for the gallery to update pic refs in gallery
- if (this.saveToPhotoAlbum && newImage != null) {
- this.scanForGallery(newImage);
- }
-
- System.gc();
- }
-
- /**
- * Used to find out if we are in a situation where the Camera Intent adds to images
- * to the content store. If we are using a FILE_URI and the number of images in the DB
- * increases by 2 we have a duplicate, when using a DATA_URL the number is 1.
- *
- * @param type FILE_URI or DATA_URL
- */
- private void checkForDuplicateImage(int type) {
- int diff = 1;
- Uri contentStore = whichContentStore();
- Cursor cursor = queryImgDB(contentStore);
- int currentNumOfImages = cursor.getCount();
-
- if (type == FILE_URI && this.saveToPhotoAlbum) {
- diff = 2;
- }
-
- // delete the duplicate file if the difference is 2 for file URI or 1 for Data URL
- if ((currentNumOfImages - numPics) == diff) {
- cursor.moveToLast();
- int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID)));
- if (diff == 2) {
- id--;
- }
- Uri uri = Uri.parse(contentStore + "/" + id);
- this.cordova.getActivity().getContentResolver().delete(uri, null, null);
- cursor.close();
- }
- }
-
- /**
- * Determine if we are storing the images in internal or external storage
- * @return Uri
- */
- private Uri whichContentStore() {
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- return android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
- } else {
- return android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI;
- }
- }
-
- /**
- * Compress bitmap using jpeg, convert to Base64 encoded string, and return to JavaScript.
- *
- * @param bitmap
- */
- public void processPicture(Bitmap bitmap) {
- ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
- try {
- if (bitmap.compress(CompressFormat.JPEG, mQuality, jpeg_data)) {
- byte[] code = jpeg_data.toByteArray();
- byte[] output = Base64.encode(code, Base64.NO_WRAP);
- String js_out = new String(output);
- this.callbackContext.success(js_out);
- js_out = null;
- output = null;
- code = null;
- }
- } catch (Exception e) {
- this.failPicture("Error compressing image.");
- }
- jpeg_data = null;
- }
-
- /**
- * Send error message to JavaScript.
- *
- * @param err
- */
- public void failPicture(String err) {
- this.callbackContext.error(err);
- }
-
- private void scanForGallery(Uri newImage) {
- this.scanMe = newImage;
- if(this.conn != null) {
- this.conn.disconnect();
- }
- this.conn = new MediaScannerConnection(this.cordova.getActivity().getApplicationContext(), this);
- conn.connect();
- }
-
- public void onMediaScannerConnected() {
- try{
- this.conn.scanFile(this.scanMe.toString(), "image/*");
- } catch (java.lang.IllegalStateException e){
- LOG.e(LOG_TAG, "Can't scan file in MediaScanner after taking picture");
- }
-
- }
-
- public void onScanCompleted(String path, Uri uri) {
- this.conn.disconnect();
- }
-}
diff --git a/src/android/ExifHelper.java b/src/android/ExifHelper.java
deleted file mode 100644
index 5160a2f..0000000
--- a/src/android/ExifHelper.java
+++ /dev/null
@@ -1,185 +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.
-*/
-package org.apache.cordova.camera;
-
-import java.io.IOException;
-
-import android.media.ExifInterface;
-
-public class ExifHelper {
- private String aperture = null;
- private String datetime = null;
- private String exposureTime = null;
- private String flash = null;
- private String focalLength = null;
- private String gpsAltitude = null;
- private String gpsAltitudeRef = null;
- private String gpsDateStamp = null;
- private String gpsLatitude = null;
- private String gpsLatitudeRef = null;
- private String gpsLongitude = null;
- private String gpsLongitudeRef = null;
- private String gpsProcessingMethod = null;
- private String gpsTimestamp = null;
- private String iso = null;
- private String make = null;
- private String model = null;
- private String orientation = null;
- private String whiteBalance = null;
-
- private ExifInterface inFile = null;
- private ExifInterface outFile = null;
-
- /**
- * The file before it is compressed
- *
- * @param filePath
- * @throws IOException
- */
- public void createInFile(String filePath) throws IOException {
- this.inFile = new ExifInterface(filePath);
- }
-
- /**
- * The file after it has been compressed
- *
- * @param filePath
- * @throws IOException
- */
- public void createOutFile(String filePath) throws IOException {
- this.outFile = new ExifInterface(filePath);
- }
-
- /**
- * Reads all the EXIF data from the input file.
- */
- public void readExifData() {
- this.aperture = inFile.getAttribute(ExifInterface.TAG_APERTURE);
- this.datetime = inFile.getAttribute(ExifInterface.TAG_DATETIME);
- this.exposureTime = inFile.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
- this.flash = inFile.getAttribute(ExifInterface.TAG_FLASH);
- this.focalLength = inFile.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
- this.gpsAltitude = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE);
- this.gpsAltitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF);
- this.gpsDateStamp = inFile.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
- this.gpsLatitude = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
- this.gpsLatitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
- this.gpsLongitude = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
- this.gpsLongitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
- this.gpsProcessingMethod = inFile.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
- this.gpsTimestamp = inFile.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
- this.iso = inFile.getAttribute(ExifInterface.TAG_ISO);
- this.make = inFile.getAttribute(ExifInterface.TAG_MAKE);
- this.model = inFile.getAttribute(ExifInterface.TAG_MODEL);
- this.orientation = inFile.getAttribute(ExifInterface.TAG_ORIENTATION);
- this.whiteBalance = inFile.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
- }
-
- /**
- * Writes the previously stored EXIF data to the output file.
- *
- * @throws IOException
- */
- public void writeExifData() throws IOException {
- // Don't try to write to a null file
- if (this.outFile == null) {
- return;
- }
-
- if (this.aperture != null) {
- this.outFile.setAttribute(ExifInterface.TAG_APERTURE, this.aperture);
- }
- if (this.datetime != null) {
- this.outFile.setAttribute(ExifInterface.TAG_DATETIME, this.datetime);
- }
- if (this.exposureTime != null) {
- this.outFile.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, this.exposureTime);
- }
- if (this.flash != null) {
- this.outFile.setAttribute(ExifInterface.TAG_FLASH, this.flash);
- }
- if (this.focalLength != null) {
- this.outFile.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, this.focalLength);
- }
- if (this.gpsAltitude != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, this.gpsAltitude);
- }
- if (this.gpsAltitudeRef != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, this.gpsAltitudeRef);
- }
- if (this.gpsDateStamp != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, this.gpsDateStamp);
- }
- if (this.gpsLatitude != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE, this.gpsLatitude);
- }
- if (this.gpsLatitudeRef != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, this.gpsLatitudeRef);
- }
- if (this.gpsLongitude != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, this.gpsLongitude);
- }
- if (this.gpsLongitudeRef != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, this.gpsLongitudeRef);
- }
- if (this.gpsProcessingMethod != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, this.gpsProcessingMethod);
- }
- if (this.gpsTimestamp != null) {
- this.outFile.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, this.gpsTimestamp);
- }
- if (this.iso != null) {
- this.outFile.setAttribute(ExifInterface.TAG_ISO, this.iso);
- }
- if (this.make != null) {
- this.outFile.setAttribute(ExifInterface.TAG_MAKE, this.make);
- }
- if (this.model != null) {
- this.outFile.setAttribute(ExifInterface.TAG_MODEL, this.model);
- }
- if (this.orientation != null) {
- this.outFile.setAttribute(ExifInterface.TAG_ORIENTATION, this.orientation);
- }
- if (this.whiteBalance != null) {
- this.outFile.setAttribute(ExifInterface.TAG_WHITE_BALANCE, this.whiteBalance);
- }
-
- this.outFile.saveAttributes();
- }
-
- public int getOrientation() {
- int o = Integer.parseInt(this.orientation);
-
- if (o == ExifInterface.ORIENTATION_NORMAL) {
- return 0;
- } else if (o == ExifInterface.ORIENTATION_ROTATE_90) {
- return 90;
- } else if (o == ExifInterface.ORIENTATION_ROTATE_180) {
- return 180;
- } else if (o == ExifInterface.ORIENTATION_ROTATE_270) {
- return 270;
- } else {
- return 0;
- }
- }
-
- public void resetOrientation() {
- this.orientation = "" + ExifInterface.ORIENTATION_NORMAL;
- }
-}
diff --git a/src/android/FileHelper.java b/src/android/FileHelper.java
deleted file mode 100644
index 24ced59..0000000
--- a/src/android/FileHelper.java
+++ /dev/null
@@ -1,158 +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.
- */
-package org.apache.cordova.camera;
-
-import android.database.Cursor;
-import android.net.Uri;
-import android.webkit.MimeTypeMap;
-
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.LOG;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-
-public class FileHelper {
- private static final String LOG_TAG = "FileUtils";
- private static final String _DATA = "_data";
-
- /**
- * Returns the real path of the given URI string.
- * If the given URI string represents a content:// URI, the real path is retrieved from the media store.
- *
- * @param uriString the URI string of the audio/image/video
- * @param cordova the current application context
- * @return the full path to the file
- */
- @SuppressWarnings("deprecation")
- public static String getRealPath(String uriString, CordovaInterface cordova) {
- String realPath = null;
-
- if (uriString.startsWith("content://")) {
- String[] proj = { _DATA };
- Cursor cursor = cordova.getActivity().managedQuery(Uri.parse(uriString), proj, null, null, null);
- int column_index = cursor.getColumnIndexOrThrow(_DATA);
- cursor.moveToFirst();
- realPath = cursor.getString(column_index);
- if (realPath == null) {
- LOG.e(LOG_TAG, "Could get real path for URI string %s", uriString);
- }
- } else if (uriString.startsWith("file://")) {
- realPath = uriString.substring(7);
- if (realPath.startsWith("/android_asset/")) {
- LOG.e(LOG_TAG, "Cannot get real path for URI string %s because it is a file:///android_asset/ URI.", uriString);
- realPath = null;
- }
- } else {
- realPath = uriString;
- }
-
- return realPath;
- }
-
- /**
- * Returns the real path of the given URI.
- * If the given URI is a content:// URI, the real path is retrieved from the media store.
- *
- * @param uri the URI of the audio/image/video
- * @param cordova the current application context
- * @return the full path to the file
- */
- public static String getRealPath(Uri uri, CordovaInterface cordova) {
- return FileHelper.getRealPath(uri.toString(), cordova);
- }
-
- /**
- * Returns an input stream based on given URI string.
- *
- * @param uriString the URI string from which to obtain the input stream
- * @param cordova the current application context
- * @return an input stream into the data at the given URI or null if given an invalid URI string
- * @throws IOException
- */
- public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova) throws IOException {
- if (uriString.startsWith("content")) {
- Uri uri = Uri.parse(uriString);
- return cordova.getActivity().getContentResolver().openInputStream(uri);
- } else if (uriString.startsWith("file://")) {
- int question = uriString.indexOf("?");
- if (question > -1) {
- uriString = uriString.substring(0,question);
- }
- if (uriString.startsWith("file:///android_asset/")) {
- Uri uri = Uri.parse(uriString);
- String relativePath = uri.getPath().substring(15);
- return cordova.getActivity().getAssets().open(relativePath);
- } else {
- return new FileInputStream(getRealPath(uriString, cordova));
- }
- } else {
- return new FileInputStream(getRealPath(uriString, cordova));
- }
- }
-
- /**
- * Removes the "file://" prefix from the given URI string, if applicable.
- * If the given URI string doesn't have a "file://" prefix, it is returned unchanged.
- *
- * @param uriString the URI string to operate on
- * @return a path without the "file://" prefix
- */
- public static String stripFileProtocol(String uriString) {
- if (uriString.startsWith("file://")) {
- uriString = uriString.substring(7);
- }
- return uriString;
- }
-
- public static String getMimeTypeForExtension(String path) {
- String extension = path;
- int lastDot = extension.lastIndexOf('.');
- if (lastDot != -1) {
- extension = extension.substring(lastDot + 1);
- }
- // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
- extension = extension.toLowerCase(Locale.getDefault());
- if (extension.equals("3ga")) {
- return "audio/3gpp";
- }
- return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
- }
-
- /**
- * Returns the mime type of the data specified by the given URI string.
- *
- * @param uriString the URI string of the data
- * @return the mime type of the specified data
- */
- public static String getMimeType(String uriString, CordovaInterface cordova) {
- String mimeType = null;
-
- Uri uri = Uri.parse(uriString);
- if (uriString.startsWith("content://")) {
- mimeType = cordova.getActivity().getContentResolver().getType(uri);
- } else {
- mimeType = getMimeTypeForExtension(uri.getPath());
- }
-
- return mimeType;
- }
-}
diff --git a/src/blackberry10/index.js b/src/blackberry10/index.js
deleted file mode 100644
index 9a5ebf3..0000000
--- a/src/blackberry10/index.js
+++ /dev/null
@@ -1,129 +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.
- *
-*/
-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)
- },
- 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)
- };
-
-function encodeBase64(filePath, callback) {
- var sandbox = window.qnx.webplatform.getController().setFileSystemSandbox, // save original sandbox value
- 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);
- },
- 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);
- },
- 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])),
- sourceType = JSON.parse(decodeURIComponent(args[2])),
- result = new PluginResult(args, env),
- 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);
- }
- });
- }
- },
- cancel = function (reason) {
- result.callbackError(reason, false);
- },
- invoked = function (error) {
- if (error) {
- result.callbackError(error, false);
- }
- };
-
- switch(sourceType) {
- case PictureSourceType.CAMERA:
- window.qnx.webplatform.getApplication().cards.camera.open("photo", done, cancel, invoked);
- 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);
- }
-};
diff --git a/src/firefoxos/CameraProxy.js b/src/firefoxos/CameraProxy.js
deleted file mode 100644
index 9afb343..0000000
--- a/src/firefoxos/CameraProxy.js
+++ /dev/null
@@ -1,51 +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.
- *
- */
-
-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/firefoxos/commandProxy").add("Camera", module.exports);
diff --git a/src/ios/CDVCamera.h b/src/ios/CDVCamera.h
deleted file mode 100644
index 744ae7f..0000000
--- a/src/ios/CDVCamera.h
+++ /dev/null
@@ -1,102 +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.
- */
-
-#import
-#import
-#import
-#import
-
-enum CDVDestinationType {
- DestinationTypeDataUrl = 0,
- DestinationTypeFileUri,
- DestinationTypeNativeUri
-};
-typedef NSUInteger CDVDestinationType;
-
-enum CDVEncodingType {
- EncodingTypeJPEG = 0,
- EncodingTypePNG
-};
-typedef NSUInteger CDVEncodingType;
-
-enum CDVMediaType {
- MediaTypePicture = 0,
- MediaTypeVideo,
- MediaTypeAll
-};
-typedef NSUInteger CDVMediaType;
-
-@interface CDVCameraPicker : UIImagePickerController
-{}
-
-@property (assign) NSInteger quality;
-@property (copy) NSString* callbackId;
-@property (copy) NSString* postUrl;
-@property (nonatomic) enum CDVDestinationType returnType;
-@property (nonatomic) enum CDVEncodingType encodingType;
-@property (strong) UIPopoverController* popoverController;
-@property (assign) CGSize targetSize;
-@property (assign) bool correctOrientation;
-@property (assign) bool saveToPhotoAlbum;
-@property (assign) bool cropToSize;
-@property (strong) UIWebView* webView;
-@property (assign) BOOL popoverSupported;
-
-@end
-
-// ======================================================================= //
-
-@interface CDVCamera : CDVPlugin
-{}
-
-@property (strong) CDVCameraPicker* pickerController;
-@property (strong) NSMutableDictionary *metadata;
-@property (strong, nonatomic) CLLocationManager *locationManager;
-@property (strong) NSData* data;
-
-/*
- * getPicture
- *
- * arguments:
- * 1: this is the javascript function that will be called with the results, the first parameter passed to the
- * javascript function is the picture as a Base64 encoded string
- * 2: this is the javascript function to be called if there was an error
- * options:
- * quality: integer between 1 and 100
- */
-- (void)takePicture:(CDVInvokedUrlCommand*)command;
-- (void)postImage:(UIImage*)anImage withFilename:(NSString*)filename toUrl:(NSURL*)url;
-- (void)cleanup:(CDVInvokedUrlCommand*)command;
-- (void)repositionPopover:(CDVInvokedUrlCommand*)command;
-
-- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info;
-- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo;
-- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker;
-- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
-- (UIImage*)imageByScalingAndCroppingForSize:(UIImage*)anImage toSize:(CGSize)targetSize;
-- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)anImage toSize:(CGSize)frameSize;
-- (UIImage*)imageCorrectedForCaptureOrientation:(UIImage*)anImage;
-
-- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation;
-- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
-
-@end
diff --git a/src/ios/CDVCamera.m b/src/ios/CDVCamera.m
deleted file mode 100644
index 9981747..0000000
--- a/src/ios/CDVCamera.m
+++ /dev/null
@@ -1,756 +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.
- */
-
-#import "CDVCamera.h"
-#import "CDVJpegHeaderWriter.h"
-#import
-#import
-#import
-#import
-#import
-#import
-#import
-#import
-#import
-
-#define CDV_PHOTO_PREFIX @"cdv_photo_"
-
-static NSSet* org_apache_cordova_validArrowDirections;
-
-@interface CDVCamera ()
-
-@property (readwrite, assign) BOOL hasPendingOperation;
-
-@end
-
-@implementation CDVCamera
-
-+ (void)initialize
-{
- org_apache_cordova_validArrowDirections = [[NSSet alloc] initWithObjects:[NSNumber numberWithInt:UIPopoverArrowDirectionUp], [NSNumber numberWithInt:UIPopoverArrowDirectionDown], [NSNumber numberWithInt:UIPopoverArrowDirectionLeft], [NSNumber numberWithInt:UIPopoverArrowDirectionRight], [NSNumber numberWithInt:UIPopoverArrowDirectionAny], nil];
-}
-
-@synthesize hasPendingOperation, pickerController, locationManager;
-
-- (BOOL)popoverSupported
-{
- return (NSClassFromString(@"UIPopoverController") != nil) &&
- (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
-}
-
-/* takePicture arguments:
- * INDEX ARGUMENT
- * 0 quality
- * 1 destination type
- * 2 source type
- * 3 targetWidth
- * 4 targetHeight
- * 5 encodingType
- * 6 mediaType
- * 7 allowsEdit
- * 8 correctOrientation
- * 9 saveToPhotoAlbum
- * 10 popoverOptions
- * 11 cameraDirection
- */
-- (void)takePicture:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
- NSArray* arguments = command.arguments;
-
- self.hasPendingOperation = NO;
-
- NSString* sourceTypeString = [arguments objectAtIndex:2];
- UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; // default
- if (sourceTypeString != nil) {
- sourceType = (UIImagePickerControllerSourceType)[sourceTypeString intValue];
- }
-
- bool hasCamera = [UIImagePickerController isSourceTypeAvailable:sourceType];
- if (!hasCamera) {
- NSLog(@"Camera.getPicture: source type %lu not available.", (unsigned long)sourceType);
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no camera available"];
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
- return;
- }
-
- bool allowEdit = [[arguments objectAtIndex:7] boolValue];
- NSNumber* targetWidth = [arguments objectAtIndex:3];
- NSNumber* targetHeight = [arguments objectAtIndex:4];
- NSNumber* mediaValue = [arguments objectAtIndex:6];
- CDVMediaType mediaType = (mediaValue) ? [mediaValue intValue] : MediaTypePicture;
-
- CGSize targetSize = CGSizeMake(0, 0);
- if ((targetWidth != nil) && (targetHeight != nil)) {
- targetSize = CGSizeMake([targetWidth floatValue], [targetHeight floatValue]);
- }
-
- // If a popover is already open, close it; we only want one at a time.
- if (([[self pickerController] popoverController] != nil) && [[[self pickerController] popoverController] isPopoverVisible]) {
- [[[self pickerController] popoverController] dismissPopoverAnimated:YES];
- [[[self pickerController] popoverController] setDelegate:nil];
- [[self pickerController] setPopoverController:nil];
- }
-
- CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
- self.pickerController = cameraPicker;
-
- cameraPicker.delegate = self;
- cameraPicker.sourceType = sourceType;
- cameraPicker.allowsEditing = allowEdit; // THIS IS ALL IT TAKES FOR CROPPING - jm
- cameraPicker.callbackId = callbackId;
- cameraPicker.targetSize = targetSize;
- cameraPicker.cropToSize = NO;
- // we need to capture this state for memory warnings that dealloc this object
- cameraPicker.webView = self.webView;
- cameraPicker.popoverSupported = [self popoverSupported];
-
- cameraPicker.correctOrientation = [[arguments objectAtIndex:8] boolValue];
- cameraPicker.saveToPhotoAlbum = [[arguments objectAtIndex:9] boolValue];
-
- cameraPicker.encodingType = ([arguments objectAtIndex:5]) ? [[arguments objectAtIndex:5] intValue] : EncodingTypeJPEG;
-
- cameraPicker.quality = ([arguments objectAtIndex:0]) ? [[arguments objectAtIndex:0] intValue] : 50;
- cameraPicker.returnType = ([arguments objectAtIndex:1]) ? [[arguments objectAtIndex:1] intValue] : DestinationTypeFileUri;
-
- if (sourceType == UIImagePickerControllerSourceTypeCamera) {
- // We only allow taking pictures (no video) in this API.
- cameraPicker.mediaTypes = [NSArray arrayWithObjects:(NSString*)kUTTypeImage, nil];
-
- // We can only set the camera device if we're actually using the camera.
- NSNumber* cameraDirection = [command argumentAtIndex:11 withDefault:[NSNumber numberWithInteger:UIImagePickerControllerCameraDeviceRear]];
- cameraPicker.cameraDevice = (UIImagePickerControllerCameraDevice)[cameraDirection intValue];
- } else if (mediaType == MediaTypeAll) {
- cameraPicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType];
- } else {
- NSArray* mediaArray = [NSArray arrayWithObjects:(NSString*)(mediaType == MediaTypeVideo ? kUTTypeMovie : kUTTypeImage), nil];
- cameraPicker.mediaTypes = mediaArray;
- }
-
- if ([self popoverSupported] && (sourceType != UIImagePickerControllerSourceTypeCamera)) {
- if (cameraPicker.popoverController == nil) {
- cameraPicker.popoverController = [[NSClassFromString(@"UIPopoverController")alloc] initWithContentViewController:cameraPicker];
- }
- NSDictionary* options = [command.arguments objectAtIndex:10 withDefault:nil];
- [self displayPopover:options];
- } else {
- SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
- if ([self.viewController respondsToSelector:selector]) {
- [self.viewController presentViewController:cameraPicker animated:YES completion:nil];
- } else {
- // deprecated as of iOS >= 6.0
- [self.viewController presentModalViewController:cameraPicker animated:YES];
- }
- }
- self.hasPendingOperation = YES;
-}
-
-- (void)repositionPopover:(CDVInvokedUrlCommand*)command
-{
- NSDictionary* options = [command.arguments objectAtIndex:0 withDefault:nil];
-
- [self displayPopover:options];
-}
-
-- (void)displayPopover:(NSDictionary*)options
-{
- NSInteger x = 0;
- NSInteger y = 32;
- NSInteger width = 320;
- NSInteger height = 480;
- UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
-
- if (options) {
- x = [options integerValueForKey:@"x" defaultValue:0];
- y = [options integerValueForKey:@"y" defaultValue:32];
- width = [options integerValueForKey:@"width" defaultValue:320];
- height = [options integerValueForKey:@"height" defaultValue:480];
- arrowDirection = [options integerValueForKey:@"arrowDir" defaultValue:UIPopoverArrowDirectionAny];
- if (![org_apache_cordova_validArrowDirections containsObject:[NSNumber numberWithUnsignedInteger:arrowDirection]]) {
- arrowDirection = UIPopoverArrowDirectionAny;
- }
- }
-
- [[[self pickerController] popoverController] setDelegate:self];
- [[[self pickerController] popoverController] presentPopoverFromRect:CGRectMake(x, y, width, height)
- inView:[self.webView superview]
- permittedArrowDirections:arrowDirection
- animated:YES];
-}
-
-- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
-{
- if([navigationController isKindOfClass:[UIImagePickerController class]]){
- UIImagePickerController * cameraPicker = (UIImagePickerController*)navigationController;
-
- if(![cameraPicker.mediaTypes containsObject:(NSString*) kUTTypeImage]){
- [viewController.navigationItem setTitle:NSLocalizedString(@"Videos title", nil)];
- }
- }
-}
-
-- (void)cleanup:(CDVInvokedUrlCommand*)command
-{
- // empty the tmp directory
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
- NSError* err = nil;
- BOOL hasErrors = NO;
-
- // clear contents of NSTemporaryDirectory
- NSString* tempDirectoryPath = NSTemporaryDirectory();
- NSDirectoryEnumerator* directoryEnumerator = [fileMgr enumeratorAtPath:tempDirectoryPath];
- NSString* fileName = nil;
- BOOL result;
-
- while ((fileName = [directoryEnumerator nextObject])) {
- // only delete the files we created
- if (![fileName hasPrefix:CDV_PHOTO_PREFIX]) {
- continue;
- }
- NSString* filePath = [tempDirectoryPath stringByAppendingPathComponent:fileName];
- result = [fileMgr removeItemAtPath:filePath error:&err];
- if (!result && err) {
- NSLog(@"Failed to delete: %@ (error: %@)", filePath, err);
- hasErrors = YES;
- }
- }
-
- CDVPluginResult* pluginResult;
- if (hasErrors) {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:@"One or more files failed to be deleted."];
- } else {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
- }
- [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
-}
-
-- (void)popoverControllerDidDismissPopover:(id)popoverController
-{
- // [ self imagePickerControllerDidCancel:self.pickerController ]; '
- UIPopoverController* pc = (UIPopoverController*)popoverController;
-
- [pc dismissPopoverAnimated:YES];
- pc.delegate = nil;
- if (self.pickerController && self.pickerController.callbackId && self.pickerController.popoverController) {
- self.pickerController.popoverController = nil;
- NSString* callbackId = self.pickerController.callbackId;
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"]; // error callback expects string ATM
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
- }
- self.hasPendingOperation = NO;
-}
-
-- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
-{
- CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
-
- if (cameraPicker.popoverSupported && (cameraPicker.popoverController != nil)) {
- [cameraPicker.popoverController dismissPopoverAnimated:YES];
- cameraPicker.popoverController.delegate = nil;
- cameraPicker.popoverController = nil;
- } else {
- if ([cameraPicker respondsToSelector:@selector(presentingViewController)]) {
- [[cameraPicker presentingViewController] dismissModalViewControllerAnimated:YES];
- } else {
- [[cameraPicker parentViewController] dismissModalViewControllerAnimated:YES];
- }
- }
-
- CDVPluginResult* result = nil;
-
- NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
- // IMAGE TYPE
- if ([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
- if (cameraPicker.returnType == DestinationTypeNativeUri) {
- NSString* nativeUri = [(NSURL*)[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
- } else {
- // get the image
- UIImage* image = nil;
- if (cameraPicker.allowsEditing && [info objectForKey:UIImagePickerControllerEditedImage]) {
- image = [info objectForKey:UIImagePickerControllerEditedImage];
- } else {
- image = [info objectForKey:UIImagePickerControllerOriginalImage];
- }
-
- if (cameraPicker.correctOrientation) {
- image = [self imageCorrectedForCaptureOrientation:image];
- }
-
- UIImage* scaledImage = nil;
-
- if ((cameraPicker.targetSize.width > 0) && (cameraPicker.targetSize.height > 0)) {
- // if cropToSize, resize image and crop to target size, otherwise resize to fit target without cropping
- if (cameraPicker.cropToSize) {
- scaledImage = [self imageByScalingAndCroppingForSize:image toSize:cameraPicker.targetSize];
- } else {
- scaledImage = [self imageByScalingNotCroppingForSize:image toSize:cameraPicker.targetSize];
- }
- }
-
- NSData* data = nil;
- // returnedImage is the image that is returned to caller and (optionally) saved to photo album
- UIImage* returnedImage = (scaledImage == nil ? image : scaledImage);
-
- if (cameraPicker.encodingType == EncodingTypePNG) {
- data = UIImagePNGRepresentation(returnedImage);
- } else if ((cameraPicker.allowsEditing==false) && (cameraPicker.targetSize.width <= 0) && (cameraPicker.targetSize.height <= 0) && (cameraPicker.correctOrientation==false)){
- // use image unedited as requested , don't resize
- data = UIImageJPEGRepresentation(returnedImage, 1.0);
- } else {
- data = UIImageJPEGRepresentation(returnedImage, cameraPicker.quality / 100.0f);
-
- NSDictionary *controllerMetadata = [info objectForKey:@"UIImagePickerControllerMediaMetadata"];
- if (controllerMetadata) {
- self.data = data;
- self.metadata = [[NSMutableDictionary alloc] init];
-
- NSMutableDictionary *EXIFDictionary = [[controllerMetadata objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy];
- if (EXIFDictionary) [self.metadata setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary];
-
- [[self locationManager] startUpdatingLocation];
- return;
- }
- }
-
- if (cameraPicker.saveToPhotoAlbum) {
- ALAssetsLibrary *library = [ALAssetsLibrary new];
- [library writeImageToSavedPhotosAlbum:returnedImage.CGImage orientation:(ALAssetOrientation)(returnedImage.imageOrientation) completionBlock:nil];
- }
-
- if (cameraPicker.returnType == DestinationTypeFileUri) {
- // write to temp directory and return URI
- // get the temp directory path
- NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
- NSError* err = nil;
- NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by apple (vs [NSFileManager defaultManager]) to be threadsafe
- // generate unique file name
- NSString* filePath;
-
- int i = 1;
- do {
- filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, cameraPicker.encodingType == EncodingTypePNG ? @"png":@"jpg"];
- } while ([fileMgr fileExistsAtPath:filePath]);
-
- // save file
- if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
- }
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[data base64EncodedString]];
- }
- }
- }
- // NOT IMAGE TYPE (MOVIE)
- else {
- NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
- }
-
- if (result) {
- [self.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
- }
-
- self.hasPendingOperation = NO;
- self.pickerController = nil;
-}
-
-// older api calls newer didFinishPickingMediaWithInfo
-- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingImage:(UIImage*)image editingInfo:(NSDictionary*)editingInfo
-{
- NSDictionary* imageInfo = [NSDictionary dictionaryWithObject:image forKey:UIImagePickerControllerOriginalImage];
-
- [self imagePickerController:picker didFinishPickingMediaWithInfo:imageInfo];
-}
-
-- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
-{
- CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
-
- if ([cameraPicker respondsToSelector:@selector(presentingViewController)]) {
- [[cameraPicker presentingViewController] dismissModalViewControllerAnimated:YES];
- } else {
- [[cameraPicker parentViewController] dismissModalViewControllerAnimated:YES];
- }
- // popoverControllerDidDismissPopover:(id)popoverController is called if popover is cancelled
-
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"]; // error callback expects string ATM
- [self.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
-
- self.hasPendingOperation = NO;
- self.pickerController = nil;
-}
-
-- (UIImage*)imageByScalingAndCroppingForSize:(UIImage*)anImage toSize:(CGSize)targetSize
-{
- UIImage* sourceImage = anImage;
- UIImage* newImage = nil;
- CGSize imageSize = sourceImage.size;
- CGFloat width = imageSize.width;
- CGFloat height = imageSize.height;
- CGFloat targetWidth = targetSize.width;
- CGFloat targetHeight = targetSize.height;
- CGFloat scaleFactor = 0.0;
- CGFloat scaledWidth = targetWidth;
- CGFloat scaledHeight = targetHeight;
- CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
-
- if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
- CGFloat widthFactor = targetWidth / width;
- CGFloat heightFactor = targetHeight / height;
-
- if (widthFactor > heightFactor) {
- scaleFactor = widthFactor; // scale to fit height
- } else {
- scaleFactor = heightFactor; // scale to fit width
- }
- scaledWidth = width * scaleFactor;
- scaledHeight = height * scaleFactor;
-
- // center the image
- if (widthFactor > heightFactor) {
- thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
- } else if (widthFactor < heightFactor) {
- thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
- }
- }
-
- UIGraphicsBeginImageContext(targetSize); // this will crop
-
- CGRect thumbnailRect = CGRectZero;
- thumbnailRect.origin = thumbnailPoint;
- thumbnailRect.size.width = scaledWidth;
- thumbnailRect.size.height = scaledHeight;
-
- [sourceImage drawInRect:thumbnailRect];
-
- newImage = UIGraphicsGetImageFromCurrentImageContext();
- if (newImage == nil) {
- NSLog(@"could not scale image");
- }
-
- // pop the context to get back to the default
- UIGraphicsEndImageContext();
- return newImage;
-}
-
-- (UIImage*)imageCorrectedForCaptureOrientation:(UIImage*)anImage
-{
- float rotation_radians = 0;
- bool perpendicular = false;
-
- switch ([anImage imageOrientation]) {
- case UIImageOrientationUp :
- rotation_radians = 0.0;
- break;
-
- case UIImageOrientationDown:
- rotation_radians = M_PI; // don't be scared of radians, if you're reading this, you're good at math
- break;
-
- case UIImageOrientationRight:
- rotation_radians = M_PI_2;
- perpendicular = true;
- break;
-
- case UIImageOrientationLeft:
- rotation_radians = -M_PI_2;
- perpendicular = true;
- break;
-
- default:
- break;
- }
-
- UIGraphicsBeginImageContext(CGSizeMake(anImage.size.width, anImage.size.height));
- CGContextRef context = UIGraphicsGetCurrentContext();
-
- // Rotate around the center point
- CGContextTranslateCTM(context, anImage.size.width / 2, anImage.size.height / 2);
- CGContextRotateCTM(context, rotation_radians);
-
- CGContextScaleCTM(context, 1.0, -1.0);
- float width = perpendicular ? anImage.size.height : anImage.size.width;
- float height = perpendicular ? anImage.size.width : anImage.size.height;
- CGContextDrawImage(context, CGRectMake(-width / 2, -height / 2, width, height), [anImage CGImage]);
-
- // Move the origin back since the rotation might've change it (if its 90 degrees)
- if (perpendicular) {
- CGContextTranslateCTM(context, -anImage.size.height / 2, -anImage.size.width / 2);
- }
-
- UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- return newImage;
-}
-
-- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)anImage toSize:(CGSize)frameSize
-{
- UIImage* sourceImage = anImage;
- UIImage* newImage = nil;
- CGSize imageSize = sourceImage.size;
- CGFloat width = imageSize.width;
- CGFloat height = imageSize.height;
- CGFloat targetWidth = frameSize.width;
- CGFloat targetHeight = frameSize.height;
- CGFloat scaleFactor = 0.0;
- CGSize scaledSize = frameSize;
-
- if (CGSizeEqualToSize(imageSize, frameSize) == NO) {
- CGFloat widthFactor = targetWidth / width;
- CGFloat heightFactor = targetHeight / height;
-
- // opposite comparison to imageByScalingAndCroppingForSize in order to contain the image within the given bounds
- if (widthFactor > heightFactor) {
- scaleFactor = heightFactor; // scale to fit height
- } else {
- scaleFactor = widthFactor; // scale to fit width
- }
- scaledSize = CGSizeMake(MIN(width * scaleFactor, targetWidth), MIN(height * scaleFactor, targetHeight));
- }
-
- UIGraphicsBeginImageContext(scaledSize); // this will resize
-
- [sourceImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)];
-
- newImage = UIGraphicsGetImageFromCurrentImageContext();
- if (newImage == nil) {
- NSLog(@"could not scale image");
- }
-
- // pop the context to get back to the default
- UIGraphicsEndImageContext();
- return newImage;
-}
-
-- (void)postImage:(UIImage*)anImage withFilename:(NSString*)filename toUrl:(NSURL*)url
-{
- self.hasPendingOperation = YES;
-
- NSString* boundary = @"----BOUNDARY_IS_I";
-
- NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:url];
- [req setHTTPMethod:@"POST"];
-
- NSString* contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
- [req setValue:contentType forHTTPHeaderField:@"Content-type"];
-
- NSData* imageData = UIImagePNGRepresentation(anImage);
-
- // adding the body
- NSMutableData* postBody = [NSMutableData data];
-
- // first parameter an image
- [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
- [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"upload\"; filename=\"%@\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]];
- [postBody appendData:[@"Content-Type: image/png\r\n\r\n" dataUsingEncoding : NSUTF8StringEncoding]];
- [postBody appendData:imageData];
-
- // // second parameter information
- // [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
- // [postBody appendData:[@"Content-Disposition: form-data; name=\"some_other_name\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
- // [postBody appendData:[@"some_other_value" dataUsingEncoding:NSUTF8StringEncoding]];
- // [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r \n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
-
- [req setHTTPBody:postBody];
-
- NSURLResponse* response;
- NSError* error;
- [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];
-
- // NSData* result = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&error];
- // NSString * resultStr = [[[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding] autorelease];
-
- self.hasPendingOperation = NO;
-}
-
-
-- (CLLocationManager *)locationManager {
-
- if (locationManager != nil) {
- return locationManager;
- }
-
- locationManager = [[CLLocationManager alloc] init];
- [locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
- [locationManager setDelegate:self];
-
- return locationManager;
-}
-
-- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation
-{
- if (locationManager != nil) {
- [self.locationManager stopUpdatingLocation];
- self.locationManager = nil;
-
- NSMutableDictionary *GPSDictionary = [[NSMutableDictionary dictionary] init];
-
- CLLocationDegrees latitude = newLocation.coordinate.latitude;
- CLLocationDegrees longitude = newLocation.coordinate.longitude;
-
- // latitude
- if (latitude < 0.0) {
- latitude = latitude * -1.0f;
- [GPSDictionary setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
- } else {
- [GPSDictionary setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
- }
- [GPSDictionary setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString*)kCGImagePropertyGPSLatitude];
-
- // longitude
- if (longitude < 0.0) {
- longitude = longitude * -1.0f;
- [GPSDictionary setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
- }
- else {
- [GPSDictionary setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
- }
- [GPSDictionary setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString*)kCGImagePropertyGPSLongitude];
-
- // altitude
- CGFloat altitude = newLocation.altitude;
- if (!isnan(altitude)){
- if (altitude < 0) {
- altitude = -altitude;
- [GPSDictionary setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
- } else {
- [GPSDictionary setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
- }
- [GPSDictionary setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude];
- }
-
- // Time and date
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"HH:mm:ss.SSSSSS"];
- [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
- [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp];
- [formatter setDateFormat:@"yyyy:MM:dd"];
- [GPSDictionary setObject:[formatter stringFromDate:newLocation.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp];
-
- [self.metadata setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
- [self imagePickerControllerReturnImageResult];
- }
-}
-
-- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
- if (locationManager != nil) {
- [self.locationManager stopUpdatingLocation];
- self.locationManager = nil;
-
- [self imagePickerControllerReturnImageResult];
- }
-}
-
-- (void)imagePickerControllerReturnImageResult
-{
- CDVPluginResult* result = nil;
-
- if (self.metadata) {
- CGImageSourceRef sourceImage = CGImageSourceCreateWithData((__bridge_retained CFDataRef)self.data, NULL);
- CFStringRef sourceType = CGImageSourceGetType(sourceImage);
-
- CGImageDestinationRef destinationImage = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)self.data, sourceType, 1, NULL);
- CGImageDestinationAddImageFromSource(destinationImage, sourceImage, 0, (__bridge CFDictionaryRef)self.metadata);
- CGImageDestinationFinalize(destinationImage);
-
- CFRelease(sourceImage);
- CFRelease(destinationImage);
- }
-
- if (self.pickerController.saveToPhotoAlbum) {
- ALAssetsLibrary *library = [ALAssetsLibrary new];
- [library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
- }
-
- if (self.pickerController.returnType == DestinationTypeFileUri) {
- // write to temp directory and return URI
- // get the temp directory path
- NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
- NSError* err = nil;
- NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by apple (vs [NSFileManager defaultManager]) to be threadsafe
- // generate unique file name
- NSString* filePath;
-
- int i = 1;
- do {
- filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, self.pickerController.encodingType == EncodingTypePNG ? @"png":@"jpg"];
- } while ([fileMgr fileExistsAtPath:filePath]);
-
- // save file
- if (![self.data writeToFile:filePath options:NSAtomicWrite error:&err]) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
- }
- else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]];
- }
- }
- else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[self.data base64EncodedString]];
- }
- if (result) {
- [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
- }
-
- if (result) {
- [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
- }
-
- self.hasPendingOperation = NO;
- self.pickerController = nil;
- self.data = nil;
- self.metadata = nil;
-}
-
-@end
-
-@implementation CDVCameraPicker
-
-@synthesize quality, postUrl;
-@synthesize returnType;
-@synthesize callbackId;
-@synthesize popoverController;
-@synthesize targetSize;
-@synthesize correctOrientation;
-@synthesize saveToPhotoAlbum;
-@synthesize encodingType;
-@synthesize cropToSize;
-@synthesize webView;
-@synthesize popoverSupported;
-
-- (BOOL)prefersStatusBarHidden {
- return YES;
-}
-
-- (UIViewController*)childViewControllerForStatusBarHidden {
- return nil;
-}
-
-- (void)viewWillAppear:(BOOL)animated {
- SEL sel = NSSelectorFromString(@"setNeedsStatusBarAppearanceUpdate");
- if ([self respondsToSelector:sel]) {
- [self performSelector:sel withObject:nil afterDelay:0];
- }
-
- [super viewWillAppear:animated];
-}
-
-@end
diff --git a/src/ios/CDVExif.h b/src/ios/CDVExif.h
deleted file mode 100644
index 3e8adbd..0000000
--- a/src/ios/CDVExif.h
+++ /dev/null
@@ -1,43 +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 CordovaLib_ExifData_h
-#define CordovaLib_ExifData_h
-
-// exif data types
-typedef enum exifDataTypes {
- EDT_UBYTE = 1, // 8 bit unsigned integer
- EDT_ASCII_STRING, // 8 bits containing 7 bit ASCII code, null terminated
- EDT_USHORT, // 16 bit unsigned integer
- EDT_ULONG, // 32 bit unsigned integer
- EDT_URATIONAL, // 2 longs, first is numerator and second is denominator
- EDT_SBYTE,
- EDT_UNDEFINED, // 8 bits
- EDT_SSHORT,
- EDT_SLONG, // 32bit signed integer (2's complement)
- EDT_SRATIONAL, // 2 SLONGS, first long is numerator, second is denominator
- EDT_SINGLEFLOAT,
- EDT_DOUBLEFLOAT
-} ExifDataTypes;
-
-// maps integer code for exif data types to width in bytes
-static const int DataTypeToWidth[] = {1,1,2,4,8,1,1,2,4,8,4,8};
-
-static const int RECURSE_HORIZON = 8;
-#endif
diff --git a/src/ios/CDVJpegHeaderWriter.h b/src/ios/CDVJpegHeaderWriter.h
deleted file mode 100644
index 3b43ef0..0000000
--- a/src/ios/CDVJpegHeaderWriter.h
+++ /dev/null
@@ -1,62 +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.
- */
-
-#import
-
-@interface CDVJpegHeaderWriter : NSObject {
- NSDictionary * SubIFDTagFormatDict;
- NSDictionary * IFD0TagFormatDict;
-}
-
-- (NSData*) spliceExifBlockIntoJpeg: (NSData*) jpegdata
- withExifBlock: (NSString*) exifstr;
-- (NSString*) createExifAPP1 : (NSDictionary*) datadict;
-- (NSString*) formattedHexStringFromDecimalNumber: (NSNumber*) numb
- withPlaces: (NSNumber*) width;
-- (NSString*) formatNumberWithLeadingZeroes: (NSNumber*) numb
- withPlaces: (NSNumber*) places;
-- (NSString*) decimalToUnsignedRational: (NSNumber*) numb
- withResultNumerator: (NSNumber**) numerator
- withResultDenominator: (NSNumber**) denominator;
-- (void) continuedFraction: (double) val
- withFractionList: (NSMutableArray*) fractionlist
- withHorizon: (int) horizon;
-//- (void) expandContinuedFraction: (NSArray*) fractionlist;
-- (void) splitDouble: (double) val
- withIntComponent: (int*) rightside
- withFloatRemainder: (double*) leftside;
-- (NSString*) formatRationalWithNumerator: (NSNumber*) numerator
- withDenominator: (NSNumber*) denominator
- asSigned: (Boolean) signedFlag;
-- (NSString*) hexStringFromData : (NSData*) data;
-- (NSNumber*) numericFromHexString : (NSString *) hexstring;
-
-/*
-- (void) readExifMetaData : (NSData*) imgdata;
-- (void) spliceImageData : (NSData*) imgdata withExifData: (NSDictionary*) exifdata;
-- (void) locateExifMetaData : (NSData*) imgdata;
-- (NSString*) createExifAPP1 : (NSDictionary*) datadict;
-- (void) createExifDataString : (NSDictionary*) datadict;
-- (NSString*) createDataElement : (NSString*) element
- withElementData: (NSString*) data
- withExternalDataBlock: (NSDictionary*) memblock;
-- (NSString*) hexStringFromData : (NSData*) data;
-- (NSNumber*) numericFromHexString : (NSString *) hexstring;
-*/
-@end
diff --git a/src/ios/CDVJpegHeaderWriter.m b/src/ios/CDVJpegHeaderWriter.m
deleted file mode 100644
index 4d3ea24..0000000
--- a/src/ios/CDVJpegHeaderWriter.m
+++ /dev/null
@@ -1,547 +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.
- */
-
-#import "CDVJpegHeaderWriter.h"
-#include "CDVExif.h"
-
-/* macros for tag info shorthand:
- tagno : tag number
- typecode : data type
- components : number of components
- appendString (TAGINF_W_APPEND only) : string to append to data
- Exif date data format include an extra 0x00 to the end of the data
- */
-#define TAGINF(tagno, typecode, components) [NSArray arrayWithObjects: tagno, typecode, components, nil]
-#define TAGINF_W_APPEND(tagno, typecode, components, appendString) [NSArray arrayWithObjects: tagno, typecode, components, appendString, nil]
-
-const uint mJpegId = 0xffd8; // JPEG format marker
-const uint mExifMarker = 0xffe1; // APP1 jpeg header marker
-const uint mExif = 0x45786966; // ASCII 'Exif', first characters of valid exif header after size
-const uint mMotorallaByteAlign = 0x4d4d; // 'MM', motorola byte align, msb first or 'sane'
-const uint mIntelByteAlgin = 0x4949; // 'II', Intel byte align, lsb first or 'batshit crazy reverso world'
-const uint mTiffLength = 0x2a; // after byte align bits, next to bits are 0x002a(MM) or 0x2a00(II), tiff version number
-
-
-@implementation CDVJpegHeaderWriter
-
-- (id) init {
- self = [super init];
- // supported tags for exif IFD
- IFD0TagFormatDict = [[NSDictionary alloc] initWithObjectsAndKeys:
- // TAGINF(@"010e", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"ImageDescription",
- TAGINF_W_APPEND(@"0132", [NSNumber numberWithInt:EDT_ASCII_STRING], @20, @"00"), @"DateTime",
- TAGINF(@"010f", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"Make",
- TAGINF(@"0110", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"Model",
- TAGINF(@"0131", [NSNumber numberWithInt:EDT_ASCII_STRING], @0), @"Software",
- TAGINF(@"011a", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"XResolution",
- TAGINF(@"011b", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"YResolution",
- // currently supplied outside of Exif data block by UIImagePickerControllerMediaMetadata, this is set manually in CDVCamera.m
- /* TAGINF(@"0112", [NSNumber numberWithInt:EDT_USHORT], @1), @"Orientation",
-
- // rest of the tags are supported by exif spec, but are not specified by UIImagePickerControllerMediaMedadata
- // should camera hardware supply these values in future versions, or if they can be derived, ImageHeaderWriter will include them gracefully
- TAGINF(@"0128", [NSNumber numberWithInt:EDT_USHORT], @1), @"ResolutionUnit",
- TAGINF(@"013e", [NSNumber numberWithInt:EDT_URATIONAL], @2), @"WhitePoint",
- TAGINF(@"013f", [NSNumber numberWithInt:EDT_URATIONAL], @6), @"PrimaryChromaticities",
- TAGINF(@"0211", [NSNumber numberWithInt:EDT_URATIONAL], @3), @"YCbCrCoefficients",
- TAGINF(@"0213", [NSNumber numberWithInt:EDT_USHORT], @1), @"YCbCrPositioning",
- TAGINF(@"0214", [NSNumber numberWithInt:EDT_URATIONAL], @6), @"ReferenceBlackWhite",
- TAGINF(@"8298", [NSNumber numberWithInt:EDT_URATIONAL], @0), @"Copyright",
-
- // offset to exif subifd, we determine this dynamically based on the size of the main exif IFD
- TAGINF(@"8769", [NSNumber numberWithInt:EDT_ULONG], @1), @"ExifOffset",*/
- nil];
-
-
- // supported tages for exif subIFD
- SubIFDTagFormatDict = [[NSDictionary alloc] initWithObjectsAndKeys:
- //TAGINF(@"9000", [NSNumber numberWithInt:], @), @"ExifVersion",
- //TAGINF(@"9202",[NSNumber numberWithInt:EDT_URATIONAL],@1), @"ApertureValue",
- //TAGINF(@"9203",[NSNumber numberWithInt:EDT_SRATIONAL],@1), @"BrightnessValue",
- TAGINF(@"a001",[NSNumber numberWithInt:EDT_USHORT],@1), @"ColorSpace",
- TAGINF_W_APPEND(@"9004",[NSNumber numberWithInt:EDT_ASCII_STRING],@20,@"00"), @"DateTimeDigitized",
- TAGINF_W_APPEND(@"9003",[NSNumber numberWithInt:EDT_ASCII_STRING],@20,@"00"), @"DateTimeOriginal",
- TAGINF(@"a402", [NSNumber numberWithInt:EDT_USHORT], @1), @"ExposureMode",
- TAGINF(@"8822", [NSNumber numberWithInt:EDT_USHORT], @1), @"ExposureProgram",
- //TAGINF(@"829a", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"ExposureTime",
- //TAGINF(@"829d", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"FNumber",
- TAGINF(@"9209", [NSNumber numberWithInt:EDT_USHORT], @1), @"Flash",
- // FocalLengthIn35mmFilm
- TAGINF(@"a405", [NSNumber numberWithInt:EDT_USHORT], @1), @"FocalLenIn35mmFilm",
- //TAGINF(@"920a", [NSNumber numberWithInt:EDT_URATIONAL], @1), @"FocalLength",
- //TAGINF(@"8827", [NSNumber numberWithInt:EDT_USHORT], @2), @"ISOSpeedRatings",
- TAGINF(@"9207", [NSNumber numberWithInt:EDT_USHORT],@1), @"MeteringMode",
- // specific to compressed data
- TAGINF(@"a002", [NSNumber numberWithInt:EDT_ULONG],@1), @"PixelXDimension",
- TAGINF(@"a003", [NSNumber numberWithInt:EDT_ULONG],@1), @"PixelYDimension",
- // data type undefined, but this is a DSC camera, so value is always 1, treat as ushort
- TAGINF(@"a301", [NSNumber numberWithInt:EDT_USHORT],@1), @"SceneType",
- TAGINF(@"a217",[NSNumber numberWithInt:EDT_USHORT],@1), @"SensingMethod",
- //TAGINF(@"9201", [NSNumber numberWithInt:EDT_SRATIONAL], @1), @"ShutterSpeedValue",
- // specifies location of main subject in scene (x,y,wdith,height) expressed before rotation processing
- //TAGINF(@"9214", [NSNumber numberWithInt:EDT_USHORT], @4), @"SubjectArea",
- TAGINF(@"a403", [NSNumber numberWithInt:EDT_USHORT], @1), @"WhiteBalance",
- nil];
- return self;
-}
-
-- (NSData*) spliceExifBlockIntoJpeg: (NSData*) jpegdata withExifBlock: (NSString*) exifstr {
-
- CDVJpegHeaderWriter * exifWriter = [[CDVJpegHeaderWriter alloc] init];
-
- NSMutableData * exifdata = [NSMutableData dataWithCapacity: [exifstr length]/2];
- int idx;
- for (idx = 0; idx+1 < [exifstr length]; idx+=2) {
- NSRange range = NSMakeRange(idx, 2);
- NSString* hexStr = [exifstr substringWithRange:range];
- NSScanner* scanner = [NSScanner scannerWithString:hexStr];
- unsigned int intValue;
- [scanner scanHexInt:&intValue];
- [exifdata appendBytes:&intValue length:1];
- }
-
- NSMutableData * ddata = [NSMutableData dataWithCapacity: [jpegdata length]];
- NSMakeRange(0,4);
- int loc = 0;
- bool done = false;
- // read the jpeg data until we encounter the app1==0xFFE1 marker
- while (loc+1 < [jpegdata length]) {
- NSData * blag = [jpegdata subdataWithRange: NSMakeRange(loc,2)];
- if( [[blag description] isEqualToString : @""]) {
- // read the APP1 block size bits
- NSString * the = [exifWriter hexStringFromData:[jpegdata subdataWithRange: NSMakeRange(loc+2,2)]];
- NSNumber * app1width = [exifWriter numericFromHexString:the];
- //consume the original app1 block
- [ddata appendData:exifdata];
- // advance our loc marker past app1
- loc += [app1width intValue] + 2;
- done = true;
- } else {
- if(!done) {
- [ddata appendData:blag];
- loc += 2;
- } else {
- break;
- }
- }
- }
- // copy the remaining data
- [ddata appendData:[jpegdata subdataWithRange: NSMakeRange(loc,[jpegdata length]-loc)]];
- return ddata;
-}
-
-
-
-/**
- * Create the Exif data block as a hex string
- * jpeg uses Application Markers (APP's) as markers for application data
- * APP1 is the application marker reserved for exif data
- *
- * (NSDictionary*) datadict - with subdictionaries marked '{TIFF}' and '{EXIF}' as returned by imagePickerController with a valid
- * didFinishPickingMediaWithInfo data dict, under key @"UIImagePickerControllerMediaMetadata"
- *
- * the following constructs a hex string to Exif specifications, and is therefore brittle
- * altering the order of arguments to the string constructors, modifying field sizes or formats,
- * and any other minor change will likely prevent the exif data from being read
- */
-- (NSString*) createExifAPP1 : (NSDictionary*) datadict {
- NSMutableString * app1; // holds finalized product
- NSString * exifIFD; // exif information file directory
- NSString * subExifIFD; // subexif information file directory
-
- // FFE1 is the hex APP1 marker code, and will allow client apps to read the data
- NSString * app1marker = @"ffe1";
- // SSSS size, to be determined
- // EXIF ascii characters followed by 2bytes of zeros
- NSString * exifmarker = @"457869660000";
- // Tiff header: 4d4d is motorolla byte align (big endian), 002a is hex for 42
- NSString * tiffheader = @"4d4d002a";
- //first IFD offset from the Tiff header to IFD0. Since we are writing it, we know it's address 0x08
- NSString * ifd0offset = @"00000008";
- // current offset to next data area
- int currentDataOffset = 0;
-
- //data labeled as TIFF in UIImagePickerControllerMediaMetaData is part of the EXIF IFD0 portion of APP1
- exifIFD = [self createExifIFDFromDict: [datadict objectForKey:@"{TIFF}"] withFormatDict: IFD0TagFormatDict isIFD0:YES currentDataOffset:¤tDataOffset];
-
- //data labeled as EXIF in UIImagePickerControllerMediaMetaData is part of the EXIF Sub IFD portion of APP1
- subExifIFD = [self createExifIFDFromDict: [datadict objectForKey:@"{Exif}"] withFormatDict: SubIFDTagFormatDict isIFD0:NO currentDataOffset:¤tDataOffset];
- /*
- NSLog(@"SUB EXIF IFD %@ WITH SIZE: %d",exifIFD,[exifIFD length]);
-
- NSLog(@"SUB EXIF IFD %@ WITH SIZE: %d",subExifIFD,[subExifIFD length]);
- */
- // construct the complete app1 data block
- app1 = [[NSMutableString alloc] initWithFormat: @"%@%04x%@%@%@%@%@",
- app1marker,
- (unsigned int)(16 + ([exifIFD length]/2) + ([subExifIFD length]/2)) /*16+[exifIFD length]/2*/,
- exifmarker,
- tiffheader,
- ifd0offset,
- exifIFD,
- subExifIFD];
-
- return app1;
-}
-
-// returns hex string representing a valid exif information file directory constructed from the datadict and formatdict
-- (NSString*) createExifIFDFromDict : (NSDictionary*) datadict
- withFormatDict : (NSDictionary*) formatdict
- isIFD0 : (BOOL) ifd0flag
- currentDataOffset : (int*) dataoffset {
- NSArray * datakeys = [datadict allKeys]; // all known data keys
- NSArray * knownkeys = [formatdict allKeys]; // only keys in knowkeys are considered for entry in this IFD
- NSMutableArray * ifdblock = [[NSMutableArray alloc] initWithCapacity: [datadict count]]; // all ifd entries
- NSMutableArray * ifddatablock = [[NSMutableArray alloc] initWithCapacity: [datadict count]]; // data block entries
- // ifd0flag = NO; // ifd0 requires a special flag and has offset to next ifd appended to end
-
- // iterate through known provided data keys
- for (int i = 0; i < [datakeys count]; i++) {
- NSString * key = [datakeys objectAtIndex:i];
- // don't muck about with unknown keys
- if ([knownkeys indexOfObject: key] != NSNotFound) {
- // create new IFD entry
- NSString * entry = [self createIFDElement: key
- withFormat: [formatdict objectForKey:key]
- withElementData: [datadict objectForKey:key]];
- // create the IFD entry's data block
- NSString * data = [self createIFDElementDataWithFormat: [formatdict objectForKey:key]
- withData: [datadict objectForKey:key]];
- if (entry) {
- [ifdblock addObject:entry];
- if(!data) {
- [ifdblock addObject:@""];
- } else {
- [ifddatablock addObject:data];
- }
- }
- }
- }
-
- NSMutableString * exifstr = [[NSMutableString alloc] initWithCapacity: [ifdblock count] * 24];
- NSMutableString * dbstr = [[NSMutableString alloc] initWithCapacity: 100];
-
- int addr=*dataoffset; // current offset/address in datablock
- if (ifd0flag) {
- // calculate offset to datablock based on ifd file entry count
- addr += 14+(12*([ifddatablock count]+1)); // +1 for tag 0x8769, exifsubifd offset
- } else {
- // current offset + numSubIFDs (2-bytes) + 12*numSubIFDs + endMarker (4-bytes)
- addr += 2+(12*[ifddatablock count])+4;
- }
-
- for (int i = 0; i < [ifdblock count]; i++) {
- NSString * entry = [ifdblock objectAtIndex:i];
- NSString * data = [ifddatablock objectAtIndex:i];
-
- // check if the data fits into 4 bytes
- if( [data length] <= 8) {
- // concatenate the entry and the (4byte) data entry into the final IFD entry and append to exif ifd string
- [exifstr appendFormat : @"%@%@", entry, data];
- } else {
- [exifstr appendFormat : @"%@%08x", entry, addr];
- [dbstr appendFormat: @"%@", data];
- addr+= [data length] / 2;
- /*
- NSLog(@"=====data-length[%i]=======",[data length]);
- NSLog(@"addr-offset[%i]",addr);
- NSLog(@"entry[%@]",entry);
- NSLog(@"data[%@]",data);
- */
- }
- }
-
- // calculate IFD0 terminal offset tags, currently ExifSubIFD
- unsigned int entrycount = (unsigned int)[ifdblock count];
- if (ifd0flag) {
- // 18 accounts for 8769's width + offset to next ifd, 8 accounts for start of header
- NSNumber * offset = [NSNumber numberWithUnsignedInteger:[exifstr length] / 2 + [dbstr length] / 2 + 18+8];
-
- [self appendExifOffsetTagTo: exifstr
- withOffset : offset];
- entrycount++;
- }
- *dataoffset = addr;
- return [[NSString alloc] initWithFormat: @"%04x%@%@%@",
- entrycount,
- exifstr,
- @"00000000", // offset to next IFD, 0 since there is none
- dbstr]; // lastly, the datablock
-}
-
-// Creates an exif formatted exif information file directory entry
-- (NSString*) createIFDElement: (NSString*) elementName withFormat: (NSArray*) formtemplate withElementData: (NSString*) data {
- //NSArray * fielddata = [formatdict objectForKey: elementName];// format data of desired field
- if (formtemplate) {
- // format string @"%@%@%@%@", tag number, data format, components, value
- NSNumber * dataformat = [formtemplate objectAtIndex:1];
- NSNumber * components = [formtemplate objectAtIndex:2];
- if([components intValue] == 0) {
- components = [NSNumber numberWithUnsignedInteger:[data length] * DataTypeToWidth[[dataformat intValue]-1]];
- }
-
- return [[NSString alloc] initWithFormat: @"%@%@%08x",
- [formtemplate objectAtIndex:0], // the field code
- [self formatNumberWithLeadingZeroes: dataformat withPlaces: @4], // the data type code
- [components intValue]]; // number of components
- }
- return NULL;
-}
-
-/**
- * appends exif IFD0 tag 8769 "ExifOffset" to the string provided
- * (NSMutableString*) str - string you wish to append the 8769 tag to: APP1 or IFD0 hex data string
- * // TAGINF(@"8769", [NSNumber numberWithInt:EDT_ULONG], @1), @"ExifOffset",
- */
-- (void) appendExifOffsetTagTo: (NSMutableString*) str withOffset : (NSNumber*) offset {
- NSArray * format = TAGINF(@"8769", [NSNumber numberWithInt:EDT_ULONG], @1);
-
- NSString * entry = [self createIFDElement: @"ExifOffset"
- withFormat: format
- withElementData: [offset stringValue]];
-
- NSString * data = [self createIFDElementDataWithFormat: format
- withData: [offset stringValue]];
- [str appendFormat:@"%@%@", entry, data];
-}
-
-// formats the Information File Directory Data to exif format
-- (NSString*) createIFDElementDataWithFormat: (NSArray*) dataformat withData: (NSString*) data {
- NSMutableString * datastr = nil;
- NSNumber * tmp = nil;
- NSNumber * formatcode = [dataformat objectAtIndex:1];
- NSUInteger formatItemsCount = [dataformat count];
- NSNumber * num = @0;
- NSNumber * denom = @0;
-
- switch ([formatcode intValue]) {
- case EDT_UBYTE:
- break;
- case EDT_ASCII_STRING:
- datastr = [[NSMutableString alloc] init];
- for (int i = 0; i < [data length]; i++) {
- [datastr appendFormat:@"%02x",[data characterAtIndex:i]];
- }
- if (formatItemsCount > 3) {
- // We have additional data to append.
- // currently used by Date format to append final 0x00 but can be used by other data types as well in the future
- [datastr appendString:[dataformat objectAtIndex:3]];
- }
- if ([datastr length] < 8) {
- NSString * format = [NSString stringWithFormat:@"%%0%dd", (int)(8 - [datastr length])];
- [datastr appendFormat:format,0];
- }
- return datastr;
- case EDT_USHORT:
- return [[NSString alloc] initWithFormat : @"%@%@",
- [self formattedHexStringFromDecimalNumber: [NSNumber numberWithInt: [data intValue]] withPlaces: @4],
- @"0000"];
- case EDT_ULONG:
- tmp = [NSNumber numberWithUnsignedLong:[data intValue]];
- return [NSString stringWithFormat : @"%@",
- [self formattedHexStringFromDecimalNumber: tmp withPlaces: @8]];
- case EDT_URATIONAL:
- return [self decimalToUnsignedRational: [NSNumber numberWithDouble:[data doubleValue]]
- withResultNumerator: &num
- withResultDenominator: &denom];
- case EDT_SBYTE:
-
- break;
- case EDT_UNDEFINED:
- break; // 8 bits
- case EDT_SSHORT:
- break;
- case EDT_SLONG:
- break; // 32bit signed integer (2's complement)
- case EDT_SRATIONAL:
- break; // 2 SLONGS, first long is numerator, second is denominator
- case EDT_SINGLEFLOAT:
- break;
- case EDT_DOUBLEFLOAT:
- break;
- }
- return datastr;
-}
-
-//======================================================================================================================
-// Utility Methods
-//======================================================================================================================
-
-// creates a formatted little endian hex string from a number and width specifier
-- (NSString*) formattedHexStringFromDecimalNumber: (NSNumber*) numb withPlaces: (NSNumber*) width {
- NSMutableString * str = [[NSMutableString alloc] initWithCapacity:[width intValue]];
- NSString * formatstr = [[NSString alloc] initWithFormat: @"%%%@%dx", @"0", [width intValue]];
- [str appendFormat:formatstr, [numb intValue]];
- return str;
-}
-
-// format number as string with leading 0's
-- (NSString*) formatNumberWithLeadingZeroes: (NSNumber *) numb withPlaces: (NSNumber *) places {
- NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
- NSString *formatstr = [@"" stringByPaddingToLength:[places unsignedIntegerValue] withString:@"0" startingAtIndex:0];
- [formatter setPositiveFormat:formatstr];
- return [formatter stringFromNumber:numb];
-}
-
-// approximate a decimal with a rational by method of continued fraction
-// can be collasped into decimalToUnsignedRational after testing
-- (void) decimalToRational: (NSNumber *) numb
- withResultNumerator: (NSNumber**) numerator
- withResultDenominator: (NSNumber**) denominator {
- NSMutableArray * fractionlist = [[NSMutableArray alloc] initWithCapacity:8];
-
- [self continuedFraction: [numb doubleValue]
- withFractionList: fractionlist
- withHorizon: 8];
-
- // simplify complex fraction represented by partial fraction list
- [self expandContinuedFraction: fractionlist
- withResultNumerator: numerator
- withResultDenominator: denominator];
-
-}
-
-// approximate a decimal with an unsigned rational by method of continued fraction
-- (NSString*) decimalToUnsignedRational: (NSNumber *) numb
- withResultNumerator: (NSNumber**) numerator
- withResultDenominator: (NSNumber**) denominator {
- NSMutableArray * fractionlist = [[NSMutableArray alloc] initWithCapacity:8];
-
- // generate partial fraction list
- [self continuedFraction: [numb doubleValue]
- withFractionList: fractionlist
- withHorizon: 8];
-
- // simplify complex fraction represented by partial fraction list
- [self expandContinuedFraction: fractionlist
- withResultNumerator: numerator
- withResultDenominator: denominator];
-
- return [self formatFractionList: fractionlist];
-}
-
-// recursive implementation of decimal approximation by continued fraction
-- (void) continuedFraction: (double) val
- withFractionList: (NSMutableArray*) fractionlist
- withHorizon: (int) horizon {
- int whole;
- double remainder;
- // 1. split term
- [self splitDouble: val withIntComponent: &whole withFloatRemainder: &remainder];
- [fractionlist addObject: [NSNumber numberWithInt:whole]];
-
- // 2. calculate reciprocal of remainder
- if (!remainder) return; // early exit, exact fraction found, avoids recip/0
- double recip = 1 / remainder;
-
- // 3. exit condition
- if ([fractionlist count] > horizon) {
- return;
- }
-
- // 4. recurse
- [self continuedFraction:recip withFractionList: fractionlist withHorizon: horizon];
-
-}
-
-// expand continued fraction list, creating a single level rational approximation
--(void) expandContinuedFraction: (NSArray*) fractionlist
- withResultNumerator: (NSNumber**) numerator
- withResultDenominator: (NSNumber**) denominator {
- NSUInteger i = 0;
- int den = 0;
- int num = 0;
- if ([fractionlist count] == 1) {
- *numerator = [NSNumber numberWithInt:[[fractionlist objectAtIndex:0] intValue]];
- *denominator = @1;
- return;
- }
-
- //begin at the end of the list
- i = [fractionlist count] - 1;
- num = 1;
- den = [[fractionlist objectAtIndex:i] intValue];
-
- while (i > 0) {
- int t = [[fractionlist objectAtIndex: i-1] intValue];
- num = t * den + num;
- if (i==1) {
- break;
- } else {
- t = num;
- num = den;
- den = t;
- }
- i--;
- }
- // set result parameters values
- *numerator = [NSNumber numberWithInt: num];
- *denominator = [NSNumber numberWithInt: den];
-}
-
-// formats expanded fraction list to string matching exif specification
-- (NSString*) formatFractionList: (NSArray *) fractionlist {
- NSMutableString * str = [[NSMutableString alloc] initWithCapacity:16];
-
- if ([fractionlist count] == 1){
- [str appendFormat: @"%08x00000001", [[fractionlist objectAtIndex:0] intValue]];
- }
- return str;
-}
-
-// format rational as
-- (NSString*) formatRationalWithNumerator: (NSNumber*) numerator withDenominator: (NSNumber*) denominator asSigned: (Boolean) signedFlag {
- NSMutableString * str = [[NSMutableString alloc] initWithCapacity:16];
- if (signedFlag) {
- long num = [numerator longValue];
- long den = [denominator longValue];
- [str appendFormat: @"%08lx%08lx", num >= 0 ? num : ~ABS(num) + 1, num >= 0 ? den : ~ABS(den) + 1];
- } else {
- [str appendFormat: @"%08lx%08lx", [numerator unsignedLongValue], [denominator unsignedLongValue]];
- }
- return str;
-}
-
-// split a floating point number into two integer values representing the left and right side of the decimal
-- (void) splitDouble: (double) val withIntComponent: (int*) rightside withFloatRemainder: (double*) leftside {
- *rightside = val; // convert numb to int representation, which truncates the decimal portion
- *leftside = val - *rightside;
-}
-
-
-//
-- (NSString*) hexStringFromData : (NSData*) data {
- //overflow detection
- const unsigned char *dataBuffer = [data bytes];
- return [[NSString alloc] initWithFormat: @"%02x%02x",
- (unsigned char)dataBuffer[0],
- (unsigned char)dataBuffer[1]];
-}
-
-// convert a hex string to a number
-- (NSNumber*) numericFromHexString : (NSString *) hexstring {
- NSScanner * scan = NULL;
- unsigned int numbuf= 0;
-
- scan = [NSScanner scannerWithString:hexstring];
- [scan scanHexInt:&numbuf];
- return [NSNumber numberWithInt:numbuf];
-}
-
-@end
diff --git a/src/ubuntu/CaptureWidget.qml b/src/ubuntu/CaptureWidget.qml
deleted file mode 100644
index e3fe20e..0000000
--- a/src/ubuntu/CaptureWidget.qml
+++ /dev/null
@@ -1,119 +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
- videoRecorder.mediaContainer: "mp4"
- 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.capture();
- }
- }
- }
- }
- 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"
- }
- }
-}
diff --git a/src/ubuntu/back.png b/src/ubuntu/back.png
deleted file mode 100644
index af78faa..0000000
Binary files a/src/ubuntu/back.png and /dev/null differ
diff --git a/src/ubuntu/camera.cpp b/src/ubuntu/camera.cpp
deleted file mode 100644
index eada5dc..0000000
--- a/src/ubuntu/camera.cpp
+++ /dev/null
@@ -1,143 +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
-
-#include
-#include
-#include
-#include
-#include
-
-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.object = 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) {
- newImage.setFileTemplate("imgXXXXXX.png");
- type = "png";
- } else {
- newImage.setFileTemplate("imgXXXXXX.jpg");
- type = "jpg";
- }
-
- newImage.open();
- newImage.setAutoRemove(false);
- image.save(newImage.fileName(), type, quality);
-
- path = newImage.fileName();
- 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(QUrl::fromLocalFile(absolutePath).toString());
- }
- }
-
- 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(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.object.destroy()");
- this->cb(_lastEcId, "canceled");
-
- _lastEcId = _lastScId = 0;
-}
diff --git a/src/ubuntu/camera.h b/src/ubuntu/camera.h
deleted file mode 100644
index aa06698..0000000
--- a/src/ubuntu/camera.h
+++ /dev/null
@@ -1,76 +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
-
-#include
-#include
-#include
-#include
-#include
-
-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);
-
-private:
- bool preprocessImage(QString &path);
-
- int _lastScId;
- int _lastEcId;
- QSharedPointer _camera;
-
- QVariantMap _options;
-protected:
- enum DestinationType {
- DATA_URL = 0,
- FILE_URI = 1
- };
- enum EncodingType {
- JPEG = 0,
- PNG = 1
- };
-};
-
-#endif // CAMERA_H
diff --git a/src/ubuntu/shoot.png b/src/ubuntu/shoot.png
deleted file mode 100644
index c093b63..0000000
Binary files a/src/ubuntu/shoot.png and /dev/null differ
diff --git a/src/ubuntu/toolbar-left.png b/src/ubuntu/toolbar-left.png
deleted file mode 100644
index 720d7f6..0000000
Binary files a/src/ubuntu/toolbar-left.png and /dev/null differ
diff --git a/src/ubuntu/toolbar-middle.png b/src/ubuntu/toolbar-middle.png
deleted file mode 100644
index 77595bb..0000000
Binary files a/src/ubuntu/toolbar-middle.png and /dev/null differ
diff --git a/src/ubuntu/toolbar-right.png b/src/ubuntu/toolbar-right.png
deleted file mode 100644
index e4e6aa6..0000000
Binary files a/src/ubuntu/toolbar-right.png and /dev/null differ
diff --git a/src/windows8/CameraProxy.js b/src/windows8/CameraProxy.js
deleted file mode 100644
index d46553b..0000000
--- a/src/windows8/CameraProxy.js
+++ /dev/null
@@ -1,354 +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.
- *
-*/
-
-/*global Windows:true, URL:true */
-
-
-
-var cordova = require('cordova'),
- Camera = require('./Camera'),
- FileEntry = require('org.apache.cordova.file.FileEntry'),
- FileError = require('org.apache.cordova.file.FileError'),
- FileReader = require('org.apache.cordova.file.FileReader');
-
-module.exports = {
-
- // args will contain :
- // ... it is an array, so be careful
- // 0 quality:50,
- // 1 destinationType:Camera.DestinationType.FILE_URI,
- // 2 sourceType:Camera.PictureSourceType.CAMERA,
- // 3 targetWidth:-1,
- // 4 targetHeight:-1,
- // 5 encodingType:Camera.EncodingType.JPEG,
- // 6 mediaType:Camera.MediaType.PICTURE,
- // 7 allowEdit:false,
- // 8 correctOrientation:false,
- // 9 saveToPhotoAlbum:false,
- // 10 popoverOptions:null
-
- takePicture: function (successCallback, errorCallback, args) {
- var encodingType = args[5];
- var targetWidth = args[3];
- var targetHeight = args[4];
- var sourceType = args[2];
- var destinationType = args[1];
- var mediaType = args[6];
- var saveToPhotoAlbum = args[9];
-
- var pkg = Windows.ApplicationModel.Package.current;
- var packageId = pkg.installedLocation;
-
- var fail = function (fileError) {
- errorCallback("FileError, code:" + fileError.code);
- };
-
- // resize method :)
- var resizeImage = function (file) {
- var tempPhotoFileName = "";
- if (encodingType == Camera.EncodingType.PNG) {
- tempPhotoFileName = "camera_cordova_temp_return.png";
- } else {
- tempPhotoFileName = "camera_cordova_temp_return.jpg";
- }
- var imgObj = new Image();
- var success = function (fileEntry) {
- var successCB = function (filePhoto) {
- var fileType = file.contentType,
- reader = new FileReader();
- reader.onloadend = function () {
- var image = new Image();
- image.src = reader.result;
- image.onload = function () {
- var imageWidth = targetWidth,
- imageHeight = targetHeight;
- var canvas = document.createElement('canvas');
-
- canvas.width = imageWidth;
- canvas.height = imageHeight;
-
- var ctx = canvas.getContext("2d");
- ctx.drawImage(this, 0, 0, imageWidth, imageHeight);
-
- // The resized file ready for upload
- var _blob = canvas.msToBlob();
- var _stream = _blob.msDetachStream();
-
- var storageFolder = Windows.Storage.ApplicationData.current.localFolder;
- storageFolder.createFileAsync(tempPhotoFileName, Windows.Storage.CreationCollisionOption.generateUniqueName).done(function (file) {
- file.openAsync(Windows.Storage.FileAccessMode.readWrite).done(function (fileStream) {
- Windows.Storage.Streams.RandomAccessStream.copyAndCloseAsync(_stream, fileStream).done(function () {
- var _imageUrl = URL.createObjectURL(file);
- successCallback(_imageUrl);
- }, function () {
- errorCallback("Resize picture error.");
- });
- }, function () {
- errorCallback("Resize picture error.");
- });
- }, function () {
- errorCallback("Resize picture error.");
- });
-
- };
- };
-
- reader.readAsDataURL(filePhoto);
- };
-
- var failCB = function () {
- errorCallback("File not found.");
- };
- fileEntry.file(successCB, failCB);
- };
-
- var storageFolder = Windows.Storage.ApplicationData.current.localFolder;
- file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).then(function (storageFile) {
- success(new FileEntry(storageFile.name, storageFile.path));
- }, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }, function () {
- errorCallback("Folder not access.");
- });
-
- };
-
- // because of asynchronous method, so let the successCallback be called in it.
- var resizeImageBase64 = function (file) {
- var imgObj = new Image();
- var success = function (fileEntry) {
- var successCB = function (filePhoto) {
- var fileType = file.contentType,
- reader = new FileReader();
- reader.onloadend = function () {
- var image = new Image();
- image.src = reader.result;
-
- image.onload = function () {
- var imageWidth = targetWidth,
- imageHeight = targetHeight;
- var canvas = document.createElement('canvas');
-
- canvas.width = imageWidth;
- canvas.height = imageHeight;
-
- var ctx = canvas.getContext("2d");
- ctx.drawImage(this, 0, 0, imageWidth, imageHeight);
-
- // The resized file ready for upload
- var finalFile = canvas.toDataURL(fileType);
-
- // Remove the prefix such as "data:" + contentType + ";base64," , in order to meet the Cordova API.
- var arr = finalFile.split(",");
- var newStr = finalFile.substr(arr[0].length + 1);
- successCallback(newStr);
- };
- };
-
- reader.readAsDataURL(filePhoto);
-
- };
- var failCB = function () {
- errorCallback("File not found.");
- };
- fileEntry.file(successCB, failCB);
- };
-
- var storageFolder = Windows.Storage.ApplicationData.current.localFolder;
- file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).then(function (storageFile) {
- success(new FileEntry(storageFile.name, "ms-appdata:///local/" + storageFile.name));
- }, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }, function () {
- errorCallback("Folder not access.");
- });
-
-
- };
-
- if (sourceType != Camera.PictureSourceType.CAMERA) {
- var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
- fileOpenPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
- if (mediaType == Camera.MediaType.PICTURE) {
- fileOpenPicker.fileTypeFilter.replaceAll([".png", ".jpg", ".jpeg"]);
- }
- else if (mediaType == Camera.MediaType.VIDEO) {
- fileOpenPicker.fileTypeFilter.replaceAll([".avi", ".flv", ".asx", ".asf", ".mov", ".mp4", ".mpg", ".rm", ".srt", ".swf", ".wmv", ".vob"]);
- }
- else {
- fileOpenPicker.fileTypeFilter.replaceAll(["*"]);
- }
-
- fileOpenPicker.pickSingleFileAsync().then(function (file) {
- if (file) {
- if (destinationType == Camera.DestinationType.FILE_URI) {
- if (targetHeight > 0 && targetWidth > 0) {
- resizeImage(file);
- }
- else {
-
- var storageFolder = Windows.Storage.ApplicationData.current.localFolder;
- file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).then(function (storageFile) {
- successCallback(URL.createObjectURL(storageFile));
- }, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }, function () {
- errorCallback("Folder not access.");
- });
-
- }
- }
- else {
- if (targetHeight > 0 && targetWidth > 0) {
- resizeImageBase64(file);
- } else {
- Windows.Storage.FileIO.readBufferAsync(file).done(function (buffer) {
- var strBase64 = Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer);
- successCallback(strBase64);
- });
- }
-
- }
-
- } else {
- errorCallback("User didn't choose a file.");
- }
- }, function () {
- errorCallback("User didn't choose a file.");
- });
- }
- else {
-
- var cameraCaptureUI = new Windows.Media.Capture.CameraCaptureUI();
- cameraCaptureUI.photoSettings.allowCropping = true;
- var allowCrop = !!args[7];
- if (!allowCrop) {
- cameraCaptureUI.photoSettings.allowCropping = false;
- }
-
- if (encodingType == Camera.EncodingType.PNG) {
- cameraCaptureUI.photoSettings.format = Windows.Media.Capture.CameraCaptureUIPhotoFormat.png;
- } else {
- cameraCaptureUI.photoSettings.format = Windows.Media.Capture.CameraCaptureUIPhotoFormat.jpeg;
- }
-
- // decide which max pixels should be supported by targetWidth or targetHeight.
- if (targetWidth >= 1280 || targetHeight >= 960) {
- cameraCaptureUI.photoSettings.maxResolution = Windows.Media.Capture.CameraCaptureUIMaxPhotoResolution.large3M;
- }
- else if (targetWidth >= 1024 || targetHeight >= 768) {
- cameraCaptureUI.photoSettings.maxResolution = Windows.Media.Capture.CameraCaptureUIMaxPhotoResolution.mediumXga;
- }
- else if (targetWidth >= 800 || targetHeight >= 600) {
- cameraCaptureUI.photoSettings.maxResolution = Windows.Media.Capture.CameraCaptureUIMaxPhotoResolution.mediumXga;
- }
- else if (targetWidth >= 640 || targetHeight >= 480) {
- cameraCaptureUI.photoSettings.maxResolution = Windows.Media.Capture.CameraCaptureUIMaxPhotoResolution.smallVga;
- }
- else if (targetWidth >= 320 || targetHeight >= 240) {
- cameraCaptureUI.photoSettings.maxResolution = Windows.Media.Capture.CameraCaptureUIMaxPhotoResolution.verySmallQvga;
- }
- else {
- cameraCaptureUI.photoSettings.maxResolution = Windows.Media.Capture.CameraCaptureUIMaxPhotoResolution.highestAvailable;
- }
-
- cameraCaptureUI.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).then(function (picture) {
- if (picture) {
- // save to photo album successCallback
- var success = function (fileEntry) {
- if (destinationType == Camera.DestinationType.FILE_URI) {
- if (targetHeight > 0 && targetWidth > 0) {
- resizeImage(picture);
- } else {
-
- var storageFolder = Windows.Storage.ApplicationData.current.localFolder;
- picture.copyAsync(storageFolder, picture.name, Windows.Storage.NameCollisionOption.replaceExisting).then(function (storageFile) {
- successCallback("ms-appdata:///local/" + storageFile.name);
- }, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }, function () {
- errorCallback("Folder not access.");
- });
- }
- } else {
- if (targetHeight > 0 && targetWidth > 0) {
- resizeImageBase64(picture);
- } else {
- Windows.Storage.FileIO.readBufferAsync(picture).done(function (buffer) {
- var strBase64 = Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer);
- successCallback(strBase64);
- });
- }
- }
- };
- // save to photo album errorCallback
- var fail = function () {
- //errorCallback("FileError, code:" + fileError.code);
- errorCallback("Save fail.");
- };
-
- if (saveToPhotoAlbum) {
- Windows.Storage.StorageFile.getFileFromPathAsync(picture.path).then(function (storageFile) {
- storageFile.copyAsync(Windows.Storage.KnownFolders.picturesLibrary, picture.name, Windows.Storage.NameCollisionOption.generateUniqueName).then(function (storageFile) {
- success(storageFile);
- }, function () {
- fail();
- });
- });
- //var directory = new DirectoryEntry("Pictures", parentPath);
- //new FileEntry(picture.name, picture.path).copyTo(directory, null, success, fail);
- } else {
- if (destinationType == Camera.DestinationType.FILE_URI) {
- if (targetHeight > 0 && targetWidth > 0) {
- resizeImage(picture);
- } else {
-
- var storageFolder = Windows.Storage.ApplicationData.current.localFolder;
- picture.copyAsync(storageFolder, picture.name, Windows.Storage.NameCollisionOption.replaceExisting).then(function (storageFile) {
- successCallback("ms-appdata:///local/" + storageFile.name);
- }, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }, function () {
- errorCallback("Folder not access.");
- });
- }
- } else {
- if (targetHeight > 0 && targetWidth > 0) {
- resizeImageBase64(picture);
- } else {
- Windows.Storage.FileIO.readBufferAsync(picture).done(function (buffer) {
- var strBase64 = Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer);
- successCallback(strBase64);
- });
- }
- }
- }
- } else {
- errorCallback("User didn't capture a photo.");
- }
- }, function () {
- errorCallback("Fail to capture a photo.");
- });
- }
- }
-};
-
-require("cordova/exec/proxy").add("Camera",module.exports);
diff --git a/src/wp/Camera.cs b/src/wp/Camera.cs
deleted file mode 100644
index b76929b..0000000
--- a/src/wp/Camera.cs
+++ /dev/null
@@ -1,515 +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
- {
-
- ///
- /// Return base64 encoded string
- ///
- private const int DATA_URL = 0;
-
- ///
- /// Return file uri
- ///
- private const int FILE_URI = 1;
-
- ///
- /// Choose image from picture library
- ///
- private const int PHOTOLIBRARY = 0;
-
- ///
- /// Take picture from camera
- ///
-
- private const int CAMERA = 1;
-
- ///
- /// Choose image from picture library
- ///
- private const int SAVEDPHOTOALBUM = 2;
-
- ///
- /// Take a picture of type JPEG
- ///
- private const int JPEG = 0;
-
- ///
- /// Take a picture of type PNG
- ///
- private const int PNG = 1;
-
- ///
- /// Folder to store captured images
- ///
- private const string isoFolder = "CapturedImagesCache";
-
- ///
- /// Represents captureImage action options.
- ///
- [DataContract]
- public class CameraOptions
- {
- ///
- /// Source to getPicture from.
- ///
- [DataMember(IsRequired = false, Name = "sourceType")]
- public int PictureSourceType { get; set; }
-
- ///
- /// Format of image that returned from getPicture.
- ///
- [DataMember(IsRequired = false, Name = "destinationType")]
- public int DestinationType { get; set; }
-
- ///
- /// Quality of saved image
- ///
- [DataMember(IsRequired = false, Name = "quality")]
- public int Quality { get; set; }
-
- ///
- /// Controls whether or not the image is also added to the device photo album.
- ///
- [DataMember(IsRequired = false, Name = "saveToPhotoAlbum")]
- public bool SaveToPhotoAlbum { get; set; }
-
- ///
- /// Ignored
- ///
- [DataMember(IsRequired = false, Name = "correctOrientation")]
- public bool CorrectOrientation { get; set; }
-
- ///
- /// Ignored
- ///
- [DataMember(IsRequired = false, Name = "allowEdit")]
- public bool AllowEdit { get; set; }
-
- ///
- /// Height in pixels to scale image
- ///
- [DataMember(IsRequired = false, Name = "encodingType")]
- public int EncodingType { get; set; }
-
- ///
- /// Height in pixels to scale image
- ///
- [DataMember(IsRequired = false, Name = "mediaType")]
- public int MediaType { get; set; }
-
-
- ///
- /// Height in pixels to scale image
- ///
- [DataMember(IsRequired = false, Name = "targetHeight")]
- public int TargetHeight { get; set; }
-
-
- ///
- /// Width in pixels to scale image
- ///
- [DataMember(IsRequired = false, Name = "targetWidth")]
- public int TargetWidth { get; set; }
-
- ///
- /// Creates options object with default parameters
- ///
- public CameraOptions()
- {
- this.SetDefaultValues(new StreamingContext());
- }
-
- ///
- /// Initializes default values for class fields.
- /// Implemented in separate method because default constructor is not invoked during deserialization.
- ///
- ///
- [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;
- }
- }
-
- ///
- /// Camera options
- ///
- CameraOptions cameraOptions;
-
- public void takePicture(string options)
- {
- try
- {
- string[] args = JSON.JsonHelper.Deserialize(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;
- }
-
- if(cameraOptions.DestinationType != Camera.FILE_URI && cameraOptions.DestinationType != Camera.DATA_URL )
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Incorrect option: destinationType"));
- return;
- }
-
- ChooserBase 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;
- 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 orient = ImageExifHelper.getImageOrientationFromStream(e.ChosenPhoto);
- int newAngle = 0;
- 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
- }
-
- 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
- {
- imagePathOrContent = SaveImageToLocalStorage(rotImageStream, Path.GetFileName(e.OriginalFileName));
- }
- }
- }
- else // no need to reorient
- {
- if (cameraOptions.DestinationType == DATA_URL)
- {
- imagePathOrContent = GetImageContent(e.ChosenPhoto);
- }
- else // FILE_URL
- {
- 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;
- }
- }
-
- ///
- /// Returns image content in a form of base64 string
- ///
- /// Image stream
- /// Base64 representation of the image
- private string GetImageContent(Stream stream)
- {
- byte[] imageContent = null;
-
- try
- {
- //use photo's actual width & height if user doesn't provide width & height
- if (cameraOptions.TargetWidth < 0 && cameraOptions.TargetHeight < 0)
- {
- int streamLength = (int)stream.Length;
- imageContent = new byte[streamLength + 1];
- stream.Read(imageContent, 0, streamLength);
- }
- else
- {
- // resize photo
- imageContent = ResizePhoto(stream);
- }
- }
- finally
- {
- stream.Dispose();
- }
-
- return Convert.ToBase64String(imageContent);
- }
-
- ///
- /// Resize image
- ///
- /// Image stream
- /// File data
- /// resized image
- 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;
-
- //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);
-
- //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;
- }
-
- ///
- /// Util: Dispose a bitmap resource
- ///
- /// BitmapSource subclass to dispose
- private void DisposeImage(BitmapSource image)
- {
- if (image != null)
- {
- try
- {
- using (var ms = new MemoryStream(new byte[] { 0x0 }))
- {
- image.SetSource(ms);
- }
- }
- catch (Exception)
- {
- }
- }
- }
-
- ///
- /// Saves captured image in isolated storage
- ///
- /// image file name
- /// Image path
- 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();
- }
- }
-
- }
-}
diff --git a/www/Camera.js b/www/Camera.js
deleted file mode 100644
index 555bb5e..0000000
--- a/www/Camera.js
+++ /dev/null
@@ -1,75 +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.
- *
-*/
-
-var argscheck = require('cordova/argscheck'),
- exec = require('cordova/exec'),
- Camera = require('./Camera');
- // XXX: commented out
- //CameraPopoverHandle = require('./CameraPopoverHandle');
-
-var cameraExport = {};
-
-// Tack on the Camera Constants to the base camera plugin.
-for (var key in Camera) {
- cameraExport[key] = Camera[key];
-}
-
-/**
- * Gets a picture from source defined by "options.sourceType", and returns the
- * image as defined by the "options.destinationType" option.
-
- * The defaults are sourceType=CAMERA and destinationType=FILE_URI.
- *
- * @param {Function} successCallback
- * @param {Function} errorCallback
- * @param {Object} options
- */
-cameraExport.getPicture = function(successCallback, errorCallback, options) {
- argscheck.checkArgs('fFO', 'Camera.getPicture', arguments);
- options = options || {};
- var getValue = argscheck.getValue;
-
- var quality = getValue(options.quality, 50);
- var destinationType = getValue(options.destinationType, Camera.DestinationType.FILE_URI);
- var sourceType = getValue(options.sourceType, Camera.PictureSourceType.CAMERA);
- var targetWidth = getValue(options.targetWidth, -1);
- var targetHeight = getValue(options.targetHeight, -1);
- var encodingType = getValue(options.encodingType, Camera.EncodingType.JPEG);
- var mediaType = getValue(options.mediaType, Camera.MediaType.PICTURE);
- var allowEdit = !!options.allowEdit;
- var correctOrientation = !!options.correctOrientation;
- var saveToPhotoAlbum = !!options.saveToPhotoAlbum;
- var popoverOptions = getValue(options.popoverOptions, null);
- var cameraDirection = getValue(options.cameraDirection, Camera.Direction.BACK);
-
- var args = [quality, destinationType, sourceType, targetWidth, targetHeight, encodingType,
- mediaType, allowEdit, correctOrientation, saveToPhotoAlbum, popoverOptions, cameraDirection];
-
- exec(successCallback, errorCallback, "Camera", "takePicture", args);
- // XXX: commented out
- //return new CameraPopoverHandle();
-};
-
-cameraExport.cleanup = function(successCallback, errorCallback) {
- exec(successCallback, errorCallback, "Camera", "cleanup", []);
-};
-
-module.exports = cameraExport;
diff --git a/www/CameraConstants.js b/www/CameraConstants.js
deleted file mode 100644
index ae4e534..0000000
--- a/www/CameraConstants.js
+++ /dev/null
@@ -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.
- *
-*/
-
-module.exports = {
- 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)
- },
- EncodingType:{
- JPEG: 0, // Return JPEG encoded image
- PNG: 1 // Return PNG encoded image
- },
- MediaType:{
- PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
- VIDEO: 1, // allow selection of video only, ONLY RETURNS URL
- ALLMEDIA : 2 // allow selection from all media types
- },
- 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)
- },
- PopoverArrowDirection:{
- ARROW_UP : 1, // matches iOS UIPopoverArrowDirection constants to specify arrow location on popover
- ARROW_DOWN : 2,
- ARROW_LEFT : 4,
- ARROW_RIGHT : 8,
- ARROW_ANY : 15
- },
- Direction:{
- BACK: 0,
- FRONT: 1
- }
-};
diff --git a/www/CameraPopoverHandle.js b/www/CameraPopoverHandle.js
deleted file mode 100644
index 7a4c32d..0000000
--- a/www/CameraPopoverHandle.js
+++ /dev/null
@@ -1,33 +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.
- *
-*/
-
-var exec = require('cordova/exec');
-
-/**
- * A handle to an image picker popover.
- */
-var CameraPopoverHandle = function() {
- this.setPosition = function(popoverOptions) {
- console.log('CameraPopoverHandle.setPosition is only supported on iOS.');
- };
-};
-
-module.exports = CameraPopoverHandle;
diff --git a/www/CameraPopoverOptions.js b/www/CameraPopoverOptions.js
deleted file mode 100644
index c024984..0000000
--- a/www/CameraPopoverOptions.js
+++ /dev/null
@@ -1,37 +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.
- *
-*/
-
-var Camera = require('./Camera');
-
-/**
- * Encapsulates options for iOS Popover image picker
- */
-var CameraPopoverOptions = function(x,y,width,height,arrowDir){
- // information of rectangle that popover should be anchored to
- this.x = x || 0;
- this.y = y || 32;
- this.width = width || 320;
- this.height = height || 480;
- // The direction of the popover arrow
- this.arrowDir = arrowDir || Camera.PopoverArrowDirection.ARROW_ANY;
-};
-
-module.exports = CameraPopoverOptions;
diff --git a/www/ios/CameraPopoverHandle.js b/www/ios/CameraPopoverHandle.js
deleted file mode 100644
index fc48c11..0000000
--- a/www/ios/CameraPopoverHandle.js
+++ /dev/null
@@ -1,34 +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.
- *
-*/
-
-var exec = require('cordova/exec');
-
-/**
- * A handle to an image picker popover.
- */
-var CameraPopoverHandle = function() {
- this.setPosition = function(popoverOptions) {
- var args = [ popoverOptions ];
- exec(null, null, "Camera", "repositionPopover", args);
- };
-};
-
-module.exports = CameraPopoverHandle;