Compare commits

...

90 Commits

Author SHA1 Message Date
Jeffrey Warren
9fa4b3df86 Merge branch 'main' into ui-tests 2019-09-23 14:27:06 -04:00
Jeffrey Warren
954e684670 adding more options 2019-09-23 14:25:45 -04:00
duyquangnguyenhac
33f32251ec Document noise reduction module (#1189)
* Added documentation for noise reduction module

* Added fixed documentation for noise reduction module

* Update MODULES.md

* Minor Changes to Noise-Reduction description.

* Update docs/MODULES.md

Co-Authored-By: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>

* Move documentation to alphabetical order

* Update MODULES.md
2019-09-23 10:56:38 -04:00
dependabot-preview[bot]
5253e08d57 Bump gpu.js from 2.0.0-rc.26 to 2.0.0 (#1257)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.0.0-rc.26 to 2.0.0.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/compare/2.0.0-rc.26...2.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-18 09:20:59 -04:00
Jeffrey Warren
917c19d47a Merge branch 'main' into ui-tests 2019-09-13 17:47:27 -04:00
keshav234156
d782c147c5 fixes add-QR and color-picker in draw-rectangle,grid-overlay (#1250) 2019-09-11 15:28:02 -04:00
Devesh Kaushik
339df8768d Updated CONTRIBUTION.md (#1231)
* Update Contribution.md

As directed by rexagod

* Update Contribution.md

added libxext-dev

* Update CONTRIBUTING.md

Co-Authored-By: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
2019-09-11 11:18:44 -04:00
Jeffrey Warren
3abb606948 Merge branch 'main' into ui-tests 2019-09-09 12:25:32 -04:00
jywarren
44fc72c94c working HTML fixtures 2019-09-09 12:24:53 -04:00
dependabot-preview[bot]
4a0207bc27 Bump buffer from 5.4.0 to 5.4.2 (#1246)
Bumps [buffer](https://github.com/feross/buffer) from 5.4.0 to 5.4.2.
- [Release notes](https://github.com/feross/buffer/releases)
- [Commits](https://github.com/feross/buffer/compare/v5.4.0...v5.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-07 10:52:00 -04:00
jywarren
2459c1f7e5 Merge branch 'ui-tests' of github.com:publiclab/image-sequencer into ui-tests 2019-09-07 10:37:57 -04:00
Jeffrey Warren
e94ec775ba Update basicUi.spec.js 2019-09-07 08:41:22 -04:00
Jeffrey Warren
2ad7ed15fd jasmine.getFixtures().fixturesPath = 2019-09-06 23:40:11 -04:00
Jeffrey Warren
ca35349edb Update package.json 2019-09-06 16:17:37 -04:00
Jeffrey Warren
923d7b7fe4 Update Gruntfile.js 2019-09-06 16:17:04 -04:00
Jeffrey Warren
7e2b2bd877 Update Gruntfile.js 2019-09-06 15:00:13 -04:00
Jeffrey Warren
fe3ed2bf30 Update package.json 2019-09-06 14:58:38 -04:00
Jeffrey Warren
0bfe429c6a redo paths in jasmine.json 2019-09-06 13:59:50 -04:00
Jeffrey Warren
50f67af2ec Tried adding grunt browserify && to npm test command
to generate dist files...
2019-09-04 18:51:53 -04:00
Jeffrey Warren
6771f298e3 Merge branch 'main' into ui-tests 2019-09-04 18:20:57 -04:00
dependabot-preview[bot]
9ad6bde18e Bump husky from 2.3.0 to 3.0.5 (#1243)
Bumps [husky](https://github.com/typicode/husky) from 2.3.0 to 3.0.5.
- [Release notes](https://github.com/typicode/husky/releases)
- [Changelog](https://github.com/typicode/husky/blob/master/CHANGELOG.md)
- [Commits](https://github.com/typicode/husky/compare/v2.3.0...v3.0.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-04 16:17:36 -04:00
dependabot-preview[bot]
740acaeec7 Bump gpu.js from 2.0.0-rc.25 to 2.0.0-rc.26 (#1228)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.0.0-rc.25 to 2.0.0-rc.26.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-04 15:16:33 -04:00
Jeffrey Warren
4a25492315 Merge branch 'main' into ui-tests 2019-09-03 14:06:22 -04:00
dependabot-preview[bot]
256e1d65c7 [Security] Bump mixin-deep from 1.3.1 to 1.3.2 (#1234)
Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2. **This update includes a security fix.**
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-03 14:06:03 -04:00
Jeffrey Warren
5cbfee0ba4 add lib to helpers 2019-09-03 14:05:28 -04:00
Jeffrey Warren
1e74ece947 Merge branch 'main' into ui-tests 2019-09-03 14:02:27 -04:00
dependabot-preview[bot]
bab7573f4a Bump commander from 2.19.0 to 3.0.1 (#1244)
Bumps [commander](https://github.com/tj/commander.js) from 2.19.0 to 3.0.1.
- [Release notes](https://github.com/tj/commander.js/releases)
- [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tj/commander.js/compare/v2.19.0...v3.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-03 13:58:19 -04:00
Jeffrey Warren
1174a6922a add jquery/bootstrap js to jasmine.json 2019-09-02 11:36:14 -04:00
Jeffrey Warren
1af8dc17ab Update jasmine.json
https://stackoverflow.com/questions/37284227/how-to-set-source-files-in-jasmine-json-with-jasmine-2
2019-09-01 17:26:22 -04:00
Jeffrey Warren
7bdc71f18f Update jasmine.json
Based on jasmine.yml at e791a381ad/spec/javascripts/support/jasmine.yml (L13-L17)
2019-09-01 17:24:26 -04:00
Jeffrey Warren
e994c939dd Update basicUi.spec.js 2019-09-01 16:39:13 -04:00
Jeffrey Warren
5da914c57b Create basicUi.spec.js 2019-09-01 16:33:12 -04:00
Jeffrey Warren
2554b4ddb4 Update defaultHtmlSequencerUi.spec.js 2019-09-01 16:32:31 -04:00
Jeffrey Warren
c241739ef8 Update index.html 2019-09-01 16:28:54 -04:00
Jeffrey Warren
e7f1e2dfc3 add fixture = loadFixtures('index.html'); 2019-09-01 16:27:13 -04:00
Jeffrey Warren
a7156d58c0 Create index.html 2019-09-01 16:25:28 -04:00
Jeffrey Warren
e739cea236 UI test for quick selector add step 2019-09-01 16:15:30 -04:00
Jeffrey Warren
776cb42bd6 Revert extra test until complete 2019-09-01 16:14:52 -04:00
Jeffrey Warren
fb452f7788 add UI test for quick selector add step
re #1000
2019-09-01 16:09:49 -04:00
Tudor Anghelina
3741d679bd Update Module.js (#1090)
Added const $ = window.$; at line 19 inside extraManipulation(pixels)
2019-08-30 12:58:05 -04:00
Rishabh Shukla
1cc9fd1a50 Update Pull_Request.md (#1233)
* Update pull request template

* Update Pull_Request.md
2019-08-28 17:59:54 -04:00
keshav234156
6613af810c make select a module responsive (#1208) 2019-08-26 09:42:10 -04:00
dependabot-preview[bot]
1b3e95fdd9 Bump tape-run from 6.0.0 to 6.0.1 (#1222)
Bumps [tape-run](https://github.com/juliangruber/tape-run) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/juliangruber/tape-run/releases)
- [Changelog](https://github.com/juliangruber/tape-run/blob/master/History.md)
- [Commits](https://github.com/juliangruber/tape-run/compare/v6.0.0...v6.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-23 08:02:59 -04:00
dependabot-preview[bot]
560e027954 Bump ora from 3.0.0 to 3.4.0 (#1220)
Bumps [ora](https://github.com/sindresorhus/ora) from 3.0.0 to 3.4.0.
- [Release notes](https://github.com/sindresorhus/ora/releases)
- [Commits](https://github.com/sindresorhus/ora/compare/v3.0.0...v3.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-22 14:09:26 -04:00
dependabot-preview[bot]
b43695cedb Bump buffer from 5.2.1 to 5.4.0 (#1221)
Bumps [buffer](https://github.com/feross/buffer) from 5.2.1 to 5.4.0.
- [Release notes](https://github.com/feross/buffer/releases)
- [Commits](https://github.com/feross/buffer/compare/v5.2.1...v5.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-22 12:50:08 -04:00
dependabot-preview[bot]
142c499119 Bump eslint from 6.1.0 to 6.2.1 (#1219)
Bumps [eslint](https://github.com/eslint/eslint) from 6.1.0 to 6.2.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.1.0...v6.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-21 11:32:22 -04:00
dependabot-preview[bot]
03e9e42324 Bump qrcode from 1.3.3 to 1.4.1 (#1176)
Bumps [qrcode](https://github.com/soldair/node-qrcode) from 1.3.3 to 1.4.1.
- [Release notes](https://github.com/soldair/node-qrcode/releases)
- [Changelog](https://github.com/soldair/node-qrcode/blob/master/CHANGELOG.md)
- [Commits](https://github.com/soldair/node-qrcode/compare/v1.3.3...v1.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-21 10:02:17 -04:00
dependabot-preview[bot]
128e31492d Bump gpu.js from 2.0.0-rc.13 to 2.0.0-rc.25 (#1196)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.0.0-rc.13 to 2.0.0-rc.25.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-19 17:02:23 -04:00
aashna27
c7980c1158 grid-overlay for negetive input and 0 (#1205) 2019-08-19 10:59:09 -04:00
dependabot-preview[bot]
66e845d189 Bump @babel/core from 7.4.3 to 7.5.5 (#1177)
Bumps [@babel/core](https://github.com/babel/babel) from 7.4.3 to 7.5.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.4.3...v7.5.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-16 13:02:15 -04:00
dependabot-preview[bot]
a95e57173b Bump lodash from 4.17.13 to 4.17.15 (#1209)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.13 to 4.17.15.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.13...4.17.15)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-16 10:08:46 -04:00
dependabot-preview[bot]
df3b16a1ed Bump jsdom from 15.0.0 to 15.1.1 (#1210)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 15.0.0 to 15.1.1.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/15.0.0...15.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-16 09:45:11 -04:00
dependabot-preview[bot]
9fb87d7831 Bump eslint from 5.16.0 to 6.1.0 (#1182)
Bumps [eslint](https://github.com/eslint/eslint) from 5.16.0 to 6.1.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v5.16.0...v6.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-15 16:41:37 -04:00
dependabot-preview[bot]
451a4ac3f2 Bump tape from 4.10.2 to 4.11.0 (#1139)
Bumps [tape](https://github.com/substack/tape) from 4.10.2 to 4.11.0.
- [Release notes](https://github.com/substack/tape/releases)
- [Commits](https://github.com/substack/tape/compare/v4.10.2...v4.11.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-15 15:44:10 -04:00
aashna27
5b98d5cf44 Pixel set redundancy removed (#1188)
* Pixels.set Redundancy removed

* eslint fixes

* move require to top with const
2019-08-14 15:34:14 -04:00
aashna27
1b5607a339 save dropdown connectivity (#1197)
* dropdown connectivity for 2 options

* comment added

* save gif corrected and preview gif refactored
2019-08-14 14:21:20 -04:00
dependabot-preview[bot]
5dca76c952 Bump lint-staged from 9.1.0 to 9.2.1 (#1190)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 9.1.0 to 9.2.1.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v9.1.0...v9.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-09 17:41:27 +06:00
Devavrat Kalam
74ef42f485 Alphabetically arranged the MODULES.md file #1167 - Sorted index and the corpus (#1186)
* Sorted index and the corpus

* Changed text overlay sequence
2019-08-03 12:05:54 +03:00
dependabot-preview[bot]
e526fa47c6 Bump lodash from 4.17.11 to 4.17.13 (#1165)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-03 09:51:20 +03:00
aashna27
68d5db7cff Opencv.js via npm for blob-detection (#1185) 2019-08-02 16:56:03 +03:00
dependabot-preview[bot]
4dfdccada9 Bump puppeteer from 1.15.0 to 1.19.0 (#1183)
Bumps [puppeteer](https://github.com/GoogleChrome/puppeteer) from 1.15.0 to 1.19.0.
- [Release notes](https://github.com/GoogleChrome/puppeteer/releases)
- [Commits](https://github.com/GoogleChrome/puppeteer/compare/v1.15.0...v1.19.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-26 12:34:48 -05:00
aashna27
0db0943358 resize before loading previews (#1180)
* resize before loading previews

* min resize percentage calculated
2019-07-21 21:54:48 -04:00
aashna27
9464522017 text-overlay in Node (#1125)
* text-overlay in node

* text-overlay in node

* docs added
2019-07-15 12:17:47 -04:00
Slytherin
1b26f71654 Add minify-image module (#1149)
* Add minify-image module

* Add node modules

* corrected path

* Add browser func

* Add test and documentation
2019-07-09 19:38:06 -04:00
dependabot-preview[bot]
8033af9130 Bump gpu.js from 2.0.0-rc.13 to 2.0.0-rc.20 (#1156)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.0.0-rc.13 to 2.0.0-rc.20.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/compare/2.0.0-rc.13...2.0.0-rc.20)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-09 18:33:04 -04:00
dependabot-preview[bot]
45aba96989 Bump lint-staged from 8.1.7 to 9.1.0 (#1158)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 8.1.7 to 9.1.0.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v8.1.7...v9.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-09 17:58:29 -04:00
Harsh Khandeparkar
eff0d383c8 Fix ScopeQuery (#1132)
* update dist

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>

dist update

Revert "dist update"

This reverts commit 9ee2a987e8f978961656ae8f71f6e6702bbbd30d.

* Merge remote-tracking branch 'upstream/main' into main

* add dist

* add new func

* update itermediate

* changes

* fix gitignore

* use scopeQuery

* add mapHtmlTypes test

* scopeQuery tests added

* try something

* change

* fix stepui test

* Remove double quotes

* update new code

* refactor to spec

* fix link elems, add a new scopeQuery Method

* fixed undefined error

* fix everything

* getScope to scopeAll

* add new methods to CONTRIBUTING file
2019-07-01 11:32:11 -04:00
jywarren
a78d6bc43e built 2019-06-25 20:44:37 -04:00
jywarren
cbe4766539 Merge branch 'main' into stable 2019-06-25 20:40:17 -04:00
Slytherin
2c58edfe9a Temporary fix for insert-step btn not working (#1131)
* Temporary fix for insert-step btn not working

* Bump to v3.5.1
2019-06-25 20:28:10 -04:00
Harsh Khandeparkar
257113a948 Shorten UI code with new $step method (#710)
* update dist

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>

dist update

Revert "dist update"

This reverts commit 9ee2a987e8f978961656ae8f71f6e6702bbbd30d.

* Merge remote-tracking branch 'upstream/main' into main

* add dist

* add new func

* update itermediate

* changes

* fix gitignore

* use scopeQuery

* add mapHtmlTypes test

* scopeQuery tests added

* try something

* change

* fix stepui test

* Remove double quotes

* update new code

* refactor to spec
2019-06-21 15:11:10 -04:00
jywarren
f38e1ee180 build 2019-06-21 12:26:03 -04:00
jywarren
2f119659ad Merge branch 'main' into stable 2019-06-21 12:18:16 -04:00
jywarren
8c47bde9ba built 2019-06-15 14:44:49 -04:00
jywarren
b7795aba4d Merge branch 'main' into stable 2019-06-15 14:31:24 -04:00
jywarren
0755eb67da built v3.3.5 2019-05-27 14:00:49 -04:00
jywarren
7c80b7e349 Merge branch 'main' into stable 2019-05-27 13:58:40 -04:00
jywarren
de3c04acf7 Merge branch 'main' into stable 2019-05-25 13:40:42 -04:00
jywarren
92b6a28260 built 2019-05-25 13:38:35 -04:00
jywarren
38204cc668 Merge branch 'main' into stable 2019-05-25 13:11:07 -04:00
jywarren
8950eba228 Merge branch 'main' into stable 2019-05-25 12:01:33 -04:00
jywarren
e15cad5f0f built ui files 2019-05-25 12:00:09 -04:00
jywarren
46b2bb8167 Merge branch 'main' into stable 2019-05-25 11:47:54 -04:00
jywarren
1950d608e7 Merge branch 'main' into stable 2019-05-25 11:45:25 -04:00
jywarren
9e170368f7 version bump 2019-05-23 22:02:07 -04:00
jywarren
47a60a8e46 built 2019-05-23 21:57:28 -04:00
jywarren
9ca869fd79 Merge branch 'main' into stable 2019-05-23 15:25:42 -04:00
jywarren
506a238c83 built files 2019-04-30 14:44:02 -04:00
jywarren
6ff7b124e1 Merge branch 'main' into stable 2019-04-30 14:42:12 -04:00
jywarren
b29796e4f1 built v3.3.0 2019-04-19 13:14:42 -04:00
68 changed files with 113568 additions and 2158 deletions

View File

@@ -6,11 +6,11 @@ Make sure these boxes are checked before your pull request (PR) is ready to be r
* [ ] code is in uniquely-named feature branch and has no merge conflicts
* [ ] PR is descriptively titled
* [ ] ask `@publiclab/is-reviewers` for help, in a comment below
* [ ] Insert-step functionality is working correct as expected.
> We're happy to help you get this ready -- don't be afraid to ask for help, and **don't be discouraged** if your tests fail at first!
If tests do fail, click on the red `X` to learn why by reading the logs.
Please be sure you've reviewed our contribution guidelines at https://publiclab.org/contributing-to-public-lab-software
Please make sure to get at least two reviews before asking for merging the PR as that would make the PR more reliable on our part
Thanks!

View File

@@ -5,7 +5,7 @@ Happily accepting pull requests; to edit the core library, modify files in `./sr
On ARM based devices, the `gl` module may require some libraries to be re-installed:
`sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config` -- see https://github.com/stackgl/headless-gl#ubuntudebian for more.
`sudo apt-get install -y build-essential xserver-xorg-dev libxext-dev libxi-dev libglu1-mesa-dev libglew-dev pkg-config` -- see https://github.com/stackgl/headless-gl#ubuntudebian for more.
Most contribution (we imagine) would be in the form of API-compatible modules, which need not be directly included.
@@ -425,8 +425,10 @@ var $step = scopeQuery.scopeSelector(scope),
This will return an object with a constructor which returns a `jQuery` object (from inside the scope) but with new `elem` and `elemAll` methods.
#### Methods of the Returned Object
* `elem()`: Selects an element inside the scope;
* `elemAll()`: Selects all the instances of a given element inside the scope;
* `elem()`: Selects an element inside the scope.
* `elemAll()`: Selects all the instances of a given element inside the scope.
* `getScope()`: Returns the scope as a DOM element.
* `getDomElem()`: Returns the scoped element as a DOM element instead of a jquery object.
#### Example

View File

@@ -2,6 +2,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify-es');
grunt.loadNpmTasks('grunt-browser-sync');
grunt.loadNpmTasks('grunt-contrib-jasmine');
require('matchdep')
.filterDev('grunt-*')
@@ -57,6 +58,7 @@ module.exports = function(grunt) {
dest: 'dist/image-sequencer-ui.js'
}
},
browserSync: {
dev: {
options: {
@@ -64,6 +66,33 @@ module.exports = function(grunt) {
server: './'
}
}
},
jasmine: {
imagesequencer: {
src: 'dist/image-sequencer.js',
options: {
specs: 'test/ui/spec/*spec.js',
vendor: [
'node_modules/jquery/dist/jquery.min.js',
'node_modules/bootstrap/dist/js/bootstrap.min.js',
'node_modules/jasmine-jquery/lib/jasmine-jquery.js',
'src/ui/prepareDynamic.js',
'node_modules/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js',
'node_modules/imgareaselect/jquery.imgareaselect.dev.js',
'node_modules/gifshot/dist/gifshot.min.js',
'node_modules/downloadjs/download.min.js',
'examples/lib/scrollToTop.js',
'node_modules/selectize/dist/js/standalone/selectize.min.js',
'node_modules/opencv.js/opencv.js',
'dist/image-sequencer-ui.js'
],
keepRunner: true,
'--web-security' : false,
'--local-to-remote-url-access' : true,
'--ignore-ssl-errors' : true
}
}
}
});

18237
dist/image-sequencer-ui.js vendored Normal file

File diff suppressed because it is too large Load Diff

1
dist/image-sequencer-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

89861
dist/image-sequencer.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/image-sequencer.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -3,48 +3,230 @@ Documentation of various Modules
List of Module Documentations
1. [Crop](#crop-module)
2. [Segmented-Colormap](#segmented-colormap-module)
3. [FisheyeGl](#fisheyeGl-module)
4. [Add QR](#Add-QR-module)
5. [Average](#average-module)
6. [Blend](#blend-module)
7. [Blur](#blur-module)
8. [Brightness](#brightness-module)
9. [Channel](#channel-module)
10. [Colorbar](#colorbar-module)
11. [Colormap](#colormap-module)
12. [Contrast](#contrast-module)
13. [Convolution](#convolution-module)
14. [DecodeQr](#decodeQr-module)
15. [Dither](#dither-module)
16. [DrawRectangle](#draw-rectangle-module)
17. [Dynamic](#dynamic-module)
18. [Edge-Detect](#edge-detect-module)
1. [Add QR](#Add-QR-module)
2. [Average](#average-module)
3. [Blend](#blend-module)
4. [Blur](#blur-module)
5. [Brightness](#brightness-module)
6. [Channel](#channel-module)
7. [Colorbar](#colorbar-module)
8. [Colormap](#colormap-module)
9. [ColorTemperature](#color-temperature)
10. [Contrast](#contrast-module)
11. [Convolution](#convolution-module)
12. [Crop](#crop-module)
13. [DecodeQr](#decodeQr-module)
14. [Dither](#dither-module)
15. [DrawRectangle](#draw-rectangle-module)
16. [Dynamic](#dynamic-module)
17. [Edge-Detect](#edge-detect-module)
18. [FisheyeGl](#fisheyeGl-module)
19. [FlipImage](#flipimage-module)
20. [Gamma-Correction](#gamma-correction-module)
21. [Gradient](#gradient-module)
22. [Histogram](#histogram-module)
23. [Import-image](#import-image-module)
24. [Invert](#invert-module)
25. [Ndvi](#ndvi-module)
26. [Ndvi-Colormap](#ndvi-colormap-module)
27. [Overlay](#overlay-module)
28. [PaintBucket](#paint-bucket-module)
29. [Resize](#resize-module)
30. [ReplaceColor](#replacecolor-module)
31. [Rotate](#rotate-module)
32. [Saturation](#saturation-module)
33. [Threshold](#threshold)
34. [Tint](#tint)
35. [ColorTemperature](#color-temperature)
36. [Grid-Overlay](#grid-overlay)
22. [Grid-Overlay](#grid-overlay)
23. [Histogram](#histogram-module)
24. [Import-image](#import-image-module)
25. [Invert](#invert-module)
26. [MinifyImage](#minify-image)
27. [Ndvi](#ndvi-module)
28. [Ndvi-Colormap](#ndvi-colormap-module)
29. [NoiseReduction](#noise-reduction)
30. [Overlay](#overlay-module)
31. [PaintBucket](#paint-bucket-module)
32. [ReplaceColor](#replacecolor-module)
33. [Resize](#resize-module)
34. [Rotate](#rotate-module)
35. [Saturation](#saturation-module)
36. [Segmented-Colormap](#segmented-colormap-module)
37. [Text-Overlay](#text-overlay)
38. [Threshold](#threshold)
39. [Tint](#tint)
## add-qr-module
This module Adds QR corresponding to the given string.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('add-qr',options)
.run()
```
where `options` is an object with the following properties:
* size : size of QR code in pixels (default 200)
* qrCodeString : input string to generate QR code
## average-module
This module is used for averaging all the pixels of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('average',options)
.run()
```
## blend-module
This module is used for blending two images .
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blend',options)
.run()
```
where `options` is an object with the following properties:
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
## Blob Analysis
This module uses Opencv.js for detecting and marking blob/region in microscopic images. It requires an opencv.js file to
be loaded before using the functionalities which is currently being loaded to the webpage via script.It supports both environments, Node.js and browser for processing.
As the size of opencv.js file is quite large, the future versions will focus on loading it asynchronously, on demand of the the module to optimise performance.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blob-analysis')
.run()
```
## blur-module
This module is used for applying a Gaussian blur effect.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blur',options)
.run()
```
where `options` is an object with the following property:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
## brightness-module
This module is used for changing the brightness of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('brightness',options)
.run()
```
where `options` is an object with the following property:
* brightness : brightness of the image in percentage (0 to 100; default 100)
## channel-module
This module is used for forming a grayscale image by applying one of the three primary colors.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('channel',options)
.run()
```
where `options` is an object with the following property:
* channel : color of the channel (red, green, blue; default green)
## colorbar-module
This module is used for displaying an image with a colorbar.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colorbar',options)
.run()
```
where `options` is an object with the following properties:
* colormap : Name of the Colormap(default, greyscale, stretched, fastie, brntogrn, blutoredjet, colors16; default: default)
* x : X-position of the image on which the new image is overlayed (default 0)
* y : Y-position of the image on which the new image is overlayed (default 0)
* h : height of resulting cropped image (default : 50% of input image width )
## colormap-module
This module is used for mapping brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colormap',options)
.run()
```
where `options` is an object with the following property:
* colormap : Name of the Colormap ( greyscale, stretched, fastie, brntogrn, blutoredjet, colors16)
## Color Temperature
This changes the color temperature of the image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('color-temperature',options)
.run()
```
where `options` is an object with the following property:
* temperature : temperature between 0 - 40,000 kelvin (default 6000)
## contrast-module
This module is used for changing the contrast of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('contrast',options)
.run()
```
where `options` is an object with the following property:
* contrast : contrast for the given image (-100 to 100; default : 70)
## convolution-module
This module is used for performing image-convolution.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('convolution',options)
.run()
```
where `options` is an object with the following properties:
* constantFactor : a constant factor, multiplies all the kernel values by that factor (default : 1/9)
* kernelValues : nine space separated numbers representing the kernel values in left to right and top to bottom format(default : 1 1 1 1 1 1 1 1 1)
## crop-module
This module is used to crop an image.
#### Usage
```js
@@ -64,208 +246,9 @@ Where `options` is an object having the properties `x`, `y`, `w`, `h`. This diag
* `options.h` : half of image height
## segmented-colormap-module
This module is used to map the pixels of the image to a segmented colormap.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('segmented-colormap',options)
.run()
```
where `options` is an object with the property `colormap`. `options.colormap` can be:
* "default" : [[0, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 50, 50]]]
* "greyscale" : [[0, [0, 0, 0], [255, 255, 255]], [1, [255, 255, 255], [255, 255, 255]]]
* "stretched" : [[0, [0, 0, 255], [0, 0, 255]], [0.1, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.7, [255, 255, 0], [255, 50, 50]], [0.9, [255, 50, 50], [255, 50, 50]]]
* "fastie" : [[0, [255, 255, 255], [0, 0, 0]], [0.167, [0, 0, 0], [255, 255, 255]], [0.33, [255, 255, 255], [0, 0, 0]], [0.5, [0, 0, 0], [140, 140, 255]], [0.55, [140, 140, 255], [0, 255, 0]], [0.63, [0, 255, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 0, 0]], [0.95, [255, 0, 0], [255, 0, 255]]]
* A custom array.
## fisheyeGl-module
This module is used for correcting Fisheye or Lens Distortion
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('fisheye-gl',options)
.run()
```
where `options` is an object with the following properties:
* a : a correction (0 to 4; default 1)
* b : b correction (0 to 4; default 1)
* Fx : x correction (0 to 4; default 1)
* Fy : y correction (0 to 4; default 1)
* scale : The ratio to which the original image is to be scaled (0 to 20; default 1.5)
* x : Field of View x (0 to 2; default 1)
* y : Field of View y (0 to 2; default 1)
## add-qr-module
This module Adds QR corresponding to the given string.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('add-qr',options)
.run()
```
where `options` is an object with the following properties:
* size : size of QR code in pixels (default 200)
* qrCodeString : input string to generate QR code
## average-module
This module is used for averaging all the pixels of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('average',options)
.run()
```
## blend-module
This module is used for blending two images .
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blend',options)
.run()
```
where `options` is an object with the following properties:
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
## blur-module
This module is used for applying a Gaussian blur effect.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blur',options)
.run()
```
where `options` is an object with the following property:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
## brightness-module
This module is used for changing the brightness of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('brightness',options)
.run()
```
where `options` is an object with the following property:
* brightness : brightness of the image in percentage (0 to 100; default 100)
## channel-module
This module is used for forming a grayscale image by applying one of the three primary colors.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('channel',options)
.run()
```
where `options` is an object with the following property:
* channel : color of the channel (red, green, blue; default green)
## colorbar-module
This module is used for displaying an image with a colorbar.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colorbar',options)
.run()
```
where `options` is an object with the following properties:
* colormap : Name of the Colormap(default, greyscale, stretched, fastie, brntogrn, blutoredjet, colors16; default: default)
* x : X-position of the image on which the new image is overlayed (default 0)
* y : Y-position of the image on which the new image is overlayed (default 0)
* h : height of resulting cropped image (default : 50% of input image width )
## colormap-module
This module is used for mapping brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colormap',options)
.run()
```
where `options` is an object with the following property:
* colormap : Name of the Colormap ( greyscale, stretched, fastie, brntogrn, blutoredjet, colors16)
## contrast-module
This module is used for changing the contrast of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('contrast',options)
.run()
```
where `options` is an object with the following property:
* contrast : contrast for the given image (-100 to 100; default : 70)
## convolution-module
This module is used for performing image-convolution.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('convolution',options)
.run()
```
where `options` is an object with the following properties:
* constantFactor : a constant factor, multiplies all the kernel values by that factor (default : 1/9)
* kernelValues : nine space separated numbers representing the kernel values in left to right and top to bottom format(default : 1 1 1 1 1 1 1 1 1)
## decodeQr-module
This module is used for decoding a QR in image (if present).
#### Usage
```js
@@ -279,8 +262,7 @@ This module is used for decoding a QR in image (if present).
This module approximates a color from a mixture of other colors when the required color is not available, creating illusions of the color that is not present actually.
[more info on wikipedia](https://en.wikipedia.org/wiki/Dither)
## Usage
#### Usage
```js
sequencer.loadImage('PATH')
@@ -290,10 +272,10 @@ This module approximates a color from a mixture of other colors when the require
where `options` is an object with the following property:
* dither : Can select the name of the Dithering Algorithm(default none)
## draw-rectangle-module
This module helps to draw a rectangle on the image with a starting and ending corner with the specified thickness and color of the border.
## Usage
```js
@@ -309,10 +291,10 @@ where `options` is an object with the following properties:
* thickness : thickness of the border (default 1)
* color : RGBA values separated by a space (default "0 0 0 255")
## dynamic-module
This module is used for producing each color channel based on the original image's color.
#### Usage
```js
@@ -327,6 +309,7 @@ where `options` is an object with the following properties:
* blue : expression for blue channel (R, G, B and A as inputs; default b)
* monochrome: fallback for other channels if none provided (default : r+g+b/3)
## edge-detect-module
This module is used for detecting images.
@@ -343,12 +326,33 @@ where `options` is an object with the following properties:
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
## fisheyeGl-module
This module is used for correcting Fisheye or Lens Distortion
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('fisheye-gl',options)
.run()
```
where `options` is an object with the following properties:
* a : a correction (0 to 4; default 1)
* b : b correction (0 to 4; default 1)
* Fx : x correction (0 to 4; default 1)
* Fy : y correction (0 to 4; default 1)
* scale : The ratio to which the original image is to be scaled (0 to 20; default 1.5)
* x : Field of View x (0 to 2; default 1)
* y : Field of View y (0 to 2; default 1)
## flipimage-module
This module is used for flipping the image on the selected axis.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('flip-image',options)
@@ -373,6 +377,7 @@ This module is used for applying gamma correction.
where `options` is an object with the following property:
* adjustment : Inverse of actual gamma factor (default 0.2)
## gradient-module
This module is used for finding gradient of the image.
@@ -384,6 +389,23 @@ This module is used for finding gradient of the image.
.run()
```
## Grid Overlay
This adds the grid over an image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('grid-overlay',options)
.run()
```
where `options` is an object with the following property:
* options.x : The value at which the grid line should start in x-axis.
* options.y : The value at which the grid line should start in y-axis.
* color : Color for the grid on the image.
## histogram-module
This module is used for calculating histogram of the image.
@@ -398,6 +420,7 @@ This module is used for calculating histogram of the image.
where `options` is an object with the following property:
* gradient : boolean value used to toggle gradient along x-axis (true or false; default true)
## import-image-module
This module is used for importing a new image and replacing the original with it.
@@ -412,6 +435,7 @@ This module is used for importing a new image and replacing the original with it
where `options` is an object with the following property:
* url : url of the new image (local image url or data url;default : "./images/monarch.png")
## invert-module
This module is used for inverting the image.
@@ -423,6 +447,21 @@ This module is used for inverting the image.
.run()
```
## Minify Image
This module minifies the image using lossy compression that is the image-dimensions are not lost but the size is reduced.
The module supports jpg/jpeg/webp images in browser; but the node version supports all of the types.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('minify-image')
.run()
```
## ndvi-module
This module is used for applying ndvi technique to the image.
@@ -437,6 +476,7 @@ This module is used for applying ndvi technique to the image.
where `options` is an object with the following property:
* filter : filter for NDVI (blue or red; default red)
## ndvi-colormap-module
This module is used for demonstrating ndvi and colormap properties consecutively.
@@ -448,6 +488,22 @@ This module is used for demonstrating ndvi and colormap properties consecutively
.run()
```
## Noise-Reduction
Noise in an image are atypical pixels that are not representing the color or the exposure of the scene correctly. This Noise Reduction module reduces the noise in the image by using either median filtering or mean filtering techniques to change the RGB value of the pixels to create a smoother and fuller image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('noise-reduction',options)
.run()
```
where `options` is an object with the property `method`. `options.method` can be:
* Median Filtering: Set the RGB value of the pixel to the median RGB pixel value of all adjacent pixels (maximum 8 adjacent pixels and itself)
* Mean Filtering: Set the RGB value of the pixel to the mean RGB pixel value of all adjacent pixels (maximum 8 adjacent pixels and itself)
## overlay-module
This module is used for overlaying an Image over another .
@@ -464,10 +520,10 @@ where `options` is an object with the following properties:
* y : Y-position of the image on which the new image is overlayed (default 0)
* offset : offset to the step on which the output of the last step is overlayed (default -2)
## paint-bucket-module
This module fills any polygonal shape with the specified color in pixels.
## Usage
```js
@@ -482,19 +538,6 @@ where `options` is an object with the following property:
* fillColor : they are four spaced seperated numbers representing the RGBA values of fill-color (default "100 100 100 255")
* tolerance : it is the % tolerance (default 10)
## resize-module
This module is used for resizing an image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('resize',options)
.run()
```
where `options` is an object with the following property:
* resize : Percentage value of resize (default 125%)
## replacecolor-module
@@ -512,6 +555,22 @@ where `options` is an object with the following properties:
* color : three space separated numbers representing the RGB values of color to be replaced (default "228 86 81")
* tolerance : it is the % tolerance (default 50)
## resize-module
This module is used for resizing an image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('resize',options)
.run()
```
where `options` is an object with the following property:
* resize : Percentage value of resize (default 125%)
## rotate-module
This module is used for rotating an image.
@@ -526,6 +585,7 @@ This module is used for rotating an image.
where `options` is an object with the following property:
* rotate : angular value for rotation in degrees (between 0 and 360; default 0)
## saturation-module
This module is used for changing the saturation of the image.
@@ -540,11 +600,49 @@ This module is used for changing the saturation of the image.
where `options` is an object with the following property:
* saturation : saturation for the new image (between 0 and 2; default 0)
## segmented-colormap-module
This module is used to map the pixels of the image to a segmented colormap.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('segmented-colormap',options)
.run()
```
where `options` is an object with the property `colormap`. `options.colormap` can be:
* "default" : [[0, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 50, 50]]]
* "greyscale" : [[0, [0, 0, 0], [255, 255, 255]], [1, [255, 255, 255], [255, 255, 255]]]
* "stretched" : [[0, [0, 0, 255], [0, 0, 255]], [0.1, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.7, [255, 255, 0], [255, 50, 50]], [0.9, [255, 50, 50], [255, 50, 50]]]
* "fastie" : [[0, [255, 255, 255], [0, 0, 0]], [0.167, [0, 0, 0], [255, 255, 255]], [0.33, [255, 255, 255], [0, 0, 0]], [0.5, [0, 0, 0], [140, 140, 255]], [0.55, [140, 140, 255], [0, 255, 0]], [0.63, [0, 255, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 0, 0]], [0.95, [255, 0, 0], [255, 0, 255]]]
* A custom array.
## Text Overlay
The modules allows to add text to image in both browser and node environment. We have the options to modify the font-size and also support few font-styles. The text color can also be modified.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('grid-overlay',options)
.run()
```
The options can take various attributes like,
var options = { text : 'Hello World', size : '12'};
## Threshold
Thresholding is used to create binary images.
## Usage
#### Usage
```js
sequencer.loadImage('PATH')
@@ -559,8 +657,7 @@ where `options` is an object with the following property:
## Tint
It adds color tint to an image
## Usage
#### Usage
```js
sequencer.loadImage('PATH')
@@ -570,34 +667,3 @@ It adds color tint to an image
where `options` is an object with the following property:
* color : RGB values seperated by a space (default "0 0 255")
* factor : amount of tint (default 0.5)
## Color Temperature
This changes the color temperature of the image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('color-temperature',options)
.run()
```
where `options` is an object with the following property:
* temperature : temperature between 0 - 40,000 kelvin (default 6000)
## Grid Overlay
This adds the grid over an image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('grid-overlay',options)
.run()
```
where `options` is an object with the following property:
* options.x : The value at which the grid line should start in x-axis.
* options.y : The value at which the grid line should start in y-axis.
* color : Color for the grid on the image.

View File

@@ -44,6 +44,7 @@ body > .container-fluid {
.panel {
margin-left: 20px;
margin-right: 20px;
min-width:400px;
}
.nomargin {
@@ -61,6 +62,7 @@ body > .container-fluid {
border-radius: 8px;
text-align: center;
color: #444;
min-width:300px;
}
.hover {
@@ -103,7 +105,10 @@ body > .container-fluid {
}
#add-step-btn{
margin-left: 10px;
width: 100%
}
.selectize-input {
width: 100%;
}
#addStep .labels {
@@ -140,7 +145,6 @@ body > .container-fluid {
#dwnld {
max-width: 500px;
margin: 20px auto;
margin-left: 5px;
}
#gif_element {

View File

@@ -5,50 +5,15 @@ var defaultHtmlSequencerUi = require('./lib/defaultHtmlSequencerUi.js'),
urlHash = require('./lib/urlHash.js'),
insertPreview = require('./lib/insertPreview.js');
window.onload = function() {
initializeSequencerUi = function initializeSequencerUi() {
sequencer = ImageSequencer();
function refreshOptions() {
// Load information of all modules (Name, Inputs, Outputs)
var modulesInfo = sequencer.modulesInfo();
var addStepSelect = $('#addStep select');
addStepSelect.html('');
// Add modules to the addStep dropdown
for (var m in modulesInfo) {
if (modulesInfo[m] && modulesInfo[m].name)
addStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
);
}
// Null option
addStepSelect.append('<option value="" disabled selected>Select a Module</option>');
addStepSelect.selectize({
sortField: 'text'
});
}
refreshOptions();
$(window).on('scroll', scrollFunction);
function scrollFunction() {
var shouldDisplay = $('body').scrollTop() > 20 || $(':root').scrollTop() > 20;
$('#move-up').css({
display: shouldDisplay ? 'block' : 'none'
});
}
function topFunction() {
$('body').animate({scrollTop: 0});
$(':root').animate({scrollTop: 0});
}
$('#move-up').on('click', topFunction);
// UI for each step:
sequencer.setUI(DefaultHtmlStepUi(sequencer));
@@ -62,18 +27,12 @@ window.onload = function() {
sequencer.loadImage('images/tulips.png', ui.onLoad);
}
var resetSequence = function(){
var r = confirm('Do you want to reset the sequence?');
if (r)
window.location = '/';
};
$('#addStep select').on('change', ui.selectNewStepUi);
$('#addStep #add-step-btn').on('click', ui.addStepUi);
$('#resetButton').on('click', resetSequence);
//Module button radio selection
$('.radio-group .radio').on('click', function() {
$('.radio-group .radio').on('click', function () {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
@@ -84,29 +43,27 @@ window.onload = function() {
$(this).removeClass('selected');
});
function displayMessageOnSaveSequence(){
$('.savesequencemsg').fadeIn();
setTimeout(function() {
$('.savesequencemsg').fadeOut();
}, 1000);
}
$('body').on('click', 'button.remove', ui.removeStepUi);
$('#save-seq').click(() => {
var result = window.prompt('Please give a name to your sequence... (Saved sequence will only be available in this browser).');
if(result){
result = result + ' (local)';
sequencer.saveSequence(result, sequencer.toString());
sequencer.loadModules();
displayMessageOnSaveSequence();
refreshOptions();
$('#saveButton').on('click', function () {
// different handlers triggered for different dropdown options
let dropDownValue = $('#selectSaveOption option:selected').val();
if (dropDownValue == 'save-image') {
$('.download-btn:last()').trigger('click');
}
else if (dropDownValue == 'save-gif') {
handleSavePNG();
}
else if (dropDownValue == 'save-seq') {
saveSequence();
}
});
var isWorkingOnGifGeneration = false;
let isWorkingOnGifGeneration = false;
$('.js-view-as-gif').on('click', function(event) {
// Prevent user from triggering generation multiple times
$('.js-view-as-gif').on('click', function (event) {
/* Prevent user from triggering generation multiple times*/
if (isWorkingOnGifGeneration) return;
isWorkingOnGifGeneration = true;
@@ -116,23 +73,10 @@ window.onload = function() {
button.innerHTML = '<i class="fa fa-circle-o-notch fa-spin"></i>';
try {
// Select all images from previous steps
var imgs = document.getElementsByClassName('step-thumbnail');
/* Get gif resources of previous steps */
let options = getGifResources();
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
var options = {
'gifWidth': imgs[0].width,
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
};
gifshot.createGIF(options, function(obj) {
gifshot.createGIF(options, function (obj) { // gif generation
if (!obj.error) {
// Final gif encoded with base64 format
var image = obj.image;
@@ -141,13 +85,11 @@ window.onload = function() {
animatedImage.id = 'gif_element';
animatedImage.src = image;
let modal = $('#js-download-gif-modal');
var modal = $('#js-download-gif-modal');
$('#js-download-as-gif-button').one('click', function() {
$('#js-download-as-gif-button').one('click', function () {
// Trigger download
download(image, 'index.gif', 'image/gif');
downloadGif(image);
// Close modal
modal.modal('hide');
});
@@ -175,10 +117,42 @@ window.onload = function() {
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
});
function getGifResources() {
/* Returns an object with specific gif options */
let imgs = document.getElementsByClassName('step-thumbnail');
var imgSrcs = [];
// Pushes image sources of all the modules in dom
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
var options = { // gif frame options
'gifWidth': imgs[0].width,
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
};
return options;
}
function handleSavePNG() {
let options = getGifResources();
gifshot.createGIF(options, function(obj){
downloadGif(obj.image);
});
}
function downloadGif(image) {
download(image, 'index.gif', 'image/gif');// downloadjs library function
}
// image selection and drag/drop handling from examples/lib/imageSelection.js
sequencer.setInputStep({
dropZoneSelector: '#dropzone',
@@ -190,7 +164,7 @@ window.onload = function() {
var util = intermediateHtmlStepUi(sequencer);
step.output.src = reader.result;
sequencer.run({ index: 0 });
if(typeof step.options !== 'undefined')
if (typeof step.options !== 'undefined')
step.options.step.imgElement.src = reader.result;
else
step.imgElement.src = reader.result;
@@ -201,7 +175,7 @@ window.onload = function() {
var step = sequencer.steps[0];
step.output.src = url;
sequencer.run({ index: 0 });
if(typeof step.options !== 'undefined')
if (typeof step.options !== 'undefined')
step.options.step.imgElement.src = url;
else
step.imgElement.src = url;
@@ -218,3 +192,61 @@ window.onload = function() {
insertPreview.updatePreviews('images/tulips.png', '#addStep');
}
};
function scrollFunction() {
var shouldDisplay = $('body').scrollTop() > 20 || $(':root').scrollTop() > 20;
$('#move-up').css({
display: shouldDisplay ? 'block' : 'none'
});
}
function topFunction() {
$('body').animate({scrollTop: 0});
$(':root').animate({scrollTop: 0});
}
function refreshOptions() {
// Load information of all modules (Name, Inputs, Outputs)
var modulesInfo = sequencer.modulesInfo();
var addStepSelect = $('#addStep select');
addStepSelect.html('');
// Add modules to the addStep dropdown
for (var m in modulesInfo) {
if (modulesInfo[m] && modulesInfo[m].name)
addStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
);
}
// Null option
addStepSelect.append('<option value="" disabled selected>Select a Module</option>');
addStepSelect.selectize({
sortField: 'text'
});
}
var resetSequence = function () {
var r = confirm('Do you want to reset the sequence?');
if (r)
window.location = '/';
};
function displayMessageOnSaveSequence() {
$('.savesequencemsg').fadeIn();
setTimeout(function () {
$('.savesequencemsg').fadeOut();
}, 3000);
}
function saveSequence() { // 1. save seq
var result = window.prompt('Please give a name to your sequence... (Saved sequence will only be available in this browser).');
if (result) {
result = result + ' (local)';
sequencer.saveSequence(result, sequencer.toString()); // 1.a study saveSequence
sequencer.loadModules();
displayMessageOnSaveSequence();
refreshOptions();
}
}

View File

@@ -1,7 +1,5 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -55,7 +53,7 @@
<div class="container-fluid">
<header class="text-center">
<header class="text-center" style="min-width: 450px">
<h1><a href="/" target='_blank' class="name-header">Image Sequencer</a></h1>
<p>
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original
@@ -91,7 +89,7 @@
</section>
<hr />
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules.
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules in browser's localStorage.
</p>
<div class="row">
<div class="col-sm-8">
@@ -139,15 +137,15 @@
<p>Crop</p>
</div>
</div>
<div class="row center-align">
<div class="col-md-8">
<div class="row justify-content-center">
<div class="col-lg-8">
<select id="selectStep">
<select id="selectStep" class="text-center">
<!-- The default null selection has been appended manually in demo.js
This is because the options in select are overritten when options are appended.-->
</select>
</div>
<div class="col-md-4">
<div class="col-lg-4">
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
</div>
<div class="row center-align">
@@ -188,10 +186,10 @@
<div style="text-align:center;">
<h2 style="margin-top:20px">Save</h2>
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
<option>Save as PNG</option>
<option>Save as GIF (all steps)</option>
<option>Save sequence</option>
<option>Save sequence string</option>
<option value="save-image">Save as PNG</option>
<option value="save-gif">Save as GIF (all steps)</option>
<option value="save-seq">Save sequence</option>
<option value="save-seq-string">Save sequence string</option>
</select>
<p><button id="saveButton" class="btn btn-primary btn-lg save-button">Save</button></p>
<p><button class="btn btn-default btn-lg js-view-as-gif" id="gif">Preview GIF</button></p>
@@ -228,10 +226,12 @@
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
<script type="text/javascript">
var sequencer;
$(function () {
var sequencer;
initializeSequencerUi();
})
</script>
<script async src="../node_modules/opencv.js/opencv.js" type="text/javascript"></script>
</body>

View File

@@ -8,18 +8,21 @@
// output values, step information.
// See documetation for more details.
var intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js');
var urlHash = require('./urlHash.js');
var _ = require('lodash');
var mapHtmlTypes = require('./mapHtmltypes');
const intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
urlHash = require('./urlHash.js'),
_ = require('lodash'),
mapHtmlTypes = require('./mapHtmltypes'),
scopeQuery = require('./scopeQuery');
function DefaultHtmlStepUi(_sequencer, options) {
let $step, $stepAll;
options = options || {};
var stepsEl = options.stepsEl || document.querySelector('#steps');
var selectStepSel = options.selectStepSel = options.selectStepSel || '#selectStep';
function onSetup(step, stepOptions) {
if (step.options && step.options.description)
step.description = step.options.description;
@@ -67,8 +70,14 @@ function DefaultHtmlStepUi(_sequencer, options) {
var parser = new DOMParser();
step.ui = parser.parseFromString(step.ui, 'text/html');
step.ui = step.ui.querySelector('div.container-fluid');
$step = scopeQuery.scopeSelector(step.ui);
$stepAll = scopeQuery.scopeSelectorAll(step.ui);
step.ui.$step = $step;
step.ui.$stepAll = $stepAll;
step.linkElements = step.ui.querySelectorAll('a');
step.imgElement = step.ui.querySelector('a img.img-thumbnail');
step.imgElement = $step('a img.img-thumbnail')[0];
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
var inputs = _sequencer.modulesInfo(step.name).inputs;
@@ -144,12 +153,12 @@ function DefaultHtmlStepUi(_sequencer, options) {
html +
'\
</div>';
step.ui.querySelector('div.details').appendChild(div);
$step('div.details').append(div);
}
$(step.ui.querySelector('div.panel-footer')).append(
$step('div.panel-footer').append(
'<div class="cal collapse in"><button type="submit" class="btn btn-sm btn-default btn-save" disabled = "true" >Apply</button> <small style="padding-top:2px;">Press apply to see changes</small></div>'
);
$(step.ui.querySelector('div.panel-footer')).prepend(
$step('div.panel-footer').prepend(
'<button class="pull-right btn btn-default btn-sm insert-step" >\
<span class="insert-text"><i class="fa fa-plus"></i> Insert Step</span><span class="no-insert-text" style="display:none">Close</span></button>\
<button class="pull-right btn btn-default btn-sm download-btn" style="margin-right:2px" >\
@@ -159,39 +168,40 @@ function DefaultHtmlStepUi(_sequencer, options) {
}
if (step.name != 'load-image') {
step.ui
.querySelector('div.trash-container')
$step('div.trash-container')
.prepend(
parser.parseFromString(tools, 'text/html').querySelector('div')
);
$(step.ui.querySelectorAll('.remove')).on('click', function() {notify('Step Removed', 'remove-notification');});
$(step.ui.querySelectorAll('.insert-step')).on('click', function() { util.insertStep(step.ID); });
$stepAll('.remove').on('click', function() {notify('Step Removed', 'remove-notification');});
$stepAll('.insert-step').on('click', function() { util.insertStep(step.ID); });
// Insert the step's UI in the right place
if (stepOptions.index == _sequencer.steps.length) {
stepsEl.appendChild(step.ui);
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
if($('#steps .step-container:nth-last-child(2)'))
$('#steps .step-container:nth-last-child(2) .insert-step').prop('disabled', false);
} else {
}
else {
stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]);
}
}
else {
$('#load-image').append(step.ui);
}
$(step.ui.querySelector('.toggle')).on('click', () => {
$(step.ui.querySelector('.toggleIcon')).toggleClass('rotated');
$(step.ui.querySelectorAll('.cal')).collapse('toggle');
$step('.toggle').on('click', () => {
$step('.toggleIcon').toggleClass('rotated');
$stepAll('.cal').collapse('toggle');
});
$(step.imgElement).on('mousemove', _.debounce(() => imageHover(step), 150));
$(step.imgElement).on('click', (e) => {e.preventDefault(); });
$(step.ui.querySelectorAll('#color-picker')).colorpicker();
$stepAll('#color-picker').colorpicker();
function saveOptions(e) {
function saveOptions(e) { // 1. SAVE OPTIONS
e.preventDefault();
if (optionsChanged){
$(step.ui.querySelector('div.details'))
$step('div.details')
.find('input,select')
.each(function(i, input) {
$(input)
@@ -204,7 +214,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
// modify the url hash
urlHash.setUrlHashParameter('steps', _sequencer.toString());
// disable the save button
$(step.ui.querySelector('.btn-save')).prop('disabled', true);
$step('.btn-save').prop('disabled', true);
optionsChanged = false;
changedInputs = 0;
}
@@ -215,15 +225,15 @@ function DefaultHtmlStepUi(_sequencer, options) {
changedInputs += hasChangedBefore ? inputChanged ? 0 : -1 : inputChanged ? 1 : 0;
optionsChanged = changedInputs > 0;
$(step.ui.querySelector('.btn-save')).prop('disabled', !optionsChanged);
$step('.btn-save').prop('disabled', !optionsChanged);
return inputChanged;
}
var
changedInputs = 0,
optionsChanged = false;
$(step.ui.querySelector('.input-form')).on('submit', saveOptions);
$(step.ui.querySelectorAll('.target')).each(function(i, input) {
$step('.input-form').on('submit', saveOptions);
$stepAll('.target').each(function(i, input) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false)
@@ -248,19 +258,19 @@ function DefaultHtmlStepUi(_sequencer, options) {
}
function onDraw(step) {
$(step.ui.querySelector('.load')).show();
$(step.ui.querySelector('img')).hide();
$(step.ui.querySelectorAll('.load-spin')).show();
function onDraw() {
$step('.load').show();
$step('img').hide();
$stepAll('.load-spin').show();
}
function onComplete(step) {
$(step.ui.querySelector('img')).show();
$(step.ui.querySelectorAll('.load-spin')).hide();
$(step.ui.querySelector('.load')).hide();
$step('img').show();
$stepAll('.load-spin').hide();
$step('.load').hide();
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
var imgthumbnail = step.ui.querySelector('.img-thumbnail');
var imgthumbnail = $step('.img-thumbnail').getDomElem();
for (let index = 0; index < step.linkElements.length; index++) {
if (step.linkElements[index].contains(imgthumbnail))
step.linkElements[index].href = step.imgElement.src;
@@ -271,7 +281,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
return output.split('/')[1].split(';')[0];
}
$(step.ui.querySelectorAll('.download-btn')).on('click', () => {
$stepAll('.download-btn').on('click', () => {
for (let index = 0; index < step.linkElements.length; index++){
@@ -294,18 +304,18 @@ function DefaultHtmlStepUi(_sequencer, options) {
for (var i in inputs) {
if (step.options[i] !== undefined) {
if (inputs[i].type.toLowerCase() === 'input')
$(step.ui.querySelector('div[name="' + i + '"] input'))
$step('div[name="' + i + '"] input')
.val(step.options[i])
.data('initValue', step.options[i]);
if (inputs[i].type.toLowerCase() === 'select')
$(step.ui.querySelector('div[name="' + i + '"] select'))
$step('div[name="' + i + '"] select')
.val(step.options[i])
.data('initValue', step.options[i]);
}
}
for (var i in outputs) {
if (step[i] !== undefined)
$(step.ui.querySelector('div[name="' + i + '"] input'))
$step('div[name="' + i + '"] input')
.val(step[i]);
}
}

View File

@@ -23,7 +23,10 @@ function generatePreview(previewStepName, customValues, path, selector) {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
previewSequencer.loadImage(path, loadPreview);
if(previewStepName === 'resize')
insertPreview(path);
else
previewSequencer.loadImage(path, loadPreview);
}
function updatePreviews(src, selector) {
@@ -44,11 +47,30 @@ function updatePreviews(src, selector) {
}
};
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
});
var img = new Image();
img.onload = function(){
var height = img.height;
var width = img.width;
let percentage = (80 / height) * 100; //take the min resize value that fits the preview area => (new-width/orig_ht) - '80 as the preview area has 80*80 dimension
percentage = Math.max((80 / width) * 100, percentage); // make sure that one dimension doesn't resize greater, leading distorting preview-area fitting
percentage = Math.ceil(percentage);
var sequencer = ImageSequencer();
sequencer.loadImage(src, function(){
this.addSteps('resize', {['resize']: percentage + '%'});
this.run((src)=>{
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
});
});
});
};
img.src = src;
}
module.exports = {
generatePreview : generatePreview,
updatePreviews : updatePreviews

View File

@@ -65,32 +65,33 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
}
function selectNewStepUi() {
var insertSelect = $(step.ui.querySelector('.insert-step-select'));
function selectNewStepUi($step) {
var insertSelect = $step('.insert-step-select');
var m = insertSelect.val();
$(step.ui.querySelector('.insertDiv .info')).html(_sequencer.modulesInfo(m).description);
$(step.ui.querySelector('.insertDiv .add-step-btn')).prop('disabled', false);
$step('.insertDiv .info').html(_sequencer.modulesInfo(m).description);
$step('.insertDiv .add-step-btn').prop('disabled', false);
}
var toggleDiv = function(callback = function(){}){
$(step.ui.querySelector('.insertDiv')).collapse('toggle');
if ($(step.ui.querySelector('.insert-text')).css('display') != 'none'){
$(step.ui.querySelector('.insert-text')).fadeToggle(200, function(){$(step.ui.querySelector('.no-insert-text')).fadeToggle(200, callback);});
var toggleDiv = function($step, callback = function(){}){
$step('.insertDiv').collapse('toggle');
if ($step('.insert-text').css('display') != 'none'){
$step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback);});
}
else {
$(step.ui.querySelector('.no-insert-text')).fadeToggle(200, function(){$(step.ui.querySelector('.insert-text')).fadeToggle(200, callback);});
$step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback);});
}
};
insertStep = function (id) {
const $step = step.ui.$step,
$stepAll = step.ui.$stepAll;
var modulesInfo = _sequencer.modulesInfo();
var parser = new DOMParser();
var addStepUI = stepUI();
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
if ($(step.ui.querySelector('.insertDiv')).length > 0){
toggleDiv();
if ($step('.insertDiv').length > 0){
toggleDiv($step);
}
else {
step.ui
@@ -98,14 +99,14 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
.insertAdjacentElement('afterend',
addStepUI
);
toggleDiv(function(){
toggleDiv($step, function(){
insertPreview.updatePreviews(step.output, '.insertDiv');
});
}
$(step.ui.querySelector('.insertDiv .close-insert-box')).off('click').on('click', function(){toggleDiv(function(){});});
$step('.insertDiv .close-insert-box').off('click').on('click', function(){toggleDiv(function(){});});
var insertStepSelect = $(step.ui.querySelector('.insert-step-select'));
var insertStepSelect = $step('.insert-step-select');
insertStepSelect.html('');
// Add modules to the insertStep dropdown
for (var m in modulesInfo) {
@@ -117,30 +118,30 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
insertStepSelect.selectize({
sortField: 'text'
});
$(step.ui.querySelector('.inserDiv .add-step-btn')).prop('disabled', true);
$step('.inserDiv .add-step-btn').prop('disabled', true);
insertStepSelect.append('<option value="" disabled selected>Select a Module</option>');
$(step.ui.querySelector('.insertDiv .radio-group .radio')).on('click', function () {
$step('.insertDiv .radio-group .radio').on('click', function () {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
$(step.ui.querySelector('.insert-step-select')).val(newStep);
selectNewStepUi();
insert(id);
$step('.insert-step-select').val(newStep);
selectNewStepUi($step);
insert(id, $step);
$(this).removeClass('selected');
});
insertStepSelect.on('change', selectNewStepUi);
$(step.ui.querySelector('.insertDiv .add-step-btn')).on('click', function () { insert(id); });
insertStepSelect.on('change', () => {selectNewStepUi($step);});
$step('.insertDiv .add-step-btn').on('click', function () { insert(id, $step); });
};
function insert(id) {
function insert(id, $step) {
options = options || {};
var insertStepSelect = $(step.ui.querySelector('.insert-step-select'));
var insertStepSelect = $step('.insert-step-select');
if (insertStepSelect.val() == 'none') return;
var newStepName = insertStepSelect.val();
toggleDiv();
toggleDiv($step);
var sequenceLength = 1;
if (sequencer.sequences[newStepName]) {
sequenceLength = sequencer.sequences[newStepName].length;

View File

@@ -0,0 +1,68 @@
/**
* @method $scope
* @param {"DOMNode"} scope A DOM Node as the scope
*/
function $scope(scope) {
return function(queryString){
var element = $(scope.querySelector(queryString));
element.elem = function(queryString){
return new $scope(scope)(queryString);
};
element.elemAll = function(queryString){
return new $scopeAll(scope)(queryString);
};
element.getDomElem = function(i = 0){
return element[i];
};
element.getScope = () => scope;
return element;
};
}
/**
* @method $scopeAll
* @param {"DOMNode"} scope A DOM Node as the scope
*/
function $scopeAll(scope){
return function(queryString){
var element = $(scope.querySelectorAll(queryString));
element.elem = function(queryString){
return new $scope(scope)(queryString);
};
element.elemAll = function(queryString){
return new $scopeAll(scope)(queryString);
};
element.getDomElem = function(i = 0){
return element[i];
};
element.getScope = () => scope;
return element;
};
}
/**
* @method scopeSelector
* @description A scoped jQuery selector
* @param {"DOMNode"} scope DOM Node as the scope
*/
function scopeSelector(scope){
return $scope(scope);
}
/**
* @method scopeSelectorAll
* @description A scoped jQuery multiple selector
* @param {"DOMNode} scope DOM Node as the scope
*/
function scopeSelectorAll(scope){
return $scopeAll(scope);
}
module.exports = {
scopeSelector,
scopeSelectorAll
};

3387
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,13 @@
{
"name": "image-sequencer",
"version": "3.5.0",
"version": "3.5.1",
"description": "A modular JavaScript image manipulation library modeled on a storyboard.",
"main": "src/ImageSequencer.js",
"scripts": {
"debug": "TEST=true node ./index.js -i ./examples/images/monarch.png -s invert",
"test": "TEST=true istanbul cover tape test/core/*.js test/core/ui/user-interface.js test/core/modules/*.js | tap-spec; node test/core/sequencer/benchmark.js; browserify test/core/sequencer/meta-modules.js test/core/sequencer/image-sequencer.js test/core/sequencer/chain.js test/core/sequencer/replace.js test/core/sequencer/import-export.js test/core/sequencer/run.js test/core/sequencer/dynamic-imports.js test/core/util/*.js | tape-run --render=\"tap-spec\"",
"test-ui": "node node_modules/jasmine/bin/jasmine test/spec/*.js",
"test-ui": "grunt browserify && grunt jasmine",
"test-ui-unit": "node node_modules/jasmine/bin/jasmine test/ui/spec/unit/*spec.js",
"setup": "npm i && npm i -g grunt grunt-cli && grunt build",
"start": "grunt serve"
},
@@ -30,14 +31,16 @@
"url": "https://github.com/publiclab/image-sequencer/issues"
},
"dependencies": {
"atob": "^2.1.2",
"base64-img": "^1.0.4",
"bootstrap": "~3.4.0",
"bootstrap-colorpicker": "^2.5.3",
"buffer": "~5.2.1",
"commander": "^2.11.0",
"buffer": "~5.4.0",
"commander": "^3.0.1",
"compressorjs": "^1.0.5",
"data-uri-to-buffer": "^2.0.0",
"downloadjs": "^1.4.7",
"eslint": "^5.16.0",
"eslint": "^6.1.0",
"fisheyegl": "^0.1.2",
"font-awesome": "~4.7.0",
"geotiff": "^1.0.0-beta.6",
@@ -47,6 +50,9 @@
"gpu.js": "^2.0.0-rc.12",
"image-sequencer-invert": "^1.0.0",
"imagejs": "0.0.9",
"imagemin": "^7.0.0",
"imagemin-jpegtran": "^6.0.0",
"imagemin-pngquant": "^8.0.0",
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
"istanbul": "^0.4.5",
"jasmine": "^3.4.0",
@@ -55,6 +61,7 @@
"jsqr": "^1.1.1",
"lodash": "^4.17.11",
"ndarray": "^1.0.18",
"opencv.js": "^1.2.1",
"ora": "^3.0.0",
"pace": "0.0.4",
"puppeteer": "^1.14.0",
@@ -62,6 +69,7 @@
"readline-sync": "^1.4.7",
"save-pixels": "~2.3.4",
"selectize": "^0.12.6",
"spawn-sync": "^2.0.0",
"urify": "^2.1.1",
"webgl-distort": "0.0.2"
},
@@ -71,20 +79,21 @@
"@babel/plugin-syntax-object-rest-spread": "^7.2.0",
"babelify": "^10.0.0",
"browserify": "16.2.3",
"eslint": "^5.16.0",
"eslint": "^6.1.0",
"grunt": "^1.0.3",
"grunt-browser-sync": "^2.2.0",
"grunt-browserify": "^5.0.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-uglify-es": "^3.3.0",
"grunt-contrib-watch": "^1.1.0",
"husky": "^2.2.0",
"grunt-contrib-jasmine": "~1.0.3",
"husky": "^3.0.5",
"image-filter-core": "~2.0.2",
"image-filter-threshold": "~2.0.1",
"jasmine-core": "^3.3.0",
"jasmine-jquery": "^2.1.1",
"jasmine-spec-reporter": "^4.2.1",
"lint-staged": "^8.1.6",
"lint-staged": "^9.1.0",
"looks-same": "^7.0.0",
"matchdep": "^2.0.0",
"tap-spec": "^5.0.0",

View File

@@ -1,26 +0,0 @@
describe('Preview UI HTML', function() {
var InsertPreview = require('../examples/lib/insertPreview');
var sequencer = require('../src/ImageSequencer')();
var insertPreview;
var options = { brightness: 50 };
beforeEach(()=>{
insertPreview = InsertPreview;
spyOn(insertPreview, 'generatePreview');
spyOn(insertPreview, 'updatePreviews');
insertPreview.generatePreview('brightness', options, 'src', 'selector');
insertPreview.updatePreviews('src', 'selector');
});
it('generate preview ui', function() {
expect(insertPreview.generatePreview).toHaveBeenCalledWith('brightness', options, 'src', 'selector');
});
it('update preview ui', function() {
expect(insertPreview.updatePreviews).toHaveBeenCalledWith('src', 'selector');
});
});

View File

@@ -1,19 +0,0 @@
describe('Intermediate step HTML', function() {
var IntermediateHtmlStepUi = require('../examples/lib/intermediateHtmlStepUi');
var sequencer = require('../src/ImageSequencer')();
var intermediateHtmlStepUi;
beforeEach(()=>{
intermediateHtmlStepUi = new IntermediateHtmlStepUi(sequencer);
spyOn(intermediateHtmlStepUi, 'insertStep');
intermediateHtmlStepUi.insertStep();
});
it('insert step ui', function() {
expect(intermediateHtmlStepUi.insertStep).toHaveBeenCalled();
});
});

View File

@@ -1,11 +0,0 @@
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}

View File

@@ -1,40 +0,0 @@
describe('URL manipulation methods', function() {
var UrlHash = require('../examples/lib/urlHash');
var urlHash;
var params = {
module: 'brightness',
brightness: 50
};
beforeEach(()=>{
urlHash = UrlHash;
spyOn(urlHash, 'getUrlHashParameters');
spyOn(urlHash, 'getUrlHashParameter');
spyOn(urlHash, 'setUrlHashParameters');
spyOn(urlHash, 'setUrlHashParameter');
urlHash.getUrlHashParameters();
urlHash.getUrlHashParameter('module');
urlHash.setUrlHashParameters(params);
urlHash.setUrlHashParameter('module', 'brightness');
});
it('gets url hash params from window hash', function() {
expect(urlHash.getUrlHashParameters).toHaveBeenCalled();
});
it('gets url hash param from params object', function() {
expect(urlHash.getUrlHashParameter).toHaveBeenCalledWith('module');
});
it('accepts param object and sets url hash params', function() {
expect(urlHash.setUrlHashParameters).toHaveBeenCalledWith(params);
});
it('accepts param key-value pair and sets url hash params', function() {
expect(urlHash.setUrlHashParameter).toHaveBeenCalledWith('module', 'brightness');
});
});

View File

@@ -4,6 +4,8 @@ require('./util/getStep.js');
ImageSequencer = function ImageSequencer(options) {
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
var sequencer = (this.name == 'ImageSequencer') ? this : this.sequencer;
options = options || {};
options.inBrowser = options.inBrowser === undefined ? isBrowser : options.inBrowser;
@@ -256,8 +258,8 @@ ImageSequencer = function ImageSequencer(options) {
fs.writeFileSync('./src/Modules.js', mods);
}
function saveSequence(name, sequenceString) {
const sequence = stringToJSON(sequenceString);
function saveSequence(name, sequenceString) { // 4. save sequence
const sequence = str.stringToJSON(sequenceString);
// Save the given sequence string as a module
if (options.inBrowser) {
// Inside the browser we save the meta-modules using the Web Storage API
@@ -282,7 +284,6 @@ ImageSequencer = function ImageSequencer(options) {
this.sequences = require('./SavedSequences.json');
}
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
return {
//literals and objects

View File

@@ -5,6 +5,7 @@ module.exports = {
'add-qr': require('./modules/AddQR'),
'average': require('./modules/Average'),
'blend': require('./modules/Blend'),
'blob-analysis': require('./modules/BlobAnalysis'),
'blur': require('./modules/Blur'),
'brightness': require('./modules/Brightness'),
'canvas-resize': require('./modules/CanvasResize'),
@@ -28,6 +29,7 @@ module.exports = {
'gradient': require('./modules/Gradient'),
'grid-overlay': require('./modules/GridOverlay'),
'import-image': require('./modules/ImportImage'),
'minify-image': require('./modules/MinifyImage'),
'invert': require('image-sequencer-invert'),
'ndvi': require('./modules/Ndvi'),
'ndvi-colormap': require('./modules/NdviColormap'),

View File

@@ -1,4 +1,6 @@
module.exports = exports = function (options, pixels, oldPixels, callback) {
const pixelSetter = require('../../util/pixelSetter.js');
var QRCode = require('qrcode');
QRCode.toDataURL(options.qrCodeString, function (err, url) {
var getPixels = require('get-pixels');
@@ -26,17 +28,11 @@ module.exports = exports = function (options, pixels, oldPixels, callback) {
for (var m = 0; m < width; m++) {
for (var n = 0; n < height; n++) {
if (m >= xe && n >= ye) {
pixels.set(m, n, 0, qrPixels.get(m - xe, n - ye, 0));
pixels.set(m, n, 1, qrPixels.get(m - xe, n - ye, 1));
pixels.set(m, n, 2, qrPixels.get(m - xe, n - ye, 2));
pixels.set(m, n, 3, qrPixels.get(m - xe, n - ye, 3));
pixelSetter(m, n, [qrPixels.get(m - xe, n - ye, 0), qrPixels.get(m - xe, n - ye, 1), qrPixels.get(m - xe, n - ye, 2), qrPixels.get(m - xe, n - ye, 3)], pixels);
}
else {
pixels.set(m, n, 0, oldPixels.get(m, n, 0));
pixels.set(m, n, 1, oldPixels.get(m, n, 1));
pixels.set(m, n, 2, oldPixels.get(m, n, 2));
pixels.set(m, n, 3, oldPixels.get(m, n, 3));
pixelSetter(m, n, [oldPixels.get(m, n, 0), oldPixels.get(m, n, 1), oldPixels.get(m, n, 2), oldPixels.get(m, n, 3)], pixels);
}
}

View File

@@ -16,6 +16,7 @@ module.exports = function Average(options, UI) {
// do the averaging
function extraManipulation(pixels) {
const $ = window.$;
var i = 0, sum = [0, 0, 0, 0];
while (i < pixels.data.length) {
sum[0] += pixels.data[i++];

View File

@@ -0,0 +1,81 @@
module.exports = function(pixels, options, priorStep){
var $ = require('jquery'); // to make Blob-analysis work for node.js
var img = $(priorStep.imgElement);
if(Object.keys(img).length === 0){
img = $(priorStep.options.step.imgElement);
}
var canvas = document.createElement('canvas');
canvas.width = pixels.shape[0];
canvas.height = pixels.shape[1];
var ctx = canvas.getContext('2d');
ctx.drawImage(img[0], 0, 0);
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let src = cv.matFromImageData(imgData);
let dst = new cv.Mat();
let gray = new cv.Mat();
let opening = new cv.Mat();
let imageBg = new cv.Mat();
let imageFg = new cv.Mat();
let distTrans = new cv.Mat();
let unknown = new cv.Mat();
let markers = new cv.Mat();
// gray and threshold image
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
// get background
let M = cv.Mat.ones(3, 3, cv.CV_8U);
cv.erode(gray, gray, M);
cv.dilate(gray, opening, M);
cv.dilate(opening, imageBg, M, new cv.Point(-1, -1), 3);
// distance transform
cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
// get foreground
cv.threshold(distTrans, imageFg, 0.7 * 1, 255, cv.THRESH_BINARY);
imageFg.convertTo(imageFg, cv.CV_8U, 1, 0);
cv.subtract(imageBg, imageFg, unknown);
// get connected components markers
cv.connectedComponents(imageFg, markers);
for (let i = 0; i < markers.rows; i++) {
for (let j = 0; j < markers.cols; j++) {
markers.intPtr(i, j)[0] = markers.ucharPtr(i, j)[0] + 1;
if (unknown.ucharPtr(i, j)[0] == 255) {
markers.intPtr(i, j)[0] = 0;
}
}
}
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
cv.watershed(src, markers);
// draw barriers
for (let i = 0; i < markers.rows; i++) {
for (let j = 0; j < markers.cols; j++) {
if (markers.intPtr(i, j)[0] == -1) {
src.ucharPtr(i, j)[0] = 255; // R
src.ucharPtr(i, j)[1] = 0; // G
src.ucharPtr(i, j)[2] = 0; // B
}
}
}
cv.imshow(canvas, src);
src.delete(); dst.delete(); gray.delete(); opening.delete(); imageBg.delete();
imageFg.delete(); distTrans.delete(); unknown.delete(); markers.delete(); M.delete();
var myImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
pixels.data = myImageData.data;
return pixels;
};

View File

@@ -0,0 +1,43 @@
module.exports = function BlobAnalysis(options, UI){
var output;
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var priorStep = this.getStep(-1); // get the previous step to process it
function extraManipulation(pixels){
pixels = require('./BlobAnalysis')(pixels, options, priorStep);
return pixels;
}
function output(image, datauri, mimetype){
step.output = { src: datauri, format: mimetype};
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

@@ -0,0 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];

View File

@@ -0,0 +1,6 @@
{
"name": "Blob Analysis",
"description": "Blob/Region identification for microscopic images.",
"inputs": {},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#blob-analysis"
}

View File

@@ -1,4 +1,6 @@
module.exports = exports = function(pixels, blur) {
const pixelSetter = require('../../util/pixelSetter.js');
let kernel = kernelGenerator(blur),
pixs = {
r: [],
@@ -24,9 +26,10 @@ module.exports = exports = function(pixels, blur) {
for (let y = 0; y < pixels.shape[1]; y++){
for (let x = 0; x < pixels.shape[0]; x++){
pixels.set(x, y, 0, Math.max(0, Math.min(conPix[0][y][x], 255)));
pixels.set(x, y, 1, Math.max(0, Math.min(conPix[1][y][x], 255)));
pixels.set(x, y, 2, Math.max(0, Math.min(conPix[2][y][x], 255)));
var pixelvalue = [Math.max(0, Math.min(conPix[0][y][x], 255)),
Math.max(0, Math.min(conPix[1][y][x], 255)),
Math.max(0, Math.min(conPix[2][y][x], 255))];
pixelSetter(x, y, pixelvalue, pixels);
}
}

View File

@@ -4,10 +4,10 @@
module.exports = function canvasResize(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const pixelSetter = require('../../util/pixelSetter.js');
var output;
function draw(input, callback, progressObj) {
options.width = parseInt(options.width || defaults.width);
@@ -21,16 +21,15 @@ module.exports = function canvasResize(options, UI) {
var step = this;
function extraManipulation(pixels) {
let newPixels = require('ndarray')(new Uint8Array(4 * options.width * options.height).fill(0), [options.width, options.height, 4]);
let iMax = options.width - options.x,
jMax = options.height - options.y;
for (let i = 0; i < iMax && i < pixels.shape[0]; i++) {
for (let j = 0; j < jMax && j < pixels.shape[1]; j++) {
let x = i + options.x, y = j + options.y;
newPixels.set(x, y, 0, pixels.get(i, j, 0));
newPixels.set(x, y, 1, pixels.get(i, j, 1));
newPixels.set(x, y, 2, pixels.get(i, j, 2));
newPixels.set(x, y, 3, pixels.get(i, j, 3));
pixelSetter(x, y, [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2), pixels.get(i, j, 3)], newPixels);
}
}
return newPixels;

View File

@@ -1,4 +1,6 @@
module.exports = function ColorTemperature(options, UI) {
const pixelSetter = require('../../util/pixelSetter.js');
var output;
@@ -38,17 +40,12 @@ module.exports = function ColorTemperature(options, UI) {
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
r_data = pixels.get(i, j, 0);
r_new_data = (255 / r) * r_data;
pixels.set(i, j, 0, r_new_data);
var rgbdata = [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2)];
rgbdata[0] = (255 / r) * rgbdata[0];
rgbdata[1] = (255 / g) * rgbdata[1];
rgbdata[2] = (255 / b) * rgbdata[2];
pixelSetter(i, j, rgbdata, pixels);
g_data = pixels.get(i, j, 1);
g_new_data = (255 / g) * g_data;
pixels.set(i, j, 1, g_new_data);
b_data = pixels.get(i, j, 2);
b_new_data = (255 / b) * b_data;
pixels.set(i, j, 2, b_new_data);
}
}

View File

@@ -1,4 +1,5 @@
var _ = require('lodash');
const pixelSetter = require('../../util/pixelSetter.js');
module.exports = exports = function(pixels, contrast) {
let oldpix = _.cloneDeep(pixels);
@@ -10,37 +11,19 @@ module.exports = exports = function(pixels, contrast) {
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
var r = oldpix.get(i, j, 0) / 255.0;
r -= 0.5;
r *= contrast;
r += 0.5;
r *= 255;
if (r < 0) r = 0;
if (r > 255) r = 255;
var g = oldpix.get(i, j, 1) / 255.0;
g -= 0.5;
g *= contrast;
g += 0.5;
g *= 255;
if (g < 0) g = 0;
if (g > 255) g = 255;
var b = oldpix.get(i, j, 2) / 255.0;
b -= 0.5;
b *= contrast;
b += 0.5;
b *= 255;
if (b < 0) b = 0;
if (b > 255) b = 255;
pixels.set(i, j, 0, r);
pixels.set(i, j, 1, g);
pixels.set(i, j, 2, b);
var rgbarray = [oldpix.get(i, j, 0) / 255.0, oldpix.get(i, j, 1) / 255.0, oldpix.get(i, j, 2) / 255.0];
for(var idx = 0;idx < 3;idx++){
rgbarray[idx] -= 0.5;
rgbarray[idx] *= contrast;
rgbarray[idx] += 0.5;
rgbarray[idx] *= 255;
if (rgbarray[idx] < 0) rgbarray[idx] = 0;
if (rgbarray[idx] > 255) rgbarray[idx] = 255;
}
pixelSetter(i, j, rgbarray, pixels);
}
}
return pixels;

View File

@@ -1,4 +1,6 @@
var _ = require('lodash');
const pixelSetter = require('../../util/pixelSetter.js');
module.exports = exports = function(pixels, constantFactor, kernelValues, texMode) {
let kernel = kernelGenerator(constantFactor, kernelValues),
pixs = {
@@ -24,9 +26,8 @@ module.exports = exports = function(pixels, constantFactor, kernelValues, texMod
for (let y = 0; y < pixels.shape[1]; y++){
for (let x = 0; x < pixels.shape[0]; x++){
pixels.set(x, y, 0, Math.max(0, Math.min(conPix[0][y][x], 255)));
pixels.set(x, y, 1, Math.max(0, Math.min(conPix[1][y][x], 255)));
pixels.set(x, y, 2, Math.max(0, Math.min(conPix[2][y][x], 255)));
var value = [Math.max(0, Math.min(conPix[0][y][x], 255)), Math.max(0, Math.min(conPix[1][y][x], 255)), Math.max(0, Math.min(conPix[2][y][x], 255))];
pixelSetter(x, y, value, pixels);
}
}

View File

@@ -1,5 +1,6 @@
module.exports = exports = function(pixels, options){
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const pixelSetter = require('../../util/pixelSetter.js');
options.startingX = options.startingX || defaults.startingX;
options.startingY = options.startingY || defaults.startingY;
@@ -17,10 +18,8 @@ module.exports = exports = function(pixels, options){
var drawSide = function(startX, startY, endX, endY){
for (var n = startX; n <= endX + thickness; n++){
for (var k = startY; k <= endY + thickness; k++){
pixels.set(n, k, 0, color[0]);
pixels.set(n, k, 1, color[1]);
pixels.set(n, k, 2, color[2]);
//pixels.set(n, k, 3, color[3]);
pixelSetter(n, k, [color[0], color[1], color[2]], pixels); //to remove 4th channel - pixels.set(n, k, 3, color[3]);
}
}
};

View File

@@ -1,4 +1,6 @@
// Define kernels for the sobel filter
const pixelSetter = require('../../util/pixelSetter.js');
const kernelx = [
[-1, 0, 1],
[-2, 0, 2],
@@ -41,19 +43,14 @@ module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, useHyst
return pixels;
};
function supress(pixels, pixel) {
pixels.set(pixel[0], pixel[1], 0, 0);
pixels.set(pixel[0], pixel[1], 1, 0);
pixels.set(pixel[0], pixel[1], 2, 0);
pixels.set(pixel[0], pixel[1], 3, 255);
pixelSetter(pixel[0], pixel[1], [0, 0, 0, 255], pixels);
}
function preserve(pixels, pixel) {
pixels.set(pixel[0], pixel[1], 0, 255);
pixels.set(pixel[0], pixel[1], 1, 255);
pixels.set(pixel[0], pixel[1], 2, 255);
pixels.set(pixel[0], pixel[1], 3, 255);
pixelSetter(pixel[0], pixel[1], [255, 255, 255, 255], pixels);
}
// sobelFilter function that convolves sobel kernel over every pixel

View File

@@ -1,12 +1,12 @@
module.exports = function flipImage(oldPixels, pixels, axis) {
const pixelSetter = require('../../util/pixelSetter.js');
var width = oldPixels.shape[0],
height = oldPixels.shape[1];
function copyPixel(x1, y1, x2, y2){
pixels.set(x1, y1, 0, oldPixels.get(x2, y2, 0));
pixels.set(x1, y1, 1, oldPixels.get(x2, y2, 1));
pixels.set(x1, y1, 2, oldPixels.get(x2, y2, 2));
pixels.set(x1, y1, 3, oldPixels.get(x2, y2, 3));
pixelSetter(x1, y1, [oldPixels.get(x2, y2, 0), oldPixels.get(x2, y2, 1), oldPixels.get(x2, y2, 2), oldPixels.get(x2, y2, 3)], pixels);
}
function flip(){

View File

@@ -1,9 +1,11 @@
module.exports = function Invert(options, UI) {
const pixelSetter = require('../../util/pixelSetter.js');
var output;
// The function which is called on every draw.
function draw(input, callback, progressObj) {
function draw(input, callback) {
var getPixels = require('get-pixels');
var savePixels = require('save-pixels');
@@ -21,10 +23,8 @@ module.exports = function Invert(options, UI) {
for (var i = 0; i < pixels.shape[0]; i++) {
for (var j = 0; j < pixels.shape[1]; j++) {
let val = (i / width) * 255;
pixels.set(i, j, 0, val);
pixels.set(i, j, 1, val);
pixels.set(i, j, 2, val);
pixels.set(i, j, 3, 255);
pixelSetter(i, j, [val, val, val, 255], pixels);
}
}
var chunks = [];

View File

@@ -1,27 +1,31 @@
module.exports = exports = function(pixels, options){
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const pixelSetter = require('../../util/pixelSetter.js');
options.x = Number(options.x) || defaults.x;
options.y = Number(options.y) || defaults.y;
if(Number(options.x) == 0){
options.x = 1;
}
if( Number(options.y) == 0) {
options.y = 1;
}
options.x = Math.abs(Number(options.x)) || defaults.x;
options.y = Math.abs(Number(options.y)) || defaults.y;
color = options.color || defaults.color;
color = color.substring(color.indexOf('(') + 1, color.length - 1); // extract only the values from rgba(_,_,_,_)
color = color.split(',');
for(var x = 0; x < pixels.shape[0]; x += options.x){
for(var y = 0 ; y < pixels.shape[1]; y++){
pixels.set(x, y, 0, color[0]);
pixels.set(x, y, 1, color[1]);
pixels.set(x, y, 2, color[2]);
//pixels.set(x, y, 3, color[3]);
pixelSetter(x, y, [color[0], color[1], color[2]], pixels); // to remove 4th channel - pixels.set(x, y, 3, color[3]);
}
}
for(var y = 0; y < pixels.shape[1]; y += options.y){
for(var x = 0 ; x < pixels.shape[0]; x++){
pixels.set(x, y, 0, color[0]);
pixels.set(x, y, 1, color[1]);
pixels.set(x, y, 2, color[2]);
//pixels.set(x, y, 3, color[3]);
pixelSetter(x, y, [color[0], color[1], color[2]], pixels); // to remove 4th channel - pixels.set(x, y, 3, color[3]);
}
}

View File

@@ -7,7 +7,9 @@ module.exports = function Channel(options, UI) {
function draw(input, callback, progressObj) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const pixelSetter = require('../../util/pixelSetter.js');
options.gradient = options.gradient || defaults.gradient;
options.gradient = JSON.parse(options.gradient);
@@ -32,10 +34,8 @@ module.exports = function Channel(options, UI) {
for (let x = 0; x < 256; x++) {
for (let y = 0; y < 256; y++) {
pixels.set(x, y, 0, 255);
pixels.set(x, y, 1, 255);
pixels.set(x, y, 2, 255);
pixels.set(x, y, 3, 255);
pixelSetter(x, y, [255, 255, 255, 255], pixels);
}
}
@@ -43,9 +43,8 @@ module.exports = function Channel(options, UI) {
if (options.gradient) {
for (let x = 0; x < 256; x++) {
for (let y = 0; y < 10; y++) {
pixels.set(x, 255 - y, 0, x);
pixels.set(x, 255 - y, 1, x);
pixels.set(x, 255 - y, 2, x);
pixelSetter(x, 255 - y, [x, x, x], pixels);
}
}
}
@@ -56,9 +55,8 @@ module.exports = function Channel(options, UI) {
let pixCount = Math.round(convfactor * hist[x]);
for (let y = startY; y < pixCount; y++) {
pixels.set(x, 255 - y, 0, 204);
pixels.set(x, 255 - y, 1, 255);
pixels.set(x, 255 - y, 2, 153);
pixelSetter(x, 255 - y, [204, 255, 153], pixels);
}
}

View File

@@ -0,0 +1,102 @@
module.exports = function MinifyImage(options, UI) {
var output;
if (!options.inBrowser) {
base64Img = require('base64-img');
imagemin = require('imagemin');
imageminJpegtran = require('imagemin-jpegtran');
imageminPngquant = require('imagemin-pngquant');
}
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
// create a view into the buffer
var ia = new Uint8Array(ab);
// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {
type: mimeString
});
return blob;
}
if (options.inBrowser) {
var Compressor = require('compressorjs');
var blob = dataURItoBlob(input.src);
new Compressor(blob, {
quality: options.quality || 0.5,
success(result) {
var reader = new FileReader();
reader.readAsDataURL(result);
reader.onloadend = function () {
base64data = reader.result;
output(base64data, input.format);
if (callback) callback();
return;
};
},
error(err) {
console.log(err.message);
},
});
}
else{
let filePath = __dirname + '/images/';
var returnPath = base64Img.imgSync(input.src, filePath, 'test');
(async () => {
const files = await imagemin([returnPath], {
destination: __dirname + '/results/',
plugins: [
imageminJpegtran(),
imageminPngquant({
quality: [0.6, 0.8]
})
]
});
var destPath = __dirname + '/results/test.' + input.format;
var data = base64Img.base64Sync(destPath);
output(data, input.format);
if (callback) callback();
})();
}
function output(datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = {
src: datauri,
format: mimetype
};
}
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

@@ -0,0 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];

View File

@@ -0,0 +1,14 @@
{
"name": "minify-image",
"description": "Minifies the given image (Works for jpg/jpeg/webp images in browser)",
"url": "https://github.com/publiclab/image-sequencer/tree/master/MODULES.md",
"inputs": {
"quality":{
"type": "float",
"desc": "quality aspect of the given image",
"default": "0.5"
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#add-qr-module"
}

View File

@@ -6,7 +6,7 @@ module.exports = function Noise(pixels, method) {
for(let y = 0; y < pixels.shape[1]; y++){
for(let x = 0; x < pixels.shape[0]; x++){
let i = 0, k = 0, windowr = [],windowg = [], windowb = [];
let i = 0, k = 0, windowr = [], windowg = [], windowb = [];
while( k <= 8){
let newX = x + neighbourX[k], newY = y + neighbourY[k];
@@ -14,9 +14,9 @@ module.exports = function Noise(pixels, method) {
if( newX >= 0 && newX < pixels.shape[0])
{
if( newY >= 0 && newY < pixels.shape[1]){
windowr[i] = pixels.get((newX),(newY),0);
windowg[i] = pixels.get((newX),(newY),1);
windowb[i] = pixels.get((newX),(newY),2);
windowr[i] = pixels.get((newX), (newY), 0);
windowg[i] = pixels.get((newX), (newY), 1);
windowb[i] = pixels.get((newX), (newY), 2);
i++;
}
}
@@ -27,22 +27,22 @@ module.exports = function Noise(pixels, method) {
windowg.sort();
windowb.sort();
if(i%2 == 0)
if(i % 2 == 0)
{
let value = windowr[i/2] + windowr[(i/2)-1];
pixels.set(x,y,0,value);
let value = windowr[i / 2] + windowr[(i / 2) - 1];
pixels.set(x, y, 0, value);
value = windowg[i/2] + windowg[(i/2)-1];
pixels.set(x,y,1,value);
value = windowg[i / 2] + windowg[(i / 2) - 1];
pixels.set(x, y, 1, value);
value = windowb[i/2] + windowb[(i/2)-1];
pixels.set(x,y,2,value);
value = windowb[i / 2] + windowb[(i / 2) - 1];
pixels.set(x, y, 2, value);
}
else {
pixels.set(x, y, 0, windowr[Math.floor(i/2)]);
pixels.set(x, y, 1, windowg[Math.floor(i/2)]);
pixels.set(x, y, 2, windowb[Math.floor(i/2)]);
pixels.set(x, y, 0, windowr[Math.floor(i / 2)]);
pixels.set(x, y, 1, windowg[Math.floor(i / 2)]);
pixels.set(x, y, 2, windowb[Math.floor(i / 2)]);
}
}
@@ -52,7 +52,7 @@ module.exports = function Noise(pixels, method) {
for(let y = 0; y < pixels.shape[1]; y++){
for(let x = 0; x < pixels.shape[0]; x++){
let i = 0, k = 0, sumR=0, sumG = 0, sumB =0;
let i = 0, k = 0, sumR = 0, sumG = 0, sumB = 0;
while( k <= 8){
let newX = x + neighbourX[k], newY = y + neighbourY[k];
@@ -60,18 +60,18 @@ module.exports = function Noise(pixels, method) {
if( newX >= 0 && newX < pixels.shape[0])
{
if( newY >= 0 && newY < pixels.shape[1]){
sumR += pixels.get(newX,newY,0);
sumG += pixels.get(newX,newY,1);
sumB += pixels.get(newX,newY,2);
sumR += pixels.get(newX, newY, 0);
sumG += pixels.get(newX, newY, 1);
sumB += pixels.get(newX, newY, 2);
i++;
}
}
k++;
}
pixels.set(x, y, 0, sumR/i);
pixels.set(x, y, 1, sumG/i);
pixels.set(x, y, 2, sumB/i);
pixels.set(x, y, 0, sumR / i);
pixels.set(x, y, 1, sumG / i);
pixels.set(x, y, 2, sumB / i);
}
}

View File

@@ -2,6 +2,7 @@ module.exports = exports = function(pixels, options) {
let defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const pixelSetter = require('../../util/pixelSetter.js');
let fillColor = options.fillColor || defaults.fillColor,
x = parseInt(options.startingX) || defaults.startingX,
@@ -47,10 +48,8 @@ module.exports = exports = function(pixels, options) {
} while (isSimilar(currx, south) && south < height);
for (n = north + 1; n < south; n += 1) {
pixels.set(currx, n, 0, fillColor[0]);
pixels.set(currx, n, 1, fillColor[1]);
pixels.set(currx, n, 2, fillColor[2]);
pixels.set(currx, n, 3, fillColor[3]);
pixelSetter(currx, n, fillColor, pixels);
if (isSimilar(currx - 1, n)) {
queuex.push(currx - 1);
queuey.push(n);

View File

@@ -1,4 +1,6 @@
module.exports = exports = function(pixels, options){
const pixelSetter = require('../../util/pixelSetter.js');
var color = options.color || 'rgb(228,86,81)';
color = color.substring(color.indexOf('(') + 1, color.length - 1); // extract only the values from rgba(_,_,_,_)
@@ -23,7 +25,6 @@ module.exports = exports = function(pixels, options){
g >= cg * minFactor && g <= cg * maxFactor &&
b >= cb * minFactor && b <= cb * maxFactor);
}
for(var i = 0; i < pixels.shape[0]; i++){
for(var j = 0; j < pixels.shape[1]; j++){
var r = pixels.get(i, j, 0),
@@ -32,16 +33,16 @@ module.exports = exports = function(pixels, options){
if(isSimilar(r, g, b)){
if (replaceMethod == 'greyscale'){
var avg = (r + g + b) / 3;
pixels.set(i, j, 0, avg);
pixels.set(i, j, 1, avg);
pixels.set(i, j, 2, avg);
pixelSetter(i, j, [avg, avg, avg], pixels);
}else {
pixels.set(i, j, 0, replaceColor[0]);
pixels.set(i, j, 1, replaceColor[1]);
pixels.set(i, j, 2, replaceColor[2]);
pixelSetter(i, j, replaceColor, pixels);
}
}
}
}
return pixels;
};

View File

@@ -3,44 +3,36 @@ module.exports = function TextOverlay(options, UI) {
var output;
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
function draw(input, callback) {
var step = this;
if (!options.step.inBrowser) { // This module is only for browser
this.output = input;
callback();
var priorStep = this.getStep(-1); // get the previous step to add text onto it.
function extraManipulation(pixels) {
//if (options.step.inBrowser)
pixels = require('./TextOverlay')(pixels, options, priorStep);
return pixels;
}
else {
var priorStep = this.getStep(-1); // get the previous step to add text onto it.
function extraManipulation(pixels) {
//if (options.step.inBrowser)
pixels = require('./TextOverlay')(pixels, options, priorStep);
return pixels;
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
// This output is accesible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
// This output is accesible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {

View File

@@ -1,4 +1,7 @@
module.exports = exports = function(pixels, options, priorstep){
var $ = require('jquery'); // to make text-overlay work for node.js
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.text = options.text || defaults.text;

View File

@@ -40,6 +40,5 @@
"desc": "Enter the font size in pixels.",
"default": "12"
}
},
"only": "browser"
}
}

View File

@@ -5,6 +5,9 @@
module.exports = function PixelManipulation(image, options) {
// To handle the case where pixelmanipulation is called on the input object itself
// like input.pixelManipulation(options)
const pixelSetter = require('../../util/pixelSetter.js');
if (arguments.length <= 1) {
options = image;
image = this;
@@ -86,10 +89,8 @@ module.exports = function PixelManipulation(image, options) {
y
);
pixels.set(x, y, 0, pixel[0]);
pixels.set(x, y, 1, pixel[1]);
pixels.set(x, y, 2, pixel[2]);
pixels.set(x, y, 3, pixel[3]);
pixelSetter(x, y, pixel, pixels);
}
}
};

5
src/util/pixelSetter.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = function(x, y, value, pixels){
for(let i = 0; i < value.length; i++){
pixels.set(x, y, i, value[i]);
}
};

View File

@@ -0,0 +1,32 @@
const dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEX+AAD///+KQee0AAAAAWJLR0QB/wIt3gAAAAd0SU1FB+EGHRIVAvrm6EMAAAAMSURBVAjXY2AgDQAAADAAAceqhY4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDYtMjlUMTg6MjE6MDIrMDI6MDDGD83DAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTA2LTI5VDE4OjIxOjAyKzAyOjAwt1J1fwAAAABJRU5ErkJggg==';
console.log(dataURI);
const ImageSequencer = require('../../../src/ImageSequencer');
const test = require('tape');
var atob = require('atob');
var sequencer = ImageSequencer();
var base64str = dataURI.substr(22);
var decoded = atob(base64str);
var initialSize = decoded.length;
sequencer.loadImage(dataURI, function(){
this.addSteps('minify-image');
});
test('minify-image minifies the image', t => {
sequencer.run(function callback(out){
console.log(out);
var base64str = out.substr(22);
var decoded = atob(base64str);
var miniifiedSize = decoded.length;
var isLess = miniifiedSize < initialSize;
t.equal(isLess, true, 'image minified');
t.end();
});
});

View File

@@ -1,42 +0,0 @@
describe('Default sequencer HTML', function() {
var DefaultHtmlSequencerUi = require('../../examples/lib/defaultHtmlSequencerUi');
var sequencer = require('../../src/ImageSequencer')();
var defaultHtmlSequencerUi;
beforeEach(()=>{
defaultHtmlSequencerUi = new DefaultHtmlSequencerUi(sequencer);
spyOn(defaultHtmlSequencerUi, 'onLoad');
spyOn(defaultHtmlSequencerUi, 'selectNewStepUi');
spyOn(defaultHtmlSequencerUi, 'removeStepUi');
spyOn(defaultHtmlSequencerUi, 'addStepUi');
spyOn(defaultHtmlSequencerUi, 'importStepsFromUrlHash');
defaultHtmlSequencerUi.onLoad();
defaultHtmlSequencerUi.selectNewStepUi();
defaultHtmlSequencerUi.addStepUi();
defaultHtmlSequencerUi.removeStepUi();
defaultHtmlSequencerUi.importStepsFromUrlHash();
});
it('load default ui', function() {
expect(defaultHtmlSequencerUi.onLoad).toHaveBeenCalled();
});
it('select step ui', function() {
expect(defaultHtmlSequencerUi.selectNewStepUi).toHaveBeenCalled();
});
it('add step ui', function() {
expect(defaultHtmlSequencerUi.addStepUi).toHaveBeenCalled();
});
it('remove step ui', function() {
expect(defaultHtmlSequencerUi.removeStepUi).toHaveBeenCalled();
});
it('import options from url', function() {
expect(defaultHtmlSequencerUi.importStepsFromUrlHash).toHaveBeenCalled();
});
});

View File

@@ -1,61 +0,0 @@
var { JSDOM } = require('jsdom');
var DOM = new JSDOM('<body></body>');
global.document = DOM.window.document;
describe('Sequencer step HTML', function() {
var DefaultHtmlStepUi = require('../../examples/lib/defaultHtmlStepUi');
var sequencer = require('../../src/ImageSequencer')();
var defaultHtmlStepUi;
var step = 'brightness';
var options = {
name: 'Brightness',
description: 'Change the brightness of the image by given percent value'
};
// options = JSON.parse(options)
beforeEach(()=>{
defaultHtmlStepUi = new DefaultHtmlStepUi(sequencer);
spyOn(defaultHtmlStepUi, 'getPreview');
spyOn(defaultHtmlStepUi, 'onSetup');
spyOn(defaultHtmlStepUi, 'onComplete');
spyOn(defaultHtmlStepUi, 'onDraw');
spyOn(defaultHtmlStepUi, 'onRemove');
spyOn(defaultHtmlStepUi, 'notify');
defaultHtmlStepUi.getPreview();
defaultHtmlStepUi.onSetup(step, options);
defaultHtmlStepUi.onComplete(step);
defaultHtmlStepUi.onDraw(step);
defaultHtmlStepUi.onRemove(step);
defaultHtmlStepUi.notify('Step removed', 'remove-notification');
});
it('result preview ui', function() {
expect(defaultHtmlStepUi.getPreview).toHaveBeenCalled();
});
it('load initial setup ui', function() {
expect(defaultHtmlStepUi.onSetup).toHaveBeenCalledWith(step, options);
});
it('load completion ui', function() {
expect(defaultHtmlStepUi.onComplete).toHaveBeenCalledWith(step);
});
it('draw step ui', function() {
expect(defaultHtmlStepUi.onDraw).toHaveBeenCalledWith(step);
});
it('remove step ui', function() {
expect(defaultHtmlStepUi.onRemove).toHaveBeenCalledWith(step);
});
it('notification ui', function() {
expect(defaultHtmlStepUi.notify).toHaveBeenCalledWith('Step removed', 'remove-notification');
});
});

View File

@@ -1,8 +0,0 @@
var SpecReporter = require('jasmine-spec-reporter').SpecReporter;
jasmine.getEnv().clearReporters(); // remove default reporter logs
jasmine.getEnv().addReporter(new SpecReporter({ // add jasmine-spec-reporter
spec: {
displayPending: true
}
}));

View File

@@ -1,11 +0,0 @@
{
"spec_dir": "test/spec",
"spec_files": [
"**/*.[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}

View File

@@ -0,0 +1,35 @@
describe('Default sequencer HTML', function() {
beforeAll(function() {
jasmine.getFixtures().fixturesPath = 'test/ui/spec/fixtures';
fixture = loadFixtures('index.html');
// ImageSequencer();
initializeSequencerUi();
});
//it('detects HTML from the fixture', function() {
it('adds a step from the quick selector', function() {
expect($('#steps').length).toBe(1);
expect($('#steps').length).toBe(1);
expect($('#dropzone').length).toBe(1);
//});
//it('adds a step from the quick selector', function() {
expect($('#dropzone').length).toBe(1);
console.log('dropzone',$('#dropzone').length);
expect($('.step').length).toBe(1);
console.log('step',$('.step').length);
expect($('.step:first img').length).not.toBe(0);
expect($('.step:first img')[0].src).not.toBeUndefined();
expect($('.step:first img')[0].src).not.toBe('');
// needs more setup
$("[data-value='brightness']").click()
expect($('.step').length).toBe(2);
expect($('.step:last img')[0].src).not.toBeUndefined();
expect($('.step:last img')[0].src).not.toBe('');
expect($('.step:last img')[0].src).not.toEqual($('.step:first img')[0].src);
// TODO: test the actual `src` attribute of $('.step:last img') against a known value
});
});

View File

@@ -1,7 +1,7 @@
describe('Default sequencer HTML', function() {
var DefaultHtmlSequencerUi = require('../examples/lib/defaultHtmlSequencerUi');
var sequencer = require('../src/ImageSequencer')();
var DefaultHtmlSequencerUi = require('../../../examples/lib/defaultHtmlSequencerUi');
var sequencer = require('../../../src/ImageSequencer')();
var defaultHtmlSequencerUi;
beforeEach(()=>{
@@ -39,4 +39,5 @@ describe('Default sequencer HTML', function() {
it('import options from url', function() {
expect(defaultHtmlSequencerUi.importStepsFromUrlHash).toHaveBeenCalled();
});
});
});

View File

@@ -5,8 +5,8 @@ global.document = DOM.window.document;
describe('Sequencer step HTML', function() {
var DefaultHtmlStepUi = require('../examples/lib/defaultHtmlStepUi');
var sequencer = require('../src/ImageSequencer')();
var DefaultHtmlStepUi = require('../../../examples/lib/defaultHtmlStepUi');
var sequencer = require('../../../src/ImageSequencer')();
var defaultHtmlStepUi;
var step = 'brightness';
var options = {
@@ -15,6 +15,16 @@ describe('Sequencer step HTML', function() {
};
// options = JSON.parse(options)
beforeAll(() => {
const { JSDOM } = require('jsdom');
var { window } = new JSDOM();
const { document } = window;
global.window = window;
global.document = document;
const $ = global.jQuery = global.$ = require('jquery');
});
beforeEach(()=>{
defaultHtmlStepUi = new DefaultHtmlStepUi(sequencer);

157
test/ui/spec/fixtures/index.html vendored Normal file
View File

@@ -0,0 +1,157 @@
<!--<script src="../../dist/image-sequencer-ui.js" charset="utf-8"></script>-->
<script type="text/javascript">
var sequencer;
window.onload = function() {
(function () {
//initializeSequencerUi();
})();
}
</script>
<link href="../../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../../node_modules/bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css" rel="stylesheet">
<link rel="stylesheet" href="../../examples/demo.css">
<link href="../../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="../../node_modules/selectize/dist/css/selectize.default.css" rel="stylesheet">
<!-- for crop module: -->
<link href="../../node_modules/imgareaselect/distfiles/css/imgareaselect-default.css" rel="stylesheet">
<link href="../../examples/selectize.default.css" rel="stylesheet">
<div class="container-fluid">
<div id="dropzone" class="dropzone">
<p>
<i>Select or drag in an image to start!</i>
</p>
<center>
<input type="file" id="fileInput" value="" accept="image/*"><br />
<button type="button" id="take-photo" class="btn btn-primary btn-block btn-lg ">Take a Photo</button>
<video id="video" width="100%" height="100%" style="display:none"></video>
<a href="#" id="capture" style="display:none" class="btn btn-primary btn-md">Click Picture</a>
<a href="#" id="close" style="display:none" class="btn btn-default btn-md">Close</a>
<canvas id="canvas" width="400" height="300" style="display:none"></canvas>
</center>
</div>
<section id="steps" class="row">
<div id="load-image"></div>
</section>
<hr />
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules in browser's localStorage.
</p>
<div class="row">
<div class="col-sm-8">
<section id="addStep" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="display:flex; justify-content:center;">
</div>
<p class="info">Select a new module to add to your sequence.</p>
<div class="row center-align radio-group">
<div>
<div class="radio" data-value="resize">
<i class="fa fa-arrows-alt fa-4x i-over"></i>
</div>
<p>Resize</p>
</div>
<div>
<div class="radio" data-value="brightness">
<i class="fa fa-sun-o fa-4x i-over"></i>
</div>
<p>Brightness</p>
</div>
<div>
<div class="radio" data-value="contrast">
<i class="fa fa-adjust fa-4x i-over"></i>
</div>
<p>Contrast</p>
</div>
<div>
<div class="radio" data-value="saturation">
<i class="fa fa-tint fa-4x i-over i-small"></i>
</div>
<p>Saturation</p>
</div>
<div>
<div class="radio" data-value="rotate">
<i class="fa fa-rotate-right fa-4x i-over"></i>
</div>
<p>Rotate</p>
</div>
<div>
<div class="radio" data-value="crop">
<i class="fa fa-crop fa-4x i-over"></i>
</div>
<p>Crop</p>
</div>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<select id="selectStep" class="text-center">
<!-- The default null selection has been appended manually in demo.js
This is because the options in select are overritten when options are appended.-->
</select>
</div>
<div class="col-lg-4">
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
</div>
<div class="row center-align">
<button id="resetButton" class="btn btn-default btn-lg"
style=" margin: 20px 35px 0px 35px; width:100%;">Clear All Steps</button>
</div>
</div>
</div>
</section>
<div class="modal fade" id="js-download-gif-modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Your gif is ready</h4>
</div>
<div class="modal-body">
<div id="js-download-modal-gif-container">
<!-- Gif should appear here -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Done</button>
<button id="js-download-as-gif-button" class="btn btn-primary">Download</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-4">
<section id="dwnld" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="text-align:center;">
<h2 style="margin-top:20px">Save</h2>
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
<option value="save-image">Save as PNG</option>
<option value="save-gif">Save as GIF (all steps)</option>
<option value="save-seq">Save sequence</option>
<option value="save-seq-string">Save sequence string</option>
</select>
<p><button id="saveButton" class="btn btn-primary btn-lg save-button">Save</button></p>
<p><button class="btn btn-default btn-lg js-view-as-gif" id="gif">Preview GIF</button></p>
</div>
</div>
</div>
</section>
</div>
</div>
</div>
<footer>
<center><button class="btn btn-default btn-sm" id="clear-cache">Clear offline cache</button></center>
</footer>

View File

@@ -1,7 +1,7 @@
describe('Preview UI HTML', function() {
var InsertPreview = require('../../examples/lib/insertPreview');
var sequencer = require('../../src/ImageSequencer')();
var InsertPreview = require('../../../examples/lib/insertPreview');
var sequencer = require('../../../src/ImageSequencer')();
var insertPreview;
var options = { brightness: 50 };

View File

@@ -1,7 +1,7 @@
describe('Intermediate step HTML', function() {
var IntermediateHtmlStepUi = require('../../examples/lib/intermediateHtmlStepUi');
var sequencer = require('../../src/ImageSequencer')();
var IntermediateHtmlStepUi = require('../../../examples/lib/intermediateHtmlStepUi');
var sequencer = require('../../../src/ImageSequencer')();
var intermediateHtmlStepUi;
beforeEach(()=>{

View File

@@ -0,0 +1,81 @@
const scopeQuery = require('../../../examples/lib/scopeQuery');
describe('scopeQuery Method', function() {
beforeAll(() => {
const { JSDOM } = require('jsdom');
var { window } = new JSDOM(`
<body>
<div id="scope1">
<div class="child" id="child1">Child1</div>
<div class="child" id="child2">Child2</div>
<div class="child" id="child3">Child3</div>
<div class="child" id="child4">Child4</div>
<div class="child" id="child5">Child5</div>
<div class="child" id="child6">Child6</div>
</div>
<div id="scope2">
<div class="child" id="child1">Child1Scope2</div>
<div class="child" id="child2">Child2Scope2</div>
<div class="child" id="child3">Child3Scope2</div>
<div class="child" id="child4">Child4Scope2</div>
<div class="child" id="child5">Child5Scope2</div>
</div>
</body>`);
const { document } = window;
global.window = window;
global.document = document;
const $ = global.jQuery = global.$ = require('jquery');
});
it('scope 1 querySelector', function() {
const $scope1 = scopeQuery.scopeSelector(document.querySelector('#scope1'));
const $scope1All = scopeQuery.scopeSelectorAll(document.querySelector('#scope1'));
expect($scope1('.child').length).toBe(1);
expect($scope1All('.child').length).toBe(6);
expect($scope1('#child1').text()).toBe('Child1');
expect($scope1('#child2').text()).toBe('Child2');
expect($scope1All('#child1').text()).toBe('Child1');
expect($scope1All('#child2').text()).toBe('Child2');
expect($scope1().elem('.child').length).toBe(1);
expect($scope1().elemAll('.child').length).toBe(6);
expect($scope1All().elem('.child').length).toBe(1);
expect($scope1All().elemAll('.child').length).toBe(6);
});
it('scope 2 querySelector', function() {
const $scope2 = scopeQuery.scopeSelector(document.querySelector('#scope2'));
const $scope2All = scopeQuery.scopeSelectorAll(document.querySelector('#scope2'));
expect($scope2('.child').length).toBe(1);
expect($scope2All('.child').length).toBe(5);
expect($scope2('#child1').text()).toBe('Child1Scope2');
expect($scope2('#child2').text()).toBe('Child2Scope2');
expect($scope2All('#child1').text()).toBe('Child1Scope2');
expect($scope2All('#child2').text()).toBe('Child2Scope2');
expect($scope2().elem('.child').length).toBe(1);
expect($scope2().elemAll('.child').length).toBe(5);
expect($scope2All().elem('.child').length).toBe(1);
expect($scope2All().elemAll('.child').length).toBe(5);
});
});
global.document = null;
global.$ = null;
DOM = null;

View File

@@ -0,0 +1,16 @@
{
"spec_dir": "test/ui/spec",
"spec_files": [
"**/*.[sS]pec.js"
],
"helpers": [
"helpers/**/*.js",
"../../../node_modules/jquery/dist/jquery.min.js",
"../../../node_modules/bootstrap/dist/js/bootstrap.min.js",
"../../../node_modules/jasmine-jquery/lib/jasmine-jquery.js",
"../../../dist/image-sequencer.js",
"../../../dist/image-sequencer-ui.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}

View File

@@ -0,0 +1,24 @@
describe('HTML Types Mapping Function', function() {
var mapHtmlTypes = require('../../../examples/lib/mapHtmltypes');
it('maps range and number types', function() {
expect(mapHtmlTypes({type: 'percentage'})).toEqual({type: 'number'});
expect(mapHtmlTypes({type: 'integer'})).toEqual({type: 'number'});
expect(mapHtmlTypes({type: 'integer', min: 20, max: 100})).toEqual({type: 'range', min: 20, max: 100});
expect(mapHtmlTypes({type: 'float'})).toEqual({type: 'text'});
expect(mapHtmlTypes({type: 'float', min: 20, max: 100})).toEqual({type: 'range', min: 20, max: 100});
});
it('maps text type', function() {
expect(mapHtmlTypes({type: 'string'})).toEqual({type: 'text'});
expect(mapHtmlTypes({type: 'anything'})).toEqual({type: 'text'});
});
it('maps select type', function() {
expect(mapHtmlTypes({type: 'select'})).toEqual({type: 'select'});
});
});

View File

@@ -1,6 +1,6 @@
describe('URL manipulation methods', function() {
var UrlHash = require('../../examples/lib/urlHash');
var UrlHash = require('../../../examples/lib/urlHash');
var urlHash;
var params = {
module: 'brightness',

1885
yarn.lock

File diff suppressed because it is too large Load Diff