mirror of
https://github.com/publiclab/image-sequencer.git
synced 2025-12-13 20:00:05 +01:00
Merge branch 'ui-tests' of github.com:publiclab/image-sequencer into ui-tests
This commit is contained in:
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -6,11 +6,11 @@ Make sure these boxes are checked before your pull request (PR) is ready to be r
|
|||||||
* [ ] code is in uniquely-named feature branch and has no merge conflicts
|
* [ ] code is in uniquely-named feature branch and has no merge conflicts
|
||||||
* [ ] PR is descriptively titled
|
* [ ] PR is descriptively titled
|
||||||
* [ ] ask `@publiclab/is-reviewers` for help, in a comment below
|
* [ ] 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!
|
> 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.
|
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 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!
|
Thanks!
|
||||||
|
|||||||
@@ -425,8 +425,10 @@ var $step = scopeQuery.scopeSelector(scope),
|
|||||||
This will return an object with a constructor which returns a `jQuery` object (from inside the scope) but with new `elem` and `elemAll` methods.
|
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
|
#### Methods of the Returned Object
|
||||||
* `elem()`: Selects an element inside the scope;
|
* `elem()`: Selects an element inside the scope.
|
||||||
* `elemAll()`: Selects all the instances of a given 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
|
#### Example
|
||||||
|
|
||||||
|
|||||||
17
Gruntfile.js
17
Gruntfile.js
@@ -2,6 +2,7 @@ module.exports = function(grunt) {
|
|||||||
grunt.loadNpmTasks('grunt-browserify');
|
grunt.loadNpmTasks('grunt-browserify');
|
||||||
grunt.loadNpmTasks('grunt-contrib-uglify-es');
|
grunt.loadNpmTasks('grunt-contrib-uglify-es');
|
||||||
grunt.loadNpmTasks('grunt-browser-sync');
|
grunt.loadNpmTasks('grunt-browser-sync');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jasmine');
|
||||||
|
|
||||||
require('matchdep')
|
require('matchdep')
|
||||||
.filterDev('grunt-*')
|
.filterDev('grunt-*')
|
||||||
@@ -57,6 +58,7 @@ module.exports = function(grunt) {
|
|||||||
dest: 'dist/image-sequencer-ui.js'
|
dest: 'dist/image-sequencer-ui.js'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
browserSync: {
|
browserSync: {
|
||||||
dev: {
|
dev: {
|
||||||
options: {
|
options: {
|
||||||
@@ -64,6 +66,21 @@ module.exports = function(grunt) {
|
|||||||
server: './'
|
server: './'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
jasmine: {
|
||||||
|
imageSequencer: {
|
||||||
|
src: 'dist/*.js',
|
||||||
|
options: {
|
||||||
|
specs: 'test/ui/spec/*spec.js',
|
||||||
|
vendor: [
|
||||||
|
'node_modules/jquery/dist/jquery.min.js',
|
||||||
|
'node_modules/bootstrap/dist/js/bootstrap.min.js',
|
||||||
|
'node_modules/jasmine-jquery/lib/jasmine-jquery.js',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
624
docs/MODULES.md
624
docs/MODULES.md
@@ -3,48 +3,229 @@ Documentation of various Modules
|
|||||||
|
|
||||||
List of Module Documentations
|
List of Module Documentations
|
||||||
|
|
||||||
1. [Crop](#crop-module)
|
1. [Add QR](#Add-QR-module)
|
||||||
2. [Segmented-Colormap](#segmented-colormap-module)
|
2. [Average](#average-module)
|
||||||
3. [FisheyeGl](#fisheyeGl-module)
|
3. [Blend](#blend-module)
|
||||||
4. [Add QR](#Add-QR-module)
|
4. [Blur](#blur-module)
|
||||||
5. [Average](#average-module)
|
5. [Brightness](#brightness-module)
|
||||||
6. [Blend](#blend-module)
|
6. [Channel](#channel-module)
|
||||||
7. [Blur](#blur-module)
|
7. [Colorbar](#colorbar-module)
|
||||||
8. [Brightness](#brightness-module)
|
8. [Colormap](#colormap-module)
|
||||||
9. [Channel](#channel-module)
|
9. [ColorTemperature](#color-temperature)
|
||||||
10. [Colorbar](#colorbar-module)
|
10. [Contrast](#contrast-module)
|
||||||
11. [Colormap](#colormap-module)
|
11. [Convolution](#convolution-module)
|
||||||
12. [Contrast](#contrast-module)
|
12. [Crop](#crop-module)
|
||||||
13. [Convolution](#convolution-module)
|
13. [DecodeQr](#decodeQr-module)
|
||||||
14. [DecodeQr](#decodeQr-module)
|
14. [Dither](#dither-module)
|
||||||
15. [Dither](#dither-module)
|
15. [DrawRectangle](#draw-rectangle-module)
|
||||||
16. [DrawRectangle](#draw-rectangle-module)
|
16. [Dynamic](#dynamic-module)
|
||||||
17. [Dynamic](#dynamic-module)
|
17. [Edge-Detect](#edge-detect-module)
|
||||||
18. [Edge-Detect](#edge-detect-module)
|
18. [FisheyeGl](#fisheyeGl-module)
|
||||||
19. [FlipImage](#flipimage-module)
|
19. [FlipImage](#flipimage-module)
|
||||||
20. [Gamma-Correction](#gamma-correction-module)
|
20. [Gamma-Correction](#gamma-correction-module)
|
||||||
21. [Gradient](#gradient-module)
|
21. [Gradient](#gradient-module)
|
||||||
22. [Histogram](#histogram-module)
|
22. [Grid-Overlay](#grid-overlay)
|
||||||
23. [Import-image](#import-image-module)
|
23. [Histogram](#histogram-module)
|
||||||
24. [Invert](#invert-module)
|
24. [Import-image](#import-image-module)
|
||||||
25. [Ndvi](#ndvi-module)
|
25. [Invert](#invert-module)
|
||||||
26. [Ndvi-Colormap](#ndvi-colormap-module)
|
26. [MinifyImage](#minify-image)
|
||||||
27. [Overlay](#overlay-module)
|
27. [Ndvi](#ndvi-module)
|
||||||
28. [PaintBucket](#paint-bucket-module)
|
28. [Ndvi-Colormap](#ndvi-colormap-module)
|
||||||
29. [Resize](#resize-module)
|
29. [Overlay](#overlay-module)
|
||||||
30. [ReplaceColor](#replacecolor-module)
|
30. [PaintBucket](#paint-bucket-module)
|
||||||
31. [Rotate](#rotate-module)
|
31. [ReplaceColor](#replacecolor-module)
|
||||||
32. [Saturation](#saturation-module)
|
32. [Resize](#resize-module)
|
||||||
33. [Threshold](#threshold)
|
33. [Rotate](#rotate-module)
|
||||||
34. [Tint](#tint)
|
34. [Saturation](#saturation-module)
|
||||||
35. [ColorTemperature](#color-temperature)
|
35. [Segmented-Colormap](#segmented-colormap-module)
|
||||||
36. [Grid-Overlay](#grid-overlay)
|
36. [Text-Overlay](#text-overlay)
|
||||||
|
37. [Threshold](#threshold)
|
||||||
|
38. [Tint](#tint)
|
||||||
|
|
||||||
|
|
||||||
|
## add-qr-module
|
||||||
|
|
||||||
|
This module Adds QR corresponding to the given string.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('add-qr',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following properties:
|
||||||
|
* size : size of QR code in pixels (default 200)
|
||||||
|
* qrCodeString : input string to generate QR code
|
||||||
|
|
||||||
|
|
||||||
|
## average-module
|
||||||
|
|
||||||
|
This module is used for averaging all the pixels of the image.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('average',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## blend-module
|
||||||
|
|
||||||
|
This module is used for blending two images .
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('blend',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following properties:
|
||||||
|
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
|
||||||
|
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
|
||||||
|
|
||||||
|
## Blob Analysis
|
||||||
|
|
||||||
|
This module uses Opencv.js for detecting and marking blob/region in microscopic images. It requires an opencv.js file to
|
||||||
|
be loaded before using the functionalities which is currently being loaded to the webpage via script.It supports both environments, Node.js and browser for processing.
|
||||||
|
|
||||||
|
As the size of opencv.js file is quite large, the future versions will focus on loading it asynchronously, on demand of the the module to optimise performance.
|
||||||
|
|
||||||
|
#### Usage
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('blob-analysis')
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
## blur-module
|
||||||
|
|
||||||
|
This module is used for applying a Gaussian blur effect.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('blur',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following property:
|
||||||
|
* blur : Intensity of Gaussian blur (0 to 5; default 2)
|
||||||
|
|
||||||
|
|
||||||
|
## brightness-module
|
||||||
|
|
||||||
|
This module is used for changing the brightness of the image.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('brightness',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following property:
|
||||||
|
* brightness : brightness of the image in percentage (0 to 100; default 100)
|
||||||
|
|
||||||
|
|
||||||
|
## channel-module
|
||||||
|
|
||||||
|
This module is used for forming a grayscale image by applying one of the three primary colors.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('channel',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following property:
|
||||||
|
* channel : color of the channel (red, green, blue; default green)
|
||||||
|
|
||||||
|
|
||||||
|
## colorbar-module
|
||||||
|
|
||||||
|
This module is used for displaying an image with a colorbar.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('colorbar',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following properties:
|
||||||
|
* colormap : Name of the Colormap(default, greyscale, stretched, fastie, brntogrn, blutoredjet, colors16; default: default)
|
||||||
|
* x : X-position of the image on which the new image is overlayed (default 0)
|
||||||
|
* y : Y-position of the image on which the new image is overlayed (default 0)
|
||||||
|
* h : height of resulting cropped image (default : 50% of input image width )
|
||||||
|
|
||||||
|
|
||||||
|
## colormap-module
|
||||||
|
|
||||||
|
This module is used for mapping brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('colormap',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following property:
|
||||||
|
* colormap : Name of the Colormap ( greyscale, stretched, fastie, brntogrn, blutoredjet, colors16)
|
||||||
|
|
||||||
|
|
||||||
|
## Color Temperature
|
||||||
|
|
||||||
|
This changes the color temperature of the image.
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('color-temperature',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
where `options` is an object with the following property:
|
||||||
|
* temperature : temperature between 0 - 40,000 kelvin (default 6000)
|
||||||
|
|
||||||
|
|
||||||
|
## contrast-module
|
||||||
|
|
||||||
|
This module is used for changing the contrast of the image.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('contrast',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following property:
|
||||||
|
* contrast : contrast for the given image (-100 to 100; default : 70)
|
||||||
|
|
||||||
|
|
||||||
|
## convolution-module
|
||||||
|
|
||||||
|
This module is used for performing image-convolution.
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('convolution',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following properties:
|
||||||
|
* constantFactor : a constant factor, multiplies all the kernel values by that factor (default : 1/9)
|
||||||
|
* kernelValues : nine space separated numbers representing the kernel values in left to right and top to bottom format(default : 1 1 1 1 1 1 1 1 1)
|
||||||
|
|
||||||
|
|
||||||
## crop-module
|
## crop-module
|
||||||
|
|
||||||
This module is used to crop an image.
|
This module is used to crop an image.
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -64,208 +245,9 @@ Where `options` is an object having the properties `x`, `y`, `w`, `h`. This diag
|
|||||||
* `options.h` : half of image height
|
* `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
|
## decodeQr-module
|
||||||
|
|
||||||
This module is used for decoding a QR in image (if present).
|
This module is used for decoding a QR in image (if present).
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -279,8 +261,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.
|
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)
|
[more info on wikipedia](https://en.wikipedia.org/wiki/Dither)
|
||||||
|
#### Usage
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
sequencer.loadImage('PATH')
|
sequencer.loadImage('PATH')
|
||||||
@@ -290,10 +271,10 @@ This module approximates a color from a mixture of other colors when the require
|
|||||||
where `options` is an object with the following property:
|
where `options` is an object with the following property:
|
||||||
* dither : Can select the name of the Dithering Algorithm(default none)
|
* dither : Can select the name of the Dithering Algorithm(default none)
|
||||||
|
|
||||||
|
|
||||||
## draw-rectangle-module
|
## 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.
|
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
|
## Usage
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -309,10 +290,10 @@ where `options` is an object with the following properties:
|
|||||||
* thickness : thickness of the border (default 1)
|
* thickness : thickness of the border (default 1)
|
||||||
* color : RGBA values separated by a space (default "0 0 0 255")
|
* color : RGBA values separated by a space (default "0 0 0 255")
|
||||||
|
|
||||||
|
|
||||||
## dynamic-module
|
## dynamic-module
|
||||||
|
|
||||||
This module is used for producing each color channel based on the original image's color.
|
This module is used for producing each color channel based on the original image's color.
|
||||||
|
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -327,6 +308,7 @@ where `options` is an object with the following properties:
|
|||||||
* blue : expression for blue channel (R, G, B and A as inputs; default b)
|
* 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)
|
* monochrome: fallback for other channels if none provided (default : r+g+b/3)
|
||||||
|
|
||||||
|
|
||||||
## edge-detect-module
|
## edge-detect-module
|
||||||
|
|
||||||
This module is used for detecting images.
|
This module is used for detecting images.
|
||||||
@@ -343,12 +325,33 @@ where `options` is an object with the following properties:
|
|||||||
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
|
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
|
||||||
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
|
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
|
||||||
|
|
||||||
|
|
||||||
|
## fisheyeGl-module
|
||||||
|
|
||||||
|
This module is used for correcting Fisheye or Lens Distortion
|
||||||
|
#### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
sequencer.loadImage('PATH')
|
||||||
|
.addSteps('fisheye-gl',options)
|
||||||
|
.run()
|
||||||
|
```
|
||||||
|
|
||||||
|
where `options` is an object with the following properties:
|
||||||
|
* a : a correction (0 to 4; default 1)
|
||||||
|
* b : b correction (0 to 4; default 1)
|
||||||
|
* Fx : x correction (0 to 4; default 1)
|
||||||
|
* Fy : y correction (0 to 4; default 1)
|
||||||
|
* scale : The ratio to which the original image is to be scaled (0 to 20; default 1.5)
|
||||||
|
* x : Field of View x (0 to 2; default 1)
|
||||||
|
* y : Field of View y (0 to 2; default 1)
|
||||||
|
|
||||||
|
|
||||||
## flipimage-module
|
## flipimage-module
|
||||||
|
|
||||||
This module is used for flipping the image on the selected axis.
|
This module is used for flipping the image on the selected axis.
|
||||||
#### Usage
|
#### Usage
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
sequencer.loadImage('PATH')
|
sequencer.loadImage('PATH')
|
||||||
.addSteps('flip-image',options)
|
.addSteps('flip-image',options)
|
||||||
@@ -373,6 +376,7 @@ This module is used for applying gamma correction.
|
|||||||
where `options` is an object with the following property:
|
where `options` is an object with the following property:
|
||||||
* adjustment : Inverse of actual gamma factor (default 0.2)
|
* adjustment : Inverse of actual gamma factor (default 0.2)
|
||||||
|
|
||||||
|
|
||||||
## gradient-module
|
## gradient-module
|
||||||
|
|
||||||
This module is used for finding gradient of the image.
|
This module is used for finding gradient of the image.
|
||||||
@@ -384,6 +388,23 @@ This module is used for finding gradient of the image.
|
|||||||
.run()
|
.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
|
## histogram-module
|
||||||
|
|
||||||
This module is used for calculating histogram of the image.
|
This module is used for calculating histogram of the image.
|
||||||
@@ -398,6 +419,7 @@ This module is used for calculating histogram of the image.
|
|||||||
where `options` is an object with the following property:
|
where `options` is an object with the following property:
|
||||||
* gradient : boolean value used to toggle gradient along x-axis (true or false; default true)
|
* gradient : boolean value used to toggle gradient along x-axis (true or false; default true)
|
||||||
|
|
||||||
|
|
||||||
## import-image-module
|
## import-image-module
|
||||||
|
|
||||||
This module is used for importing a new image and replacing the original with it.
|
This module is used for importing a new image and replacing the original with it.
|
||||||
@@ -412,6 +434,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:
|
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")
|
* url : url of the new image (local image url or data url;default : "./images/monarch.png")
|
||||||
|
|
||||||
|
|
||||||
## invert-module
|
## invert-module
|
||||||
|
|
||||||
This module is used for inverting the image.
|
This module is used for inverting the image.
|
||||||
@@ -423,6 +446,21 @@ This module is used for inverting the image.
|
|||||||
.run()
|
.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
|
## ndvi-module
|
||||||
|
|
||||||
This module is used for applying ndvi technique to the image.
|
This module is used for applying ndvi technique to the image.
|
||||||
@@ -437,6 +475,7 @@ This module is used for applying ndvi technique to the image.
|
|||||||
where `options` is an object with the following property:
|
where `options` is an object with the following property:
|
||||||
* filter : filter for NDVI (blue or red; default red)
|
* filter : filter for NDVI (blue or red; default red)
|
||||||
|
|
||||||
|
|
||||||
## ndvi-colormap-module
|
## ndvi-colormap-module
|
||||||
|
|
||||||
This module is used for demonstrating ndvi and colormap properties consecutively.
|
This module is used for demonstrating ndvi and colormap properties consecutively.
|
||||||
@@ -448,6 +487,7 @@ This module is used for demonstrating ndvi and colormap properties consecutively
|
|||||||
.run()
|
.run()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## overlay-module
|
## overlay-module
|
||||||
|
|
||||||
This module is used for overlaying an Image over another .
|
This module is used for overlaying an Image over another .
|
||||||
@@ -464,10 +504,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)
|
* 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)
|
* offset : offset to the step on which the output of the last step is overlayed (default -2)
|
||||||
|
|
||||||
|
|
||||||
## paint-bucket-module
|
## paint-bucket-module
|
||||||
|
|
||||||
This module fills any polygonal shape with the specified color in pixels.
|
This module fills any polygonal shape with the specified color in pixels.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -482,19 +522,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")
|
* 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)
|
* 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
|
## replacecolor-module
|
||||||
|
|
||||||
@@ -512,6 +539,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")
|
* 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)
|
* 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
|
## rotate-module
|
||||||
|
|
||||||
This module is used for rotating an image.
|
This module is used for rotating an image.
|
||||||
@@ -526,6 +569,7 @@ This module is used for rotating an image.
|
|||||||
where `options` is an object with the following property:
|
where `options` is an object with the following property:
|
||||||
* rotate : angular value for rotation in degrees (between 0 and 360; default 0)
|
* rotate : angular value for rotation in degrees (between 0 and 360; default 0)
|
||||||
|
|
||||||
|
|
||||||
## saturation-module
|
## saturation-module
|
||||||
|
|
||||||
This module is used for changing the saturation of the image.
|
This module is used for changing the saturation of the image.
|
||||||
@@ -540,11 +584,49 @@ This module is used for changing the saturation of the image.
|
|||||||
where `options` is an object with the following property:
|
where `options` is an object with the following property:
|
||||||
* saturation : saturation for the new image (between 0 and 2; default 0)
|
* 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
|
## Threshold
|
||||||
|
|
||||||
Thresholding is used to create binary images.
|
Thresholding is used to create binary images.
|
||||||
|
#### Usage
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
sequencer.loadImage('PATH')
|
sequencer.loadImage('PATH')
|
||||||
@@ -559,8 +641,7 @@ where `options` is an object with the following property:
|
|||||||
## Tint
|
## Tint
|
||||||
|
|
||||||
It adds color tint to an image
|
It adds color tint to an image
|
||||||
|
#### Usage
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
sequencer.loadImage('PATH')
|
sequencer.loadImage('PATH')
|
||||||
@@ -570,34 +651,3 @@ It adds color tint to an image
|
|||||||
where `options` is an object with the following property:
|
where `options` is an object with the following property:
|
||||||
* color : RGB values seperated by a space (default "0 0 255")
|
* color : RGB values seperated by a space (default "0 0 255")
|
||||||
* factor : amount of tint (default 0.5)
|
* factor : amount of tint (default 0.5)
|
||||||
|
|
||||||
|
|
||||||
## Color Temperature
|
|
||||||
|
|
||||||
This changes the color temperature of the image.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
sequencer.loadImage('PATH')
|
|
||||||
.addSteps('color-temperature',options)
|
|
||||||
.run()
|
|
||||||
```
|
|
||||||
where `options` is an object with the following property:
|
|
||||||
* temperature : temperature between 0 - 40,000 kelvin (default 6000)
|
|
||||||
|
|
||||||
## Grid Overlay
|
|
||||||
|
|
||||||
This adds the grid over an image.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```js
|
|
||||||
sequencer.loadImage('PATH')
|
|
||||||
.addSteps('grid-overlay',options)
|
|
||||||
.run()
|
|
||||||
```
|
|
||||||
where `options` is an object with the following property:
|
|
||||||
* options.x : The value at which the grid line should start in x-axis.
|
|
||||||
* options.y : The value at which the grid line should start in y-axis.
|
|
||||||
* color : Color for the grid on the image.
|
|
||||||
@@ -44,6 +44,7 @@ body > .container-fluid {
|
|||||||
.panel {
|
.panel {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
min-width:400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nomargin {
|
.nomargin {
|
||||||
@@ -61,6 +62,7 @@ body > .container-fluid {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #444;
|
color: #444;
|
||||||
|
min-width:300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover {
|
.hover {
|
||||||
@@ -103,7 +105,10 @@ body > .container-fluid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#add-step-btn{
|
#add-step-btn{
|
||||||
margin-left: 10px;
|
width: 100%
|
||||||
|
}
|
||||||
|
.selectize-input {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#addStep .labels {
|
#addStep .labels {
|
||||||
@@ -140,7 +145,6 @@ body > .container-fluid {
|
|||||||
#dwnld {
|
#dwnld {
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
margin-left: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#gif_element {
|
#gif_element {
|
||||||
|
|||||||
104
examples/demo.js
104
examples/demo.js
@@ -5,7 +5,7 @@ var defaultHtmlSequencerUi = require('./lib/defaultHtmlSequencerUi.js'),
|
|||||||
urlHash = require('./lib/urlHash.js'),
|
urlHash = require('./lib/urlHash.js'),
|
||||||
insertPreview = require('./lib/insertPreview.js');
|
insertPreview = require('./lib/insertPreview.js');
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function () {
|
||||||
sequencer = ImageSequencer();
|
sequencer = ImageSequencer();
|
||||||
|
|
||||||
function refreshOptions() {
|
function refreshOptions() {
|
||||||
@@ -62,7 +62,7 @@ window.onload = function() {
|
|||||||
sequencer.loadImage('images/tulips.png', ui.onLoad);
|
sequencer.loadImage('images/tulips.png', ui.onLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
var resetSequence = function(){
|
var resetSequence = function () {
|
||||||
var r = confirm('Do you want to reset the sequence?');
|
var r = confirm('Do you want to reset the sequence?');
|
||||||
if (r)
|
if (r)
|
||||||
window.location = '/';
|
window.location = '/';
|
||||||
@@ -73,7 +73,7 @@ window.onload = function() {
|
|||||||
$('#resetButton').on('click', resetSequence);
|
$('#resetButton').on('click', resetSequence);
|
||||||
|
|
||||||
//Module button radio selection
|
//Module button radio selection
|
||||||
$('.radio-group .radio').on('click', function() {
|
$('.radio-group .radio').on('click', function () {
|
||||||
$(this).parent().find('.radio').removeClass('selected');
|
$(this).parent().find('.radio').removeClass('selected');
|
||||||
$(this).addClass('selected');
|
$(this).addClass('selected');
|
||||||
newStep = $(this).attr('data-value');
|
newStep = $(this).attr('data-value');
|
||||||
@@ -84,29 +84,44 @@ window.onload = function() {
|
|||||||
$(this).removeClass('selected');
|
$(this).removeClass('selected');
|
||||||
});
|
});
|
||||||
|
|
||||||
function displayMessageOnSaveSequence(){
|
function displayMessageOnSaveSequence() {
|
||||||
$('.savesequencemsg').fadeIn();
|
$('.savesequencemsg').fadeIn();
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
$('.savesequencemsg').fadeOut();
|
$('.savesequencemsg').fadeOut();
|
||||||
}, 1000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
$('body').on('click', 'button.remove', ui.removeStepUi);
|
$('body').on('click', 'button.remove', ui.removeStepUi);
|
||||||
$('#save-seq').click(() => {
|
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).');
|
var result = window.prompt('Please give a name to your sequence... (Saved sequence will only be available in this browser).');
|
||||||
if(result){
|
if (result) {
|
||||||
result = result + ' (local)';
|
result = result + ' (local)';
|
||||||
sequencer.saveSequence(result, sequencer.toString());
|
sequencer.saveSequence(result, sequencer.toString()); // 1.a study saveSequence
|
||||||
sequencer.loadModules();
|
sequencer.loadModules();
|
||||||
displayMessageOnSaveSequence();
|
displayMessageOnSaveSequence();
|
||||||
refreshOptions();
|
refreshOptions();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
$('#saveButton').on('click', function () {
|
||||||
|
// different handlers triggered for different dropdown options
|
||||||
|
|
||||||
|
let dropDownValue = $('#selectSaveOption option:selected').val();
|
||||||
|
|
||||||
|
if (dropDownValue == 'save-image') {
|
||||||
|
$('.download-btn:last()').trigger('click');
|
||||||
|
}
|
||||||
|
else if (dropDownValue == 'save-gif') {
|
||||||
|
handleSavePNG();
|
||||||
|
}
|
||||||
|
else if (dropDownValue == 'save-seq') {
|
||||||
|
saveSequence();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var isWorkingOnGifGeneration = false;
|
let isWorkingOnGifGeneration = false;
|
||||||
|
|
||||||
$('.js-view-as-gif').on('click', function(event) {
|
$('.js-view-as-gif').on('click', function (event) {
|
||||||
// Prevent user from triggering generation multiple times
|
/* Prevent user from triggering generation multiple times*/
|
||||||
if (isWorkingOnGifGeneration) return;
|
if (isWorkingOnGifGeneration) return;
|
||||||
|
|
||||||
isWorkingOnGifGeneration = true;
|
isWorkingOnGifGeneration = true;
|
||||||
@@ -116,23 +131,10 @@ window.onload = function() {
|
|||||||
button.innerHTML = '<i class="fa fa-circle-o-notch fa-spin"></i>';
|
button.innerHTML = '<i class="fa fa-circle-o-notch fa-spin"></i>';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Select all images from previous steps
|
/* Get gif resources of previous steps */
|
||||||
var imgs = document.getElementsByClassName('step-thumbnail');
|
let options = getGifResources();
|
||||||
|
|
||||||
var imgSrcs = [];
|
gifshot.createGIF(options, function (obj) { // gif generation
|
||||||
|
|
||||||
for (var i = 0; i < imgs.length; i++) {
|
|
||||||
imgSrcs.push(imgs[i].src);
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
'gifWidth': imgs[0].width,
|
|
||||||
'gifHeight': imgs[0].height,
|
|
||||||
'images': imgSrcs,
|
|
||||||
'frameDuration': 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
gifshot.createGIF(options, function(obj) {
|
|
||||||
if (!obj.error) {
|
if (!obj.error) {
|
||||||
// Final gif encoded with base64 format
|
// Final gif encoded with base64 format
|
||||||
var image = obj.image;
|
var image = obj.image;
|
||||||
@@ -141,13 +143,11 @@ window.onload = function() {
|
|||||||
animatedImage.id = 'gif_element';
|
animatedImage.id = 'gif_element';
|
||||||
animatedImage.src = image;
|
animatedImage.src = image;
|
||||||
|
|
||||||
|
let modal = $('#js-download-gif-modal');
|
||||||
|
|
||||||
var modal = $('#js-download-gif-modal');
|
$('#js-download-as-gif-button').one('click', function () {
|
||||||
|
|
||||||
$('#js-download-as-gif-button').one('click', function() {
|
|
||||||
// Trigger download
|
// Trigger download
|
||||||
download(image, 'index.gif', 'image/gif');
|
downloadGif(image);
|
||||||
|
|
||||||
// Close modal
|
// Close modal
|
||||||
modal.modal('hide');
|
modal.modal('hide');
|
||||||
});
|
});
|
||||||
@@ -175,10 +175,42 @@ window.onload = function() {
|
|||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
button.innerHTML = 'View GIF';
|
button.innerHTML = 'View GIF';
|
||||||
isWorkingOnGifGeneration = false;
|
isWorkingOnGifGeneration = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getGifResources() {
|
||||||
|
/* Returns an object with specific gif options */
|
||||||
|
let imgs = document.getElementsByClassName('step-thumbnail');
|
||||||
|
var imgSrcs = [];
|
||||||
|
|
||||||
|
// Pushes image sources of all the modules in dom
|
||||||
|
for (var i = 0; i < imgs.length; i++) {
|
||||||
|
imgSrcs.push(imgs[i].src);
|
||||||
|
}
|
||||||
|
|
||||||
|
var options = { // gif frame options
|
||||||
|
'gifWidth': imgs[0].width,
|
||||||
|
'gifHeight': imgs[0].height,
|
||||||
|
'images': imgSrcs,
|
||||||
|
'frameDuration': 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSavePNG() {
|
||||||
|
let options = getGifResources();
|
||||||
|
gifshot.createGIF(options, function(obj){
|
||||||
|
|
||||||
|
downloadGif(obj.image);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadGif(image) {
|
||||||
|
download(image, 'index.gif', 'image/gif');// downloadjs library function
|
||||||
|
}
|
||||||
|
|
||||||
// image selection and drag/drop handling from examples/lib/imageSelection.js
|
// image selection and drag/drop handling from examples/lib/imageSelection.js
|
||||||
sequencer.setInputStep({
|
sequencer.setInputStep({
|
||||||
dropZoneSelector: '#dropzone',
|
dropZoneSelector: '#dropzone',
|
||||||
@@ -190,7 +222,7 @@ window.onload = function() {
|
|||||||
var util = intermediateHtmlStepUi(sequencer);
|
var util = intermediateHtmlStepUi(sequencer);
|
||||||
step.output.src = reader.result;
|
step.output.src = reader.result;
|
||||||
sequencer.run({ index: 0 });
|
sequencer.run({ index: 0 });
|
||||||
if(typeof step.options !== 'undefined')
|
if (typeof step.options !== 'undefined')
|
||||||
step.options.step.imgElement.src = reader.result;
|
step.options.step.imgElement.src = reader.result;
|
||||||
else
|
else
|
||||||
step.imgElement.src = reader.result;
|
step.imgElement.src = reader.result;
|
||||||
@@ -201,7 +233,7 @@ window.onload = function() {
|
|||||||
var step = sequencer.steps[0];
|
var step = sequencer.steps[0];
|
||||||
step.output.src = url;
|
step.output.src = url;
|
||||||
sequencer.run({ index: 0 });
|
sequencer.run({ index: 0 });
|
||||||
if(typeof step.options !== 'undefined')
|
if (typeof step.options !== 'undefined')
|
||||||
step.options.step.imgElement.src = url;
|
step.options.step.imgElement.src = url;
|
||||||
else
|
else
|
||||||
step.imgElement.src = url;
|
step.imgElement.src = url;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<div class="container-fluid">
|
<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>
|
<h1><a href="/" target='_blank' class="name-header">Image Sequencer</a></h1>
|
||||||
<p>
|
<p>
|
||||||
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original
|
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules.
|
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules in browser's localStorage.
|
||||||
</p>
|
</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
@@ -139,15 +139,15 @@
|
|||||||
<p>Crop</p>
|
<p>Crop</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row center-align">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-lg-8">
|
||||||
|
|
||||||
<select id="selectStep">
|
<select id="selectStep" class="text-center">
|
||||||
<!-- The default null selection has been appended manually in demo.js
|
<!-- The default null selection has been appended manually in demo.js
|
||||||
This is because the options in select are overritten when options are appended.-->
|
This is because the options in select are overritten when options are appended.-->
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-lg-4">
|
||||||
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
|
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row center-align">
|
<div class="row center-align">
|
||||||
@@ -188,10 +188,10 @@
|
|||||||
<div style="text-align:center;">
|
<div style="text-align:center;">
|
||||||
<h2 style="margin-top:20px">Save</h2>
|
<h2 style="margin-top:20px">Save</h2>
|
||||||
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
|
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
|
||||||
<option>Save as PNG</option>
|
<option value="save-image">Save as PNG</option>
|
||||||
<option>Save as GIF (all steps)</option>
|
<option value="save-gif">Save as GIF (all steps)</option>
|
||||||
<option>Save sequence</option>
|
<option value="save-seq">Save sequence</option>
|
||||||
<option>Save sequence string</option>
|
<option value="save-seq-string">Save sequence string</option>
|
||||||
</select>
|
</select>
|
||||||
<p><button id="saveButton" class="btn btn-primary btn-lg save-button">Save</button></p>
|
<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>
|
<p><button class="btn btn-default btn-lg js-view-as-gif" id="gif">Preview GIF</button></p>
|
||||||
@@ -232,6 +232,7 @@
|
|||||||
var sequencer;
|
var sequencer;
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
<script async src="../node_modules/opencv.js/opencv.js" type="text/javascript"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -8,15 +8,14 @@
|
|||||||
// output values, step information.
|
// output values, step information.
|
||||||
// See documetation for more details.
|
// See documetation for more details.
|
||||||
|
|
||||||
var intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
|
const intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
|
||||||
urlHash = require('./urlHash.js'),
|
urlHash = require('./urlHash.js'),
|
||||||
_ = require('lodash'),
|
_ = require('lodash'),
|
||||||
mapHtmlTypes = require('./mapHtmltypes'),
|
mapHtmlTypes = require('./mapHtmltypes'),
|
||||||
scopeQuery = require('./scopeQuery'),
|
scopeQuery = require('./scopeQuery');
|
||||||
$stepAll,
|
|
||||||
$step;
|
|
||||||
|
|
||||||
function DefaultHtmlStepUi(_sequencer, options) {
|
function DefaultHtmlStepUi(_sequencer, options) {
|
||||||
|
let $step, $stepAll;
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var stepsEl = options.stepsEl || document.querySelector('#steps');
|
var stepsEl = options.stepsEl || document.querySelector('#steps');
|
||||||
@@ -74,8 +73,10 @@ function DefaultHtmlStepUi(_sequencer, options) {
|
|||||||
|
|
||||||
$step = scopeQuery.scopeSelector(step.ui);
|
$step = scopeQuery.scopeSelector(step.ui);
|
||||||
$stepAll = scopeQuery.scopeSelectorAll(step.ui);
|
$stepAll = scopeQuery.scopeSelectorAll(step.ui);
|
||||||
|
step.ui.$step = $step;
|
||||||
|
step.ui.$stepAll = $stepAll;
|
||||||
|
|
||||||
step.linkElements = $stepAll('a');
|
step.linkElements = step.ui.querySelectorAll('a');
|
||||||
step.imgElement = $step('a img.img-thumbnail')[0];
|
step.imgElement = $step('a img.img-thumbnail')[0];
|
||||||
|
|
||||||
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
|
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
|
||||||
@@ -180,7 +181,8 @@ function DefaultHtmlStepUi(_sequencer, options) {
|
|||||||
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
|
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
|
||||||
if($('#steps .step-container:nth-last-child(2)'))
|
if($('#steps .step-container:nth-last-child(2)'))
|
||||||
$('#steps .step-container:nth-last-child(2) .insert-step').prop('disabled', false);
|
$('#steps .step-container:nth-last-child(2) .insert-step').prop('disabled', false);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]);
|
stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,7 +198,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
|
|||||||
$(step.imgElement).on('click', (e) => {e.preventDefault(); });
|
$(step.imgElement).on('click', (e) => {e.preventDefault(); });
|
||||||
$stepAll('#color-picker').colorpicker();
|
$stepAll('#color-picker').colorpicker();
|
||||||
|
|
||||||
function saveOptions(e) {
|
function saveOptions(e) { // 1. SAVE OPTIONS
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (optionsChanged){
|
if (optionsChanged){
|
||||||
$step('div.details')
|
$step('div.details')
|
||||||
@@ -268,7 +270,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
|
|||||||
$step('.load').hide();
|
$step('.load').hide();
|
||||||
|
|
||||||
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
|
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
|
||||||
var imgthumbnail = $step('.img-thumbnail');
|
var imgthumbnail = $step('.img-thumbnail').getDomElem();
|
||||||
for (let index = 0; index < step.linkElements.length; index++) {
|
for (let index = 0; index < step.linkElements.length; index++) {
|
||||||
if (step.linkElements[index].contains(imgthumbnail))
|
if (step.linkElements[index].contains(imgthumbnail))
|
||||||
step.linkElements[index].href = step.imgElement.src;
|
step.linkElements[index].href = step.imgElement.src;
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ function generatePreview(previewStepName, customValues, path, selector) {
|
|||||||
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
|
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previewSequencer.loadImage(path, loadPreview);
|
if(previewStepName === 'resize')
|
||||||
|
insertPreview(path);
|
||||||
|
else
|
||||||
|
previewSequencer.loadImage(path, loadPreview);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePreviews(src, selector) {
|
function updatePreviews(src, selector) {
|
||||||
@@ -44,11 +47,30 @@ function updatePreviews(src, selector) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(previewSequencerSteps).forEach(function (step, index) {
|
var img = new Image();
|
||||||
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
|
img.onload = function(){
|
||||||
});
|
var height = img.height;
|
||||||
|
var width = img.width;
|
||||||
|
|
||||||
|
let percentage = (80 / height) * 100; //take the min resize value that fits the preview area => (new-width/orig_ht) - '80 as the preview area has 80*80 dimension
|
||||||
|
percentage = Math.max((80 / width) * 100, percentage); // make sure that one dimension doesn't resize greater, leading distorting preview-area fitting
|
||||||
|
percentage = Math.ceil(percentage);
|
||||||
|
|
||||||
|
var sequencer = ImageSequencer();
|
||||||
|
|
||||||
|
sequencer.loadImage(src, function(){
|
||||||
|
this.addSteps('resize', {['resize']: percentage + '%'});
|
||||||
|
this.run((src)=>{
|
||||||
|
Object.keys(previewSequencerSteps).forEach(function (step, index) {
|
||||||
|
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
img.src = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
generatePreview : generatePreview,
|
generatePreview : generatePreview,
|
||||||
updatePreviews : updatePreviews
|
updatePreviews : updatePreviews
|
||||||
|
|||||||
@@ -65,41 +65,33 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function selectNewStepUi() {
|
function selectNewStepUi($step) {
|
||||||
//var insertSelect = $step('.insert-step-select');
|
var insertSelect = $step('.insert-step-select');
|
||||||
var insertSelect = $(step.ui.querySelector('.insert-step-select'));
|
|
||||||
var m = insertSelect.val();
|
var m = insertSelect.val();
|
||||||
// $step('.insertDiv .info').html(_sequencer.modulesInfo(m).description);
|
$step('.insertDiv .info').html(_sequencer.modulesInfo(m).description);
|
||||||
// $step('.insertDiv .add-step-btn').prop('disabled', false);
|
$step('.insertDiv .add-step-btn').prop('disabled', false);
|
||||||
$(step.ui.querySelector('.insertDiv .info').html(_sequencer.modulesInfo(m).description));
|
|
||||||
$(step.ui.querySelector('.insertDiv .add-step-btn').prop('disabled', false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var toggleDiv = function(callback = function(){}){
|
var toggleDiv = function($step, callback = function(){}){
|
||||||
/*$step('.insertDiv').collapse('toggle');
|
$step('.insertDiv').collapse('toggle');
|
||||||
if ($step('.insert-text').css('display') != 'none'){
|
if ($step('.insert-text').css('display') != 'none'){
|
||||||
$step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback)});*/
|
$step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback);});
|
||||||
|
|
||||||
$(step.ui.querySelector('.insertDiv')).collapse('toggle');
|
|
||||||
if ($(step.ui.querySelector('.insert-text')).css('display') != 'none'){
|
|
||||||
$(step.ui.querySelector('.insert-text')).fadeToggle(200, function(){$(step.ui.querySelector('.no-insert-text')).fadeToggle(200, callback);});
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//$step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback)});
|
$step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback);});
|
||||||
$(step.ui.querySelector('.no-insert-text')).fadeToggle(200, function(){$(step.ui.querySelector('.insert-text')).fadeToggle(200, callback);});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
insertStep = function (id) {
|
insertStep = function (id) {
|
||||||
|
const $step = step.ui.$step,
|
||||||
|
$stepAll = step.ui.$stepAll;
|
||||||
var modulesInfo = _sequencer.modulesInfo();
|
var modulesInfo = _sequencer.modulesInfo();
|
||||||
var parser = new DOMParser();
|
var parser = new DOMParser();
|
||||||
var addStepUI = stepUI();
|
var addStepUI = stepUI();
|
||||||
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
|
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
|
||||||
|
if ($step('.insertDiv').length > 0){
|
||||||
//if ($step('.insertDiv').length > 0){
|
toggleDiv($step);
|
||||||
if ($(step.ui.querySelector('.insertDiv')).length > 0){
|
|
||||||
toggleDiv();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
step.ui
|
step.ui
|
||||||
@@ -107,19 +99,14 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
|
|||||||
.insertAdjacentElement('afterend',
|
.insertAdjacentElement('afterend',
|
||||||
addStepUI
|
addStepUI
|
||||||
);
|
);
|
||||||
toggleDiv(function(){
|
toggleDiv($step, function(){
|
||||||
insertPreview.updatePreviews(step.output, '.insertDiv');
|
insertPreview.updatePreviews(step.output, '.insertDiv');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*$step('.insertDiv .close-insert-box').off('click').on('click', function(){toggleDiv(function(){})});
|
$step('.insertDiv .close-insert-box').off('click').on('click', function(){toggleDiv(function(){});});
|
||||||
|
|
||||||
var insertStepSelect = $step('.insert-step-select');*/
|
var insertStepSelect = $step('.insert-step-select');
|
||||||
|
|
||||||
$(step.ui.querySelector('.insertDiv .close-insert-box')).off('click').on('click', function(){toggleDiv(function(){});});
|
|
||||||
|
|
||||||
//var insertStepSelect = $step('.insert-step-select');
|
|
||||||
var insertStepSelect = $(step.ui.querySelector('.insert-step-select'));
|
|
||||||
insertStepSelect.html('');
|
insertStepSelect.html('');
|
||||||
// Add modules to the insertStep dropdown
|
// Add modules to the insertStep dropdown
|
||||||
for (var m in modulesInfo) {
|
for (var m in modulesInfo) {
|
||||||
@@ -131,35 +118,30 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
|
|||||||
insertStepSelect.selectize({
|
insertStepSelect.selectize({
|
||||||
sortField: 'text'
|
sortField: 'text'
|
||||||
});
|
});
|
||||||
//$step('.inserDiv .add-step-btn').prop('disabled', true);
|
$step('.inserDiv .add-step-btn').prop('disabled', true);
|
||||||
$(step.ui.querySelector('.inserDiv .add-step-btn')).prop('disabled', true);
|
|
||||||
|
|
||||||
insertStepSelect.append('<option value="" disabled selected>Select a Module</option>');
|
insertStepSelect.append('<option value="" disabled selected>Select a Module</option>');
|
||||||
//$step('.insertDiv .radio-group .radio').on('click', function () {
|
$step('.insertDiv .radio-group .radio').on('click', function () {
|
||||||
$(step.ui.querySelector('.insertDiv .radio-group .radio')).on('click', function () {
|
|
||||||
$(this).parent().find('.radio').removeClass('selected');
|
$(this).parent().find('.radio').removeClass('selected');
|
||||||
$(this).addClass('selected');
|
$(this).addClass('selected');
|
||||||
newStep = $(this).attr('data-value');
|
newStep = $(this).attr('data-value');
|
||||||
//$step('.insert-step-select').val(newStep);
|
$step('.insert-step-select').val(newStep);
|
||||||
$(step.ui.querySelector('.insert-step-select')).val(newStep);
|
selectNewStepUi($step);
|
||||||
selectNewStepUi();
|
insert(id, $step);
|
||||||
insert(id);
|
|
||||||
$(this).removeClass('selected');
|
$(this).removeClass('selected');
|
||||||
});
|
});
|
||||||
insertStepSelect.on('change', selectNewStepUi);
|
insertStepSelect.on('change', () => {selectNewStepUi($step);});
|
||||||
//$step('.insertDiv .add-step-btn').on('click', function () { insert(id) });
|
$step('.insertDiv .add-step-btn').on('click', function () { insert(id, $step); });
|
||||||
$(step.ui.querySelector('.insertDiv .add-step-btn')).on('click', function () { insert(id); });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function insert(id) {
|
function insert(id, $step) {
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
//var insertStepSelect = $step('.insert-step-select');
|
var insertStepSelect = $step('.insert-step-select');
|
||||||
var insertStepSelect = $(step.ui.querySelector('.insert-step-select'));
|
|
||||||
if (insertStepSelect.val() == 'none') return;
|
if (insertStepSelect.val() == 'none') return;
|
||||||
|
|
||||||
var newStepName = insertStepSelect.val();
|
var newStepName = insertStepSelect.val();
|
||||||
toggleDiv();
|
toggleDiv($step);
|
||||||
var sequenceLength = 1;
|
var sequenceLength = 1;
|
||||||
if (sequencer.sequences[newStepName]) {
|
if (sequencer.sequences[newStepName]) {
|
||||||
sequenceLength = sequencer.sequences[newStepName].length;
|
sequenceLength = sequencer.sequences[newStepName].length;
|
||||||
|
|||||||
@@ -8,13 +8,17 @@ function $scope(scope) {
|
|||||||
|
|
||||||
element.elem = function(queryString){
|
element.elem = function(queryString){
|
||||||
return new $scope(scope)(queryString);
|
return new $scope(scope)(queryString);
|
||||||
}
|
};
|
||||||
element.elemAll = function(queryString){
|
element.elemAll = function(queryString){
|
||||||
return new $scopeAll(scope)(queryString);
|
return new $scopeAll(scope)(queryString);
|
||||||
}
|
};
|
||||||
|
element.getDomElem = function(i = 0){
|
||||||
|
return element[i];
|
||||||
|
};
|
||||||
|
element.getScope = () => scope;
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,13 +31,17 @@ function $scopeAll(scope){
|
|||||||
|
|
||||||
element.elem = function(queryString){
|
element.elem = function(queryString){
|
||||||
return new $scope(scope)(queryString);
|
return new $scope(scope)(queryString);
|
||||||
}
|
};
|
||||||
element.elemAll = function(queryString){
|
element.elemAll = function(queryString){
|
||||||
return new $scopeAll(scope)(queryString);
|
return new $scopeAll(scope)(queryString);
|
||||||
}
|
};
|
||||||
|
element.getDomElem = function(i = 0){
|
||||||
|
return element[i];
|
||||||
|
};
|
||||||
|
element.getScope = () => scope;
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,4 +65,4 @@ function scopeSelectorAll(scope){
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
scopeSelector,
|
scopeSelector,
|
||||||
scopeSelectorAll
|
scopeSelectorAll
|
||||||
}
|
};
|
||||||
3146
package-lock.json
generated
3146
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -6,7 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"debug": "TEST=true node ./index.js -i ./examples/images/monarch.png -s invert",
|
"debug": "TEST=true node ./index.js -i ./examples/images/monarch.png -s invert",
|
||||||
"test": "TEST=true istanbul cover tape test/core/*.js test/core/ui/user-interface.js test/core/modules/*.js | tap-spec; node test/core/sequencer/benchmark.js; browserify test/core/sequencer/meta-modules.js test/core/sequencer/image-sequencer.js test/core/sequencer/chain.js test/core/sequencer/replace.js test/core/sequencer/import-export.js test/core/sequencer/run.js test/core/sequencer/dynamic-imports.js test/core/util/*.js | tape-run --render=\"tap-spec\"",
|
"test": "TEST=true istanbul cover tape test/core/*.js test/core/ui/user-interface.js test/core/modules/*.js | tap-spec; node test/core/sequencer/benchmark.js; browserify test/core/sequencer/meta-modules.js test/core/sequencer/image-sequencer.js test/core/sequencer/chain.js test/core/sequencer/replace.js test/core/sequencer/import-export.js test/core/sequencer/run.js test/core/sequencer/dynamic-imports.js test/core/util/*.js | tape-run --render=\"tap-spec\"",
|
||||||
"test-ui": "node node_modules/jasmine/bin/jasmine test/ui/spec/*.js",
|
"test-ui": "grunt browserify && grunt jasmine",
|
||||||
"setup": "npm i && npm i -g grunt grunt-cli && grunt build",
|
"setup": "npm i && npm i -g grunt grunt-cli && grunt build",
|
||||||
"start": "grunt serve"
|
"start": "grunt serve"
|
||||||
},
|
},
|
||||||
@@ -30,14 +30,16 @@
|
|||||||
"url": "https://github.com/publiclab/image-sequencer/issues"
|
"url": "https://github.com/publiclab/image-sequencer/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"atob": "^2.1.2",
|
||||||
"base64-img": "^1.0.4",
|
"base64-img": "^1.0.4",
|
||||||
"bootstrap": "~3.4.0",
|
"bootstrap": "~3.4.0",
|
||||||
"bootstrap-colorpicker": "^2.5.3",
|
"bootstrap-colorpicker": "^2.5.3",
|
||||||
"buffer": "~5.2.1",
|
"buffer": "~5.4.0",
|
||||||
"commander": "^2.11.0",
|
"commander": "^3.0.1",
|
||||||
|
"compressorjs": "^1.0.5",
|
||||||
"data-uri-to-buffer": "^2.0.0",
|
"data-uri-to-buffer": "^2.0.0",
|
||||||
"downloadjs": "^1.4.7",
|
"downloadjs": "^1.4.7",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^6.1.0",
|
||||||
"fisheyegl": "^0.1.2",
|
"fisheyegl": "^0.1.2",
|
||||||
"font-awesome": "~4.7.0",
|
"font-awesome": "~4.7.0",
|
||||||
"geotiff": "^1.0.0-beta.6",
|
"geotiff": "^1.0.0-beta.6",
|
||||||
@@ -47,6 +49,9 @@
|
|||||||
"gpu.js": "^2.0.0-rc.12",
|
"gpu.js": "^2.0.0-rc.12",
|
||||||
"image-sequencer-invert": "^1.0.0",
|
"image-sequencer-invert": "^1.0.0",
|
||||||
"imagejs": "0.0.9",
|
"imagejs": "0.0.9",
|
||||||
|
"imagemin": "^7.0.0",
|
||||||
|
"imagemin-jpegtran": "^6.0.0",
|
||||||
|
"imagemin-pngquant": "^8.0.0",
|
||||||
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
|
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
|
||||||
"istanbul": "^0.4.5",
|
"istanbul": "^0.4.5",
|
||||||
"jasmine": "^3.4.0",
|
"jasmine": "^3.4.0",
|
||||||
@@ -55,6 +60,7 @@
|
|||||||
"jsqr": "^1.1.1",
|
"jsqr": "^1.1.1",
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
"ndarray": "^1.0.18",
|
"ndarray": "^1.0.18",
|
||||||
|
"opencv.js": "^1.2.1",
|
||||||
"ora": "^3.0.0",
|
"ora": "^3.0.0",
|
||||||
"pace": "0.0.4",
|
"pace": "0.0.4",
|
||||||
"puppeteer": "^1.14.0",
|
"puppeteer": "^1.14.0",
|
||||||
@@ -62,6 +68,7 @@
|
|||||||
"readline-sync": "^1.4.7",
|
"readline-sync": "^1.4.7",
|
||||||
"save-pixels": "~2.3.4",
|
"save-pixels": "~2.3.4",
|
||||||
"selectize": "^0.12.6",
|
"selectize": "^0.12.6",
|
||||||
|
"spawn-sync": "^2.0.0",
|
||||||
"urify": "^2.1.1",
|
"urify": "^2.1.1",
|
||||||
"webgl-distort": "0.0.2"
|
"webgl-distort": "0.0.2"
|
||||||
},
|
},
|
||||||
@@ -71,20 +78,21 @@
|
|||||||
"@babel/plugin-syntax-object-rest-spread": "^7.2.0",
|
"@babel/plugin-syntax-object-rest-spread": "^7.2.0",
|
||||||
"babelify": "^10.0.0",
|
"babelify": "^10.0.0",
|
||||||
"browserify": "16.2.3",
|
"browserify": "16.2.3",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^6.1.0",
|
||||||
"grunt": "^1.0.3",
|
"grunt": "^1.0.3",
|
||||||
"grunt-browser-sync": "^2.2.0",
|
"grunt-browser-sync": "^2.2.0",
|
||||||
"grunt-browserify": "^5.0.0",
|
"grunt-browserify": "^5.0.0",
|
||||||
"grunt-contrib-concat": "^1.0.1",
|
"grunt-contrib-concat": "^1.0.1",
|
||||||
"grunt-contrib-uglify-es": "^3.3.0",
|
"grunt-contrib-uglify-es": "^3.3.0",
|
||||||
"grunt-contrib-watch": "^1.1.0",
|
"grunt-contrib-watch": "^1.1.0",
|
||||||
"husky": "^2.2.0",
|
"grunt-contrib-jasmine": "~1.0.3",
|
||||||
|
"husky": "^3.0.5",
|
||||||
"image-filter-core": "~2.0.2",
|
"image-filter-core": "~2.0.2",
|
||||||
"image-filter-threshold": "~2.0.1",
|
"image-filter-threshold": "~2.0.1",
|
||||||
"jasmine-core": "^3.3.0",
|
"jasmine-core": "^3.3.0",
|
||||||
"jasmine-jquery": "^2.1.1",
|
"jasmine-jquery": "^2.1.1",
|
||||||
"jasmine-spec-reporter": "^4.2.1",
|
"jasmine-spec-reporter": "^4.2.1",
|
||||||
"lint-staged": "^8.1.6",
|
"lint-staged": "^9.1.0",
|
||||||
"looks-same": "^7.0.0",
|
"looks-same": "^7.0.0",
|
||||||
"matchdep": "^2.0.0",
|
"matchdep": "^2.0.0",
|
||||||
"tap-spec": "^5.0.0",
|
"tap-spec": "^5.0.0",
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ require('./util/getStep.js');
|
|||||||
|
|
||||||
ImageSequencer = function ImageSequencer(options) {
|
ImageSequencer = function ImageSequencer(options) {
|
||||||
|
|
||||||
|
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
|
||||||
|
|
||||||
var sequencer = (this.name == 'ImageSequencer') ? this : this.sequencer;
|
var sequencer = (this.name == 'ImageSequencer') ? this : this.sequencer;
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.inBrowser = options.inBrowser === undefined ? isBrowser : options.inBrowser;
|
options.inBrowser = options.inBrowser === undefined ? isBrowser : options.inBrowser;
|
||||||
@@ -256,8 +258,8 @@ ImageSequencer = function ImageSequencer(options) {
|
|||||||
fs.writeFileSync('./src/Modules.js', mods);
|
fs.writeFileSync('./src/Modules.js', mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSequence(name, sequenceString) {
|
function saveSequence(name, sequenceString) { // 4. save sequence
|
||||||
const sequence = stringToJSON(sequenceString);
|
const sequence = str.stringToJSON(sequenceString);
|
||||||
// Save the given sequence string as a module
|
// Save the given sequence string as a module
|
||||||
if (options.inBrowser) {
|
if (options.inBrowser) {
|
||||||
// Inside the browser we save the meta-modules using the Web Storage API
|
// Inside the browser we save the meta-modules using the Web Storage API
|
||||||
@@ -282,7 +284,6 @@ ImageSequencer = function ImageSequencer(options) {
|
|||||||
this.sequences = require('./SavedSequences.json');
|
this.sequences = require('./SavedSequences.json');
|
||||||
}
|
}
|
||||||
|
|
||||||
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
//literals and objects
|
//literals and objects
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ module.exports = {
|
|||||||
'add-qr': require('./modules/AddQR'),
|
'add-qr': require('./modules/AddQR'),
|
||||||
'average': require('./modules/Average'),
|
'average': require('./modules/Average'),
|
||||||
'blend': require('./modules/Blend'),
|
'blend': require('./modules/Blend'),
|
||||||
|
'blob-analysis': require('./modules/BlobAnalysis'),
|
||||||
'blur': require('./modules/Blur'),
|
'blur': require('./modules/Blur'),
|
||||||
'brightness': require('./modules/Brightness'),
|
'brightness': require('./modules/Brightness'),
|
||||||
'canvas-resize': require('./modules/CanvasResize'),
|
'canvas-resize': require('./modules/CanvasResize'),
|
||||||
@@ -28,6 +29,7 @@ module.exports = {
|
|||||||
'gradient': require('./modules/Gradient'),
|
'gradient': require('./modules/Gradient'),
|
||||||
'grid-overlay': require('./modules/GridOverlay'),
|
'grid-overlay': require('./modules/GridOverlay'),
|
||||||
'import-image': require('./modules/ImportImage'),
|
'import-image': require('./modules/ImportImage'),
|
||||||
|
'minify-image': require('./modules/MinifyImage'),
|
||||||
'invert': require('image-sequencer-invert'),
|
'invert': require('image-sequencer-invert'),
|
||||||
'ndvi': require('./modules/Ndvi'),
|
'ndvi': require('./modules/Ndvi'),
|
||||||
'ndvi-colormap': require('./modules/NdviColormap'),
|
'ndvi-colormap': require('./modules/NdviColormap'),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
module.exports = exports = function (options, pixels, oldPixels, callback) {
|
module.exports = exports = function (options, pixels, oldPixels, callback) {
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
var QRCode = require('qrcode');
|
var QRCode = require('qrcode');
|
||||||
QRCode.toDataURL(options.qrCodeString, function (err, url) {
|
QRCode.toDataURL(options.qrCodeString, function (err, url) {
|
||||||
var getPixels = require('get-pixels');
|
var getPixels = require('get-pixels');
|
||||||
@@ -26,17 +28,11 @@ module.exports = exports = function (options, pixels, oldPixels, callback) {
|
|||||||
for (var m = 0; m < width; m++) {
|
for (var m = 0; m < width; m++) {
|
||||||
for (var n = 0; n < height; n++) {
|
for (var n = 0; n < height; n++) {
|
||||||
if (m >= xe && n >= ye) {
|
if (m >= xe && n >= ye) {
|
||||||
pixels.set(m, n, 0, qrPixels.get(m - xe, n - ye, 0));
|
pixelSetter(m, n, [qrPixels.get(m - xe, n - ye, 0), qrPixels.get(m - xe, n - ye, 1), qrPixels.get(m - xe, n - ye, 2), qrPixels.get(m - xe, n - ye, 3)], pixels);
|
||||||
pixels.set(m, n, 1, qrPixels.get(m - xe, n - ye, 1));
|
|
||||||
pixels.set(m, n, 2, qrPixels.get(m - xe, n - ye, 2));
|
|
||||||
pixels.set(m, n, 3, qrPixels.get(m - xe, n - ye, 3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
pixels.set(m, n, 0, oldPixels.get(m, n, 0));
|
pixelSetter(m, n, [qrPixels.get(m, n, 0), qrPixels.get(m, n, 1), qrPixels.get(m, n, 2), qrPixels.get(m, n, 3)], pixels);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ module.exports = function Average(options, UI) {
|
|||||||
|
|
||||||
// do the averaging
|
// do the averaging
|
||||||
function extraManipulation(pixels) {
|
function extraManipulation(pixels) {
|
||||||
|
const $ = window.$;
|
||||||
var i = 0, sum = [0, 0, 0, 0];
|
var i = 0, sum = [0, 0, 0, 0];
|
||||||
while (i < pixels.data.length) {
|
while (i < pixels.data.length) {
|
||||||
sum[0] += pixels.data[i++];
|
sum[0] += pixels.data[i++];
|
||||||
|
|||||||
81
src/modules/BlobAnalysis/BlobAnalysis.js
Normal file
81
src/modules/BlobAnalysis/BlobAnalysis.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
module.exports = function(pixels, options, priorStep){
|
||||||
|
|
||||||
|
var $ = require('jquery'); // to make Blob-analysis work for node.js
|
||||||
|
|
||||||
|
var img = $(priorStep.imgElement);
|
||||||
|
if(Object.keys(img).length === 0){
|
||||||
|
img = $(priorStep.options.step.imgElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.width = pixels.shape[0];
|
||||||
|
canvas.height = pixels.shape[1];
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
ctx.drawImage(img[0], 0, 0);
|
||||||
|
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
|
||||||
|
let src = cv.matFromImageData(imgData);
|
||||||
|
let dst = new cv.Mat();
|
||||||
|
let gray = new cv.Mat();
|
||||||
|
let opening = new cv.Mat();
|
||||||
|
let imageBg = new cv.Mat();
|
||||||
|
let imageFg = new cv.Mat();
|
||||||
|
let distTrans = new cv.Mat();
|
||||||
|
let unknown = new cv.Mat();
|
||||||
|
let markers = new cv.Mat();
|
||||||
|
|
||||||
|
// gray and threshold image
|
||||||
|
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||||
|
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
|
||||||
|
|
||||||
|
// get background
|
||||||
|
let M = cv.Mat.ones(3, 3, cv.CV_8U);
|
||||||
|
cv.erode(gray, gray, M);
|
||||||
|
cv.dilate(gray, opening, M);
|
||||||
|
cv.dilate(opening, imageBg, M, new cv.Point(-1, -1), 3);
|
||||||
|
|
||||||
|
// distance transform
|
||||||
|
cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
|
||||||
|
cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
|
||||||
|
|
||||||
|
// get foreground
|
||||||
|
cv.threshold(distTrans, imageFg, 0.7 * 1, 255, cv.THRESH_BINARY);
|
||||||
|
imageFg.convertTo(imageFg, cv.CV_8U, 1, 0);
|
||||||
|
cv.subtract(imageBg, imageFg, unknown);
|
||||||
|
|
||||||
|
// get connected components markers
|
||||||
|
cv.connectedComponents(imageFg, markers);
|
||||||
|
for (let i = 0; i < markers.rows; i++) {
|
||||||
|
for (let j = 0; j < markers.cols; j++) {
|
||||||
|
markers.intPtr(i, j)[0] = markers.ucharPtr(i, j)[0] + 1;
|
||||||
|
if (unknown.ucharPtr(i, j)[0] == 255) {
|
||||||
|
markers.intPtr(i, j)[0] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
|
||||||
|
cv.watershed(src, markers);
|
||||||
|
|
||||||
|
// draw barriers
|
||||||
|
for (let i = 0; i < markers.rows; i++) {
|
||||||
|
for (let j = 0; j < markers.cols; j++) {
|
||||||
|
if (markers.intPtr(i, j)[0] == -1) {
|
||||||
|
src.ucharPtr(i, j)[0] = 255; // R
|
||||||
|
src.ucharPtr(i, j)[1] = 0; // G
|
||||||
|
src.ucharPtr(i, j)[2] = 0; // B
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cv.imshow(canvas, src);
|
||||||
|
|
||||||
|
src.delete(); dst.delete(); gray.delete(); opening.delete(); imageBg.delete();
|
||||||
|
imageFg.delete(); distTrans.delete(); unknown.delete(); markers.delete(); M.delete();
|
||||||
|
|
||||||
|
var myImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
|
pixels.data = myImageData.data;
|
||||||
|
|
||||||
|
return pixels;
|
||||||
|
};
|
||||||
43
src/modules/BlobAnalysis/Module.js
Normal file
43
src/modules/BlobAnalysis/Module.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
module.exports = function BlobAnalysis(options, UI){
|
||||||
|
|
||||||
|
var output;
|
||||||
|
|
||||||
|
function draw(input, callback, progressObj) {
|
||||||
|
|
||||||
|
progressObj.stop(true);
|
||||||
|
progressObj.overrideFlag = true;
|
||||||
|
|
||||||
|
var step = this;
|
||||||
|
|
||||||
|
var priorStep = this.getStep(-1); // get the previous step to process it
|
||||||
|
|
||||||
|
function extraManipulation(pixels){
|
||||||
|
|
||||||
|
pixels = require('./BlobAnalysis')(pixels, options, priorStep);
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
function output(image, datauri, mimetype){
|
||||||
|
|
||||||
|
step.output = { src: datauri, format: mimetype};
|
||||||
|
}
|
||||||
|
|
||||||
|
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||||
|
output: output,
|
||||||
|
extraManipulation: extraManipulation,
|
||||||
|
format: input.format,
|
||||||
|
image: options.image,
|
||||||
|
inBrowser: options.inBrowser,
|
||||||
|
callback: callback
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
options: options,
|
||||||
|
draw: draw,
|
||||||
|
output: output,
|
||||||
|
UI: UI
|
||||||
|
};
|
||||||
|
};
|
||||||
4
src/modules/BlobAnalysis/index.js
Normal file
4
src/modules/BlobAnalysis/index.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = [
|
||||||
|
require('./Module'),
|
||||||
|
require('./info.json')
|
||||||
|
];
|
||||||
6
src/modules/BlobAnalysis/info.json
Normal file
6
src/modules/BlobAnalysis/info.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "Blob Analysis",
|
||||||
|
"description": "Blob/Region identification for microscopic images.",
|
||||||
|
"inputs": {},
|
||||||
|
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#blob-analysis"
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
module.exports = exports = function(pixels, blur) {
|
module.exports = exports = function(pixels, blur) {
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
let kernel = kernelGenerator(blur),
|
let kernel = kernelGenerator(blur),
|
||||||
pixs = {
|
pixs = {
|
||||||
r: [],
|
r: [],
|
||||||
@@ -24,9 +26,10 @@ module.exports = exports = function(pixels, blur) {
|
|||||||
|
|
||||||
for (let y = 0; y < pixels.shape[1]; y++){
|
for (let y = 0; y < pixels.shape[1]; y++){
|
||||||
for (let x = 0; x < pixels.shape[0]; x++){
|
for (let x = 0; x < pixels.shape[0]; x++){
|
||||||
pixels.set(x, y, 0, Math.max(0, Math.min(conPix[0][y][x], 255)));
|
var pixelvalue = [Math.max(0, Math.min(conPix[0][y][x], 255)),
|
||||||
pixels.set(x, y, 1, Math.max(0, Math.min(conPix[1][y][x], 255)));
|
Math.max(0, Math.min(conPix[1][y][x], 255)),
|
||||||
pixels.set(x, y, 2, Math.max(0, Math.min(conPix[2][y][x], 255)));
|
Math.max(0, Math.min(conPix[2][y][x], 255))];
|
||||||
|
pixelSetter(x, y, pixelvalue, pixels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
module.exports = function canvasResize(options, UI) {
|
module.exports = function canvasResize(options, UI) {
|
||||||
|
|
||||||
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
var output;
|
var output;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function draw(input, callback, progressObj) {
|
function draw(input, callback, progressObj) {
|
||||||
|
|
||||||
options.width = parseInt(options.width || defaults.width);
|
options.width = parseInt(options.width || defaults.width);
|
||||||
@@ -21,16 +21,15 @@ module.exports = function canvasResize(options, UI) {
|
|||||||
var step = this;
|
var step = this;
|
||||||
|
|
||||||
function extraManipulation(pixels) {
|
function extraManipulation(pixels) {
|
||||||
|
|
||||||
let newPixels = require('ndarray')(new Uint8Array(4 * options.width * options.height).fill(0), [options.width, options.height, 4]);
|
let newPixels = require('ndarray')(new Uint8Array(4 * options.width * options.height).fill(0), [options.width, options.height, 4]);
|
||||||
let iMax = options.width - options.x,
|
let iMax = options.width - options.x,
|
||||||
jMax = options.height - options.y;
|
jMax = options.height - options.y;
|
||||||
for (let i = 0; i < iMax && i < pixels.shape[0]; i++) {
|
for (let i = 0; i < iMax && i < pixels.shape[0]; i++) {
|
||||||
for (let j = 0; j < jMax && j < pixels.shape[1]; j++) {
|
for (let j = 0; j < jMax && j < pixels.shape[1]; j++) {
|
||||||
let x = i + options.x, y = j + options.y;
|
let x = i + options.x, y = j + options.y;
|
||||||
newPixels.set(x, y, 0, pixels.get(i, j, 0));
|
pixelSetter(x, y, [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2), pixels.get(i, j, 3)], newPixels);
|
||||||
newPixels.set(x, y, 1, pixels.get(i, j, 1));
|
|
||||||
newPixels.set(x, y, 2, pixels.get(i, j, 2));
|
|
||||||
newPixels.set(x, y, 3, pixels.get(i, j, 3));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newPixels;
|
return newPixels;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
module.exports = function ColorTemperature(options, UI) {
|
module.exports = function ColorTemperature(options, UI) {
|
||||||
|
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
var output;
|
var output;
|
||||||
|
|
||||||
function draw(input, callback, progressObj) {
|
function draw(input, callback, progressObj) {
|
||||||
@@ -38,17 +40,12 @@ module.exports = function ColorTemperature(options, UI) {
|
|||||||
for (let i = 0; i < pixels.shape[0]; i++) {
|
for (let i = 0; i < pixels.shape[0]; i++) {
|
||||||
for (let j = 0; j < pixels.shape[1]; j++) {
|
for (let j = 0; j < pixels.shape[1]; j++) {
|
||||||
|
|
||||||
r_data = pixels.get(i, j, 0);
|
var rgbdata = [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2)];
|
||||||
r_new_data = (255 / r) * r_data;
|
rgbdata[0] = (255 / r) * rgbdata[0];
|
||||||
pixels.set(i, j, 0, r_new_data);
|
rgbdata[1] = (255 / g) * rgbdata[1];
|
||||||
|
rgbdata[2] = (255 / b) * rgbdata[2];
|
||||||
|
pixelSetter(i, j, rgbdata, pixels);
|
||||||
|
|
||||||
g_data = pixels.get(i, j, 1);
|
|
||||||
g_new_data = (255 / g) * g_data;
|
|
||||||
pixels.set(i, j, 1, g_new_data);
|
|
||||||
|
|
||||||
b_data = pixels.get(i, j, 2);
|
|
||||||
b_new_data = (255 / b) * b_data;
|
|
||||||
pixels.set(i, j, 2, b_new_data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
module.exports = exports = function(pixels, contrast) {
|
module.exports = exports = function(pixels, contrast) {
|
||||||
let oldpix = _.cloneDeep(pixels);
|
let oldpix = _.cloneDeep(pixels);
|
||||||
@@ -10,36 +11,18 @@ module.exports = exports = function(pixels, contrast) {
|
|||||||
|
|
||||||
for (let i = 0; i < pixels.shape[0]; i++) {
|
for (let i = 0; i < pixels.shape[0]; i++) {
|
||||||
for (let j = 0; j < pixels.shape[1]; j++) {
|
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 rgbarray = [oldpix.get(i, j, 0) / 255.0, oldpix.get(i, j, 1) / 255.0, oldpix.get(i, j, 2) / 255.0];
|
||||||
|
for(var idx = 0;idx < 3;idx++){
|
||||||
|
rgbarray[idx] -= 0.5;
|
||||||
|
rgbarray[idx] *= contrast;
|
||||||
|
rgbarray[idx] += 0.5;
|
||||||
|
rgbarray[idx] *= 255;
|
||||||
|
if (rgbarray[idx] < 0) rgbarray[idx] = 0;
|
||||||
|
if (rgbarray[idx] > 255) rgbarray[idx] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
var g = oldpix.get(i, j, 1) / 255.0;
|
pixelSetter(i, j, rgbarray, pixels);
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
module.exports = exports = function(pixels, constantFactor, kernelValues, texMode) {
|
module.exports = exports = function(pixels, constantFactor, kernelValues, texMode) {
|
||||||
let kernel = kernelGenerator(constantFactor, kernelValues),
|
let kernel = kernelGenerator(constantFactor, kernelValues),
|
||||||
pixs = {
|
pixs = {
|
||||||
@@ -24,9 +26,8 @@ module.exports = exports = function(pixels, constantFactor, kernelValues, texMod
|
|||||||
|
|
||||||
for (let y = 0; y < pixels.shape[1]; y++){
|
for (let y = 0; y < pixels.shape[1]; y++){
|
||||||
for (let x = 0; x < pixels.shape[0]; x++){
|
for (let x = 0; x < pixels.shape[0]; x++){
|
||||||
pixels.set(x, y, 0, Math.max(0, Math.min(conPix[0][y][x], 255)));
|
var value = [Math.max(0, Math.min(conPix[0][y][x], 255)), Math.max(0, Math.min(conPix[1][y][x], 255)), Math.max(0, Math.min(conPix[2][y][x], 255))];
|
||||||
pixels.set(x, y, 1, Math.max(0, Math.min(conPix[1][y][x], 255)));
|
pixelSetter(x, y, value, pixels);
|
||||||
pixels.set(x, y, 2, Math.max(0, Math.min(conPix[2][y][x], 255)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
module.exports = exports = function(pixels, options){
|
module.exports = exports = function(pixels, options){
|
||||||
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
options.startingX = options.startingX || defaults.startingX;
|
options.startingX = options.startingX || defaults.startingX;
|
||||||
options.startingY = options.startingY || defaults.startingY;
|
options.startingY = options.startingY || defaults.startingY;
|
||||||
@@ -17,10 +18,8 @@ module.exports = exports = function(pixels, options){
|
|||||||
var drawSide = function(startX, startY, endX, endY){
|
var drawSide = function(startX, startY, endX, endY){
|
||||||
for (var n = startX; n <= endX + thickness; n++){
|
for (var n = startX; n <= endX + thickness; n++){
|
||||||
for (var k = startY; k <= endY + thickness; k++){
|
for (var k = startY; k <= endY + thickness; k++){
|
||||||
pixels.set(n, k, 0, color[0]);
|
|
||||||
pixels.set(n, k, 1, color[1]);
|
pixelSetter(n, k, color, pixels); //to remove 4th channel - pixels.set(n, k, 3, color[3]);
|
||||||
pixels.set(n, k, 2, color[2]);
|
|
||||||
//pixels.set(n, k, 3, color[3]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
// Define kernels for the sobel filter
|
// Define kernels for the sobel filter
|
||||||
|
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
const kernelx = [
|
const kernelx = [
|
||||||
[-1, 0, 1],
|
[-1, 0, 1],
|
||||||
[-2, 0, 2],
|
[-2, 0, 2],
|
||||||
@@ -41,19 +43,14 @@ module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, useHyst
|
|||||||
return pixels;
|
return pixels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function supress(pixels, pixel) {
|
function supress(pixels, pixel) {
|
||||||
pixels.set(pixel[0], pixel[1], 0, 0);
|
pixelSetter(pixel[0], pixel[1], [0, 0, 0, 255], pixels);
|
||||||
pixels.set(pixel[0], pixel[1], 1, 0);
|
|
||||||
pixels.set(pixel[0], pixel[1], 2, 0);
|
|
||||||
pixels.set(pixel[0], pixel[1], 3, 255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function preserve(pixels, pixel) {
|
function preserve(pixels, pixel) {
|
||||||
pixels.set(pixel[0], pixel[1], 0, 255);
|
pixelSetter(pixel[0], pixel[1], [255, 255, 255, 255], pixels);
|
||||||
pixels.set(pixel[0], pixel[1], 1, 255);
|
|
||||||
pixels.set(pixel[0], pixel[1], 2, 255);
|
|
||||||
pixels.set(pixel[0], pixel[1], 3, 255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sobelFilter function that convolves sobel kernel over every pixel
|
// sobelFilter function that convolves sobel kernel over every pixel
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
module.exports = function flipImage(oldPixels, pixels, axis) {
|
module.exports = function flipImage(oldPixels, pixels, axis) {
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
var width = oldPixels.shape[0],
|
var width = oldPixels.shape[0],
|
||||||
height = oldPixels.shape[1];
|
height = oldPixels.shape[1];
|
||||||
|
|
||||||
function copyPixel(x1, y1, x2, y2){
|
function copyPixel(x1, y1, x2, y2){
|
||||||
pixels.set(x1, y1, 0, oldPixels.get(x2, y2, 0));
|
pixelSetter(x1, y1, [oldPixels.get(x2, y2, 0), oldPixels.get(x2, y2, 1), oldPixels.get(x2, y2, 2), oldPixels.get(x2, y2, 3)], pixels);
|
||||||
pixels.set(x1, y1, 1, oldPixels.get(x2, y2, 1));
|
|
||||||
pixels.set(x1, y1, 2, oldPixels.get(x2, y2, 2));
|
|
||||||
pixels.set(x1, y1, 3, oldPixels.get(x2, y2, 3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function flip(){
|
function flip(){
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
module.exports = function Invert(options, UI) {
|
module.exports = function Invert(options, UI) {
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
var output;
|
var output;
|
||||||
|
|
||||||
// The function which is called on every draw.
|
// The function which is called on every draw.
|
||||||
function draw(input, callback, progressObj) {
|
function draw(input, callback) {
|
||||||
|
|
||||||
var getPixels = require('get-pixels');
|
var getPixels = require('get-pixels');
|
||||||
var savePixels = require('save-pixels');
|
var savePixels = require('save-pixels');
|
||||||
|
|
||||||
@@ -21,10 +23,8 @@ module.exports = function Invert(options, UI) {
|
|||||||
for (var i = 0; i < pixels.shape[0]; i++) {
|
for (var i = 0; i < pixels.shape[0]; i++) {
|
||||||
for (var j = 0; j < pixels.shape[1]; j++) {
|
for (var j = 0; j < pixels.shape[1]; j++) {
|
||||||
let val = (i / width) * 255;
|
let val = (i / width) * 255;
|
||||||
pixels.set(i, j, 0, val);
|
pixelSetter(i, j, [val, val, val, 255], pixels);
|
||||||
pixels.set(i, j, 1, val);
|
|
||||||
pixels.set(i, j, 2, val);
|
|
||||||
pixels.set(i, j, 3, 255);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var chunks = [];
|
var chunks = [];
|
||||||
|
|||||||
@@ -1,27 +1,31 @@
|
|||||||
module.exports = exports = function(pixels, options){
|
module.exports = exports = function(pixels, options){
|
||||||
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
options.x = Number(options.x) || defaults.x;
|
if(Number(options.x)==0){
|
||||||
options.y = Number(options.y) || defaults.y;
|
options.x = 1;
|
||||||
|
}
|
||||||
|
if( Number(options.y)==0) {
|
||||||
|
options.y =1;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.x = Math.abs(Number(options.x)) || defaults.x;
|
||||||
|
options.y = Math.abs(Number(options.y)) || defaults.y;
|
||||||
color = options.color || defaults.color;
|
color = options.color || defaults.color;
|
||||||
color = color.substring(color.indexOf('(') + 1, color.length - 1); // extract only the values from rgba(_,_,_,_)
|
color = color.substring(color.indexOf('(') + 1, color.length - 1); // extract only the values from rgba(_,_,_,_)
|
||||||
color = color.split(',');
|
color = color.split(',');
|
||||||
|
|
||||||
for(var x = 0; x < pixels.shape[0]; x += options.x){
|
for(var x = 0; x < pixels.shape[0]; x += options.x){
|
||||||
for(var y = 0 ; y < pixels.shape[1]; y++){
|
for(var y = 0 ; y < pixels.shape[1]; y++){
|
||||||
pixels.set(x, y, 0, color[0]);
|
pixelSetter(x, y, color, pixels); // to remove 4th channel - pixels.set(x, y, 3, color[3]);
|
||||||
pixels.set(x, y, 1, color[1]);
|
|
||||||
pixels.set(x, y, 2, color[2]);
|
|
||||||
//pixels.set(x, y, 3, color[3]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var y = 0; y < pixels.shape[1]; y += options.y){
|
for(var y = 0; y < pixels.shape[1]; y += options.y){
|
||||||
for(var x = 0 ; x < pixels.shape[0]; x++){
|
for(var x = 0 ; x < pixels.shape[0]; x++){
|
||||||
pixels.set(x, y, 0, color[0]);
|
pixelSetter(x, y, color, pixels); // to remove 4th channel - pixels.set(x, y, 3, color[3]);
|
||||||
pixels.set(x, y, 1, color[1]);
|
|
||||||
pixels.set(x, y, 2, color[2]);
|
|
||||||
//pixels.set(x, y, 3, color[3]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ module.exports = function Channel(options, UI) {
|
|||||||
|
|
||||||
function draw(input, callback, progressObj) {
|
function draw(input, callback, progressObj) {
|
||||||
|
|
||||||
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
const defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
options.gradient = options.gradient || defaults.gradient;
|
options.gradient = options.gradient || defaults.gradient;
|
||||||
options.gradient = JSON.parse(options.gradient);
|
options.gradient = JSON.parse(options.gradient);
|
||||||
|
|
||||||
@@ -32,10 +34,8 @@ module.exports = function Channel(options, UI) {
|
|||||||
|
|
||||||
for (let x = 0; x < 256; x++) {
|
for (let x = 0; x < 256; x++) {
|
||||||
for (let y = 0; y < 256; y++) {
|
for (let y = 0; y < 256; y++) {
|
||||||
pixels.set(x, y, 0, 255);
|
pixelSetter(x, y, [255, 255, 255, 255], pixels);
|
||||||
pixels.set(x, y, 1, 255);
|
|
||||||
pixels.set(x, y, 2, 255);
|
|
||||||
pixels.set(x, y, 3, 255);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,9 +43,8 @@ module.exports = function Channel(options, UI) {
|
|||||||
if (options.gradient) {
|
if (options.gradient) {
|
||||||
for (let x = 0; x < 256; x++) {
|
for (let x = 0; x < 256; x++) {
|
||||||
for (let y = 0; y < 10; y++) {
|
for (let y = 0; y < 10; y++) {
|
||||||
pixels.set(x, 255 - y, 0, x);
|
pixelSetter(x, 255 - y, [x, x, x], pixels);
|
||||||
pixels.set(x, 255 - y, 1, x);
|
|
||||||
pixels.set(x, 255 - y, 2, x);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,9 +55,8 @@ module.exports = function Channel(options, UI) {
|
|||||||
let pixCount = Math.round(convfactor * hist[x]);
|
let pixCount = Math.round(convfactor * hist[x]);
|
||||||
|
|
||||||
for (let y = startY; y < pixCount; y++) {
|
for (let y = startY; y < pixCount; y++) {
|
||||||
pixels.set(x, 255 - y, 0, 204);
|
pixelSetter(x, 255 - y, [204, 255, 153], pixels);
|
||||||
pixels.set(x, 255 - y, 1, 255);
|
|
||||||
pixels.set(x, 255 - y, 2, 153);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
102
src/modules/MinifyImage/Module.js
Normal file
102
src/modules/MinifyImage/Module.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
module.exports = function MinifyImage(options, UI) {
|
||||||
|
var output;
|
||||||
|
if (!options.inBrowser) {
|
||||||
|
base64Img = require('base64-img');
|
||||||
|
imagemin = require('imagemin');
|
||||||
|
imageminJpegtran = require('imagemin-jpegtran');
|
||||||
|
imageminPngquant = require('imagemin-pngquant');
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw(input, callback, progressObj) {
|
||||||
|
progressObj.stop(true);
|
||||||
|
progressObj.overrideFlag = true;
|
||||||
|
|
||||||
|
var step = this;
|
||||||
|
|
||||||
|
function dataURItoBlob(dataURI) {
|
||||||
|
// convert base64 to raw binary data held in a string
|
||||||
|
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
|
||||||
|
var byteString = atob(dataURI.split(',')[1]);
|
||||||
|
|
||||||
|
// separate out the mime component
|
||||||
|
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
||||||
|
|
||||||
|
// write the bytes of the string to an ArrayBuffer
|
||||||
|
var ab = new ArrayBuffer(byteString.length);
|
||||||
|
|
||||||
|
// create a view into the buffer
|
||||||
|
var ia = new Uint8Array(ab);
|
||||||
|
|
||||||
|
// set the bytes of the buffer to the correct values
|
||||||
|
for (var i = 0; i < byteString.length; i++) {
|
||||||
|
ia[i] = byteString.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the ArrayBuffer to a blob, and you're done
|
||||||
|
var blob = new Blob([ab], {
|
||||||
|
type: mimeString
|
||||||
|
});
|
||||||
|
return blob;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (options.inBrowser) {
|
||||||
|
var Compressor = require('compressorjs');
|
||||||
|
var blob = dataURItoBlob(input.src);
|
||||||
|
new Compressor(blob, {
|
||||||
|
quality: options.quality || 0.5,
|
||||||
|
success(result) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.readAsDataURL(result);
|
||||||
|
reader.onloadend = function () {
|
||||||
|
base64data = reader.result;
|
||||||
|
output(base64data, input.format);
|
||||||
|
if (callback) callback();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
error(err) {
|
||||||
|
console.log(err.message);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
let filePath = __dirname + '/images/';
|
||||||
|
var returnPath = base64Img.imgSync(input.src, filePath, 'test');
|
||||||
|
(async () => {
|
||||||
|
const files = await imagemin([returnPath], {
|
||||||
|
destination: __dirname + '/results/',
|
||||||
|
plugins: [
|
||||||
|
imageminJpegtran(),
|
||||||
|
imageminPngquant({
|
||||||
|
quality: [0.6, 0.8]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
var destPath = __dirname + '/results/test.' + input.format;
|
||||||
|
var data = base64Img.base64Sync(destPath);
|
||||||
|
output(data, input.format);
|
||||||
|
if (callback) callback();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function output(datauri, mimetype) {
|
||||||
|
|
||||||
|
// This output is accessible by Image Sequencer
|
||||||
|
step.output = {
|
||||||
|
src: datauri,
|
||||||
|
format: mimetype
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
options: options,
|
||||||
|
draw: draw,
|
||||||
|
output: output,
|
||||||
|
UI: UI
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
4
src/modules/MinifyImage/index.js
Normal file
4
src/modules/MinifyImage/index.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = [
|
||||||
|
require('./Module'),
|
||||||
|
require('./info.json')
|
||||||
|
];
|
||||||
14
src/modules/MinifyImage/info.json
Normal file
14
src/modules/MinifyImage/info.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "minify-image",
|
||||||
|
"description": "Minifies the given image (Works for jpg/jpeg/webp images in browser)",
|
||||||
|
"url": "https://github.com/publiclab/image-sequencer/tree/master/MODULES.md",
|
||||||
|
"inputs": {
|
||||||
|
"quality":{
|
||||||
|
"type": "float",
|
||||||
|
"desc": "quality aspect of the given image",
|
||||||
|
"default": "0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#add-qr-module"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -2,6 +2,7 @@ module.exports = exports = function(pixels, options) {
|
|||||||
|
|
||||||
|
|
||||||
let defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
let defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
let fillColor = options.fillColor || defaults.fillColor,
|
let fillColor = options.fillColor || defaults.fillColor,
|
||||||
x = parseInt(options.startingX) || defaults.startingX,
|
x = parseInt(options.startingX) || defaults.startingX,
|
||||||
@@ -47,10 +48,8 @@ module.exports = exports = function(pixels, options) {
|
|||||||
} while (isSimilar(currx, south) && south < height);
|
} while (isSimilar(currx, south) && south < height);
|
||||||
|
|
||||||
for (n = north + 1; n < south; n += 1) {
|
for (n = north + 1; n < south; n += 1) {
|
||||||
pixels.set(currx, n, 0, fillColor[0]);
|
pixelSetter(currx, n, fillColor, pixels);
|
||||||
pixels.set(currx, n, 1, fillColor[1]);
|
|
||||||
pixels.set(currx, n, 2, fillColor[2]);
|
|
||||||
pixels.set(currx, n, 3, fillColor[3]);
|
|
||||||
if (isSimilar(currx - 1, n)) {
|
if (isSimilar(currx - 1, n)) {
|
||||||
queuex.push(currx - 1);
|
queuex.push(currx - 1);
|
||||||
queuey.push(n);
|
queuey.push(n);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
module.exports = exports = function(pixels, options){
|
module.exports = exports = function(pixels, options){
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
var color = options.color || 'rgb(228,86,81)';
|
var color = options.color || 'rgb(228,86,81)';
|
||||||
color = color.substring(color.indexOf('(') + 1, color.length - 1); // extract only the values from rgba(_,_,_,_)
|
color = color.substring(color.indexOf('(') + 1, color.length - 1); // extract only the values from rgba(_,_,_,_)
|
||||||
|
|
||||||
@@ -23,7 +25,6 @@ module.exports = exports = function(pixels, options){
|
|||||||
g >= cg * minFactor && g <= cg * maxFactor &&
|
g >= cg * minFactor && g <= cg * maxFactor &&
|
||||||
b >= cb * minFactor && b <= cb * maxFactor);
|
b >= cb * minFactor && b <= cb * maxFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < pixels.shape[0]; i++){
|
for(var i = 0; i < pixels.shape[0]; i++){
|
||||||
for(var j = 0; j < pixels.shape[1]; j++){
|
for(var j = 0; j < pixels.shape[1]; j++){
|
||||||
var r = pixels.get(i, j, 0),
|
var r = pixels.get(i, j, 0),
|
||||||
@@ -32,16 +33,16 @@ module.exports = exports = function(pixels, options){
|
|||||||
if(isSimilar(r, g, b)){
|
if(isSimilar(r, g, b)){
|
||||||
if (replaceMethod == 'greyscale'){
|
if (replaceMethod == 'greyscale'){
|
||||||
var avg = (r + g + b) / 3;
|
var avg = (r + g + b) / 3;
|
||||||
pixels.set(i, j, 0, avg);
|
pixelSetter(i, j, [avg, avg, avg], pixels);
|
||||||
pixels.set(i, j, 1, avg);
|
|
||||||
pixels.set(i, j, 2, avg);
|
|
||||||
}else {
|
}else {
|
||||||
pixels.set(i, j, 0, replaceColor[0]);
|
pixelSetter(i, j, replaceColor, pixels);
|
||||||
pixels.set(i, j, 1, replaceColor[1]);
|
|
||||||
pixels.set(i, j, 2, replaceColor[2]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return pixels;
|
return pixels;
|
||||||
};
|
};
|
||||||
@@ -3,44 +3,36 @@ module.exports = function TextOverlay(options, UI) {
|
|||||||
|
|
||||||
var output;
|
var output;
|
||||||
|
|
||||||
function draw(input, callback, progressObj) {
|
function draw(input, callback) {
|
||||||
|
|
||||||
progressObj.stop(true);
|
|
||||||
progressObj.overrideFlag = true;
|
|
||||||
|
|
||||||
var step = this;
|
var step = this;
|
||||||
if (!options.step.inBrowser) { // This module is only for browser
|
|
||||||
this.output = input;
|
var priorStep = this.getStep(-1); // get the previous step to add text onto it.
|
||||||
callback();
|
|
||||||
|
function extraManipulation(pixels) {
|
||||||
|
//if (options.step.inBrowser)
|
||||||
|
pixels = require('./TextOverlay')(pixels, options, priorStep);
|
||||||
|
return pixels;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
var priorStep = this.getStep(-1); // get the previous step to add text onto it.
|
|
||||||
|
|
||||||
function extraManipulation(pixels) {
|
function output(image, datauri, mimetype) {
|
||||||
//if (options.step.inBrowser)
|
|
||||||
pixels = require('./TextOverlay')(pixels, options, priorStep);
|
|
||||||
return pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
function output(image, datauri, mimetype) {
|
// This output is accesible by Image Sequencer
|
||||||
|
step.output = { src: datauri, format: mimetype };
|
||||||
// This output is accesible by Image Sequencer
|
|
||||||
step.output = { src: datauri, format: mimetype };
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
|
||||||
output: output,
|
|
||||||
ui: options.step.ui,
|
|
||||||
extraManipulation: extraManipulation,
|
|
||||||
format: input.format,
|
|
||||||
image: options.image,
|
|
||||||
inBrowser: options.inBrowser,
|
|
||||||
callback: callback,
|
|
||||||
useWasm:options.useWasm
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
return {
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
module.exports = exports = function(pixels, options, priorstep){
|
module.exports = exports = function(pixels, options, priorstep){
|
||||||
|
|
||||||
|
var $ = require('jquery'); // to make text-overlay work for node.js
|
||||||
|
|
||||||
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||||
|
|
||||||
options.text = options.text || defaults.text;
|
options.text = options.text || defaults.text;
|
||||||
|
|||||||
@@ -40,6 +40,5 @@
|
|||||||
"desc": "Enter the font size in pixels.",
|
"desc": "Enter the font size in pixels.",
|
||||||
"default": "12"
|
"default": "12"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"only": "browser"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
module.exports = function PixelManipulation(image, options) {
|
module.exports = function PixelManipulation(image, options) {
|
||||||
// To handle the case where pixelmanipulation is called on the input object itself
|
// To handle the case where pixelmanipulation is called on the input object itself
|
||||||
// like input.pixelManipulation(options)
|
// like input.pixelManipulation(options)
|
||||||
|
|
||||||
|
const pixelSetter = require('../../util/pixelSetter.js');
|
||||||
|
|
||||||
if (arguments.length <= 1) {
|
if (arguments.length <= 1) {
|
||||||
options = image;
|
options = image;
|
||||||
image = this;
|
image = this;
|
||||||
@@ -86,10 +89,8 @@ module.exports = function PixelManipulation(image, options) {
|
|||||||
y
|
y
|
||||||
);
|
);
|
||||||
|
|
||||||
pixels.set(x, y, 0, pixel[0]);
|
pixelSetter(x, y, pixel, pixels);
|
||||||
pixels.set(x, y, 1, pixel[1]);
|
|
||||||
pixels.set(x, y, 2, pixel[2]);
|
|
||||||
pixels.set(x, y, 3, pixel[3]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
5
src/util/pixelSetter.js
Normal file
5
src/util/pixelSetter.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = function(x, y, value, pixels){
|
||||||
|
for(let i = 0; i < value.length; i++){
|
||||||
|
pixels.set(x, y, i, value[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
32
test/core/modules/minify-image.js
Normal file
32
test/core/modules/minify-image.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
const dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEX+AAD///+KQee0AAAAAWJLR0QB/wIt3gAAAAd0SU1FB+EGHRIVAvrm6EMAAAAMSURBVAjXY2AgDQAAADAAAceqhY4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDYtMjlUMTg6MjE6MDIrMDI6MDDGD83DAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTA2LTI5VDE4OjIxOjAyKzAyOjAwt1J1fwAAAABJRU5ErkJggg==';
|
||||||
|
console.log(dataURI);
|
||||||
|
const ImageSequencer = require('../../../src/ImageSequencer');
|
||||||
|
const test = require('tape');
|
||||||
|
var atob = require('atob');
|
||||||
|
|
||||||
|
var sequencer = ImageSequencer();
|
||||||
|
var base64str = dataURI.substr(22);
|
||||||
|
var decoded = atob(base64str);
|
||||||
|
|
||||||
|
|
||||||
|
var initialSize = decoded.length;
|
||||||
|
|
||||||
|
|
||||||
|
sequencer.loadImage(dataURI, function(){
|
||||||
|
this.addSteps('minify-image');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('minify-image minifies the image', t => {
|
||||||
|
sequencer.run(function callback(out){
|
||||||
|
console.log(out);
|
||||||
|
var base64str = out.substr(22);
|
||||||
|
var decoded = atob(base64str);
|
||||||
|
var miniifiedSize = decoded.length;
|
||||||
|
var isLess = miniifiedSize < initialSize;
|
||||||
|
t.equal(isLess, true, 'image minified');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
21
test/ui/spec/basicUi.spec.js
Normal file
21
test/ui/spec/basicUi.spec.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
describe('Default sequencer HTML', function() {
|
||||||
|
|
||||||
|
beforeAll(function() {
|
||||||
|
jasmine.getFixtures().fixturesPath = 'test/ui/spec/fixtures';
|
||||||
|
fixture = loadFixtures('index.html');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds a step from the quick selector', function() {
|
||||||
|
expect($('.step').length).toBe(1);
|
||||||
|
expect($('.step:first img')[0].src).not.toBeUndefined();
|
||||||
|
expect($('.step:first img')[0].src).not.toBe('');
|
||||||
|
// needs more setup
|
||||||
|
$("[data-value='brightness']").click()
|
||||||
|
expect($('.step').length).toBe(2);
|
||||||
|
expect($('.step:last img')[0].src).not.toBeUndefined();
|
||||||
|
expect($('.step:last img')[0].src).not.toBe('');
|
||||||
|
expect($('.step:last img')[0].src).not.toEqual($('.step:first img')[0].src);
|
||||||
|
// TODO: test the actual `src` attribute of $('.step:last img') against a known value
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -39,4 +39,5 @@ describe('Default sequencer HTML', function() {
|
|||||||
it('import options from url', function() {
|
it('import options from url', function() {
|
||||||
expect(defaultHtmlSequencerUi.importStepsFromUrlHash).toHaveBeenCalled();
|
expect(defaultHtmlSequencerUi.importStepsFromUrlHash).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
187
test/ui/spec/fixtures/index.html
vendored
Normal file
187
test/ui/spec/fixtures/index.html
vendored
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF8">
|
||||||
|
<link rel="manifest" href="manifest.json">
|
||||||
|
|
||||||
|
<title>Image Sequencer</title>
|
||||||
|
|
||||||
|
<script src="../../node_modules/jquery/dist/jquery.min.js"></script>
|
||||||
|
<script src="../../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||||
|
<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="../../examples/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="../../examples/demo.css">
|
||||||
|
<link href="../../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
|
||||||
|
<link href="../../node_modules/selectize/dist/css/selectize.default.css" rel="stylesheet">
|
||||||
|
<!-- for crop module: -->
|
||||||
|
<link href="../../node_modules/imgareaselect/distfiles/css/imgareaselect-default.css" rel="stylesheet">
|
||||||
|
<link href="../../examples/selectize.default.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<div id="dropzone" class="dropzone">
|
||||||
|
<p>
|
||||||
|
<i>Select or drag in an image to start!</i>
|
||||||
|
</p>
|
||||||
|
<center>
|
||||||
|
<input type="file" id="fileInput" value="" accept="image/*"><br />
|
||||||
|
<button type="button" id="take-photo" class="btn btn-primary btn-block btn-lg ">Take a Photo</button>
|
||||||
|
<video id="video" width="100%" height="100%" style="display:none"></video>
|
||||||
|
<a href="#" id="capture" style="display:none" class="btn btn-primary btn-md">Click Picture</a>
|
||||||
|
<a href="#" id="close" style="display:none" class="btn btn-default btn-md">Close</a>
|
||||||
|
<canvas id="canvas" width="400" height="300" style="display:none"></canvas>
|
||||||
|
</center>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section id="steps" class="row">
|
||||||
|
<div id="load-image"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules in browser's localStorage.
|
||||||
|
</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<section id="addStep" class="panel panel-primary">
|
||||||
|
<div class="form-inline">
|
||||||
|
<div class="panel-body">
|
||||||
|
<div style="display:flex; justify-content:center;">
|
||||||
|
</div>
|
||||||
|
<p class="info">Select a new module to add to your sequence.</p>
|
||||||
|
<div class="row center-align radio-group">
|
||||||
|
<div>
|
||||||
|
<div class="radio" data-value="resize">
|
||||||
|
<i class="fa fa-arrows-alt fa-4x i-over"></i>
|
||||||
|
</div>
|
||||||
|
<p>Resize</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="radio" data-value="brightness">
|
||||||
|
<i class="fa fa-sun-o fa-4x i-over"></i>
|
||||||
|
</div>
|
||||||
|
<p>Brightness</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="radio" data-value="contrast">
|
||||||
|
<i class="fa fa-adjust fa-4x i-over"></i>
|
||||||
|
</div>
|
||||||
|
<p>Contrast</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="radio" data-value="saturation">
|
||||||
|
<i class="fa fa-tint fa-4x i-over i-small"></i>
|
||||||
|
</div>
|
||||||
|
<p>Saturation</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="radio" data-value="rotate">
|
||||||
|
<i class="fa fa-rotate-right fa-4x i-over"></i>
|
||||||
|
</div>
|
||||||
|
<p>Rotate</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="radio" data-value="crop">
|
||||||
|
<i class="fa fa-crop fa-4x i-over"></i>
|
||||||
|
</div>
|
||||||
|
<p>Crop</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
|
||||||
|
<select id="selectStep" class="text-center">
|
||||||
|
<!-- The default null selection has been appended manually in demo.js
|
||||||
|
This is because the options in select are overritten when options are appended.-->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
|
||||||
|
</div>
|
||||||
|
<div class="row center-align">
|
||||||
|
<button id="resetButton" class="btn btn-default btn-lg"
|
||||||
|
style=" margin: 20px 35px 0px 35px; width:100%;">Clear All Steps</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="modal fade" id="js-download-gif-modal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
|
||||||
|
aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title">Your gif is ready</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="js-download-modal-gif-container">
|
||||||
|
<!-- Gif should appear here -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Done</button>
|
||||||
|
|
||||||
|
<button id="js-download-as-gif-button" class="btn btn-primary">Download</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<section id="dwnld" class="panel panel-primary">
|
||||||
|
<div class="form-inline">
|
||||||
|
<div class="panel-body">
|
||||||
|
<div style="text-align:center;">
|
||||||
|
<h2 style="margin-top:20px">Save</h2>
|
||||||
|
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
|
||||||
|
<option value="save-image">Save as PNG</option>
|
||||||
|
<option value="save-gif">Save as GIF (all steps)</option>
|
||||||
|
<option value="save-seq">Save sequence</option>
|
||||||
|
<option value="save-seq-string">Save sequence string</option>
|
||||||
|
</select>
|
||||||
|
<p><button id="saveButton" class="btn btn-primary btn-lg save-button">Save</button></p>
|
||||||
|
<p><button class="btn btn-default btn-lg js-view-as-gif" id="gif">Preview GIF</button></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<center><button class="btn btn-default btn-sm" id="clear-cache">Clear offline cache</button></center>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
var sequencer;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<script async src="../../node_modules/opencv.js/opencv.js" type="text/javascript"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
{
|
{
|
||||||
"spec_dir": "test/spec",
|
"spec_dir": "test/ui/spec",
|
||||||
"spec_files": [
|
"spec_files": [
|
||||||
"**/*.[sS]pec.js"
|
"**/*.[sS]pec.js"
|
||||||
],
|
],
|
||||||
"helpers": [
|
"helpers": [
|
||||||
"helpers/**/*.js"
|
"helpers/**/*.js",
|
||||||
|
"../../../node_modules/jquery/dist/jquery.min.js",
|
||||||
|
"../../../node_modules/bootstrap/dist/js/bootstrap.min.js",
|
||||||
|
"../../../node_modules/jasmine-jquery/lib/jasmine-jquery.js",
|
||||||
|
"../../../dist/image-sequencer.js",
|
||||||
|
"../../../dist/image-sequencer-ui.js"
|
||||||
],
|
],
|
||||||
"stopSpecOnExpectationFailure": false,
|
"stopSpecOnExpectationFailure": false,
|
||||||
"random": false
|
"random": false
|
||||||
|
|||||||
Reference in New Issue
Block a user