Compare commits

...

122 Commits

Author SHA1 Message Date
Harsh Khandeparkar
a091bd9ab8 Merge branch 'main' into user-prefs 2019-06-23 15:05:12 +05:30
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
0eb3f263f9 version bump to v3.5.0 with WebAssembly acceleration 2019-06-21 12:15:51 -04:00
Slytherin
30659d4656 Using wasm to accelerate PixelManipulation.js (#1093)
* Add wasm code

* First working model

* Add PixelManipulation web assembly code to browser and node

* Tests corrected for modules

* Corrected test script

* Add wasm bechmarks

* Update Readme

* Applies toggling functionality and refactored PixelManipulation code

* Added documentation and corrected wasm toggling

* change noise reduction module to use wasm code

* Corrected formatting  and removed extra comments

* Add default wasm option and made README changes

* Fixed negative test timings

* combined benchmarks file

* Update benchmark.js

* Removed copies of wasm file and corrected test format

* Update package.json

Co-Authored-By: Jeffrey Warren <jeff@unterbahn.com>

* Added wasm file and removed redundant code

* Removed earlier benchmarks

* move test/core/sequencer/benchmark.js to its own test command, not passing to tape-spec

* Solves memory leaks and blank lines

* Solves memory leaks and blank lines

* Added handler for node code

* Modify test script

* Modify test script

* Correct doc and removed pace fuctionality
2019-06-21 10:54:56 -04:00
dependabot-preview[bot]
c3af98ea93 Bump gpu.js from 2.0.0-rc.14 to 2.0.0-rc.15 (#1116)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.0.0-rc.14 to 2.0.0-rc.15.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/compare/2.0.0-rc.14...2.0.0-rc.15)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-18 08:03:01 -04:00
aashna27
b34ec00efd Added Color Picker for selecting RGBA values in modules (#1095)
* Added Color Picker for selecting RGBA values in modules

* added scripts from node_modules

* selector-all added and alpha removed for some modules

* Modified description
2019-06-16 13:38:51 -04:00
jywarren
e1e9d57d7a bump to v3.4.5 2019-06-15 14:30:56 -04:00
aashna27
ec6ce155f5 Solved Module undefined error (#1104)
* Resolve Module undefined  error

* Lower-case-hyphen module names
2019-06-15 14:25:53 -04:00
dependabot-preview[bot]
70e7876230 Bump lint-staged from 8.2.0 to 8.2.1 (#1111)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v8.2.0...v8.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-15 12:18:50 -04:00
Varun Gupta
80cb5b1194 Make progress bars on UI true (#1112)
* Make progress bars on UI true

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

* update docs

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

* fix typo

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2019-06-15 10:51:02 -04:00
freerangeandy
f5d7b0ae09 add moduleInfo to step construction (#1107) (#1110) 2019-06-14 12:32:58 -04:00
aashna27
440c3e0ad0 Eslint operator spacing config (#1109)
* Eslint operator spacing config

* consistent spacing after comma

* comma styling config

* Trailing spaces config
2019-06-13 16:59:43 -04:00
aashna27
9eac21897a Added noise reduction module (#1105)
* Added Noise Removal Module

* Remove ChangePixel Function
2019-06-13 13:09:13 -04:00
dependabot-preview[bot]
cfdb7e2606 Bump @babel/plugin-proposal-object-rest-spread from 7.4.3 to 7.4.4 (#1056)
Bumps [@babel/plugin-proposal-object-rest-spread](https://github.com/babel/babel) from 7.4.3 to 7.4.4.
- [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.4.4)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-06-12 15:49:40 -04:00
dependabot-preview[bot]
278016fb8f Bump husky from 2.3.0 to 2.4.1 (#1106)
Bumps [husky](https://github.com/typicode/husky) from 2.3.0 to 2.4.1.
- [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...v2.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-12 15:48:45 -04:00
dependabot-preview[bot]
64ad4b4a95 Bump lint-staged from 8.1.7 to 8.2.0 (#1102)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 8.1.7 to 8.2.0.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v8.1.7...v8.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-12 15:48:18 -04:00
Johan Uribe
52ef31cdab Show default cursor on hover (#1036)
Show default cursor on hover
2019-06-10 12:54:50 -04:00
aashna27
c653ce65b9 Modified jasmine script (#1101)
* jasmine script modified

* added jasmine script

* Jasmine install script removed from travis
2019-06-07 08:17:47 -07:00
dependabot-preview[bot]
abc4b51de9 Bump jsdom from 15.0.0 to 15.1.1 (#1085) 2019-06-05 19:03:48 +00:00
dependabot-preview[bot]
8d9a3c1f4f Bump puppeteer from 1.15.0 to 1.17.0 (#1077)
Bumps [puppeteer](https://github.com/GoogleChrome/puppeteer) from 1.15.0 to 1.17.0.
- [Release notes](https://github.com/GoogleChrome/puppeteer/releases)
- [Commits](https://github.com/GoogleChrome/puppeteer/compare/v1.15.0...v1.17.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-06-05 14:48:07 -04:00
dependabot-preview[bot]
d6bb1ba5b9 Bump @babel/core from 7.4.3 to 7.4.5 (#1071)
Bumps [@babel/core](https://github.com/babel/babel) from 7.4.3 to 7.4.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.4.5)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-06-05 14:47:54 -04:00
aashna27
427c81d8fe Added Download button (#1096) 2019-06-05 14:46:25 -04:00
dependabot-preview[bot]
31bc45cb91 Bump gpu.js from 2.0.0-rc.13 to 2.0.0-rc.14 (#1097)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.0.0-rc.13 to 2.0.0-rc.14.
- [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.14)
2019-06-04 15:16:27 -04:00
jywarren
81f13c03a7 v3.3.5 2019-05-27 13:58:23 -04:00
dependabot-preview[bot]
c5ca02bcb3 Bump gpu.js from 2.0.0-rc.12 to 2.0.0-rc.13 (#1053)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.0.0-rc.12 to 2.0.0-rc.13.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/compare/2.0.0-rc.12...2.0.0-rc.13)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-27 13:55:18 -04:00
dependabot-preview[bot]
45df69e8e1 Bump looks-same from 7.2.0 to 7.2.1 (#1067)
Bumps [looks-same](https://github.com/gemini-testing/looks-same) from 7.2.0 to 7.2.1.
- [Release notes](https://github.com/gemini-testing/looks-same/releases)
- [Changelog](https://github.com/gemini-testing/looks-same/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gemini-testing/looks-same/compare/v7.2.0...v7.2.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-27 13:54:51 -04:00
dependabot-preview[bot]
dd3d15eef2 Bump tape from 4.10.1 to 4.10.2 (#1081)
Bumps [tape](https://github.com/substack/tape) from 4.10.1 to 4.10.2.
- [Release notes](https://github.com/substack/tape/releases)
- [Commits](https://github.com/substack/tape/compare/v4.10.1...v4.10.2)
2019-05-27 13:54:22 -04:00
Varun Gupta
641ffd7a1a Fix overlay (#1082)
* fix Overlay

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

* update canvas background color

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2019-05-27 13:53:55 -04:00
aashna27
ca73a4115e dist ignored from eslint and documentation added (#1083) 2019-05-27 08:17:13 -04:00
jywarren
a7fe5edb4b v3.3.4 2019-05-25 13:39:58 -04:00
Jeffrey Warren
f222bf7669 Update CONTRIBUTING.md 2019-05-25 13:37:59 -04:00
Varun Gupta
b506f7a356 fix import-image and canvas-resize (#1079)
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2019-05-25 12:38:01 -04:00
jywarren
ba39a40c7e bump to v3.3.3 2019-05-25 12:01:15 -04:00
Bhavay Anand
461f3f905a fix: module names had spaces instead of hyphen (#1073) 2019-05-25 11:42:47 -04:00
dependabot-preview[bot]
6f4cf80648 [Security] Bump tar from 2.2.1 to 2.2.2 (#1078)
Bumps [tar](https://github.com/npm/node-tar) from 2.2.1 to 2.2.2. **This update includes security fixes.**
- [Release notes](https://github.com/npm/node-tar/releases)
- [Commits](https://github.com/npm/node-tar/compare/v2.2.1...v2.2.2)
2019-05-24 15:32:17 -04:00
aashna27
102d2b21ca ESLINT config added (#1063) 2019-05-24 01:02:20 -04:00
jywarren
dc2375043f bump to v3.3.2 2019-05-23 22:01:25 -04:00
Jeffrey Warren
e1e23c213c Update CONTRIBUTING.md 2019-05-23 15:15:03 -04:00
Varun Gupta
8751211967 fix webgl-distort (#1074)
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2019-05-23 14:40:55 -04:00
aashna27
c784de0c19 Added Eslint and husky (#1062) 2019-05-11 10:39:15 -04:00
Harsh Khandeparkar
0c3d7be7e2 Module tests (#1058)
* change all old module benchmarks

* no node 6

* add average module tests

* edge-detect test added

* edge detect tests

* flip-image tests

* tint tests

* saturation tests

* gradient tests

* exposure tests

* draw-rectangle tests

* color-temperature tests

* convolution tests

* paint-bucket tests

* ndvi tests

* ndvi-colormap tests

* histogram tests

* crop tests

* gamma-correction tests

* dynamic tests

* colorbar tests

* webgl-distort tests

* fisheye-gl tests

* blend module tests

* overlay module tests
2019-05-06 15:41:42 -04:00
dependabot[bot]
06ac596d7e [Security] Bump static-eval from 0.2.4 to 2.0.2 (#1051) 2019-05-04 19:15:22 +00:00
dependabot[bot]
3220886db0 Bump jquery from 3.4.0 to 3.4.1 (#1052) 2019-05-04 19:06:53 +00:00
Harsh Khandeparkar
bfff8f093b drop nodejs 6 support (#1057) 2019-05-04 14:49:20 -04:00
dependabot[bot]
d6cb02cd52 Bump tape-run from 5.0.0 to 6.0.0 (#1054)
Bumps [tape-run](https://github.com/juliangruber/tape-run) from 5.0.0 to 6.0.0.
- [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/v5.0.0...v6.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-04 14:48:03 -04:00
Harsh Khandeparkar
b0096a13f4 GPU Acceleration achieved! (#1038)
* add gpu.js 2.0.0-rc.7

* add gpuUtils

* add gpuUtil convolve

* add convolution to edgeDetect

* bench it

* bench change

* newline

* pipeline

* revert edge-detect

* gpu accelerate gaussian blur

* edgeDetect use blur

* tweak values

* remove ndarray-gaussian-filter

* audit

* turn on previews

* remove oldPix

* fix travis

* Travis fix

* Try fixing travis

* Fix

* Retry

* tweaks

* convolution module on GPU

* use babelify

* trial

* remove logs

* Update .travis.yml

* Update .travis.yml

* bump version

* bump to rc.9

* rc.10

* rc.11

* Update package.json

* convolution fix

* unit test gpuUtils

* tests changed, fixed

* new fix

* more obvious parseFloat

* remove old commented code
2019-05-02 12:53:57 -04:00
Jeffrey Warren
43a8d0f2c1 update puppeteer for headless (#1031)
* update puppeteer for headless

* version bump for v3.1.1 bugfix

* --disable-setuid-sandbox

* remove --no-sandbox but leave --disable-setuid-sandbox

* Update gl-context.js

* ['--no-sandbox', '--disable-setuid-sandbox']
2019-04-30 14:41:41 -04:00
dependabot[bot]
8b110c241f Bump jsdom from 14.0.0 to 15.0.0 (#1037)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 14.0.0 to 15.0.0.
- [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/14.0.0...15.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-29 15:00:53 -04:00
Guillermo Murua
5566152e52 Fixed unresponsive webcam preview window (#1047) 2019-04-29 15:00:41 -04:00
Slytherin
269215f48b Fixes threshold bug (#1041)
* Fixes threshold bug

* Update examples/lib/defaultHtmlSequencerUi.js

Co-Authored-By: Divy123 <31225007+Divy123@users.noreply.github.com>

* Fix threshold module bug
2019-04-27 17:18:20 -04:00
Jeffrey Warren
1aa9a0e99c codecov badge url 2019-04-26 15:45:44 -04:00
aashna27
ff8c27eac2 Fixes Grid-Overlay with node Compatibility (#1024)
* Fixes Grid-Overlay

* Tests

* Correct bounds

Co-Authored-By: aashna27 <aashna.mittal27@gmail.com>

* Correct bounds

Co-Authored-By: aashna27 <aashna.mittal27@gmail.com>

* Correct bounds

Co-Authored-By: aashna27 <aashna.mittal27@gmail.com>

* Correct bounds

Co-Authored-By: aashna27 <aashna.mittal27@gmail.com>
2019-04-26 15:40:22 -04:00
dependabot[bot]
9eed50153c Bump puppeteer from 1.14.0 to 1.15.0 (#1043)
Bumps [puppeteer](https://github.com/GoogleChrome/puppeteer) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/GoogleChrome/puppeteer/releases)
- [Commits](https://github.com/GoogleChrome/puppeteer/compare/v1.14.0...v1.15.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-26 08:43:49 -04:00
Vibhor Gupta
df09cf62d0 Close parenthesis fix (#580)
* close parenthesis fix

* possible map fix

* remove ending parenthesis when passing options
2019-04-19 18:15:19 -04:00
Jeffrey Warren
e7fbada71e Update README.md 2019-04-19 13:31:20 -04:00
Varun Gupta
c36922dbdf attempting webgl-distort (#1022)
* attempting webgl-distort

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

* fixed the error

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

* WIP

* custom inputs for distort

* added test suite

* test fix and input parse

* test fix

* 3.3.0
2019-04-19 13:10:58 -04:00
jywarren
c1996e576e v3.2.0 2019-04-19 12:46:22 -04:00
Jeffrey Warren
04838d3c2e Audit fix (#1028)
* bump v3.1.0

* audit fix
2019-04-19 12:36:01 -04:00
Jeffrey Warren
a35433acfe bump v3.1.0 (#1027) 2019-04-19 12:27:45 -04:00
Vibhor Gupta
ec40224831 Detect and Parse string separated module names (#787)
* detecting and parsing string separated module names

* test fix

* parsing multiple input methods

* travis fix

* test cases

* requested changes made

* test fix

* rebase and fix conflicts
2019-04-18 16:12:33 -04:00
Slytherin
84aede7bc3 Add meta description with keywords for SEO (#1018) 2019-04-18 16:10:17 -04:00
Vibhor Gupta
6339229836 Refactor: String parsing methods (#667)
* WIP

* string methods refactor

* fixed refactor
2019-04-18 07:59:38 -04:00
Slytherin
2be7a3dca6 Fixes crop module bug (#1019)
* Fixes crop module bug

* Fixes crop functionality

* Add looks like test for crop module
2019-04-18 07:40:36 -04:00
hodbadger
6fa8b1b880 Add a description of the scopeQuery method (#916)
* Add a description of the scopeQuery method

* Added changes to the description of scopeQuery

* Added changes to the description of scopeQuery
2019-04-15 18:10:49 -05:00
dependabot[bot]
900e0eda57 Bump data-uri-to-buffer from 2.0.0 to 2.0.1 (#989)
Bumps [data-uri-to-buffer](https://github.com/TooTallNate/node-data-uri-to-buffer) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/TooTallNate/node-data-uri-to-buffer/releases)
- [Changelog](https://github.com/TooTallNate/node-data-uri-to-buffer/blob/master/History.md)
- [Commits](https://github.com/TooTallNate/node-data-uri-to-buffer/compare/2.0.0...2.0.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-15 18:09:13 -05:00
Jeffrey Warren
3b9bacb2fb Add codecov comments (#1016)
* Add codecov comments

* Update .codecov.yml
2019-04-15 17:21:44 -05:00
Jeffrey Warren
11f73242fa Update README.md (#1015) 2019-04-15 16:33:41 -05:00
Harsh Khandeparkar
3772f78f51 1000 contributions PR (#1008)
* Update PULL_REQUEST_TEMPLATE.md

* changes
2019-04-15 16:24:29 -05:00
Slytherin
6ba604550b Add codecov (#1014) 2019-04-15 15:58:58 -05:00
Harsh Khandeparkar
2f86dcb0c8 Fixed Service Worker (#976)
* Update cache.js

* Update cache.js

* Create sw.js

* Delete sw.js
2019-04-15 12:38:39 -05:00
dependabot[bot]
fd981634fa Bump commander from 2.19.0 to 2.20.0 (#980)
Bumps [commander](https://github.com/tj/commander.js) from 2.19.0 to 2.20.0.
- [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...v2.20.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-15 12:33:00 -05:00
dependabot[bot]
142464bb8b Bump ora from 3.2.0 to 3.4.0 (#981)
Bumps [ora](https://github.com/sindresorhus/ora) from 3.2.0 to 3.4.0.
- [Release notes](https://github.com/sindresorhus/ora/releases)
- [Commits](https://github.com/sindresorhus/ora/compare/v3.2.0...v3.4.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-15 12:32:09 -05:00
dependabot[bot]
78d9cd91e7 Bump jasmine-core from 3.3.0 to 3.4.0 (#986)
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/master/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v3.3.0...v3.4.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-15 09:18:26 -05:00
Vibhor Gupta
e22eacf666 Add: white balance module (#1011)
* WIP

* added white balance and renamed temperature module

* import defaults

* white balance module test
2019-04-15 07:21:39 -05:00
Varun Gupta
c3e8c3fb74 Gl puppeteer (#1007)
* add geotiff

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

* now running gl using localhost fixes #216

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

* modularize api and fix tests

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

* finishing up

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

* add docs

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

* fixes

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

* fix benchmark.js

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2019-04-14 10:50:26 -05:00
aashna27
4e43c9123a Fixes Text-Overlay (#1004) 2019-04-12 10:11:00 -04:00
dependabot[bot]
914a172f5d Bump jquery from 3.3.1 to 3.4.0 (#1001)
Bumps [jquery](https://github.com/jquery/jquery) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/jquery/jquery/releases)
- [Commits](https://github.com/jquery/jquery/compare/3.3.1...3.4.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-11 04:42:32 -04:00
Lohitha
e4ddb04601 Add spinner while gif is generating (#991)
fixes #843
2019-04-08 19:47:26 -04:00
Harshith pabbati
edcc253029 fixed the bug (#999) 2019-04-08 08:26:39 -04:00
Terrence
51a38fe3cf More Modules option removed. Placeholder text added (#996)
* More Modules option removed. Placeholder text added

* 'A' changed to 'a' in placeholder text

* Update examples/lib/intermediateHtmlStepUi.js

Suggested update

Co-Authored-By: teisenhower <47988669+teisenhower@users.noreply.github.com>
2019-04-07 13:12:18 -04:00
Varun Gupta
e4e4548c09 add canvas resize module (#994)
* add canvas resize module

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

* add tests

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2019-04-07 12:41:14 -04:00
Vajean Stan
7cf96df1ee Removed redundant parameters in ImageSequencer.js (#967)
* Removed redundant parameters in ImageSequencer.js

* Re-added loadImages, deleted loadImage

* Left both loadImage and loadImages in

I think I need more details to the last phrase in the instructions, telling me to remove the export of loadImages, I tried deleting that line and cannot pass the test.
2019-04-05 18:03:04 -04:00
Harsh Khandeparkar
2a0eff41f4 Fix insert step and allow "closing" it (#655)
* update dist

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

dist update

Revert "dist update"

This reverts commit 9ee2a987e8f978961656ae8f71f6e6702bbbd30d.

* fix insert step button

* add icon

* add dist

* use normal functions

* use normal functions

* no lag

* changes

* changes

* changes

* Update intermediateHtmlStepUi.js

* toggleDiv global

- Globalised toggleDiv
- toggleDiv has default callback which does nothing.
2019-04-05 15:08:42 -04:00
Harsh Khandeparkar
b95728f95c Create fto-template.md (#977)
* Create fto-template.md

* Create first-timers.yml
2019-04-05 14:42:34 -04:00
Harshith pabbati
d63aab79a6 Added doc for grid-overlay (#983) 2019-04-05 14:37:17 -04:00
Harshith pabbati
0e7323efa9 Grid-Overlay module. (#974)
* Grid-Overlay module

* Added the X and Y for inputs
2019-04-03 08:46:57 -04:00
Harshith pabbati
1de170c978 made few changes to css (#975) 2019-04-02 09:37:39 -04:00
Jeffrey Warren
9a666a2f06 add maintainability badge from codeclimate 2019-04-01 14:33:02 -04:00
Harshith pabbati
985c67847e Changes to make the insert-step disable at the first step (#968) 2019-04-01 10:36:45 -04:00
Jeffrey Warren
690c126f41 ui-tweaks (#960) 2019-03-30 12:47:56 -04:00
Harshith pabbati
bc1151c340 Made it to work (#958) 2019-03-29 18:21:01 -04:00
Harsh Khandeparkar
3e645f9f7d error handling 2019-03-29 14:47:46 +00:00
Jeffrey Warren
32268c54df remove container class from step div (#956) 2019-03-28 21:35:10 -04:00
dependabot[bot]
12df02a0fd Bump jsdom from 13.2.0 to 14.0.0 (#845)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 13.2.0 to 14.0.0.
- [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/13.2.0...14.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-28 21:32:05 -04:00
MichaelLin250
a51644963a TRYING SO HARD TO FIX IT (#950) 2019-03-28 21:29:41 -04:00
Harshith pabbati
9f524615a5 Bootstrap panel (#942)
* Bootstrap panel

* Indentation.

* css tidying

* more tweaks
2019-03-28 20:59:21 -04:00
Harsh Khandeparkar
4b9d67ca4a docs 2019-03-28 21:04:27 +00:00
Harsh Khandeparkar
a2cd5bafd6 create API 2019-03-28 20:27:55 +00:00
Harsh Khandeparkar
e505ef6c25 Create userPrefs.js 2019-03-28 19:36:18 +00:00
aashna27
8ad171ee56 Tests added (#943) 2019-03-27 07:49:42 -04:00
vaari gupta
a8757a888a Improved Footer (#904)
* improved footer

* corrected Footer

* Delete image-sequencer-ui.js

* Delete image-sequencer-ui.min.js

* Delete image-sequencer.js

* Delete image-sequencer.min.js
2019-03-26 18:33:48 -04:00
Harsh Khandeparkar
24fb83a565 Delete image-sequencer-ui.js (#941)
* Delete image-sequencer-ui.js

* fix link
2019-03-25 16:53:06 -04:00
aashna27
60cfcb4d30 Added Text Overlay module (#917) 2019-03-25 15:58:02 -04:00
Jeffrey Warren
488bbd86da Rearrange buttons in UI (#936) 2019-03-25 15:57:18 -04:00
Harsh Khandeparkar
a923f48c87 gitignore dist and update links (#908)
* Update .gitignore

* Delete image-sequencer-ui.min.js

* Delete image-sequencer.js

* Delete image-sequencer.min.js

* Update README.md

* Update README.md

* Update CONTRIBUTING.md

* Update .npmignore

* Update README.md

* Update .npmignore

* Update CONTRIBUTING.md
2019-03-25 15:55:34 -04:00
dependabot[bot]
15e93f09bd Bump grunt from 1.0.3 to 1.0.4 (#939)
Bumps [grunt](https://github.com/gruntjs/grunt) from 1.0.3 to 1.0.4.
- [Release notes](https://github.com/gruntjs/grunt/releases)
- [Changelog](https://github.com/gruntjs/grunt/blob/master/CHANGELOG)
- [Commits](https://github.com/gruntjs/grunt/compare/v1.0.3...v1.0.4)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-25 11:01:52 -04:00
dependabot[bot]
eb12d061ee Bump looks-same from 7.1.1 to 7.2.0 (#940)
Bumps [looks-same](https://github.com/gemini-testing/looks-same) from 7.1.1 to 7.2.0.
- [Release notes](https://github.com/gemini-testing/looks-same/releases)
- [Changelog](https://github.com/gemini-testing/looks-same/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gemini-testing/looks-same/commits/v7.2.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-25 11:01:42 -04:00
Harsh Khandeparkar
95efe812c3 Rename White balance to ColorTemperature (#931)
* Update and rename src/modules/WhiteBalance/Module.js to src/modules/ColorTemperature/Module.js

* Rename src/modules/WhiteBalance/index.js to src/modules/ColorTemperature/index.js

* Update and rename src/modules/WhiteBalance/info.json to src/modules/ColorTemperature/info.json

* Update Modules.js

* Update MODULES.md

* Update MODULES.md

* Update Module.js

* Update info.json
2019-03-25 10:11:55 -04:00
rohithGoudM
9be102e1dd Fixed Unresponsive Select Step Box (#927)
* The cursor changes to pointer when hovered over select element

* Cursor to pointer changes added to demo.css

* adding csrtoptr class directly to dist file

* small bug in ui fixed through bootstrap

* small bug in ui fixed through bootstrap

* Fixed unresponsive bug in ui with bootstrap

* all changes have been deleted regarding the cursor bug. only unresponsive bug has been solved
2019-03-25 10:11:09 -04:00
Jeffrey Warren
b0a00a71d3 Update diagram (#921) 2019-03-24 12:08:57 -04:00
dependabot[bot]
001ad61954 Bump looks-same from 7.1.0 to 7.1.1 (#907)
Bumps [looks-same](https://github.com/gemini-testing/looks-same) from 7.1.0 to 7.1.1.
- [Release notes](https://github.com/gemini-testing/looks-same/releases)
- [Changelog](https://github.com/gemini-testing/looks-same/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gemini-testing/looks-same/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-22 19:21:12 -04:00
Jeffrey Warren
ca8b7ecb95 Update CONTRIBUTING.md 2019-03-22 14:37:22 -04:00
Harshith pabbati
33dcb5794f clear cache offline button (#910) 2019-03-21 18:51:36 -04:00
Harshith pabbati
9ffd60c707 Seo tags for google search (#914)
* Seo tags for google search

* changes

* changes
2019-03-21 16:50:24 -04:00
Harsh Khandeparkar
32bd372139 Minify JS for production (#897)
* Create prod.js

* Delete prod.js

* add production task

* add grunt tasks to contributing file

* add default task.
2019-03-20 23:19:18 -04:00
Slytherin
bae2013243 Fixed quick buttons issue (#905) 2019-03-20 17:21:57 -04:00
Varun Gupta
cb53efbe21 redid import-image and fix ExportBin fixes #899 (#900)
* redid import-image and fix ExportBin fixes #899

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

* 3.0.1

* bypass import-image

Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2019-03-20 13:53:02 -04:00
MAYANK CHHIPA
21ff486618 Add Dropdown Transitions (#881)
* Add Dropdown Transitions

* Add Dropdown Transitions

* Update defaultHtmlStepUi.js

* Add Dropdown Transitions

* Add Dropdown Transitions

* Add Dropdown Transitions
2019-03-19 15:28:05 -04:00
Harsh Khandeparkar
951afdbc4f add grunt build to setup script (#895) 2019-03-19 11:50:09 -04:00
aashna27
709df84cb2 Corrected view (#867) 2019-03-19 11:41:39 -04:00
Harsh Khandeparkar
f852730d98 Is Nightly Completed (#893)
* beta demo

* config.yml

* Update config.yml

* Update ISSUE_TEMPLATE.md

* Update package.json

* mistake

* mistake
2019-03-19 10:25:06 -04:00
Vibhor Gupta
e5cf6a311f Add: Exposure Module (#721)
* exposure module

* requested changes

* update module
2019-03-19 08:02:28 -04:00
289 changed files with 10807 additions and 97717 deletions

11
.codecov.yml Normal file
View File

@@ -0,0 +1,11 @@
comment:
layout: "reach, diff, flags, files"
behavior: default
require_changes: false # if true: only post the comment if coverage changes
require_base: no # [yes :: must have a base report to post]
require_head: yes # [yes :: must have a head report to post]
branches: null # branch names that can post comment
coverage:
status:
project: off
patch: off

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
dist/*

36
.eslintrc.js Normal file
View File

@@ -0,0 +1,36 @@
module.exports = {
'env': {
'browser': true,
'commonjs': true,
'es6': true,
'node': true
},
'extends': 'eslint:recommended',
'globals': {
'Atomics': 'readonly',
'SharedArrayBuffer': 'readonly'
},
'parserOptions': {
'ecmaVersion': 2018
},
'rules': {
'indent': ['error',2],
'linebreak-style': ['error','unix'],
'quotes': ['error','single'],
'semi': ['error','always'], //
'no-undef': 0,
'no-console': 'off',
'no-unused-vars': 'off',
'no-redeclare': 'off',
'no-inner-declarations':'off',
'no-empty':'off',
'no-mixed-spaces-and-tabs':'off',
'no-self-assign':'off',
'no-constant-condition':'off',
'no-dupe-keys':'off',
'space-infix-ops': ['error', {'int32Hint': false}], // Enforce spaces around operators
'comma-spacing': ['error', { "before": false, "after": true }], // require spacing after a comma
'comma-style': ['error', 'last'], // requires comma after and on the same line
'no-trailing-spaces': ['error', { 'skipBlankLines': true }], // Disallows trailing whitespace on end of lines and empty lines
}
};

View File

@@ -10,7 +10,7 @@
### Please show us where to look
http://sequencer.publiclab.org...
https://beta.sequencer.publiclab.org
### What's your PublicLab.org username?

View File

@@ -1,4 +1,4 @@
Fixes #[Add issue number here.]
Fixes #0000 (<=== Replace `0000` with the Issue Number)
Make sure these boxes are checked before your pull request (PR) is ready to be reviewed and merged. Thanks!

2
.github/config.yml vendored
View File

@@ -17,7 +17,7 @@ newPRWelcomeComment: |
# Comment to be posted to on pull requests merged by a first time user
firstPRMergeComment: |
Congrats on merging your first pull request! 🙌🎉⚡️
Your code will likely be published to https://sequencer.publiclab.org in the next few days.
Your code will be published to https://beta.sequencer.publiclab.org in a day or two.
In the meantime, can you tell us your Twitter handle so we can thank you properly?
Now that you've completed this, you can help someone else take their first step!
See: [Public Lab's coding community!](https://code.publiclab.org)

12
.github/first-timers.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# You can change the labels to suit your needs if "first-timers-only" is not what you are looking for.
# These are some examples.
labels:
- first-timers-only
- help wanted
#If you would like to add your own template for the issue, add an .md file to your .github folder
template: .github/fto-template.md
# You can create the issue in a different repo than where the problem is. Just make sure you installed the bot on the configured repository.
# The issue will link back to the original repository where the contribution will be made.
#repository: repo-name

51
.github/fto-template.md vendored Normal file
View File

@@ -0,0 +1,51 @@
Hi, this is a [first-timers-only issue](https://code.publiclab.org/#r=all). This means we've worked to make it more legible to folks who either **haven't contributed to our codebase before, or even folks who haven't contributed to open source before**.
If that's you, we're interested in helping you take the first step and can answer questions and help you out as you do. Note that we're especially interested in contributions from people from groups underrepresented in free and open source software!
We know that the process of creating a pull request is the biggest barrier for new contributors. This issue is for you 💝
If you have contributed before, **consider leaving this one for someone new**, and looking through our general [help wanted](https://github.com/publiclab/image-sequencer/labels/help-wanted) issues. Thanks!
### 🤔 What you will need to know.
Nothing. This issue is meant to welcome you to Open Source :) We are happy to walk you through the process.
### 📋 Step by Step
- [ ] 🙋 **Claim this issue**: Comment below. If someone else has claimed it, ask if they've opened a pull request already and if they're stuck -- maybe you can help them solve a problem or move it along!
- [ ] 📝 **Update** the file [$FILENAME]($BRANCH_URL) in the `$REPO` repository (press the little pen Icon) and edit the line as shown below.
[See this page](https://code.publiclab.org/#r=all) for some help in taking your first steps!
Below is a "diff" showing in red (and a `-`) which lines to remove, and in green (and a `+`) which lines to add:
```diff
$DIFF
```
- [ ] 💾 **Commit** your changes
- [ ] 🔀 **Start a Pull Request**. There are two ways how you can start a pull request:
1. If you are familiar with the terminal or would like to learn it, [here is a great tutorial](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) on how to send a pull request using the terminal.
2. You can also [edit files directly in your browser](https://help.github.com/articles/editing-files-in-your-repository/) and open a pull request from there.
- [ ] 🏁 **Done** Ask in comments for a review :)
### Please keep us updated
💬⏰ - We encourage contributors to be respectful to the community and provide an update **within a week** of claiming a first-timers-only issue. We're happy to keep it assigned to you as long as you need if you update us with a request for more time or help, but if we don't see any activity a week after you claim it we may reassign it to give someone else a chance. Thank you in advance!
If this happens to you, don't sweat it! Grab another open issue.
### Is someone else already working on this?
🔗- We encourage contributors to link to the original issue in their pull request so all users can easily see if someone's already started on it.
👥- **If someone seems stuck, offer them some help!** Otherwise, [take a look at some other issues you can help with](https://code.publiclab.org/#r=all). Thanks!
### 🤔❓ Questions?
Leave a comment below!

6
.gitignore vendored
View File

@@ -27,6 +27,10 @@ build/Release
node_modules
node_modules/*
# Dist Files
dist/*
dist
# Optional npm cache directory
.npm
@@ -45,4 +49,4 @@ test/core/modules/test_outputs/*
node_modules/
node_modules/*
test_outputs
/test_outputs
/test_outputs

View File

@@ -37,6 +37,8 @@ test.js
output.txt
output/
examples/
icons/

View File

@@ -1,13 +1,12 @@
sudo: required
language: node_js
node_js:
- '6'
- '8'
- '10'
env:
- CXX=g++-4.8
before_script:
- npm install grunt-cli -g # for "grunt build"
- npm install jasmine -g
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
- ./cc-test-reporter before-build
@@ -15,6 +14,8 @@ script:
- npm test
- npm run test-ui
- grunt build
after_success:
- bash <(curl -s https://codecov.io/bash)
after_script:
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
addons:
@@ -24,6 +25,10 @@ addons:
packages:
- g++-4.8
- xvfb # for tape-run
before_install:
- sudo apt-get update
- sudo apt-get install xserver-xorg-dev libxext-dev libxi-dev
- sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config libglu1-mesa-dev freeglut3-dev mesa-common-dev
install:
- export DISPLAY=':99.0' # for tape-run
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & # for tape-run

View File

@@ -3,6 +3,10 @@ Contributing to Image Sequencer
Happily accepting pull requests; to edit the core library, modify files in `./src/`. To build, run `npm install` followed by `grunt build`.
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.
Most contribution (we imagine) would be in the form of API-compatible modules, which need not be directly included.
## Jump To
@@ -11,6 +15,9 @@ Most contribution (we imagine) would be in the form of API-compatible modules, w
* [Contributing Modules](#contributing-modules)
* [Info File](#info-file)
* [Ideas](#Contribution-ideas)
* [User Preferences](#user-preferences)
* [Grunt Tasks](#grunt-tasks)
* [UI Helper Methods](#ui-helper-methods)
****
@@ -26,7 +33,7 @@ If you find a bug please list it here, and help us develop Image Sequencer by [o
## Contributing modules
Most contributions can happen in modules, rather than to core library code. Modules and their [corresponding info files](#info-file) are included into the library in this file: https://github.com/publiclab/image-sequencer/blob/master/src/Modules.js#L5-L7
Most contributions can happen in modules, rather than to core library code. Modules and their [corresponding info files](#info-file) are included into the library in this file: https://github.com/publiclab/image-sequencer/blob/main/src/Modules.js#L5-L7
Module names, descriptions, and parameters are set in the `info.json` file -- [see below](#info-file).
@@ -62,6 +69,8 @@ Image Sequencer modules are designed to be run either in the browser or in a Nod
https://github.com/tech4gt/image-sequencer
### Browser/node compatibility
If you wish to offer a module without browser-compatibility, please indicate this in the returned `info` object as:
module.exports = [
@@ -108,7 +117,20 @@ function ModuleName(options,UI) {
// load a standard info.json file.
];
```
### Running a browser-only module in node
If your module has browser specific code or you are consuming a dependency which does the `gl-context` api. We designed this api especially for webl based modules but since it runs the module in a headless browser, ti supports all browser specific APIs.
The api must be used in the following format
```js
var step = this;
if (!options.inBrowser) {
require('../_nomodule/gl-context')(input, callback, step, options);
}
else {
/* Browser specific code */
}
```
### options
@@ -139,7 +161,7 @@ input = {
pixelManipulation: "general purpose pixel manipulation API, see https://github.com/publiclab/image-sequencer/blob/master/src/modules/_nomodule/PixelManipulation.js"
}
```
For example usage for pixelManipulation see https://github.com/publiclab/image-sequencer/blob/master/src/modules/Invert/Module.js
For example usage of pixelManipulation see https://github.com/publiclab/image-sequencer/blob/main/src/modules/Invert/Module.js
**The module is included in the browser inside a script tag and since the code runs directly in the browser if any other module is required apart from the apis available on the input object, it should be either bundled with the module code and imported in es6 format or the module code must be browserified before distribution for browser**
@@ -259,11 +281,12 @@ module.exports = function ModuleName(options,UI) {
The `progressObj` parameter of `draw()` is not consumed unless a custom progress bar needs to be drawn, for which this default spinner should be stopped with `progressObj.stop()` and image-sequencer is informed about the custom progress bar with `progressObj.overrideFlag = true;` following which this object can be overriden with custom progress object.
### Module example
See existing module `green-channel` for an example: https://github.com/publiclab/image-sequencer/tree/master/src/modules/GreenChannel/Module.js
See existing module `channel` for an example: https://github.com/publiclab/image-sequencer/blob/main/src/modules/Channel/Module.js
The `green-channel` module is included into the core modules here: https://github.com/publiclab/image-sequencer/blob/master/src/Modules.js#L5-L7
The `channel` module is included into the core modules here: https://github.com/publiclab/image-sequencer/blob/main/src/Modules.js#L5-L7
For help integrating, please open an issue.
@@ -345,4 +368,131 @@ module.exports =
}
}
});
```
```
## User Preferences
The user preferences API can be used for adding, reading, updating and deleting user preferences in the browser using **indexedDB** API.
* File Path: [/src/ui/userPrefs.js](https://github.com/publiclab/image-sequencer/blob/main/src/ui/userPrefs.js)
### Usage
```js
var userPrefs = require('/path/to/userPrefs')(options);
if (userPrefs.error) {
console.log(error);
return;
}
userPrefs.addPref('user-name', {name: 'user'}, () => {
userPrefs.new().getPref('user-name', (pref) => {
console.log(pref.name); // user
userPrefs.new().deletePref('user-name', () => {console.log('deleted')}) // preference deleted
})
})
```
### Return Value
A new `userPreferenceManager` object is returned by the function.
###### note: If an error occured or if **indexedDB** is not supported by he browser, the return value will be an object with a string `error` property.
#### Properties
The `userPreferenceManager` object has the following properties.
- `dbName`: Name of the database the user preferences are stored in.
- `storeName`: The object store in the database where the user preferences are stored.
#### Options
The function accepts a single object called `options` as an argument which has the following properties.
* `dbName`: Name of a custom database. Default is `user-prefs`.
* `storeName`: Name of a custom objectStore. Default is `user-prefs`.
#### Methods
The following methods are available on the returned object.
* `addPref(prefName, preference, callback)`: Adds a preference with the name `prefName` and value `preference`. `preference` is an object containing any key but `preference`. `callback` is a function executed once a preference as been added.
* `deletePref(prefName, callback)`: Deletes he preference with the name `prefName` if it exists. `callback` is executed once the preference is deleted.
* `updatePref(prefName, preference, callback)`: Updates the value of the preference with the name `prefName` to `preference`.
* `getPref(prefName, callback)`: Gets the preference with the name `prefName`. The value is passed to `callback` which is executed once the preference is fetched. If the requested preference doesn't exist then the value passed to `callback` will be `undefined`.
* `new()`: Returns a new `userPreferenceManager` object with the same options as before. This function can be used if the original object is to be reused as the `userPreferenceManager` object can only be used once.
## Linting
We are now using `eslint` and `husky` to help lint and format our code each time we commit. Eslint defines coding standards and helps in cleaning up the code. To run eslint for checking errors globally or within a specific file run:
```
npx eslint .
npx eslint <file path>
```
And to fix those errors globally or in a file, run these in your terminal:
```
npx eslint . --fix
npx eslint <file path> --fix
```
Be sure to not include the angular brackets(<>).
Husky ensures automation of the above steps with git-hooks(eg. git add,git commit..). However we don't want to check and fix changes of the entire codebase with each commit and that the fixes made by eslint appear unstaged and require us to commit them again and that is where lint-staged helps.
If we want `husky` to not verify the commit and push it anyway, use `git commit -m "message" --no-verify.`
## Grunt Tasks
This repository has different grunt tasks for different uses. The source code is in the [Gruntfile](https://github.com/publiclab/image-sequencer/blob/main/Gruntfile.js).
The following command is used for running the tasks: `grunt [task-name]`. Here `[task-name]` should be replaced by the name of the task to be run. To run the default task run `grunt` without any options.
#### Tasks
1. **compile**: Compiles/Browserifies the dist files in `/dist/image-sequencer.js` and `/dist/image-sequencer-ui.js`.
2. **build**: Compiles the files as in the **compile** task and minifies/uglifies dist files in `/dist/image-sequencer.min.js` and `/dist/image-sequencer-ui.min.js`.
3. **watch**: Checks for any changes in the source code and runs the **compile** task if any changes are found.
4. **serve**: Compiles the dist files as in the **compile** task and starts a local server on `localhost:3000` to host the demo site in `/examples/` directory. Also runs the **watch** task.
5. **production**: Compiles and minifies dist files in `/dist/image-sequencer.js` and `/dist/image-sequencer-ui.js` without the `.min.js` extension to include minified files in the demo site. This script should only be used in production mode while deploying.
6. **default**: Runs the **watch** task as default.
## UI Helper Methods
### scopeQuery
###### Path: `/examples/lib/scopeQuery.js`
The method returns a scoped `jQuery` object which only searches for elements inside a given scope (a DOM element).
To use the method,
* import the `scopeSelector` and `scopeSelectorAll` methods from `lib/scopeQuery.js`
* call the methods with scope as a parameter
```js
var scopeQuery = require('./scopeQuery');
var $step = scopeQuery.scopeSelector(scope),
$stepAll = scopeQuery.scopeSelectorAll(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;
#### Example
```js
//The scope is a div element with id=“container“ and there are three divs in it
//with ids „1“, „2“, and „3“, and all of them have a „child“ class attribute
var $step = require('./scopeQuery').scopeSelector(document.getElementById('container'));
$step('#1'); // returns the div element with id=“1“
$step('#1').hide().elemAll('.child').fadeOut(); // abruptly hides the div element with id=“1“ and fades out all other div elements
```
These two methods are chainable and will always return elements from inside the scope.
#### Usage
Instead of using
```js
$(step.ui.querySelector('query')).show().hide();
$(step.ui.querySelectorAll('q2')).show().hide();
```
The following code can be used
```js
$step('query').show().hide();
$stepAll('q2').show().hide();
```

View File

@@ -1,59 +1,76 @@
module.exports = function(grunt) {
grunt.loadNpmTasks("grunt-browserify");
grunt.loadNpmTasks("grunt-contrib-uglify-es");
grunt.loadNpmTasks("grunt-browser-sync");
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify-es');
grunt.loadNpmTasks('grunt-browser-sync');
require("matchdep")
.filterDev("grunt-*")
require('matchdep')
.filterDev('grunt-*')
.forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
pkg: grunt.file.readJSON('package.json'),
watch: {
options: {
livereload: true
},
source: {
files: ["src/**/*", "Gruntfile.js", "examples/lib/*","examples/demo.js"],
tasks: ["browserify"]
files: ['src/**/*', 'Gruntfile.js', 'examples/lib/*', 'examples/demo.js'],
tasks: ['compile']
}
},
browserify: {
core: {
src: ["src/ImageSequencer.js"],
dest: "dist/image-sequencer.js"
},
src: ['src/ImageSequencer.js'],
dest: 'dist/image-sequencer.js'
},
ui: {
src: ["examples/demo.js"],
dest: "dist/image-sequencer-ui.js"
src: ['examples/demo.js'],
dest: 'dist/image-sequencer-ui.js'
},
prodcore: {
src: ['src/ImageSequencer.js'],
dest: 'dist/image-sequencer.brow.js'
},
produi: {
src: ['examples/demo.js'],
dest: 'dist/image-sequencer-ui.brow.js'
}
},
uglify: {
core: {
src: ["./dist/image-sequencer.js"],
dest: "./dist/image-sequencer.min.js"
src: ['./dist/image-sequencer.js'],
dest: './dist/image-sequencer.min.js'
},
ui: {
src: ['dist/image-sequencer-ui.js'],
dest: 'dist/image-sequencer-ui.min.js'
},
prodcore: {
src: ['dist/image-sequencer.brow.js'],
dest: 'dist/image-sequencer.js'
},
produi: {
src: ['dist/image-sequencer-ui.brow.js'],
dest: 'dist/image-sequencer-ui.js'
}
},
browserSync: {
dev: {
options: {
watchTask: true,
server: "./"
server: './'
}
}
}
});
/* Default (development): Watch files and build on change. */
grunt.registerTask("default", ["watch"]);
grunt.registerTask("build", ["browserify", "uglify"]);
grunt.registerTask("serve", ["browserify", "browserSync", "watch"]);
grunt.registerTask("compile", ["browserify"]);
grunt.registerTask('default', ['watch']);
grunt.registerTask('build', ['browserify:core', 'browserify:ui', 'uglify:core', 'uglify:ui']);
grunt.registerTask('serve', ['browserify:core', 'browserify:ui', 'browserSync', 'watch']);
grunt.registerTask('compile', ['browserify:core', 'browserify:ui']);
grunt.registerTask('production', ['browserify:prodcore', 'browserify:produi', 'uglify:prodcore', 'uglify:produi']);
};

112
README.md
View File

@@ -1,7 +1,12 @@
Image Sequencer
====
[![Build Status](https://travis-ci.org/publiclab/image-sequencer.svg?branch=master)](https://travis-ci.org/publiclab/image-sequencer)
[![Build Status](https://travis-ci.org/publiclab/image-sequencer.svg?branch=master)](https://travis-ci.org/publiclab/image-sequencer) [![Maintainability](https://api.codeclimate.com/v1/badges/5906996dd2e90aca6398/maintainability)](https://codeclimate.com/github/publiclab/image-sequencer/maintainability) [![Codecov](https://img.shields.io/codecov/c/github/publiclab/image-sequencer.svg?logo=codecov)](https://codecov.io/gh/publiclab/image-sequencer)
- **Latest Stable Demo**: https://sequencer.publiclab.org
- **Latest Beta Demo**: https://beta.sequencer.publiclab.org
- **Stable Branch**: https://github.com/publiclab/image-sequencer/tree/stable/
## Why
@@ -14,9 +19,9 @@ Image Sequencer is different from other image processing systems because it's _n
The following diagrams attempt to explain how the applications various components interconnect:
![general diagram](https://i.imgur.com/S3Dou2M.jpg)
![general diagram](https://publiclab.org/i/30547.png?s=o)
![workflow diagram](https://raw.githubusercontent.com/publiclab/image-sequencer/master/examples/images/diagram-workflows.png)
![workflow diagram](https://raw.githubusercontent.com/publiclab/image-sequencer/main/examples/images/diagram-workflows.png)
It also for prototypes other related ideas:
@@ -24,15 +29,17 @@ It also for prototypes other related ideas:
* test-based image processing -- the ability to create a sequence of steps that do the same task as other image processing tools, provable with example before/after images to compare with
* logging each step -- to produce an evidentiary record of modifications to an original image
* cascading changes -- change an earlier step's settings, and see those changes affect later steps
* "small modules" -- based extensibility: see [Contributing](https://github.com/publiclab/image-sequencer/blob/master/CONTRIBUTING.md)
* "small modules" -- based extensibility: see [Contributing](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md)
## Examples
* [Simple Demo](https://publiclab.github.io/image-sequencer/)
* [Simple Demo](https://sequencer.publiclab.org)
* [Latest Beta Demo](https://beta.sequencer.publiclab.org)
A diagram of this running 5 steps on a single sample image may help explain how it works:
![example workflow](https://raw.githubusercontent.com/publiclab/image-sequencer/master/examples/images/diagram-6-steps.png)
![example workflow](https://raw.githubusercontent.com/publiclab/image-sequencer/main/examples/images/diagram-6-steps.png)
## Jump to:
@@ -43,8 +50,8 @@ A diagram of this running 5 steps on a single sample image may help explain how
* [Method Chaining](#method-chaining)
* [Multiple Images](#multiple-images)
* [Creating a User Interface](#creating-a-user-interface)
* [Contributing](https://github.com/publiclab/image-sequencer/blob/master/CONTRIBUTING.md)
* [Submit a Module](https://github.com/publiclab/image-sequencer/blob/master/CONTRIBUTING.md#contributing-modules)
* [Contributing](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md)
* [Submit a Module](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md#contributing-modules)
* [Get Demo Bookmarklet](https://publiclab.org/w/imagesequencerbookmarklet)
## Installation
@@ -52,12 +59,12 @@ A diagram of this running 5 steps on a single sample image may help explain how
This library conveniently works in the browser, in Node, and on the command line (CLI).
### Unix based platforms
You can set up a local environment to test the UI with `sudo npm run setup` followed by `npm start`
You can set up a local environment to test the UI with `sudo npm run setup` followed by `npm start`.
### Windows
Our npm scripts do not support windows shells, please run the following snippet in PowerShell.
```powershell
npm i ; npm i -g grunt grunt-cli ; grunt serve
npm i ; npm i -g grunt grunt-cli ; grunt build; grunt serve
```
In case of a port conflict please run the following
```powershell
@@ -66,12 +73,12 @@ npm i -g http-server ; http-server -p 3000
### Browser
Just include [image-sequencer.js](https://publiclab.github.io/image-sequencer/dist/image-sequencer.js) in the Head section of your web page. See the [demo here](https://publiclab.github.io/image-sequencer/)!
Just include [image-sequencer.min.js](https://github.com/publiclab/image-sequencer/blob/stable/dist/image-sequencer.min.js) in the Head section of your web page. See the [demo here](https://sequencer.publiclab.org)!
### Node (via NPM)
(You must have NPM for this)
Add `image-sequencer` to your list of dependencies and run `$ npm install`
Add `image-sequencer` to your list of dependencies and run `npm install`
### CLI
@@ -88,7 +95,7 @@ $ npm install image-sequencer -g
```
$ npm run debug invert
```
## Quick Usage
### Initializing the Sequencer
@@ -108,7 +115,7 @@ Note: Browser CORS Restrictions apply. Some browsers may not allow local images
from other folders, and throw a Security Error instead.
```js
sequencer.replaceImage(selector,steps,optional_options);
sequencer.replaceImage(selector,steps,optional_options);
```
`optional_options` allows passing additional arguments to the module itself.
@@ -116,8 +123,8 @@ from other folders, and throw a Security Error instead.
For example:
```js
sequencer.replaceImage('#photo','invert');
sequencer.replaceImage('#photo',['invert','ndvi-red']);
sequencer.replaceImage('#photo','invert');
sequencer.replaceImage('#photo',['invert','ndvi-red']);
```
### Data URL usage
@@ -143,7 +150,7 @@ Image Sequencer also provides a CLI for applying operations to local files. The
The basic format for using the CLI is as follows:
```
$ ./index.js -i [PATH] -s step-name
$ ./index.js -i [PATH] -s step-name
```
*NOTE:* On Windows you'll have to use `node index.js` instead of `./index.js`.
@@ -151,7 +158,7 @@ The basic format for using the CLI is as follows:
The CLI also can take multiple steps at once, like so:
```
$ ./index.js -i [PATH] -s "step-name-1 step-name-2 ..."
$ ./index.js -i [PATH] -s "step-name-1 step-name-2 ..."
```
But for this, double quotes must wrap the space-separated steps.
@@ -194,15 +201,17 @@ var sequencer = ImageSequencer();
### Loading an Image into the Sequencer
The `loadImage` method is used to load an image into the sequencer. It accepts
a name and an image. The method also accepts an optional callback.
an image `src`, either a URL or a data-url. The method also accepts an optional callback.
```js
sequencer.loadImage(image_src,optional_callback);
sequencer.loadImage(image_src, optional_callback);
```
On `Node.js` the `image_src` may be a DataURI or a local path or a URL.
On browsers, it may be a DatURI, a local image or a URL (Unless this violates
CORS Restrictions). To sum up, these are accepted:
* Images in the same domain (or directory - for a local implementation)
* CORS-Proof images in another domain.
* DataURLs
@@ -212,7 +221,7 @@ The callback is called within the scope of a sequencer. For example:
(addSteps is defined later)
```js
sequencer.loadImage('SRC',function(){
sequencer.loadImage('SRC', function(){
this.addSteps('module-name');
});
```
@@ -234,7 +243,39 @@ If multiple images are to be added, `modules` is an array, which holds the names
to be added, in that particular order.
optional_otions is just an optional parameter, in object form, which you might
want to provide to the modules.
want to provide to the modules.
A variety of syntaxes are supported by Image Sequencer to add multiple steps and configurations quickly for module chaining. The project supports the string syntax, designed to be compact and URL friendly, and JSON, for handling more complex sequences. This can be achieved by passing strings to `sequencer.addStep()`:
```js
sequencer.addSteps('invert,channel');
sequencer.addSteps(['invert','channel']);
```
For passing default configurations ({} is optional):
```js
sequencer.addSteps('brightness{}');
```
For passing custom configurations:
```js
sequencer.addSteps('brightness{brightness:80}');
```
For passing multiple custom configurations:
```js
sequencer.addSteps('crop{x:120|y:90}')
```
For passing multiple custom configurable modules:
```js
sequencer.addSteps('crop{x:130|y:80},brightness{brightness:80}')
```
return value: **`sequencer`** (To allow method chaining)
@@ -391,7 +432,7 @@ Image sequencer supports stringifying a sequence which is appended to the url an
channel{channel:green},invert{}
```
Sequencer also supports the use of `()` in place of `{}` for backward compatibility with older links. (This syntax is deprecated and should be avoided as far as possible)
The use of `()` in place of `{}` for backward compatibility with older links is now **deprecated**. (There is no longer support for the following syntax, and should be avoided)
```
channel(channel:green),invert()
```
@@ -430,7 +471,7 @@ sequencer.importJSON([
To see this in action, please refer to line # 51 of the following:
[test/core/modules/import-export.js](https://github.com/publiclab/image-sequencer/blob/main/test/core/modules/import-export.js)
## Creating a User Interface
@@ -507,7 +548,7 @@ sequencer.setUI({
Image Sequencer object supports one imageURL at a time.
Adding a seccond image to same sequencer will result to adding same set of steps added to prior image and flushing out the previous one.
Adding a seccond image to same sequencer will result to adding same set of steps added to prior image and flushing out the previous one.
```js
s1 = new ImageSequencer(...);
@@ -537,3 +578,24 @@ sequencer2.run();
This method returns an object which defines the name and inputs of the modules. If a module name (hyphenated) is passed in the method, then only the details of that module are returned.
The `notify` function takes two parameters `msg` and `id`, former being the message to be displayed on console (in case of CLI and node ) and a HTML component(in browser). The id is optional and is useful for HTML interface to give appropriate IDs.
## Using WebAssembly for heavy pixel processing
Any module which uses the `changePixel` function gets WebAssembly acceleration (`wasm`). Both node and browser code use WebAssembly and the only code which falls back to non-`wasm` code is the [browserified unit tests](https://github.com/publiclab/image-sequencer/blob/main/test/core/sequencer/benchmark.js).
The main advantage we get using `wasm` is blazing fast speed attained in processing pixels for many modules that is very clear from [checking module benchmarks](https://travis-ci.org/publiclab/image-sequencer/jobs/544415673#L1931).
The only limitation is that browser and node code for `wasm` had to be written separately, and switched between. This is because in browser we use `fetch` to retrieve the compiled `wasm` program while in node we use the `fs` module, each of which cannot be used in the other's environment.
`wasm` mode is enabled by default. If you need to force this mode to be on or off, you can use the `useWasm` option when initializing ImageSequencer:
```js
let sequencer = ImageSequencer({useWasm:true}) // for wasm mode or simply
let sequencer = ImageSequencer() // also for wasm mode i.e. default mode
let sequencer = ImageSequencer({useWasm:false}) //for non-wasm mode
```

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

73614
dist/image-sequencer.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
dist/manipulation.wasm vendored Normal file

Binary file not shown.

View File

@@ -37,7 +37,8 @@ List of Module Documentations
32. [Saturation](#saturation-module)
33. [Threshold](#threshold)
34. [Tint](#tint)
35. [WhiteBalance](#white-balance)
35. [ColorTemperature](#color-temperature)
36. [Grid-Overlay](#grid-overlay)
## crop-module
@@ -571,17 +572,32 @@ where `options` is an object with the following property:
* factor : amount of tint (default 0.5)
## White Balance
## Color Temperature
This Change the colour balance of the image by adjusting the colour temperature.
This changes the color temperature of the image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('white-balance',options)
.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

@@ -1,14 +1,14 @@
/* https://github.com/theleagueof/league-spartan */
@font-face {
font-family: 'League Spartan';
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot');
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot?#iefix') format('embedded-opentype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff2') format('woff2'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff') format('woff'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.ttf') format('truetype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.svg#league_spartanbold') format('svg');
font-weight: bold;
font-style: normal;
font-family: 'League Spartan';
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot');
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot?#iefix') format('embedded-opentype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff2') format('woff2'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff') format('woff'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.ttf') format('truetype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.svg#league_spartanbold') format('svg');
font-weight: bold;
font-style: normal;
}
body {
@@ -18,11 +18,19 @@ body {
background: #f8f8fa;
}
footer {
margin-top: 40px;
}
h1 {
font-family: 'League Spartan';
color: #445;
}
body > .container,
body > .container-fluid {
}
.center-align {
display: flex;
justify-content: center;
@@ -71,17 +79,6 @@ h1 {
margin-bottom: 20px;
}
.details {
border-top: 3px solid #444;
padding-left: 6px;
}
.details h3 {
font-family: monospace;
margin-top: 12px;
font-size: 1.3em;
}
.det {
padding: 10px 16px;
text-decoration: italic;
@@ -100,11 +97,6 @@ h1 {
color: #444;
}
.load-spin{
position: absolute;
right: 0px;
}
#addStep {
max-width: 500px;
margin: 20px auto;
@@ -159,19 +151,19 @@ h1 {
}
#move-up {
position: fixed;
bottom: 50px;
right: 40px;
z-index: 550;
display: none;
background:transparent;
border:none;
position: fixed;
bottom: 50px;
right: 40px;
z-index: 550;
display: none;
background:transparent;
border:none;
}
#move-up i {
font-size:60px;
opacity:0.7;
color:#BABABA;
font-size:60px;
opacity:0.7;
color:#BABABA;
}
.btn-circle{
@@ -208,7 +200,7 @@ h1 {
.savesequencemsg{
display: none;
text-align: center;
}
}
.notification {
background-color: #808b96;
@@ -251,14 +243,36 @@ a.name-header{
color: #445;
}
.step-column{
display:flex;
flex-direction:row;
align-items:center;
.step-column{
display:flex;
align-content: center;
justify-content: center;
}
.step-image{
width:100%;
display:flex;
flex-direction:column;
align-items:center;
.trash-container button.btn-xs {
margin-top: -5px !important;
}
.toggleIcon {
transition: transform 0.2s;
}
.rotated {
transform: rotate(180deg);
}
#gif{
margin-left:0px;
margin-top:5px;
width:100%;
}
.save-button{
margin-top:20px;
margin-bottom:0px;
align:center;
width:100%;
}
.toggle {
cursor: default;
}

View File

@@ -1,9 +1,9 @@
var defaultHtmlSequencerUi = require('./lib/defaultHtmlSequencerUi.js'),
setupCache = require('./lib/cache.js'),
intermediateHtmlStepUi = require('./lib/intermediateHtmlStepUi.js'),
DefaultHtmlStepUi = require('./lib/defaultHtmlStepUi.js'),
urlHash = require('./lib/urlHash.js'),
insertPreview = require('./lib/insertPreview.js');
setupCache = require('./lib/cache.js'),
intermediateHtmlStepUi = require('./lib/intermediateHtmlStepUi.js'),
DefaultHtmlStepUi = require('./lib/defaultHtmlStepUi.js'),
urlHash = require('./lib/urlHash.js'),
insertPreview = require('./lib/insertPreview.js');
window.onload = function() {
sequencer = ImageSequencer();
@@ -12,21 +12,21 @@ window.onload = function() {
// Load information of all modules (Name, Inputs, Outputs)
var modulesInfo = sequencer.modulesInfo();
var addStepSelect = $("#addStep select");
addStepSelect.html("");
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>"
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
);
}
// Null option
addStepSelect.append('<option value="none" disabled selected>More modules...</option>');
addStepSelect.append('<option value="" disabled selected>Select a Module</option>');
addStepSelect.selectize({
sortField: 'text'
});
});
}
refreshOptions();
@@ -36,7 +36,7 @@ window.onload = function() {
var shouldDisplay = $('body').scrollTop() > 20 || $(':root').scrollTop() > 20;
$('#move-up').css({
display: shouldDisplay ? 'block' : 'none'
display: shouldDisplay ? 'block' : 'none'
});
}
@@ -46,7 +46,7 @@ window.onload = function() {
$(':root').animate({scrollTop: 0});
}
$('#move-up').on("click",topFunction);
$('#move-up').on('click', topFunction);
// UI for each step:
@@ -59,48 +59,43 @@ window.onload = function() {
if (urlHash.getUrlHashParameter('src')) {
sequencer.loadImage(urlHash.getUrlHashParameter('src'), ui.onLoad);
} else {
sequencer.loadImage("images/tulips.png", ui.onLoad);
sequencer.loadImage('images/tulips.png', ui.onLoad);
}
var resetSequence = function(){
var r=confirm("Do you want to reset the sequence?");
var r = confirm('Do you want to reset the sequence?');
if (r)
window.location = "/";
}
window.location = '/';
};
$("#addStep select").on("change", ui.selectNewStepUi);
$("#addStep #add-step-btn").on("click", ui.addStepUi);
$("#resetButton").on("click",resetSequence);
$('#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');
//$("#addStep option[value=" + newStep + "]").attr('selected', 'selected');
$("#addStep select").val(newStep);
ui.selectNewStepUi();
ui.addStepUi();
$('#addStep select').val(newStep);
ui.selectNewStepUi(newStep);
ui.addStepUi(newStep);
$(this).removeClass('selected');
});
$('#download-btn').click(function() {
$('.step-thumbnail:last()').trigger("click");
return false;
});
function displayMessageOnSaveSequence(){
$(".savesequencemsg").fadeIn();
setTimeout(function() {
$(".savesequencemsg").fadeOut();
}, 1000);
}
$('.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).");
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)";
result = result + ' (local)';
sequencer.saveSequence(result, sequencer.toString());
sequencer.loadModules();
displayMessageOnSaveSequence();
@@ -118,11 +113,11 @@ window.onload = function() {
var button = event.target;
button.disabled = true;
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");
var imgs = document.getElementsByClassName('step-thumbnail');
var imgSrcs = [];
@@ -135,7 +130,7 @@ window.onload = function() {
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
}
};
gifshot.createGIF(options, function(obj) {
if (!obj.error) {
@@ -143,21 +138,21 @@ window.onload = function() {
var image = obj.image;
var animatedImage = document.createElement('img');
animatedImage.id = "gif_element";
animatedImage.id = 'gif_element';
animatedImage.src = image;
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");
download(image, 'index.gif', 'image/gif');
// Close modal
modal.modal('hide');
})
});
var gifContainer = document.getElementById("js-download-modal-gif-container");
var gifContainer = document.getElementById('js-download-modal-gif-container');
// Clear previous results
gifContainer.innerHTML = '';
@@ -170,6 +165,7 @@ window.onload = function() {
modal.modal();
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
});
@@ -177,6 +173,7 @@ window.onload = function() {
catch (e) {
console.error(e);
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
@@ -184,40 +181,40 @@ window.onload = function() {
// image selection and drag/drop handling from examples/lib/imageSelection.js
sequencer.setInputStep({
dropZoneSelector: "#dropzone",
fileInputSelector: "#fileInput",
takePhotoSelector: "#take-photo",
dropZoneSelector: '#dropzone',
fileInputSelector: '#fileInput',
takePhotoSelector: '#take-photo',
onLoad: function onFileReaderLoad(progress) {
var reader = progress.target;
var step = sequencer.steps[0];
var util= intermediateHtmlStepUi(sequencer);
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;
insertPreview.updatePreviews(reader.result,'addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src,'insertStep');
insertPreview.updatePreviews(reader.result, '#addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src, '.insertDiv');
},
onTakePhoto: function (url) {
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;
insertPreview.updatePreviews(url,'addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src,'insertStep');
insertPreview.updatePreviews(url, '#addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src, '.insertDiv');
}
});
setupCache();
if (urlHash.getUrlHashParameter('src')) {
insertPreview.updatePreviews(urlHash.getUrlHashParameter('src'),'addStep');
insertPreview.updatePreviews(urlHash.getUrlHashParameter('src'), '#addStep');
} else {
insertPreview.updatePreviews("images/tulips.png",'addStep');
insertPreview.updatePreviews('images/tulips.png', '#addStep');
}
};
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,6 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -11,6 +10,16 @@
<link rel="icon" sizes="192x192" href="../icons/ic_192.png">
<link rel="manifest" href="manifest.json">
<!--Adding meta Tag for search engine optimisation-->
<meta property="og:description"
content="A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original image, it creates a new image at each step in a sequence.">
<meta property="og:site_name" content="sequencer.publiclab.org">
<meta property="og:url" content="https://sequencer.publiclab.org">
<meta property="og:title" content="Image Sequencer">
<meta name="Description"
content="Image Sequencer is an image editing tool that creates a new downloadble image at each step.It works in browser and supports both node and CLI.">
<meta name="Keywords" content="image editing downloadable browser node CLI">
<title>Image Sequencer</title>
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
@@ -18,25 +27,29 @@
<script src="../src/ui/prepareDynamic.js"></script>
<script src="../dist/image-sequencer.js" charset="utf-8"></script>
<script src="../dist/image-sequencer-ui.js" charset="utf-8"></script>
<script src="../node_modules/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js"></script>
<!-- for crop module: -->
<script src="../node_modules/imgareaselect/jquery.imgareaselect.dev.js"></script>
<script src="../node_modules/gifshot/dist/gifshot.min.js" type="text/javascript"></script>
<!-- Download.js for large files -->
<script src="../node_modules/downloadjs/download.min.js" type="text/javascript"/>
<script src="../node_modules/downloadjs/download.min.js" type="text/javascript" />
<script src="lib/scrollToTop.js"></script>
<script src="../node_modules/selectize/dist/js/standalone/selectize.min.js"></script>
</head>
<body>
<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="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: -->
<!-- for crop module: -->
<link href="../node_modules/imgareaselect/distfiles/css/imgareaselect-default.css" rel="stylesheet">
<link href="./selectize.default.css" rel="stylesheet">
<link rel="stylesheet" href="demo.css">
@@ -45,7 +58,8 @@
<header class="text-center">
<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 image, it
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original
image, it
creates a new image at each step in a sequence.
<a href="https://publiclab.org/image-sequencer">Learn more</a>
</p>
@@ -54,7 +68,7 @@
<a href="https://github.com/publiclab/image-sequencer">
<i class="fa fa-github"></i>
</a>
by <a href= "https://publiclab.org" title = "Publiclab Website"><i class = "fa fa-globe"></i> Publiclab</a>
by <a href="https://publiclab.org" title="Publiclab Website"><i class="fa fa-globe"></i> Publiclab</a>
</p>
</header>
@@ -65,7 +79,7 @@
<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="400" height="300" style="display:none"></video>
<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>
@@ -77,82 +91,79 @@
</section>
<hr />
<p class = "alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules.</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>
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules.
</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>Resize</p>
</div>
<div>
<div class="radio" data-value="brightness">
<i class="fa fa-sun-o fa-4x i-over"></i>
<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>
<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="center-align">
<select id="selectStep" >
<!-- The default null selection has been appended manually in demo.js
<div class="row center-align">
<div class="col-md-8">
<select id="selectStep">
<!-- 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>
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button>
</select>
</div>
<div class="col-md-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>
<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>
<section id="sequence-actions" class="panel">
<div class="panel-body">
<div class="row center-align">
<!--<button class="btn btn-primary btn-block btn-lg" name="save-sequence" id="save-seq">Save Sequence</button> -->
<!--<button class="btn btn-primary btn-block btn-lg" id="download-btn" name="download" style="display: block; margin: 0px 10px 0px 0px; width: 250px;">Download PNG</button> -->
<button class="btn btn-primary btn-block btn-lg js-view-as-gif" id="gif" style="margin: 0px 35px 0px 35px;width:100%;">View GIF</button>
</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>
<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">
@@ -170,61 +181,57 @@
</div>
</div>
</section>
</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>
<p>Or click ARROW to save the entire sequence as a workflow for future use.</p>
<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>
</select>
<button id="saveButton" class="btn btn-primary btn-lg" style="margin-top:20px; margin-bottom:0px;align:center; width:100%;">Save</button>
<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>Save as PNG</option>
<option>Save as GIF (all steps)</option>
<option>Save sequence</option>
<option>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>
<footer>
<hr style="margin:20px;">
<center><button class="btn btn-default btn-sm" id="clear-cache">Clear offline cache</button></center>
<div class="row">
<div class="col-md-6">
<h2>Need Help?</h2>
<p>
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer/issues">Ask a question</a>
<a class="btn btn-default" href="https://publiclab.org/chat">Ask in our chatroom</a>
</p>
</div>
<div class="col-md-6">
<h2>Improve this tool</h2>
<p>
This is an open source toolkit which you can help improve on Github
</p>
<p>
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer">View the code &raquo;</a>
</p>
</div>
</div>
</section>
</div>
</div>
</footer>
<footer>
<hr style="margin:20px;"><center><a class="color:grey;" id="clear-cache">Clear offline cache</a></center>
<div class="row">
<div class="col-md-6">
<h2>Need Help?</h2>
<p>
Post a link to this and ask help from other community members on <a href="https://github.com/publiclab/image-sequencer/issues/new">Github Issues</a>
</p>
<p>
<a class="btn btn-primary" href="https://gitter.im/publiclab/publiclab">Ask a question on Gitter</a>
</p>
</div>
<div class="col-md-6">
<h2>Improve this tool</h2>
<p>
This is an open source toolkit which you can help add to and improve on <a href="https://github.com/publiclab/image-sequencer/">Github</a>
</p>
<p>
<a class="btn btn-primary" href="https://github.com/publiclab/image-sequencer">View the code &raquo;</a>
</p>
</div>
</div>
</footer>
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
<script type="text/javascript">
$(function() {
var sequencer;
})
</script>
<script type="text/javascript">
$(function () {
var sequencer;
})
</script>
</body>

View File

@@ -4,11 +4,11 @@ var setupCache = function() {
.then(function(registration) {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
console.log(installingWorker)
console.log(installingWorker);
if (installingWorker.state === 'installed') {
location.reload();
}
}
};
console.log('Registration successful, scope is:', registration.scope);
})
.catch(function(error) {
@@ -19,12 +19,12 @@ var setupCache = function() {
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
$("#clear-cache").append(" " + cacheName);
$('#clear-cache').append(' ' + cacheName);
});
});
}
$("#clear-cache").click(function() {
$('#clear-cache').click(function() {
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
@@ -34,6 +34,6 @@ var setupCache = function() {
}
location.reload();
});
}
};
module.exports = setupCache;
module.exports = setupCache;

View File

@@ -2,48 +2,52 @@ var urlHash = require('./urlHash.js');
function DefaultHtmlSequencerUi(_sequencer, options) {
options = options || {};
var addStepSel = options.addStepSel = options.addStepSel || "#addStep";
var removeStepSel = options.removeStepSel = options.removeStepSel || "button.remove";
var selectStepSel = options.selectStepSel = options.selectStepSel || "#selectStep";
var addStepSel = options.addStepSel = options.addStepSel || '#addStep';
var removeStepSel = options.removeStepSel = options.removeStepSel || 'button.remove';
var selectStepSel = options.selectStepSel = options.selectStepSel || '#selectStep';
function onLoad() {
importStepsFromUrlHash();
if ($('#selectStep').val()==='none')
$(addStepSel + " #add-step-btn").prop("disabled", true);
handleSaveSequence();
if ($('#selectStep').val() === 'none')
$(addStepSel + ' #add-step-btn').prop('disabled', true);
handleSaveSequence();
}
// look up needed steps from Url Hash:
function importStepsFromUrlHash() {
var hash = urlHash.getUrlHashParameter("steps");
var hash = urlHash.getUrlHashParameter('steps');
if (hash) {
_sequencer.importString(hash);
_sequencer.run({ index: 0 });
}
urlHash.setUrlHashParameter("steps", sequencer.toString());
urlHash.setUrlHashParameter('steps', sequencer.toString());
}
function selectNewStepUi() {
var m = $(addStepSel + " select").val();
$(addStepSel + " .info").html(_sequencer.modulesInfo(m).description);
$(addStepSel + " #add-step-btn").prop("disabled", false);
var m = $(addStepSel + ' select').val();
if(!m) m = arguments[0];
$(addStepSel + ' .info').html(_sequencer.modulesInfo(m).description);
$(addStepSel + ' #add-step-btn').prop('disabled', false);
}
function removeStepUi() {
var index = $(removeStepSel).index(this) + 1;
sequencer.removeSteps(index).run({ index: index - 1 });
// remove from URL hash too
urlHash.setUrlHashParameter("steps", sequencer.toString());
urlHash.setUrlHashParameter('steps', sequencer.toString());
//disable save-sequence button if all steps are removed
handleSaveSequence();
}
function addStepUi() {
if ($(addStepSel + " select").val() == "none") return;
var newStepName = $(addStepSel + " select").val();
if ($(addStepSel + ' select').val() == 'none') return;
var newStepName;
if(typeof arguments[0] !== 'string')
newStepName = $(addStepSel + ' select option').html().toLowerCase().split(' ').join('-');
else newStepName = arguments[0];
/*
* after adding the step we run the sequencer from defined step
* and since loadImage is not a part of the drawarray the step lies at current
@@ -52,28 +56,28 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
var sequenceLength = 1;
if (sequencer.sequences[newStepName]) {
sequenceLength = sequencer.sequences[newStepName].length;
} else if (sequencer.modules[newStepName][1]["length"]) {
sequenceLength = sequencer.modules[newStepName][1]["length"];
} else if (sequencer.modules[newStepName][1]['length']) {
sequenceLength = sequencer.modules[newStepName][1]['length'];
}
_sequencer
.addSteps(newStepName, options)
.run({ index: _sequencer.steps.length - sequenceLength - 1 });
$(addStepSel + " .info").html("Select a new module to add to your sequence.");
$(addStepSel + " select").val("none");
$(addStepSel + ' .info').html('Select a new module to add to your sequence.');
$(addStepSel + ' select').val('none');
//enable save-sequence button if disabled initially
handleSaveSequence();
// add to URL hash too
urlHash.setUrlHashParameter("steps", _sequencer.toString())
urlHash.setUrlHashParameter('steps', _sequencer.toString());
}
function handleSaveSequence(){
var stepCount=sequencer.steps.length;
if(stepCount<2)
$(" #save-seq").prop("disabled", true);
var stepCount = sequencer.steps.length;
if(stepCount < 2)
$(' #save-seq').prop('disabled', true);
else
$(" #save-seq").prop("disabled", false);
$(' #save-seq').prop('disabled', false);
}
return {
@@ -82,7 +86,7 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
selectNewStepUi: selectNewStepUi,
removeStepUi: removeStepUi,
addStepUi: addStepUi
}
};
}
module.exports = DefaultHtmlSequencerUi;

View File

@@ -8,63 +8,75 @@
// 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');
var intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
urlHash = require('./urlHash.js'),
_ = require('lodash'),
mapHtmlTypes = require('./mapHtmltypes'),
scopeQuery = require('./scopeQuery'),
$stepAll,
$step;
function DefaultHtmlStepUi(_sequencer, options) {
options = options || {};
var stepsEl = options.stepsEl || document.querySelector("#steps");
var selectStepSel = options.selectStepSel = options.selectStepSel || "#selectStep";
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;
step.ui =
'\
<div class="container">\
<div class="row step" style="display:flex">\
<form class="input-form">\
<div class="col-md-4 details" style="flex:1">\
<h3>\
<span class = "toggle">' +step.name + ' <i class="fa fa-caret-up toggleIcon" aria-hidden="true"></i></span>' +
'<span class="load-spin" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></span>' +
'</h3><div class="cal"><p><i>"'+
(step.description || "") +
'</i></p></div>\
</div>\
</form>\
<div class="col-md-8 cal step-column">\
<div class="load" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></div>\
<div class="step-image">\
<a><img alt="" class="img-thumbnail step-thumbnail"/></a>\
</div>\
</div>\
</div>\
</div>\
</div>';
<div class="container-fluid step-container">\
<div class="panel panel-default">\
<div class="panel-heading">\
<div class="trash-container pull-right"></div>\
<h3 class="panel-title">' +
'<span class="toggle">' + step.name + ' <span class="caret toggleIcon rotated"></span>\
<span class="load-spin pull-right" style="display:none;padding:1px 8px;"><i class="fa fa-circle-o-notch fa-spin"></i></span>\
</h3>\
</div>\
<form class="input-form">\
<div class="panel-body cal collapse in">\
<div class="row step">\
<div class="col-md-4 details container-fluid">\
<div class="cal collapse in"><p>' +
'<i>' + (step.description || '') + '</i>' +
'</p></div>\
</div>\
<div class="col-md-8 cal collapse in step-column">\
<div class="load load-spin" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></div>\
<div class="step-image">\
<a class="cal collapse in"><img class="img-thumbnail step-thumbnail"/></a>\
</div>\
</div>\
</div>\
</div>\
<div class="panel-footer cal collapse in"></div>\
</form>\
</div>\
</div>';
var tools =
'<div class="cal"><div class="tools btn-group">\
<button confirm="Are you sure?" class="remove btn btn btn-default">\
<i class="fa fa-trash"></i>\
</button>\
<button class="btn insert-step" style="margin-left:10px;border-radius:6px;background-color:#fff;border:solid #bababa 1.1px;" >\
<i class="fa fa-plus"></i> Add\
</button>\
</div>\
'<div class="trash">\
<button confirm="Are you sure?" class="remove btn btn-default btn-xs">\
<i class="fa fa-trash"></i>\
</button>\
</div>';
var util = intermediateHtmlStepUi(_sequencer, step);
var parser = new DOMParser();
step.ui = parser.parseFromString(step.ui, "text/html");
step.ui = step.ui.querySelector("div.container");
step.linkElements = step.ui.querySelectorAll("a");
step.imgElement = step.ui.querySelector("a img");
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.linkElements = $stepAll('a');
step.imgElement = $step('a img.img-thumbnail')[0];
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
var inputs = _sequencer.modulesInfo(step.name).inputs;
@@ -73,112 +85,134 @@ function DefaultHtmlStepUi(_sequencer, options) {
for (var paramName in merged) {
var isInput = inputs.hasOwnProperty(paramName);
var html = "";
var html = '';
var inputDesc = isInput ? mapHtmlTypes(inputs[paramName]) : {};
if (!isInput) {
html += '<span class="output"></span>';
} else if (inputDesc.type.toLowerCase() == "select") {
}
else if (inputDesc.type.toLowerCase() == 'select') {
html += '<select class="form-control target" name="' + paramName + '">';
for (var option in inputDesc.values) {
html += "<option>" + inputDesc.values[option] + "</option>";
html += '<option>' + inputDesc.values[option] + '</option>';
}
html += "</select>";
} else {
html += '</select>';
}
else {
let paramVal = step.options[paramName] || inputDesc.default;
html =
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal +
'" placeholder ="' +
(inputDesc.placeholder || "");
if (inputDesc.type.toLowerCase() == "range") {
if (inputDesc.id == 'color-picker') { // separate input field for color-picker
html +=
'"min="' +
inputDesc.min +
'"max="' +
inputDesc.max +
'"step="' +
(inputDesc.step ? inputDesc.step : 1)+ '">' + '<span>' + paramVal + '</span>';
'<div id="color-picker" class="input-group colorpicker-component">' +
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal + '">' + '<span class="input-group-addon"><i></i></span>' +
'</div>';
}
else { // use this if the the field isn't color-picker
html =
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal +
'" placeholder ="' +
(inputDesc.placeholder || '');
if (inputDesc.type.toLowerCase() == 'range') {
html +=
'"min="' +
inputDesc.min +
'"max="' +
inputDesc.max +
'"step="' +
(inputDesc.step ? inputDesc.step : 1) + '">' + '<span>' + paramVal + '</span>';
}
else html += '">';
}
else html += '">';
}
var div = document.createElement("div");
div.className = "row";
div.setAttribute("name", paramName);
var div = document.createElement('div');
div.className = 'row';
div.setAttribute('name', paramName);
var description = inputs[paramName].desc || paramName;
div.innerHTML =
"<div class='det cal'>\
<label for='" +
'<div class=\'det cal collapse in\'>\
<label for=\'' +
paramName +
"'>" +
'\'>' +
description +
"</label>\
" +
'</label>\
' +
html +
"\
</div>";
step.ui.querySelector("div.details").appendChild(div);
'\
</div>';
$step('div.details').append(div);
}
$(step.ui.querySelector("div.details")).append(
'<div class="cal"><p><button type="submit" class="btn btn-default btn-save" disabled = "true" >Apply</button><span> Press apply to see changes</span></p></div>'
$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('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" >\
<i class="fa fa-download"></i>\
</button>'
);
}
if (step.name != "load-image") {
step.ui
.querySelector("div.details")
.appendChild(
parser.parseFromString(tools, "text/html").querySelector("div")
if (step.name != 'load-image') {
$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 .container:nth-last-child(1) .insert-step").prop('disabled',true);
if($("#steps .container:nth-last-child(2)"))
$("#steps .container:nth-last-child(2) .insert-step").prop('disabled',false);
$('#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 {
stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]);
}
}
else {
$("#load-image").append(step.ui);
$('#load-image').append(step.ui);
}
$(step.ui.querySelector(".toggle")).on("click", () => {
$(step.ui.querySelector('.toggleIcon')).toggleClass('fa-caret-up').toggleClass('fa-caret-down');
$(step.ui.querySelectorAll(".cal")).toggleClass("collapse");
$step('.toggle').on('click', () => {
$step('.toggleIcon').toggleClass('rotated');
$stepAll('.cal').collapse('toggle');
});
$(step.imgElement).on("mousemove", _.debounce(() => imageHover(step), 150));
$(step.imgElement).on('mousemove', _.debounce(() => imageHover(step), 150));
$(step.imgElement).on('click', (e) => {e.preventDefault(); });
$stepAll('#color-picker').colorpicker();
function saveOptions(e) {
e.preventDefault();
if (optionsChanged){
$(step.ui.querySelector("div.details"))
.find("input,select")
$step('div.details')
.find('input,select')
.each(function(i, input) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false);
step.options[$(input).attr("name")] = $(input).val();
step.options[$(input).attr('name')] = $(input).val();
});
_sequencer.run({ index: step.index - 1 });
// modify the url hash
urlHash.setUrlHashParameter("steps", _sequencer.toString())
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;
}
@@ -189,19 +223,19 @@ 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
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)
.on('input', function() {
.on('input change', function() {
$(this)
.focus()
.data('hasChangedBefore',
@@ -209,35 +243,32 @@ function DefaultHtmlStepUi(_sequencer, options) {
$(this).val(),
$(this).data('initValue'),
$(this).data('hasChangedBefore')
)
)
})
})
)
);
});
});
$('input[type="range"]').on('input', function() {
$(this).next().html($(this).val());
})
$(this).next().html($(this).val());
});
}
function onDraw(step) {
$(step.ui.querySelector(".load")).show();
$(step.ui.querySelector("img")).hide();
if( $(step.ui.querySelector(".toggleIcon")).hasClass("fa-caret-down") )
{
$(step.ui.querySelector(".load-spin")).show();
}
function onDraw() {
$step('.load').show();
$step('img').hide();
$stepAll('.load-spin').show();
}
function onComplete(step) {
$(step.ui.querySelector(".load")).hide();
$(step.ui.querySelector("img")).show();
$(step.ui.querySelector(".load-spin")).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");
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
var imgthumbnail = $step('.img-thumbnail');
for (let index = 0; index < step.linkElements.length; index++) {
if (step.linkElements[index].contains(imgthumbnail))
step.linkElements[index].href = step.imgElement.src;
@@ -245,14 +276,24 @@ function DefaultHtmlStepUi(_sequencer, options) {
// TODO: use a generalized version of this
function fileExtension(output) {
return output.split("/")[1].split(";")[0];
return output.split('/')[1].split(';')[0];
}
for (let index = 0; index < step.linkElements.length; index++) {
$stepAll('.download-btn').on('click', () => {
step.linkElements[index].download = step.name + "." + fileExtension(step.imgElement.src);
step.linkElements[index].target = "_blank";
}
for (let index = 0; index < step.linkElements.length; index++){
var element = document.createElement('a');
element.setAttribute('href', step.linkElements[index].href);
element.setAttribute('download', step.name + '.' + fileExtension(step.imgElement.src));
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
});
// fill inputs with stored step options
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
@@ -260,19 +301,19 @@ function DefaultHtmlStepUi(_sequencer, options) {
var outputs = _sequencer.modulesInfo(step.name).outputs;
for (var i in inputs) {
if (step.options[i] !== undefined) {
if (inputs[i].type.toLowerCase() === "input")
$(step.ui.querySelector('div[name="' + i + '"] input'))
if (inputs[i].type.toLowerCase() === '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'))
if (inputs[i].type.toLowerCase() === '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]);
}
}
@@ -282,24 +323,24 @@ function DefaultHtmlStepUi(_sequencer, options) {
var img = $(step.imgElement);
img.mousemove(function(e) {
img.mousemove(function(e) {
var canvas = document.createElement('canvas');
canvas.width = img.width();
canvas.height = img.height();
var context = canvas.getContext('2d');
context.drawImage(this,0,0);
context.drawImage(this, 0, 0);
var offset = $(this).offset();
var xPos = e.pageX - offset.left;
var yPos = e.pageY - offset.top;
var myData = context.getImageData(xPos, yPos, 1, 1);
img[0].title = "rgb: " +myData.data[0]+","+ myData.data[1]+","+myData.data[2];//+ rgbdata;
});
img[0].title = 'rgb: ' + myData.data[0] + ',' + myData.data[1] + ',' + myData.data[2];//+ rgbdata;
});
}
function onRemove(step) {
step.ui.remove();
$("#steps .container:nth-last-child(1) .insert-step").prop('disabled',true);
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
$('div[class*=imgareaselect-]').remove();
}
@@ -307,35 +348,35 @@ function DefaultHtmlStepUi(_sequencer, options) {
return step.imgElement;
}
function notify(msg,id){
if ($('#'+id).length == 0) {
function notify(msg, id){
if ($('#' + id).length == 0) {
var notification = document.createElement('span');
notification.innerHTML = ' <i class="fa fa-info-circle" aria-hidden="true"></i> ' + msg ;
notification.id = id;
notification.classList.add("notification");
notification.classList.add('notification');
$('body').append(notification);
}
$('#'+id).fadeIn(500).delay(200).fadeOut(500);
$('#' + id).fadeIn(500).delay(200).fadeOut(500);
}
return {
getPreview: getPreview,
onSetup: onSetup,
onComplete: onComplete,
onRemove: onRemove,
onDraw: onDraw,
onDraw: onDraw,
notify: notify,
imageHover: imageHover
}
};
}
if(typeof window === "undefined"){
module.exports={
if(typeof window === 'undefined'){
module.exports = {
DefaultHtmlStepUi: DefaultHtmlStepUi
}
};
}
module.exports = DefaultHtmlStepUi;

View File

@@ -1,55 +1,55 @@
function generatePreview(previewStepName, customValues, path, selector) {
var previewSequencer = ImageSequencer();
function insertPreview(src) {
var img = document.createElement('img');
img.classList.add('img-thumbnail')
img.classList.add('no-border');
img.src = src;
$(img).css("max-width", "200%");
$(img).css("transform", "translateX(-20%)");
var stepDiv = $('#'+selector+' .row').find('div').each(function() {
if ($(this).find('div').attr('data-value') === previewStepName) {
$(this).find('div').append(img);
}
});
}
function loadPreview() {
if (previewStepName === "crop") {
previewSequencer.addSteps(previewStepName, customValues).run(insertPreview);
var previewSequencer = ImageSequencer();
function insertPreview(src) {
var img = document.createElement('img');
img.classList.add('img-thumbnail');
img.classList.add('no-border');
img.src = src;
$(img).css('max-width', '200%');
$(img).css('transform', 'translateX(-20%)');
$(selector + ' .radio-group').find('div').each(function() {
if ($(this).find('div').attr('data-value') === previewStepName) {
$(this).find('div').append(img);
}
else {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
previewSequencer.loadImage(path, loadPreview);
}
function updatePreviews(src, selector) {
$('#'+selector+' img').remove();
var previewSequencerSteps = {
"resize": "125%",
"brightness": "175",
"saturation": "0.5",
"rotate": 90,
"contrast": 90,
"crop": {
"x": 0,
"y": 0,
"w": "(50%)",
"h": "(50%)",
"noUI": true
}
}
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
});
}
function loadPreview() {
if (previewStepName === 'crop') {
previewSequencer.addSteps(previewStepName, customValues).run(insertPreview);
}
else {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
previewSequencer.loadImage(path, loadPreview);
}
function updatePreviews(src, selector) {
$(selector + ' img').remove();
var previewSequencerSteps = {
'resize': '125%',
'brightness': '175',
'saturation': '0.5',
'rotate': 90,
'contrast': 90,
'crop': {
'x': 0,
'y': 0,
'w': '(50%)',
'h': '(50%)',
'noUI': true
}
};
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
});
}
module.exports = {
generatePreview : generatePreview,
updatePreviews : updatePreviews
}
};

View File

@@ -1,135 +1,163 @@
var urlHash = require('./urlHash.js'),
insertPreview = require('./insertPreview.js');
insertPreview = require('./insertPreview.js');
function IntermediateHtmlStepUi(_sequencer, step, options) {
function stepUI() {
return '<div class="row insertDiv">\
<div class="col-md-6 col-md-offset-2" style="margin-top:5%">\
<section id="insertStep" class="panel panel-primary">\
<div class="form-inline">\
<div class="panel-body">\
<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>\
return '<div class="row insertDiv collapse">\
<section class="panel panel-primary .insert-step">\
<button class="btn btn-default close-insert-box"><i class="fa fa-times" aria-hidden="true"></i> Close</button>\
<div class="form-inline">\
<div class="panel-body">\
<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>\
<div class="radio" data-value="brightness">\
<i class="fa fa-sun-o fa-4x i-over"></i>\
</div>\
<p>Brightness</p>\
<div class="row center-align">\
<div class="col-md-8">\
<select class="insert-step-select">\
<!-- 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">\
<button class="btn btn-success btn-lg insert-save-btn add-step-btn" name="add">Add Step</button>\
<div>\
</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="center-align">\
<select class="form-control input-lg" id="selectStep">\
<!-- 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>\
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button>\
</div>\
</div>\
</div>\
</section>\
</section>\
</div>';
}
function selectNewStepUi() {
var m = $("#insertStep select").val();
$("#insertStep .info").html(_sequencer.modulesInfo(m).description);
$("#insertStep #add-step-btn").prop("disabled", false);
var insertSelect = $step('.insert-step-select');
var m = insertSelect.val();
$step('.insertDiv .info').html(_sequencer.modulesInfo(m).description);
$step('.insertDiv .add-step-btn').prop('disabled', false);
}
var toggleDiv = function(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('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback)});
}
};
insertStep = function (id) {
var modulesInfo = _sequencer.modulesInfo();
var parser = new DOMParser();
var addStepUI = stepUI();
addStepUI = parser.parseFromString(addStepUI, "text/html").querySelector("div")
step.ui
.querySelector("div.step")
.insertAdjacentElement('afterend',
addStepUI
);
insertPreview.updatePreviews(step.output,'insertStep');
var insertStepSelect = $("#insertStep select");
insertStepSelect.html("");
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
if ($step('.insertDiv').length > 0){
toggleDiv();
}
else {
step.ui
.querySelector('div.step')
.insertAdjacentElement('afterend',
addStepUI
);
toggleDiv(function(){
insertPreview.updatePreviews(step.output, '.insertDiv');
});
}
$step('.insertDiv .close-insert-box').off('click').on('click', function(){toggleDiv(function(){})});
var insertStepSelect = $step('.insert-step-select');
insertStepSelect.html('');
// Add modules to the insertStep dropdown
for (var m in modulesInfo) {
if (modulesInfo[m] !== undefined)
insertStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + "</option>"
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
);
}
$('#insertStep #add-step-btn').selectize({
insertStepSelect.selectize({
sortField: 'text'
});
$('#insertStep #add-step-btn').prop('disabled', true);
insertStepSelect.append('<option value="none" disabled selected>More modules...</option>');
$('#insertStep .radio-group .radio').on("click", function () {
$step('.inserDiv .add-step-btn').prop('disabled', true);
insertStepSelect.append('<option value="" disabled selected>Select a Module</option>');
$step('.insertDiv .radio-group .radio').on('click', function () {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
insertStepSelect.val(newStep);
$step('.insert-step-select').val(newStep);
selectNewStepUi();
insert(id);
$(this).removeClass('selected');
});
$(step.ui.querySelector("#insertStep select")).on('change', selectNewStepUi);
$(step.ui.querySelector("#insertStep #add-step-btn")).on('click', function () { insert(id) });
insertStepSelect.on('change', selectNewStepUi);
$step('.insertDiv .add-step-btn').on('click', function () { insert(id) });
}
function insert(id) {
options = options || {};
var insertStepSelect = $("#insertStep select");
if (insertStepSelect.val() == "none") return;
var insertStepSelect = $step('.insert-step-select');
if (insertStepSelect.val() == 'none') return;
var newStepName = insertStepSelect.val()
$('div .insertDiv').remove();
var newStepName = insertStepSelect.val();
toggleDiv();
var sequenceLength = 1;
if (sequencer.sequences[newStepName]) {
sequenceLength = sequencer.sequences[newStepName].length;
} else if (sequencer.modules[newStepName][1]["length"]) {
sequenceLength = sequencer.modules[newStepName][1]["length"];
} else if (sequencer.modules[newStepName][1]['length']) {
sequenceLength = sequencer.modules[newStepName][1]['length'];
}
_sequencer
.insertSteps(id + 1, newStepName).run({ index: id });
// add to URL hash too
urlHash.setUrlHashParameter("steps", _sequencer.toString());
urlHash.setUrlHashParameter('steps', _sequencer.toString());
}
return {
insertStep
}
};
}
module.exports = IntermediateHtmlStepUi;

View File

@@ -1,24 +1,24 @@
function mapHtmlTypes(inputInfo){
var htmlType;
switch(inputInfo.type.toLowerCase()){
case 'integer':
htmlType = inputInfo.min != undefined ? 'range' : 'number';
break;
case 'string':
htmlType = 'text';
break;
case 'select':
htmlType = 'select';
break;
case 'percentage':
htmlType = 'number';
break;
case 'float':
htmlType = inputInfo.min != undefined ? 'range' : 'text';
break;
default:
htmlType = 'text';
break;
case 'integer':
htmlType = inputInfo.min != undefined ? 'range' : 'number';
break;
case 'string':
htmlType = 'text';
break;
case 'select':
htmlType = 'select';
break;
case 'percentage':
htmlType = 'number';
break;
case 'float':
htmlType = inputInfo.min != undefined ? 'range' : 'text';
break;
default:
htmlType = 'text';
break;
}
var response = inputInfo;
response.type = htmlType;

View File

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

View File

@@ -42,8 +42,8 @@ function setUrlHashParameter(param, value) {
}
module.exports = {
getUrlHashParameter: getUrlHashParameter,
setUrlHashParameter: setUrlHashParameter,
getUrlHashParameters: getUrlHashParameters,
setUrlHashParameters: setUrlHashParameters
}
getUrlHashParameter: getUrlHashParameter,
setUrlHashParameter: setUrlHashParameter,
getUrlHashParameters: getUrlHashParameters,
setUrlHashParameters: setUrlHashParameters
};

View File

@@ -17,7 +17,7 @@ self.addEventListener('activate', function(e) {
})
);
})
);
);
});
self.addEventListener('fetch', function(event) {
@@ -25,11 +25,11 @@ self.addEventListener('fetch', function(event) {
caches.open(staticCacheName).then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function(response) {
if(event.request.method == "GET")
if(event.request.method == 'GET')
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
});

View File

@@ -1,14 +1,14 @@
#!/usr/bin/env node
require('./src/ImageSequencer');
sequencer = ImageSequencer({ ui: false });
var fs = require('fs')
sequencer = ImageSequencer({ ui: true });
var fs = require('fs');
var program = require('commander');
var utils = require('./src/CliUtils')
var utils = require('./src/CliUtils');
var saveSequence = require('./src/cli/saveSequence.js')
var installModule = require('./src/cli/installModule.js')
var sequencerSteps = require('./src/cli/sequencerSteps.js')
var saveSequence = require('./src/cli/saveSequence.js');
var installModule = require('./src/cli/installModule.js');
var sequencerSteps = require('./src/cli/sequencerSteps.js');
function exit(message) {
console.error(message);
@@ -16,39 +16,39 @@ function exit(message) {
}
program
.version("0.1.0")
.option("-i, --image [PATH/URL]", "Input image URL")
.option("-s, --step [step-name]", "Name of the step to be added.")
.option("-o, --output [PATH]", "Directory where output will be stored.")
.option("-b, --basic", "Basic mode outputs only final image")
.option("-c, --config [Object]", "Options for the step")
.option("--save-sequence [string]", "Name space separated with Stringified sequence")
.option('--install-module [string]', "Module name space seaprated npm package name")
.version('0.1.0')
.option('-i, --image [PATH/URL]', 'Input image URL')
.option('-s, --step [step-name]', 'Name of the step to be added.')
.option('-o, --output [PATH]', 'Directory where output will be stored.')
.option('-b, --basic', 'Basic mode outputs only final image')
.option('-c, --config [Object]', 'Options for the step')
.option('--save-sequence [string]', 'Name space separated with Stringified sequence')
.option('--install-module [string]', 'Module name space seaprated npm package name')
.parse(process.argv);
if (program.saveSequence) saveSequence(program, sequencer)
if (program.saveSequence) saveSequence(program, sequencer);
else if (program.installModule) installModule(program, sequencer)
else if (program.installModule) installModule(program, sequencer);
else {
// Parse step into an array to allow for multiple steps.
if (!program.step) exit("No steps passed");
program.step = program.step.split(" ");
if (!program.step) exit('No steps passed');
program.step = program.step.split(' ');
// User must input an image.
if (!program.image) exit("Can't read file.");
if (!program.image) exit('Can\'t read file.');
// User must input an image.
fs.access(program.image, function(err) {
if (err) exit("Can't read file.");
if (err) exit('Can\'t read file.');
});
// User must input a step. If steps exist, check that every step is a valid step.
if (!program.step || !(utils.validateSteps(program.step, sequencer)))
exit("Please ensure all steps are valid.");
exit('Please ensure all steps are valid.');
// If there's no user defined output directory, select a default directory.
program.output = program.output || "./output/";
program.output = program.output || './output/';
// Set sequencer to log module outputs, if any.
sequencer.setUI({
@@ -57,19 +57,19 @@ else {
step.info = sequencer.modulesInfo(step.name);
for (var output in step.info.outputs) {
console.log("[" + program.step + "]: " + output + " = " + step[output]);
console.log('[' + program.step + ']: ' + output + ' = ' + step[output]);
}
},
notify: function(msg) {
console.log('\x1b[36m%s\x1b[0m','🌟 '+msg);
console.log('\x1b[36m%s\x1b[0m', '🌟 ' + msg);
}
});
// Finally, if everything is alright, load the image, add the steps and run the sequencer.
sequencer.loadImages(program.image, function() {
console.warn(
"\x1b[33m%s\x1b[0m",
"Please wait \n output directory generated will be empty until the execution is complete"
'\x1b[33m%s\x1b[0m',
'Please wait \n output directory generated will be empty until the execution is complete'
);
//Generate the Output Directory
@@ -82,7 +82,7 @@ else {
outputFilename = null;
}
sequencerSteps(program, sequencer, outputFilename)
sequencerSteps(program, sequencer, outputFilename);
});

4421
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,21 @@
{
"name": "image-sequencer",
"version": "3.0.0",
"version": "3.5.0",
"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 tape test/core/*.js test/core/ui/user-interface.js test/core/modules/QR.js | tap-spec; browserify test/core/modules/image-sequencer.js test/core/modules/chain.js test/core/modules/meta-modules.js test/core/modules/replace.js test/core/modules/import-export.js test/core/modules/run.js test/core/modules/dynamic-imports.js test/core/util/parse-input.js test/core/modules/benchmark.js| tape-run --render=\"tap-spec\"",
"test-ui": "jasmine test/spec/*.js",
"setup": "npm i && npm i -g grunt grunt-cli",
"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/ui/spec/*.js",
"setup": "npm i && npm i -g grunt grunt-cli && grunt build",
"start": "grunt serve"
},
"lint-staged": {
"*.js": [
"./node_modules/.bin/eslint --fix",
"git add"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/publiclab/image-sequencer.git"
@@ -24,53 +30,74 @@
"url": "https://github.com/publiclab/image-sequencer/issues"
},
"dependencies": {
"base64-img": "^1.0.4",
"bootstrap": "~3.4.0",
"bootstrap-colorpicker": "^2.5.3",
"buffer": "~5.2.1",
"commander": "^2.11.0",
"data-uri-to-buffer": "^2.0.0",
"downloadjs": "^1.4.7",
"eslint": "^5.16.0",
"fisheyegl": "^0.1.2",
"font-awesome": "~4.7.0",
"geotiff": "^1.0.0-beta.6",
"get-pixels": "~3.3.0",
"gifshot": "^0.4.5",
"glfx": "0.0.4",
"gpu.js": "^2.0.0-rc.12",
"image-sequencer-invert": "^1.0.0",
"imagejs": "0.0.9",
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
"istanbul": "^0.4.5",
"jasmine": "^3.4.0",
"jquery": "^3.3.1",
"jsdom": "^13.1.0",
"jsdom": "^15.0.0",
"jsqr": "^1.1.1",
"lodash": "^4.17.11",
"ndarray-gaussian-filter": "^1.0.0",
"ndarray": "^1.0.18",
"ora": "^3.0.0",
"pace": "0.0.4",
"puppeteer": "^1.14.0",
"qrcode": "^1.3.3",
"readline-sync": "^1.4.7",
"save-pixels": "~2.3.4",
"selectize": "^0.12.6",
"urify": "^2.1.1"
"urify": "^2.1.1",
"webgl-distort": "0.0.2"
},
"devDependencies": {
"base64-img": "^1.0.4",
"@babel/core": "^7.4.3",
"@babel/plugin-proposal-object-rest-spread": "^7.4.3",
"@babel/plugin-syntax-object-rest-spread": "^7.2.0",
"babelify": "^10.0.0",
"browserify": "16.2.3",
"eslint": "^5.16.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",
"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",
"looks-same": "^7.0.0",
"matchdep": "^2.0.0",
"tap-spec": "^5.0.0",
"tape": "^4.9.2",
"tape-run": "^5.0.0",
"tape-run": "^6.0.0",
"uglify-es": "^3.3.7"
},
"homepage": "https://github.com/publiclab/image-sequencer",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"homepage": "https://sequencer.publiclab.org",
"bin": {
"sequencer": "./index.js"
}

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,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,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

@@ -1,5 +1,5 @@
// add steps to the sequencer
function AddStep(_sequencer, name, o) {
return require('./InsertStep')(_sequencer,-1,name,o);
return require('./InsertStep')(_sequencer, -1, name, o);
}
module.exports = AddStep;

View File

@@ -1,18 +1,18 @@
var fs = require('fs')
var fs = require('fs');
/*
* This function checks if the directory exists, if not it creates one on the given path
* Callback is called with argument error if an error is encountered
*/
function makedir(path,callback){
fs.access(path,function(err){
if(err) fs.mkdir(path,function(err){
if(err) callback(err);
callback();
});
else callback()
function makedir(path, callback){
fs.access(path, function(err){
if(err) fs.mkdir(path, function(err){
if(err) callback(err);
callback();
});
};
else callback();
});
}
// Takes an array of steps and checks if they are valid steps for the sequencer.
function validateSteps(steps, sequencer) {
@@ -37,9 +37,9 @@ function validateConfig(config_, options_) {
for (var input in options_) {
if (!config_[options_[input]]) {
console.error(
"\x1b[31m%s\x1b[0m",
'\x1b[31m%s\x1b[0m',
`Options Object does not have the required details "${
options_[input]
options_[input]
}" not specified. Fallback case activated`
);
return false;
@@ -52,7 +52,7 @@ function validateConfig(config_, options_) {
}
module.exports = exports = {
makedir: makedir,
validateSteps: validateSteps,
validateConfig: validateConfig
}
makedir: makedir,
validateSteps: validateSteps,
validateConfig: validateConfig
};

View File

@@ -2,7 +2,7 @@ var fs = require('fs');
var getDirectories = function(rootDir, cb) {
fs.readdir(rootDir, function(err, files) {
var dirs = [];
if (typeof (files) == "undefined" || files.length == 0) {
if (typeof (files) == 'undefined' || files.length == 0) {
cb(dirs);
return [];
}
@@ -21,22 +21,22 @@ var getDirectories = function(rootDir, cb) {
}
}
});
}
};
module.exports = function ExportBin(dir = "./output/", ref, basic, filename) {
module.exports = function ExportBin(dir = './output/', ref, basic, filename) {
// If user did not give an output filename so we can continue without doing anything
dir = (dir[dir.length - 1] == "/") ? dir : dir + "/";
dir = (dir[dir.length - 1] == '/') ? dir : dir + '/';
if (ref.options.inBrowser) return false;
fs.access(dir, function(err) {
if (err) console.error(err)
if (err) console.error(err);
});
if (filename && basic) {
var steps = ref.steps;
var datauri = steps.slice(-1)[0].output.src;
var ext = steps.slice(-1)[0].output.format;
var buffer = require('data-uri-to-buffer')(datauri);
fs.writeFile(dir + filename, buffer, function() { });
var steps = ref.steps;
var datauri = steps.slice(-1)[0].output.src;
var ext = steps.slice(-1)[0].output.format;
var buffer = require('data-uri-to-buffer')(datauri);
fs.writeFile(dir + filename, buffer, function() { });
}
else {
getDirectories(dir, function(dirs) {
@@ -48,22 +48,22 @@ module.exports = function ExportBin(dir = "./output/", ref, basic, filename) {
}
fs.mkdir(dir + 'sequencer' + num, function() {
var root = dir + 'sequencer' + num + '/';
var steps = ref.steps;
if (basic) {
var datauri = steps.slice(-1)[0].output.src;
var ext = steps.slice(-1)[0].output.format;
var steps = ref.steps;
if (basic) {
var datauri = steps.slice(-1)[0].output.src;
var ext = steps.slice(-1)[0].output.format;
var buffer = require('data-uri-to-buffer')(datauri);
fs.writeFile(root + 'image' + '_' + (steps.length - 1) + '.' + ext, buffer, function() { });
}
else {
for (var i in steps) {
var datauri = steps[i].output.src;
var ext = steps[i].output.format;
var buffer = require('data-uri-to-buffer')(datauri);
fs.writeFile(root + image + "_" + (steps.length - 1) + "." + ext, buffer, function() { });
}
else {
for (var i in steps) {
var datauri = steps[i].output.src;
var ext = steps[i].output.format;
var buffer = require('data-uri-to-buffer')(datauri);
fs.writeFile(root + image + "_" + i + "." + ext, buffer, function() { });
}
fs.writeFile(root + 'image' + '_' + i + '.' + ext, buffer, function() { });
}
}
});
});
}
}
};

View File

@@ -1,19 +1,19 @@
function objTypeOf(object){
return Object.prototype.toString.call(object).split(" ")[1].slice(0,-1)
return Object.prototype.toString.call(object).split(' ')[1].slice(0, -1);
}
function getPrimitive(object){
return (objTypeOf(object)=='Array')?object[0]:object;
return (objTypeOf(object) == 'Array') ? object[0] : object;
}
function makeArray(input) {
return (objTypeOf(input)=="Array")?input:[input];
return (objTypeOf(input) == 'Array') ? input : [input];
}
function copy(a) {
if (!typeof(a) == "object") return a;
if (objTypeOf(a) == "Array") return a.slice();
if (objTypeOf(a) == "Object") {
if (!typeof(a) == 'object') return a;
if (objTypeOf(a) == 'Array') return a.slice();
if (objTypeOf(a) == 'Object') {
var b = {};
for (var v in a) {
b[v] = copy(a[v]);
@@ -23,80 +23,80 @@ function copy(a) {
return a;
}
function formatInput(args,format,images) {
function formatInput(args, format, images) {
var json_q = {};
var format_i = format;
if (format == "+")
if (format == '+')
format = ['string_a', 'o_object'];
else if (format == "-")
else if (format == '-')
format = ['number_a'];
else if (format == "^")
else if (format == '^')
format = ['number', 'string', 'o_object'];
else if (format == "r")
else if (format == 'r')
format = ['o_number'];
else if (format == "l")
format = ['string','o_function'];
else if (format == 'l')
format = ['string', 'o_function'];
if(format[format.length-1] == "o_object") {
if(objTypeOf(args[args.length-1]) != "Object")
if(format[format.length - 1] == 'o_object') {
if(objTypeOf(args[args.length - 1]) != 'Object')
args.push({});
}
else if (format[format.length-1] == "o_number") {
if(typeof(args[args.length-1]) != "number" && objTypeOf(args[0])!="Object")
else if (format[format.length - 1] == 'o_number') {
if(typeof(args[args.length - 1]) != 'number' && objTypeOf(args[0]) != 'Object')
args.push(1);
}
else if (format[format.length-1] == "o_function") {
if(objTypeOf(args[args.length-1]) != "Function" && objTypeOf(args[0])!="Object")
else if (format[format.length - 1] == 'o_function') {
if(objTypeOf(args[args.length - 1]) != 'Function' && objTypeOf(args[0]) != 'Object')
args.push(function(){});
}
if(args.length == format.length) {//making of arrays
for (var i in format) {
if (format[i].substr(format[i].length-2,2)=="_a")
if (format[i].substr(format[i].length - 2, 2) == '_a')
args[i] = makeArray(args[i]);
}
}
if (args.length == 1 ) {
if(format_i == "r") json_q = {0:copy(args[0])};
else if(format_i == "-") {
json_q=[];
json_q= copy(args[0]);
if(format_i == 'r') json_q = {0:copy(args[0])};
else if(format_i == '-') {
json_q = [];
json_q = copy(args[0]);
}
}
else if (format_i == "r" ) {
else if (format_i == 'r' ) {
for (var img in args[0]) json_q = {0:args[0]};
}
else if (format_i == "l") {
else if (format_i == 'l') {
json_q = {
image: args[0],
callback: args[1]
}
};
}
else {
json_q = [];
if(format_i == "+") {
for(var s in args[0]) {
json_q.push({
name: args[0][s],
o: args[1]
});
}
}
if(format_i == "^") {
var size = this.steps.length;
var index = args[0];
index = (index==size)?index:index%size;
if (index<0) index += size+1;
json_q = [];
if(format_i == '+') {
for(var s in args[0]) {
json_q.push({
index: index,
name: args[1],
o: args[2]
name: args[0][s],
o: args[1]
});
}
}
if(format_i == '^') {
var size = this.steps.length;
var index = args[0];
index = (index == size) ? index : index % size;
if (index < 0) index += size + 1;
json_q.push({
index: index,
name: args[1],
o: args[2]
});
}
}

View File

@@ -1,30 +1,29 @@
if (typeof window !== 'undefined') { isBrowser = true }
else { var isBrowser = false }
if (typeof window !== 'undefined') { isBrowser = true; }
else { var isBrowser = false; }
require('./util/getStep.js');
ImageSequencer = function ImageSequencer(options) {
var sequencer = (this.name == "ImageSequencer") ? this : this.sequencer;
var sequencer = (this.name == 'ImageSequencer') ? this : this.sequencer;
options = options || {};
options.inBrowser = options.inBrowser === undefined ? isBrowser : options.inBrowser;
options.sequencerCounter = 0;
function objTypeOf(object) {
return Object.prototype.toString.call(object).split(" ")[1].slice(0, -1)
return Object.prototype.toString.call(object).split(' ')[1].slice(0, -1);
}
function log(color, msg) {
if (options.ui != "none") {
if (options.ui != 'none') {
if (arguments.length == 1) console.log(arguments[0]);
else if (arguments.length == 2) console.log(color, msg);
}
}
function copy(a) {
if (!typeof (a) == "object") return a;
if (objTypeOf(a) == "Array") return a.slice();
if (objTypeOf(a) == "Object") {
var b = {};
if (!typeof (a) == 'object') return a;
if (objTypeOf(a) == 'Array') return a.slice();
if (objTypeOf(a) == 'Object') {
var b = {};
for (var v in a) {
b[v] = copy(a[v]);
}
@@ -34,7 +33,7 @@ ImageSequencer = function ImageSequencer(options) {
}
function makeArray(input) {
return (objTypeOf(input) == "Array") ? input : [input];
return (objTypeOf(input) == 'Array') ? input : [input];
}
var image,
@@ -64,15 +63,15 @@ ImageSequencer = function ImageSequencer(options) {
// else if (options.imageUrl) loadImage(imageUrl);
function addSteps() {
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
var json_q = {};
for (var arg in arguments) { args.push(copy(arguments[arg])); }
json_q = formatInput.call(this_, args, "+");
json_q = formatInput.call(this_, args, '+');
inputlog.push({ method: "addSteps", json_q: copy(json_q) });
for (var j in json_q)
require("./AddStep")(this_, json_q[j].name, json_q[j].o);
inputlog.push({ method: 'addSteps', json_q: copy(json_q) });
for (var j in json_q)
require('./AddStep')(this_, json_q[j].name, json_q[j].o);
return this;
}
@@ -87,58 +86,58 @@ ImageSequencer = function ImageSequencer(options) {
//tell the UI a step has been removed
}
function removeSteps(index) {
function removeSteps() {
var indices;
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this_, args, "-");
inputlog.push({ method: "removeSteps", json_q: copy(json_q) });
var json_q = formatInput.call(this_, args, '-');
inputlog.push({ method: 'removeSteps', json_q: copy(json_q) });
indices = json_q.sort(function(a, b) { return b - a });
for (var i in indices)
removeStep(this_, indices[i]);
indices = json_q.sort(function(a, b) { return b - a; });
for (var i in indices)
removeStep(this_, indices[i]);
return this;
}
function insertSteps(image, index, name, o) {
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = []
function insertSteps() {
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(arguments[arg]);
var json_q = formatInput.call(this_, args, "^");
inputlog.push({ method: "insertSteps", json_q: copy(json_q) });
var json_q = formatInput.call(this_, args, '^');
inputlog.push({ method: 'insertSteps', json_q: copy(json_q) });
var details = json_q;
details = details.sort(function(a, b) { return b.index - a.index });
for (var i in details)
require("./InsertStep")(this_, details[i].index, details[i].name, details[i].o);
var details = json_q;
details = details.sort(function(a, b) { return b.index - a.index; });
for (var i in details)
require('./InsertStep')(this_, details[i].index, details[i].name, details[i].o);
return this;
}
// Config is an object which contains the runtime configuration like progress bar
// information and index from which the sequencer should run
function run(config, t_image, t_from) {
function run(config) {
var progressObj, index = 0;
config = config || { mode: 'no-arg' };
if (config.index) index = config.index;
if (config.mode != "no-arg" && typeof config != 'function') {
if (config.progressObj) progressObj = config.progressObj;
delete arguments['0'];
}
if (config.mode != 'no-arg' && typeof config != 'function') {
if (config.progressObj) progressObj = config.progressObj;
delete arguments['0'];
}
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(copy(arguments[arg]));
var callback = function() { };
for (var arg in args)
if (objTypeOf(args[arg]) == "Function")
if (objTypeOf(args[arg]) == 'Function')
callback = args.splice(arg, 1)[0]; //callback is formed
var json_q = formatInput.call(this_, args, "r");
var json_q = formatInput.call(this_, args, 'r');
require('./Run')(this_, json_q, callback, index, progressObj);
@@ -147,19 +146,19 @@ ImageSequencer = function ImageSequencer(options) {
function loadImages() {
var args = [];
var prevSteps = this.getSteps().slice(1).map(step=>step.options.name)
var prevSteps = this.getSteps().slice(1).map(step=>step.options.name);
var sequencer = this;
sequencer.image = arguments[0];
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this, args, "l");
if(this.getSteps().length!=0){
var json_q = formatInput.call(this, args, 'l');
if(this.getSteps().length != 0){
this.options.sequencerCounter = 0;
inputlog = [];
this.steps = [];
}
inputlog.push({ method: "loadImages", json_q: copy(json_q) });
inputlog.push({ method: 'loadImages', json_q: copy(json_q) });
var ret = {
name: "ImageSequencer Wrapper",
name: 'ImageSequencer Wrapper',
sequencer: this,
addSteps: this.addSteps,
removeSteps: this.removeSteps,
@@ -169,16 +168,16 @@ ImageSequencer = function ImageSequencer(options) {
setUI: this.setUI
};
function loadPrevSteps(ref){
if(prevSteps.length!=0){
ref.addSteps(prevSteps)
prevSteps=[];
if(prevSteps.length != 0){
ref.addSteps(prevSteps);
prevSteps = [];
}
}
require('./ui/LoadImage')(sequencer, "image", json_q.image, function() {
require('./ui/LoadImage')(sequencer, 'image', json_q.image, function() {
loadPrevSteps(sequencer);
json_q.callback.call(ret);
});
}
function replaceImage(selector, steps, options) {
@@ -198,11 +197,11 @@ ImageSequencer = function ImageSequencer(options) {
var exportBin = function(dir, basic, filename) {
return require('./ExportBin')(dir, this, basic, filename);
}
};
function modulesInfo(name) {
var modulesdata = {}
if (name == "load-image") return {};
var modulesdata = {};
if (name == 'load-image') return {};
if (arguments.length == 0) {
for (var modulename in this.modules) {
modulesdata[modulename] = modules[modulename][1];
@@ -212,133 +211,15 @@ ImageSequencer = function ImageSequencer(options) {
}
}
else {
if (modules[name]){
modulesdata = modules[name][1];
}
if (modules[name]){
modulesdata = modules[name][1];
}
else
modulesdata = { 'inputs': sequences[name]['options'] };
}
return modulesdata;
}
// Genates a CLI string for the current sequence
function toCliString() {
var cliStringSteps = `"`, cliOptions = {};
for (var step in this.steps) {
var name = (typeof this.steps[step].options !== "undefined")? this.steps[step].options.name : this.steps[step].name
if (name !== "load-image"){
cliStringSteps += `${name} `;
}
for (var inp in modulesInfo(name).inputs) {
cliOptions[inp] = this.steps[step].options[inp];
}
}
cliStringSteps = cliStringSteps.substr(0, cliStringSteps.length - 1) + `"`;
return `sequencer -i [PATH] -s ${cliStringSteps} -d '${JSON.stringify(cliOptions)}'`
}
// Strigifies the current sequence
function toString(step) {
if (step) {
return stepToString(step);
} else {
return copy(this.steps.map(stepToString).slice(1).join(','));
}
}
// Stringifies one step of the sequence
function stepToString(step) {
var arg = (step.name)?step.name:step.options.name;
let inputs = modulesInfo(arg).inputs || {}, op = {};
for (let input in inputs) {
if (!!step.options[input] && step.options[input] != inputs[input].default) {
op[input] = step.options[input];
op[input] = encodeURIComponent(op[input]);
}
}
var configurations = Object.keys(op).map(key => key + ':' + op[key]).join('|');
return `${arg}{${configurations}}`;
}
// exports the current sequence as an array of JSON steps
function toJSON() {
return this.stringToJSON(this.toString());
}
// Coverts stringified sequence into an array of JSON steps
function stringToJSON(str) {
let steps;
if (str.includes(','))
steps = str.split(',');
else
steps = [str];
return steps.map(stringToJSONstep);
}
// Converts one stringified step into JSON
function stringToJSONstep(str) {
var bracesStrings;
if (str.includes('{'))
if (str.includes('(') && str.indexOf('(') < str.indexOf('{'))
bracesStrings = ['(', ')'];
else
bracesStrings = ['{', '}'];
else
bracesStrings = ['(', ')'];
if (str.indexOf(bracesStrings[0]) === -1) { // if there are no settings specified
var moduleName = str.substr(0);
stepSettings = "";
} else {
var moduleName = str.substr(0, str.indexOf(bracesStrings[0]));
stepSettings = str.slice(str.indexOf(bracesStrings[0]) + 1, -1);
}
stepSettings = stepSettings.split('|').reduce(function formatSettings(accumulator, current, i) {
var settingName = current.substr(0, current.indexOf(':')),
settingValue = current.substr(current.indexOf(':') + 1);
settingValue = settingValue.replace(/^\(/, '').replace(/\)$/, ''); // strip () at start/end
settingValue = settingValue.replace(/^\{/, '').replace(/\}$/, ''); // strip {} at start/end
settingValue = decodeURIComponent(settingValue);
current = [
settingName,
settingValue
];
if (!!settingName) accumulator[settingName] = settingValue;
return accumulator;
}, {});
return {
name: moduleName,
options: stepSettings
}
}
// imports a string into the sequencer steps
function importString(str) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
var stepsFromString = stringToJSON(str);
stepsFromString.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// imports a array of JSON steps into the sequencer steps
function importJSON(obj) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
obj.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
function loadNewModule(name, options) {
if (!options) {
@@ -371,7 +252,7 @@ ImageSequencer = function ImageSequencer(options) {
return;
}
var mods = fs.readFileSync('./src/Modules.js').toString();
mods = mods.substr(0, mods.length - 1) + " '" + name + "': require('" + path + "'),\n}";
mods = mods.substr(0, mods.length - 1) + ' \'' + name + '\': require(\'' + path + '\'),\n}';
fs.writeFileSync('./src/Modules.js', mods);
}
@@ -401,9 +282,11 @@ ImageSequencer = function ImageSequencer(options) {
this.sequences = require('./SavedSequences.json');
}
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
return {
//literals and objects
name: "ImageSequencer",
name: 'ImageSequencer',
options: options,
inputlog: inputlog,
modules: modules,
@@ -423,14 +306,17 @@ ImageSequencer = function ImageSequencer(options) {
setUI: setUI,
exportBin: exportBin,
modulesInfo: modulesInfo,
toCliString: toCliString,
toString: toString,
stepToString: stepToString,
toJSON: toJSON,
stringToJSON: stringToJSON,
stringToJSONstep: stringToJSONstep,
importString: importString,
importJSON: importJSON,
toCliString: str.toCliString,
detectStringSyntax: str.detectStringSyntax,
parseStringSyntax: str.parseStringSyntax,
stringToSteps: str.stringToSteps,
toString: str.toString,
stepToString: str.stepToString,
toJSON: str.toJSON,
stringToJSON: str.stringToJSON,
stringToJSONstep: str.stringToJSONstep,
importString: str.importString,
importJSON: str.importJSON,
loadNewModule: loadNewModule,
saveNewModule: saveNewModule,
createMetaModule: require('./util/createMetaModule'),
@@ -444,7 +330,7 @@ ImageSequencer = function ImageSequencer(options) {
copy: copy,
setInputStep: require('./ui/SetInputStep')(sequencer)
}
};
}
};
module.exports = ImageSequencer;

View File

@@ -6,6 +6,9 @@ function InsertStep(ref, index, name, o) {
return ref.importJSON(ref.sequences[name]);
}
if (ref.detectStringSyntax(name)) {
return ref.stringToSteps(name);
}
function insertStep(index, name, o_) {
if (ref.modules[name]) var moduleInfo = ref.modules[name][1];
@@ -18,15 +21,17 @@ function InsertStep(ref, index, name, o) {
o.number = ref.options.sequencerCounter++; //Gives a Unique ID to each step
o.name = o_.name || name || moduleInfo.name;
o.description = o_.description || moduleInfo.description;
o.moduleInfo = o_.moduleInfo || moduleInfo;
o.selector = o_.selector || 'ismod-' + name;
o.container = o_.container || ref.options.selector;
o.inBrowser = ref.options.inBrowser;
o.useWasm = (ref.options.useWasm === false) ? false : true;
if (index == -1) index = ref.steps.length;
o.step = {
name: o.name,
description: o.description,
moduleInfo: o.moduleInfo,
ID: o.number,
inBrowser: ref.options.inBrowser,
ui: ref.options.ui,
@@ -40,7 +45,7 @@ function InsertStep(ref, index, name, o) {
let step = stepsArray[i];
ref.insertSteps(index + Number.parseInt(i), step['name'], step['options']);
}
}
};
// Tell UI that a step has been set up.
o = o || {};

View File

@@ -7,8 +7,10 @@ module.exports = {
'blend': require('./modules/Blend'),
'blur': require('./modules/Blur'),
'brightness': require('./modules/Brightness'),
'canvas-resize': require('./modules/CanvasResize'),
'channel': require('./modules/Channel'),
'colorbar': require('./modules/Colorbar'),
'color-temperature': require('./modules/ColorTemperature'),
'colormap': require('./modules/Colormap'),
'contrast': require('./modules/Contrast'),
'convolution': require('./modules/Convolution'),
@@ -18,22 +20,27 @@ module.exports = {
'draw-rectangle': require('./modules/DrawRectangle'),
'dynamic': require('./modules/Dynamic'),
'edge-detect': require('./modules/EdgeDetect'),
'exposure': require('./modules/Exposure'),
'flip-image': require('./modules/FlipImage'),
'fisheye-gl': require('./modules/FisheyeGl'),
'histogram': require('./modules/Histogram'),
'gamma-correction': require('./modules/GammaCorrection'),
'gradient': require('./modules/Gradient'),
'grid-overlay': require('./modules/GridOverlay'),
'import-image': require('./modules/ImportImage'),
'invert': require('image-sequencer-invert'),
'ndvi': require('./modules/Ndvi'),
'ndvi-colormap': require('./modules/NdviColormap'),
'paint-bucket': require('./modules/PaintBucket'),
'noise-reduction': require('./modules/NoiseReduction'),
'overlay': require('./modules/Overlay'),
'replace-color':require('./modules/ReplaceColor'),
'paint-bucket': require('./modules/PaintBucket'),
'replace-color': require('./modules/ReplaceColor'),
'resize': require('./modules/Resize'),
'rotate': require('./modules/Rotate'),
'saturation': require('./modules/Saturation'),
'text-overlay': require('./modules/TextOverlay'),
'threshold': require('./modules/Threshold'),
'tint': require('./modules/Tint'),
'webgl-distort': require('./modules/WebglDistort'),
'white-balance': require('./modules/WhiteBalance')
}
};

View File

@@ -1,6 +1,6 @@
// Uses a given image as input and replaces it with the output.
// Works only in the browser.
function ReplaceImage(ref,selector,steps,options) {
function ReplaceImage(ref, selector, steps, options) {
if(!ref.options.inBrowser) return false; // This isn't for Node.js
var tempSequencer = ImageSequencer({ui: false});
var this_ = ref;
@@ -26,23 +26,27 @@ function ReplaceImage(ref,selector,steps,options) {
// https://github.com/publiclab/image-sequencer/issues/241
// https://stackoverflow.com/a/20048852/1116657
var raw = '';
var i,j,subArray,chunk = 5000;
for (i=0,j=arr.length; i<j; i+=chunk) {
subArray = arr.subarray(i,i+chunk);
var i, j, subArray, chunk = 5000;
for (i = 0, j = arr.length; i < j; i += chunk) {
subArray = arr.subarray(i, i + chunk);
raw += String.fromCharCode.apply(null, subArray);
}
var base64 = btoa(raw);
var dataURL="data:image/"+ext+";base64," + base64;
var dataURL = 'data:image/' + ext + ';base64,' + base64;
make(dataURL);
};
if(url.substr(0,11).toLowerCase()!="data:image/") xmlHTTP.send();
if(url.substr(0, 11).toLowerCase() != 'data:image/') xmlHTTP.send();
else make(url);
function make(url) {
tempSequencer.loadImage(url, function(){
this.addSteps(steps).run({stop:function(){}},function(out){
// this.addSteps(steps).run({stop:function(){}},function(out){
var sequence = this.addSteps(steps);
if (ref.detectStringSyntax(steps))
sequence = this.stringToSteps(steps);
sequence.run({stop:function(){}}, function(out){
img.src = out;
});
});
@@ -50,8 +54,8 @@ function ReplaceImage(ref,selector,steps,options) {
}
for (var i = 0; i < images.length; i++) {
replaceImage(images[i],steps);
if (i == images.length-1)
replaceImage(images[i], steps);
if (i == images.length - 1)
options.callback();
}
}

View File

@@ -5,7 +5,7 @@ function Run(ref, json_q, callback, ind, progressObj) {
function drawStep(drawarray, pos) {
if (pos == drawarray.length && drawarray[pos - 1] !== undefined) {
if (ref.objTypeOf(callback) == "Function" && ref.steps.slice(-1)[0].output) {
if (ref.objTypeOf(callback) == 'Function' && ref.steps.slice(-1)[0].output) {
var steps = ref.steps;
var out = steps[steps.length - 1].output.src;
callback(out);
@@ -25,7 +25,7 @@ function Run(ref, json_q, callback, ind, progressObj) {
};
step.getIndex = function getIndex() {
return i;
}
};
for (var util in getStepUtils) {
if (getStepUtils.hasOwnProperty(util)) {
@@ -43,7 +43,7 @@ function Run(ref, json_q, callback, ind, progressObj) {
inputForNextStep,
function onEachStep() {
// This output is accessible by UI
// This output is accessible by UI
ref.steps[i].options.step.output = ref.steps[i].output.src;
// Tell UI that step has been drawn.
@@ -58,26 +58,26 @@ function Run(ref, json_q, callback, ind, progressObj) {
function drawSteps(json_q) {
var drawarray = [],
no_steps = ref.steps.length,
init = json_q[0];
for (var i = 0; i < no_steps - init; i++) {
drawarray.push({i: init + i });
}
no_steps = ref.steps.length,
init = json_q[0];
for (var i = 0; i < no_steps - init; i++) {
drawarray.push({i: init + i });
}
drawStep(drawarray, ind);
}
function filter(json_q) {
if (json_q[0] == 0 && ref.steps.length == 1)
delete json_q[0];
else if (json_q[0] == 0) json_q[0]++;
var prevstep = ref.steps[json_q[0] - 1];
while (
typeof prevstep == "undefined" ||
typeof prevstep.output == "undefined"
) {
prevstep = ref.steps[--json_q[0] - 1];
}
if (json_q[0] == 0 && ref.steps.length == 1)
delete json_q[0];
else if (json_q[0] == 0) json_q[0]++;
var prevstep = ref.steps[json_q[0] - 1];
while (
typeof prevstep == 'undefined' ||
typeof prevstep.output == 'undefined'
) {
prevstep = ref.steps[--json_q[0] - 1];
}
return json_q;
}

View File

@@ -5,10 +5,10 @@ const dataUriToBuffer = require('data-uri-to-buffer');
const savePixels = require('save-pixels');
module.exports = function(input) {
input.getPixels = getPixels;
input.pixelManipulation = pixelManipulation;
input.lodash = lodash;
input.dataUriToBuffer = dataUriToBuffer;
input.savePixels = savePixels;
return input;
}
input.getPixels = getPixels;
input.pixelManipulation = pixelManipulation;
input.lodash = lodash;
input.dataUriToBuffer = dataUriToBuffer;
input.savePixels = savePixels;
return input;
};

159
src/Strings.js Normal file
View File

@@ -0,0 +1,159 @@
module.exports = function(steps, modulesInfo, addSteps, copy) {
// Genates a CLI string for the current sequence
function toCliString() {
var cliStringSteps = '"', cliOptions = {};
for (var step in this.steps) {
var name = (typeof this.steps[step].options !== 'undefined') ? this.steps[step].options.name : this.steps[step].name;
if (name !== 'load-image'){
cliStringSteps += `${name} `;
}
for (var inp in modulesInfo(name).inputs) {
cliOptions[inp] = this.steps[step].options[inp];
}
}
cliStringSteps = cliStringSteps.substr(0, cliStringSteps.length - 1) + '"';
return `sequencer -i [PATH] -s ${cliStringSteps} -d '${JSON.stringify(cliOptions)}'`;
}
// Checks if input is a string of comma separated module names
function detectStringSyntax(str) {
let result = (str.includes(',') || str.includes('{')) ? true : false;
return result;
}
// Parses input string and returns array of module names
function parseStringSyntax(str) {
let stringifiedNames = str.replace(/\s/g, '');
let moduleNames = stringifiedNames.split(',');
return moduleNames;
}
// imports string of comma separated module names to sequencer steps
function stringToSteps(str) {
let sequencer = this;
let names = [];
if (this.name != 'ImageSequencer')
sequencer = this.sequencer;
if (detectStringSyntax(str))
names = stringToJSON(str);
names.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// Strigifies the current sequence
function toString(step) {
if (step) {
return stepToString(step);
} else {
return copy(this.steps.map(stepToString).slice(1).join(','));
}
}
// Stringifies one step of the sequence
function stepToString(step) {
var arg = (step.name) ? step.name : step.options.name;
let inputs = modulesInfo(arg).inputs || {}, op = {};
for (let input in inputs) {
if (!!step.options[input] && step.options[input] != inputs[input].default) {
op[input] = step.options[input];
op[input] = encodeURIComponent(op[input]);
}
}
var configurations = Object.keys(op).map(key => key + ':' + op[key]).join('|');
return `${arg}{${configurations}}`;
}
// exports the current sequence as an array of JSON steps
function toJSON() {
return this.stringToJSON(this.toString());
}
// Coverts stringified sequence into an array of JSON steps
function stringToJSON(str) {
let steps;
if (detectStringSyntax(str))
steps = parseStringSyntax(str);
else
steps = [str];
return steps.map(stringToJSONstep);
}
// Converts one stringified step into JSON
function stringToJSONstep(str) {
var bracesStrings;
if (str.includes('{'))
if (str.includes('(') && str.indexOf('(') < str.indexOf('{'))
bracesStrings = ['(', ')'];
else
bracesStrings = ['{', '}'];
else
bracesStrings = ['(', ')'];
if (str.indexOf(bracesStrings[0]) === -1) { // if there are no settings specified
var moduleName = str.substr(0);
stepSettings = '';
} else {
var moduleName = str.substr(0, str.indexOf(bracesStrings[0]));
stepSettings = str.slice(str.indexOf(bracesStrings[0]) + 1, -1);
}
stepSettings = stepSettings.split('|').reduce(function formatSettings(accumulator, current, i) {
var settingName = current.substr(0, current.indexOf(':')),
settingValue = current.substr(current.indexOf(':') + 1);
settingValue = settingValue.replace(/^\(/, ''); // strip () at start/end
settingValue = settingValue.replace(/^\{/, '').replace(/\}$/, ''); // strip {} at start/end
settingValue = decodeURIComponent(settingValue);
current = [
settingName,
settingValue
];
if (settingName) accumulator[settingName] = settingValue;
return accumulator;
}, {});
return {
name: moduleName,
options: stepSettings
};
}
// imports a string into the sequencer steps
function importString(str) {
let sequencer = this;
if (this.name != 'ImageSequencer')
sequencer = this.sequencer;
var stepsFromString = stringToJSON(str);
stepsFromString.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// imports a array of JSON steps into the sequencer steps
function importJSON(obj) {
let sequencer = this;
if (this.name != 'ImageSequencer')
sequencer = this.sequencer;
obj.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
return {
toCliString: toCliString,
detectStringSyntax: detectStringSyntax,
parseStringSyntax: parseStringSyntax,
stringToSteps: stringToSteps,
toString: toString,
stepToString: stepToString,
toJSON: toJSON,
stringToJSON: stringToJSON,
stringToJSONstep: stringToJSONstep,
importString: importString,
importJSON: importJSON
};
};

View File

@@ -1,17 +1,17 @@
var childProcess = require('child_process')
var childProcess = require('child_process');
var Spinner = require('ora');
module.exports = function (program, sequencer) {
console.log(
"\x1b[33m%s\x1b[0m",
"Please wait while your Module is being Installed...\nThis may take a while!"
);
console.log(
'\x1b[33m%s\x1b[0m',
'Please wait while your Module is being Installed...\nThis may take a while!'
);
var params = program.installModule.split(' ');
var spinner = Spinner("Now Installing...").start();
childProcess.execSync(`npm i ${params[1]}`)
sequencer.saveNewModule(params[0], params[1]);
sequencer.loadNewModule(params[0], require(params[1]));
spinner.stop();
console.log("\x1b[32m%s\x1b[0m", "Your module was installed successfully!!");
}
var params = program.installModule.split(' ');
var spinner = Spinner('Now Installing...').start();
childProcess.execSync(`npm i ${params[1]}`);
sequencer.saveNewModule(params[0], params[1]);
sequencer.loadNewModule(params[0], require(params[1]));
spinner.stop();
console.log('\x1b[32m%s\x1b[0m', 'Your module was installed successfully!!');
};

View File

@@ -1,7 +1,7 @@
module.exports = function (program, sequencer) {
var params = program.saveSequence.split(' ');
sequencer.saveSequence(params[0], params[1]);
console.log("\x1b[32m", "Your sequence was saved successfully!!");
var params = program.saveSequence.split(' ');
sequencer.saveSequence(params[0], params[1]);
console.log('\x1b[32m', 'Your sequence was saved successfully!!');
}
};

View File

@@ -1,13 +1,13 @@
var Spinner = require('ora');
var readlineSync = require('readline-sync');
var utils = require('../CliUtils')
var utils = require('../CliUtils');
module.exports = function (program, sequencer, outputFilename) {
utils.makedir(program.output, () => {
console.log('Files will be exported to "' + program.output + '"');
if (program.basic)
console.log("Basic mode is enabled, outputting only final image");
console.log('Basic mode is enabled, outputting only final image');
// Iterate through the steps and retrieve their inputs.
program.step.forEach(function(step) {
@@ -15,7 +15,7 @@ module.exports = function (program, sequencer, outputFilename) {
// If inputs exists, print to console.
if (Object.keys(options).length) {
console.log("[" + step + "]: Inputs");
console.log('[' + step + ']: Inputs');
}
// If inputs exists, print them out with descriptions.
@@ -23,9 +23,9 @@ module.exports = function (program, sequencer, outputFilename) {
// The array below creates a variable number of spaces. This is done with (length + 1).
// The extra 4 that makes it (length + 5) is to account for the []: characters
console.log(
new Array(step.length + 5).join(" ") +
new Array(step.length + 5).join(' ') +
input +
": " +
': ' +
options[input].desc
);
});
@@ -33,18 +33,18 @@ module.exports = function (program, sequencer, outputFilename) {
if (program.config) {
try {
var config = JSON.parse(program.config);
console.log(`The parsed options object: `, config);
console.log('The parsed options object: ', config);
} catch (e) {
console.error(
"\x1b[31m%s\x1b[0m",
`Options(Config) is not a not valid JSON Fallback activate`
'\x1b[31m%s\x1b[0m',
'Options(Config) is not a not valid JSON Fallback activate'
);
program.config = false;
console.log(e);
}
}
if (program.config && utils.validateConfig(config, options)) {
console.log("Now using Options object");
console.log('Now using Options object');
Object.keys(options).forEach(function(input) {
options[input] = config[input];
});
@@ -52,15 +52,15 @@ module.exports = function (program, sequencer, outputFilename) {
// If inputs exist, iterate through them and prompt for values.
Object.keys(options).forEach(function(input) {
var value = readlineSync.question(
"[" +
'[' +
step +
"]: Enter a value for " +
']: Enter a value for ' +
input +
" (" +
' (' +
options[input].type +
", default: " +
', default: ' +
options[input].default +
"): "
'): '
);
options[input] = value;
});
@@ -71,7 +71,7 @@ module.exports = function (program, sequencer, outputFilename) {
var spinnerObj = { succeed: () => { }, stop: () => { } };
if (!process.env.TEST)
spinnerObj = Spinner("Your Image is being processed..").start();
spinnerObj = Spinner('Your Image is being processed..').start();
// Run the sequencer.
sequencer.run({ progressObj: spinnerObj }, function() {
@@ -81,8 +81,8 @@ module.exports = function (program, sequencer, outputFilename) {
//check if spinner was not overriden stop it
if (!spinnerObj.overrideFlag) {
spinnerObj.succeed();
console.log(`\nDone!!`);
console.log('\nDone!!');
}
});
});
}
};

View File

@@ -1,51 +1,52 @@
module.exports = function AddQR(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.size = options.size || defaults.size;
options.qrCodeString = options.qrCodeString || "https://github.com/publiclab/image-sequencer";
var output;
getPixels = require('get-pixels');
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.size = options.size || defaults.size;
options.qrCodeString = options.qrCodeString || 'https://github.com/publiclab/image-sequencer';
var output;
getPixels = require('get-pixels');
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
return getPixels(input.src, function (err, oldPixels) {
function changePixel(r, g, b, a) {
return [r, g, b, a];
}
function extraManipulation(pixels,generateOutput) {
if (err) {
console.log(err);
return;
}
require('./QR')(options, pixels, oldPixels, generateOutput);
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
}
return getPixels(input.src, function(err, oldPixels) {
function changePixel(r, g, b, a) {
return [r, g, b, a];
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
})
}
return {
options: options,
draw: draw,
function extraManipulation(pixels, generateOutput) {
if (err) {
console.log(err);
return;
}
require('./QR')(options, pixels, oldPixels, generateOutput);
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
UI: UI
}
}
ui: options.step.ui,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

@@ -1,48 +1,48 @@
module.exports = exports = function (options, pixels, oldPixels, callback) {
var QRCode = require('qrcode')
QRCode.toDataURL(options.qrCodeString, function (err, url) {
var getPixels = require("get-pixels");
getPixels(url, function (err, qrPixels) {
if (err) {
console.log("Bad image path", image);
}
var QRCode = require('qrcode');
QRCode.toDataURL(options.qrCodeString, function (err, url) {
var getPixels = require('get-pixels');
getPixels(url, function (err, qrPixels) {
if (err) {
console.log('Bad image path', image);
}
var imagejs = require('imagejs');
var bitmap = new imagejs.Bitmap({ width: qrPixels.shape[0], height: qrPixels.shape[1] });
bitmap._data.data = qrPixels.data;
var resized = bitmap.resize({
width: options.size, height: options.size,
algorithm: "bicubicInterpolation"
});
var imagejs = require('imagejs');
var bitmap = new imagejs.Bitmap({ width: qrPixels.shape[0], height: qrPixels.shape[1] });
bitmap._data.data = qrPixels.data;
var resized = bitmap.resize({
width: options.size, height: options.size,
algorithm: 'bicubicInterpolation'
});
qrPixels.data = resized._data.data;
qrPixels.shape = [options.size, options.size, 4];
qrPixels.stride[1] = 4 * options.size;
qrPixels.data = resized._data.data;
qrPixels.shape = [options.size, options.size, 4];
qrPixels.stride[1] = 4 * options.size;
var width = oldPixels.shape[0],
height = oldPixels.shape[1];
var xe = width - options.size,
ye = height - options.size;
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))
}
var width = oldPixels.shape[0],
height = oldPixels.shape[1];
var xe = width - options.size,
ye = height - options.size;
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));
}
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))
}
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));
}
}
}
callback();
}
}
callback();
})
})
}
});
});
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Add QR",
"name": "add-qr",
"description": "Adds QR corresponding to the given string",
"url": "https://github.com/publiclab/image-sequencer/tree/master/MODULES.md",
"inputs": {

View File

@@ -3,72 +3,74 @@
*/
module.exports = function Average(options, UI) {
var output;
var output;
options.step.metadata = options.step.metadata || {};
options.step.metadata = options.step.metadata || {};
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
// do the averaging
function extraManipulation(pixels) {
var i = 0, sum = [0, 0, 0, 0];
while (i < pixels.data.length) {
sum[0] += pixels.data[i++];
sum[1] += pixels.data[i++];
sum[2] += pixels.data[i++];
sum[3] += pixels.data[i++];
}
// do the averaging
function extraManipulation(pixels) {
var i = 0, sum = [0, 0, 0, 0];
while (i < pixels.data.length) {
sum[0] += pixels.data[i++];
sum[1] += pixels.data[i++];
sum[2] += pixels.data[i++];
sum[3] += pixels.data[i++];
}
let divisor = pixels.data.length / 4;
let divisor = pixels.data.length / 4;
sum[0] = Math.floor(sum[0] / divisor);
sum[1] = Math.floor(sum[1] / divisor);
sum[2] = Math.floor(sum[2] / divisor);
sum[3] = Math.floor(sum[3] / divisor);
sum[0] = Math.floor(sum[0] / divisor);
sum[1] = Math.floor(sum[1] / divisor);
sum[2] = Math.floor(sum[2] / divisor);
sum[3] = Math.floor(sum[3] / divisor);
i = 0
while (i < pixels.data.length) {
pixels.data[i++] = sum[0];
pixels.data[i++] = sum[1];
pixels.data[i++] = sum[2];
pixels.data[i++] = sum[3];
}
i = 0;
while (i < pixels.data.length) {
pixels.data[i++] = sum[0];
pixels.data[i++] = sum[1];
pixels.data[i++] = sum[2];
pixels.data[i++] = sum[3];
}
// report back and store average in metadata:
options.step.metadata.averages = sum;
// TODO: refactor into a new "display()" method as per https://github.com/publiclab/image-sequencer/issues/242
if (options.step.inBrowser && options.step.ui) $(options.step.ui).find('.details').append("<p><b>Averages</b> (r, g, b, a): " + sum.join(', ') + "</p>");
return pixels;
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = {
src: datauri,
format: mimetype
};
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
// report back and store average in metadata:
options.step.metadata.averages = sum;
// TODO: refactor into a new "display()" method as per https://github.com/publiclab/image-sequencer/issues/242
if (options.step.inBrowser && options.step.ui) $(options.step.ui).find('.details').append('<p><b>Averages</b> (r, g, b, a): ' + sum.join(', ') + '</p>');
return pixels;
}
return {
options: options,
draw: draw,
output: output,
UI: UI
function output(image, datauri, mimetype) {
// This output is accessible 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,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Average",
"name": "average",
"description": "Average all pixel color",
"inputs": {
},

View File

@@ -1,75 +1,77 @@
module.exports = function Dynamic(options, UI, util) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.func = options.func || defaults.blend;
options.offset = options.offset || defaults.offset;
options.func = options.func || defaults.blend;
options.offset = options.offset || defaults.offset;
var output;
var output;
// This function is called on every draw.
function draw(input, callback, progressObj) {
// This function is called on every draw.
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
// convert to runnable code:
if (typeof options.func === "string") eval('options.func = ' + options.func);
// convert to runnable code:
if (typeof options.func === 'string') eval('options.func = ' + options.func);
var getPixels = require('get-pixels');
var getPixels = require('get-pixels');
// convert offset as string to int
if (typeof options.offset === "string") options.offset = parseInt(options.offset);
// convert offset as string to int
if (typeof options.offset === 'string') options.offset = parseInt(options.offset);
// save first image's pixels
var priorStep = this.getStep(options.offset);
// save first image's pixels
var priorStep = this.getStep(options.offset);
if (priorStep.output === undefined) {
this.output = input;
UI.notify('Offset Unavailable', 'offset-notification');
callback();
}
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
let p = options.firstImagePixels;
return options.func(
r2, g2, b2, a2,
p.get(x, y, 0),
p.get(x, y, 1),
p.get(x, y, 2),
p.get(x, y, 3)
)
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
// run PixelManipulatin on second image's pixels
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
});
if (priorStep.output === undefined) {
this.output = input;
UI.notify('Offset Unavailable', 'offset-notification');
callback();
}
return {
options: options,
draw: draw,
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
let p = options.firstImagePixels;
return options.func(
r2, g2, b2, a2,
p.get(x, y, 0),
p.get(x, y, 1),
p.get(x, y, 2),
p.get(x, y, 3)
);
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
// run PixelManipulatin on second image's pixels
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
UI: UI
}
}
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Blend",
"name": "blend",
"description": "Blend two chosen image steps with the given function. Defaults to using the red channel from image 1 and the green and blue and alpha channels of image 2. Easier to use interfaces coming soon!",
"inputs": {
"offset": {

View File

@@ -1,84 +1,62 @@
module.exports = exports = function(pixels, blur) {
let kernel = kernelGenerator(blur, 1), oldpix = require('lodash').cloneDeep(pixels);
kernel = flipKernel(kernel);
let kernel = kernelGenerator(blur),
pixs = {
r: [],
g: [],
b: [],
};
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let neighboutPos = getNeighbouringPixelPositions([i, j]);
let acc = [0.0, 0.0, 0.0, 0.0];
for (let a = 0; a < kernel.length; a++) {
for (let b = 0; b < kernel.length; b++) {
acc[0] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 0) * kernel[a][b]);
acc[1] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 1) * kernel[a][b]);
acc[2] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 2) * kernel[a][b]);
acc[3] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 3) * kernel[a][b]);
}
}
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
for (let y = 0; y < pixels.shape[1]; y++){
pixs.r.push([]);
pixs.g.push([]);
pixs.b.push([]);
for (let x = 0; x < pixels.shape[0]; x++){
pixs.r[y].push(pixels.get(x, y, 0));
pixs.g[y].push(pixels.get(x, y, 1));
pixs.b[y].push(pixels.get(x, y, 2));
}
return pixels;
}
const convolve = require('../_nomodule/gpuUtils').convolve;
const conPix = convolve([pixs.r, pixs.g, pixs.b], kernel);
//Generates a 3x3 Gaussian kernel
function kernelGenerator(sigma, size) {
/*
Trying out a variable radius kernel not working as of now
*/
// const coeff = (1.0/(2.0*Math.PI*sigma*sigma))
// const expCoeff = -1 * (1.0/2.0 * sigma * sigma)
// let e = Math.E
// let result = []
// for(let i = -1 * size;i<=size;i++){
// let arr = []
// for(let j= -1 * size;j<=size;j++){
// arr.push(coeff * Math.pow(e,expCoeff * ((i * i) + (j*j))))
// }
// result.push(arr)
// }
// let sum = result.reduce((sum,val)=>{
// return val.reduce((sumInner,valInner)=>{
// return sumInner+valInner
// })
// })
// result = result.map(arr=>arr.map(val=>(val + 0.0)/(sum + 0.0)))
// return result
return [
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[5.0 / 159.0, 12.0 / 159.0, 15.0 / 159.0, 12.0 / 159.0, 5.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0]
];
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)));
}
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0], y = pixelPosition[1], result = [];
}
for (let i = -2; i <= 2; i++) {
let arr = [];
for (let j = -2; j <= 2; j++)
arr.push([x + i, y + j]);
return pixels;
result.push(arr);
}
return result;
//Generates a 5x5 Gaussian kernel
function kernelGenerator(sigma = 1) {
let kernel = [],
sum = 0;
if (sigma == 0) sigma += 0.05;
const s = 2 * Math.pow(sigma, 2);
for (let y = -2; y <= 2; y++) {
kernel.push([]);
for (let x = -2; x <= 2; x++) {
let r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
kernel[y + 2].push(Math.exp(-(r / s)));
sum += kernel[y + 2][x + 2];
}
}
function flipKernel(kernel) {
let result = [];
for (let i = kernel.length - 1; i >= 0; i--) {
let arr = [];
for (let j = kernel[i].length - 1; j >= 0; j--) {
arr.push(kernel[i][j]);
}
result.push(arr);
}
return result;
for (let x = 0; x < 5; x++){
for (let y = 0; y < 5; y++){
kernel[y][x] = (kernel[y][x] / sum);
}
}
}
return kernel;
}
};

View File

@@ -3,42 +3,45 @@
*/
module.exports = function Blur(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.blur = options.blur || defaults.blur;
var output;
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.blur = options.blur || defaults.blur;
options.blur = parseFloat(options.blur);
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
pixels = require('./Blur')(pixels, options.blur);
return pixels;
}
function extraManipulation(pixels) {
pixels = require('./Blur')(pixels, options.blur);
return pixels;
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Blur",
"name": "blur",
"description": "Applies a Gaussian blur given by the intensity value",
"inputs": {
"blur": {
@@ -8,7 +8,7 @@
"default": 2,
"min": 0,
"max": 5,
"step": 0.25
"step": 0.05
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#blur-module"

View File

@@ -3,55 +3,57 @@
*/
module.exports = function Brightness(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
options.brightness = options.brightness || defaults.brightness;
options.brightness = options.brightness || defaults.brightness;
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
/*
/*
In this case progress is handled by changepixel internally otherwise progressObj
needs to be overriden and used
For eg. progressObj = new SomeProgressModule()
*/
var step = this, val = (options.brightness) / 100.0;;
var step = this, val = (options.brightness) / 100.0;
function changePixel(r, g, b, a) {
function changePixel(r, g, b, a) {
r = Math.min(val * r, 255);
g = Math.min(val * g, 255);
b = Math.min(val * b, 255);
return [r, g, b, a];
}
r = Math.min(val * r, 255);
g = Math.min(val * g, 255);
b = Math.min(val * b, 255);
return [r, g, b, a];
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui, //don't pass this in if you don't want your module to support progress bars
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Brightness",
"name": "brightness",
"description": "Change the brightness of the image by given percent value",
"inputs": {
"brightness": {

View File

@@ -0,0 +1,64 @@
/*
* Changes the Canvas Size
*/
module.exports = function canvasResize(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
function draw(input, callback, progressObj) {
options.width = parseInt(options.width || defaults.width);
options.height = parseInt(options.height || defaults.height);
options.x = parseInt(options.x || defaults.x);
options.y = parseInt(options.y || defaults.y);
progressObj.stop(true);
progressObj.overrideFlag = true;
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));
}
}
return newPixels;
}
function output(image, datauri, mimetype) {
// This output is accessible 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 {
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,26 @@
{
"name": "canvas-resize",
"description": "This module resizes the canvas and overlays the ouput of the previous step at given location",
"inputs": {
"width": {
"type": "integer",
"desc": "Final width of the canvas",
"default": 1000
},
"height": {
"type": "integer",
"desc": "Final height of the canvas",
"default": 1000
},
"x": {
"type": "integer",
"desc": "X-cord of the top left corner of the image on the canvas",
"default": 500
},
"y": {
"type": "float",
"desc": "Y-cord of the top left corner of the image on the canvas",
"default": 500
}
}
}

View File

@@ -17,9 +17,9 @@ module.exports = function Channel(options, UI) {
var step = this;
function changePixel(r, g, b, a) {
if (options.channel === "red") return [r, 0, 0, a];
if (options.channel === "green") return [0, g, 0, a];
if (options.channel === "blue") return [0, 0, b, a];
if (options.channel === 'red') return [r, 0, 0, a];
if (options.channel === 'green') return [0, g, 0, a];
if (options.channel === 'blue') return [0, 0, b, a];
}
function output(image, datauri, mimetype) {
@@ -31,11 +31,13 @@ module.exports = function Channel(options, UI) {
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
callback: callback,
useWasm:options.useWasm
});
}
@@ -46,5 +48,5 @@ module.exports = function Channel(options, UI) {
draw: draw,
output: output,
UI: UI
}
}
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Channel",
"name": "channel",
"description": "Displays only one color channel of an image -- default is green",
"inputs": {
"channel": {

View File

@@ -0,0 +1,83 @@
module.exports = function ColorTemperature(options, UI) {
var output;
function draw(input, callback, progressObj) {
options.temperature = (options.temperature > '40000') ? '40000' : options.temperature;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function extraManipulation(pixels) {
let temp = parseInt(options.temperature);
temp /= 100;
let r, g, b;
if (temp <= 66) {
r = 255;
g = Math.min(Math.max(99.4708025861 * Math.log(temp) - 161.1195681661, 0), 255);
} else {
r = Math.min(Math.max(329.698727446 * Math.pow(temp - 60, -0.1332047592), 0), 255);
g = Math.min(Math.max(288.1221695283 * Math.pow(temp - 60, -0.0755148492), 0), 255);
}
if (temp >= 66) {
b = 255;
} else if (temp <= 19) {
b = 0;
} else {
b = temp - 10;
b = Math.min(Math.max(138.5177312231 * Math.log(b) - 305.0447927307, 0), 255);
}
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);
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);
}
}
return pixels;
}
function output(image, datauri, mimetype) {
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 {
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,12 @@
{
"name": "color-temperature",
"description": "Changes the color temperature of the image.",
"inputs": {
"temperature": {
"type": "integer",
"desc": "Temperature between 0 - 40,000 Kelvin",
"default": 6000
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#color-temperature"
}

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Colorbar",
"name": "colorbar",
"description": "Generates a colorbar to lay over the image",
"inputs": {
"colormap": {

View File

@@ -1,27 +1,27 @@
/*
* Accepts a value from 0-255 and returns the new color-mapped pixel
* from a lookup table, which can be specified as an array of [begin, end]
* gradients, where begin and end are represented as [r, g, b] colors. In
* Accepts a value from 0-255 and returns the new color-mapped pixel
* from a lookup table, which can be specified as an array of [begin, end]
* gradients, where begin and end are represented as [r, g, b] colors. In
* combination, a lookup table which maps values from 0 - 255 smoothly from black to white looks like:
* [
* [0, [0, 0, 0], [255, 255, 255]],
* [1, [255, 255, 255], [255, 255, 255]]
* ]
*
*
* Adapted from bgamari's work in Infragram: https://github.com/p-v-o-s/infragram-js/commit/346c97576a07b71a55671d17e0153b7df74e803b
*/
module.exports = function Colormap(value, options) {
options.colormap = options.colormap || colormaps.default;
// if a lookup table is provided as an array:
if(typeof(options.colormap) == "object")
if(typeof(options.colormap) == 'object')
colormapFunction = colormap(options.colormap);
// if a stored colormap is named with a string like "fastie":
else if(colormaps.hasOwnProperty(options.colormap))
colormapFunction = colormaps[options.colormap];
else colormapFunction = colormaps.default;
return colormapFunction(value / 255.00);
}
};
function colormap(segments) {
return function(x) {
@@ -49,149 +49,149 @@ function colormap(segments) {
}
return result;
};
};
}
var colormaps = {
greyscale: colormap([
[0, [0, 0, 0], [255, 255, 255] ],
[1, [255, 255, 255], [255, 255, 255] ]
]),
[0, [0, 0, 0], [255, 255, 255] ],
[1, [255, 255, 255], [255, 255, 255] ]
]),
bluwhtgrngis: colormap([
[0, [6,23,86], [6,25, 84] ],
[0.0625, [6,25,84], [6,25, 84] ],//1
[0.125, [6,25,84], [6,25, 84] ],//2
[0.1875, [6,25,84], [6,25, 84] ],
[0.25, [6,25,84], [6,25,84] ],
[0.3125, [6,25,84], [9,24, 84] ],//5
[0.3438, [9,24, 84], [119,120,162] ],//5
[0.375, [119,129,162],[249,250,251] ], //6
[0.406, [249,250,251],[255,255,255] ], //6.5
[0.4375, [255,255,255],[255,255,255] ], //7 white
[0.50, [255,255,255],[214,205,191] ],//8
[0.52, [214,205,191],[178,175,96] ],//8.2
[0.5625, [178,175,96], [151,176,53] ],//9
[0.593, [151,176,53], [146,188,12] ],//9.5
[0.625, [146,188,12], [96,161,1] ], //10
[0.6875, [96,161,1], [30,127,3] ],//11
[0.75, [30,127,3], [0,99,1] ],//12
[0.8125, [0,99,1], [0,74,1] ],//13
[0.875, [0,74,1], [0,52, 0] ],//14
[0.9375, [0,52, 0], [0,34,0] ], //15
[0.968, [0,34,0], [68,70,67] ] //16
]),
bluwhtgrngis: colormap([
[0, [6, 23, 86], [6, 25, 84] ],
[0.0625, [6, 25, 84], [6, 25, 84] ], //1
[0.125, [6, 25, 84], [6, 25, 84] ], //2
[0.1875, [6, 25, 84], [6, 25, 84] ],
[0.25, [6, 25, 84], [6, 25, 84] ],
[0.3125, [6, 25, 84], [9, 24, 84] ], //5
[0.3438, [9, 24, 84], [119, 120, 162] ], //5
[0.375, [119, 129, 162], [249, 250, 251] ], //6
[0.406, [249, 250, 251], [255, 255, 255] ], //6.5
[0.4375, [255, 255, 255], [255, 255, 255] ], //7 white
[0.50, [255, 255, 255], [214, 205, 191] ], //8
[0.52, [214, 205, 191], [178, 175, 96] ], //8.2
[0.5625, [178, 175, 96], [151, 176, 53] ], //9
[0.593, [151, 176, 53], [146, 188, 12] ], //9.5
[0.625, [146, 188, 12], [96, 161, 1] ], //10
[0.6875, [96, 161, 1], [30, 127, 3] ], //11
[0.75, [30, 127, 3], [0, 99, 1] ], //12
[0.8125, [0, 99, 1], [0, 74, 1] ], //13
[0.875, [0, 74, 1], [0, 52, 0] ], //14
[0.9375, [0, 52, 0], [0, 34, 0] ], //15
[0.968, [0, 34, 0], [68, 70, 67] ] //16
]),
brntogrn: colormap([
[0, [110,12,3], [118,6,1] ],
[0.0625, [118,6,1], [141,19,6] ],
[0.125, [141,19,6], [165,35,13] ],
[0.1875, [165,35,13], [177,59,25] ],
[0.2188, [177,59,25], [192,91,36] ],
[0.25, [192,91,36], [214, 145, 76] ],
[0.3125, [214,145,76], [230,183,134] ],
[0.375, [230,183,134],[243, 224, 194]],
[0.4375, [243,224,194],[250,252,229] ],
[0.50, [250,252,229],[217,235,185] ],
[0.5625, [217,235,185],[184,218,143] ],
[0.625, [184,218,143],[141,202,89] ],
[0.6875, [141,202,89], [80,176,61] ],
[0.75, [80,176,61], [0, 147, 32] ],
[0.8125, [0,147,32], [1, 122, 22] ],
[0.875, [1,122,22], [0, 114, 19] ],
[0.90, [0,114,19], [0,105,18] ],
[0.9375, [0,105,18], [7,70,14] ]
[0, [110, 12, 3], [118, 6, 1] ],
[0.0625, [118, 6, 1], [141, 19, 6] ],
[0.125, [141, 19, 6], [165, 35, 13] ],
[0.1875, [165, 35, 13], [177, 59, 25] ],
[0.2188, [177, 59, 25], [192, 91, 36] ],
[0.25, [192, 91, 36], [214, 145, 76] ],
[0.3125, [214, 145, 76], [230, 183, 134] ],
[0.375, [230, 183, 134], [243, 224, 194]],
[0.4375, [243, 224, 194], [250, 252, 229] ],
[0.50, [250, 252, 229], [217, 235, 185] ],
[0.5625, [217, 235, 185], [184, 218, 143] ],
[0.625, [184, 218, 143], [141, 202, 89] ],
[0.6875, [141, 202, 89], [80, 176, 61] ],
[0.75, [80, 176, 61], [0, 147, 32] ],
[0.8125, [0, 147, 32], [1, 122, 22] ],
[0.875, [1, 122, 22], [0, 114, 19] ],
[0.90, [0, 114, 19], [0, 105, 18] ],
[0.9375, [0, 105, 18], [7, 70, 14] ]
]),
]),
blutoredjet: colormap([
[0, [0,0,140], [1,1,186] ],
[0.0625, [1,1,186], [0,1,248] ],
[0.125, [0,1,248], [0,70,254] ],
[0.1875, [0,70,254], [0,130,255] ],
[0.25, [0,130,255], [2,160,255] ],
[0.2813, [2,160,255], [0,187,255] ], //inset
[0.3125, [0,187,255], [6,250,255] ],
// [0.348, [0,218,255], [8,252,251] ],//inset
[0.375, [8,252,251], [27,254,228] ],
[0.406, [27,254,228], [70,255,187] ], //insert
[0.4375, [70,255,187], [104,254,151]],
[0.47, [104,254,151],[132,255,19] ],//insert
[0.50, [132,255,19], [195,255,60] ],
[0.5625, [195,255,60], [231,254,25] ],
[0.5976, [231,254,25], [253,246,1] ],//insert
[0.625, [253,246,1], [252,210,1] ], //yellow
[0.657, [252,210,1], [255,183,0] ],//insert
[0.6875, [255,183,0], [255,125,2] ],
[0.75, [255,125,2], [255,65, 1] ],
[0.8125, [255,65, 1], [247, 1, 1] ],
[0.875, [247,1,1], [200, 1, 3] ],
[0.9375, [200,1,3], [122, 3, 2] ]
[0, [0, 0, 140], [1, 1, 186] ],
[0.0625, [1, 1, 186], [0, 1, 248] ],
[0.125, [0, 1, 248], [0, 70, 254] ],
[0.1875, [0, 70, 254], [0, 130, 255] ],
[0.25, [0, 130, 255], [2, 160, 255] ],
[0.2813, [2, 160, 255], [0, 187, 255] ], //inset
[0.3125, [0, 187, 255], [6, 250, 255] ],
// [0.348, [0,218,255], [8,252,251] ],//inset
[0.375, [8, 252, 251], [27, 254, 228] ],
[0.406, [27, 254, 228], [70, 255, 187] ], //insert
[0.4375, [70, 255, 187], [104, 254, 151]],
[0.47, [104, 254, 151], [132, 255, 19] ], //insert
[0.50, [132, 255, 19], [195, 255, 60] ],
[0.5625, [195, 255, 60], [231, 254, 25] ],
[0.5976, [231, 254, 25], [253, 246, 1] ], //insert
[0.625, [253, 246, 1], [252, 210, 1] ], //yellow
[0.657, [252, 210, 1], [255, 183, 0] ], //insert
[0.6875, [255, 183, 0], [255, 125, 2] ],
[0.75, [255, 125, 2], [255, 65, 1] ],
[0.8125, [255, 65, 1], [247, 1, 1] ],
[0.875, [247, 1, 1], [200, 1, 3] ],
[0.9375, [200, 1, 3], [122, 3, 2] ]
]),
]),
colors16: colormap([
[0, [0,0,0], [0,0,0] ],
[0.0625, [3,1,172], [3,1,172] ],
[0.125, [3,1,222], [3,1, 222] ],
[0.1875, [0,111,255], [0,111,255] ],
[0.25, [3,172,255], [3,172,255] ],
[0.3125, [1,226,255], [1,226,255] ],
[0.375, [2,255,0], [2,255,0] ],
[0.4375, [198,254,0], [190,254,0] ],
[0.50, [252,255,0], [252,255,0] ],
[0.5625, [255,223,3], [255,223,3] ],
[0.625, [255,143,3], [255,143,3] ],
[0.6875, [255,95,3], [255,95,3] ],
[0.75, [242,0,1], [242,0,1] ],
[0.8125, [245,0,170], [245,0,170] ],
[0.875, [223,180,225], [223,180,225] ],
[0.9375, [255,255,255], [255,255, 255]]
[0, [0, 0, 0], [0, 0, 0] ],
[0.0625, [3, 1, 172], [3, 1, 172] ],
[0.125, [3, 1, 222], [3, 1, 222] ],
[0.1875, [0, 111, 255], [0, 111, 255] ],
[0.25, [3, 172, 255], [3, 172, 255] ],
[0.3125, [1, 226, 255], [1, 226, 255] ],
[0.375, [2, 255, 0], [2, 255, 0] ],
[0.4375, [198, 254, 0], [190, 254, 0] ],
[0.50, [252, 255, 0], [252, 255, 0] ],
[0.5625, [255, 223, 3], [255, 223, 3] ],
[0.625, [255, 143, 3], [255, 143, 3] ],
[0.6875, [255, 95, 3], [255, 95, 3] ],
[0.75, [242, 0, 1], [242, 0, 1] ],
[0.8125, [245, 0, 170], [245, 0, 170] ],
[0.875, [223, 180, 225], [223, 180, 225] ],
[0.9375, [255, 255, 255], [255, 255, 255]]
]),
]),
default: colormap([
[0, [45,1,121], [25,1,137] ],
[0.125, [25,1,137], [0,6,156] ],
[0.1875, [0,6,156], [7,41,172] ],
[0.25, [7,41,172], [22,84,187] ],
[0.3125, [22,84,187], [25,125,194] ],
[0.375, [25,125,194], [26,177,197] ],
[0.4375, [26,177,197], [23,199,193] ],
[0.47, [23,199,193], [25, 200,170] ],
[0.50, [25, 200,170], [21,209,27] ],
[0.5625, [21,209,27], [108,215,18] ],
[0.625, [108,215,18], [166,218,19] ],
[0.6875, [166,218,19], [206,221,20] ],
[0.75, [206,221,20], [222,213,19 ] ],
[0.7813, [222,213,19], [222, 191, 19]],
[0.8125, [222, 191, 19], [227,133,17] ],
[0.875, [227,133,17], [231,83,16] ],
[0.9375, [231,83,16], [220,61,48] ]
default: colormap([
[0, [45, 1, 121], [25, 1, 137] ],
[0.125, [25, 1, 137], [0, 6, 156] ],
[0.1875, [0, 6, 156], [7, 41, 172] ],
[0.25, [7, 41, 172], [22, 84, 187] ],
[0.3125, [22, 84, 187], [25, 125, 194] ],
[0.375, [25, 125, 194], [26, 177, 197] ],
[0.4375, [26, 177, 197], [23, 199, 193] ],
[0.47, [23, 199, 193], [25, 200, 170] ],
[0.50, [25, 200, 170], [21, 209, 27] ],
[0.5625, [21, 209, 27], [108, 215, 18] ],
[0.625, [108, 215, 18], [166, 218, 19] ],
[0.6875, [166, 218, 19], [206, 221, 20] ],
[0.75, [206, 221, 20], [222, 213, 19 ] ],
[0.7813, [222, 213, 19], [222, 191, 19]],
[0.8125, [222, 191, 19], [227, 133, 17] ],
[0.875, [227, 133, 17], [231, 83, 16] ],
[0.9375, [231, 83, 16], [220, 61, 48] ]
]),
]),
fastie: colormap([
[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] ]
]),
[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] ]
]),
stretched: colormap([
[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] ]
])
[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] ]
])
}
};

View File

@@ -24,11 +24,13 @@ module.exports = function Colormap(options, UI) {
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
callback: callback,
useWasm:options.useWasm
});
}
@@ -38,5 +40,5 @@ module.exports = function Colormap(options, UI) {
draw: draw,
output: output,
UI: UI
}
}
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Colormap",
"name": "colormap",
"description": "Maps brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.\n\nFor example, 'cooler' colors like blue could represent low values, while 'hot' colors like red could represent high values.",
"inputs": {
"colormap": {

View File

@@ -1,47 +1,47 @@
var _ = require('lodash');
module.exports = exports = function(pixels, contrast) {
let oldpix = _.cloneDeep(pixels);
contrast = Number(contrast)
if (contrast < -100) contrast = -100;
if (contrast > 100) contrast = 100;
contrast = (100.0 + contrast) / 100.0;
contrast *= contrast;
let oldpix = _.cloneDeep(pixels);
contrast = Number(contrast);
if (contrast < -100) contrast = -100;
if (contrast > 100) contrast = 100;
contrast = (100.0 + contrast) / 100.0;
contrast *= 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;
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 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;
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);
pixels.set(i, j, 0, r);
pixels.set(i, j, 1, g);
pixels.set(i, j, 2, b);
}
}
return pixels;
}
}
return pixels;
};

View File

@@ -4,42 +4,44 @@
module.exports = function Contrast(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.contrast = options.contrast || defaults.contrast;
var output;
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.contrast = options.contrast || defaults.contrast;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
pixels = require('./Contrast')(pixels, options.contrast)
return pixels
}
function extraManipulation(pixels) {
pixels = require('./Contrast')(pixels, options.contrast);
return pixels;
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Contrast",
"name": "contrast",
"description": "Change the contrast of the image by given value",
"inputs": {
"contrast": {

View File

@@ -1,71 +1,50 @@
var _ = require('lodash');
module.exports = exports = function(pixels, constantFactor, kernelValues) {
let kernel = kernelGenerator(constantFactor, kernelValues), oldpix = _.cloneDeep(pixels);
kernel = flipKernel(kernel);
module.exports = exports = function(pixels, constantFactor, kernelValues, texMode) {
let kernel = kernelGenerator(constantFactor, kernelValues),
pixs = {
r: [],
g: [],
b: [],
};
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let neighboutPos = getNeighbouringPixelPositions([i, j]);
let acc = [0.0, 0.0, 0.0, 0.0];
for (let a = 0; a < kernel.length; a++) {
for (let b = 0; b < kernel.length; b++) {
acc[0] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 0) * kernel[a][b]);
acc[1] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 1) * kernel[a][b]);
acc[2] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 2) * kernel[a][b]);
acc[3] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 3) * kernel[a][b]);
}
}
acc[0] = Math.min(acc[0], 255);
acc[1] = Math.min(acc[1], 255);
acc[2] = Math.min(acc[2], 255);
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
for (let y = 0; y < pixels.shape[1]; y++){
pixs.r.push([]);
pixs.g.push([]);
pixs.b.push([]);
for (let x = 0; x < pixels.shape[0]; x++){
pixs.r[y].push(pixels.get(x, y, 0));
pixs.g[y].push(pixels.get(x, y, 1));
pixs.b[y].push(pixels.get(x, y, 2));
}
return pixels;
}
const convolve = require('../_nomodule/gpuUtils').convolve;
const conPix = convolve([pixs.r, pixs.g, pixs.b], kernel, (pixels.shape[0] * pixels.shape[1]) < 400000 ? true : false);
function kernelGenerator(constantFactor, kernelValues) {
kernelValues = kernelValues.split(" ");
for (i = 0; i < 9; i++) {
kernelValues[i] = Number(kernelValues[i]) * constantFactor;
}
let k = 0;
let arr = [];
for (i = 0; i < 3; i++) {
let columns = [];
for (j = 0; j < 3; j++) {
columns.push(kernelValues[k]);
k += 1;
}
arr.push(columns);
}
return arr;
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)));
}
}
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0], y = pixelPosition[1], result = [];
for (let i = -1; i <= 1; i++) {
let arr = [];
for (let j = -1; j <= 1; j++)
arr.push([x + i, y + j]);
result.push(arr);
}
return result;
}
function flipKernel(kernel) {
let result = [];
for (let i = kernel.length - 1; i >= 0; i--) {
let arr = [];
for (let j = kernel[i].length - 1; j >= 0; j--) {
arr.push(kernel[i][j]);
}
result.push(arr);
}
return result;
return pixels;
};
function kernelGenerator(constantFactor, kernelValues) {
kernelValues = kernelValues.split(' ');
for (i = 0; i < 9; i++) {
kernelValues[i] = Number(kernelValues[i]) * constantFactor;
}
let k = 0;
let arr = [];
for (y = 0; y < 3; y++) {
arr.push([]);
for (x = 0; x < 3; x++) {
arr[y].push(kernelValues[k]);
k += 1;
}
}
return arr;
}

View File

@@ -1,42 +1,45 @@
module.exports = function Convolution(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.kernelValues = options.kernelValues || defaults.kernelValues;
options.constantFactor = options.constantFactor || defaults.constantFactor;
var output;
options.kernelValues = options.kernelValues || defaults.kernelValues;
options.constantFactor = options.constantFactor || defaults.constantFactor;
options.texMode = options.texMode || defaults.texMode;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
pixels = require('./Convolution')(pixels, options.constantFactor, options.kernelValues);
return pixels;
}
function extraManipulation(pixels) {
pixels = require('./Convolution')(pixels, options.constantFactor, options.kernelValues, options.texMode);
return pixels;
}
function output(image, datauri, mimetype) {
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,
callback: callback
});
step.output = { src: datauri, format: mimetype };
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,14 +1,15 @@
{
"name": "Convolution",
"name": "convolution",
"description": "Image Convolution using a given 3x3 kernel matrix <a href='https://en.wikipedia.org/wiki/Kernel_(image_processing)'>Read more</a>",
"inputs": {
"constantFactor":{
"type": "float",
"desc": "a constant factor, multiplies all the kernel values by that factor",
"default": 0.1111,
"placeholder": 0.1111
"default": 0.111,
"min": 0.001,
"max": 2,
"step": 0.001
},
"kernelValues": {
"type": "string",
"desc": "nine space separated numbers representing the kernel values in left to right and top to bottom format.",

View File

@@ -1,12 +1,12 @@
module.exports = function Crop(input,options,callback) {
module.exports = function Crop(input, options, callback) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var getPixels = require('get-pixels'),
savePixels = require('save-pixels');
savePixels = require('save-pixels');
options.x = parseInt(options.x) || defaults.x;
options.y = parseInt(options.y) || defaults.y;
getPixels(input.src,function(err,pixels){
getPixels(input.src, function(err, pixels){
options.w = parseInt(options.w) || Math.floor(pixels.shape[0]);
options.h = parseInt(options.h) || Math.floor(pixels.shape[1]);
options.backgroundColor = options.backgroundColor || defaults.backgroundColor;
@@ -17,21 +17,29 @@ module.exports = function Crop(input,options,callback) {
var iw = pixels.shape[0]; //Width of Original Image
var ih = pixels.shape[1]; //Height of Original Image
var backgroundArray = [];
backgroundColor = options.backgroundColor.split(" ");
backgroundColor = options.backgroundColor.substring(options.backgroundColor.indexOf('(') + 1, options.backgroundColor.length - 1); // extract only the values from rgba(_,_,_,_)
backgroundColor = backgroundColor.split(',');
for(var i = 0; i < w ; i++){
backgroundArray = backgroundArray.concat([backgroundColor[0],backgroundColor[1],backgroundColor[2],backgroundColor[3]]);
backgroundArray = backgroundArray.concat([backgroundColor[0], backgroundColor[1], backgroundColor[2], backgroundColor[3]]);
}
var newarray = new Uint8Array(4*w*h);
// var newarray = new Uint8Array(4*w*h);
var array = [];
for (var n = oy; n < oy + h; n++) {
if(n<ih){
newarray.set(pixels.data.slice(n*4*iw + ox, n*4*iw + ox + 4*w),4*w*(n-oy));
var offsetValue = 4 * w * n;
if(n < ih){
var start = n * 4 * iw + ox * 4;
var end = n * 4 * iw + ox * 4 + 4 * w;
var pushArray = Array.from(pixels.data.slice(start, end ));
array.push.apply(array, pushArray);
} else {
newarray.set(backgroundArray,4*w*(n-oy));
array.push.apply(array, backgroundArray);
}
}
var newarray = Uint8Array.from(array);
pixels.data = newarray;
pixels.shape = [w,h,4];
pixels.stride[1] = 4*w;
pixels.shape = [w, h, 4];
pixels.stride[1] = 4 * w;
options.format = input.format;
@@ -47,7 +55,7 @@ module.exports = function Crop(input,options,callback) {
r.on('end', function(){
var data = Buffer.concat(chunks, totalLength).toString('base64');
var datauri = 'data:image/' + options.format + ';base64,' + data;
callback(datauri,options.format);
callback(datauri, options.format);
});
});
};

View File

@@ -22,7 +22,7 @@ module.exports = function CropModule(options, UI) {
setupComplete = false;
// This function is caled everytime the step has to be redrawn
function draw(input,callback) {
function draw(input, callback) {
var step = this;
@@ -32,7 +32,7 @@ module.exports = function CropModule(options, UI) {
var parseCornerCoordinateInputs = require('../../util/ParseInputCoordinates');
//parse the inputs
parseCornerCoordinateInputs(options,{
parseCornerCoordinateInputs(options, {
src: input.src,
x: { valInp: options.x, type: 'horizontal' },
y: { valInp: options.y, type: 'vertical' },
@@ -51,7 +51,7 @@ module.exports = function CropModule(options, UI) {
step.output = {
src: out,
format: format
}
};
// This output is accessible to the UI
options.step.output = out;
@@ -81,5 +81,5 @@ module.exports = function CropModule(options, UI) {
draw: draw,
output: output,
UI: UI
}
}
};
};

View File

@@ -2,7 +2,7 @@
module.exports = function CropModuleUi(step, ui) {
let inputWidth = 0,
inputHeight = 0;
inputHeight = 0;
// We don't have input image dimensions at the
// time of setting up the UI; that comes when draw() is triggered.
@@ -10,7 +10,7 @@ module.exports = function CropModuleUi(step, ui) {
// TODO: link this to an event rather than an explicit call in Module.js
function setup() {
let x = 0,
y = 0;
y = 0;
// display original uncropped input image on initial setup
showOriginal();
@@ -42,20 +42,21 @@ module.exports = function CropModuleUi(step, ui) {
converted[2],
converted[3]
);
$($(imgEl()).parents()[3]).find('input').trigger('change');
}
});
}
function convertToNatural(_x, _y, _width, _height) {
let displayWidth = $(imgEl()).width(),
displayHeight = $(imgEl()).height();
displayHeight = $(imgEl()).height();
// return in same order [ x, y, width, height ]:
return [
Math.floor(( _x / displayWidth ) * inputWidth),
Math.floor(( _y / displayHeight ) * inputHeight),
Math.floor(( _width / displayWidth ) * inputWidth),
Math.floor(( _height / displayHeight ) * inputHeight)
]
];
}
function remove() {
@@ -77,7 +78,7 @@ module.exports = function CropModuleUi(step, ui) {
}
function setOptions(x1, y1, width, height) {
let options = $($(imgEl()).parents()[2]).find("input");
let options = $($(imgEl()).parents()[3]).find('input');
options[0].value = x1;
options[1].value = y1;
options[2].value = width;
@@ -93,5 +94,5 @@ module.exports = function CropModuleUi(step, ui) {
setup: setup,
remove: remove,
hide: hide
}
}
};
};

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