Ben 8 years ago
parent
commit
022b2d2764
100 changed files with 18518 additions and 7 deletions
  1. 1 0
      .gitignore
  2. BIN
      .vs/miaomiao/v14/.suo
  3. BIN
      miaomiao/bin/Android/Debug/android-debug-unaligned.apk
  4. BIN
      miaomiao/bin/Android/Debug/android-debug.apk
  5. 8 5
      miaomiao/config.xml
  6. 5 1
      miaomiao/miaomiao.jsproj.user
  7. 3 1
      miaomiao/package.json
  8. 12 0
      miaomiao/plugins/android.json
  9. 37 0
      miaomiao/plugins/cordova-plugin-camera/CONTRIBUTING.md
  10. 202 0
      miaomiao/plugins/cordova-plugin-camera/LICENSE
  11. 5 0
      miaomiao/plugins/cordova-plugin-camera/NOTICE
  12. 793 0
      miaomiao/plugins/cordova-plugin-camera/README.md
  13. 360 0
      miaomiao/plugins/cordova-plugin-camera/RELEASENOTES.md
  14. 628 0
      miaomiao/plugins/cordova-plugin-camera/appium-tests/android/android.spec.js
  15. 305 0
      miaomiao/plugins/cordova-plugin-camera/appium-tests/helpers/cameraHelper.js
  16. 489 0
      miaomiao/plugins/cordova-plugin-camera/appium-tests/ios/ios.spec.js
  17. 421 0
      miaomiao/plugins/cordova-plugin-camera/doc/de/README.md
  18. 434 0
      miaomiao/plugins/cordova-plugin-camera/doc/de/index.md
  19. 411 0
      miaomiao/plugins/cordova-plugin-camera/doc/es/README.md
  20. 391 0
      miaomiao/plugins/cordova-plugin-camera/doc/es/index.md
  21. 378 0
      miaomiao/plugins/cordova-plugin-camera/doc/fr/README.md
  22. 391 0
      miaomiao/plugins/cordova-plugin-camera/doc/fr/index.md
  23. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/android-fail.png
  24. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/android-success.png
  25. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/blackberry-fail.png
  26. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/blackberry-success.png
  27. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/browser-fail.png
  28. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/browser-success.png
  29. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/firefox-fail.png
  30. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/firefox-success.png
  31. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/fireos-fail.png
  32. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/fireos-success.png
  33. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/ios-fail.png
  34. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/ios-success.png
  35. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/ubuntu-fail.png
  36. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/ubuntu-success.png
  37. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/windows-fail.png
  38. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/windows-success.png
  39. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/wp8-fail.png
  40. BIN
      miaomiao/plugins/cordova-plugin-camera/doc/img/wp8-success.png
  41. 421 0
      miaomiao/plugins/cordova-plugin-camera/doc/it/README.md
  42. 434 0
      miaomiao/plugins/cordova-plugin-camera/doc/it/index.md
  43. 421 0
      miaomiao/plugins/cordova-plugin-camera/doc/ja/README.md
  44. 434 0
      miaomiao/plugins/cordova-plugin-camera/doc/ja/index.md
  45. 421 0
      miaomiao/plugins/cordova-plugin-camera/doc/ko/README.md
  46. 434 0
      miaomiao/plugins/cordova-plugin-camera/doc/ko/index.md
  47. 421 0
      miaomiao/plugins/cordova-plugin-camera/doc/pl/README.md
  48. 434 0
      miaomiao/plugins/cordova-plugin-camera/doc/pl/index.md
  49. 417 0
      miaomiao/plugins/cordova-plugin-camera/doc/ru/index.md
  50. 421 0
      miaomiao/plugins/cordova-plugin-camera/doc/zh/README.md
  51. 435 0
      miaomiao/plugins/cordova-plugin-camera/doc/zh/index.md
  52. 443 0
      miaomiao/plugins/cordova-plugin-camera/jsdoc2md/TEMPLATE.md
  53. 63 0
      miaomiao/plugins/cordova-plugin-camera/package.json
  54. 283 0
      miaomiao/plugins/cordova-plugin-camera/plugin.xml
  55. 1399 0
      miaomiao/plugins/cordova-plugin-camera/src/android/CameraLauncher.java
  56. 104 0
      miaomiao/plugins/cordova-plugin-camera/src/android/CordovaUri.java
  57. 185 0
      miaomiao/plugins/cordova-plugin-camera/src/android/ExifHelper.java
  58. 319 0
      miaomiao/plugins/cordova-plugin-camera/src/android/FileHelper.java
  59. 21 0
      miaomiao/plugins/cordova-plugin-camera/src/android/xml/provider_paths.xml
  60. 227 0
      miaomiao/plugins/cordova-plugin-camera/src/blackberry10/index.js
  61. 123 0
      miaomiao/plugins/cordova-plugin-camera/src/browser/CameraProxy.js
  62. 53 0
      miaomiao/plugins/cordova-plugin-camera/src/firefoxos/CameraProxy.js
  63. 116 0
      miaomiao/plugins/cordova-plugin-camera/src/ios/CDVCamera.h
  64. 771 0
      miaomiao/plugins/cordova-plugin-camera/src/ios/CDVCamera.m
  65. 43 0
      miaomiao/plugins/cordova-plugin-camera/src/ios/CDVExif.h
  66. 62 0
      miaomiao/plugins/cordova-plugin-camera/src/ios/CDVJpegHeaderWriter.h
  67. 547 0
      miaomiao/plugins/cordova-plugin-camera/src/ios/CDVJpegHeaderWriter.m
  68. 29 0
      miaomiao/plugins/cordova-plugin-camera/src/ios/UIImage+CropScaleOrientation.h
  69. 175 0
      miaomiao/plugins/cordova-plugin-camera/src/ios/UIImage+CropScaleOrientation.m
  70. 118 0
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/CaptureWidget.qml
  71. BIN
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/back.png
  72. 140 0
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/camera.cpp
  73. 86 0
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/camera.h
  74. BIN
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/shoot.png
  75. BIN
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/toolbar-left.png
  76. BIN
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/toolbar-middle.png
  77. BIN
      miaomiao/plugins/cordova-plugin-camera/src/ubuntu/toolbar-right.png
  78. 882 0
      miaomiao/plugins/cordova-plugin-camera/src/windows/CameraProxy.js
  79. 534 0
      miaomiao/plugins/cordova-plugin-camera/src/wp/Camera.cs
  80. 1 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/.npmignore
  81. 7 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest.xcworkspace/contents.xcworkspacedata
  82. 41 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest.xcworkspace/xcshareddata/CDVCameraTest.xccheckout
  83. 77 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest.xcworkspace/xcshareddata/xcschemes/CordovaLib.xcscheme
  84. 511 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraLibTests/CameraTest.m
  85. 44 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraLibTests/Info.plist
  86. 561 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.pbxproj
  87. 7 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  88. 41 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.xcworkspace/xcshareddata/CDVCameraTest.xccheckout
  89. 77 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/xcshareddata/xcschemes/CDVCameraLib.xcscheme
  90. 96 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/xcshareddata/xcschemes/CDVCameraLibTests.xcscheme
  91. 40 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/README.md
  92. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/de/README.md
  93. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/es/README.md
  94. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/fr/README.md
  95. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/it/README.md
  96. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/ja/README.md
  97. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/ko/README.md
  98. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/pl/README.md
  99. 39 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/zh/README.md
  100. 13 0
      miaomiao/plugins/cordova-plugin-camera/tests/ios/package.json

+ 1 - 0
.gitignore

xqd
@@ -21,3 +21,4 @@ server/public/apidoc/
 miaomiao/miaomiao/platforms/android/.gradle/2.2.1/taskArtifacts/cache.properties.lock
 miaomiao/miaomiao/platforms/android/.gradle/2.2.1/taskArtifacts/fileHashes.bin
 
+platforms

BIN
.vs/miaomiao/v14/.suo


BIN
miaomiao/bin/Android/Debug/android-debug-unaligned.apk


BIN
miaomiao/bin/Android/Debug/android-debug.apk


+ 8 - 5
miaomiao/config.xml

xqd xqd
@@ -24,11 +24,6 @@
   <feature name="StatusBar">
     <param name="ios-package" onload="true" value="CDVStatusBar"/>
   </feature>
-  <plugin name="cordova-plugin-device" spec="~1.1.1"/>
-  <plugin name="cordova-plugin-console" spec="~1.0.2"/>
-  <plugin name="cordova-plugin-whitelist" spec="~1.2.1"/>
-  <plugin name="cordova-plugin-statusbar" spec="~2.1.0"/>
-  <plugin name="ionic-plugin-keyboard" spec="~1.0.9"/>
   <platform name="ios">
     <icon height="57" src="resources/ios/icon/icon.png" width="57"/>
     <icon height="114" src="resources/ios/icon/icon@2x.png" width="114"/>
@@ -81,4 +76,12 @@
     <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/>
     <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/>
   </platform>
+  <plugin name="cordova-plugin-device" spec="~1.1.1"/>
+  <plugin name="cordova-plugin-console" spec="~1.0.2"/>
+  <plugin name="cordova-plugin-whitelist" spec="~1.2.1"/>
+  <plugin name="cordova-plugin-statusbar" spec="~2.1.0"/>
+  <plugin name="ionic-plugin-keyboard" spec="~1.0.9"/>
+  <plugin name="cordova-plugin-file-transfer" version="1.6.2" />
+  <plugin name="cordova-plugin-file" version="4.3.2" />
+  <plugin name="cordova-plugin-camera" version="2.4.0" />
 </widget>

+ 5 - 1
miaomiao/miaomiao.jsproj.user

xqd
@@ -1,6 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
-    <ReferenceCachePath>C:\Users\RD2\AppData\Local\Temp\miaomiao_refcache</ReferenceCachePath>
+    <ReferenceCachePath>C:\Users\Ben\AppData\Local\Temp\miaomiao_refcache</ReferenceCachePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Android'">
+    <DebuggerFlavor>AndroidEmulator</DebuggerFlavor>
+    <AndroidEmulatorID>AndroidDevice;设备</AndroidEmulatorID>
   </PropertyGroup>
 </Project>

+ 3 - 1
miaomiao/package.json

xqd
@@ -21,7 +21,9 @@
     "cordova-plugin-console",
     "cordova-plugin-whitelist",
     "cordova-plugin-statusbar",
-    "ionic-plugin-keyboard"
+    "ionic-plugin-keyboard",
+    "cordova-plugin-file-transfer@1.6.2",
+    "cordova-plugin-camera@2.4.0"
   ],
   "cordovaPlatforms": []
 }

+ 12 - 0
miaomiao/plugins/android.json

xqd
@@ -7,12 +7,24 @@
         "files": {}
     },
     "installed_plugins": {
+        "cordova-plugin-camera": {
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
+        "cordova-plugin-compat": {
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
         "cordova-plugin-console": {
             "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
         },
         "cordova-plugin-device": {
             "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
         },
+        "cordova-plugin-file": {
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
+        "cordova-plugin-file-transfer": {
+            "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
+        },
         "cordova-plugin-splashscreen": {
             "PACKAGE_NAME": "com.ionicframework.ionictabs121641"
         },

+ 37 - 0
miaomiao/plugins/cordova-plugin-camera/CONTRIBUTING.md

xqd
@@ -0,0 +1,37 @@
+<!--
+#
+# 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.
+#
+-->
+
+# Contributing to Apache Cordova
+
+Anyone can contribute to Cordova. And we need your contributions.
+
+There are multiple ways to contribute: report bugs, improve the docs, and
+contribute code.
+
+For instructions on this, start with the 
+[contribution overview](http://cordova.apache.org/contribute/).
+
+The details are explained there, but the important items are:
+ - Sign and submit an Apache ICLA (Contributor License Agreement).
+ - Have a Jira issue open that corresponds to your contribution.
+ - Run the tests so your patch doesn't break existing functionality.
+
+We look forward to your contributions!

+ 202 - 0
miaomiao/plugins/cordova-plugin-camera/LICENSE

xqd
@@ -0,0 +1,202 @@
+
+                                 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.

+ 5 - 0
miaomiao/plugins/cordova-plugin-camera/NOTICE

xqd
@@ -0,0 +1,5 @@
+Apache Cordova
+Copyright 2012 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).

+ 793 - 0
miaomiao/plugins/cordova-plugin-camera/README.md

xqd
@@ -0,0 +1,793 @@
+---
+title: Camera
+description: Take pictures with the device camera.
+---
+<!---
+# license: 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.
+-->
+
+|Android|iOS| Windows 8.1 Store | Windows 8.1 Phone | Windows 10 Store | Travis CI |
+|:-:|:-:|:-:|:-:|:-:|:-:|
+|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=android,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=android,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=ios,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=ios,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=windows-8.1-store,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-8.1-store,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=windows-8.1-phone,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-8.1-phone,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=windows-10-store,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-10-store,PLUGIN=cordova-plugin-camera/)|[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg?branch=master)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+# cordova-plugin-camera
+
+This plugin defines a global `navigator.camera` object, which provides an API for taking pictures and for choosing images from
+the system's image library.
+
+Although the object is attached to the global scoped `navigator`, it is not available until after the `deviceready` event.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+
+
+## Installation
+
+This requires cordova 5.0+
+
+    cordova plugin add cordova-plugin-camera
+Older versions of cordova can still install via the __deprecated__ id
+
+    cordova plugin add org.apache.cordova.camera
+It is also possible to install via repo url directly ( unstable )
+
+    cordova plugin add https://github.com/apache/cordova-plugin-camera.git
+
+
+## How to Contribute
+
+Contributors are welcome! And we need your contributions to keep the project moving forward. You can [report bugs](https://issues.apache.org/jira/issues/?jql=project%20%3D%20CB%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20resolution%20%3D%20Unresolved%20AND%20component%20%3D%20%22Plugin%20Camera%22%20ORDER%20BY%20priority%20DESC%2C%20summary%20ASC%2C%20updatedDate%20DESC), improve the documentation, or [contribute code](https://github.com/apache/cordova-plugin-camera/pulls).
+
+There is a specific [contributor workflow](http://wiki.apache.org/cordova/ContributorWorkflow) we recommend. Start reading there. More information is available on [our wiki](http://wiki.apache.org/cordova).
+
+:warning: **Found an issue?** File it on [JIRA issue tracker](https://issues.apache.org/jira/issues/?jql=project%20%3D%20CB%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20resolution%20%3D%20Unresolved%20AND%20component%20%3D%20%22Plugin%20Camera%22%20ORDER%20BY%20priority%20DESC%2C%20summary%20ASC%2C%20updatedDate%20DESC).
+
+**Have a solution?** Send a [Pull Request](https://github.com/apache/cordova-plugin-camera/pulls).
+
+In order for your changes to be accepted, you need to sign and submit an Apache [ICLA](http://www.apache.org/licenses/#clas) (Individual Contributor License Agreement). Then your name will appear on the list of CLAs signed by [non-committers](https://people.apache.org/committer-index.html#unlistedclas) or [Cordova committers](http://people.apache.org/committers-by-project.html#cordova).
+
+**And don't forget to test and document your code.**
+
+
+## This documentation is generated by a tool
+
+:warning: Run `npm install` in the plugin repo to enable automatic docs generation if you plan to send a PR.  
+[jsdoc-to-markdown](https://www.npmjs.com/package/jsdoc-to-markdown) is used to generate the docs.  
+Documentation consists of template and API docs produced from the plugin JS code and should be regenerated before each commit (done automatically via [husky](https://github.com/typicode/husky), running `npm run gen-docs` script as a `precommit` hook - see `package.json` for details).
+
+
+
+### iOS Quirks
+
+Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` and `NSPhotoLibraryUsageDescription` in the info.plist.
+
+- `NSCameraUsageDescription` describes the reason that the app accesses the user’s camera.
+- `NSPhotoLibraryUsageDescription` describes the reason the app accesses the user's photo library. 
+
+When the system prompts the user to allow access, this string is displayed as part of the dialog box. 
+
+To add this entry you can pass the following variables on plugin install.
+
+- `CAMERA_USAGE_DESCRIPTION` for `NSCameraUsageDescription`
+- `PHOTOLIBRARY_USAGE_DESCRIPTION` for `NSPhotoLibraryUsageDescription`
+
+Example:
+
+    cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="your usage message" --variable PHOTOLIBRARY_USAGE_DESCRIPTION="your usage message"
+
+If you don't pass the variable, the plugin will add an empty string as value.
+
+---
+
+# API Reference <a name="reference"></a>
+
+
+* [camera](#module_camera)
+    * [.getPicture(successCallback, errorCallback, options)](#module_camera.getPicture)
+    * [.cleanup()](#module_camera.cleanup)
+    * [.onError](#module_camera.onError) : <code>function</code>
+    * [.onSuccess](#module_camera.onSuccess) : <code>function</code>
+    * [.CameraOptions](#module_camera.CameraOptions) : <code>Object</code>
+
+
+* [Camera](#module_Camera)
+    * [.DestinationType](#module_Camera.DestinationType) : <code>enum</code>
+    * [.EncodingType](#module_Camera.EncodingType) : <code>enum</code>
+    * [.MediaType](#module_Camera.MediaType) : <code>enum</code>
+    * [.PictureSourceType](#module_Camera.PictureSourceType) : <code>enum</code>
+    * [.PopoverArrowDirection](#module_Camera.PopoverArrowDirection) : <code>enum</code>
+    * [.Direction](#module_Camera.Direction) : <code>enum</code>
+
+* [CameraPopoverHandle](#module_CameraPopoverHandle)
+* [CameraPopoverOptions](#module_CameraPopoverOptions)
+
+---
+
+<a name="module_camera"></a>
+
+## camera
+<a name="module_camera.getPicture"></a>
+
+### camera.getPicture(successCallback, errorCallback, options)
+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 `camera.getPicture` function opens the device's default camera
+application that allows users to snap pictures by default - this behavior occurs,
+when `Camera.sourceType` equals [`Camera.PictureSourceType.CAMERA`](#module_Camera.PictureSourceType).
+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 return value is sent to the [`cameraSuccess`](#module_camera.onSuccess) 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 `<img>` 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__
+
+- Android
+- BlackBerry
+- Browser
+- Firefox
+- FireOS
+- iOS
+- Windows
+- WP8
+- Ubuntu
+
+More examples [here](#camera-getPicture-examples). Quirks [here](#camera-getPicture-quirks).
+
+**Kind**: static method of <code>[camera](#module_camera)</code>  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| successCallback | <code>[onSuccess](#module_camera.onSuccess)</code> |  |
+| errorCallback | <code>[onError](#module_camera.onError)</code> |  |
+| options | <code>[CameraOptions](#module_camera.CameraOptions)</code> | CameraOptions |
+
+**Example**  
+```js
+navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+```
+<a name="module_camera.cleanup"></a>
+
+### camera.cleanup()
+Removes intermediate image files that are kept in temporary storage
+after calling [`camera.getPicture`](#module_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
+
+**Kind**: static method of <code>[camera](#module_camera)</code>  
+**Example**  
+```js
+navigator.camera.cleanup(onSuccess, onFail);
+
+function onSuccess() {
+    console.log("Camera cleanup success.")
+}
+
+function onFail(message) {
+    alert('Failed because: ' + message);
+}
+```
+<a name="module_camera.onError"></a>
+
+### camera.onError : <code>function</code>
+Callback function that provides an error message.
+
+**Kind**: static typedef of <code>[camera](#module_camera)</code>  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| message | <code>string</code> | The message is provided by the device's native code. |
+
+<a name="module_camera.onSuccess"></a>
+
+### camera.onSuccess : <code>function</code>
+Callback function that provides the image data.
+
+**Kind**: static typedef of <code>[camera](#module_camera)</code>  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| imageData | <code>string</code> | Base64 encoding of the image data, _or_ the image file URI, depending on [`cameraOptions`](#module_camera.CameraOptions) in effect. |
+
+**Example**  
+```js
+// Show image
+//
+function cameraCallback(imageData) {
+   var image = document.getElementById('myImage');
+   image.src = "data:image/jpeg;base64," + imageData;
+}
+```
+<a name="module_camera.CameraOptions"></a>
+
+### camera.CameraOptions : <code>Object</code>
+Optional parameters to customize the camera settings.
+* [Quirks](#CameraOptions-quirks)
+
+**Kind**: static typedef of <code>[camera](#module_camera)</code>  
+**Properties**
+
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| quality | <code>number</code> | <code>50</code> | Quality of the saved image, expressed as a range of 0-100, where 100 is typically full resolution with no loss from file compression. (Note that information about the camera's resolution is unavailable.) |
+| destinationType | <code>[DestinationType](#module_Camera.DestinationType)</code> | <code>FILE_URI</code> | Choose the format of the return value. |
+| sourceType | <code>[PictureSourceType](#module_Camera.PictureSourceType)</code> | <code>CAMERA</code> | Set the source of the picture. |
+| allowEdit | <code>Boolean</code> | <code>true</code> | Allow simple editing of image before selection. |
+| encodingType | <code>[EncodingType](#module_Camera.EncodingType)</code> | <code>JPEG</code> | Choose the  returned image file's encoding. |
+| targetWidth | <code>number</code> |  | Width in pixels to scale image. Must be used with `targetHeight`. Aspect ratio remains constant. |
+| targetHeight | <code>number</code> |  | Height in pixels to scale image. Must be used with `targetWidth`. Aspect ratio remains constant. |
+| mediaType | <code>[MediaType](#module_Camera.MediaType)</code> | <code>PICTURE</code> | Set the type of media to select from.  Only works when `PictureSourceType` is `PHOTOLIBRARY` or `SAVEDPHOTOALBUM`. |
+| correctOrientation | <code>Boolean</code> |  | Rotate the image to correct for the orientation of the device during capture. |
+| saveToPhotoAlbum | <code>Boolean</code> |  | Save the image to the photo album on the device after capture. |
+| popoverOptions | <code>[CameraPopoverOptions](#module_CameraPopoverOptions)</code> |  | iOS-only options that specify popover location in iPad. |
+| cameraDirection | <code>[Direction](#module_Camera.Direction)</code> | <code>BACK</code> | Choose the camera to use (front- or back-facing). |
+
+---
+
+<a name="module_Camera"></a>
+
+## Camera
+<a name="module_Camera.DestinationType"></a>
+
+### Camera.DestinationType : <code>enum</code>
+Defines the output format of `Camera.getPicture` call.
+_Note:_ On iOS passing `DestinationType.NATIVE_URI` along with
+`PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM` will
+disable any image modifications (resize, quality change, cropping, etc.) due
+to implementation specific.
+
+**Kind**: static enum property of <code>[Camera](#module_Camera)</code>  
+**Properties**
+
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| DATA_URL | <code>number</code> | <code>0</code> | Return base64 encoded string. DATA_URL can be very memory intensive and cause app crashes or out of memory errors. Use FILE_URI or NATIVE_URI if possible |
+| FILE_URI | <code>number</code> | <code>1</code> | Return file uri (content://media/external/images/media/2 for Android) |
+| NATIVE_URI | <code>number</code> | <code>2</code> | Return native uri (eg. asset-library://... for iOS) |
+
+<a name="module_Camera.EncodingType"></a>
+
+### Camera.EncodingType : <code>enum</code>
+**Kind**: static enum property of <code>[Camera](#module_Camera)</code>  
+**Properties**
+
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| JPEG | <code>number</code> | <code>0</code> | Return JPEG encoded image |
+| PNG | <code>number</code> | <code>1</code> | Return PNG encoded image |
+
+<a name="module_Camera.MediaType"></a>
+
+### Camera.MediaType : <code>enum</code>
+**Kind**: static enum property of <code>[Camera](#module_Camera)</code>  
+**Properties**
+
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| PICTURE | <code>number</code> | <code>0</code> | Allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType |
+| VIDEO | <code>number</code> | <code>1</code> | Allow selection of video only, ONLY RETURNS URL |
+| ALLMEDIA | <code>number</code> | <code>2</code> | Allow selection from all media types |
+
+<a name="module_Camera.PictureSourceType"></a>
+
+### Camera.PictureSourceType : <code>enum</code>
+Defines the output format of `Camera.getPicture` call.
+_Note:_ On iOS passing `PictureSourceType.PHOTOLIBRARY` or `PictureSourceType.SAVEDPHOTOALBUM`
+along with `DestinationType.NATIVE_URI` will disable any image modifications (resize, quality
+change, cropping, etc.) due to implementation specific.
+
+**Kind**: static enum property of <code>[Camera](#module_Camera)</code>  
+**Properties**
+
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| PHOTOLIBRARY | <code>number</code> | <code>0</code> | Choose image from the device's photo library (same as SAVEDPHOTOALBUM for Android) |
+| CAMERA | <code>number</code> | <code>1</code> | Take picture from camera |
+| SAVEDPHOTOALBUM | <code>number</code> | <code>2</code> | Choose image only from the device's Camera Roll album (same as PHOTOLIBRARY for Android) |
+
+<a name="module_Camera.PopoverArrowDirection"></a>
+
+### Camera.PopoverArrowDirection : <code>enum</code>
+Matches iOS UIPopoverArrowDirection constants to specify arrow location on popover.
+
+**Kind**: static enum property of <code>[Camera](#module_Camera)</code>  
+**Properties**
+
+| Name | Type | Default |
+| --- | --- | --- |
+| ARROW_UP | <code>number</code> | <code>1</code> | 
+| ARROW_DOWN | <code>number</code> | <code>2</code> | 
+| ARROW_LEFT | <code>number</code> | <code>4</code> | 
+| ARROW_RIGHT | <code>number</code> | <code>8</code> | 
+| ARROW_ANY | <code>number</code> | <code>15</code> | 
+
+<a name="module_Camera.Direction"></a>
+
+### Camera.Direction : <code>enum</code>
+**Kind**: static enum property of <code>[Camera](#module_Camera)</code>  
+**Properties**
+
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| BACK | <code>number</code> | <code>0</code> | Use the back-facing camera |
+| FRONT | <code>number</code> | <code>1</code> | Use the front-facing camera |
+
+---
+
+<a name="module_CameraPopoverOptions"></a>
+
+## 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.
+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.
+
+
+| Param | Type | Default | Description |
+| --- | --- | --- | --- |
+| [x] | <code>Number</code> | <code>0</code> | x pixel coordinate of screen element onto which to anchor the popover. |
+| [y] | <code>Number</code> | <code>32</code> | y pixel coordinate of screen element onto which to anchor the popover. |
+| [width] | <code>Number</code> | <code>320</code> | width, in pixels, of the screen element onto which to anchor the popover. |
+| [height] | <code>Number</code> | <code>480</code> | height, in pixels, of the screen element onto which to anchor the popover. |
+| [arrowDir] | <code>[PopoverArrowDirection](#module_Camera.PopoverArrowDirection)</code> | <code>ARROW_ANY</code> | Direction the arrow on the popover should point. |
+
+---
+
+<a name="module_CameraPopoverHandle"></a>
+
+## CameraPopoverHandle
+A handle to an image picker popover.
+
+__Supported Platforms__
+
+- iOS
+
+**Example**  
+```js
+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 cameraPopoverHandle = new CameraPopoverHandle();
+    var cameraPopoverOptions = new CameraPopoverOptions(0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY);
+    cameraPopoverHandle.setPosition(cameraPopoverOptions);
+}
+```
+---
+
+
+## `camera.getPicture` Errata
+
+#### Example <a name="camera-getPicture-examples"></a>
+
+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);
+    }
+
+Take a photo and retrieve it as a Base64-encoded image:
+
+    /**
+     * Warning: Using DATA_URL is not recommended! The DATA_URL destination
+     * type is very memory intensive, even with a low quality setting. Using it
+     * can result in out of memory errors and application crashes. Use FILE_URI
+     * or NATIVE_URI instead.
+     */
+    navigator.camera.getPicture(onSuccess, onFail, { quality: 25,
+        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);
+    }
+
+#### Preferences (iOS)
+
+-  __CameraUsesGeolocation__ (boolean, defaults to false). For capturing JPEGs, set to true to get geolocation data in the EXIF header. This will trigger a request for geolocation permissions if set to true.
+
+        <preference name="CameraUsesGeolocation" value="false" />
+
+#### Amazon Fire OS Quirks <a name="camera-getPicture-quirks"></a>
+
+Amazon Fire OS uses intents to launch the camera activity on the device to capture
+images, and on phones with low memory, the Cordova activity may be killed.  In this
+scenario, the image may not appear when the Cordova activity is restored.
+
+#### Android Quirks
+
+Android 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 result from the plugin call will be delivered via the resume event.
+See [the Android Lifecycle guide][android_lifecycle]
+for more information. The `pendingResult.result` value will contain the value that
+would be passed to the callbacks (either the URI/URL or an error message). Check
+the `pendingResult.pluginStatus` to determine whether or not the call was
+successful.
+
+#### Browser Quirks
+
+Can only return photos as Base64-encoded image.
+
+#### Firefox OS Quirks
+
+Camera plugin is currently implemented using [Web Activities][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.
+
+#### Windows quirks
+
+On Windows Phone 8.1 using `SAVEDPHOTOALBUM` or `PHOTOLIBRARY` as a source type causes application to suspend until file picker returns the selected image and
+then restore with start page as defined in app's `config.xml`. In case when `camera.getPicture` was called from different page, this will lead to reloading
+start page from scratch and success and error callbacks will never be called.
+
+To avoid this we suggest using SPA pattern or call `camera.getPicture` only from your app's start page.
+
+More information about Windows Phone 8.1 picker APIs is here: [How to continue your Windows Phone app after calling a file picker](https://msdn.microsoft.com/en-us/library/windows/apps/dn720490.aspx)
+
+#### Tizen Quirks
+
+Tizen only supports a `destinationType` of
+`Camera.DestinationType.FILE_URI` and a `sourceType` of
+`Camera.PictureSourceType.PHOTOLIBRARY`.
+
+
+## `CameraOptions` Errata <a name="CameraOptions-quirks"></a>
+
+#### Amazon Fire OS Quirks
+
+- Any `cameraDirection` value results in a back-facing photo.
+
+- Ignores the `allowEdit` parameter.
+
+- `Camera.PictureSourceType.PHOTOLIBRARY` and `Camera.PictureSourceType.SAVEDPHOTOALBUM` both display the same photo album.
+
+#### Android Quirks
+
+- Any `cameraDirection` value results in a back-facing photo.
+
+- **`allowEdit` is unpredictable on Android and it should not be used!** The Android implementation of this plugin tries to find and use an application on the user's device to do image cropping. The plugin has no control over what application the user selects to perform the image cropping and it is very possible that the user could choose an incompatible option and cause the plugin to fail. This sometimes works because most devices come with an application that handles cropping in a way that is compatible with this plugin (Google Plus Photos), but it is unwise to rely on that being the case. If image editing is essential to your application, consider seeking a third party library or plugin that provides its own image editing utility for a more robust solution.
+
+- `Camera.PictureSourceType.PHOTOLIBRARY` and `Camera.PictureSourceType.SAVEDPHOTOALBUM` both display the same photo album.
+
+- Ignores the `encodingType` parameter if the image is unedited (i.e. `quality` is 100, `correctOrientation` is false, and no `targetHeight` or `targetWidth` are specified). The `CAMERA` source will always return the JPEG file given by the native camera and the `PHOTOLIBRARY` and `SAVEDPHOTOALBUM` sources will return the selected file in its existing encoding.
+
+#### BlackBerry 10 Quirks
+
+- Ignores the `quality` parameter.
+
+- Ignores the `allowEdit` parameter.
+
+- `Camera.MediaType` is not supported.
+
+- Ignores the `correctOrientation` parameter.
+
+- Ignores the `cameraDirection` parameter.
+
+#### Firefox OS Quirks
+
+- Ignores the `quality` parameter.
+
+- `Camera.DestinationType` is ignored and equals `1` (image file URI)
+
+- Ignores the `allowEdit` parameter.
+
+- Ignores the `PictureSourceType` parameter (user chooses it in a dialog window)
+
+- Ignores the `encodingType`
+
+- Ignores the `targetWidth` and `targetHeight`
+
+- `Camera.MediaType` is not supported.
+
+- Ignores the `correctOrientation` parameter.
+
+- Ignores the `cameraDirection` parameter.
+
+#### iOS Quirks
+
+- When using `destinationType.FILE_URI`, photos are saved in the application's temporary directory. The contents of the application's temporary directory is deleted when the application ends.
+
+- When using `destinationType.NATIVE_URI` and `sourceType.CAMERA`, photos are saved in the saved photo album regardless on the value of `saveToPhotoAlbum` parameter.
+
+- When using `destinationType.NATIVE_URI` and `sourceType.PHOTOLIBRARY` or `sourceType.SAVEDPHOTOALBUM`, all editing options are ignored and link is returned to original picture.
+
+#### Tizen Quirks
+
+- options not supported
+
+- always returns a FILE URI
+
+#### Windows Phone 7 and 8 Quirks
+
+- Ignores the `allowEdit` parameter.
+
+- Ignores the `correctOrientation` parameter.
+
+- Ignores the `cameraDirection` parameter.
+
+- Ignores the `saveToPhotoAlbum` parameter.  IMPORTANT: All images taken with the WP8/8 Cordova camera API are always copied to the phone's camera roll.  Depending on the user's settings, this could also mean the image is auto-uploaded to their OneDrive.  This could potentially mean the image is available to a wider audience than your app intended. If this is a blocker for your application, you will need to implement the CameraCaptureTask as [documented on MSDN][msdn_wp8_docs]. You may also comment or up-vote the related issue in the [issue tracker][wp8_bug].
+
+- Ignores the `mediaType` property of `cameraOptions` as the Windows Phone SDK does not provide a way to choose videos from PHOTOLIBRARY.
+
+[android_lifecycle]: http://cordova.apache.org/docs/en/dev/guide/platforms/android/lifecycle.html
+[web_activities]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+[wp8_bug]: https://issues.apache.org/jira/browse/CB-2083
+[msdn_wp8_docs]: http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx
+
+## Sample: Take Pictures, Select Pictures from the Picture Library, and Get Thumbnails <a name="sample"></a>
+
+The Camera plugin allows you to do things like open the device's Camera app and take a picture, or open the file picker and select one. The code snippets in this section demonstrate different tasks including:
+
+* Open the Camera app and [take a Picture](#takePicture)
+* Take a picture and [return thumbnails](#getThumbnails) (resized picture)
+* Take a picture and [generate a FileEntry object](#convert)
+* [Select a file](#selectFile) from the picture library
+* Select a JPEG image and [return thumbnails](#getFileThumbnails) (resized image)
+* Select an image and [generate a FileEntry object](#convert)
+
+## Take a Picture <a name="takePicture"></a>
+
+Before you can take a picture, you need to set some Camera plugin options to pass into the Camera plugin's `getPicture` function. Here is a common set of recommendations. In this example, you create the object that you will use for the Camera options, and set the `sourceType` dynamically to support both the Camera app and the file picker.
+
+```js
+function setOptions(srcType) {
+    var options = {
+        // Some common settings are 20, 50, and 100
+        quality: 50,
+        destinationType: Camera.DestinationType.FILE_URI,
+        // In this app, dynamically set the picture source, Camera or photo gallery
+        sourceType: srcType,
+        encodingType: Camera.EncodingType.JPEG,
+        mediaType: Camera.MediaType.PICTURE,
+        allowEdit: true,
+        correctOrientation: true  //Corrects Android orientation quirks
+    }
+    return options;
+}
+```
+
+Typically, you want to use a FILE_URI instead of a DATA_URL to avoid most memory issues. JPEG is the recommended encoding type for Android.
+
+You take a picture by passing in the options object to `getPicture`, which takes a CameraOptions object as the third argument. When you call `setOptions`, pass `Camera.PictureSourceType.CAMERA` as the picture source.
+
+```js
+function openCamera(selection) {
+
+    var srcType = Camera.PictureSourceType.CAMERA;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        displayImage(imageUri);
+        // You may choose to copy the picture, save it somewhere, or upload.
+        func(imageUri);
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+Once you take the picture, you can display it or do something else. In this example, call the app's `displayImage` function from the preceding code.
+
+```js
+function displayImage(imgUri) {
+
+    var elem = document.getElementById('imageFile');
+    elem.src = imgUri;
+}
+```
+
+To display the image on some platforms, you might need to include the main part of the URI in the Content-Security-Policy `<meta>` element in index.html. For example, on Windows 10, you can include `ms-appdata:` in your `<meta>` element. Here is an example.
+
+```html
+<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ms-appdata: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
+```
+
+## Take a Picture and Return Thumbnails (Resize the Picture) <a name="getThumbnails"></a>
+
+To get smaller images, you can return a resized image by passing both `targetHeight` and `targetWidth` values with your CameraOptions object. In this example, you resize the returned image to fit in a 100px by 100px box (the aspect ratio is maintained, so 100px is either the height or width, whichever is greater in the source).
+
+```js
+function openCamera(selection) {
+
+    var srcType = Camera.PictureSourceType.CAMERA;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    if (selection == "camera-thmb") {
+        options.targetHeight = 100;
+        options.targetWidth = 100;
+    }
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        // Do something
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+## Select a File from the Picture Library <a name="selectFile"></a>
+
+When selecting a file using the file picker, you also need to set the CameraOptions object. In this example, set the `sourceType` to `Camera.PictureSourceType.SAVEDPHOTOALBUM`. To open the file picker, call `getPicture` just as you did in the previous example, passing in the success and error callbacks along with CameraOptions object.
+
+```js
+function openFilePicker(selection) {
+
+    var srcType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        // Do something
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+## Select an Image and Return Thumbnails (resized images) <a name="getFileThumbnails"></a>
+
+Resizing a file selected with the file picker works just like resizing using the Camera app; set the `targetHeight` and `targetWidth` options.
+
+```js
+function openFilePicker(selection) {
+
+    var srcType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    if (selection == "picker-thmb") {
+        // To downscale a selected image,
+        // Camera.EncodingType (e.g., JPEG) must match the selected image type.
+        options.targetHeight = 100;
+        options.targetWidth = 100;
+    }
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        // Do something with image
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+## Take a picture and get a FileEntry Object <a name="convert"></a>
+
+If you want to do something like copy the image to another location, or upload it somewhere using the FileTransfer plugin, you need to get a FileEntry object for the returned picture. To do that, call `window.resolveLocalFileSystemURL` on the file URI returned by the Camera app. If you need to use a FileEntry object, set the `destinationType` to `Camera.DestinationType.FILE_URI` in your CameraOptions object (this is also the default value).
+
+>*Note* You need the [File plugin](https://www.npmjs.com/package/cordova-plugin-file) to call `window.resolveLocalFileSystemURL`.
+
+Here is the call to `window.resolveLocalFileSystemURL`. The image URI is passed to this function from the success callback of `getPicture`. The success handler of `resolveLocalFileSystemURL` receives the FileEntry object.
+
+```js
+function getFileEntry(imgUri) {
+    window.resolveLocalFileSystemURL(imgUri, function success(fileEntry) {
+
+        // Do something with the FileEntry object, like write to it, upload it, etc.
+        // writeFile(fileEntry, imgUri);
+        console.log("got file: " + fileEntry.fullPath);
+        // displayFileData(fileEntry.nativeURL, "Native URL");
+
+    }, function () {
+      // If don't get the FileEntry (which may happen when testing
+      // on some emulators), copy to a new FileEntry.
+        createNewFileEntry(imgUri);
+    });
+}
+```
+
+In the example shown in the preceding code, you call the app's `createNewFileEntry` function if you don't get a valid FileEntry object. The image URI returned from the Camera app should result in a valid FileEntry, but platform behavior on some emulators may be different for files returned from the file picker.
+
+>*Note* To see an example of writing to a FileEntry, see the [File plugin README](https://www.npmjs.com/package/cordova-plugin-file).
+
+The code shown here creates a file in your app's cache (in sandboxed storage) named `tempFile.jpeg`. With the new FileEntry object, you can copy the image to the file or do something else like upload it.
+
+```js
+function createNewFileEntry(imgUri) {
+    window.resolveLocalFileSystemURL(cordova.file.cacheDirectory, function success(dirEntry) {
+
+        // JPEG file
+        dirEntry.getFile("tempFile.jpeg", { create: true, exclusive: false }, function (fileEntry) {
+
+            // Do something with it, like write to it, upload it, etc.
+            // writeFile(fileEntry, imgUri);
+            console.log("got file: " + fileEntry.fullPath);
+            // displayFileData(fileEntry.fullPath, "File copied to");
+
+        }, onErrorCreateFile);
+
+    }, onErrorResolveUrl);
+}
+```

+ 360 - 0
miaomiao/plugins/cordova-plugin-camera/RELEASENOTES.md

xqd
@@ -0,0 +1,360 @@
+<!--
+#
+# 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.
+#
+-->
+# Release Notes
+
+### 2.4.0 (Feb 28, 2017)
+* [CB-12501](https://issues.apache.org/jira/browse/CB-12501) **Android**: Appium tests don't use `XPath` selectors anymore
+* [CB-12469](https://issues.apache.org/jira/browse/CB-12469) Appium tests can now run on **iOS 10**
+* [CB-12005](https://issues.apache.org/jira/browse/CB-12005) Changing the `getOrientation` method to return the defined enumerated `EXIF` instead of orientation in degrees for Consistency
+* [CB-12368](https://issues.apache.org/jira/browse/CB-12368) Fix permission check on **Android**
+* [CB-12353](https://issues.apache.org/jira/browse/CB-12353) Corrected merges usage in `plugin.xml`
+* [CB-12369](https://issues.apache.org/jira/browse/CB-12369) Add plugin typings from `DefinitelyTyped`
+* [CB-12363](https://issues.apache.org/jira/browse/CB-12363) Added build badges for **iOS 9.3** and **iOS 10.0**
+* [CB-12312](https://issues.apache.org/jira/browse/CB-12312) [Appium] [Android] A few changes to the tests:  - updated comments on how to run the tests. extra comments around functionality at certain points in the automation.  - stub of a resolution checker on test startup - still need to figure out acceptable values.  - moved session shutdown to an afterAll clause.  - changed resolution determiner from using webview-based values to using the native windows dimensions - this helps as the webview values may be scaled down intentionally by manufacturers (via changing devicePixelRatio). furthermore, since the screen dimension automation is used purely for native UI automation, better to use the dimensions reported by the native context rather than the web context.  - when finding elements by XPath, use multiple calls to avoid a Windows emulator + Android bug. Made this pattern consistent in the entire test.
+* [CB-12236](https://issues.apache.org/jira/browse/CB-12236) - Fixed RELEASENOTES for cordova-plugin-camera
+* [CB-12230](https://issues.apache.org/jira/browse/CB-12230) Removed Windows 8.1 build badges
+
+### 2.3.1 (Dec 07, 2016)
+* [CB-12224](https://issues.apache.org/jira/browse/CB-12224) Updated version and RELEASENOTES.md for release 2.3.1
+* Fix missing license headers.
+* [CB-12086](https://issues.apache.org/jira/browse/CB-12086) Regenerate README.md from template
+* Added NSPhotoLibraryUsageDescription parameter to example install command Fixing some usages of NSPhotoLibraryUsageDescriptionentry
+* Updating compat dependency to 1.1.0 or better
+* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Forgot to add CordovaUri.java to plugin.xml
+* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Files Provider does not work with Android 4.4.4 or lower, and I have no idea why.  Working around with CordovaUri
+* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) (Android) : Make this work with previous versions of Cordova via cordova-plugin-compat
+* BuildConfig from test project crept in source code thanks to Android Studio, removing
+* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Managed to get Content Providers to work with a weird mix of Content Providers and non-Content Providers
+* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Working on fix to API 24 no longer allowing File URIs to be passed across intents
+* [CB-11917](https://issues.apache.org/jira/browse/CB-11917) - Remove pull request template checklist item: "iCLA has been submitted…"
+* [CB-11832](https://issues.apache.org/jira/browse/CB-11832) Incremented plugin version.
+
+### 2.3.0 (Sep 08, 2016)
+* [CB-11795](https://issues.apache.org/jira/browse/CB-11795) Add 'protective' entry to cordovaDependencies
+* [CB-11661](https://issues.apache.org/jira/browse/CB-11661) Add mandatory **iOS 10** privacy description
+* [CB-11714](https://issues.apache.org/jira/browse/CB-11714) **windows** added more explicit content-type when converting to target data on canvas
+* [CB-11295](https://issues.apache.org/jira/browse/CB-11295) Add **WP8.1** quirk when choosing image from `photoalbum`
+* [CB-10067](https://issues.apache.org/jira/browse/CB-10067) Update `PictureSourceType` JSDoc to reflect `README` update
+* [CB-9070](https://issues.apache.org/jira/browse/CB-9070) Update `CameraPopoverHandle` docs to reflect `README` update
+* Plugin uses `Android Log class` and not `Cordova LOG class`
+* [CB-11631](https://issues.apache.org/jira/browse/CB-11631) Appium tests: A working fix for a flaky `selection canceled` failure
+* [CB-11709](https://issues.apache.org/jira/browse/CB-11709) Tests should use `resolveLocalFileSystemURL()` instead of deprecated `resolveFileSystemURI()`
+* [CB-11695](https://issues.apache.org/jira/browse/CB-11695) Increased session creation timeout for Appium tests
+* [CB-11656](https://issues.apache.org/jira/browse/CB-11656) (**Android**) Appium tests: Fixed side menu opening on some more resolutions
+* [CB-11376](https://issues.apache.org/jira/browse/CB-11376) (**ios**): fix `CameraUsesGeolocation` error
+* [CB-10067](https://issues.apache.org/jira/browse/CB-10067) (**ios**) clarifications on `PictureSourceType`
+* [CB-11410](https://issues.apache.org/jira/browse/CB-11410) (**ios**) fix `cameraPopoverHandle.setPosition`
+* [CB-9070](https://issues.apache.org/jira/browse/CB-9070) (**ios**) Fixed `CameraPopoverHandle` documentation
+* [CB-11447](https://issues.apache.org/jira/browse/CB-11447) Respect output format when retrieving images from gallery
+* [CB-11447](https://issues.apache.org/jira/browse/CB-11447) Resolve **iOS** tests failures due to **iOS** quirks
+* [CB-11553](https://issues.apache.org/jira/browse/CB-11553) Pend failing Appium tests on Sauce Labs for the time being (reverted from commit b69571724035f41642f3ee612c5b66e1f0c4386c)
+* [CB-11553](https://issues.apache.org/jira/browse/CB-11553) Pend failing Appium tests on Sauce Labs for the time being
+* [CB-11498](https://issues.apache.org/jira/browse/CB-11498) [**Android**] Appium tests should not fail when there is no camera
+* Add badges for paramedic builds on Jenkins
+* [CB-11296](https://issues.apache.org/jira/browse/CB-11296) Appium: Better element clicking and session error handling
+* [CB-11232](https://issues.apache.org/jira/browse/CB-11232) Appium tests: fixed element tapping on **iOS 9**
+* [CB-11183](https://issues.apache.org/jira/browse/CB-11183) Appium tests: Added image verification
+* fixed some bad formatting that hid `HTML` tags and added link to sample
+* Set **android** quality default value to 50 on the java code
+* Moving message in PR template to a comment
+* Add pull request template. This closes #213
+* [CB-11228](https://issues.apache.org/jira/browse/CB-11228) **browser**: Add classes for styling purposes
+* [CB-10139](https://issues.apache.org/jira/browse/CB-10139) **browser**: Respect target width and height
+* [CB-11227](https://issues.apache.org/jira/browse/CB-11227) **browser**: Fix incorrect `mime type`
+* [CB-11162](https://issues.apache.org/jira/browse/CB-11162) Appium tests: retry spec on failure
+* [CB-4078](https://issues.apache.org/jira/browse/CB-4078) Fix for `orientation/scaling` on **Android 4.4+** devices
+* [CB-11165](https://issues.apache.org/jira/browse/CB-11165) removed peer dependency
+* [CB-11147](https://issues.apache.org/jira/browse/CB-11147) Appium tests: generate descriptive spec names
+* [CB-10996](https://issues.apache.org/jira/browse/CB-10996) Adding front matter to `README.md`
+* [CB-11128](https://issues.apache.org/jira/browse/CB-11128) Appum tests: Fixed some of the flaky failures
+* [CB-11003](https://issues.apache.org/jira/browse/CB-11003) Added Sample section to the Camera plugin README
+
+### 2.2.0 (Apr 15, 2016)
+* [CB-10873](https://issues.apache.org/jira/browse/CB-10873) Avoid crash due to usage of uninitialized variable when writing geolocation data to image destination. Properly handle 'CameraUsesGeolocation' option by properly setting geolocation data in EXIF header in all cases
+* [CB-11073](https://issues.apache.org/jira/browse/CB-11073) Appium tests stability improvements
+* Replace `PermissionHelper.java` with `cordova-plugin-compat`
+* Making focus handler work only for **windows 10** phone
+* [CB-10865](https://issues.apache.org/jira/browse/CB-10865) Run **ios** native tests on **Travis**
+* [CB-10120](https://issues.apache.org/jira/browse/CB-10120) Fixing use of constants and `PermissionHelper`
+* [CB-10120](https://issues.apache.org/jira/browse/CB-10120) Fix missing CAMERA permission for **Android M**
+* [CB-10756](https://issues.apache.org/jira/browse/CB-10756) Adding sterner warnings about `DATA_URL`
+* [CB-10460](https://issues.apache.org/jira/browse/CB-10460) `getRealPath` return null in some cases
+
+### 2.1.1 (Mar 09, 2016)
+* [CB-10825](https://issues.apache.org/jira/browse/CB-10825) **Android** should request READ permission for gallery source
+* added apache license header to appium files
+* [CB-10720](https://issues.apache.org/jira/browse/CB-10720) Fixed spelling, capitalization, and other small issues.
+* [CB-10414](https://issues.apache.org/jira/browse/CB-10414) Adding focus handler to resume video when user comes back on leaving the app while preview was running
+* Appium tests: adjust swipe distance on **Android**
+* [CB-10750](https://issues.apache.org/jira/browse/CB-10750) Appium tests: fail fast if session is irrecoverable
+* Adding missing semi colon
+* Adding focus handler to make sure filepicker gets launched when app is active on **Windows**
+* [CB-10128](https://issues.apache.org/jira/browse/CB-10128) **iOS** Fixed how checks access authorization to camera & library. This closes #146
+* [CB-10636](https://issues.apache.org/jira/browse/CB-10636) Add JSHint for plugins
+* [CB-10639](https://issues.apache.org/jira/browse/CB-10639) Appium tests: Added some timeouts, Taking a screenshot on failure, Retry taking a picture up to 3 times, Try to restart the Appium session if it's lost
+* [CB-10552](https://issues.apache.org/jira/browse/CB-10552) Replacing images in README.md.
+* Added a lot of more cases to get the real path on **Android** 
+* [CB-10625](https://issues.apache.org/jira/browse/CB-10625) **Android** getPicture fails when getting a photo from the Photo Library - Google Photos
+* [CB-10619](https://issues.apache.org/jira/browse/CB-10619) Appium tests: Properly switch to webview on **Android**
+* [CB-10397](https://issues.apache.org/jira/browse/CB-10397) Added Appium tests
+* [CB-10576](https://issues.apache.org/jira/browse/CB-10576) MobileSpec can't get results for **Windows**-Store 8.1 Builds
+* chore: edit package.json license to match SPDX id
+* [CB-10539](https://issues.apache.org/jira/browse/CB-10539) Commenting out the verySmallQvga maxResolution option on **Windows**
+* [CB-10541](https://issues.apache.org/jira/browse/CB-10541) Changing default maxResoltion to be highestAvailable for CameraCaptureUI on **Windows**
+* [CB-10113](https://issues.apache.org/jira/browse/CB-10113) **Browse** - Layer camera UI on top of all! 
+* [CB-10502](https://issues.apache.org/jira/browse/CB-10502) **Browser** - Fix camera plugin exception in Chrome when click capture.
+* Adding comments
+* Camera tapping fix on **Windows**
+
+### 2.1.0 (Jan 15, 2016)
+* added `.ratignore`
+* [CB-10319](https://issues.apache.org/jira/browse/CB-10319) **Android** Adding reflective helper methods for permission requests
+* [CB-9189](https://issues.apache.org/jira/browse/CB-9189) **Android** Implementing `save/restore` API to handle Activity destruction
+* [CB-10241](https://issues.apache.org/jira/browse/CB-10241) App Crash cause by Camera Plugin **iOS 7**
+* [CB-8940](https://issues.apache.org/jira/browse/CB-8940) Setting `z-index` values to maximum for UI buttons.
+
+### 2.0.0 (Nov 18, 2015)
+* [CB-10035](https://issues.apache.org/jira/browse/CB-10035) Updated `RELEASENOTES` to be newest to oldest
+* [CB-8863](https://issues.apache.org/jira/browse/CB-8863) correct block usage for `async` calls
+* [CB-5479](https://issues.apache.org/jira/browse/CB-5479) changed `saveToPhotoAlbum` to save uncompressed images for **Android**
+* [CB-9169](https://issues.apache.org/jira/browse/CB-9169) Fixed `filetype` for uncompressed images and added quirk for **Android**
+* [CB-9446](https://issues.apache.org/jira/browse/CB-9446) Removing `CordovaResource` library code in favour of the code we're supposed to be deprecating because that at least works.
+* [CB-9942](https://issues.apache.org/jira/browse/CB-9942) Normalize line endings in Camera plugin docs
+* [CB-9910](https://issues.apache.org/jira/browse/CB-9910) Add permission request for some gallery requests for **Android**
+* [CB-7668](https://issues.apache.org/jira/browse/CB-7668) Adding a sterner warning for `allowedit` on **Android**
+* Fixing contribute link.
+* Using the `CordovaResourceApi` to fine paths of files in the background thread.  If the file doesn't exist, return the content `URI`. 
+* Add engine tag for **Cordova-Android 5.0.x**
+* [CB-9583](https://issues.apache.org/jira/browse/CB-9583): Added support for **Marshmallow** permissions (**Android 6.0**)
+* Try to use `realpath` filename instead of default `modified.jpg`
+* [CB-6190](https://issues.apache.org/jira/browse/CB-6190) **iOS** camera plugin ignores quality parameter
+* [CB-9633](https://issues.apache.org/jira/browse/CB-9633) **iOS** Taking a Picture With Option `destinationType:NATIVE_URI` doesn't show image
+* [CB-9745](https://issues.apache.org/jira/browse/CB-9745) Camera plugin docs should be generated from the source
+* [CB-9622](https://issues.apache.org/jira/browse/CB-9622) **WP8** Camera Option `destinationType:NATIVE_URI` is a `NO-OP`
+* [CB-9623](https://issues.apache.org/jira/browse/CB-9623) Fixes various issues when `encodingType` set to `png`
+* [CB-9591](https://issues.apache.org/jira/browse/CB-9591) Retaining aspect ratio when resizing
+* [CB-9443](https://issues.apache.org/jira/browse/CB-9443) Pick correct `maxResolution` 
+* [CB-9151](https://issues.apache.org/jira/browse/CB-9151) Trigger `captureAction` only once
+* [CB-9413](https://issues.apache.org/jira/browse/CB-9413) Close `RandomAccessStream` once copied
+* [CB-5661](https://issues.apache.org/jira/browse/CB-5661) Remove outdated **iOS** quirks about memory
+* [CB-9349](https://issues.apache.org/jira/browse/CB-9349) Focus control and nice UI
+* [CB-9259](https://issues.apache.org/jira/browse/CB-9259) Forgot to add another check on which `URI` we're using when fixing this thing the first time
+* [CB-9247](https://issues.apache.org/jira/browse/CB-9247) Added macro to conditionally add `NSData+Base64.h`
+* [CB-9247](https://issues.apache.org/jira/browse/CB-9247) Fixes compilation errors with **cordova-ios 4.x**
+* Fix returning native url on **Windows**.
+
+### 1.2.0 (Jun 17, 2015)
+* Closing stale pull request: close #84
+* Closing stale pull request: close #66
+* [CB-9128](https://issues.apache.org/jira/browse/CB-9128) cordova-plugin-camera documentation translation: cordova-plugin-camera
+* Update docs. This closes #100
+* attempt to fix npm markdown issue
+* [CB-8883](https://issues.apache.org/jira/browse/CB-8883) fix picture rotation issue
+* one more alias
+* Fixed some nit white-space issues, aliased a little more
+* major refactor : readability
+* Patch for [CB-8498](https://issues.apache.org/jira/browse/CB-8498), this closes #64
+* [CB-8879](https://issues.apache.org/jira/browse/CB-8879) fix stripe issue with correct aspect ratio
+* [CB-8601](https://issues.apache.org/jira/browse/CB-8601) - iOS camera unit tests broken
+* [CB-7667](https://issues.apache.org/jira/browse/CB-7667) iOS8: Handle case where camera is not authorized (closes #49)
+* add missing license header
+
+### 1.1.0 (May 06, 2015)
+* [CB-8943](https://issues.apache.org/jira/browse/CB-8943) fix `PickAndContinue` issue on *Win10Phone*
+* [CB-8253](https://issues.apache.org/jira/browse/CB-8253) Fix potential unreleased resources
+* [CB-8909](https://issues.apache.org/jira/browse/CB-8909): Remove unused import from File
+* [CB-8404](https://issues.apache.org/jira/browse/CB-8404) typo fix `cameraproxy.js`
+* [CB-8404](https://issues.apache.org/jira/browse/CB-8404) Rotate camera feed with device orientation
+* [CB-8054](https://issues.apache.org/jira/browse/CB-8054) Support taking pictures from file for *WP8*
+* [CB-8405](https://issues.apache.org/jira/browse/CB-8405) Use `z-index` instead of `z-order`
+
+### 1.0.0 (Apr 15, 2015)
+* [CB-8780](https://issues.apache.org/jira/browse/CB-8780) - Display popover using main thread. Fixes popover slowness (closes #81)
+* [CB-8746](https://issues.apache.org/jira/browse/CB-8746) bumped version of file dependency
+* [CB-8746](https://issues.apache.org/jira/browse/CB-8746) gave plugin major version bump
+* [CB-8707](https://issues.apache.org/jira/browse/CB-8707) refactoring windows code to improve readability
+* [CB-8706](https://issues.apache.org/jira/browse/CB-8706) use filePicker if saveToPhotoAlbum is true
+* [CB-8706](https://issues.apache.org/jira/browse/CB-8706) remove unnecessary capabilities from xml
+* [CB-8747](https://issues.apache.org/jira/browse/CB-8747) updated dependency, added peer dependency
+* [CB-8683](https://issues.apache.org/jira/browse/CB-8683) updated blackberry specific references of org.apache.cordova.camera to cordova-plugin-camera
+* [CB-8782](https://issues.apache.org/jira/browse/CB-8782): Updated the docs to talk about the allowEdit quirks, it's not 100% working, but better than it was
+* [CB-8782](https://issues.apache.org/jira/browse/CB-8782): Fixed the flow so that we save the cropped image and use it, not the original non-cropped.  Crop only supports G+ Photos Crop, other crops may not work, depending on the OEM
+* [CB-8740](https://issues.apache.org/jira/browse/CB-8740): Removing FileHelper call that was failing on Samsung Galaxy S3, now that we have a real path, we only need to update the MediaStore, not pull from it in this case
+* [CB-8740](https://issues.apache.org/jira/browse/CB-8740): Partial fix for Save Image to Gallery error found in MobileSpec
+* [CB-8683](https://issues.apache.org/jira/browse/CB-8683) changed plugin-id to pacakge-name
+* [CB-8653](https://issues.apache.org/jira/browse/CB-8653) properly updated translated docs to use new id
+* [CB-8653](https://issues.apache.org/jira/browse/CB-8653) updated translated docs to use new id
+* [CB-8351](https://issues.apache.org/jira/browse/CB-8351) Fix custom implementation of integerValueForKey (close #79)
+* Fix cordova-paramedic path change, build with TRAVIS_BUILD_DIR, use npm to install paramedic
+* docs: added 'Windows' to supported platforms
+* [CB-8653](https://issues.apache.org/jira/browse/CB-8653) Updated Readme
+* [CB-8659](https://issues.apache.org/jira/browse/CB-8659): ios: 4.0.x Compatibility: Remove use of deprecated headers
+
+### 0.3.6 (Mar 10, 2015)
+* Fix localize key for Videos. This closes #58
+* [CB-8235](https://issues.apache.org/jira/browse/CB-8235) android: Fix crash when selecting images from DropBox with spaces in path (close #65)
+* add try ... catch for getting image orientation
+* [CB-8599](https://issues.apache.org/jira/browse/CB-8599) fix threading issue with cameraPicker (fixes #72)
+* [CB-8559](https://issues.apache.org/jira/browse/CB-8559) Integrate TravisCI
+* [CB-8438](https://issues.apache.org/jira/browse/CB-8438) cordova-plugin-camera documentation translation: cordova-plugin-camera
+* [CB-8538](https://issues.apache.org/jira/browse/CB-8538) Added package.json file
+
+### 0.3.5 (Feb 04, 2015)
+* [CB-8351](https://issues.apache.org/jira/browse/CB-8351) ios: Stop using now-deprecated [NSData base64EncodedString]
+* [CB-8351](https://issues.apache.org/jira/browse/CB-8351) ios: Stop using now-deprecated integerValueForKey: class extension
+* [CB-8351](https://issues.apache.org/jira/browse/CB-8351) ios: Use argumentForIndex rather than NSArray extension
+* [CB-8032](https://issues.apache.org/jira/browse/CB-8032) ios: Add nativeURL external method support for CDVFileSystem->makeEntryForPath:isDirectory:
+* [CB-7938](https://issues.apache.org/jira/browse/CB-7938) ios: Added XCTest unit tests project, with stubs (adapted from SplashScreen unit test setup)
+* [CB-7937](https://issues.apache.org/jira/browse/CB-7937) ios: Re-factor iOS Camera plugin so that it is testable
+
+### 0.3.4 (Dec 02, 2014)
+* [CB-7977](https://issues.apache.org/jira/browse/CB-7977) Mention `deviceready` in plugin docs
+* [CB-7979](https://issues.apache.org/jira/browse/CB-7979) Each plugin doc should have a ## Installation section
+* Fix memory leak of image data in `imagePickerControllerReturnImageResult`
+* Pass uri to crop instead of pulling the low resolution image out of the intent return (close #43)
+* Add orientation support for PNG to Android (closes #45)
+* [CB-7700](https://issues.apache.org/jira/browse/CB-7700) cordova-plugin-camera documentation translation: cordova-plugin-camera
+
+### 0.3.3 (Oct 03, 2014)
+* [CB-7600](https://issues.apache.org/jira/browse/CB-7600) Adds informative message to error callback in manual test.
+
+### 0.3.2 (Sep 17, 2014)
+* [CB-7551](https://issues.apache.org/jira/browse/CB-7551) [Camera][iOS 8] Scaled images show a white line
+* [CB-7558](https://issues.apache.org/jira/browse/CB-7558) hasPendingOperation flag in Camera plugin's takePicture should be reversed to fix memory errors
+* [CB-7557](https://issues.apache.org/jira/browse/CB-7557) Camera plugin tests is missing a File dependency
+* [CB-7423](https://issues.apache.org/jira/browse/CB-7423) do cleanup after copyImage manual test
+* [CB-7471](https://issues.apache.org/jira/browse/CB-7471) cordova-plugin-camera documentation translation: cordova-plugin-camera
+* [CB-7413](https://issues.apache.org/jira/browse/CB-7413) Resolve 'ms-appdata' URIs with File plugin
+* Fixed minor bugs with the browser
+* [CB-7433](https://issues.apache.org/jira/browse/CB-7433) Adds missing window reference to prevent manual tests failure on Android and iOS
+* [CB-7249](https://issues.apache.org/jira/browse/CB-7249) cordova-plugin-camera documentation translation: cordova-plugin-camera
+* [CB-4003](https://issues.apache.org/jira/browse/CB-4003) Add config option to not use location information in Camera plugin (and default to not use it)
+* [CB-7461](https://issues.apache.org/jira/browse/CB-7461) Geolocation fails in Camera plugin in iOS 8
+* [CB-7378](https://issues.apache.org/jira/browse/CB-7378) Use single Proxy for both windows8 and windows.
+* [CB-7378](https://issues.apache.org/jira/browse/CB-7378) Adds support for windows platform
+* [CB-7433](https://issues.apache.org/jira/browse/CB-7433) Fixes manual tests failure on windows
+* [CB-6958](https://issues.apache.org/jira/browse/CB-6958) Get the correct default for "quality" in the test
+* add documentation for manual tests
+* [CB-7249](https://issues.apache.org/jira/browse/CB-7249) cordova-plugin-camera documentation translation: cordova-plugin-camera
+* [CB-4003](https://issues.apache.org/jira/browse/CB-4003) Add config option to not use location information in Camera plugin (and default to not use it)
+* [CB-7461](https://issues.apache.org/jira/browse/CB-7461) Geolocation fails in Camera plugin in iOS 8
+* [CB-7433](https://issues.apache.org/jira/browse/CB-7433) Fixes manual tests failure on windows
+* [CB-7378](https://issues.apache.org/jira/browse/CB-7378) Use single Proxy for both windows8 and windows.
+* [CB-7378](https://issues.apache.org/jira/browse/CB-7378) Adds support for windows platform
+* [CB-6958](https://issues.apache.org/jira/browse/CB-6958) Get the correct default for "quality" in the test
+* add documentation for manual tests
+* Updated docs for browser
+* Added support for the browser
+* [CB-7286](https://issues.apache.org/jira/browse/CB-7286) [BlackBerry10] Use getUserMedia if camera card is unavailable
+* [CB-7180](https://issues.apache.org/jira/browse/CB-7180) Update Camera plugin to support generic plugin webView UIView (which can be either a UIWebView or WKWebView)
+* Renamed test dir, added nested plugin.xml
+* [CB-6958](https://issues.apache.org/jira/browse/CB-6958) added manual tests
+* [CB-6958](https://issues.apache.org/jira/browse/CB-6958) Port camera tests to plugin-test-framework
+
+### 0.3.1 (Aug 06, 2014)
+* **FFOS** update CameraProxy.js
+* [CB-7187](https://issues.apache.org/jira/browse/CB-7187) ios: Add explicit dependency on CoreLocation.framework
+* [BlackBerry10] Doc correction - sourceType is supported
+* [CB-7071](https://issues.apache.org/jira/browse/CB-7071) android: Fix callback firing before CROP intent is sent when allowEdit=true
+* [CB-6875](https://issues.apache.org/jira/browse/CB-6875) android: Handle exception when SDCard is not mounted
+* ios: Delete postImage (dead code)
+* Prevent NPE on processResiultFromGallery when intent comes null
+* Remove iOS doc reference to non-existing navigator.fileMgr API
+* Docs updated with some default values
+* Removes File plugin dependency from windows8 code.
+* Use WinJS functionality to resize image instead of File plugin functionality
+* [CB-6127](https://issues.apache.org/jira/browse/CB-6127) Updated translations for docs
+
+### 0.3.0 (Jun 05, 2014)
+* [CB-5895](https://issues.apache.org/jira/browse/CB-5895) documented saveToPhotoAlbum quirk on WP8
+* Remove deprecated symbols for iOS < 6
+* documentation translation: cordova-plugin-camera
+* ubuntu: use application directory for images
+* [CB-6795](https://issues.apache.org/jira/browse/CB-6795) Add license
+* Little fix in code formatting
+* [CB-6613](https://issues.apache.org/jira/browse/CB-6613) Use WinJS functionality to get base64-encoded content of image instead of File plugin functionality
+* [CB-6612](https://issues.apache.org/jira/browse/CB-6612) camera.getPicture now always returns encoded JPEG image
+* Removed invalid note from [CB-5398](https://issues.apache.org/jira/browse/CB-5398)
+* [CB-6576](https://issues.apache.org/jira/browse/CB-6576) - Returns a specific error message when app has no access to library.
+* [CB-6491](https://issues.apache.org/jira/browse/CB-6491) add CONTRIBUTING.md
+* [CB-6546](https://issues.apache.org/jira/browse/CB-6546) android: Fix a couple bugs with allowEdit pull request
+* [CB-6546](https://issues.apache.org/jira/browse/CB-6546) android: Add support for allowEdit Camera option
+
+### 0.2.9 (Apr 17, 2014)
+* [CB-6460](https://issues.apache.org/jira/browse/CB-6460): Update license headers
+* [CB-6422](https://issues.apache.org/jira/browse/CB-6422): [windows8] use cordova/exec/proxy
+* [WP8] When only targetWidth or targetHeight is provided, use it as the only bound
+* [CB-4027](https://issues.apache.org/jira/browse/CB-4027), [CB-5102](https://issues.apache.org/jira/browse/CB-5102), [CB-2737](https://issues.apache.org/jira/browse/CB-2737), [CB-2387](https://issues.apache.org/jira/browse/CB-2387): [WP] Fix camera issues, cropping, memory leaks
+* [CB-6212](https://issues.apache.org/jira/browse/CB-6212): [iOS] fix warnings compiled under arm64 64-bit
+* [BlackBerry10] Add rim xml namespaces declaration
+* Add NOTICE file
+
+### 0.2.8 (Feb 26, 2014)
+* [CB-1826](https://issues.apache.org/jira/browse/CB-1826) Catch OOM on gallery image resize
+
+### 0.2.7 (Feb 05, 2014)
+* [CB-4919](https://issues.apache.org/jira/browse/CB-4919) firefox os quirks added and supported platforms list is updated
+* getPicture via web activities
+* Documented quirk for [CB-5335](https://issues.apache.org/jira/browse/CB-5335) + [CB-5206](https://issues.apache.org/jira/browse/CB-5206) for WP7+8
+* reference the correct firefoxos implementation
+* [BlackBerry10] Add permission to access_shared
+
+### 0.2.6 (Jan 02, 2014)
+* [CB-5658](https://issues.apache.org/jira/browse/CB-5658) Add doc/index.md for Camera plugin
+* [CB-2442](https://issues.apache.org/jira/browse/CB-2442) [CB-2419](https://issues.apache.org/jira/browse/CB-2419) Use Windows.Storage.ApplicationData.current.localFolder, instead of writing to app package.
+* [BlackBerry10] Adding platform level permissions
+* [CB-5599](https://issues.apache.org/jira/browse/CB-5599) Android: Catch and ignore OutOfMemoryError in getRotatedBitmap()
+
+### 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.4 (Oct 28, 2013)
+* [CB-5128](https://issues.apache.org/jira/browse/CB-5128): added repo + issue tag to plugin.xml for camera plugin
+* [CB-4958](https://issues.apache.org/jira/browse/CB-4958) - iOS - Camera plugin should not show the status bar
+* [CB-4919](https://issues.apache.org/jira/browse/CB-4919) updated plugin.xml for FxOS
+* [CB-4915](https://issues.apache.org/jira/browse/CB-4915) Incremented plugin version on dev branch.
+
+### 0.2.3 (Sept 25, 2013)
+* [CB-4889](https://issues.apache.org/jira/browse/CB-4889) bumping&resetting version
+* [CB-4889](https://issues.apache.org/jira/browse/CB-4889) forgot index.html
+* [CB-4889](https://issues.apache.org/jira/browse/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](https://issues.apache.org/jira/browse/CB-4823) Fix XCode 5 camera plugin warnings
+* Fix compiler warnings
+* [CB-4765](https://issues.apache.org/jira/browse/CB-4765) Move ExifHelper.java into Camera Plugin
+* [CB-4764](https://issues.apache.org/jira/browse/CB-4764) Remove reference to DirectoryManager from CameraLauncher
+* [CB-4763](https://issues.apache.org/jira/browse/CB-4763) Use a copy of FileHelper.java within camera-plugin.
+* [CB-4752](https://issues.apache.org/jira/browse/CB-4752) Incremented plugin version on dev branch.
+* [CB-4633](https://issues.apache.org/jira/browse/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](https://issues.apache.org/jira/browse/CB-4889) renaming org.apache.cordova.core.camera to org.apache.cordova.camera
+
+### 0.2.1 (Sept 5, 2013)
+* [CB-4656](https://issues.apache.org/jira/browse/CB-4656) Don't add line-breaks to base64-encoded images (Fixes type=DataURI)
+* [CB-4432](https://issues.apache.org/jira/browse/CB-4432) copyright notice change

+ 628 - 0
miaomiao/plugins/cordova-plugin-camera/appium-tests/android/android.spec.js

xqd
@@ -0,0 +1,628 @@
+/*jshint node: true, jasmine: true */
+
+/*
+ *
+ * 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.
+ *
+*/
+
+// these tests are meant to be executed by Cordova ParaMedic Appium runner
+// you can find it here: https://github.com/apache/cordova-paramedic/
+// it is not necessary to do a full CI setup to run these tests
+// Run:
+//      node cordova-paramedic/main.js --platform android --plugin cordova-plugin-camera --skipMainTests --target <emulator name>
+// Please note only Android 5.1 and 4.4 are supported at this point.
+
+'use strict';
+
+var wdHelper = global.WD_HELPER;
+var screenshotHelper = global.SCREENSHOT_HELPER;
+var wd = wdHelper.getWD();
+var cameraConstants = require('../../www/CameraConstants');
+var cameraHelper = require('../helpers/cameraHelper');
+
+var MINUTE = 60 * 1000;
+var BACK_BUTTON = 4;
+var DEFAULT_SCREEN_WIDTH = 360;
+var DEFAULT_SCREEN_HEIGHT = 567;
+var DEFAULT_WEBVIEW_CONTEXT = 'WEBVIEW';
+var PROMISE_PREFIX = 'appium_camera_promise_';
+var CONTEXT_NATIVE_APP = 'NATIVE_APP';
+
+describe('Camera tests Android.', function () {
+    var driver;
+    // the name of webview context, it will be changed to match needed context if there are named ones:
+    var webviewContext = DEFAULT_WEBVIEW_CONTEXT;
+    // this indicates that the device library has the test picture:
+    var isTestPictureSaved = false;
+    // we need to know the screen width and height to properly click on an image in the gallery:
+    var screenWidth = DEFAULT_SCREEN_WIDTH;
+    var screenHeight = DEFAULT_SCREEN_HEIGHT;
+    // promise count to use in promise ID
+    var promiseCount = 0;
+    // determine if Appium session is created successfully
+    var appiumSessionStarted = false;
+    // determine if camera is present on the device/emulator
+    var cameraAvailable = false;
+    // determine if emulator is within a range of acceptable resolutions able to run these tests
+    var isResolutionBad = true;
+    // a path to the image we add to the gallery before test run
+    var fillerImagePath;
+
+    function getNextPromiseId() {
+        promiseCount += 1;
+        return getCurrentPromiseId();
+    }
+
+    function getCurrentPromiseId() {
+        return PROMISE_PREFIX + promiseCount;
+    }
+
+    function gracefullyFail(error) {
+        fail(error);
+        return driver
+            .quit()
+            .then(function () {
+                return getDriver();
+            });
+    }
+
+    // combinines specified options in all possible variations
+    // you can add more options to test more scenarios
+    function generateOptions() {
+        var sourceTypes = [
+                cameraConstants.PictureSourceType.CAMERA,
+                cameraConstants.PictureSourceType.PHOTOLIBRARY
+            ];
+        var destinationTypes = cameraConstants.DestinationType;
+        var encodingTypes = cameraConstants.EncodingType;
+        var allowEditOptions = [ true, false ];
+        var correctOrientationOptions = [ true, false ];
+
+        return cameraHelper.generateSpecs(sourceTypes, destinationTypes, encodingTypes, allowEditOptions, correctOrientationOptions);
+    }
+
+    // invokes Camera.getPicture() with the specified options
+    // and goes through all UI interactions unless 'skipUiInteractions' is true
+    function getPicture(options, skipUiInteractions) {
+        var promiseId = getNextPromiseId();
+        if (!options) {
+            options = {};
+        }
+
+        return driver
+            .context(webviewContext)
+            .execute(cameraHelper.getPicture, [options, promiseId])
+            .context(CONTEXT_NATIVE_APP)
+            .then(function () {
+                if (skipUiInteractions) {
+                    return;
+                }
+                // selecting a picture from gallery
+                if (options.hasOwnProperty('sourceType') &&
+                        (options.sourceType === cameraConstants.PictureSourceType.PHOTOLIBRARY ||
+                        options.sourceType === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM)) {
+                    var tapTile = new wd.TouchAction();
+                    var swipeRight = new wd.TouchAction();
+                    tapTile
+                        .tap({
+                            x: Math.round(screenWidth / 4),
+                            y: Math.round(screenHeight / 4)
+                        });
+                    swipeRight
+                        .press({x: 10, y: Math.round(screenHeight / 4)})
+                        .wait(300)
+                        .moveTo({x: Math.round(screenWidth - (screenWidth / 8)), y: 0})
+                        .wait(1500)
+                        .release()
+                        .wait(1000);
+                    if (options.allowEdit) {
+                        return driver
+                            // always wait before performing touchAction
+                            .sleep(7000)
+                            .performTouchAction(tapTile);
+                    }
+                    return driver
+                        .waitForElementByAndroidUIAutomator('new UiSelector().text("Gallery");', 20000)
+                        .fail(function () {
+                            // If the Gallery button is not present, swipe right to reveal the Gallery button!
+                            return driver
+                                .performTouchAction(swipeRight)
+                                .waitForElementByAndroidUIAutomator('new UiSelector().text("Gallery");', 20000)
+                        })
+                        .click()
+                        // always wait before performing touchAction
+                        .sleep(7000)
+                        .performTouchAction(tapTile);
+                }
+                // taking a picture from camera
+                return driver
+                    .waitForElementByAndroidUIAutomator('new UiSelector().resourceIdMatches(".*shutter.*")', MINUTE / 2)
+                    .click()
+                    .waitForElementByAndroidUIAutomator('new UiSelector().resourceIdMatches(".*done.*")', MINUTE / 2)
+                    .click();
+            })
+            .then(function () {
+                if (skipUiInteractions) {
+                    return;
+                }
+                if (options.allowEdit) {
+                    return driver
+                        .waitForElementByAndroidUIAutomator('new UiSelector().text("Save")', MINUTE)
+                        .click();
+                }
+            })
+            .fail(function (failure) {
+                throw failure;
+            });
+    }
+
+    // checks if the picture was successfully taken
+    // if shouldLoad is falsy, ensures that the error callback was called
+    function checkPicture(shouldLoad, options) {
+        if (!options) {
+            options = {};
+        }
+        return driver
+            .context(webviewContext)
+            .setAsyncScriptTimeout(MINUTE / 2)
+            .executeAsync(cameraHelper.checkPicture, [getCurrentPromiseId(), options])
+            .then(function (result) {
+                if (shouldLoad) {
+                    if (result !== 'OK') {
+                        fail(result);
+                    }
+                } else if (result.indexOf('ERROR') === -1) {
+                    throw 'Unexpected success callback with result: ' + result;
+                }
+            });
+    }
+
+    // deletes the latest image from the gallery
+    function deleteImage() {
+        var holdTile = new wd.TouchAction();
+        holdTile
+            .press({x: Math.round(screenWidth / 4), y: Math.round(screenHeight / 5)})
+            .wait(1000)
+            .release();
+        return driver
+            // always wait before performing touchAction
+            .sleep(7000)
+            .performTouchAction(holdTile)
+            .elementByAndroidUIAutomator('new UiSelector().text("Delete")')
+            .then(function (element) {
+                return element
+                    .click()
+                    .elementByAndroidUIAutomator('new UiSelector().text("OK")')
+                    .click();
+            }, function () {
+                // couldn't find Delete menu item. Possibly there is no image.
+                return driver;
+            });
+    }
+
+    function getDriver() {
+        driver = wdHelper.getDriver('Android');
+        return driver.getWebviewContext()
+            .then(function(context) {
+                webviewContext = context;
+                return driver.context(webviewContext);
+            })
+            .waitForDeviceReady()
+            .injectLibraries()
+            .deleteFillerImage(fillerImagePath)
+            .then(function () {
+                fillerImagePath = null;
+            })
+            .addFillerImage()
+            .then(function (result) {
+                if (result && result.indexOf('ERROR:') === 0) {
+                    throw new Error(result);
+                } else {
+                    fillerImagePath = result;
+                }
+            });
+    }
+
+    function recreateSession() {
+        return driver
+            .quit()
+            .finally(function () {
+                return getDriver();
+            });
+    }
+
+    function tryRunSpec(spec) {
+        return driver
+            .then(spec)
+            .fail(function () {
+                return recreateSession()
+                    .then(spec)
+                    .fail(function() {
+                        return recreateSession()
+                            .then(spec);
+                    });
+            })
+            .fail(gracefullyFail);
+    }
+
+    // produces a generic spec function which
+    // takes a picture with specified options
+    // and then verifies it
+    function generateSpec(options) {
+        return function () {
+            return driver
+                .then(function () {
+                    return getPicture(options);
+                })
+                .then(function () {
+                    return checkPicture(true, options);
+                });
+        };
+    }
+
+    function checkSession(done, skipResolutionCheck) {
+        if (!appiumSessionStarted) {
+            fail('Failed to start a session ' + (lastFailureReason ? lastFailureReason : ''));
+            done();
+        }
+        if (!skipResolutionCheck && isResolutionBad) {
+            fail('The resolution of this target device is not within the appropriate range of width: blah-blah and height: bleh-bleh. The target\'s current resolution is: ' + isResolutionBad);
+        }
+    }
+
+    function checkCamera(pending) {
+        if (!cameraAvailable) {
+            pending('This test requires a functioning camera on the Android device/emulator, and this test suite\'s functional camera test failed on your target environment.');
+        }
+    }
+    afterAll(function (done) {
+        checkSession(done);
+        driver
+            .quit()
+            .done(done);
+    }, MINUTE);
+
+    it('camera.ui.util configuring driver and starting a session', function (done) {
+        getDriver()
+            .then(function () {
+                appiumSessionStarted = true;
+            }, fail)
+            .done(done);
+    }, 10 * MINUTE);
+
+    it('camera.ui.util determine screen dimensions', function (done) {
+        checkSession(done, /*skipResolutionCheck?*/ true); // skip the resolution check here since we are about to find out in this spec!
+        driver
+            .context(CONTEXT_NATIVE_APP)
+            .getWindowSize()
+            .then(function (size) {
+                screenWidth = Number(size.width);
+                screenHeight = Number(size.height);
+                isResolutionBad = false;
+                /*
+                TODO: what are acceptable resolution values?
+                need to check what the emulators used in CI return.
+                and also what local device definitions work and dont
+                */
+            })
+            .done(done);
+    }, MINUTE);
+
+    it('camera.ui.util determine camera availability', function (done) {
+        checkSession(done);
+        var opts = {
+            sourceType: cameraConstants.PictureSourceType.CAMERA,
+            saveToPhotoAlbum: false
+        };
+
+        return driver
+            .then(function () {
+                return getPicture(opts);
+            })
+            .then(function () {
+                cameraAvailable = true;
+            }, function () {
+                return recreateSession();
+            })
+            .done(done);
+    }, 5 * MINUTE);
+
+    describe('Specs.', function () {
+        // getPicture() with saveToPhotoLibrary = true
+        it('camera.ui.spec.1 Saving a picture to the photo library', function (done) {
+            checkSession(done);
+            checkCamera(pending);
+            var spec = generateSpec({
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.CAMERA,
+                saveToPhotoAlbum: true
+            });
+
+            tryRunSpec(spec)
+                .then(function () {
+                    isTestPictureSaved = true;
+                })
+                .done(done);
+        }, 10 * MINUTE);
+
+        // getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
+        it('camera.ui.spec.2 Selecting only videos', function (done) {
+            checkSession(done);
+            var spec = function () {
+                var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                                mediaType: cameraConstants.MediaType.VIDEO };
+                return driver
+                    .then(function () {
+                        return getPicture(options, true);
+                    })
+                    .context(CONTEXT_NATIVE_APP)
+                    .then(function () {
+                        // try to find "Gallery" menu item
+                        // if there's none, the gallery should be already opened
+                        return driver
+                            .waitForElementByAndroidUIAutomator('new UiSelector().text("Gallery")', 20000)
+                            .then(function (element) {
+                                return element.click();
+                            }, function () {
+                                return driver;
+                            });
+                    })
+                    .then(function () {
+                        // if the gallery is opened on the videos page,
+                        // there should be a "Choose video" caption
+                        return driver
+                            .elementByAndroidUIAutomator('new UiSelector().text("Choose video")')
+                            .fail(function () {
+                                throw 'Couldn\'t find "Choose video" element.';
+                            });
+                    })
+                    .deviceKeyEvent(BACK_BUTTON)
+                    .elementByAndroidUIAutomator('new UiSelector().text("Gallery")')
+                    .deviceKeyEvent(BACK_BUTTON)
+                    .finally(function () {
+                        return driver
+                            .elementById('action_bar_title')
+                            .then(function () {
+                                // success means we're still in native app
+                                return driver
+                                    .deviceKeyEvent(BACK_BUTTON)
+                                    // give native app some time to close
+                                    .sleep(2000)
+                                    // try again! because every ~30th build
+                                    // on Sauce Labs this backbutton doesn't work
+                                    .elementById('action_bar_title')
+                                    .then(function () {
+                                        // success means we're still in native app
+                                        return driver
+                                            .deviceKeyEvent(BACK_BUTTON);
+                                        }, function () {
+                                            // error means we're already in webview
+                                            return driver;
+                                        });
+                            }, function () {
+                                // error means we're already in webview
+                                return driver;
+                            });
+                    });
+            };
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        // getPicture(), then dismiss
+        // wait for the error callback to be called
+        it('camera.ui.spec.3 Dismissing the camera', function (done) {
+            checkSession(done);
+            checkCamera(pending);
+            var spec = function () {
+                var options = {
+                    quality: 50,
+                    allowEdit: true,
+                    sourceType: cameraConstants.PictureSourceType.CAMERA,
+                    destinationType: cameraConstants.DestinationType.FILE_URI
+                };
+                return driver
+                    .then(function () {
+                        return getPicture(options, true);
+                    })
+                    .context(CONTEXT_NATIVE_APP)
+                    .waitForElementByAndroidUIAutomator('new UiSelector().resourceIdMatches(".*cancel.*")', MINUTE / 2)
+                    .click()
+                    .then(function () {
+                        return checkPicture(false);
+                    });
+            };
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        // getPicture(), then take picture but dismiss the edit
+        // wait for the error callback to be called
+        it('camera.ui.spec.4 Dismissing the edit', function (done) {
+            checkSession(done);
+            checkCamera(pending);
+            var spec = function () {
+                var options = {
+                    quality: 50,
+                    allowEdit: true,
+                    sourceType: cameraConstants.PictureSourceType.CAMERA,
+                    destinationType: cameraConstants.DestinationType.FILE_URI
+                };
+                return driver
+                    .then(function () {
+                        return getPicture(options, true);
+                    })
+                    .waitForElementByAndroidUIAutomator('new UiSelector().resourceIdMatches(".*shutter.*")', MINUTE / 2)
+                    .click()
+                    .waitForElementByAndroidUIAutomator('new UiSelector().resourceIdMatches(".*done.*")', MINUTE / 2)
+                    .click()
+                    .waitForElementByAndroidUIAutomator('new UiSelector().resourceIdMatches(".*discard.*")', MINUTE / 2)
+                    .click()
+                    .then(function () {
+                        return checkPicture(false);
+                    });
+            };
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        it('camera.ui.spec.5 Verifying target image size, sourceType=CAMERA', function (done) {
+            checkSession(done);
+            checkCamera(pending);
+            var spec = generateSpec({
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.CAMERA,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            });
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        it('camera.ui.spec.6 Verifying target image size, sourceType=PHOTOLIBRARY', function (done) {
+            checkSession(done);
+            var spec = generateSpec({
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            });
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        it('camera.ui.spec.7 Verifying target image size, sourceType=CAMERA, DestinationType=NATIVE_URI', function (done) {
+            checkSession(done);
+            checkCamera(pending);
+            var spec = generateSpec({
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.CAMERA,
+                destinationType: cameraConstants.DestinationType.NATIVE_URI,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            });
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        it('camera.ui.spec.8 Verifying target image size, sourceType=PHOTOLIBRARY, DestinationType=NATIVE_URI', function (done) {
+            checkSession(done);
+            var spec = generateSpec({
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                destinationType: cameraConstants.DestinationType.NATIVE_URI,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            });
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        it('camera.ui.spec.9 Verifying target image size, sourceType=CAMERA, DestinationType=NATIVE_URI, quality=100', function (done) {
+            checkSession(done);
+            checkCamera(pending);
+            var spec = generateSpec({
+                quality: 100,
+                allowEdit: true,
+                sourceType: cameraConstants.PictureSourceType.CAMERA,
+                destinationType: cameraConstants.DestinationType.NATIVE_URI,
+                saveToPhotoAlbum: false,
+                targetWidth: 305,
+                targetHeight: 305
+            });
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        it('camera.ui.spec.10 Verifying target image size, sourceType=PHOTOLIBRARY, DestinationType=NATIVE_URI, quality=100', function (done) {
+            checkSession(done);
+            var spec = generateSpec({
+                quality: 100,
+                allowEdit: true,
+                sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                destinationType: cameraConstants.DestinationType.NATIVE_URI,
+                saveToPhotoAlbum: false,
+                targetWidth: 305,
+                targetHeight: 305
+            });
+
+            tryRunSpec(spec).done(done);
+        }, 10 * MINUTE);
+
+        // combine various options for getPicture()
+        generateOptions().forEach(function (spec) {
+            it('camera.ui.spec.11.' + spec.id + ' Combining options. ' + spec.description, function (done) {
+                checkSession(done);
+                if (spec.options.sourceType == cameraConstants.PictureSourceType.CAMERA) {
+                    checkCamera(pending);
+                }
+                var s = generateSpec(spec.options);
+                tryRunSpec(s).done(done);
+            }, 10 * MINUTE);
+        });
+
+        it('camera.ui.util Delete filler picture from device library', function (done) {
+            driver
+                .context(webviewContext)
+                .deleteFillerImage(fillerImagePath)
+                .done(done);
+        }, MINUTE);
+
+        it('camera.ui.util Delete taken picture from device library', function (done) {
+            checkSession(done);
+            if (!isTestPictureSaved) {
+                // couldn't save test picture earlier, so nothing to delete here
+                done();
+                return;
+            }
+            // delete exactly one latest picture
+            // this should be the picture we've taken in the first spec
+            driver
+                .context(CONTEXT_NATIVE_APP)
+                .deviceKeyEvent(BACK_BUTTON)
+                .sleep(1000)
+                .deviceKeyEvent(BACK_BUTTON)
+                .sleep(1000)
+                .deviceKeyEvent(BACK_BUTTON)
+                .elementById('Apps')
+                .click()
+                .elementByAndroidUIAutomator('new UiSelector().text("Gallery")')
+                .click()
+                .elementByAndroidUIAutomator('new UiSelector().textContains("Pictures")')
+                .click()
+                .then(deleteImage)
+                .deviceKeyEvent(BACK_BUTTON)
+                .sleep(1000)
+                .deviceKeyEvent(BACK_BUTTON)
+                .sleep(1000)
+                .deviceKeyEvent(BACK_BUTTON)
+                .fail(fail)
+                .finally(done);
+        }, 3 * MINUTE);
+    });
+
+});

+ 305 - 0
miaomiao/plugins/cordova-plugin-camera/appium-tests/helpers/cameraHelper.js

xqd
@@ -0,0 +1,305 @@
+/*jshint node: true */
+/* global Q, resolveLocalFileSystemURL, Camera, cordova */
+/*
+ *
+ * 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.
+ *
+*/
+
+'use strict';
+
+var cameraConstants = require('../../www/CameraConstants');
+
+function findKeyByValue(set, value) {
+   for (var k in set) {
+      if (set.hasOwnProperty(k)) {
+         if (set[k] == value) {
+            return k;
+         }
+      }
+   }
+   return undefined;
+}
+
+function getDescription(spec) {
+    var desc = '';
+
+    desc += 'sourceType: ' + findKeyByValue(cameraConstants.PictureSourceType, spec.options.sourceType);
+    desc += ', destinationType: ' + findKeyByValue(cameraConstants.DestinationType, spec.options.destinationType);
+    desc += ', encodingType: ' + findKeyByValue(cameraConstants.EncodingType, spec.options.encodingType);
+    desc += ', allowEdit: ' + spec.options.allowEdit.toString();
+    desc += ', correctOrientation: ' + spec.options.correctOrientation.toString();
+
+    return desc;
+}
+
+module.exports.generateSpecs = function (sourceTypes, destinationTypes, encodingTypes, allowEditOptions, correctOrientationOptions) {
+    var destinationType,
+        sourceType,
+        encodingType,
+        allowEdit,
+        correctOrientation,
+        specs = [],
+        id = 1;
+    for (destinationType in destinationTypes) {
+        if (destinationTypes.hasOwnProperty(destinationType)) {
+            for (sourceType in sourceTypes) {
+                if (sourceTypes.hasOwnProperty(sourceType)) {
+                    for (encodingType in encodingTypes) {
+                        if (encodingTypes.hasOwnProperty(encodingType)) {
+                            for (allowEdit in allowEditOptions) {
+                                if (allowEditOptions.hasOwnProperty(allowEdit)) {
+                                    for (correctOrientation in correctOrientationOptions) {
+                                        // if taking picture from photolibrary, don't vary 'correctOrientation' option
+                                        if ((sourceTypes[sourceType] === cameraConstants.PictureSourceType.PHOTOLIBRARY ||
+                                            sourceTypes[sourceType] === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM) &&
+                                            correctOrientation === true) { continue; }
+                                        var spec = {
+                                            'id': id++,
+                                            'options': {
+                                                'destinationType': destinationTypes[destinationType],
+                                                'sourceType': sourceTypes[sourceType],
+                                                'encodingType': encodingTypes[encodingType],
+                                                'allowEdit': allowEditOptions[allowEdit],
+                                                'saveToPhotoAlbum': false,
+                                                'correctOrientation': correctOrientationOptions[correctOrientation]
+                                            }
+                                        };
+                                        spec.description = getDescription(spec);
+                                        specs.push(spec);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return specs;
+};
+
+// calls getPicture() and saves the result in promise
+// note that this function is executed in the context of tested app
+// and not in the context of tests
+module.exports.getPicture = function (opts, pid) {
+    if (navigator._appiumPromises[pid - 1]) {
+        navigator._appiumPromises[pid - 1] = null;
+    }
+    navigator._appiumPromises[pid] = Q.defer();
+    navigator.camera.getPicture(function (result) {
+        navigator._appiumPromises[pid].resolve(result);
+    }, function (err) {
+        navigator._appiumPromises[pid].reject(err);
+    }, opts);
+};
+
+// verifies taken picture when the promise is resolved,
+// calls a callback with 'OK' if everything is good,
+// calls a callback with 'ERROR: <error message>' if something is wrong
+// note that this function is executed in the context of tested app
+// and not in the context of tests
+module.exports.checkPicture = function (pid, options, cb) {
+    var isIos = cordova.platformId === "ios";
+    var isAndroid = cordova.platformId === "android";
+    // skip image type check if it's unmodified on Android:
+    // https://github.com/apache/cordova-plugin-camera/#android-quirks-1
+    var skipFileTypeCheckAndroid = isAndroid && options.quality === 100 &&
+        !options.targetWidth && !options.targetHeight &&
+        !options.correctOrientation;
+
+    // Skip image type check if destination is NATIVE_URI and source - device's photoalbum
+    // https://github.com/apache/cordova-plugin-camera/#ios-quirks-1
+    var skipFileTypeCheckiOS = isIos && options.destinationType === Camera.DestinationType.NATIVE_URI &&
+        (options.sourceType === Camera.PictureSourceType.PHOTOLIBRARY ||
+         options.sourceType === Camera.PictureSourceType.SAVEDPHOTOALBUM);
+
+    var skipFileTypeCheck = skipFileTypeCheckAndroid || skipFileTypeCheckiOS;
+
+    var desiredType = 'JPEG';
+    var mimeType = 'image/jpeg';
+    if (options.encodingType === Camera.EncodingType.PNG) {
+        desiredType = 'PNG';
+        mimeType = 'image/png';
+    }
+
+    function errorCallback(msg) {
+        if (msg.hasOwnProperty('message')) {
+            msg = msg.message;
+        }
+        cb('ERROR: ' + msg);
+    }
+
+    // verifies the image we get from plugin
+    function verifyResult(result) {
+        if (result.length === 0) {
+            errorCallback('The result is empty.');
+            return;
+        } else if (isIos && options.destinationType === Camera.DestinationType.NATIVE_URI && result.indexOf('assets-library:') !== 0) {
+            errorCallback('Expected "' + result.substring(0, 150) + '"to start with "assets-library:"');
+            return;
+        } else if (isIos && options.destinationType === Camera.DestinationType.FILE_URI && result.indexOf('file:') !== 0) {
+            errorCallback('Expected "' + result.substring(0, 150) + '"to start with "file:"');
+            return;
+        }
+
+        try {
+            window.atob(result);
+            // if we got here it is a base64 string (DATA_URL)
+            result = "data:" + mimeType + ";base64," + result;
+        } catch (e) {
+            // not DATA_URL
+            if (options.destinationType === Camera.DestinationType.DATA_URL) {
+                errorCallback('Expected ' + result.substring(0, 150) + 'not to be DATA_URL');
+                return;
+            }
+        }
+        try {
+            if (result.indexOf('file:') === 0 ||
+                result.indexOf('content:') === 0 ||
+                result.indexOf('assets-library:') === 0) {
+
+                if (!window.resolveLocalFileSystemURL) {
+                    errorCallback('Cannot read file. Please install cordova-plugin-file to fix this.');
+                    return;
+                }
+                resolveLocalFileSystemURL(result, function (entry) {
+                    if (skipFileTypeCheck) {
+                        displayFile(entry);
+                    } else {
+                        verifyFile(entry);
+                    }
+                });
+            } else {
+                displayImage(result);
+            }
+        } catch (e) {
+            errorCallback(e);
+        }
+    }
+
+    // verifies that the file type matches the requested type
+    function verifyFile(entry) {
+        try {
+            var reader = new FileReader();
+            reader.onloadend = function(e) {
+                var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
+                var header = '';
+                for(var i = 0; i < arr.length; i++) {
+                    header += arr[i].toString(16);
+                }
+                var actualType = 'unknown';
+
+                switch (header) {
+                    case "89504e47":
+                        actualType = 'PNG';
+                        break;
+                    case 'ffd8ffe0':
+                    case 'ffd8ffe1':
+                    case 'ffd8ffe2':
+                        actualType = 'JPEG';
+                        break;
+                }
+
+                if (actualType === desiredType) {
+                    displayFile(entry);
+                } else {
+                    errorCallback('File type mismatch. Expected ' + desiredType + ', got ' + actualType);
+                }
+            };
+            reader.onerror = function (e) {
+                errorCallback(e);
+            };
+            entry.file(function (file) {
+                reader.readAsArrayBuffer(file);
+            }, function (e) {
+                errorCallback(e);
+            });
+        } catch (e) {
+            errorCallback(e);
+        }
+    }
+
+    // reads the file, then displays the image
+    function displayFile(entry) {
+        function onFileReceived(file) {
+            var reader = new FileReader();
+            reader.onerror = function (e) {
+                errorCallback(e);
+            };
+            reader.onloadend = function (evt) {
+                displayImage(evt.target.result);
+            };
+            reader.readAsDataURL(file);
+        }
+
+        entry.file(onFileReceived, function (e) {
+            errorCallback(e);
+        });
+    }
+
+    function displayImage(image) {
+        try {
+            var imgEl = document.getElementById('camera_test_image');
+            if (!imgEl) {
+                imgEl = document.createElement('img');
+                imgEl.id = 'camera_test_image';
+                document.body.appendChild(imgEl);
+            }
+            var timedOut = false;
+            var loadTimeout = setTimeout(function () {
+                timedOut = true;
+                imgEl.src = '';
+                errorCallback('The image did not load: ' + image.substring(0, 150));
+            }, 10000);
+            var done = function (status) {
+                if (!timedOut) {
+                    clearTimeout(loadTimeout);
+                    imgEl.src = '';
+                    cb(status);
+                }
+            };
+            imgEl.onload = function () {
+                try {
+                    // aspect ratio is preserved so only one dimension should match
+                    if ((typeof options.targetWidth === 'number' && imgEl.naturalWidth !== options.targetWidth) &&
+                        (typeof options.targetHeight === 'number' && imgEl.naturalHeight !== options.targetHeight))
+                    {
+                        done('ERROR: Wrong image size: ' + imgEl.naturalWidth + 'x' + imgEl.naturalHeight +
+                            '. Requested size: ' + options.targetWidth + 'x' + options.targetHeight);
+                    } else {
+                        done('OK');
+                    }
+                } catch (e) {
+                    errorCallback(e);
+                }
+            };
+            imgEl.src = image;
+        } catch (e) {
+            errorCallback(e);
+        }
+    }
+
+    navigator._appiumPromises[pid].promise
+        .then(function (result) {
+            verifyResult(result);
+        })
+        .fail(function (e) {
+            errorCallback(e);
+        });
+};

+ 489 - 0
miaomiao/plugins/cordova-plugin-camera/appium-tests/ios/ios.spec.js

xqd
@@ -0,0 +1,489 @@
+/*jshint node: true, jasmine: true */
+
+/*
+ *
+ * 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.
+ *
+*/
+
+// these tests are meant to be executed by Cordova Paramedic test runner
+// you can find it here: https://github.com/apache/cordova-paramedic/
+// it is not necessary to do a full CI setup to run these tests
+// just run "node cordova-paramedic/main.js --platform ios --plugin cordova-plugin-camera"
+
+'use strict';
+
+var wdHelper = global.WD_HELPER;
+var screenshotHelper = global.SCREENSHOT_HELPER;
+var isDevice = global.DEVICE;
+var cameraConstants = require('../../www/CameraConstants');
+var cameraHelper = require('../helpers/cameraHelper');
+
+var MINUTE = 60 * 1000;
+var DEFAULT_WEBVIEW_CONTEXT = 'WEBVIEW_1';
+var PROMISE_PREFIX = 'appium_camera_promise_';
+var CONTEXT_NATIVE_APP = 'NATIVE_APP';
+
+describe('Camera tests iOS.', function () {
+    var driver;
+    var webviewContext = DEFAULT_WEBVIEW_CONTEXT;
+    // promise count to use in promise ID
+    var promiseCount = 0;
+    // going to set this to false if session is created successfully
+    var failedToStart = true;
+    // points out which UI automation to use
+    var isXCUI = false;
+    // spec counter to restart the session
+    var specsRun = 0;
+
+    function getNextPromiseId() {
+        promiseCount += 1;
+        return getCurrentPromiseId();
+    }
+
+    function getCurrentPromiseId() {
+        return PROMISE_PREFIX + promiseCount;
+    }
+
+    function gracefullyFail(error) {
+        fail(error);
+        return driver
+            .quit()
+            .then(function () {
+                return getDriver();
+            });
+    }
+
+    // generates test specs by combining all the specified options
+    // you can add more options to test more scenarios
+    function generateOptions() {
+        var sourceTypes = cameraConstants.PictureSourceType;
+        var destinationTypes = cameraConstants.DestinationType;
+        var encodingTypes = cameraConstants.EncodingType;
+        var allowEditOptions = [ true, false ];
+        var correctOrientationOptions = [ true, false ];
+
+        return cameraHelper.generateSpecs(sourceTypes, destinationTypes, encodingTypes, allowEditOptions, correctOrientationOptions);
+    }
+
+    function usePicture() {
+        return driver
+            .elementByXPath('//*[@label="Use"]')
+            .click()
+            .fail(function () {
+                if (isXCUI) {
+                    return driver
+                        .waitForElementByAccessibilityId('Choose', MINUTE / 3)
+                        .click();
+                }
+                // For some reason "Choose" element is not clickable by standard Appium methods on iOS <= 9
+                return wdHelper.tapElementByXPath('//UIAButton[@label="Choose"]', driver);
+            });
+    }
+
+    function clickPhoto() {
+        if (isXCUI) {
+            // iOS >=10
+            return driver
+                .context(CONTEXT_NATIVE_APP)
+                .elementsByXPath('//XCUIElementTypeCell')
+                .then(function(photos) {
+                    if (photos.length == 0) {
+                        return driver
+                            .sleep(0) // driver.source is not a function o.O
+                            .source()
+                            .then(function (src) {
+                                console.log(src);
+                                gracefullyFail('Couldn\'t find an image to click');
+                            });
+                    }
+                    // intentionally clicking the second photo here
+                    // the first one is not clickable for some reason
+                    return photos[1].click();
+                });
+        }
+        // iOS <10
+        return driver
+            .elementByXPath('//UIACollectionCell')
+            .click();
+    }
+
+    function getPicture(options, cancelCamera, skipUiInteractions) {
+        var promiseId = getNextPromiseId();
+        if (!options) {
+            options = {};
+        }
+
+        return driver
+            .context(webviewContext)
+            .execute(cameraHelper.getPicture, [options, promiseId])
+            .context(CONTEXT_NATIVE_APP)
+            .then(function () {
+                if (skipUiInteractions) {
+                    return;
+                }
+                if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.PHOTOLIBRARY) {
+                    return driver
+                        .waitForElementByAccessibilityId('Camera Roll', MINUTE / 2)
+                        .click()
+                        .then(function () {
+                            return clickPhoto();
+                        })
+                        .then(function () {
+                            if (!options.allowEdit) {
+                                return driver;
+                            }
+                            return usePicture();
+                        });
+                }
+                if (options.hasOwnProperty('sourceType') && options.sourceType === cameraConstants.PictureSourceType.SAVEDPHOTOALBUM) {
+                    return clickPhoto()
+                        .then(function () {
+                            if (!options.allowEdit) {
+                                return driver;
+                            }
+                            return usePicture();
+                        });
+                }
+                if (cancelCamera) {
+                    return driver
+                        .waitForElementByAccessibilityId('Cancel', MINUTE / 2)
+                        .click();
+                }
+                return driver
+                    .waitForElementByAccessibilityId('Take Picture', MINUTE / 2)
+                    .click()
+                    .waitForElementByAccessibilityId('Use Photo', MINUTE / 2)
+                    .click();
+            })
+            .fail(fail);
+    }
+
+    // checks if the picture was successfully taken
+    // if shouldLoad is falsy, ensures that the error callback was called
+    function checkPicture(shouldLoad, options) {
+        if (!options) {
+            options = {};
+        }
+        return driver
+            .context(webviewContext)
+            .setAsyncScriptTimeout(MINUTE / 2)
+            .executeAsync(cameraHelper.checkPicture, [getCurrentPromiseId(), options])
+            .then(function (result) {
+                if (shouldLoad) {
+                    if (result !== 'OK') {
+                        fail(result);
+                    }
+                } else if (result.indexOf('ERROR') === -1) {
+                    throw 'Unexpected success callback with result: ' + result;
+                }
+            });
+    }
+
+    // takes a picture with the specified options
+    // and then verifies it
+    function runSpec(options, done, pending) {
+        if (options.sourceType === cameraConstants.PictureSourceType.CAMERA && !isDevice) {
+            pending('Camera is not available on iOS simulator');
+        }
+        checkSession(done);
+        specsRun += 1;
+        return driver
+            .then(function () {
+                return getPicture(options);
+            })
+            .then(function () {
+                return checkPicture(true, options);
+            })
+            .fail(gracefullyFail);
+    }
+
+    function getDriver() {
+        failedToStart = true;
+        driver = wdHelper.getDriver('iOS');
+        return wdHelper.getWebviewContext(driver)
+            .then(function(context) {
+                webviewContext = context;
+                return driver.context(webviewContext);
+            })
+            .then(function () {
+                return wdHelper.waitForDeviceReady(driver);
+            })
+            .then(function () {
+                return wdHelper.injectLibraries(driver);
+            })
+            .sessionCapabilities()
+            .then(function (caps) {
+                var platformVersion = parseFloat(caps.platformVersion);
+                isXCUI = platformVersion >= 10.0;
+            })
+            .then(function () {
+                var options = {
+                    quality: 50,
+                    allowEdit: false,
+                    sourceType: cameraConstants.PictureSourceType.SAVEDPHOTOALBUM,
+                    saveToPhotoAlbum: false,
+                    targetWidth: 210,
+                    targetHeight: 210
+                };
+                return driver
+                    .then(function () { return getPicture(options, false, true); })
+                    .context(CONTEXT_NATIVE_APP)
+                    .acceptAlert()
+                    .then(function alertDismissed() {
+                        // TODO: once we move to only XCUITest-based (which is force on you in either iOS 10+ or Xcode 8+)
+                        // UI tests, we will have to:
+                        // a) remove use of autoAcceptAlerts appium capability since it no longer functions in XCUITest
+                        // b) can remove this entire then() clause, as we do not need to explicitly handle the acceptAlert
+                        //    failure callback, since we will be guaranteed to hit the permission dialog on startup.
+                    }, function noAlert() {
+                        // in case the contacts permission alert never showed up: no problem, don't freak out.
+                        // This can happen if:
+                        // a) The application-under-test already had photos permissions granted to it
+                        // b) Appium's autoAcceptAlerts capability is provided (and functioning)
+                    })
+                    .elementByAccessibilityId('Cancel', 10000)
+                    .click();
+            })
+            .then(function () {
+                failedToStart = false;
+            });
+    }
+
+    function checkSession(done) {
+        if (failedToStart) {
+            fail('Failed to start a session');
+            done();
+        }
+    }
+
+    it('camera.ui.util configure driver and start a session', function (done) {
+        getDriver()
+            .fail(fail)
+            .done(done);
+    }, 15 * MINUTE);
+
+    describe('Specs.', function () {
+        afterEach(function (done) {
+            if (specsRun >= 15) {
+                specsRun = 0;
+                // we need to restart the session regularly because for some reason
+                // when running against iOS 10 simulator on SauceLabs, 
+                // Appium cannot handle more than ~20 specs at one session
+                // the error would be as follows:
+                // "Could not proxy command to remote server. Original error: Error: connect ECONNREFUSED 127.0.0.1:8100"
+                checkSession(done);
+                return driver
+                    .quit()
+                    .then(function () {
+                        return getDriver();
+                    })
+                    .done(done);
+            } else {
+                done();
+            }
+        }, 15 * MINUTE);
+
+        // getPicture() with mediaType: VIDEO, sourceType: PHOTOLIBRARY
+        it('camera.ui.spec.1 Selecting only videos', function (done) {
+            checkSession(done);
+            specsRun += 1;
+            var options = { sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                            mediaType: cameraConstants.MediaType.VIDEO };
+            driver
+                // skip ui unteractions
+                .then(function () { return getPicture(options, false, true); })
+                .waitForElementByXPath('//*[contains(@label,"Videos")]', MINUTE / 2)
+                .elementByAccessibilityId('Cancel')
+                .click()
+                .fail(gracefullyFail)
+                .done(done);
+        }, 7 * MINUTE);
+
+        // getPicture(), then dismiss
+        // wait for the error callback to be called
+        it('camera.ui.spec.2 Dismissing the camera', function (done) {
+            checkSession(done);
+            if (!isDevice) {
+                pending('Camera is not available on iOS simulator');
+            }
+            specsRun += 1;
+            var options = { sourceType: cameraConstants.PictureSourceType.CAMERA,
+                            saveToPhotoAlbum: false };
+            driver
+                .then(function () {
+                    return getPicture(options, true);
+                })
+                .then(function () {
+                    return checkPicture(false);
+                })
+                .fail(gracefullyFail)
+                .done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.3 Verifying target image size, sourceType=CAMERA', function (done) {
+            var options = {
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.CAMERA,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.4 Verifying target image size, sourceType=SAVEDPHOTOALBUM', function (done) {
+            var options = {
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.SAVEDPHOTOALBUM,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.5 Verifying target image size, sourceType=PHOTOLIBRARY', function (done) {
+            var options = {
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.6 Verifying target image size, sourceType=CAMERA, destinationType=FILE_URL', function (done) {
+            // remove this line if you don't mind the tests leaving a photo saved on device
+            pending('Cannot prevent iOS from saving the picture to photo library');
+
+            var options = {
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.CAMERA,
+                destinationType: cameraConstants.DestinationType.FILE_URL,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.7 Verifying target image size, sourceType=SAVEDPHOTOALBUM, destinationType=FILE_URL', function (done) {
+            var options = {
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.SAVEDPHOTOALBUM,
+                destinationType: cameraConstants.DestinationType.FILE_URL,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.8 Verifying target image size, sourceType=PHOTOLIBRARY, destinationType=FILE_URL', function (done) {
+            var options = {
+                quality: 50,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                destinationType: cameraConstants.DestinationType.FILE_URL,
+                saveToPhotoAlbum: false,
+                targetWidth: 210,
+                targetHeight: 210
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.9 Verifying target image size, sourceType=CAMERA, destinationType=FILE_URL, quality=100', function (done) {
+            // remove this line if you don't mind the tests leaving a photo saved on device
+            pending('Cannot prevent iOS from saving the picture to photo library');
+
+            var options = {
+                quality: 100,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.CAMERA,
+                destinationType: cameraConstants.DestinationType.FILE_URL,
+                saveToPhotoAlbum: false,
+                targetWidth: 305,
+                targetHeight: 305
+            };
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.10 Verifying target image size, sourceType=SAVEDPHOTOALBUM, destinationType=FILE_URL, quality=100', function (done) {
+            var options = {
+                quality: 100,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.SAVEDPHOTOALBUM,
+                destinationType: cameraConstants.DestinationType.FILE_URL,
+                saveToPhotoAlbum: false,
+                targetWidth: 305,
+                targetHeight: 305
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        it('camera.ui.spec.11 Verifying target image size, sourceType=PHOTOLIBRARY, destinationType=FILE_URL, quality=100', function (done) {
+            var options = {
+                quality: 100,
+                allowEdit: false,
+                sourceType: cameraConstants.PictureSourceType.PHOTOLIBRARY,
+                destinationType: cameraConstants.DestinationType.FILE_URL,
+                saveToPhotoAlbum: false,
+                targetWidth: 305,
+                targetHeight: 305
+            };
+
+            runSpec(options, done, pending).done(done);
+        }, 7 * MINUTE);
+
+        // combine various options for getPicture()
+        generateOptions().forEach(function (spec) {
+            it('camera.ui.spec.12.' + spec.id + ' Combining options. ' + spec.description, function (done) {
+                // remove this check if you don't mind the tests leaving a photo saved on device
+                if (spec.options.sourceType === cameraConstants.PictureSourceType.CAMERA &&
+                    spec.options.destinationType === cameraConstants.DestinationType.NATIVE_URI) {
+                    pending('Skipping: cannot prevent iOS from saving the picture to photo library and cannot delete it. ' +
+                        'For more info, see iOS quirks here: https://github.com/apache/cordova-plugin-camera#ios-quirks-1');
+                }
+
+                runSpec(spec.options, done, pending).done(done);
+            }, 7 * MINUTE);
+        });
+
+    });
+
+    it('camera.ui.util Destroy the session', function (done) {
+        checkSession(done);
+        driver
+            .quit()
+            .done(done);
+    }, 5 * MINUTE);
+});

+ 421 - 0
miaomiao/plugins/cordova-plugin-camera/doc/de/README.md

xqd
@@ -0,0 +1,421 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+Dieses Plugin definiert eine globale `navigator.camera`-Objekt, das eine API für Aufnahmen und für die Auswahl der Bilder aus dem System-Image-Library bietet.
+
+Obwohl das Objekt mit der globalen Gültigkeitsbereich `navigator` verbunden ist, steht es nicht bis nach dem `Deviceready`-Ereignis.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## Installation
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * Kamera 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * navigator.camera.cleanup
+
+## navigator.camera.getPicture
+
+Nimmt ein Foto mit der Kamera, oder ein Foto aus dem Gerät Bildergalerie abgerufen. Das Bild wird an den Erfolg-Rückruf als base64-codierte `String` oder als URI für die Image-Datei übergeben. Die Methode selbst gibt ein `CameraPopoverHandle`-Objekt, das verwendet werden kann, um die Datei-Auswahl-Popover neu zu positionieren.
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### Beschreibung
+
+Die `camera.getPicture`-Funktion öffnet das Gerät Standard-Kamera-Anwendung, die Benutzern ermöglicht, Bilder ausrichten. Dieses Verhalten tritt in der Standardeinstellung, wenn `Camera.sourceType` `Camera.PictureSourceType.CAMERA` entspricht. Sobald der Benutzer die Fotoschnäpper, die Kameraanwendung geschlossen wird und die Anwendung wird wiederhergestellt.
+
+Wenn `Camera.sourceType` `Camera.PictureSourceType.PHOTOLIBRARY` oder `Camera.PictureSourceType.SAVEDPHOTOALBUM` ist, dann wird ein Dialogfeld angezeigt, das Benutzern ermöglicht, ein vorhandenes Bild auszuwählen. Die `camera.getPicture`-Funktion gibt ein `CameraPopoverHandle`-Objekt, das verwendet werden kann, um die Bild-Auswahl-Dialog, z. B. beim ändert sich der Orientierung des Geräts neu positionieren.
+
+Der Rückgabewert wird an die `cameraSuccess`-Callback-Funktion in einem der folgenden Formate, je nach dem angegebenen `cameraOptions` gesendet:
+
+  * A `String` mit dem base64-codierte Foto-Bild.
+
+  * A `String` , die die Bild-Datei-Stelle auf lokalem Speicher (Standard).
+
+Sie können tun, was Sie wollen, mit dem codierten Bildes oder URI, zum Beispiel:
+
+  * Rendern Sie das Bild in ein `<img>` Tag, wie im folgenden Beispiel
+
+  * Die Daten lokal zu speichern ( `LocalStorage` , [Lawnchair](http://brianleroux.github.com/lawnchair/), etc..)
+
+  * Post die Daten an einen entfernten server
+
+**Hinweis**: Fotoauflösung auf neueren Geräten ist ganz gut. Fotos aus dem Gerät Galerie ausgewählt sind nicht zu einer niedrigeren Qualität herunterskaliert, selbst wenn ein `Qualität`-Parameter angegeben wird. Um Speicherprobleme zu vermeiden, legen Sie `Camera.destinationType` auf `FILE_URI` statt `DATA_URL`.
+
+#### Unterstützte Plattformen
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### Beispiel
+
+Nehmen Sie ein Foto und rufen Sie sie als base64-codierte Bild:
+
+    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);
+    }
+    
+
+Nehmen Sie ein Foto und rufen Sie das Bild-Datei-Speicherort:
+
+    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);
+    }
+    
+
+#### "Einstellungen" (iOS)
+
+  * **CameraUsesGeolocation** (Boolean, Standardwert ist False). Zur Erfassung von JPEGs, auf true festgelegt, um Geolocation-Daten im EXIF-Header zu erhalten. Dies löst einen Antrag auf Geolocation-Berechtigungen, wenn auf True festgelegt.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### Amazon Fire OS Macken
+
+Amazon Fire OS verwendet Absichten zum Starten von der Kamera-Aktivität auf dem Gerät, um Bilder zu erfassen und auf Handys mit wenig Speicher, Cordova Tätigkeit getötet werden kann. In diesem Szenario kann das Bild nicht angezeigt, wenn die Aktivität von Cordova wiederhergestellt wird.
+
+#### Android Eigenarten
+
+Android verwendet Absichten zum Starten von der Kamera-Aktivität auf dem Gerät, um Bilder zu erfassen und auf Handys mit wenig Speicher, Cordova Tätigkeit getötet werden kann. In diesem Szenario kann das Bild nicht angezeigt, wenn die Aktivität von Cordova wiederhergestellt wird.
+
+#### Browser-Eigenheiten
+
+Fotos können nur als base64-codierte Bild zurückgeben werden.
+
+#### Firefox OS Macken
+
+Kamera-Plugin ist derzeit implementiert mithilfe von [Web-Aktivitäten](https://hacks.mozilla.org/2013/01/introducing-web-activities/).
+
+#### iOS Macken
+
+Einschließlich einer JavaScript-`alert()` entweder Rückruffunktionen kann Probleme verursachen. Wickeln Sie die Warnung innerhalb eine `setTimeout()` erlauben die iOS-Bild-Picker oder Popover vollständig zu schließen, bevor die Warnung angezeigt:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+#### Windows Phone 7 Macken
+
+Die native Kameraanwendung aufrufen, während das Gerät via Zune angeschlossen ist funktioniert nicht und löst eine Fehler-Callback.
+
+#### Tizen Macken
+
+Tizen unterstützt nur ein `DestinationType` von `Camera.DestinationType.FILE_URI` und ein `SourceType` von `Camera.PictureSourceType.PHOTOLIBRARY`.
+
+## CameraOptions
+
+Optionale Parameter die Kameraeinstellungen anpassen.
+
+    { 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 };
+    
+
+  * **Qualität**: Qualität des gespeicherten Bildes, ausgedrückt als ein Bereich von 0-100, wo 100 in der Regel voller Auflösung ohne Verlust aus der Dateikomprimierung ist. Der Standardwert ist 50. *(Anzahl)* (Beachten Sie, dass Informationen über die Kamera Auflösung nicht verfügbar ist.)
+
+  * **DestinationType**: Wählen Sie das Format des Rückgabewerts. Der Standardwert ist FILE_URI. Im Sinne `navigator.camera.DestinationType` *(Anzahl)*
+    
+        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**: Legen Sie die Quelle des Bildes. Der Standardwert ist die Kamera. Im Sinne `navigator.camera.PictureSourceType` *(Anzahl)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **AllowEdit**: einfache Bearbeitung des Bildes vor Auswahl zu ermöglichen. *(Boolesch)*
+
+  * **EncodingType**: die zurückgegebene Image-Datei ist Codierung auswählen. Standardwert ist JPEG. Im Sinne `navigator.camera.EncodingType` *(Anzahl)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **TargetWidth**: Breite in Pixel zum Bild skalieren. Muss mit **TargetHeight**verwendet werden. Seitenverhältnis bleibt konstant. *(Anzahl)*
+
+  * **TargetHeight**: Höhe in Pixel zum Bild skalieren. Muss mit **TargetWidth**verwendet werden. Seitenverhältnis bleibt konstant. *(Anzahl)*
+
+  * **MediaType**: Legen Sie den Typ der Medien zur Auswahl. Funktioniert nur, wenn `PictureSourceType` ist `PHOTOLIBRARY` oder `SAVEDPHOTOALBUM` . Im Sinne `nagivator.camera.MediaType` *(Anzahl)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. STANDARD. 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**: Drehen Sie das Bild um die Ausrichtung des Geräts während der Aufnahme zu korrigieren. *(Boolesch)*
+
+  * **SaveToPhotoAlbum**: das Bild auf das Fotoalbum auf dem Gerät zu speichern, nach Einnahme. *(Boolesch)*
+
+  * **PopoverOptions**: iOS-nur Optionen, die Popover Lage in iPad angeben. In definierten`CameraPopoverOptions`.
+
+  * **CameraDirection**: Wählen Sie die Kamera (vorn oder hinten-gerichtete) verwenden. Der Standardwert ist zurück. Im Sinne `navigator.camera.Direction` *(Anzahl)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### Amazon Fire OS Macken
+
+  * `cameraDirection`Ergebnisse in einem hinten gerichteter Foto Wert.
+
+  * Ignoriert die `allowEdit` Parameter.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`und `Camera.PictureSourceType.SAVEDPHOTOALBUM` beide das gleiche Fotoalbum anzuzeigen.
+
+#### Android Eigenarten
+
+  * `cameraDirection`Ergebnisse in einem hinten gerichteter Foto Wert.
+
+  * Android verwendet auch die Ernte-Aktivität für AllowEdit, obwohl Ernte sollte arbeiten und das zugeschnittene Bild zurück zu Cordova, das einzige, dass Werke konsequent die gebündelt mit der Google-Plus-Fotos-Anwendung ist tatsächlich zu übergeben. Andere Kulturen funktioniert möglicherweise nicht.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`und `Camera.PictureSourceType.SAVEDPHOTOALBUM` beide das gleiche Fotoalbum anzuzeigen.
+
+#### BlackBerry 10 Macken
+
+  * Ignoriert die `quality` Parameter.
+
+  * Ignoriert die `allowEdit` Parameter.
+
+  * `Camera.MediaType`wird nicht unterstützt.
+
+  * Ignoriert die `correctOrientation` Parameter.
+
+  * Ignoriert die `cameraDirection` Parameter.
+
+#### Firefox OS Macken
+
+  * Ignoriert die `quality` Parameter.
+
+  * `Camera.DestinationType`wird ignoriert, und gleich `1` (Bilddatei-URI)
+
+  * Ignoriert die `allowEdit` Parameter.
+
+  * Ignoriert die `PictureSourceType` Parameter (Benutzer wählt es in einem Dialogfenster)
+
+  * Ignoriert die`encodingType`
+
+  * Ignoriert die `targetWidth` und`targetHeight`
+
+  * `Camera.MediaType`wird nicht unterstützt.
+
+  * Ignoriert die `correctOrientation` Parameter.
+
+  * Ignoriert die `cameraDirection` Parameter.
+
+#### iOS Macken
+
+  * Legen Sie `quality` unter 50 Speicherfehler auf einigen Geräten zu vermeiden.
+
+  * Bei der Verwendung `destinationType.FILE_URI` , Fotos werden im temporären Verzeichnis der Anwendung gespeichert. Den Inhalt des temporären Verzeichnis der Anwendung wird gelöscht, wenn die Anwendung beendet.
+
+#### Tizen Macken
+
+  * nicht unterstützte Optionen
+
+  * gibt immer einen Datei-URI
+
+#### Windows Phone 7 und 8 Eigenarten
+
+  * Ignoriert die `allowEdit` Parameter.
+
+  * Ignoriert die `correctOrientation` Parameter.
+
+  * Ignoriert die `cameraDirection` Parameter.
+
+  * Ignoriert die `saveToPhotoAlbum` Parameter. WICHTIG: Alle Aufnahmen die wp7/8 Cordova-Kamera-API werden immer in Kamerarolle des Telefons kopiert. Abhängig von den Einstellungen des Benutzers könnte dies auch bedeuten, dass das Bild in ihre OneDrive automatisch hochgeladen ist. Dies könnte möglicherweise bedeuten, dass das Bild für ein breiteres Publikum als Ihre Anwendung vorgesehen ist. Wenn diese einen Blocker für Ihre Anwendung, Sie müssen die CameraCaptureTask zu implementieren, wie im Msdn dokumentiert: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> Sie können kommentieren oder Up-Abstimmung das Beiträge zu diesem Thema im [Bugtracker](https://issues.apache.org/jira/browse/CB-2083)
+
+  * Ignoriert die `mediaType` -Eigenschaft des `cameraOptions` wie das Windows Phone SDK keine Möglichkeit, Fotothek Videos wählen.
+
+## CameraError
+
+onError-Callback-Funktion, die eine Fehlermeldung bereitstellt.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+#### Beschreibung
+
+  * **Meldung**: die Nachricht wird durch das Gerät systemeigenen Code bereitgestellt. *(String)*
+
+## cameraSuccess
+
+onSuccess Callback-Funktion, die die Bilddaten bereitstellt.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+#### Beschreibung
+
+  * **CMYK**: Base64-Codierung der Bilddaten, *oder* die Image-Datei-URI, je nach `cameraOptions` in Kraft. *(String)*
+
+#### Beispiel
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Ein Handle für das Dialogfeld "Popover" erstellt von `navigator.camera.getPicture`.
+
+#### Beschreibung
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### Unterstützte Plattformen
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Beispiel
+
+     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
+
+nur iOS-Parametern, die Anker-Element Lage und Pfeil Richtung der Popover angeben, bei der Auswahl von Bildern aus einem iPad Bibliothek oder Album.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+#### Beschreibung
+
+  * **X**: x Pixelkoordinate des Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+  * **y**: y Pixelkoordinate des Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+  * **width**: Breite in Pixeln, das Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+  * **height**: Höhe in Pixeln, das Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+  * **arrowDir**: Richtung der Pfeil auf der Popover zeigen sollte. Im Sinne `Camera.PopoverArrowDirection` *(Anzahl)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Beachten Sie, dass die Größe der Popover ändern kann, um die Richtung des Pfeils und Ausrichtung des Bildschirms anzupassen. Achten Sie darauf, um Orientierung zu berücksichtigen, wenn Sie den Anker-Element-Speicherort angeben.
+
+## navigator.camera.cleanup
+
+Entfernt Mittelstufe Fotos von der Kamera aus der vorübergehenden Verwahrung genommen.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+#### Beschreibung
+
+Fortgeschrittene Image-Dateien, die in vorübergehender Verwahrung gehalten werden, nach dem Aufruf von `camera.getPicture` entfernt. Gilt nur wenn der Wert von `Camera.sourceType` gleich `Camera.PictureSourceType.CAMERA` und `Camera.destinationType` gleich `Camera.DestinationType.FILE_URI`.
+
+#### Unterstützte Plattformen
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Beispiel
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 434 - 0
miaomiao/plugins/cordova-plugin-camera/doc/de/index.md

xqd
@@ -0,0 +1,434 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+Dieses Plugin definiert eine globale `navigator.camera`-Objekt, das eine API für Aufnahmen und für die Auswahl der Bilder aus dem System-Image-Library bietet.
+
+Obwohl das Objekt mit der globalen Gültigkeitsbereich `navigator` verbunden ist, steht es nicht bis nach dem `Deviceready`-Ereignis.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## Installation
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+Nimmt ein Foto mit der Kamera, oder ein Foto aus dem Gerät Bildergalerie abgerufen. Das Bild wird an den Erfolg-Rückruf als base64-codierte `String` oder als URI für die Image-Datei übergeben. Die Methode selbst gibt ein `CameraPopoverHandle`-Objekt, das verwendet werden kann, um die Datei-Auswahl-Popover neu zu positionieren.
+
+    navigator.camera.getPicture( cameraSuccess, cameraError, cameraOptions );
+    
+
+### Beschreibung
+
+Die `camera.getPicture`-Funktion öffnet das Gerät Standard-Kamera-Anwendung, die Benutzern ermöglicht, Bilder ausrichten. Dieses Verhalten tritt in der Standardeinstellung, wenn `Camera.sourceType` `Camera.PictureSourceType.CAMERA` entspricht. Sobald der Benutzer die Fotoschnäpper, die Kameraanwendung geschlossen wird und die Anwendung wird wiederhergestellt.
+
+Wenn `Camera.sourceType` `Camera.PictureSourceType.PHOTOLIBRARY` oder `Camera.PictureSourceType.SAVEDPHOTOALBUM` ist, dann wird ein Dialogfeld angezeigt, das Benutzern ermöglicht, ein vorhandenes Bild auszuwählen. Die `camera.getPicture`-Funktion gibt ein `CameraPopoverHandle`-Objekt, das verwendet werden kann, um die Bild-Auswahl-Dialog, z. B. beim ändert sich der Orientierung des Geräts neu positionieren.
+
+Der Rückgabewert wird an die `cameraSuccess`-Callback-Funktion in einem der folgenden Formate, je nach dem angegebenen `cameraOptions` gesendet:
+
+*   A `String` mit dem base64-codierte Foto-Bild.
+
+*   A `String` , die die Bild-Datei-Stelle auf lokalem Speicher (Standard).
+
+Sie können tun, was Sie wollen, mit dem codierten Bildes oder URI, zum Beispiel:
+
+*   Rendern Sie das Bild in ein `<img>` Tag, wie im folgenden Beispiel
+
+*   Die Daten lokal zu speichern ( `LocalStorage` , [Lawnchair][1], etc..)
+
+*   Post die Daten an einen entfernten server
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**Hinweis**: Fotoauflösung auf neueren Geräten ist ganz gut. Fotos aus dem Gerät Galerie ausgewählt sind nicht zu einer niedrigeren Qualität herunterskaliert, selbst wenn ein `Qualität`-Parameter angegeben wird. Um Speicherprobleme zu vermeiden, legen Sie `Camera.destinationType` auf `FILE_URI` statt `DATA_URL`.
+
+### Unterstützte Plattformen
+
+*   Amazon Fire OS
+*   Android
+*   BlackBerry 10
+*   Browser
+*   Firefox OS
+*   iOS
+*   Tizen
+*   Windows Phone 7 und 8
+*   Windows 8
+
+### "Einstellungen" (iOS)
+
+*   **CameraUsesGeolocation** (Boolean, Standardwert ist False). Zur Erfassung von JPEGs, auf true festgelegt, um Geolocation-Daten im EXIF-Header zu erhalten. Dies löst einen Antrag auf Geolocation-Berechtigungen, wenn auf True festgelegt.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### Amazon Fire OS Macken
+
+Amazon Fire OS verwendet Absichten zum Starten von der Kamera-Aktivität auf dem Gerät, um Bilder zu erfassen und auf Handys mit wenig Speicher, Cordova Tätigkeit getötet werden kann. In diesem Szenario kann das Bild nicht angezeigt, wenn die Aktivität von Cordova wiederhergestellt wird.
+
+### Android Eigenarten
+
+Android verwendet Absichten zum Starten von der Kamera-Aktivität auf dem Gerät, um Bilder zu erfassen und auf Handys mit wenig Speicher, Cordova Tätigkeit getötet werden kann. In diesem Szenario kann das Bild nicht angezeigt, wenn die Aktivität von Cordova wiederhergestellt wird.
+
+### Browser-Eigenheiten
+
+Fotos können nur als base64-codierte Bild zurückgeben werden.
+
+### Firefox OS Macken
+
+Kamera-Plugin ist derzeit implementiert mithilfe von [Web-Aktivitäten][2].
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### iOS Macken
+
+Einschließlich einer JavaScript-`alert()` entweder Rückruffunktionen kann Probleme verursachen. Wickeln Sie die Warnung innerhalb eine `setTimeout()` erlauben die iOS-Bild-Picker oder Popover vollständig zu schließen, bevor die Warnung angezeigt:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+### Windows Phone 7 Macken
+
+Die native Kameraanwendung aufrufen, während das Gerät via Zune angeschlossen ist funktioniert nicht und löst eine Fehler-Callback.
+
+### Tizen Macken
+
+Tizen unterstützt nur ein `DestinationType` von `Camera.DestinationType.FILE_URI` und ein `SourceType` von `Camera.PictureSourceType.PHOTOLIBRARY`.
+
+### Beispiel
+
+Nehmen Sie ein Foto und rufen Sie sie als base64-codierte Bild:
+
+    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);
+    }
+    
+
+Nehmen Sie ein Foto und rufen Sie das Bild-Datei-Speicherort:
+
+    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
+
+Optionale Parameter die Kameraeinstellungen anpassen.
+
+    { 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 };
+    
+
+### Optionen
+
+*   **Qualität**: Qualität des gespeicherten Bildes, ausgedrückt als ein Bereich von 0-100, wo 100 in der Regel voller Auflösung ohne Verlust aus der Dateikomprimierung ist. Der Standardwert ist 50. *(Anzahl)* (Beachten Sie, dass Informationen über die Kamera Auflösung nicht verfügbar ist.)
+
+*   **DestinationType**: Wählen Sie das Format des Rückgabewerts. Der Standardwert ist FILE_URI. Im Sinne `navigator.camera.DestinationType` *(Anzahl)*
+    
+        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**: Legen Sie die Quelle des Bildes. Der Standardwert ist die Kamera. Im Sinne `navigator.camera.PictureSourceType` *(Anzahl)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **AllowEdit**: einfache Bearbeitung des Bildes vor Auswahl zu ermöglichen. *(Boolesch)*
+
+*   **EncodingType**: die zurückgegebene Image-Datei ist Codierung auswählen. Standardwert ist JPEG. Im Sinne `navigator.camera.EncodingType` *(Anzahl)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **TargetWidth**: Breite in Pixel zum Bild skalieren. Muss mit **TargetHeight**verwendet werden. Seitenverhältnis bleibt konstant. *(Anzahl)*
+
+*   **TargetHeight**: Höhe in Pixel zum Bild skalieren. Muss mit **TargetWidth**verwendet werden. Seitenverhältnis bleibt konstant. *(Anzahl)*
+
+*   **MediaType**: Legen Sie den Typ der Medien zur Auswahl. Funktioniert nur, wenn `PictureSourceType` ist `PHOTOLIBRARY` oder `SAVEDPHOTOALBUM` . Im Sinne `nagivator.camera.MediaType` *(Anzahl)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. STANDARD. 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**: Drehen Sie das Bild um die Ausrichtung des Geräts während der Aufnahme zu korrigieren. *(Boolesch)*
+
+*   **SaveToPhotoAlbum**: das Bild auf das Fotoalbum auf dem Gerät zu speichern, nach Einnahme. *(Boolesch)*
+
+*   **PopoverOptions**: iOS-nur Optionen, die Popover Lage in iPad angeben. In definierten`CameraPopoverOptions`.
+
+*   **CameraDirection**: Wählen Sie die Kamera (vorn oder hinten-gerichtete) verwenden. Der Standardwert ist zurück. Im Sinne `navigator.camera.Direction` *(Anzahl)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### Amazon Fire OS Macken
+
+*   `cameraDirection`Ergebnisse in einem hinten gerichteter Foto Wert.
+
+*   Ignoriert die `allowEdit` Parameter.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`und `Camera.PictureSourceType.SAVEDPHOTOALBUM` beide das gleiche Fotoalbum anzuzeigen.
+
+### Android Eigenarten
+
+*   `cameraDirection`Ergebnisse in einem hinten gerichteter Foto Wert.
+
+*   Ignoriert die `allowEdit` Parameter.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`und `Camera.PictureSourceType.SAVEDPHOTOALBUM` beide das gleiche Fotoalbum anzuzeigen.
+
+### BlackBerry 10 Macken
+
+*   Ignoriert die `quality` Parameter.
+
+*   Ignoriert die `allowEdit` Parameter.
+
+*   `Camera.MediaType`wird nicht unterstützt.
+
+*   Ignoriert die `correctOrientation` Parameter.
+
+*   Ignoriert die `cameraDirection` Parameter.
+
+### Firefox OS Macken
+
+*   Ignoriert die `quality` Parameter.
+
+*   `Camera.DestinationType`wird ignoriert, und gleich `1` (Bilddatei-URI)
+
+*   Ignoriert die `allowEdit` Parameter.
+
+*   Ignoriert die `PictureSourceType` Parameter (Benutzer wählt es in einem Dialogfenster)
+
+*   Ignoriert die`encodingType`
+
+*   Ignoriert die `targetWidth` und`targetHeight`
+
+*   `Camera.MediaType`wird nicht unterstützt.
+
+*   Ignoriert die `correctOrientation` Parameter.
+
+*   Ignoriert die `cameraDirection` Parameter.
+
+### iOS Macken
+
+*   Legen Sie `quality` unter 50 Speicherfehler auf einigen Geräten zu vermeiden.
+
+*   Bei der Verwendung `destinationType.FILE_URI` , Fotos werden im temporären Verzeichnis der Anwendung gespeichert. Den Inhalt des temporären Verzeichnis der Anwendung wird gelöscht, wenn die Anwendung beendet.
+
+### Tizen Macken
+
+*   nicht unterstützte Optionen
+
+*   gibt immer einen Datei-URI
+
+### Windows Phone 7 und 8 Eigenarten
+
+*   Ignoriert die `allowEdit` Parameter.
+
+*   Ignoriert die `correctOrientation` Parameter.
+
+*   Ignoriert die `cameraDirection` Parameter.
+
+*   Ignoriert die `saveToPhotoAlbum` Parameter. WICHTIG: Alle Aufnahmen die wp7/8 Cordova-Kamera-API werden immer in Kamerarolle des Telefons kopiert. Abhängig von den Einstellungen des Benutzers könnte dies auch bedeuten, dass das Bild in ihre OneDrive automatisch hochgeladen ist. Dies könnte möglicherweise bedeuten, dass das Bild für ein breiteres Publikum als Ihre Anwendung vorgesehen ist. Wenn diese einen Blocker für Ihre Anwendung, Sie müssen die CameraCaptureTask zu implementieren, wie im Msdn dokumentiert: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> Sie können kommentieren oder Up-Abstimmung das Beiträge zu diesem Thema im [Bugtracker][3]
+
+*   Ignoriert die `mediaType` -Eigenschaft des `cameraOptions` wie das Windows Phone SDK keine Möglichkeit, Fotothek Videos wählen.
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+onError-Callback-Funktion, die eine Fehlermeldung bereitstellt.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+### Parameter
+
+*   **Meldung**: die Nachricht wird durch das Gerät systemeigenen Code bereitgestellt. *(String)*
+
+## cameraSuccess
+
+onSuccess Callback-Funktion, die die Bilddaten bereitstellt.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+### Parameter
+
+*   **CMYK**: Base64-Codierung der Bilddaten, *oder* die Image-Datei-URI, je nach `cameraOptions` in Kraft. *(String)*
+
+### Beispiel
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Ein Handle für das Dialogfeld "Popover" erstellt von `navigator.camera.getPicture`.
+
+### Methoden
+
+*   **SetPosition**: Legen Sie die Position der Popover.
+
+### Unterstützte Plattformen
+
+*   iOS
+
+### setPosition
+
+Legen Sie die Position von der Popover.
+
+**Parameter**:
+
+*   `cameraPopoverOptions`: die `CameraPopoverOptions` angeben, dass die neue Position
+
+### Beispiel
+
+     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
+
+nur iOS-Parametern, die Anker-Element Lage und Pfeil Richtung der Popover angeben, bei der Auswahl von Bildern aus einem iPad Bibliothek oder Album.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+### CameraPopoverOptions
+
+*   **X**: x Pixelkoordinate des Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+*   **y**: y Pixelkoordinate des Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+*   **width**: Breite in Pixeln, das Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+*   **height**: Höhe in Pixeln, das Bildschirmelement auf dem der Popover zu verankern. *(Anzahl)*
+
+*   **arrowDir**: Richtung der Pfeil auf der Popover zeigen sollte. Im Sinne `Camera.PopoverArrowDirection` *(Anzahl)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Beachten Sie, dass die Größe der Popover ändern kann, um die Richtung des Pfeils und Ausrichtung des Bildschirms anzupassen. Achten Sie darauf, um Orientierung zu berücksichtigen, wenn Sie den Anker-Element-Speicherort angeben.
+
+## navigator.camera.cleanup
+
+Entfernt Mittelstufe Fotos von der Kamera aus der vorübergehenden Verwahrung genommen.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+### Beschreibung
+
+Fortgeschrittene Image-Dateien, die in vorübergehender Verwahrung gehalten werden, nach dem Aufruf von `camera.getPicture` entfernt. Gilt nur wenn der Wert von `Camera.sourceType` gleich `Camera.PictureSourceType.CAMERA` und `Camera.destinationType` gleich `Camera.DestinationType.FILE_URI`.
+
+### Unterstützte Plattformen
+
+*   iOS
+
+### Beispiel
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 411 - 0
miaomiao/plugins/cordova-plugin-camera/doc/es/README.md

xqd
@@ -0,0 +1,411 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+Este plugin define un global `navigator.camera` objeto que proporciona una API para tomar fotografías y por elegir imágenes de biblioteca de imágenes del sistema.
+
+Aunque el objeto está unido al ámbito global `navigator` , no estará disponible hasta después de la `deviceready` evento.
+
+    document.addEventListener ("deviceready", onDeviceReady, false);
+    function onDeviceReady() {console.log(navigator.camera)};
+    
+
+## Instalación
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * Cámara 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * Navigator.Camera.Cleanup
+
+## navigator.camera.getPicture
+
+Toma una foto con la cámara, o recupera una foto de Galería de imágenes del dispositivo. La imagen se pasa a la devolución de llamada de éxito como un codificado en base64 `String` , o como el URI para el archivo de imagen. El método se devuelve un `CameraPopoverHandle` objeto que puede utilizarse para volver a colocar el popover de selección de archivo.
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### Descripción
+
+El `camera.getPicture` función abre la aplicación de cámara predeterminada del dispositivo que permite a los usuarios ajustar imágenes. Este comportamiento se produce de forma predeterminada, cuando `Camera.sourceType` es igual a `Camera.PictureSourceType.CAMERA` . Una vez que el usuario ajusta la foto, una aplicación de cámara se cierra y se restablecerá la aplicación.
+
+Si `Camera.sourceType` es `Camera.PictureSourceType.PHOTOLIBRARY` o `Camera.PictureSourceType.SAVEDPHOTOALBUM` , entonces una muestra de diálogo que permite a los usuarios seleccionar una imagen existente. El `camera.getPicture` función devuelve un `CameraPopoverHandle` objeto, que puede utilizarse para volver a colocar el diálogo de selección de imagen, por ejemplo, cuando cambia la orientación del dispositivo.
+
+El valor devuelto es enviado a la `cameraSuccess` función de callback, en uno de los formatos siguientes, dependiendo del objeto `cameraOptions` :
+
+  * Una `String` que contiene la imagen codificada en base64.
+
+  * Una `String` que representa la ubicación del archivo de imagen en almacenamiento local (por defecto).
+
+Puedes hacer lo que quieras con la imagen codificada o URI, por ejemplo:
+
+  * Representar la imagen en una etiqueta de `<img>`, como en el ejemplo siguiente
+
+  * Guardar los datos localmente (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+
+  * Enviar los datos a un servidor remoto
+
+**Nota**: resolución de la foto en los nuevos dispositivos es bastante bueno. Fotos seleccionadas de la Galería del dispositivo no son degradadas a una calidad más baja, incluso si un `quality` se especifica el parámetro. Para evitar problemas con la memoria común, establezca `Camera.destinationType` a `FILE_URI` en lugar de`DATA_URL`.
+
+#### Plataformas soportadas
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### Ejemplo
+
+Tomar una foto y recuperarlo como una imagen codificada en base64:
+
+    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);
+    }
+    
+
+Tomar una foto y recuperar la ubicación del archivo de la imagen:
+
+    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);
+    }
+    
+
+#### Preferencias (iOS)
+
+  * **CameraUsesGeolocation** (booleano, el valor predeterminado de false). Para la captura de imágenes JPEG, establecido en true para obtener datos de geolocalización en la cabecera EXIF. Esto activará la solicitud de permisos de geolocalización si establecido en true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### Amazon fuego OS rarezas
+
+Amazon fuego OS utiliza los intentos para poner en marcha la actividad de la cámara del dispositivo para capturar imágenes y en teléfonos con poca memoria, puede matar la actividad Cordova. En este escenario, la imagen no aparezca cuando se restaura la actividad cordova.
+
+#### Rarezas Android
+
+Android utiliza los intentos para iniciar la actividad de la cámara del dispositivo para capturar imágenes, y en los teléfonos con poca memoria, puede matar la actividad Cordova. En este escenario, la imagen no aparezca cuando se restaura la actividad Cordova.
+
+#### Navegador rarezas
+
+Sólo puede devolver fotos como imagen codificada en base64.
+
+#### Firefox OS rarezas
+
+Cámara plugin actualmente se implementa mediante [Actividades Web](https://hacks.mozilla.org/2013/01/introducing-web-activities/).
+
+#### iOS rarezas
+
+Incluyendo un JavaScript `alert()` en cualquiera de la devolución de llamada funciones pueden causar problemas. Envuelva la alerta dentro de un `setTimeout()` para permitir que el selector de imagen iOS o popover cerrar completamente antes de la alerta se muestra:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+#### Windows Phone 7 rarezas
+
+Invocando la aplicación de cámara nativa mientras el dispositivo está conectado vía Zune no funciona y desencadena un callback de error.
+
+#### Rarezas Tizen
+
+Tizen sólo es compatible con un `destinationType` de `Camera.DestinationType.FILE_URI` y un `sourceType` de`Camera.PictureSourceType.PHOTOLIBRARY`.
+
+## CameraOptions
+
+Parámetros opcionales para personalizar la configuración de la cámara.
+
+    {calidad: destinationType 75,: Camera.DestinationType.DATA_URL, sourceType: Camera.PictureSourceType.CAMERA, allowEdit: true, encodingType: Camera.EncodingType.JPEG, targetWidth: 100, targetHeight: 100, popoverOptions: CameraPopoverOptions, saveToPhotoAlbum: falsa};
+    
+
+  * **calidad**: calidad de la imagen guardada, expresada en un rango de 0-100, donde 100 es típicamente resolución sin pérdida de compresión del archivo. El valor predeterminado es 50. *(Número)* (Tenga en cuenta que no está disponible información sobre resolución de la cámara).
+
+  * **destinationType**: elegir el formato del valor devuelto. El valor predeterminado es FILE_URI. Definido en `navigator.camera.DestinationType` *(número)*
+    
+        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**: establecer el origen de la imagen. El valor predeterminado es cámara. Definido en `navigator.camera.PictureSourceType` *(número)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **allowEdit**: permite edición sencilla de imagen antes de la selección. *(Booleano)*
+
+  * **encodingType**: elegir la codificación del archivo de imagen devuelta. Por defecto es JPEG. Definido en `navigator.camera.EncodingType` *(número)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **targetWidth**: ancho en píxeles a escala de la imagen. Debe usarse con **targetHeight**. Proporción se mantiene constante. *(Número)*
+
+  * **targetHeight**: altura en píxeles a escala de la imagen. Debe usarse con **targetWidth**. Proporción se mantiene constante. *(Número)*
+
+  * **mediaType**: definir el tipo de medios para seleccionar. Sólo funciona cuando `PictureSourceType` es `PHOTOLIBRARY` o `SAVEDPHOTOALBUM` . Definido en `nagivator.camera.MediaType` *(número)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. DE FORMA PREDETERMINADA. 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**: rotar la imagen para corregir la orientación del dispositivo durante la captura. *(Booleano)*
+
+  * **saveToPhotoAlbum**: guardar la imagen en el álbum de fotos en el dispositivo después de su captura. *(Booleano)*
+
+  * **popoverOptions**: opciones sólo iOS que especifican popover ubicación en iPad. Definido en`CameraPopoverOptions`.
+
+  * **cameraDirection**: elegir la cámara para usar (o parte posterior-frontal). El valor predeterminado es atrás. Definido en `navigator.camera.Direction` *(número)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### Amazon fuego OS rarezas
+
+  * Cualquier valor de `cameraDirection` da como resultado una foto orientada hacia atrás.
+
+  * Ignora el `allowEdit` parámetro.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY` y `Camera.PictureSourceType.SAVEDPHOTOALBUM` Mostrar el mismo álbum de fotos.
+
+#### Rarezas Android
+
+  * Cualquier valor de `cameraDirection` da como resultado una foto orientada hacia atrás.
+
+  * Android también utiliza la actividad de cultivo de allowEdit, aunque cultivo debe trabajar y realmente pasar la imagen recortada a Córdoba, el único que funciona constantemente es el integrado con la aplicación de Google Plus fotos. Otros cultivos pueden no funcionar.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY` y `Camera.PictureSourceType.SAVEDPHOTOALBUM` Mostrar el mismo álbum de fotos.
+
+#### BlackBerry 10 rarezas
+
+  * Ignora el `quality` parámetro.
+
+  * Ignora el `allowEdit` parámetro.
+
+  * `Camera.MediaType`No se admite.
+
+  * Ignora el `correctOrientation` parámetro.
+
+  * Ignora el `cameraDirection` parámetro.
+
+#### Firefox OS rarezas
+
+  * Ignora el `quality` parámetro.
+
+  * `Camera.DestinationType`se ignora y es igual a `1` (URI del archivo de imagen)
+
+  * Ignora el `allowEdit` parámetro.
+
+  * Ignora el `PictureSourceType` parámetro (el usuario lo elige en una ventana de diálogo)
+
+  * Ignora el`encodingType`
+
+  * Ignora el `targetWidth` y`targetHeight`
+
+  * `Camera.MediaType`No se admite.
+
+  * Ignora el `correctOrientation` parámetro.
+
+  * Ignora el `cameraDirection` parámetro.
+
+#### iOS rarezas
+
+  * Establecer `quality` por debajo de 50 para evitar errores de memoria en algunos dispositivos.
+
+  * Cuando se utiliza `destinationType.FILE_URI` , fotos se guardan en el directorio temporal de la aplicación. El contenido del directorio temporal de la aplicación se eliminará cuando finalice la aplicación.
+
+#### Rarezas Tizen
+
+  * opciones no compatibles
+
+  * siempre devuelve un identificador URI de archivo
+
+#### Windows Phone 7 y 8 rarezas
+
+  * Ignora el `allowEdit` parámetro.
+
+  * Ignora el `correctOrientation` parámetro.
+
+  * Ignora el `cameraDirection` parámetro.
+
+  * Ignora el `saveToPhotoAlbum` parámetro. IMPORTANTE: Todas las imágenes tomadas con la cámara wp7/8 cordova API siempre se copian en rollo de cámara del teléfono. Dependiendo de la configuración del usuario, esto podría significar también que la imagen es auto-subido a su OneDrive. Esto potencialmente podría significar que la imagen está disponible a una audiencia más amplia que su aplicación previsto. Si un bloqueador para su aplicación, usted necesitará aplicar el CameraCaptureTask como se documenta en msdn: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> también puede comentar o votar hasta el tema relacionado en el [issue tracker de](https://issues.apache.org/jira/browse/CB-2083)
+
+  * Ignora el `mediaType` propiedad de `cameraOptions` como el SDK de Windows Phone no proporciona una manera para elegir vídeos fototeca.
+
+## CameraError
+
+onError función callback que proporciona un mensaje de error.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+#### Descripción
+
+  * **mensaje**: el mensaje es proporcionado por código nativo del dispositivo. *(String)*
+
+## cameraSuccess
+
+onSuccess función callback que proporciona los datos de imagen.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+#### Descripción
+
+  * **imageData**: codificación en Base64 de los datos de imagen, *o* el archivo de imagen URI, dependiendo de `cameraOptions` en vigor. *(String)*
+
+#### Ejemplo
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Un identificador para el cuadro de diálogo popover creado por`navigator.camera.getPicture`.
+
+#### Descripción
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### Plataformas soportadas
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Ejemplo
+
+     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
+
+Sólo iOS parámetros que especifican la dirección ancla elemento ubicación y la flecha de la popover al seleccionar imágenes de biblioteca o álbum de un iPad.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+#### Descripción
+
+  * **x**: coordenadas de píxeles del elemento de la pantalla en la que anclar el popover x. *(Número)*
+
+  * **y**: coordenada píxeles del elemento de la pantalla en la que anclar el popover. *(Número)*
+
+  * **anchura**: anchura, en píxeles, del elemento sobre el que anclar el popover pantalla. *(Número)*
+
+  * **altura**: alto, en píxeles, del elemento sobre el que anclar el popover pantalla. *(Número)*
+
+  * **arrowDir**: dirección de la flecha en el popover debe apuntar. Definido en `Camera.PopoverArrowDirection` *(número)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Tenga en cuenta que puede cambiar el tamaño de la popover para ajustar la dirección de la flecha y orientación de la pantalla. Asegúrese de que para tener en cuenta los cambios de orientación cuando se especifica la ubicación del elemento de anclaje.
+
+## Navigator.Camera.Cleanup
+
+Elimina intermedio fotos tomadas por la cámara de almacenamiento temporal.
+
+    Navigator.Camera.cleanup (cameraSuccess, cameraError);
+    
+
+#### Descripción
+
+Elimina intermedio archivos de imagen que se mantienen en depósito temporal después de llamar `camera.getPicture` . Se aplica sólo cuando el valor de `Camera.sourceType` es igual a `Camera.PictureSourceType.CAMERA` y el `Camera.destinationType` es igual a`Camera.DestinationType.FILE_URI`.
+
+#### Plataformas soportadas
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Ejemplo
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 391 - 0
miaomiao/plugins/cordova-plugin-camera/doc/es/index.md

xqd
@@ -0,0 +1,391 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+Este plugin define un global `navigator.camera` objeto que proporciona una API para tomar fotografías y por elegir imágenes de biblioteca de imágenes del sistema.
+
+Aunque el objeto está unido al ámbito global `navigator` , no estará disponible hasta después de la `deviceready` evento.
+
+    document.addEventListener ("deviceready", onDeviceReady, false);
+    function onDeviceReady() {console.log(navigator.camera)};
+    
+
+## Instalación
+
+    Cordova plugin agregar cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+Toma una foto con la cámara, o recupera una foto de Galería de imágenes del dispositivo. La imagen se pasa a la devolución de llamada de éxito como un codificado en base64 `String` , o como el URI para el archivo de imagen. El método se devuelve un `CameraPopoverHandle` objeto que puede utilizarse para volver a colocar el popover de selección de archivo.
+
+    navigator.camera.getPicture (cameraSuccess, cameraError, cameraOptions);
+    
+
+### Descripción
+
+El `camera.getPicture` función abre la aplicación de cámara predeterminada del dispositivo que permite a los usuarios ajustar imágenes. Este comportamiento se produce de forma predeterminada, cuando `Camera.sourceType` es igual a `Camera.PictureSourceType.CAMERA` . Una vez que el usuario ajusta la foto, una aplicación de cámara se cierra y se restablecerá la aplicación.
+
+Si `Camera.sourceType` es `Camera.PictureSourceType.PHOTOLIBRARY` o `Camera.PictureSourceType.SAVEDPHOTOALBUM` , entonces una muestra de diálogo que permite a los usuarios seleccionar una imagen existente. El `camera.getPicture` función devuelve un `CameraPopoverHandle` objeto, que puede utilizarse para volver a colocar el diálogo de selección de imagen, por ejemplo, cuando cambia la orientación del dispositivo.
+
+El valor devuelto es enviado a la `cameraSuccess` función de callback, en uno de los formatos siguientes, dependiendo del objeto `cameraOptions` :
+
+*   Una `String` que contiene la imagen codificada en base64.
+
+*   Una `String` que representa la ubicación del archivo de imagen en almacenamiento local (por defecto).
+
+Puedes hacer lo que quieras con la imagen codificada o URI, por ejemplo:
+
+*   Representar la imagen en una etiqueta de `<img>`, como en el ejemplo siguiente
+
+*   Guardar los datos localmente (`LocalStorage`, [Lawnchair][1], etc.)
+
+*   Enviar los datos a un servidor remoto
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**Nota**: resolución de la foto en los nuevos dispositivos es bastante bueno. Fotos seleccionadas de la Galería del dispositivo no son degradadas a una calidad más baja, incluso si un `quality` se especifica el parámetro. Para evitar problemas con la memoria común, establezca `Camera.destinationType` a `FILE_URI` en lugar de`DATA_URL`.
+
+### Plataformas soportadas
+
+*   Amazon fire OS
+*   Android
+*   BlackBerry 10
+*   Explorador
+*   Firefox OS
+*   iOS
+*   Tizen
+*   Windows Phone 7 y 8
+*   Windows 8
+
+### Preferencias (iOS)
+
+*   **CameraUsesGeolocation** (booleano, el valor predeterminado de false). Para la captura de imágenes JPEG, establecido en true para obtener datos de geolocalización en la cabecera EXIF. Esto activará la solicitud de permisos de geolocalización si establecido en true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### Amazon fuego OS rarezas
+
+Amazon fuego OS utiliza los intentos para poner en marcha la actividad de la cámara del dispositivo para capturar imágenes y en teléfonos con poca memoria, puede matar la actividad Cordova. En este escenario, la imagen no aparezca cuando se restaura la actividad cordova.
+
+### Rarezas Android
+
+Android utiliza los intentos para iniciar la actividad de la cámara del dispositivo para capturar imágenes, y en los teléfonos con poca memoria, puede matar la actividad Cordova. En este escenario, la imagen no aparezca cuando se restaura la actividad Cordova.
+
+### Navegador rarezas
+
+Sólo puede devolver fotos como imagen codificada en base64.
+
+### Firefox OS rarezas
+
+Cámara plugin actualmente se implementa mediante [Actividades Web][2].
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### iOS rarezas
+
+Incluyendo un JavaScript `alert()` en cualquiera de la devolución de llamada funciones pueden causar problemas. Envuelva la alerta dentro de un `setTimeout()` para permitir que el selector de imagen iOS o popover cerrar completamente antes de la alerta se muestra:
+
+    setTimeout(function() {/ / Haz lo tuyo aquí!}, 0);
+    
+
+### Windows Phone 7 rarezas
+
+Invocando la aplicación de cámara nativa mientras el dispositivo está conectado vía Zune no funciona y desencadena un callback de error.
+
+### Rarezas Tizen
+
+Tizen sólo es compatible con un `destinationType` de `Camera.DestinationType.FILE_URI` y un `sourceType` de`Camera.PictureSourceType.PHOTOLIBRARY`.
+
+### Ejemplo
+
+Tomar una foto y recuperarlo como una imagen codificada en base64:
+
+    navigator.camera.getPicture (onSuccess, onFail, { quality: 50,
+        destinationType: Camera.DestinationType.DATA_URL
+    });
+    
+    function onSuccess(imageData) {var imagen = document.getElementById('myImage');
+        Image.src = "datos: image / jpeg; base64," + imageData;}
+    
+    function onFail(message) {alert (' falló porque: ' + mensaje);}
+    
+
+Tomar una foto y recuperar la ubicación del archivo de la imagen:
+
+    navigator.camera.getPicture (onSuccess, onFail, { quality: 50,
+        destinationType: Camera.DestinationType.FILE_URI });
+    
+    function onSuccess(imageURI) {var imagen = document.getElementById('myImage');
+        Image.src = imageURI;
+    } function onFail(message) {alert (' falló porque: ' + mensaje);}
+    
+
+## CameraOptions
+
+Parámetros opcionales para personalizar la configuración de la cámara.
+
+    {calidad: destinationType 75,: Camera.DestinationType.DATA_URL, sourceType: Camera.PictureSourceType.CAMERA, allowEdit: true, encodingType: Camera.EncodingType.JPEG, targetWidth: 100, targetHeight: 100, popoverOptions: CameraPopoverOptions, saveToPhotoAlbum: falsa};
+    
+
+### Opciones
+
+*   **calidad**: calidad de la imagen guardada, expresada en un rango de 0-100, donde 100 es típicamente resolución sin pérdida de compresión del archivo. El valor predeterminado es 50. *(Número)* (Tenga en cuenta que no está disponible información sobre resolución de la cámara).
+
+*   **destinationType**: elegir el formato del valor devuelto. El valor predeterminado es FILE_URI. Definido en `navigator.camera.DestinationType` *(número)*
+    
+        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**: establecer el origen de la imagen. El valor predeterminado es cámara. Definido en `navigator.camera.PictureSourceType` *(número)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **allowEdit**: permite edición sencilla de imagen antes de la selección. *(Booleano)*
+
+*   **encodingType**: elegir la codificación del archivo de imagen devuelta. Por defecto es JPEG. Definido en `navigator.camera.EncodingType` *(número)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **targetWidth**: ancho en píxeles a escala de la imagen. Debe usarse con **targetHeight**. Proporción se mantiene constante. *(Número)*
+
+*   **targetHeight**: altura en píxeles a escala de la imagen. Debe usarse con **targetWidth**. Proporción se mantiene constante. *(Número)*
+
+*   **mediaType**: definir el tipo de medios para seleccionar. Sólo funciona cuando `PictureSourceType` es `PHOTOLIBRARY` o `SAVEDPHOTOALBUM` . Definido en `nagivator.camera.MediaType` *(número)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. DE FORMA PREDETERMINADA. 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**: rotar la imagen para corregir la orientación del dispositivo durante la captura. *(Booleano)*
+
+*   **saveToPhotoAlbum**: guardar la imagen en el álbum de fotos en el dispositivo después de su captura. *(Booleano)*
+
+*   **popoverOptions**: opciones sólo iOS que especifican popover ubicación en iPad. Definido en`CameraPopoverOptions`.
+
+*   **cameraDirection**: elegir la cámara para usar (o parte posterior-frontal). El valor predeterminado es atrás. Definido en `navigator.camera.Direction` *(número)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### Amazon fuego OS rarezas
+
+*   Cualquier valor de `cameraDirection` da como resultado una foto orientada hacia atrás.
+
+*   Ignora el `allowEdit` parámetro.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY` y `Camera.PictureSourceType.SAVEDPHOTOALBUM` Mostrar el mismo álbum de fotos.
+
+### Rarezas Android
+
+*   Cualquier valor de `cameraDirection` da como resultado una foto orientada hacia atrás.
+
+*   Ignora el `allowEdit` parámetro.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY` y `Camera.PictureSourceType.SAVEDPHOTOALBUM` Mostrar el mismo álbum de fotos.
+
+### BlackBerry 10 rarezas
+
+*   Ignora el `quality` parámetro.
+
+*   Ignora el `allowEdit` parámetro.
+
+*   `Camera.MediaType`No se admite.
+
+*   Ignora el `correctOrientation` parámetro.
+
+*   Ignora el `cameraDirection` parámetro.
+
+### Firefox OS rarezas
+
+*   Ignora el `quality` parámetro.
+
+*   `Camera.DestinationType`se ignora y es igual a `1` (URI del archivo de imagen)
+
+*   Ignora el `allowEdit` parámetro.
+
+*   Ignora el `PictureSourceType` parámetro (el usuario lo elige en una ventana de diálogo)
+
+*   Ignora el`encodingType`
+
+*   Ignora el `targetWidth` y`targetHeight`
+
+*   `Camera.MediaType`No se admite.
+
+*   Ignora el `correctOrientation` parámetro.
+
+*   Ignora el `cameraDirection` parámetro.
+
+### iOS rarezas
+
+*   Establecer `quality` por debajo de 50 para evitar errores de memoria en algunos dispositivos.
+
+*   Cuando se utiliza `destinationType.FILE_URI` , fotos se guardan en el directorio temporal de la aplicación. El contenido del directorio temporal de la aplicación se eliminará cuando finalice la aplicación.
+
+### Rarezas Tizen
+
+*   opciones no compatibles
+
+*   siempre devuelve un identificador URI de archivo
+
+### Windows Phone 7 y 8 rarezas
+
+*   Ignora el `allowEdit` parámetro.
+
+*   Ignora el `correctOrientation` parámetro.
+
+*   Ignora el `cameraDirection` parámetro.
+
+*   Ignora el `saveToPhotoAlbum` parámetro. IMPORTANTE: Todas las imágenes tomadas con la cámara wp7/8 cordova API siempre se copian en rollo de cámara del teléfono. Dependiendo de la configuración del usuario, esto podría significar también que la imagen es auto-subido a su OneDrive. Esto potencialmente podría significar que la imagen está disponible a una audiencia más amplia que su aplicación previsto. Si un bloqueador para su aplicación, usted necesitará aplicar el CameraCaptureTask como se documenta en msdn: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> también puede comentar o votar hasta el tema relacionado en el [issue tracker de][3]
+
+*   Ignora el `mediaType` propiedad de `cameraOptions` como el SDK de Windows Phone no proporciona una manera para elegir vídeos fototeca.
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+onError función callback que proporciona un mensaje de error.
+
+    function(Message) {/ / Mostrar un mensaje útil}
+    
+
+### Parámetros
+
+*   **mensaje**: el mensaje es proporcionado por código nativo del dispositivo. *(String)*
+
+## cameraSuccess
+
+onSuccess función callback que proporciona los datos de imagen.
+
+    function(ImageData) {/ / hacer algo con la imagen}
+    
+
+### Parámetros
+
+*   **imageData**: codificación en Base64 de los datos de imagen, *o* el archivo de imagen URI, dependiendo de `cameraOptions` en vigor. *(String)*
+
+### Ejemplo
+
+    Mostrar imagen / / function cameraCallback(imageData) {var imagen = document.getElementById('myImage');
+        Image.src = "datos: image / jpeg; base64," + imageData;}
+    
+
+## CameraPopoverHandle
+
+Un identificador para el cuadro de diálogo popover creado por`navigator.camera.getPicture`.
+
+### Métodos
+
+*   **setPosition**: establecer la posición de la popover.
+
+### Plataformas soportadas
+
+*   iOS
+
+### setPosition
+
+Establecer la posición de la popover.
+
+**Parámetros**:
+
+*   `cameraPopoverOptions`: el `CameraPopoverOptions` que especifican la nueva posición
+
+### Ejemplo
+
+     var cameraPopoverHandle = navigator.camera.getPicture (onSuccess, onFail, {destinationType: Camera.DestinationType.FILE_URI, sourceType: Camera.PictureSourceType.PHOTOLIBRARY, popoverOptions: CameraPopoverOptions nuevo (300, 300, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY)});
+    
+     Vuelva a colocar el popover si cambia la orientación.
+     Window.onorientationchange = function() {var cameraPopoverOptions = new CameraPopoverOptions (0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY);
+         cameraPopoverHandle.setPosition(cameraPopoverOptions);
+     }
+    
+
+## CameraPopoverOptions
+
+Sólo iOS parámetros que especifican la dirección ancla elemento ubicación y la flecha de la popover al seleccionar imágenes de biblioteca o álbum de un iPad.
+
+    {x: 0, y: 32, ancho: 320, altura: 480, arrowDir: Camera.PopoverArrowDirection.ARROW_ANY};
+    
+
+### CameraPopoverOptions
+
+*   **x**: coordenadas de píxeles del elemento de la pantalla en la que anclar el popover x. *(Número)*
+
+*   **y**: coordenada píxeles del elemento de la pantalla en la que anclar el popover. *(Número)*
+
+*   **anchura**: anchura, en píxeles, del elemento sobre el que anclar el popover pantalla. *(Número)*
+
+*   **altura**: alto, en píxeles, del elemento sobre el que anclar el popover pantalla. *(Número)*
+
+*   **arrowDir**: dirección de la flecha en el popover debe apuntar. Definido en `Camera.PopoverArrowDirection` *(número)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Tenga en cuenta que puede cambiar el tamaño de la popover para ajustar la dirección de la flecha y orientación de la pantalla. Asegúrese de que para tener en cuenta los cambios de orientación cuando se especifica la ubicación del elemento de anclaje.
+
+## Navigator.Camera.Cleanup
+
+Elimina intermedio fotos tomadas por la cámara de almacenamiento temporal.
+
+    Navigator.Camera.cleanup (cameraSuccess, cameraError);
+    
+
+### Descripción
+
+Elimina intermedio archivos de imagen que se mantienen en depósito temporal después de llamar `camera.getPicture` . Se aplica sólo cuando el valor de `Camera.sourceType` es igual a `Camera.PictureSourceType.CAMERA` y el `Camera.destinationType` es igual a`Camera.DestinationType.FILE_URI`.
+
+### Plataformas soportadas
+
+*   iOS
+
+### Ejemplo
+
+    Navigator.Camera.cleanup (onSuccess, onFail);
+    
+    function onSuccess() {console.log ("cámara limpieza éxito.")}
+    
+    function onFail(message) {alert (' falló porque: ' + mensaje);}

+ 378 - 0
miaomiao/plugins/cordova-plugin-camera/doc/fr/README.md

xqd
@@ -0,0 +1,378 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+Ce plugin définit un global `navigator.camera` objet qui fournit une API pour la prise de photos et de choisir des images de la bibliothèque d'images du système.
+
+Bien que l'objet est attaché à la portée globale `navigator` , il n'est pas disponible jusqu'après la `deviceready` événement.
+
+    document.addEventListener (« deviceready », onDeviceReady, false) ;
+    function onDeviceReady() {console.log(navigator.camera);}
+    
+
+## Installation
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * Appareil photo 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * Navigator.Camera.Cleanup
+
+## navigator.camera.getPicture
+
+Prend une photo à l'aide de la caméra, ou récupère une photo de la Galerie d'images de l'appareil. L'image est passé au rappel succès comme un codage base64 `String` , ou comme l'URI du fichier de l'image. La méthode elle-même retourne un `CameraPopoverHandle` objet qui permet de repositionner le kangourou de sélection de fichier.
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### Description
+
+Le `camera.getPicture` fonction ouvre l'application de caméra par défaut de l'appareil qui permet aux utilisateurs de prendre des photos. Ce comportement se produit par défaut, lorsque `Camera.sourceType` est égal à `Camera.PictureSourceType.CAMERA` . Une fois que l'utilisateur s'enclenche la photo, l'application appareil photo se ferme et l'application est restaurée.
+
+Si `Camera.sourceType` est `Camera.PictureSourceType.PHOTOLIBRARY` ou `Camera.PictureSourceType.SAVEDPHOTOALBUM` , puis un dialogue affiche qui permet aux utilisateurs de sélectionner une image existante. Le `camera.getPicture` retourne un `CameraPopoverHandle` objet, ce qui permet de repositionner le dialogue de sélection d'image, par exemple, lorsque l'orientation de l'appareil change.
+
+La valeur de retour est envoyée à la `cameraSuccess` la fonction de rappel, dans l'un des formats suivants, selon les `cameraOptions` :
+
+  * A `String` contenant l'image photo codée en base64.
+
+  * A `String` qui représente l'emplacement du fichier image sur le stockage local (par défaut).
+
+Vous pouvez faire ce que vous voulez avec l'image codée ou URI, par exemple :
+
+  * Afficher l'image dans un `<img>` tag, comme dans l'exemple ci-dessous
+
+  * Enregistrer les données localement ( `LocalStorage` , [poids](http://brianleroux.github.com/lawnchair/), etc..)
+
+  * Publier les données sur un serveur distant
+
+**NOTE**: la résolution de Photo sur les nouveaux appareils est assez bonne. Photos sélectionnées de la Galerie de l'appareil ne sont pas réduites à une baisse de la qualité, même si un `quality` paramètre est spécifié. Pour éviter les problèmes de mémoire commun, définissez `Camera.destinationType` à `FILE_URI` au lieu de`DATA_URL`.
+
+#### Plates-formes supportées
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### Exemple
+
+Prendre une photo, puis extrayez-la comme une image codée en base64 :
+
+    navigator.camera.getPicture (onSuccess, onFail, { quality: 50,
+        destinationType: Camera.DestinationType.DATA_URL
+    }) ;
+    
+    function onSuccess(imageData) {var image = document.getElementById('myImage') ;
+        image.src = "données : image / jpeg ; base64," + imageData;}
+    
+    function onFail(message) {alert (' a échoué car: "+ message);}
+    
+
+Prendre une photo et récupérer l'emplacement du fichier de l'image :
+
+    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 (' a échoué car: "+ message);}
+    
+
+#### Préférences (iOS)
+
+  * **CameraUsesGeolocation** (boolean, par défaut, false). Pour capturer des images JPEG, true pour obtenir des données de géolocalisation dans l'en-tête EXIF. Cela va déclencher une demande d'autorisations de géolocalisation si défini à true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### Amazon Fire OS Quirks
+
+Amazon Fire OS utilise des intentions pour lancer l'activité de l'appareil photo sur l'appareil pour capturer des images et sur les téléphones avec peu de mémoire, l'activité de Cordova peut être tuée. Dans ce scénario, l'image peut ne pas apparaître lorsque l'activité de cordova est restaurée.
+
+#### Quirks Android
+
+Android utilise des intentions pour lancer l'activité de l'appareil photo sur l'appareil pour capturer des images et sur les téléphones avec peu de mémoire, l'activité de Cordova peut être tuée. Dans ce scénario, l'image peut ne pas apparaître lorsque l'activité de Cordova est restaurée.
+
+#### Bizarreries navigateur
+
+Peut retourner uniquement les photos comme image codée en base64.
+
+#### Firefox OS Quirks
+
+Appareil photo plugin est actuellement mis en œuvre à l'aide [d'Activités sur le Web](https://hacks.mozilla.org/2013/01/introducing-web-activities/).
+
+#### Notes au sujet d'iOS
+
+Y compris un JavaScript `alert()` dans les deux le rappel fonctions peuvent causer des problèmes. Envelopper l'alerte dans un `setTimeout()` pour permettre le sélecteur d'image iOS ou kangourou pour fermer entièrement avant que l'alerte s'affiche :
+
+    setTimeout(function() {/ / faire votre truc ici!}, 0) ;
+    
+
+#### Windows Phone 7 Quirks
+
+Invoquant l'application native caméra alors que l'appareil est connecté via Zune ne fonctionne pas et déclenche un rappel de l'erreur.
+
+#### Bizarreries de paciarelli
+
+Paciarelli prend uniquement en charge un `destinationType` de `Camera.DestinationType.FILE_URI` et un `sourceType` de`Camera.PictureSourceType.PHOTOLIBRARY`.
+
+## CameraOptions
+
+Paramètres optionnels pour personnaliser les réglages de l'appareil.
+
+    {qualité : destinationType 75,: Camera.DestinationType.DATA_URL, TypeSource : Camera.PictureSourceType.CAMERA, allowEdit : encodingType vrai,: Camera.EncodingType.JPEG, targetWidth : 100, targetHeight : 100, popoverOptions : CameraPopoverOptions, saveToPhotoAlbum : false} ;
+    
+
+  * **qualité**: qualité de l'image enregistrée, exprimée en une gamme de 0 à 100, 100 étant généralement pleine résolution sans perte de compression de fichiers. La valeur par défaut est 50. *(Nombre)* (Notez que les informations sur la résolution de la caméra sont indisponibles).
+
+  * **destinationType**: choisissez le format de la valeur de retour. La valeur par défaut est FILE_URI. Définies dans `navigator.camera.DestinationType` *(nombre)*
+    
+        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**: définissez la source de l'image. La valeur par défaut est la caméra. Définies dans `navigator.camera.PictureSourceType` *(nombre)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **allowEdit**: permettre un montage simple d'image avant la sélection. *(Booléen)*
+
+  * **encodingType**: choisir le fichier image retournée de codage. Valeur par défaut est JPEG. Définies dans `navigator.camera.EncodingType` *(nombre)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **targetWidth**: largeur en pixels de l'image de l'échelle. Doit être utilisé avec **targetHeight**. Aspect ratio reste constant. *(Nombre)*
+
+  * **targetHeight**: hauteur en pixels de l'image de l'échelle. Doit être utilisé avec **targetWidth**. Aspect ratio reste constant. *(Nombre)*
+
+  * **mediaType**: définir le type de média pour choisir de. Ne fonctionne que quand `PictureSourceType` est `PHOTOLIBRARY` ou `SAVEDPHOTOALBUM` . Définies dans `nagivator.camera.MediaType` *(nombre)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. PAR DÉFAUT. 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**: faire pivoter l'image afin de corriger l'orientation de l'appareil lors de la capture. *(Booléen)*
+
+  * **saveToPhotoAlbum**: enregistrer l'image sur l'album photo sur l'appareil après la capture. *(Booléen)*
+
+  * **popoverOptions**: iOS uniquement des options qui spécifient l'emplacement de kangourou dans iPad. Défini dans`CameraPopoverOptions`.
+
+  * **cameraDirection**: choisissez la caméra à utiliser (ou dos-face). La valeur par défaut est de retour. Définies dans `navigator.camera.Direction` *(nombre)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### Amazon Fire OS Quirks
+
+  * Tout `cameraDirection` résultats dans le back-face photo de valeur.
+
+  * Ignore la `allowEdit` paramètre.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`et `Camera.PictureSourceType.SAVEDPHOTOALBUM` les deux affichent le même album photo.
+
+#### Quirks Android
+
+  * Tout `cameraDirection` résultats dans le back-face photo de valeur.
+
+  * Android utilise également l'activité de récolte pour allowEdit, même si la récolte doit travailler et transmet en réalité l'image recadrée à Cordoue, le seul que les œuvres sont toujours celui livré avec l'application Google Plus Photos. Autres cultures peuvent ne pas fonctionner.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`et `Camera.PictureSourceType.SAVEDPHOTOALBUM` les deux affichent le même album photo.
+
+#### BlackBerry 10 Quirks
+
+  * Ignore la `quality` paramètre.
+
+  * Ignore la `allowEdit` paramètre.
+
+  * `Camera.MediaType`n'est pas pris en charge.
+
+  * Ignore la `correctOrientation` paramètre.
+
+  * Ignore la `cameraDirection` paramètre.
+
+#### Firefox OS Quirks
+
+  * Ignore la `quality` paramètre.
+
+  * `Camera.DestinationType`est ignorée et est égal à `1` (URI du fichier image)
+
+  * Ignore la `allowEdit` paramètre.
+
+  * Ignore la `PictureSourceType` paramètre (utilisateur il choisit dans une fenêtre de dialogue)
+
+  * Ignore le`encodingType`
+
+  * Ignore la `targetWidth` et`targetHeight`
+
+  * `Camera.MediaType`n'est pas pris en charge.
+
+  * Ignore la `correctOrientation` paramètre.
+
+  * Ignore la `cameraDirection` paramètre.
+
+#### Notes au sujet d'iOS
+
+  * La valeur `quality` inférieur à 50 pour éviter les erreurs de mémoire sur certains appareils.
+
+  * Lorsque vous utilisez `destinationType.FILE_URI` , les photos sont sauvegardées dans le répertoire temporaire de l'application. Le contenu du répertoire temporaire de l'application est supprimé lorsque l'application se termine.
+
+#### Bizarreries de paciarelli
+
+  * options non prises en charge
+
+  * retourne toujours un URI de fichier
+
+#### Notes au sujet de Windows Phone 7 et 8
+
+  * Ignore la `allowEdit` paramètre.
+
+  * Ignore la `correctOrientation` paramètre.
+
+  * Ignore la `cameraDirection` paramètre.
+
+  * Ignore la `saveToPhotoAlbum` paramètre. IMPORTANT : Toutes les images prises avec la caméra de cordova wp7/8 API sont toujours copiés au rôle d'appareil photo du téléphone. Selon les paramètres de l'utilisateur, cela pourrait également signifier que l'image est auto-téléchargées à leur OneDrive. Potentiellement, cela pourrait signifier que l'image est disponible à un public plus large que votre application destinée. Si ce un bloqueur pour votre application, vous devrez implémenter le CameraCaptureTask tel que documenté sur msdn : <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> vous pouvez aussi commenter ou haut-vote la question connexe dans le [gestionnaire d'incidents](https://issues.apache.org/jira/browse/CB-2083)
+
+  * Ignore la `mediaType` propriété de `cameraOptions` comme le kit de développement Windows Phone ne fournit pas un moyen de choisir les vidéos de PHOTOLIBRARY.
+
+## CameraError
+
+fonction de rappel onError qui fournit un message d'erreur.
+
+    function(message) {/ / afficher un message utile}
+    
+
+#### Description
+
+  * **message**: le message est fourni par du code natif de l'appareil. *(String)*
+
+## cameraSuccess
+
+fonction de rappel onSuccess qui fournit les données d'image.
+
+    function(ImageData) {/ / faire quelque chose avec l'image}
+    
+
+#### Description
+
+  * **imageData**: codage Base64 de l'image, *ou* le fichier image URI, selon `cameraOptions` en vigueur. *(String)*
+
+#### Exemple
+
+    Afficher image / / function cameraCallback(imageData) {var image = document.getElementById('myImage') ;
+        image.src = "données : image / jpeg ; base64," + imageData;}
+    
+
+## CameraPopoverHandle
+
+Un handle vers la boîte de dialogue de kangourou créé par`navigator.camera.getPicture`.
+
+#### Description
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### Plates-formes supportées
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Exemple
+
+     var cameraPopoverHandle = navigator.camera.getPicture (onSuccess, onFail, {destinationType : Camera.DestinationType.FILE_URI, TypeSource : Camera.PictureSourceType.PHOTOLIBRARY, popoverOptions : nouvelle CameraPopoverOptions (300, 300, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY)}) ;
+    
+     Repositionner le kangourou si l'orientation change.
+     Window.onorientationchange = function() {var cameraPopoverOptions = new CameraPopoverOptions (0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY) ;
+         cameraPopoverHandle.setPosition(cameraPopoverOptions) ;
+     }
+    
+
+## CameraPopoverOptions
+
+iOS uniquement les paramètres qui spécifient la direction ancre élément emplacement et de la flèche de la kangourou lors de la sélection des images de la bibliothèque de l'iPad ou l'album.
+
+    {x: 0, y: 32, largeur : 320, hauteur : 480, arrowDir : Camera.PopoverArrowDirection.ARROW_ANY} ;
+    
+
+#### Description
+
+  * **x**: coordonnée de pixel de l'élément de l'écran sur lequel ancrer le kangourou x. *(Nombre)*
+
+  * **y**: coordonnée de y pixels de l'élément de l'écran sur lequel ancrer le kangourou. *(Nombre)*
+
+  * **largeur**: largeur, en pixels, de l'élément de l'écran sur lequel ancrer le kangourou. *(Nombre)*
+
+  * **hauteur**: hauteur, en pixels, de l'élément de l'écran sur lequel ancrer le kangourou. *(Nombre)*
+
+  * **arrowDir**: Direction de la flèche sur le kangourou doit pointer. Définies dans `Camera.PopoverArrowDirection` *(nombre)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Notez que la taille de la kangourou peut changer pour s'adapter à la direction de la flèche et l'orientation de l'écran. Assurez-vous que tenir compte des changements d'orientation lors de la spécification de l'emplacement d'élément d'ancrage.
+
+## Navigator.Camera.Cleanup
+
+Supprime les intermédiaires photos prises par la caméra de stockage temporaire.
+
+    Navigator.Camera.Cleanup (cameraSuccess, cameraError) ;
+    
+
+#### Description
+
+Supprime les intermédiaires les fichiers image qui sont gardées en dépôt temporaire après avoir appelé `camera.getPicture` . S'applique uniquement lorsque la valeur de `Camera.sourceType` est égale à `Camera.PictureSourceType.CAMERA` et le `Camera.destinationType` est égal à`Camera.DestinationType.FILE_URI`.
+
+#### Plates-formes supportées
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Exemple
+
+    Navigator.Camera.Cleanup (onSuccess, onFail) ;
+    
+    fonction onSuccess() {console.log ("succès de caméra nettoyage.")}
+    
+    function onFail(message) {alert (' a échoué car: "+ message);}

+ 391 - 0
miaomiao/plugins/cordova-plugin-camera/doc/fr/index.md

xqd
@@ -0,0 +1,391 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+Ce plugin définit un global `navigator.camera` objet qui fournit une API pour la prise de photos et de choisir des images de la bibliothèque d'images du système.
+
+Bien que l'objet est attaché à la portée globale `navigator` , il n'est pas disponible jusqu'après la `deviceready` événement.
+
+    document.addEventListener (« deviceready », onDeviceReady, false) ;
+    function onDeviceReady() {console.log(navigator.camera);}
+    
+
+## Installation
+
+    Cordova plugin ajouter cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+Prend une photo à l'aide de la caméra, ou récupère une photo de la Galerie d'images de l'appareil. L'image est passé au rappel succès comme un codage base64 `String` , ou comme l'URI du fichier de l'image. La méthode elle-même retourne un `CameraPopoverHandle` objet qui permet de repositionner le kangourou de sélection de fichier.
+
+    navigator.camera.getPicture (cameraSuccess, cameraError, cameraOptions) ;
+    
+
+### Description
+
+Le `camera.getPicture` fonction ouvre l'application de caméra par défaut de l'appareil qui permet aux utilisateurs de prendre des photos. Ce comportement se produit par défaut, lorsque `Camera.sourceType` est égal à `Camera.PictureSourceType.CAMERA` . Une fois que l'utilisateur s'enclenche la photo, l'application appareil photo se ferme et l'application est restaurée.
+
+Si `Camera.sourceType` est `Camera.PictureSourceType.PHOTOLIBRARY` ou `Camera.PictureSourceType.SAVEDPHOTOALBUM` , puis un dialogue affiche qui permet aux utilisateurs de sélectionner une image existante. Le `camera.getPicture` retourne un `CameraPopoverHandle` objet, ce qui permet de repositionner le dialogue de sélection d'image, par exemple, lorsque l'orientation de l'appareil change.
+
+La valeur de retour est envoyée à la `cameraSuccess` la fonction de rappel, dans l'un des formats suivants, selon les `cameraOptions` :
+
+*   A `String` contenant l'image photo codée en base64.
+
+*   A `String` qui représente l'emplacement du fichier image sur le stockage local (par défaut).
+
+Vous pouvez faire ce que vous voulez avec l'image codée ou URI, par exemple :
+
+*   Afficher l'image dans un `<img>` tag, comme dans l'exemple ci-dessous
+
+*   Enregistrer les données localement ( `LocalStorage` , [poids][1], etc..)
+
+*   Publier les données sur un serveur distant
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**NOTE**: la résolution de Photo sur les nouveaux appareils est assez bonne. Photos sélectionnées de la Galerie de l'appareil ne sont pas réduites à une baisse de la qualité, même si un `quality` paramètre est spécifié. Pour éviter les problèmes de mémoire commun, définissez `Camera.destinationType` à `FILE_URI` au lieu de`DATA_URL`.
+
+### Plates-formes prises en charge
+
+*   Amazon Fire OS
+*   Android
+*   BlackBerry 10
+*   Navigateur
+*   Firefox OS
+*   iOS
+*   Paciarelli
+*   Windows Phone 7 et 8
+*   Windows 8
+
+### Préférences (iOS)
+
+*   **CameraUsesGeolocation** (boolean, par défaut, false). Pour capturer des images JPEG, true pour obtenir des données de géolocalisation dans l'en-tête EXIF. Cela va déclencher une demande d'autorisations de géolocalisation si défini à true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### Amazon Fire OS Quirks
+
+Amazon Fire OS utilise des intentions pour lancer l'activité de l'appareil photo sur l'appareil pour capturer des images et sur les téléphones avec peu de mémoire, l'activité de Cordova peut être tuée. Dans ce scénario, l'image peut ne pas apparaître lorsque l'activité de cordova est restaurée.
+
+### Quirks Android
+
+Android utilise des intentions pour lancer l'activité de l'appareil photo sur l'appareil pour capturer des images et sur les téléphones avec peu de mémoire, l'activité de Cordova peut être tuée. Dans ce scénario, l'image peut ne pas apparaître lorsque l'activité de Cordova est restaurée.
+
+### Bizarreries navigateur
+
+Peut retourner uniquement les photos comme image codée en base64.
+
+### Firefox OS Quirks
+
+Appareil photo plugin est actuellement mis en œuvre à l'aide [d'Activités sur le Web][2].
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### iOS Quirks
+
+Y compris un JavaScript `alert()` dans les deux le rappel fonctions peuvent causer des problèmes. Envelopper l'alerte dans un `setTimeout()` pour permettre le sélecteur d'image iOS ou kangourou pour fermer entièrement avant que l'alerte s'affiche :
+
+    setTimeout(function() {/ / faire votre truc ici!}, 0) ;
+    
+
+### Windows Phone 7 Quirks
+
+Invoquant l'application native caméra alors que l'appareil est connecté via Zune ne fonctionne pas et déclenche un rappel de l'erreur.
+
+### Bizarreries de paciarelli
+
+Paciarelli prend uniquement en charge un `destinationType` de `Camera.DestinationType.FILE_URI` et un `sourceType` de`Camera.PictureSourceType.PHOTOLIBRARY`.
+
+### Exemple
+
+Prendre une photo, puis extrayez-la comme une image codée en base64 :
+
+    navigator.camera.getPicture (onSuccess, onFail, { quality: 50,
+        destinationType: Camera.DestinationType.DATA_URL
+    }) ;
+    
+    function onSuccess(imageData) {var image = document.getElementById('myImage') ;
+        image.src = "données : image / jpeg ; base64," + imageData;}
+    
+    function onFail(message) {alert (' a échoué car: "+ message);}
+    
+
+Prendre une photo et récupérer l'emplacement du fichier de l'image :
+
+    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 (' a échoué car: "+ message);}
+    
+
+## CameraOptions
+
+Paramètres optionnels pour personnaliser les réglages de l'appareil.
+
+    {qualité : destinationType 75,: Camera.DestinationType.DATA_URL, TypeSource : Camera.PictureSourceType.CAMERA, allowEdit : encodingType vrai,: Camera.EncodingType.JPEG, targetWidth : 100, targetHeight : 100, popoverOptions : CameraPopoverOptions, saveToPhotoAlbum : false} ;
+    
+
+### Options
+
+*   **qualité**: qualité de l'image enregistrée, exprimée en une gamme de 0 à 100, 100 étant généralement pleine résolution sans perte de compression de fichiers. La valeur par défaut est 50. *(Nombre)* (Notez que les informations sur la résolution de la caméra sont indisponibles).
+
+*   **destinationType**: choisissez le format de la valeur de retour. La valeur par défaut est FILE_URI. Définies dans `navigator.camera.DestinationType` *(nombre)*
+    
+        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**: définissez la source de l'image. La valeur par défaut est la caméra. Définies dans `navigator.camera.PictureSourceType` *(nombre)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **allowEdit**: permettre un montage simple d'image avant la sélection. *(Booléen)*
+
+*   **encodingType**: choisir le fichier image retournée de codage. Valeur par défaut est JPEG. Définies dans `navigator.camera.EncodingType` *(nombre)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **targetWidth**: largeur en pixels de l'image de l'échelle. Doit être utilisé avec **targetHeight**. Aspect ratio reste constant. *(Nombre)*
+
+*   **targetHeight**: hauteur en pixels de l'image de l'échelle. Doit être utilisé avec **targetWidth**. Aspect ratio reste constant. *(Nombre)*
+
+*   **mediaType**: définir le type de média pour choisir de. Ne fonctionne que quand `PictureSourceType` est `PHOTOLIBRARY` ou `SAVEDPHOTOALBUM` . Définies dans `nagivator.camera.MediaType` *(nombre)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. PAR DÉFAUT. 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**: faire pivoter l'image afin de corriger l'orientation de l'appareil lors de la capture. *(Booléen)*
+
+*   **saveToPhotoAlbum**: enregistrer l'image sur l'album photo sur l'appareil après la capture. *(Booléen)*
+
+*   **popoverOptions**: iOS uniquement des options qui spécifient l'emplacement de kangourou dans iPad. Défini dans`CameraPopoverOptions`.
+
+*   **cameraDirection**: choisissez la caméra à utiliser (ou dos-face). La valeur par défaut est de retour. Définies dans `navigator.camera.Direction` *(nombre)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### Amazon Fire OS Quirks
+
+*   Tout `cameraDirection` résultats dans le back-face photo de valeur.
+
+*   Ignore la `allowEdit` paramètre.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`et `Camera.PictureSourceType.SAVEDPHOTOALBUM` les deux affichent le même album photo.
+
+### Quirks Android
+
+*   Tout `cameraDirection` résultats dans le back-face photo de valeur.
+
+*   Ignore la `allowEdit` paramètre.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`et `Camera.PictureSourceType.SAVEDPHOTOALBUM` les deux affichent le même album photo.
+
+### BlackBerry 10 Quirks
+
+*   Ignore la `quality` paramètre.
+
+*   Ignore la `allowEdit` paramètre.
+
+*   `Camera.MediaType`n'est pas pris en charge.
+
+*   Ignore la `correctOrientation` paramètre.
+
+*   Ignore la `cameraDirection` paramètre.
+
+### Firefox OS Quirks
+
+*   Ignore la `quality` paramètre.
+
+*   `Camera.DestinationType`est ignorée et est égal à `1` (URI du fichier image)
+
+*   Ignore la `allowEdit` paramètre.
+
+*   Ignore la `PictureSourceType` paramètre (utilisateur il choisit dans une fenêtre de dialogue)
+
+*   Ignore le`encodingType`
+
+*   Ignore la `targetWidth` et`targetHeight`
+
+*   `Camera.MediaType`n'est pas pris en charge.
+
+*   Ignore la `correctOrientation` paramètre.
+
+*   Ignore la `cameraDirection` paramètre.
+
+### iOS Quirks
+
+*   La valeur `quality` inférieur à 50 pour éviter les erreurs de mémoire sur certains appareils.
+
+*   Lorsque vous utilisez `destinationType.FILE_URI` , les photos sont sauvegardées dans le répertoire temporaire de l'application. Le contenu du répertoire temporaire de l'application est supprimé lorsque l'application se termine.
+
+### Bizarreries de paciarelli
+
+*   options non prises en charge
+
+*   retourne toujours un URI de fichier
+
+### Windows Phone 7 et 8 Quirks
+
+*   Ignore la `allowEdit` paramètre.
+
+*   Ignore la `correctOrientation` paramètre.
+
+*   Ignore la `cameraDirection` paramètre.
+
+*   Ignore la `saveToPhotoAlbum` paramètre. IMPORTANT : Toutes les images prises avec la caméra de cordova wp7/8 API sont toujours copiés au rôle d'appareil photo du téléphone. Selon les paramètres de l'utilisateur, cela pourrait également signifier que l'image est auto-téléchargées à leur OneDrive. Potentiellement, cela pourrait signifier que l'image est disponible à un public plus large que votre application destinée. Si ce un bloqueur pour votre application, vous devrez implémenter le CameraCaptureTask tel que documenté sur msdn : <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> vous pouvez aussi commenter ou haut-vote la question connexe dans le [gestionnaire d'incidents][3]
+
+*   Ignore la `mediaType` propriété de `cameraOptions` comme le kit de développement Windows Phone ne fournit pas un moyen de choisir les vidéos de PHOTOLIBRARY.
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+fonction de rappel onError qui fournit un message d'erreur.
+
+    function(message) {/ / afficher un message utile}
+    
+
+### Paramètres
+
+*   **message**: le message est fourni par du code natif de l'appareil. *(String)*
+
+## cameraSuccess
+
+fonction de rappel onSuccess qui fournit les données d'image.
+
+    function(ImageData) {/ / faire quelque chose avec l'image}
+    
+
+### Paramètres
+
+*   **imageData**: codage Base64 de l'image, *ou* le fichier image URI, selon `cameraOptions` en vigueur. *(String)*
+
+### Exemple
+
+    Afficher image / / function cameraCallback(imageData) {var image = document.getElementById('myImage') ;
+        image.src = "données : image / jpeg ; base64," + imageData;}
+    
+
+## CameraPopoverHandle
+
+Un handle vers la boîte de dialogue de kangourou créé par`navigator.camera.getPicture`.
+
+### Méthodes
+
+*   **setPosition**: définir la position de la kangourou.
+
+### Plates-formes prises en charge
+
+*   iOS
+
+### setPosition
+
+Définir la position de la kangourou.
+
+**Paramètres**:
+
+*   `cameraPopoverOptions`: la `CameraPopoverOptions` qui spécifie la nouvelle position
+
+### Exemple
+
+     var cameraPopoverHandle = navigator.camera.getPicture (onSuccess, onFail, {destinationType : Camera.DestinationType.FILE_URI, TypeSource : Camera.PictureSourceType.PHOTOLIBRARY, popoverOptions : nouvelle CameraPopoverOptions (300, 300, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY)}) ;
+    
+     Repositionner le kangourou si l'orientation change.
+     Window.onorientationchange = function() {var cameraPopoverOptions = new CameraPopoverOptions (0, 0, 100, 100, Camera.PopoverArrowDirection.ARROW_ANY) ;
+         cameraPopoverHandle.setPosition(cameraPopoverOptions) ;
+     }
+    
+
+## CameraPopoverOptions
+
+iOS uniquement les paramètres qui spécifient la direction ancre élément emplacement et de la flèche de la kangourou lors de la sélection des images de la bibliothèque de l'iPad ou l'album.
+
+    {x: 0, y: 32, largeur : 320, hauteur : 480, arrowDir : Camera.PopoverArrowDirection.ARROW_ANY} ;
+    
+
+### CameraPopoverOptions
+
+*   **x**: coordonnée de pixel de l'élément de l'écran sur lequel ancrer le kangourou x. *(Nombre)*
+
+*   **y**: coordonnée de y pixels de l'élément de l'écran sur lequel ancrer le kangourou. *(Nombre)*
+
+*   **largeur**: largeur, en pixels, de l'élément de l'écran sur lequel ancrer le kangourou. *(Nombre)*
+
+*   **hauteur**: hauteur, en pixels, de l'élément de l'écran sur lequel ancrer le kangourou. *(Nombre)*
+
+*   **arrowDir**: Direction de la flèche sur le kangourou doit pointer. Définies dans `Camera.PopoverArrowDirection` *(nombre)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Notez que la taille de la kangourou peut changer pour s'adapter à la direction de la flèche et l'orientation de l'écran. Assurez-vous que tenir compte des changements d'orientation lors de la spécification de l'emplacement d'élément d'ancrage.
+
+## Navigator.Camera.Cleanup
+
+Supprime les intermédiaires photos prises par la caméra de stockage temporaire.
+
+    Navigator.Camera.Cleanup (cameraSuccess, cameraError) ;
+    
+
+### Description
+
+Supprime les intermédiaires les fichiers image qui sont gardées en dépôt temporaire après avoir appelé `camera.getPicture` . S'applique uniquement lorsque la valeur de `Camera.sourceType` est égale à `Camera.PictureSourceType.CAMERA` et le `Camera.destinationType` est égal à`Camera.DestinationType.FILE_URI`.
+
+### Plates-formes prises en charge
+
+*   iOS
+
+### Exemple
+
+    Navigator.Camera.Cleanup (onSuccess, onFail) ;
+    
+    fonction onSuccess() {console.log ("succès de caméra nettoyage.")}
+    
+    function onFail(message) {alert (' a échoué car: "+ message);}

BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/android-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/android-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/blackberry-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/blackberry-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/browser-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/browser-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/firefox-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/firefox-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/fireos-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/fireos-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/ios-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/ios-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/ubuntu-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/ubuntu-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/windows-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/windows-success.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/wp8-fail.png


BIN
miaomiao/plugins/cordova-plugin-camera/doc/img/wp8-success.png


+ 421 - 0
miaomiao/plugins/cordova-plugin-camera/doc/it/README.md

xqd
@@ -0,0 +1,421 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+Questo plugin definisce un oggetto globale `navigator.camera`, che fornisce un'API per scattare foto e per aver scelto immagini dalla libreria di immagini del sistema.
+
+Anche se l'oggetto è associato con ambito globale del `navigator`, non è disponibile fino a dopo l'evento `deviceready`.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## Installazione
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * Fotocamera 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * navigator.camera.cleanup
+
+## navigator.camera.getPicture
+
+Prende una foto utilizzando la fotocamera, o recupera una foto dalla galleria di immagini del dispositivo. L'immagine è passata al callback di successo come `String` con codifica base64, o come l'URI per il file di immagine. Lo stesso metodo restituisce un oggetto `CameraPopoverHandle` che può essere utilizzato per riposizionare il Muffin di selezione file.
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### Descrizione
+
+La funzione `camera.getPicture` apre predefinito fotocamera applicazione il dispositivo che consente agli utenti di scattare foto. Questo comportamento si verifica per impostazione predefinita, quando `Camera.sourceType` è uguale a `Camera.PictureSourceType.CAMERA`. Una volta che l'utente scatta la foto, si chiude l'applicazione fotocamera e l'applicazione viene ripristinato.
+
+Se `Camera.sourceType` è `Camera.PictureSourceType.PHOTOLIBRARY` o `Camera.PictureSourceType.SAVEDPHOTOALBUM`, una finestra di dialogo Visualizza che permette agli utenti di selezionare un'immagine esistente. La funzione `camera.getPicture` restituisce un oggetto `CameraPopoverHandle` che può essere utilizzato per riposizionare la finestra di selezione immagine, ad esempio, quando l'orientamento del dispositivo.
+
+Il valore restituito viene inviato alla funzione di callback `cameraSuccess`, in uno dei seguenti formati, a seconda il `cameraOptions` specificato:
+
+  * A `String` contenente l'immagine della foto con codifica base64.
+
+  * A `String` che rappresenta il percorso del file di immagine su archiviazione locale (predefinito).
+
+Si può fare quello che vuoi con l'immagine codificata o URI, ad esempio:
+
+  * Il rendering dell'immagine in un `<img>` tag, come nell'esempio qui sotto
+
+  * Salvare i dati localmente ( `LocalStorage` , [Lawnchair](http://brianleroux.github.com/lawnchair/), ecc.)
+
+  * Inviare i dati a un server remoto
+
+**Nota**: risoluzione foto sui più recenti dispositivi è abbastanza buona. Foto selezionate dalla galleria del dispositivo non è percepiranno di qualità inferiore, anche se viene specificato un parametro di `quality`. Per evitare problemi di memoria comune, impostare `Camera.destinationType` `FILE_URI` piuttosto che `DATA_URL`.
+
+#### Piattaforme supportate
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### Esempio
+
+Scattare una foto e recuperarla come un'immagine con codifica base64:
+
+    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);
+    }
+    
+
+Scattare una foto e recuperare il percorso del file dell'immagine:
+
+    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);
+    }
+    
+
+#### Preferenze (iOS)
+
+  * **CameraUsesGeolocation** (boolean, default è false). Per l'acquisizione di immagini JPEG, impostato su true per ottenere dati di geolocalizzazione nell'intestazione EXIF. Questo innescherà una richiesta per le autorizzazioni di geolocalizzazione, se impostato su true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### Amazon fuoco OS stranezze
+
+Amazon fuoco OS utilizza intenti a lanciare l'attività della fotocamera sul dispositivo per catturare immagini e sui telefoni con poca memoria, l'attività di Cordova può essere ucciso. In questo scenario, l'immagine potrebbe non apparire quando viene ripristinata l'attività di cordova.
+
+#### Stranezze Android
+
+Android utilizza intenti a lanciare l'attività della fotocamera sul dispositivo per catturare immagini e sui telefoni con poca memoria, l'attività di Cordova può essere ucciso. In questo scenario, l'immagine potrebbe non apparire quando viene ripristinata l'attività di Cordova.
+
+#### Stranezze browser
+
+Può restituire solo la foto come immagine con codifica base64.
+
+#### Firefox OS stranezze
+
+Fotocamera plugin è attualmente implementato mediante [Web Activities](https://hacks.mozilla.org/2013/01/introducing-web-activities/).
+
+#### iOS stranezze
+
+Compreso un JavaScript `alert()` in una delle funzioni di callback può causare problemi. Avvolgere l'avviso all'interno di un `setTimeout()` per consentire la selezione immagine iOS o muffin per chiudere completamente la prima che viene visualizzato l'avviso:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+#### Windows Phone 7 capricci
+
+Richiamando l'applicazione nativa fotocamera mentre il dispositivo è collegato tramite Zune non funziona e innesca un callback di errore.
+
+#### Tizen stranezze
+
+Tizen supporta solo a `destinationType` di `Camera.DestinationType.FILE_URI` e un `sourceType` di `Camera.PictureSourceType.PHOTOLIBRARY`.
+
+## CameraOptions
+
+Parametri opzionali per personalizzare le impostazioni della fotocamera.
+
+    { 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 };
+    
+
+  * **quality**: qualità dell'immagine salvata, espressa come un intervallo di 0-100, dove 100 è tipicamente piena risoluzione senza perdita di compressione file. Il valore predefinito è 50. *(Numero)* (Si noti che informazioni sulla risoluzione della fotocamera non sono disponibile).
+
+  * **destinationType**: Scegli il formato del valore restituito. Il valore predefinito è FILE_URI. Definito in `navigator.camera.DestinationType` *(numero)*
+    
+        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**: impostare l'origine dell'immagine. Il valore predefinito è la fotocamera. Definito in `navigator.camera.PictureSourceType` *(numero)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **Proprietà allowEdit**: consentire la semplice modifica dell'immagine prima di selezione. *(Booleano)*
+
+  * **encodingType**: scegliere il file immagine restituita di codifica. Predefinito è JPEG. Definito in `navigator.camera.EncodingType` *(numero)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **targetWidth**: larghezza in pixel all'immagine della scala. Deve essere usato con **targetHeight**. Proporzioni rimane costante. *(Numero)*
+
+  * **targetHeight**: altezza in pixel all'immagine della scala. Deve essere usato con **targetWidth**. Proporzioni rimane costante. *(Numero)*
+
+  * **mediaType**: impostare il tipo di supporto per scegliere da. Funziona solo quando `PictureSourceType` è `PHOTOLIBRARY` o `SAVEDPHOTOALBUM` . Definito in `nagivator.camera.MediaType` *(numero)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. PER IMPOSTAZIONE PREDEFINITA. 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**: ruotare l'immagine per correggere l'orientamento del dispositivo durante l'acquisizione. *(Booleano)*
+
+  * **saveToPhotoAlbum**: salvare l'immagine nell'album di foto sul dispositivo dopo la cattura. *(Booleano)*
+
+  * **popoverOptions**: solo iOS opzioni che specificano la posizione di muffin in iPad. Definito in`CameraPopoverOptions`.
+
+  * **cameraDirection**: scegliere la telecamera da utilizzare (o retro-frontale). Il valore predefinito è tornato. Definito in `navigator.camera.Direction` *(numero)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### Amazon fuoco OS stranezze
+
+  * Qualsiasi `cameraDirection` valore i risultati in una foto di lamatura.
+
+  * Ignora il `allowEdit` parametro.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`e `Camera.PictureSourceType.SAVEDPHOTOALBUM` entrambi visualizzare l'album fotografico stesso.
+
+#### Stranezze Android
+
+  * Qualsiasi `cameraDirection` valore i risultati in una foto di lamatura.
+
+  * Android utilizza anche l'attività di ritaglio per allowEdit, anche se raccolto dovrebbe funzionare ed effettivamente passare l'immagine ritagliata a Cordova, l'unico che funziona è sempre quello in bundle con l'applicazione di Google Plus foto. Altre colture potrebbero non funzionare.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`e `Camera.PictureSourceType.SAVEDPHOTOALBUM` entrambi visualizzare l'album fotografico stesso.
+
+#### BlackBerry 10 capricci
+
+  * Ignora il `quality` parametro.
+
+  * Ignora il `allowEdit` parametro.
+
+  * `Camera.MediaType`non è supportato.
+
+  * Ignora il `correctOrientation` parametro.
+
+  * Ignora il `cameraDirection` parametro.
+
+#### Firefox OS stranezze
+
+  * Ignora il `quality` parametro.
+
+  * `Camera.DestinationType`viene ignorato e corrisponde a `1` (URI del file di immagine)
+
+  * Ignora il `allowEdit` parametro.
+
+  * Ignora il `PictureSourceType` parametro (utente ne sceglie in una finestra di dialogo)
+
+  * Ignora il`encodingType`
+
+  * Ignora le `targetWidth` e`targetHeight`
+
+  * `Camera.MediaType`non è supportato.
+
+  * Ignora il `correctOrientation` parametro.
+
+  * Ignora il `cameraDirection` parametro.
+
+#### iOS stranezze
+
+  * Impostare `quality` inferiore al 50 per evitare errori di memoria su alcuni dispositivi.
+
+  * Quando si utilizza `destinationType.FILE_URI` , foto vengono salvati nella directory temporanea dell'applicazione. Il contenuto della directory temporanea dell'applicazione viene eliminato quando l'applicazione termina.
+
+#### Tizen stranezze
+
+  * opzioni non supportate
+
+  * restituisce sempre un URI del FILE
+
+#### Windows Phone 7 e 8 stranezze
+
+  * Ignora il `allowEdit` parametro.
+
+  * Ignora il `correctOrientation` parametro.
+
+  * Ignora il `cameraDirection` parametro.
+
+  * Ignora il `saveToPhotoAlbum` parametro. IMPORTANTE: Tutte le immagini scattate con la fotocamera di cordova wp7/8 API vengono sempre copiate rotolo fotocamera del telefono cellulare. A seconda delle impostazioni dell'utente, questo potrebbe anche significare che l'immagine viene caricato in automatico a loro OneDrive. Questo potenzialmente potrebbe significare che l'immagine è disponibile a un pubblico più ampio di app destinate. Se questo un blocco dell'applicazione, sarà necessario implementare il CameraCaptureTask come documentato su msdn: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> si può anche commentare o up-voto la questione correlata nel [tracciatore di problemi](https://issues.apache.org/jira/browse/CB-2083)
+
+  * Ignora la `mediaType` proprietà di `cameraOptions` come il SDK di Windows Phone non fornisce un modo per scegliere il video da PHOTOLIBRARY.
+
+## CameraError
+
+funzione di callback onError che fornisce un messaggio di errore.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+#### Descrizione
+
+  * **message**: il messaggio è fornito dal codice nativo del dispositivo. *(String)*
+
+## cameraSuccess
+
+funzione di callback onSuccess che fornisce i dati di immagine.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+#### Descrizione
+
+  * **imageData**: Base64 codifica dei dati immagine, *o* il file di immagine URI, a seconda `cameraOptions` in vigore. *(String)*
+
+#### Esempio
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Un handle per la finestra di dialogo di muffin creato da `navigator.camera.getPicture`.
+
+#### Descrizione
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### Piattaforme supportate
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Esempio
+
+     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 solo parametri che specificano l'ancoraggio elemento posizione e freccia direzione il Muffin quando si selezionano le immagini dalla libreria un iPad o un album.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+#### Descrizione
+
+  * **x**: pixel coordinata x dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+  * **y**: coordinata y di pixel dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+  * **width**: larghezza, in pixel, dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+  * **height**: altezza, in pixel, dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+  * **arrowDir**: direzione dovrebbe puntare la freccia il muffin. Definito in `Camera.PopoverArrowDirection` *(numero)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Si noti che la dimensione del muffin possa cambiare per regolare la direzione della freccia e l'orientamento dello schermo. Assicurarsi che tenere conto di modifiche di orientamento quando si specifica la posizione di elemento di ancoraggio.
+
+## navigator.camera.cleanup
+
+Rimuove intermedio foto scattate con la fotocamera da deposito temporaneo.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+#### Descrizione
+
+Rimuove i file di immagine intermedia che vengono tenuti in custodia temporanea dopo la chiamata a `camera.getPicture`. Si applica solo quando il valore di `Camera.sourceType` è uguale a `Camera.PictureSourceType.CAMERA` e il `Camera.destinationType` è uguale a `Camera.DestinationType.FILE_URI`.
+
+#### Piattaforme supportate
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Esempio
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 434 - 0
miaomiao/plugins/cordova-plugin-camera/doc/it/index.md

xqd
@@ -0,0 +1,434 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+Questo plugin definisce un oggetto globale `navigator.camera`, che fornisce un'API per scattare foto e per aver scelto immagini dalla libreria di immagini del sistema.
+
+Anche se l'oggetto è associato con ambito globale del `navigator`, non è disponibile fino a dopo l'evento `deviceready`.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## Installazione
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+Prende una foto utilizzando la fotocamera, o recupera una foto dalla galleria di immagini del dispositivo. L'immagine è passata al callback di successo come `String` con codifica base64, o come l'URI per il file di immagine. Lo stesso metodo restituisce un oggetto `CameraPopoverHandle` che può essere utilizzato per riposizionare il Muffin di selezione file.
+
+    navigator.camera.getPicture( cameraSuccess, cameraError, cameraOptions );
+    
+
+### Descrizione
+
+La funzione `camera.getPicture` apre predefinito fotocamera applicazione il dispositivo che consente agli utenti di scattare foto. Questo comportamento si verifica per impostazione predefinita, quando `Camera.sourceType` è uguale a `Camera.PictureSourceType.CAMERA`. Una volta che l'utente scatta la foto, si chiude l'applicazione fotocamera e l'applicazione viene ripristinato.
+
+Se `Camera.sourceType` è `Camera.PictureSourceType.PHOTOLIBRARY` o `Camera.PictureSourceType.SAVEDPHOTOALBUM`, una finestra di dialogo Visualizza che permette agli utenti di selezionare un'immagine esistente. La funzione `camera.getPicture` restituisce un oggetto `CameraPopoverHandle` che può essere utilizzato per riposizionare la finestra di selezione immagine, ad esempio, quando l'orientamento del dispositivo.
+
+Il valore restituito viene inviato alla funzione di callback `cameraSuccess`, in uno dei seguenti formati, a seconda il `cameraOptions` specificato:
+
+*   A `String` contenente l'immagine della foto con codifica base64.
+
+*   A `String` che rappresenta il percorso del file di immagine su archiviazione locale (predefinito).
+
+Si può fare quello che vuoi con l'immagine codificata o URI, ad esempio:
+
+*   Il rendering dell'immagine in un `<img>` tag, come nell'esempio qui sotto
+
+*   Salvare i dati localmente ( `LocalStorage` , [Lawnchair][1], ecc.)
+
+*   Inviare i dati a un server remoto
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**Nota**: risoluzione foto sui più recenti dispositivi è abbastanza buona. Foto selezionate dalla galleria del dispositivo non è percepiranno di qualità inferiore, anche se viene specificato un parametro di `quality`. Per evitare problemi di memoria comune, impostare `Camera.destinationType` `FILE_URI` piuttosto che `DATA_URL`.
+
+### Piattaforme supportate
+
+*   Amazon fuoco OS
+*   Android
+*   BlackBerry 10
+*   Browser
+*   Firefox OS
+*   iOS
+*   Tizen
+*   Windows Phone 7 e 8
+*   Windows 8
+
+### Preferenze (iOS)
+
+*   **CameraUsesGeolocation** (boolean, default è false). Per l'acquisizione di immagini JPEG, impostato su true per ottenere dati di geolocalizzazione nell'intestazione EXIF. Questo innescherà una richiesta per le autorizzazioni di geolocalizzazione, se impostato su true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### Amazon fuoco OS stranezze
+
+Amazon fuoco OS utilizza intenti a lanciare l'attività della fotocamera sul dispositivo per catturare immagini e sui telefoni con poca memoria, l'attività di Cordova può essere ucciso. In questo scenario, l'immagine potrebbe non apparire quando viene ripristinata l'attività di cordova.
+
+### Stranezze Android
+
+Android utilizza intenti a lanciare l'attività della fotocamera sul dispositivo per catturare immagini e sui telefoni con poca memoria, l'attività di Cordova può essere ucciso. In questo scenario, l'immagine potrebbe non apparire quando viene ripristinata l'attività di Cordova.
+
+### Stranezze browser
+
+Può restituire solo la foto come immagine con codifica base64.
+
+### Firefox OS stranezze
+
+Fotocamera plugin è attualmente implementato mediante [Web Activities][2].
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### iOS stranezze
+
+Compreso un JavaScript `alert()` in una delle funzioni di callback può causare problemi. Avvolgere l'avviso all'interno di un `setTimeout()` per consentire la selezione immagine iOS o muffin per chiudere completamente la prima che viene visualizzato l'avviso:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+### Windows Phone 7 stranezze
+
+Richiamando l'applicazione nativa fotocamera mentre il dispositivo è collegato tramite Zune non funziona e innesca un callback di errore.
+
+### Tizen stranezze
+
+Tizen supporta solo a `destinationType` di `Camera.DestinationType.FILE_URI` e un `sourceType` di `Camera.PictureSourceType.PHOTOLIBRARY`.
+
+### Esempio
+
+Scattare una foto e recuperarla come un'immagine con codifica base64:
+
+    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);
+    }
+    
+
+Scattare una foto e recuperare il percorso del file dell'immagine:
+
+    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
+
+Parametri opzionali per personalizzare le impostazioni della fotocamera.
+
+    { 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 };
+    
+
+### Opzioni
+
+*   **quality**: qualità dell'immagine salvata, espressa come un intervallo di 0-100, dove 100 è tipicamente piena risoluzione senza perdita di compressione file. Il valore predefinito è 50. *(Numero)* (Si noti che informazioni sulla risoluzione della fotocamera non sono disponibile).
+
+*   **destinationType**: Scegli il formato del valore restituito. Il valore predefinito è FILE_URI. Definito in `navigator.camera.DestinationType` *(numero)*
+    
+        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**: impostare l'origine dell'immagine. Il valore predefinito è la fotocamera. Definito in `navigator.camera.PictureSourceType` *(numero)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **Proprietà allowEdit**: consentire la semplice modifica dell'immagine prima di selezione. *(Booleano)*
+
+*   **encodingType**: scegliere il file immagine restituita di codifica. Predefinito è JPEG. Definito in `navigator.camera.EncodingType` *(numero)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **targetWidth**: larghezza in pixel all'immagine della scala. Deve essere usato con **targetHeight**. Proporzioni rimane costante. *(Numero)*
+
+*   **targetHeight**: altezza in pixel all'immagine della scala. Deve essere usato con **targetWidth**. Proporzioni rimane costante. *(Numero)*
+
+*   **mediaType**: impostare il tipo di supporto per scegliere da. Funziona solo quando `PictureSourceType` è `PHOTOLIBRARY` o `SAVEDPHOTOALBUM` . Definito in `nagivator.camera.MediaType` *(numero)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. PER IMPOSTAZIONE PREDEFINITA. 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**: ruotare l'immagine per correggere l'orientamento del dispositivo durante l'acquisizione. *(Booleano)*
+
+*   **saveToPhotoAlbum**: salvare l'immagine nell'album di foto sul dispositivo dopo la cattura. *(Booleano)*
+
+*   **popoverOptions**: solo iOS opzioni che specificano la posizione di muffin in iPad. Definito in`CameraPopoverOptions`.
+
+*   **cameraDirection**: scegliere la telecamera da utilizzare (o retro-frontale). Il valore predefinito è tornato. Definito in `navigator.camera.Direction` *(numero)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### Amazon fuoco OS stranezze
+
+*   Qualsiasi `cameraDirection` valore i risultati in una foto di lamatura.
+
+*   Ignora il `allowEdit` parametro.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`e `Camera.PictureSourceType.SAVEDPHOTOALBUM` entrambi visualizzare l'album fotografico stesso.
+
+### Stranezze Android
+
+*   Qualsiasi `cameraDirection` valore i risultati in una foto di lamatura.
+
+*   Ignora il `allowEdit` parametro.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`e `Camera.PictureSourceType.SAVEDPHOTOALBUM` entrambi visualizzare l'album fotografico stesso.
+
+### BlackBerry 10 capricci
+
+*   Ignora il `quality` parametro.
+
+*   Ignora il `allowEdit` parametro.
+
+*   `Camera.MediaType`non è supportato.
+
+*   Ignora il `correctOrientation` parametro.
+
+*   Ignora il `cameraDirection` parametro.
+
+### Firefox OS stranezze
+
+*   Ignora il `quality` parametro.
+
+*   `Camera.DestinationType`viene ignorato e corrisponde a `1` (URI del file di immagine)
+
+*   Ignora il `allowEdit` parametro.
+
+*   Ignora il `PictureSourceType` parametro (utente ne sceglie in una finestra di dialogo)
+
+*   Ignora il`encodingType`
+
+*   Ignora le `targetWidth` e`targetHeight`
+
+*   `Camera.MediaType`non è supportato.
+
+*   Ignora il `correctOrientation` parametro.
+
+*   Ignora il `cameraDirection` parametro.
+
+### iOS stranezze
+
+*   Impostare `quality` inferiore al 50 per evitare errori di memoria su alcuni dispositivi.
+
+*   Quando si utilizza `destinationType.FILE_URI` , foto vengono salvati nella directory temporanea dell'applicazione. Il contenuto della directory temporanea dell'applicazione viene eliminato quando l'applicazione termina.
+
+### Tizen stranezze
+
+*   opzioni non supportate
+
+*   restituisce sempre un URI del FILE
+
+### Windows Phone 7 e 8 stranezze
+
+*   Ignora il `allowEdit` parametro.
+
+*   Ignora il `correctOrientation` parametro.
+
+*   Ignora il `cameraDirection` parametro.
+
+*   Ignora il `saveToPhotoAlbum` parametro. IMPORTANTE: Tutte le immagini scattate con la fotocamera di cordova wp7/8 API vengono sempre copiate rotolo fotocamera del telefono cellulare. A seconda delle impostazioni dell'utente, questo potrebbe anche significare che l'immagine viene caricato in automatico a loro OneDrive. Questo potenzialmente potrebbe significare che l'immagine è disponibile a un pubblico più ampio di app destinate. Se questo un blocco dell'applicazione, sarà necessario implementare il CameraCaptureTask come documentato su msdn: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> si può anche commentare o up-voto la questione correlata nel [tracciatore di problemi][3]
+
+*   Ignora la `mediaType` proprietà di `cameraOptions` come il SDK di Windows Phone non fornisce un modo per scegliere il video da PHOTOLIBRARY.
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+funzione di callback onError che fornisce un messaggio di errore.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+### Parametri
+
+*   **message**: il messaggio è fornito dal codice nativo del dispositivo. *(String)*
+
+## cameraSuccess
+
+funzione di callback onSuccess che fornisce i dati di immagine.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+### Parametri
+
+*   **imageData**: Base64 codifica dei dati immagine, *o* il file di immagine URI, a seconda `cameraOptions` in vigore. *(String)*
+
+### Esempio
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Un handle per la finestra di dialogo di muffin creato da `navigator.camera.getPicture`.
+
+### Metodi
+
+*   **setPosition**: impostare la posizione dei muffin.
+
+### Piattaforme supportate
+
+*   iOS
+
+### setPosition
+
+Impostare la posizione dei muffin.
+
+**Parametri**:
+
+*   `cameraPopoverOptions`: il `CameraPopoverOptions` che specificare la nuova posizione
+
+### Esempio
+
+     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 solo parametri che specificano l'ancoraggio elemento posizione e freccia direzione il Muffin quando si selezionano le immagini dalla libreria un iPad o un album.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+### CameraPopoverOptions
+
+*   **x**: pixel coordinata x dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+*   **y**: coordinata y di pixel dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+*   **width**: larghezza, in pixel, dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+*   **height**: altezza, in pixel, dell'elemento dello schermo su cui ancorare il muffin. *(Numero)*
+
+*   **arrowDir**: direzione dovrebbe puntare la freccia il muffin. Definito in `Camera.PopoverArrowDirection` *(numero)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Si noti che la dimensione del muffin possa cambiare per regolare la direzione della freccia e l'orientamento dello schermo. Assicurarsi che tenere conto di modifiche di orientamento quando si specifica la posizione di elemento di ancoraggio.
+
+## navigator.camera.cleanup
+
+Rimuove intermedio foto scattate con la fotocamera da deposito temporaneo.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+### Descrizione
+
+Rimuove i file di immagine intermedia che vengono tenuti in custodia temporanea dopo la chiamata a `camera.getPicture`. Si applica solo quando il valore di `Camera.sourceType` è uguale a `Camera.PictureSourceType.CAMERA` e il `Camera.destinationType` è uguale a `Camera.DestinationType.FILE_URI`.
+
+### Piattaforme supportate
+
+*   iOS
+
+### Esempio
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 421 - 0
miaomiao/plugins/cordova-plugin-camera/doc/ja/README.md

xqd
@@ -0,0 +1,421 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+このプラグインは、写真を撮るため、システムのイメージ ライブラリからイメージを選択するために API を提供します、グローバル `navigator.camera` オブジェクトを定義します。
+
+オブジェクトは、グローバル スコープの `ナビゲーター` に添付、それがないまで `deviceready` イベントの後。
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## インストール
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * カメラ 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * navigator.camera.cleanup
+
+## navigator.camera.getPicture
+
+カメラを使用して写真を取るか、デバイスの画像ギャラリーから写真を取得します。 イメージが渡されます成功時のコールバックを base64 エンコードされた `文字列`、または、URI としてイメージ ファイル。 メソッド自体はファイル選択ポップ オーバーの位置を変更するために使用できる `CameraPopoverHandle` オブジェクトを返します。
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### 解説
+
+`camera.getPicture` 関数は、ユーザーの写真をスナップすることができますデバイスのデフォルト カメラ アプリケーションを開きます。 `Camera.sourceType` が `Camera.PictureSourceType.CAMERA` と等しい場合既定では、この現象が発生します。 ユーザーは写真をスナップ、カメラ アプリケーションを閉じるし、アプリケーションが復元されます。
+
+`Camera.sourceType` `Camera.PictureSourceType.PHOTOLIBRARY` または `Camera.PictureSourceType.SAVEDPHOTOALBUM` の場合、ダイアログ ボックスはユーザーを既存のイメージを選択することができますが表示されます。 `camera.getPicture` 関数は、デバイスの向きが変更されたとき、たとえば、イメージの選択ダイアログには、位置を変更するために使用することができます、`CameraPopoverHandle` オブジェクトを返します。
+
+戻り値が `cameraSuccess` コールバック関数の指定 `cameraOptions` に応じて、次の形式のいずれかに送信されます。
+
+  * A `String` 写真の base64 でエンコードされたイメージを含んでいます。
+
+  * A `String` (既定値) のローカル記憶域上のイメージ ファイルの場所を表します。
+
+自由に変更、エンコードされたイメージ、または URI などを行うことができます。
+
+  * イメージをレンダリングする `<img>` 以下の例のように、タグ
+
+  * ローカル データの保存 ( `LocalStorage` 、 [Lawnchair](http://brianleroux.github.com/lawnchair/)など)。
+
+  * リモート サーバーにデータを投稿します。
+
+**注**: 新しいデバイス上の写真の解像度はかなり良いです。 デバイスのギャラリーから選択した写真は `quality` パラメーターが指定されて場合でも下方の品質に縮小されません。 一般的なメモリの問題を避けるために `DATA_URL` ではなく `FILE_URI` に `Camera.destinationType` を設定します。.
+
+#### サポートされているプラットフォーム
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### 例
+
+写真を撮るし、base64 エンコード イメージとして取得します。
+
+    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);
+    }
+    
+
+写真を撮るし、イメージのファイルの場所を取得します。
+
+    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);
+    }
+    
+
+#### 環境設定 (iOS)
+
+  * **CameraUsesGeolocation**(ブール値、デフォルトは false)。 Jpeg 画像をキャプチャするため EXIF ヘッダーで地理位置情報データを取得する場合は true に設定します。 これは、場合地理位置情報のアクセス許可に対する要求をトリガーする true に設定します。
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### アマゾン火 OS 癖
+
+アマゾン火 OS イメージをキャプチャするデバイス上のカメラの活動を開始する意図を使用して、メモリの少ない携帯電話、コルドバ活動が殺されるかもしれない。 このシナリオではコルドバ活動が復元されると、イメージが表示されません。
+
+#### Android の癖
+
+アンドロイド、イメージをキャプチャするデバイス上でカメラのアクティビティを開始する意図を使用し、メモリの少ない携帯電話、コルドバ活動が殺されるかもしれない。 このシナリオではコルドバ活動が復元されると、イメージが表示されません。
+
+#### ブラウザーの癖
+
+Base64 エンコード イメージとして写真を返すのみことができます。
+
+#### Firefox OS 癖
+
+カメラのプラグインは現在、[Web アクティビティ](https://hacks.mozilla.org/2013/01/introducing-web-activities/) を使用して実装されていた.
+
+#### iOS の癖
+
+コールバック関数のいずれかの JavaScript `alert()` を含む問題が発生することができます。 IOS イメージ ピッカーまたは完全が終了するまで、警告が表示されますポップ オーバーを許可する `setTimeout()` 内でアラートをラップします。
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+#### Windows Phone 7 の癖
+
+ネイティブ カメラ アプリケーションを呼び出すと、デバイスが Zune を介して接続されている動作しませんし、エラー コールバックをトリガーします。
+
+#### Tizen の癖
+
+Tizen のみ `Camera.DestinationType.FILE_URI` の `destinationType` と `Camera.PictureSourceType.PHOTOLIBRARY` の `sourceType` をサポートしています.
+
+## CameraOptions
+
+カメラの設定をカスタマイズするオプションのパラメーター。
+
+    { 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 };
+    
+
+  * **quality**: 0-100、100 がファイルの圧縮から損失なしで通常のフル解像度の範囲で表される、保存されたイメージの品質。 既定値は 50 です。 *(数)*(カメラの解像度についての情報が利用できないことに注意してください)。
+
+  * **destinationType**: 戻り値の形式を選択します。既定値は FILE_URI です。定義されている `navigator.camera.DestinationType` *(番号)*
+    
+        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**: 画像のソースを設定します。既定値は、カメラです。定義されている `navigator.camera.PictureSourceType` *(番号)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **allowEdit**: 単純な選択の前に画像の編集を許可します。*(ブール値)*
+
+  * **encodingType**: 返されるイメージ ファイルのエンコーディングを選択します。デフォルトは JPEG です。定義されている `navigator.camera.EncodingType` *(番号)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **targetWidth**: スケール イメージにピクセル単位の幅。**TargetHeight**を使用する必要があります。縦横比は変わりません。*(数)*
+
+  * **targetHeight**: スケール イメージにピクセル単位の高さ。**TargetWidth**を使用する必要があります。縦横比は変わりません。*(数)*
+
+  * **mediaType**: から選択するメディアの種類を設定します。 場合にのみ働きます `PictureSourceType` は `PHOTOLIBRARY` または `SAVEDPHOTOALBUM` 。 定義されている `nagivator.camera.MediaType` *(番号)*
+    
+        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**: キャプチャ中に、デバイスの向きを修正する画像を回転させます。*(ブール値)*
+
+  * **saveToPhotoAlbum**: キャプチャ後、デバイス上のフォト アルバムに画像を保存します。*(ブール値)*
+
+  * **popoverOptions**: iPad のポップ オーバーの場所を指定する iOS のみのオプションです。定義されています。`CameraPopoverOptions`.
+
+  * **cameraDirection**: (前面または背面側) を使用するカメラを選択します。既定値は戻るです。定義されている `navigator.camera.Direction` *(番号)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### アマゾン火 OS 癖
+
+  * 任意 `cameraDirection` 背面写真で結果の値します。
+
+  * 無視、 `allowEdit` パラメーター。
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY``Camera.PictureSourceType.SAVEDPHOTOALBUM`両方のアルバムが表示されます同じ写真。
+
+#### Android の癖
+
+  * 任意 `cameraDirection` 背面写真で結果の値します。
+
+  * アンドロイドも使用しています作物活性、allowEdit もトリミングする必要があります動作し、実際にトリミングされた画像をコルドバで 1 つだけの作品一貫して Google プラス写真アプリケーションにバンドルされているものであることに渡します。 他の作物が機能しません。
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY``Camera.PictureSourceType.SAVEDPHOTOALBUM`両方のアルバムが表示されます同じ写真。
+
+#### ブラックベリー 10 癖
+
+  * 無視、 `quality` パラメーター。
+
+  * 無視、 `allowEdit` パラメーター。
+
+  * `Camera.MediaType`サポートされていません。
+
+  * 無視、 `correctOrientation` パラメーター。
+
+  * 無視、 `cameraDirection` パラメーター。
+
+#### Firefox OS 癖
+
+  * 無視、 `quality` パラメーター。
+
+  * `Camera.DestinationType`無視され、等しい `1` (イメージ ファイル URI)
+
+  * 無視、 `allowEdit` パラメーター。
+
+  * 無視、 `PictureSourceType` パラメーター (ユーザーが選択ダイアログ ウィンドウに)
+
+  * 無視します、`encodingType`
+
+  * 無視、 `targetWidth` と`targetHeight`
+
+  * `Camera.MediaType`サポートされていません。
+
+  * 無視、 `correctOrientation` パラメーター。
+
+  * 無視、 `cameraDirection` パラメーター。
+
+#### iOS の癖
+
+  * 設定 `quality` 一部のデバイスでメモリ不足エラーを避けるために 50 の下。
+
+  * 使用する場合 `destinationType.FILE_URI` 、写真、アプリケーションの一時ディレクトリに保存されます。アプリケーションの一時ディレクトリの内容は、アプリケーションの終了時に削除されます。
+
+#### Tizen の癖
+
+  * サポートされていないオプション
+
+  * 常にファイルの URI を返す
+
+#### Windows Phone 7 と 8 癖
+
+  * 無視、 `allowEdit` パラメーター。
+
+  * 無視、 `correctOrientation` パラメーター。
+
+  * 無視、 `cameraDirection` パラメーター。
+
+  * 無視、 `saveToPhotoAlbum` パラメーター。 重要: wp7/8 コルドバ カメラ API で撮影したすべての画像は携帯電話のカメラ巻き物に常にコピーします。 ユーザーの設定に応じて、これも、画像はその OneDrive に自動アップロードを意味できます。 イメージは意図したアプリより広い聴衆に利用できる可能性があります可能性があります。 場合は、このアプリケーションのブロッカー、msdn で説明されているように、CameraCaptureTask を実装する必要があります: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx>コメントにすることがありますもかアップ投票関連の問題を[課題追跡システム](https://issues.apache.org/jira/browse/CB-2083)で
+
+  * 無視、 `mediaType` のプロパティ `cameraOptions` として Windows Phone SDK には、フォト ライブラリからビデオを選択する方法は行いません。
+
+## CameraError
+
+エラー メッセージを提供する onError コールバック関数。
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+#### 解説
+
+  * **message**: メッセージは、デバイスのネイティブ コードによって提供されます。*(文字列)*
+
+## cameraSuccess
+
+画像データを提供する onSuccess コールバック関数。
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+#### 解説
+
+  * **imagedata を扱う**: Base64 エンコード イメージのデータ、*または*画像ファイルによって URI の `cameraOptions` 効果。*(文字列)*
+
+#### 例
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+`Navigator.camera.getPicture` によって作成されたポップオーバーパン ダイアログ ボックスへのハンドル.
+
+#### 解説
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### サポートされているプラットフォーム
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### 例
+
+     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 だけ指定パラメーターをポップ オーバーのアンカー要素の場所および矢印方向計算されたライブラリまたはアルバムから画像を選択するとき。
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+#### 解説
+
+  * **x**: ピクセルの x 座標画面要素にポップ オーバーのアンカーになります。*(数)*
+
+  * **y**: y ピクセル座標の画面要素にポップ オーバーのアンカーになります。*(数)*
+
+  * **width**: ポップ オーバーのアンカーになる上の画面要素のピクセル単位の幅。*(数)*
+
+  * **height**: ポップ オーバーのアンカーになる上の画面要素のピクセル単位の高さ。*(数)*
+
+  * **arrowDir**: 方向のポップ オーバーで矢印をポイントする必要があります。定義されている `Camera.PopoverArrowDirection` *(番号)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+矢印の方向と、画面の向きを調整するポップ オーバーのサイズを変更可能性がありますに注意してください。 アンカー要素の位置を指定するときの方向の変化を考慮することを確認します。
+
+## navigator.camera.cleanup
+
+削除中間一時ストレージからカメラで撮影した写真。
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+#### 解説
+
+`camera.getPicture` を呼び出した後一時記憶域に保存されている中間画像ファイルを削除します。 `Camera.sourceType` の値が `Camera.PictureSourceType.CAMERA` に等しい、`Camera.destinationType` が `Camera.DestinationType.FILE_URI` と等しいの場合にのみ適用されます。.
+
+#### サポートされているプラットフォーム
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### 例
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 434 - 0
miaomiao/plugins/cordova-plugin-camera/doc/ja/index.md

xqd
@@ -0,0 +1,434 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+このプラグインは、写真を撮るため、システムのイメージ ライブラリからイメージを選択するために API を提供します、グローバル `navigator.camera` オブジェクトを定義します。
+
+オブジェクトは、グローバル スコープの `ナビゲーター` に添付、それがないまで `deviceready` イベントの後。
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## インストール
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+カメラを使用して写真を取るか、デバイスの画像ギャラリーから写真を取得します。 イメージが渡されます成功時のコールバックを base64 エンコードされた `文字列`、または、URI としてイメージ ファイル。 メソッド自体はファイル選択ポップ オーバーの位置を変更するために使用できる `CameraPopoverHandle` オブジェクトを返します。
+
+    navigator.camera.getPicture( cameraSuccess, cameraError, cameraOptions );
+    
+
+### 解説
+
+`camera.getPicture` 関数は、ユーザーの写真をスナップすることができますデバイスのデフォルト カメラ アプリケーションを開きます。 `Camera.sourceType` が `Camera.PictureSourceType.CAMERA` と等しい場合既定では、この現象が発生します。 ユーザーは写真をスナップ、カメラ アプリケーションを閉じるし、アプリケーションが復元されます。
+
+`Camera.sourceType` `Camera.PictureSourceType.PHOTOLIBRARY` または `Camera.PictureSourceType.SAVEDPHOTOALBUM` の場合、ダイアログ ボックスはユーザーを既存のイメージを選択することができますが表示されます。 `camera.getPicture` 関数は、デバイスの向きが変更されたとき、たとえば、イメージの選択ダイアログには、位置を変更するために使用することができます、`CameraPopoverHandle` オブジェクトを返します。
+
+戻り値が `cameraSuccess` コールバック関数の指定 `cameraOptions` に応じて、次の形式のいずれかに送信されます。
+
+*   A `String` 写真の base64 でエンコードされたイメージを含んでいます。
+
+*   A `String` (既定値) のローカル記憶域上のイメージ ファイルの場所を表します。
+
+自由に変更、エンコードされたイメージ、または URI などを行うことができます。
+
+*   イメージをレンダリングする `<img>` 以下の例のように、タグ
+
+*   ローカル データの保存 ( `LocalStorage` 、 [Lawnchair][1]など)。
+
+*   リモート サーバーにデータを投稿します。
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**注**: 新しいデバイス上の写真の解像度はかなり良いです。 デバイスのギャラリーから選択した写真は `quality` パラメーターが指定されて場合でも下方の品質に縮小されません。 一般的なメモリの問題を避けるために `DATA_URL` ではなく `FILE_URI` に `Camera.destinationType` を設定します。.
+
+### サポートされているプラットフォーム
+
+*   アマゾン火 OS
+*   アンドロイド
+*   ブラックベリー 10
+*   ブラウザー
+*   Firefox の OS
+*   iOS
+*   Tizen
+*   Windows Phone 7 と 8
+*   Windows 8
+
+### 環境設定 (iOS)
+
+*   **CameraUsesGeolocation**(ブール値、デフォルトは false)。 Jpeg 画像をキャプチャするため EXIF ヘッダーで地理位置情報データを取得する場合は true に設定します。 これは、場合地理位置情報のアクセス許可に対する要求をトリガーする true に設定します。
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### アマゾン火 OS 癖
+
+アマゾン火 OS イメージをキャプチャするデバイス上のカメラの活動を開始する意図を使用して、メモリの少ない携帯電話、コルドバ活動が殺されるかもしれない。 このシナリオではコルドバ活動が復元されると、イメージが表示されません。
+
+### Android の癖
+
+アンドロイド、イメージをキャプチャするデバイス上でカメラのアクティビティを開始する意図を使用し、メモリの少ない携帯電話、コルドバ活動が殺されるかもしれない。 このシナリオではコルドバ活動が復元されると、イメージが表示されません。
+
+### ブラウザーの癖
+
+Base64 エンコード イメージとして写真を返すのみことができます。
+
+### Firefox OS 癖
+
+カメラのプラグインは現在、[Web アクティビティ][2] を使用して実装されていた.
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### iOS の癖
+
+コールバック関数のいずれかの JavaScript `alert()` を含む問題が発生することができます。 IOS イメージ ピッカーまたは完全が終了するまで、警告が表示されますポップ オーバーを許可する `setTimeout()` 内でアラートをラップします。
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+### Windows Phone 7 の癖
+
+ネイティブ カメラ アプリケーションを呼び出すと、デバイスが Zune を介して接続されている動作しませんし、エラー コールバックをトリガーします。
+
+### Tizen の癖
+
+Tizen のみ `Camera.DestinationType.FILE_URI` の `destinationType` と `Camera.PictureSourceType.PHOTOLIBRARY` の `sourceType` をサポートしています.
+
+### 例
+
+写真を撮るし、base64 エンコード イメージとして取得します。
+
+    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);
+    }
+    
+
+写真を撮るし、イメージのファイルの場所を取得します。
+
+    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
+
+カメラの設定をカスタマイズするオプションのパラメーター。
+
+    { 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 };
+    
+
+### オプション
+
+*   **quality**: 0-100、100 がファイルの圧縮から損失なしで通常のフル解像度の範囲で表される、保存されたイメージの品質。 既定値は 50 です。 *(数)*(カメラの解像度についての情報が利用できないことに注意してください)。
+
+*   **destinationType**: 戻り値の形式を選択します。既定値は FILE_URI です。定義されている `navigator.camera.DestinationType` *(番号)*
+    
+        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**: 画像のソースを設定します。既定値は、カメラです。定義されている `navigator.camera.PictureSourceType` *(番号)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **allowEdit**: 単純な選択の前に画像の編集を許可します。*(ブール値)*
+
+*   **encodingType**: 返されるイメージ ファイルのエンコーディングを選択します。デフォルトは JPEG です。定義されている `navigator.camera.EncodingType` *(番号)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **targetWidth**: スケール イメージにピクセル単位の幅。**TargetHeight**を使用する必要があります。縦横比は変わりません。*(数)*
+
+*   **targetHeight**: スケール イメージにピクセル単位の高さ。**TargetWidth**を使用する必要があります。縦横比は変わりません。*(数)*
+
+*   **mediaType**: から選択するメディアの種類を設定します。 場合にのみ働きます `PictureSourceType` は `PHOTOLIBRARY` または `SAVEDPHOTOALBUM` 。 定義されている `nagivator.camera.MediaType` *(番号)*
+    
+        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**: キャプチャ中に、デバイスの向きを修正する画像を回転させます。*(ブール値)*
+
+*   **saveToPhotoAlbum**: キャプチャ後、デバイス上のフォト アルバムに画像を保存します。*(ブール値)*
+
+*   **popoverOptions**: iPad のポップ オーバーの場所を指定する iOS のみのオプションです。定義されています。`CameraPopoverOptions`.
+
+*   **cameraDirection**: (前面または背面側) を使用するカメラを選択します。既定値は戻るです。定義されている `navigator.camera.Direction` *(番号)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### アマゾン火 OS 癖
+
+*   任意 `cameraDirection` 背面写真で結果の値します。
+
+*   無視、 `allowEdit` パラメーター。
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY``Camera.PictureSourceType.SAVEDPHOTOALBUM`両方のアルバムが表示されます同じ写真。
+
+### Android の癖
+
+*   任意 `cameraDirection` 背面写真で結果の値します。
+
+*   無視、 `allowEdit` パラメーター。
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY``Camera.PictureSourceType.SAVEDPHOTOALBUM`両方のアルバムが表示されます同じ写真。
+
+### ブラックベリー 10 癖
+
+*   無視、 `quality` パラメーター。
+
+*   無視、 `allowEdit` パラメーター。
+
+*   `Camera.MediaType`サポートされていません。
+
+*   無視、 `correctOrientation` パラメーター。
+
+*   無視、 `cameraDirection` パラメーター。
+
+### Firefox OS 癖
+
+*   無視、 `quality` パラメーター。
+
+*   `Camera.DestinationType`無視され、等しい `1` (イメージ ファイル URI)
+
+*   無視、 `allowEdit` パラメーター。
+
+*   無視、 `PictureSourceType` パラメーター (ユーザーが選択ダイアログ ウィンドウに)
+
+*   無視します、`encodingType`
+
+*   無視、 `targetWidth` と`targetHeight`
+
+*   `Camera.MediaType`サポートされていません。
+
+*   無視、 `correctOrientation` パラメーター。
+
+*   無視、 `cameraDirection` パラメーター。
+
+### iOS の癖
+
+*   設定 `quality` 一部のデバイスでメモリ不足エラーを避けるために 50 の下。
+
+*   使用する場合 `destinationType.FILE_URI` 、写真、アプリケーションの一時ディレクトリに保存されます。アプリケーションの一時ディレクトリの内容は、アプリケーションの終了時に削除されます。
+
+### Tizen の癖
+
+*   サポートされていないオプション
+
+*   常にファイルの URI を返す
+
+### Windows Phone 7 と 8 癖
+
+*   無視、 `allowEdit` パラメーター。
+
+*   無視、 `correctOrientation` パラメーター。
+
+*   無視、 `cameraDirection` パラメーター。
+
+*   無視、 `saveToPhotoAlbum` パラメーター。 重要: wp7/8 コルドバ カメラ API で撮影したすべての画像は携帯電話のカメラ巻き物に常にコピーします。 ユーザーの設定に応じて、これも、画像はその OneDrive に自動アップロードを意味できます。 イメージは意図したアプリより広い聴衆に利用できる可能性があります可能性があります。 場合は、このアプリケーションのブロッカー、msdn で説明されているように、CameraCaptureTask を実装する必要があります: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx>コメントにすることがありますもかアップ投票関連の問題を[課題追跡システム][3]で
+
+*   無視、 `mediaType` のプロパティ `cameraOptions` として Windows Phone SDK には、フォト ライブラリからビデオを選択する方法は行いません。
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+エラー メッセージを提供する onError コールバック関数。
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+### パラメーター
+
+*   **message**: メッセージは、デバイスのネイティブ コードによって提供されます。*(文字列)*
+
+## cameraSuccess
+
+画像データを提供する onSuccess コールバック関数。
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+### パラメーター
+
+*   **imagedata を扱う**: Base64 エンコード イメージのデータ、*または*画像ファイルによって URI の `cameraOptions` 効果。*(文字列)*
+
+### 例
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+`Navigator.camera.getPicture` によって作成されたポップオーバーパン ダイアログ ボックスへのハンドル.
+
+### メソッド
+
+*   **setPosition**: ポップ オーバーの位置を設定します。
+
+### サポートされているプラットフォーム
+
+*   iOS
+
+### setPosition
+
+ポップ オーバーの位置を設定します。
+
+**パラメーター**:
+
+*   `cameraPopoverOptions`:、 `CameraPopoverOptions` の新しい位置を指定します。
+
+### 例
+
+     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 だけ指定パラメーターをポップ オーバーのアンカー要素の場所および矢印方向計算されたライブラリまたはアルバムから画像を選択するとき。
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+### CameraPopoverOptions
+
+*   **x**: ピクセルの x 座標画面要素にポップ オーバーのアンカーになります。*(数)*
+
+*   **y**: y ピクセル座標の画面要素にポップ オーバーのアンカーになります。*(数)*
+
+*   **width**: ポップ オーバーのアンカーになる上の画面要素のピクセル単位の幅。*(数)*
+
+*   **height**: ポップ オーバーのアンカーになる上の画面要素のピクセル単位の高さ。*(数)*
+
+*   **arrowDir**: 方向のポップ オーバーで矢印をポイントする必要があります。定義されている `Camera.PopoverArrowDirection` *(番号)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+矢印の方向と、画面の向きを調整するポップ オーバーのサイズを変更可能性がありますに注意してください。 アンカー要素の位置を指定するときの方向の変化を考慮することを確認します。
+
+## navigator.camera.cleanup
+
+削除中間一時ストレージからカメラで撮影した写真。
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+### 説明
+
+`camera.getPicture` を呼び出した後一時記憶域に保存されている中間画像ファイルを削除します。 `Camera.sourceType` の値が `Camera.PictureSourceType.CAMERA` に等しい、`Camera.destinationType` が `Camera.DestinationType.FILE_URI` と等しいの場合にのみ適用されます。.
+
+### サポートされているプラットフォーム
+
+*   iOS
+
+### 例
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 421 - 0
miaomiao/plugins/cordova-plugin-camera/doc/ko/README.md

xqd
@@ -0,0 +1,421 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+이 플러그인 시스템의 이미지 라이브러리에서 이미지를 선택 및 사진 촬영을 위한 API를 제공 하는 글로벌 `navigator.camera` 개체를 정의 합니다.
+
+개체 `navigator` 글로벌 범위 첨부 아니에요 때까지 사용할 수 있는 `deviceready` 이벤트 후.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## 설치
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * 카메라 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * navigator.camera.cleanup
+
+## navigator.camera.getPicture
+
+카메라를 사용 하 여 사진을 걸립니다 또는 소자의 이미지 갤러리에서 사진을 검색 합니다. 이미지는 성공 콜백에 전달 base64 인코딩된 `문자열` 또는 URI로 이미지 파일에 대 한. 방법 자체는 파일 선택 popover 위치를 사용할 수 있는 `CameraPopoverHandle` 개체를 반환 합니다.
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### 설명
+
+`Camera.getPicture` 함수 스냅 사진을 사용자가 소자의 기본 카메라 응용 프로그램을 엽니다. 이 문제는 `Camera.sourceType` `Camera.PictureSourceType.CAMERA` 경우 기본적으로 발생 합니다. 일단 사용자 스냅 사진, 카메라 응용 프로그램 종료 하 고 응용 프로그램 복원 됩니다.
+
+`Camera.sourceType`은 `Camera.PictureSourceType.PHOTOLIBRARY` 또는 `Camera.PictureSourceType.SAVEDPHOTOALBUM`, 대화 상자가 사용자가 기존 이미지를 선택할 수 있도록 표시 됩니다. `camera.getPicture` 함수는 장치 방향 변경 될 때 이미지 선택 대화 상자, 예를 들어, 위치를 변경 하려면 사용할 수 있는 `CameraPopoverHandle` 개체를 반환 합니다.
+
+반환 값은 `cameraSuccess` 콜백 함수 지정된 `cameraOptions`에 따라 다음 형식 중 하나에 전송 됩니다.
+
+  * A `String` base64 인코딩된 사진 이미지를 포함 합니다.
+
+  * A `String` 로컬 저장소 (기본값)의 이미지 파일 위치를 나타내는.
+
+할 수 있는 당신이 원하는대로 인코딩된 이미지 또는 URI, 예를 들면:
+
+  * 렌더링 이미지는 `<img>` 아래 예제와 같이 태그
+
+  * 로컬로 데이터를 저장 ( `LocalStorage` , [Lawnchair](http://brianleroux.github.com/lawnchair/), 등.)
+
+  * 원격 서버에 데이터 게시
+
+**참고**: 더 새로운 장치에 사진 해상도 아주 좋은. 소자의 갤러리에서 선택 된 사진 `품질` 매개 변수를 지정 하는 경우에 낮은 품질에 관하여 하지는. 일반적인 메모리 문제를 피하기 위해 `DATA_URL` 보다 `FILE_URI` `Camera.destinationType` 설정.
+
+#### 지원 되는 플랫폼
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### 예를 들어
+
+촬영 및 base64 인코딩 이미지로 검색:
+
+    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);
+    }
+    
+
+촬영 하 고 이미지의 파일 위치를 검색:
+
+    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);
+    }
+    
+
+#### 환경 설정 (iOS)
+
+  * **CameraUsesGeolocation** (boolean, 기본값: false)입니다. 캡처 Jpeg, EXIF 헤더에 지리적 데이터를 true로 설정 합니다. 이 경우 위치 정보 사용 권한에 대 한 요청을 일으킬 것 이다 true로 설정 합니다.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### 아마존 화재 OS 단점
+
+아마존 화재 OS 의도 사용 하 여 이미지 캡처 장치에서 카메라 활동을 시작 하 고 낮은 메모리와 휴대 전화에 코르 도우 바 활동 살해 수 있습니다. 코르도바 활동 복원 되 면이 시나리오에서는 이미지가 나타나지 않을 수 있습니다.
+
+#### 안 드 로이드 단점
+
+안 드 로이드 의도 사용 하 여 이미지 캡처 장치에서 카메라 활동을 시작 하 고 낮은 메모리와 휴대 전화에 코르 도우 바 활동 살해 수 있습니다. 코르도바 활동 복원 되 면이 시나리오에서는 이미지가 나타나지 않을 수 있습니다.
+
+#### 브라우저 만지면
+
+수 base64 인코딩 이미지로 사진을 반환 합니다.
+
+#### 파이어 폭스 OS 단점
+
+카메라 플러그인은 현재 [웹 활동](https://hacks.mozilla.org/2013/01/introducing-web-activities/)를 사용 하 여 구현.
+
+#### iOS 단점
+
+자바 `alert()`를 포함 하 여 콜백 함수 중 하나에 문제가 발생할 수 있습니다. 포장 허용 iOS 이미지 피커 또는 popover를 완벽 하 게 경고를 표시 하기 전에 닫습니다 `setTimeout()` 내에서 경고:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+#### Windows Phone 7 단점
+
+장치 Zune 통해 연결 된 동안 네이티브 카메라 응용 프로그램을 호출 하면 작동 하지 않습니다 하 고 오류 콜백 트리거합니다.
+
+#### Tizen 특수
+
+`Camera.DestinationType.FILE_URI`의 `destinationType`와 `Camera.PictureSourceType.PHOTOLIBRARY`의 `sourceType` Tizen 지원.
+
+## CameraOptions
+
+카메라 설정을 사용자 지정 하는 선택적 매개 변수.
+
+    { 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 };
+    
+
+  * **품질**: 범위 0-100, 100은 파일 압축에서 손실 없이 일반적으로 전체 해상도 저장된 된 이미지의 품질. 기본값은 50입니다. *(수)* (Note 카메라의 해상도 대 한 정보는 사용할 수 없습니다.)
+
+  * **destinationType**: 반환 값의 형식을 선택 합니다. 기본값은 FILE_URI입니다. 에 정의 된 `navigator.camera.DestinationType` *(수)*
+    
+        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**: 그림의 소스를 설정 합니다. 기본값은 카메라입니다. 에 정의 된 `navigator.camera.PictureSourceType` *(수)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **allowEdit**: 선택 하기 전에 이미지의 간단한 편집을 허용 합니다. *(부울)*
+
+  * **encodingType**: 반환 된 이미지 파일의 인코딩을 선택 합니다. 기본값은 JPEG입니다. 에 정의 된 `navigator.camera.EncodingType` *(수)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **targetWidth**: 스케일 이미지를 픽셀 너비. **TargetHeight**와 함께 사용 해야 합니다. 가로 세로 비율이 일정 하 게 유지 합니다. *(수)*
+
+  * **targetHeight**: 스케일 이미지를 픽셀 단위로 높이. **TargetWidth**와 함께 사용 해야 합니다. 가로 세로 비율이 일정 하 게 유지 합니다. *(수)*
+
+  * **mediaType**:에서 선택 미디어 유형을 설정 합니다. 때에 작동 `PictureSourceType` 는 `PHOTOLIBRARY` 또는 `SAVEDPHOTOALBUM` . 에 정의 된 `nagivator.camera.MediaType` *(수)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. 기본입니다. 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**: 캡처 도중 장치의 방향에 대 한 해결 하기 위해 이미지를 회전 합니다. *(부울)*
+
+  * **saveToPhotoAlbum**: 캡처 후 장치에서 사진 앨범에 이미지를 저장 합니다. *(부울)*
+
+  * **popoverOptions**: iPad에 popover 위치를 지정 하는 iOS 전용 옵션. 에 정의 된`CameraPopoverOptions`.
+
+  * **cameraDirection**: (앞 이나 뒤로-연결)를 사용 하 여 카메라를 선택 하십시오. 기본값은 다시. 에 정의 된 `navigator.camera.Direction` *(수)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### 아마존 화재 OS 단점
+
+  * 어떤 `cameraDirection` 다시 연결 사진에 결과 값.
+
+  * 무시는 `allowEdit` 매개 변수.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`그리고 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 둘 다 동일한 사진 앨범을 표시 합니다.
+
+#### 안 드 로이드 단점
+
+  * 어떤 `cameraDirection` 다시 연결 사진에 결과 값.
+
+  * 안 드 로이드도 사용 자르기 활동 allowEdit, 비록 작물 작업과 실제로 코르도바, 유일 하 게 작품 지속적으로 구글 플러스 사진 응용 프로그램과 함께 번들로 제공 하는 것은 등을 맞댄 자른된 이미지를 전달 해야 합니다. 다른 작물은 작동 하지 않을 수 있습니다.
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`그리고 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 둘 다 동일한 사진 앨범을 표시 합니다.
+
+#### 블랙베리 10 단점
+
+  * 무시는 `quality` 매개 변수.
+
+  * 무시는 `allowEdit` 매개 변수.
+
+  * `Camera.MediaType`지원 되지 않습니다.
+
+  * 무시는 `correctOrientation` 매개 변수.
+
+  * 무시는 `cameraDirection` 매개 변수.
+
+#### 파이어 폭스 OS 단점
+
+  * 무시는 `quality` 매개 변수.
+
+  * `Camera.DestinationType`무시 되 고 `1` (이미지 파일 URI)
+
+  * 무시는 `allowEdit` 매개 변수.
+
+  * 무시는 `PictureSourceType` 매개 변수 (사용자가 선택 그것 대화 창에서)
+
+  * 무시 하는`encodingType`
+
+  * 무시는 `targetWidth` 와`targetHeight`
+
+  * `Camera.MediaType`지원 되지 않습니다.
+
+  * 무시는 `correctOrientation` 매개 변수.
+
+  * 무시는 `cameraDirection` 매개 변수.
+
+#### iOS 단점
+
+  * 설정 `quality` 일부 장치 메모리 오류를 피하기 위해 50 아래.
+
+  * 사용 하는 경우 `destinationType.FILE_URI` , 사진 응용 프로그램의 임시 디렉터리에 저장 됩니다. 응용 프로그램이 종료 될 때 응용 프로그램의 임시 디렉터리의 내용은 삭제 됩니다.
+
+#### Tizen 특수
+
+  * 지원 되지 않는 옵션
+
+  * 항상 파일 URI를 반환 합니다.
+
+#### Windows Phone 7, 8 특수
+
+  * 무시는 `allowEdit` 매개 변수.
+
+  * 무시는 `correctOrientation` 매개 변수.
+
+  * 무시는 `cameraDirection` 매개 변수.
+
+  * 무시는 `saveToPhotoAlbum` 매개 변수. 중요: 모든 이미지 API wp7/8 코르도바 카메라로 촬영 항상 복사 됩니다 휴대 전화의 카메라 롤에. 사용자의 설정에 따라이 또한 그들의 OneDrive에 자동 업로드 이미지는 의미. 이 잠재적으로 이미지는 당신의 애플 리 케이 션을 위한 보다 넓은 청중에 게 사용할 수 있는 의미. 이 경우 응용 프로그램에 대 한 차단, 당신은 msdn에 설명 대로 단말기를 구현 해야 합니다: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> 수 있습니다 또한 의견 또는 [이슈 트래커](https://issues.apache.org/jira/browse/CB-2083) 에서 업-투표 관련된 문제
+
+  * 무시는 `mediaType` 속성을 `cameraOptions` 으로 Windows Phone SDK PHOTOLIBRARY에서 비디오를 선택 하는 방법을 제공 하지 않습니다.
+
+## CameraError
+
+오류 메시지를 제공 하는 onError 콜백 함수.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+#### 설명
+
+  * **메시지**: 메시지는 장치의 네이티브 코드에 의해 제공 됩니다. *(문자열)*
+
+## cameraSuccess
+
+이미지 데이터를 제공 하는 onSuccess 콜백 함수.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+#### 설명
+
+  * **imageData**: Base64 인코딩은 이미지 데이터, *또는* 이미지 파일에 따라 URI의 `cameraOptions` 적용. *(문자열)*
+
+#### 예를 들어
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+`navigator.camera.getPicture`에 의해 만들어진 popover 대화에 대 한 핸들.
+
+#### 설명
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### 지원 되는 플랫폼
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### 예를 들어
+
+     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 전용 매개 변수 iPad의 보관 함 또는 앨범에서 이미지를 선택 하면 앵커 요소 위치와 화살표의 방향으로 popover 지정 하는.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+#### 설명
+
+  * **x**: x는 popover 앵커는 화면 요소의 픽셀 좌표. *(수)*
+
+  * **y**: y 픽셀 좌표는 popover 앵커는 화면 요소입니다. *(수)*
+
+  * **폭**: 폭 (픽셀)는 popover 앵커는 화면 요소. *(수)*
+
+  * **높이**: 높이 (픽셀)는 popover 앵커는 화면 요소. *(수)*
+
+  * **arrowDir**: 방향 화살표는 popover 가리켜야 합니다. 에 정의 된 `Camera.PopoverArrowDirection` *(수)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+참고는 popover의 크기 조정 화살표 방향 및 화면 방향 변경 될 수 있습니다. 앵커 요소 위치를 지정 하는 경우 방향 변경에 대 한 계정에 있는지 확인 합니다.
+
+## navigator.camera.cleanup
+
+제거 임시 저장소에서 카메라로 찍은 사진을 중간.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+#### 설명
+
+`camera.getPicture`를 호출한 후 임시 저장소에 보관 됩니다 중간 이미지 파일을 제거 합니다. `Camera.sourceType` 값은 `Camera.PictureSourceType.CAMERA` 및 `Camera.destinationType`와 `Camera.DestinationType.FILE_URI` 때만 적용 됩니다..
+
+#### 지원 되는 플랫폼
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### 예를 들어
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 434 - 0
miaomiao/plugins/cordova-plugin-camera/doc/ko/index.md

xqd
@@ -0,0 +1,434 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+이 플러그인 시스템의 이미지 라이브러리에서 이미지를 선택 및 사진 촬영을 위한 API를 제공 하는 글로벌 `navigator.camera` 개체를 정의 합니다.
+
+개체 `navigator` 글로벌 범위 첨부 아니에요 때까지 사용할 수 있는 `deviceready` 이벤트 후.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## 설치
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+카메라를 사용 하 여 사진을 걸립니다 또는 소자의 이미지 갤러리에서 사진을 검색 합니다. 이미지는 성공 콜백에 전달 base64 인코딩된 `문자열` 또는 URI로 이미지 파일에 대 한. 방법 자체는 파일 선택 popover 위치를 사용할 수 있는 `CameraPopoverHandle` 개체를 반환 합니다.
+
+    navigator.camera.getPicture( cameraSuccess, cameraError, cameraOptions );
+    
+
+### 설명
+
+`Camera.getPicture` 함수 스냅 사진을 사용자가 소자의 기본 카메라 응용 프로그램을 엽니다. 이 문제는 `Camera.sourceType` `Camera.PictureSourceType.CAMERA` 경우 기본적으로 발생 합니다. 일단 사용자 스냅 사진, 카메라 응용 프로그램 종료 하 고 응용 프로그램 복원 됩니다.
+
+`Camera.sourceType`은 `Camera.PictureSourceType.PHOTOLIBRARY` 또는 `Camera.PictureSourceType.SAVEDPHOTOALBUM`, 대화 상자가 사용자가 기존 이미지를 선택할 수 있도록 표시 됩니다. `camera.getPicture` 함수는 장치 방향 변경 될 때 이미지 선택 대화 상자, 예를 들어, 위치를 변경 하려면 사용할 수 있는 `CameraPopoverHandle` 개체를 반환 합니다.
+
+반환 값은 `cameraSuccess` 콜백 함수 지정된 `cameraOptions`에 따라 다음 형식 중 하나에 전송 됩니다.
+
+*   A `String` base64 인코딩된 사진 이미지를 포함 합니다.
+
+*   A `String` 로컬 저장소 (기본값)의 이미지 파일 위치를 나타내는.
+
+할 수 있는 당신이 원하는대로 인코딩된 이미지 또는 URI, 예를 들면:
+
+*   렌더링 이미지는 `<img>` 아래 예제와 같이 태그
+
+*   로컬로 데이터를 저장 ( `LocalStorage` , [Lawnchair][1], 등.)
+
+*   원격 서버에 데이터 게시
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**참고**: 더 새로운 장치에 사진 해상도 아주 좋은. 소자의 갤러리에서 선택 된 사진 `품질` 매개 변수를 지정 하는 경우에 낮은 품질에 관하여 하지는. 일반적인 메모리 문제를 피하기 위해 `DATA_URL` 보다 `FILE_URI` `Camera.destinationType` 설정.
+
+### 지원 되는 플랫폼
+
+*   아마존 화재 운영 체제
+*   안 드 로이드
+*   블랙베리 10
+*   브라우저
+*   Firefox 운영 체제
+*   iOS
+*   Tizen
+*   Windows Phone 7과 8
+*   윈도우 8
+
+### 환경 설정 (iOS)
+
+*   **CameraUsesGeolocation** (boolean, 기본값: false)입니다. 캡처 Jpeg, EXIF 헤더에 지리적 데이터를 true로 설정 합니다. 이 경우 위치 정보 사용 권한에 대 한 요청을 일으킬 것 이다 true로 설정 합니다.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### 아마존 화재 OS 단점
+
+아마존 화재 OS 의도 사용 하 여 이미지 캡처 장치에서 카메라 활동을 시작 하 고 낮은 메모리와 휴대 전화에 코르 도우 바 활동 살해 수 있습니다. 코르도바 활동 복원 되 면이 시나리오에서는 이미지가 나타나지 않을 수 있습니다.
+
+### 안 드 로이드 단점
+
+안 드 로이드 의도 사용 하 여 이미지 캡처 장치에서 카메라 활동을 시작 하 고 낮은 메모리와 휴대 전화에 코르 도우 바 활동 살해 수 있습니다. 코르도바 활동 복원 되 면이 시나리오에서는 이미지가 나타나지 않을 수 있습니다.
+
+### 브라우저 만지면
+
+수 base64 인코딩 이미지로 사진을 반환 합니다.
+
+### 파이어 폭스 OS 단점
+
+카메라 플러그인은 현재 [웹 활동][2]를 사용 하 여 구현.
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### iOS 단점
+
+자바 `alert()`를 포함 하 여 콜백 함수 중 하나에 문제가 발생할 수 있습니다. 포장 허용 iOS 이미지 피커 또는 popover를 완벽 하 게 경고를 표시 하기 전에 닫습니다 `setTimeout()` 내에서 경고:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+### Windows Phone 7 단점
+
+장치 Zune 통해 연결 된 동안 네이티브 카메라 응용 프로그램을 호출 하면 작동 하지 않습니다 하 고 오류 콜백 트리거합니다.
+
+### Tizen 특수
+
+`Camera.DestinationType.FILE_URI`의 `destinationType`와 `Camera.PictureSourceType.PHOTOLIBRARY`의 `sourceType` Tizen 지원.
+
+### 예를 들어
+
+촬영 및 base64 인코딩 이미지로 검색:
+
+    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);
+    }
+    
+
+촬영 하 고 이미지의 파일 위치를 검색:
+
+    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
+
+카메라 설정을 사용자 지정 하는 선택적 매개 변수.
+
+    { 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 };
+    
+
+### 옵션
+
+*   **품질**: 범위 0-100, 100은 파일 압축에서 손실 없이 일반적으로 전체 해상도 저장된 된 이미지의 품질. 기본값은 50입니다. *(수)* (Note 카메라의 해상도 대 한 정보는 사용할 수 없습니다.)
+
+*   **destinationType**: 반환 값의 형식을 선택 합니다. 기본값은 FILE_URI입니다. 에 정의 된 `navigator.camera.DestinationType` *(수)*
+    
+        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**: 그림의 소스를 설정 합니다. 기본값은 카메라입니다. 에 정의 된 `navigator.camera.PictureSourceType` *(수)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **allowEdit**: 선택 하기 전에 이미지의 간단한 편집을 허용 합니다. *(부울)*
+
+*   **encodingType**: 반환 된 이미지 파일의 인코딩을 선택 합니다. 기본값은 JPEG입니다. 에 정의 된 `navigator.camera.EncodingType` *(수)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **targetWidth**: 스케일 이미지를 픽셀 너비. **TargetHeight**와 함께 사용 해야 합니다. 가로 세로 비율이 일정 하 게 유지 합니다. *(수)*
+
+*   **targetHeight**: 스케일 이미지를 픽셀 단위로 높이. **TargetWidth**와 함께 사용 해야 합니다. 가로 세로 비율이 일정 하 게 유지 합니다. *(수)*
+
+*   **mediaType**:에서 선택 미디어 유형을 설정 합니다. 때에 작동 `PictureSourceType` 는 `PHOTOLIBRARY` 또는 `SAVEDPHOTOALBUM` . 에 정의 된 `nagivator.camera.MediaType` *(수)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. 기본입니다. 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**: 캡처 도중 장치의 방향에 대 한 해결 하기 위해 이미지를 회전 합니다. *(부울)*
+
+*   **saveToPhotoAlbum**: 캡처 후 장치에서 사진 앨범에 이미지를 저장 합니다. *(부울)*
+
+*   **popoverOptions**: iPad에 popover 위치를 지정 하는 iOS 전용 옵션. 에 정의 된`CameraPopoverOptions`.
+
+*   **cameraDirection**: (앞 이나 뒤로-연결)를 사용 하 여 카메라를 선택 하십시오. 기본값은 다시. 에 정의 된 `navigator.camera.Direction` *(수)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### 아마존 화재 OS 단점
+
+*   어떤 `cameraDirection` 다시 연결 사진에 결과 값.
+
+*   무시는 `allowEdit` 매개 변수.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`그리고 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 둘 다 동일한 사진 앨범을 표시 합니다.
+
+### 안 드 로이드 단점
+
+*   어떤 `cameraDirection` 다시 연결 사진에 결과 값.
+
+*   무시는 `allowEdit` 매개 변수.
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`그리고 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 둘 다 동일한 사진 앨범을 표시 합니다.
+
+### 블랙베리 10 단점
+
+*   무시는 `quality` 매개 변수.
+
+*   무시는 `allowEdit` 매개 변수.
+
+*   `Camera.MediaType`지원 되지 않습니다.
+
+*   무시는 `correctOrientation` 매개 변수.
+
+*   무시는 `cameraDirection` 매개 변수.
+
+### 파이어 폭스 OS 단점
+
+*   무시는 `quality` 매개 변수.
+
+*   `Camera.DestinationType`무시 되 고 `1` (이미지 파일 URI)
+
+*   무시는 `allowEdit` 매개 변수.
+
+*   무시는 `PictureSourceType` 매개 변수 (사용자가 선택 그것 대화 창에서)
+
+*   무시 하는`encodingType`
+
+*   무시는 `targetWidth` 와`targetHeight`
+
+*   `Camera.MediaType`지원 되지 않습니다.
+
+*   무시는 `correctOrientation` 매개 변수.
+
+*   무시는 `cameraDirection` 매개 변수.
+
+### iOS 단점
+
+*   설정 `quality` 일부 장치 메모리 오류를 피하기 위해 50 아래.
+
+*   사용 하는 경우 `destinationType.FILE_URI` , 사진 응용 프로그램의 임시 디렉터리에 저장 됩니다. 응용 프로그램이 종료 될 때 응용 프로그램의 임시 디렉터리의 내용은 삭제 됩니다.
+
+### Tizen 특수
+
+*   지원 되지 않는 옵션
+
+*   항상 파일 URI를 반환 합니다.
+
+### Windows Phone 7, 8 특수
+
+*   무시는 `allowEdit` 매개 변수.
+
+*   무시는 `correctOrientation` 매개 변수.
+
+*   무시는 `cameraDirection` 매개 변수.
+
+*   무시는 `saveToPhotoAlbum` 매개 변수. 중요: 모든 이미지 API wp7/8 코르도바 카메라로 촬영 항상 복사 됩니다 휴대 전화의 카메라 롤에. 사용자의 설정에 따라이 또한 그들의 OneDrive에 자동 업로드 이미지는 의미. 이 잠재적으로 이미지는 당신의 애플 리 케이 션을 위한 보다 넓은 청중에 게 사용할 수 있는 의미. 이 경우 응용 프로그램에 대 한 차단, 당신은 msdn에 설명 대로 단말기를 구현 해야 합니다: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> 수 있습니다 또한 의견 또는 [이슈 트래커][3] 에서 업-투표 관련된 문제
+
+*   무시는 `mediaType` 속성을 `cameraOptions` 으로 Windows Phone SDK PHOTOLIBRARY에서 비디오를 선택 하는 방법을 제공 하지 않습니다.
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+오류 메시지를 제공 하는 onError 콜백 함수.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+### 매개 변수
+
+*   **메시지**: 메시지는 장치의 네이티브 코드에 의해 제공 됩니다. *(문자열)*
+
+## cameraSuccess
+
+이미지 데이터를 제공 하는 onSuccess 콜백 함수.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+### 매개 변수
+
+*   **imageData**: Base64 인코딩은 이미지 데이터, *또는* 이미지 파일에 따라 URI의 `cameraOptions` 적용. *(문자열)*
+
+### 예를 들어
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+`navigator.camera.getPicture`에 의해 만들어진 popover 대화에 대 한 핸들.
+
+### 메서드
+
+*   **setPosition**:는 popover의 위치를 설정 합니다.
+
+### 지원 되는 플랫폼
+
+*   iOS
+
+### setPosition
+
+popover의 위치를 설정 합니다.
+
+**매개 변수**:
+
+*   `cameraPopoverOptions`:는 `CameraPopoverOptions` 새 위치를 지정 하는
+
+### 예를 들어
+
+     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 전용 매개 변수 iPad의 보관 함 또는 앨범에서 이미지를 선택 하면 앵커 요소 위치와 화살표의 방향으로 popover 지정 하는.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+### CameraPopoverOptions
+
+*   **x**: x는 popover 앵커는 화면 요소의 픽셀 좌표. *(수)*
+
+*   **y**: y 픽셀 좌표는 popover 앵커는 화면 요소입니다. *(수)*
+
+*   **폭**: 폭 (픽셀)는 popover 앵커는 화면 요소. *(수)*
+
+*   **높이**: 높이 (픽셀)는 popover 앵커는 화면 요소. *(수)*
+
+*   **arrowDir**: 방향 화살표는 popover 가리켜야 합니다. 에 정의 된 `Camera.PopoverArrowDirection` *(수)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+참고는 popover의 크기 조정 화살표 방향 및 화면 방향 변경 될 수 있습니다. 앵커 요소 위치를 지정 하는 경우 방향 변경에 대 한 계정에 있는지 확인 합니다.
+
+## navigator.camera.cleanup
+
+제거 임시 저장소에서 카메라로 찍은 사진을 중간.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+### 설명
+
+`camera.getPicture`를 호출한 후 임시 저장소에 보관 됩니다 중간 이미지 파일을 제거 합니다. `Camera.sourceType` 값은 `Camera.PictureSourceType.CAMERA` 및 `Camera.destinationType`와 `Camera.DestinationType.FILE_URI` 때만 적용 됩니다..
+
+### 지원 되는 플랫폼
+
+*   iOS
+
+### 예를 들어
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 421 - 0
miaomiao/plugins/cordova-plugin-camera/doc/pl/README.md

xqd
@@ -0,0 +1,421 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+Ten plugin definiuje obiekt globalny `navigator.camera`, który dostarcza API do robienia zdjęć i wybór zdjęć z biblioteki obrazów systemu.
+
+Mimo, że obiekt jest dołączony do globalnego zakresu `navigator`, to nie dostępne dopiero po zdarzeniu `deviceready`.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## Instalacja
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * Aparat 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * navigator.camera.cleanup
+
+## navigator.camera.getPicture
+
+Ma zdjęcia za pomocą aparatu, lub pobiera zdjęcia z urządzenia Galeria zdjęć. Obraz jest przekazywany do wywołania zwrotnego sukces jako kodowane algorytmem base64 `ciąg`, lub identyfikator URI dla pliku obrazu. Sama metoda zwraca obiekt `CameraPopoverHandle`, który może służyć do zmiany położenia pliku wyboru popover.
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### Opis
+
+Funkcja `camera.getPicture` otwiera urządzenia domyślnej aplikacji aparat fotograficzny ów pozwala użytkownik wobec chwycić zębami kino. To zachowanie występuje domyślnie, gdy `Camera.sourceType` jest równa `Camera.PictureSourceType.CAMERA`. Gdy użytkownik zaskoczy zdjęcie, ten aparat fotograficzny applicationâ zamyka i aplikacji jest przywracany.
+
+Jeśli `Camera.sourceType` jest równe `Camera.PictureSourceType.PHOTOLIBRARY` lub `Camera.PictureSourceType.SAVEDPHOTOALBUM`, wtedy zostanie wyświetlone okno dialogowe pozwalające użytkownikowi na wybór istniejącego obrazu. Funkcja `camera.getPicture` zwraca obiekt `CameraPopoverHandle`, który obsługuje zmianę położenia okna wyboru obrazu, np. po zmianie orientacji urządzenia.
+
+Zwracana wartość jest wysyłany do funkcji wywołania zwrotnego `cameraSuccess`, w jednym z następujących formatów, w zależności od określonego `cameraOptions`:
+
+  * `String` zawierający obraz zakodowany przy pomocy base64.
+
+  * `String` reprezentujący lokalizację pliku obrazu w lokalnym magazynie (domyślnie).
+
+Może rób, co chcesz z zakodowany obraz lub identyfikatora URI, na przykład:
+
+  * Przedstawić obraz w tagu `<img>`, jak w przykładzie poniżej
+
+  * Zapisać lokalnie dane (`LocalStorage`, [Lawnchair](http://brianleroux.github.com/lawnchair/), etc.)
+
+  * Wysłać dane na zdalny serwer
+
+**Uwaga**: zdjęcie rozdzielczości na nowsze urządzenia jest bardzo dobry. Zdjęcia wybrane z galerii urządzenia są nie przeskalowanych w dół do niższej jakości, nawet jeśli określono parametr `quality`. Aby uniknąć typowych problemów z pamięci, zestaw `Camera.destinationType` `FILE_URI` zamiast `DATA_URL`.
+
+#### Obsługiwane platformy
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### Przykład
+
+Zrób zdjęcie i pobrać go jako kodowane algorytmem base64 obrazu:
+
+    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);
+    }
+    
+
+Zrób zdjęcie i pobrać lokalizacji pliku obrazu:
+
+    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);
+    }
+    
+
+#### Preferencje (iOS)
+
+  * **CameraUsesGeolocation** (boolean, wartość domyślna to false). Do przechwytywania JPEG, zestaw do true, aby uzyskać danych geolokalizacyjnych w nagłówku EXIF. To spowoduje wniosek o geolokalizacji uprawnienia, jeśli zestaw na wartość true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### Amazon ogień OS dziwactwa
+
+Amazon ogień OS używa intencje do rozpoczęcia działalności aparatu na urządzenie do przechwytywania obrazów, i na telefony z pamięci, Cordova aktywność może zostać zabity. W tym scenariuszu obraz mogą nie być wyświetlane po przywróceniu aktywności cordova.
+
+#### Dziwactwa Androida
+
+Android używa intencje do rozpoczęcia działalności aparatu na urządzenie do przechwytywania obrazów, i na telefony z pamięci, Cordova aktywność może zostać zabity. W tym scenariuszu obraz mogą nie być wyświetlane po przywróceniu aktywności Cordova.
+
+#### Quirks przeglądarki
+
+Może zwracać tylko zdjęcia jako obraz w formacie algorytmem base64.
+
+#### Firefox OS dziwactwa
+
+Aparat plugin jest obecnie implementowane za pomocą [Działania sieci Web](https://hacks.mozilla.org/2013/01/introducing-web-activities/).
+
+#### Dziwactwa iOS
+
+W jednej z funkcji wywołania zwrotnego w tym JavaScript `alert()` może powodować problemy. Owinąć w `setTimeout()` umożliwia wybór obrazu iOS lub popover całkowicie zamknąć zanim wyświetli alert alert:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+#### Dziwactwa Windows Phone 7
+
+Wywoływanie aparat native aplikacji, podczas gdy urządzenie jest podłączone przez Zune nie działa i powoduje błąd wywołania zwrotnego.
+
+#### Dziwactwa Tizen
+
+Tizen obsługuje tylko `destinationType` z `Camera.DestinationType.FILE_URI` i `sourceType` z `Camera.PictureSourceType.PHOTOLIBRARY`.
+
+## CameraOptions
+
+Opcjonalne parametry, aby dostosować ustawienia aparatu.
+
+    { 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 };
+    
+
+  * **quality**: Jakość zapisywanego obrazu, wyrażona w przedziale 0-100, gdzie 100 zazwyczaj jest maksymalną rozdzielczością bez strat w czasie kompresji pliku. Wartością domyślną jest 50. *(Liczba)* (Pamiętaj, że informacja o rozdzielczości aparatu jest niedostępna.)
+
+  * **destinationType**: Wybierz format zwracanej wartości. Wartością domyślną jest FILE_URI. Zdefiniowane w `navigator.camera.DestinationType` *(numer)*
+    
+        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**: Ustaw źródło obrazu. Wartością domyślną jest aparat fotograficzny. Zdefiniowane w `navigator.camera.PictureSourceType` *(numer)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **allowEdit**: Pozwala na prostą edycję obrazu przed zaznaczeniem. *(Boolean)*
+
+  * **encodingType**: Wybierz plik obrazu zwracany jest kodowanie. Domyślnie jest JPEG. Zdefiniowane w `navigator.camera.EncodingType` *(numer)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **targetWidth**: Szerokość w pikselach skalowanego obrazu. Musi być użyte z **targetHeight**. Współczynnik proporcji pozostaje stały. *(Liczba)*
+
+  * **targetHeight**: Wysokość w pikselach skalowanego obrazu. Musi być użyte z **targetWidth**. Współczynnik proporcji pozostaje stały. *(Liczba)*
+
+  * **mediaType**: Ustawia typ nośnika, z którego będzie wybrany. Działa tylko wtedy, gdy `PictureSourceType` jest `PHOTOLIBRARY` lub `SAVEDPHOTOALBUM`. Zdefiniowane w `nagivator.camera.MediaType` *(Liczba)*
+    
+        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**: Obraca obraz aby skorygować orientację urządzenia podczas przechwytywania. *(Boolean)*
+
+  * **saveToPhotoAlbum**: Po przechwyceniu zapisuje na urządzeniu obraz w albumie na zdjęcia. *(Boolean)*
+
+  * **popoverOptions**: Opcja tylko dla platformy iOS, która określa położenie wyskakującego okna na iPadzie. Zdefiniowane w `CameraPopoverOptions`.
+
+  * **cameraDirection**: Wybierz aparat do korzystania (lub z powrotem przodem). Wartością domyślną jest z powrotem. Zdefiniowane w `navigator.camera.Direction` *(numer)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### Amazon ogień OS dziwactwa
+
+  * Jakakolwiek wartość w `cameraDirection` skutkuje użyciem tylnej kamery.
+
+  * Parametr `allowEdit` jest ignorowany.
+
+  * Oba parametry `Camera.PictureSourceType.PHOTOLIBRARY` oraz `Camera.PictureSourceType.SAVEDPHOTOALBUM` wyświetlają ten sam album ze zdjęciami.
+
+#### Dziwactwa Androida
+
+  * Jakakolwiek wartość w `cameraDirection` skutkuje użyciem tylnej kamery.
+
+  * Android również używa aktywność upraw dla allowEdit, choć upraw powinien pracować i faktycznie przejść przycięte zdjęcie Wróć do Cordova, ten tylko jeden który działa konsekwentnie jest ten, wiązany z aplikacji Google Plus zdjęcia. Inne rośliny mogą nie działać.
+
+  * Oba parametry `Camera.PictureSourceType.PHOTOLIBRARY` oraz `Camera.PictureSourceType.SAVEDPHOTOALBUM` wyświetlają ten sam album ze zdjęciami.
+
+#### Jeżyna 10 dziwactwa
+
+  * Parametr `quality` jest ignorowany.
+
+  * Parametr `allowEdit` jest ignorowany.
+
+  * Nie jest wspierane `Camera.MediaType`.
+
+  * Parametr `correctOrientation` jest ignorowany.
+
+  * Parametr `cameraDirection` jest ignorowany.
+
+#### Firefox OS dziwactwa
+
+  * Parametr `quality` jest ignorowany.
+
+  * `Camera.DestinationType`jest ignorowane i jest równa `1` (plik obrazu URI)
+
+  * Parametr `allowEdit` jest ignorowany.
+
+  * Ignoruje `PictureSourceType` parametr (użytkownik wybiera go w oknie dialogowym)
+
+  * Ignoruje`encodingType`
+
+  * Ignoruje `targetWidth` i`targetHeight`
+
+  * Nie jest wspierane `Camera.MediaType`.
+
+  * Parametr `correctOrientation` jest ignorowany.
+
+  * Parametr `cameraDirection` jest ignorowany.
+
+#### Dziwactwa iOS
+
+  * Ustaw `quality` poniżej 50 aby uniknąć błędów pamięci na niektórych urządzeniach.
+
+  * Podczas korzystania z `destinationType.FILE_URI` , zdjęcia są zapisywane w katalogu tymczasowego stosowania. Zawartość katalogu tymczasowego stosowania jest usuwany po zakończeniu aplikacji.
+
+#### Dziwactwa Tizen
+
+  * opcje nie są obsługiwane
+
+  * zawsze zwraca FILE URI
+
+#### Windows Phone 7 i 8 dziwactwa
+
+  * Parametr `allowEdit` jest ignorowany.
+
+  * Parametr `correctOrientation` jest ignorowany.
+
+  * Parametr `cameraDirection` jest ignorowany.
+
+  * Ignoruje `saveToPhotoAlbum` parametr. Ważne: Wszystkie zdjęcia zrobione aparatem wp7/8 cordova API są zawsze kopiowane do telefonu w kamerze. W zależności od ustawień użytkownika może to też oznaczać że obraz jest automatycznie przesłane do ich OneDrive. Potencjalnie może to oznaczać, że obraz jest dostępne dla szerszego grona odbiorców niż Twoja aplikacja przeznaczona. Jeśli ten bloker aplikacji, trzeba będzie wdrożenie CameraCaptureTask, opisane na msdn: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> można także komentarz lub górę głosowanie powiązanych kwestii w [śledzenia błędów](https://issues.apache.org/jira/browse/CB-2083)
+
+  * Ignoruje `mediaType` Właściwość `cameraOptions` jako SDK Windows Phone nie umożliwiają wybór filmów z PHOTOLIBRARY.
+
+## CameraError
+
+funkcja wywołania zwrotnego PrzyBłędzie, która zawiera komunikat o błędzie.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+#### Opis
+
+  * **message**: Natywny kod komunikatu zapewniany przez urządzenie. *(Ciąg znaków)*
+
+## cameraSuccess
+
+onSuccess funkcji wywołania zwrotnego, który dostarcza dane obrazu.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+#### Opis
+
+  * **imageData**: Dane obrazu kodowane przy pomocy Base64 *lub* URI pliku obrazu, w zależności od użycia `cameraOptions`. *(Ciąg znaków)*
+
+#### Przykład
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Uchwyt do okna dialogowego popover, stworzony przez `navigator.camera.getPicture`.
+
+#### Opis
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### Obsługiwane platformy
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Przykład
+
+     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
+
+tylko do iOS parametrami, które określić kotwicy element lokalizacji i strzałka kierunku popover, przy wyborze zdjęć z iPad biblioteki lub album.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+#### Opis
+
+  * **x**: współrzędna piksela x elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+  * **y**: współrzędna piksela y elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+  * **width**: szerokość w pikselach elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+  * **height**: wysokość w pikselach elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+  * **arrowDir**: Kierunek, który powinna wskazywać strzałka na wyskakującym oknie. Zdefiniowane w `Camera.PopoverArrowDirection` *(Liczba)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Należy pamiętać, że rozmiar popover może zmienić aby zmienić kierunek strzałki i orientacji ekranu. Upewnij się uwzględnić zmiany orientacji podczas określania położenia elementu kotwicy.
+
+## navigator.camera.cleanup
+
+Usuwa pośrednie zdjęcia zrobione przez aparat z czasowego składowania.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+#### Opis
+
+Usuwa pliki obrazów pośrednich, które są przechowywane w pamięci tymczasowej po wywołaniu `camera.getPicture`. Ma zastosowanie tylko, gdy wartość `Camera.sourceType` jest równa `Camera.PictureSourceType.CAMERA` i `Camera.destinationType` jest równa `Camera.DestinationType.FILE_URI`.
+
+#### Obsługiwane platformy
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### Przykład
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 434 - 0
miaomiao/plugins/cordova-plugin-camera/doc/pl/index.md

xqd
@@ -0,0 +1,434 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+Ten plugin definiuje obiekt globalny `navigator.camera`, który dostarcza API do robienia zdjęć i wybór zdjęć z biblioteki obrazów systemu.
+
+Mimo, że obiekt jest dołączony do globalnego zakresu `navigator`, to nie dostępne dopiero po zdarzeniu `deviceready`.
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## Instalacja
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+Ma zdjęcia za pomocą aparatu, lub pobiera zdjęcia z urządzenia Galeria zdjęć. Obraz jest przekazywany do wywołania zwrotnego sukces jako kodowane algorytmem base64 `ciąg`, lub identyfikator URI dla pliku obrazu. Sama metoda zwraca obiekt `CameraPopoverHandle`, który może służyć do zmiany położenia pliku wyboru popover.
+
+    navigator.camera.getPicture( cameraSuccess, cameraError, cameraOptions );
+    
+
+### Opis
+
+Funkcja `camera.getPicture` otwiera urządzenia domyślnej aplikacji aparat fotograficzny ów pozwala użytkownik wobec chwycić zębami kino. To zachowanie występuje domyślnie, gdy `Camera.sourceType` jest równa `Camera.PictureSourceType.CAMERA`. Gdy użytkownik zaskoczy zdjęcie, ten aparat fotograficzny applicationâ zamyka i aplikacji jest przywracany.
+
+Jeśli `Camera.sourceType` jest równe `Camera.PictureSourceType.PHOTOLIBRARY` lub `Camera.PictureSourceType.SAVEDPHOTOALBUM`, wtedy zostanie wyświetlone okno dialogowe pozwalające użytkownikowi na wybór istniejącego obrazu. Funkcja `camera.getPicture` zwraca obiekt `CameraPopoverHandle`, który obsługuje zmianę położenia okna wyboru obrazu, np. po zmianie orientacji urządzenia.
+
+Zwracana wartość jest wysyłany do funkcji wywołania zwrotnego `cameraSuccess`, w jednym z następujących formatów, w zależności od określonego `cameraOptions`:
+
+*   `String` zawierający obraz zakodowany przy pomocy base64.
+
+*   `String` reprezentujący lokalizację pliku obrazu w lokalnym magazynie (domyślnie).
+
+Może rób, co chcesz z zakodowany obraz lub identyfikatora URI, na przykład:
+
+*   Przedstawić obraz w tagu `<img>`, jak w przykładzie poniżej
+
+*   Zapisać lokalnie dane (`LocalStorage`, [Lawnchair][1], etc.)
+
+*   Wysłać dane na zdalny serwer
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**Uwaga**: zdjęcie rozdzielczości na nowsze urządzenia jest bardzo dobry. Zdjęcia wybrane z galerii urządzenia są nie przeskalowanych w dół do niższej jakości, nawet jeśli określono parametr `quality`. Aby uniknąć typowych problemów z pamięci, zestaw `Camera.destinationType` `FILE_URI` zamiast `DATA_URL`.
+
+### Obsługiwane platformy
+
+*   Amazon Fire OS
+*   Android
+*   BlackBerry 10
+*   Przeglądarka
+*   Firefox OS
+*   iOS
+*   Tizen
+*   Windows Phone 7 i 8
+*   Windows 8
+
+### Preferencje (iOS)
+
+*   **CameraUsesGeolocation** (boolean, wartość domyślna to false). Do przechwytywania JPEG, zestaw do true, aby uzyskać danych geolokalizacyjnych w nagłówku EXIF. To spowoduje wniosek o geolokalizacji uprawnienia, jeśli zestaw na wartość true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### Amazon ogień OS dziwactwa
+
+Amazon ogień OS używa intencje do rozpoczęcia działalności aparatu na urządzenie do przechwytywania obrazów, i na telefony z pamięci, Cordova aktywność może zostać zabity. W tym scenariuszu obraz mogą nie być wyświetlane po przywróceniu aktywności cordova.
+
+### Dziwactwa Androida
+
+Android używa intencje do rozpoczęcia działalności aparatu na urządzenie do przechwytywania obrazów, i na telefony z pamięci, Cordova aktywność może zostać zabity. W tym scenariuszu obraz mogą nie być wyświetlane po przywróceniu aktywności Cordova.
+
+### Quirks przeglądarki
+
+Może zwracać tylko zdjęcia jako obraz w formacie algorytmem base64.
+
+### Firefox OS dziwactwa
+
+Aparat plugin jest obecnie implementowane za pomocą [Działania sieci Web][2].
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### Dziwactwa iOS
+
+W jednej z funkcji wywołania zwrotnego w tym JavaScript `alert()` może powodować problemy. Owinąć w `setTimeout()` umożliwia wybór obrazu iOS lub popover całkowicie zamknąć zanim wyświetli alert alert:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+### Dziwactwa Windows Phone 7
+
+Wywoływanie aparat native aplikacji, podczas gdy urządzenie jest podłączone przez Zune nie działa i powoduje błąd wywołania zwrotnego.
+
+### Dziwactwa Tizen
+
+Tizen obsługuje tylko `destinationType` z `Camera.DestinationType.FILE_URI` i `sourceType` z `Camera.PictureSourceType.PHOTOLIBRARY`.
+
+### Przykład
+
+Zrób zdjęcie i pobrać go jako kodowane algorytmem base64 obrazu:
+
+    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);
+    }
+    
+
+Zrób zdjęcie i pobrać lokalizacji pliku obrazu:
+
+    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
+
+Opcjonalne parametry, aby dostosować ustawienia aparatu.
+
+    { 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 };
+    
+
+### Opcje
+
+*   **quality**: Jakość zapisywanego obrazu, wyrażona w przedziale 0-100, gdzie 100 zazwyczaj jest maksymalną rozdzielczością bez strat w czasie kompresji pliku. Wartością domyślną jest 50. *(Liczba)* (Pamiętaj, że informacja o rozdzielczości aparatu jest niedostępna.)
+
+*   **destinationType**: Wybierz format zwracanej wartości. Wartością domyślną jest FILE_URI. Zdefiniowane w `navigator.camera.DestinationType` *(numer)*
+    
+        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**: Ustaw źródło obrazu. Wartością domyślną jest aparat fotograficzny. Zdefiniowane w `navigator.camera.PictureSourceType` *(numer)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **allowEdit**: Pozwala na prostą edycję obrazu przed zaznaczeniem. *(Boolean)*
+
+*   **encodingType**: Wybierz plik obrazu zwracany jest kodowanie. Domyślnie jest JPEG. Zdefiniowane w `navigator.camera.EncodingType` *(numer)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **targetWidth**: Szerokość w pikselach skalowanego obrazu. Musi być użyte z **targetHeight**. Współczynnik proporcji pozostaje stały. *(Liczba)*
+
+*   **targetHeight**: Wysokość w pikselach skalowanego obrazu. Musi być użyte z **targetWidth**. Współczynnik proporcji pozostaje stały. *(Liczba)*
+
+*   **mediaType**: Ustawia typ nośnika, z którego będzie wybrany. Działa tylko wtedy, gdy `PictureSourceType` jest `PHOTOLIBRARY` lub `SAVEDPHOTOALBUM`. Zdefiniowane w `nagivator.camera.MediaType` *(Liczba)*
+    
+        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**: Obraca obraz aby skorygować orientację urządzenia podczas przechwytywania. *(Boolean)*
+
+*   **saveToPhotoAlbum**: Po przechwyceniu zapisuje na urządzeniu obraz w albumie na zdjęcia. *(Boolean)*
+
+*   **popoverOptions**: Opcja tylko dla platformy iOS, która określa położenie wyskakującego okna na iPadzie. Zdefiniowane w `CameraPopoverOptions`.
+
+*   **cameraDirection**: Wybierz aparat do korzystania (lub z powrotem przodem). Wartością domyślną jest z powrotem. Zdefiniowane w `navigator.camera.Direction` *(numer)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### Amazon ogień OS dziwactwa
+
+*   Jakakolwiek wartość w `cameraDirection` skutkuje użyciem tylnej kamery.
+
+*   Parametr `allowEdit` jest ignorowany.
+
+*   Oba parametry `Camera.PictureSourceType.PHOTOLIBRARY` oraz `Camera.PictureSourceType.SAVEDPHOTOALBUM` wyświetlają ten sam album ze zdjęciami.
+
+### Dziwactwa Androida
+
+*   Jakakolwiek wartość w `cameraDirection` skutkuje użyciem tylnej kamery.
+
+*   Parametr `allowEdit` jest ignorowany.
+
+*   Oba parametry `Camera.PictureSourceType.PHOTOLIBRARY` oraz `Camera.PictureSourceType.SAVEDPHOTOALBUM` wyświetlają ten sam album ze zdjęciami.
+
+### Jeżyna 10 dziwactwa
+
+*   Parametr `quality` jest ignorowany.
+
+*   Parametr `allowEdit` jest ignorowany.
+
+*   Nie jest wspierane `Camera.MediaType`.
+
+*   Parametr `correctOrientation` jest ignorowany.
+
+*   Parametr `cameraDirection` jest ignorowany.
+
+### Firefox OS dziwactwa
+
+*   Parametr `quality` jest ignorowany.
+
+*   `Camera.DestinationType`jest ignorowane i jest równa `1` (plik obrazu URI)
+
+*   Parametr `allowEdit` jest ignorowany.
+
+*   Ignoruje `PictureSourceType` parametr (użytkownik wybiera go w oknie dialogowym)
+
+*   Ignoruje`encodingType`
+
+*   Ignoruje `targetWidth` i`targetHeight`
+
+*   Nie jest wspierane `Camera.MediaType`.
+
+*   Parametr `correctOrientation` jest ignorowany.
+
+*   Parametr `cameraDirection` jest ignorowany.
+
+### Dziwactwa iOS
+
+*   Ustaw `quality` poniżej 50 aby uniknąć błędów pamięci na niektórych urządzeniach.
+
+*   Podczas korzystania z `destinationType.FILE_URI` , zdjęcia są zapisywane w katalogu tymczasowego stosowania. Zawartość katalogu tymczasowego stosowania jest usuwany po zakończeniu aplikacji.
+
+### Dziwactwa Tizen
+
+*   opcje nie są obsługiwane
+
+*   zawsze zwraca FILE URI
+
+### Windows Phone 7 i 8 dziwactwa
+
+*   Parametr `allowEdit` jest ignorowany.
+
+*   Parametr `correctOrientation` jest ignorowany.
+
+*   Parametr `cameraDirection` jest ignorowany.
+
+*   Ignoruje `saveToPhotoAlbum` parametr. Ważne: Wszystkie zdjęcia zrobione aparatem wp7/8 cordova API są zawsze kopiowane do telefonu w kamerze. W zależności od ustawień użytkownika może to też oznaczać że obraz jest automatycznie przesłane do ich OneDrive. Potencjalnie może to oznaczać, że obraz jest dostępne dla szerszego grona odbiorców niż Twoja aplikacja przeznaczona. Jeśli ten bloker aplikacji, trzeba będzie wdrożenie CameraCaptureTask, opisane na msdn: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> można także komentarz lub górę głosowanie powiązanych kwestii w [śledzenia błędów][3]
+
+*   Ignoruje `mediaType` Właściwość `cameraOptions` jako SDK Windows Phone nie umożliwiają wybór filmów z PHOTOLIBRARY.
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+funkcja wywołania zwrotnego PrzyBłędzie, która zawiera komunikat o błędzie.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+### Parametry
+
+*   **message**: Natywny kod komunikatu zapewniany przez urządzenie. *(Ciąg znaków)*
+
+## cameraSuccess
+
+onSuccess funkcji wywołania zwrotnego, który dostarcza dane obrazu.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+### Parametry
+
+*   **imageData**: Dane obrazu kodowane przy pomocy Base64 *lub* URI pliku obrazu, w zależności od użycia `cameraOptions`. *(Ciąg znaków)*
+
+### Przykład
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Uchwyt do okna dialogowego popover, stworzony przez `navigator.camera.getPicture`.
+
+### Metody
+
+*   **setPosition**: Ustawia pozycję wyskakującego okna.
+
+### Obsługiwane platformy
+
+*   iOS
+
+### setPosition
+
+Ustaw pozycję popover.
+
+**Parametry**:
+
+*   `cameraPopoverOptions`: `CameraPopoverOptions`, która określa nową pozycję
+
+### Przykład
+
+     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
+
+tylko do iOS parametrami, które określić kotwicy element lokalizacji i strzałka kierunku popover, przy wyborze zdjęć z iPad biblioteki lub album.
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+### CameraPopoverOptions
+
+*   **x**: współrzędna piksela x elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+*   **y**: współrzędna piksela y elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+*   **width**: szerokość w pikselach elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+*   **height**: wysokość w pikselach elementu ekranu, na którym zakotwiczone jest wyskakujące okno. *(Liczba)*
+
+*   **arrowDir**: Kierunek, który powinna wskazywać strzałka na wyskakującym oknie. Zdefiniowane w `Camera.PopoverArrowDirection` *(Liczba)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Należy pamiętać, że rozmiar popover może zmienić aby zmienić kierunek strzałki i orientacji ekranu. Upewnij się uwzględnić zmiany orientacji podczas określania położenia elementu kotwicy.
+
+## navigator.camera.cleanup
+
+Usuwa pośrednie zdjęcia zrobione przez aparat z czasowego składowania.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+### Opis
+
+Usuwa pliki obrazów pośrednich, które są przechowywane w pamięci tymczasowej po wywołaniu `camera.getPicture`. Ma zastosowanie tylko, gdy wartość `Camera.sourceType` jest równa `Camera.PictureSourceType.CAMERA` i `Camera.destinationType` jest równa `Camera.DestinationType.FILE_URI`.
+
+### Obsługiwane platformy
+
+*   iOS
+
+### Przykład
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 417 - 0
miaomiao/plugins/cordova-plugin-camera/doc/ru/index.md

xqd
@@ -0,0 +1,417 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+Этот плагин предоставляет API для съемки и для выбора изображения из библиотеки изображений системы.
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+Снимает фотографию с помощью камеры, или получает фотографию из галереи изображений устройства. Изображение передается на функцию обратного вызова успешного завершения как `String` в base64-кодировке, или как URI указывающего на файл изображения. Метод возвращает объект `CameraPopoverHandle`, который может использоваться для перемещения инструмента выбора файла.
+
+    navigator.camera.getPicture( cameraSuccess, cameraError, cameraOptions );
+    
+
+### Описание
+
+Функция `camera.getPicture` открывает приложение камеры устройства, которое позволяет снимать фотографии. Это происходит по умолчанию, когда `Camera.sourceType` равно `Camera.PictureSourceType.CAMERA` . Как только пользователь делает снимок,приложение камеры закрывается и приложение восстанавливается.
+
+Если `Camera.sourceType` является `Camera.PictureSourceType.PHOTOLIBRARY` или `Camera.PictureSourceType.SAVEDPHOTOALBUM` , то показывается диалоговое окно, которое позволяет пользователям выбрать существующее изображение. Функция `camera.getPicture` возвращает объект `CameraPopoverHandle` объект, который может использоваться для перемещения диалога выбора изображения, например, при изменении ориентации устройства.
+
+Возвращаемое значение отправляется в функцию обратного вызова `cameraSuccess` в одном из следующих форматов, в зависимости от параметра `cameraOptions` :
+
+*   A объект `String` содержащий фото изображение в base64-кодировке.
+
+*   Объект `String` представляющий расположение файла изображения на локальном хранилище (по умолчанию).
+
+Вы можете сделать все, что угодно вы хотите с закодированным изображением или URI, например:
+
+*   Отобразить изображение с помощью тега `<img>`, как показано в примере ниже
+
+*   Сохранять данные локально (`LocalStorage`, [Lawnchair][1], и т.д.)
+
+*   Отправлять данные на удаленный сервер
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**Примечание**: разрешение фото на более новых устройствах является достаточно хорошим. Фотографии из галереи устройства не масштабируются к более низкому качеству, даже если указан параметр `quality`. Чтобы избежать общих проблем с памятью, установите `Camera.destinationType` в `FILE_URI` вместо `DATA_URL`.
+
+### Поддерживаемые платформы
+
+*   Amazon Fire OS
+*   Android
+*   BlackBerry 10
+*   Обозреватель
+*   Firefox OS
+*   iOS
+*   Tizen
+*   Windows Phone 7 и 8
+*   Windows 8
+
+### Предпочтения (iOS)
+
+*   **CameraUsesGeolocation** (логическое значение, по умолчанию false). Для захвата изображения JPEG, значение true, чтобы получить данные геопозиционирования в заголовке EXIF. Это вызовет запрос на разрешения геолокации, если задано значение true.
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### Особенности Amazon Fire OS
+
+Amazon Fire OS используют намерения для запуска активности камеры на устройстве для съемки фотографий, и на устройствах с низким объемам памяти, активность Cordova может быть завершена. В этом случае изображение может не появиться при восстановлении активности Cordova.
+
+### Особенности Android
+
+Android используют намерения для запуска активности камеры на устройстве для съемки фотографий, и на устройствах с низким объемам памяти, активность Cordova может быть завершена. В этом случае изображение может не появиться при восстановлении активности Cordova.
+
+### Браузер причуды
+
+Может возвращать только фотографии как изображения в кодировке base64.
+
+### Особенности Firefox OS
+
+Плагин Camera на данный момент реализован с использованием [Web Activities][2].
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### Особенности iOS
+
+Включение функции JavaScript `alert()` в любой из функций обратного вызова функции может вызвать проблемы. Оберните вызов alert в `setTimeout()` для позволения окну выбора изображений iOS полностью закрыться перед отображение оповещения:
+
+    setTimeout(function() {/ / ваши вещи!}, 0);
+    
+
+### Особенности Windows Phone 7
+
+Вызов встроенного приложения камеры, в то время как устройство подключено к Zune не работает, и инициирует обратный вызов для ошибки.
+
+### Особенности Tizen
+
+Tizen поддерживает только значение `destinationType` равное `Camera.DestinationType.FILE_URI` и значение `sourceType` равное `Camera.PictureSourceType.PHOTOLIBRARY`.
+
+### Пример
+
+Сделайте фотографию и получите его как изображение в base64-кодировке:
+
+    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);
+    }
+    
+
+Сделайте фотографию и получить расположение файла с изображением:
+
+    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
+
+Необязательные параметры для настройки параметров камеры.
+
+    { 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 };
+    
+
+### Параметры
+
+*   **quality**: качество сохраняемого изображения, выражается в виде числа в диапазоне от 0 до 100, где 100 является обычно полным изображением без потери качества при сжатии. Значение по умолчанию — 50. *(Число)* (Обратите внимание, что информация о разрешении камеры недоступна.)
+
+*   **параметр destinationType**: выберите формат возвращаемого значения. Значение по умолчанию — FILE_URI. Определяется в `navigator.camera.DestinationType` *(число)*
+    
+        Camera.DestinationType = {
+        DATA_URL: 0, / / возвращение изображения в base64-кодировке строки 
+        FILE_URI: 1, / / возврат файла изображения URI 
+        NATIVE_URI: 2 / / возвращение образа собственного URI (например, Библиотека активов: / / на iOS или содержание: / / на андроиде)
+        };
+        
+
+*   **тип источника**: установить источник рисунка. По умолчанию используется камера. Определяется в `navigator.camera.PictureSourceType` *(число)*
+    
+        Camera.PictureSourceType = {
+        PHOTOLIBRARY: 0, 
+        CAMERA: 1, 
+        SAVEDPHOTOALBUM: 2
+        };
+        
+
+*   **allowEdit**: позволит редактирование изображения средствами телефона перед окончательным выбором изображения. *(Логический)*
+
+*   **Тип_шифрования**: выберите возвращенный файл в кодировку. Значение по умолчанию — JPEG. Определяется в `navigator.camera.EncodingType` *(число)*
+    
+        Camera.EncodingType = {
+        JPEG: 0, // возвращает изображение в формате JPEG
+        PNG: 1 // возвращает рисунок в формате PNG
+        };
+        
+
+*   **targetWidth**: ширина изображения в пикселах к которой необходимо осуществить масштабирование. Это значение должно использоваться совместно с **targetHeight**. Пропорции изображения останутся неизменными. *(Число)*
+
+*   **targetHeight**: высота изображения в пикселах к которой необходимо осуществить масштабирование. Это значение должно использоваться совместно с **targetWidth**. Пропорции изображения останутся неизменными. *(Число)*
+
+*   **тип носителя**: Установите источник получения изображения, из которого надо выбрать изображение. Работает только если `PictureSourceType` равно `PHOTOLIBRARY` или `SAVEDPHOTOALBUM` . Определяется в `nagivator.camera.MediaType` *(число)*
+    
+        Camera.MediaType = {
+        PICTURE: 0, / / разрешить выбор только сохраненных изображений. 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**: вращает изображение, чтобы внести исправления к ориентации устройства во время захвата. *(Логический)*
+
+*   **saveToPhotoAlbum**: сохранить изображение в фотоальбом на устройстве после захвата. *(Логическое)*
+
+*   **popoverOptions**: только для iOS параметры, которые определяют местоположение инструмента в iPad. Определены в`CameraPopoverOptions`.
+
+*   **cameraDirection**: выбрать камеру для использования (передней или задней стороне). Значение по умолчанию — обратно. Определяется в `navigator.camera.Direction` *(число)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### Особенности Amazon Fire OS
+
+*   Любое значение `cameraDirection` возвращает фотографию сделанную задней камерой.
+
+*   Игнорирует параметр `allowEdit`.
+
+*   Оба параметра `Camera.PictureSourceType.PHOTOLIBRARY` и `Camera.PictureSourceType.SAVEDPHOTOALBUM` отображают один и тот же фотоальбом.
+
+### Особенности Android
+
+*   Любое значение `cameraDirection` возвращает фотографию сделанную задней камерой.
+
+*   Игнорирует параметр `allowEdit`.
+
+*   Оба параметра `Camera.PictureSourceType.PHOTOLIBRARY` и `Camera.PictureSourceType.SAVEDPHOTOALBUM` отображают один и тот же фотоальбом.
+
+### Особенности BlackBerry 10
+
+*   Игнорирует `quality` параметр.
+
+*   Игнорирует параметр `allowEdit`.
+
+*   `Camera.MediaType` не поддерживается.
+
+*   Игнорирует параметр `correctOrientation`.
+
+*   Игнорирует параметр `cameraDirection`.
+
+### Особенности Firefox OS
+
+*   Игнорирует `quality` параметр.
+
+*   Значение `Camera.DestinationType` игнорируется и равно `1` (URI для файла изображения)
+
+*   Игнорирует параметр `allowEdit`.
+
+*   Игнорирует параметр `PictureSourceType` (пользователь выбирает его в диалоговом окне)
+
+*   Игнорирует параметр `encodingType`
+
+*   Игнорирует `targetWidth` и `targetHeight`
+
+*   `Camera.MediaType` не поддерживается.
+
+*   Игнорирует параметр `correctOrientation`.
+
+*   Игнорирует параметр `cameraDirection`.
+
+### Особенности iOS
+
+*   Установите `quality` ниже 50, для того чтобы избежать ошибок памяти на некоторых устройствах.
+
+*   При использовании `destinationType.FILE_URI` , фотографии сохраняются во временном каталоге приложения. Содержимое приложения временного каталога удаляется при завершении приложения.
+
+### Особенности Tizen
+
+*   options, не поддерживается
+
+*   всегда возвращает URI файла
+
+### Особенности Windows Phone 7 и 8
+
+*   Игнорирует параметр `allowEdit`.
+
+*   Игнорирует параметр `correctOrientation`.
+
+*   Игнорирует параметр `cameraDirection`.
+
+*   Игнорирует `saveToPhotoAlbum` параметр. Важно: Все изображения, снятые камерой wp7/8 cordova API всегда копируются в рулон камеры телефона. В зависимости от параметров пользователя это также может означать, что изображение автоматически загружены на их OneDrive. Потенциально это может означать, что этот образ доступен для более широкой аудитории, чем ваше приложение предназначено. Если этот блокатор для вашего приложения, вам нужно будет осуществить CameraCaptureTask, как описано на сайте msdn: <http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx> вы можете также комментарий или вверх голосование связанный с этим вопрос [отслеживания][3]
+
+*   Игнорирует свойство `mediaType` объекта `cameraOptions` так как Windows Phone SDK не предоставляет способ выбрать видео из PHOTOLIBRARY.
+
+ [3]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+Функция обратного вызова вызываемая в случае возникновения ошибки.
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+### Параметры
+
+*   **сообщение**: сообщение об ошибке предоставляемое платформой устройства. *(Строка)*
+
+## cameraSuccess
+
+Функция обратного вызова onSuccess, получающая данные изображения.
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+### Параметры
+
+*   **imageData**: Данные изображения в Base64 кодировке, *или* URI, в зависимости от применяемых параметров `cameraOptions`. *(Строка)*
+
+### Пример
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+Дескриптор диалогового окна инструмента, созданный `navigator.camera.getPicture`.
+
+### Методы
+
+*   **setPosition**: Задайте положение инструмента выбора изображения.
+
+### Поддерживаемые платформы
+
+*   iOS
+
+### setPosition
+
+Устанавливает положение инструмента выбора изображения.
+
+**Параметры**:
+
+*   `cameraPopoverOptions`: Объект `CameraPopoverOptions`, определяющий новое положение
+
+### Пример
+
+     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, которые определяют расположение элемента привязки и направление стрелки инструмента при выборе изображений из библиотеки изображений iPad или альбома.
+
+    {x: 0, y: 32, ширина: 320, высота: 480, arrowDir: Camera.PopoverArrowDirection.ARROW_ANY};
+    
+
+### CameraPopoverOptions
+
+*   **x**: x координата в пикселях элемента экрана, на котором закрепить инструмента. *(Число)*
+
+*   **x**: y координата в пикселях элемента экрана, на котором закрепить инструмента. *(Число)*
+
+*   **width**: ширина в пикселях элемента экрана, на котором закрепить инструмент выбора изображения. *(Число)*
+
+*   **height**: высота в пикселях элемента экрана, на котором закрепить инструмент выбора изображения. *(Число)*
+
+*   **arrowDir**: Направление, куда должна указывать стрелка на инструменте. Определено в `Camera.PopoverArrowDirection` *(число)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+Обратите внимание, что размер инструмента может изменяться для корректировки в зависимости направлении стрелки и ориентации экрана. Убедитесь, что учитываете возможные изменения ориентации при указании расположения элемента привязки.
+
+## navigator.camera.cleanup
+
+Удаляет промежуточные фотографии, сделанные камерой из временного хранилища.
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+### Описание
+
+Удаляет промежуточные файлы изображений, которые хранятся во временном хранилище после вызова метода `camera.getPicture` . Применяется только тогда, когда значение `Camera.sourceType` равно `Camera.PictureSourceType.CAMERA` и `Camera.destinationType` равняется `Camera.DestinationType.FILE_URI`.
+
+### Поддерживаемые платформы
+
+*   iOS
+
+### Пример
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 421 - 0
miaomiao/plugins/cordova-plugin-camera/doc/zh/README.md

xqd
@@ -0,0 +1,421 @@
+<!---
+# license: 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.
+-->
+
+# cordova-plugin-camera
+
+[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+這個外掛程式定義了一個全球 `navigator.camera` 物件,它提供了 API,拍照,從系統的圖像庫中選擇圖像。
+
+雖然該物件附加到全球範圍內 `導航器`,它不可用直到 `deviceready` 事件之後。
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## 安裝
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## API
+
+  * 相機 
+      * navigator.camera.getPicture(success, fail, options)
+      * CameraOptions
+      * CameraPopoverHandle
+      * CameraPopoverOptions
+      * navigator.camera.cleanup
+
+## navigator.camera.getPicture
+
+需要一張照片,使用相機,或從設備的圖像庫檢索一張照片。 圖像被傳遞給成功回檔的 base64 編碼 `String`,或作為 URI 為影像檔。 該方法本身返回一個 `CameraPopoverHandle` 物件,它可以用來重新置放檔選擇氣泡框。
+
+    navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
+    
+
+#### 說明
+
+`camera.getPicture` 函數打開該設備的預設攝像頭應用程式,允許使用者拍照。 `Camera.sourceType` 等於 `Camera.PictureSourceType.CAMERA` 時,預設情況下,發生此行為。 一旦使用者打斷了他的照片,相機應用程式關閉,且應用程式還原。
+
+如果 `Camera.sourceType` 是 `Camera.PictureSourceType.PHOTOLIBRARY` 或 `Camera.PictureSourceType.SAVEDPHOTOALBUM`,然後顯示一個對話方塊,允許使用者選擇一個現有的圖像。 `camera.getPicture` 函數返回一個 `CameraPopoverHandle` 物件,它可以用於重新置放圖像選擇的對話方塊,例如,當設備的方向變化。
+
+傳回值是發送到 `cameraSuccess` 回呼函數中,在以下的格式,具體取決於指定的 `cameraOptions` 之一:
+
+  * A `String` 包含的 base64 編碼的照片圖像。
+
+  * A `String` 表示在本機存放區 (預設值) 上的影像檔位置。
+
+你可以做任何你想要的編碼的圖像或 URI,例如:
+
+  * 呈現在圖像 `<img>` 標記,如下面的示例所示
+
+  * 保存本地的資料 ( `LocalStorage` , [Lawnchair](http://brianleroux.github.com/lawnchair/),等等.)
+
+  * 將資料發佈到遠端伺服器
+
+**注**: 在更新設備上的照片解析度是很好。 選擇從設備的庫的照片是不壓縮螢幕使其以較低的品質,即使指定了一個 `quality` 參數。 要避免常見的記憶體問題,請將 `Camera.destinationType` 設置為 `FILE_URI`,而不是 `DATA_URL`.
+
+#### 支援的平臺
+
+![](doc/img/android-success.png) ![](doc/img/blackberry-success.png) ![](doc/img/browser-success.png) ![](doc/img/firefox-success.png) ![](doc/img/fireos-success.png) ![](doc/img/ios-success.png) ![](doc/img/windows-success.png) ![](doc/img/wp8-success.png) ![](doc/img/ubuntu-success.png)
+
+#### 示例
+
+拍一張照片,並檢索它作為一個 base64 編碼的圖像:
+
+    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);
+    }
+    
+
+拍一張照片和檢索圖像的檔位置:
+
+    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);
+    }
+    
+
+#### 首選項 (iOS)
+
+  * **CameraUsesGeolocation**(布林值,預設值為 false)。 用於捕獲 jpeg 檔,設置為 true,以在 EXIF 頭資訊中獲取地理定位資料。 這將觸發請求的地理位置的許可權,如果設置為 true。
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+#### 亞馬遜火 OS 怪癖
+
+亞馬遜火 OS 使用意圖啟動相機活動設備來捕捉圖像上, 和手機上記憶體不足,科爾多瓦活動可能被殺害。 在這種情況下,可能不會顯示圖像時恢復了科爾多瓦活動。
+
+#### Android 的怪癖
+
+Android 使用意圖以啟動相機活動設備來捕捉圖像上, 和手機上記憶體不足,科爾多瓦活動可能被殺害。 在這種情況下,可能不會顯示圖像時恢復了科爾多瓦活動。
+
+#### 瀏覽器的怪癖
+
+可以只返回照片作為 base64 編碼的圖像。
+
+#### 火狐瀏覽器作業系統的怪癖
+
+觀景窗外掛程式目前實施使用 [Web 活動](https://hacks.mozilla.org/2013/01/introducing-web-activities/).
+
+#### iOS 的怪癖
+
+包括 JavaScript `alert ()` 中的回呼函數會導致問題。 包裝內 `setTimeout()` 允許 iOS 圖像選取器或氣泡框以完全關閉之前,警報將顯示警報:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+#### Windows Phone 7 的怪癖
+
+調用本機攝像頭應用程式,而通過 Zune 所連接的設備不能工作,並且觸發錯誤回檔。
+
+#### Tizen 怪癖
+
+泰只支援 `destinationType` 的 `Camera.DestinationType.FILE_URI` 和 `Camera.PictureSourceType.PHOTOLIBRARY` 的 `sourceType`.
+
+## CameraOptions
+
+要自訂相機設置的可選參數。
+
+    { 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 };
+    
+
+  * **品質**: 保存的圖像,表示為範圍 0-100,100,是通常全解析度,無損失從檔案壓縮的品質。 預設值為 50。 *(人數)*(請注意相機的解析度有關的資訊是不可用)。
+
+  * **可**: 選擇傳回值的格式。預設值是 FILE_URI。定義在 `navigator.camera.DestinationType` *(人數)*
+    
+        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)
+        };
+        
+
+  * **時**: 設置圖片的來源。預設值是觀景窗。定義在 `navigator.camera.PictureSourceType` *(人數)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+  * **allowEdit**: 允許簡單編輯前選擇圖像。*(布林)*
+
+  * **encodingType**: 選擇返回的影像檔的編碼。預設值為 JPEG。定義在 `navigator.camera.EncodingType` *(人數)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+  * **targetWidth**: 向尺度圖像的圖元寬度。必須用**targetHeight**。縱橫比保持不變。*(人數)*
+
+  * **targetHeight**: 以圖元為單位向尺度圖像的高度。必須用**targetWidth**。縱橫比保持不變。*(人數)*
+
+  * **媒體類型**: 設置的媒體,從選擇類型。 時才起作用 `PictureSourceType` 是 `PHOTOLIBRARY` 或 `SAVEDPHOTOALBUM` 。 定義在 `nagivator.camera.MediaType` *(人數)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. 預設情況。 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**: 旋轉圖像,該設備時捕獲的定向的正確。*(布林)*
+
+  * **saveToPhotoAlbum**: 將圖像保存到相冊在設備上捕獲後。*(布林)*
+
+  * **popoverOptions**: 只有 iOS 在 iPad 中指定氣泡框位置的選項。在中定義`CameraPopoverOptions`.
+
+  * **cameraDirection**: 選擇相機以使用 (前面或後面-面向)。預設值是背。定義在 `navigator.camera.Direction` *(人數)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+#### 亞馬遜火 OS 怪癖
+
+  * 任何 `cameraDirection` 值回朝的照片中的結果。
+
+  * 忽略 `allowEdit` 參數。
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`和 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 都顯示相同的相冊。
+
+#### Android 的怪癖
+
+  * 任何 `cameraDirection` 值回朝的照片中的結果。
+
+  * 安卓也用於作物活動 allowEdit,即使作物應工作,實際上將裁剪的圖像傳回給科爾多瓦,那個唯一的作品一直是一個與谷歌加上照片應用程式捆綁在一起。 其他作物可能無法工作。
+
+  * `Camera.PictureSourceType.PHOTOLIBRARY`和 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 都顯示相同的相冊。
+
+#### 黑莓 10 怪癖
+
+  * 忽略 `quality` 參數。
+
+  * 忽略 `allowEdit` 參數。
+
+  * `Camera.MediaType`不受支援。
+
+  * 忽略 `correctOrientation` 參數。
+
+  * 忽略 `cameraDirection` 參數。
+
+#### 火狐瀏覽器作業系統的怪癖
+
+  * 忽略 `quality` 參數。
+
+  * `Camera.DestinationType`將被忽略並且等於 `1` (影像檔的 URI)
+
+  * 忽略 `allowEdit` 參數。
+
+  * 忽略 `PictureSourceType` 參數 (使用者選擇它在對話方塊視窗中)
+
+  * 忽略`encodingType`
+
+  * 忽略了 `targetWidth` 和`targetHeight`
+
+  * `Camera.MediaType`不受支援。
+
+  * 忽略 `correctOrientation` 參數。
+
+  * 忽略 `cameraDirection` 參數。
+
+#### iOS 的怪癖
+
+  * 設置 `quality` 低於 50,避免在某些設備上的記憶體不足錯誤。
+
+  * 當使用 `destinationType.FILE_URI` ,照片都保存在應用程式的臨時目錄。應用程式結束時,將刪除該應用程式的臨時目錄中的內容。
+
+#### Tizen 怪癖
+
+  * 不支援的選項
+
+  * 總是返回一個檔的 URI
+
+#### Windows Phone 7 和 8 怪癖
+
+  * 忽略 `allowEdit` 參數。
+
+  * 忽略 `correctOrientation` 參數。
+
+  * 忽略 `cameraDirection` 參數。
+
+  * 忽略 `saveToPhotoAlbum` 參數。 重要: 使用 wp7/8 科爾多瓦攝像頭 API 拍攝的所有圖像總是都複製到手機的相機膠捲。 根據使用者的設置,這可能也意味著圖像是自動上傳到他們另。 這有可能意味著的圖像,可以比你的應用程式的目的更多的觀眾。 如果此阻滯劑您的應用程式,您將需要實現 CameraCaptureTask 在 msdn 上記載: [HTTP://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx)你可能還評論或在[問題追蹤器](https://issues.apache.org/jira/browse/CB-2083)的向上投票的相關的問題
+
+  * 忽略了 `mediaType` 屬性的 `cameraOptions` 作為 Windows Phone SDK 並不提供從 PHOTOLIBRARY 中選擇視頻的方法。
+
+## CameraError
+
+onError 的回呼函數提供了一條錯誤訊息。
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+#### 說明
+
+  * **message**: 消息提供的設備的本機代碼。*(String)*
+
+## cameraSuccess
+
+提供的圖像資料的 onSuccess 回呼函數。
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+#### 說明
+
+  * **imageData**: Base64 編碼進行編碼的圖像資料,*或*影像檔的 URI,取決於 `cameraOptions` 效果。*(String)*
+
+#### 示例
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+由 `navigator.camera.getPicture` 創建的氣泡框對話方塊的控制碼.
+
+#### 說明
+
+  * **setPosition**: Set the position of the popover. Takes the `CameraPopoverOptions` that specify the new position.
+
+#### 支援的平臺
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### 示例
+
+     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 僅指定氣泡框的錨元素的位置和箭頭方向,從 iPad 庫或專輯選擇圖像時的參數。
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+#### 說明
+
+  * **x**: x 螢幕元素到其錨定氣泡框上的圖元座標。*(人數)*
+
+  * **y**: 螢幕元素到其錨定氣泡框上的 y 圖元座標。*(人數)*
+
+  * **width**: 寬度以圖元為單位),到其錨定氣泡框上的螢幕元素。*(人數)*
+
+  * **height**: 高度以圖元為單位),到其錨定氣泡框上的螢幕元素。*(人數)*
+
+  * **arrowDir**: 氣泡框上的箭頭應指向的方向。定義在 `Camera.PopoverArrowDirection` *(人數)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+請注意氣泡框的大小可能會更改箭頭的方向和螢幕的方向進行調整。 請確保帳戶方向更改時指定錨元素位置。
+
+## navigator.camera.cleanup
+
+刪除中間從臨時存儲攝像機所拍攝的照片。
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+#### 說明
+
+刪除保留在臨時存儲在調用 `camera.getPicture` 後的中間的影像檔。 適用只有當 `Camera.sourceType` 的值等於 `Camera.PictureSourceType.CAMERA` 和 `Camera.destinationType` 等於 `Camera.DestinationType.FILE_URI`.
+
+#### 支援的平臺
+
+![](doc/img/android-fail.png) ![](doc/img/blackberry-fail.png) ![](doc/img/browser-fail.png) ![](doc/img/firefox-fail.png) ![](doc/img/fireos-fail.png) ![](doc/img/ios-success.png) ![](doc/img/windows-fail.png) ![](doc/img/wp8-fail.png) ![](doc/img/ubuntu-fail.png)
+
+#### 示例
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 435 - 0
miaomiao/plugins/cordova-plugin-camera/doc/zh/index.md

xqd
@@ -0,0 +1,435 @@
+<!---
+    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.
+-->
+
+# cordova-plugin-camera
+
+這個外掛程式定義了一個全球 `navigator.camera` 物件,它提供了 API,拍照,從系統的圖像庫中選擇圖像。
+
+雖然該物件附加到全球範圍內 `導航器`,它不可用直到 `deviceready` 事件之後。
+
+    document.addEventListener("deviceready", onDeviceReady, false);
+    function onDeviceReady() {
+        console.log(navigator.camera);
+    }
+    
+
+## 安裝
+
+    cordova plugin add cordova-plugin-camera
+    
+
+## navigator.camera.getPicture
+
+需要一張照片,使用相機,或從設備的圖像庫檢索一張照片。 圖像被傳遞給成功回檔的 base64 編碼 `String`,或作為 URI 為影像檔。 該方法本身返回一個 `CameraPopoverHandle` 物件,它可以用來重新置放檔選擇氣泡框。
+
+    navigator.camera.getPicture( cameraSuccess, cameraError, cameraOptions );
+    
+
+### 說明
+
+`camera.getPicture` 函數打開該設備的預設攝像頭應用程式,允許使用者拍照。 `Camera.sourceType` 等於 `Camera.PictureSourceType.CAMERA` 時,預設情況下,發生此行為。 一旦使用者打斷了他的照片,相機應用程式關閉,且應用程式還原。
+
+如果 `Camera.sourceType` 是 `Camera.PictureSourceType.PHOTOLIBRARY` 或 `Camera.PictureSourceType.SAVEDPHOTOALBUM`,然後顯示一個對話方塊,允許使用者選擇一個現有的圖像。 `camera.getPicture` 函數返回一個 `CameraPopoverHandle` 物件,它可以用於重新置放圖像選擇的對話方塊,例如,當設備的方向變化。
+
+傳回值是發送到 `cameraSuccess` 回呼函數中,在以下的格式,具體取決於指定的 `cameraOptions` 之一:
+
+*   A `String` 包含的 base64 編碼的照片圖像。
+
+*   A `String` 表示在本機存放區 (預設值) 上的影像檔位置。
+
+你可以做任何你想要的編碼的圖像或 URI,例如:
+
+*   呈現在圖像 `<img>` 標記,如下面的示例所示
+
+*   保存本地的資料 ( `LocalStorage` , [Lawnchair][1],等等.)
+
+*   將資料發佈到遠端伺服器
+
+ [1]: http://brianleroux.github.com/lawnchair/
+
+**注**: 在更新設備上的照片解析度是很好。 選擇從設備的庫的照片是不壓縮螢幕使其以較低的品質,即使指定了一個 `quality` 參數。 要避免常見的記憶體問題,請將 `Camera.destinationType` 設置為 `FILE_URI`,而不是 `DATA_URL`.
+
+### 支援的平臺
+
+*   亞馬遜火 OS
+*   Android 系統
+*   黑莓 10
+*   瀏覽器
+*   火狐瀏覽器的作業系統
+*   iOS
+*   泰
+*   Windows Phone 7 和 8
+*   Windows 8
+
+### 首選項 (iOS)
+
+*   **CameraUsesGeolocation**(布林值,預設值為 false)。 用於捕獲 jpeg 檔,設置為 true,以在 EXIF 頭資訊中獲取地理定位資料。 這將觸發請求的地理位置的許可權,如果設置為 true。
+    
+        <preference name="CameraUsesGeolocation" value="false" />
+        
+
+### 亞馬遜火 OS 怪癖
+
+亞馬遜火 OS 使用意圖啟動相機活動設備來捕捉圖像上, 和手機上記憶體不足,科爾多瓦活動可能被殺害。 在這種情況下,可能不會顯示圖像時恢復了科爾多瓦活動。
+
+### Android 的怪癖
+
+Android 使用意圖以啟動相機活動設備來捕捉圖像上, 和手機上記憶體不足,科爾多瓦活動可能被殺害。 在這種情況下,可能不會顯示圖像時恢復了科爾多瓦活動。
+
+### 瀏覽器的怪癖
+
+可以只返回照片作為 base64 編碼的圖像。
+
+### 火狐瀏覽器作業系統的怪癖
+
+觀景窗外掛程式目前實施使用 [Web 活動][2].
+
+ [2]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+
+### iOS 的怪癖
+
+包括 JavaScript `alert ()` 中的回呼函數會導致問題。 包裝內 `setTimeout()` 允許 iOS 圖像選取器或氣泡框以完全關閉之前,警報將顯示警報:
+
+    setTimeout(function() {
+        // do your thing here!
+    }, 0);
+    
+
+### Windows Phone 7 的怪癖
+
+調用本機攝像頭應用程式,而通過 Zune 所連接的設備不能工作,並且觸發錯誤回檔。
+
+### 泰怪癖
+
+泰只支援 `destinationType` 的 `Camera.DestinationType.FILE_URI` 和 `Camera.PictureSourceType.PHOTOLIBRARY` 的 `sourceType`.
+
+### 示例
+
+拍一張照片,並檢索它作為一個 base64 編碼的圖像:
+
+    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);
+    }
+    
+
+拍一張照片和檢索圖像的檔位置:
+
+    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
+
+要自訂相機設置的可選參數。
+
+    { 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 };
+    
+
+### 選項
+
+*   **品質**: 保存的圖像,表示為範圍 0-100,100,是通常全解析度,無損失從檔案壓縮的品質。 預設值為 50。 *(人數)*(請注意相機的解析度有關的資訊是不可用)。
+
+*   **可**: 選擇傳回值的格式。預設值是 FILE_URI。定義在 `navigator.camera.DestinationType` *(人數)*
+    
+        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)
+        };
+        
+
+*   **時**: 設置圖片的來源。預設值是觀景窗。定義在 `navigator.camera.PictureSourceType` *(人數)*
+    
+        Camera.PictureSourceType = {
+            PHOTOLIBRARY : 0,
+            CAMERA : 1,
+            SAVEDPHOTOALBUM : 2
+        };
+        
+
+*   **allowEdit**: 允許簡單編輯前選擇圖像。*(布林)*
+
+*   **encodingType**: 選擇返回的影像檔的編碼。預設值為 JPEG。定義在 `navigator.camera.EncodingType` *(人數)*
+    
+        Camera.EncodingType = {
+            JPEG : 0,               // Return JPEG encoded image
+            PNG : 1                 // Return PNG encoded image
+        };
+        
+
+*   **targetWidth**: 向尺度圖像的圖元寬度。必須用**targetHeight**。縱橫比保持不變。*(人數)*
+
+*   **targetHeight**: 以圖元為單位向尺度圖像的高度。必須用**targetWidth**。縱橫比保持不變。*(人數)*
+
+*   **媒體類型**: 設置的媒體,從選擇類型。 時才起作用 `PictureSourceType` 是 `PHOTOLIBRARY` 或 `SAVEDPHOTOALBUM` 。 定義在 `nagivator.camera.MediaType` *(人數)*
+    
+        Camera.MediaType = {
+            PICTURE: 0,    // allow selection of still pictures only. 預設情況。 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**: 旋轉圖像,該設備時捕獲的定向的正確。*(布林)*
+
+*   **saveToPhotoAlbum**: 將圖像保存到相冊在設備上捕獲後。*(布林)*
+
+*   **popoverOptions**: 只有 iOS 在 iPad 中指定氣泡框位置的選項。在中定義`CameraPopoverOptions`.
+
+*   **cameraDirection**: 選擇相機以使用 (前面或後面-面向)。預設值是背。定義在 `navigator.camera.Direction` *(人數)*
+    
+        Camera.Direction = {
+            BACK : 0,      // Use the back-facing camera
+            FRONT : 1      // Use the front-facing camera
+        };
+        
+
+### 亞馬遜火 OS 怪癖
+
+*   任何 `cameraDirection` 值回朝的照片中的結果。
+
+*   忽略 `allowEdit` 參數。
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`和 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 都顯示相同的相冊。
+
+### Android 的怪癖
+
+*   任何 `cameraDirection` 值結果在背面的照片。
+
+*   忽略 `allowEdit` 參數。
+
+*   `Camera.PictureSourceType.PHOTOLIBRARY`和 `Camera.PictureSourceType.SAVEDPHOTOALBUM` 都顯示相同的寫真集。
+
+### 黑莓 10 的怪癖
+
+*   忽略 `quality` 參數。
+
+*   忽略 `allowEdit` 參數。
+
+*   `Camera.MediaType`不受支援。
+
+*   忽略 `correctOrientation` 參數。
+
+*   忽略 `cameraDirection` 參數。
+
+### 火狐瀏覽器作業系統的怪癖
+
+*   忽略 `quality` 參數。
+
+*   `Camera.DestinationType`將被忽略並且等於 `1` (影像檔的 URI)
+
+*   忽略 `allowEdit` 參數。
+
+*   忽略 `PictureSourceType` 參數 (使用者選擇它在對話方塊視窗中)
+
+*   忽略`encodingType`
+
+*   忽略了 `targetWidth` 和`targetHeight`
+
+*   `Camera.MediaType`不受支援。
+
+*   忽略 `correctOrientation` 參數。
+
+*   忽略 `cameraDirection` 參數。
+
+### iOS 的怪癖
+
+*   設置 `quality` 低於 50,避免在某些設備上的記憶體不足錯誤。
+
+*   當使用 `destinationType.FILE_URI` ,照片都保存在應用程式的臨時目錄。應用程式結束時,將刪除該應用程式的臨時目錄中的內容。
+
+### 泰怪癖
+
+*   不支援的選項
+
+*   總是返回一個檔的 URI
+
+### Windows Phone 7 和 8 的怪癖
+
+*   忽略 `allowEdit` 參數。
+
+*   忽略 `correctOrientation` 參數。
+
+*   忽略 `cameraDirection` 參數。
+
+*   忽略 `saveToPhotoAlbum` 參數。 重要: 使用 wp7/8 科爾多瓦攝像頭 API 拍攝的所有圖像總是都複製到手機的相機膠捲。 根據使用者的設置,這可能也意味著圖像是自動上傳到他們另。 這有可能意味著的圖像,可以比你的應用程式的目的更多的觀眾。 如果此阻滯劑您的應用程式,您將需要實現 CameraCaptureTask 在 msdn 上記載: [HTTP://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx][3]你可能還評論或在[問題追蹤器][4]的向上投票的相關的問題
+
+*   忽略了 `mediaType` 屬性的 `cameraOptions` 作為 Windows Phone SDK 並不提供從 PHOTOLIBRARY 中選擇視頻的方法。
+
+ [3]: http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx
+ [4]: https://issues.apache.org/jira/browse/CB-2083
+
+## CameraError
+
+onError 的回呼函數提供了一條錯誤訊息。
+
+    function(message) {
+        // Show a helpful message
+    }
+    
+
+### 參數
+
+*   **message**: 消息提供的設備的本機代碼。*(String)*
+
+## cameraSuccess
+
+提供的圖像資料的 onSuccess 回呼函數。
+
+    function(imageData) {
+        // Do something with the image
+    }
+    
+
+### 參數
+
+*   **imageData**: Base64 編碼進行編碼的圖像資料,*或*影像檔的 URI,取決於 `cameraOptions` 效果。*(String)*
+
+### 示例
+
+    // Show image
+    //
+    function cameraCallback(imageData) {
+        var image = document.getElementById('myImage');
+        image.src = "data:image/jpeg;base64," + imageData;
+    }
+    
+
+## CameraPopoverHandle
+
+由 `navigator.camera.getPicture` 創建的氣泡框對話方塊的控制碼.
+
+### 方法
+
+*   **setPosition**: 設置氣泡框的位置。
+
+### 支援的平臺
+
+*   iOS
+
+### setPosition
+
+設置氣泡框的位置。
+
+**參數**:
+
+*   `cameraPopoverOptions`: `CameraPopoverOptions` ,指定新的位置
+
+### 示例
+
+     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 僅指定氣泡框的錨元素的位置和箭頭方向,從 iPad 庫或專輯選擇圖像時的參數。
+
+    { x : 0,
+      y :  32,
+      width : 320,
+      height : 480,
+      arrowDir : Camera.PopoverArrowDirection.ARROW_ANY
+    };
+    
+
+### CameraPopoverOptions
+
+*   **x**: x 螢幕元素到其錨定氣泡框上的圖元座標。*(人數)*
+
+*   **y**: 螢幕元素到其錨定氣泡框上的 y 圖元座標。*(人數)*
+
+*   **width**: 寬度以圖元為單位),到其錨定氣泡框上的螢幕元素。*(人數)*
+
+*   **height**: 高度以圖元為單位),到其錨定氣泡框上的螢幕元素。*(人數)*
+
+*   **arrowDir**: 氣泡框上的箭頭應指向的方向。定義在 `Camera.PopoverArrowDirection` *(人數)*
+    
+            Camera.PopoverArrowDirection = {
+                ARROW_UP : 1,        // matches iOS UIPopoverArrowDirection constants
+                ARROW_DOWN : 2,
+                ARROW_LEFT : 4,
+                ARROW_RIGHT : 8,
+                ARROW_ANY : 15
+            };
+        
+
+請注意氣泡框的大小可能會更改箭頭的方向和螢幕的方向進行調整。 請確保帳戶方向更改時指定錨元素位置。
+
+## navigator.camera.cleanup
+
+刪除中間從臨時存儲攝像機所拍攝的照片。
+
+    navigator.camera.cleanup( cameraSuccess, cameraError );
+    
+
+### 描述
+
+刪除保留在臨時存儲在調用 `camera.getPicture` 後的中間的影像檔。 適用只有當 `Camera.sourceType` 的值等於 `Camera.PictureSourceType.CAMERA` 和 `Camera.destinationType` 等於 `Camera.DestinationType.FILE_URI`.
+
+### 支援的平臺
+
+*   iOS
+
+### 示例
+
+    navigator.camera.cleanup(onSuccess, onFail);
+    
+    function onSuccess() {
+        console.log("Camera cleanup success.")
+    }
+    
+    function onFail(message) {
+        alert('Failed because: ' + message);
+    }

+ 443 - 0
miaomiao/plugins/cordova-plugin-camera/jsdoc2md/TEMPLATE.md

xqd
@@ -0,0 +1,443 @@
+---
+title: Camera
+description: Take pictures with the device camera.
+---
+{{>cdv-license~}}
+
+|Android|iOS| Windows 8.1 Store | Windows 8.1 Phone | Windows 10 Store | Travis CI |
+|:-:|:-:|:-:|:-:|:-:|:-:|
+|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=android,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=android,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=ios,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=ios,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=windows-8.1-store,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-8.1-store,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=windows-8.1-phone,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-8.1-phone,PLUGIN=cordova-plugin-camera/)|[![Build Status](http://cordova-ci.cloudapp.net:8080/buildStatus/icon?job=cordova-periodic-build/PLATFORM=windows-10-store,PLUGIN=cordova-plugin-camera)](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-10-store,PLUGIN=cordova-plugin-camera/)|[![Build Status](https://travis-ci.org/apache/cordova-plugin-camera.svg?branch=master)](https://travis-ci.org/apache/cordova-plugin-camera)
+
+# cordova-plugin-camera
+
+This plugin defines a global `navigator.camera` object, which provides an API for taking pictures and for choosing images from
+the system's image library.
+
+{{>cdv-header device-ready-warning-obj='navigator.camera' npmName='cordova-plugin-camera' cprName='org.apache.cordova.camera' pluginName='Plugin Camera' repoUrl='https://github.com/apache/cordova-plugin-camera' }}
+
+
+### iOS Quirks
+
+Since iOS 10 it's mandatory to add a `NSCameraUsageDescription` and `NSPhotoLibraryUsageDescription` in the info.plist.
+
+- `NSCameraUsageDescription` describes the reason that the app accesses the user’s camera.
+- `NSPhotoLibraryUsageDescription` describes the reason the app accesses the user's photo library. 
+
+When the system prompts the user to allow access, this string is displayed as part of the dialog box. 
+
+To add this entry you can pass the following variables on plugin install.
+
+- `CAMERA_USAGE_DESCRIPTION` for `NSCameraUsageDescription`
+- `PHOTOLIBRARY_USAGE_DESCRIPTION` for `NSPhotoLibraryUsageDescription`
+
+Example:
+
+    cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="your usage message" --variable PHOTOLIBRARY_USAGE_DESCRIPTION="your usage message"
+
+If you don't pass the variable, the plugin will add an empty string as value.
+
+---
+
+# API Reference <a name="reference"></a>
+
+{{#orphans~}}
+{{>member-index}}
+{{/orphans}}
+* [CameraPopoverHandle](#module_CameraPopoverHandle)
+* [CameraPopoverOptions](#module_CameraPopoverOptions)
+
+---
+
+{{#modules~}}
+{{>header~}}
+{{>body~}}
+{{>members~}}
+
+---
+
+{{/modules}}
+
+## `camera.getPicture` Errata
+
+#### Example <a name="camera-getPicture-examples"></a>
+
+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);
+    }
+
+Take a photo and retrieve it as a Base64-encoded image:
+
+    /**
+     * Warning: Using DATA_URL is not recommended! The DATA_URL destination
+     * type is very memory intensive, even with a low quality setting. Using it
+     * can result in out of memory errors and application crashes. Use FILE_URI
+     * or NATIVE_URI instead.
+     */
+    navigator.camera.getPicture(onSuccess, onFail, { quality: 25,
+        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);
+    }
+
+#### Preferences (iOS)
+
+-  __CameraUsesGeolocation__ (boolean, defaults to false). For capturing JPEGs, set to true to get geolocation data in the EXIF header. This will trigger a request for geolocation permissions if set to true.
+
+        <preference name="CameraUsesGeolocation" value="false" />
+
+#### Amazon Fire OS Quirks <a name="camera-getPicture-quirks"></a>
+
+Amazon Fire OS uses intents to launch the camera activity on the device to capture
+images, and on phones with low memory, the Cordova activity may be killed.  In this
+scenario, the image may not appear when the Cordova activity is restored.
+
+#### Android Quirks
+
+Android 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 result from the plugin call will be delivered via the resume event.
+See [the Android Lifecycle guide][android_lifecycle]
+for more information. The `pendingResult.result` value will contain the value that
+would be passed to the callbacks (either the URI/URL or an error message). Check
+the `pendingResult.pluginStatus` to determine whether or not the call was
+successful.
+
+#### Browser Quirks
+
+Can only return photos as Base64-encoded image.
+
+#### Firefox OS Quirks
+
+Camera plugin is currently implemented using [Web Activities][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.
+
+#### Windows quirks
+
+On Windows Phone 8.1 using `SAVEDPHOTOALBUM` or `PHOTOLIBRARY` as a source type causes application to suspend until file picker returns the selected image and
+then restore with start page as defined in app's `config.xml`. In case when `camera.getPicture` was called from different page, this will lead to reloading
+start page from scratch and success and error callbacks will never be called.
+
+To avoid this we suggest using SPA pattern or call `camera.getPicture` only from your app's start page.
+
+More information about Windows Phone 8.1 picker APIs is here: [How to continue your Windows Phone app after calling a file picker](https://msdn.microsoft.com/en-us/library/windows/apps/dn720490.aspx)
+
+#### Tizen Quirks
+
+Tizen only supports a `destinationType` of
+`Camera.DestinationType.FILE_URI` and a `sourceType` of
+`Camera.PictureSourceType.PHOTOLIBRARY`.
+
+
+## `CameraOptions` Errata <a name="CameraOptions-quirks"></a>
+
+#### Amazon Fire OS Quirks
+
+- Any `cameraDirection` value results in a back-facing photo.
+
+- Ignores the `allowEdit` parameter.
+
+- `Camera.PictureSourceType.PHOTOLIBRARY` and `Camera.PictureSourceType.SAVEDPHOTOALBUM` both display the same photo album.
+
+#### Android Quirks
+
+- Any `cameraDirection` value results in a back-facing photo.
+
+- **`allowEdit` is unpredictable on Android and it should not be used!** The Android implementation of this plugin tries to find and use an application on the user's device to do image cropping. The plugin has no control over what application the user selects to perform the image cropping and it is very possible that the user could choose an incompatible option and cause the plugin to fail. This sometimes works because most devices come with an application that handles cropping in a way that is compatible with this plugin (Google Plus Photos), but it is unwise to rely on that being the case. If image editing is essential to your application, consider seeking a third party library or plugin that provides its own image editing utility for a more robust solution.
+
+- `Camera.PictureSourceType.PHOTOLIBRARY` and `Camera.PictureSourceType.SAVEDPHOTOALBUM` both display the same photo album.
+
+- Ignores the `encodingType` parameter if the image is unedited (i.e. `quality` is 100, `correctOrientation` is false, and no `targetHeight` or `targetWidth` are specified). The `CAMERA` source will always return the JPEG file given by the native camera and the `PHOTOLIBRARY` and `SAVEDPHOTOALBUM` sources will return the selected file in its existing encoding.
+
+#### BlackBerry 10 Quirks
+
+- Ignores the `quality` parameter.
+
+- Ignores the `allowEdit` parameter.
+
+- `Camera.MediaType` is not supported.
+
+- Ignores the `correctOrientation` parameter.
+
+- Ignores the `cameraDirection` parameter.
+
+#### Firefox OS Quirks
+
+- Ignores the `quality` parameter.
+
+- `Camera.DestinationType` is ignored and equals `1` (image file URI)
+
+- Ignores the `allowEdit` parameter.
+
+- Ignores the `PictureSourceType` parameter (user chooses it in a dialog window)
+
+- Ignores the `encodingType`
+
+- Ignores the `targetWidth` and `targetHeight`
+
+- `Camera.MediaType` is not supported.
+
+- Ignores the `correctOrientation` parameter.
+
+- Ignores the `cameraDirection` parameter.
+
+#### iOS Quirks
+
+- When using `destinationType.FILE_URI`, photos are saved in the application's temporary directory. The contents of the application's temporary directory is deleted when the application ends.
+
+- When using `destinationType.NATIVE_URI` and `sourceType.CAMERA`, photos are saved in the saved photo album regardless on the value of `saveToPhotoAlbum` parameter.
+
+- When using `destinationType.NATIVE_URI` and `sourceType.PHOTOLIBRARY` or `sourceType.SAVEDPHOTOALBUM`, all editing options are ignored and link is returned to original picture.
+
+#### Tizen Quirks
+
+- options not supported
+
+- always returns a FILE URI
+
+#### Windows Phone 7 and 8 Quirks
+
+- Ignores the `allowEdit` parameter.
+
+- Ignores the `correctOrientation` parameter.
+
+- Ignores the `cameraDirection` parameter.
+
+- Ignores the `saveToPhotoAlbum` parameter.  IMPORTANT: All images taken with the WP8/8 Cordova camera API are always copied to the phone's camera roll.  Depending on the user's settings, this could also mean the image is auto-uploaded to their OneDrive.  This could potentially mean the image is available to a wider audience than your app intended. If this is a blocker for your application, you will need to implement the CameraCaptureTask as [documented on MSDN][msdn_wp8_docs]. You may also comment or up-vote the related issue in the [issue tracker][wp8_bug].
+
+- Ignores the `mediaType` property of `cameraOptions` as the Windows Phone SDK does not provide a way to choose videos from PHOTOLIBRARY.
+
+[android_lifecycle]: http://cordova.apache.org/docs/en/dev/guide/platforms/android/lifecycle.html
+[web_activities]: https://hacks.mozilla.org/2013/01/introducing-web-activities/
+[wp8_bug]: https://issues.apache.org/jira/browse/CB-2083
+[msdn_wp8_docs]: http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394006.aspx
+
+## Sample: Take Pictures, Select Pictures from the Picture Library, and Get Thumbnails <a name="sample"></a>
+
+The Camera plugin allows you to do things like open the device's Camera app and take a picture, or open the file picker and select one. The code snippets in this section demonstrate different tasks including:
+
+* Open the Camera app and [take a Picture](#takePicture)
+* Take a picture and [return thumbnails](#getThumbnails) (resized picture)
+* Take a picture and [generate a FileEntry object](#convert)
+* [Select a file](#selectFile) from the picture library
+* Select a JPEG image and [return thumbnails](#getFileThumbnails) (resized image)
+* Select an image and [generate a FileEntry object](#convert)
+
+## Take a Picture <a name="takePicture"></a>
+
+Before you can take a picture, you need to set some Camera plugin options to pass into the Camera plugin's `getPicture` function. Here is a common set of recommendations. In this example, you create the object that you will use for the Camera options, and set the `sourceType` dynamically to support both the Camera app and the file picker.
+
+```js
+function setOptions(srcType) {
+    var options = {
+        // Some common settings are 20, 50, and 100
+        quality: 50,
+        destinationType: Camera.DestinationType.FILE_URI,
+        // In this app, dynamically set the picture source, Camera or photo gallery
+        sourceType: srcType,
+        encodingType: Camera.EncodingType.JPEG,
+        mediaType: Camera.MediaType.PICTURE,
+        allowEdit: true,
+        correctOrientation: true  //Corrects Android orientation quirks
+    }
+    return options;
+}
+```
+
+Typically, you want to use a FILE_URI instead of a DATA_URL to avoid most memory issues. JPEG is the recommended encoding type for Android.
+
+You take a picture by passing in the options object to `getPicture`, which takes a CameraOptions object as the third argument. When you call `setOptions`, pass `Camera.PictureSourceType.CAMERA` as the picture source.
+
+```js
+function openCamera(selection) {
+
+    var srcType = Camera.PictureSourceType.CAMERA;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        displayImage(imageUri);
+        // You may choose to copy the picture, save it somewhere, or upload.
+        func(imageUri);
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+Once you take the picture, you can display it or do something else. In this example, call the app's `displayImage` function from the preceding code.
+
+```js
+function displayImage(imgUri) {
+
+    var elem = document.getElementById('imageFile');
+    elem.src = imgUri;
+}
+```
+
+To display the image on some platforms, you might need to include the main part of the URI in the Content-Security-Policy `<meta>` element in index.html. For example, on Windows 10, you can include `ms-appdata:` in your `<meta>` element. Here is an example.
+
+```html
+<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ms-appdata: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
+```
+
+## Take a Picture and Return Thumbnails (Resize the Picture) <a name="getThumbnails"></a>
+
+To get smaller images, you can return a resized image by passing both `targetHeight` and `targetWidth` values with your CameraOptions object. In this example, you resize the returned image to fit in a 100px by 100px box (the aspect ratio is maintained, so 100px is either the height or width, whichever is greater in the source).
+
+```js
+function openCamera(selection) {
+
+    var srcType = Camera.PictureSourceType.CAMERA;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    if (selection == "camera-thmb") {
+        options.targetHeight = 100;
+        options.targetWidth = 100;
+    }
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        // Do something
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+## Select a File from the Picture Library <a name="selectFile"></a>
+
+When selecting a file using the file picker, you also need to set the CameraOptions object. In this example, set the `sourceType` to `Camera.PictureSourceType.SAVEDPHOTOALBUM`. To open the file picker, call `getPicture` just as you did in the previous example, passing in the success and error callbacks along with CameraOptions object.
+
+```js
+function openFilePicker(selection) {
+
+    var srcType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        // Do something
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+## Select an Image and Return Thumbnails (resized images) <a name="getFileThumbnails"></a>
+
+Resizing a file selected with the file picker works just like resizing using the Camera app; set the `targetHeight` and `targetWidth` options.
+
+```js
+function openFilePicker(selection) {
+
+    var srcType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
+    var options = setOptions(srcType);
+    var func = createNewFileEntry;
+
+    if (selection == "picker-thmb") {
+        // To downscale a selected image,
+        // Camera.EncodingType (e.g., JPEG) must match the selected image type.
+        options.targetHeight = 100;
+        options.targetWidth = 100;
+    }
+
+    navigator.camera.getPicture(function cameraSuccess(imageUri) {
+
+        // Do something with image
+
+    }, function cameraError(error) {
+        console.debug("Unable to obtain picture: " + error, "app");
+
+    }, options);
+}
+```
+
+## Take a picture and get a FileEntry Object <a name="convert"></a>
+
+If you want to do something like copy the image to another location, or upload it somewhere using the FileTransfer plugin, you need to get a FileEntry object for the returned picture. To do that, call `window.resolveLocalFileSystemURL` on the file URI returned by the Camera app. If you need to use a FileEntry object, set the `destinationType` to `Camera.DestinationType.FILE_URI` in your CameraOptions object (this is also the default value).
+
+>*Note* You need the [File plugin](https://www.npmjs.com/package/cordova-plugin-file) to call `window.resolveLocalFileSystemURL`.
+
+Here is the call to `window.resolveLocalFileSystemURL`. The image URI is passed to this function from the success callback of `getPicture`. The success handler of `resolveLocalFileSystemURL` receives the FileEntry object.
+
+```js
+function getFileEntry(imgUri) {
+    window.resolveLocalFileSystemURL(imgUri, function success(fileEntry) {
+
+        // Do something with the FileEntry object, like write to it, upload it, etc.
+        // writeFile(fileEntry, imgUri);
+        console.log("got file: " + fileEntry.fullPath);
+        // displayFileData(fileEntry.nativeURL, "Native URL");
+
+    }, function () {
+      // If don't get the FileEntry (which may happen when testing
+      // on some emulators), copy to a new FileEntry.
+        createNewFileEntry(imgUri);
+    });
+}
+```
+
+In the example shown in the preceding code, you call the app's `createNewFileEntry` function if you don't get a valid FileEntry object. The image URI returned from the Camera app should result in a valid FileEntry, but platform behavior on some emulators may be different for files returned from the file picker.
+
+>*Note* To see an example of writing to a FileEntry, see the [File plugin README](https://www.npmjs.com/package/cordova-plugin-file).
+
+The code shown here creates a file in your app's cache (in sandboxed storage) named `tempFile.jpeg`. With the new FileEntry object, you can copy the image to the file or do something else like upload it.
+
+```js
+function createNewFileEntry(imgUri) {
+    window.resolveLocalFileSystemURL(cordova.file.cacheDirectory, function success(dirEntry) {
+
+        // JPEG file
+        dirEntry.getFile("tempFile.jpeg", { create: true, exclusive: false }, function (fileEntry) {
+
+            // Do something with it, like write to it, upload it, etc.
+            // writeFile(fileEntry, imgUri);
+            console.log("got file: " + fileEntry.fullPath);
+            // displayFileData(fileEntry.fullPath, "File copied to");
+
+        }, onErrorCreateFile);
+
+    }, onErrorResolveUrl);
+}
+```

+ 63 - 0
miaomiao/plugins/cordova-plugin-camera/package.json

xqd
@@ -0,0 +1,63 @@
+{
+  "name": "cordova-plugin-camera",
+  "version": "2.4.0",
+  "description": "Cordova Camera Plugin",
+  "types": "./types/index.d.ts",
+  "cordova": {
+    "id": "cordova-plugin-camera",
+    "platforms": [
+      "firefoxos",
+      "android",
+      "amazon-fireos",
+      "ubuntu",
+      "ios",
+      "blackberry10",
+      "wp7",
+      "wp8",
+      "windows8",
+      "browser",
+      "windows"
+    ]
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/apache/cordova-plugin-camera"
+  },
+  "keywords": [
+    "cordova",
+    "camera",
+    "ecosystem:cordova",
+    "cordova-firefoxos",
+    "cordova-android",
+    "cordova-amazon-fireos",
+    "cordova-ubuntu",
+    "cordova-ios",
+    "cordova-blackberry10",
+    "cordova-wp7",
+    "cordova-wp8",
+    "cordova-windows8",
+    "cordova-browser",
+    "cordova-windows"
+  ],
+  "scripts": {
+    "precommit": "npm run gen-docs && git add README.md",
+    "gen-docs": "jsdoc2md --template \"jsdoc2md/TEMPLATE.md\" \"www/**/*.js\" --plugin \"dmd-plugin-cordova-plugin\" > README.md",
+    "test": "npm run jshint",
+    "jshint": "node node_modules/jshint/bin/jshint www && node node_modules/jshint/bin/jshint src && node node_modules/jshint/bin/jshint tests"
+  },
+  "author": "Apache Software Foundation",
+  "license": "Apache-2.0",
+  "engines": {
+    "cordovaDependencies": {
+      "3.0.0": {
+        "cordova": ">100"
+      }
+    }
+  },
+  "devDependencies": {
+    "dmd-plugin-cordova-plugin": "^0.1.0",
+    "husky": "^0.10.1",
+    "jsdoc-to-markdown": "^1.2.0",
+    "jshint": "^2.6.0"
+  }
+}

+ 283 - 0
miaomiao/plugins/cordova-plugin-camera/plugin.xml

xqd
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:rim="http://www.blackberry.com/ns/widgets"
+    id="cordova-plugin-camera"
+    version="2.4.0">
+    <name>Camera</name>
+    <description>Cordova Camera Plugin</description>
+    <license>Apache 2.0</license>
+    <keywords>cordova,camera</keywords>
+    <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git</repo>
+    <issue>https://issues.apache.org/jira/browse/CB/component/12320645</issue>
+
+    <dependency id="cordova-plugin-compat" version="^1.1.0" />
+
+    <js-module src="www/CameraConstants.js" name="Camera">
+        <clobbers target="Camera" />
+    </js-module>
+
+    <js-module src="www/CameraPopoverOptions.js" name="CameraPopoverOptions">
+        <clobbers target="CameraPopoverOptions" />
+    </js-module>
+
+
+
+    <js-module src="www/Camera.js" name="camera">
+        <clobbers target="navigator.camera" />
+    </js-module>
+
+    <!-- firefoxos -->
+    <platform name="firefoxos">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Camera">
+                <param name="firefoxos-package" value="Camera" />
+            </feature>
+        </config-file>
+
+        <js-module src="src/firefoxos/CameraProxy.js" name="CameraProxy">
+          <runs />
+        </js-module>
+    </platform>
+
+    <!-- android -->
+    <platform name="android">
+        <config-file target="res/xml/config.xml" parent="/*">
+            <feature name="Camera">
+                <param name="android-package" value="org.apache.cordova.camera.CameraLauncher"/>
+            </feature>
+        </config-file>
+        <config-file target="AndroidManifest.xml" parent="/*">
+            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+        </config-file>
+        <config-file target="AndroidManifest.xml" parent="application">
+          <provider
+              android:name="android.support.v4.content.FileProvider"
+              android:authorities="${applicationId}.provider"
+              android:exported="false"
+              android:grantUriPermissions="true" >
+              <meta-data
+                  android:name="android.support.FILE_PROVIDER_PATHS"
+                  android:resource="@xml/provider_paths"/>
+          </provider>
+        </config-file>
+
+        <source-file src="src/android/CameraLauncher.java" target-dir="src/org/apache/cordova/camera" />
+        <source-file src="src/android/CordovaUri.java" target-dir="src/org/apache/cordova/camera" />
+        <source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/camera" />
+        <source-file src="src/android/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
+        <source-file src="src/android/xml/provider_paths.xml" target-dir="res/xml" />
+
+        <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+          </js-module>
+
+        <framework src="com.android.support:support-v4:24.1.1+" />
+
+      </platform>
+
+    <!-- amazon-fireos -->
+    <platform name="amazon-fireos">
+        <config-file target="res/xml/config.xml" parent="/*">
+            <feature name="Camera">
+                <param name="android-package" value="org.apache.cordova.camera.CameraLauncher"/>
+            </feature>
+        </config-file>
+        <config-file target="AndroidManifest.xml" parent="/*">
+            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+        </config-file>
+
+        <source-file src="src/android/CameraLauncher.java" target-dir="src/org/apache/cordova/camera" />
+        <source-file src="src/android/FileHelper.java" target-dir="src/org/apache/cordova/camera" />
+        <source-file src="src/android/ExifHelper.java" target-dir="src/org/apache/cordova/camera" />
+
+        <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+        </js-module>
+
+     </platform>
+
+     <!-- ubuntu -->
+     <platform name="ubuntu">
+         <config-file target="config.xml" parent="/*">
+             <feature name="Camera">
+                 <param policy_group="camera" policy_version="1" />
+             </feature>
+         </config-file>
+         <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+         </js-module>
+         <header-file src="src/ubuntu/camera.h" />
+         <source-file src="src/ubuntu/camera.cpp" />
+
+         <resource-file src="src/ubuntu/back.png" />
+         <resource-file src="src/ubuntu/CaptureWidget.qml" />
+         <resource-file src="src/ubuntu/shoot.png" />
+         <resource-file src="src/ubuntu/toolbar-left.png" />
+         <resource-file src="src/ubuntu/toolbar-middle.png" />
+         <resource-file src="src/ubuntu/toolbar-right.png" />
+     </platform>
+
+     <!-- ios -->
+     <platform name="ios">
+         <config-file target="config.xml" parent="/*">
+             <feature name="Camera">
+                 <param name="ios-package" value="CDVCamera" />
+             </feature>
+             <preference name="CameraUsesGeolocation" value="false" />
+         </config-file>
+
+         <js-module src="www/ios/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+         </js-module>
+
+         <header-file src="src/ios/UIImage+CropScaleOrientation.h" />
+         <source-file src="src/ios/UIImage+CropScaleOrientation.m" />
+         <header-file src="src/ios/CDVCamera.h" />
+         <source-file src="src/ios/CDVCamera.m" />
+         <header-file src="src/ios/CDVJpegHeaderWriter.h" />
+         <source-file src="src/ios/CDVJpegHeaderWriter.m" />
+         <header-file src="src/ios/CDVExif.h" />
+         <framework src="ImageIO.framework" weak="true" />
+         <framework src="CoreLocation.framework" />
+         <framework src="CoreGraphics.framework" />
+         <framework src="AssetsLibrary.framework" />
+         <framework src="MobileCoreServices.framework" />
+         <framework src="CoreGraphics.framework" />
+         <framework src="AVFoundation.framework" />
+
+         <preference name="CAMERA_USAGE_DESCRIPTION" default=" " />
+         <config-file target="*-Info.plist" parent="NSCameraUsageDescription">
+             <string>$CAMERA_USAGE_DESCRIPTION</string>
+         </config-file>
+
+         <preference name="PHOTOLIBRARY_USAGE_DESCRIPTION" default=" " />
+         <config-file target="*-Info.plist" parent="NSPhotoLibraryUsageDescription">
+             <string>$PHOTOLIBRARY_USAGE_DESCRIPTION</string>
+         </config-file>
+
+         <config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
+             <string></string>
+         </config-file>
+
+     </platform>
+
+    <!-- blackberry10 -->
+    <platform name="blackberry10">
+        <source-file src="src/blackberry10/index.js" target-dir="Camera" />
+        <config-file target="www/config.xml" parent="/widget">
+            <feature name="Camera" value="Camera"/>
+        </config-file>
+        <config-file target="www/config.xml" parent="/widget/rim:permissions">
+          <rim:permit>access_shared</rim:permit>
+          <rim:permit>use_camera</rim:permit>
+        </config-file>
+        <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+        </js-module>
+        <asset src="www/blackberry10/assets" target="chrome" />
+    </platform>
+
+     <!-- wp7 -->
+    <platform name="wp7">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Camera">
+                <param name="wp-package" value="Camera"/>
+            </feature>
+        </config-file>
+
+        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
+            <Capability Name="ID_CAP_ISV_CAMERA" />
+            <Capability Name="ID_CAP_MEDIALIB" />
+        </config-file>
+
+        <source-file src="src/wp/Camera.cs" />
+
+
+        <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+        </js-module>
+    </platform>
+
+    <!-- wp8 -->
+    <platform name="wp8">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Camera">
+                <param name="wp-package" value="Camera"/>
+            </feature>
+        </config-file>
+
+        <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
+            <Capability Name="ID_CAP_ISV_CAMERA" />
+            <Capability Name="ID_CAP_MEDIALIB_PHOTO"/>
+        </config-file>
+
+        <source-file src="src/wp/Camera.cs" />
+
+        <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+        </js-module>
+    </platform>
+
+    <!-- windows8 -->
+    <platform name="windows8">
+
+        <config-file target="package.appxmanifest" parent="/Package/Capabilities">
+            <Capability Name="picturesLibrary" />
+            <DeviceCapability Name="webcam" />
+        </config-file>
+        <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+        </js-module>
+        <js-module src="src/windows/CameraProxy.js" name="CameraProxy">
+            <runs />
+        </js-module>
+
+    </platform>
+
+    <!-- browser -->
+    <platform name="browser">
+        <config-file target="config.xml" parent="/*">
+            <feature name="Camera">
+                <param name="browser-package" value="Camera" />
+            </feature>
+        </config-file>
+
+        <js-module src="src/browser/CameraProxy.js" name="CameraProxy">
+            <runs />
+        </js-module>
+    </platform>
+
+    <!-- windows -->
+    <platform name="windows">
+        <config-file target="package.appxmanifest" parent="/Package/Capabilities">
+            <DeviceCapability Name="webcam" />
+        </config-file>
+        <js-module src="www/CameraPopoverHandle.js" name="CameraPopoverHandle">
+            <clobbers target="CameraPopoverHandle" />
+        </js-module>
+        <js-module src="src/windows/CameraProxy.js" name="CameraProxy">
+            <runs />
+        </js-module>
+    </platform>
+
+</plugin>

+ 1399 - 0
miaomiao/plugins/cordova-plugin-camera/src/android/CameraLauncher.java

xqd
@@ -0,0 +1,1399 @@
+/*
+       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.InputStream;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.cordova.BuildHelper;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.LOG;
+import org.apache.cordova.PermissionHelper;
+import org.apache.cordova.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.media.ExifInterface;
+import android.media.MediaScannerConnection;
+import android.media.MediaScannerConnection.MediaScannerConnectionClient;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import android.support.v4.content.FileProvider;
+import android.util.Base64;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+/**
+ * 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";
+
+    public static final int PERMISSION_DENIED_ERROR = 20;
+    public static final int TAKE_PIC_SEC = 0;
+    public static final int SAVE_TO_ALBUM_SEC = 1;
+
+    private static final String LOG_TAG = "CameraLauncher";
+
+    //Where did this come from?
+    private static final int CROP_CAMERA = 100;
+
+    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 CordovaUri imageUri;            // Uri of captured image
+    private int encodingType;               // Type of encoding to use
+    private int mediaType;                  // What type of media to retrieve
+    private int destType;                   // Source type (needs to be saved for the permission handling)
+    private int srcType;                    // Destination type (needs to be saved for permission handling)
+    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.
+
+    protected final static String[] permissions = { Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE };
+
+    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
+    private Uri croppedUri;
+    private ExifHelper exifData;            // Exif data from source
+    private String applicationId;
+
+
+    /**
+     * 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;
+        //Adding an API to CoreAndroid to get the BuildConfigValue
+        //This allows us to not make this a breaking change to embedding
+        this.applicationId = (String) BuildHelper.getBuildConfigValue(cordova.getActivity(), "APPLICATION_ID");
+        this.applicationId = preferences.getString("applicationId", this.applicationId);
+
+
+        if (action.equals("takePicture")) {
+            this.srcType = CAMERA;
+            this.destType = FILE_URI;
+            this.saveToPhotoAlbum = false;
+            this.targetHeight = 0;
+            this.targetWidth = 0;
+            this.encodingType = JPEG;
+            this.mediaType = PICTURE;
+            this.mQuality = 50;
+
+            //Take the values from the arguments if they're not already defined (this is tricky)
+            this.destType = args.getInt(1);
+            this.srcType = args.getInt(2);
+            this.mQuality = args.getInt(0);
+            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.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;
+            }
+
+            // We don't return full-quality PNG files. The camera outputs a JPEG
+            // so requesting it as a PNG provides no actual benefit
+            if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
+                    !this.correctOrientation && this.encodingType == PNG && this.srcType == CAMERA) {
+                this.encodingType = JPEG;
+            }
+
+            try {
+                if (this.srcType == CAMERA) {
+                    this.callTakePicture(destType, encodingType);
+                }
+                else if ((this.srcType == PHOTOLIBRARY) || (this.srcType == SAVEDPHOTOALBUM)) {
+                    // FIXME: Stop always requesting the permission
+                    if(!PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
+                        PermissionHelper.requestPermission(this, SAVE_TO_ALBUM_SEC, Manifest.permission.READ_EXTERNAL_STORAGE);
+                    } else {
+                        this.getImage(this.srcType, destType, encodingType);
+                    }
+                }
+            }
+            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 = cordova.getActivity().getExternalCacheDir();
+        }
+        // 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 returnType        Set the type of image to return.
+     * @param encodingType           Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
+     */
+    public void callTakePicture(int returnType, int encodingType) {
+        boolean saveAlbumPermission = PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
+        boolean takePicturePermission = PermissionHelper.hasPermission(this, Manifest.permission.CAMERA);
+
+        // CB-10120: The CAMERA permission does not need to be requested unless it is declared
+        // in AndroidManifest.xml. This plugin does not declare it, but others may and so we must
+        // check the package info to determine if the permission is present.
+
+        if (!takePicturePermission) {
+            takePicturePermission = true;
+            try {
+                PackageManager packageManager = this.cordova.getActivity().getPackageManager();
+                String[] permissionsInPackage = packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions;
+                if (permissionsInPackage != null) {
+                    for (String permission : permissionsInPackage) {
+                        if (permission.equals(Manifest.permission.CAMERA)) {
+                            takePicturePermission = false;
+                            break;
+                        }
+                    }
+                }
+            } catch (NameNotFoundException e) {
+                // We are requesting the info for our package, so this should
+                // never be caught
+            }
+        }
+
+        if (takePicturePermission && saveAlbumPermission) {
+            takePicture(returnType, encodingType);
+        } else if (saveAlbumPermission && !takePicturePermission) {
+            PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.CAMERA);
+        } else if (!saveAlbumPermission && takePicturePermission) {
+            PermissionHelper.requestPermission(this, TAKE_PIC_SEC, Manifest.permission.READ_EXTERNAL_STORAGE);
+        } else {
+            PermissionHelper.requestPermissions(this, TAKE_PIC_SEC, permissions);
+        }
+    }
+
+    public void takePicture(int returnType, int encodingType)
+    {
+        // Save the number of images currently on disk for later
+        this.numPics = queryImgDB(whichContentStore()).getCount();
+
+        // Let's use the intent and see what happens
+        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+
+        // Specify file so that large image is captured and returned
+        File photo = createCaptureFile(encodingType);
+        this.imageUri = new CordovaUri(FileProvider.getUriForFile(cordova.getActivity(),
+                applicationId + ".provider",
+                photo));
+        intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageUri.getCorrectUri());
+        //We can write to this URI, this will hopefully allow us to write files to get to the next step
+        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        if (this.cordova != null) {
+            // Let's check to make sure the camera is actually installed. (Legacy Nexus 7 code)
+            PackageManager mPm = this.cordova.getActivity().getPackageManager();
+            if(intent.resolveActivity(mPm) != null)
+            {
+
+                this.cordova.startActivityForResult((CordovaPlugin) this, intent, (CAMERA + 1) * 16 + returnType + 1);
+            }
+            else
+            {
+                LOG.d(LOG_TAG, "Error: You don't have a default camera.  Your device may not be CTS complaint.");
+            }
+        }
+//        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) {
+        return createCaptureFile(encodingType, "");
+    }
+
+    /**
+     * Create a file in the applications temporary directory based upon the supplied encoding.
+     *
+     * @param encodingType of the image to be taken
+     * @param fileName or resultant File object.
+     * @return a File object pointing to the temporary picture
+     */
+    private File createCaptureFile(int encodingType, String fileName) {
+        if (fileName.isEmpty()) {
+            fileName = ".Pic";
+        }
+
+        if (encodingType == JPEG) {
+            fileName = fileName + ".jpg";
+        } else if (encodingType == PNG) {
+            fileName = fileName + ".png";
+        } else {
+            throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
+        }
+
+        return new File(getTempDirectoryPath(), fileName);
+    }
+
+
+
+    /**
+     * Get image from photo library.
+     *
+     * @param srcType           The album to get image from.
+     * @param returnType        Set the type of image to return.
+     * @param encodingType
+     */
+    // TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do!
+    // TODO: Images from kitkat filechooser not going into crop function
+    public void getImage(int srcType, int returnType, int encodingType) {
+        Intent intent = new Intent();
+        String title = GET_PICTURE;
+        croppedUri = null;
+        if (this.mediaType == PICTURE) {
+            intent.setType("image/*");
+            if (this.allowEdit) {
+                intent.setAction(Intent.ACTION_PICK);
+                intent.putExtra("crop", "true");
+                if (targetWidth > 0) {
+                    intent.putExtra("outputX", targetWidth);
+                }
+                if (targetHeight > 0) {
+                    intent.putExtra("outputY", targetHeight);
+                }
+                if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
+                    intent.putExtra("aspectX", 1);
+                    intent.putExtra("aspectY", 1);
+                }
+                File photo = createCaptureFile(JPEG);
+                croppedUri = Uri.fromFile(photo);
+                intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, croppedUri);
+            } else {
+                intent.setAction(Intent.ACTION_GET_CONTENT);
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
+            }
+        } else if (this.mediaType == VIDEO) {
+            intent.setType("video/*");
+            title = GET_VIDEO;
+            intent.setAction(Intent.ACTION_GET_CONTENT);
+            intent.addCategory(Intent.CATEGORY_OPENABLE);
+        } 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);
+        }
+    }
+
+
+  /**
+   * Brings up the UI to perform crop on passed image URI
+   *
+   * @param picUri
+   */
+  private void performCrop(Uri picUri, int destType, Intent cameraIntent) {
+    try {
+        Intent cropIntent = new Intent("com.android.camera.action.CROP");
+        // indicate image type and Uri
+        cropIntent.setDataAndType(picUri, "image/*");
+        // set crop properties
+        cropIntent.putExtra("crop", "true");
+
+
+        // indicate output X and Y
+        if (targetWidth > 0) {
+          cropIntent.putExtra("outputX", targetWidth);
+        }
+        if (targetHeight > 0) {
+          cropIntent.putExtra("outputY", targetHeight);
+        }
+        if (targetHeight > 0 && targetWidth > 0 && targetWidth == targetHeight) {
+          cropIntent.putExtra("aspectX", 1);
+          cropIntent.putExtra("aspectY", 1);
+        }
+        // create new file handle to get full resolution crop
+        croppedUri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
+        cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        cropIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        cropIntent.putExtra("output", croppedUri);
+
+
+        // start the activity - we handle returning in onActivityResult
+
+        if (this.cordova != null) {
+            this.cordova.startActivityForResult((CordovaPlugin) this,
+                cropIntent, CROP_CAMERA + destType);
+        }
+    } catch (ActivityNotFoundException anfe) {
+      LOG.e(LOG_TAG, "Crop operation not supported on this device");
+      try {
+          processResultFromCamera(destType, cameraIntent);
+      }
+      catch (IOException e)
+      {
+          e.printStackTrace();
+          LOG.e(LOG_TAG, "Unable to write to file");
+      }
+    }
+  }
+
+    /**
+     * 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();
+
+        String sourcePath = (this.allowEdit && this.croppedUri != null) ?
+                FileHelper.stripFileProtocol(this.croppedUri.toString()) :
+                this.imageUri.getFilePath();
+
+
+        if (this.encodingType == JPEG) {
+            try {
+                //We don't support PNG, so let's not pretend we do
+                exif.createInFile(sourcePath);
+                exif.readExifData();
+                rotate = exif.getOrientation();
+
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        Bitmap bitmap = null;
+        Uri galleryUri = null;
+
+        // CB-5479 When this option is given the unchanged image should be saved
+        // in the gallery and the modified image is saved in the temporary
+        // directory
+        if (this.saveToPhotoAlbum) {
+            galleryUri = Uri.fromFile(new File(getPicturesPath()));
+
+            if (this.allowEdit && this.croppedUri != null) {
+                writeUncompressedImage(croppedUri, galleryUri);
+            } else {
+                Uri imageUri = this.imageUri.getFileUri();
+                writeUncompressedImage(imageUri, galleryUri);
+            }
+
+            refreshGallery(galleryUri);
+        }
+
+        // If sending base64 image back
+        if (destType == DATA_URL) {
+            bitmap = getScaledAndRotatedBitmap(sourcePath);
+
+            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;
+            }
+
+
+            this.processPicture(bitmap, this.encodingType);
+
+            if (!this.saveToPhotoAlbum) {
+                checkForDuplicateImage(DATA_URL);
+            }
+        }
+
+        // If sending filename back
+        else if (destType == FILE_URI || destType == NATIVE_URI) {
+            // If all this is true we shouldn't compress the image.
+            if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 &&
+                    !this.correctOrientation) {
+
+                // If we saved the uncompressed photo to the album, we can just
+                // return the URI we already created
+                if (this.saveToPhotoAlbum) {
+                    this.callbackContext.success(galleryUri.toString());
+                } else {
+                    Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
+
+                    if (this.allowEdit && this.croppedUri != null) {
+                        Uri croppedUri = Uri.fromFile(new File(getFileNameFromUri(this.croppedUri)));
+                        writeUncompressedImage(croppedUri, uri);
+                    } else {
+                        Uri imageUri = this.imageUri.getFileUri();
+                        writeUncompressedImage(imageUri, uri);
+                    }
+
+                    this.callbackContext.success(uri.toString());
+                }
+            } else {
+                Uri uri = Uri.fromFile(createCaptureFile(this.encodingType, System.currentTimeMillis() + ""));
+                bitmap = getScaledAndRotatedBitmap(sourcePath);
+
+                // 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;
+                }
+
+
+                // Add compressed version of captured image to returned media store Uri
+                OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
+                CompressFormat compressFormat = encodingType == JPEG ?
+                        CompressFormat.JPEG :
+                        CompressFormat.PNG;
+
+                bitmap.compress(compressFormat, this.mQuality, os);
+                os.close();
+
+                // Restore exif data to file
+                if (this.encodingType == JPEG) {
+                    String exifPath;
+                    exifPath = uri.getPath();
+                    //We just finished rotating it by an arbitrary orientation, just make sure it's normal
+                    if(rotate != ExifInterface.ORIENTATION_NORMAL)
+                        exif.resetOrientation();
+                    exif.createOutFile(exifPath);
+                    exif.writeExifData();
+                }
+
+                // Send Uri back to JavaScript for viewing image
+                this.callbackContext.success(uri.toString());
+
+            }
+        } else {
+            throw new IllegalStateException();
+        }
+
+        this.cleanup(FILE_URI, this.imageUri.getFileUri(), galleryUri, bitmap);
+        bitmap = null;
+    }
+
+    private String getPicturesPath() {
+        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+        String imageFileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
+        File storageDir = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_PICTURES);
+        String galleryPath = storageDir.getAbsolutePath() + "/" + imageFileName;
+        return galleryPath;
+    }
+
+    private void refreshGallery(Uri contentUri) {
+        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+        mediaScanIntent.setData(contentUri);
+        this.cordova.getActivity().sendBroadcast(mediaScanIntent);
+    }
+
+    /**
+     * Converts output image format int value to string value of mime type.
+     * @param outputFormat int Output format of camera API.
+     *                     Must be value of either JPEG or PNG constant
+     * @return String String value of mime type or empty string if mime type is not supported
+     */
+    private String getMimetypeForFormat(int outputFormat) {
+        if (outputFormat == PNG) return "image/png";
+        if (outputFormat == JPEG) return "image/jpeg";
+        return "";
+    }
+
+
+    private String outputModifiedBitmap(Bitmap bitmap, Uri uri) throws IOException {
+        // Some content: URIs do not map to file paths (e.g. picasa).
+        String realPath = FileHelper.getRealPath(uri, this.cordova);
+
+        // Get filename from uri
+        String fileName = realPath != null ?
+                realPath.substring(realPath.lastIndexOf('/') + 1) :
+                "modified." + (this.encodingType == JPEG ? "jpg" : "png");
+
+        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+        //String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
+        String modifiedPath = getTempDirectoryPath() + "/" + fileName;
+
+        OutputStream os = new FileOutputStream(modifiedPath);
+        CompressFormat compressFormat = this.encodingType == JPEG ?
+                CompressFormat.JPEG :
+                CompressFormat.PNG;
+
+        bitmap.compress(compressFormat, this.mQuality, os);
+        os.close();
+
+        if (exifData != null && this.encodingType == JPEG) {
+            try {
+                if (this.correctOrientation && this.orientationCorrected) {
+                    exifData.resetOrientation();
+                }
+                exifData.createOutFile(modifiedPath);
+                exifData.writeExifData();
+                exifData = null;
+            } 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();
+        if (uri == null) {
+            if (croppedUri != null) {
+                uri = croppedUri;
+            } else {
+                this.failPicture("null data from photo library");
+                return;
+            }
+        }
+        int rotate = 0;
+
+        String fileLocation = FileHelper.getRealPath(uri, this.cordova);
+        LOG.d(LOG_TAG, "File locaton is: " + fileLocation);
+
+        // 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(fileLocation);
+        }
+        else {
+            String uriString = uri.toString();
+            // Get the path to the image. Makes loading so much easier.
+            String mimeType = FileHelper.getMimeType(uriString, this.cordova);
+
+            // 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 &&
+                    mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
+            {
+                this.callbackContext.success(uriString);
+            } else {
+                // 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 = getScaledAndRotatedBitmap(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 sending base64 image back
+                if (destType == DATA_URL) {
+                    this.processPicture(bitmap, this.encodingType);
+                }
+
+                // 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) ||
+                            !mimeType.equalsIgnoreCase(getMimetypeForFormat(encodingType)))
+                    {
+                        try {
+                            String modifiedPath = this.outputModifiedBitmap(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(fileLocation);
+                    }
+                }
+                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 for a Camera Activity
+        int srcType = (requestCode / 16) - 1;
+        int destType = (requestCode % 16) - 1;
+
+        // If Camera Crop
+        if (requestCode >= CROP_CAMERA) {
+            if (resultCode == Activity.RESULT_OK) {
+
+                // Because of the inability to pass through multiple intents, this hack will allow us
+                // to pass arcane codes back.
+                destType = requestCode - CROP_CAMERA;
+                try {
+                    processResultFromCamera(destType, intent);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    LOG.e(LOG_TAG, "Unable to write to file");
+                }
+
+            }// If cancelled
+            else if (resultCode == Activity.RESULT_CANCELED) {
+                this.failPicture("Camera cancelled.");
+            }
+
+            // If something else
+            else {
+                this.failPicture("Did not complete!");
+            }
+        }
+        // If CAMERA
+        else if (srcType == CAMERA) {
+            // If image available
+            if (resultCode == Activity.RESULT_OK) {
+                try {
+                    if (this.allowEdit) {
+                        Uri tmpFile = FileProvider.getUriForFile(cordova.getActivity(),
+                                applicationId + ".provider",
+                                createCaptureFile(this.encodingType));
+                        performCrop(tmpFile, destType, intent);
+                    } else {
+                        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 && intent != null) {
+                final Intent i = intent;
+                final int finalDestType = destType;
+                cordova.getThreadPool().execute(new Runnable() {
+                    public void run() {
+                        processResultFromGallery(finalDestType, i);
+                    }
+                });
+            } else if (resultCode == Activity.RESULT_CANCELED) {
+                this.failPicture("Selection cancelled.");
+            } else {
+                this.failPicture("Selection did not complete!");
+            }
+        }
+    }
+
+    private int exifToDegrees(int exifOrientation) {
+        if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
+            return 90;
+        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
+            return 180;
+        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
+            return 270;
+        } else {
+            return 0;
+        }
+    }
+    
+    /**
+     * Write an inputstream to local disk
+     *
+     * @param fis - The InputStream to write
+     * @param dest - Destination on disk to write to
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void writeUncompressedImage(InputStream fis, Uri dest) throws FileNotFoundException,
+            IOException {
+        OutputStream os = null;
+        try {
+            os = this.cordova.getActivity().getContentResolver().openOutputStream(dest);
+            byte[] buffer = new byte[4096];
+            int len;
+            while ((len = fis.read(buffer)) != -1) {
+                os.write(buffer, 0, len);
+            }
+            os.flush();
+        } finally {
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (IOException e) {
+                    LOG.d(LOG_TAG, "Exception while closing output stream.");
+                }
+            }
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                    LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                }
+            }
+        }
+    }
+    /**
+     * 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 src
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void writeUncompressedImage(Uri src, Uri dest) throws FileNotFoundException,
+            IOException {
+
+        FileInputStream fis = new FileInputStream(FileHelper.stripFileProtocol(src.toString()));
+        writeUncompressedImage(fis, dest);
+
+    }
+
+    /**
+     * 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 (RuntimeException 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 (RuntimeException ex) {
+                LOG.d(LOG_TAG, "Can't write to internal media storage.");
+                return null;
+            }
+        }
+        return uri;
+    }
+
+    /**
+     * Return a scaled and rotated bitmap based on the target width and height
+     *
+     * @param imageUrl
+     * @return
+     * @throws IOException
+     */
+    private Bitmap getScaledAndRotatedBitmap(String imageUrl) throws IOException {
+        // If no new width or height were specified, and orientation is not needed return the original bitmap
+        if (this.targetWidth <= 0 && this.targetHeight <= 0 && !(this.correctOrientation)) {
+            InputStream fileStream = null;
+            Bitmap image = null;
+            try {
+                fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova);
+                image = BitmapFactory.decodeStream(fileStream);
+            } finally {
+                if (fileStream != null) {
+                    try {
+                        fileStream.close();
+                    } catch (IOException e) {
+                        LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                    }
+                }
+            }
+            return image;
+        }
+
+
+        /*  Copy the inputstream to a temporary file on the device.
+            We then use this temporary file to determine the width/height/orientation.
+            This is the only way to determine the orientation of the photo coming from 3rd party providers (Google Drive, Dropbox,etc)
+            This also ensures we create a scaled bitmap with the correct orientation
+
+             We delete the temporary file once we are done
+         */
+        File localFile = null;
+        Uri galleryUri = null;
+        int rotate = 0;
+        try {
+            InputStream fileStream = FileHelper.getInputStreamFromUriString(imageUrl, cordova);
+            if (fileStream != null) {
+                // Generate a temporary file
+                String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+                String fileName = "IMG_" + timeStamp + (this.encodingType == JPEG ? ".jpg" : ".png");
+                localFile = new File(getTempDirectoryPath() + fileName);
+                galleryUri = Uri.fromFile(localFile);
+                writeUncompressedImage(fileStream, galleryUri);
+                try {
+                    String mimeType = FileHelper.getMimeType(imageUrl.toString(), cordova);
+                    if ("image/jpeg".equalsIgnoreCase(mimeType)) {
+                        //  ExifInterface doesn't like the file:// prefix
+                        String filePath = galleryUri.toString().replace("file://", "");
+                        // read exifData of source
+                        exifData = new ExifHelper();
+                        exifData.createInFile(filePath);
+                        // Use ExifInterface to pull rotation information
+                        if (this.correctOrientation) {
+                            ExifInterface exif = new ExifInterface(filePath);
+                            rotate = exifToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED));
+                        }
+                    }
+                } catch (Exception oe) {
+                    LOG.w(LOG_TAG,"Unable to read Exif data: "+ oe.toString());
+                    rotate = 0;
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            LOG.e(LOG_TAG,"Exception while getting input stream: "+ e.toString());
+            return null;
+        }
+
+
+
+        try {
+            // figure out the original width and height of the image
+            BitmapFactory.Options options = new BitmapFactory.Options();
+            options.inJustDecodeBounds = true;
+            InputStream fileStream = null;
+            try {
+                fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova);
+                BitmapFactory.decodeStream(fileStream, null, options);
+            } finally {
+                if (fileStream != null) {
+                    try {
+                        fileStream.close();
+                    } catch (IOException e) {
+                        LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                    }
+                }
+            }
+
+
+            //CB-2292: WTF? Why is the width null?
+            if (options.outWidth == 0 || options.outHeight == 0) {
+                return null;
+            }
+
+            // User didn't specify output dimensions, but they need orientation
+            if (this.targetWidth <= 0 && this.targetHeight <= 0) {
+                this.targetWidth = options.outWidth;
+                this.targetHeight = options.outHeight;
+            }
+
+            // Setup target width/height based on orientation
+            int rotatedWidth, rotatedHeight;
+            boolean rotated= false;
+            if (rotate == 90 || rotate == 270) {
+                rotatedWidth = options.outHeight;
+                rotatedHeight = options.outWidth;
+                rotated = true;
+            } else {
+                rotatedWidth = options.outWidth;
+                rotatedHeight = options.outHeight;
+            }
+
+            // determine the correct aspect ratio
+            int[] widthHeight = calculateAspectRatio(rotatedWidth, rotatedHeight);
+
+
+            // Load in the smallest bitmap possible that is closest to the size we want
+            options.inJustDecodeBounds = false;
+            options.inSampleSize = calculateSampleSize(rotatedWidth, rotatedHeight,  widthHeight[0], widthHeight[1]);
+            Bitmap unscaledBitmap = null;
+            try {
+                fileStream = FileHelper.getInputStreamFromUriString(galleryUri.toString(), cordova);
+                unscaledBitmap = BitmapFactory.decodeStream(fileStream, null, options);
+            } finally {
+                if (fileStream != null) {
+                    try {
+                        fileStream.close();
+                    } catch (IOException e) {
+                        LOG.d(LOG_TAG, "Exception while closing file input stream.");
+                    }
+                }
+            }
+            if (unscaledBitmap == null) {
+                return null;
+            }
+
+            int scaledWidth = (!rotated) ? widthHeight[0] : widthHeight[1];
+            int scaledHeight = (!rotated) ? widthHeight[1] : widthHeight[0];
+
+            Bitmap scaledBitmap = Bitmap.createScaledBitmap(unscaledBitmap, scaledWidth, scaledHeight, true);
+            if (scaledBitmap != unscaledBitmap) {
+                unscaledBitmap.recycle();
+                unscaledBitmap = null;
+            }
+            if (this.correctOrientation && (rotate != 0)) {
+                Matrix matrix = new Matrix();
+                matrix.setRotate(rotate);
+                try {
+                    scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
+                    this.orientationCorrected = true;
+                } catch (OutOfMemoryError oom) {
+                    this.orientationCorrected = false;
+                }
+            }
+            return scaledBitmap;
+        }
+        finally {
+            // delete the temporary copy
+            if (localFile != null) {
+                localFile.delete();
+            }
+        }
+
+    }
+
+    /**
+     * 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 = (int)((double)(newWidth / (double)origWidth) * origHeight);
+        }
+        // only the height was specified
+        else if (newWidth <= 0 && newHeight > 0) {
+            newWidth = (int)((double)(newHeight / (double)origHeight) * origWidth);
+        }
+        // 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, int encodingType) {
+        ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
+        CompressFormat compressFormat = encodingType == JPEG ?
+                CompressFormat.JPEG :
+                CompressFormat.PNG;
+
+        try {
+            if (bitmap.compress(compressFormat, 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();
+    }
+
+
+    public void onRequestPermissionResult(int requestCode, String[] permissions,
+                                          int[] grantResults) throws JSONException {
+        for (int r : grantResults) {
+            if (r == PackageManager.PERMISSION_DENIED) {
+                this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
+                return;
+            }
+        }
+        switch (requestCode) {
+            case TAKE_PIC_SEC:
+                takePicture(this.destType, this.encodingType);
+                break;
+            case SAVE_TO_ALBUM_SEC:
+                this.getImage(this.srcType, this.destType, this.encodingType);
+                break;
+        }
+    }
+
+    /**
+     * Taking or choosing a picture launches another Activity, so we need to implement the
+     * save/restore APIs to handle the case where the CordovaActivity is killed by the OS
+     * before we get the launched Activity's result.
+     */
+    public Bundle onSaveInstanceState() {
+        Bundle state = new Bundle();
+        state.putInt("destType", this.destType);
+        state.putInt("srcType", this.srcType);
+        state.putInt("mQuality", this.mQuality);
+        state.putInt("targetWidth", this.targetWidth);
+        state.putInt("targetHeight", this.targetHeight);
+        state.putInt("encodingType", this.encodingType);
+        state.putInt("mediaType", this.mediaType);
+        state.putInt("numPics", this.numPics);
+        state.putBoolean("allowEdit", this.allowEdit);
+        state.putBoolean("correctOrientation", this.correctOrientation);
+        state.putBoolean("saveToPhotoAlbum", this.saveToPhotoAlbum);
+
+        if (this.croppedUri != null) {
+            state.putString("croppedUri", this.croppedUri.toString());
+        }
+
+        if (this.imageUri != null) {
+            state.putString("imageUri", this.imageUri.getFileUri().toString());
+        }
+
+        return state;
+    }
+
+    public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {
+        this.destType = state.getInt("destType");
+        this.srcType = state.getInt("srcType");
+        this.mQuality = state.getInt("mQuality");
+        this.targetWidth = state.getInt("targetWidth");
+        this.targetHeight = state.getInt("targetHeight");
+        this.encodingType = state.getInt("encodingType");
+        this.mediaType = state.getInt("mediaType");
+        this.numPics = state.getInt("numPics");
+        this.allowEdit = state.getBoolean("allowEdit");
+        this.correctOrientation = state.getBoolean("correctOrientation");
+        this.saveToPhotoAlbum = state.getBoolean("saveToPhotoAlbum");
+
+        if (state.containsKey("croppedUri")) {
+            this.croppedUri = Uri.parse(state.getString("croppedUri"));
+        }
+
+        if (state.containsKey("imageUri")) {
+            //I have no idea what type of URI is being passed in
+            this.imageUri = new CordovaUri(Uri.parse(state.getString("imageUri")));
+        }
+
+        this.callbackContext = callbackContext;
+    }
+
+ /*
+  * This is dirty, but it does the job.
+  *
+  * Since the FilesProvider doesn't really provide you a way of getting a URL from the file,
+  * and since we actually need the Camera to create the file for us most of the time, we don't
+  * actually write the file, just generate the location based on a timestamp, we need to get it
+  * back from the Intent.
+  *
+  * However, the FilesProvider preserves the path, so we can at least write to it from here, since
+  * we own the context in this case.
+ */
+
+    private String getFileNameFromUri(Uri uri) {
+        String fullUri = uri.toString();
+        String partial_path = fullUri.split("external_files")[1];
+        File external_storage = Environment.getExternalStorageDirectory();
+        String path = external_storage.getAbsolutePath() + partial_path;
+        return path;
+
+    }
+
+
+}

+ 104 - 0
miaomiao/plugins/cordova-plugin-camera/src/android/CordovaUri.java

xqd
@@ -0,0 +1,104 @@
+/*
+       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.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.support.v4.content.FileProvider;
+
+import java.io.File;
+
+/*
+ * This class exists because Andorid FilesProvider doesn't work on Android 4.4.4 and below and throws
+ * weird errors.  I'm not sure why writing to shared cache directories is somehow verboten, but it is
+ * and this error is irritating for a Compatibility library to have.
+ *
+ */
+
+public class CordovaUri {
+
+    private Uri androidUri;
+    private String fileName;
+    private Uri fileUri;
+
+    /*
+     * We always expect a FileProvider string to be passed in for the file that we create
+     *
+     */
+    CordovaUri (Uri inputUri)
+    {
+        //Determine whether the file is a content or file URI
+        if(inputUri.getScheme().equals("content"))
+        {
+            androidUri = inputUri;
+            fileName = getFileNameFromUri(androidUri);
+            fileUri = Uri.parse("file://" + fileName);
+        }
+        else
+        {
+            fileUri = inputUri;
+            fileName = FileHelper.stripFileProtocol(inputUri.toString());
+        }
+    }
+
+    public Uri getFileUri()
+    {
+        return fileUri;
+    }
+
+    public String getFilePath()
+    {
+        return fileName;
+    }
+
+    /*
+     * This only gets called by takePicture
+     */
+
+    public Uri getCorrectUri()
+    {
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+            return androidUri;
+        else
+            return fileUri;
+    }
+
+ /*
+  * This is dirty, but it does the job.
+  *
+  * Since the FilesProvider doesn't really provide you a way of getting a URL from the file,
+  * and since we actually need the Camera to create the file for us most of the time, we don't
+  * actually write the file, just generate the location based on a timestamp, we need to get it
+  * back from the Intent.
+  *
+  * However, the FilesProvider preserves the path, so we can at least write to it from here, since
+  * we own the context in this case.
+ */
+
+    private String getFileNameFromUri(Uri uri) {
+        String fullUri = uri.toString();
+        String partial_path = fullUri.split("external_files")[1];
+        File external_storage = Environment.getExternalStorageDirectory();
+        String path = external_storage.getAbsolutePath() + partial_path;
+        return path;
+
+    }
+}

+ 185 - 0
miaomiao/plugins/cordova-plugin-camera/src/android/ExifHelper.java

xqd
@@ -0,0 +1,185 @@
+/*
+       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;
+    }
+}

+ 319 - 0
miaomiao/plugins/cordova-plugin-camera/src/android/FileHelper.java

xqd
@@ -0,0 +1,319 @@
+/*
+       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.annotation.SuppressLint;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.CursorLoader;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+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(Uri uri, CordovaInterface cordova) {
+        String realPath = null;
+
+        if (Build.VERSION.SDK_INT < 11)
+            realPath = FileHelper.getRealPathFromURI_BelowAPI11(cordova.getActivity(), uri);
+
+        // SDK >= 11
+        else
+            realPath = FileHelper.getRealPathFromURI_API11_And_Above(cordova.getActivity(), uri);
+
+        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(String uriString, CordovaInterface cordova) {
+        return FileHelper.getRealPath(Uri.parse(uriString), cordova);
+    }
+
+    @SuppressLint("NewApi")
+    public static String getRealPathFromURI_API11_And_Above(final Context context, final Uri uri) {
+
+        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+        // DocumentProvider
+        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+
+            // ExternalStorageProvider
+            if (isExternalStorageDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                if ("primary".equalsIgnoreCase(type)) {
+                    return Environment.getExternalStorageDirectory() + "/" + split[1];
+                }
+
+                // TODO handle non-primary volumes
+            }
+            // DownloadsProvider
+            else if (isDownloadsDocument(uri)) {
+
+                final String id = DocumentsContract.getDocumentId(uri);
+                final Uri contentUri = ContentUris.withAppendedId(
+                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+
+                return getDataColumn(context, contentUri, null, null);
+            }
+            // MediaProvider
+            else if (isMediaDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                Uri contentUri = null;
+                if ("image".equals(type)) {
+                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                } else if ("video".equals(type)) {
+                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                } else if ("audio".equals(type)) {
+                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                }
+
+                final String selection = "_id=?";
+                final String[] selectionArgs = new String[] {
+                        split[1]
+                };
+
+                return getDataColumn(context, contentUri, selection, selectionArgs);
+            }
+        }
+        // MediaStore (and general)
+        else if ("content".equalsIgnoreCase(uri.getScheme())) {
+
+            // Return the remote address
+            if (isGooglePhotosUri(uri))
+                return uri.getLastPathSegment();
+
+            return getDataColumn(context, uri, null, null);
+        }
+        // File
+        else if ("file".equalsIgnoreCase(uri.getScheme())) {
+            return uri.getPath();
+        }
+
+        return null;
+    }
+
+    public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
+        String[] proj = { MediaStore.Images.Media.DATA };
+        String result = null;
+
+        try {
+            Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
+            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+            cursor.moveToFirst();
+            result = cursor.getString(column_index);
+
+        } catch (Exception e) {
+            result = null;
+        }
+        return result;
+    }
+
+    /**
+     * 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 {
+        InputStream returnValue = null;
+        if (uriString.startsWith("content")) {
+            Uri uri = Uri.parse(uriString);
+            returnValue = 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);
+                returnValue = cordova.getActivity().getAssets().open(relativePath);
+            } else {
+                // might still be content so try that first
+                try {
+                    returnValue = cordova.getActivity().getContentResolver().openInputStream(Uri.parse(uriString));
+                } catch (Exception e) {
+                    returnValue = null;
+                }
+                if (returnValue == null) {
+                    returnValue = new FileInputStream(getRealPath(uriString, cordova));
+                }
+            }
+        } else {
+            returnValue = new FileInputStream(uriString);
+        }
+        return returnValue;
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Get the value of the data column for this Uri. This is useful for
+     * MediaStore Uris, and other file-based ContentProviders.
+     *
+     * @param context The context.
+     * @param uri The Uri to query.
+     * @param selection (Optional) Filter used in the query.
+     * @param selectionArgs (Optional) Selection arguments used in the query.
+     * @return The value of the _data column, which is typically a file path.
+     * @author paulburke
+     */
+    public static String getDataColumn(Context context, Uri uri, String selection,
+                                       String[] selectionArgs) {
+
+        Cursor cursor = null;
+        final String column = "_data";
+        final String[] projection = {
+                column
+        };
+
+        try {
+            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
+                    null);
+            if (cursor != null && cursor.moveToFirst()) {
+
+                final int column_index = cursor.getColumnIndexOrThrow(column);
+                return cursor.getString(column_index);
+            }
+        } catch (Exception e) {
+            return null;
+        } finally {
+            if (cursor != null)
+                cursor.close();
+        }
+        return null;
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is ExternalStorageProvider.
+     * @author paulburke
+     */
+    public static boolean isExternalStorageDocument(Uri uri) {
+        return "com.android.externalstorage.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is DownloadsProvider.
+     * @author paulburke
+     */
+    public static boolean isDownloadsDocument(Uri uri) {
+        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is MediaProvider.
+     * @author paulburke
+     */
+    public static boolean isMediaDocument(Uri uri) {
+        return "com.android.providers.media.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is Google Photos.
+     */
+    public static boolean isGooglePhotosUri(Uri uri) {
+        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
+    }
+}

+ 21 - 0
miaomiao/plugins/cordova-plugin-camera/src/android/xml/provider_paths.xml

xqd
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+-->
+
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+    <external-path name="external_files" path="."/>
+</paths>

+ 227 - 0
miaomiao/plugins/cordova-plugin-camera/src/blackberry10/index.js

xqd
@@ -0,0 +1,227 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/* globals qnx, FileError, PluginResult */
+
+var PictureSourceType = {
+        PHOTOLIBRARY : 0,    // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
+        CAMERA : 1,          // Take picture from camera
+        SAVEDPHOTOALBUM : 2  // Choose image from picture library (same as PHOTOLIBRARY for Android)
+    },
+    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)
+    },
+    savePath = window.qnx.webplatform.getApplication().getEnv("HOME").replace('/data', '') + '/shared/camera/',
+    invokeAvailable = true;
+
+//check for camera card - it isn't currently availble in work perimeter
+window.qnx.webplatform.getApplication().invocation.queryTargets(
+    {
+        type: 'image/jpeg',
+        action: 'bb.action.CAPTURE',
+        target_type: 'CARD'
+    },
+    function (error, targets) {
+        invokeAvailable = !error && targets && targets instanceof Array &&
+            targets.filter(function (t) { return t.default === 'sys.camera.card'; }).length > 0;
+    }
+);
+
+//open a webview with getUserMedia camera card implementation when camera card not available
+function showCameraDialog (done, cancel, fail) {
+    var wv = qnx.webplatform.createWebView(function () {
+        wv.url = 'local:///chrome/camera.html';
+        wv.allowQnxObject = true;
+        wv.allowRpc = true;
+        wv.zOrder = 1;
+        wv.setGeometry(0, 0, screen.width, screen.height);
+        wv.backgroundColor = 0x00000000;
+        wv.active = true;
+        wv.visible = true;
+        wv.on('UserMediaRequest', function (evt, args) {
+            wv.allowUserMedia(JSON.parse(args).id, 'CAMERA_UNIT_REAR');
+        });
+        wv.on('JavaScriptCallback', function (evt, data) {
+            var args = JSON.parse(data).args;
+            if (args[0] === 'cordova-plugin-camera') {
+                if (args[1] === 'cancel') {
+                    cancel('User canceled');
+                } else if (args[1] === 'error') {
+                    fail(args[2]);
+                } else {
+                    saveImage(args[1], done, fail);
+                }
+                wv.un('JavaScriptCallback', arguments.callee);
+                wv.visible = false;
+                wv.destroy();
+                qnx.webplatform.getApplication().unlockRotation();
+            }
+        });
+        wv.on('Destroyed', function () {
+            wv.delete();
+        });
+        qnx.webplatform.getApplication().lockRotation();
+        qnx.webplatform.getController().dispatchEvent('webview.initialized', [wv]);
+    });
+}
+
+//create unique name for saved file (same pattern as BB10 camera app)
+function imgName() {
+    var date = new Date(),
+        pad = function (n) { return n < 10 ? '0' + n : n; };
+    return 'IMG_' + date.getFullYear() + pad(date.getMonth() + 1) + pad(date.getDate()) + '_' +
+            pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds()) + '.png';
+}
+
+//convert dataURI to Blob
+function dataURItoBlob(dataURI) {
+    var byteString = atob(dataURI.split(',')[1]),
+        mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0],
+        arrayBuffer = new ArrayBuffer(byteString.length),
+        ia = new Uint8Array(arrayBuffer),
+        i;
+    for (i = 0; i < byteString.length; i++) {
+        ia[i] = byteString.charCodeAt(i);
+    }
+    return new Blob([new DataView(arrayBuffer)], { type: mimeString });
+}
+
+//save dataURI to file system and call success with path
+function saveImage(data, success, fail) {
+    var name = savePath + imgName();
+    require('lib/webview').setSandbox(false);
+    window.webkitRequestFileSystem(window.PERSISTENT, 0, function (fs) {
+        fs.root.getFile(name, { create: true }, function (entry) {
+            entry.createWriter(function (writer) {
+                writer.onwriteend = function () {
+                    success(name);
+                };
+                writer.onerror = fail;
+                writer.write(dataURItoBlob(data));
+            });
+        }, fail);
+    }, fail);
+}
+
+function encodeBase64(filePath, callback) {
+    var sandbox = window.qnx.webplatform.getController().setFileSystemSandbox, // save original sandbox value
+        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:
+            if (invokeAvailable) {
+                window.qnx.webplatform.getApplication().cards.camera.open("photo", done, cancel, invoked);
+            } else {
+                showCameraDialog(done, cancel, fail);
+            }
+            break;
+
+        case PictureSourceType.PHOTOLIBRARY:
+        case PictureSourceType.SAVEDPHOTOALBUM:
+            window.qnx.webplatform.getApplication().cards.filePicker.open({
+                mode: "Picker",
+                type: ["picture"]
+            }, done, cancel, invoked);
+            break;
+        }
+
+        result.noResult(true);
+    }
+};

+ 123 - 0
miaomiao/plugins/cordova-plugin-camera/src/browser/CameraProxy.js

xqd
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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 HIGHEST_POSSIBLE_Z_INDEX = 2147483647;
+
+function takePicture(success, error, opts) {
+    if (opts && opts[2] === 1) {
+        capture(success, error, opts);
+    } else {
+        var input = document.createElement('input');
+        input.style.position = 'relative';
+        input.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
+        input.className = 'cordova-camera-select';
+        input.type = 'file';
+        input.name = 'files[]';
+
+        input.onchange = function(inputEvent) {
+            var reader = new FileReader();
+            reader.onload = function(readerEvent) {
+                input.parentNode.removeChild(input);
+
+                var imageData = readerEvent.target.result;
+
+                return success(imageData.substr(imageData.indexOf(',') + 1));
+            };
+
+            reader.readAsDataURL(inputEvent.target.files[0]);
+        };
+
+        document.body.appendChild(input);
+    }
+}
+
+function capture(success, errorCallback, opts) {
+    var localMediaStream;
+    var targetWidth = opts[3];
+    var targetHeight = opts[4];
+
+    targetWidth = targetWidth == -1?320:targetWidth;
+    targetHeight = targetHeight == -1?240:targetHeight;
+
+    var video = document.createElement('video');
+    var button = document.createElement('button');
+    var parent = document.createElement('div');
+    parent.style.position = 'relative';
+    parent.style.zIndex = HIGHEST_POSSIBLE_Z_INDEX;
+    parent.className = 'cordova-camera-capture';
+    parent.appendChild(video);
+    parent.appendChild(button);
+
+    video.width = targetWidth;
+    video.height = targetHeight;
+    button.innerHTML = 'Capture!';
+
+    button.onclick = function() {
+        // create a canvas and capture a frame from video stream
+        var canvas = document.createElement('canvas');
+        canvas.width = targetWidth;
+        canvas.height = targetHeight;
+        canvas.getContext('2d').drawImage(video, 0, 0, targetWidth, targetHeight);
+
+        // convert image stored in canvas to base64 encoded image
+        var imageData = canvas.toDataURL('image/png');
+        imageData = imageData.replace('data:image/png;base64,', '');
+
+        // stop video stream, remove video and button.
+        // Note that MediaStream.stop() is deprecated as of Chrome 47.
+        if (localMediaStream.stop) {
+            localMediaStream.stop();
+        } else {
+            localMediaStream.getTracks().forEach(function (track) {
+                track.stop();
+            });
+        }
+        parent.parentNode.removeChild(parent);
+
+        return success(imageData);
+    };
+
+    navigator.getUserMedia = navigator.getUserMedia ||
+                             navigator.webkitGetUserMedia ||
+                             navigator.mozGetUserMedia ||
+                             navigator.msGetUserMedia;
+
+    var successCallback = function(stream) {
+        localMediaStream = stream;
+        video.src = window.URL.createObjectURL(localMediaStream);
+        video.play();
+
+        document.body.appendChild(parent);
+    };
+
+    if (navigator.getUserMedia) {
+        navigator.getUserMedia({video: true, audio: true}, successCallback, errorCallback);
+    } else {
+        alert('Browser does not support camera :(');
+    }
+}
+
+module.exports = {
+    takePicture: takePicture,
+    cleanup: function(){}
+};
+
+require("cordova/exec/proxy").add("Camera",module.exports);

+ 53 - 0
miaomiao/plugins/cordova-plugin-camera/src/firefoxos/CameraProxy.js

xqd
@@ -0,0 +1,53 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/* globals MozActivity */
+
+function takePicture(success, error, opts) {
+    var pick = new MozActivity({
+        name: "pick",
+        data: {
+            type: ["image/*"]
+        }
+    });
+
+    pick.onerror = error || function() {};
+
+    pick.onsuccess = function() {
+        // image is returned as Blob in this.result.blob
+        // we need to call success with url or base64 encoded image
+        if (opts && opts.destinationType === 0) {
+            // TODO: base64
+            return;
+        }
+        if (!opts || !opts.destinationType || opts.destinationType > 0) {
+            // url
+            return success(window.URL.createObjectURL(this.result.blob));
+        }
+    };
+}
+
+module.exports = {
+    takePicture: takePicture,
+    cleanup: function(){}
+};
+
+require("cordova/exec/proxy").add("Camera", module.exports);

+ 116 - 0
miaomiao/plugins/cordova-plugin-camera/src/ios/CDVCamera.h

xqd
@@ -0,0 +1,116 @@
+/*
+ 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 <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+#import <CoreLocation/CLLocationManager.h>
+#import <Cordova/CDVPlugin.h>
+
+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 CDVPictureOptions : NSObject
+
+@property (strong) NSNumber* quality;
+@property (assign) CDVDestinationType destinationType;
+@property (assign) UIImagePickerControllerSourceType sourceType;
+@property (assign) CGSize targetSize;
+@property (assign) CDVEncodingType encodingType;
+@property (assign) CDVMediaType mediaType;
+@property (assign) BOOL allowsEditing;
+@property (assign) BOOL correctOrientation;
+@property (assign) BOOL saveToPhotoAlbum;
+@property (strong) NSDictionary* popoverOptions;
+@property (assign) UIImagePickerControllerCameraDevice cameraDirection;
+
+@property (assign) BOOL popoverSupported;
+@property (assign) BOOL usesGeolocation;
+@property (assign) BOOL cropToSize;
+
++ (instancetype) createFromTakePictureArguments:(CDVInvokedUrlCommand*)command;
+
+@end
+
+@interface CDVCameraPicker : UIImagePickerController
+
+@property (strong) CDVPictureOptions* pictureOptions;
+
+@property (copy)   NSString* callbackId;
+@property (copy)   NSString* postUrl;
+@property (strong) UIPopoverController* pickerPopoverController;
+@property (assign) BOOL cropToSize;
+@property (strong) UIView* webView;
+
++ (instancetype) createFromPictureOptions:(CDVPictureOptions*)options;
+
+@end
+
+// ======================================================================= //
+
+@interface CDVCamera : CDVPlugin <UIImagePickerControllerDelegate,
+                       UINavigationControllerDelegate,
+                       UIPopoverControllerDelegate,
+                       CLLocationManagerDelegate>
+{}
+
+@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)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;
+
+- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation;
+- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
+
+@end

+ 771 - 0
miaomiao/plugins/cordova-plugin-camera/src/ios/CDVCamera.m

xqd
@@ -0,0 +1,771 @@
+/*
+ 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 "UIImage+CropScaleOrientation.h"
+#import <ImageIO/CGImageProperties.h>
+#import <AssetsLibrary/ALAssetRepresentation.h>
+#import <AssetsLibrary/AssetsLibrary.h>
+#import <AVFoundation/AVFoundation.h>
+#import <ImageIO/CGImageSource.h>
+#import <ImageIO/CGImageProperties.h>
+#import <ImageIO/CGImageDestination.h>
+#import <MobileCoreServices/UTCoreTypes.h>
+#import <objc/message.h>
+
+#ifndef __CORDOVA_4_0_0
+    #import <Cordova/NSData+Base64.h>
+#endif
+
+#define CDV_PHOTO_PREFIX @"cdv_photo_"
+
+static NSSet* org_apache_cordova_validArrowDirections;
+
+static NSString* toBase64(NSData* data) {
+    SEL s1 = NSSelectorFromString(@"cdv_base64EncodedString");
+    SEL s2 = NSSelectorFromString(@"base64EncodedString");
+    SEL s3 = NSSelectorFromString(@"base64EncodedStringWithOptions:");
+    
+    if ([data respondsToSelector:s1]) {
+        NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s1];
+        return func(data, s1);
+    } else if ([data respondsToSelector:s2]) {
+        NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s2];
+        return func(data, s2);
+    } else if ([data respondsToSelector:s3]) {
+        NSString* (*func)(id, SEL, NSUInteger) = (void *)[data methodForSelector:s3];
+        return func(data, s3, 0);
+    } else {
+        return nil;
+    }
+}
+
+@implementation CDVPictureOptions
+
++ (instancetype) createFromTakePictureArguments:(CDVInvokedUrlCommand*)command
+{
+    CDVPictureOptions* pictureOptions = [[CDVPictureOptions alloc] init];
+
+    pictureOptions.quality = [command argumentAtIndex:0 withDefault:@(50)];
+    pictureOptions.destinationType = [[command argumentAtIndex:1 withDefault:@(DestinationTypeFileUri)] unsignedIntegerValue];
+    pictureOptions.sourceType = [[command argumentAtIndex:2 withDefault:@(UIImagePickerControllerSourceTypeCamera)] unsignedIntegerValue];
+    
+    NSNumber* targetWidth = [command argumentAtIndex:3 withDefault:nil];
+    NSNumber* targetHeight = [command argumentAtIndex:4 withDefault:nil];
+    pictureOptions.targetSize = CGSizeMake(0, 0);
+    if ((targetWidth != nil) && (targetHeight != nil)) {
+        pictureOptions.targetSize = CGSizeMake([targetWidth floatValue], [targetHeight floatValue]);
+    }
+
+    pictureOptions.encodingType = [[command argumentAtIndex:5 withDefault:@(EncodingTypeJPEG)] unsignedIntegerValue];
+    pictureOptions.mediaType = [[command argumentAtIndex:6 withDefault:@(MediaTypePicture)] unsignedIntegerValue];
+    pictureOptions.allowsEditing = [[command argumentAtIndex:7 withDefault:@(NO)] boolValue];
+    pictureOptions.correctOrientation = [[command argumentAtIndex:8 withDefault:@(NO)] boolValue];
+    pictureOptions.saveToPhotoAlbum = [[command argumentAtIndex:9 withDefault:@(NO)] boolValue];
+    pictureOptions.popoverOptions = [command argumentAtIndex:10 withDefault:nil];
+    pictureOptions.cameraDirection = [[command argumentAtIndex:11 withDefault:@(UIImagePickerControllerCameraDeviceRear)] unsignedIntegerValue];
+    
+    pictureOptions.popoverSupported = NO;
+    pictureOptions.usesGeolocation = NO;
+    
+    return pictureOptions;
+}
+
+@end
+
+
+@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;
+
+- (NSURL*) urlTransformer:(NSURL*)url
+{
+    NSURL* urlToTransform = url;
+    
+    // for backwards compatibility - we check if this property is there
+    SEL sel = NSSelectorFromString(@"urlTransformer");
+    if ([self.commandDelegate respondsToSelector:sel]) {
+        // grab the block from the commandDelegate
+        NSURL* (^urlTransformer)(NSURL*) = ((id(*)(id, SEL))objc_msgSend)(self.commandDelegate, sel);
+        // if block is not null, we call it
+        if (urlTransformer) {
+            urlToTransform = urlTransformer(url);
+        }
+    }
+    
+    return urlToTransform;
+}
+
+- (BOOL)usesGeolocation
+{
+    id useGeo = [self.commandDelegate.settings objectForKey:[@"CameraUsesGeolocation" lowercaseString]];
+    return [(NSNumber*)useGeo boolValue];
+}
+
+- (BOOL)popoverSupported
+{
+    return (NSClassFromString(@"UIPopoverController") != nil) &&
+           (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
+}
+
+- (void)takePicture:(CDVInvokedUrlCommand*)command
+{
+    self.hasPendingOperation = YES;
+    
+    __weak CDVCamera* weakSelf = self;
+
+    [self.commandDelegate runInBackground:^{
+        
+        CDVPictureOptions* pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
+        pictureOptions.popoverSupported = [weakSelf popoverSupported];
+        pictureOptions.usesGeolocation = [weakSelf usesGeolocation];
+        pictureOptions.cropToSize = NO;
+        
+        BOOL hasCamera = [UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType];
+        if (!hasCamera) {
+            NSLog(@"Camera.getPicture: source type %lu not available.", (unsigned long)pictureOptions.sourceType);
+            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No camera available"];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+            return;
+        }
+
+        // Validate the app has permission to access the camera
+        if (pictureOptions.sourceType == UIImagePickerControllerSourceTypeCamera && [AVCaptureDevice respondsToSelector:@selector(authorizationStatusForMediaType:)]) {
+            AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+            if (authStatus == AVAuthorizationStatusDenied ||
+                authStatus == AVAuthorizationStatusRestricted) {
+                // If iOS 8+, offer a link to the Settings app
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+                NSString* settingsButton = (&UIApplicationOpenSettingsURLString != NULL)
+                    ? NSLocalizedString(@"Settings", nil)
+                    : nil;
+#pragma clang diagnostic pop
+
+                // Denied; show an alert
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    [[[UIAlertView alloc] initWithTitle:[[NSBundle mainBundle]
+                                                         objectForInfoDictionaryKey:@"CFBundleDisplayName"]
+                                                message:NSLocalizedString(@"Access to the camera has been prohibited; please enable it in the Settings app to continue.", nil)
+                                               delegate:weakSelf
+                                      cancelButtonTitle:NSLocalizedString(@"OK", nil)
+                                      otherButtonTitles:settingsButton, nil] show];
+                });
+            }
+        }
+
+        CDVCameraPicker* cameraPicker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
+        weakSelf.pickerController = cameraPicker;
+        
+        cameraPicker.delegate = weakSelf;
+        cameraPicker.callbackId = command.callbackId;
+        // we need to capture this state for memory warnings that dealloc this object
+        cameraPicker.webView = weakSelf.webView;
+        
+        // Perform UI operations on the main thread
+        dispatch_async(dispatch_get_main_queue(), ^{
+            // If a popover is already open, close it; we only want one at a time.
+            if (([[weakSelf pickerController] pickerPopoverController] != nil) && [[[weakSelf pickerController] pickerPopoverController] isPopoverVisible]) {
+                [[[weakSelf pickerController] pickerPopoverController] dismissPopoverAnimated:YES];
+                [[[weakSelf pickerController] pickerPopoverController] setDelegate:nil];
+                [[weakSelf pickerController] setPickerPopoverController:nil];
+            }
+
+            if ([weakSelf popoverSupported] && (pictureOptions.sourceType != UIImagePickerControllerSourceTypeCamera)) {
+                if (cameraPicker.pickerPopoverController == nil) {
+                    cameraPicker.pickerPopoverController = [[NSClassFromString(@"UIPopoverController") alloc] initWithContentViewController:cameraPicker];
+                }
+                [weakSelf displayPopover:pictureOptions.popoverOptions];
+                weakSelf.hasPendingOperation = NO;
+            } else {
+                [weakSelf.viewController presentViewController:cameraPicker animated:YES completion:^{
+                    weakSelf.hasPendingOperation = NO;
+                }];
+            }
+        });
+    }];
+}
+
+// Delegate for camera permission UIAlertView
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+    // If Settings button (on iOS 8), open the settings app
+    if (buttonIndex == 1) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+        if (&UIApplicationOpenSettingsURLString != NULL) {
+            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
+        }
+#pragma clang diagnostic pop
+    }
+
+    // Dismiss the view
+    [[self.pickerController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to camera"];   // error callback expects string ATM
+
+    [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
+
+    self.hasPendingOperation = NO;
+    self.pickerController = nil;
+}
+
+- (void)repositionPopover:(CDVInvokedUrlCommand*)command
+{
+    if (([[self pickerController] pickerPopoverController] != nil) && [[[self pickerController] pickerPopoverController] isPopoverVisible]) {
+
+        [[[self pickerController] pickerPopoverController] dismissPopoverAnimated:NO];
+
+        NSDictionary* options = [command argumentAtIndex:0 withDefault:nil];
+        [self displayPopover:options];
+    }
+}
+
+- (NSInteger)integerValueForKey:(NSDictionary*)dict key:(NSString*)key defaultValue:(NSInteger)defaultValue
+{
+    NSInteger value = defaultValue;
+
+    NSNumber* val = [dict valueForKey:key];  // value is an NSNumber
+
+    if (val != nil) {
+        value = [val integerValue];
+    }
+    return value;
+}
+
+- (void)displayPopover:(NSDictionary*)options
+{
+    NSInteger x = 0;
+    NSInteger y = 32;
+    NSInteger width = 320;
+    NSInteger height = 480;
+    UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
+
+    if (options) {
+        x = [self integerValueForKey:options key:@"x" defaultValue:0];
+        y = [self integerValueForKey:options key:@"y" defaultValue:32];
+        width = [self integerValueForKey:options key:@"width" defaultValue:320];
+        height = [self integerValueForKey:options key:@"height" defaultValue:480];
+        arrowDirection = [self integerValueForKey:options key:@"arrowDir" defaultValue:UIPopoverArrowDirectionAny];
+        if (![org_apache_cordova_validArrowDirections containsObject:[NSNumber numberWithUnsignedInteger:arrowDirection]]) {
+            arrowDirection = UIPopoverArrowDirectionAny;
+        }
+    }
+
+    [[[self pickerController] pickerPopoverController] setDelegate:self];
+    [[[self pickerController] pickerPopoverController] 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", 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
+{
+    UIPopoverController* pc = (UIPopoverController*)popoverController;
+
+    [pc dismissPopoverAnimated:YES];
+    pc.delegate = nil;
+    if (self.pickerController && self.pickerController.callbackId && self.pickerController.pickerPopoverController) {
+        self.pickerController.pickerPopoverController = 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;
+}
+
+- (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPictureOptions*)options
+{
+    NSData* data = nil;
+    
+    switch (options.encodingType) {
+        case EncodingTypePNG:
+            data = UIImagePNGRepresentation(image);
+            break;
+        case EncodingTypeJPEG:
+        {
+            if ((options.allowsEditing == NO) && (options.targetSize.width <= 0) && (options.targetSize.height <= 0) && (options.correctOrientation == NO) && (([options.quality integerValue] == 100) || (options.sourceType != UIImagePickerControllerSourceTypeCamera))){
+                // use image unedited as requested , don't resize
+                data = UIImageJPEGRepresentation(image, 1.0);
+            } else {
+                data = UIImageJPEGRepresentation(image, [options.quality floatValue] / 100.0f);
+            }
+            
+            if (options.usesGeolocation) {
+                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];
+                    }
+                    
+                    if (IsAtLeastiOSVersion(@"8.0")) {
+                        [[self locationManager] performSelector:NSSelectorFromString(@"requestWhenInUseAuthorization") withObject:nil afterDelay:0];
+                    }
+                    [[self locationManager] startUpdatingLocation];
+                }
+            }
+        }
+            break;
+        default:
+            break;
+    };
+    
+    return data;
+}
+
+- (NSString*)tempFilePath:(NSString*)extension
+{
+    NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
+    NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by Apple (vs [NSFileManager defaultManager]) to be threadsafe
+    NSString* filePath;
+    
+    // generate unique file name
+    int i = 1;
+    do {
+        filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, extension];
+    } while ([fileMgr fileExistsAtPath:filePath]);
+    
+    return filePath;
+}
+
+- (UIImage*)retrieveImage:(NSDictionary*)info options:(CDVPictureOptions*)options
+{
+    // get the image
+    UIImage* image = nil;
+    if (options.allowsEditing && [info objectForKey:UIImagePickerControllerEditedImage]) {
+        image = [info objectForKey:UIImagePickerControllerEditedImage];
+    } else {
+        image = [info objectForKey:UIImagePickerControllerOriginalImage];
+    }
+    
+    if (options.correctOrientation) {
+        image = [image imageCorrectedForCaptureOrientation];
+    }
+    
+    UIImage* scaledImage = nil;
+    
+    if ((options.targetSize.width > 0) && (options.targetSize.height > 0)) {
+        // if cropToSize, resize image and crop to target size, otherwise resize to fit target without cropping
+        if (options.cropToSize) {
+            scaledImage = [image imageByScalingAndCroppingForSize:options.targetSize];
+        } else {
+            scaledImage = [image imageByScalingNotCroppingForSize:options.targetSize];
+        }
+    }
+    
+    return (scaledImage == nil ? image : scaledImage);
+}
+
+- (void)resultForImage:(CDVPictureOptions*)options info:(NSDictionary*)info completion:(void (^)(CDVPluginResult* res))completion
+{
+    CDVPluginResult* result = nil;
+    BOOL saveToPhotoAlbum = options.saveToPhotoAlbum;
+    UIImage* image = nil;
+
+    switch (options.destinationType) {
+        case DestinationTypeNativeUri:
+        {
+            NSURL* url = [info objectForKey:UIImagePickerControllerReferenceURL];
+            saveToPhotoAlbum = NO;
+            // If, for example, we use sourceType = Camera, URL might be nil because image is stored in memory.
+            // In this case we must save image to device before obtaining an URI.
+            if (url == nil) {
+                image = [self retrieveImage:info options:options];
+                ALAssetsLibrary* library = [ALAssetsLibrary new];
+                [library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:^(NSURL *assetURL, NSError *error) {
+                    CDVPluginResult* resultToReturn = nil;
+                    if (error) {
+                        resultToReturn = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]];
+                    } else {
+                        NSString* nativeUri = [[self urlTransformer:assetURL] absoluteString];
+                        resultToReturn = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
+                    }
+                    completion(resultToReturn);
+                }];
+                return;
+            } else {
+                NSString* nativeUri = [[self urlTransformer:url] absoluteString];
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nativeUri];
+            }
+        }
+            break;
+        case DestinationTypeFileUri:
+        {
+            image = [self retrieveImage:info options:options];
+            NSData* data = [self processImage:image info:info options:options];
+            if (data) {
+                
+                NSString* extension = options.encodingType == EncodingTypePNG? @"png" : @"jpg";
+                NSString* filePath = [self tempFilePath:extension];
+                NSError* err = nil;
+                
+                // 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:[[self urlTransformer:[NSURL fileURLWithPath:filePath]] absoluteString]];
+                }
+            }
+        }
+            break;
+        case DestinationTypeDataUrl:
+        {
+            image = [self retrieveImage:info options:options];
+            NSData* data = [self processImage:image info:info options:options];
+            if (data)  {
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(data)];
+            }
+        }
+            break;
+        default:
+            break;
+    };
+    
+    if (saveToPhotoAlbum && image) {
+        ALAssetsLibrary* library = [ALAssetsLibrary new];
+        [library writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)(image.imageOrientation) completionBlock:nil];
+    }
+
+    completion(result);
+}
+
+- (CDVPluginResult*)resultForVideo:(NSDictionary*)info
+{
+    NSString* moviePath = [[info objectForKey:UIImagePickerControllerMediaURL] absoluteString];
+    return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:moviePath];
+}
+
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
+{
+    __weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
+    __weak CDVCamera* weakSelf = self;
+    
+    dispatch_block_t invoke = ^(void) {
+        __block CDVPluginResult* result = nil;
+        
+        NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
+        if ([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
+            [weakSelf resultForImage:cameraPicker.pictureOptions info:info completion:^(CDVPluginResult* res) {
+                if (![self usesGeolocation] || picker.sourceType != UIImagePickerControllerSourceTypeCamera) {
+                    [weakSelf.commandDelegate sendPluginResult:res callbackId:cameraPicker.callbackId];
+                    weakSelf.hasPendingOperation = NO;
+                    weakSelf.pickerController = nil;
+                }
+            }];
+        }
+        else {
+            result = [weakSelf resultForVideo:info];
+            [weakSelf.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
+            weakSelf.hasPendingOperation = NO;
+            weakSelf.pickerController = nil;
+        }
+    };
+    
+    if (cameraPicker.pictureOptions.popoverSupported && (cameraPicker.pickerPopoverController != nil)) {
+        [cameraPicker.pickerPopoverController dismissPopoverAnimated:YES];
+        cameraPicker.pickerPopoverController.delegate = nil;
+        cameraPicker.pickerPopoverController = nil;
+        invoke();
+    } else {
+        [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:invoke];
+    }
+}
+
+// older api calls newer didFinishPickingMediaWithInfo
+- (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
+{
+    __weak CDVCameraPicker* cameraPicker = (CDVCameraPicker*)picker;
+    __weak CDVCamera* weakSelf = self;
+    
+    dispatch_block_t invoke = ^ (void) {
+        CDVPluginResult* result;
+        if (picker.sourceType == UIImagePickerControllerSourceTypeCamera && [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] != ALAuthorizationStatusAuthorized) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to camera"];
+        } else if (picker.sourceType != UIImagePickerControllerSourceTypeCamera && [ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusAuthorized) {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"has no access to assets"];
+        } else {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"no image selected"];
+        }
+
+        
+        [weakSelf.commandDelegate sendPluginResult:result callbackId:cameraPicker.callbackId];
+        
+        weakSelf.hasPendingOperation = NO;
+        weakSelf.pickerController = nil;
+    };
+
+    [[cameraPicker presentingViewController] dismissViewControllerAnimated:YES completion:invoke];
+}
+
+- (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) {
+        return;
+    }
+    
+    [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) {
+        return;
+    }
+
+    [self.locationManager stopUpdatingLocation];
+    self.locationManager = nil;
+    
+    [self imagePickerControllerReturnImageResult];
+}
+
+- (void)imagePickerControllerReturnImageResult
+{
+    CDVPictureOptions* options = self.pickerController.pictureOptions;
+    CDVPluginResult* result = nil;
+    
+    if (self.metadata) {
+        CGImageSourceRef sourceImage = CGImageSourceCreateWithData((__bridge 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);
+    }
+    
+    switch (options.destinationType) {
+        case DestinationTypeFileUri:
+        {
+            NSError* err = nil;
+            NSString* extension = self.pickerController.pictureOptions.encodingType == EncodingTypePNG ? @"png":@"jpg";
+            NSString* filePath = [self tempFilePath:extension];
+            
+            // 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:[[self urlTransformer:[NSURL fileURLWithPath:filePath]] absoluteString]];
+            }
+        }
+            break;
+        case DestinationTypeDataUrl:
+        {
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:toBase64(self.data)];
+        }
+            break;
+        case DestinationTypeNativeUri:
+        default:
+            break;
+    };
+    
+    if (result) {
+        [self.commandDelegate sendPluginResult:result callbackId:self.pickerController.callbackId];
+    }
+    
+    self.hasPendingOperation = NO;
+    self.pickerController = nil;
+    self.data = nil;
+    self.metadata = nil;
+    
+    if (options.saveToPhotoAlbum) {
+        ALAssetsLibrary *library = [ALAssetsLibrary new];
+        [library writeImageDataToSavedPhotosAlbum:self.data metadata:self.metadata completionBlock:nil];
+    }
+}
+
+@end
+
+@implementation CDVCameraPicker
+
+- (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];
+}
+
++ (instancetype) createFromPictureOptions:(CDVPictureOptions*)pictureOptions;
+{
+    CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
+    cameraPicker.pictureOptions = pictureOptions;
+    cameraPicker.sourceType = pictureOptions.sourceType;
+    cameraPicker.allowsEditing = pictureOptions.allowsEditing;
+    
+    if (cameraPicker.sourceType == UIImagePickerControllerSourceTypeCamera) {
+        // We only allow taking pictures (no video) in this API.
+        cameraPicker.mediaTypes = @[(NSString*)kUTTypeImage];
+        // We can only set the camera device if we're actually using the camera.
+        cameraPicker.cameraDevice = pictureOptions.cameraDirection;
+    } else if (pictureOptions.mediaType == MediaTypeAll) {
+        cameraPicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:cameraPicker.sourceType];
+    } else {
+        NSArray* mediaArray = @[(NSString*)(pictureOptions.mediaType == MediaTypeVideo ? kUTTypeMovie : kUTTypeImage)];
+        cameraPicker.mediaTypes = mediaArray;
+    }
+    
+    return cameraPicker;
+}
+
+@end

+ 43 - 0
miaomiao/plugins/cordova-plugin-camera/src/ios/CDVExif.h

xqd
@@ -0,0 +1,43 @@
+/*
+ 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

+ 62 - 0
miaomiao/plugins/cordova-plugin-camera/src/ios/CDVJpegHeaderWriter.h

xqd
@@ -0,0 +1,62 @@
+/*
+ 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 <Foundation/Foundation.h>
+
+@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

+ 547 - 0
miaomiao/plugins/cordova-plugin-camera/src/ios/CDVJpegHeaderWriter.m

xqd
@@ -0,0 +1,547 @@
+/*
+ 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 : @"<ffe1>"]) {
+            // 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:&currentDataOffset];
+
+    //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:&currentDataOffset];
+    /*
+    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

+ 29 - 0
miaomiao/plugins/cordova-plugin-camera/src/ios/UIImage+CropScaleOrientation.h

xqd
@@ -0,0 +1,29 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface UIImage (CropScaleOrientation)
+
+- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize;
+- (UIImage*)imageCorrectedForCaptureOrientation;
+- (UIImage*)imageCorrectedForCaptureOrientation:(UIImageOrientation)imageOrientation;
+- (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize;
+
+@end

+ 175 - 0
miaomiao/plugins/cordova-plugin-camera/src/ios/UIImage+CropScaleOrientation.m

xqd
@@ -0,0 +1,175 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "UIImage+CropScaleOrientation.h"
+
+@implementation UIImage (CropScaleOrientation)
+
+- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
+{
+    UIImage* sourceImage = self;
+    UIImage* newImage = nil;
+    CGSize imageSize = sourceImage.size;
+    CGFloat width = imageSize.width;
+    CGFloat height = imageSize.height;
+    CGFloat targetWidth = targetSize.width;
+    CGFloat targetHeight = targetSize.height;
+    CGFloat scaleFactor = 0.0;
+    CGFloat scaledWidth = targetWidth;
+    CGFloat scaledHeight = targetHeight;
+    CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
+    
+    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
+        CGFloat widthFactor = targetWidth / width;
+        CGFloat heightFactor = targetHeight / height;
+        
+        if (widthFactor > heightFactor) {
+            scaleFactor = widthFactor; // scale to fit height
+        } else {
+            scaleFactor = heightFactor; // scale to fit width
+        }
+        scaledWidth = width * scaleFactor;
+        scaledHeight = height * scaleFactor;
+        
+        // center the image
+        if (widthFactor > heightFactor) {
+            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
+        } else if (widthFactor < heightFactor) {
+            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
+        }
+    }
+    
+    UIGraphicsBeginImageContext(targetSize); // this will crop
+    
+    CGRect thumbnailRect = CGRectZero;
+    thumbnailRect.origin = thumbnailPoint;
+    thumbnailRect.size.width = scaledWidth;
+    thumbnailRect.size.height = scaledHeight;
+    
+    [sourceImage drawInRect:thumbnailRect];
+    
+    newImage = UIGraphicsGetImageFromCurrentImageContext();
+    if (newImage == nil) {
+        NSLog(@"could not scale image");
+    }
+    
+    // pop the context to get back to the default
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+- (UIImage*)imageCorrectedForCaptureOrientation:(UIImageOrientation)imageOrientation
+{
+    float rotation_radians = 0;
+    bool perpendicular = false;
+    
+    switch (imageOrientation) {
+        case UIImageOrientationUp :
+            rotation_radians = 0.0;
+            break;
+            
+        case UIImageOrientationDown:
+            rotation_radians = M_PI; // don't be scared of radians, if you're reading this, you're good at math
+            break;
+            
+        case UIImageOrientationRight:
+            rotation_radians = M_PI_2;
+            perpendicular = true;
+            break;
+            
+        case UIImageOrientationLeft:
+            rotation_radians = -M_PI_2;
+            perpendicular = true;
+            break;
+            
+        default:
+            break;
+    }
+    
+    UIGraphicsBeginImageContext(CGSizeMake(self.size.width, self.size.height));
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    // Rotate around the center point
+    CGContextTranslateCTM(context, self.size.width / 2, self.size.height / 2);
+    CGContextRotateCTM(context, rotation_radians);
+    
+    CGContextScaleCTM(context, 1.0, -1.0);
+    float width = perpendicular ? self.size.height : self.size.width;
+    float height = perpendicular ? self.size.width : self.size.height;
+    CGContextDrawImage(context, CGRectMake(-width / 2, -height / 2, width, height), [self CGImage]);
+    
+    // Move the origin back since the rotation might've change it (if its 90 degrees)
+    if (perpendicular) {
+        CGContextTranslateCTM(context, -self.size.height / 2, -self.size.width / 2);
+    }
+    
+    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+- (UIImage*)imageCorrectedForCaptureOrientation
+{
+    return [self imageCorrectedForCaptureOrientation:[self imageOrientation]];
+}
+
+- (UIImage*)imageByScalingNotCroppingForSize:(CGSize)targetSize
+{
+    UIImage* sourceImage = self;
+    UIImage* newImage = nil;
+    CGSize imageSize = sourceImage.size;
+    CGFloat width = imageSize.width;
+    CGFloat height = imageSize.height;
+    CGFloat targetWidth = targetSize.width;
+    CGFloat targetHeight = targetSize.height;
+    CGFloat scaleFactor = 0.0;
+    CGSize scaledSize = targetSize;
+    
+    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
+        CGFloat widthFactor = targetWidth / width;
+        CGFloat heightFactor = targetHeight / height;
+        
+        // opposite comparison to imageByScalingAndCroppingForSize in order to contain the image within the given bounds
+        if (widthFactor > heightFactor) {
+            scaleFactor = heightFactor; // scale to fit height
+        } else {
+            scaleFactor = widthFactor; // scale to fit width
+        }
+        scaledSize = CGSizeMake(MIN(width * scaleFactor, targetWidth), MIN(height * scaleFactor, targetHeight));
+    }
+    
+    // If the pixels are floats, it causes a white line in iOS8 and probably other versions too
+    scaledSize.width = (int)scaledSize.width;
+    scaledSize.height = (int)scaledSize.height;
+    
+    UIGraphicsBeginImageContext(scaledSize); // this will resize
+    
+    [sourceImage drawInRect:CGRectMake(0, 0, scaledSize.width, scaledSize.height)];
+    
+    newImage = UIGraphicsGetImageFromCurrentImageContext();
+    if (newImage == nil) {
+        NSLog(@"could not scale image");
+    }
+    
+    // pop the context to get back to the default
+    UIGraphicsEndImageContext();
+    return newImage;
+}
+
+@end

+ 118 - 0
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/CaptureWidget.qml

xqd
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+import QtQuick 2.0
+import QtMultimedia 5.0
+
+Rectangle {
+    property string shootImagePath: "shoot.png"
+    function isSuffix(str, suffix) {
+        return String(str).substr(String(str).length - suffix.length) == suffix
+    }
+
+    id: ui
+    color: "#252423"
+    anchors.fill: parent
+
+    Camera {
+        objectName: "camera"
+        id: camera
+        onError: {
+            console.log(errorString);
+        }
+        videoRecorder.audioBitRate: 128000
+        imageCapture {
+            onImageSaved: {
+                root.exec("Camera", "onImageSaved", [path]);
+                ui.destroy();
+            }
+        }
+    }
+    VideoOutput {
+        id: output
+        source: camera
+        width: parent.width
+        height: parent.height
+    }
+
+    Item {
+        anchors.bottom: parent.bottom
+        width: parent.width
+        height: shootButton.height
+        BorderImage {
+            id: leftBackground
+            anchors.left: parent.left
+            anchors.top: parent.top
+            anchors.bottom: parent.bottom
+            anchors.right: middle.left
+            anchors.topMargin: units.dp(2)
+            anchors.bottomMargin: units.dp(2)
+            source: "toolbar-left.png"
+            Image {
+                anchors.verticalCenter: parent.verticalCenter
+                anchors.left: parent.left
+                anchors.leftMargin: parent.iconSpacing
+                source: "back.png"
+                width: units.gu(6)
+                height: units.gu(5)
+                MouseArea {
+                    anchors.fill: parent
+                    onClicked: {
+                        root.exec("Camera", "cancel");
+                    }
+                }
+            }
+        }
+        BorderImage {
+            id: middle
+            anchors.top: parent.top
+            anchors.bottom: parent.bottom
+            anchors.horizontalCenter: parent.horizontalCenter
+            height: shootButton.height + units.gu(1)
+            width: shootButton.width
+            source: "toolbar-middle.png"
+            Image {
+                id: shootButton
+                width: units.gu(8)
+                height: width
+                anchors.horizontalCenter: parent.horizontalCenter
+                source: shootImagePath
+                MouseArea {
+                    anchors.fill: parent
+                    onClicked: {
+                        camera.imageCapture.captureToLocation(ui.parent.plugin('Camera').generateLocation("jpg"));
+                    }
+                }
+            }
+        }
+        BorderImage {
+            id: rightBackground
+            anchors.right: parent.right
+            anchors.top: parent.top
+            anchors.bottom: parent.bottom
+            anchors.left: middle.right
+            anchors.topMargin: units.dp(2)
+            anchors.bottomMargin: units.dp(2)
+            source: "toolbar-right.png"
+        }
+    }
+}

BIN
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/back.png


+ 140 - 0
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/camera.cpp

xqd
@@ -0,0 +1,140 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#include "camera.h"
+#include <cordova.h>
+
+#include <QCameraViewfinder>
+#include <QCameraImageCapture>
+#include <QGraphicsObject>
+#include <QCloseEvent>
+#include <QQuickItem>
+
+const char code[] = "\
+var component, object;                                                  \
+function createObject() {                                               \
+    component = Qt.createComponent(%1);                                 \
+    if (component.status == Component.Ready)                            \
+        finishCreation();                                               \
+    else                                                                \
+        component.statusChanged.connect(finishCreation);                \
+}                                                                       \
+function finishCreation() {                                             \
+    CordovaWrapper.global.cameraPluginWidget = component.createObject(root, \
+        {root: root, cordova: cordova});                                \
+}                                                                       \
+createObject()";
+
+
+Camera::Camera(Cordova *cordova):
+    CPlugin(cordova),
+    _lastScId(0),
+    _lastEcId(0) {
+}
+
+bool Camera::preprocessImage(QString &path) {
+    bool convertToPNG = (*_options.find("encodingType")).toInt() == Camera::PNG;
+    int quality = (*_options.find("quality")).toInt();
+    int width = (*_options.find("targetWidth")).toInt();
+    int height = (*_options.find("targetHeight")).toInt();
+
+    QImage image(path);
+    if (width <= 0)
+        width = image.width();
+    if (height <= 0)
+        height = image.height();
+    image = image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+
+    QFile oldImage(path);
+    QTemporaryFile newImage;
+
+    const char *type;
+    if (convertToPNG) {
+        path = generateLocation("png");
+        type = "png";
+    } else {
+        path = generateLocation("jpg");
+        type = "jpg";
+    }
+
+    image.save(path, type, quality);
+
+    oldImage.remove();
+
+    return true;
+}
+
+void Camera::onImageSaved(QString path) {
+    bool dataURL = _options.find("destinationType")->toInt() == Camera::DATA_URL;
+
+    QString cbParams;
+    if (preprocessImage(path)) {
+        QString absolutePath = QFileInfo(path).absoluteFilePath();
+        if (dataURL) {
+            QFile image(absolutePath);
+            image.open(QIODevice::ReadOnly);
+            QByteArray content = image.readAll().toBase64();
+            cbParams = QString("\"%1\"").arg(content.data());
+            image.remove();
+        } else {
+            cbParams = CordovaInternal::format(QString("file://localhost") + absolutePath);
+        }
+    }
+
+    this->callback(_lastScId, cbParams);
+
+    _lastEcId = _lastScId = 0;
+}
+
+void Camera::takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
+                         int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &/*popoverOptions*/, int/*cameraDirection*/) {
+    if (_camera.isNull()) {
+        _camera = QSharedPointer<QCamera>(new QCamera());
+    }
+
+    if (((_lastScId || _lastEcId) && (_lastScId != scId && _lastEcId != ecId)) || !_camera->isAvailable() || _camera->lockStatus() != QCamera::Unlocked) {
+        this->cb(_lastEcId, "Device is busy");
+        return;
+    }
+
+    _options.clear();
+    _options.insert("quality", quality);
+    _options.insert("destinationType", destinationType);
+    _options.insert("targetWidth", targetWidth);
+    _options.insert("targetHeight", targetHeight);
+    _options.insert("encodingType", encodingType);
+
+    _lastScId = scId;
+    _lastEcId = ecId;
+
+    QString path = m_cordova->get_app_dir() + "/../qml/CaptureWidget.qml";
+
+    // TODO: relative url
+    QString qml = QString(code).arg(CordovaInternal::format(path));
+    m_cordova->execQML(qml);
+}
+
+void Camera::cancel() {
+    m_cordova->execQML("CordovaWrapper.global.cameraPluginWidget.destroy()");
+    this->cb(_lastEcId, "canceled");
+
+    _lastEcId = _lastScId = 0;
+}

+ 86 - 0
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/camera.h

xqd
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <cplugin.h>
+
+#include <QtCore>
+#include <QQuickView>
+#include <QCamera>
+#include <QtMultimediaWidgets/QCameraViewfinder>
+#include <QCameraImageCapture>
+
+class Camera: public CPlugin {
+    Q_OBJECT
+public:
+    explicit Camera(Cordova *cordova);
+
+    virtual const QString fullName() override {
+        return Camera::fullID();
+    }
+
+    virtual const QString shortName() override {
+        return "Camera";
+    }
+
+    static const QString fullID() {
+        return "Camera";
+    }
+
+public slots:
+    void takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
+                     int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &popoverOptions, int cameraDirection);
+    void cancel();
+
+    void onImageSaved(QString path);
+
+    QString generateLocation(const QString &extension) {
+        int i = 1;
+        for (;;++i) {
+            QString path = QString("%1/.local/share/%2/persistent/%3.%4").arg(QDir::homePath())
+                .arg(QCoreApplication::applicationName()).arg(i).arg(extension);
+
+            if (!QFileInfo(path).exists())
+                return path;
+        }
+    }
+private:
+    bool preprocessImage(QString &path);
+
+    int _lastScId;
+    int _lastEcId;
+    QSharedPointer<QCamera> _camera;
+
+    QVariantMap _options;
+protected:
+    enum DestinationType {
+        DATA_URL = 0,
+        FILE_URI = 1
+    };
+    enum EncodingType {
+        JPEG = 0,
+        PNG = 1
+    };
+};
+
+#endif // CAMERA_H

BIN
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/shoot.png


BIN
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/toolbar-left.png


BIN
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/toolbar-middle.png


BIN
miaomiao/plugins/cordova-plugin-camera/src/ubuntu/toolbar-right.png


+ 882 - 0
miaomiao/plugins/cordova-plugin-camera/src/windows/CameraProxy.js

xqd
@@ -0,0 +1,882 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+/*jshint unused:true, undef:true, browser:true */
+/*global Windows:true, URL:true, module:true, require:true, WinJS:true */
+
+
+var Camera = require('./Camera');
+
+
+var getAppData = function () {
+    return Windows.Storage.ApplicationData.current;
+};
+var encodeToBase64String = function (buffer) {
+    return Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer);
+};
+var OptUnique = Windows.Storage.CreationCollisionOption.generateUniqueName;
+var CapMSType = Windows.Media.Capture.MediaStreamType;
+var webUIApp = Windows.UI.WebUI.WebUIApplication;
+var fileIO = Windows.Storage.FileIO;
+var pickerLocId = Windows.Storage.Pickers.PickerLocationId;
+
+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
+    // 11 cameraDirection:0
+
+    takePicture: function (successCallback, errorCallback, args) {
+        var sourceType = args[2];
+
+        if (sourceType != Camera.PictureSourceType.CAMERA) {
+            takePictureFromFile(successCallback, errorCallback, args);
+        } else {
+            takePictureFromCamera(successCallback, errorCallback, args);
+        }
+    }
+};
+
+// https://msdn.microsoft.com/en-us/library/windows/apps/ff462087(v=vs.105).aspx
+var windowsVideoContainers = [".avi", ".flv", ".asx", ".asf", ".mov", ".mp4", ".mpg", ".rm", ".srt", ".swf", ".wmv", ".vob"];
+var windowsPhoneVideoContainers =  [".avi", ".3gp", ".3g2", ".wmv", ".3gp", ".3g2", ".mp4", ".m4v"];
+
+// Default aspect ratio 1.78 (16:9 hd video standard)
+var DEFAULT_ASPECT_RATIO = '1.8';
+
+// Highest possible z-index supported across browsers. Anything used above is converted to this value.
+var HIGHEST_POSSIBLE_Z_INDEX = 2147483647;
+
+// Resize method
+function resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType) {
+    var tempPhotoFileName = "";
+    var targetContentType = "";
+
+    if (encodingType == Camera.EncodingType.PNG) {
+        tempPhotoFileName = "camera_cordova_temp_return.png";
+        targetContentType = "image/png";
+    } else {
+        tempPhotoFileName = "camera_cordova_temp_return.jpg";
+        targetContentType = "image/jpeg";
+    }
+
+    var storageFolder = getAppData().localFolder;
+    file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting)
+        .then(function (storageFile) {
+            return fileIO.readBufferAsync(storageFile);
+        })
+        .then(function(buffer) {
+            var strBase64 = encodeToBase64String(buffer);
+            var imageData = "data:" + file.contentType + ";base64," + strBase64;
+            var image = new Image();
+            image.src = imageData;
+            image.onload = function() {
+                var ratio = Math.min(targetWidth / this.width, targetHeight / this.height);
+                var imageWidth = ratio * this.width;
+                var imageHeight = ratio * this.height;
+
+                var canvas = document.createElement('canvas');
+                var storageFileName;
+
+                canvas.width = imageWidth;
+                canvas.height = imageHeight;
+
+                canvas.getContext("2d").drawImage(this, 0, 0, imageWidth, imageHeight);
+
+                var fileContent = canvas.toDataURL(targetContentType).split(',')[1];
+
+                var storageFolder = getAppData().localFolder;
+
+                storageFolder.createFileAsync(tempPhotoFileName, OptUnique)
+                    .then(function (storagefile) {
+                        var content = Windows.Security.Cryptography.CryptographicBuffer.decodeFromBase64String(fileContent);
+                        storageFileName = storagefile.name;
+                        return fileIO.writeBufferAsync(storagefile, content);
+                    })
+                    .done(function () {
+                        successCallback("ms-appdata:///local/" + storageFileName);
+                    }, errorCallback);
+            };
+        })
+        .done(null, function(err) {
+            errorCallback(err);
+        }
+    );
+}
+
+// Because of asynchronous method, so let the successCallback be called in it.
+function resizeImageBase64(successCallback, errorCallback, file, targetWidth, targetHeight) {
+    fileIO.readBufferAsync(file).done( function(buffer) {
+        var strBase64 = encodeToBase64String(buffer);
+        var imageData = "data:" + file.contentType + ";base64," + strBase64;
+
+        var image = new Image();
+        image.src = imageData;
+
+        image.onload = function() {
+            var ratio = Math.min(targetWidth / this.width, targetHeight / this.height);
+            var imageWidth = ratio * this.width;
+            var imageHeight = ratio * this.height;
+            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(file.contentType);
+
+            // 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);
+        };
+    }, function(err) { errorCallback(err); });
+}
+
+function takePictureFromFile(successCallback, errorCallback, args) {
+    // Detect Windows Phone
+    if (navigator.appVersion.indexOf('Windows Phone 8.1') >= 0) {
+        takePictureFromFileWP(successCallback, errorCallback, args);
+    } else {
+        takePictureFromFileWindows(successCallback, errorCallback, args);
+    }
+}
+
+function takePictureFromFileWP(successCallback, errorCallback, args) {
+    var mediaType = args[6],
+        destinationType = args[1],
+        targetWidth = args[3],
+        targetHeight = args[4],
+        encodingType = args[5];
+
+    /*
+        Need to add and remove an event listener to catch activation state
+        Using FileOpenPicker will suspend the app and it's required to catch the PickSingleFileAndContinue
+        https://msdn.microsoft.com/en-us/library/windows/apps/xaml/dn631755.aspx
+    */
+    var filePickerActivationHandler = function(eventArgs) {
+        if (eventArgs.kind === Windows.ApplicationModel.Activation.ActivationKind.pickFileContinuation) {
+            var file = eventArgs.files[0];
+            if (!file) {
+                errorCallback("User didn't choose a file.");
+                webUIApp.removeEventListener("activated", filePickerActivationHandler);
+                return;
+            }
+            if (destinationType == Camera.DestinationType.FILE_URI || destinationType == Camera.DestinationType.NATIVE_URI) {
+                if (targetHeight > 0 && targetWidth > 0) {
+                    resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
+                }
+                else {
+                    var storageFolder = getAppData().localFolder;
+                    file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
+                        if(destinationType == Camera.DestinationType.NATIVE_URI) {
+                            successCallback("ms-appdata:///local/" + storageFile.name);
+                        }
+                        else {
+                            successCallback(URL.createObjectURL(storageFile));
+                        }
+                    }, function () {
+                        errorCallback("Can't access localStorage folder.");
+                    });
+                }
+            }
+            else {
+                if (targetHeight > 0 && targetWidth > 0) {
+                    resizeImageBase64(successCallback, errorCallback, file, targetWidth, targetHeight);
+                } else {
+                    fileIO.readBufferAsync(file).done(function (buffer) {
+                        var strBase64 =encodeToBase64String(buffer);
+                        successCallback(strBase64);
+                    }, errorCallback);
+                }
+            }
+            webUIApp.removeEventListener("activated", filePickerActivationHandler);
+        }
+    };
+
+    var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
+    if (mediaType == Camera.MediaType.PICTURE) {
+        fileOpenPicker.fileTypeFilter.replaceAll([".png", ".jpg", ".jpeg"]);
+        fileOpenPicker.suggestedStartLocation = pickerLocId.picturesLibrary;
+    }
+    else if (mediaType == Camera.MediaType.VIDEO) {
+        fileOpenPicker.fileTypeFilter.replaceAll(windowsPhoneVideoContainers);
+        fileOpenPicker.suggestedStartLocation = pickerLocId.videosLibrary;
+    }
+    else {
+        fileOpenPicker.fileTypeFilter.replaceAll(["*"]);
+        fileOpenPicker.suggestedStartLocation = pickerLocId.documentsLibrary;
+    }
+
+    webUIApp.addEventListener("activated", filePickerActivationHandler);
+    fileOpenPicker.pickSingleFileAndContinue();
+}
+
+function takePictureFromFileWindows(successCallback, errorCallback, args) {
+    var mediaType = args[6],
+        destinationType = args[1],
+        targetWidth = args[3],
+        targetHeight = args[4],
+        encodingType = args[5];
+
+    var fileOpenPicker = new Windows.Storage.Pickers.FileOpenPicker();
+    if (mediaType == Camera.MediaType.PICTURE) {
+        fileOpenPicker.fileTypeFilter.replaceAll([".png", ".jpg", ".jpeg"]);
+        fileOpenPicker.suggestedStartLocation = pickerLocId.picturesLibrary;
+    }
+    else if (mediaType == Camera.MediaType.VIDEO) {
+        fileOpenPicker.fileTypeFilter.replaceAll(windowsVideoContainers);
+        fileOpenPicker.suggestedStartLocation = pickerLocId.videosLibrary;
+    }
+    else {
+        fileOpenPicker.fileTypeFilter.replaceAll(["*"]);
+        fileOpenPicker.suggestedStartLocation = pickerLocId.documentsLibrary;
+    }
+
+    fileOpenPicker.pickSingleFileAsync().done(function (file) {
+        if (!file) {
+            errorCallback("User didn't choose a file.");
+            return;
+        }
+        if (destinationType == Camera.DestinationType.FILE_URI || destinationType == Camera.DestinationType.NATIVE_URI) {
+            if (targetHeight > 0 && targetWidth > 0) {
+                resizeImage(successCallback, errorCallback, file, targetWidth, targetHeight, encodingType);
+            }
+            else {
+                var storageFolder = getAppData().localFolder;
+                file.copyAsync(storageFolder, file.name, Windows.Storage.NameCollisionOption.replaceExisting).done(function (storageFile) {
+                        if(destinationType == Camera.DestinationType.NATIVE_URI) {
+                            successCallback("ms-appdata:///local/" + storageFile.name);
+                        }
+                        else {
+                            successCallback(URL.createObjectURL(storageFile));
+                        }
+                }, function () {
+                    errorCallback("Can't access localStorage folder.");
+                });
+            }
+        }
+        else {
+            if (targetHeight > 0 && targetWidth > 0) {
+                resizeImageBase64(successCallback, errorCallback, file, targetWidth, targetHeight);
+            } else {
+                fileIO.readBufferAsync(file).done(function (buffer) {
+                    var strBase64 =encodeToBase64String(buffer);
+                    successCallback(strBase64);
+                }, errorCallback);
+            }
+        }
+    }, function () {
+        errorCallback("User didn't choose a file.");
+    });
+}
+
+function takePictureFromCamera(successCallback, errorCallback, args) {
+    // Check if necessary API available
+    if (!Windows.Media.Capture.CameraCaptureUI) {
+        takePictureFromCameraWP(successCallback, errorCallback, args);
+    } else {
+        takePictureFromCameraWindows(successCallback, errorCallback, args);
+    }
+}
+
+function takePictureFromCameraWP(successCallback, errorCallback, args) {
+    // We are running on WP8.1 which lacks CameraCaptureUI class
+    // so we need to use MediaCapture class instead and implement custom UI for camera
+    var destinationType = args[1],
+        targetWidth = args[3],
+        targetHeight = args[4],
+        encodingType = args[5],
+        saveToPhotoAlbum = args[9],
+        cameraDirection = args[11],
+        capturePreview = null,
+        cameraCaptureButton = null,
+        cameraCancelButton = null,
+        capture = null,
+        captureSettings = null,
+        CaptureNS = Windows.Media.Capture,
+        sensor = null;
+
+    function createCameraUI() {
+        // create style for take and cancel buttons
+        var buttonStyle = "width:45%;padding: 10px 16px;font-size: 18px;line-height: 1.3333333;color: #333;background-color: #fff;border-color: #ccc; border: 1px solid transparent;border-radius: 6px; display: block; margin: 20px; z-index: 1000;border-color: #adadad;";
+
+        // Create fullscreen preview
+        // z-order style element for capturePreview and cameraCancelButton elts
+        // is necessary to avoid overriding by another page elements, -1 sometimes is not enough
+        capturePreview = document.createElement("video");
+        capturePreview.style.cssText = "position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: " + (HIGHEST_POSSIBLE_Z_INDEX - 1) + ";";
+
+        // Create capture button
+        cameraCaptureButton = document.createElement("button");
+        cameraCaptureButton.innerText = "Take";
+        cameraCaptureButton.style.cssText = buttonStyle + "position: fixed; left: 0; bottom: 0; margin: 20px; z-index: " + HIGHEST_POSSIBLE_Z_INDEX + ";";
+
+        // Create cancel button
+        cameraCancelButton = document.createElement("button");
+        cameraCancelButton.innerText = "Cancel";
+        cameraCancelButton.style.cssText = buttonStyle + "position: fixed; right: 0; bottom: 0; margin: 20px; z-index: " + HIGHEST_POSSIBLE_Z_INDEX + ";";
+
+        capture = new CaptureNS.MediaCapture();
+
+        captureSettings = new CaptureNS.MediaCaptureInitializationSettings();
+        captureSettings.streamingCaptureMode = CaptureNS.StreamingCaptureMode.video;
+    }
+
+    function continueVideoOnFocus() {
+        // if preview is defined it would be stuck, play it
+        if (capturePreview) {
+            capturePreview.play();
+        }
+    }
+
+    function startCameraPreview() {
+        // Search for available camera devices
+        // This is necessary to detect which camera (front or back) we should use
+        var DeviceEnum = Windows.Devices.Enumeration;
+        var expectedPanel = cameraDirection === 1 ? DeviceEnum.Panel.front : DeviceEnum.Panel.back;
+
+        // Add focus event handler to capture the event when user suspends the app and comes back while the preview is on
+        window.addEventListener("focus", continueVideoOnFocus);
+
+        DeviceEnum.DeviceInformation.findAllAsync(DeviceEnum.DeviceClass.videoCapture).then(function (devices) {
+            if (devices.length <= 0) {
+                destroyCameraPreview();
+                errorCallback('Camera not found');
+                return;
+            }
+
+            devices.forEach(function(currDev) {
+                if (currDev.enclosureLocation.panel && currDev.enclosureLocation.panel == expectedPanel) {
+                    captureSettings.videoDeviceId = currDev.id;
+                }
+            });
+
+            captureSettings.photoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.photo;
+
+            return capture.initializeAsync(captureSettings);
+        }).then(function () {
+
+            // create focus control if available
+            var VideoDeviceController = capture.videoDeviceController;
+            var FocusControl = VideoDeviceController.focusControl;
+
+            if (FocusControl.supported === true) {
+                capturePreview.addEventListener('click', function () {
+                    // Make sure function isn't called again before previous focus is completed
+                    if (this.getAttribute('clicked') === '1') {
+                        return false;
+                    } else {
+                        this.setAttribute('clicked', '1');
+                    }
+                    var preset = Windows.Media.Devices.FocusPreset.autoNormal;
+                    var parent = this;
+                    FocusControl.setPresetAsync(preset).done(function () {
+                        // set the clicked attribute back to '0' to allow focus again
+                        parent.setAttribute('clicked', '0');
+                    });
+                });
+            }
+
+            // msdn.microsoft.com/en-us/library/windows/apps/hh452807.aspx
+            capturePreview.msZoom = true;
+            capturePreview.src = URL.createObjectURL(capture);
+            capturePreview.play();
+
+            // Bind events to controls
+            sensor = Windows.Devices.Sensors.SimpleOrientationSensor.getDefault();
+            if (sensor !== null) {
+                sensor.addEventListener("orientationchanged", onOrientationChange);
+            }
+
+            // add click events to capture and cancel buttons
+            cameraCaptureButton.addEventListener('click', onCameraCaptureButtonClick);
+            cameraCancelButton.addEventListener('click', onCameraCancelButtonClick);
+
+            // Change default orientation
+            if (sensor) {
+                setPreviewRotation(sensor.getCurrentOrientation());
+            } else {
+                setPreviewRotation(Windows.Graphics.Display.DisplayInformation.getForCurrentView().currentOrientation);
+            }
+
+            // Get available aspect ratios
+            var aspectRatios = getAspectRatios(capture);
+
+            // Couldn't find a good ratio
+            if (aspectRatios.length === 0) {
+                destroyCameraPreview();
+                errorCallback('There\'s not a good aspect ratio available');
+                return;
+            }
+
+            // add elements to body
+            document.body.appendChild(capturePreview);
+            document.body.appendChild(cameraCaptureButton);
+            document.body.appendChild(cameraCancelButton);
+
+            if (aspectRatios.indexOf(DEFAULT_ASPECT_RATIO) > -1) {
+                return setAspectRatio(capture, DEFAULT_ASPECT_RATIO);
+            } else {
+                // Doesn't support 16:9 - pick next best
+                return setAspectRatio(capture, aspectRatios[0]);
+            }
+        }).done(null, function (err) {
+            destroyCameraPreview();
+            errorCallback('Camera intitialization error ' + err);
+        });
+    }
+
+    function destroyCameraPreview() {
+        // If sensor is available, remove event listener
+        if (sensor !== null) {
+            sensor.removeEventListener('orientationchanged', onOrientationChange);
+        }
+
+        // Pause and dispose preview element
+        capturePreview.pause();
+        capturePreview.src = null;
+
+        // Remove event listeners from buttons
+        cameraCaptureButton.removeEventListener('click', onCameraCaptureButtonClick);
+        cameraCancelButton.removeEventListener('click', onCameraCancelButtonClick);
+
+        // Remove the focus event handler
+        window.removeEventListener("focus", continueVideoOnFocus);
+
+        // Remove elements
+        [capturePreview, cameraCaptureButton, cameraCancelButton].forEach(function (elem) {
+            if (elem /* && elem in document.body.childNodes */) {
+                document.body.removeChild(elem);
+            }
+        });
+
+        // Stop and dispose media capture manager
+        if (capture) {
+            capture.stopRecordAsync();
+            capture = null;
+        }
+    }
+
+    function captureAction() {
+
+        var encodingProperties,
+            fileName,
+            tempFolder = getAppData().temporaryFolder;
+
+        if (encodingType == Camera.EncodingType.PNG) {
+            fileName = 'photo.png';
+            encodingProperties = Windows.Media.MediaProperties.ImageEncodingProperties.createPng();
+        } else {
+            fileName = 'photo.jpg';
+            encodingProperties = Windows.Media.MediaProperties.ImageEncodingProperties.createJpeg();
+        }
+
+        tempFolder.createFileAsync(fileName, OptUnique)
+            .then(function(tempCapturedFile) {
+                return new WinJS.Promise(function (complete) {
+                    var photoStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
+                    var finalStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
+                    capture.capturePhotoToStreamAsync(encodingProperties, photoStream)
+                        .then(function() {
+                            return Windows.Graphics.Imaging.BitmapDecoder.createAsync(photoStream);
+                        })
+                        .then(function(dec) {
+                            finalStream.size = 0; // BitmapEncoder requires the output stream to be empty
+                            return Windows.Graphics.Imaging.BitmapEncoder.createForTranscodingAsync(finalStream, dec);
+                        })
+                        .then(function(enc) {
+                            // We need to rotate the photo wrt sensor orientation
+                            enc.bitmapTransform.rotation = orientationToRotation(sensor.getCurrentOrientation());
+                            return enc.flushAsync();
+                        })
+                        .then(function() {
+                            return tempCapturedFile.openAsync(Windows.Storage.FileAccessMode.readWrite);
+                        })
+                        .then(function(fileStream) {
+                            return Windows.Storage.Streams.RandomAccessStream.copyAndCloseAsync(finalStream, fileStream);
+                        })
+                        .done(function() {
+                            photoStream.close();
+                            finalStream.close();
+                            complete(tempCapturedFile);
+                        }, function() {
+                            photoStream.close();
+                            finalStream.close();
+                            throw new Error("An error has occured while capturing the photo.");
+                        });
+                });
+            })
+            .done(function(capturedFile) {
+                destroyCameraPreview();
+                savePhoto(capturedFile, {
+                    destinationType: destinationType,
+                    targetHeight: targetHeight,
+                    targetWidth: targetWidth,
+                    encodingType: encodingType,
+                    saveToPhotoAlbum: saveToPhotoAlbum
+                }, successCallback, errorCallback);
+            }, function(err) {
+                destroyCameraPreview();
+                errorCallback(err);
+            });
+    }
+
+    function getAspectRatios(capture) {
+        var videoDeviceController = capture.videoDeviceController;
+        var photoAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo).map(function (element) {
+            return (element.width / element.height).toFixed(1);
+        }).filter(function (element, index, array) { return (index === array.indexOf(element)); });
+
+        var videoAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoRecord).map(function (element) {
+            return (element.width / element.height).toFixed(1);
+        }).filter(function (element, index, array) { return (index === array.indexOf(element)); });
+
+        var videoPreviewAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoPreview).map(function (element) {
+            return (element.width / element.height).toFixed(1);
+        }).filter(function (element, index, array) { return (index === array.indexOf(element)); });
+
+        var allAspectRatios = [].concat(photoAspectRatios, videoAspectRatios, videoPreviewAspectRatios);
+
+        var aspectObj = allAspectRatios.reduce(function (map, item) {
+            if (!map[item]) {
+                map[item] = 0;
+            }
+            map[item]++;
+            return map;
+        }, {});
+
+        return Object.keys(aspectObj).filter(function (k) {
+            return aspectObj[k] === 3;
+        });
+    }
+
+    function setAspectRatio(capture, aspect) {
+        // Max photo resolution with desired aspect ratio
+        var videoDeviceController = capture.videoDeviceController;
+        var photoResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo)
+            .filter(function (elem) {
+                return ((elem.width / elem.height).toFixed(1) === aspect);
+            })
+            .reduce(function (prop1, prop2) {
+                return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
+            });
+
+        // Max video resolution with desired aspect ratio
+        var videoRecordResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoRecord)
+            .filter(function (elem) {
+                return ((elem.width / elem.height).toFixed(1) === aspect);
+            })
+            .reduce(function (prop1, prop2) {
+                return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
+            });
+
+        // Max video preview resolution with desired aspect ratio
+        var videoPreviewResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoPreview)
+            .filter(function (elem) {
+                return ((elem.width / elem.height).toFixed(1) === aspect);
+            })
+            .reduce(function (prop1, prop2) {
+                return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
+            });
+
+        return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.photo, photoResolution)
+            .then(function () {
+                return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.videoPreview, videoPreviewResolution);
+            })
+            .then(function () {
+                return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.videoRecord, videoRecordResolution);
+            });
+    }
+
+    /**
+     * When Capture button is clicked, try to capture a picture and return
+     */
+    function onCameraCaptureButtonClick() {
+        // Make sure user can't click more than once
+        if (this.getAttribute('clicked') === '1') {
+            return false;
+        } else {
+            this.setAttribute('clicked', '1');
+        }
+        captureAction();
+    }
+
+    /**
+     * When Cancel button is clicked, destroy camera preview and return with error callback
+     */
+    function onCameraCancelButtonClick() {
+        // Make sure user can't click more than once
+        if (this.getAttribute('clicked') === '1') {
+            return false;
+        } else {
+            this.setAttribute('clicked', '1');
+        }
+        destroyCameraPreview();
+        errorCallback('no image selected');
+    }
+
+    /**
+     * When the phone orientation change, get the event and change camera preview rotation
+     * @param  {Object} e - SimpleOrientationSensorOrientationChangedEventArgs
+     */
+    function onOrientationChange(e) {
+        setPreviewRotation(e.orientation);
+    }
+
+    /**
+     * Converts SimpleOrientation to a VideoRotation to remove difference between camera sensor orientation
+     * and video orientation
+     * @param  {number} orientation - Windows.Devices.Sensors.SimpleOrientation
+     * @return {number} - Windows.Media.Capture.VideoRotation
+     */
+    function orientationToRotation(orientation) {
+        // VideoRotation enumerable and BitmapRotation enumerable have the same values
+        // https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.capture.videorotation.aspx
+        // https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmaprotation.aspx
+
+        switch (orientation) {
+            // portrait
+            case Windows.Devices.Sensors.SimpleOrientation.notRotated:
+                return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+            // landscape
+            case Windows.Devices.Sensors.SimpleOrientation.rotated90DegreesCounterclockwise:
+                return Windows.Media.Capture.VideoRotation.none;
+            // portrait-flipped (not supported by WinPhone Apps)
+            case Windows.Devices.Sensors.SimpleOrientation.rotated180DegreesCounterclockwise:
+                // Falling back to portrait default
+                return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+            // landscape-flipped
+            case Windows.Devices.Sensors.SimpleOrientation.rotated270DegreesCounterclockwise:
+                return Windows.Media.Capture.VideoRotation.clockwise180Degrees;
+            // faceup & facedown
+            default:
+                // Falling back to portrait default
+                return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+        }
+    }
+
+    /**
+     * Rotates the current MediaCapture's video
+     * @param {number} orientation - Windows.Devices.Sensors.SimpleOrientation
+     */
+    function setPreviewRotation(orientation) {
+        capture.setPreviewRotation(orientationToRotation(orientation));
+    }
+
+    try {
+        createCameraUI();
+        startCameraPreview();
+    } catch (ex) {
+        errorCallback(ex);
+    }
+}
+
+function takePictureFromCameraWindows(successCallback, errorCallback, args) {
+    var destinationType = args[1],
+        targetWidth = args[3],
+        targetHeight = args[4],
+        encodingType = args[5],
+        allowCrop = !!args[7],
+        saveToPhotoAlbum = args[9],
+        WMCapture = Windows.Media.Capture,
+        cameraCaptureUI = new WMCapture.CameraCaptureUI();
+
+    cameraCaptureUI.photoSettings.allowCropping = allowCrop;
+
+    if (encodingType == Camera.EncodingType.PNG) {
+        cameraCaptureUI.photoSettings.format = WMCapture.CameraCaptureUIPhotoFormat.png;
+    } else {
+        cameraCaptureUI.photoSettings.format = WMCapture.CameraCaptureUIPhotoFormat.jpeg;
+    }
+
+    // decide which max pixels should be supported by targetWidth or targetHeight.
+    var maxRes = null;
+    var UIMaxRes = WMCapture.CameraCaptureUIMaxPhotoResolution;
+    var totalPixels = targetWidth * targetHeight;
+
+    if (targetWidth == -1 && targetHeight == -1) {
+        maxRes = UIMaxRes.highestAvailable;
+    }
+    // Temp fix for CB-10539
+    /*else if (totalPixels <= 320 * 240) {
+        maxRes = UIMaxRes.verySmallQvga;
+    }*/
+    else if (totalPixels <= 640 * 480) {
+        maxRes = UIMaxRes.smallVga;
+    } else if (totalPixels <= 1024 * 768) {
+        maxRes = UIMaxRes.mediumXga;
+    } else if (totalPixels <= 3 * 1000 * 1000) {
+        maxRes = UIMaxRes.large3M;
+    } else if (totalPixels <= 5 * 1000 * 1000) {
+        maxRes = UIMaxRes.veryLarge5M;
+    } else {
+        maxRes = UIMaxRes.highestAvailable;
+    }
+
+    cameraCaptureUI.photoSettings.maxResolution = maxRes;
+
+    var cameraPicture;
+
+    // define focus handler for windows phone 10.0
+    var savePhotoOnFocus = function () {
+        window.removeEventListener("focus", savePhotoOnFocus);
+        // call only when the app is in focus again
+        savePhoto(cameraPicture, {
+            destinationType: destinationType,
+            targetHeight: targetHeight,
+            targetWidth: targetWidth,
+            encodingType: encodingType,
+            saveToPhotoAlbum: saveToPhotoAlbum
+        }, successCallback, errorCallback);
+    };
+
+    // if windows phone 10, add and delete focus eventHandler to capture the focus back from cameraUI to app
+    if (navigator.appVersion.indexOf('Windows Phone 10.0') >= 0) {
+        window.addEventListener("focus", savePhotoOnFocus);
+    }
+
+    cameraCaptureUI.captureFileAsync(WMCapture.CameraCaptureUIMode.photo).done(function (picture) {
+        if (!picture) {
+            errorCallback("User didn't capture a photo.");
+            // Remove the focus handler if present
+            window.removeEventListener("focus", savePhotoOnFocus);
+            return;
+        }
+        cameraPicture = picture;
+
+        // If not windows 10, call savePhoto() now. If windows 10, wait for the app to be in focus again
+        if (navigator.appVersion.indexOf('Windows Phone 10.0') < 0) {
+            savePhoto(cameraPicture, {
+                destinationType: destinationType,
+                targetHeight: targetHeight,
+                targetWidth: targetWidth,
+                encodingType: encodingType,
+                saveToPhotoAlbum: saveToPhotoAlbum
+            }, successCallback, errorCallback);
+        }
+    }, function () {
+        errorCallback("Fail to capture a photo.");
+        window.removeEventListener("focus", savePhotoOnFocus);
+    });
+}
+
+function savePhoto(picture, options, successCallback, errorCallback) {
+    // success callback for capture operation
+    var success = function(picture) {
+        if (options.destinationType == Camera.DestinationType.FILE_URI || options.destinationType == Camera.DestinationType.NATIVE_URI) {
+            if (options.targetHeight > 0 && options.targetWidth > 0) {
+                resizeImage(successCallback, errorCallback, picture, options.targetWidth, options.targetHeight, options.encodingType);
+            } else {
+                picture.copyAsync(getAppData().localFolder, picture.name, OptUnique).done(function (copiedFile) {
+                    successCallback("ms-appdata:///local/" + copiedFile.name);
+                },errorCallback);
+            }
+        } else {
+            if (options.targetHeight > 0 && options.targetWidth > 0) {
+                resizeImageBase64(successCallback, errorCallback, picture, options.targetWidth, options.targetHeight);
+            } else {
+                fileIO.readBufferAsync(picture).done(function(buffer) {
+                    var strBase64 = encodeToBase64String(buffer);
+                    picture.deleteAsync().done(function() {
+                        successCallback(strBase64);
+                    }, function(err) {
+                        errorCallback(err);
+                    });
+                }, errorCallback);
+            }
+        }
+    };
+
+    if (!options.saveToPhotoAlbum) {
+        success(picture);
+        return;
+    } else {
+        var savePicker = new Windows.Storage.Pickers.FileSavePicker();
+        var saveFile = function(file) {
+            if (file) {
+                // Prevent updates to the remote version of the file until we're done
+                Windows.Storage.CachedFileManager.deferUpdates(file);
+                picture.moveAndReplaceAsync(file)
+                    .then(function() {
+                        // Let Windows know that we're finished changing the file so
+                        // the other app can update the remote version of the file.
+                        return Windows.Storage.CachedFileManager.completeUpdatesAsync(file);
+                    })
+                    .done(function(updateStatus) {
+                        if (updateStatus === Windows.Storage.Provider.FileUpdateStatus.complete) {
+                            success(picture);
+                        } else {
+                            errorCallback("File update status is not complete.");
+                        }
+                    }, errorCallback);
+            } else {
+                errorCallback("Failed to select a file.");
+            }
+        };
+        savePicker.suggestedStartLocation = pickerLocId.picturesLibrary;
+
+        if (options.encodingType === Camera.EncodingType.PNG) {
+            savePicker.fileTypeChoices.insert("PNG", [".png"]);
+            savePicker.suggestedFileName = "photo.png";
+        } else {
+            savePicker.fileTypeChoices.insert("JPEG", [".jpg"]);
+            savePicker.suggestedFileName = "photo.jpg";
+        }
+
+        // If Windows Phone 8.1 use pickSaveFileAndContinue()
+        if (navigator.appVersion.indexOf('Windows Phone 8.1') >= 0) {
+            /*
+                Need to add and remove an event listener to catch activation state
+                Using FileSavePicker will suspend the app and it's required to catch the pickSaveFileContinuation
+                https://msdn.microsoft.com/en-us/library/windows/apps/xaml/dn631755.aspx
+            */
+            var fileSaveHandler = function(eventArgs) {
+                if (eventArgs.kind === Windows.ApplicationModel.Activation.ActivationKind.pickSaveFileContinuation) {
+                    var file = eventArgs.file;
+                    saveFile(file);
+                    webUIApp.removeEventListener("activated", fileSaveHandler);
+                }
+            };
+            webUIApp.addEventListener("activated", fileSaveHandler);
+            savePicker.pickSaveFileAndContinue();
+        } else {
+            savePicker.pickSaveFileAsync()
+                .done(saveFile, errorCallback);
+        }
+    }
+}
+
+require("cordova/exec/proxy").add("Camera",module.exports);

+ 534 - 0
miaomiao/plugins/cordova-plugin-camera/src/wp/Camera.cs

xqd
@@ -0,0 +1,534 @@
+/*  
+	Licensed under the Apache License, Version 2.0 (the "License");
+	you may not use this file except in compliance with the License.
+	You may obtain a copy of the License at
+	
+	http://www.apache.org/licenses/LICENSE-2.0
+	
+	Unless required by applicable law or agreed to in writing, software
+	distributed under the License is distributed on an "AS IS" BASIS,
+	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	See the License for the specific language governing permissions and
+	limitations under the License.
+*/
+
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Collections.Generic;
+using Microsoft.Phone.Tasks;
+using System.Runtime.Serialization;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Windows.Media.Imaging;
+using Microsoft.Phone;
+using Microsoft.Xna.Framework.Media;
+using System.Diagnostics;
+
+namespace WPCordovaClassLib.Cordova.Commands
+{
+    public class Camera : BaseCommand
+    {
+
+        /// <summary>
+        /// Return base64 encoded string
+        /// </summary>
+        private const int DATA_URL = 0;
+
+        /// <summary>
+        /// Return file uri
+        /// </summary>
+        private const int FILE_URI = 1;
+
+        /// <summary>
+        /// Return native uri
+        /// </summary>
+        private const int NATIVE_URI = 2;
+
+        /// <summary>
+        /// Choose image from picture library
+        /// </summary>
+        private const int PHOTOLIBRARY = 0;
+
+        /// <summary>
+        /// Take picture from camera
+        /// </summary>
+
+        private const int CAMERA = 1;
+
+        /// <summary>
+        /// Choose image from picture library
+        /// </summary>
+        private const int SAVEDPHOTOALBUM = 2;
+
+        /// <summary>
+        /// Take a picture of type JPEG
+        /// </summary>
+        private const int JPEG = 0;
+
+        /// <summary>
+        /// Take a picture of type PNG
+        /// </summary>
+        private const int PNG = 1;
+
+        /// <summary>
+        /// Folder to store captured images
+        /// </summary>
+        private const string isoFolder = "CapturedImagesCache";
+
+        /// <summary>
+        /// Represents captureImage action options.
+        /// </summary>
+        [DataContract]
+        public class CameraOptions
+        {
+            /// <summary>
+            /// Source to getPicture from.
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "sourceType")]
+            public int PictureSourceType { get; set; }
+
+            /// <summary>
+            /// Format of image that returned from getPicture.
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "destinationType")]
+            public int DestinationType { get; set; }
+
+            /// <summary>
+            /// Quality of saved image
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "quality")]
+            public int Quality { get; set; }
+
+            /// <summary>
+            /// Controls whether or not the image is also added to the device photo album.
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "saveToPhotoAlbum")]
+            public bool SaveToPhotoAlbum { get; set; }
+
+            /// <summary>
+            /// Ignored
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "correctOrientation")]
+            public bool CorrectOrientation { get; set; }
+
+            /// <summary>
+            /// Ignored
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "allowEdit")]
+            public bool AllowEdit { get; set; }
+
+                        /// <summary>
+            /// Height in pixels to scale image
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "encodingType")]
+            public int EncodingType { get; set; }
+
+                        /// <summary>
+            /// Height in pixels to scale image
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "mediaType")]
+            public int MediaType { get; set; }
+
+
+            /// <summary>
+            /// Height in pixels to scale image
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "targetHeight")]
+            public int TargetHeight { get; set; }
+
+
+            /// <summary>
+            /// Width in pixels to scale image
+            /// </summary>
+            [DataMember(IsRequired = false, Name = "targetWidth")]
+            public int TargetWidth { get; set; }
+
+            /// <summary>
+            /// Creates options object with default parameters
+            /// </summary>
+            public CameraOptions()
+            {
+                this.SetDefaultValues(new StreamingContext());
+            }
+
+            /// <summary>
+            /// Initializes default values for class fields.
+            /// Implemented in separate method because default constructor is not invoked during deserialization.
+            /// </summary>
+            /// <param name="context"></param>
+            [OnDeserializing()]
+            public void SetDefaultValues(StreamingContext context)
+            {
+                PictureSourceType = CAMERA;
+                DestinationType = FILE_URI;
+                Quality = 80;
+                TargetHeight = -1;
+                TargetWidth = -1;
+                SaveToPhotoAlbum = false;
+                CorrectOrientation = true;
+                AllowEdit = false;
+                MediaType = -1;
+                EncodingType = -1;
+            }
+        }
+
+        /// <summary>
+        /// Camera options
+        /// </summary>
+        CameraOptions cameraOptions;
+
+        public void takePicture(string options)
+        {
+            try
+            {
+                string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
+                // ["quality", "destinationType", "sourceType", "targetWidth", "targetHeight", "encodingType",
+                //     "mediaType", "allowEdit", "correctOrientation", "saveToPhotoAlbum" ]
+                cameraOptions = new CameraOptions();
+                cameraOptions.Quality = int.Parse(args[0]);
+                cameraOptions.DestinationType = int.Parse(args[1]);
+                cameraOptions.PictureSourceType = int.Parse(args[2]);
+                cameraOptions.TargetWidth = int.Parse(args[3]);
+                cameraOptions.TargetHeight = int.Parse(args[4]);
+                cameraOptions.EncodingType = int.Parse(args[5]);
+                cameraOptions.MediaType = int.Parse(args[6]);
+                cameraOptions.AllowEdit = bool.Parse(args[7]);
+                cameraOptions.CorrectOrientation = bool.Parse(args[8]);
+                cameraOptions.SaveToPhotoAlbum = bool.Parse(args[9]);
+
+                // a very large number will force the other value to be the bound
+                if (cameraOptions.TargetWidth > -1 && cameraOptions.TargetHeight == -1)
+                {
+                    cameraOptions.TargetHeight = 100000;   
+                }
+                else if (cameraOptions.TargetHeight > -1 && cameraOptions.TargetWidth == -1)
+                {
+                    cameraOptions.TargetWidth = 100000;
+                }
+            }
+            catch (Exception ex)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
+                return;
+            }
+
+            // Api supports FILE_URI, DATA_URL, NATIVE_URI destination types.
+            // Treat all other destination types as an error.
+            switch (cameraOptions.DestinationType)
+            {
+                case Camera.FILE_URI:
+                case Camera.DATA_URL:
+                case Camera.NATIVE_URI:
+                    break;
+                default:
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Incorrect option: destinationType"));
+                    return;
+            }
+
+            ChooserBase<PhotoResult> chooserTask = null;
+            if (cameraOptions.PictureSourceType == CAMERA)
+            {
+                chooserTask = new CameraCaptureTask();
+            }
+            else if ((cameraOptions.PictureSourceType == PHOTOLIBRARY) || (cameraOptions.PictureSourceType == SAVEDPHOTOALBUM))
+            {
+                chooserTask = new PhotoChooserTask();
+            }
+            // if chooserTask is still null, then PictureSourceType was invalid
+            if (chooserTask != null)
+            {
+                chooserTask.Completed += onTaskCompleted;
+                chooserTask.Show();
+            }
+            else
+            {
+                Debug.WriteLine("Unrecognized PictureSourceType :: " + cameraOptions.PictureSourceType.ToString());
+                DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
+            }
+        }
+
+        public void onTaskCompleted(object sender, PhotoResult e)
+        {
+            var task = sender as ChooserBase<PhotoResult>;
+            if (task != null)
+            {
+                task.Completed -= onTaskCompleted;
+            }
+
+            if (e.Error != null)
+            {
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR));
+                return;
+            }
+
+            switch (e.TaskResult)
+            {
+                case TaskResult.OK:
+                    try
+                    {
+                        string imagePathOrContent = string.Empty;
+
+                        // Save image back to media library
+                        // only save to photoalbum if it didn't come from there ...
+                        if (cameraOptions.PictureSourceType == CAMERA && cameraOptions.SaveToPhotoAlbum)
+                        {
+                            MediaLibrary library = new MediaLibrary();
+                            Picture pict = library.SavePicture(e.OriginalFileName, e.ChosenPhoto); // to save to photo-roll ...
+                        }
+
+                        int newAngle = 0;
+                        // There's bug in Windows Phone 8.1 causing Seek on a DssPhotoStream not working properly.
+                        // https://connect.microsoft.com/VisualStudio/feedback/details/783252
+                        // But a mis-oriented file is better than nothing, so try and catch.
+                        try {
+                            int orient = ImageExifHelper.getImageOrientationFromStream(e.ChosenPhoto);
+                            switch (orient) {
+                                case ImageExifOrientation.LandscapeLeft:
+                                    newAngle = 90;
+                                    break;
+                                case ImageExifOrientation.PortraitUpsideDown:
+                                    newAngle = 180;
+                                    break;
+                                case ImageExifOrientation.LandscapeRight:
+                                    newAngle = 270;
+                                    break;
+                                case ImageExifOrientation.Portrait:
+                                default: break; // 0 default already set
+                            }
+                        } catch {
+                            Debug.WriteLine("Error fetching orientation from Exif");
+                        }
+
+                        if (newAngle != 0)
+                        {
+                            using (Stream rotImageStream = ImageExifHelper.RotateStream(e.ChosenPhoto, newAngle))
+                            {
+                                // we should reset stream position after saving stream to media library
+                                rotImageStream.Seek(0, SeekOrigin.Begin);
+                                if (cameraOptions.DestinationType == DATA_URL)
+                                {
+                                    imagePathOrContent = GetImageContent(rotImageStream);
+                                }
+                                else   // FILE_URL or NATIVE_URI (both use the same resultant uri format)
+                                {
+                                    imagePathOrContent = SaveImageToLocalStorage(rotImageStream, Path.GetFileName(e.OriginalFileName));
+                                }
+                            }
+                        }
+                        else   // no need to reorient
+                        {
+                            if (cameraOptions.DestinationType == DATA_URL)
+                            {
+                                imagePathOrContent = GetImageContent(e.ChosenPhoto);
+                            }
+                            else  // FILE_URL or NATIVE_URI (both use the same resultant uri format)
+                            {
+                                imagePathOrContent = SaveImageToLocalStorage(e.ChosenPhoto, Path.GetFileName(e.OriginalFileName));
+                            }
+                        }
+
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.OK, imagePathOrContent));
+                    }
+                    catch (Exception)
+                    {
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Error retrieving image."));
+                    }
+                    break;
+                case TaskResult.Cancel:
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection cancelled."));
+                    break;
+                default:
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection did not complete!"));
+                    break;
+            }
+        }
+     
+        /// <summary>
+        /// Returns image content in a form of base64 string
+        /// </summary>
+        /// <param name="stream">Image stream</param>
+        /// <returns>Base64 representation of the image</returns>
+        private string GetImageContent(Stream stream)
+        {
+            byte[] imageContent = null;
+
+            try
+            {
+                // Resize photo and convert to JPEG
+                imageContent = ResizePhoto(stream);
+            }
+            finally
+            {
+                stream.Dispose();
+            }
+
+            return Convert.ToBase64String(imageContent);
+        }
+
+        /// <summary>
+        /// Resize image
+        /// </summary>
+        /// <param name="stream">Image stream</param>
+        /// <returns>resized image</returns>
+        private byte[] ResizePhoto(Stream stream)
+        {
+            //output
+            byte[] resizedFile;
+
+            BitmapImage objBitmap = new BitmapImage();
+            objBitmap.SetSource(stream);
+            objBitmap.CreateOptions = BitmapCreateOptions.None;
+
+            WriteableBitmap objWB = new WriteableBitmap(objBitmap);
+            objBitmap.UriSource = null;
+
+            // Calculate resultant image size
+            int width, height;
+            if (cameraOptions.TargetWidth >= 0 && cameraOptions.TargetHeight >= 0)
+            {
+                // Keep proportionally
+                double ratio = Math.Min(
+                    (double)cameraOptions.TargetWidth / objWB.PixelWidth,
+                    (double)cameraOptions.TargetHeight / objWB.PixelHeight);
+                width = Convert.ToInt32(ratio * objWB.PixelWidth);
+                height = Convert.ToInt32(ratio * objWB.PixelHeight);
+            }
+            else
+            {
+                width = objWB.PixelWidth;
+                height = objWB.PixelHeight;
+            }
+
+            //Hold the result stream
+            using (MemoryStream objBitmapStreamResized = new MemoryStream())
+            {
+
+                try
+                {
+                    // resize the photo with user defined TargetWidth & TargetHeight
+                    Extensions.SaveJpeg(objWB, objBitmapStreamResized, width, height, 0, cameraOptions.Quality);
+                }
+                finally
+                {
+                    //Dispose bitmaps immediately, they are memory expensive
+                    DisposeImage(objBitmap);
+                    DisposeImage(objWB);
+                    GC.Collect();
+                }
+
+                //Convert the resized stream to a byte array. 
+                int streamLength = (int)objBitmapStreamResized.Length;
+                resizedFile = new Byte[streamLength]; //-1 
+                objBitmapStreamResized.Position = 0;
+
+                //for some reason we have to set Position to zero, but we don't have to earlier when we get the bytes from the chosen photo... 
+                objBitmapStreamResized.Read(resizedFile, 0, streamLength);
+            }
+
+            return resizedFile;
+        }
+
+        /// <summary>
+        /// Util: Dispose a bitmap resource
+        /// </summary>
+        /// <param name="image">BitmapSource subclass to dispose</param>
+        private void DisposeImage(BitmapSource image)
+        {
+            if (image != null)
+            {
+                try
+                {
+                    using (var ms = new MemoryStream(new byte[] { 0x0 }))
+                    {
+                        image.SetSource(ms);
+                    }
+                }
+                catch (Exception)
+                {
+                }
+            }
+        }
+
+        /// <summary>
+        /// Saves captured image in isolated storage
+        /// </summary>
+        /// <param name="imageFileName">image file name</param>
+        /// <returns>Image path</returns>
+        private string SaveImageToLocalStorage(Stream stream, string imageFileName)
+        {
+
+            if (stream == null)
+            {
+                throw new ArgumentNullException("imageBytes");
+            }
+            try
+            {
+                var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
+
+                if (!isoFile.DirectoryExists(isoFolder))
+                {
+                    isoFile.CreateDirectory(isoFolder);
+                }
+
+                string filePath = System.IO.Path.Combine("///" + isoFolder + "/", imageFileName);
+
+                using (IsolatedStorageFileStream outputStream = isoFile.CreateFile(filePath))
+                {
+                    BitmapImage objBitmap = new BitmapImage();
+                    objBitmap.SetSource(stream);
+                    objBitmap.CreateOptions = BitmapCreateOptions.None;
+
+                    WriteableBitmap objWB = new WriteableBitmap(objBitmap);
+                    objBitmap.UriSource = null;
+
+                    try
+                    {
+
+                        //use photo's actual width & height if user doesn't provide width & height
+                        if (cameraOptions.TargetWidth < 0 && cameraOptions.TargetHeight < 0)
+                        {
+                            objWB.SaveJpeg(outputStream, objWB.PixelWidth, objWB.PixelHeight, 0, cameraOptions.Quality);
+                        }
+                        else
+                        {
+                            //Resize
+                            //Keep proportionally
+                            double ratio = Math.Min((double)cameraOptions.TargetWidth / objWB.PixelWidth, (double)cameraOptions.TargetHeight / objWB.PixelHeight);
+                            int width = Convert.ToInt32(ratio * objWB.PixelWidth);
+                            int height = Convert.ToInt32(ratio * objWB.PixelHeight);
+
+                            // resize the photo with user defined TargetWidth & TargetHeight
+                            objWB.SaveJpeg(outputStream, width, height, 0, cameraOptions.Quality);
+                        }
+                    }
+                    finally
+                    {
+                        //Dispose bitmaps immediately, they are memory expensive
+                        DisposeImage(objBitmap);
+                        DisposeImage(objWB);
+                        GC.Collect();
+                    }
+                }
+
+                return new Uri(filePath, UriKind.Relative).ToString();
+            }
+            catch (Exception)
+            {
+                //TODO: log or do something else
+                throw;
+            }
+            finally
+            {
+                stream.Dispose();
+            }
+        }
+
+    }
+}

+ 1 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/.npmignore

xqd
@@ -0,0 +1 @@
+node_modules

+ 7 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest.xcworkspace/contents.xcworkspacedata

xqd
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "container:CDVCameraTest/CDVCameraTest.xcodeproj">
+   </FileRef>
+</Workspace>

+ 41 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest.xcworkspace/xcshareddata/CDVCameraTest.xccheckout

xqd
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDESourceControlProjectFavoriteDictionaryKey</key>
+	<false/>
+	<key>IDESourceControlProjectIdentifier</key>
+	<string>6BE9AD73-1B9F-4362-98D7-DC631BEC6185</string>
+	<key>IDESourceControlProjectName</key>
+	<string>CDVCameraTest</string>
+	<key>IDESourceControlProjectOriginsDictionary</key>
+	<dict>
+		<key>729B5706E7BAF4E9EE7AEE3C003A08107411AB7C</key>
+		<string>github.com:shazron/cordova-plugin-camera.git</string>
+	</dict>
+	<key>IDESourceControlProjectPath</key>
+	<string>tests/ios/CDVCameraTest.xcworkspace</string>
+	<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
+	<dict>
+		<key>729B5706E7BAF4E9EE7AEE3C003A08107411AB7C</key>
+		<string>../../..</string>
+	</dict>
+	<key>IDESourceControlProjectURL</key>
+	<string>github.com:shazron/cordova-plugin-camera.git</string>
+	<key>IDESourceControlProjectVersion</key>
+	<integer>111</integer>
+	<key>IDESourceControlProjectWCCIdentifier</key>
+	<string>729B5706E7BAF4E9EE7AEE3C003A08107411AB7C</string>
+	<key>IDESourceControlProjectWCConfigurations</key>
+	<array>
+		<dict>
+			<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
+			<string>public.vcs.git</string>
+			<key>IDESourceControlWCCIdentifierKey</key>
+			<string>729B5706E7BAF4E9EE7AEE3C003A08107411AB7C</string>
+			<key>IDESourceControlWCCName</key>
+			<string>cordova-plugin-camera</string>
+		</dict>
+	</array>
+</dict>
+</plist>

+ 77 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest.xcworkspace/xcshareddata/xcschemes/CordovaLib.xcscheme

xqd
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0610"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "D2AAC07D0554694100DB518D"
+               BuildableName = "libCordova.a"
+               BlueprintName = "CordovaLib"
+               ReferencedContainer = "container:node_modules/cordova-ios/CordovaLib/CordovaLib.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "D2AAC07D0554694100DB518D"
+            BuildableName = "libCordova.a"
+            BlueprintName = "CordovaLib"
+            ReferencedContainer = "container:node_modules/cordova-ios/CordovaLib/CordovaLib.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "D2AAC07D0554694100DB518D"
+            BuildableName = "libCordova.a"
+            BlueprintName = "CordovaLib"
+            ReferencedContainer = "container:node_modules/cordova-ios/CordovaLib/CordovaLib.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 511 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraLibTests/CameraTest.m

xqd
@@ -0,0 +1,511 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+#import "CDVCamera.h"
+#import "UIImage+CropScaleOrientation.h"
+#import <MobileCoreServices/UTCoreTypes.h>
+
+
+@interface CameraTest : XCTestCase
+
+@property (nonatomic, strong) CDVCamera* plugin;
+
+@end
+
+@interface CDVCamera ()
+
+// expose private interface
+- (NSData*)processImage:(UIImage*)image info:(NSDictionary*)info options:(CDVPictureOptions*)options;
+- (UIImage*)retrieveImage:(NSDictionary*)info options:(CDVPictureOptions*)options;
+- (CDVPluginResult*)resultForImage:(CDVPictureOptions*)options info:(NSDictionary*)info;
+- (CDVPluginResult*)resultForVideo:(NSDictionary*)info;
+
+@end
+
+@implementation CameraTest
+
+- (void)setUp {
+    [super setUp];
+    // Put setup code here. This method is called before the invocation of each test method in the class.
+    
+    self.plugin = [[CDVCamera alloc] init];
+}
+
+- (void)tearDown {
+    // Put teardown code here. This method is called after the invocation of each test method in the class.
+    [super tearDown];
+}
+
+- (void) testPictureOptionsCreate
+{
+    NSArray* args;
+    CDVPictureOptions* options;
+    NSDictionary* popoverOptions;
+    
+    // No arguments, check whether the defaults are set
+    args = @[];
+    CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
+    
+    options = [CDVPictureOptions createFromTakePictureArguments:command];
+    
+    XCTAssertEqual([options.quality intValue], 50);
+    XCTAssertEqual(options.destinationType, (int)DestinationTypeFileUri);
+    XCTAssertEqual(options.sourceType, (int)UIImagePickerControllerSourceTypeCamera);
+    XCTAssertEqual(options.targetSize.width, 0);
+    XCTAssertEqual(options.targetSize.height, 0);
+    XCTAssertEqual(options.encodingType, (int)EncodingTypeJPEG);
+    XCTAssertEqual(options.mediaType, (int)MediaTypePicture);
+    XCTAssertEqual(options.allowsEditing, NO);
+    XCTAssertEqual(options.correctOrientation, NO);
+    XCTAssertEqual(options.saveToPhotoAlbum, NO);
+    XCTAssertEqualObjects(options.popoverOptions, nil);
+    XCTAssertEqual(options.cameraDirection, (int)UIImagePickerControllerCameraDeviceRear);
+    XCTAssertEqual(options.popoverSupported, NO);
+    XCTAssertEqual(options.usesGeolocation, NO);
+    
+    // Set each argument, check whether they are set. different from defaults
+    popoverOptions = @{ @"x" : @1, @"y" : @2, @"width" : @3, @"height" : @4 };
+    
+    args = @[
+             @(49),
+             @(DestinationTypeDataUrl),
+             @(UIImagePickerControllerSourceTypePhotoLibrary),
+             @(120),
+             @(240),
+             @(EncodingTypePNG),
+             @(MediaTypeVideo),
+             @YES,
+             @YES,
+             @YES,
+             popoverOptions,
+             @(UIImagePickerControllerCameraDeviceFront),
+             ];
+    
+    command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
+    options = [CDVPictureOptions createFromTakePictureArguments:command];
+    
+    XCTAssertEqual([options.quality intValue], 49);
+    XCTAssertEqual(options.destinationType, (int)DestinationTypeDataUrl);
+    XCTAssertEqual(options.sourceType, (int)UIImagePickerControllerSourceTypePhotoLibrary);
+    XCTAssertEqual(options.targetSize.width, 120);
+    XCTAssertEqual(options.targetSize.height, 240);
+    XCTAssertEqual(options.encodingType, (int)EncodingTypePNG);
+    XCTAssertEqual(options.mediaType, (int)MediaTypeVideo);
+    XCTAssertEqual(options.allowsEditing, YES);
+    XCTAssertEqual(options.correctOrientation, YES);
+    XCTAssertEqual(options.saveToPhotoAlbum, YES);
+    XCTAssertEqualObjects(options.popoverOptions, popoverOptions);
+    XCTAssertEqual(options.cameraDirection, (int)UIImagePickerControllerCameraDeviceFront);
+    XCTAssertEqual(options.popoverSupported, NO);
+    XCTAssertEqual(options.usesGeolocation, NO);
+}
+
+- (void) testCameraPickerCreate
+{
+    NSDictionary* popoverOptions;
+    NSArray* args;
+    CDVPictureOptions* pictureOptions;
+    CDVCameraPicker* picker;
+    
+    // Souce is Camera, and image type
+    
+    popoverOptions = @{ @"x" : @1, @"y" : @2, @"width" : @3, @"height" : @4 };
+    args = @[
+             @(49),
+             @(DestinationTypeDataUrl),
+             @(UIImagePickerControllerSourceTypeCamera),
+             @(120),
+             @(240),
+             @(EncodingTypePNG),
+             @(MediaTypeAll),
+             @YES,
+             @YES,
+             @YES,
+             popoverOptions,
+             @(UIImagePickerControllerCameraDeviceFront),
+             ];
+    
+    CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
+    pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
+    
+    if ([UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType]) {
+        picker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
+        
+        XCTAssertEqualObjects(picker.pictureOptions, pictureOptions);
+
+        XCTAssertEqual(picker.sourceType, pictureOptions.sourceType);
+        XCTAssertEqual(picker.allowsEditing, pictureOptions.allowsEditing);
+        XCTAssertEqualObjects(picker.mediaTypes, @[(NSString*)kUTTypeImage]);
+        XCTAssertEqual(picker.cameraDevice, pictureOptions.cameraDirection);
+    }
+
+    // Souce is not Camera, and all media types
+
+    args = @[
+          @(49),
+          @(DestinationTypeDataUrl),
+          @(UIImagePickerControllerSourceTypePhotoLibrary),
+          @(120),
+          @(240),
+          @(EncodingTypePNG),
+          @(MediaTypeAll),
+          @YES,
+          @YES,
+          @YES,
+          popoverOptions,
+          @(UIImagePickerControllerCameraDeviceFront),
+          ];
+    
+    command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
+    pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
+
+    if ([UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType]) {
+        picker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
+
+         XCTAssertEqualObjects(picker.pictureOptions, pictureOptions);
+         
+         XCTAssertEqual(picker.sourceType, pictureOptions.sourceType);
+         XCTAssertEqual(picker.allowsEditing, pictureOptions.allowsEditing);
+         XCTAssertEqualObjects(picker.mediaTypes, [UIImagePickerController availableMediaTypesForSourceType:picker.sourceType]);
+    }
+    
+    // Souce is not Camera, and either Image or Movie media type
+
+    args = @[
+             @(49),
+             @(DestinationTypeDataUrl),
+             @(UIImagePickerControllerSourceTypePhotoLibrary),
+             @(120),
+             @(240),
+             @(EncodingTypePNG),
+             @(MediaTypeVideo),
+             @YES,
+             @YES,
+             @YES,
+             popoverOptions,
+             @(UIImagePickerControllerCameraDeviceFront),
+             ];
+    
+    command = [[CDVInvokedUrlCommand alloc] initWithArguments:args callbackId:@"dummy" className:@"myclassname" methodName:@"mymethodname"];
+    pictureOptions = [CDVPictureOptions createFromTakePictureArguments:command];
+    
+    if ([UIImagePickerController isSourceTypeAvailable:pictureOptions.sourceType]) {
+        picker = [CDVCameraPicker createFromPictureOptions:pictureOptions];
+        
+        XCTAssertEqualObjects(picker.pictureOptions, pictureOptions);
+        
+        XCTAssertEqual(picker.sourceType, pictureOptions.sourceType);
+        XCTAssertEqual(picker.allowsEditing, pictureOptions.allowsEditing);
+        XCTAssertEqualObjects(picker.mediaTypes, @[(NSString*)kUTTypeMovie]);
+    }
+}
+
+- (UIImage*) createImage:(CGRect)rect orientation:(UIImageOrientation)imageOrientation {
+    UIGraphicsBeginImageContext(rect.size);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    CGContextSetFillColorWithColor(context, [[UIColor greenColor] CGColor]);
+    CGContextFillRect(context, rect);
+    
+    CGImageRef result = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());
+    UIImage* image = [UIImage imageWithCGImage:result scale:1.0f orientation:imageOrientation];
+    
+    UIGraphicsEndImageContext();
+    
+    return image;
+}
+
+- (void) testImageScaleCropForSize {
+    
+    UIImage *sourceImagePortrait, *sourceImageLandscape, *targetImage;
+    CGSize targetSize = CGSizeZero;
+    
+    sourceImagePortrait = [self createImage:CGRectMake(0, 0, 2448, 3264) orientation:UIImageOrientationUp];
+    sourceImageLandscape = [self createImage:CGRectMake(0, 0, 3264, 2448) orientation:UIImageOrientationUp];
+    
+    // test 640x480
+    
+    targetSize = CGSizeMake(640, 480);
+
+    targetImage = [sourceImagePortrait imageByScalingAndCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+
+    targetImage = [sourceImageLandscape imageByScalingAndCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+
+
+    // test 800x600
+    
+    targetSize = CGSizeMake(800, 600);
+    
+    targetImage = [sourceImagePortrait imageByScalingAndCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    
+    targetImage = [sourceImageLandscape imageByScalingAndCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    
+    // test 1024x768
+    
+    targetSize = CGSizeMake(1024, 768);
+    
+    targetImage = [sourceImagePortrait imageByScalingAndCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+
+    targetImage = [sourceImageLandscape imageByScalingAndCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+}
+
+- (void) testImageScaleNoCropForSize {
+    UIImage *sourceImagePortrait, *sourceImageLandscape, *targetImage;
+    CGSize targetSize = CGSizeZero;
+    
+    sourceImagePortrait = [self createImage:CGRectMake(0, 0, 2448, 3264) orientation:UIImageOrientationUp];
+    sourceImageLandscape = [self createImage:CGRectMake(0, 0, 3264, 2448) orientation:UIImageOrientationUp];
+    
+    // test 640x480
+    
+    targetSize = CGSizeMake(480, 640);
+    
+    targetImage = [sourceImagePortrait imageByScalingNotCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+
+    targetSize = CGSizeMake(640, 480);
+
+    targetImage = [sourceImageLandscape imageByScalingNotCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    
+    
+    // test 800x600
+    
+    targetSize = CGSizeMake(600, 800);
+    
+    targetImage = [sourceImagePortrait imageByScalingNotCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    
+    targetSize = CGSizeMake(800, 600);
+
+    targetImage = [sourceImageLandscape imageByScalingNotCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    
+    // test 1024x768
+    
+    targetSize = CGSizeMake(768, 1024);
+    
+    targetImage = [sourceImagePortrait imageByScalingNotCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    
+    targetSize = CGSizeMake(1024, 768);
+
+    targetImage = [sourceImageLandscape imageByScalingNotCroppingForSize:targetSize];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+}
+
+- (void) testImageCorrectedForOrientation {
+    UIImage *sourceImagePortrait, *sourceImageLandscape, *targetImage;
+    CGSize targetSize = CGSizeZero;
+    
+    sourceImagePortrait = [self createImage:CGRectMake(0, 0, 2448, 3264) orientation:UIImageOrientationDown];
+    sourceImageLandscape = [self createImage:CGRectMake(0, 0, 3264, 2448) orientation:UIImageOrientationDown];
+    
+    // PORTRAIT - image size should be unchanged
+
+    targetSize = CGSizeMake(2448, 3264);
+    
+    targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationUp];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
+
+    targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationDown];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
+
+    targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationRight];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
+
+    targetImage = [sourceImagePortrait imageCorrectedForCaptureOrientation:UIImageOrientationLeft];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    XCTAssertEqual(targetImage.imageOrientation, UIImageOrientationUp);
+
+    // LANDSCAPE - image size should be unchanged
+    
+    targetSize = CGSizeMake(3264, 2448);
+    
+    targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationUp];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+
+    targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationDown];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+
+    targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationRight];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+    
+    targetImage = [sourceImageLandscape imageCorrectedForCaptureOrientation:UIImageOrientationLeft];
+    XCTAssertEqual(targetImage.size.width, targetSize.width);
+    XCTAssertEqual(targetImage.size.height, targetSize.height);
+}
+
+
+- (void) testRetrieveImage
+{
+    CDVPictureOptions* pictureOptions = [[CDVPictureOptions alloc] init];
+    NSDictionary *infoDict1, *infoDict2;
+    UIImage* resultImage;
+    
+    UIImage* originalImage = [self createImage:CGRectMake(0, 0, 1024, 768) orientation:UIImageOrientationDown];
+    UIImage* originalCorrectedForOrientation = [originalImage imageCorrectedForCaptureOrientation];
+
+    UIImage* editedImage = [self createImage:CGRectMake(0, 0, 800, 600) orientation:UIImageOrientationDown];
+    UIImage* scaledImageWithCrop = [originalImage imageByScalingAndCroppingForSize:CGSizeMake(640, 480)];
+    UIImage* scaledImageNoCrop = [originalImage imageByScalingNotCroppingForSize:CGSizeMake(640, 480)];
+    
+    infoDict1 = @{
+                  UIImagePickerControllerOriginalImage : originalImage
+                  };
+    
+    infoDict2 = @{
+                   UIImagePickerControllerOriginalImage : originalImage,
+                   UIImagePickerControllerEditedImage : editedImage
+                };
+    
+    // Original with no options
+    
+    pictureOptions.allowsEditing = YES;
+    pictureOptions.targetSize = CGSizeZero;
+    pictureOptions.cropToSize = NO;
+    pictureOptions.correctOrientation = NO;
+    
+    resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
+    XCTAssertEqualObjects(resultImage, originalImage);
+    
+    // Original with no options
+    
+    pictureOptions.allowsEditing = YES;
+    pictureOptions.targetSize = CGSizeZero;
+    pictureOptions.cropToSize = NO;
+    pictureOptions.correctOrientation = NO;
+    
+    resultImage = [self.plugin retrieveImage:infoDict2 options:pictureOptions];
+    XCTAssertEqualObjects(resultImage, editedImage);
+
+    // Original with corrected orientation
+    
+    pictureOptions.allowsEditing = YES;
+    pictureOptions.targetSize = CGSizeZero;
+    pictureOptions.cropToSize = NO;
+    pictureOptions.correctOrientation = YES;
+    
+    resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
+    XCTAssertNotEqual(resultImage.imageOrientation, originalImage.imageOrientation);
+    XCTAssertEqual(resultImage.imageOrientation, originalCorrectedForOrientation.imageOrientation);
+    XCTAssertEqual(resultImage.size.width, originalCorrectedForOrientation.size.width);
+    XCTAssertEqual(resultImage.size.height, originalCorrectedForOrientation.size.height);
+
+    // Original with targetSize, no crop
+    
+    pictureOptions.allowsEditing = YES;
+    pictureOptions.targetSize = CGSizeMake(640, 480);
+    pictureOptions.cropToSize = NO;
+    pictureOptions.correctOrientation = NO;
+    
+    resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
+    XCTAssertEqual(resultImage.size.width, scaledImageNoCrop.size.width);
+    XCTAssertEqual(resultImage.size.height, scaledImageNoCrop.size.height);
+
+    // Original with targetSize, plus crop
+    
+    pictureOptions.allowsEditing = YES;
+    pictureOptions.targetSize = CGSizeMake(640, 480);
+    pictureOptions.cropToSize = YES;
+    pictureOptions.correctOrientation = NO;
+    
+    resultImage = [self.plugin retrieveImage:infoDict1 options:pictureOptions];
+    XCTAssertEqual(resultImage.size.width, scaledImageWithCrop.size.width);
+    XCTAssertEqual(resultImage.size.height, scaledImageWithCrop.size.height);
+}
+
+- (void) testProcessImage
+{
+    CDVPictureOptions* pictureOptions = [[CDVPictureOptions alloc] init];
+    NSData* resultData;
+    
+    UIImage* originalImage = [self createImage:CGRectMake(0, 0, 1024, 768) orientation:UIImageOrientationDown];
+    NSData* originalImageDataPNG = UIImagePNGRepresentation(originalImage);
+    NSData* originalImageDataJPEG = UIImageJPEGRepresentation(originalImage, 1.0);
+    
+    // Original, PNG
+    
+    pictureOptions.allowsEditing = YES;
+    pictureOptions.targetSize = CGSizeZero;
+    pictureOptions.cropToSize = NO;
+    pictureOptions.correctOrientation = NO;
+    pictureOptions.encodingType = EncodingTypePNG;
+    
+    resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
+    XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataPNG base64EncodedStringWithOptions:0]);
+
+    // Original, JPEG, full quality
+    
+    pictureOptions.allowsEditing = NO;
+    pictureOptions.targetSize = CGSizeZero;
+    pictureOptions.cropToSize = NO;
+    pictureOptions.correctOrientation = NO;
+    pictureOptions.encodingType = EncodingTypeJPEG;
+    
+    resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
+    XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataJPEG base64EncodedStringWithOptions:0]);
+    
+    // Original, JPEG, with quality value
+    
+    pictureOptions.allowsEditing = YES;
+    pictureOptions.targetSize = CGSizeZero;
+    pictureOptions.cropToSize = NO;
+    pictureOptions.correctOrientation = NO;
+    pictureOptions.encodingType = EncodingTypeJPEG;
+    pictureOptions.quality = @(57);
+    
+    NSData* originalImageDataJPEGWithQuality = UIImageJPEGRepresentation(originalImage, [pictureOptions.quality floatValue]/ 100.f);
+    resultData = [self.plugin processImage:originalImage info:@{} options:pictureOptions];
+    XCTAssertEqualObjects([resultData base64EncodedStringWithOptions:0], [originalImageDataJPEGWithQuality base64EncodedStringWithOptions:0]);
+    
+    // TODO: usesGeolocation is not tested
+}
+
+@end

+ 44 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraLibTests/Info.plist

xqd
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+#
+# 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.
+#
+-->
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.apache.cordova.$(PRODUCT_NAME:rfc1034identifier)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>

+ 561 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.pbxproj

xqd
@@ -0,0 +1,561 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		30486FEB1A40DC350065C233 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FEA1A40DC350065C233 /* UIKit.framework */; };
+		30486FED1A40DC3B0065C233 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FEC1A40DC3A0065C233 /* Foundation.framework */; };
+		30486FF91A40DCC70065C233 /* CDVCamera.m in Sources */ = {isa = PBXBuildFile; fileRef = 30486FF31A40DCC70065C233 /* CDVCamera.m */; };
+		30486FFA1A40DCC70065C233 /* CDVJpegHeaderWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 30486FF61A40DCC70065C233 /* CDVJpegHeaderWriter.m */; };
+		30486FFB1A40DCC70065C233 /* UIImage+CropScaleOrientation.m in Sources */ = {isa = PBXBuildFile; fileRef = 30486FF81A40DCC70065C233 /* UIImage+CropScaleOrientation.m */; };
+		304870011A40DD620065C233 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FFE1A40DD180065C233 /* CoreGraphics.framework */; };
+		304870021A40DD860065C233 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FFE1A40DD180065C233 /* CoreGraphics.framework */; };
+		304870031A40DD8C0065C233 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30486FEA1A40DC350065C233 /* UIKit.framework */; };
+		304870051A40DD9A0065C233 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 304870041A40DD9A0065C233 /* MobileCoreServices.framework */; };
+		304870071A40DDAC0065C233 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 304870061A40DDAC0065C233 /* AssetsLibrary.framework */; };
+		304870091A40DDB90065C233 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 304870081A40DDB90065C233 /* CoreLocation.framework */; };
+		3048700B1A40DDF30065C233 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3048700A1A40DDF30065C233 /* ImageIO.framework */; };
+		308F59B11A4228730031A4D4 /* libCordova.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E9F519019DA0F8300DA31AC /* libCordova.a */; };
+		7E9F51B119DA114400DA31AC /* CameraTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E9F51B019DA114400DA31AC /* CameraTest.m */; };
+		7E9F51B919DA1B1600DA31AC /* libCDVCameraLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E9F519519DA102000DA31AC /* libCDVCameraLib.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		30486FFC1A40DCE80065C233 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */;
+			proxyType = 1;
+			remoteGlobalIDString = D2AAC07D0554694100DB518D;
+			remoteInfo = CordovaLib;
+		};
+		7E9F518F19DA0F8300DA31AC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 68A32D7114102E1C006B237C;
+			remoteInfo = CordovaLib;
+		};
+		7E9F51AC19DA10DE00DA31AC /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 7E9F517219DA09CE00DA31AC /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 7E9F519419DA102000DA31AC;
+			remoteInfo = CDVCameraLib;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		7E9F519319DA102000DA31AC /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "include/$(PRODUCT_NAME)";
+			dstSubfolderSpec = 16;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		30486FEA1A40DC350065C233 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+		30486FEC1A40DC3A0065C233 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+		30486FF21A40DCC70065C233 /* CDVCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVCamera.h; sourceTree = "<group>"; };
+		30486FF31A40DCC70065C233 /* CDVCamera.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVCamera.m; sourceTree = "<group>"; };
+		30486FF41A40DCC70065C233 /* CDVExif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVExif.h; sourceTree = "<group>"; };
+		30486FF51A40DCC70065C233 /* CDVJpegHeaderWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVJpegHeaderWriter.h; sourceTree = "<group>"; };
+		30486FF61A40DCC70065C233 /* CDVJpegHeaderWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVJpegHeaderWriter.m; sourceTree = "<group>"; };
+		30486FF71A40DCC70065C233 /* UIImage+CropScaleOrientation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+CropScaleOrientation.h"; sourceTree = "<group>"; };
+		30486FF81A40DCC70065C233 /* UIImage+CropScaleOrientation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+CropScaleOrientation.m"; sourceTree = "<group>"; };
+		30486FFE1A40DD180065C233 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
+		304870041A40DD9A0065C233 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; };
+		304870061A40DDAC0065C233 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/AssetsLibrary.framework; sourceTree = DEVELOPER_DIR; };
+		304870081A40DDB90065C233 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/CoreLocation.framework; sourceTree = DEVELOPER_DIR; };
+		3048700A1A40DDF30065C233 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; };
+		7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = "../node_modules/cordova-ios/CordovaLib/CordovaLib.xcodeproj"; sourceTree = "<group>"; };
+		7E9F519519DA102000DA31AC /* libCDVCameraLib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCDVCameraLib.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		7E9F519F19DA102000DA31AC /* CDVCameraLibTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CDVCameraLibTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		7E9F51A219DA102000DA31AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		7E9F51B019DA114400DA31AC /* CameraTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraTest.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		7E9F519219DA102000DA31AC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				308F59B11A4228730031A4D4 /* libCordova.a in Frameworks */,
+				304870011A40DD620065C233 /* CoreGraphics.framework in Frameworks */,
+				30486FED1A40DC3B0065C233 /* Foundation.framework in Frameworks */,
+				30486FEB1A40DC350065C233 /* UIKit.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7E9F519C19DA102000DA31AC /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3048700B1A40DDF30065C233 /* ImageIO.framework in Frameworks */,
+				304870091A40DDB90065C233 /* CoreLocation.framework in Frameworks */,
+				304870071A40DDAC0065C233 /* AssetsLibrary.framework in Frameworks */,
+				304870051A40DD9A0065C233 /* MobileCoreServices.framework in Frameworks */,
+				304870031A40DD8C0065C233 /* UIKit.framework in Frameworks */,
+				304870021A40DD860065C233 /* CoreGraphics.framework in Frameworks */,
+				7E9F51B919DA1B1600DA31AC /* libCDVCameraLib.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		30486FF11A40DCC70065C233 /* CDVCameraLib */ = {
+			isa = PBXGroup;
+			children = (
+				30486FF21A40DCC70065C233 /* CDVCamera.h */,
+				30486FF31A40DCC70065C233 /* CDVCamera.m */,
+				30486FF41A40DCC70065C233 /* CDVExif.h */,
+				30486FF51A40DCC70065C233 /* CDVJpegHeaderWriter.h */,
+				30486FF61A40DCC70065C233 /* CDVJpegHeaderWriter.m */,
+				30486FF71A40DCC70065C233 /* UIImage+CropScaleOrientation.h */,
+				30486FF81A40DCC70065C233 /* UIImage+CropScaleOrientation.m */,
+			);
+			name = CDVCameraLib;
+			path = ../../../src/ios;
+			sourceTree = "<group>";
+		};
+		308F59B01A4227A60031A4D4 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				3048700A1A40DDF30065C233 /* ImageIO.framework */,
+				304870081A40DDB90065C233 /* CoreLocation.framework */,
+				304870061A40DDAC0065C233 /* AssetsLibrary.framework */,
+				304870041A40DD9A0065C233 /* MobileCoreServices.framework */,
+				30486FFE1A40DD180065C233 /* CoreGraphics.framework */,
+				30486FEC1A40DC3A0065C233 /* Foundation.framework */,
+				30486FEA1A40DC350065C233 /* UIKit.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		7E9F517119DA09CE00DA31AC = {
+			isa = PBXGroup;
+			children = (
+				7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */,
+				308F59B01A4227A60031A4D4 /* Frameworks */,
+				30486FF11A40DCC70065C233 /* CDVCameraLib */,
+				7E9F51A019DA102000DA31AC /* CDVCameraLibTests */,
+				7E9F517D19DA0A0A00DA31AC /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		7E9F517D19DA0A0A00DA31AC /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				7E9F519519DA102000DA31AC /* libCDVCameraLib.a */,
+				7E9F519F19DA102000DA31AC /* CDVCameraLibTests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		7E9F518C19DA0F8300DA31AC /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				7E9F519019DA0F8300DA31AC /* libCordova.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		7E9F51A019DA102000DA31AC /* CDVCameraLibTests */ = {
+			isa = PBXGroup;
+			children = (
+				7E9F51A119DA102000DA31AC /* Supporting Files */,
+				7E9F51B019DA114400DA31AC /* CameraTest.m */,
+			);
+			path = CDVCameraLibTests;
+			sourceTree = "<group>";
+		};
+		7E9F51A119DA102000DA31AC /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				7E9F51A219DA102000DA31AC /* Info.plist */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		7E9F519419DA102000DA31AC /* CDVCameraLib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7E9F51A319DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLib" */;
+			buildPhases = (
+				7E9F519119DA102000DA31AC /* Sources */,
+				7E9F519219DA102000DA31AC /* Frameworks */,
+				7E9F519319DA102000DA31AC /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				30486FFD1A40DCE80065C233 /* PBXTargetDependency */,
+			);
+			name = CDVCameraLib;
+			productName = CDVCameraLib;
+			productReference = 7E9F519519DA102000DA31AC /* libCDVCameraLib.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		7E9F519E19DA102000DA31AC /* CDVCameraLibTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7E9F51A619DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLibTests" */;
+			buildPhases = (
+				7E9F519B19DA102000DA31AC /* Sources */,
+				7E9F519C19DA102000DA31AC /* Frameworks */,
+				7E9F519D19DA102000DA31AC /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				7E9F51AD19DA10DE00DA31AC /* PBXTargetDependency */,
+			);
+			name = CDVCameraLibTests;
+			productName = CDVCameraLibTests;
+			productReference = 7E9F519F19DA102000DA31AC /* CDVCameraLibTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		7E9F517219DA09CE00DA31AC /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0610;
+				TargetAttributes = {
+					7E9F519419DA102000DA31AC = {
+						CreatedOnToolsVersion = 6.0;
+					};
+					7E9F519E19DA102000DA31AC = {
+						CreatedOnToolsVersion = 6.0;
+					};
+				};
+			};
+			buildConfigurationList = 7E9F517519DA09CE00DA31AC /* Build configuration list for PBXProject "CDVCameraTest" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 7E9F517119DA09CE00DA31AC;
+			productRefGroup = 7E9F517D19DA0A0A00DA31AC /* Products */;
+			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = 7E9F518C19DA0F8300DA31AC /* Products */;
+					ProjectRef = 7E9F518B19DA0F8300DA31AC /* CordovaLib.xcodeproj */;
+				},
+			);
+			projectRoot = "";
+			targets = (
+				7E9F519419DA102000DA31AC /* CDVCameraLib */,
+				7E9F519E19DA102000DA31AC /* CDVCameraLibTests */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+		7E9F519019DA0F8300DA31AC /* libCordova.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libCordova.a;
+			remoteRef = 7E9F518F19DA0F8300DA31AC /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+		7E9F519D19DA102000DA31AC /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		7E9F519119DA102000DA31AC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				30486FF91A40DCC70065C233 /* CDVCamera.m in Sources */,
+				30486FFB1A40DCC70065C233 /* UIImage+CropScaleOrientation.m in Sources */,
+				30486FFA1A40DCC70065C233 /* CDVJpegHeaderWriter.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7E9F519B19DA102000DA31AC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7E9F51B119DA114400DA31AC /* CameraTest.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		30486FFD1A40DCE80065C233 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = CordovaLib;
+			targetProxy = 30486FFC1A40DCE80065C233 /* PBXContainerItemProxy */;
+		};
+		7E9F51AD19DA10DE00DA31AC /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 7E9F519419DA102000DA31AC /* CDVCameraLib */;
+			targetProxy = 7E9F51AC19DA10DE00DA31AC /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		7E9F517619DA09CE00DA31AC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ONLY_ACTIVE_ARCH = YES;
+			};
+			name = Debug;
+		};
+		7E9F517719DA09CE00DA31AC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Release;
+		};
+		7E9F51A419DA102000DA31AC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"",
+					"\"$(OBJROOT)/UninstalledProducts/include\"",
+					"\"$(BUILT_PRODUCTS_DIR)\"",
+				);
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		7E9F51A519DA102000DA31AC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = YES;
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"",
+					"\n\"$(OBJROOT)/UninstalledProducts/include\"\n\"$(BUILT_PRODUCTS_DIR)\"",
+				);
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "-ObjC";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		7E9F51A719DA102000DA31AC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(SDKROOT)/Developer/Library/Frameworks",
+					"$(inherited)",
+				);
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				INFOPLIST_FILE = CDVCameraLibTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"-framework",
+					XCTest,
+					"-all_load",
+					"-ObjC",
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		7E9F51A819DA102000DA31AC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = YES;
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(SDKROOT)/Developer/Library/Frameworks",
+					"$(inherited)",
+				);
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				INFOPLIST_FILE = CDVCameraLibTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"-framework",
+					XCTest,
+					"-all_load",
+					"-ObjC",
+				);
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		7E9F517519DA09CE00DA31AC /* Build configuration list for PBXProject "CDVCameraTest" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7E9F517619DA09CE00DA31AC /* Debug */,
+				7E9F517719DA09CE00DA31AC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7E9F51A319DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7E9F51A419DA102000DA31AC /* Debug */,
+				7E9F51A519DA102000DA31AC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7E9F51A619DA102000DA31AC /* Build configuration list for PBXNativeTarget "CDVCameraLibTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7E9F51A719DA102000DA31AC /* Debug */,
+				7E9F51A819DA102000DA31AC /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 7E9F517219DA09CE00DA31AC /* Project object */;
+}

+ 7 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata

xqd
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:CDVCameraTest.xcodeproj">
+   </FileRef>
+</Workspace>

+ 41 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/project.xcworkspace/xcshareddata/CDVCameraTest.xccheckout

xqd
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDESourceControlProjectFavoriteDictionaryKey</key>
+	<false/>
+	<key>IDESourceControlProjectIdentifier</key>
+	<string>6BE9AD73-1B9F-4362-98D7-DC631BEC6185</string>
+	<key>IDESourceControlProjectName</key>
+	<string>CDVCameraTest</string>
+	<key>IDESourceControlProjectOriginsDictionary</key>
+	<dict>
+		<key>BEF5A5D0FF64801E558286389440357A9233D7DB</key>
+		<string>https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git</string>
+	</dict>
+	<key>IDESourceControlProjectPath</key>
+	<string>tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj</string>
+	<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
+	<dict>
+		<key>BEF5A5D0FF64801E558286389440357A9233D7DB</key>
+		<string>../../../../..</string>
+	</dict>
+	<key>IDESourceControlProjectURL</key>
+	<string>https://git-wip-us.apache.org/repos/asf/cordova-plugin-camera.git</string>
+	<key>IDESourceControlProjectVersion</key>
+	<integer>111</integer>
+	<key>IDESourceControlProjectWCCIdentifier</key>
+	<string>BEF5A5D0FF64801E558286389440357A9233D7DB</string>
+	<key>IDESourceControlProjectWCConfigurations</key>
+	<array>
+		<dict>
+			<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
+			<string>public.vcs.git</string>
+			<key>IDESourceControlWCCIdentifierKey</key>
+			<string>BEF5A5D0FF64801E558286389440357A9233D7DB</string>
+			<key>IDESourceControlWCCName</key>
+			<string>cordova-plugin-camera</string>
+		</dict>
+	</array>
+</dict>
+</plist>

+ 77 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/xcshareddata/xcschemes/CDVCameraLib.xcscheme

xqd
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0610"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "7E9F519419DA102000DA31AC"
+               BuildableName = "libCDVCameraLib.a"
+               BlueprintName = "CDVCameraLib"
+               ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7E9F519419DA102000DA31AC"
+            BuildableName = "libCDVCameraLib.a"
+            BlueprintName = "CDVCameraLib"
+            ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7E9F519419DA102000DA31AC"
+            BuildableName = "libCDVCameraLib.a"
+            BlueprintName = "CDVCameraLib"
+            ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 96 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/CDVCameraTest/CDVCameraTest.xcodeproj/xcshareddata/xcschemes/CDVCameraLibTests.xcscheme

xqd
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0610"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "7E9F519E19DA102000DA31AC"
+               BuildableName = "CDVCameraLibTests.xctest"
+               BlueprintName = "CDVCameraLibTests"
+               ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "7E9F519E19DA102000DA31AC"
+               BuildableName = "CDVCameraLibTests.xctest"
+               BlueprintName = "CDVCameraLibTests"
+               ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7E9F519E19DA102000DA31AC"
+            BuildableName = "CDVCameraLibTests.xctest"
+            BlueprintName = "CDVCameraLibTests"
+            ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7E9F519E19DA102000DA31AC"
+            BuildableName = "CDVCameraLibTests.xctest"
+            BlueprintName = "CDVCameraLibTests"
+            ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7E9F519E19DA102000DA31AC"
+            BuildableName = "CDVCameraLibTests.xctest"
+            BlueprintName = "CDVCameraLibTests"
+            ReferencedContainer = "container:CDVCameraTest.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 40 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/README.md

xqd
@@ -0,0 +1,40 @@
+<!---
+ license: 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.
+-->
+
+# iOS Tests for CDVCamera
+
+You need to install `node.js` to pull in `cordova-ios`.
+
+First install cordova-ios:
+
+    npm install
+
+... in the current folder.
+
+
+# Testing from Xcode
+
+1. Launch the `CDVCameraTest.xcworkspace` file.
+2. Choose "CDVCameraLibTests" from the scheme drop-down menu
+3. Click and hold on the `Play` button, and choose the `Wrench` icon to run the tests
+
+
+# Testing from the command line
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/de/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# iOS-Tests für CDVCamera
+
+Sie müssen installieren `node.js` in `Cordova-Ios` zu ziehen.
+
+Installieren Sie Cordova-Ios zum ersten Mal:
+
+    npm install
+    
+
+... im aktuellen Ordner.
+
+# Testen von Xcode
+
+  1. Starten Sie die Datei `CDVCameraTest.xcworkspace` .
+  2. Wählen Sie im Dropdown-Schema "CDVCameraLibTests"
+  3. Klicken Sie und halten Sie auf den `Play` -Button und wählen Sie das `Schraubenschlüssel` -Symbol zum Ausführen der tests
+
+# Tests von der Befehlszeile aus
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/es/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# Pruebas de iOS para CDVCamera
+
+Necesita instalar `node.js` en `Córdoba-ios`.
+
+Primero instalar cordova-ios:
+
+    npm install
+    
+
+... en la carpeta actual.
+
+# Prueba de Xcode
+
+  1. Iniciar el archivo `CDVCameraTest.xcworkspace` .
+  2. Elija "CDVCameraLibTests" en el menú de lista desplegable esquema
+  3. Haga clic y mantenga el botón de `Play` y elegir el icono de `llave inglesa` para ejecutar las pruebas
+
+# Pruebas desde la línea de comandos
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/fr/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# Tests d'iOS pour CDVCamera
+
+Vous devez installer `node.js` à `cordova-ios`.
+
+Commencez par installer cordova-ios :
+
+    npm install
+    
+
+... dans le dossier actuel.
+
+# Tests de Xcode
+
+  1. Lancez le fichier `CDVCameraTest.xcworkspace` .
+  2. Choisissez « CDVCameraLibTests » dans le menu déroulant de régime
+  3. Cliquez et maintenez sur la touche `Play` et cliquez sur l'icône de `clé` pour exécuter les tests
+
+# Test de la ligne de commande
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/it/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# Test di iOS per CDVCamera
+
+È necessario installare `node. js` per tirare in `cordova-ios`.
+
+In primo luogo installare cordova-ios:
+
+    npm install
+    
+
+... nella cartella corrente.
+
+# Test da Xcode
+
+  1. Lanciare il file `CDVCameraTest.xcworkspace` .
+  2. Scegli "CDVCameraLibTests" dal menu a discesa Schema
+  3. Fare clic e tenere premuto il pulsante `Play` e scegliere l'icona della `chiave inglese` per eseguire i test
+
+# Test dalla riga di comando
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/ja/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# CDVCamera の iOS のテスト
+
+`Node.js` `コルドバ`ios をプルするをインストールする必要があります。.
+
+コルドバ ios をインストールします。
+
+    npm install
+    
+
+現在のフォルダーに.
+
+# Xcode からテスト
+
+  1. `CDVCameraTest.xcworkspace`ファイルを起動します。
+  2. スキーム] ドロップダウン メニューから"CDVCameraLibTests"を選択します。
+  3. クリックし、`再生`ボタンを押し、テストを実行する`レンチ`のアイコンを選択
+
+# コマンドラインからテスト
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/ko/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# CDVCamera에 대 한 iOS 테스트
+
+`Node.js` `코르도바` ios에서를 설치 해야.
+
+코르도바-ios를 설치 하는 첫번째는:
+
+    npm install
+    
+
+현재 폴더에....
+
+# Xcode에서 테스트
+
+  1. `CDVCameraTest.xcworkspace` 파일을 시작 합니다.
+  2. 구성표 드롭 다운 메뉴에서 "CDVCameraLibTests"를 선택
+  3. 클릭 하 고 `재생` 버튼에는 테스트를 실행 하려면 `공구 모양` 아이콘을 선택
+
+# 명령줄에서 테스트
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/pl/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# iOS testy dla CDVCamera
+
+Musisz zainstalować `node.js` ciągnąć w `cordova-ios`.
+
+Najpierw zainstalować cordova-ios:
+
+    npm install
+    
+
+... w folderze bieżącym.
+
+# Badania z Xcode
+
+  1. Uruchom plik `CDVCameraTest.xcworkspace` .
+  2. Wybierz z menu rozwijanego systemu "CDVCameraLibTests"
+  3. Kliknij i przytrzymaj przycisk `Play` i wybrać ikonę `klucz` do testów
+
+# Badania z wiersza polecenia
+
+    npm test

+ 39 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/doc/zh/README.md

xqd
@@ -0,0 +1,39 @@
+<!---
+ license: 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.
+-->
+
+# CDVCamera 的 iOS 測試
+
+您需要安裝`node.js`拉`科爾多瓦 ios`中.
+
+第一次安裝科爾多瓦 ios:
+
+    npm install
+    
+
+在當前資料夾中。
+
+# 從 Xcode 測試
+
+  1. 啟動`CDVCameraTest.xcworkspace`檔。
+  2. 從方案下拉式功能表中選擇"CDVCameraLibTests"
+  3. 按一下並堅持`播放`按鈕,然後選擇要運行的測試的`扳手`圖示
+
+# 從命令列測試
+
+    npm test

+ 13 - 0
miaomiao/plugins/cordova-plugin-camera/tests/ios/package.json

xqd
@@ -0,0 +1,13 @@
+{
+    "name": "cordova-plugin-camera-test-ios",
+    "version": "1.0.0",
+    "description": "iOS Unit Tests for Camera Plugin",
+    "author": "Apache Software Foundation",
+    "license": "Apache Version 2.0",
+    "dependencies": {
+        "cordova-ios": "*"
+    },
+    "scripts": {
+        "test": "xcodebuild -scheme CordovaLib && xcodebuild test -scheme CDVCameraLibTests -destination 'platform=iOS Simulator,name=iPhone 5'"
+    }
+}

Some files were not shown because too many files changed in this diff