Compare commits

...

118 Commits

Author SHA1 Message Date
MargaretAN9
fb023a5305 added "bluwhtgrngis" colormap to dropdown list
publiclab/image-sequencer #475
2018-12-31 05:36:14 +00:00
HarshKhandeparkar
611016b022 Fixed Gif Generation (#561)
* update dist

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

dist update

Revert "dist update"

This reverts commit 9ee2a987e8f978961656ae8f71f6e6702bbbd30d.

* Fix Gif
2018-12-28 22:10:02 +05:30
Varun Gupta
f77cface7b Merge pull request #560 from tech4GT/updateDist2
update dist
2018-12-27 12:33:34 +05:30
tech4GT
f3291e201f update dist
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-27 12:32:34 +05:30
Varun Gupta
901cf6a96c Merge pull request #555 from Divy123/docs-improve
Added documentation for all remaining modules
2018-12-27 12:30:38 +05:30
divy123
7f4f9a0950 Added dist file changes 2018-12-26 22:36:24 +05:30
divy123
3a39d2b4bb Merge remote-tracking branch 'upstream/main' into docs-improve 2018-12-26 22:05:02 +05:30
Slytherin
3ab02125cb Fixed a typo. 2018-12-26 20:25:30 +05:30
Varun Gupta
d5aac98a29 Merge pull request #554 from HarshKhandeparkar/btn-rearrange
Rearrange Sequence Buttons
2018-12-26 19:49:06 +05:30
divy123
8ff09e26cc Corrected markdown format-2 2018-12-26 00:33:30 +05:30
divy123
d7b175eceb Corrected markdown format 2018-12-26 00:26:14 +05:30
divy123
ee5a3a5e4f Added index to MODULES.md 2018-12-26 00:21:19 +05:30
divy123
35b95a68b1 Added documentation for all modules in Modules.md and added a link in info.json of each Module 2018-12-25 03:59:39 +05:30
HarshKhandeparkar
5288973a48 cleanup 2018-12-23 17:27:58 +05:30
HarshKhandeparkar
d49acd504e btn-fix 2018-12-23 17:26:06 +05:30
HarshKhandeparkar
ac9086e4ef rearrange buttons 2018-12-21 00:17:28 +05:30
Varun Gupta
94e4dfe1b9 Merge pull request #553 from tech4GT/deadLink
fix contributing.md
2018-12-20 08:51:48 +05:30
tech4GT
056e57af8b fix contributing.md
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-20 08:50:30 +05:30
Varun Gupta
9fedf4b9c7 Merge pull request #552 from tech4GT/dependencies
Update dist files
2018-12-19 17:20:04 +05:30
tech4GT
300d972718 update dist files
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-19 17:17:57 +05:30
Varun Gupta
e2f1fb9729 Merge pull request #548 from publiclab/dependabot/npm_and_yarn/tape-run-5.0.0
Bump tape-run from 4.0.0 to 5.0.0
2018-12-19 17:16:57 +05:30
Varun Gupta
3e5cec32e4 Merge pull request #549 from aashna27/Take-Photo-functionality
TakePhoto functionality added
2018-12-19 17:12:09 +05:30
tech4GT
8a96bd8cac update dist files
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-19 17:04:09 +05:30
tech4GT
7cd89c4481 Merge branch 'main' of https://github.com/publiclab/image-sequencer into local 2018-12-19 17:01:45 +05:30
Varun Gupta
980966ecfa Merge pull request #551 from tech4GT/fixInsertStep
fix bug preventing insert-step
2018-12-19 17:01:17 +05:30
tech4GT
eebf149532 fix bug preventing insert-step
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-19 17:00:09 +05:30
aashna27
59898d72fe TakePhoto functionality added 2018-12-18 02:43:28 +05:30
Varun Gupta
23f4851bb5 Merge pull request #545 from Divy123/add-step-btn
Added insert step button at every step
2018-12-17 16:34:57 +05:30
divy123
6bab70ad09 Add step butoon disabled for last step 2018-12-17 16:02:32 +05:30
tech4GT
327b421284 remove excess logs
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-17 11:54:25 +05:30
tech4GT
98e4eca24f update sequence expansion
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-17 11:50:16 +05:30
dependabot[bot]
a93440093b Bump tape-run from 4.0.0 to 5.0.0
Bumps [tape-run](https://github.com/juliangruber/tape-run) from 4.0.0 to 5.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/v4.0.0...v5.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-17 06:12:30 +00:00
tech4GT
0c2d2a47d8 fix save-sequence and refactor
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-17 10:56:17 +05:30
tech4GT
16debae154 fixes #544 and final changes
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-16 20:01:53 +05:30
tech4GT
3e30c0f7ed Merge branch 'add-step-btn' of https://github.com/Divy123/image-sequencer into divy 2018-12-16 16:32:07 +05:30
divy123
fd78285ac7 Merge branch 'add-step-btn' of https://github.com/Divy123/image-sequencer into add-step-btn 2018-12-16 16:03:56 +05:30
divy123
4eb386eb47 Added font-awesome icon and added colors to it 2018-12-16 16:02:49 +05:30
divy123
f27b09793c Changed arrow functions to normal functions 2018-12-16 15:39:48 +05:30
dependabot[bot]
a56e8a3b16 Bump buffer from 5.0.8 to 5.2.1 (#524)
Bumps [buffer](https://github.com/feross/buffer) from 5.0.8 to 5.2.1.
- [Release notes](https://github.com/feross/buffer/releases)
- [Commits](https://github.com/feross/buffer/compare/v5.0.8...v5.2.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-15 19:14:39 -05:00
dependabot[bot]
b666ad510b [Security] Bump bootstrap from 3.3.7 to 3.4.0 (#543)
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 3.3.7 to 3.4.0. **This update includes security fixes.**
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v3.3.7...v3.4.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-15 18:58:45 -05:00
dependabot[bot]
809fb0b37a [Security] Bump cached-path-relative from 1.0.1 to 1.0.2 (#519)
Bumps [cached-path-relative](https://github.com/ashaffer/cached-path-relative) from 1.0.1 to 1.0.2. **This update includes security fixes.**
- [Release notes](https://github.com/ashaffer/cached-path-relative/releases)
- [Changelog](https://github.com/ashaffer/cached-path-relative/blob/master/History.md)
- [Commits](https://github.com/ashaffer/cached-path-relative/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-15 18:58:08 -05:00
Slytherin
a4818d70d8 Merge branch 'main' into add-step-btn 2018-12-16 02:25:12 +05:30
divy123
537cc41b36 Added insert step button at every step 2018-12-16 02:16:45 +05:30
Jonathan Xu
95f8dad901 Add grid of thumbnails (#539)
* Added four preview images

* Added preview images to buttons

* Maked the crop preview resposive

* icon overlays

* made previews square

* finalized css for square images

* Added four preview images

* Added preview images to buttons

* Maked the crop preview resposive

* icon overlays

* made previews square

* finalized css for square images
2018-12-09 22:35:32 -05:00
Varun Gupta
ceca433806 Merge pull request #536 from tech4GT/update
Update dist and lock files
2018-12-07 23:37:09 +05:30
tech4GT
1e719936c4 update dist and lock files
Signed-off-by: tech4GT <varun.gupta1798@gmail.com>
2018-12-07 23:31:01 +05:30
pomyo
1ae20b536a Update defaultHtmlStepUi.js (#517) 2018-12-07 12:52:48 -05:00
Osama Mostafa
753e73f355 Update README.md (#525)
Updated the command for installing dependencies for Unix based platform to:
`sudo npm run setup` instead of  `sudo npm setup` as requested in issues.
2018-12-07 12:41:59 -05:00
dependabot[bot]
a26a441b20 Bump browserify from 13.0.0 to 16.2.3 (#533)
Bumps [browserify](https://github.com/browserify/browserify) from 13.0.0 to 16.2.3.
- [Release notes](https://github.com/browserify/browserify/releases)
- [Changelog](https://github.com/browserify/browserify/blob/master/changelog.markdown)
- [Commits](https://github.com/browserify/browserify/compare/13.0.0...v16.2.3)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-06 21:12:01 -05:00
dependabot[bot]
7ae8a2ddf7 Bump bootstrap from 3.2.0 to 3.3.7 (#523)
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 3.2.0 to 3.3.7.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v3.2.0...v3.3.7)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-06 21:11:48 -05:00
dependabot[bot]
c81f5c6caf Bump looks-same from 3.3.0 to 4.1.0 (#531)
Bumps [looks-same](https://github.com/gemini-testing/looks-same) from 3.3.0 to 4.1.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/compare/v3.3.0...v4.1.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-06 16:20:32 -05:00
dependabot[bot]
6d381c0df8 Bump font-awesome from 4.5.0 to 4.7.0 (#527)
Bumps [font-awesome](https://github.com/FortAwesome/Font-Awesome) from 4.5.0 to 4.7.0.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/master/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/v4.5.0...v4.7.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-06 16:20:09 -05:00
dependabot[bot]
6a2f106b4c Bump image-filter-core from 1.0.0 to 2.0.2 (#528)
Bumps [image-filter-core](https://github.com/canastro/image-filter-core) from 1.0.0 to 2.0.2.
- [Release notes](https://github.com/canastro/image-filter-core/releases)
- [Commits](https://github.com/canastro/image-filter-core/commits/2.0.2)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-06 16:14:57 -05:00
dependabot[bot]
65a6b77b78 Bump grunt-contrib-concat from 0.5.1 to 1.0.1 (#522)
Bumps [grunt-contrib-concat](https://github.com/gruntjs/grunt-contrib-concat) from 0.5.1 to 1.0.1.
- [Release notes](https://github.com/gruntjs/grunt-contrib-concat/releases)
- [Changelog](https://github.com/gruntjs/grunt-contrib-concat/blob/master/CHANGELOG)
- [Commits](https://github.com/gruntjs/grunt-contrib-concat/compare/v0.5.1...v1.0.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-05 18:42:04 -05:00
dependabot[bot]
c688817ffc Bump image-filter-threshold from 1.0.0 to 2.0.1 (#521)
Bumps [image-filter-threshold](https://github.com/canastro/image-filter-threshold) from 1.0.0 to 2.0.1.
- [Release notes](https://github.com/canastro/image-filter-threshold/releases)
- [Commits](https://github.com/canastro/image-filter-threshold/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-05 18:41:54 -05:00
dependabot[bot]
ca67bf1ece Bump ora from 2.1.0 to 3.0.0 (#529)
Bumps [ora](https://github.com/sindresorhus/ora) from 2.1.0 to 3.0.0.
- [Release notes](https://github.com/sindresorhus/ora/releases)
- [Commits](https://github.com/sindresorhus/ora/compare/v2.1.0...v3.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-05 18:41:41 -05:00
dependabot[bot]
88a31e564e Bump tape-run from 3.0.4 to 4.0.0 (#520)
Bumps [tape-run](https://github.com/juliangruber/tape-run) from 3.0.4 to 4.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/v3.0.4...v4.0.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-05 11:36:37 -05:00
Bhavay Anand
2161d58e50 slider now goes all the way to right & left (#510) 2018-11-30 18:36:26 -05:00
Oorjit Chowdhary
108e87996a Corrected brightness default view (#509) 2018-11-30 12:50:20 -05:00
Bhavay Anand
f152a78e70 align add-step button with select-module input (#501) 2018-11-30 12:48:21 -05:00
Ville Pajala
5af30d9046 Change button text (#505) 2018-11-29 17:39:28 -05:00
Jan Okoński
ddf4bd0dae Added the sucessfull installation prompt (#485) 2018-11-26 14:06:43 -05:00
Mridul97
3712f0c1cf Skip writing defaults (#497)
* skip writing defaults

* solve build errors
2018-11-26 14:06:13 -05:00
Jonathan Xu
f672dc814a display add step menu with common modules as "quick" buttons (#479)
* added icons, rearranging

* basic framework for addstep modules

* linked buttons to automatic step addition

* Delete package-lock.json

* rounded buttons and text movement in image sequencer select

* made null option visible in select dropdown

* package-lock.json
2018-11-21 19:49:48 -05:00
Jeffrey Warren
98c71b18a8 Add manifest.json and cache static assets for offline use (#331) (#486)
* Add manifest.json

* cache static assets for offline use

* update cache

* add meta theme-color and change static files to be cache

* cache the files on network request

* caching on first run

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

* add a button to clear cache

* add styling to clear cache link
2018-11-20 22:53:38 -05:00
Bhavay Anand
3ca4081042 fixed few typos (#482)
* fixed few typos

* fixed typos in docs

* suggested changes
2018-11-20 18:04:34 -05:00
HarshKhandeparkar
cd6f61d71a Flash Message bug fix (#481) 2018-11-20 17:04:09 -05:00
HarshKhandeparkar
20cf3277ea Feature enter to save (#483)
* Flash Message bug fix

* enter-to-submit functionality added

* cleanup
2018-11-20 16:46:07 -05:00
HarshKhandeparkar
bf13d5807a GCI task pull request (#474)
* GCI task commit

* GCI task commit

* Cleaned up the code

* Added the css to demo.css file

* Final cleanup and shortened code

* Code compacting

* All beautify changes reverted

* Spacing corrected
2018-11-18 12:29:19 -05:00
Rishabh Rawat
ef10fb77f1 Capitalize the Gif text on View Gif button. (#476) 2018-11-17 23:17:22 -05:00
Jeffrey Warren
19110c4677 Colormap fixes! (#475)
* updated colormap.js

* remove redundancy

* compile

* added maps to interface
2018-11-17 11:19:58 -05:00
Jan Okoński
d209cd46b1 Added a success message after a successfull sequence saving (#469) 2018-11-13 14:35:57 -05:00
Mridul97
4bdc5b6583 Add contrast module (#463) 2018-11-13 12:22:48 -05:00
Slytherin
4576e497db Disabled save-sequence button when no steps are added (#462) 2018-11-11 14:41:55 -05:00
kevinzluo
1311119787 Alphabetizes the modules in src/Modules.js (#441) 2018-11-11 13:12:56 -05:00
aashna27
9e1a12c58d brightness module's info.json modified (#461) 2018-11-11 12:51:09 -05:00
aashna27
948f67fb60 rebuild (#454) 2018-11-08 15:44:36 -05:00
Jeffrey Warren
8685dcb66c bugfixes (#457) 2018-11-08 14:22:25 -05:00
Jeffrey Warren
2243a4b8f7 Update README.md 2018-11-08 10:46:12 -05:00
Jeffrey Warren
7fe16735b3 Update README.md 2018-11-05 12:19:37 -05:00
Jeffrey Warren
a17d1a6ccd ability to set image via url hash (#455) 2018-11-05 12:10:20 -05:00
KusioDev
5f57123503 Add resize module (#451)
* added resize module - without test

* Added resize test, deleted unused value in blend test (which I've added before)

* Fixed test

* Fixed test

* added modules file

* added imagejs to package

* removed test - not able to check width and height of the element

* Changed resize calculations
2018-11-03 00:39:41 -04:00
Varun Gupta
d2ff6f2d6c add demo files to npmignore (#425)
* add demo files to npmignore

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

* remove dist and test from npmignore
2018-10-30 20:14:10 -04:00
TheRealBilaal
361be0074c Added cli installation message (#448)
* Added cli installation message (#338)

* Added cli installation message (#338)
2018-10-30 19:16:47 -04:00
Sparks
f9376808fd Include a back-to-top Button on scrolling down (#446)
* Update index.html

* Create scrollToTop.js

* Update demo.css

* Update index.html
2018-10-27 18:34:21 -04:00
faithngetich
85c92626e4 Create config.yml (#404)
* Create config.yml

* Update the link where the code will be published 

Co-Authored-By: faithngetich <faithngetich188@gmail.com>
2018-10-27 18:30:28 -04:00
Timofey Barinov
b30b539dab Added gif download modal (#442)
* Enhance gif view

* Gif modal download button & Fix gif downloading

* Fix gif generation aspect ratio

* Fix fix gif downloading

* Clarified Download(PNG) button
2018-10-26 13:53:49 -04:00
KusioDev
e5e372d89d Add configurable parameter for blend module to chose image (#424)
* Add configurable parameter for blend module to chose image

* Made minor changes

* Edit test to work with new parameter

* blend offset test added

* blend offset test added

* fixed blend offset test
2018-10-23 15:03:41 -04:00
aashna27
11b65604cd Added slider for Brightness and Blur modules (#428) 2018-10-22 17:01:12 -04:00
Sasha Boginsky
c762f1ad5d Add issue and pull request templates into image sequencer repository (#420)
* Add issue and pull request templates into image sequencer repository

* Add issue and pull request templates into image sequencer repository
2018-10-22 15:09:25 -04:00
aashna27
965399a2b4 Added scripts in package.json to fix installation (#411)
* Added scripts in package.json to fix installation

* Update setup script

* Update README.md

Add installation instructions for windows

* Update README.md

added headers for windows and Unix
2018-10-22 11:55:18 -04:00
aashna27
3df5ca3802 Added link in description of edge-detect module (#419) 2018-10-22 11:54:39 -04:00
Jeffrey Warren
7e594c4168 updated package.json versions (#426) 2018-10-20 18:40:32 -04:00
Kshitij
5e28f901eb fix typos (#412)
* fix typos

This commit fixes the issue #408

* remove trailing space
2018-10-20 02:37:14 +08:00
sagarwala
48eafe806f removed typos as mentioned in issue #408 (#410) 2018-10-17 09:32:20 +08:00
Sasha Boginsky
6638e9bdb4 Update info.json #407 (#413)
* Update info.json

* Update PRs #413
2018-10-16 12:16:56 +08:00
Varun Gupta
bf80c2b2b6 add lock files (#414)
Signed-off-by: Varun Gupta <varun.gupta1798@gmail.com>
2018-10-16 12:12:11 +08:00
Varun Gupta
e512e98921 update start script (#406)
Signed-off-by: Varun Gupta <varun.gupta1798@gmail.com>
2018-10-14 06:22:19 +08:00
puneet bindal
9168c15cf9 added gif feature (#360)
* added gif feature

* increased frame duration n changed gif btn name

* removed inline css

* improved ui

* #363 Add placeholder option to input (#370)

* Add placeholder option to input , change type of brightness input to number

 Changes to be committed:
	modified:   examples/lib/defaultHtmlStepUi.js
	modified:   src/modules/Brightness/info.json

* change 0% to 0 in brightness placeholder

* Add gamma module (#374)

* Add gamma module

* update description

* Add matrix math module (#358)

* Add matrix math module

* add info.json file

* correct format of module

* Add a constant factor input field

* clone the pixels array

* change default values

* add extra information on convolution module (#381)

* adds default values to input fields for all module steps ( fixes #382 ) (#384)

* added default values to input fields for all module steps

* merged

Signed-off-by: Ankit Singla <asingla590@gmail.com>

* Accept type images in input field #364 (#366)

* gif button name changed

* fixes #383 (#396)

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

* fix (#387)

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

* updated

* Issue #392 Fixes alignment of message in Add step box (#393)

*  Fixes alignment of message in Add step box

* fixes css info id

* updates class selector in demo

* Spacing changes

* correctly regulates the behaviour of all links (#397)

Signed-off-by: Ankit Singla <asingla590@gmail.com>

* enables Save button for an action if any of its input fields gain focus (#394)

* Updated index.html (#379)

* add histogram module (#354)

* add histogram module

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

* add option to drop gradient

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

* fix bug

Signed-off-by: Varun Gupta <varun.gupta1798@gmail.com>
2018-10-10 03:46:04 -05:00
Varun Gupta
276a637ac3 add histogram module (#354)
* add histogram module

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

* add option to drop gradient

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

* fix bug

Signed-off-by: Varun Gupta <varun.gupta1798@gmail.com>
2018-10-08 14:56:35 -05:00
Daksh Gondaliya
1d085c7f20 Updated index.html (#379) 2018-10-08 14:14:02 -04:00
Ankit Singla
802b281096 enables Save button for an action if any of its input fields gain focus (#394) 2018-10-08 14:13:09 -04:00
Ankit Singla
67408ca338 correctly regulates the behaviour of all links (#397)
Signed-off-by: Ankit Singla <asingla590@gmail.com>
2018-10-08 14:12:34 -04:00
Daniel Larner
a67fe91d0d Issue #392 Fixes alignment of message in Add step box (#393)
*  Fixes alignment of message in Add step box

* fixes css info id

* updates class selector in demo

* Spacing changes
2018-10-08 12:22:56 -04:00
Varun Gupta
09669fe858 fix (#387)
Signed-off-by: Varun Gupta <varun.gupta1798@gmail.com>
2018-10-06 13:06:41 -04:00
Varun Gupta
768117a078 fixes #383 (#396)
Signed-off-by: Varun Gupta <varun.gupta1798@gmail.com>
2018-10-06 13:06:15 -04:00
aashna27
2e7e042baa Accept type images in input field #364 (#366) 2018-10-05 13:18:56 -04:00
Ankit Singla
b300dc2d1f adds default values to input fields for all module steps ( fixes #382 ) (#384)
* added default values to input fields for all module steps

* merged

Signed-off-by: Ankit Singla <asingla590@gmail.com>
2018-10-05 11:55:11 -04:00
Mridul97
fef021911b add extra information on convolution module (#381) 2018-10-05 08:00:05 -04:00
Mridul97
70654a5aac Add matrix math module (#358)
* Add matrix math module

* add info.json file

* correct format of module

* Add a constant factor input field

* clone the pixels array

* change default values
2018-10-04 12:46:21 -04:00
Mridul97
338e610fe7 Add gamma module (#374)
* Add gamma module

* update description
2018-10-03 15:00:42 -04:00
Adriano Costa
06d2aaf1e2 #363 Add placeholder option to input (#370)
* Add placeholder option to input , change type of brightness input to number

 Changes to be committed:
	modified:   examples/lib/defaultHtmlStepUi.js
	modified:   src/modules/Brightness/info.json

* change 0% to 0 in brightness placeholder
2018-10-02 18:18:31 -04:00
vikul1234
5a362f5c9a Update demo.css (#365) 2018-10-01 11:46:57 -06:00
puneet bindal
76826d431d refracted defaultHtmlStepUi.js (#362) 2018-09-30 19:43:51 -06:00
Mridul97
88364decf6 change display value of ndvi from 0-255 to -1 to 1 (#333)
* change display value of ndvi from 0-255 to -1 to 1

* change in dist files

* Truncate ndvi value for displaying
2018-09-12 11:10:32 -04:00
Mridul97
bb17e9452f Add download button (#328) 2018-09-11 15:57:55 -04:00
Varun Gupta
cce65141d2 fix UI functions (#330)
* fix UI functions

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

* Update package.json
2018-09-08 11:13:25 -04:00
Mridul97
b707592588 Show 'Press save to see changes' next to each step's 'Save' button (#329) 2018-09-05 18:17:28 -04:00
77 changed files with 46862 additions and 16940 deletions

35
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,35 @@
### Please describe the problem (or idea)
> What happened just before the problem occurred? Or what problem could this idea solve?
> What did you expect to see that you didn't?
### Please show us where to look
http://sequencer.publiclab.org...
### What's your PublicLab.org username?
> This can help us diagnose the issue:
### Browser, version, and operating system
> Many bugs are related to these -- please help us track it down and reproduce what you're seeing!
****
## Thank you!
Your help makes Public Lab better! We *deeply* appreciate your helping refine and improve this site.
To learn how to write really great issues, which increases the chances they'll be resolved, see:
https://publiclab.org/wiki/developers#Contributing+for+non-coders

16
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,16 @@
Fixes #[Add issue number here.]
Make sure these boxes are checked before your pull request (PR) is ready to be reviewed and merged. Thanks!
* [ ] tests pass -- look for a green checkbox ✔️ a few minutes after opening your PR -- or run tests locally with `rake test`
* [ ] code is in uniquely-named feature branch and has no merge conflicts
* [ ] PR is descriptively titled
* [ ] ask `@publiclab/reviewers` for help, in a comment below
> We're happy to help you get this ready -- don't be afraid to ask for help, and **don't be discouraged** if your tests fail at first!
If tests do fail, click on the red `X` to learn why by reading the logs.
Please be sure you've reviewed our contribution guidelines at https://publiclab.org/contributing-to-public-lab-software
Thanks!

25
.github/config.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
# Configuration for welcome - https://github.com/behaviorbot/welcome
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
# Comment to be posted to on first time issues
newIssueWelcomeComment: |
Thanks for opening your first issue here! Please follow the issue template to help us help you 👍🎉😄
If you have screenshots to share demonstrating the issue, that's really helpful! 📸 You can [make a gif](https://www.cockos.com/licecap/) too!
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
# Comment to be posted to on PRs from first time contributors in your repository
newPRWelcomeComment: |
Thanks for opening this pull request! `Dangerbot` will test out your code and reply in a bit with some pointers and requests.
There may be some errors, **but don't worry!** We're here to help! 👍🎉😄
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
# 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.
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)
# It is recommended to include as many gifs and emojis as possible

45
.npmignore Normal file
View File

@@ -0,0 +1,45 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
.DS_Store
*.swp
todo.txt
test.js
output.txt
output/
examples/
icons/
.travis.yml
Gruntfile.js
yarn.lock

View File

@@ -10,13 +10,13 @@ Most contribution (we imagine) would be in the form of API-compatible modules, w
* [README.md](https://github.com/publiclab/image-sequencer)
* [Contributing Modules](#contributing-modules)
* [Info File](#info-file)
* [Ideas](#ideas)
* [Ideas](#Contribution-ideas)
****
## Contribution ideas
## Contribution-ideas
See [this issue](https://github.com/publiclab/image-sequencer/issues/118) for a range of ideas for new contributions, and links to possibly helpful libraries. Also see the [new features issues list](https://github.com/publiclab/image-sequencer/labels/new-feature).
See [this issue](https://github.com/publiclab/image-sequencer/issues/118) for a range of ideas for new contributions and links to possibly helpful libraries, or you can solve an [existing issue](https://github.com/publiclab/image-sequencer/labels/module). Also see the [new features issues list](https://github.com/publiclab/image-sequencer/labels/new-feature).
### Bugs

View File

@@ -10,13 +10,13 @@ Image Sequencer is different from other image processing systems in that it's _n
* produces a legible trail of operations, to "show your work" for evidential, educational, or reproducibility reasons
* makes the creation of new tools or "modules" simpler -- each must accept an input image, and produce an output image
* allows many images to be run through the same sequence of steps
* works identically in the browser, on Node.js, and on the commandline
* works identically in the browser, on Node.js, and on the command line
![workflow diagram](https://raw.githubusercontent.com/publiclab/image-sequencer/master/examples/images/diagram-workflows.png)
It is also for prototyping some other related ideas:
* filter-like image processing -- applying a transform to any image from a given source, like a proxy. I.e. every image tile of a satellite imagery web map
* filter-like image processing -- applying a transform to an image from a given source, like a proxy. I.e. [every image tile of a satellite imagery web map](https://publiclab.org/notes/warren/05-10-2018/prototype-filter-map-tiles-in-real-time-in-a-browser-with-imagesequencer-ndvi-landsat)
* test-based image processing -- the ability to create a sequence of steps that do the same task as some other image processing tool, provable with example before/after images to compare with
* logging of 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
@@ -45,7 +45,20 @@ A diagram of this running 5 steps on a single sample image may help explain how
## Installation
This library works in the browser, in Node, and on the commandline (CLI), which we think is great. You can start a local environement to test the UI with `npm start`
This library works in the browser, in Node, and on the command line (CLI), which we think is great.
### Unix based platforms
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
```
In case of a port conflict please run the following
```powershell
npm i -g http-server ; http-server -p 3000
```
### Browser
@@ -54,7 +67,7 @@ Just include [image-sequencer.js](https://publiclab.github.io/image-sequencer/di
### Node (via NPM)
(You must have NPM for this)
Add `image-sequencer` to your list of dependancies and run `$ npm install`
Add `image-sequencer` to your list of dependencies and run `$ npm install`
### CLI
@@ -80,13 +93,13 @@ Image Sequencer can be used to run modules on an HTML Image Element using the
modified. `steps` may be the name of a module or array of names of modules.
Note: Browser CORS Restrictions apply. Some browsers may not allow local images
form other folders, and throw a Security Error instead.
from other folders, and throw a Security Error instead.
```js
sequencer.replaceImage(selector,steps,optional_options);
```
`optional_options` allows to pass additional arguments to the module itself.
`optional_options` allows passing additional arguments to the module itself.
For example:
@@ -95,6 +108,14 @@ For example:
sequencer.replaceImage('#photo',['invert','ndvi-red']);
```
### Data URL usage
Since Image Sequencer uses data-urls, you can initiate a new sequence by providing an image in the [data URL format](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), which will import into the demo and run:
[Try this example link with a very small Data URL](http://sequencer.publiclab.org/examples/#src=data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAQABADASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAf/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAABgj/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABykX//Z&steps=invert{})
To produce a data URL from an HTML image, see [this nice blog post with example code](https://davidwalsh.name/convert-image-data-uri-javascript).
## CLI Usage
Image Sequencer also provides a CLI for applying operations to local files. The CLI takes the following arguments:
@@ -123,7 +144,7 @@ The CLI also can take multiple steps at once, like so:
But for this, double quotes must wrap the space-separated steps.
Options for the steps can be passed in one line as json in the details option like
Options for the steps can be passed in one line as JSON in the details option like
```
$ ./index.js -i [PATH] -s "brightness" -c '{"brightness":50}'
@@ -137,7 +158,7 @@ Or the values can be given through terminal prompt like
sequencer --save-sequence "invert-colormap invert(),colormap()"
```
`install-module` option can be used to install new modules from npm. You can register this module in your sequencer with a custom name space sepated with the npm package name. Below is an example for the `image-sequencer-invert` module.
`install-module` option can be used to install new modules from npm. You can register this module in your sequencer with a custom namespace separated with the npm package name. Below is an example of the `image-sequencer-invert` module.
```shell
sequencer --install-module "invert image-sequencer-invert"
```
@@ -175,7 +196,7 @@ CORS Restrictions). To sum up, these are accepted:
* DataURLs
return value: **none** (A callback should be used to ensure the image gets loaded)
The callback is called within the scope of a the sequencer. For example:
The callback is called within the scope of a sequencer. For example:
(addSteps is defined later)
```js
@@ -189,7 +210,7 @@ In this case, only `'SRC'`.
### Adding steps to the image
The `addSteps` method is used to add steps on the image. One or more steps can
The `addSteps` method is used to add steps to the image. One or more steps can
be added at a time. Each step is called a module.
```js
@@ -218,7 +239,7 @@ sequencer.run();
Sequencer can be run with a custom config object
```js
// The config object enables custom progress bars in node environment and
// The config object enables custom progress bars in a node environment and
// ability to run the sequencer from a particular index(of the steps array)
sequencer.run(config);
@@ -242,7 +263,7 @@ sequencer.run(function callback(out){
// "out" is the DataURL of the final image.
});
sequencer.run(config,function callback(out){
// the callback is supported with all types of invocations
// the callback is supported by all types of invocations
});
```
@@ -252,7 +273,7 @@ return value: **`sequencer`** (To allow method chaining)
### Removing a step from the sequencer
The `removeSteps` method is used to remove unwanted steps from the sequencer.
It accepts the index of the step as an input, or an array of the unwanted indices
It accepts the index of the step as an input or an array of the unwanted indices
if there are more than one.
For example, if the modules ['ndvi-red','crop','invert'] were added in this order,
@@ -272,7 +293,7 @@ return value: **`sequencer`** (To allow method chaining)
### Inserting a step in between the sequencer
The `insertSteps` method can be used to insert one or more steps at a given index
in the sequencer. It accepts the index where the module is to be inserted, name of
in the sequencer. It accepts the index where the module is to be inserted, the name of
the module, and an optional options parameter. `index` is the index of the inserted
step. Only one step can be inserted at a time. `optional_options` plays the same
role it played in `addSteps`.
@@ -290,7 +311,7 @@ return value: **`sequencer`** (To allow method chaining)
### Importing an independent module
The `loadNewModule` method can be used to import a new module inside sequencer. Modules can be downloaded via npm, yarn or cdn and are imported with a custom name. If you wish to load a new module at runtime, it will need to avoid using `require()` -- unless it is compiled with a system like browserify or webpack.
The `loadNewModule` method can be used to import a new module inside the sequencer. Modules can be downloaded via npm, yarn or CDN and are imported with a custom name. If you wish to load a new module at runtime, it will need to avoid using `require()` -- unless it is compiled with a system like browserify or webpack.
```js
const module = require('sequencer-moduleName')
@@ -306,7 +327,7 @@ Methods can be chained on the Image Sequencer:
* If the chain starts with loadImage() or loadImages(), the following methods are
applied only to the newly loaded images.
* If no name is provided to the image, a name will be generated for it. The name will
be of the form "image<number>". For ex: "image1", "image2", "image3", etc.
be of the form "image<number>". For Ex: "image1", "image2", "image3", etc.
Valid Chains:
```js
@@ -363,7 +384,7 @@ return value: **none**
### Adding Steps on Multiple Images
The same method `addSteps` is used for this. There's just a slight obvious change
in the syntax that the image name has to be supplied too. `image_name` as well as
in the syntax that the image name has to be supplied too. `image_name` as well as,
`module_name` in the following examples can be either strings or arrays of strings.
```js
@@ -414,7 +435,7 @@ The `run` method also accepts an optional callback just like before:
});
```
JSON Input is also acceptable.
JSON input is also acceptable.
```js
sequencer.run({
@@ -453,7 +474,7 @@ return value: **`sequencer`** (To allow method chaining)
### Inserting steps on an image
The `insertSteps` method can also accept an `image_name` parameter. `image_name`
may be an array. Everything else remains the same. JSON Inout is acceptable too.
may be an array. Everything else remains the same. JSON Input is acceptable too.
```js
sequencer.insertSteps("image",index,"module_name",o);
@@ -474,7 +495,7 @@ return value: **`sequencer`** (To allow method chaining)
## Saving Sequences
IMAGE SEQUENCER supports saving a sequence of modules and their associated settings in a simple string syntax. These sequences can be saved in the local storage inside the browser and inside a json file in node.js. sequences can be saved in node context using the CLI option
IMAGE SEQUENCER supports saving a sequence of modules and their associated settings in a simple string syntax. These sequences can be saved in the local storage inside the browser and inside a JSON file in node.js. sequences can be saved in node context using the CLI option
```shell
--save-sequence "name stringified-sequence"
@@ -495,7 +516,7 @@ Image sequencer supports stringifying a sequence which is appended to the url an
channel{channel:green},invert{}
```
Sequencer also supports use of `()` in place of `{}` for backwards compatibility with older links.(This syntax is deprecated and should be avoided as far as possible)
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)
```
channel(channel:green),invert()
```

46249
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

View File

@@ -1,7 +1,38 @@
Documentation of various Modules
===
## Crop Module (crop)
List of Module Documentations
1. [Crop](#crop-module)
2. [Segmented-Colormap](#segmented-colormap-module)
3. [FisheyeGl](#fisheyeGl-module)
4. [Average](#average-module)
5. [Blend](#blend-module)
6. [Blur](#blur-module)
7. [Brightness](#brightness-module)
8. [Channel](#channel-module)
9. [Colorbar](#colorbar-module)
10. [Colormap](#colormap-module)
11. [Contrast](#contrast-module)
12. [Convolution](#convolutioon-module)
13. [DecodeQr](#decodeQr-module)
14. [Dynamic](#dynamic-module)
15. [Edge-Detect](#edge-detect-module)
16. [Gamma-Correction](#gamma-correction-module)
17. [Gradient](#gradient-module)
18. [Histogram](#histogram-module)
19. [Import-image](#import-image-module)
20. [Invert](#invert-module)
21. [Ndvi](#ndvi-module)
22. [Ndvi-Colormap](#ndvi-colormap-module)
23. [Overlay](#overlay-module)
24. [Resize](#resize-module)
25. [Rotate](#rotate-module)
26. [Saturation](#saturation-module)
## crop-module
This module is used to crop an image.
@@ -24,7 +55,7 @@ Where `options` is an object having the properties `x`, `y`, `w`, `h`. This diag
* `options.h` : half of image height
## Segmented Colormap Module (segmented-colormap)
## segmented-colormap-module
This module is used to map the pixels of the image to a segmented colormap.
@@ -48,7 +79,7 @@ where `options` is an object with the property `colormap`. `options.colormap` ca
* A custom array.
## FisheyeGl (fisheye-gl)
## fisheyeGl-module
This module is used for correcting Fisheye or Lens Distortion
@@ -68,3 +99,333 @@ where `options` is an object with the following properties:
* scale : The ratio to which the original image is to be scaled (0 to 20; default 1.5)
* x : Field of View x (0 to 2; default 1)
* y : Field of View y (0 to 2; default 1)
## average-module
This module is used for averaging all the pixels of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('average',options)
.run()
```
## blend-module
This module is used for blending two images .
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blend',options)
.run()
```
where `options` is an object with the following properties:
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
## blur-module
This module is used for applying a Gaussian blur effect.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blur',options)
.run()
```
where `options` is an object with the following property:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
## brightness-module
This module is used for changing the brightness of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('brightness',options)
.run()
```
where `options` is an object with the following property:
* brightness : brightness of the image in percentage (0 to 100; default 100)
## channel-module
This module is used for forming a grayscale image by applying one of the three primary colors.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('channel',options)
.run()
```
where `options` is an object with the following property:
* channel : color of the channel (red, green, blue; default green)
## colorbar-module
This module is used for displaying an image with a colorbar.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colorbar',options)
.run()
```
where `options` is an object with the following properties:
* colormap : Name of the Colormap(default, greyscale, stretched, fastie, brntogrn, blutoredjet, colors16; default: default)
* x : X-position of the image on which the new image is overlayed (default 0)
* y : Y-position of the image on which the new image is overlayed (default 0)
* h : height of resulting cropped image (default : 50% of input image width )
## colormap-module
This module is used for mapping brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colormap',options)
.run()
```
where `options` is an object with the following property:
* colormap : Name of the Colormap ( greyscale, stretched, fastie, brntogrn, blutoredjet, colors16)
## contrast-module
This module is used for changing the contrast of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('contrast',options)
.run()
```
where `options` is an object with the following property:
* contrast : contrast for the given image (-100 to 100; default : 70)
## convolution-module
This module is used for performing image-convolution.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('convolution',options)
.run()
```
where `options` is an object with the following properties:
* constantFactor : a constant factor, multiplies all the kernel values by that factor (default : 1/9)
* kernelValues : nine space separated numbers representing the kernel values in left to right and top to bottom format(default : 1 1 1 1 1 1 1 1 1)
## decodeQr-module
This module is used for decoding a QR in image (if present).
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('decode-qr',options)
.run()
```
## dynamic-module
This module is used for producing each color channel based on the original image's color.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('dynamic',options)
.run()
```
where `options` is an object with the following properties:
* red : expression for red channel (R, G, B and A as inputs; default r)
* green : expression for green channel (R, G, B and A as inputs; default g)
* blue : expression for blue channel (R, G, B and A as inputs; default b)
* monochrome: fallback for other channels if none provided (default : r+g+b/3)
## edge-detect-module
This module is used for detecting images.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('edge-detect',options)
.run()
```
where `options` is an object with the following properties:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
## gamma-correction-module
This module is used for applying gamma correction.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('gamma-correction',options)
.run()
```
where `options` is an object with the following property:
* adjustment : Inverse of actual gamma factor (default 0.2)
## gradient-module
This module is used for finding gradient of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('gradient',options)
.run()
```
## histogram-module
This module is used for calculating histogram of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('histogram',options)
.run()
```
where `options` is an object with the following property:
* gradient : boolean value used to toggle gradient along x-axis (true or false; default true)
## import-image-module
This module is used for importing a new image and replacing the original with it.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('import-image',options)
.run()
```
where `options` is an object with the following property:
* url : url of the new image (local image url or data url;default : "./images/monarch.png")
## invert-module
This module is used for inverting the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('invert',options)
.run()
```
## ndvi-module
This module is used for applying ndvi technique to the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('ndvi',options)
.run()
```
where `options` is an object with the following property:
* filter : filter for NDVI (blue or red; default red)
## ndvi-colormap-module
This module is used for demonstrating ndvi and colormap properties consecutively.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('ndvi-colormap',options)
.run()
```
## overlay-module
This module is used for overlaying an Image over another .
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('overlay',options)
.run()
```
where `options` is an object with the following properties:
* x : X-position of the image on which the new image is overlayed (default 0)
* y : Y-position of the image on which the new image is overlayed (default 0)
* offset : offset to the step on which the output of the last step is overlayed (default -2)
## resize-module
This module is used for resizing an image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('resize',options)
.run()
```
where `options` is an object with the following property:
* resize : Percentage value of resize (default 125%)
## rotate-module
This module is used for rotating an image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('rotate',options)
.run()
```
where `options` is an object with the following property:
* rotate : angular value for rotation in degrees (between 0 and 360; default 0)
## saturation-module
This module is used for changing the saturation of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('saturation',options)
.run()
```
where `options` is an object with the following property:
* saturation : saturation for the new image (between 0 and 2; default 0)

View File

@@ -23,14 +23,29 @@ h1 {
color: #445;
}
.center-align {
display: flex;
justify-content: center;
text-align:center;
}
.header {
text-align: center;
}
.panel {
margin-left: 20px;
margin-right: 20px;
}
.nomargin {
margin: 0 !important;
}
.form-control {
padding: 0px 0px;
}
#dropzone {
padding: 30px;
margin: 0 20% 30px;
@@ -90,6 +105,10 @@ h1 {
margin: 20px auto;
}
#add-step-btn{
margin-left: 10px;
}
#addStep .labels {
text-align: right;
padding: 6px;
@@ -110,4 +129,104 @@ h1 {
#save-seq {
display: block;
margin: 0 auto;
}
min-width: 250px;
}
.info {
padding: 8px;
text-align: center;
}
#gif {
display: block;
margin: 0 auto;
min-width: 250px;
}
#dwnld {
max-width: 500px;
margin: 20px auto;
margin-left: 5px;
}
#gif_element {
display: block;
margin: 0 auto;
width: 100%;
height: auto;
}
.move-up {
position: fixed;
bottom: 50px;
right: 40px;
z-index: 3;
display: none;
z-index:1000;
}
.move-up button {
background:transparent;
border:none;
}
.move-up button:active:hover {
padding-right:4px !important;
margin-right:2px;
}
.move-up i {
font-size:60px;
opacity:0.5;
color:#BABABA;
}
.btn-circle{
min-width: 80px;
min-height: 80px;
text-align: center;
display: flex !important;
flex-direction: column;
padding: 6px 0;
font-size: 12px;
line-height: 1.42;
border-radius: 10px;
margin-left: 5px;
margin-right: 5px;
}
.radio{
cursor:pointer;
overflow: hidden;
height: 80px;
width: 80px;
margin-left: 5px;
margin-right: 5px;
}
.radio-group {
margin-bottom: 20px;
}
#stepRemovedNotification {
background-color: #808b96;
padding:4px;
color:white;
border-radius:3px;
font-size:2rem;
position:fixed;
bottom:8px;
left:45%;
min-width:14rem;
text-align:center;
display:none;
}
.no-border {
border: 0px;
}
.i-over {
position: absolute;
left: 15px;
top: 15px;
z-index: 2;
color: white;
}
.i-small {
left: 25px;
}

View File

@@ -1,19 +1,54 @@
window.onload = function() {
function generatePreview(previewStepName, customValues, path) {
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 = $('#addStep .row').find('div').each(function() {
if ($(this).find('div').attr('data-value') === previewStepName) {
$(this).find('div').append(img);
}
});
}
function loadPreview() {
previewSequencer = previewSequencer.addSteps('resize', { resize: "40%" });
if (previewStepName === "crop") {
console.log(customValues);
previewSequencer.addSteps(previewStepName, customValues).run(insertPreview);
}
else {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
previewSequencer.loadImage(path, loadPreview);
}
sequencer = ImageSequencer();
function refreshOptions() {
// Load information of all modules (Name, Inputs, Outputs)
var modulesInfo = sequencer.modulesInfo();
console.log(modulesInfo)
var addStepSelect = $("#addStep select");
addStepSelect.html("");
// Add modules to the addStep dropdown
for (var m in modulesInfo) {
addStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + "</option>"
);
if (modulesInfo[m] && modulesInfo[m].name)
addStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + "</option>"
);
}
// Null option
addStepSelect.append('<option value="none" disabled selected>More modules...</option>');
}
refreshOptions();
@@ -23,10 +58,34 @@ window.onload = function() {
// UI for the overall demo:
var ui = DefaultHtmlSequencerUi(sequencer);
sequencer.loadImage("images/tulips.png", ui.onLoad);
// find any `src` parameters in URL hash and attempt to source image from them and run the sequencer
if (getUrlHashParameter('src')) {
sequencer.loadImage(getUrlHashParameter('src'), ui.onLoad);
} else {
sequencer.loadImage("images/tulips.png", ui.onLoad);
}
$("#addStep select").on("change", ui.selectNewStepUi);
$("#addStep button").on("click", ui.addStepUi);
$("#addStep #add-step-btn").on("click", ui.addStepUi);
//Module button radio selection
$('.radio-group .radio').on("click", function() {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
console.log(newStep);
//$("#addStep option[value=" + newStep + "]").attr('selected', 'selected');
$("#addStep select").val(newStep);
ui.selectNewStepUi();
ui.addStepUi();
$(this).removeClass('selected');
});
$('#download-btn').click(function() {
$('.step-thumbnail:last()').trigger("click");
return false;
});
$('body').on('click', 'button.remove', ui.removeStepUi);
$('#save-seq').click(() => {
sequencer.saveSequence(window.prompt("Please give a name to your sequence..."), sequencer.toString());
@@ -34,16 +93,162 @@ window.onload = function() {
refreshOptions();
});
var isWorkingOnGifGeneration = false;
$('.js-view-as-gif').on('click', function(event) {
// Prevent user from triggering generation multiple times
if (isWorkingOnGifGeneration) return;
isWorkingOnGifGeneration = true;
var button = event.target;
button.disabled = true;
try {
// Select all images from previous steps
var imgs = document.getElementsByClassName("step-thumbnail");
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
var options = {
'gifWidth': imgs[0].width,
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
}
gifshot.createGIF(options, function(obj) {
if (!obj.error) {
// Final gif encoded with base64 format
var image = obj.image;
var animatedImage = document.createElement('img');
animatedImage.id = "gif_element";
animatedImage.src = image;
var modal = $('#js-download-gif-modal');
$("#js-download-as-gif-button").one("click", function() {
// Trigger download
download(image, "index.gif", "image/gif");
// Close modal
modal.modal('hide');
})
var gifContainer = document.getElementById("js-download-modal-gif-container");
// Clear previous results
gifContainer.innerHTML = '';
// Insert image
gifContainer.appendChild(animatedImage);
// Open modal
modal.modal();
button.disabled = false;
isWorkingOnGifGeneration = false;
}
});
}
catch (e) {
console.error(e);
button.disabled = false;
isWorkingOnGifGeneration = false;
}
});
// image selection and drag/drop handling from examples/lib/imageSelection.js
sequencer.setInputStep({
dropZoneSelector: "#dropzone",
fileInputSelector: "#fileInput",
takePhotoSelector: "#take-photo",
onLoad: function onFileReaderLoad(progress) {
var reader = progress.target;
var step = sequencer.images.image1.steps[0];
step.output.src = reader.result;
sequencer.run({ index: 0 });
step.options.step.imgElement.src = reader.result;
updatePreviews(reader.result);
},
onTakePhoto: function (url) {
var step = sequencer.images.image1.steps[0];
step.output.src = url;
sequencer.run({ index: 0 });
step.options.step.imgElement.src = url;
}
});
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js', { scope: '/examples/' })
.then(function(registration) {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
console.log(installingWorker)
if (installingWorker.state === 'installed') {
location.reload();
}
}
console.log('Registration successful, scope is:', registration.scope);
})
.catch(function(error) {
console.log('Service worker registration failed, error:', error);
});
}
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
$("#clear-cache").append(" " + cacheName);
});
});
}
$("#clear-cache").click(function() {
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
caches.delete(cacheName);
});
});
}
location.reload();
});
function updatePreviews(src) {
$('#addStep img').remove();
var previewSequencerSteps = {
"brightness": "20",
"saturation": "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);
});
}
if (getUrlHashParameter('src')) {
updatePreviews(getUrlHashParameter('src'));
} else {
updatePreviews("images/tulips.png");
}
};

2839
examples/gifshot.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=UTF8">
<meta name="theme-color" content="#428bca">
<link rel="icon" sizes="192x192" href="../icons/ic_192.png">
<link rel="manifest" href="manifest.json">
<title>Image Sequencer</title>
@@ -19,9 +20,16 @@
<script src="lib/urlHash.js" charset="utf-8"></script>
<script src="lib/defaultHtmlStepUi.js" charset="utf-8"></script>
<script src="lib/defaultHtmlSequencerUi.js" charset="utf-8"></script>
<script src="lib/intermediateHtmlStepUi.js" charset="utf-8"></script>
<script src="demo.js" charset="utf-8"></script>
<!-- for crop module: -->
<script src="../node_modules/imgareaselect/jquery.imgareaselect.dev.js"></script>
<script src="gifshot.js" type="text/javascript"></script>
<!-- Download.js for large files -->
<script src="../node_modules/downloadjs/download.min.js" type="text/javascript"/>
<script src="lib/scrollToTop.js"></script>
</head>
@@ -30,8 +38,7 @@
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<!-- for crop module: -->
<link href="../node_modules/imgareaselect/distfiles/css/imgareaselect-default.css" rel="stylesheet">
<link rel="stylesheet" href="demo.css">
@@ -49,8 +56,8 @@
Open Source
<a href="https://github.com/publiclab/image-sequencer">
<i class="fa fa-github"></i>
</a> by
<a href="https://publiclab.org">Public Lab</a>
</a>
by <a href= "https://publiclab.org" title = "Publiclab Website"><i class = "fa fa-globe"></i> Publiclab</a>
</p>
</header>
@@ -59,32 +66,124 @@
<i>Select or drag in an image to start!</i>
</p>
<center>
<input type="file" id="fileInput" value="">
<input type="file" id="fileInput" value="" accept="image/*"><br />
<button type="button" id="take-photo">Take a Photo</button>
<video id="video" width="400" height="300" style="display:none"></video>
<a href="#" id="capture" style="display:none" class="btn btn-primary btn-md">Click Picture</a>
<a href="#" id="close" style="display:none" class="btn btn-default btn-md">Close</a>
<canvas id="canvas" width="400" height="300" style="display:none"></canvas>
</center>
</div>
<section id="steps" class="row"></section>
<section id="steps" class="row">
<div id="load-image"></div>
</section>
<hr />
<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="text-align:center;">
<select class="form-control input-lg" id="selectStep">
<option value="none" disabled selected>Select a new step...</option>
</select>
<button class="btn btn-success btn-lg" name="add">Add Step</button>
<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="brightness">
<i class="fa fa-sun-o fa-4x i-over"></i>
</div>
<p>Brightness</p>
</div>
<div>
<div class="radio" data-value="contrast">
<i class="fa fa-adjust fa-4x i-over"></i>
</div>
<p>Contrast</p>
</div>
<div>
<div class="radio" data-value="saturation">
<i class="fa fa-tint fa-4x i-over i-small"></i>
</div>
<p>Saturation</p>
</div>
<div>
<div class="radio" data-value="rotate">
<i class="fa fa-rotate-right fa-4x i-over"></i>
</div>
<p>Rotate</p>
</div>
<div>
<div class="radio" data-value="crop">
<i class="fa fa-crop fa-4x i-over"></i>
</div>
<p>Crop</p>
</div>
</div>
<div class="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>
<br />
<p class="info" style="padding:8px;">Select a new module to add to your sequence.</p>
</div>
</div>
</section>
<button class="btn btn-primary btn-lg" name="save-sequence" id="save-seq">Save Sequence</button>
<section id="sequence-actions" class="panel">
<div class="panel-body">
<div class="row center-align">
<button class="btn btn-primary btn-lg" name="save-sequence" id="save-seq">Save Sequence</button>
<button class="btn btn-primary btn-lg js-view-as-gif" id="gif">View GIF</button>
</div>
<div class="modal fade" id="js-download-gif-modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Your gif is ready</h4>
</div>
<div class="modal-body">
<div id="js-download-modal-gif-container">
<!-- Gif should appear here -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Done</button>
<button id="js-download-as-gif-button" class="btn btn-primary">Download</button>
</div>
</div>
</div>
</div>
</div>
</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;">
<button class="btn btn-success btn-lg" id="download-btn" name="download">Download PNG</button>
</div>
</div>
</div>
</section>
</div>
</div>
<form class="move-up" action="#up">
<button><i class="fa fa-arrow-circle-o-up"></i></button>
</form>
<footer>
<hr style="margin:20px;"><center><a class="color:grey;" id="clear-cache">Clear offline cache</a></center>
</footer>
<script type="text/javascript">
$(function() {
var sequencer;
@@ -93,4 +192,4 @@
</body>
</html>
</html>

View File

@@ -8,7 +8,8 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
function onLoad() {
importStepsFromUrlHash();
if (!$('#selectStep').val())
$(addStepSel + " button").prop("disabled", true);
$(addStepSel + " #add-step-btn").prop("disabled", true);
handleSaveSequence();
}
// look up needed steps from Url Hash:
@@ -25,7 +26,7 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
function selectNewStepUi() {
var m = $(addStepSel + " select").val();
$(addStepSel + " .info").html(_sequencer.modulesInfo(m).description);
$(addStepSel + " button").prop("disabled", false);
$(addStepSel + " #add-step-btn").prop("disabled", false);
}
function removeStepUi() {
@@ -33,6 +34,8 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
sequencer.removeSteps(index).run({ index: index - 1 });
// remove from URL hash too
setUrlHashParameter("steps", sequencer.toString());
//disable save-sequence button if all steps are removed
handleSaveSequence();
}
function addStepUi() {
@@ -55,10 +58,21 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
.addSteps(newStepName, options)
.run({ index: _sequencer.images.image1.steps.length - sequenceLength - 1 });
//enable save-sequence button if disabled initially
handleSaveSequence();
// add to URL hash too
setUrlHashParameter("steps", _sequencer.toString());
}
function handleSaveSequence(){
var stepCount=sequencer.images.image1.steps.length;
if(stepCount<2)
$(" #save-seq").prop("disabled", true);
else
$(" #save-seq").prop("disabled", false);
}
return {
onLoad: onLoad,
importStepsFromUrlHash: importStepsFromUrlHash,

View File

@@ -7,18 +7,29 @@
// The variable 'step' stores useful data like input and
// output values, step information.
// See documetation for more details.
function stepRemovedNotify() {
if ($('#stepRemovedNotification').length == 0) {
var notification = document.createElement('span');
notification.innerHTML = ' <i class="fa fa-info-circle" aria-hidden="true"></i> Step Removed ';
notification.id = 'stepRemovedNotification';
$('body').append(notification);
}
$('#stepRemovedNotification').fadeIn(500).delay(200).fadeOut(500);
}
function DefaultHtmlStepUi(_sequencer, options) {
options = options || {};
var stepsEl = options.stepsEl || document.querySelector("#steps");
var selectStepSel = options.selectStepSel = options.selectStepSel || "#selectStep";
function onSetup(step) {
function onSetup(step, stepOptions) {
if (step.options && step.options.description)
step.description = step.options.description;
step.ui =
'\
<div class="container">\
<div class="row step">\
<div class="col-md-4 details">\
<h3>' +
@@ -30,22 +41,28 @@ function DefaultHtmlStepUi(_sequencer, options) {
</div>\
<div class="col-md-8">\
<div class="load" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></div>\
<a><img alt="" style="max-width=100%" class="img-thumbnail" /></a>\
<a><img alt="" style="max-width=100%" class="img-thumbnail step-thumbnail"/></a>\
</div>\
</div>\
';
</div>\
</div>';
var tools =
'<div class="tools btn-group">\
<button confirm="Are you sure?" class="remove btn btn btn-default">\
<button confirm="Are you sure?" onclick="stepRemovedNotify()" class="remove btn btn btn-default">\
<i class="fa fa-trash"></i>\
</button>\
</div>';
<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>';
var util = IntermediateHtmlStepUi(_sequencer, step);
var parser = new DOMParser();
step.ui = parser.parseFromString(step.ui, "text/html");
step.ui = step.ui.querySelector("div.row");
step.linkElement = step.ui.querySelector("a");
step.ui = step.ui.querySelector("div.container");
step.linkElements = step.ui.querySelectorAll("a");
step.imgElement = step.ui.querySelector("a img");
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
@@ -66,12 +83,28 @@ function DefaultHtmlStepUi(_sequencer, options) {
}
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") {
html +=
'"min="' +
inputDesc.min +
'"max="' +
inputDesc.max +
'"step="' +
inputDesc.step + '">' + '<span>' + paramVal + '</span>';
}
else html += '">';
}
var div = document.createElement("div");
@@ -80,6 +113,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
var description = inputs[paramName].desc || paramName;
div.innerHTML =
"<div class='det'>\
<form class='input-form'>\
<label for='" +
paramName +
"'>" +
@@ -88,21 +122,28 @@ function DefaultHtmlStepUi(_sequencer, options) {
" +
html +
"\
</form>\
</div>";
step.ui.querySelector("div.details").appendChild(div);
}
function toggleSaveButton(){
$(step.ui.querySelector("div.details .btn-save")).prop("disabled",false);
function toggleSaveButton() {
$(step.ui.querySelector("div.details .btn-save")).prop("disabled", false);
focusInput();
}
$(step.ui.querySelector(".target")).change(toggleSaveButton);
$(step.ui.querySelectorAll(".target")).on('change', toggleSaveButton);
$(step.ui.querySelector("div.details")).append(
"<p><button class='btn btn-default btn-save' disabled = 'true' >Save</button></p>"
"<p><button class='btn btn-default btn-save' disabled = 'true' >Apply</button><span> Press apply to see changes</span></p>"
);
function saveOptions() {
function focusInput() {
$(step.ui.querySelector("div.details .target")).focus();
}
function saveOptions(e) {
e.preventDefault();
$(step.ui.querySelector("div.details"))
.find("input,select")
.each(function(i, input) {
@@ -113,23 +154,43 @@ function DefaultHtmlStepUi(_sequencer, options) {
// modify the url hash
setUrlHashParameter("steps", _sequencer.toString());
// disable the save button
$(step.ui.querySelector("div.details .btn-save")).prop("disabled",true);
$(step.ui.querySelector("div.details .btn-save")).prop("disabled", true);
}
// on clicking Save in the details pane of the step
$(step.ui.querySelector("div.details .btn-save")).click(saveOptions);
$(step.ui.querySelector("div.details .input-form")).on('submit', saveOptions);
}
if (step.name != "load-image")
if (step.name != "load-image") {
step.ui
.querySelector("div.details")
.appendChild(
parser.parseFromString(tools, "text/html").querySelector("div")
);
$(step.ui.querySelectorAll(".insert-step")).on('click', function() { util.insertStep(step.ID) });
stepsEl.appendChild(step.ui);
// Insert the step's UI in the right place
if (stepOptions.index == _sequencer.images.image1.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);
} else {
stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]);
}
}
else {
$("#load-image").append(step.ui);
}
}
var inputs = document.querySelectorAll('input[type="range"]')
for (i in inputs)
inputs[i].oninput = function(e) {
e.target.nextSibling.innerHTML = e.target.value;
}
function onDraw(step) {
$(step.ui.querySelector(".load")).show();
$(step.ui.querySelector("img")).hide();
@@ -140,33 +201,35 @@ function DefaultHtmlStepUi(_sequencer, options) {
$(step.ui.querySelector("img")).show();
step.imgElement.src = step.output;
step.linkElement.href = step.output;
var imgthumbnail = step.ui.querySelector(".img-thumbnail");
for (let index = 0; index < step.linkElements.length; index++) {
if (step.linkElements[index].contains(imgthumbnail))
step.linkElements[index].href = step.output;
}
// TODO: use a generalized version of this
function fileExtension(output) {
return output.split("/")[1].split(";")[0];
}
step.linkElement.download = step.name + "." + fileExtension(step.output);
step.linkElement.target = "_blank";
for (let index = 0; index < step.linkElements.length; index++) {
step.linkElements[index].download = step.name + "." + fileExtension(step.output);
step.linkElements[index].target = "_blank";
}
// fill inputs with stored step options
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
var inputs = _sequencer.modulesInfo(step.name).inputs;
var outputs = _sequencer.modulesInfo(step.name).outputs;
for (var i in inputs) {
if (
step.options[i] !== undefined &&
inputs[i].type.toLowerCase() === "input"
)
step.ui.querySelector('div[name="' + i + '"] input').value =
step.options[i];
if (
step.options[i] !== undefined &&
inputs[i].type.toLowerCase() === "select"
)
step.ui.querySelector('div[name="' + i + '"] select').value =
step.options[i];
if (step.options[i] !== undefined) {
if (inputs[i].type.toLowerCase() === "input")
step.ui.querySelector('div[name="' + i + '"] input').value =
step.options[i];
if (inputs[i].type.toLowerCase() === "select")
step.ui.querySelector('div[name="' + i + '"] select').value =
step.options[i];
}
}
for (var i in outputs) {
if (step[i] !== undefined)
@@ -178,6 +241,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
function onRemove(step) {
step.ui.remove();
$("#steps .container:nth-last-child(1) .insert-step").prop('disabled',true);
}
function getPreview() {
@@ -191,4 +255,4 @@ function DefaultHtmlStepUi(_sequencer, options) {
onRemove: onRemove,
onDraw: onDraw
}
}
}

View File

@@ -0,0 +1,118 @@
function IntermediateHtmlStepUi(_sequencer, step, options) {
function stepUI() {
return '<div class="row insertDiv">\
<div class="col-md-6" 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>\
<button type="button" class="btn btn-default btn-circle btn-xl radio" data-value="brightness">\
<i class="fa fa-sun-o fa-4x"></i>\
</button>\
<p>Brightness</p>\
</div>\
<div>\
<button type="button" class="btn btn-default btn-circle btn-xl radio" data-value="contrast">\
<i class="fa fa-adjust fa-4x"></i>\
</button>\
<p>Contrast</p>\
</div>\
<div>\
<button type="button" class="btn btn-default btn-circle btn-xl radio" data-value="saturation">\
<i class="fa fa-tint fa-4x"></i>\
</button>\
<p>Saturation</p>\
</div>\
<div>\
<button type="button" class="btn btn-default btn-circle btn-xl radio" data-value="rotate">\
<i class="fa fa-rotate-right fa-4x"></i>\
</button>\
<p>Rotate</p>\
</div>\
<div>\
<button type="button" class="btn btn-default btn-circle btn-xl radio" data-value="crop">\
<i class="fa fa-crop fa-4x"></i>\
</button>\
<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>\
</div>';
}
function selectNewStepUi() {
var m = $("#insertStep select").val();
$("#insertStep .info").html(_sequencer.modulesInfo(m).description);
$("#insertStep #add-step-btn").prop("disabled", false);
}
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
);
var insertStepSelect = $("#insertStep 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>"
);
}
$('#insertStep #add-step-btn').prop('disabled', true);
insertStepSelect.append('<option value="none" disabled selected>More modules...</option>');
$('#insertStep .radio-group .radio').on("click", function() {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
insertStepSelect.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) });
}
function insert(id) {
options = options || {};
var insertStepSelect = $("#insertStep select");
if (insertStepSelect.val() == "none") return;
var newStepName = insertStepSelect.val()
$('div .insertDiv').remove();
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"];
}
_sequencer
.insertSteps(id + 1, newStepName).run({ index: id });
// add to URL hash too
setUrlHashParameter("steps", _sequencer.toString());
}
return {
insertStep
}
}

View File

@@ -0,0 +1,17 @@
$(document).ready(function($){
$(function(){
$(window).scroll(function(){
if ($(this).scrollTop() > 100){
$('.move-up').fadeIn();
} else {
$('.move-up').fadeOut();
}
});
$('.move-up button').click(function(){
$('body,html').animate({
scrollTop: 0
}, 800);
return false;
});
});
});

21
examples/manifest.json Normal file
View File

@@ -0,0 +1,21 @@
{
"short_name": "IS",
"name": "Image Sequencer",
"icons": [
{
"src": "../icons/ic_192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "../icons/ic_512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "/examples/#steps=",
"background_color": "#428bca",
"display": "standalone",
"scope": "/examples/",
"theme_color": "#428bca"
}

35
examples/sw.js Normal file
View File

@@ -0,0 +1,35 @@
const staticCacheName = 'image-sequencer-static-v3';
self.addEventListener('install', event => {
console.log('Attempting to install service worker');
});
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName){
return cacheName.startsWith('image-sequencer-') &&
cacheName != staticCacheName;
}).map(function(cacheName){
return caches.delete(cacheName);
})
);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
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")
cache.put(event.request, response.clone());
return response;
});
});
})
);
});

BIN
icons/ic_512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -26,13 +26,20 @@ program
if (program.saveSequence) {
var params = program.saveSequence.split(' ');
sequencer.saveSequence(params[0], params[1]);
console.log("\x1b[32m", "Your sequence was saved successfully!!");
} else if (program.installModule) {
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();
require('child_process').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!!");
} else {
// Parse step into an array to allow for multiple steps.
if (!program.step) exit("No steps passed");
@@ -202,4 +209,3 @@ if (program.saveSequence) {
else return true;
}
}

6162
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
{
"name": "image-sequencer",
"version": "2.2.2",
"version": "2.2.3",
"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/**/*.js test/*.js | tap-spec; browserify test/modules/image-sequencer.js test/modules/chain.js test/modules/meta-modules.js test/modules/replace.js test/modules/import-export.js test/modules/run.js test/modules/dynamic-imports.js | tape-run --render=\"tap-spec\"",
"setup": "npm i && npm i -g grunt grunt-cli",
"start": "grunt serve"
},
"repository": {
@@ -22,40 +23,42 @@
"url": "https://github.com/publiclab/image-sequencer/issues"
},
"dependencies": {
"bootstrap": "~3.2.0",
"buffer": "~5.0.2",
"bootstrap": "~3.4.0",
"buffer": "~5.2.1",
"commander": "^2.11.0",
"data-uri-to-buffer": "^2.0.0",
"downloadjs": "^1.4.7",
"fisheyegl": "^0.1.2",
"font-awesome": "~4.5.0",
"font-awesome": "~4.7.0",
"get-pixels": "~3.3.0",
"image-sequencer-invert": "^1.0.0",
"imagejs": "0.0.9",
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
"jquery": "~2",
"jquery": "^3.3.1",
"jsqr": "^0.2.2",
"lodash": "^4.17.5",
"ndarray-gaussian-filter": "^1.0.0",
"ora": "^2.0.0",
"ora": "^3.0.0",
"pace": "0.0.4",
"readline-sync": "^1.4.7",
"save-pixels": "~2.3.4",
"urify": "^2.1.0"
"urify": "^2.1.1"
},
"devDependencies": {
"browserify": "13.0.0",
"grunt": "^0.4.5",
"browserify": "16.2.3",
"grunt": "^1.0.3",
"grunt-browser-sync": "^2.2.0",
"grunt-browserify": "^5.0.0",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-uglify-es": "^3.3.0",
"grunt-contrib-watch": "^0.6.1",
"image-filter-core": "~1.0.0",
"image-filter-threshold": "~1.0.0",
"looks-same": "^3.2.1",
"matchdep": "^0.3.0",
"tap-spec": "^4.1.1",
"grunt-contrib-watch": "^1.1.0",
"image-filter-core": "~2.0.2",
"image-filter-threshold": "~2.0.1",
"looks-same": "^4.1.0",
"matchdep": "^2.0.0",
"tap-spec": "^5.0.0",
"tape": ">=4.7.0",
"tape-run": "^3.0.0",
"tape-run": "^5.0.0",
"uglify-es": "^3.3.7"
},
"homepage": "https://github.com/publiclab/image-sequencer",

View File

@@ -219,7 +219,7 @@ ImageSequencer = function ImageSequencer(options) {
modulesdata[modulename] = modules[modulename][1];
}
for (var sequencename in this.sequences) {
modulesdata[sequencename] = { name: sequencename, steps: sequences[sequencename] };
modulesdata[sequencename] = { name: sequencename, steps: this.sequences[sequencename] };
}
}
else {
@@ -256,15 +256,18 @@ ImageSequencer = function ImageSequencer(options) {
// Stringifies one step of the sequence
function stepToString(step) {
let inputs = copy(modulesInfo(step.options.name).inputs);
inputs = inputs || {};
let inputs = modulesInfo(step.options.name).inputs || {}, op = {};
for (let input in inputs) {
inputs[input] = step.options[input] || inputs[input].default;
inputs[input] = encodeURIComponent(inputs[input]);
if (!!step.options[input] && step.options[input] != inputs[input].default) {
op[input] = step.options[input];
op[input] = encodeURIComponent(op[input]);
}
}
var configurations = Object.keys(inputs).map(key => key + ':' + inputs[key]).join('|');
var configurations = Object.keys(op).map(key => key + ':' + op[key]).join('|');
return `${step.options.name}{${configurations}}`;
}

View File

@@ -34,17 +34,25 @@ function InsertStep(ref, image, index, name, o) {
};
var UI = ref.events;
// Tell UI that a step has been set up.
o = o || {};
// define the expandSteps function for sequencer
ref.modules[name].expandSteps = function expandSteps(stepsArray) {
for (var step of stepsArray) {
ref.addSteps(step['name'], step['options']);
for (var i in stepsArray) {
let step = stepsArray[i];
console.log(step['name'])
console.log(step['options'])
ref.insertSteps(index + Number.parseInt(i), step['name'], step['options']);
// ref.addSteps(step['name'], step['options']);
}
}
var mod = ref.modules[name][0](o, UI);
if (!mod.isMeta) {
UI.onSetup(o.step);
ref.images[image].steps.splice(index, 0, mod);
// Tell UI that a step has been set up.
o = o || {};
if (!ref.modules[name][1].length) {
UI.onSetup(o.step, { index: index });
ref.images[image].steps.splice(index, 0, ref.modules[name][0](o, UI));
} else {
ref.modules[name][0](o, UI);
}
return true;

View File

@@ -2,23 +2,29 @@
* Core modules and their info files
*/
module.exports = {
'channel': require('./modules/Channel'),
'brightness': require('./modules/Brightness'),
'edge-detect': require('./modules/EdgeDetect'),
'ndvi': require('./modules/Ndvi'),
'crop': require('./modules/Crop'),
'colormap': require('./modules/Colormap'),
'decode-qr': require('./modules/DecodeQr'),
'fisheye-gl': require('./modules/FisheyeGl'),
'dynamic': require('./modules/Dynamic'),
'blur': require('./modules/Blur'),
'saturation': require('./modules/Saturation'),
'average': require('./modules/Average'),
'blend': require('./modules/Blend'),
'import-image': require('./modules/ImportImage'),
'overlay': require('./modules/Overlay'),
'gradient': require('./modules/Gradient'),
'invert': require('image-sequencer-invert'),
'ndvi-colormap': require('./modules/NdviColormap'),
'blur': require('./modules/Blur'),
'brightness': require('./modules/Brightness'),
'channel': require('./modules/Channel'),
'colorbar': require('./modules/Colorbar'),
}
'colormap': require('./modules/Colormap'),
'contrast': require('./modules/Contrast'),
'convolution': require('./modules/Convolution'),
'crop': require('./modules/Crop'),
'decode-qr': require('./modules/DecodeQr'),
'dynamic': require('./modules/Dynamic'),
'edge-detect': require('./modules/EdgeDetect'),
'fisheye-gl': require('./modules/FisheyeGl'),
'histogram': require('./modules/Histogram'),
'gamma-correction': require('./modules/GammaCorrection'),
'gradient': require('./modules/Gradient'),
'import-image': require('./modules/ImportImage'),
'invert': require('image-sequencer-invert'),
'ndvi': require('./modules/Ndvi'),
'ndvi-colormap': require('./modules/NdviColormap'),
'overlay': require('./modules/Overlay'),
'resize': require('./modules/Resize'),
'rotate': require('./modules/Rotate'),
'saturation': require('./modules/Saturation')
}

View File

@@ -2,5 +2,6 @@
"name": "Average",
"description": "Average all pixel color",
"inputs": {
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -1,63 +1,67 @@
module.exports = function Dynamic(options, UI, util) {
options.func = options.func || "function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] }";
options.func = options.func || "function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] }";
options.offset = options.offset || -2;
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');
// save first image's pixels
var priorStep = this.getStep(-2);
// convert offset as string to int
if(typeof options.offset === "string") options.offset = parseInt(options.offset);
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
// save first image's pixels
var priorStep = this.getStep(options.offset);
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
var 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)
)
}
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
function output(image, datauri, mimetype) {
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
var 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)
)
}
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
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, {
}
// 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
});
});
}
return {
options: options,
draw: draw,
output: output,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
UI: UI
}
}

View File

@@ -1,11 +1,17 @@
{
"name": "Blend",
"description": "Blend the past two 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!",
"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": {
"type": "integer",
"desc": "Choose which image to blend the current image with. Two steps back is -2, three steps back is -3 etc.",
"default": -2
},
"blend": {
"type": "input",
"desc": "Function to use to blend the two images.",
"default": "function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] }"
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -1,11 +1,15 @@
{
"name": "Blur",
"description": "Gaussian blur an image by a given value, typically 0-5",
"description": "Applies a Gaussian blur given by the intensity value",
"inputs": {
"blur": {
"type": "integer",
"desc": "amount of gaussian blur(Less blur gives more detail, typically 0-5)",
"default": 2
"type": "range",
"desc": "Amount of gaussian blur(Less blur gives more detail, typically 0-5)",
"default": "2",
"min": "0",
"max": "5",
"step": "0.25"
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -20,12 +20,14 @@ module.exports = function Brightness(options,UI){
var step = this;
function changePixel(r, g, b, a){
options.brightness =
options.brightness || 100
var val = (options.brightness)/100.0
r = val*r<255?val*r:255
g = val*g<255?val*g:255
b = val*b<255?val*b:255
return [r , g, b, a]
return [r, g, b, a]
}
function output(image,datauri,mimetype){

View File

@@ -1,11 +1,15 @@
{
"name": "Brightness",
"description": "Change the brightness of the image by given percent value",
"inputs": {
"brightness": {
"type": "integer",
"desc": "% brightness for the new image",
"default": 0
}
}
"name": "Brightness",
"description": "Change the brightness of the image by given percent value",
"inputs": {
"brightness": {
"type": "range",
"desc": "% brightness for the new image",
"default": "100",
"min": "0",
"max": "200",
"step": "1"
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -8,5 +8,6 @@
"default": "green",
"values": ["red", "green", "blue"]
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -29,5 +29,6 @@
"default": 10
}
},
"length": 4
"length": 4,
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -53,35 +53,145 @@ function colormap(segments) {
var colormaps = {
greyscale: colormap([
[0, [0, 0, 0], [255, 255, 255] ],
[0, [0, 0, 0], [220, 20, 60] ],
[1, [255, 255, 255], [255, 255, 255] ]
]),
default: colormap([
[0, [0, 0, 255], [0, 255, 0] ],
[0.25, [0, 255, 0], [255, 255, 0] ],
[0.50, [0, 255, 255], [255, 255, 0] ],
[0.75, [255, 255, 0], [255, 0, 0] ]
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] ]
]),
ndvi: colormap([
[0, [0, 0, 255], [38, 195, 195] ],
[0.5, [0, 150, 0], [255, 255, 0] ],
[0.75, [255, 255, 0], [255, 50, 50] ]
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] ]
]),
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]]
]),
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, [2, 0, 226], [2, 0, 226] ],
[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] ]
]),
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] ]
])
}
}

View File

@@ -6,7 +6,8 @@
"type": "select",
"desc": "Name of the Colormap",
"default": "default",
"values": ["default","greyscale","stretched","fastie"]
"values": ["default","greyscale","bluwhtgrngis","stretched","fastie","brntogrn","blutoredjet","colors16"]
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -0,0 +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;
for (let i = 0; i < oldpix.shape[0]; i++) {
for (let j = 0; j < oldpix.shape[1]; j++) {
var r = oldpix.get(i,j,0)/255.0;
r -= 0.5;
r *= contrast;
r += 0.5;
r *= 255;
if (r < 0) r = 0;
if (r > 255) r = 255;
var g = oldpix.get(i,j,1)/255.0;
g -= 0.5;
g *= contrast;
g += 0.5;
g *= 255;
if (g < 0) g = 0;
if (g > 255) g = 255;
var b = oldpix.get(i,j,2)/255.0;
b -= 0.5;
b *= contrast;
b += 0.5;
b *= 255;
if (b < 0) b = 0;
if (b > 255) b = 255;
pixels.set(i, j, 0, r);
pixels.set(i, j, 1, g);
pixels.set(i, j, 2, b);
}
}
return pixels;
}

View File

@@ -0,0 +1,49 @@
// /*
// * Changes the Image Contrast
// */
module.exports = function Contrast(options, UI) {
options.contrast = options.contrast || 70
var output;
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function changePixel(r, g, b, a) {
return [r, g, b, a]
}
function extraManipulation(pixels) {
pixels = require('./Contrast')(pixels, options.contrast)
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,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

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

View File

@@ -0,0 +1,12 @@
{
"name": "Contrast",
"description": "Change the contrast of the image by given value",
"inputs": {
"contrast": {
"type": "Number",
"desc": "contrast for the new image, typically -100 to 100",
"default": 70
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -0,0 +1,71 @@
var _ = require('lodash');
module.exports = exports = function(pixels, constantFactor, kernelValues){
let kernel = kernelGenerator(constantFactor, kernelValues), oldpix = _.cloneDeep(pixels);
kernel = flipKernel(kernel);
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] = acc[0]%255;
acc[1] = acc[1]%255;
acc[2] = acc[2]%255;
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
}
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(i = 0; i < 3; i++){
let columns = [];
for(j = 0; j < 3; j++){
columns.push(kernelValues[k]);
k += 1;
}
arr.push(columns);
}
return arr;
}
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;
}
}

View File

@@ -0,0 +1,45 @@
module.exports = function Convolution(options, UI) {
options.kernelValues = options.kernelValues || '1 1 1 1 1 1 1 1 1';
options.constantFactor = options.constantFactor || 1/9;
var output;
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function changePixel(r, g, b, a) {
return [r, g, b, a]
}
function extraManipulation(pixels) {
pixels = require('./Convolution')(pixels, options.constantFactor, options.kernelValues)
return pixels
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

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

View File

@@ -0,0 +1,20 @@
{
"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
},
"kernelValues": {
"type": "String",
"desc": "nine space separated numbers representing the kernel values in left to right and top to bottom format.",
"default": "1 1 1 1 1 1 1 1 1",
"placeholder": "1 1 1 1 1 1 1 1 1"
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -17,7 +17,7 @@ module.exports = function CropModule(options, UI) {
// we should get UI to return the image thumbnail so we can attach our own UI extensions
// add our custom in-module html ui:
if (options.step.inBrowser) var ui = require('./Ui.js')(options.step, UI);
if (options.step.inBrowser && !options.noUI) var ui = require('./Ui.js')(options.step, UI);
var output,
setupComplete = false;
@@ -49,7 +49,7 @@ module.exports = function CropModule(options, UI) {
// start custom UI setup (draggable UI)
// only once we have an input image
if (setupComplete === false && options.step.inBrowser) {
if (setupComplete === false && options.step.inBrowser && !options.noUI) {
setupComplete = true;
ui.setup();
}

View File

@@ -23,5 +23,6 @@
"desc": "Height of crop",
"default": "(100%)"
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -7,5 +7,6 @@
"qrval": {
"type": "text"
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -54,6 +54,22 @@ module.exports = function Dynamic(options,UI) {
]
}
// via P5js: https://github.com/processing/p5.js/blob/2920492842aae9a8bf1a779916893ac19d65cd38/src/math/calculation.js#L461-L472
function map(n, start1, stop1, start2, stop2, withinBounds) {
var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
if (!withinBounds) {
return newval;
}
// also via P5js: https://github.com/processing/p5.js/blob/2920492842aae9a8bf1a779916893ac19d65cd38/src/math/calculation.js#L116-L119
function constrain(n, low, high) {
return Math.max(Math.min(n, high), low);
};
if (start2 < stop2) {
return constrain(newval, start2, stop2);
} else {
return constrain(newval, stop2, start2);
}
};
function output(image,datauri,mimetype){

View File

@@ -22,5 +22,6 @@
"desc": "Expression to return with R, G, B, and A inputs; fallback for other channels if none provided",
"default": "r + g + b"
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -4,9 +4,8 @@ const _ = require('lodash')
const kernelx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]],
kernely = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]];
let angles = [], mags = [], strongEdgePixels = [], weakEdgePixels = [], notInUI;
module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, inBrowser) {
notInUI = !inBrowser;
let angles = [], mags = [], strongEdgePixels = [], weakEdgePixels = [], notInUI = !inBrowser;
for (var x = 0; x < pixels.shape[0]; x++) {
angles.push([]);
mags.push([]);
@@ -29,8 +28,9 @@ module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, inBrows
angles.slice(-1)[0].push(result.angle);
}
}
return doubleThreshold(nonMaxSupress(pixels), highThresholdRatio, lowThresholdRatio);
nonMaxSupress(pixels, mags, angles);
doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio, mags, strongEdgePixels, weakEdgePixels);
return pixels;
}
//changepixel function that convolutes every pixel (sobel filter)
@@ -65,7 +65,7 @@ function changePixel(pixels, val, a, x, y) {
}
//Non Maximum Supression without interpolation
function nonMaxSupress(pixels) {
function nonMaxSupress(pixels, mags, angles) {
angles = angles.map((arr) => arr.map(convertToDegrees));
@@ -113,7 +113,6 @@ function nonMaxSupress(pixels) {
}
}
return pixels;
}
//Converts radians to degrees
var convertToDegrees = radians => (radians * 180) / Math.PI;
@@ -122,9 +121,9 @@ var convertToDegrees = radians => (radians * 180) / Math.PI;
var findMaxInMatrix = arr => Math.max(...arr.map(el => el.map(val => !!val ? val : 0)).map(el => Math.max(...el)));
//Applies the double threshold to the image
function doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio) {
function doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio, mags, strongEdgePixels, weakEdgePixels) {
const highThreshold = findMaxInMatrix(mags) * 0.2;
const highThreshold = findMaxInMatrix(mags) * highThresholdRatio;
const lowThreshold = highThreshold * lowThresholdRatio;
for (let i = 0; i < pixels.shape[0]; i++) {
@@ -140,8 +139,6 @@ function doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio) {
}
strongEdgePixels.forEach(pix => pixels.set(pix[0], pix[1], 3, 255));
return pixels;
}
// hysteresis edge tracking algorithm -- not working as of now

View File

@@ -1,16 +1,16 @@
/*
* Detect Edges in an Image
*/
module.exports = function edgeDetect(options,UI) {
module.exports = function edgeDetect(options, UI) {
options.blur = options.blur || 2;
options.highThresholdRatio = options.highThresholdRatio||0.2;
options.lowThresholdRatio = options.lowThresholdRatio||0.15;
options.highThresholdRatio = options.highThresholdRatio || 0.2;
options.lowThresholdRatio = options.lowThresholdRatio || 0.15;
var output;
// The function which is called on every draw.
function draw(input,callback,progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
@@ -19,19 +19,20 @@ module.exports = function edgeDetect(options,UI) {
// Extra Manipulation function used as an enveloper for applying gaussian blur and Convolution
function extraManipulation(pixels){
pixels = require('ndarray-gaussian-filter')(pixels,options.blur);
return require('./EdgeUtils')(pixels,options.highThresholdRatio,options.lowThresholdRatio,options.inBrowser);
function extraManipulation(pixels) {
pixels = require('ndarray-gaussian-filter')(pixels, options.blur);
pixels = require('./EdgeUtils')(pixels, options.highThresholdRatio, options.lowThresholdRatio, options.inBrowser);
return pixels;
}
function changePixel(r, g, b, a) {
return [(r+g+b)/3, (r+g+b)/3, (r+g+b)/3, a];
return [(r + g + b) / 3, (r + g + b) / 3, (r + g + b) / 3, a];
}
function output(image,datauri,mimetype){
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = {src:datauri,format:mimetype};
step.output = { src: datauri, format: mimetype };
}
@@ -49,7 +50,7 @@ module.exports = function edgeDetect(options,UI) {
return {
options: options,
draw: draw,
draw: draw,
output: output,
UI: UI
}

View File

@@ -1,6 +1,6 @@
{
"name": "Detect Edges",
"description": "this module detects edges using the Canny method, which first Gaussian blurs the image to reduce noise (amount of blur configurable in settings as `options.blur`), then applies a number of steps to highlight edges, resulting in a greyscale image where the brighter the pixel, the stronger the detected edge. Read more at: https://en.wikipedia.org/wiki/Canny_edge_detector",
"description": "this module detects edges using the Canny method, which first Gaussian blurs the image to reduce noise (amount of blur configurable in settings as `options.blur`), then applies a number of steps to highlight edges, resulting in a greyscale image where the brighter the pixel, the stronger the detected edge.<a href='https://en.wikipedia.org/wiki/Canny_edge_detector'> Read more. </a>",
"inputs": {
"blur": {
"type": "integer",
@@ -17,5 +17,6 @@
"desc": "The low threshold value for the image",
"default": 0.15
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -54,13 +54,14 @@
},
"fragmentSrc": {
"type": "PATH",
"desc": "Patht to a WebGL fragment shader file",
"desc": "Path to a WebGL fragment shader file",
"default": "(inbuilt)"
},
"vertexSrc": {
"type": "PATH",
"desc": "Patht to a WebGL vertex shader file",
"desc": "Path to a WebGL vertex shader file",
"default": "(inbuilt)"
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -0,0 +1,44 @@
module.exports = function Gamma(options,UI){
var output;
function draw(input,callback,progressObj){
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function changePixel(r, g, b, a){
var val = options.adjustment || 0.2;
r = Math.pow(r / 255, val) * 255;
g = Math.pow(g / 255, val) * 255;
b = Math.pow(b / 255, val) * 255;
return [r , g, b, a];
}
function output(image,datauri,mimetype){
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
});
}
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": "Gamma Correction",
"description": "Apply gamma correction on the image <a href='https://en.wikipedia.org/wiki/Gamma_correction'>Read more</a>",
"inputs": {
"adjustment": {
"type": "float",
"desc": "gamma correction (inverse of actual gamma factor) for the new image",
"default": 0.2
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -1,5 +1,6 @@
{
"name": "Gradient",
"description": "Gives a gradient of the image",
"inputs": {}
"inputs": {},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -0,0 +1,93 @@
/*
* Calculates the histogram of the image
*/
module.exports = function Channel(options, UI) {
var output;
function draw(input, callback, progressObj) {
options.gradient = options.gradient || "true";
options.gradient = JSON.parse(options.gradient);
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this, hist = new Array(256).fill(0);
function changePixel(r, g, b, a) {
let pixVal = Math.round((r + g + b) / 3);
hist[pixVal]++;
return [r, g, b, a];
}
function extraManipulation(pixels) {
// if (!options.inBrowser)
// require('fs').writeFileSync('./output/histo.txt', hist.reduce((tot, cur, idx) => `${tot}\n${idx} : ${cur}`, ``));
var newarray = new Uint8Array(4 * 256 * 256);
pixels.data = newarray;
pixels.shape = [256, 256, 4];
pixels.stride[1] = 4 * 256;
for (let x = 0; x < 256; x++) {
for (let y = 0; y < 256; y++) {
pixels.set(x, y, 0, 255);
pixels.set(x, y, 1, 255);
pixels.set(x, y, 2, 255);
pixels.set(x, y, 3, 255);
}
}
let startY = options.gradient ? 10 : 0;
if (options.gradient) {
for (let x = 0; x < 256; x++) {
for (let y = 0; y < 10; y++) {
pixels.set(x, 255 - y, 0, x);
pixels.set(x, 255 - y, 1, x);
pixels.set(x, 255 - y, 2, x);
}
}
}
let convfactor = (256 - startY) / Math.max(...hist);
for (let x = 0; x < 256; x++) {
let pixCount = Math.round(convfactor * hist[x]);
for (let y = startY; y < pixCount; y++) {
pixels.set(x, 255 - y, 0, 204);
pixels.set(x, 255 - y, 1, 255);
pixels.set(x, 255 - y, 2, 153);
}
}
return pixels;
}
function output(image, datauri, mimetype) {
// This output is accesible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
return {
options: options,
//setup: setup, // optional
draw: draw,
output: output,
UI: UI
}
}

View File

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

View File

@@ -0,0 +1,16 @@
{
"name": "Histogram",
"description": "Calculates the histogram for the image",
"inputs": {
"gradient": {
"type": "select",
"desc": "Toggle the gradient along x-axis",
"default": "true",
"values": [
"true",
"false"
]
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -8,5 +8,6 @@
"desc": "URL of image to import",
"default": "./images/monarch.png"
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -2,5 +2,6 @@
"name": "Invert",
"description": "Inverts the image.",
"inputs": {
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -17,7 +17,10 @@ module.exports = function CropModuleUi(step, ui) {
var offset = $(this).offset();
var xPos = e.pageX - offset.left;
var yPos = e.pageY - offset.top;
ndviImage[0].title = "NDVI: " + canvas.getContext('2d').getImageData(xPos, yPos, 1, 1).data[0];
var ndvi = canvas.getContext('2d').getImageData(xPos, yPos, 1, 1).data[0];
ndvi = ndvi/127.5 - 1 ;
ndvi = ndvi.toFixed(2);
ndviImage[0].title = "NDVI: " + ndvi;
});
}
// step.imgSelector is not defined, imgElement is:

View File

@@ -8,5 +8,6 @@
"default": "red",
"values": ["red", "blue"]
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -2,5 +2,6 @@
"name": "NDVI-Colormap",
"description": "Sequentially Applies NDVI and Colormap steps",
"inputs": {},
"length": 2
"length": 2,
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -17,5 +17,6 @@
"desc": "offset to the output of the step on which the output of the last step is overlayed",
"default": -2
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -0,0 +1,71 @@
/*
* Resize the image by given percentage value
*/
module.exports = function Resize(options, UI) {
var output;
function draw(input, callback, progressObj) {
options.resize = options.resize || "125%";
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var imagejs = require('imagejs');
function changePixel(r, g, b, a) {
return [r, g, b, a]
}
function extraManipulation(pixels) {
// value above 100% scales up, and below 100% scales down
var resize_value = parseInt(options.resize.slice(0, -1));
var new_width,
new_height;
new_width = Math.round(pixels.shape[0] * (resize_value / 100));
new_height = Math.round(pixels.shape[1] * (resize_value / 100));
var bitmap = new imagejs.Bitmap({width: pixels.shape[0], height: pixels.shape[1]});
bitmap._data.data = pixels.data;
var resized = bitmap.resize({
width: new_width, height: new_height,
algorithm: "bicubicInterpolation"
});
pixels.data = resized._data.data;
pixels.shape = [new_width,new_height,4];
pixels.stride[1] = 4 * new_width;
return pixels;
}
function output(image, datauri, mimetype) {
// This output is accesible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

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

View File

@@ -0,0 +1,12 @@
{
"name": "Resize",
"description": "Resize image by given percentage value",
"inputs": {
"resize": {
"type": "string",
"desc": "Percentage value of the resize",
"default": "125%"
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -0,0 +1,62 @@
/*
* Rotates image
*/
module.exports = function Rotate(options, UI) {
var output;
function draw(input, callback, progressObj) {
options.rotate = parseInt(options.rotate) || 0;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var imagejs = require('imagejs');
function changePixel(r, g, b, a) {
return [r, g, b, a]
}
function extraManipulation(pixels) {
var rotate_value = (options.rotate)%360;
if(rotate_value%360 == 0)
return pixels;
var bitmap = new imagejs.Bitmap({width: pixels.shape[0], height: pixels.shape[1]});
bitmap._data.data = pixels.data;
var rotated = bitmap.rotate({
degrees: rotate_value,
});
pixels.data = rotated._data.data;
return pixels;
}
function output(image, datauri, mimetype) {
// This output is accesible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

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

View File

@@ -0,0 +1,12 @@
{
"name": "Rotate",
"description": "Rotates image by specified degrees",
"inputs": {
"rotate": {
"type": "integer",
"desc": "Angular value for rotation in degrees",
"default": 0
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -7,5 +7,6 @@
"desc": "saturation for the new image between 0 and 2, 0 being black and white and 2 being highly saturated",
"default": 0
}
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md"
}

View File

@@ -5,9 +5,11 @@ function setInputStepInit() {
var dropzone = $(options.dropZoneSelector);
var fileInput = $(options.fileInputSelector);
var takePhoto = $(options.takePhotoSelector);
var onLoad = options.onLoad;
var onTakePhoto = options.onTakePhoto;
var reader = new FileReader();
function handleFile(e) {
@@ -25,8 +27,53 @@ function setInputStepInit() {
reader.readAsDataURL(file);
}
function runVideo(){
/* event handler for Take-Photo */
document.getElementById('video').style.display='inline';
document.getElementById('capture').style.display='inline';
document.getElementById('close').style.display='inline';
var video = document.getElementById('video');
canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
vendorUrl = window.URL || window.webkitURL;
navigator.getMedia = navigator.getUserMedia || navigator.wekitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.getMedia({
video: true,
audio: false
}, function(stream){ // success callback
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
};
document.getElementById('close').addEventListener('click', function () {
stopStream(stream);
});
}, function(error){ // error
console.log("error");
});
document.getElementById('capture').addEventListener('click', function(stream){
context.drawImage(video, 0, 0, 400, 300);
options.onTakePhoto(canvas.toDataURL());
});
function stopStream(stream) {
stream.getVideoTracks().forEach(function (track) {
track.stop();
});
document.getElementById('video').style.display='none';
document.getElementById('capture').style.display='none';
document.getElementById('close').style.display='none';
}
}
fileInput.on('change', handleFile);
takePhoto.on('click', runVideo);
dropzone[0].addEventListener('drop', handleFile, false);

View File

@@ -184,10 +184,22 @@ test('getStep(offset) returns the step at offset distance relative to current st
});
test('toCliString() returns the CLI command for the sequence', function(t) {
t.deepEqual(sequencer.toCliString(), `sequencer -i [PATH] -s "channel channel channel channel channel invert blend" -d '{"channel":"green"}'`, "works correctly");
t.deepEqual(sequencer.toCliString(), `sequencer -i [PATH] -s "channel channel channel channel channel invert blend" -d '{"channel":"green","offset":-2}'`, "works correctly");
t.end();
});
test('blend returns different output depending on the set offset', function(t) {
sequencer.addSteps('test', 'invert', {});
sequencer.addSteps('test', 'invert', {});
sequencer.addSteps('test', 'blend', {});
// because we've added blend before, so instead of -3 we set it to -4
sequencer.addSteps('test', 'blend', {'offset': -4});
sequencer.run({ mode: 'test' }, function(out) {
t.notStrictEqual(out, sequencer.images.test.steps[sequencer.images.test.steps.length - 2].output.src, 'different offsets give different output');
t.end();
});
});
test('replaceImage returns false in NodeJS', function(t) {
var returnvalue = (sequencer.options.inBrowser) ? false : sequencer.replaceImage("#selector", "test");
t.equal(returnvalue, false, "It does.");

View File

@@ -8,8 +8,8 @@ test('toString() and stepToString() return the step/steps in string format', fun
sequencer.loadImages('image1', red);
sequencer.addSteps('channel');
sequencer.addSteps('invert');
t.equal(sequencer.toString(), "channel{channel:green},invert{}", "toString works");
t.equal(sequencer.stepToString(sequencer.steps[1]), "channel{channel:green}", "stepToString works");
t.equal(sequencer.toString(), "channel{},invert{}", "toString works");
t.equal(sequencer.stepToString(sequencer.steps[1]), "channel{}", "stepToString works");
t.end();
});
@@ -36,7 +36,7 @@ test('stringToJSON() and stringToJSONstep() return the step/steps from a string
test('toJSON() returns the right sequence of steps', function(t) {
t.deepEqual(sequencer.toJSON(), [
{ name: 'channel', options: { channel: 'green' } },
{ name: 'channel', options: {} },
{ name: 'invert', options: {} }
]);
t.end();
@@ -44,7 +44,7 @@ test('toJSON() returns the right sequence of steps', function(t) {
test('importString() imports a string of steps into the sequencer', function(t) {
sequencer.importString('brightness{brightness:50},invert');
t.equal(sequencer.toString(), "channel{channel:green},invert{},brightness{brightness:50},invert{}");
t.equal(sequencer.toString(), "channel{},invert{},brightness{brightness:50},invert{}");
t.end();
});
@@ -52,7 +52,7 @@ test('importJSON() imports a JSON array of steps into the sequencer', function(t
sequencer.importJSON([
{ name: 'blur', options: {} }
]);
t.equal(sequencer.toString(), "channel{channel:green},invert{},brightness{brightness:50},invert{},blur{blur:2}")
t.equal(sequencer.toString(), "channel{},invert{},brightness{brightness:50},invert{},blur{}")
t.end();
});

5979
yarn.lock Normal file

File diff suppressed because it is too large Load Diff