Compare commits

...

243 Commits

Author SHA1 Message Date
Jeffrey Warren
3bbe6fa6dc Merge branch 'main' into HarshKhandeparkar-patch-3 2020-01-28 13:03:47 -05:00
dependabot-preview[bot]
8483c07847 Bump lint-staged from 9.5.0 to 10.0.3
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 9.5.0 to 10.0.3.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v9.5.0...v10.0.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-28 17:30:21 +00:00
Rishabh Shukla
ceff43a502 Merge branch 'main' into HarshKhandeparkar-patch-3 2020-01-28 22:32:27 +05:30
dependabot-preview[bot]
4bba811848 Bump @babel/plugin-syntax-object-rest-spread from 7.7.4 to 7.8.3
Bumps [@babel/plugin-syntax-object-rest-spread](https://github.com/babel/babel) from 7.7.4 to 7.8.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.7.4...v7.8.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-28 16:52:49 +00:00
Harsh Khandeparkar
bb4e3162f9 Merge branch 'main' into HarshKhandeparkar-patch-3 2020-01-28 21:32:06 +05:30
Naman Aggarwal
166a0d894c Adding Test modules for GIF's (#1530)
* Test for GIF

* some cleanup

* Some cleanup

* Some code cleanup

* cleanup

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
Co-authored-by: Rishabh Shukla <42492389+blurry-x-face@users.noreply.github.com>
Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
2020-01-28 11:01:41 -05:00
Harsh Khandeparkar
64c23bee31 Update package.json 2020-01-28 21:31:24 +05:30
Harsh Khandeparkar
de4a2cb50f Fix typo 2020-01-28 21:25:37 +05:30
Naman Aggarwal
3ffea1f5e9 [FIXED]Draw rectangle's rectangle shinking down with every frame in gif's (#1535)
* Fix

* .

Co-authored-by: Rishabh Shukla <42492389+blurry-x-face@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-28 10:52:40 -05:00
Shazeb Ata
79472baec4 Clear step (#1386)
* Added test clear_step

* Updated clear step test

* Changed name of clear step

* Changed name of clear step

* Added delete step

* Added Linebreaks

* Added clear and delete step

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-27 17:40:22 -05:00
dependabot-preview[bot]
70003521c6 Bump gpu.js from 2.6.2 to 2.6.6
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.6.2 to 2.6.6.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-27 22:24:36 +00:00
dependabot-preview[bot]
f6d53163b9 Bump tape from 4.12.1 to 4.13.0 (#1449) 2020-01-22 17:22:02 +00:00
dependabot-preview[bot]
19ae9262f2 Bump jest from 24.9.0 to 25.1.0 (#1556)
Bumps [jest](https://github.com/facebook/jest) from 24.9.0 to 25.1.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/compare/v24.9.0...v25.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-22 12:09:00 -05:00
Ove Sundal
2378a67895 remove redundant function (#1532)
Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-22 11:31:06 -05:00
dependabot-preview[bot]
ecaa3ecd13 Bump @babel/plugin-proposal-object-rest-spread from 7.7.7 to 7.8.3 (#1494) 2020-01-21 22:05:49 +00:00
Rishabh Shukla
2cd728b54c Fix minify Module (#1512)
* Fix minify Module

* fix minify module
2020-01-21 16:25:34 -05:00
Naman Aggarwal
40dc23bedd [FIXED] travis test not failing when module test fails (#1550)
* travis test error fix

* Updated PULL_REQUEST template

* code cleanup

* ..

* some minor changes

* some minor changes

* Trying to restrat the build

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
Co-authored-by: Rishabh Shukla <42492389+blurry-x-face@users.noreply.github.com>
2020-01-21 16:22:46 -05:00
Rishabh Shukla
8b18d2d780 fix extraManipulation (#1551)
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-21 14:53:32 -05:00
dependabot-preview[bot]
b6d07c035f Bump gpu.js from 2.4.8 to 2.6.2 (#1544)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.4.8 to 2.6.2.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-21 14:32:42 -05:00
Arghadip Chakraborty
7c63bb53a4 Fixed issue #1528: UI Learn More Link Should Lead to the README (#1539)
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-21 12:58:54 -05:00
Olusola
5b92ba5dc5 Fixed paint bucket fill color error (#1519)
* fillColor getting correct color

* Fixed #1488

Corrected the multiplier from 256 to 255

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-21 12:44:06 -05:00
Naman Aggarwal
2b3e5a2915 Added options startingX and startingY in Add-Qr Module (#1520)
* Added options startingX and startingY in Add-Qr Module

* requeste changes

* Fixing Qr Code at the end when not fit in the image

Co-authored-by: Rishabh Shukla <42492389+blurry-x-face@users.noreply.github.com>
2020-01-18 19:48:52 -05:00
Shazeb Ata
2fba0d2074 Added url for canvas (#1533) 2020-01-18 10:47:34 -05:00
Vladimir Mikulic
afc903192c FIX: Histogram module selected value not displayed (#1510)
The histogram module values are "true" and "false".
jQuery would coerce them to Boolean true and false instead of String
"true" and "false" which would result in empty value being displayed.

Resolves #1295
2020-01-17 16:44:05 -05:00
Naman Aggarwal
c703836198 Draw Rectangle default values (#1443)
Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-17 16:43:09 -05:00
Rishabh Shukla
c22c6c70d0 Adding easier to use interface for blend module and different blend modes (#1453)
* Bump data-uri-to-buffer from 2.0.1 to 3.0.0

Bumps [data-uri-to-buffer](https://github.com/TooTallNate/node-data-uri-to-buffer) from 2.0.1 to 3.0.0.
- [Release notes](https://github.com/TooTallNate/node-data-uri-to-buffer/releases)
- [Commits](https://github.com/TooTallNate/node-data-uri-to-buffer/compare/2.0.1...3.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

* add blend modes

* fix toCliString test

* add docs link for blend modes

* fix crop module

* undo last commit

* minor change

* change default to custom

* add docs link

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-17 15:47:47 -05:00
Rishabh Shukla
1fa8c6b8c1 Refactoring isGIF() as a utility function (#1511)
* refactor isGif

* refactor isGif

* fix isGif func

* Update isGif.js

* Update isGif.js
2020-01-17 15:27:05 -05:00
Rishabh Shukla
89fb3585ac Tests for checking image change upon change in options (#1490)
* add test for change in option for colormap

* add test for change in option for colormap

* add comments

* add few tests

* Add options change test for 14 more modules

* add test

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
2020-01-17 15:00:13 -05:00
keshav234156
d1b9b8becc Fixes disabling of clicking after crop is deleted and added test for the cropUI (#1481)
* crop-ui

* crop-ui

* Added test

* Adding test

* improving comments

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 17:18:34 -05:00
keshav234156
1a0f4d4042 Blend new (#1499)
* fixes blend

* change info.json

* improve readablity and comments

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 17:00:13 -05:00
Naman Aggarwal
9a2f4c1d19 Fix for Dynamic module (#1451)
* ..

* fix Dynamic Module

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 16:26:52 -05:00
Rishabh Shukla
b8c7df760a Add ranged input for overlay module. (#1459)
* add ranged input for overlay module

* fix bug

* change input type to integer

* Add tests

* Add tests

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 15:07:35 -05:00
Naman Aggarwal
2736b481a4 Added aspect ratio module (#1454)
* Base file

* Added aspect ratio module

* Compatiable with Experimental GIF Manipulation

* some refactoring

* Changed the name from aspect-ratio to Constrained Crop

* cleanup

* Changes requested

* Added test module

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 14:40:30 -05:00
Naman Aggarwal
5ae545904d Fix Average module editing the UI from the source (#1469)
* Fix Average module editing the UI from the source

* requested changes

* Delete demo.js

* cleanup

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 14:16:51 -05:00
Rishabh Shukla
b0ddea012a Add test for import image (#1513)
* add test for import image

* add test for import image

* remove log

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 13:55:43 -05:00
Rishabh Shukla
94caefa2cd Contrast module now uses changePixel Method (#1482)
* contrast module uses changePixel Method

* change if block to Math function

* fix bug

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 12:47:55 -05:00
Oktawian Jurkiewicz
45c54bb9af crop default options changes (#1487)
Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 12:29:58 -05:00
Rishabh Shukla
c1c682c0a6 Fix color picker bug (#1465)
* fix color picker bug

* minor change

* change step to stepAll

* add test

* add comments to colorpicker UI test

* add space

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-16 12:23:36 -05:00
Shazeb Ata
423422a61f Remove Multiple Downloads (#1428)
* Removed event listeners

* Added Unbind

* Removed Event Listener

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-15 18:56:06 -05:00
Sanjana Nayar
cded94509b Updated defaultHtmlStepUi.js to add docs link in UI (#1506) 2020-01-15 16:22:32 -05:00
Rishabh Shukla
bfff7e7b99 fix crop module (#1463) 2020-01-13 17:36:53 -05:00
dependabot-preview[bot]
12c422a07b Bump gpu.js from 2.4.7 to 2.4.8
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.4.7 to 2.4.8.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/compare/2.4.7...2.4.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-12 17:28:12 +00:00
Harsh Khandeparkar
ea2069d7f6 [GCI] Experimental GIF Manipulation (#1404)
* wasmSuccess

* modules use wasmSuccess

* modules use wasmSuccess

* add the tooltip

* add GIF support

* fix imageDImensions function

* fix inputCoordinatesParser function

* show correct image dimensions

* show correct image dimensions

* don't allow save as PDF for GIFs

* fix QR module

* fix BlobAnalysis

* fix Blur

* fix Colorbar

* fix Crop

* fix crop defaults

* fix DrawRectangle

* fix EdgeDetect

* fix FlipImage

* fix Gradient

* fix Invert

* fix Overlay

* fix Resize

* fix Rotate

* fix TextOverlay

* fix parse input test

* make GIFs work in nodejs

* sample GIF test

* small change

* cleanup

* cleanup

* cleanup

* small fix

* small change

* handle errors

* proper error handling and fix tests

* cleanup

* try a fix

* try another fix

* fix module benchmarks

* try more fixes

* revert

* try fixing the tests

* fix overlay test

* add the gif tests

* remove unnecessary changes

* fix tests

* whoops

* add some docs

* inBrowser

* fix all module tests

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-11 12:05:10 -05:00
dependabot-preview[bot]
61b2d75383 Bump data-uri-to-buffer from 2.0.1 to 3.0.0 (#1437)
Bumps [data-uri-to-buffer](https://github.com/TooTallNate/node-data-uri-to-buffer) from 2.0.1 to 3.0.0.
- [Release notes](https://github.com/TooTallNate/node-data-uri-to-buffer/releases)
- [Commits](https://github.com/TooTallNate/node-data-uri-to-buffer/compare/2.0.1...3.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-09 16:05:56 -05:00
dependabot-preview[bot]
20f7d7ca2e Bump jsdom from 15.1.1 to 15.2.1 (#1438)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 15.1.1 to 15.2.1.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/15.1.1...15.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-08 18:16:05 -05:00
dependabot-preview[bot]
9ef5d38084 Bump @babel/plugin-syntax-object-rest-spread from 7.2.0 to 7.7.4 (#1444)
Bumps [@babel/plugin-syntax-object-rest-spread](https://github.com/babel/babel) from 7.2.0 to 7.7.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.2.0...v7.7.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-08 16:56:41 -05:00
Rishabh Shukla
c453bbbd92 Fix Meta modules and add inputs to ndvi-colormap (#1432)
* fix meta module bug

* fix create meta module and add inputs to ndvi-colormap

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-08 16:14:50 -05:00
dependabot-preview[bot]
448848b2d1 Bump gpu.js from 2.4.6 to 2.4.7 (#1434)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.4.6 to 2.4.7.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/compare/2.4.6...2.4.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-07 17:03:13 -05:00
dependabot-preview[bot]
9822da6a78 Bump ndarray from 1.0.18 to 1.0.19 (#1436)
Bumps [ndarray](https://github.com/mikolalysenko/ndarray) from 1.0.18 to 1.0.19.
- [Release notes](https://github.com/mikolalysenko/ndarray/releases)
- [Commits](https://github.com/mikolalysenko/ndarray/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-07 16:39:32 -05:00
Naman Aggarwal
d215b43a09 Fixing defaults in various modules (#1441)
* Fix AddQr

* Fix Threshold

* Fix ReplaceColor Modulr

* Fix Overlay Module

* Fix FlipImage Module

* fix Colorbar Module

* Fix colormap module

* fix overlay

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-07 16:18:45 -05:00
anthony-zhou
00ed0f148d Expand out offline app features for smoother cache clearing and version tracking (#1384)
* Add version number to bottom

* Get latest version number from GitHub

* Create versionManagement.js

Fetching the latest and local version number is now done through versionManagement.js

* Add popup to prompt for refresh when a new version is available

A new version is available whenever the sw.js file is changed.

* Add version number fixed in top right corner

* Fix Codeclimate issues

* Update versionManagement.js

* Update versionManagement.js

* Make update prompt appear at front of page

Changed z-index

* Delete unecessary code

* Create task to automatically update sw.js

Used grunt-text-replace

* Uninstall semver

* Add replace task to serve and production tasks

* Update demo.js

Make version statements more descriptive.

* Update versionManagement.js

Remove unused versionCompare function

* Change URL for getting latest version

Changed the URL for getting the latest NPM version to be based on the package.json file's attribute for "homepage".

* Update index.html

* Update demo.css

* Added explanatory comments

* Update versionManagement.js

* Update versionManagement.js

* Updates for readability

Changed single-line comments to multiline comments.

* Update versionManagement.js

* Update versionManagement.js

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-07 14:56:34 -05:00
dependabot-preview[bot]
ab793bcf4e Bump commander from 4.0.1 to 4.1.0 (#1435)
Bumps [commander](https://github.com/tj/commander.js) from 4.0.1 to 4.1.0.
- [Release notes](https://github.com/tj/commander.js/releases)
- [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tj/commander.js/compare/4.0.1...v4.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-07 12:02:23 -05:00
dependabot-preview[bot]
865e4bc268 Bump jasmine from 3.4.0 to 3.5.0 (#1433)
Bumps [jasmine](https://github.com/jasmine/jasmine-npm) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/jasmine/jasmine-npm/releases)
- [Commits](https://github.com/jasmine/jasmine-npm/compare/v3.4.0...v3.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-07 11:35:53 -05:00
Rishabh Shukla
6420bb05e8 fix meta module bug (#1426) 2020-01-06 16:26:35 -05:00
dependabot-preview[bot]
79d395bf24 Bump ora from 3.4.0 to 4.0.3 (#1415)
Bumps [ora](https://github.com/sindresorhus/ora) from 3.4.0 to 4.0.3.
- [Release notes](https://github.com/sindresorhus/ora/releases)
- [Commits](https://github.com/sindresorhus/ora/compare/v3.4.0...v4.0.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 13:59:57 -05:00
dependabot-preview[bot]
17ea0c8b44 Bump compressorjs from 1.0.5 to 1.0.6 (#1414)
Bumps [compressorjs](https://github.com/fengyuanchen/compressorjs) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/fengyuanchen/compressorjs/releases)
- [Changelog](https://github.com/fengyuanchen/compressorjs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/fengyuanchen/compressorjs/compare/v1.0.5...v1.0.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-06 13:48:26 -05:00
Shazeb Ata
81ef136b20 Change dimension upon loading an Image through UI (#1395)
* Change dimension upon loading an Image

* Refactored changedimension

* Refactored changedimension

* Added Comments

* Added description

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-06 13:38:48 -05:00
dependabot-preview[bot]
639eaf644f Bump readline-sync from 1.4.9 to 1.4.10 (#1206)
Bumps [readline-sync](https://github.com/anseki/readline-sync) from 1.4.9 to 1.4.10.
- [Release notes](https://github.com/anseki/readline-sync/releases)
- [Commits](https://github.com/anseki/readline-sync/compare/1.4.9...1.4.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 13:31:48 -05:00
dependabot-preview[bot]
a5da2ebc24 Bump @babel/plugin-proposal-object-rest-spread from 7.4.3 to 7.7.7 (#1372)
Bumps [@babel/plugin-proposal-object-rest-spread](https://github.com/babel/babel) from 7.4.3 to 7.7.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.4.3...v7.7.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 13:00:36 -05:00
dependabot-preview[bot]
6654e2a3f7 Bump jest-puppeteer from 4.3.0 to 4.4.0 (#1424)
Bumps [jest-puppeteer](https://github.com/smooth-code/jest-puppeteer) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/smooth-code/jest-puppeteer/releases)
- [Changelog](https://github.com/smooth-code/jest-puppeteer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/smooth-code/jest-puppeteer/compare/v4.3.0...v4.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-06 10:34:10 -05:00
dependabot-preview[bot]
7473a256e9 Bump looks-same from 7.2.1 to 7.2.2 (#1423)
Bumps [looks-same](https://github.com/gemini-testing/looks-same) from 7.2.1 to 7.2.2.
- [Release notes](https://github.com/gemini-testing/looks-same/releases)
- [Changelog](https://github.com/gemini-testing/looks-same/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gemini-testing/looks-same/compare/v7.2.1...v7.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 10:07:51 -05:00
dependabot-preview[bot]
76e5eb85ce Bump imagemin from 7.0.0 to 7.0.1 (#1425)
Bumps [imagemin](https://github.com/imagemin/imagemin) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/imagemin/imagemin/releases)
- [Commits](https://github.com/imagemin/imagemin/compare/v7.0.0...v7.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-06 08:50:43 -05:00
Sparks
a8b6aac5b3 Update defaultHtmlStepUi.js (#1388)
Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-03 14:19:53 -05:00
dependabot-preview[bot]
d3b49ff187 Bump jasmine-core from 3.4.0 to 3.5.0 (#1408)
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/master/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v3.4.0...v3.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-03 14:16:13 -05:00
dependabot-preview[bot]
cd41d1e8d9 Bump qrcode from 1.4.1 to 1.4.4 (#1416)
Bumps [qrcode](https://github.com/soldair/node-qrcode) from 1.4.1 to 1.4.4.
- [Release notes](https://github.com/soldair/node-qrcode/releases)
- [Changelog](https://github.com/soldair/node-qrcode/blob/master/CHANGELOG.md)
- [Commits](https://github.com/soldair/node-qrcode/compare/v1.4.1...v1.4.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-03 13:01:26 -05:00
dependabot-preview[bot]
33d601fb58 Bump gpu.js from 2.3.1 to 2.4.6 (#1417)
Bumps [gpu.js](https://github.com/gpujs/gpu.js) from 2.3.1 to 2.4.6.
- [Release notes](https://github.com/gpujs/gpu.js/releases)
- [Commits](https://github.com/gpujs/gpu.js/compare/2.3.1...2.4.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-03 12:20:20 -05:00
dependabot-preview[bot]
4e96b7fb55 Bump commander from 3.0.1 to 4.0.1 (#1406)
Bumps [commander](https://github.com/tj/commander.js) from 3.0.1 to 4.0.1.
- [Release notes](https://github.com/tj/commander.js/releases)
- [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tj/commander.js/compare/v3.0.1...4.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-02 17:48:26 -05:00
Shazeb Ata
12a78c5745 Created a new object instead of passing by reference (#1379)
* Creating copy of object

* Creating copy of object

* Create new object

Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-02 15:46:50 -05:00
Naman Aggarwal
6ffba532c3 Fixed bug => Color Temperature showing black image when set on default. (#1401)
* fixed issue #1392

* required changes fix

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-02 13:43:03 -05:00
keshav234156
7905cc9252 fixing module test (#1410) 2020-01-02 12:53:50 -05:00
dependabot-preview[bot]
fd138ffb47 Bump tape from 4.11.0 to 4.12.1 (#1405)
Bumps [tape](https://github.com/substack/tape) from 4.11.0 to 4.12.1.
- [Release notes](https://github.com/substack/tape/releases)
- [Commits](https://github.com/substack/tape/compare/v4.11.0...v4.12.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-02 11:36:50 -05:00
dependabot-preview[bot]
0ceb354c56 Bump browserify from 16.2.3 to 16.5.0 (#1207)
Bumps [browserify](https://github.com/browserify/browserify) from 16.2.3 to 16.5.0.
- [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/v16.2.3...v16.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-02 08:46:06 -05:00
dependabot-preview[bot]
48c65d3c64 Bump buffer from 5.4.2 to 5.4.3 (#1254)
Bumps [buffer](https://github.com/feross/buffer) from 5.4.2 to 5.4.3.
- [Release notes](https://github.com/feross/buffer/releases)
- [Commits](https://github.com/feross/buffer/compare/v5.4.2...v5.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-01 19:52:03 -05:00
dependabot-preview[bot]
4539f264b3 Bump lint-staged from 9.2.1 to 9.5.0 (#1308)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 9.2.1 to 9.5.0.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v9.2.1...v9.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-01 18:47:36 -05:00
dependabot-preview[bot]
b43cfc522f Bump jsqr from 1.1.1 to 1.2.0 (#1214)
Bumps [jsqr](https://github.com/cozmo/jsQR) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/cozmo/jsQR/releases)
- [Commits](https://github.com/cozmo/jsQR/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-01 16:37:57 -05:00
dependabot-preview[bot]
8d38088914 [Security] Bump handlebars from 4.1.2 to 4.5.3 (#1397)
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.1.2 to 4.5.3. **This update includes a security fix.**
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.1.2...v4.5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-01 16:24:59 -05:00
Naman Aggarwal
772a56989f fix issue 1394 (#1399) 2020-01-01 15:04:53 -05:00
Srihari
13270a668c fix case (#1387) 2020-01-01 14:47:20 -05:00
Isaac Miti
cb47bf2341 Change the button to blue from green (#1380) 2020-01-01 14:41:18 -05:00
dependabot-preview[bot]
4097361599 Bump @babel/core from 7.5.5 to 7.7.7 (#1371)
Bumps [@babel/core](https://github.com/babel/babel) from 7.5.5 to 7.7.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.5.5...v7.7.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-01 13:46:58 -05:00
Harsh Khandeparkar
0bf178022d standardise comments (#1347) 2020-01-01 13:32:34 -05:00
Harsh Khandeparkar
51ce1c52f4 [GCI] Standardised Edge Detect module code comments (#1346)
* standardise comments

* more fixes

* fix

* Apply suggestions from code review

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-01 12:51:53 -05:00
Harsh Khandeparkar
1af9655bca [GCI] Standardised UI code comments (#1345)
* standardise comments

* fix some stuff

* A googol issues fixed

* Update examples/demo.js

* .

* .

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-01 12:39:17 -05:00
Harsh Khandeparkar
1db650cdd7 [GCI] Standardised UI util code comments (#1344)
* standardise comments

* small fix

Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
2020-01-01 12:26:41 -05:00
Veer Gadodia
d83703cf02 Update README.md (#1326) 2020-01-01 11:38:14 -05:00
Harsh Khandeparkar
c370a8b4ea Install GPU.js v2.3.1 (#1374)
* fix: Upgrade GPU.js to v2.3.0 and handle browserifying it

* fix?

* fiiix

* fix

* fix tests browserify

Co-authored-by: Robert Plummer <robertleeplummerjr@gmail.com>
2019-12-21 11:59:11 -05:00
Harsh Khandeparkar
6476b8d698 [GCI] Added Lightning Bolt for WASM accelerated modules (#1365)
* wasmSuccess

* modules use wasmSuccess

* modules use wasmSuccess

* add the tooltip
2019-12-19 18:45:42 -05:00
keshav234156
b7d5a98cdb seprated the title and radio group file (#1367) 2019-12-18 23:28:37 -05:00
Đoàn Ngọc Huân
2e94f20875 Update demo.css (#1368)
https://github.com/publiclab/image-sequencer/issues/1314
2019-12-18 13:30:18 -05:00
keshav234156
ed0f76c78d test for add step (#1366)
* test for add step

* adding relative path and testing with npm run test-ui(for testing in travis but it will abort previous test-ui)

* checking index.html

* checking index.html

* changing test location and reverting index.html

* remove console.log
2019-12-17 19:37:27 -05:00
Harsh Khandeparkar
4a86abbafd [GCI] InsertStep functionality added for loadImage step (#1360)
* add markuo

* add markupfix insertPreview

* fix insertPreview test

* make the new insertPreview work

* fix disabled

* small fix

* fix comments

* remove console log

* fix enabling/disabling of insert-step btn
2019-12-16 13:42:15 -05:00
Harsh Khandeparkar
426733f625 [GCI] Standardised Core code comments (#1343)
* standardise comments

* fix

* fixes

* add docs links

* remove extra .

* ., this and other changes
2019-12-16 12:56:03 -05:00
Harsh Khandeparkar
0ce2cf9492 [GCI] Standardised Blob Analysis module comments (#1351)
* fix comments

* Update src/modules/BlobAnalysis/BlobAnalysis.js

Fix double image

* Update src/modules/BlobAnalysis/BlobAnalysis.js

* . fix
2019-12-16 12:47:25 -05:00
Ryan10145
3d4025fd93 Disables Take a Photo Button and File Chooser While Camera is Active (#1357)
* Disables Other Buttons While Camera is Active

* Remove dropzone-text id from ImportImage UI
2019-12-16 11:53:32 -05:00
Sparks
76575b567a Dropdown 'Select a Module' fix (#1352)
* Update demo.js

* Codeclimate

* Update demo.js

* Code comments

* Comments codestyle

* Update demo.js
2019-12-12 11:53:18 -05:00
keshav234156
86dca0400e Allow saving onto Publiclab.org (#1353)
* Allow saving onto Publiclab.org

* success to primary

* fixing merge conflictx
2019-12-11 15:20:03 -05:00
anthony-zhou
5421a80fb3 Add Save as PDF option (#1349)
* Add Save as PDF option

* Edit coments for consistency

Edits follow the JSDoc guidelines. Comments begin with a capital letter and end with a period.
2019-12-11 13:23:13 -05:00
Vladimir Mikulic
bb4fc5b691 FIX: Dragzone overlapping (#1333)
* FIX: Dragzone overlapping

Changes:
- inline styles moved from ../ImportImage/Ui.js to demo.css
- minor code improvements

The change was necessary because in the old UI dragzone was overlapping
an image.

Resolves #1294

* FIX: Improve commit #ead4b932

Changes:
- rollback .dropzone input style
- add styles to  .import-image-zone input element

* FIX:  .import-image-zone input element width

Changes:
-  max-width increased to 120% on import-image-zone input element

* FIX: .import-image-zone max-width

Changes:
- rollback .import-image-zone input max-width to fit-content
- increase .import-image-zone max-width from 230px to 250px

* FIX: .import-image-zone input element max-width

Changes:
 - max-width set to 100%
2019-12-10 11:07:43 -05:00
Ryan10145
d371a0f2e4 Add Missing Modules to Documentation (#1325) 2019-12-10 11:02:07 -05:00
keshav234156
2459e53fda Fixes unexpected behavior of step panel dropdown (#1328)
* Fixes  dropdown

* Update defaultHtmlStepUi.js

* Update intermediateHtmlStepUi.js
2019-12-09 17:59:14 -05:00
keshav234156
032971d269 Fixes window error in Average module.Commented the test that were affecting other modules (#1330) 2019-12-09 17:52:01 -05:00
anthony-zhou
510fd7a934 Make "Add Step" button blue (#1331)
Changed the button's class from "btn-success" to "btn-primary."
2019-12-09 17:18:19 -05:00
Sasha Boginsky
5c76cb4012 Update CODE_OF_CONDUCT.md (#1248)
update to reflect the updates on 
https://publiclab.org/conduct Aug 28 2019, and also standardize format to match LDI, Mk, etc.
2019-12-09 16:58:29 -05:00
Rishabh Shukla
f1c94fd788 Display width and height of image at each step (#1309) 2019-11-28 14:42:25 -05:00
dependabot-preview[bot]
89626838e3 [Security] Bump https-proxy-agent from 2.2.1 to 2.2.4 (#1301)
Bumps [https-proxy-agent](https://github.com/TooTallNate/node-https-proxy-agent) from 2.2.1 to 2.2.4. **This update includes security fixes.**
- [Release notes](https://github.com/TooTallNate/node-https-proxy-agent/releases)
- [Commits](https://github.com/TooTallNate/node-https-proxy-agent/compare/2.2.1...2.2.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-18 15:15:56 -05:00
VAIBHAV MATTA
cff82c998f Small Typo Error Corrected (#1278) 2019-10-29 22:45:14 +01:00
keshav234156
b1600af374 fixes insert-step functionality (#1266) 2019-10-28 19:21:43 +01:00
keshav234156
43e81c3847 fixes bugs in gamma-correction module (#1256)
* fixes gamma-correction module slider

* Update info.json
2019-10-07 12:03:00 -04:00
Samagra Gupta
44f5cb4e03 cursor change into pointer (#1259) 2019-10-01 14:23:19 -04:00
keshav234156
3eb741c6d9 rotate module (#1218)
* this PR solves the problem of clipping of the image while rotating

* a little clipping was still present .so made the changes

* Splitted into two files

* ommitted extra declared variables

* Update Module.js

* Update Rotate.js

* Update Rotate.js
2019-09-24 16:45:02 -04:00
duyquangnguyenhac
33f32251ec Document noise reduction module (#1189)
* Added documentation for noise reduction module

* Added fixed documentation for noise reduction module

* Update MODULES.md

* Minor Changes to Noise-Reduction description.

* Update docs/MODULES.md

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

* Move documentation to alphabetical order

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

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-18 09:20:59 -04:00
keshav234156
d782c147c5 fixes add-QR and color-picker in draw-rectangle,grid-overlay (#1250) 2019-09-11 15:28:02 -04:00
Devesh Kaushik
339df8768d Updated CONTRIBUTION.md (#1231)
* Update Contribution.md

As directed by rexagod

* Update Contribution.md

added libxext-dev

* Update CONTRIBUTING.md

Co-Authored-By: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
2019-09-11 11:18:44 -04:00
dependabot-preview[bot]
4a0207bc27 Bump buffer from 5.4.0 to 5.4.2 (#1246)
Bumps [buffer](https://github.com/feross/buffer) from 5.4.0 to 5.4.2.
- [Release notes](https://github.com/feross/buffer/releases)
- [Commits](https://github.com/feross/buffer/compare/v5.4.0...v5.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-07 10:52:00 -04:00
dependabot-preview[bot]
9ad6bde18e Bump husky from 2.3.0 to 3.0.5 (#1243)
Bumps [husky](https://github.com/typicode/husky) from 2.3.0 to 3.0.5.
- [Release notes](https://github.com/typicode/husky/releases)
- [Changelog](https://github.com/typicode/husky/blob/master/CHANGELOG.md)
- [Commits](https://github.com/typicode/husky/compare/v2.3.0...v3.0.5)

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

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-04 15:16:33 -04:00
dependabot-preview[bot]
256e1d65c7 [Security] Bump mixin-deep from 1.3.1 to 1.3.2 (#1234)
Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2. **This update includes a security fix.**
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-03 14:06:03 -04:00
dependabot-preview[bot]
bab7573f4a Bump commander from 2.19.0 to 3.0.1 (#1244)
Bumps [commander](https://github.com/tj/commander.js) from 2.19.0 to 3.0.1.
- [Release notes](https://github.com/tj/commander.js/releases)
- [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tj/commander.js/compare/v2.19.0...v3.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-03 13:58:19 -04:00
Jeffrey Warren
776cb42bd6 Revert extra test until complete 2019-09-01 16:14:52 -04:00
Jeffrey Warren
fb452f7788 add UI test for quick selector add step
re #1000
2019-09-01 16:09:49 -04:00
Tudor Anghelina
3741d679bd Update Module.js (#1090)
Added const $ = window.$; at line 19 inside extraManipulation(pixels)
2019-08-30 12:58:05 -04:00
Rishabh Shukla
1cc9fd1a50 Update Pull_Request.md (#1233)
* Update pull request template

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

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

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

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

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

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

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

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

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

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

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

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

* eslint fixes

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

* comment added

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

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

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

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

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

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

* text-overlay in node

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

* Add node modules

* corrected path

* Add browser func

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

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

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

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

dist update

Revert "dist update"

This reverts commit 9ee2a987e8f978961656ae8f71f6e6702bbbd30d.

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

* add dist

* add new func

* update itermediate

* changes

* fix gitignore

* use scopeQuery

* add mapHtmlTypes test

* scopeQuery tests added

* try something

* change

* fix stepui test

* Remove double quotes

* update new code

* refactor to spec

* fix link elems, add a new scopeQuery Method

* fixed undefined error

* fix everything

* getScope to scopeAll

* add new methods to CONTRIBUTING file
2019-07-01 11:32:11 -04:00
Slytherin
2c58edfe9a Temporary fix for insert-step btn not working (#1131)
* Temporary fix for insert-step btn not working

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

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

dist update

Revert "dist update"

This reverts commit 9ee2a987e8f978961656ae8f71f6e6702bbbd30d.

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

* add dist

* add new func

* update itermediate

* changes

* fix gitignore

* use scopeQuery

* add mapHtmlTypes test

* scopeQuery tests added

* try something

* change

* fix stepui test

* Remove double quotes

* update new code

* refactor to spec
2019-06-21 15:11:10 -04:00
jywarren
0eb3f263f9 version bump to v3.5.0 with WebAssembly acceleration 2019-06-21 12:15:51 -04:00
Slytherin
30659d4656 Using wasm to accelerate PixelManipulation.js (#1093)
* Add wasm code

* First working model

* Add PixelManipulation web assembly code to browser and node

* Tests corrected for modules

* Corrected test script

* Add wasm bechmarks

* Update Readme

* Applies toggling functionality and refactored PixelManipulation code

* Added documentation and corrected wasm toggling

* change noise reduction module to use wasm code

* Corrected formatting  and removed extra comments

* Add default wasm option and made README changes

* Fixed negative test timings

* combined benchmarks file

* Update benchmark.js

* Removed copies of wasm file and corrected test format

* Update package.json

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

* Added wasm file and removed redundant code

* Removed earlier benchmarks

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

* Solves memory leaks and blank lines

* Solves memory leaks and blank lines

* Added handler for node code

* Modify test script

* Modify test script

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

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

* added scripts from node_modules

* selector-all added and alpha removed for some modules

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

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

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

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

* update docs

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

* fix typo

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

* consistent spacing after comma

* comma styling config

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

* Remove ChangePixel Function
2019-06-13 13:09:13 -04:00
dependabot-preview[bot]
cfdb7e2606 Bump @babel/plugin-proposal-object-rest-spread from 7.4.3 to 7.4.4 (#1056)
Bumps [@babel/plugin-proposal-object-rest-spread](https://github.com/babel/babel) from 7.4.3 to 7.4.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.4.3...v7.4.4)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-06-12 15:49:40 -04:00
dependabot-preview[bot]
278016fb8f Bump husky from 2.3.0 to 2.4.1 (#1106)
Bumps [husky](https://github.com/typicode/husky) from 2.3.0 to 2.4.1.
- [Release notes](https://github.com/typicode/husky/releases)
- [Changelog](https://github.com/typicode/husky/blob/master/CHANGELOG.md)
- [Commits](https://github.com/typicode/husky/compare/v2.3.0...v2.4.1)

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

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

* added jasmine script

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

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-06-05 14:48:07 -04:00
dependabot-preview[bot]
d6bb1ba5b9 Bump @babel/core from 7.4.3 to 7.4.5 (#1071)
Bumps [@babel/core](https://github.com/babel/babel) from 7.4.3 to 7.4.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.4.3...v7.4.5)

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

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

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

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

* update canvas background color

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

* no node 6

* add average module tests

* edge-detect test added

* edge detect tests

* flip-image tests

* tint tests

* saturation tests

* gradient tests

* exposure tests

* draw-rectangle tests

* color-temperature tests

* convolution tests

* paint-bucket tests

* ndvi tests

* ndvi-colormap tests

* histogram tests

* crop tests

* gamma-correction tests

* dynamic tests

* colorbar tests

* webgl-distort tests

* fisheye-gl tests

* blend module tests

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

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

* add gpuUtils

* add gpuUtil convolve

* add convolution to edgeDetect

* bench it

* bench change

* newline

* pipeline

* revert edge-detect

* gpu accelerate gaussian blur

* edgeDetect use blur

* tweak values

* remove ndarray-gaussian-filter

* audit

* turn on previews

* remove oldPix

* fix travis

* Travis fix

* Try fixing travis

* Fix

* Retry

* tweaks

* convolution module on GPU

* use babelify

* trial

* remove logs

* Update .travis.yml

* Update .travis.yml

* bump version

* bump to rc.9

* rc.10

* rc.11

* Update package.json

* convolution fix

* unit test gpuUtils

* tests changed, fixed

* new fix

* more obvious parseFloat

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

* version bump for v3.1.1 bugfix

* --disable-setuid-sandbox

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

* Update gl-context.js

* ['--no-sandbox', '--disable-setuid-sandbox']
2019-04-30 14:41:41 -04:00
dependabot[bot]
8b110c241f Bump jsdom from 14.0.0 to 15.0.0 (#1037)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 14.0.0 to 15.0.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/14.0.0...15.0.0)

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

* Update examples/lib/defaultHtmlSequencerUi.js

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

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

* Tests

* Correct bounds

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

* Correct bounds

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

* Correct bounds

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

* Correct bounds

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

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

* possible map fix

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

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

* fixed the error

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

* WIP

* custom inputs for distort

* added test suite

* test fix and input parse

* test fix

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

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

* test fix

* parsing multiple input methods

* travis fix

* test cases

* requested changes made

* test fix

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

* string methods refactor

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

* Fixes crop functionality

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

* Added changes to the description of scopeQuery

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

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

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

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

* Update cache.js

* Create sw.js

* Delete sw.js
2019-04-15 12:38:39 -05:00
dependabot[bot]
fd981634fa Bump commander from 2.19.0 to 2.20.0 (#980)
Bumps [commander](https://github.com/tj/commander.js) from 2.19.0 to 2.20.0.
- [Release notes](https://github.com/tj/commander.js/releases)
- [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tj/commander.js/compare/v2.19.0...v2.20.0)

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

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

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

* added white balance and renamed temperature module

* import defaults

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

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

* now running gl using localhost fixes #216

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

* modularize api and fix tests

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

* finishing up

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

* add docs

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

* fixes

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

* fix benchmark.js

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

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

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

* Update examples/lib/intermediateHtmlStepUi.js

Suggested update

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

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

* add tests

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

* Re-added loadImages, deleted loadImage

* Left both loadImage and loadImages in

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

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

dist update

Revert "dist update"

This reverts commit 9ee2a987e8f978961656ae8f71f6e6702bbbd30d.

* fix insert step button

* add icon

* add dist

* use normal functions

* use normal functions

* no lag

* changes

* changes

* changes

* Update intermediateHtmlStepUi.js

* toggleDiv global

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

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

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

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-03-28 21:32:05 -04:00
MichaelLin250
a51644963a TRYING SO HARD TO FIX IT (#950) 2019-03-28 21:29:41 -04:00
350 changed files with 22781 additions and 7314 deletions

11
.codecov.yml Normal file
View File

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

1
.eslintignore Normal file
View File

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

36
.eslintrc.js Normal file
View File

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

View File

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

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

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

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

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

View File

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

View File

@@ -1,114 +1,11 @@
This document was copied from its home at https://publiclab.org/conduct on October 12, 2017. See that page if you would like to submit your concerns in a safe, completely anonymous way, and to learn more about this document.
****
# Public Lab Code of Conduct
_Public Lab, PO Box 426113, Cambridge, MA 02142_
_Public Lab, 55 Cromwell Street, 1C, Providence, RI 02907_
We are coming together with an intent to care for ourselves and one another. We want to nurture a compassionate democratic culture where responsibility is shared. We -- visitors, community members, community moderators, staff, organizers, sponsors, and all others -- hold ourselves accountable to the same values regardless of position or experience. For this to work for everybody, individual decisions will not be allowed to run counter to the welfare of other people. This community aspires to be a respectful place both during online and in-person interactions so that all people are able to fully participate with their dignity intact. This document is a piece of the culture we're creating.
We are coming together with an intent to care for ourselves and one another as we produce knowledge in pursuit of environmental justice. For this to work for everybody, individual decisions will not be allowed to run counter to the welfare of other people. We—visitors, community members, community moderators, staff, organizers, sponsors, and all othershold ourselves accountable to the same values regardless of position or experience. This community aspires to be a respectful place both during online and in-person interactions so that all people are able to fully participate with their dignity intact. This document is a piece of the culture we're creating.
This code of conduct applies to all spaces managed by the Public Lab community and non-profit, both online and in person. It provides a clear set of practical guidelines for events led by organizers and community members, multi-day events such as Barnraisings, and online venues such as the website, comment threads on software platforms, chatrooms, our mailing lists, the issue tracker, and any other forums created by Public Lab which the community uses for communication. For interactions with additional groups, see our Partnership Guidelines at https://publiclab.org/partners.
This code of conduct applies to all spaces managed by the Public Lab community and non-profit, both online and in person. It was written by the Conduct Committee (formed in 2015 during Public Labs annual conference “The Barnraising”) and facilitated by staff to provide a clear set of practical guidelines for multi-day events such as Barnraisings, events led by organizers and community members, and online venues such as the website, comment threads on software platforms, chatrooms, our mailing lists, the issue tracker, and any other forums created by Public Lab which the community uses for communication.
To read the full Code of Conduct and learn how to contact the Conduct Committee or the Moderators group, see:
## We come from all kinds of backgrounds
Our community is best when we fully invite and include participants from a wide range of backgrounds. We specifically design spaces to be welcoming and accessible to newcomers and folks from underrepresented groups. Public Lab is dedicated to providing a harassment-free, safe, and inclusive experience for everyone, regardless of personal and professional background, gender, gender identity and expression, style of clothing, sexual orientation, dis-/ability, physical appearance, body size, race, class, age, or religion. Public Lab resists and rejects: racism, sexism, ableism, ageism, homophobia, transphobia, body shaming, religion shaming, “geekier-than-thou” shaming, education bias, the shaming of people nursing children, and the dismissal or bullying of children or adults.
## We do not tolerate harassment or shaming
While we operate under the assumption that all people involved with Public Lab subscribe to the basic understanding laid out above, we take these issues very seriously and think they should, in general, be taken seriously. Therefore, individuals who violate this Code both in and outside of Public Lab spaces may affect their ability to participate in Public Lab ranging from temporarily being placed into online moderation to, as a last resort, expulsion from the community. If you have any questions about our commitment to this framework and/or if you are unsure about aspects of it, email conduct@publiclab.org and we will do our best to provide clarification.
## How It Works
Sometimes things go wrong. When a situation is uncomfortable, hurtful, exclusionary, or upsetting, there is a problem that should be addressed. This code of conduct is an effort to maintain a safe space for everyone, and to talk about what might happen if that space is compromised. Please see additional guidelines below for community behavior on how we expect people to interact with one another.
### Two helpful groups
__Conduct Committee (ConductCom)__: If at any time you experience something that you are not comfortable with, you may contact the Conduct Committee. As established during the 2015 Annual Barnraising, the following individuals are on the Conduct Committee: Klie Kliebert, Carla Green, Nick Shapiro, and Shannon Dosemagen, the executive director of the Public Lab nonprofit.
If you would like to have a confidential conversation, connect with ConductCom in person or email via [conduct@publiclab.org](mailto:conduct@publiclab.org). A minimum of two committee members will confer and respond as swiftly as possible. If you would prefer to speak privately with a representative of the nonprofit, please contact the executive director directly either in person or by email: [shannon@publiclab.org.](mailto:conduct@publiclab.org)
To submit a report anonymously for review by ConductCom, go online via phone or computer to our anonymous “contact” app, located at [http://bit.ly/PLReport](http://bit.ly/PLReport). This contact app will be monitored daily at 8am CST during in-person events like Barnraisings and weekly at all other times. During multi-day in-person events hosted by the Public Lab non-profit, there will also be a physical suggestion box available. This box will be monitored throughout the event and can also be used to let us know if you need us to check on an anonymous online submission sooner.
__Moderators Group:__ The moderators group is responsible for addressing immediate moderation issues that arise during online violations of the code over email lists and Public Lab community websites, as well as approving first-time posts and generally handling spam. Instructions on how to become a moderator, and, if youve been placed in moderation how to begin the process of getting out of moderation can be found at: https://publiclab.org/wiki/moderation.
****
## A Culture of Empathy
We begin interactions by acknowledging that we are part of a community with complementary goals. Different views are allowed to respectfully coexist in the same space. When something's happened and someone is uncomfortable, our first choice is to work through it. Endeavor to listen and appropriately adjust your behavior if someone approaches you privately with a request that you apologize or publicly requests that you stop an ongoing presentation. If someone questions your words, actions or motives, or "calls you out", hear their feedback and respond respectfully. Its okay to not understand why something is hurtful or causes discomfort, as long as you approach it respectfully, with empathy. Repeating hurtful behavior after it has been addressed is disrespectful and is not allowed. Doing so will result in removal and subsequent banning from in-person events and being placed into moderation in online spaces.
### The first rule of engaging with others is consent
During in-person gatherings, consent is important to highlight because the negotiation of consent can be subtle, and its easy to miss each others non-verbal cues, resulting in miscommunication and/or offense. During online interactions, consent can be even harder to distinguish.
We make guesses or assessments of consent (willingness, welcome, invitation) all the time. Then we stay open to signs that the consent isn't there. Handshakes are a clear example of consent: someone offers a hand, and you take it if you want to shake it. A friendly smile might indicate consent to start a conversation. It might not. We learn that in the interaction. Sometimes we ask directly. We are open to making mistakes, and learning from them. The more we learn to be empathetic and see other people, the more we're able to talk about consent.
Before you engage with someone on any level, be sure you have their consent. If your indications aren't being heard, you can also ask for help from other folks, especially Conduct Committee members and staff of the non-profit: "They aren't taking the hint. Will you help?" Turning a blind eye to hurtful interactions can be as bad for our community as the exchange itself. If you witness something, it's your responsibility to say something. This is how we keep each other accountable, encourage empathy, and keep our community safe.
## Guidelines for in-person community behavior
Do | Dont
----------- | -----------
Respectfully share what method works best for you, while giving others space to think differently and contribute other ideas | Disparage entire groups/sets of people for their beliefs or methods
Ask permission to take pictures of and post about others on social media (see Media Consent, above)| Upload photos, tag or mention others online without their consent
Speak your own narrative, from your own unique culture | Caricature the cultural expressions of groups you are not a member of
Model inclusionary expertise - if others in the group appear to be “lost”, slow down; stop and ask for input | Present information in a way / at a level that no one else in the room can understand, with no attempt to include others in the discussion
Create events that are all-ages appropriate | Use language that excludes youth and their experiences as vital contributors
Give everyone a chance to talk, only interrupting if absolutely necessary - for example, Code of Conduct violations | Repeatedly disrupt a discussion
Stop, listen and ask for clarification if someone perceives your behavior or presentation as violating the Code of Conduct | Ignore others request to stop potentially harmful behavior, even if it was an accident
Cultivate a sense of humor based on other subjects, such as word play (especially puns!) | Joke using words related to actual or insulting descriptions of people
Use words that accurately describe the situation - For example, “The wind was ridiculously strong!” instead of “The wind was crazy!” | Use disability and mental/emotional health terminology to describe a situation metaphorically, especially if the phrasing is meant as an insult
Only discuss someone elses lifestyle practices if they invite you to a conversation on the topic | Make unwelcomed comments regarding a persons lifestyle practices, including those related to food, health, parenting, relationships, and employment
Ask someone before you hug them; keep your hands/body to yourself, even when joking, unless the other person has given verbal consent | Initiate physical contact or simulate physical contact without consent
Disengage and find another activity if someone did not invite you and is not engaging with you | Violate personal space by continuing your physical presence into private spaces without consent
Exercise the right to talk about your own identity if you want to, or not if you dont want to | Deliberately “out” any aspect of a persons identity without their consent
Use the pronouns people have specified for themselves | Purposely misgender someone (ie, refusing to use their correct gender pronouns) after they have told you their correct pronouns
## Additional guidelines for online community behavior
Online modes of interaction involve large numbers of people without the helpful presence of gestural, expression, and tonal cues regarding consent. Because of this, respectful and self-aware online conduct is both especially important and difficult. Our community has evolved specific guidelines for online interactions.
_If someone violates these guidelines, someone from the Moderators group will place them into moderation by changing that persons posting permission on the relevant list, on the website, or both._
Our triple notification standard for moderation means a point person from the Moderators group will:
1. e-mail the person directly with a brief explanation of what was violated,
2. send a summary email to the rest of the moderators group,
3. if it happened on a public list (vs a website), notify the list that one of our members has been placed into moderation with a brief explanation of what is not tolerated.
If you wish to begin the process of getting out of moderation, respond to the email sent to you from [moderators@publiclab.org](mailto:moderators@publiclab.org). The Moderators group has the option to involve ConductCom.
Do | Dont
-------|--------
Stay on topic to make long threads easier to follow |Send spurious one-line responses that effectively "spam" hundreds of people and lower the overall content quality of a conversation. (Exception: expressions of appreciation and encouragement!)
Start a new thread to help others follow along. Important if your response starts to significantly diverge from the original topic | Respond with off-topic information making it hard for the large group of readers to follow along
Write short and literal subject lines to help the readers of the list manage the volume of communication | Humor and euphemisms in subject lines are easily misunderstood, although enthusiasm is welcome!
Mind your tone. We are not having this conversation in person, so it is all the more important to maintain a tone of respect | Write in aggressive tone, disrespectful tone, mocking tone, off-color tone. Note: writing in all caps is regarded as shouting
## Media Consent
* ALWAYS check with parents about posting anything with minors.
* Never post the names of minors in conjunction with their photo.
* During multi-day events like Barnraisings most people will have signed media releases. Those who havent will be responsible for placing stickers on their nametags, and/or raising their hands in the moment to alert photographers to move them out of frame.
* For events where people have not signed blanket media release forms, the photographer is responsible for letting the room know that you are taking photos that will be posted online. Pay special attention to the presence of minors and their parent's wishes.
## Addendum for all staff
Staff are bound by their Employment Handbook, you must reference it. Additionally:
* Direct problems that come up among community members to the Conduct Committee.
* When organizing events, circulate access information regarding wheelchair-accessible ADA bathrooms, non-gendered bathrooms, the presence of stairs or curb ramps in the parking lot, et cetera.
* During events that you are attending in person, solve accessibility issues by making sure attendees know where bathrooms are located and can access them by wheelchair without being obstructed by things like chairs, kites, contraptions, or cords.
* Watch for people feeling left out and include them.
https://publiclab.org/conduct

View File

@@ -3,6 +3,10 @@ Contributing to Image Sequencer
Happily accepting pull requests; to edit the core library, modify files in `./src/`. To build, run `npm install` followed by `grunt build`.
On ARM based devices, the `gl` module may require some libraries to be re-installed:
`sudo apt-get install -y build-essential xserver-xorg-dev libxext-dev libxi-dev libglu1-mesa-dev libglew-dev pkg-config` -- see https://github.com/stackgl/headless-gl#ubuntudebian for more.
Most contribution (we imagine) would be in the form of API-compatible modules, which need not be directly included.
## Jump To
@@ -12,6 +16,7 @@ Most contribution (we imagine) would be in the form of API-compatible modules, w
* [Info File](#info-file)
* [Ideas](#Contribution-ideas)
* [Grunt Tasks](#grunt-tasks)
* [UI Helper Methods](#ui-helper-methods)
****
@@ -111,7 +116,20 @@ function ModuleName(options,UI) {
// load a standard info.json file.
];
```
### Running a browser-only module in node
If your module has browser specific code or you are consuming a dependency which does the `gl-context` api. We designed this api especially for webl based modules but since it runs the module in a headless browser, ti supports all browser specific APIs.
The api must be used in the following format
```js
var step = this;
if (!options.inBrowser) {
require('../_nomodule/gl-context')(input, callback, step, options);
}
else {
/* Browser specific code */
}
```
### options
@@ -262,6 +280,7 @@ module.exports = function ModuleName(options,UI) {
The `progressObj` parameter of `draw()` is not consumed unless a custom progress bar needs to be drawn, for which this default spinner should be stopped with `progressObj.stop()` and image-sequencer is informed about the custom progress bar with `progressObj.overrideFlag = true;` following which this object can be overriden with custom progress object.
### Module example
See existing module `channel` for an example: https://github.com/publiclab/image-sequencer/blob/main/src/modules/Channel/Module.js
@@ -350,7 +369,29 @@ module.exports =
});
```
## Linting
We are now using `eslint` and `husky` to help lint and format our code each time we commit. Eslint defines coding standards and helps in cleaning up the code. To run eslint for checking errors globally or within a specific file run:
```
npx eslint .
npx eslint <file path>
```
And to fix those errors globally or in a file, run these in your terminal:
```
npx eslint . --fix
npx eslint <file path> --fix
```
Be sure to not include the angular brackets(<>).
Husky ensures automation of the above steps with git-hooks(eg. git add,git commit..). However we don't want to check and fix changes of the entire codebase with each commit and that the fixes made by eslint appear unstaged and require us to commit them again and that is where lint-staged helps.
If we want `husky` to not verify the commit and push it anyway, use `git commit -m "message" --no-verify.`
## Grunt Tasks
This repository has different grunt tasks for different uses. The source code is in the [Gruntfile](https://github.com/publiclab/image-sequencer/blob/main/Gruntfile.js).
The following command is used for running the tasks: `grunt [task-name]`. Here `[task-name]` should be replaced by the name of the task to be run. To run the default task run `grunt` without any options.
@@ -362,3 +403,58 @@ The following command is used for running the tasks: `grunt [task-name]`. Here `
4. **serve**: Compiles the dist files as in the **compile** task and starts a local server on `localhost:3000` to host the demo site in `/examples/` directory. Also runs the **watch** task.
5. **production**: Compiles and minifies dist files in `/dist/image-sequencer.js` and `/dist/image-sequencer-ui.js` without the `.min.js` extension to include minified files in the demo site. This script should only be used in production mode while deploying.
6. **default**: Runs the **watch** task as default.
## UI Helper Methods
### scopeQuery
###### Path: `/examples/lib/scopeQuery.js`
The method returns a scoped `jQuery` object which only searches for elements inside a given scope (a DOM element).
To use the method,
* import the `scopeSelector` and `scopeSelectorAll` methods from `lib/scopeQuery.js`
* call the methods with scope as a parameter
```js
var scopeQuery = require('./scopeQuery');
var $step = scopeQuery.scopeSelector(scope),
$stepAll = scopeQuery.scopeSelectorAll(scope);
```
This will return an object with a constructor which returns a `jQuery` object (from inside the scope) but with new `elem` and `elemAll` methods.
#### Methods of the Returned Object
* `elem()`: Selects an element inside the scope.
* `elemAll()`: Selects all the instances of a given element inside the scope.
* `getScope()`: Returns the scope as a DOM element.
* `getDomElem()`: Returns the scoped element as a DOM element instead of a jquery object.
#### Example
```js
//The scope is a div element with id=“container“ and there are three divs in it
//with ids „1“, „2“, and „3“, and all of them have a „child“ class attribute
var $step = require('./scopeQuery').scopeSelector(document.getElementById('container'));
$step('#1'); // returns the div element with id=“1“
$step('#1').hide().elemAll('.child').fadeOut(); // abruptly hides the div element with id=“1“ and fades out all other div elements
```
These two methods are chainable and will always return elements from inside the scope.
#### Usage
Instead of using
```js
$(step.ui.querySelector('query')).show().hide();
$(step.ui.querySelectorAll('q2')).show().hide();
```
The following code can be used
```js
$step('query').show().hide();
$stepAll('q2').show().hide();
```

View File

@@ -1,76 +1,99 @@
module.exports = function(grunt) {
grunt.loadNpmTasks("grunt-browserify");
grunt.loadNpmTasks("grunt-contrib-uglify-es");
grunt.loadNpmTasks("grunt-browser-sync");
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify-es');
grunt.loadNpmTasks('grunt-browser-sync');
grunt.loadNpmTasks('grunt-text-replace');
require("matchdep")
.filterDev("grunt-*")
require('matchdep')
.filterDev('grunt-*')
.forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
pkg: grunt.file.readJSON('package.json'),
watch: {
options: {
livereload: true
},
source: {
files: ["src/**/*", "Gruntfile.js", "examples/lib/*","examples/demo.js"],
tasks: ["compile"]
files: ['src/**/*', 'Gruntfile.js', 'examples/lib/*', 'examples/demo.js'],
tasks: ['compile']
}
},
browserify: {
options: {
alias: {
'gpu.js': './node_modules/gpu.js/src/index.js'
}
},
core: {
src: ["src/ImageSequencer.js"],
dest: "dist/image-sequencer.js"
},
src: ['src/ImageSequencer.js'],
dest: 'dist/image-sequencer.js'
},
ui: {
src: ["examples/demo.js"],
dest: "dist/image-sequencer-ui.js"
src: ['examples/demo.js'],
dest: 'dist/image-sequencer-ui.js'
},
prodcore: {
src: ["src/ImageSequencer.js"],
dest: "dist/image-sequencer.brow.js"
src: ['src/ImageSequencer.js'],
dest: 'dist/image-sequencer.brow.js'
},
produi: {
src: ["examples/demo.js"],
dest: "dist/image-sequencer-ui.brow.js"
src: ['examples/demo.js'],
dest: 'dist/image-sequencer-ui.brow.js'
},
tests: {
src: ['test/core/sequencer/meta-modules.js', 'test/core/sequencer/image-sequencer.js', 'test/core/sequencer/chain.js', 'test/core/sequencer/replace.js', 'test/core/sequencer/import-export.js', 'test/core/sequencer/run.js', 'test/core/sequencer/dynamic-imports.js', 'test/core/util/*.js'],
dest: './output/core-tests.js'
}
},
replace: {
version: {
src: ['examples/sw.js'],
overwrite: true,
replacements: [{
from: /image-sequencer-static-v.*/g,
to: "image-sequencer-static-v<%= pkg.version %>';"
}]
}
},
uglify: {
core: {
src: ["./dist/image-sequencer.js"],
dest: "./dist/image-sequencer.min.js"
src: ['./dist/image-sequencer.js'],
dest: './dist/image-sequencer.min.js'
},
ui: {
src: ['dist/image-sequencer-ui.js'],
dest: 'dist/image-sequencer-ui.min.js'
},
prodcore: {
src: ["dist/image-sequencer.brow.js"],
dest: "dist/image-sequencer.js"
src: ['dist/image-sequencer.brow.js'],
dest: 'dist/image-sequencer.js'
},
produi: {
src: ["dist/image-sequencer-ui.brow.js"],
dest: "dist/image-sequencer-ui.js"
src: ['dist/image-sequencer-ui.brow.js'],
dest: 'dist/image-sequencer-ui.js'
}
},
browserSync: {
dev: {
options: {
watchTask: true,
server: "./"
server: './'
}
}
}
});
/* Default (development): Watch files and build on change. */
grunt.registerTask("default", ["watch"]);
grunt.registerTask("build", ["browserify:core", "browserify:ui", "uglify:core", "uglify:ui"]);
grunt.registerTask("serve", ["browserify:core", "browserify:ui", "browserSync", "watch"]);
grunt.registerTask("compile", ["browserify:core", "browserify:ui"]);
grunt.registerTask("production", ["browserify:prodcore", "browserify:produi", "uglify:prodcore", "uglify:produi"]);
grunt.registerTask('default', ['watch']);
grunt.registerTask('build', ['browserify:core', 'browserify:ui', 'replace:version', 'uglify:core', 'uglify:ui']);
grunt.registerTask('serve', ['browserify:core', 'browserify:ui', 'replace:version', 'browserSync', 'watch']);
grunt.registerTask('compile', ['browserify:core', 'browserify:ui']);
grunt.registerTask('production', ['browserify:prodcore', 'browserify:produi', 'replace:version', 'uglify:prodcore', 'uglify:produi']);
grunt.registerTask('tests', ['browserify:tests']);
};

103
README.md
View File

@@ -1,8 +1,8 @@
Image Sequencer
====
[![Build Status](https://travis-ci.org/publiclab/image-sequencer.svg?branch=master)](https://travis-ci.org/publiclab/image-sequencer)
[![Code of Conduct](https://img.shields.io/badge/code-of%20conduct-green.svg)](https://publiclab.org/conduct)
[![Build Status](https://travis-ci.org/publiclab/image-sequencer.svg?branch=master)](https://travis-ci.org/publiclab/image-sequencer) [![Maintainability](https://api.codeclimate.com/v1/badges/5906996dd2e90aca6398/maintainability)](https://codeclimate.com/github/publiclab/image-sequencer/maintainability) [![Codecov](https://img.shields.io/codecov/c/github/publiclab/image-sequencer.svg?logo=codecov)](https://codecov.io/gh/publiclab/image-sequencer)
- **Latest Stable Demo**: https://sequencer.publiclab.org
- **Latest Beta Demo**: https://beta.sequencer.publiclab.org
@@ -59,7 +59,7 @@ A diagram of this running 5 steps on a single sample image may help explain how
This library conveniently works in the browser, in Node, and on the command line (CLI).
### Unix based platforms
You can set up a local environment to test the UI with `npm run setup` followed by `npm start`.
You can set up a local environment to test the UI with `sudo npm run setup` followed by `npm start`.
### Windows
Our npm scripts do not support windows shells, please run the following snippet in PowerShell.
@@ -95,7 +95,7 @@ $ npm install image-sequencer -g
```
$ npm run debug invert
```
## Quick Usage
### Initializing the Sequencer
@@ -115,7 +115,7 @@ Note: Browser CORS Restrictions apply. Some browsers may not allow local images
from other folders, and throw a Security Error instead.
```js
sequencer.replaceImage(selector,steps,optional_options);
sequencer.replaceImage(selector,steps,optional_options);
```
`optional_options` allows passing additional arguments to the module itself.
@@ -123,8 +123,8 @@ from other folders, and throw a Security Error instead.
For example:
```js
sequencer.replaceImage('#photo','invert');
sequencer.replaceImage('#photo',['invert','ndvi-red']);
sequencer.replaceImage('#photo','invert');
sequencer.replaceImage('#photo',['invert','ndvi-red']);
```
### Data URL usage
@@ -150,7 +150,7 @@ Image Sequencer also provides a CLI for applying operations to local files. The
The basic format for using the CLI is as follows:
```
$ ./index.js -i [PATH] -s step-name
$ ./index.js -i [PATH] -s step-name
```
*NOTE:* On Windows you'll have to use `node index.js` instead of `./index.js`.
@@ -158,7 +158,7 @@ The basic format for using the CLI is as follows:
The CLI also can take multiple steps at once, like so:
```
$ ./index.js -i [PATH] -s "step-name-1 step-name-2 ..."
$ ./index.js -i [PATH] -s "step-name-1 step-name-2 ..."
```
But for this, double quotes must wrap the space-separated steps.
@@ -201,15 +201,17 @@ var sequencer = ImageSequencer();
### Loading an Image into the Sequencer
The `loadImage` method is used to load an image into the sequencer. It accepts
a name and an image. The method also accepts an optional callback.
an image `src`, either a URL or a data-url. The method also accepts an optional callback.
```js
sequencer.loadImage(image_src,optional_callback);
sequencer.loadImage(image_src, optional_callback);
```
On `Node.js` the `image_src` may be a DataURI or a local path or a URL.
On browsers, it may be a DatURI, a local image or a URL (Unless this violates
CORS Restrictions). To sum up, these are accepted:
* Images in the same domain (or directory - for a local implementation)
* CORS-Proof images in another domain.
* DataURLs
@@ -219,7 +221,7 @@ The callback is called within the scope of a sequencer. For example:
(addSteps is defined later)
```js
sequencer.loadImage('SRC',function(){
sequencer.loadImage('SRC', function(){
this.addSteps('module-name');
});
```
@@ -240,8 +242,40 @@ If only one module is to be added, `modules` is simply the name of the module.
If multiple images are to be added, `modules` is an array, which holds the names of modules
to be added, in that particular order.
optional_otions is just an optional parameter, in object form, which you might
want to provide to the modules.
optional_options is just an optional parameter, in object form, which you might
want to provide to the modules.
A variety of syntaxes are supported by Image Sequencer to add multiple steps and configurations quickly for module chaining. The project supports the string syntax, designed to be compact and URL friendly, and JSON, for handling more complex sequences. This can be achieved by passing strings to `sequencer.addStep()`:
```js
sequencer.addSteps('invert,channel');
sequencer.addSteps(['invert','channel']);
```
For passing default configurations ({} is optional):
```js
sequencer.addSteps('brightness{}');
```
For passing custom configurations:
```js
sequencer.addSteps('brightness{brightness:80}');
```
For passing multiple custom configurations:
```js
sequencer.addSteps('crop{x:120|y:90}')
```
For passing multiple custom configurable modules:
```js
sequencer.addSteps('crop{x:130|y:80},brightness{brightness:80}')
```
return value: **`sequencer`** (To allow method chaining)
@@ -398,7 +432,7 @@ Image sequencer supports stringifying a sequence which is appended to the url an
channel{channel:green},invert{}
```
Sequencer also supports the use of `()` in place of `{}` for backward compatibility with older links. (This syntax is deprecated and should be avoided as far as possible)
The use of `()` in place of `{}` for backward compatibility with older links is now **deprecated**. (There is no longer support for the following syntax, and should be avoided)
```
channel(channel:green),invert()
```
@@ -437,7 +471,7 @@ sequencer.importJSON([
To see this in action, please refer to line # 51 of the following:
[test/core/modules/import-export.js](https://github.com/publiclab/image-sequencer/blob/main/test/core/modules/import-export.js)
## Creating a User Interface
@@ -514,7 +548,7 @@ sequencer.setUI({
Image Sequencer object supports one imageURL at a time.
Adding a seccond image to same sequencer will result to adding same set of steps added to prior image and flushing out the previous one.
Adding a seccond image to same sequencer will result to adding same set of steps added to prior image and flushing out the previous one.
```js
s1 = new ImageSequencer(...);
@@ -544,3 +578,38 @@ sequencer2.run();
This method returns an object which defines the name and inputs of the modules. If a module name (hyphenated) is passed in the method, then only the details of that module are returned.
The `notify` function takes two parameters `msg` and `id`, former being the message to be displayed on console (in case of CLI and node ) and a HTML component(in browser). The id is optional and is useful for HTML interface to give appropriate IDs.
## Using WebAssembly for heavy pixel processing
Any module which uses the `changePixel` function gets WebAssembly acceleration (`wasm`). Both node and browser code use WebAssembly and the only code which falls back to non-`wasm` code is the [browserified unit tests](https://github.com/publiclab/image-sequencer/blob/main/test/core/sequencer/benchmark.js).
The main advantage we get using `wasm` is blazing fast speed attained in processing pixels for many modules that is very clear from [checking module benchmarks](https://travis-ci.org/publiclab/image-sequencer/jobs/544415673#L1931).
The only limitation is that browser and node code for `wasm` had to be written separately, and switched between. This is because in browser we use `fetch` to retrieve the compiled `wasm` program while in node we use the `fs` module, each of which cannot be used in the other's environment.
`wasm` mode is enabled by default. If you need to force this mode to be on or off, you can use the `useWasm` option when initializing ImageSequencer:
```js
let sequencer = ImageSequencer({useWasm:true}) // for wasm mode or simply
let sequencer = ImageSequencer() // also for wasm mode i.e. default mode
let sequencer = ImageSequencer({useWasm:false}) //for non-wasm mode
```
## Experimental GIF processing support
ImageSequencer currently can process GIFs but only for most of the modules. Every frame of the GIF is manipulated sequentially (parallel processing would be preferable in the future).
The final frames are then converted back to a GIF but in the process, the time duration of each frame is lost and defaults to `0.1s`.
Modules that do not work:
1. ColorBar (Will get fixed upon fixing overlay as this is a meta module which uses overlay)
2. FisheyeGL
4. Overlay
5. Text Overlay (Almost fixed)
6. Blend
7. Histogram
8. WebGL Distort

BIN
dist/manipulation.wasm vendored Normal file

Binary file not shown.

View File

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

View File

@@ -18,14 +18,22 @@ body {
background: #f8f8fa;
}
footer {
margin-top: 40px;
}
h1 {
font-family: 'League Spartan';
color: #445;
}
body > .container,
body > .container-fluid {
}
.center-align {
display: flex;
justify-content: center;
justify-content: left;
text-align:center;
}
@@ -36,6 +44,11 @@ h1 {
.panel {
margin-left: 20px;
margin-right: 20px;
min-width:400px;
}
.mouse {
cursor: pointer !important;
}
.nomargin {
@@ -53,16 +66,27 @@ h1 {
border-radius: 8px;
text-align: center;
color: #444;
}
.hover {
background: #eee;
min-width:300px;
}
.dropzone input {
max-width: 100%;
}
.import-image-zone {
margin: 10px auto 30px auto;
max-width: 250px;
min-width: 230px;
}
.import-image-zone input {
max-width: 100%;
}
.hover {
background: #eee;
}
.step {
margin-bottom: 20px;
}
@@ -71,16 +95,6 @@ h1 {
margin-bottom: 20px;
}
.details {
padding-left: 6px;
}
.details h3 {
font-family: monospace;
margin-top: 12px;
font-size: 1.3em;
}
.det {
padding: 10px 16px;
text-decoration: italic;
@@ -99,18 +113,16 @@ h1 {
color: #444;
}
.load-spin{
position: absolute;
right: 0px;
}
#addStep {
max-width: 500px;
margin: 20px auto;
}
#add-step-btn{
margin-left: 10px;
width: 100%
}
.selectize-input {
width: 100%;
}
#addStep .labels {
@@ -147,7 +159,6 @@ h1 {
#dwnld {
max-width: 500px;
margin: 20px auto;
margin-left: 5px;
}
#gif_element {
@@ -251,29 +262,108 @@ a.name-header{
}
.step-column{
display:flex;
display:flex;
align-content: center;
justify-content: center;
}
.trash-container button.btn-xs {
margin-top: -5px !important;
position: relative;
bottom: 7px;
}
/*
.panel-footer .insert-step{
margin-left:10px;
border-radius:6px;
background-color:#fff;
border:solid #bababa 1.1px;
.toggleIcon {
transition: transform 0.2s;
}
.col-md-4{
padding-left: 30px;
.rotated {
transform: rotate(180deg);
}
.panel-heading{
height:45px;
#gif{
margin-left:0px;
margin-top:5px;
width:100%;
}
.panel-footer{
height: 45px;
.save-button{
margin-top:20px;
margin-bottom:0px;
align:center;
width:100%;
}
.toggle {
cursor: default;
}
.general-tooltip:hover{
text-decoration: none;
}
.general-tooltip:focus{
outline: none;
}
.general-tooltip:focus-within{
outline: none;
}
.general-tooltip{
position: relative;
bottom: 7px;
font-size: 16px;
color: #444;
}
#version-number-text {
text-align: center;
padding-top: 100px;
color: gray;
}
#version-number-top-right {
position: fixed;
right: 2%;
top: 5%;
color: lightgray;
}
/* Non float rightward alignment*/
.right {
margin-left: auto;
display: block;
}
#update-prompt-modal {
visibility: hidden;
min-width: 250px;
margin-left: -125px;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 2px;
padding: 16px;
position: fixed;
z-index: 1000;
left: 10%;
top: 30px;
}
#update-prompt-modal.show {
visibility: visible;
-webkit-animation: fadein 0.5s;
animation: fadein 0.5s;
}
@-webkit-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
*/

View File

@@ -1,52 +1,91 @@
var defaultHtmlSequencerUi = require('./lib/defaultHtmlSequencerUi.js'),
setupCache = require('./lib/cache.js'),
intermediateHtmlStepUi = require('./lib/intermediateHtmlStepUi.js'),
DefaultHtmlStepUi = require('./lib/defaultHtmlStepUi.js'),
urlHash = require('./lib/urlHash.js'),
insertPreview = require('./lib/insertPreview.js');
setupCache = require('./lib/cache.js'),
intermediateHtmlStepUi = require('./lib/intermediateHtmlStepUi.js'),
DefaultHtmlStepUi = require('./lib/defaultHtmlStepUi.js'),
urlHash = require('./lib/urlHash.js'),
insertPreview = require('./lib/insertPreview.js'),
versionManagement = require('./lib/versionManagement.js'),
isGIF = require('../src/util/isGif');
window.onload = function() {
sequencer = ImageSequencer();
function refreshOptions() {
window.onload = function () {
sequencer = ImageSequencer(); // Set the global sequencer variable
options = {
sortField: 'text',
openOnFocus: false,
onInitialize: function () {
this.$control.on('click', () => {
this.ignoreFocusOpen = true;
setTimeout(() => {
// Trigger onFocus and open dropdown.
this.ignoreFocusOpen = false;
}, 50);
});
},
// Open dropdown after timeout of onClick.
onFocus: function () {
if (!this.ignoreFocusOpen) {
this.open();
}
}
};
versionManagement.getLatestVersionNumber(function(versionNumber) {
console.log('The latest NPM version number for Image Sequencer (from GitHub) is v' + versionNumber);
});
console.log('The local version number for Image Sequencer is v' + versionManagement.getLocalVersionNumber());
function displayVersionNumber() {
$('#version-number-text').text('Image Sequencer v' + versionManagement.getLocalVersionNumber());
$('#version-number-top-right').text('v' + versionManagement.getLocalVersionNumber());
}
displayVersionNumber();
function refreshOptions(options) {
// Default options if parameter is empty.
if (options == undefined) options = { sortField: 'text' };
// Load information of all modules (Name, Inputs, Outputs)
var modulesInfo = sequencer.modulesInfo();
var addStepSelect = $("#addStep select");
addStepSelect.html("");
var addStepSelect = $('#addStep select');
addStepSelect.html('');
// Add modules to the addStep dropdown
for (var m in modulesInfo) {
if (modulesInfo[m] && modulesInfo[m].name)
addStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + "</option>"
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
);
}
// Null option
addStepSelect.append('<option value="none" disabled selected>More modules...</option>');
addStepSelect.selectize({
sortField: 'text'
});
addStepSelect.append('<option value="" disabled selected>Select a Module</option>');
addStepSelect.selectize(options);
}
refreshOptions();
refreshOptions(options);
$(window).on('scroll', scrollFunction);
function scrollFunction() {
/**
* @description Method to toggle the scroll-up arrow.
*/
function scrollFunction(A, B) {
var shouldDisplay = $('body').scrollTop() > 20 || $(':root').scrollTop() > 20;
$('#move-up').css({
display: shouldDisplay ? 'block' : 'none'
display: shouldDisplay ? 'block' : 'none'
});
}
/**
* @description Method to scroll to the top of the page.
*/
function topFunction() {
$('body').animate({scrollTop: 0});
$(':root').animate({scrollTop: 0});
}
$('#move-up').on("click",topFunction);
$('#move-up').on('click', topFunction);
// UI for each step:
@@ -55,109 +94,114 @@ window.onload = function() {
// UI for the overall demo:
var ui = defaultHtmlSequencerUi(sequencer);
// find any `src` parameters in URL hash and attempt to source image from them and run the sequencer
// Load image data from URL `src` parameter.
if (urlHash.getUrlHashParameter('src')) {
sequencer.loadImage(urlHash.getUrlHashParameter('src'), ui.onLoad);
} else {
sequencer.loadImage("images/tulips.png", ui.onLoad);
sequencer.loadImage('images/tulips.png', ui.onLoad);
}
var resetSequence = function(){
var r=confirm("Do you want to reset the sequence?");
var resetSequence = function () {
var r = confirm('Do you want to reset the sequence?');
if (r)
window.location = "/";
}
{
window.location.hash = '';
location.reload();
}
};
$("#addStep select").on("change", ui.selectNewStepUi);
$("#addStep #add-step-btn").on("click", ui.addStepUi);
$("#resetButton").on("click",resetSequence);
$('#addStep select').on('change', ui.selectNewStepUi);
$('#addStep #add-step-btn').on('click', ui.addStepUi);
$('#resetButton').on('click', resetSequence);
//Module button radio selection
$('.radio-group .radio').on("click", function() {
// Module Selector quick buttons click handler.
$('.radio-group .radio').on('click', function () {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
//$("#addStep option[value=" + newStep + "]").attr('selected', 'selected');
$("#addStep select").val(newStep);
$('#addStep select').val(newStep);
ui.selectNewStepUi(newStep);
ui.addStepUi(newStep);
$(this).removeClass('selected');
});
$('#download-btn').click(function() {
$('.step-thumbnail:last()').trigger("click");
return false;
});
function displayMessageOnSaveSequence(){
$(".savesequencemsg").fadeIn();
setTimeout(function() {
$(".savesequencemsg").fadeOut();
}, 1000);
}
/**
* @method displayMessageOnSaveSequence
* @description When a sequence is saved to a browser, notification is displayed.
* @returns {Null}
*/
function displayMessageOnSaveSequence() {
$('.savesequencemsg').fadeIn();
setTimeout(function () {
$('.savesequencemsg').fadeOut();
}, 3000);
}
$('body').on('click', 'button.remove', ui.removeStepUi);
$('#save-seq').click(() => {
var result = window.prompt("Please give a name to your sequence... (Saved sequence will only be available in this browser).");
if(result){
result = result + " (local)";
sequencer.saveSequence(result, sequencer.toString());
function saveSequence() { // 1. save seq
var result = window.prompt('Please give a name to your sequence... (Saved sequence will only be available in this browser).');
if (result) {
result = result + ' (local)';
sequencer.saveSequence(result, sequencer.toString()); // 1.a study saveSequence
sequencer.loadModules();
displayMessageOnSaveSequence();
refreshOptions();
}
}
$('#saveButton').on('click', function () {
// Different handlers triggered for different dropdown options.
let dropDownValue = $('#selectSaveOption option:selected').val();
if (dropDownValue == 'save-image') {
$('.download-btn:last()').trigger('click');
}
else if (dropDownValue == 'save-gif') {
handleSavePNG();
}
else if (dropDownValue == 'save-seq') {
saveSequence();
} else if(dropDownValue == 'save-pdf') {
savePDF(getLastImage());
}
else if (dropDownValue == 'save-to-publiclab.org' ){
SaveToPubliclab();
}
});
var isWorkingOnGifGeneration = false;
let isWorkingOnGifGeneration = false;
$('.js-view-as-gif').on('click', function(event) {
// Prevent user from triggering generation multiple times
if (isWorkingOnGifGeneration) return;
$('.js-view-as-gif').on('click', function (event) { // GIF generation and display
if (isWorkingOnGifGeneration) return; // Prevent multiple button clicks
isWorkingOnGifGeneration = true;
var button = event.target;
button.disabled = true;
button.innerHTML = '<i class="fa fa-circle-o-notch fa-spin"></i>';
try {
// Select all images from previous steps
var imgs = document.getElementsByClassName("step-thumbnail");
// Get GIF resources from previous steps
let options = getGifResources();
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
var options = {
'gifWidth': imgs[0].width,
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
}
gifshot.createGIF(options, function(obj) {
gifshot.createGIF(options, function (obj) { // GIF generation
if (!obj.error) {
// Final gif encoded with base64 format
// Final GIF encoded with base64 format
var image = obj.image;
var animatedImage = document.createElement('img');
animatedImage.id = "gif_element";
animatedImage.id = 'gif_element';
animatedImage.src = image;
let modal = $('#js-download-gif-modal');
var modal = $('#js-download-gif-modal');
$("#js-download-as-gif-button").one("click", function() {
// Trigger download
download(image, "index.gif", "image/gif");
// Close modal
$('#js-download-as-gif-button').one('click', function () {
downloadGif(image); // Trigger GIF download
modal.modal('hide');
})
});
var gifContainer = document.getElementById("js-download-modal-gif-container");
var gifContainer = document.getElementById('js-download-modal-gif-container');
// Clear previous results
gifContainer.innerHTML = '';
@@ -165,11 +209,11 @@ window.onload = function() {
// Insert image
gifContainer.appendChild(animatedImage);
// Open modal
modal.modal();
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
});
@@ -177,47 +221,133 @@ window.onload = function() {
catch (e) {
console.error(e);
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
});
// image selection and drag/drop handling from examples/lib/imageSelection.js
function getGifResources() {
// Returns an object with specific gif options
let imgs = document.getElementsByClassName('step-thumbnail');
var imgSrcs = [];
// Pushes image sources of all the modules in the DOM
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
var options = { // GIF frame options
'gifWidth': imgs[0].width,
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
};
return options;
}
function handleSavePNG() {
let options = getGifResources();
gifshot.createGIF(options, function(obj){
downloadGif(obj.image);
});
}
/**
* Get the data URL for the last image in the sequence.
* @return {string} The data URL for the last image in the sequence.
*/
function getLastImage() {
// Get the image from the last step.
let imgs = document.getElementsByClassName('step-thumbnail');
let lastStepImage = imgs[imgs.length - 1];
return lastStepImage.getAttribute('src');
}
/**
* Download the given image URL as a PDF file.
* @param {string} imageDataURL - The data URL for the image.
*/
function savePDF(imageDataURL) {
sequencer.getImageDimensions(imageDataURL, function(dimensions) {
if (isGIF(imageDataURL)) {
// Get the dimensions of the image.
let pageWidth = dimensions.width;
let pageHeight = dimensions.height;
// Create a new pdf with the same dimensions as the image.
const pdf = new jsPDF({
orientation: pageHeight > pageWidth ? 'portrait' : 'landscape',
unit: 'px',
format: [pageHeight, pageWidth]
});
// Add the image to the pdf with dimensions equal to the internal dimensions of the page.
pdf.addImage(imageDataURL, 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight());
// Save the pdf with the filename specified here:
pdf.save('index.pdf');
}
else console.log('GIFs cannot be converted to PDF');
});
}
function downloadGif(image) {
download(image, 'index.gif', 'image/gif'); // Downloadjs library function
}
function SaveToPubliclab() {
function postToPL(imgSrc) {
var uniq = Date.now();
$('body').append('<form method="post" id="postToPL' + uniq + '" action="https://publiclab.org/post" target="postToPLWindow"><input type="hidden" name="datauri_main_image" /></form>');
f = $('#postToPL' + uniq)[0];
f.datauri_main_image.value = imgSrc;
window.open('', 'postToPLWindow');
f.submit();
}
postToPL($('img')[sequencer.steps.length - 1].src);
}
// Image selection and drag/drop handling from examples/lib/imageSelection.js
sequencer.setInputStep({
dropZoneSelector: "#dropzone",
fileInputSelector: "#fileInput",
takePhotoSelector: "#take-photo",
dropZoneSelector: '#dropzone',
fileInputSelector: '#fileInput',
takePhotoSelector: '#take-photo',
onLoad: function onFileReaderLoad(progress) {
var reader = progress.target;
var step = sequencer.steps[0];
var util= intermediateHtmlStepUi(sequencer);
var util = intermediateHtmlStepUi(sequencer);
step.output.src = reader.result;
sequencer.run({ index: 0 });
if(typeof step.options !=="undefined")
if (typeof step.options !== 'undefined')
step.options.step.imgElement.src = reader.result;
else
step.imgElement.src = reader.result;
insertPreview.updatePreviews(reader.result,'addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src,'insertStep');
insertPreview.updatePreviews(reader.result, document.querySelector('#addStep'));
DefaultHtmlStepUi(sequencer).updateDimensions(step);
},
onTakePhoto: function (url) {
var step = sequencer.steps[0];
step.output.src = url;
sequencer.run({ index: 0 });
if(typeof step.options !=="undefined")
if (typeof step.options !== 'undefined')
step.options.step.imgElement.src = url;
else
step.imgElement.src = url;
insertPreview.updatePreviews(url,'addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src,'insertStep');
insertPreview.updatePreviews(url, document.querySelector('#addStep'));
}
});
setupCache();
if (urlHash.getUrlHashParameter('src')) {
insertPreview.updatePreviews(urlHash.getUrlHashParameter('src'),'addStep');
if (urlHash.getUrlHashParameter('src')) { // Gets the sequence from the URL
insertPreview.updatePreviews(urlHash.getUrlHashParameter('src'), document.querySelector('#addStep'));
} else {
insertPreview.updatePreviews("images/tulips.png",'addStep');
insertPreview.updatePreviews('images/tulips.png', document.querySelector('#addStep'));
}
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -9,11 +9,16 @@
<meta name="theme-color" content="#428bca">
<link rel="icon" sizes="192x192" href="../icons/ic_192.png">
<link rel="manifest" href="manifest.json">
<!--Adding meta Tag for search engine optimisation-->
<meta property="og:description" content="A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original image, it creates a new image at each step in a sequence.">
<meta property="og:site_name" content="sequencer.publiclab.org">
<meta property="og:url" content="https://sequencer.publiclab.org">
<meta property="og:title" content="Image Sequencer">
<!--Adding meta Tag for search engine optimisation-->
<meta property="og:description"
content="A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original image, it creates a new image at each step in a sequence.">
<meta property="og:site_name" content="sequencer.publiclab.org">
<meta property="og:url" content="https://sequencer.publiclab.org">
<meta property="og:title" content="Image Sequencer">
<meta name="Description"
content="Image Sequencer is an image editing tool that creates a new downloadble image at each step.It works in browser and supports both node and CLI.">
<meta name="Keywords" content="image editing downloadable browser node CLI">
<title>Image Sequencer</title>
@@ -22,53 +27,65 @@
<script src="../src/ui/prepareDynamic.js"></script>
<script src="../dist/image-sequencer.js" charset="utf-8"></script>
<script src="../dist/image-sequencer-ui.js" charset="utf-8"></script>
<script src="../node_modules/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js"></script>
<!-- for crop module: -->
<script src="../node_modules/imgareaselect/jquery.imgareaselect.dev.js"></script>
<script src="../node_modules/gifshot/dist/gifshot.min.js" type="text/javascript"></script>
<!-- Download.js for large files -->
<script src="../node_modules/downloadjs/download.min.js" type="text/javascript"/>
<script src="../node_modules/downloadjs/download.min.js" type="text/javascript" ></script>
<script src="lib/scrollToTop.js"></script>
<!-- jspdf to enable save image as pdf -->
<script src="../node_modules/jspdf/dist/jspdf.min.js" type="text/javascript" ></script>
<!-- <script src="lib/scrollToTop.js"></script> -->
<script src="../node_modules/selectize/dist/js/standalone/selectize.min.js"></script>
</head>
<body>
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../node_modules/bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css" rel="stylesheet">
<link rel="stylesheet" href="demo.css">
<link href="../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="../node_modules/selectize/dist/css/selectize.default.css" rel="stylesheet">
<!-- for crop module: -->
<!-- for crop module: -->
<link href="../node_modules/imgareaselect/distfiles/css/imgareaselect-default.css" rel="stylesheet">
<link href="./selectize.default.css" rel="stylesheet">
<link rel="stylesheet" href="demo.css">
<div id="update-prompt-modal">A new version of image sequencer is available. Click <a href="#" id="reload">here</a> to update.</div>
<div class="container-fluid">
<header class="text-center">
<header class="text-center" style="min-width: 450px">
<h1><a href="/" target='_blank' class="name-header">Image Sequencer</a></h1>
<p>
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original image, it
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original
image, it
creates a new image at each step in a sequence.
<a href="https://publiclab.org/image-sequencer">Learn more</a>
<a href="https://github.com/publiclab/image-sequencer/blob/main/README.md">Learn more</a>
</p>
<p>
Open Source
<a href="https://github.com/publiclab/image-sequencer">
<i class="fa fa-github"></i>
</a>
by <a href= "https://publiclab.org" title = "Publiclab Website"><i class = "fa fa-globe"></i> Publiclab</a>
by <a href="https://publiclab.org" title="Publiclab Website"><i class="fa fa-globe"></i> Publiclab</a>
</p>
<span id="version-number-top-right"></span>
</header>
<div id="dropzone" class="dropzone">
<p>
<p id="dropzone-text">
<i>Select or drag in an image to start!</i>
</p>
<center>
<input type="file" id="fileInput" value="" accept="image/*"><br />
<button type="button" id="take-photo" class="btn btn-primary btn-block btn-lg ">Take a Photo</button>
<video id="video" width="400" height="300" style="display:none"></video>
<video id="video" width="100%" height="100%" style="display:none"></video>
<a href="#" id="capture" style="display:none" class="btn btn-primary btn-md">Click Picture</a>
<a href="#" id="close" style="display:none" class="btn btn-default btn-md">Close</a>
<canvas id="canvas" width="400" height="300" style="display:none"></canvas>
@@ -80,79 +97,79 @@
</section>
<hr />
<p class = "alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules.</p>
<div class="row">
<div class="col-sm-8">
<section id="addStep" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="display:flex; justify-content:center;">
</div>
<p class="info">Select a new module to add to your sequence.</p>
<div class="row center-align radio-group">
<div>
<div class="radio" data-value="resize">
<i class="fa fa-arrows-alt fa-4x i-over"></i>
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules in browser's localStorage.
</p>
<div class="row">
<div class="col-sm-8">
<section id="addStep" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="display:flex; justify-content:center;">
</div>
<p>Resize</p>
</div>
<div>
<div class="radio" data-value="brightness">
<i class="fa fa-sun-o fa-4x i-over"></i>
<p class="info">Select a new module to add to your sequence.</p>
<div class="row center-align radio-group">
<div>
<div class="radio" data-value="resize">
<i class="fa fa-arrows-alt fa-4x i-over"></i>
</div>
<p>Resize</p>
</div>
<div>
<div class="radio" data-value="brightness">
<i class="fa fa-sun-o fa-4x i-over"></i>
</div>
<p>Brightness</p>
</div>
<div>
<div class="radio" data-value="contrast">
<i class="fa fa-adjust fa-4x i-over"></i>
</div>
<p>Contrast</p>
</div>
<div>
<div class="radio" data-value="saturation">
<i class="fa fa-tint fa-4x i-over i-small"></i>
</div>
<p>Saturation</p>
</div>
<div>
<div class="radio" data-value="rotate">
<i class="fa fa-rotate-right fa-4x i-over"></i>
</div>
<p>Rotate</p>
</div>
<div>
<div class="radio" data-value="crop">
<i class="fa fa-crop fa-4x i-over"></i>
</div>
<p>Crop</p>
</div>
</div>
<p>Brightness</p>
</div>
<div>
<div class="radio" data-value="contrast">
<i class="fa fa-adjust fa-4x i-over"></i>
</div>
<p>Contrast</p>
</div>
<div>
<div class="radio" data-value="saturation">
<i class="fa fa-tint fa-4x i-over i-small"></i>
</div>
<p>Saturation</p>
</div>
<div>
<div class="radio" data-value="rotate">
<i class="fa fa-rotate-right fa-4x i-over"></i>
</div>
<p>Rotate</p>
</div>
<div>
<div class="radio" data-value="crop">
<i class="fa fa-crop fa-4x i-over"></i>
</div>
<p>Crop</p>
</div>
</div>
<div class="row center-align">
<div class="col-md-8">
<select id="selectStep" >
<!-- The default null selection has been appended manually in demo.js
This is because the options in select are overritten when options are appended.-->
</select>
</div>
<div class="col-md-4">
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
</div>
<div class="row center-align">
<button id="resetButton" class="btn btn-default btn-lg" style=" margin: 20px 35px 0px 35px; width:100%;">Clear All Steps</button>
</div>
</div>
</div>
</section>
<div class="row justify-content-center">
<div class="col-lg-8">
<section id="sequence-actions" class="panel">
<div class="panel-body">
<select id="selectStep" class="text-center">
<!-- The default null selection has been appended manually in demo.js
This is because the options in select are overritten when options are appended.-->
</select>
</div>
<div class="col-lg-4">
<button class="btn btn-primary btn-lg" name="add" id="add-step-btn">Add Step</button></div>
</div>
<div class="row center-align">
<button id="resetButton" class="btn btn-default btn-lg"
style=" margin: 20px 35px 0px 35px; width:100%;">Clear All Steps</button>
</div>
</div>
</div>
</section>
<div class="modal fade" id="js-download-gif-modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Your gif is ready</h4>
</div>
<div class="modal-body">
@@ -170,61 +187,63 @@
</div>
</div>
</section>
</div>
<div class="col-sm-4">
<section id="dwnld" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="text-align:center;">
<h2 style="margin-top:20px">Save</h2>
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
<option>Save as PNG</option>
<option>Save as GIF (all steps)</option>
<option>Save sequence</option>
<option>Save sequence string</option>
</select>
<p><button id="saveButton" class="btn btn-primary btn-lg" style="margin-top:20px; margin-bottom:0px;align:center; width:100%;">Save</button></p>
<p><button class="btn btn-default js-view-as-gif" id="gif" style="align:center;">Preview GIF</button></p>
<div class="col-sm-4">
<section id="dwnld" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="text-align:center;">
<h2 style="margin-top:20px">Save</h2>
<select class="form-control input-md mouse" id="selectSaveOption" style="margin-top:20px">
<option value="save-image">Save as PNG</option>
<option value="save-gif">Save as GIF (all steps)</option>
<option value="save-pdf">Save as PDF</option>
<option value="save-seq">Save sequence</option>
<option value="save-seq-string">Save sequence string</option>
<option value="save-to-publiclab.org">Save to PublicLab.org</option>>
</select>
<p><button id="saveButton" class="btn btn-primary btn-lg save-button">Save</button></p>
<p><button class="btn btn-default btn-lg js-view-as-gif" id="gif">Preview GIF</button></p>
</div>
</div>
</div>
</section>
</div>
</div>
<footer>
<hr style="margin:20px;">
<center><button class="btn btn-default btn-sm" id="clear-cache">Clear offline cache</button></center>
<div class="row">
<div class="col-md-6">
<h2>Need Help?</h2>
<p>
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer/issues">Ask a question</a>
<a class="btn btn-default" href="https://publiclab.org/chat">Ask in our chatroom</a>
</p>
</div>
<div class="col-md-6">
<h2>Improve this tool</h2>
<p>
This is an open source toolkit which you can help improve on Github
</p>
<p>
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer">View the code &raquo;</a>
</p>
</div>
</div>
</section>
</div>
</div>
<footer>
<hr style="margin:20px;"><center><button class="btn btn-default btn-sm" id="clear-cache">Clear offline cache</button></center>
<div class="row">
<div class="col-md-6">
<h2>Need Help?</h2>
<p>
Post a link to this and ask help from other community members on Gitter
</p>
<p>
<a class="btn btn-primary" href="https://gitter.im/publiclab/publiclab">Ask a question on Gitter</a>
</p>
<div class="row">
<p id="version-number-text">Unable to load version number</p>
</div>
<div class="col-md-6">
<h2>Improve this tool</h2>
<p>
This is an open source toolkit which you can help add to and improve on Github
</p>
<p>
<a class="btn btn-primary" href="https://github.com/publiclab/image-sequencer">View the code &raquo;</a>
</p>
</div>
</div>
</footer>
</footer>
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
<script type="text/javascript">
$(function() {
var sequencer;
})
</script>
<script type="text/javascript">
$(function () {
var sequencer;
})
</script>
<script async src="../node_modules/opencv.js/opencv.js" type="text/javascript"></script>
</body>

View File

@@ -1,30 +1,75 @@
var setupCache = function() {
let newWorker; // When sw.js is changed, this is the new service worker generated.
// Toggle a CSS class to display a popup prompting the user to fetch a new version.
function showUpdateModal() {
$('#update-prompt-modal').addClass('show');
}
/**
* When a new service worker has been loaded, the button in the update prompt
* modal should trigger the skipWaiting event to replace the current
* service worker with the new one.
*/
$('#reload').on('click', function() {
newWorker.postMessage({ action: 'skipWaiting' });
});
if ('serviceWorker' in navigator) {
// Register the service worker.
navigator.serviceWorker.register('sw.js', { scope: '/examples/' })
.then(function(registration) {
registration.addEventListener('updatefound', () => {
// When sw.js has been changed, get a reference to the new service worker.
newWorker = registration.installing;
newWorker.addEventListener('statechange', () => {
// Check if service worker state has changed.
switch(newWorker.state) {
case 'installed':
if(navigator.serviceWorker.controller) {
// New service worker available; prompt the user to update.
showUpdateModal();
}
// No updates available; do nothing.
break;
}
});
});
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
console.log(installingWorker)
console.log(installingWorker);
if (installingWorker.state === 'installed') {
location.reload();
}
}
};
console.log('Registration successful, scope is:', registration.scope);
})
.catch(function(error) {
console.log('Service worker registration failed, error:', error);
});
/**
* This is the event listener for when the service worker updates.
* When the service worker updates, reload the page.
*/
let refreshing;
navigator.serviceWorker.addEventListener('controllerchange', function() {
if(refreshing) return;
window.location.reload();
refreshing = true;
});
}
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
$("#clear-cache").append(" " + cacheName);
$('#clear-cache').append(' ' + cacheName);
});
});
}
$("#clear-cache").click(function() {
$('#clear-cache').click(function() {
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
@@ -34,6 +79,11 @@ var setupCache = function() {
}
location.reload();
});
}
module.exports = setupCache;
};
module.exports = setupCache;

View File

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

View File

@@ -8,56 +8,63 @@
// output values, step information.
// See documetation for more details.
var intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js');
var urlHash = require('./urlHash.js');
var _ = require('lodash');
var mapHtmlTypes = require('./mapHtmltypes');
const intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
urlHash = require('./urlHash.js'),
_ = require('lodash'),
mapHtmlTypes = require('./mapHtmltypes'),
scopeQuery = require('./scopeQuery'),
isGIF = require('../../src/util/isGif');
function DefaultHtmlStepUi(_sequencer, options) {
options = options || {};
var stepsEl = options.stepsEl || document.querySelector("#steps");
var selectStepSel = options.selectStepSel = options.selectStepSel || "#selectStep";
var stepsEl = options.stepsEl || document.querySelector('#steps');
var selectStepSel = options.selectStepSel = options.selectStepSel || '#selectStep';
function onSetup(step, stepOptions) {
if (step.options && step.options.description)
step.description = step.options.description;
step.ui =
step.ui = // Basic UI markup for the step
'\
<div class="container">\
<form class="input-form">\
<div class="container-fluid step-container">\
<div class="panel panel-default">\
<div class="panel-heading">\
<div class="trash-container pull-right"></div>\
<h3 class="panel-title">' +
'<span class="toggle">' +step.name + '<span class="caret"></span>\
<div class="trash-container pull-right">\
<a type="button" target="_blank" href="https://developer.mozilla.org/en-US/docs/WebAssembly" style="display: none;" class="btn btn-link general-tooltip wasm-tooltip" data-toggle="tooltip" data-html="true" data-original-title="<div style=\'text-align: center\'><p>This step is Web Assembly accelerated. Click to Read More</div>">\
<i class="fa fa-bolt"></i>\
</a>\
<button type="button" class="btn btn-link ' + step.name + ' general-tooltip dimension-tooltip" data-toggle="tooltip" data-html="true" data-original-title="">\
<i class="fa fa-info-circle"></i>\
</button>\
</div>\
<h3 class="panel-title">' +
'<span class="toggle mouse">' + step.name + ' <span class="caret toggleIcon rotated"></span>\
<span class="load-spin pull-right" style="display:none;padding:1px 8px;"><i class="fa fa-circle-o-notch fa-spin"></i></span>\
</h3>\
</div>\
<form class="input-form">\
<div class="panel-body cal collapse in">\
<div class="row step">\
<div class="col-md-4 details">\
<h3>\
<span class="load-spin" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></span>' +
'</h3><div class="cal collapse in"><p><i>'+
(step.description || "") +
'</i></p></div>\
<div class="col-md-4 details container-fluid">\
<div class="cal collapse in"><p>' +
'<a href="https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#' + step.name + '-module">' + (step.description || '') + '</a>' +
'</p></div>\
</div>\
<div class="col-md-8 cal collapse in step-column">\
<div class="load" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></div>\
<div class="col-md-8 cal collapse in step-column">\
<div class="load load-spin" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></div>\
<div class="step-image">\
<a class="cal collapse in"><img class="img-thumbnail step-thumbnail"/></a>\
</div>\
</div>\
</div>\
</div>\
<div class="panel-footer cal collapse in"></div>\
</div>\
</form>\
</div>';
<div class="panel-footer cal collapse in"></div>\
</form>\
</div>\
</div>';
var tools =
'<div class="trash">\
'<div class="trash" style="display: inline-block">\
<button confirm="Are you sure?" class="remove btn btn-default btn-xs">\
<i class="fa fa-trash"></i>\
</button>\
@@ -66,148 +73,198 @@ function DefaultHtmlStepUi(_sequencer, options) {
var util = intermediateHtmlStepUi(_sequencer, step);
var parser = new DOMParser();
step.ui = parser.parseFromString(step.ui, "text/html");
step.ui = step.ui.querySelector("div.container");
step.linkElements = step.ui.querySelectorAll("a");
step.imgElement = step.ui.querySelector("a img");
step.ui = parser.parseFromString(step.ui, 'text/html'); // Convert the markup string to a DOM node.
step.ui = step.ui.querySelector('div.container-fluid');
step.$step = scopeQuery.scopeSelector(step.ui); // Shorthand methods for scoped DOM queries. Read the docs [CONTRIBUTING.md](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md) for more info.
step.$stepAll = scopeQuery.scopeSelectorAll(step.ui);
let {$step, $stepAll} = step;
step.linkElements = step.ui.querySelectorAll('a'); // All the anchor tags in the step UI
step.imgElement = $step('a img.img-thumbnail')[0]; // The output image
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
var inputs = _sequencer.modulesInfo(step.name).inputs;
var outputs = _sequencer.modulesInfo(step.name).outputs;
var merged = Object.assign(inputs, outputs); // combine outputs w inputs
var merged = Object.assign(inputs, outputs); // Combine outputs with inputs
for (var paramName in merged) {
var isInput = inputs.hasOwnProperty(paramName);
var html = "";
var html = '';
var inputDesc = isInput ? mapHtmlTypes(inputs[paramName]) : {};
if (!isInput) {
html += '<span class="output"></span>';
} else if (inputDesc.type.toLowerCase() == "select") {
}
else if (inputDesc.type.toLowerCase() == 'select') {
html += '<select class="form-control target" name="' + paramName + '">';
for (var option in inputDesc.values) {
html += "<option>" + inputDesc.values[option] + "</option>";
html += '<option>' + inputDesc.values[option] + '</option>';
}
html += "</select>";
} else {
html += '</select>';
}
else {
let paramVal = step.options[paramName] || inputDesc.default;
html =
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal +
'" placeholder ="' +
(inputDesc.placeholder || "");
if (inputDesc.type.toLowerCase() == "range") {
if (inputDesc.id == 'color-picker') { // Separate input field for color-picker
html +=
'"min="' +
inputDesc.min +
'"max="' +
inputDesc.max +
'"step="' +
(inputDesc.step ? inputDesc.step : 1)+ '">' + '<span>' + paramVal + '</span>';
'<div id="color-picker" class="input-group colorpicker-component">' +
'<input class="form-control color-picker-target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal + '">' + '<span class="input-group-addon"><i></i></span>' +
'</div>';
}
else { // Non color-picker input types
html =
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal +
'" placeholder ="' +
(inputDesc.placeholder || '');
if (inputDesc.type.toLowerCase() == 'range') {
html +=
'"min="' +
inputDesc.min +
'"max="' +
inputDesc.max +
'"step="' +
(inputDesc.step ? inputDesc.step : 1) + '">' + '<span>' + paramVal + '</span>';
}
else html += '">';
}
else html += '">';
}
var div = document.createElement("div");
div.className = "row";
div.setAttribute("name", paramName);
var div = document.createElement('div');
div.className = 'row';
div.setAttribute('name', paramName);
var description = inputs[paramName].desc || paramName;
div.innerHTML =
"<div class='det cal collapse in'>\
<label for='" +
'<div class=\'det cal collapse in\'>\
<label for=\'' +
paramName +
"'>" +
'\'>' +
description +
"</label>\
" +
'</label>\
' +
html +
"\
</div>";
step.ui.querySelector("div.details").appendChild(div);
'\
</div>';
$step('div.details').append(div);
}
$(step.ui.querySelector("div.panel-footer")).append(
$step('div.panel-footer').append( // Save button
'<div class="cal collapse in"><button type="submit" class="btn btn-sm btn-default btn-save" disabled = "true" >Apply</button> <small style="padding-top:2px;">Press apply to see changes</small></div>'
);
$(step.ui.querySelector("div.panel-footer")).prepend(
$step('div.panel-footer').prepend( // Markup for tools: download and insert step buttons
'<button class="pull-right btn btn-default btn-sm insert-step" >\
<i class="fa fa-plus"></i> Insert Module\
</button>'
);
<span class="insert-text"><i class="fa fa-plus"></i> Insert Step</span><span class="no-insert-text" style="display:none">Close</span></button>\
<button class="pull-right btn btn-default btn-sm download-btn" style="margin-right:2px" >\
<i class="fa fa-download"></i>\
</button>'
);
}
if (step.name != "load-image") {
step.ui
.querySelector("div.trash-container")
if (step.name != 'load-image') {
$step('div.trash-container')
.prepend(
parser.parseFromString(tools, "text/html").querySelector("div")
parser.parseFromString(tools, 'text/html').querySelector('div')
);
$(step.ui.querySelectorAll(".remove")).on('click', function() {notify('Step Removed','remove-notification')});
$(step.ui.querySelectorAll(".insert-step")).on('click', function() { util.insertStep(step.ID) });
$stepAll('.remove').on('click', function() {notify('Step Removed', 'remove-notification');}); // Notification on removal of a step
$step('.insert-step').on('click', function() { util.insertStep(step.ID); }); // Insert a step in between the sequence
// Insert the step's UI in the right place
if (stepOptions.index == _sequencer.steps.length) {
stepsEl.appendChild(step.ui);
$("#steps .container:nth-last-child(1) .insert-step").prop('disabled',true);
if($("#steps .container:nth-last-child(2)"))
$("#steps .container:nth-last-child(2) .insert-step").prop('disabled',false);
} else {
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
if($('#steps .step-container:nth-last-child(2)'))
$('#steps .step-container:nth-last-child(2) .insert-step').prop('disabled', false);
}
else {
stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]);
}
// Enable the load-image insert-step button when there are steps after load-image
// The logical operator is `> 0` because the number of steps is found before adding the step, actual logic is `steps.length + 1 > 1` which is later simplified.
if (_sequencer.steps.length > 0) $('#load-image .insert-step').prop('disabled', false);
else $('#load-image .insert-step').prop('disabled', true);
}
else {
$("#load-image").append(step.ui);
}
$(step.ui.querySelector(".toggle")).on("click", () => {
$(step.ui.querySelector('.toggleIcon')).toggleClass('fa-caret-up').toggleClass('fa-caret-down');
$(step.ui.querySelectorAll(".cal")).collapse('toggle');
});
$(step.imgElement).on("mousemove", _.debounce(() => imageHover(step), 150));
$('#load-image').append(step.ui); // Default UI without extra tools for the first step(load image)
function saveOptions(e) {
$step('div.panel-footer').prepend( `
<button class="right btn btn-default btn-sm insert-step" disabled="true">
<span class="insert-text"><i class="fa fa-plus"></i> Insert Step</span>
<span class="no-insert-text" style="display:none">Close</span>
</button>`
);
$step('.insert-step').on('click', function() { util.insertStep(step.ID); });
}
$step('.toggle').on('click', () => { // Step container dropdown
$step('.toggleIcon').toggleClass('rotated');
$stepAll('.cal').collapse('toggle');
});
$(step.imgElement).on('mousemove', _.debounce(() => imageHover(step), 150)); // Shows the pixel coordinates on hover
$(step.imgElement).on('click', (e) => {e.preventDefault(); });
$stepAll('#color-picker').colorpicker();
function saveOptions(e) { // 1. SAVE OPTIONS
e.preventDefault();
if (optionsChanged){
$(step.ui.querySelector("div.details"))
.find("input,select")
$step('div.details')
.find('input,select')
.each(function(i, input) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false);
step.options[$(input).attr("name")] = $(input).val();
step.options[$(input).attr('name')] = $(input).val();
});
_sequencer.run({ index: step.index - 1 });
// modify the url hash
urlHash.setUrlHashParameter("steps", _sequencer.toString())
// disable the save button
$(step.ui.querySelector('.btn-save')).prop('disabled', true);
// Modify the URL hash
urlHash.setUrlHashParameter('steps', _sequencer.toString());
// Disable the save button
$step('.btn-save').prop('disabled', true);
optionsChanged = false;
changedInputs = 0;
}
}
/**
* @method handleInputValueChange
* @description Enables the save button on input change
* @param {*} currentValue The current value of the input
* @param {*} initValue The initial/old value of the input
* @param {Boolean} hasChangedBefore Whether the input was changed before
* @returns {Boolean} True if the value has changed
*/
function handleInputValueChange(currentValue, initValue, hasChangedBefore) {
var inputChanged = !(isNaN(initValue) || isNaN(currentValue) ? currentValue === initValue : currentValue - initValue === 0);
changedInputs += hasChangedBefore ? inputChanged ? 0 : -1 : inputChanged ? 1 : 0;
optionsChanged = changedInputs > 0;
$(step.ui.querySelector('.btn-save')).prop('disabled', !optionsChanged);
$step('.btn-save').prop('disabled', !optionsChanged);
return inputChanged;
}
var
var
changedInputs = 0,
optionsChanged = false;
$(step.ui.querySelector('.input-form')).on('submit', saveOptions);
$(step.ui.querySelectorAll('.target')).each(function(i, input) {
$step('.input-form').on('submit', saveOptions);
$stepAll('.target').each(function(i, input) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false)
.on('input', function() {
.on('input change', function() {
$(this)
.focus()
.data('hasChangedBefore',
@@ -215,134 +272,199 @@ function DefaultHtmlStepUi(_sequencer, options) {
$(this).val(),
$(this).data('initValue'),
$(this).data('hasChangedBefore')
)
)
})
})
)
);
});
});
$stepAll('.color-picker-target').each(function(i, input) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false)
.on('input change', function() {
$(this)
.data('hasChangedBefore',
handleInputValueChange(
$(this).val(),
$(this).data('initValue'),
$(this).data('hasChangedBefore')
)
);
});
});
$('input[type="range"]').on('input', function() {
$(this).next().html($(this).val());
})
$(this).next().html($(this).val());
});
}
function onDraw(step) {
$(step.ui.querySelector(".load")).show();
$(step.ui.querySelector("img")).hide();
if( $(step.ui.querySelector(".toggleIcon")).hasClass("fa-caret-down") )
{
$(step.ui.querySelector(".load-spin")).show();
}
function onDraw({$step, $stepAll}) {
$step('.load').show();
$step('img').hide();
$stepAll('.load-spin').show();
}
function onComplete(step) {
$(step.ui.querySelector(".load")).hide();
$(step.ui.querySelector("img")).show();
$(step.ui.querySelector(".load-spin")).hide();
let {$step, $stepAll} = step;
$step('img').show();
$stepAll('.load-spin').hide();
$step('.load').hide();
step.imgElement.src = (step.name == "load-image") ? step.output.src : step.output;
var imgthumbnail = step.ui.querySelector(".img-thumbnail");
$stepAll('.download-btn').off('click');
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
var imgthumbnail = $step('.img-thumbnail').getDomElem();
for (let index = 0; index < step.linkElements.length; index++) {
if (step.linkElements[index].contains(imgthumbnail))
step.linkElements[index].href = step.imgElement.src;
}
// TODO: use a generalized version of this
// TODO: use a generalized version of this.
function fileExtension(output) {
return output.split("/")[1].split(";")[0];
return output.split('/')[1].split(';')[0];
}
for (let index = 0; index < step.linkElements.length; index++) {
$stepAll('.download-btn').on('click', () => {
step.linkElements[index].download = step.name + "." + fileExtension(step.imgElement.src);
step.linkElements[index].target = "_blank";
}
var element = document.createElement('a');
element.setAttribute('href', step.output);
element.setAttribute('download', step.name + '.' + fileExtension(step.imgElement.src));
element.style.display = 'none';
document.body.appendChild(element);
// fill inputs with stored step options
element.click();
});
// 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) {
if (inputs[i].type.toLowerCase() === "input")
$(step.ui.querySelector('div[name="' + i + '"] input'))
if (inputs[i].type.toLowerCase() === 'input')
$step('div[name="' + i + '"] input')
.val(step.options[i])
.data('initValue', step.options[i]);
if (inputs[i].type.toLowerCase() === "select")
$(step.ui.querySelector('div[name="' + i + '"] select'))
.val(step.options[i])
if (inputs[i].type.toLowerCase() === 'select')
$step('div[name="' + i + '"] select')
.val(String(step.options[i]))
.data('initValue', step.options[i]);
}
}
for (var i in outputs) {
if (step[i] !== undefined)
$(step.ui.querySelector('div[name="' + i + '"] input'))
$step('div[name="' + i + '"] input')
.val(step[i]);
}
}
$(function () {
$('[data-toggle="tooltip"]').tooltip();
updateDimensions(step);
});
// Handle the wasm bolt display
if (step.useWasm) {
if (step.wasmSuccess) $step('.wasm-tooltip').fadeIn();
else $step('.wasm-tooltip').fadeOut();
}
else $step('.wasm-tooltip').fadeOut();
}
/**
* @description Updates Dimension of the image
* @param {Object} step - Current Step
* @returns {void}
*
*/
function updateDimensions(step){
_sequencer.getImageDimensions(step.imgElement.src, function (dim) {
step.ui.querySelector('.' + step.name).attributes['data-original-title'].value = `<div style="text-align: center"><p>Image Width: ${dim.width}<br>Image Height: ${dim.height}</br>${isGIF(step.output) ? `Frames: ${dim.frames}` : ''}</div>`;
});
}
/**
* @method imageHover
* @description Handler to display image coordinates on hover.
* @param {Object} step Current step variable
* @returns {Null}
*/
function imageHover(step){
var img = $(step.imgElement);
img.mousemove(function(e) {
img.mousemove(function(e) {
var canvas = document.createElement('canvas');
canvas.width = img.width();
canvas.height = img.height();
var context = canvas.getContext('2d');
context.drawImage(this,0,0);
context.drawImage(this, 0, 0);
var offset = $(this).offset();
var xPos = e.pageX - offset.left;
var yPos = e.pageY - offset.top;
var myData = context.getImageData(xPos, yPos, 1, 1);
img[0].title = "rgb: " +myData.data[0]+","+ myData.data[1]+","+myData.data[2];//+ rgbdata;
});
img[0].title = 'rgb: ' + myData.data[0] + ',' + myData.data[1] + ',' + myData.data[2];//+ rgbdata;
});
}
function onRemove(step) {
step.ui.remove();
$("#steps .container:nth-last-child(1) .insert-step").prop('disabled',true);
$('div[class*=imgareaselect-]').remove();
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
// Enable the load-image insert-step button when there are steps after load-image
// The logical operator is `> 2` because the number of steps is found before removing the step, actual logic is `steps.length - 1 > 1` which is later simplified.
if (_sequencer.steps.length - 1 > 1) $('#load-image .insert-step').prop('disabled', false);
else $('#load-image .insert-step').prop('disabled', true);
$(step.imgElement).imgAreaSelect({
remove: true
});
}
function getPreview() {
return step.imgElement;
}
function notify(msg,id){
if ($('#'+id).length == 0) {
/**
* @method notify
* @description General purpose DOM toast notification
* @param {String} msg Message to be displayed
* @param {String} id A unique identifier for the notification
* @returns {Null}
*/
function notify(msg, id){
if ($('#' + id).length == 0) {
var notification = document.createElement('span');
notification.innerHTML = ' <i class="fa fa-info-circle" aria-hidden="true"></i> ' + msg ;
notification.id = id;
notification.classList.add("notification");
notification.classList.add('notification');
$('body').append(notification);
}
$('#'+id).fadeIn(500).delay(200).fadeOut(500);
$('#' + id).fadeIn(500).delay(200).fadeOut(500);
}
return {
getPreview: getPreview,
onSetup: onSetup,
onComplete: onComplete,
onRemove: onRemove,
onDraw: onDraw,
onDraw: onDraw,
notify: notify,
imageHover: imageHover
}
imageHover: imageHover,
updateDimensions: updateDimensions
};
}
if(typeof window === "undefined"){
module.exports={
if(typeof window === 'undefined'){
module.exports = {
DefaultHtmlStepUi: DefaultHtmlStepUi
}
};
}
module.exports = DefaultHtmlStepUi;

View File

@@ -1,55 +1,78 @@
function generatePreview(previewStepName, customValues, path, selector) {
var previewSequencer = ImageSequencer();
function insertPreview(src) {
var img = document.createElement('img');
img.classList.add('img-thumbnail')
img.classList.add('no-border');
img.src = src;
$(img).css("max-width", "200%");
$(img).css("transform", "translateX(-20%)");
var stepDiv = $('#'+selector+' .row').find('div').each(function() {
if ($(this).find('div').attr('data-value') === previewStepName) {
$(this).find('div').append(img);
}
});
}
function loadPreview() {
if (previewStepName === "crop") {
previewSequencer.addSteps(previewStepName, customValues).run(insertPreview);
// Generate downscaled preview images for quick buttons.
function generatePreview(previewStepName, customValues, path, DomNode) {
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%)');
$(DomNode.querySelector('.radio-group')).find('.radio').each(function() {
if ($(this).attr('data-value') === previewStepName) {
$(this).append(img);
}
else {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
previewSequencer.loadImage(path, loadPreview);
}
function updatePreviews(src, selector) {
$('#'+selector+' img').remove();
var previewSequencerSteps = {
"resize": "125%",
"brightness": "175",
"saturation": "0.5",
"rotate": 90,
"contrast": 90,
"crop": {
"x": 0,
"y": 0,
"w": "(50%)",
"h": "(50%)",
"noUI": true
}
}
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
});
}
function loadPreview() {
if (previewStepName === 'crop') {
previewSequencer.addSteps(previewStepName, customValues).run(insertPreview);
}
else {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
if(previewStepName === 'resize')
insertPreview(path);
else
previewSequencer.loadImage(path, loadPreview);
}
function updatePreviews(src, DomNode) {
$(DomNode).find('img').remove();
var previewSequencerSteps = {
'resize': '125%',
'brightness': '175',
'saturation': '0.5',
'rotate': 90,
'contrast': 90,
'crop': {
'x': 0,
'y': 0,
'w': '50%',
'h': '50%',
'noUI': true
}
};
var img = new Image();
img.onload = function(){
var height = img.height;
var width = img.width;
let percentage = (80 / height) * 100; // Take the min resize value that fits the preview area => (new-width/orig_ht) - '80 as the preview area has 80*80 dimension.
percentage = Math.max((80 / width) * 100, percentage); // Make sure that one dimension doesn't resize greater, leading distorting preview-area fitting.
percentage = Math.ceil(percentage);
var sequencer = ImageSequencer();
sequencer.loadImage(src, function(){
this.addSteps('resize', {['resize']: percentage + '%'});
this.run((src)=>{
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, DomNode);
});
});
});
};
img.src = src;
}
module.exports = {
generatePreview : generatePreview,
updatePreviews : updatePreviews
}
};

View File

@@ -1,139 +1,172 @@
var urlHash = require('./urlHash.js'),
insertPreview = require('./insertPreview.js');
insertPreview = require('./insertPreview.js');
/**
* @method IntermediateHtmlStepUi
* @description Inserts a module selector in between the current sequence
* @param {Object} _sequencer Sequencer instance
* @param {Object} step Current step variable
* @param {Object} options Optional options Object
* @returns {Object} Object containing the insertStep function
*/
function IntermediateHtmlStepUi(_sequencer, step, options) {
function stepUI() {
return '<div class="row insertDiv">\
<div class="col-md-6 col-md-offset-2" style="margin-top:5%">\
<section id="insertStep" class="panel panel-primary">\
<div class="form-inline">\
<div class="panel-body">\
<p class="info">Select a new module to add to your sequence.</p>\
<div class="row center-align radio-group">\
<div>\
<div class="radio" data-value="resize">\
<i class="fa fa-arrows-alt fa-4x i-over"></i>\
</div>\
<p>Resize</p>\
// Basic markup for the selector
return '<div class="row insertDiv collapse">\
<section class="panel panel-primary .insert-step">\
<button class="btn btn-default close-insert-box"><i class="fa fa-times" aria-hidden="true"></i> Close</button>\
<div class="form-inline">\
<div class="panel-body">\
<p class="info">Select a new module to add to your sequence.</p>\
<div class="row center-align radio-group">\
<div>\
<div class="radio" data-value="resize">\
<i class="fa fa-arrows-alt fa-4x i-over"></i>\
</div>\
<p>Resize</p>\
</div>\
<div>\
<div class="radio" data-value="brightness">\
<i class="fa fa-sun-o fa-4x i-over"></i>\
</div>\
<p>Brightness</p>\
</div>\
<div>\
<div class="radio" data-value="contrast">\
<i class="fa fa-adjust fa-4x i-over"></i>\
</div>\
<p>Contrast</p>\
</div>\
<div>\
<div class="radio" data-value="saturation">\
<i class="fa fa-tint fa-4x i-over i-small"></i>\
</div>\
<p>Saturation</p>\
</div>\
<div>\
<div class="radio" data-value="rotate">\
<i class="fa fa-rotate-right fa-4x i-over"></i>\
</div>\
<p>Rotate</p>\
</div>\
<div>\
<div class="radio" data-value="crop">\
<i class="fa fa-crop fa-4x i-over"></i>\
</div>\
<p>Crop</p>\
</div>\
</div>\
<div>\
<div class="radio" data-value="brightness">\
<i class="fa fa-sun-o fa-4x i-over"></i>\
</div>\
<p>Brightness</p>\
<div class="row center-align">\
<div class="col-md-8">\
<select class="insert-step-select">\
<!-- The default null selection has been appended manually in demo.js\
This is because the options in select are overritten when options are appended.-->\
</select>\
<div>\
<div class="col-md-4">\
<button class="btn btn-primary btn-lg insert-save-btn add-step-btn" name="add">Add Step</button>\
<div>\
</div>\
<div>\
<div class="radio" data-value="contrast">\
<i class="fa fa-adjust fa-4x i-over"></i>\
</div>\
<p>Contrast</p>\
</div>\
<div>\
<div class="radio" data-value="saturation">\
<i class="fa fa-tint fa-4x i-over i-small"></i>\
</div>\
<p>Saturation</p>\
</div>\
<div>\
<div class="radio" data-value="rotate">\
<i class="fa fa-rotate-right fa-4x i-over"></i>\
</div>\
<p>Rotate</p>\
</div>\
<div>\
<div class="radio" data-value="crop">\
<i class="fa fa-crop fa-4x i-over"></i>\
</div>\
<p>Crop</p>\
</div>\
</div>\
<div class="row center-align">\
<div class="col-md-8">\
<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>\
<div>\
<div class="col-md-4">\
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button>\
<div>\
</div>\
</div>\
</div>\
</section>\
</section>\
</div>';
}
/**
* @method toggleDiv
* @description Toggles the module selector dropdown.
* @param {Object} $step $step util function
* @param {Fucntion} callback Optional callback function
* @returns {Null}
*/
var toggleDiv = function($step, callback = function(){}){
$step('.insertDiv').collapse('toggle');
if ($step('.insert-text').css('display') != 'none'){
$step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback);});
}
else {
$step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback);});
}
};
function selectNewStepUi() {
var m = $("#insertStep select").val();
$("#insertStep .info").html(_sequencer.modulesInfo(m).description);
$("#insertStep #add-step-btn").prop("disabled", false);
}
/**
* @method insertStep
* @description Handler to insert selected module in the sequence
* @returns {Null}
*/
insertStep = function (id) {
const $step = step.$step,
$stepAll = step.$stepAll;
var modulesInfo = _sequencer.modulesInfo();
var parser = new DOMParser();
var addStepUI = stepUI();
addStepUI = parser.parseFromString(addStepUI, "text/html").querySelector("div")
step.ui
.querySelector("div.step")
.insertAdjacentElement('afterend',
addStepUI
);
insertPreview.updatePreviews(step.output,'insertStep');
var insertStepSelect = $("#insertStep select");
insertStepSelect.html("");
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
if ($step('.insertDiv').length > 0){
toggleDiv($step);
}
else {
step.ui
.querySelector('div.step')
.insertAdjacentElement('afterend',
addStepUI
);
toggleDiv($step, function(){
if (step.name === 'load-image') insertPreview.updatePreviews(step.output.src, $step('.insertDiv').getDomElem());
else insertPreview.updatePreviews(step.output, $step('.insertDiv').getDomElem());
});
}
$step('.insertDiv .close-insert-box').off('click').on('click', function(){
toggleDiv($step);
$step('.insertDiv').removeClass('insertDiv');
});
var insertStepSelect = $step('.insert-step-select');
insertStepSelect.html('');
// Add modules to the insertStep dropdown
for (var m in modulesInfo) {
if (modulesInfo[m] !== undefined)
if (modulesInfo[m] && modulesInfo[m].name)
insertStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + "</option>"
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
);
}
$('#insertStep #add-step-btn').selectize({
insertStepSelect.selectize({
sortField: 'text'
});
$('#insertStep #add-step-btn').prop('disabled', true);
insertStepSelect.append('<option value="none" disabled selected>More modules...</option>');
$('#insertStep .radio-group .radio').on("click", function () {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
insertStepSelect.val(newStep);
selectNewStepUi();
insert(id);
$(this).removeClass('selected');
$('.insertDiv .radio-group .radio').on('click', function () {
var newStepName = $(this).attr('data-value'); // Get the name of the module to be inserted
id = $($step('.insertDiv').parents()[3]).prevAll().length;
insert(id, $step, newStepName); // Insert the selected module
});
$(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
urlHash.setUrlHashParameter("steps", _sequencer.toString());
$step('.insertDiv .add-step-btn').on('click', function () {
var newStepName = insertStepSelect.val();
id = $($step('.insertDiv').parents()[3]).prevAll().length;
insert(id, $step, newStepName); });
};
/**
* @method insert
* @description Inserts the specified step at the specified index in the sequence
* @param {Number} id Index of the step
* @param {Function} $step $step util function
* @param {String} newStepName Name of the new step
*/
function insert(id, $step, newStepName) {
toggleDiv($step);
$step('.insertDiv').removeClass('insertDiv');
_sequencer.insertSteps(id + 1, newStepName).run({ index: id });
urlHash.setUrlHashParameter('steps', _sequencer.toString());
}
return {
insertStep
}
};
}
module.exports = IntermediateHtmlStepUi;

View File

@@ -1,28 +1,32 @@
/**
* @description Maps module input types to their respective html <input> tag types.
* @param {Object} inputInfo Object containing the type and optionally min/max for range type inputs.
*/
function mapHtmlTypes(inputInfo){
var htmlType;
switch(inputInfo.type.toLowerCase()){
case 'integer':
htmlType = inputInfo.min != undefined ? 'range' : 'number';
break;
case 'string':
htmlType = 'text';
break;
case 'select':
htmlType = 'select';
break;
case 'percentage':
htmlType = 'number';
break;
case 'float':
htmlType = inputInfo.min != undefined ? 'range' : 'text';
break;
default:
htmlType = 'text';
break;
case 'integer':
htmlType = inputInfo.min != undefined ? 'range' : 'number';
break;
case 'string':
htmlType = 'text';
break;
case 'select':
htmlType = 'select';
break;
case 'percentage':
htmlType = 'number';
break;
case 'float':
htmlType = inputInfo.min != undefined ? 'range' : 'text';
break;
default:
htmlType = 'text';
break;
}
var response = inputInfo;
var response = Object.assign({}, inputInfo);
response.type = htmlType;
return response;
}
module.exports = mapHtmlTypes;
module.exports = mapHtmlTypes;

View File

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

View File

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

View File

@@ -0,0 +1,43 @@
/**
* Functions for getting version information.
* Note: these functions are not used by the service worker to check for updates;
* the service worker updates whenever sw.js has changed.
* sw.js is changed when grunt replace:version is run. This task is run during
* grunt build, serve, and productions tasks.
*/
const package = require('../../package.json');
/**
* Get the current version number from package.json on the homepage.
* @param {function} callback The function that uses the version number.
*/
function getLatestVersionNumber(callback) {
// Get the homepage reference from the local package.json.
var homepage = package.homepage;
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
var response = JSON.parse(this.responseText);
var latestVersionNumber = response.version;
// Do something with the version number using a callback function.
if (callback)
callback(latestVersionNumber);
}
}
// Get the package.json file from online using a GET request.
request.open("GET", homepage + "/package.json", true);
request.send();
}
// Get the version number from the local package.json file.
function getLocalVersionNumber() {
return package.version;
}
module.exports = {
getLatestVersionNumber,
getLocalVersionNumber
}

View File

@@ -1,5 +1,4 @@
const staticCacheName = 'image-sequencer-static-v3';
const staticCacheName = 'image-sequencer-static-v3.5.1';
self.addEventListener('install', event => {
console.log('Attempting to install service worker');
});
@@ -17,7 +16,7 @@ self.addEventListener('activate', function(e) {
})
);
})
);
);
});
self.addEventListener('fetch', function(event) {
@@ -25,11 +24,18 @@ self.addEventListener('fetch', function(event) {
caches.open(staticCacheName).then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function(response) {
if(event.request.method == "GET")
if(event.request.method == 'GET')
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
});
// When the update modal sends a 'skipWaiting' message, call the skipWaiting method.
self.addEventListener('message', function(event) {
if(event.data.action === 'skipWaiting') {
self.skipWaiting();
}
});

View File

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

11
jest-puppeteer.config.js Normal file
View File

@@ -0,0 +1,11 @@
module.exports = {
launch: {
headless: process.env.HEADLESS !== 'false',
},
server: {
command: 'grunt serve',
port:3000,
launchTimeout: 5000000,
},
};

6
jest.config.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
preset: 'jest-puppeteer',
testRegex: './*\\.test\\.js$',
verbose: true,
};

11004
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,26 @@
{
"name": "image-sequencer",
"version": "3.0.1",
"version": "3.5.1",
"description": "A modular JavaScript image manipulation library modeled on a storyboard.",
"main": "src/ImageSequencer.js",
"scripts": {
"debug": "TEST=true node ./index.js -i ./examples/images/monarch.png -s invert",
"test": "TEST=true tape test/core/*.js test/core/ui/user-interface.js test/core/modules/QR.js | tap-spec; browserify test/core/modules/image-sequencer.js test/core/modules/chain.js test/core/modules/meta-modules.js test/core/modules/replace.js test/core/modules/import-export.js test/core/modules/run.js test/core/modules/dynamic-imports.js test/core/util/parse-input.js test/core/modules/benchmark.js| tape-run --render=\"tap-spec\"",
"test-ui": "jasmine test/spec/*.js",
"setup": "npm i && npm i -g grunt grunt-cli && grunt build",
"test": "TEST=true istanbul cover tape test/core/*.js test/core/ui/user-interface.js test/core/modules/*.js | tap-spec;",
"benchmark" : "node test/core/sequencer/benchmark.js | tap-spec;",
"gif-test" : "node test/core/gifs/gif-test.js | tap-spec;",
"core-tests" : "cat ./output/core-tests.js | tape-run --render=\"tap-spec\"",
"test-all": "npm run test && npm run benchmark && npm run gif-test && grunt tests && npm run core-tests",
"test-ui": "node node_modules/jasmine/bin/jasmine test/ui/spec/*.js",
"test-ui-2": "node ./node_modules/.bin/jest",
"setup": "npm i && npm i -g grunt grunt-cli && npm rebuild --build-from-source && grunt build",
"start": "grunt serve"
},
"lint-staged": {
"*.js": [
"./node_modules/.bin/eslint --fix",
"git add"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/publiclab/image-sequencer.git"
@@ -24,54 +35,88 @@
"url": "https://github.com/publiclab/image-sequencer/issues"
},
"dependencies": {
"bootstrap": "~3.4.0",
"buffer": "~5.2.1",
"commander": "^2.11.0",
"data-uri-to-buffer": "^2.0.0",
"atob": "^2.1.2",
"base64-img": "^1.0.4",
"bootstrap": "^3.4.1",
"bootstrap-colorpicker": "^2.5.3",
"buffer": "~5.4.0",
"commander": "^4.0.1",
"compressorjs": "^1.0.5",
"data-uri-to-buffer": "^3.0.0",
"downloadjs": "^1.4.7",
"eslint": "^6.1.0",
"fisheyegl": "^0.1.2",
"font-awesome": "~4.7.0",
"geotiff": "^1.0.0-beta.6",
"get-pixels": "~3.3.0",
"gifshot": "^0.4.5",
"glfx": "0.0.4",
"gpu.js": "^2.3.1",
"image-sequencer-invert": "^1.0.0",
"imagejs": "0.0.9",
"imagemin": "^7.0.1",
"imagemin-jpegtran": "^6.0.0",
"imagemin-pngquant": "^8.0.0",
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
"istanbul": "^0.4.5",
"jasmine": "^3.4.0",
"jpegtran-bin": "^4.0.0",
"jquery": "^3.3.1",
"jsdom": "^13.1.0",
"jsdom": "^15.0.0",
"jspdf": "^1.5.3",
"jsqr": "^1.1.1",
"lodash": "^4.17.11",
"ndarray-gaussian-filter": "^1.0.0",
"ora": "^3.0.0",
"ndarray": "^1.0.18",
"opencv.js": "^1.2.1",
"ora": "^4.0.3",
"pace": "0.0.4",
"pngquant-bin": "^5.0.2",
"puppeteer": "^1.14.0",
"qrcode": "^1.3.3",
"readline-sync": "^1.4.7",
"save-pixels": "~2.3.4",
"selectize": "^0.12.6",
"urify": "^2.1.1"
"spawn-sync": "^2.0.0",
"urify": "^2.1.1",
"webgl-distort": "0.0.2"
},
"devDependencies": {
"base64-img": "^1.0.4",
"browserify": "16.2.3",
"@babel/core": "^7.4.3",
"@babel/plugin-proposal-object-rest-spread": "^7.4.3",
"@babel/plugin-syntax-object-rest-spread": "^7.2.0",
"babelify": "^10.0.0",
"browserify": "16.5.0",
"eslint": "^6.1.0",
"grunt": "^1.0.3",
"grunt-browser-sync": "^2.2.0",
"grunt-browserify": "^5.0.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-uglify-es": "^3.3.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-text-replace": "^0.4.0",
"husky": "^3.0.5",
"image-filter-core": "~2.0.2",
"image-filter-threshold": "~2.0.1",
"jasmine-core": "^3.3.0",
"jasmine-jquery": "^2.1.1",
"jasmine-spec-reporter": "^4.2.1",
"jest": "^25.1.0",
"jest-puppeteer": "^4.3.0",
"lint-staged": "^10.0.3",
"looks-same": "^7.0.0",
"matchdep": "^2.0.0",
"tap-spec": "^5.0.0",
"tape": "^4.9.2",
"tape-run": "^5.0.0",
"tape-run": "^6.0.0",
"uglify-es": "^3.3.7"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"homepage": "https://sequencer.publiclab.org",
"bin": {
"sequencer": "./index.js"
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,30 +1,48 @@
if (typeof window !== 'undefined') { isBrowser = true }
else { var isBrowser = false }
if (typeof window !== 'undefined') { isBrowser = true; }
else { var isBrowser = false; }
require('./util/getStep.js');
/**
* @method ImageSequencer
* @param {Object|Float32Array} options Optional options
* @returns {Object}
*/
ImageSequencer = function ImageSequencer(options) {
var sequencer = (this.name == "ImageSequencer") ? this : this.sequencer;
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
var sequencer = (this.name == 'ImageSequencer') ? this : this.sequencer;
options = options || {};
options.inBrowser = options.inBrowser === undefined ? isBrowser : options.inBrowser;
options.sequencerCounter = 0;
function objTypeOf(object) {
return Object.prototype.toString.call(object).split(" ")[1].slice(0, -1)
return Object.prototype.toString.call(object).split(' ')[1].slice(0, -1);
}
/**
* @method log
* @description Logs colored messages to the console using ASCII color codes
* @param {String} color ASCII color code
* @param {String} msg Message to be logged to the console
*/
function log(color, msg) {
if (options.ui != "none") {
if (options.ui != 'none') {
if (arguments.length == 1) console.log(arguments[0]);
else if (arguments.length == 2) console.log(color, msg);
}
}
/**
* @method copy
* @description Returns a clone of the input object.
* @param {Object|Float32Array} a The Object/Array to be cloned
* @returns {Object|Float32Array}
*/
function copy(a) {
if (!typeof (a) == "object") return a;
if (objTypeOf(a) == "Array") return a.slice();
if (objTypeOf(a) == "Object") {
var b = {};
if (!typeof (a) == 'object') return a;
if (objTypeOf(a) == 'Array') return a.slice();
if (objTypeOf(a) == 'Object') {
var b = {};
for (var v in a) {
b[v] = copy(a[v]);
}
@@ -34,7 +52,7 @@ ImageSequencer = function ImageSequencer(options) {
}
function makeArray(input) {
return (objTypeOf(input) == "Array") ? input : [input];
return (objTypeOf(input) == 'Array') ? input : [input];
}
var image,
@@ -52,10 +70,10 @@ ImageSequencer = function ImageSequencer(options) {
for (o in sequencer) {
modules[o] = sequencer[o];
}
sequences = JSON.parse(window.localStorage.getItem('sequences'));
sequences = JSON.parse(window.localStorage.getItem('sequences')); // Get saved sequences from localStorage
if (!sequences) {
sequences = {};
window.localStorage.setItem('sequences', JSON.stringify(sequences));
window.localStorage.setItem('sequences', JSON.stringify(sequences)); // Set the localStorage entry as an empty Object by default
}
}
@@ -63,103 +81,132 @@ ImageSequencer = function ImageSequencer(options) {
// if (options.imageSelect || options.inBrowser) addStep('image-select');
// else if (options.imageUrl) loadImage(imageUrl);
/**
* @method addSteps
* @description Adds one of more steps to the sequence.
* @return {Object}
*/
function addSteps() {
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
var json_q = {};
for (var arg in arguments) { args.push(copy(arguments[arg])); }
json_q = formatInput.call(this_, args, "+");
for (var arg in arguments) { args.push(copy(arguments[arg])); } // Get all the module names from the arguments
json_q = formatInput.call(this_, args, '+');
inputlog.push({ method: "addSteps", json_q: copy(json_q) });
for (var j in json_q)
require("./AddStep")(this_, json_q[j].name, json_q[j].o);
inputlog.push({ method: 'addSteps', json_q: copy(json_q) });
for (var j in json_q)
require('./AddStep')(this_, json_q[j].name, json_q[j].o);
return this;
}
/**
* @method removeStep
* @description Removes the step at the specified index from the sequence.
* @param {Object} ref ImageSequencer instance
* @param {Number} index Index of the step to be removed
* @returns {Null}
*/
function removeStep(ref, index) {
//remove the step from images[image].steps and redraw remaining images
// Remove the step from images[image].steps and redraw remaining images
if (index > 0) {
//var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
// var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
thisStep = ref.steps[index];
thisStep.UI.onRemove(thisStep.options.step);
ref.steps.splice(index, 1);
}
//tell the UI a step has been removed
}
function removeSteps(index) {
/**
* @method removeSteps
* @description Removes one or more steps from the sequence
* @returns {Object}
*/
function removeSteps() {
var indices;
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this_, args, "-");
inputlog.push({ method: "removeSteps", json_q: copy(json_q) });
var json_q = formatInput.call(this_, args, '-');
inputlog.push({ method: 'removeSteps', json_q: copy(json_q) });
indices = json_q.sort(function(a, b) { return b - a });
for (var i in indices)
removeStep(this_, indices[i]);
indices = json_q.sort(function(a, b) { return b - a; });
for (var i in indices)
removeStep(this_, indices[i]);
return this;
}
function insertSteps(image, index, name, o) {
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = []
/**
* @method insertSteps
* @description Inserts steps at the specified index
* @returns {Object}
*/
function insertSteps() {
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(arguments[arg]);
var json_q = formatInput.call(this_, args, "^");
inputlog.push({ method: "insertSteps", json_q: copy(json_q) });
var json_q = formatInput.call(this_, args, '^');
inputlog.push({ method: 'insertSteps', json_q: copy(json_q) });
var details = json_q;
details = details.sort(function(a, b) { return b.index - a.index });
for (var i in details)
require("./InsertStep")(this_, details[i].index, details[i].name, details[i].o);
var details = json_q;
details = details.sort(function(a, b) { return b.index - a.index; });
for (var i in details)
require('./InsertStep')(this_, details[i].index, details[i].name, details[i].o);
return this;
}
// Config is an object which contains the runtime configuration like progress bar
// information and index from which the sequencer should run
function run(config, t_image, t_from) {
/**
* @method run
* @param {Object} config Object which contains the runtime configuration like progress bar information and index from which the sequencer should run.
* @returns {Boolean}
*/
function run(config) {
var progressObj, index = 0;
config = config || { mode: 'no-arg' };
if (config.index) index = config.index;
if (config.mode != "no-arg" && typeof config != 'function') {
if (config.progressObj) progressObj = config.progressObj;
delete arguments['0'];
}
if (config.mode != 'no-arg' && typeof config != 'function') {
if (config.progressObj) progressObj = config.progressObj;
delete arguments['0'];
}
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(copy(arguments[arg]));
var callback = function() { };
for (var arg in args)
if (objTypeOf(args[arg]) == "Function")
callback = args.splice(arg, 1)[0]; //callback is formed
if (objTypeOf(args[arg]) == 'Function')
callback = args.splice(arg, 1)[0]; // Callback is formed
var json_q = formatInput.call(this_, args, "r");
var json_q = formatInput.call(this_, args, 'r');
require('./Run')(this_, json_q, callback, index, progressObj);
return true;
}
/**
* @method loadImages
* @description Loads an image via dataURL or normal URL. Read the docs(https://github.com/publiclab/image-sequencer/blob/main/README.md) for more info.
* @returns {Null}
*/
function loadImages() {
var args = [];
var prevSteps = this.getSteps().slice(1).map(step=>step.options.name)
var prevSteps = this.getSteps().slice(1).map(step=>step.options.name);
var sequencer = this;
sequencer.image = arguments[0];
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this, args, "l");
if(this.getSteps().length!=0){
var json_q = formatInput.call(this, args, 'l');
if(this.getSteps().length != 0){
this.options.sequencerCounter = 0;
inputlog = [];
this.steps = [];
}
inputlog.push({ method: "loadImages", json_q: copy(json_q) });
inputlog.push({ method: 'loadImages', json_q: copy(json_q) });
var ret = {
name: "ImageSequencer Wrapper",
name: 'ImageSequencer Wrapper',
sequencer: this,
addSteps: this.addSteps,
removeSteps: this.removeSteps,
@@ -169,40 +216,64 @@ ImageSequencer = function ImageSequencer(options) {
setUI: this.setUI
};
function loadPrevSteps(ref){
if(prevSteps.length!=0){
ref.addSteps(prevSteps)
prevSteps=[];
if(prevSteps.length != 0){
ref.addSteps(prevSteps);
prevSteps = [];
}
}
require('./ui/LoadImage')(sequencer, "image", json_q.image, function() {
require('./ui/LoadImage')(sequencer, 'image', json_q.image, function() {
loadPrevSteps(sequencer);
json_q.callback.call(ret);
});
}
/**
* @method replaceImage
* @description Replaces the current image in the sequencer
* @param {String} selector DOM selector string for the image input
* @param {*} steps Current steps Object
* @param {Object} options
* @returns {*}
*/
function replaceImage(selector, steps, options) {
options = options || {};
options.callback = options.callback || function() { };
return require('./ReplaceImage')(this, selector, steps, options);
}
//returns the steps added
/**
* @method getSteps
* @description Returns the current sequence of steps
* @returns {Object}
*/
function getSteps(){
return this.steps;
}
/**
* @method setUI
* @description To set up a UI for ImageSequencer via different callback methods. Read the docs(https://github.com/publiclab/image-sequencer/blob/main/README.md) for more info.
* @param {Object} UI Object containing UI callback methods. Read the docs(https://github.com/publiclab/image-sequencer/blob/main/README.md) for more info.
* @returns {Null}
*/
function setUI(UI) {
this.events = require('./ui/UserInterface')(UI);
}
var exportBin = function(dir, basic, filename) {
return require('./ExportBin')(dir, this, basic, filename);
}
};
/**
* @method modulesInfo
* @description Returns information about the given module or all the available modules
* @param {String} name Module name
* @returns {Object}
*/
function modulesInfo(name) {
var modulesdata = {}
if (name == "load-image") return {};
var modulesdata = {};
if (name == 'load-image') return {};
if (arguments.length == 0) {
for (var modulename in this.modules) {
modulesdata[modulename] = modules[modulename][1];
@@ -212,150 +283,39 @@ ImageSequencer = function ImageSequencer(options) {
}
}
else {
if (modules[name]){
modulesdata = modules[name][1];
}
if (modules[name]){
modulesdata = modules[name][1];
}
else
modulesdata = { 'inputs': sequences[name]['options'] };
}
return modulesdata;
}
// Genates a CLI string for the current sequence
function toCliString() {
var cliStringSteps = `"`, cliOptions = {};
for (var step in this.steps) {
var name = (typeof this.steps[step].options !== "undefined")? this.steps[step].options.name : this.steps[step].name
if (name !== "load-image"){
cliStringSteps += `${name} `;
}
for (var inp in modulesInfo(name).inputs) {
cliOptions[inp] = this.steps[step].options[inp];
}
}
cliStringSteps = cliStringSteps.substr(0, cliStringSteps.length - 1) + `"`;
return `sequencer -i [PATH] -s ${cliStringSteps} -d '${JSON.stringify(cliOptions)}'`
}
// Strigifies the current sequence
function toString(step) {
if (step) {
return stepToString(step);
} else {
return copy(this.steps.map(stepToString).slice(1).join(','));
}
}
// Stringifies one step of the sequence
function stepToString(step) {
var arg = (step.name)?step.name:step.options.name;
let inputs = modulesInfo(arg).inputs || {}, op = {};
for (let input in inputs) {
if (!!step.options[input] && step.options[input] != inputs[input].default) {
op[input] = step.options[input];
op[input] = encodeURIComponent(op[input]);
}
}
var configurations = Object.keys(op).map(key => key + ':' + op[key]).join('|');
return `${arg}{${configurations}}`;
}
// exports the current sequence as an array of JSON steps
function toJSON() {
return this.stringToJSON(this.toString());
}
// Coverts stringified sequence into an array of JSON steps
function stringToJSON(str) {
let steps;
if (str.includes(','))
steps = str.split(',');
else
steps = [str];
return steps.map(stringToJSONstep);
}
// Converts one stringified step into JSON
function stringToJSONstep(str) {
var bracesStrings;
if (str.includes('{'))
if (str.includes('(') && str.indexOf('(') < str.indexOf('{'))
bracesStrings = ['(', ')'];
else
bracesStrings = ['{', '}'];
else
bracesStrings = ['(', ')'];
if (str.indexOf(bracesStrings[0]) === -1) { // if there are no settings specified
var moduleName = str.substr(0);
stepSettings = "";
} else {
var moduleName = str.substr(0, str.indexOf(bracesStrings[0]));
stepSettings = str.slice(str.indexOf(bracesStrings[0]) + 1, -1);
}
stepSettings = stepSettings.split('|').reduce(function formatSettings(accumulator, current, i) {
var settingName = current.substr(0, current.indexOf(':')),
settingValue = current.substr(current.indexOf(':') + 1);
settingValue = settingValue.replace(/^\(/, '').replace(/\)$/, ''); // strip () at start/end
settingValue = settingValue.replace(/^\{/, '').replace(/\}$/, ''); // strip {} at start/end
settingValue = decodeURIComponent(settingValue);
current = [
settingName,
settingValue
];
if (!!settingName) accumulator[settingName] = settingValue;
return accumulator;
}, {});
return {
name: moduleName,
options: stepSettings
}
}
// imports a string into the sequencer steps
function importString(str) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
var stepsFromString = stringToJSON(str);
stepsFromString.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// imports a array of JSON steps into the sequencer steps
function importJSON(obj) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
obj.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
/**
* @method loadNewModule
* @description Adds a new local module to sequencer. Read the docs(https://github.com/publiclab/image-sequencer/blob/main/README.md) for mode info.
* @param {String} name Name of the new module
* @param {Object} options An Object containing path and info about the new module.
* @returns {Object}
*/
function loadNewModule(name, options) {
if (!options) {
return this;
} else if (Array.isArray(options)) {
// contains the array of module and info
// Contains the array of module and info
this.modules[name] = options;
} else if (options.func && options.info) {
// passed in options object
// Passed in options object
this.modules[name] = [
options.func, options.info
];
} else if (options.path && !this.inBrowser) {
// load from path(only in node)
// Load from path(only in node)
const module = [
require(`${options.path}/Module.js`),
require(`${options.path}/info.json`)
@@ -365,18 +325,32 @@ ImageSequencer = function ImageSequencer(options) {
return this;
}
/**
* @method saveNewModule
* @description Saves a new local module to ImageSequencer
* @param {String} name Name of the new module
* @param {String} path Path to the new module
* @returns {Null}
*/
function saveNewModule(name, path) {
if (options.inBrowser) {
// Not for browser context
return;
}
var mods = fs.readFileSync('./src/Modules.js').toString();
mods = mods.substr(0, mods.length - 1) + " '" + name + "': require('" + path + "'),\n}";
mods = mods.substr(0, mods.length - 1) + ' \'' + name + '\': require(\'' + path + '\'),\n}';
fs.writeFileSync('./src/Modules.js', mods);
}
function saveSequence(name, sequenceString) {
const sequence = stringToJSON(sequenceString);
/**
* @method saveSequence
* @description Saves a sequence on the browser localStorage.
* @param {String} name Name for the sequence
* @param {String} sequenceString Sequence data as a string
* @returns {Null}
*/
function saveSequence(name, sequenceString) { // 4. save sequence
const sequence = str.stringToJSON(sequenceString);
// Save the given sequence string as a module
if (options.inBrowser) {
// Inside the browser we save the meta-modules using the Web Storage API
@@ -393,7 +367,7 @@ ImageSequencer = function ImageSequencer(options) {
}
function loadModules() {
// This function loads the modules and saved sequences
// loadModules function loads the modules and saved sequences.
this.modules = require('./Modules');
if (options.inBrowser)
this.sequences = JSON.parse(window.localStorage.getItem('sequences'));
@@ -401,9 +375,10 @@ ImageSequencer = function ImageSequencer(options) {
this.sequences = require('./SavedSequences.json');
}
return {
//literals and objects
name: "ImageSequencer",
// Literals and objects
name: 'ImageSequencer',
options: options,
inputlog: inputlog,
modules: modules,
@@ -412,7 +387,7 @@ ImageSequencer = function ImageSequencer(options) {
steps: steps,
image: image,
//user functions
// User functions
loadImages: loadImages,
loadImage: loadImages,
addSteps: addSteps,
@@ -423,14 +398,17 @@ ImageSequencer = function ImageSequencer(options) {
setUI: setUI,
exportBin: exportBin,
modulesInfo: modulesInfo,
toCliString: toCliString,
toString: toString,
stepToString: stepToString,
toJSON: toJSON,
stringToJSON: stringToJSON,
stringToJSONstep: stringToJSONstep,
importString: importString,
importJSON: importJSON,
toCliString: str.toCliString,
detectStringSyntax: str.detectStringSyntax,
parseStringSyntax: str.parseStringSyntax,
stringToSteps: str.stringToSteps,
toString: str.toString,
stepToString: str.stepToString,
toJSON: str.toJSON,
stringToJSON: str.stringToJSON,
stringToJSONstep: str.stringToJSONstep,
importString: str.importString,
importJSON: str.importJSON,
loadNewModule: loadNewModule,
saveNewModule: saveNewModule,
createMetaModule: require('./util/createMetaModule'),
@@ -438,13 +416,14 @@ ImageSequencer = function ImageSequencer(options) {
loadModules: loadModules,
getSteps:getSteps,
//other functions
// Other functions
log: log,
objTypeOf: objTypeOf,
copy: copy,
getImageDimensions: require('./util/getImageDimensions'),
setInputStep: require('./ui/SetInputStep')(sequencer)
}
};
}
};
module.exports = ImageSequencer;

View File

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

View File

@@ -5,11 +5,15 @@ module.exports = {
'add-qr': require('./modules/AddQR'),
'average': require('./modules/Average'),
'blend': require('./modules/Blend'),
'blob-analysis': require('./modules/BlobAnalysis'),
'blur': require('./modules/Blur'),
'brightness': require('./modules/Brightness'),
'canvas-resize': require('./modules/CanvasResize'),
'channel': require('./modules/Channel'),
'colorbar': require('./modules/Colorbar'),
'color-temperature': require('./modules/ColorTemperature'),
'colormap': require('./modules/Colormap'),
'constrained-crop': require('./modules/ConstrainedCrop'),
'contrast': require('./modules/Contrast'),
'convolution': require('./modules/Convolution'),
'crop': require('./modules/Crop'),
@@ -24,18 +28,23 @@ module.exports = {
'histogram': require('./modules/Histogram'),
'gamma-correction': require('./modules/GammaCorrection'),
'gradient': require('./modules/Gradient'),
'grid-overlay': require('./modules/GridOverlay'),
'import-image': require('./modules/ImportImage'),
'invert': require('image-sequencer-invert'),
'minify-image': require('./modules/MinifyImage'),
// 'invert': require('image-sequencer-invert'),
'invert': require('./modules/Invert'),
'ndvi': require('./modules/Ndvi'),
'ndvi-colormap': require('./modules/NdviColormap'),
'paint-bucket': require('./modules/PaintBucket'),
'noise-reduction': require('./modules/NoiseReduction'),
'overlay': require('./modules/Overlay'),
'replace-color':require('./modules/ReplaceColor'),
'paint-bucket': require('./modules/PaintBucket'),
'replace-color': require('./modules/ReplaceColor'),
'resize': require('./modules/Resize'),
'rotate': require('./modules/Rotate'),
'saturation': require('./modules/Saturation'),
'text-overlay': require('./modules/TextOverlay'),
'threshold': require('./modules/Threshold'),
'tint': require('./modules/Tint'),
'color-temperature': require('./modules/ColorTemperature')
}
'webgl-distort': require('./modules/WebglDistort'),
'white-balance': require('./modules/WhiteBalance')
};

View File

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

View File

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

View File

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

159
src/Strings.js Normal file
View File

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

View File

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

View File

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

View File

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

View File

@@ -1,51 +1,64 @@
const _ = require('lodash'),
parseCornerCoordinateInputs = require('../../util/ParseInputCoordinates');
module.exports = function AddQR(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.size = options.size || defaults.size;
options.qrCodeString = options.qrCodeString || "https://github.com/publiclab/image-sequencer";
var output;
getPixels = require('get-pixels');
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
getPixels = require('get-pixels');
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
options.size = Number(options.size || defaults.size);
options.qrCodeString = options.qrCodeString || defaults.qrCodeString;
options.startingX = options.startingX || defaults.startingX;
options.startingY = options.startingY || defaults.startingY;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
return getPixels(input.src, function (err, oldPixels) {
function changePixel(r, g, b, a) {
return [r, g, b, a];
}
function extraManipulation(pixels,generateOutput) {
if (err) {
console.log(err);
return;
}
require('./QR')(options, pixels, oldPixels, generateOutput);
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
}
function extraManipulation(pixels, setRenderState, generateOutput) {
let iw = pixels.shape[0], // Width of Original Image
ih = pixels.shape[1]; // Height of Original Image
const oldPixels = _.cloneDeep(pixels);
setRenderState(false); // Prevent rendering of final output image until extraManipulation completes.
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
})
// Parse the inputs.
parseCornerCoordinateInputs({iw, ih},
{
startingX: { valInp: options.startingX, type: 'horizontal'},
startingY: { valInp: options.startingY, type: 'vertical' },
}, function(opt, cord){
options.startingX = Math.floor(cord.startingX.valInp);
options.startingY = Math.floor(cord.startingY.valInp);
});
require('./QR')(options, pixels, oldPixels, () => {
setRenderState(true); // Allow rendering in the callback.
generateOutput();
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

@@ -1,48 +1,37 @@
module.exports = exports = function (options, pixels, oldPixels, callback) {
var QRCode = require('qrcode')
QRCode.toDataURL(options.qrCodeString, function (err, url) {
var getPixels = require("get-pixels");
getPixels(url, function (err, qrPixels) {
if (err) {
console.log("Bad image path", image);
}
const pixelSetter = require('../../util/pixelSetter.js'),
getPixels = require('get-pixels'),
QRCode = require('qrcode');
module.exports = exports = function (options, pixels, oldPixels, cb) {
var imagejs = require('imagejs');
var bitmap = new imagejs.Bitmap({ width: qrPixels.shape[0], height: qrPixels.shape[1] });
bitmap._data.data = qrPixels.data;
var resized = bitmap.resize({
width: options.size, height: options.size,
algorithm: "bicubicInterpolation"
});
QRCode.toDataURL(options.qrCodeString, {width: options.size, scale: 1}, function (error, url) {
getPixels(url, function (err, qrPixels) {
if (err) {
console.log('get-pixels error: ', err);
}
qrPixels.data = resized._data.data;
qrPixels.shape = [options.size, options.size, 4];
qrPixels.stride[1] = 4 * options.size;
const width = oldPixels.shape[0],
height = oldPixels.shape[1];
var width = oldPixels.shape[0],
height = oldPixels.shape[1];
var xe = width - options.size,
ye = height - options.size;
for (var m = 0; m < width; m++) {
for (var n = 0; n < height; n++) {
if (m >= xe && n >= ye) {
pixels.set(m, n, 0, qrPixels.get(m - xe, n - ye, 0))
pixels.set(m, n, 1, qrPixels.get(m - xe, n - ye, 1))
pixels.set(m, n, 2, qrPixels.get(m - xe, n - ye, 2))
pixels.set(m, n, 3, qrPixels.get(m - xe, n - ye, 3))
}
const xe = Math.min(options.startingX, width - options.size), // Starting pixel coordinates
ye = Math.min(options.startingY, height - options.size);
else {
pixels.set(m, n, 0, oldPixels.get(m, n, 0))
pixels.set(m, n, 1, oldPixels.get(m, n, 1))
pixels.set(m, n, 2, oldPixels.get(m, n, 2))
pixels.set(m, n, 3, oldPixels.get(m, n, 3))
}
for (let x = xe; x < Math.min(xe + options.size, width); x++) {
for (let y = ye; y < Math.min(ye + options.size, height); y++) {
pixelSetter(
x,
y,
[
qrPixels.get(x - xe, y - ye, 0),
qrPixels.get(x - xe, y - ye, 1),
qrPixels.get(x - xe, y - ye, 2),
qrPixels.get(x - xe, y - ye, 3)
],
pixels
);
}
}
}
}
callback();
})
})
}
if(cb) cb();
});
});
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Add QR",
"name": "add-qr",
"description": "Adds QR corresponding to the given string",
"url": "https://github.com/publiclab/image-sequencer/tree/master/MODULES.md",
"inputs": {
@@ -12,6 +12,16 @@
"type": "string",
"desc": "input string to generate QR code",
"default": "https://github.com/publiclab/image-sequencer"
},
"startingX": {
"type": "string",
"desc": "X-position (measured from left) from where QR starts",
"default": "0"
},
"startingY": {
"type": "string",
"desc": "Y-position (measured from top) from where QR starts",
"default": "0"
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#add-qr-module"

View File

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

View File

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

View File

@@ -1,7 +1,13 @@
{
"name": "Average",
"name": "average",
"description": "Average all pixel color",
"inputs": {
},
"outputs": {
"average": {
"type": "string",
"desc": "The average value of all the pixels."
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#average-module"
}

View File

@@ -1,75 +1,132 @@
module.exports = function Dynamic(options, UI, util) {
module.exports = function Blend(options, UI, util) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.func = options.func || defaults.blend;
options.offset = options.offset || defaults.offset;
options.func = options.blend || defaults.blend;
options.offset = options.offset || defaults.offset;
options.blendMode = options.blendMode || defaults.blendMode;
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);
var getPixels = require('get-pixels');
var getPixels = require('get-pixels');
// convert offset as string to int
if (typeof options.offset === 'string') options.offset = parseInt(options.offset);
// convert offset as string to int
if (typeof options.offset === "string") options.offset = parseInt(options.offset);
// save first image's pixels
var priorStep = this.getStep(options.offset);
// save first image's pixels
var priorStep = this.getStep(options.offset);
if (priorStep.output === undefined) {
this.output = input;
UI.notify('Offset Unavailable', 'offset-notification');
callback();
}
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
let p = options.firstImagePixels;
return options.func(
r2, g2, b2, a2,
p.get(x, y, 0),
p.get(x, y, 1),
p.get(x, y, 2),
p.get(x, y, 3)
)
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
// run PixelManipulatin on second image's pixels
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
});
if (priorStep.output === undefined) {
this.output = input;
UI.notify('Offset Unavailable', 'offset-notification');
callback();
}
return {
options: options,
draw: draw,
// see http://docs.gimp.org/en/gimp-concepts-layer-modes.html for other blend modes
const multiply_mode = function (i, m) {
return ~~( (i * m) / 255 );
};
const divide_mode = function (i, m) {
return ~~( (256 * i) / (m + 1) );
};
const overlay_mode = function (i, m) {
return ~~( (i / 255) * (i + ((2 * m) / 255) * (255 - i)) );
};
const screen_mode = function (i, m) {
return ~~( 255 - ((255 - m) * (255 - i)) / 255 );
};
const sof_light_mode = function (i, m) {
var Rs = screen_mode(i, m);
return ~~( ((((255 - i) * m) + Rs) * i) / 255 );
};
const color_dodge = function (i, m) {
return ~~( (256 * i) / (255 - m + 1) );
};
const burn_mode = function (i, m) {
return ~~( 255 - (256 * (255 - i)) / (m + 1));
};
const grain_extract_mode = function (i, m) {
return ~~( i - m + 128 );
};
const grain_merge_mode = function (i, m) {
return ~~( i + m - 128 );
};
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
// Convert to runnable code.
if (typeof options.func === 'string') eval('options.func = ' + options.func);
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
let p = options.firstImagePixels;
let r1 = p.get(x, y, 0),
g1 = p.get(x, y, 1),
b1 = p.get(x, y, 2),
a1 = p.get(x, y, 3);
const blends = {
'Color Dodge': () => [color_dodge(r2, r1), color_dodge(g2, g1), color_dodge(b2, b1), 255],
'Multiply': () => [multiply_mode(r2, r1), multiply_mode(g2, g1), multiply_mode(b2, b1), multiply_mode(a2, a1)],
'Divide': () => [divide_mode(r2, r1), divide_mode(g2, g1), divide_mode(b2, b1), 255],
'Overlay': () => [overlay_mode(r2, r1), overlay_mode(g2, g1), overlay_mode(b2, b1), 255],
'Screen': () => [screen_mode(r2, r1), screen_mode(g2, g1), screen_mode(b2, b1), 255],
'Soft Light': () => [sof_light_mode(r2, r1), sof_light_mode(g2, g1), sof_light_mode(b2, b1), 255],
'Color Burn': () => [burn_mode(r2, r1), burn_mode(g2, g1), burn_mode(b2, b1), 255],
'Grain Extract': () => [grain_extract_mode(r2, r1), grain_extract_mode(g2, g1), grain_extract_mode(b2, b1), 255],
'Grain Merge': () => [grain_merge_mode(r2, r1), grain_merge_mode(g2, g1), grain_merge_mode(b2, b1), 255]
};
if(options.blendMode == 'custom')
return options.func(
r2, g2, b2, a2, r1, g1, b1, a1
);
else {
return blends[options.blendMode]();
}
}
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
// run PixelManipulatin on second image's pixels
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
UI: UI
}
}
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,17 +1,34 @@
{
"name": "Blend",
"description": "Blend two chosen image steps with the given function. Defaults to using the red channel from image 1 and the green and blue and alpha channels of image 2. Easier to use interfaces coming soon!",
"name": "blend",
"description": "Blend two chosen image steps with the given function. Defaults to using the red channel from image 1 and the green and blue and alpha channels of image 2.",
"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
},
"blendMode": {
"type": "select",
"desc": "Name of the Blend Mode to use",
"default": "custom",
"values": [
"custom",
"Multiply",
"Divide",
"Overlay",
"Screen",
"Soft Light",
"Color Burn",
"Color Dodge",
"Grain Extract",
"Grain Merge"
]
},
"blend": {
"type": "string",
"desc": "Function to use to blend the two images.",
"default": "function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] }"
"default": "function(r1, g1, b1, a1, r2, g2, b2, a2, x, y) { return [ r2, g2, b2, a2 ] }"
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#blend-module"
"docs-link": "https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#blend-module"
}

View File

@@ -0,0 +1,74 @@
module.exports = function(pixels){
var canvas = document.createElement('canvas');
canvas.width = pixels.shape[0];
canvas.height = pixels.shape[1];
var ctx = canvas.getContext('2d');
ctx.putImageData(new ImageData(new Uint8ClampedArray(pixels.data), pixels.shape[0], pixels.shape[1]), 0, 0);
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let src = cv.matFromImageData(imgData);
let dst = new cv.Mat();
let gray = new cv.Mat();
let opening = new cv.Mat();
let imageBg = new cv.Mat();
let imageFg = new cv.Mat();
let distTrans = new cv.Mat();
let unknown = new cv.Mat();
let markers = new cv.Mat();
// Gray and Threshold the image
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
// Get background
let M = cv.Mat.ones(3, 3, cv.CV_8U);
cv.erode(gray, gray, M);
cv.dilate(gray, opening, M);
cv.dilate(opening, imageBg, M, new cv.Point(-1, -1), 3);
// Distance transform
cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
// Get foreground
cv.threshold(distTrans, imageFg, 0.7 * 1, 255, cv.THRESH_BINARY);
imageFg.convertTo(imageFg, cv.CV_8U, 1, 0);
cv.subtract(imageBg, imageFg, unknown);
// Get connected components markers
cv.connectedComponents(imageFg, markers);
for (let i = 0; i < markers.rows; i++) {
for (let j = 0; j < markers.cols; j++) {
markers.intPtr(i, j)[0] = markers.ucharPtr(i, j)[0] + 1;
if (unknown.ucharPtr(i, j)[0] == 255) {
markers.intPtr(i, j)[0] = 0;
}
}
}
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
cv.watershed(src, markers);
// Grow barriers
for (let i = 0; i < markers.rows; i++) {
for (let j = 0; j < markers.cols; j++) {
if (markers.intPtr(i, j)[0] == -1) {
src.ucharPtr(i, j)[0] = 255; // Red
src.ucharPtr(i, j)[1] = 0; // Green
src.ucharPtr(i, j)[2] = 0; // Blue
}
}
}
cv.imshow(canvas, src);
src.delete(); dst.delete(); gray.delete(); opening.delete(); imageBg.delete();
imageFg.delete(); distTrans.delete(); unknown.delete(); markers.delete(); M.delete();
var myImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
pixels.data = myImageData.data;
return pixels;
};

View File

@@ -0,0 +1,40 @@
module.exports = function BlobAnalysis(options, UI){
var output;
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function extraManipulation(pixels){
pixels = require('./BlobAnalysis')(pixels);
return pixels;
}
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

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

View File

@@ -1,84 +1,65 @@
// Generates a 5x5 Gaussian kernel
function kernelGenerator(sigma = 1) {
let kernel = [],
sum = 0;
if (sigma == 0) sigma += 0.05;
const s = 2 * Math.pow(sigma, 2);
for (let y = -2; y <= 2; y++) {
kernel.push([]);
for (let x = -2; x <= 2; x++) {
let r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
kernel[y + 2].push(Math.exp(-(r / s)));
sum += kernel[y + 2][x + 2];
}
}
for (let x = 0; x < 5; x++){
for (let y = 0; y < 5; y++){
kernel[y][x] = (kernel[y][x] / sum);
}
}
return kernel;
}
module.exports = exports = function(pixels, blur) {
let kernel = kernelGenerator(blur, 1), oldpix = require('lodash').cloneDeep(pixels);
kernel = flipKernel(kernel);
const pixelSetter = require('../../util/pixelSetter.js');
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let neighboutPos = getNeighbouringPixelPositions([i, j]);
let acc = [0.0, 0.0, 0.0, 0.0];
for (let a = 0; a < kernel.length; a++) {
for (let b = 0; b < kernel.length; b++) {
acc[0] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 0) * kernel[a][b]);
acc[1] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 1) * kernel[a][b]);
acc[2] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 2) * kernel[a][b]);
acc[3] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 3) * kernel[a][b]);
}
}
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
let kernel = kernelGenerator(blur), // Generate the Gaussian kernel based on the sigma input.
pixs = { // Separates the rgb channel pixels to convolve on the GPU.
r: [],
g: [],
b: [],
};
for (let y = 0; y < pixels.shape[1]; y++){
pixs.r.push([]);
pixs.g.push([]);
pixs.b.push([]);
for (let x = 0; x < pixels.shape[0]; x++){
pixs.r[y].push(pixels.get(x, y, 0));
pixs.g[y].push(pixels.get(x, y, 1));
pixs.b[y].push(pixels.get(x, y, 2));
}
return pixels;
}
const convolve = require('../_nomodule/gpuUtils').convolve; // GPU convolution function.
const conPix = convolve([pixs.r, pixs.g, pixs.b], kernel); // Convolves the pixels (all channels separately) on the GPU.
//Generates a 3x3 Gaussian kernel
function kernelGenerator(sigma, size) {
/*
Trying out a variable radius kernel not working as of now
*/
// const coeff = (1.0/(2.0*Math.PI*sigma*sigma))
// const expCoeff = -1 * (1.0/2.0 * sigma * sigma)
// let e = Math.E
// let result = []
// for(let i = -1 * size;i<=size;i++){
// let arr = []
// for(let j= -1 * size;j<=size;j++){
// arr.push(coeff * Math.pow(e,expCoeff * ((i * i) + (j*j))))
// }
// result.push(arr)
// }
// let sum = result.reduce((sum,val)=>{
// return val.reduce((sumInner,valInner)=>{
// return sumInner+valInner
// })
// })
// result = result.map(arr=>arr.map(val=>(val + 0.0)/(sum + 0.0)))
// return result
return [
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[5.0 / 159.0, 12.0 / 159.0, 15.0 / 159.0, 12.0 / 159.0, 5.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0]
];
for (let y = 0; y < pixels.shape[1]; y++){
for (let x = 0; x < pixels.shape[0]; x++){
var pixelvalue = [Math.max(0, Math.min(conPix[0][y][x], 255)),
Math.max(0, Math.min(conPix[1][y][x], 255)),
Math.max(0, Math.min(conPix[2][y][x], 255))];
pixelSetter(x, y, pixelvalue, pixels); // Sets the image pixels according to the blurred values.
}
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0], y = pixelPosition[1], result = [];
}
for (let i = -2; i <= 2; i++) {
let arr = [];
for (let j = -2; j <= 2; j++)
arr.push([x + i, y + j]);
result.push(arr);
}
return result;
}
function flipKernel(kernel) {
let result = [];
for (let i = kernel.length - 1; i >= 0; i--) {
let arr = [];
for (let j = kernel[i].length - 1; j >= 0; j--) {
arr.push(kernel[i][j]);
}
result.push(arr);
}
return result;
}
}
return pixels;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,60 @@
/*
* Changes the Canvas Size
*/
module.exports = function canvasResize(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const pixelSetter = require('../../util/pixelSetter.js');
var output;
function draw(input, callback, progressObj) {
options.width = parseInt(options.width || defaults.width);
options.height = parseInt(options.height || defaults.height);
options.x = parseInt(options.x || defaults.x);
options.y = parseInt(options.y || defaults.y);
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function extraManipulation(pixels) {
let newPixels = require('ndarray')(new Uint8Array(4 * options.width * options.height).fill(0), [options.width, options.height, 4]);
let iMax = options.width - options.x,
jMax = options.height - options.y;
for (let i = 0; i < iMax && i < pixels.shape[0]; i++) {
for (let j = 0; j < jMax && j < pixels.shape[1]; j++) {
let x = i + options.x, y = j + options.y;
pixelSetter(x, y, [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2), pixels.get(i, j, 3)], newPixels);
}
}
return newPixels;
}
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -0,0 +1,27 @@
{
"name": "canvas-resize",
"description": "This module resizes the canvas and overlays the ouput of the previous step at given location",
"inputs": {
"width": {
"type": "integer",
"desc": "Final width of the canvas",
"default": 1000
},
"height": {
"type": "integer",
"desc": "Final height of the canvas",
"default": 1000
},
"x": {
"type": "integer",
"desc": "X-cord of the top left corner of the image on the canvas",
"default": 500
},
"y": {
"type": "float",
"desc": "Y-cord of the top left corner of the image on the canvas",
"default": 500
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#canvas-resize-module"
}

View File

@@ -17,25 +17,24 @@ module.exports = function Channel(options, UI) {
var step = this;
function changePixel(r, g, b, a) {
if (options.channel === "red") return [r, 0, 0, a];
if (options.channel === "green") return [0, g, 0, a];
if (options.channel === "blue") return [0, 0, b, a];
if (options.channel === 'red') return [r, 0, 0, a];
if (options.channel === 'green') return [0, g, 0, a];
if (options.channel === 'blue') return [0, 0, b, a];
}
function output(image, datauri, mimetype) {
// This output is accesible by Image Sequencer
step.output = { src: datauri, format: mimetype };
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
callback: callback,
useWasm:options.useWasm
});
}
@@ -46,5 +45,5 @@ module.exports = function Channel(options, UI) {
draw: draw,
output: output,
UI: UI
}
}
};
};

View File

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

View File

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

View File

@@ -1,81 +1,81 @@
module.exports = function ColorTemperature(options, UI) {
const pixelSetter = require('../../util/pixelSetter.js');
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
options.temperature = (options.temperature > "40000") ? "40000" : options.temperature
options.temperature = options.temperature || defaults.temperature;
options.temperature = (options.temperature > 40000) ? 40000 : options.temperature;
options.temperature = (options.temperature < 0) ? 0 : options.temperature;
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
function extraManipulation(pixels) {
let temp = parseInt(options.temperature)
temp /= 100
let temp = parseInt(options.temperature);
temp /= 100;
let r, g, b;
let r, g, b;
if (temp <= 66) {
r = 255;
g = Math.min(Math.max(99.4708025861 * Math.log(temp) - 161.1195681661, 0), 255);
} else {
r = Math.min(Math.max(329.698727446 * Math.pow(temp - 60, -0.1332047592), 0), 255);
g = Math.min(Math.max(288.1221695283 * Math.pow(temp - 60, -0.0755148492), 0), 255);
}
if (temp <= 66) {
r = 255;
g = Math.min(Math.max(99.4708025861 * Math.log(temp) - 161.1195681661, 0), 255);
} else {
r = Math.min(Math.max(329.698727446 * Math.pow(temp - 60, -0.1332047592), 0), 255);
g = Math.min(Math.max(288.1221695283 * Math.pow(temp - 60, -0.0755148492), 0), 255);
}
if (temp >= 66) {
b = 255;
} else if (temp <= 19) {
b = 0;
} else {
b = temp - 10;
b = Math.min(Math.max(138.5177312231 * Math.log(b) - 305.0447927307, 0), 255);
}
if (temp >= 66) {
b = 255;
} else if (temp <= 19) {
b = 0;
} else {
b = temp - 10;
b = Math.min(Math.max(138.5177312231 * Math.log(b) - 305.0447927307, 0), 255);
}
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
r_data = pixels.get(i, j, 0)
r_new_data = (255 / r) * r_data
pixels.set(i, j, 0, r_new_data)
g_data = pixels.get(i, j, 1)
g_new_data = (255 / g) * g_data
pixels.set(i, j, 1, g_new_data)
b_data = pixels.get(i, j, 2)
b_new_data = (255 / b) * b_data
pixels.set(i, j, 2, b_new_data)
}
}
return pixels
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
var rgbdata = [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2)];
rgbdata[0] = (255 / r) * rgbdata[0];
rgbdata[1] = (255 / g) * rgbdata[1];
rgbdata[2] = (255 / b) * rgbdata[2];
pixelSetter(i, j, rgbdata, pixels);
}
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
return pixels;
}
return {
options: options,
draw: draw,
output: output,
UI: UI
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "Color Temperature",
"name": "color-temperature",
"description": "Changes the color temperature of the image.",
"inputs": {
"temperature": {
@@ -9,4 +9,4 @@
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#color-temperature"
}
}

View File

@@ -1,12 +1,12 @@
module.exports = require('../../util/createMetaModule.js')(
function mapFunction(options) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
// return steps with options:
return [
{ 'name': 'gradient', 'options': {} },
{ 'name': 'colormap', 'options': { colormap: options.colormap } },
{ 'name': 'crop', 'options': { 'y': 0, 'h': options.h } },
{ 'name': 'overlay', 'options': { 'x': options.x, 'y': options.y, 'offset': -4 } }
{ 'name': 'colormap', 'options': { colormap: options.colormap || defaults.colormap } },
{ 'name': 'crop', 'options': { 'y': 0, 'w': '100%', 'h': options.h || defaults.h } },
{ 'name': 'overlay', 'options': { 'x': options.x || defaults.h, 'y': options.y || defaults.y, 'offset': -4 } }
];
}, {
infoJson: require('./info.json')

View File

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

View File

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

View File

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

View File

@@ -16,19 +16,19 @@ module.exports = function Colormap(options, UI) {
return [res[0], res[1], res[2], 255];
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
callback: callback,
useWasm:options.useWasm
});
}
@@ -38,5 +38,5 @@ module.exports = function Colormap(options, UI) {
draw: draw,
output: output,
UI: UI
}
}
};
};

View File

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

View File

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

View File

@@ -0,0 +1,56 @@
/*
* Crops an Image on the basis of the ratio provided
*/
module.exports = function ConstrainedCrop(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
function draw(input, callback) {
var step = this,
startingX = Number(options.startingX || defaults.startingX),
startingY = Number(options.startingY || defaults.startingY),
aspectRatio = (options.aspectRatio || defaults.aspectRatio).split(':'),
widthRatio = Number(aspectRatio[0]),
heightRatio = Number(aspectRatio[1]);
function extraManipulation(pixels) {
var width = pixels.shape[0],
height = pixels.shape[1];
var endX, endY;
if(((width - startingX) / widthRatio) * heightRatio <= (height - startingY)) {
endX = width;
endY = (((width - startingX) / widthRatio) * heightRatio) + startingY;
}
else {
endX = (((height - startingY) / heightRatio) * widthRatio) + startingX;
endY = height;
}
const newPixels = require('../Crop/Crop')(pixels, {'x': startingX, 'y': startingY, 'w': endX - startingX, 'h': endY - startingY}, function() {
});
return newPixels;
}
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
return require('../_nomodule/PixelManipulation')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

@@ -0,0 +1,23 @@
{
"name": "constrained-crop",
"description": "Crops an image in a particular aspect-ratio",
"inputs": {
"startingX": {
"type": "integer",
"desc": "X-position (measured from left) from where cropping starts",
"default": 0
},
"startingY": {
"type": "integer",
"desc": "Y-position (measured from top) from where cropping starts",
"default": 0
},
"aspectRatio":{
"type": "string",
"desc": "Enter aspect ratio in following format width:height",
"default": "1:1"
}
},
"docs-link":""
}

View File

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

View File

@@ -4,42 +4,60 @@
module.exports = function Contrast(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.contrast = options.contrast || defaults.contrast;
var output;
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.contrast = options.contrast || defaults.contrast;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
pixels = require('./Contrast')(pixels, options.contrast)
return pixels
}
let contrast = options.contrast;
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
contrast = Number(contrast);
if (contrast < -100) contrast = -100;
if (contrast > 100) contrast = 100;
contrast = (100.0 + contrast) / 100.0;
contrast *= contrast;
function changeContrast(p){
p -= 0.5;
p *= contrast;
p += 0.5;
p *= 255;
p = Math.max(0, p);
p = Math.min(p, 255);
return p;
}
return {
options: options,
draw: draw,
output: output,
UI: UI
function changePixel(r, g, b, a) {
return [changeContrast(r / 255), changeContrast(g / 255), changeContrast(b / 255), a];
}
}
function output(image, datauri, mimetype, wasmSuccess) {
step.output = { src: datauri, format: mimetype, wasmSuccess, useWasm: options.useWasm };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
callback: callback,
inBrowser: options.inBrowser,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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