├── .editorconfig ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .jshintrc ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── docs └── api.md ├── package.json ├── plugin.xml ├── spec ├── helper │ └── cordova.js └── index.spec.js ├── src ├── android │ └── ImageEditor.java └── ios │ ├── CDVImageEditor.h │ └── CDVImageEditor.m └── www └── ImageEditor.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style of different editors and IDEs. 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | indent_size = 4 10 | indent_style = space 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.json] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We love pull requests from everyone. Read through this guide to learn how to contribute. 4 | 5 | _**Note:** This project only accepts pull requests related to open issues. If suggesting a new feature or change, please discuss it in an issue first._ 6 | 7 | **Contents** 8 | 9 | - [Workflow](#workflow) 10 | - [Tools](#tools) 11 | 12 | 13 | ## Workflow 14 | 15 | Quick overview: 16 | 17 | 1. Forking and cloning 18 | 1. Using the npm scripts 19 | 1. Pushing your changes 20 | 1. Submitting a pull request 21 | 22 | ### 1. Forking and cloning 23 | 24 | [Fork](https://help.github.com/articles/fork-a-repo/), then [clone](https://help.github.com/articles/cloning-a-repository/) the repo: 25 | 26 | ``` 27 | git clone git@github.com:your-username/phonegap-plugin-csdk-image-editor.git 28 | ``` 29 | 30 | Set up a branch for your feature or bugfix with a link to the original repo: 31 | 32 | ``` 33 | git checkout -b my-awesome-new-feature 34 | git push --set-upstream origin my-awesome-new-feature 35 | git remote add upstream https://github.com/CreativeSDK/phonegap-plugin-csdk-image-editor 36 | ``` 37 | 38 | 39 | ### 2. Using the npm scripts 40 | 41 | Set up the project: 42 | 43 | ``` 44 | npm install 45 | ``` 46 | 47 | Make sure the tests pass before changing anything: 48 | 49 | ``` 50 | npm test 51 | ``` 52 | 53 | Make your change. Add tests for your change. Make the tests pass: 54 | 55 | ``` 56 | npm test 57 | ``` 58 | 59 | Add or edit [JSDoc](http://usejsdoc.org/) in the source code, then run: 60 | 61 | ``` 62 | npm run build:docs 63 | ``` 64 | 65 | You can check the JSDoc output in `docs/api.md`. 66 | 67 | 68 | ### 3. Pushing your changes 69 | 70 | Commit changes: 71 | 72 | ``` 73 | git commit -m "Cool stuff" 74 | ``` 75 | 76 | Make sure your branch is up to date with the original repo: 77 | 78 | ``` 79 | git fetch upstream 80 | git merge upstream/master 81 | ``` 82 | 83 | Review your changes and any possible conflicts and push to your fork: 84 | 85 | ``` 86 | git push origin 87 | ``` 88 | 89 | ### 4. Submitting a pull request 90 | 91 | [Read here about how to submit a pull request](https://help.github.com/articles/creating-a-pull-request/). 92 | 93 | At this point you're waiting on us. We do our best to keep on top of all the pull requests. We may suggest some changes, improvements or alternatives. 94 | 95 | Some things that will increase the chance that your pull request is accepted: 96 | 97 | - Write tests. 98 | - Write a [good commit message](http://chris.beams.io/posts/git-commit/). 99 | - Make sure the PR merges cleanly with the latest master. 100 | - Describe your feature/bugfix and why it's needed/important in the pull request description. 101 | 102 | 103 | ## Tools 104 | 105 | ### Editor Config 106 | 107 | The project uses [.editorconfig](http://editorconfig.org/) to define the coding 108 | style of each file. We recommend that you install the Editor Config extension 109 | for your preferred IDE. Consistency is key. 110 | 111 | ### JSHint 112 | 113 | The project uses [.jshint](http://jshint.com/docs) to define the JavaScript 114 | coding conventions. Most editors now have a JSHint add-on to provide on-save 115 | or on-edit linting. 116 | 117 | #### Install JSHint for vim 118 | 119 | 1. Install [jshint](https://www.npmjs.com/package/jshint). 120 | 1. Install [jshint.vim](https://github.com/wookiehangover/jshint.vim). 121 | 122 | #### Install JSHint for Sublime 123 | 124 | 1. Install [Package Control](https://packagecontrol.io/installation) 125 | 1. Restart Sublime 126 | 1. Type `CMD+SHIFT+P` 127 | 1. Type _Install Package_ 128 | 1. Type _JSHint Gutter_ 129 | 1. Sublime -> Preferences -> Package Settings -> JSHint Gutter 130 | 1. Set `lint_on_load` and `lint_on_save` to `true` 131 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Expected Behaviour 2 | 3 | ### Actual Behaviour 4 | 5 | ### Reproduce Scenario (including but not limited to) 6 | 7 | #### Steps to Reproduce 8 | 9 | #### Platform and Version (eg. Android 5.0 or iOS 9.2.1) 10 | 11 | #### (Android) What device vendor (e.g. Samsung, HTC, Sony...) 12 | 13 | #### PhoneGap CLI version and PhoneGap platform version 14 | 15 | phonegap --version # e.g. 6.0.0 16 | phonegap platform version android # e.g. 4.1.1 17 | 18 | #### Plugin version 19 | 20 | phonegap plugin version | grep phonegap-plugin-csdk-image-editor # e.g. 1.5.3 21 | 22 | #### Sample Code that illustrates the problem 23 | 24 | #### Logs taken while reproducing problem 25 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Related Issue 7 | 8 | 9 | 10 | 11 | 12 | ## Motivation and Context 13 | 14 | 15 | ## How Has This Been Tested? 16 | 17 | 18 | 19 | 20 | ## Screenshots (if appropriate): 21 | 22 | ## Types of changes 23 | 24 | - [ ] Bug fix (non-breaking change which fixes an issue) 25 | - [ ] New feature (non-breaking change which adds functionality) 26 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 27 | 28 | ## Checklist: 29 | 30 | 31 | - [ ] My code follows the code style of this project. 32 | - [ ] My change requires a change to the documentation. 33 | - [ ] I have updated the documentation accordingly. 34 | - [ ] I have read the **CONTRIBUTING** document. 35 | - [ ] I have added tests to cover my changes. 36 | - [ ] All new and existing tests passed. 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | .DS_Store 4 | /node_modules/ 5 | src/ios/AdobeCreativeSDKFrameworks/* 6 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "asi": false, 3 | "boss": false, 4 | "camelcase": true, 5 | "curly": true, 6 | "eqeqeq": true, 7 | "eqnull": false, 8 | "es5": false, 9 | "evil": false, 10 | "expr": false, 11 | "forin": true, 12 | "funcscope": false, 13 | "jasmine": true, 14 | "immed": true, 15 | "indent": 4, 16 | "latedef": true, 17 | "loopfunc": false, 18 | "maxerr": 7, 19 | "newcap": true, 20 | "node": true, 21 | "nonew": true, 22 | "plusplus": false, 23 | "quotmark": "single", 24 | "shadow": false, 25 | "strict": false, 26 | "supernew": false, 27 | "trailing": true, 28 | "undef": true, 29 | "white": true 30 | } 31 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | spec/ 2 | tests/ 3 | src/ios/AdobeCreativeSDKFrameworks 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [v1.0.0](https://github.com/* remote origin 4 | Fetch URL: https://github.com//tree/v1.0.0) (2016-07-09) 5 | [Full Changelog](https://github.com/* remote origin 6 | Fetch URL: https://github.com//compare/v0.0.2...v1.0.0) 7 | 8 | - 1.0.0 [view commit](http://github.com/* remote origin 9 | Fetch URL: https://github.com//commit/76f07f0da8d616c49d34fc3ebbf7e8ddbc32ceea) 10 | - Bumping plugin version to 1.0.0 [view commit](http://github.com/* remote origin 11 | Fetch URL: https://github.com//commit/64a7780a87a6aca8ddeeeab81213797fea5ae050) 12 | - Prepare for 1.0.0 release [view commit](http://github.com/* remote origin 13 | Fetch URL: https://github.com//commit/53d13675e45ee1807ab636d49cd6c0c95253ac1b) 14 | - Issue #17: Add tests for OrientationType, LeftButtonType & RightButtonType [view commit](http://github.com/* remote origin 15 | Fetch URL: https://github.com//commit/529d8e5ce4066df56a4a7088797d3931eda72e5b) 16 | - Specifying which options are platform-specific. (#18) [view commit](http://github.com/* remote origin 17 | Fetch URL: https://github.com//commit/f0b811a7496ceb58ce56f64eaa28994d0a398fa7) 18 | - Implement missing options on iOS [view commit](http://github.com/* remote origin 19 | Fetch URL: https://github.com//commit/c5dba1474d23c839dab6f6883488a53afd2e9039) 20 | - Remove unused confirmExit on iOS [view commit](http://github.com/* remote origin 21 | Fetch URL: https://github.com//commit/8fab73eaa5c461eb970e7865337c07e6895d1c03) 22 | - Added .github contribution guidelines. (#15) [view commit](http://github.com/* remote origin 23 | Fetch URL: https://github.com//commit/a542241965c77a111c4f4870f75d24e5d3f55fb7) 24 | - [whoops] lazy copy and paste error [view commit](http://github.com/* remote origin 25 | Fetch URL: https://github.com//commit/629dc11a46e83a0afd68baafbe9dc144f1cd0244) 26 | - [doc] outputFile option [view commit](http://github.com/* remote origin 27 | Fetch URL: https://github.com//commit/fb1b9e152e6345a2bb7f0db12455becf76aa16f3) 28 | - Implement missing options on Android (Part 2) [view commit](http://github.com/* remote origin 29 | Fetch URL: https://github.com//commit/21d6ff0d8ddf8bb0ee8f12fc64b961ddd97e8f2b) 30 | - Issue #11: Add npm script to export jsdoc2md docs [view commit](http://github.com/* remote origin 31 | Fetch URL: https://github.com//commit/211ff93dc7463080f56df9ab1ae1f34f0450f227) 32 | - Implement missing options on Android (#14) [view commit](http://github.com/* remote origin 33 | Fetch URL: https://github.com//commit/f14a231b0d8feb4da0e759081604b8e167f05cfe) 34 | - Merge pull request #13 from CreativeSDK/docs [view commit](http://github.com/* remote origin 35 | Fetch URL: https://github.com//commit/0772103cc2970526e23c970ecb9048e2197e27c7) 36 | - Adding details for options docs, and sample code for using the quality setting. [view commit](http://github.com/* remote origin 37 | Fetch URL: https://github.com//commit/5c070a33a8b8e7b24eee6878d01fcfcbd6d889d1) 38 | - Merge pull request #10 from CreativeSDK/docs [view commit](http://github.com/* remote origin 39 | Fetch URL: https://github.com//commit/18ef3be8629c93b6b262285ce1ee289cdcf4c118) 40 | - Added defaults docs to options object. [view commit](http://github.com/* remote origin 41 | Fetch URL: https://github.com//commit/dfc6cc7dff05fad4edc2e96f6534598dde1f6551) 42 | - Updated anchors for gfm. [view commit](http://github.com/* remote origin 43 | Fetch URL: https://github.com//commit/55eacf1799889ced5c572c51963e5d4896a7806a) 44 | - API docs output with jsdoc2md. [view commit](http://github.com/* remote origin 45 | Fetch URL: https://github.com//commit/73dee885b0f331ba459c910dfc57b0a4c519f2b4) 46 | - First attempt at JSDoc. [view commit](http://github.com/* remote origin 47 | Fetch URL: https://github.com//commit/35b0329da07f50a1b31639e6d4f2d7530b65ea7f) 48 | - Added manual API docs. [view commit](http://github.com/* remote origin 49 | Fetch URL: https://github.com//commit/1140059570d0024e1605a3a6110620fdb52e7271) 50 | - Issue #6: Check if is working as intended [view commit](http://github.com/* remote origin 51 | Fetch URL: https://github.com//commit/32c563c506c72cf53b87879155481955add1eb39) 52 | - Issue #7: Fix argcheck issue when running tests [view commit](http://github.com/* remote origin 53 | Fetch URL: https://github.com//commit/8c2310fcccfeb28343bd8837d7f4b346b4039c7c) 54 | - Adding documentation. API guide still needs to be added. [view commit](http://github.com/* remote origin 55 | Fetch URL: https://github.com//commit/e85e96396447584c20bfdd53577f39bc3626c3be) 56 | - Issue #8: Upgrade to CSDK 0.9.1062 [view commit](http://github.com/* remote origin 57 | Fetch URL: https://github.com//commit/ec0a9d380f27fbbbe63455498c8afe2ccfcfd600) 58 | - Issue #4: Rename to CSDKImageEditor [view commit](http://github.com/* remote origin 59 | Fetch URL: https://github.com//commit/c0a830fa182826510dbc9138276c7ca444001492) 60 | - Added Waffle badge. [view commit](http://github.com/* remote origin 61 | Fetch URL: https://github.com//commit/220b673a250b45e655613a9a208bfe1b693550ee) 62 | - Update plugin.xml [view commit](http://github.com/* remote origin 63 | Fetch URL: https://github.com//commit/b407561b799476f0dc046b3680fe84dddac7f09e) 64 | - If no tools are specified, show all tools [view commit](http://github.com/* remote origin 65 | Fetch URL: https://github.com//commit/998478d1821ce3751dc0ca9600b9b68fc763868b) 66 | - Add tool support to iOS [view commit](http://github.com/* remote origin 67 | Fetch URL: https://github.com//commit/6435669609cef76204e538d262c951f7734be3c3) 68 | - Use encoding and quality parameters on iOS [view commit](http://github.com/* remote origin 69 | Fetch URL: https://github.com//commit/7f8f7a3148c08ced9973acc20f9797e4123c90ef) 70 | - Write modified image to disk [view commit](http://github.com/* remote origin 71 | Fetch URL: https://github.com//commit/c7fe1152bb6e40b1de3724a413d7995372beb1b0) 72 | - Start on ImageEditor for iOS [view commit](http://github.com/* remote origin 73 | Fetch URL: https://github.com//commit/b07bc28fae69af95f4f5d2cba5edb8c4ab6185e5) 74 | - Fire error callback when editor cancled [view commit](http://github.com/* remote origin 75 | Fetch URL: https://github.com//commit/138e75652c2cc07504280fae2284442a650573f7) 76 | - Adding installation instructions to README [view commit](http://github.com/* remote origin 77 | Fetch URL: https://github.com//commit/2eec7d249be10ba91da206e17ea37ce054075094) 78 | - Add Quality support [view commit](http://github.com/* remote origin 79 | Fetch URL: https://github.com//commit/d25e741d81323516f0af3e783d61ceaace4ec9f2) 80 | - Add Tool type support (too many to list) [view commit](http://github.com/* remote origin 81 | Fetch URL: https://github.com//commit/d266658ded3fee42029f4f6cef896a6f52ea33be) 82 | - Add Output type support (JPEG,PNG) [view commit](http://github.com/* remote origin 83 | Fetch URL: https://github.com//commit/0113e89ecd61e98b79c1f234e9969fde4add2f2f) 84 | - Image editor depends on client auth [view commit](http://github.com/* remote origin 85 | Fetch URL: https://github.com//commit/a3b01f8b871ca813ef388bb30cee84d76de7dc13) 86 | - Start on ImageEditor [view commit](http://github.com/* remote origin 87 | Fetch URL: https://github.com//commit/faeb2dad3dddde1ad978754464c135ed123a3f71) 88 | 89 | # Change Log 90 | 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 21 | 22 | phonegap-plugin-csdk-image-editor 23 | ------------------------ 24 | 25 | [![Stories in Ready](https://badge.waffle.io/CreativeSDK/phonegap-plugin-csdk-image-editor.png?label=ready&title=Ready)](http://waffle.io/CreativeSDK/phonegap-plugin-csdk-image-editor) 26 | 27 | The Creative SDK Image Editor UI component provides a solution for developers seeking to add powerful photo editing to their Android, iOS, and Web apps. 28 | 29 | The Image Editor includes over twenty advanced imaging tools covering everything from Effects and Crop to Redeye and Blemish. The tools are all GPU-accelerated, so all image modifications happen in real time or close to it. 30 | 31 | This plugin makes it possible for you to use the Creative SDK Image Editor in your PhoneGap apps on Android and iOS. Read on to learn how! 32 | 33 | ### Contents 34 | 35 | - [Prerequisites](#prerequisites) 36 | - [Installation](#installation) 37 | - [Setup guide](#setup-guide) 38 | - [Sample code](#sample-code) 39 | - [API guide](#api-guide) 40 | 41 | # Prerequisites 42 | 43 | **Required:** You must first install the [Client Auth plugin](https://github.com/CreativeSDK/phonegap-plugin-csdk-client-auth) for this plugin to work. 44 | 45 | **Required:** This guide will assume that you have installed all software and completed all of the steps in the [Client Auth guide](https://github.com/CreativeSDK/phonegap-plugin-csdk-client-auth). 46 | 47 | 48 | # Installation 49 | 50 | ## Adding the plugin 51 | 52 | Use the command below to add the plugin to your app. 53 | 54 | ### Adding released version 55 | 56 | ``` 57 | phonegap plugin add --save phonegap-plugin-csdk-image-editor 58 | ``` 59 | 60 | ### Adding development version 61 | 62 | ``` 63 | phonegap plugin add --save https://github.com/CreativeSDK/phonegap-plugin-csdk-image-editor 64 | ``` 65 | 66 | ## Downloading the Creative SDK 67 | 68 | **iOS** 69 | 70 | To get the iOS SDK, go to the [Downloads page](https://creativesdk.adobe.com/downloads.html), click the download link for `STATIC FRAMEWORKS (DEPRECATED)`, and extract it to the `src/ios` folder of this plugin. Extracting the ZIP will create an `AdobeCreativeSDKFrameworks` folder. 71 | 72 | The ZIP files contain all the frameworks in the Creative SDK, but for this plugin we will only be using the `AdobeCreativeSDKImage.framework`. 73 | 74 | 75 | **Android** 76 | 77 | No action is required for Android. The Creative SDK for Android is delivered as a remote Maven repository, and the required framework will be downloaded automatically by the plugin. 78 | 79 | 80 | # Setup guide 81 | 82 | 1. `cd` into your existing PhoneGap app (must already include [Client Auth](https://github.com/CreativeSDK/phonegap-plugin-csdk-client-auth)) 83 | 1. Add this plugin (see "Adding the plugin" above) 84 | 1. **iOS only:** download and add the Creative SDK to this plugin's `src/ios` directory (see "Downloading the Creative SDK" above) 85 | 1. Build and run for your platform 86 | 87 | 88 | # Sample code 89 | 90 | ## `www/index.html` 91 | 92 | Add a button within the `body`. The PhoneGap "Hello World" example includes a `div` with an ID of `app`, so for this example, we are including it in there. 93 | 94 | ``` 95 | // ... 96 | 97 |
98 | 99 | // ... 100 | 101 | 102 |
103 | 104 | // ... 105 | 106 | ``` 107 | 108 | ## `www/js/index.js` 109 | 110 | _**Note:** Most of the code below comes from the PhoneGap "Hello World" example, and we are providing it here for context._ 111 | 112 | This plugin provides access to a global `CSDKImageEditor` object. 113 | 114 | The `CSDKImageEditor` object exposes a `.edit()` function, and some enums to use when setting up your options. 115 | 116 | See comments **#1-2** below for relevant code: 117 | 118 | ``` 119 | var app = { 120 | initialize: function() { 121 | this.bindEvents(); 122 | }, 123 | bindEvents: function() { 124 | // ... 125 | 126 | /* 1) Add a click handler for your button */ 127 | document.getElementById('launch-editor').addEventListener('click', this.launchEditor, false); 128 | }, 129 | onDeviceReady: function() { 130 | app.receivedEvent('deviceready'); 131 | }, 132 | receivedEvent: function(id) { 133 | // ... 134 | }, 135 | 136 | /* 2) Make a helper function to launch the Image Editor */ 137 | launchEditor: function() { 138 | 139 | /* 2.a) Prep work for calling `.edit()` */ 140 | function success(newUrl) { 141 | console.log("Success!", newUrl); 142 | } 143 | 144 | function error(error) { 145 | console.log("Error!", error); 146 | } 147 | 148 | var imageUrl = ""; 149 | 150 | var options = { 151 | outputType: CSDKImageEditor.OutputType.JPEG, 152 | tools: [ 153 | CSDKImageEditor.ToolType.EFFECTS, 154 | CSDKImageEditor.ToolType.CROP 155 | ], 156 | quality: 50 157 | }; 158 | 159 | /* 2.b) Launch the Image Editor */ 160 | CSDKImageEditor.edit(success, error, imageUrl, options); 161 | } 162 | }; 163 | ``` 164 | 165 | 166 | # API guide 167 | 168 | [See the full API guide](docs/api.md). 169 | -------------------------------------------------------------------------------- /docs/api.md: -------------------------------------------------------------------------------- 1 | ## Members 2 | 3 |
4 |
CSDKImageEditor
5 |

A global object that lets you interact with the Creative SDK Image Editor.

6 |
7 |
8 | 9 | ## Typedefs 10 | 11 |
12 |
successCallback : function
13 |

A callback to be used upon successful editing of an image.

14 |
15 |
errorCallback : function
16 |

A callback to handle errors when attempting to edit an image.

17 |
18 |
Options : Object
19 |

An object for configuring Image Editor behavior.

20 |
21 |
22 | 23 | 24 | 25 | ## CSDKImageEditor 26 | A global object that lets you interact with the Creative SDK Image Editor. 27 | 28 | **Kind**: global variable 29 | 30 | * [CSDKImageEditor](#CSDKImageEditor) 31 | * [.OutputType](#CSDKImageEditor.OutputType) : enum 32 | * [.ToolType](#CSDKImageEditor.ToolType) : enum 33 | * [.OrientationType](#CSDKImageEditor.OrientationType) : enum 34 | * [.LeftButtonType](#CSDKImageEditor.LeftButtonType) : enum 35 | * [.RightButtonType](#CSDKImageEditor.RightButtonType) : enum 36 | * [.edit(successCallback, errorCallback, imageUrl, options)](#CSDKImageEditor.edit) 37 | 38 | 39 | 40 | ### CSDKImageEditor.OutputType : enum 41 | **Kind**: static enum property of [CSDKImageEditor](#CSDKImageEditor) 42 | **Read only**: true 43 | **Properties** 44 | 45 | | Name | Type | Default | Description | 46 | | --- | --- | --- | --- | 47 | | JPEG | number | 0 | Return JPEG encoded image | 48 | | PNG | number | 1 | Return PNG encoded image | 49 | 50 | 51 | 52 | ### CSDKImageEditor.ToolType : enum 53 | **Kind**: static enum property of [CSDKImageEditor](#CSDKImageEditor) 54 | **Read only**: true 55 | **Properties** 56 | 57 | | Name | Type | Default | 58 | | --- | --- | --- | 59 | | SHARPNESS | number | 0 | 60 | | EFFECTS | number | 1 | 61 | | REDEYE | number | 2 | 62 | | CROP | number | 3 | 63 | | WHITEN | number | 4 | 64 | | DRAW | number | 5 | 65 | | STICKERS | number | 6 | 66 | | TEXT | number | 7 | 67 | | BLEMISH | number | 8 | 68 | | MEME | number | 9 | 69 | | ORIENTATION | number | 10 | 70 | | ENHANCE | number | 11 | 71 | | FRAMES | number | 12 | 72 | | SPLASH | number | 13 | 73 | | FOCUS | number | 14 | 74 | | BLUR | number | 15 | 75 | | VIGNETTE | number | 16 | 76 | | LIGHTING | number | 17 | 77 | | COLOR | number | 18 | 78 | | OVERLAYS | number | 19 | 79 | | ADJUST | number | 20 | 80 | 81 | 82 | 83 | ### CSDKImageEditor.OrientationType : enum 84 | **Kind**: static enum property of [CSDKImageEditor](#CSDKImageEditor) 85 | **Read only**: true 86 | **Properties** 87 | 88 | | Name | Type | Default | 89 | | --- | --- | --- | 90 | | PORTRAIT | number | 1 | 91 | | PORTRAIT_UPSIDE_DOWN | number | 2 | 92 | | LANDSCAPE_RIGHT | number | 3 | 93 | | LANDSCAPE_LEFT | number | 4 | 94 | 95 | 96 | 97 | ### CSDKImageEditor.LeftButtonType : enum 98 | **Kind**: static enum property of [CSDKImageEditor](#CSDKImageEditor) 99 | **Read only**: true 100 | **Properties** 101 | 102 | | Name | Type | Default | 103 | | --- | --- | --- | 104 | | CANCEL | number | 0 | 105 | | BACK | number | 1 | 106 | | EXIT | number | 2 | 107 | 108 | 109 | 110 | ### CSDKImageEditor.RightButtonType : enum 111 | **Kind**: static enum property of [CSDKImageEditor](#CSDKImageEditor) 112 | **Read only**: true 113 | **Properties** 114 | 115 | | Name | Type | Default | 116 | | --- | --- | --- | 117 | | DONE | number | 0 | 118 | | SAVE | number | 1 | 119 | | NEXT | number | 2 | 120 | | SEND | number | 3 | 121 | 122 | 123 | 124 | ### CSDKImageEditor.edit(successCallback, errorCallback, imageUrl, options) 125 | Launches the Image Editor. 126 | 127 | **Kind**: static method of [CSDKImageEditor](#CSDKImageEditor) 128 | 129 | | Param | Type | Description | 130 | | --- | --- | --- | 131 | | successCallback | [successCallback](#successCallback) | See type definition. | 132 | | errorCallback | [errorCallback](#errorCallback) | See type definition. | 133 | | imageUrl | string | URL of the image to be edited. | 134 | | options | [Options](#Options) | An object containing optional property/value pairs. | 135 | 136 | 137 | 138 | ## successCallback : function 139 | A callback to be used upon successful editing of an image. 140 | 141 | **Kind**: global typedef 142 | 143 | | Param | Type | Description | 144 | | --- | --- | --- | 145 | | newUrl | string | The URL of the new edited image. | 146 | 147 | 148 | 149 | ## errorCallback : function 150 | A callback to handle errors when attempting to edit an image. 151 | 152 | **Kind**: global typedef 153 | 154 | | Param | Type | Description | 155 | | --- | --- | --- | 156 | | error | Object | Error object. | 157 | 158 | 159 | 160 | ## Options : Object 161 | An object for configuring Image Editor behavior. 162 | 163 | **Kind**: global typedef 164 | **Properties** 165 | 166 | | Name | Type | Default | Description | 167 | | --- | --- | --- | --- | 168 | | outputType | [OutputType](#CSDKImageEditor.OutputType) | Same as original image | Forces a specific output type. Ex: `CSDKImageEditor.OutputType.JPEG`. | 169 | | tools | [Array.<ToolType>](#CSDKImageEditor.ToolType) | All tools | Sets the list of tools that are available to the user, in the order you provide them within the array. Ex: `[CSDKImageEditor.Tooltype.CROP]`. | 170 | | quality | number | 100 | Sets the quality of the output of the image. This setting only affects `OutputType.JPEG` images. Valid values are `1` to `100`, inclusive. | 171 | | confirmExit | boolean | false | **[Android only]** Sets whether or not to confirm exiting the image editor when the user clicks done. | 172 | | outputSize | number | 0 | **[Android only]** Sets the size of the output image in mega pixels. Valid values are `0` to `30`, inclusive. Where `0` is the size of the preview image. | 173 | | saveWithNoChanges | boolean | true | **[Android only]** When `true` the success callback will be invoked even when the user does not make any changes to the image. If `false` the error callback will be invoked even when the user does not make any changes to the image. | 174 | | vibrate | boolean | false | **[Android only]** Whether or not to vibrate when certain tasks are performed. | 175 | | previewSize | number | 0 | **[Android only]** Changes the size of the preview used in the editor. This is not the size of the output file, but only the size of the preview used during the edit. | 176 | | outputFile | string | "''" | **[Android only]** Path to save the file. If not specified the system default is used. | 177 | | crop.custom | boolean | true | **[iOS only]** Show custom option in crop tool | 178 | | crop.invert | boolean | true | **[iOS only]** Show invert option in crop tool | 179 | | crop.original | boolean | true | **[iOS only]** Show original option in crop tool | 180 | | crop.customArray | boolean | [] | **[iOS only]** An array of custom crop options. Each array element must be an object with three properties: `label`, `width` and `height` | 181 | | orientations | [Array.<OrientationType>](#CSDKImageEditor.OrientationType) | [CSDKImageEditor.OrientationType.PORTRAIT] | **[iOS only]** Sets the list of orientations that are available to the user. Ex: `[CSDKImageEditor.OrientationType.LANDSCAPE_LEFT, CSDKImageEditor.OrientationType.LANDSCAPE_RIGHT]`. | 182 | | buttons.left | [LeftButtonType](#CSDKImageEditor.LeftButtonType) | CSDKImageEditor.LeftButtonType.CANCEL | **[iOS only]** Label for the left button. Must be one of CSDKImageEditor.LeftButtonType. | 183 | | buttons.left | [RightButtonType](#CSDKImageEditor.RightButtonType) | CSDKImageEditor.RightButtonType.APPLY | **[iOS only]** Label for the right button. Must be one of CSDKImageEditor.RightButtonType. | 184 | 185 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phonegap-plugin-csdk-image-editor", 3 | "description": "This repo is a template for starting a new plugin.", 4 | "version": "1.0.0", 5 | "homepage": "http://github.com/CreativeSDK/phonegap-plugin-csdk-image-editor#readme", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/CreativeSDK/phonegap-plugin-csdk-image-editor.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/CreativeSDK/phonegap-plugin-csdk-image-editor/issues" 12 | }, 13 | "cordova": { 14 | "id": "phonegap-plugin-csdk-image-editor", 15 | "platforms": [ 16 | "ios", 17 | "android", 18 | "browser" 19 | ] 20 | }, 21 | "keywords": [ 22 | "ecosystem:cordova", 23 | "ecosystem:phonegap", 24 | "cordova-ios", 25 | "cordova-android", 26 | "cordova-browser" 27 | ], 28 | "engines": [ 29 | { 30 | "name": "cordova", 31 | "version": ">=3.0.0" 32 | } 33 | ], 34 | "author": "Adobe PhoneGap Team", 35 | "license": "Apache-2.0", 36 | "scripts": { 37 | "build": "npm run build:docs && npm test", 38 | "build:docs": "jsdoc2md www/ImageEditor.js > docs/api.md", 39 | "test": "jasmine-node --color spec" 40 | }, 41 | "devDependencies": { 42 | "jasmine-node": "1.14.5", 43 | "jsdoc-to-markdown": "^1.3.7", 44 | "pluginpub": "^0.0.5" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | phonegap-plugin-csdk-image-editor 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /spec/helper/cordova.js: -------------------------------------------------------------------------------- 1 | /* global cordova:true */ 2 | 3 | /*! 4 | * Module dependencies. 5 | */ 6 | 7 | /** 8 | * cordova.js for node. 9 | * 10 | * Think of this as cordova-node, which would be simliar to cordova-android 11 | * or cordova-browser. The purpose of this module is to enable testing 12 | * of a plugin's JavaScript interface. 13 | * 14 | * When this module is first required, it will insert a global cordova 15 | * instance, which can hijack cordova-specific commands within the pluin's 16 | * implementation. 17 | * 18 | * Remember to require this module before the plugin that you want to test. 19 | * 20 | * Example: 21 | * 22 | * var cordova = require('./helper/cordova'), 23 | * myPlugin = require('../www/myPlugin'); 24 | */ 25 | 26 | module.exports = global.cordova = cordova = { 27 | 28 | /** 29 | * cordova.require Mock. 30 | * 31 | * Hijacks all cordova.requires. By default, it returns an empty function. 32 | * You can define your own implementation of each required module before 33 | * or after it has been required. 34 | * 35 | * See `cordova.required` to learn how to add your own module implemtnation. 36 | */ 37 | 38 | require: function(moduleId) { 39 | // define a default function if it doesn't exist 40 | if (!cordova.required[moduleId]) { 41 | cordova.required[moduleId] = function() {}; 42 | } 43 | // create a new module mapping between the module Id and cordova.required. 44 | return new ModuleMap(moduleId); 45 | }, 46 | 47 | /** 48 | * Cordova module implementations. 49 | * 50 | * A key-value hash, where the key is the module such as 'cordova/exec' 51 | * and the value is the function or object returned. 52 | * 53 | * For example: 54 | * 55 | * var exec = require('cordova/exec'); 56 | * 57 | * Will map to: 58 | * 59 | * cordova.required['cordova/exec']; 60 | */ 61 | 62 | required: { 63 | // populated at runtime 64 | } 65 | }; 66 | 67 | /** 68 | * Module Mapper. 69 | * 70 | * Returns a function that when executed will lookup the implementation 71 | * in cordova.required[id]. 72 | * 73 | * @param {String} moduleId is the module name/path, such as 'cordova/exec' 74 | * @return {Function}. 75 | */ 76 | 77 | function ModuleMap(moduleId) { 78 | return function() { 79 | // lookup and execute the module's mock implementation, passing 80 | // in any parameters that were provided. 81 | return cordova.required[moduleId].apply(this, arguments); 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /spec/index.spec.js: -------------------------------------------------------------------------------- 1 | /* globals require */ 2 | 3 | /*! 4 | * Module dependencies. 5 | */ 6 | 7 | var cordova = require('./helper/cordova'), 8 | CSDKImageEditor = require('../www/ImageEditor'), 9 | execSpy, 10 | execWin, 11 | options; 12 | 13 | /*! 14 | * Specification. 15 | */ 16 | 17 | describe('phonegap-plugin-csdk-image-editor', function () { 18 | beforeEach(function () { 19 | execWin = jasmine.createSpy(); 20 | execSpy = spyOn(cordova.required, 'cordova/exec').andCallFake(execWin); 21 | }); 22 | 23 | describe('Image Editor', function () { 24 | it('should exist', function () { 25 | expect(CSDKImageEditor).toBeDefined(); 26 | expect(typeof CSDKImageEditor === 'object').toBe(true); 27 | }); 28 | 29 | it('should contain a edit function', function () { 30 | expect(CSDKImageEditor.edit).toBeDefined(); 31 | expect(typeof CSDKImageEditor.edit === 'function').toBe(true); 32 | }); 33 | 34 | describe('Output Type', function() { 35 | it('should contain a getOutputType function', function () { 36 | expect(CSDKImageEditor.getOutputType).toBeDefined(); 37 | expect(typeof CSDKImageEditor.getOutputType === 'function').toBe(true); 38 | }); 39 | 40 | it('should contain two OutputType constants', function () { 41 | expect(CSDKImageEditor.OutputType.JPEG).toBe(0); 42 | expect(CSDKImageEditor.OutputType.PNG).toBe(1); 43 | }); 44 | 45 | it('should return correct output type', function () { 46 | expect(CSDKImageEditor.getOutputType('file.jpg')).toBe(CSDKImageEditor.OutputType.JPEG); 47 | expect(CSDKImageEditor.getOutputType('file.jpeg')).toBe(CSDKImageEditor.OutputType.JPEG); 48 | expect(CSDKImageEditor.getOutputType('file.JPG')).toBe(CSDKImageEditor.OutputType.JPEG); 49 | expect(CSDKImageEditor.getOutputType('file.JPEG')).toBe(CSDKImageEditor.OutputType.JPEG); 50 | 51 | expect(CSDKImageEditor.getOutputType('file.png')).toBe(CSDKImageEditor.OutputType.PNG); 52 | expect(CSDKImageEditor.getOutputType('file.PNG')).toBe(CSDKImageEditor.OutputType.PNG); 53 | 54 | expect(CSDKImageEditor.getOutputType('file.jpg', CSDKImageEditor.OutputType.JPEG)) 55 | .toBe(CSDKImageEditor.OutputType.JPEG); 56 | expect(CSDKImageEditor.getOutputType('file.jpeg', CSDKImageEditor.OutputType.JPEG)) 57 | .toBe(CSDKImageEditor.OutputType.JPEG); 58 | expect(CSDKImageEditor.getOutputType('file.JPG', CSDKImageEditor.OutputType.JPEG)) 59 | .toBe(CSDKImageEditor.OutputType.JPEG); 60 | expect(CSDKImageEditor.getOutputType('file.JPEG', CSDKImageEditor.OutputType.JPEG)) 61 | .toBe(CSDKImageEditor.OutputType.JPEG); 62 | 63 | expect(CSDKImageEditor.getOutputType('file.png', CSDKImageEditor.OutputType.PNG)) 64 | .toBe(CSDKImageEditor.OutputType.PNG); 65 | expect(CSDKImageEditor.getOutputType('file.PNG', CSDKImageEditor.OutputType.PNG)) 66 | .toBe(CSDKImageEditor.OutputType.PNG); 67 | 68 | expect(CSDKImageEditor.getOutputType('file.jpg', CSDKImageEditor.OutputType.PNG)) 69 | .toBe(CSDKImageEditor.OutputType.PNG); 70 | expect(CSDKImageEditor.getOutputType('file.jpeg', CSDKImageEditor.OutputType.PNG)) 71 | .toBe(CSDKImageEditor.OutputType.PNG); 72 | expect(CSDKImageEditor.getOutputType('file.JPG', CSDKImageEditor.OutputType.PNG)) 73 | .toBe(CSDKImageEditor.OutputType.PNG); 74 | expect(CSDKImageEditor.getOutputType('file.JPEG', CSDKImageEditor.OutputType.PNG)) 75 | .toBe(CSDKImageEditor.OutputType.PNG); 76 | 77 | expect(CSDKImageEditor.getOutputType('file.png', CSDKImageEditor.OutputType.JPEG)) 78 | .toBe(CSDKImageEditor.OutputType.JPEG); 79 | expect(CSDKImageEditor.getOutputType('file.PNG', CSDKImageEditor.OutputType.JPEG)) 80 | .toBe(CSDKImageEditor.OutputType.JPEG); 81 | }); 82 | }); 83 | 84 | describe('Tools', function() { 85 | it('should contain a getTools function', function () { 86 | expect(CSDKImageEditor.getTools).toBeDefined(); 87 | expect(typeof CSDKImageEditor.getTools === 'function').toBe(true); 88 | }); 89 | 90 | it('should contain the ToolType constants', function () { 91 | expect(CSDKImageEditor.ToolType.SHARPNESS).toBe(0); 92 | expect(CSDKImageEditor.ToolType.EFFECTS).toBe(1); 93 | expect(CSDKImageEditor.ToolType.REDEYE).toBe(2); 94 | expect(CSDKImageEditor.ToolType.CROP).toBe(3); 95 | expect(CSDKImageEditor.ToolType.WHITEN).toBe(4); 96 | expect(CSDKImageEditor.ToolType.DRAW).toBe(5); 97 | expect(CSDKImageEditor.ToolType.STICKERS).toBe(6); 98 | expect(CSDKImageEditor.ToolType.TEXT).toBe(7); 99 | expect(CSDKImageEditor.ToolType.BLEMISH).toBe(8); 100 | expect(CSDKImageEditor.ToolType.MEME).toBe(9); 101 | expect(CSDKImageEditor.ToolType.ORIENTATION).toBe(10); 102 | expect(CSDKImageEditor.ToolType.ENHANCE).toBe(11); 103 | expect(CSDKImageEditor.ToolType.FRAMES).toBe(12); 104 | expect(CSDKImageEditor.ToolType.SPLASH).toBe(13); 105 | expect(CSDKImageEditor.ToolType.FOCUS).toBe(14); 106 | expect(CSDKImageEditor.ToolType.BLUR).toBe(15); 107 | expect(CSDKImageEditor.ToolType.VIGNETTE).toBe(16); 108 | expect(CSDKImageEditor.ToolType.LIGHTING).toBe(17); 109 | expect(CSDKImageEditor.ToolType.COLOR).toBe(18); 110 | expect(CSDKImageEditor.ToolType.OVERLAYS).toBe(19); 111 | expect(CSDKImageEditor.ToolType.ADJUST).toBe(20); 112 | }); 113 | 114 | it('empty array should be valid', function() { 115 | expect(CSDKImageEditor.getTools([]).length).toBe(0); 116 | }); 117 | 118 | it('should be valid', function() { 119 | expect(CSDKImageEditor.getTools([CSDKImageEditor.ToolType.SHARPNESS]).length).toBe(1); 120 | expect(CSDKImageEditor.getTools([CSDKImageEditor.ToolType.SHARPNESS, CSDKImageEditor.ToolType.LIGHTING]).length).toBe(2); 121 | }); 122 | 123 | it('should remove invalid values', function() { 124 | expect(CSDKImageEditor.getTools([-1]).length).toBe(0); 125 | expect(CSDKImageEditor.getTools([21]).length).toBe(0); 126 | expect(CSDKImageEditor.getTools([CSDKImageEditor.ToolType.SHARPNESS, 42, CSDKImageEditor.ToolType.LIGHTING]).length).toBe(2); 127 | }); 128 | }); 129 | 130 | describe('Output Size', function() { 131 | it('should contain a getOutputSize function', function () { 132 | expect(CSDKImageEditor.getOutputSize).toBeDefined(); 133 | expect(typeof CSDKImageEditor.getOutputSize === 'function').toBe(true); 134 | }); 135 | 136 | it('should be valid', function() { 137 | expect(CSDKImageEditor.getOutputSize(0)).toBe(0); 138 | expect(CSDKImageEditor.getOutputSize(1)).toBe(1); 139 | expect(CSDKImageEditor.getOutputSize(15)).toBe(15); 140 | expect(CSDKImageEditor.getOutputSize(30)).toBe(30); 141 | }); 142 | 143 | it('should convert invalid values to 0', function() { 144 | expect(CSDKImageEditor.getOutputSize()).toBe(0); 145 | expect(CSDKImageEditor.getOutputSize(null)).toBe(0); 146 | expect(CSDKImageEditor.getOutputSize(undefined)).toBe(0); 147 | expect(CSDKImageEditor.getOutputSize(-1)).toBe(0); 148 | expect(CSDKImageEditor.getOutputSize(-10)).toBe(0); 149 | expect(CSDKImageEditor.getOutputSize(31)).toBe(0); 150 | expect(CSDKImageEditor.getOutputSize(457)).toBe(0); 151 | }); 152 | }); 153 | 154 | describe('Preview Size', function() { 155 | it('should contain a getPreviewSize function', function () { 156 | expect(CSDKImageEditor.getPreviewSize).toBeDefined(); 157 | expect(typeof CSDKImageEditor.getPreviewSize === 'function').toBe(true); 158 | }); 159 | 160 | it('should be valid', function() { 161 | expect(CSDKImageEditor.getPreviewSize(1)).toBe(1); 162 | expect(CSDKImageEditor.getPreviewSize(15)).toBe(15); 163 | expect(CSDKImageEditor.getPreviewSize(30)).toBe(30); 164 | }); 165 | 166 | it('should convert invalid values to 0', function() { 167 | expect(CSDKImageEditor.getPreviewSize()).toBe(0); 168 | expect(CSDKImageEditor.getPreviewSize(null)).toBe(0); 169 | expect(CSDKImageEditor.getPreviewSize(undefined)).toBe(0); 170 | expect(CSDKImageEditor.getPreviewSize(-1)).toBe(0); 171 | expect(CSDKImageEditor.getPreviewSize(-10)).toBe(0); 172 | }); 173 | }); 174 | 175 | 176 | describe('Output File', function() { 177 | it('should contain a getOutputFile function', function () { 178 | expect(CSDKImageEditor.getOutputFile).toBeDefined(); 179 | expect(typeof CSDKImageEditor.getOutputFile === 'function').toBe(true); 180 | }); 181 | 182 | it('should be valid', function() { 183 | expect(CSDKImageEditor.getOutputFile('/data/data/ack.jpg')).toBe('/data/data/ack.jpg'); 184 | expect(CSDKImageEditor.getOutputFile('file:///data/data/ack.jpg')).toBe('/data/data/ack.jpg'); 185 | }); 186 | 187 | it('should convert invalid values to empty string', function() { 188 | expect(CSDKImageEditor.getOutputFile()).toBe(''); 189 | expect(CSDKImageEditor.getOutputFile('')).toBe(''); 190 | expect(CSDKImageEditor.getOutputFile(null)).toBe(''); 191 | expect(CSDKImageEditor.getOutputFile(undefined)).toBe(''); 192 | }); 193 | }); 194 | 195 | describe('Orientation Type', function() { 196 | it('should contain the OrientationType constants', function () { 197 | expect(CSDKImageEditor.OrientationType.PORTRAIT).toBe(1); 198 | expect(CSDKImageEditor.OrientationType.PORTRAIT_UPSIDE_DOWN).toBe(2); 199 | expect(CSDKImageEditor.OrientationType.LANDSCAPE_RIGHT).toBe(3); 200 | expect(CSDKImageEditor.OrientationType.LANDSCAPE_LEFT).toBe(4); 201 | }); 202 | }); 203 | 204 | describe('Left Button Type', function() { 205 | it('should contain the LeftButtonType constants', function () { 206 | expect(CSDKImageEditor.LeftButtonType.CANCEL).toBe(0); 207 | expect(CSDKImageEditor.LeftButtonType.BACK).toBe(1); 208 | expect(CSDKImageEditor.LeftButtonType.EXIT).toBe(2); 209 | }); 210 | }); 211 | 212 | describe('Right Button Type', function() { 213 | it('should contain the RightButtonType constants', function () { 214 | expect(CSDKImageEditor.RightButtonType.DONE).toBe(0); 215 | expect(CSDKImageEditor.RightButtonType.SAVE).toBe(1); 216 | expect(CSDKImageEditor.RightButtonType.NEXT).toBe(2); 217 | expect(CSDKImageEditor.RightButtonType.SEND).toBe(3); 218 | }); 219 | }); 220 | }); 221 | }); 222 | -------------------------------------------------------------------------------- /src/android/ImageEditor.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package com.adobe.phonegap.csdk; 21 | 22 | import org.apache.cordova.CallbackContext; 23 | import org.apache.cordova.CordovaPlugin; 24 | import org.apache.cordova.PluginResult; 25 | import org.json.JSONArray; 26 | import org.json.JSONException; 27 | 28 | import android.app.Activity; 29 | import android.annotation.SuppressLint; 30 | import android.content.Intent; 31 | import android.graphics.Bitmap; 32 | import android.graphics.Bitmap.CompressFormat; 33 | import android.net.Uri; 34 | import android.util.Base64; 35 | import android.util.Log; 36 | 37 | import java.io.File; 38 | import java.util.ArrayList; 39 | 40 | import com.adobe.creativesdk.aviary.AdobeImageIntent; 41 | import com.adobe.creativesdk.aviary.internal.filters.ToolLoaderFactory; 42 | import com.adobe.creativesdk.aviary.internal.headless.utils.MegaPixels; 43 | 44 | /** 45 | * This class exposes methods in Cordova that can be called from JavaScript. 46 | */ 47 | public class ImageEditor extends CordovaPlugin { 48 | private static final String LOG_TAG = "CreativeSDK_ImageEditor"; 49 | 50 | // Output types 51 | private static final int JPEG = 0; // Take a picture of type JPEG 52 | private static final int PNG = 1; // Take a picture of type PNG 53 | 54 | // Tool types 55 | private static final int SHARPNESS = 0; 56 | private static final int EFFECTS = 1; 57 | private static final int REDEYE = 2; 58 | private static final int CROP = 3; 59 | private static final int WHITEN = 4; 60 | private static final int DRAW = 5; 61 | private static final int STICKERS = 6; 62 | private static final int TEXT = 7; 63 | private static final int BLEMISH = 8; 64 | private static final int MEME = 9; 65 | private static final int ORIENTATION = 10; 66 | private static final int ENHANCE = 11; 67 | private static final int FRAMES = 12; 68 | private static final int SPLASH = 13; 69 | private static final int FOCUS = 14; 70 | private static final int BLUR = 15; 71 | private static final int VIGNETTE = 16; 72 | private static final int LIGHTING = 17; 73 | private static final int COLOR = 18; 74 | private static final int OVERLAYS = 19; 75 | private static final int ADJUST = 20; 76 | 77 | public CallbackContext callbackContext; 78 | 79 | /** 80 | * Executes the request and returns PluginResult. 81 | * 82 | * @param action The action to execute. 83 | * @param args JSONArry of arguments for the plugin. 84 | * @param callbackContext The callback context from which we were invoked. 85 | */ 86 | @SuppressLint("NewApi") 87 | public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { 88 | this.callbackContext = callbackContext; 89 | 90 | if (action.equals("edit")) { 91 | String imageStr = args.getString(0); 92 | if (imageStr == null || "".equals(imageStr)) { 93 | this.callbackContext.error("Image Path must be specified"); 94 | } 95 | Uri imageUri = Uri.parse(imageStr); 96 | 97 | AdobeImageIntent.Builder builder = 98 | new AdobeImageIntent.Builder(this.cordova.getActivity().getApplicationContext()) 99 | .setData(imageUri); 100 | 101 | // setup options 102 | setOutputType(builder, args.getInt(1)); 103 | setToolsArray(builder, args.getJSONArray(2)); 104 | builder.withOutputQuality(args.getInt(3)); 105 | builder.withNoExitConfirmation(args.getBoolean(4)); 106 | builder.withOutputSize(MegaPixels.valueOf("Mp"+args.getString(5))); 107 | builder.saveWithNoChanges(args.getBoolean(6)); 108 | builder.withVibrationEnabled(args.getBoolean(7)); 109 | 110 | int color = args.getInt(8); 111 | if (color != 0) { 112 | builder.withAccentColor(color); 113 | } 114 | 115 | int previewSize = args.getInt(9); 116 | if (previewSize > 0) { 117 | builder.withPreviewSize(previewSize); 118 | } 119 | 120 | String outputFile = args.getString(10); 121 | if (!"".equals(outputFile)) { 122 | File fp = new File(outputFile); 123 | builder.withOutput(fp); 124 | } 125 | 126 | Intent imageEditorIntent = builder.build(); 127 | 128 | this.cordova.startActivityForResult((CordovaPlugin) this, imageEditorIntent, 1); 129 | 130 | PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT); 131 | r.setKeepCallback(true); 132 | callbackContext.sendPluginResult(r); 133 | } else { 134 | return false; 135 | } 136 | return true; 137 | } 138 | 139 | /** 140 | * Called when the image editor exits. 141 | * 142 | * @param requestCode The request code originally supplied to startActivityForResult(), 143 | * allowing you to identify who this result came from. 144 | * @param resultCode The integer result code returned by the child activity through its setResult(). 145 | * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). 146 | */ 147 | public void onActivityResult(int requestCode, int resultCode, Intent intent) { 148 | if (resultCode == Activity.RESULT_OK) { 149 | switch (requestCode) { 150 | case 1: 151 | Uri editedImageUri = intent.getParcelableExtra(AdobeImageIntent.EXTRA_OUTPUT_URI); 152 | this.callbackContext.success(editedImageUri.toString()); 153 | 154 | break; 155 | } 156 | } else if (resultCode == Activity.RESULT_CANCELED) { 157 | this.callbackContext.error("Editor Canceled"); 158 | } 159 | } 160 | 161 | private void setOutputType(AdobeImageIntent.Builder builder, int outputType) { 162 | if (ImageEditor.JPEG == outputType) { 163 | builder.withOutputFormat(Bitmap.CompressFormat.JPEG); 164 | } else { 165 | builder.withOutputFormat(Bitmap.CompressFormat.PNG); 166 | } 167 | } 168 | 169 | private void setToolsArray(AdobeImageIntent.Builder builder, JSONArray toolsArray) { 170 | try { 171 | ToolLoaderFactory.Tools[] tools = createToolsArray(toolsArray); 172 | if (tools.length > 0) { 173 | builder.withToolList(tools); 174 | } 175 | } catch(JSONException e) { 176 | Log.e(LOG_TAG, e.getLocalizedMessage(), e); 177 | } 178 | } 179 | 180 | private ToolLoaderFactory.Tools[] createToolsArray(JSONArray toolsArray) throws JSONException { 181 | ArrayList tools = new ArrayList(); 182 | for (int i=0; i= 0 && tool <= 20) { 185 | switch(tool) { 186 | case SHARPNESS: 187 | tools.add(ToolLoaderFactory.Tools.SHARPNESS); 188 | break; 189 | case EFFECTS: 190 | tools.add(ToolLoaderFactory.Tools.EFFECTS); 191 | break; 192 | case REDEYE: 193 | tools.add(ToolLoaderFactory.Tools.REDEYE); 194 | break; 195 | case CROP: 196 | tools.add(ToolLoaderFactory.Tools.CROP); 197 | break; 198 | case WHITEN: 199 | tools.add(ToolLoaderFactory.Tools.WHITEN); 200 | break; 201 | case DRAW: 202 | tools.add(ToolLoaderFactory.Tools.DRAW); 203 | break; 204 | case STICKERS: 205 | tools.add(ToolLoaderFactory.Tools.STICKERS); 206 | break; 207 | case TEXT: 208 | tools.add(ToolLoaderFactory.Tools.TEXT); 209 | break; 210 | case BLEMISH: 211 | tools.add(ToolLoaderFactory.Tools.BLEMISH); 212 | break; 213 | case MEME: 214 | tools.add(ToolLoaderFactory.Tools.MEME); 215 | break; 216 | case ORIENTATION: 217 | tools.add(ToolLoaderFactory.Tools.ORIENTATION); 218 | break; 219 | case ENHANCE: 220 | tools.add(ToolLoaderFactory.Tools.ENHANCE); 221 | break; 222 | case FRAMES: 223 | tools.add(ToolLoaderFactory.Tools.FRAMES); 224 | break; 225 | case SPLASH: 226 | tools.add(ToolLoaderFactory.Tools.SPLASH); 227 | break; 228 | case FOCUS: 229 | tools.add(ToolLoaderFactory.Tools.FOCUS); 230 | break; 231 | case BLUR: 232 | tools.add(ToolLoaderFactory.Tools.BLUR); 233 | break; 234 | case VIGNETTE: 235 | tools.add(ToolLoaderFactory.Tools.VIGNETTE); 236 | break; 237 | case LIGHTING: 238 | tools.add(ToolLoaderFactory.Tools.LIGHTING); 239 | break; 240 | case COLOR: 241 | tools.add(ToolLoaderFactory.Tools.COLOR); 242 | break; 243 | case OVERLAYS: 244 | tools.add(ToolLoaderFactory.Tools.OVERLAYS); 245 | break; 246 | case ADJUST: 247 | tools.add(ToolLoaderFactory.Tools.ADJUST); 248 | break; 249 | } 250 | } 251 | } 252 | return tools.toArray(new ToolLoaderFactory.Tools[tools.size()]); 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /src/ios/CDVImageEditor.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | enum CDVEncodingType { 4 | EncodingTypeJPEG = 0, 5 | EncodingTypePNG 6 | }; 7 | typedef NSUInteger CDVEncodingType; 8 | 9 | enum CDVToolType { 10 | ToolTypeSharpness = 0, 11 | ToolTypeEffects, 12 | ToolTypeRedeye, 13 | ToolTypeCrop, 14 | ToolTypeWhiten, 15 | ToolTypeDraw, 16 | ToolTypeStickers, 17 | ToolTypeText, 18 | ToolTypeBlemish, 19 | ToolTypeMeme, 20 | ToolTypeOrientation, 21 | ToolTypeEnhance, 22 | ToolTypeFrames, 23 | ToolTypeSplash, 24 | ToolTypeFocus, 25 | ToolTypeBlur, 26 | ToolTypeVignette, 27 | ToolTypeLighting, 28 | ToolTypeColor, 29 | ToolTypeOverlays, 30 | ToolTypeAdjust 31 | }; 32 | typedef NSUInteger CDVToolType; 33 | 34 | enum CDVLeftButtonType { 35 | LeftButtonTypeCancel = 0, 36 | LeftButtonTypeBack, 37 | LeftButtonTypeExit 38 | }; 39 | typedef NSUInteger CDVLeftButtonType; 40 | 41 | enum CDVRightButtonType { 42 | RightButtonTypeDone = 0, 43 | RightButtonTypeSave, 44 | RightButtonTypeNext, 45 | RightButtonTypeSend 46 | }; 47 | typedef NSUInteger CDVRightButtonType; 48 | 49 | @interface CDVImageEditor : CDVPlugin 50 | { 51 | NSString *callbackId; 52 | NSString *imageUri; 53 | NSNumber *encodingType; 54 | NSNumber *quality; 55 | } 56 | 57 | @property (nonatomic, retain) NSString *callbackId; 58 | @property (nonatomic, retain) NSString *imageUri; 59 | @property (nonatomic, retain) NSNumber *encodingType; 60 | @property (nonatomic, retain) NSNumber *quality; 61 | 62 | - (void)edit:(CDVInvokedUrlCommand*)command; 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /src/ios/CDVImageEditor.m: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | #import 21 | #import "CDVImageEditor.h" 22 | 23 | #define ADB_PHOTO_PREFIX @"adb_photo_" 24 | #define isEqualIgnoreCaseToString(string1, string2) ([string1 caseInsensitiveCompare:string2] == NSOrderedSame) 25 | 26 | @implementation CDVImageEditor 27 | 28 | @synthesize callbackId; 29 | @synthesize imageUri; 30 | @synthesize encodingType; 31 | @synthesize quality; 32 | 33 | - (void)edit:(CDVInvokedUrlCommand*)command 34 | { 35 | self.callbackId = command.callbackId; 36 | 37 | self.imageUri = [command.arguments objectAtIndex:0]; 38 | self.encodingType = [command.arguments objectAtIndex:1]; 39 | NSArray *tools = [self createToolArray:[command.arguments objectAtIndex:2]]; 40 | self.quality = [[command.arguments objectAtIndex:3] integerValue] != 100 ? [command.arguments objectAtIndex:3] : [NSNumber numberWithInt:100]; 41 | 42 | NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.imageUri]]; 43 | UIImage *image = [UIImage imageWithData:imageData]; 44 | 45 | AdobeUXImageEditorViewController *editorController = 46 | [[AdobeUXImageEditorViewController alloc] initWithImage:image]; 47 | [editorController setDelegate:self]; 48 | if ([tools count] > 0) { 49 | [AdobeImageEditorCustomization setToolOrder:tools]; 50 | } 51 | 52 | BOOL custom = [[command.arguments objectAtIndex:11] boolValue]; 53 | [AdobeImageEditorCustomization setCropToolCustomEnabled: custom]; 54 | 55 | if (custom) { 56 | NSArray *crops = [self createCustomCropArray: [command.arguments objectAtIndex:14]]; 57 | [AdobeImageEditorCustomization setCropToolPresets: crops]; 58 | } 59 | 60 | BOOL invert = [[command.arguments objectAtIndex:12] boolValue]; 61 | [AdobeImageEditorCustomization setCropToolInvertEnabled: invert]; 62 | 63 | BOOL orig = [[command.arguments objectAtIndex:13] boolValue]; 64 | [AdobeImageEditorCustomization setCropToolOriginalEnabled: orig]; 65 | 66 | NSArray *orientations = [command.arguments objectAtIndex:15]; 67 | [AdobeImageEditorCustomization setSupportedIpadOrientations:orientations]; 68 | 69 | // setup buttons 70 | [AdobeImageEditorCustomization setLeftNavigationBarButtonTitle:[self getLeftButtonLabel:[command.arguments objectAtIndex:16]]]; 71 | [AdobeImageEditorCustomization setRightNavigationBarButtonTitle:[self getRightButtonLabel:[command.arguments objectAtIndex:17]]]; 72 | 73 | [self.viewController presentViewController:editorController animated:YES completion:nil]; 74 | } 75 | 76 | - (void)photoEditor:(AdobeUXImageEditorViewController *)editor finishedWithImage:(UIImage *)image 77 | { 78 | CDVPluginResult *pluginResult = nil; 79 | NSString *extension = [self.encodingType integerValue] == EncodingTypePNG ? @"png" : @"jpg"; 80 | NSData* data = [self processImage:image]; 81 | if (data) { 82 | NSString* filePath = [self tempFilePath:extension]; 83 | NSError* err = nil; 84 | 85 | // save file 86 | if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) { 87 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]]; 88 | } else { 89 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[[NSURL fileURLWithPath:filePath] absoluteString]]; 90 | } 91 | } 92 | 93 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; 94 | [self.viewController dismissViewControllerAnimated:YES completion:nil]; 95 | } 96 | 97 | - (void)photoEditorCanceled:(AdobeUXImageEditorViewController *)editor 98 | { 99 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 100 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; 101 | [self.viewController dismissViewControllerAnimated:YES completion:nil]; 102 | } 103 | 104 | - (NSString*)tempFilePath:(NSString*)extension 105 | { 106 | NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath]; 107 | NSFileManager* fileMgr = [[NSFileManager alloc] init]; // recommended by Apple (vs [NSFileManager defaultManager]) to be threadsafe 108 | NSString* filePath; 109 | 110 | // generate unique file name 111 | int i = 1; 112 | do { 113 | filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, ADB_PHOTO_PREFIX, i++, extension]; 114 | } while ([fileMgr fileExistsAtPath:filePath]); 115 | 116 | return filePath; 117 | } 118 | 119 | - (NSData*)processImage:(UIImage*)image 120 | { 121 | NSData* data = nil; 122 | 123 | if ([self.encodingType integerValue] == EncodingTypePNG) { 124 | data = UIImagePNGRepresentation(image); 125 | } else if ([self.encodingType integerValue] == EncodingTypeJPEG) { 126 | data = UIImageJPEGRepresentation(image, [self.quality floatValue] / 100.0f); 127 | } 128 | 129 | return data; 130 | } 131 | 132 | - (NSString *) getLeftButtonLabel:(NSNumber*)buttonIndex 133 | { 134 | NSString *label = kAFLeftNavigationTitlePresetCancel; 135 | int buttonId = [buttonIndex integerValue]; 136 | switch(buttonId) { 137 | case LeftButtonTypeBack: 138 | label = kAFLeftNavigationTitlePresetBack; 139 | break; 140 | case LeftButtonTypeExit: 141 | label = kAFLeftNavigationTitlePresetExit; 142 | break; 143 | case LeftButtonTypeCancel: 144 | default: 145 | label = kAFLeftNavigationTitlePresetCancel; 146 | break; 147 | } 148 | return label; 149 | } 150 | 151 | - (NSString *) getRightButtonLabel:(NSNumber*)buttonIndex 152 | { 153 | NSString *label = kAFRightNavigationTitlePresetDone; 154 | int buttonId = [buttonIndex integerValue]; 155 | switch(buttonId) { 156 | case RightButtonTypeSave: 157 | label = kAFRightNavigationTitlePresetSave; 158 | break; 159 | case RightButtonTypeNext: 160 | label = kAFRightNavigationTitlePresetNext; 161 | break; 162 | case RightButtonTypeSend: 163 | label = kAFRightNavigationTitlePresetSend; 164 | break; 165 | case RightButtonTypeDone: 166 | default: 167 | label = kAFRightNavigationTitlePresetDone; 168 | break; 169 | } 170 | return label; 171 | } 172 | 173 | - (NSArray*) createToolArray:(NSArray*)toolOptions 174 | { 175 | NSMutableArray *tools = [NSMutableArray array]; 176 | 177 | for (NSNumber *tempNumber in toolOptions) { 178 | int toolId = [tempNumber integerValue]; 179 | NSLog(@"Single element: %d", toolId); 180 | switch(toolId){ 181 | case ToolTypeSharpness: 182 | [tools addObject: kAdobeImageEditorSharpness]; 183 | break; 184 | case ToolTypeEffects: 185 | [tools addObject: kAdobeImageEditorEffects]; 186 | break; 187 | case ToolTypeRedeye: 188 | [tools addObject: kAdobeImageEditorRedeye]; 189 | break; 190 | case ToolTypeCrop: 191 | [tools addObject: kAdobeImageEditorCrop]; 192 | break; 193 | case ToolTypeWhiten: 194 | [tools addObject: kAdobeImageEditorWhiten]; 195 | break; 196 | case ToolTypeDraw: 197 | [tools addObject: kAdobeImageEditorDraw]; 198 | break; 199 | case ToolTypeStickers: 200 | [tools addObject: kAdobeImageEditorStickers]; 201 | break; 202 | case ToolTypeText: 203 | [tools addObject: kAdobeImageEditorText]; 204 | break; 205 | case ToolTypeBlemish: 206 | [tools addObject: kAdobeImageEditorBlemish]; 207 | break; 208 | case ToolTypeMeme: 209 | [tools addObject: kAdobeImageEditorMeme]; 210 | break; 211 | case ToolTypeOrientation: 212 | [tools addObject: kAdobeImageEditorOrientation]; 213 | break; 214 | case ToolTypeEnhance: 215 | [tools addObject: kAdobeImageEditorEnhance]; 216 | break; 217 | case ToolTypeFrames: 218 | [tools addObject: kAdobeImageEditorFrames]; 219 | break; 220 | case ToolTypeSplash: 221 | [tools addObject: kAdobeImageEditorSplash]; 222 | break; 223 | case ToolTypeFocus: 224 | [tools addObject: kAdobeImageEditorFocus]; 225 | break; 226 | case ToolTypeBlur: 227 | [tools addObject: kAdobeImageEditorBlur]; 228 | break; 229 | case ToolTypeVignette: 230 | [tools addObject: kAdobeImageEditorVignette]; 231 | break; 232 | case ToolTypeLighting: 233 | [tools addObject: kAdobeImageEditorLightingAdjust]; 234 | break; 235 | case ToolTypeColor: 236 | [tools addObject: kAdobeImageEditorColorAdjust]; 237 | break; 238 | case ToolTypeOverlays: 239 | [tools addObject: kAdobeImageEditorOverlay]; 240 | break; 241 | /* 242 | * apparently the adjust tool is only on Android 243 | * 244 | case ToolTypeAdjust: 245 | [tools addObject: xxxxx]; 246 | break; 247 | */ 248 | default: 249 | // Ignore any tool not from the above 250 | break; 251 | } 252 | } 253 | 254 | return [tools copy]; 255 | } 256 | 257 | - (NSArray*) createCustomCropArray:(NSArray*)cropOptions 258 | { 259 | NSMutableArray *crops = [NSMutableArray array]; 260 | 261 | for (NSDictionary *tempCrop in cropOptions) { 262 | NSMutableDictionary *crop = [NSMutableDictionary dictionaryWithCapacity: 3]; 263 | [crop setObject:[tempCrop objectForKey:@"label"] forKey:kAFCropPresetName]; 264 | [crop setObject:[tempCrop objectForKey:@"width"] forKey:kAFCropPresetWidth]; 265 | [crop setObject:[tempCrop objectForKey:@"height"] forKey:kAFCropPresetHeight]; 266 | 267 | [crops addObject: crop]; 268 | } 269 | 270 | return [crops copy]; 271 | } 272 | 273 | @end 274 | -------------------------------------------------------------------------------- /www/ImageEditor.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, 14 | * software distributed under the License is distributed on an 15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | * KIND, either express or implied. See the License for the 17 | * specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | */ 21 | 22 | /* global cordova:false */ 23 | /* globals window */ 24 | 25 | var argscheck = cordova.require('cordova/argscheck'), 26 | exec = cordova.require('cordova/exec'), 27 | utils = cordova.require('cordova/utils'); 28 | 29 | /** 30 | @description A global object that lets you interact with the Creative SDK Image Editor. 31 | @global 32 | */ 33 | var CSDKImageEditor = { 34 | /** 35 | * @description Launches the Image Editor. 36 | * @function edit 37 | * @memberof CSDKImageEditor 38 | * @param {!successCallback} successCallback - See type definition. 39 | * @param {!errorCallback} errorCallback - See type definition. 40 | * @param {!string} imageUrl URL of the image to be edited. 41 | * @param {?Options} options An object containing optional property/value pairs. 42 | */ 43 | edit: function(successCallback, errorCallback, imageUrl, options) { 44 | var getValue = argscheck.getValue; 45 | options = options || {}; 46 | 47 | var outputType = CSDKImageEditor.getOutputType(imageUrl, options.outputType); 48 | var tools = CSDKImageEditor.getTools(options.tools); 49 | var quality = getValue(options.quality, 100); 50 | var confirmExit = getValue(options.confirmExit, false); 51 | var outputSize = CSDKImageEditor.getOutputSize(options.outputSize); 52 | var saveWithNoChanges = getValue(options.saveWithNoChanges, true); 53 | var vibrate = getValue(options.vibrate, false); 54 | var color = getValue(options.color, 0); 55 | var previewSize = getValue(options.previewSize, 0); 56 | var outputFile = CSDKImageEditor.getOutputFile(options.outputFile); 57 | 58 | // crop options for iOS 59 | if (!options.crop) { 60 | options.crop = {}; 61 | } 62 | var cropCustom = getValue(options.crop.custom, true); 63 | var cropInvert = getValue(options.crop.invert, true); 64 | var cropOriginal = getValue(options.crop.original, true); 65 | var customArray = getValue(options.crop.customArray, []); 66 | 67 | var orientations = getValue(options.orientations, [CSDKImageEditor.OrientationType.PORTRAIT]); 68 | 69 | // button options 70 | if (!options.buttons) { 71 | options.buttons = {}; 72 | } 73 | var leftButton = getValue(options.buttons.left, CSDKImageEditor.LeftButtonType.CANCEL); 74 | var rightButton = getValue(options.buttons.right, CSDKImageEditor.RightButtonType.DONE); 75 | 76 | var args = [imageUrl, outputType, tools, quality, confirmExit, outputSize, 77 | saveWithNoChanges, vibrate, color, previewSize, outputFile, cropCustom, 78 | cropInvert, cropOriginal, customArray, orientations, leftButton, rightButton 79 | ]; 80 | 81 | exec(successCallback, errorCallback, 'CSDKImageEditor', 'edit', args); 82 | }, 83 | /** @private */ 84 | getOutputType: function(imageUrl, outputType) { 85 | if (outputType !== null && outputType !== 'undefined' && 86 | (outputType === CSDKImageEditor.OutputType.JPEG || outputType === CSDKImageEditor.OutputType.PNG)) { 87 | return outputType; 88 | } else { 89 | if (imageUrl.toLowerCase().endsWith('png')) { 90 | return CSDKImageEditor.OutputType.PNG; 91 | } else { 92 | return CSDKImageEditor.OutputType.JPEG; 93 | } 94 | } 95 | }, 96 | /** @private */ 97 | getTools: function(tools) { 98 | var validTools = []; 99 | if (tools) { 100 | for(var i=0; i= 0 && tools[i] <= 20) { 102 | validTools.push(tools[i]); 103 | } 104 | } 105 | } 106 | return validTools; 107 | }, 108 | /** @private */ 109 | getOutputSize: function(size) { 110 | if (!size || size < 0 || size > 30) { 111 | return 0; 112 | } 113 | return size; 114 | }, 115 | /** @private */ 116 | getPreviewSize: function(size) { 117 | if (!size || size < 0) { 118 | return 0; 119 | } 120 | return size; 121 | }, 122 | /** @private */ 123 | getOutputFile: function(file) { 124 | if (!file) { 125 | return ''; 126 | } else if (file.startsWith('file://')) { 127 | file = file.substr(7); 128 | } 129 | return file; 130 | }, 131 | /** 132 | * @readonly 133 | * @enum {number} 134 | */ 135 | OutputType:{ 136 | /** Return JPEG encoded image */ 137 | JPEG: 0, 138 | /** Return PNG encoded image */ 139 | PNG: 1 140 | }, 141 | /** 142 | * @readonly 143 | * @enum {number} 144 | */ 145 | ToolType:{ 146 | SHARPNESS: 0, 147 | EFFECTS: 1, 148 | REDEYE: 2, 149 | CROP: 3, 150 | WHITEN: 4, 151 | DRAW: 5, 152 | STICKERS: 6, 153 | TEXT: 7, 154 | BLEMISH: 8, 155 | MEME: 9, 156 | ORIENTATION: 10, 157 | ENHANCE: 11, 158 | FRAMES: 12, 159 | SPLASH: 13, 160 | FOCUS: 14, 161 | BLUR: 15, 162 | VIGNETTE: 16, 163 | LIGHTING: 17, 164 | COLOR: 18, 165 | OVERLAYS: 19, 166 | ADJUST: 20 167 | }, 168 | /** 169 | * @readonly 170 | * @enum {number} 171 | */ 172 | OrientationType:{ 173 | PORTRAIT: 1, 174 | PORTRAIT_UPSIDE_DOWN: 2, 175 | LANDSCAPE_RIGHT: 3, 176 | LANDSCAPE_LEFT: 4 177 | }, 178 | /** 179 | * @readonly 180 | * @enum {number} 181 | */ 182 | LeftButtonType:{ 183 | CANCEL: 0, 184 | BACK: 1, 185 | EXIT: 2 186 | }, 187 | /** 188 | * @readonly 189 | * @enum {number} 190 | */ 191 | RightButtonType:{ 192 | DONE: 0, 193 | SAVE: 1, 194 | NEXT: 2, 195 | SEND: 3 196 | } 197 | }; 198 | 199 | /** 200 | * @description A callback to be used upon successful editing of an image. 201 | * 202 | * @callback successCallback 203 | * @param {string} newUrl - The URL of the new edited image. 204 | */ 205 | 206 | /** 207 | * @description A callback to handle errors when attempting to edit an image. 208 | * 209 | * @callback errorCallback 210 | * @param {Object} error - Error object. 211 | */ 212 | 213 | /** 214 | * @typedef {Object} Options - An object for configuring Image Editor behavior. 215 | * @property {CSDKImageEditor.OutputType} [outputType=Same as original image] - Forces a specific output type. Ex: `CSDKImageEditor.OutputType.JPEG`. 216 | * @property {CSDKImageEditor.ToolType[]} [tools=All tools] - Sets the list of tools that are available to the user, in the order you provide them within the array. Ex: `[CSDKImageEditor.Tooltype.CROP]`. 217 | * @property {number} [quality=100] - Sets the quality of the output of the image. This setting only affects `OutputType.JPEG` images. Valid values are `1` to `100`, inclusive. 218 | * @property {boolean} [confirmExit=false] - **[Android only]** Sets whether or not to confirm exiting the image editor when the user clicks done. 219 | * @property {number} [outputSize=0] - **[Android only]** Sets the size of the output image in mega pixels. Valid values are `0` to `30`, inclusive. Where `0` is the size of the preview image. 220 | * @property {boolean} [saveWithNoChanges=true] - **[Android only]** When `true` the success callback will be invoked even when the user does not make any changes to the image. If `false` the error callback will be invoked even when the user does not make any changes to the image. 221 | * @property {boolean} [vibrate=false] - **[Android only]** Whether or not to vibrate when certain tasks are performed. 222 | * @property {number} [previewSize=0] - **[Android only]** Changes the size of the preview used in the editor. This is not the size of the output file, but only the size of the preview used during the edit. 223 | * @property {string} [outputFile=''] - **[Android only]** Path to save the file. If not specified the system default is used. 224 | * @property {boolean} [crop.custom=true] - **[iOS only]** Show custom option in crop tool 225 | * @property {boolean} [crop.invert=true] - **[iOS only]** Show invert option in crop tool 226 | * @property {boolean} [crop.original=true] - **[iOS only]** Show original option in crop tool 227 | * @property {boolean} [crop.customArray=[]] - **[iOS only]** An array of custom crop options. Each array element must be an object with three properties: `label`, `width` and `height` 228 | * @property {CSDKImageEditor.OrientationType[]} [orientations=[CSDKImageEditor.OrientationType.PORTRAIT]] - **[iOS only]** Sets the list of orientations that are available to the user. Ex: `[CSDKImageEditor.OrientationType.LANDSCAPE_LEFT, CSDKImageEditor.OrientationType.LANDSCAPE_RIGHT]`. 229 | * @property {CSDKImageEditor.LeftButtonType} [buttons.left=CSDKImageEditor.LeftButtonType.CANCEL] - **[iOS only]** Label for the left button. Must be one of CSDKImageEditor.LeftButtonType. 230 | * @property {CSDKImageEditor.RightButtonType} [buttons.left=CSDKImageEditor.RightButtonType.APPLY] - **[iOS only]** Label for the right button. Must be one of CSDKImageEditor.RightButtonType. 231 | */ 232 | 233 | module.exports = CSDKImageEditor; 234 | --------------------------------------------------------------------------------