mirror of
https://github.com/publiclab/image-sequencer.git
synced 2025-12-11 10:49:59 +01:00
Compare commits
5 Commits
origin/mco
...
user-prefs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a091bd9ab8 | ||
|
|
3e645f9f7d | ||
|
|
4b9d67ca4a | ||
|
|
a2cd5bafd6 | ||
|
|
e505ef6c25 |
@@ -15,6 +15,7 @@ Most contribution (we imagine) would be in the form of API-compatible modules, w
|
||||
* [Contributing Modules](#contributing-modules)
|
||||
* [Info File](#info-file)
|
||||
* [Ideas](#Contribution-ideas)
|
||||
* [User Preferences](#user-preferences)
|
||||
* [Grunt Tasks](#grunt-tasks)
|
||||
* [UI Helper Methods](#ui-helper-methods)
|
||||
|
||||
@@ -368,6 +369,45 @@ module.exports =
|
||||
}
|
||||
});
|
||||
```
|
||||
## User Preferences
|
||||
The user preferences API can be used for adding, reading, updating and deleting user preferences in the browser using **indexedDB** API.
|
||||
* File Path: [/src/ui/userPrefs.js](https://github.com/publiclab/image-sequencer/blob/main/src/ui/userPrefs.js)
|
||||
### Usage
|
||||
```js
|
||||
var userPrefs = require('/path/to/userPrefs')(options);
|
||||
if (userPrefs.error) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
userPrefs.addPref('user-name', {name: 'user'}, () => {
|
||||
userPrefs.new().getPref('user-name', (pref) => {
|
||||
console.log(pref.name); // user
|
||||
userPrefs.new().deletePref('user-name', () => {console.log('deleted')}) // preference deleted
|
||||
|
||||
})
|
||||
})
|
||||
```
|
||||
### Return Value
|
||||
A new `userPreferenceManager` object is returned by the function.
|
||||
###### note: If an error occured or if **indexedDB** is not supported by he browser, the return value will be an object with a string `error` property.
|
||||
#### Properties
|
||||
The `userPreferenceManager` object has the following properties.
|
||||
- `dbName`: Name of the database the user preferences are stored in.
|
||||
- `storeName`: The object store in the database where the user preferences are stored.
|
||||
#### Options
|
||||
The function accepts a single object called `options` as an argument which has the following properties.
|
||||
* `dbName`: Name of a custom database. Default is `user-prefs`.
|
||||
* `storeName`: Name of a custom objectStore. Default is `user-prefs`.
|
||||
#### Methods
|
||||
The following methods are available on the returned object.
|
||||
* `addPref(prefName, preference, callback)`: Adds a preference with the name `prefName` and value `preference`. `preference` is an object containing any key but `preference`. `callback` is a function executed once a preference as been added.
|
||||
* `deletePref(prefName, callback)`: Deletes he preference with the name `prefName` if it exists. `callback` is executed once the preference is deleted.
|
||||
* `updatePref(prefName, preference, callback)`: Updates the value of the preference with the name `prefName` to `preference`.
|
||||
* `getPref(prefName, callback)`: Gets the preference with the name `prefName`. The value is passed to `callback` which is executed once the preference is fetched. If the requested preference doesn't exist then the value passed to `callback` will be `undefined`.
|
||||
* `new()`: Returns a new `userPreferenceManager` object with the same options as before. This function can be used if the original object is to be reused as the `userPreferenceManager` object can only be used once.
|
||||
|
||||
|
||||
|
||||
## Linting
|
||||
|
||||
@@ -425,10 +465,8 @@ var $step = scopeQuery.scopeSelector(scope),
|
||||
This will return an object with a constructor which returns a `jQuery` object (from inside the scope) but with new `elem` and `elemAll` methods.
|
||||
|
||||
#### Methods of the Returned Object
|
||||
* `elem()`: Selects an element inside the scope.
|
||||
* `elemAll()`: Selects all the instances of a given element inside the scope.
|
||||
* `getScope()`: Returns the scope as a DOM element.
|
||||
* `getDomElem()`: Returns the scoped element as a DOM element instead of a jquery object.
|
||||
* `elem()`: Selects an element inside the scope;
|
||||
* `elemAll()`: Selects all the instances of a given element inside the scope;
|
||||
|
||||
#### Example
|
||||
|
||||
|
||||
706
docs/MODULES.md
706
docs/MODULES.md
@@ -3,229 +3,48 @@ Documentation of various Modules
|
||||
|
||||
List of Module Documentations
|
||||
|
||||
1. [Add QR](#Add-QR-module)
|
||||
2. [Average](#average-module)
|
||||
3. [Blend](#blend-module)
|
||||
4. [Blur](#blur-module)
|
||||
5. [Brightness](#brightness-module)
|
||||
6. [Channel](#channel-module)
|
||||
7. [Colorbar](#colorbar-module)
|
||||
8. [Colormap](#colormap-module)
|
||||
9. [ColorTemperature](#color-temperature)
|
||||
10. [Contrast](#contrast-module)
|
||||
11. [Convolution](#convolution-module)
|
||||
12. [Crop](#crop-module)
|
||||
13. [DecodeQr](#decodeQr-module)
|
||||
14. [Dither](#dither-module)
|
||||
15. [DrawRectangle](#draw-rectangle-module)
|
||||
16. [Dynamic](#dynamic-module)
|
||||
17. [Edge-Detect](#edge-detect-module)
|
||||
18. [FisheyeGl](#fisheyeGl-module)
|
||||
1. [Crop](#crop-module)
|
||||
2. [Segmented-Colormap](#segmented-colormap-module)
|
||||
3. [FisheyeGl](#fisheyeGl-module)
|
||||
4. [Add QR](#Add-QR-module)
|
||||
5. [Average](#average-module)
|
||||
6. [Blend](#blend-module)
|
||||
7. [Blur](#blur-module)
|
||||
8. [Brightness](#brightness-module)
|
||||
9. [Channel](#channel-module)
|
||||
10. [Colorbar](#colorbar-module)
|
||||
11. [Colormap](#colormap-module)
|
||||
12. [Contrast](#contrast-module)
|
||||
13. [Convolution](#convolution-module)
|
||||
14. [DecodeQr](#decodeQr-module)
|
||||
15. [Dither](#dither-module)
|
||||
16. [DrawRectangle](#draw-rectangle-module)
|
||||
17. [Dynamic](#dynamic-module)
|
||||
18. [Edge-Detect](#edge-detect-module)
|
||||
19. [FlipImage](#flipimage-module)
|
||||
20. [Gamma-Correction](#gamma-correction-module)
|
||||
21. [Gradient](#gradient-module)
|
||||
22. [Grid-Overlay](#grid-overlay)
|
||||
23. [Histogram](#histogram-module)
|
||||
24. [Import-image](#import-image-module)
|
||||
25. [Invert](#invert-module)
|
||||
26. [MinifyImage](#minify-image)
|
||||
27. [Ndvi](#ndvi-module)
|
||||
28. [Ndvi-Colormap](#ndvi-colormap-module)
|
||||
29. [Overlay](#overlay-module)
|
||||
30. [PaintBucket](#paint-bucket-module)
|
||||
31. [ReplaceColor](#replacecolor-module)
|
||||
32. [Resize](#resize-module)
|
||||
33. [Rotate](#rotate-module)
|
||||
34. [Saturation](#saturation-module)
|
||||
35. [Segmented-Colormap](#segmented-colormap-module)
|
||||
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)
|
||||
22. [Histogram](#histogram-module)
|
||||
23. [Import-image](#import-image-module)
|
||||
24. [Invert](#invert-module)
|
||||
25. [Ndvi](#ndvi-module)
|
||||
26. [Ndvi-Colormap](#ndvi-colormap-module)
|
||||
27. [Overlay](#overlay-module)
|
||||
28. [PaintBucket](#paint-bucket-module)
|
||||
29. [Resize](#resize-module)
|
||||
30. [ReplaceColor](#replacecolor-module)
|
||||
31. [Rotate](#rotate-module)
|
||||
32. [Saturation](#saturation-module)
|
||||
33. [Threshold](#threshold)
|
||||
34. [Tint](#tint)
|
||||
35. [ColorTemperature](#color-temperature)
|
||||
36. [Grid-Overlay](#grid-overlay)
|
||||
|
||||
|
||||
## crop-module
|
||||
|
||||
This module is used to crop an image.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
@@ -245,90 +64,34 @@ Where `options` is an object having the properties `x`, `y`, `w`, `h`. This diag
|
||||
* `options.h` : half of image height
|
||||
|
||||
|
||||
## decodeQr-module
|
||||
## segmented-colormap-module
|
||||
|
||||
This module is used to map the pixels of the image to a segmented colormap.
|
||||
|
||||
This module is used for decoding a QR in image (if present).
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('decode-qr',options)
|
||||
.addSteps('segmented-colormap',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
## dither-module
|
||||
where `options` is an object with the property `colormap`. `options.colormap` can be:
|
||||
|
||||
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.
|
||||
* "default" : [[0, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 50, 50]]]
|
||||
|
||||
[more info on wikipedia](https://en.wikipedia.org/wiki/Dither)
|
||||
#### Usage
|
||||
* "greyscale" : [[0, [0, 0, 0], [255, 255, 255]], [1, [255, 255, 255], [255, 255, 255]]]
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('dither',options)
|
||||
.run()
|
||||
```
|
||||
where `options` is an object with the following property:
|
||||
* dither : Can select the name of the Dithering Algorithm(default none)
|
||||
|
||||
* "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]]]
|
||||
|
||||
## draw-rectangle-module
|
||||
|
||||
This module helps to draw a rectangle on the image with a starting and ending corner with the specified thickness and color of the border.
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('draw-rectangle',options)
|
||||
.run()
|
||||
```
|
||||
where `options` is an object with the following properties:
|
||||
* startingX : starting x position of the rectangle (default 0)
|
||||
* startingY : starting y position of the rectangle (default 0)
|
||||
* endX : last x position of the rectangle (default "width")
|
||||
* endY : last y position of the rectangle (default "height")
|
||||
* thickness : thickness of the border (default 1)
|
||||
* color : RGBA values separated by a space (default "0 0 0 255")
|
||||
|
||||
|
||||
## dynamic-module
|
||||
|
||||
This module is used for producing each color channel based on the original image's color.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('dynamic',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* red : expression for red channel (R, G, B and A as inputs; default r)
|
||||
* green : expression for green channel (R, G, B and A as inputs; default g)
|
||||
* blue : expression for blue channel (R, G, B and A as inputs; default b)
|
||||
* monochrome: fallback for other channels if none provided (default : r+g+b/3)
|
||||
|
||||
|
||||
## edge-detect-module
|
||||
|
||||
This module is used for detecting images.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('edge-detect',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* blur : Intensity of Gaussian blur (0 to 5; default 2)
|
||||
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
|
||||
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
|
||||
* "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
|
||||
@@ -346,12 +109,246 @@ where `options` is an object with the following properties:
|
||||
* x : Field of View x (0 to 2; default 1)
|
||||
* y : Field of View y (0 to 2; default 1)
|
||||
|
||||
## add-qr-module
|
||||
|
||||
This module Adds QR corresponding to the given string.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('add-qr',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* size : size of QR code in pixels (default 200)
|
||||
* qrCodeString : input string to generate QR code
|
||||
|
||||
|
||||
## average-module
|
||||
|
||||
This module is used for averaging all the pixels of the image.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('average',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
## blend-module
|
||||
|
||||
This module is used for blending two images .
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('blend',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
|
||||
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
|
||||
|
||||
## blur-module
|
||||
|
||||
This module is used for applying a Gaussian blur effect.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('blur',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following property:
|
||||
* blur : Intensity of Gaussian blur (0 to 5; default 2)
|
||||
|
||||
## brightness-module
|
||||
|
||||
This module is used for changing the brightness of the image.
|
||||
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('brightness',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following property:
|
||||
* brightness : brightness of the image in percentage (0 to 100; default 100)
|
||||
|
||||
## channel-module
|
||||
|
||||
This module is used for forming a grayscale image by applying one of the three primary colors.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('channel',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following property:
|
||||
* channel : color of the channel (red, green, blue; default green)
|
||||
|
||||
## colorbar-module
|
||||
|
||||
This module is used for displaying an image with a colorbar.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('colorbar',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* colormap : Name of the Colormap(default, greyscale, stretched, fastie, brntogrn, blutoredjet, colors16; default: default)
|
||||
* x : X-position of the image on which the new image is overlayed (default 0)
|
||||
* y : Y-position of the image on which the new image is overlayed (default 0)
|
||||
* h : height of resulting cropped image (default : 50% of input image width )
|
||||
|
||||
## colormap-module
|
||||
|
||||
This module is used for mapping brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('colormap',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following property:
|
||||
* colormap : Name of the Colormap ( greyscale, stretched, fastie, brntogrn, blutoredjet, colors16)
|
||||
|
||||
## contrast-module
|
||||
|
||||
This module is used for changing the contrast of the image.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('contrast',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following property:
|
||||
* contrast : contrast for the given image (-100 to 100; default : 70)
|
||||
|
||||
## convolution-module
|
||||
|
||||
This module is used for performing image-convolution.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('convolution',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* constantFactor : a constant factor, multiplies all the kernel values by that factor (default : 1/9)
|
||||
* kernelValues : nine space separated numbers representing the kernel values in left to right and top to bottom format(default : 1 1 1 1 1 1 1 1 1)
|
||||
|
||||
## decodeQr-module
|
||||
|
||||
This module is used for decoding a QR in image (if present).
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('decode-qr',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
## dither-module
|
||||
|
||||
This module approximates a color from a mixture of other colors when the required color is not available, creating illusions of the color that is not present actually.
|
||||
|
||||
[more info on wikipedia](https://en.wikipedia.org/wiki/Dither)
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('dither',options)
|
||||
.run()
|
||||
```
|
||||
where `options` is an object with the following property:
|
||||
* dither : Can select the name of the Dithering Algorithm(default none)
|
||||
|
||||
## draw-rectangle-module
|
||||
|
||||
This module helps to draw a rectangle on the image with a starting and ending corner with the specified thickness and color of the border.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('draw-rectangle',options)
|
||||
.run()
|
||||
```
|
||||
where `options` is an object with the following properties:
|
||||
* startingX : starting x position of the rectangle (default 0)
|
||||
* startingY : starting y position of the rectangle (default 0)
|
||||
* endX : last x position of the rectangle (default "width")
|
||||
* endY : last y position of the rectangle (default "height")
|
||||
* thickness : thickness of the border (default 1)
|
||||
* color : RGBA values separated by a space (default "0 0 0 255")
|
||||
|
||||
## dynamic-module
|
||||
|
||||
This module is used for producing each color channel based on the original image's color.
|
||||
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('dynamic',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* red : expression for red channel (R, G, B and A as inputs; default r)
|
||||
* green : expression for green channel (R, G, B and A as inputs; default g)
|
||||
* blue : expression for blue channel (R, G, B and A as inputs; default b)
|
||||
* monochrome: fallback for other channels if none provided (default : r+g+b/3)
|
||||
|
||||
## edge-detect-module
|
||||
|
||||
This module is used for detecting images.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('edge-detect',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following properties:
|
||||
* blur : Intensity of Gaussian blur (0 to 5; default 2)
|
||||
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
|
||||
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
|
||||
|
||||
## flipimage-module
|
||||
|
||||
This module is used for flipping the image on the selected axis.
|
||||
#### Usage
|
||||
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('flip-image',options)
|
||||
@@ -376,7 +373,6 @@ This module is used for applying gamma correction.
|
||||
where `options` is an object with the following property:
|
||||
* adjustment : Inverse of actual gamma factor (default 0.2)
|
||||
|
||||
|
||||
## gradient-module
|
||||
|
||||
This module is used for finding gradient of the image.
|
||||
@@ -388,23 +384,6 @@ This module is used for finding gradient of the image.
|
||||
.run()
|
||||
```
|
||||
|
||||
|
||||
## Grid Overlay
|
||||
|
||||
This adds the grid over an image.
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('grid-overlay',options)
|
||||
.run()
|
||||
```
|
||||
where `options` is an object with the following property:
|
||||
* options.x : The value at which the grid line should start in x-axis.
|
||||
* options.y : The value at which the grid line should start in y-axis.
|
||||
* color : Color for the grid on the image.
|
||||
|
||||
|
||||
## histogram-module
|
||||
|
||||
This module is used for calculating histogram of the image.
|
||||
@@ -419,7 +398,6 @@ This module is used for calculating histogram of the image.
|
||||
where `options` is an object with the following property:
|
||||
* gradient : boolean value used to toggle gradient along x-axis (true or false; default true)
|
||||
|
||||
|
||||
## import-image-module
|
||||
|
||||
This module is used for importing a new image and replacing the original with it.
|
||||
@@ -434,7 +412,6 @@ This module is used for importing a new image and replacing the original with it
|
||||
where `options` is an object with the following property:
|
||||
* url : url of the new image (local image url or data url;default : "./images/monarch.png")
|
||||
|
||||
|
||||
## invert-module
|
||||
|
||||
This module is used for inverting the image.
|
||||
@@ -446,21 +423,6 @@ This module is used for inverting the image.
|
||||
.run()
|
||||
```
|
||||
|
||||
|
||||
## Minify Image
|
||||
|
||||
This module minifies the image using lossy compression that is the image-dimensions are not lost but the size is reduced.
|
||||
|
||||
The module supports jpg/jpeg/webp images in browser; but the node version supports all of the types.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('minify-image')
|
||||
.run()
|
||||
```
|
||||
|
||||
|
||||
## ndvi-module
|
||||
|
||||
This module is used for applying ndvi technique to the image.
|
||||
@@ -475,7 +437,6 @@ This module is used for applying ndvi technique to the image.
|
||||
where `options` is an object with the following property:
|
||||
* filter : filter for NDVI (blue or red; default red)
|
||||
|
||||
|
||||
## ndvi-colormap-module
|
||||
|
||||
This module is used for demonstrating ndvi and colormap properties consecutively.
|
||||
@@ -487,7 +448,6 @@ This module is used for demonstrating ndvi and colormap properties consecutively
|
||||
.run()
|
||||
```
|
||||
|
||||
|
||||
## overlay-module
|
||||
|
||||
This module is used for overlaying an Image over another .
|
||||
@@ -504,10 +464,10 @@ where `options` is an object with the following properties:
|
||||
* y : Y-position of the image on which the new image is overlayed (default 0)
|
||||
* offset : offset to the step on which the output of the last step is overlayed (default -2)
|
||||
|
||||
|
||||
## paint-bucket-module
|
||||
|
||||
This module fills any polygonal shape with the specified color in pixels.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
@@ -522,6 +482,19 @@ where `options` is an object with the following property:
|
||||
* fillColor : they are four spaced seperated numbers representing the RGBA values of fill-color (default "100 100 100 255")
|
||||
* tolerance : it is the % tolerance (default 10)
|
||||
|
||||
## resize-module
|
||||
|
||||
This module is used for resizing an image.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('resize',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following property:
|
||||
* resize : Percentage value of resize (default 125%)
|
||||
|
||||
## replacecolor-module
|
||||
|
||||
@@ -539,22 +512,6 @@ where `options` is an object with the following properties:
|
||||
* color : three space separated numbers representing the RGB values of color to be replaced (default "228 86 81")
|
||||
* tolerance : it is the % tolerance (default 50)
|
||||
|
||||
|
||||
## resize-module
|
||||
|
||||
This module is used for resizing an image.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('resize',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the following property:
|
||||
* resize : Percentage value of resize (default 125%)
|
||||
|
||||
|
||||
## rotate-module
|
||||
|
||||
This module is used for rotating an image.
|
||||
@@ -569,7 +526,6 @@ This module is used for rotating an image.
|
||||
where `options` is an object with the following property:
|
||||
* rotate : angular value for rotation in degrees (between 0 and 360; default 0)
|
||||
|
||||
|
||||
## saturation-module
|
||||
|
||||
This module is used for changing the saturation of the image.
|
||||
@@ -584,49 +540,11 @@ This module is used for changing the saturation of the image.
|
||||
where `options` is an object with the following property:
|
||||
* saturation : saturation for the new image (between 0 and 2; default 0)
|
||||
|
||||
|
||||
## segmented-colormap-module
|
||||
|
||||
This module is used to map the pixels of the image to a segmented colormap.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('segmented-colormap',options)
|
||||
.run()
|
||||
```
|
||||
|
||||
where `options` is an object with the property `colormap`. `options.colormap` can be:
|
||||
|
||||
* "default" : [[0, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 50, 50]]]
|
||||
|
||||
* "greyscale" : [[0, [0, 0, 0], [255, 255, 255]], [1, [255, 255, 255], [255, 255, 255]]]
|
||||
|
||||
* "stretched" : [[0, [0, 0, 255], [0, 0, 255]], [0.1, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.7, [255, 255, 0], [255, 50, 50]], [0.9, [255, 50, 50], [255, 50, 50]]]
|
||||
|
||||
* "fastie" : [[0, [255, 255, 255], [0, 0, 0]], [0.167, [0, 0, 0], [255, 255, 255]], [0.33, [255, 255, 255], [0, 0, 0]], [0.5, [0, 0, 0], [140, 140, 255]], [0.55, [140, 140, 255], [0, 255, 0]], [0.63, [0, 255, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 0, 0]], [0.95, [255, 0, 0], [255, 0, 255]]]
|
||||
|
||||
* A custom array.
|
||||
|
||||
|
||||
## Text Overlay
|
||||
|
||||
The modules allows to add text to image in both browser and node environment. We have the options to modify the font-size and also support few font-styles. The text color can also be modified.
|
||||
#### Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('grid-overlay',options)
|
||||
.run()
|
||||
```
|
||||
The options can take various attributes like,
|
||||
var options = { text : 'Hello World', size : '12'};
|
||||
|
||||
|
||||
## Threshold
|
||||
|
||||
Thresholding is used to create binary images.
|
||||
#### Usage
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
@@ -641,7 +559,8 @@ where `options` is an object with the following property:
|
||||
## Tint
|
||||
|
||||
It adds color tint to an image
|
||||
#### Usage
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
@@ -651,3 +570,34 @@ It adds color tint to an image
|
||||
where `options` is an object with the following property:
|
||||
* color : RGB values seperated by a space (default "0 0 255")
|
||||
* factor : amount of tint (default 0.5)
|
||||
|
||||
|
||||
## Color Temperature
|
||||
|
||||
This changes the color temperature of the image.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('color-temperature',options)
|
||||
.run()
|
||||
```
|
||||
where `options` is an object with the following property:
|
||||
* temperature : temperature between 0 - 40,000 kelvin (default 6000)
|
||||
|
||||
## Grid Overlay
|
||||
|
||||
This adds the grid over an image.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
sequencer.loadImage('PATH')
|
||||
.addSteps('grid-overlay',options)
|
||||
.run()
|
||||
```
|
||||
where `options` is an object with the following property:
|
||||
* options.x : The value at which the grid line should start in x-axis.
|
||||
* options.y : The value at which the grid line should start in y-axis.
|
||||
* color : Color for the grid on the image.
|
||||
@@ -232,7 +232,6 @@
|
||||
var sequencer;
|
||||
})
|
||||
</script>
|
||||
<script async src="../node_modules/opencv.js/opencv.js" type="text/javascript"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -8,14 +8,15 @@
|
||||
// output values, step information.
|
||||
// See documetation for more details.
|
||||
|
||||
const intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
|
||||
var intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
|
||||
urlHash = require('./urlHash.js'),
|
||||
_ = require('lodash'),
|
||||
mapHtmlTypes = require('./mapHtmltypes'),
|
||||
scopeQuery = require('./scopeQuery');
|
||||
scopeQuery = require('./scopeQuery'),
|
||||
$stepAll,
|
||||
$step;
|
||||
|
||||
function DefaultHtmlStepUi(_sequencer, options) {
|
||||
let $step, $stepAll;
|
||||
|
||||
options = options || {};
|
||||
var stepsEl = options.stepsEl || document.querySelector('#steps');
|
||||
@@ -73,10 +74,8 @@ function DefaultHtmlStepUi(_sequencer, options) {
|
||||
|
||||
$step = scopeQuery.scopeSelector(step.ui);
|
||||
$stepAll = scopeQuery.scopeSelectorAll(step.ui);
|
||||
step.ui.$step = $step;
|
||||
step.ui.$stepAll = $stepAll;
|
||||
|
||||
step.linkElements = step.ui.querySelectorAll('a');
|
||||
step.linkElements = $stepAll('a');
|
||||
step.imgElement = $step('a img.img-thumbnail')[0];
|
||||
|
||||
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
|
||||
@@ -269,7 +268,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
|
||||
$step('.load').hide();
|
||||
|
||||
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
|
||||
var imgthumbnail = $step('.img-thumbnail').getDomElem();
|
||||
var imgthumbnail = $step('.img-thumbnail');
|
||||
for (let index = 0; index < step.linkElements.length; index++) {
|
||||
if (step.linkElements[index].contains(imgthumbnail))
|
||||
step.linkElements[index].href = step.imgElement.src;
|
||||
|
||||
@@ -23,10 +23,7 @@ function generatePreview(previewStepName, customValues, path, selector) {
|
||||
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
|
||||
}
|
||||
}
|
||||
if(previewStepName === 'resize')
|
||||
insertPreview(path);
|
||||
else
|
||||
previewSequencer.loadImage(path, loadPreview);
|
||||
previewSequencer.loadImage(path, loadPreview);
|
||||
}
|
||||
|
||||
function updatePreviews(src, selector) {
|
||||
@@ -47,30 +44,11 @@ function updatePreviews(src, selector) {
|
||||
}
|
||||
};
|
||||
|
||||
var img = new Image();
|
||||
img.onload = function(){
|
||||
var height = img.height;
|
||||
var width = img.width;
|
||||
|
||||
let percentage = (80 / height) * 100; //take the min resize value that fits the preview area => (new-width/orig_ht) - '80 as the preview area has 80*80 dimension
|
||||
percentage = Math.max((80 / width) * 100, percentage); // make sure that one dimension doesn't resize greater, leading distorting preview-area fitting
|
||||
percentage = Math.ceil(percentage);
|
||||
|
||||
var sequencer = ImageSequencer();
|
||||
|
||||
sequencer.loadImage(src, function(){
|
||||
this.addSteps('resize', {['resize']: percentage + '%'});
|
||||
this.run((src)=>{
|
||||
Object.keys(previewSequencerSteps).forEach(function (step, index) {
|
||||
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
img.src = src;
|
||||
Object.keys(previewSequencerSteps).forEach(function (step, index) {
|
||||
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
generatePreview : generatePreview,
|
||||
updatePreviews : updatePreviews
|
||||
|
||||
@@ -65,7 +65,7 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
|
||||
}
|
||||
|
||||
|
||||
function selectNewStepUi($step) {
|
||||
function selectNewStepUi() {
|
||||
var insertSelect = $step('.insert-step-select');
|
||||
var m = insertSelect.val();
|
||||
$step('.insertDiv .info').html(_sequencer.modulesInfo(m).description);
|
||||
@@ -73,25 +73,24 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
|
||||
}
|
||||
|
||||
|
||||
var toggleDiv = function($step, callback = function(){}){
|
||||
var toggleDiv = function(callback = function(){}){
|
||||
$step('.insertDiv').collapse('toggle');
|
||||
if ($step('.insert-text').css('display') != 'none'){
|
||||
$step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback);});
|
||||
$step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback)});
|
||||
}
|
||||
else {
|
||||
$step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback);});
|
||||
$step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback)});
|
||||
}
|
||||
};
|
||||
|
||||
insertStep = function (id) {
|
||||
const $step = step.ui.$step,
|
||||
$stepAll = step.ui.$stepAll;
|
||||
var modulesInfo = _sequencer.modulesInfo();
|
||||
var parser = new DOMParser();
|
||||
var addStepUI = stepUI();
|
||||
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
|
||||
|
||||
if ($step('.insertDiv').length > 0){
|
||||
toggleDiv($step);
|
||||
toggleDiv();
|
||||
}
|
||||
else {
|
||||
step.ui
|
||||
@@ -99,12 +98,12 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
|
||||
.insertAdjacentElement('afterend',
|
||||
addStepUI
|
||||
);
|
||||
toggleDiv($step, function(){
|
||||
toggleDiv(function(){
|
||||
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');
|
||||
insertStepSelect.html('');
|
||||
@@ -126,22 +125,22 @@ function IntermediateHtmlStepUi(_sequencer, step, options) {
|
||||
$(this).addClass('selected');
|
||||
newStep = $(this).attr('data-value');
|
||||
$step('.insert-step-select').val(newStep);
|
||||
selectNewStepUi($step);
|
||||
insert(id, $step);
|
||||
selectNewStepUi();
|
||||
insert(id);
|
||||
$(this).removeClass('selected');
|
||||
});
|
||||
insertStepSelect.on('change', () => {selectNewStepUi($step);});
|
||||
$step('.insertDiv .add-step-btn').on('click', function () { insert(id, $step); });
|
||||
};
|
||||
insertStepSelect.on('change', selectNewStepUi);
|
||||
$step('.insertDiv .add-step-btn').on('click', function () { insert(id) });
|
||||
}
|
||||
|
||||
function insert(id, $step) {
|
||||
function insert(id) {
|
||||
|
||||
options = options || {};
|
||||
var insertStepSelect = $step('.insert-step-select');
|
||||
if (insertStepSelect.val() == 'none') return;
|
||||
|
||||
var newStepName = insertStepSelect.val();
|
||||
toggleDiv($step);
|
||||
toggleDiv();
|
||||
var sequenceLength = 1;
|
||||
if (sequencer.sequences[newStepName]) {
|
||||
sequenceLength = sequencer.sequences[newStepName].length;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @method $scope
|
||||
* @param {"DOMNode"} scope A DOM Node as the scope
|
||||
* @param {"DOMNode"} scope A DOM Node as the scope
|
||||
*/
|
||||
function $scope(scope) {
|
||||
return function(queryString){
|
||||
@@ -8,22 +8,18 @@ function $scope(scope) {
|
||||
|
||||
element.elem = function(queryString){
|
||||
return new $scope(scope)(queryString);
|
||||
};
|
||||
}
|
||||
element.elemAll = function(queryString){
|
||||
return new $scopeAll(scope)(queryString);
|
||||
};
|
||||
element.getDomElem = function(i = 0){
|
||||
return element[i];
|
||||
};
|
||||
element.getScope = () => scope;
|
||||
}
|
||||
|
||||
return element;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @method $scopeAll
|
||||
* @param {"DOMNode"} scope A DOM Node as the scope
|
||||
* @param {"DOMNode"} scope A DOM Node as the scope
|
||||
*/
|
||||
function $scopeAll(scope){
|
||||
return function(queryString){
|
||||
@@ -31,23 +27,19 @@ function $scopeAll(scope){
|
||||
|
||||
element.elem = function(queryString){
|
||||
return new $scope(scope)(queryString);
|
||||
};
|
||||
}
|
||||
element.elemAll = function(queryString){
|
||||
return new $scopeAll(scope)(queryString);
|
||||
};
|
||||
element.getDomElem = function(i = 0){
|
||||
return element[i];
|
||||
};
|
||||
element.getScope = () => scope;
|
||||
}
|
||||
|
||||
return element;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @method scopeSelector
|
||||
* @description A scoped jQuery selector
|
||||
* @param {"DOMNode"} scope DOM Node as the scope
|
||||
* @param {"DOMNode"} scope DOM Node as the scope
|
||||
*/
|
||||
function scopeSelector(scope){
|
||||
return $scope(scope);
|
||||
@@ -56,7 +48,7 @@ function scopeSelector(scope){
|
||||
/**
|
||||
* @method scopeSelectorAll
|
||||
* @description A scoped jQuery multiple selector
|
||||
* @param {"DOMNode} scope DOM Node as the scope
|
||||
* @param {"DOMNode} scope DOM Node as the scope
|
||||
*/
|
||||
function scopeSelectorAll(scope){
|
||||
return $scopeAll(scope);
|
||||
@@ -65,4 +57,4 @@ function scopeSelectorAll(scope){
|
||||
module.exports = {
|
||||
scopeSelector,
|
||||
scopeSelectorAll
|
||||
};
|
||||
}
|
||||
2060
package-lock.json
generated
2060
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "image-sequencer",
|
||||
"version": "3.5.1",
|
||||
"version": "3.5.0",
|
||||
"description": "A modular JavaScript image manipulation library modeled on a storyboard.",
|
||||
"main": "src/ImageSequencer.js",
|
||||
"scripts": {
|
||||
@@ -30,13 +30,11 @@
|
||||
"url": "https://github.com/publiclab/image-sequencer/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"atob": "^2.1.2",
|
||||
"base64-img": "^1.0.4",
|
||||
"bootstrap": "~3.4.0",
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
"buffer": "~5.2.1",
|
||||
"commander": "^2.11.0",
|
||||
"compressorjs": "^1.0.5",
|
||||
"data-uri-to-buffer": "^2.0.0",
|
||||
"downloadjs": "^1.4.7",
|
||||
"eslint": "^5.16.0",
|
||||
@@ -49,9 +47,6 @@
|
||||
"gpu.js": "^2.0.0-rc.12",
|
||||
"image-sequencer-invert": "^1.0.0",
|
||||
"imagejs": "0.0.9",
|
||||
"imagemin": "^7.0.0",
|
||||
"imagemin-jpegtran": "^6.0.0",
|
||||
"imagemin-pngquant": "^8.0.0",
|
||||
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
|
||||
"istanbul": "^0.4.5",
|
||||
"jasmine": "^3.4.0",
|
||||
@@ -60,7 +55,6 @@
|
||||
"jsqr": "^1.1.1",
|
||||
"lodash": "^4.17.11",
|
||||
"ndarray": "^1.0.18",
|
||||
"opencv.js": "^1.2.1",
|
||||
"ora": "^3.0.0",
|
||||
"pace": "0.0.4",
|
||||
"puppeteer": "^1.14.0",
|
||||
@@ -68,7 +62,6 @@
|
||||
"readline-sync": "^1.4.7",
|
||||
"save-pixels": "~2.3.4",
|
||||
"selectize": "^0.12.6",
|
||||
"spawn-sync": "^2.0.0",
|
||||
"urify": "^2.1.1",
|
||||
"webgl-distort": "0.0.2"
|
||||
},
|
||||
@@ -91,7 +84,7 @@
|
||||
"jasmine-core": "^3.3.0",
|
||||
"jasmine-jquery": "^2.1.1",
|
||||
"jasmine-spec-reporter": "^4.2.1",
|
||||
"lint-staged": "^9.1.0",
|
||||
"lint-staged": "^8.1.6",
|
||||
"looks-same": "^7.0.0",
|
||||
"matchdep": "^2.0.0",
|
||||
"tap-spec": "^5.0.0",
|
||||
|
||||
@@ -5,7 +5,6 @@ module.exports = {
|
||||
'add-qr': require('./modules/AddQR'),
|
||||
'average': require('./modules/Average'),
|
||||
'blend': require('./modules/Blend'),
|
||||
'blob-analysis': require('./modules/BlobAnalysis'),
|
||||
'blur': require('./modules/Blur'),
|
||||
'brightness': require('./modules/Brightness'),
|
||||
'canvas-resize': require('./modules/CanvasResize'),
|
||||
@@ -29,9 +28,7 @@ module.exports = {
|
||||
'gradient': require('./modules/Gradient'),
|
||||
'grid-overlay': require('./modules/GridOverlay'),
|
||||
'import-image': require('./modules/ImportImage'),
|
||||
'minify-image': require('./modules/MinifyImage'),
|
||||
'invert': require('image-sequencer-invert'),
|
||||
'matcher': require('./modules/Matcher'),
|
||||
'ndvi': require('./modules/Ndvi'),
|
||||
'ndvi-colormap': require('./modules/NdviColormap'),
|
||||
'noise-reduction': require('./modules/NoiseReduction'),
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
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;
|
||||
};
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
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
|
||||
};
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = [
|
||||
require('./Module'),
|
||||
require('./info.json')
|
||||
];
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"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,69 +0,0 @@
|
||||
/*
|
||||
* Match the images
|
||||
*/
|
||||
function Match(options, UI) {
|
||||
|
||||
var output, points;
|
||||
|
||||
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||
|
||||
global.XY = [
|
||||
options.imageX || defaults.imageX,
|
||||
options.imageY || defaults.imageY
|
||||
];
|
||||
|
||||
const res = require('matcher-core');
|
||||
|
||||
async function run() {
|
||||
const r = await res;
|
||||
return r;
|
||||
}
|
||||
run().then(function(r) {
|
||||
points = r.points;
|
||||
}).catch(function(e) {
|
||||
console.error(e);
|
||||
});
|
||||
|
||||
function draw(input, callback, progressObj) {
|
||||
|
||||
progressObj.stop(true);
|
||||
progressObj.overrideFlag = true;
|
||||
|
||||
var step = this;
|
||||
|
||||
function changePixel(r, g, b, a, x, y) {
|
||||
for(var i = 0; i < 500; i++){
|
||||
if(Math.abs(points[i].x - x) <= 10 && Math.abs(points[i].y - y) <= 10){
|
||||
return [0, 255, 0];
|
||||
}
|
||||
}
|
||||
return [r, g, b, a];
|
||||
}
|
||||
|
||||
function output(image, datauri, mimetype) {
|
||||
|
||||
step.output = { src: datauri, format: mimetype };
|
||||
|
||||
}
|
||||
|
||||
return input.pixelManipulation({
|
||||
output: output,
|
||||
changePixel: changePixel,
|
||||
format: input.format,
|
||||
image: options.image,
|
||||
inBrowser: options.inBrowser,
|
||||
callback: callback,
|
||||
useWasm:options.useWasm
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
options: options,
|
||||
draw: draw,
|
||||
output: output,
|
||||
UI: UI
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = Match;
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = [
|
||||
require('./Module'),
|
||||
require('./info.json')
|
||||
];
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "matcher-core",
|
||||
"description": "Pattern-mining module for detecting key-points in images",
|
||||
"url": "https://github.com/publiclab/matcher-core.git",
|
||||
"inputs": {
|
||||
"imageX": {
|
||||
"type": "text",
|
||||
"default": ""
|
||||
},
|
||||
"imageY": {
|
||||
"type": "text",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
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
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = [
|
||||
require('./Module'),
|
||||
require('./info.json')
|
||||
];
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -3,36 +3,44 @@ module.exports = function TextOverlay(options, UI) {
|
||||
|
||||
var output;
|
||||
|
||||
function draw(input, callback) {
|
||||
function draw(input, callback, progressObj) {
|
||||
|
||||
progressObj.stop(true);
|
||||
progressObj.overrideFlag = true;
|
||||
|
||||
var step = this;
|
||||
|
||||
var priorStep = this.getStep(-1); // get the previous step to add text onto it.
|
||||
|
||||
function extraManipulation(pixels) {
|
||||
//if (options.step.inBrowser)
|
||||
pixels = require('./TextOverlay')(pixels, options, priorStep);
|
||||
return pixels;
|
||||
if (!options.step.inBrowser) { // This module is only for browser
|
||||
this.output = input;
|
||||
callback();
|
||||
}
|
||||
else {
|
||||
var priorStep = this.getStep(-1); // get the previous step to add text onto it.
|
||||
|
||||
function output(image, datauri, mimetype) {
|
||||
function extraManipulation(pixels) {
|
||||
//if (options.step.inBrowser)
|
||||
pixels = require('./TextOverlay')(pixels, options, priorStep);
|
||||
return pixels;
|
||||
}
|
||||
|
||||
// This output is accesible by Image Sequencer
|
||||
step.output = { src: datauri, format: mimetype };
|
||||
function output(image, datauri, mimetype) {
|
||||
|
||||
// This output is accesible by Image Sequencer
|
||||
step.output = { src: datauri, format: mimetype };
|
||||
|
||||
}
|
||||
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
ui: options.step.ui,
|
||||
extraManipulation: extraManipulation,
|
||||
format: input.format,
|
||||
image: options.image,
|
||||
inBrowser: options.inBrowser,
|
||||
callback: callback,
|
||||
useWasm:options.useWasm
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
module.exports = exports = function(pixels, options, priorstep){
|
||||
|
||||
var $ = require('jquery'); // to make text-overlay work for node.js
|
||||
|
||||
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
|
||||
|
||||
options.text = options.text || defaults.text;
|
||||
|
||||
@@ -40,5 +40,6 @@
|
||||
"desc": "Enter the font size in pixels.",
|
||||
"default": "12"
|
||||
}
|
||||
}
|
||||
},
|
||||
"only": "browser"
|
||||
}
|
||||
|
||||
58
src/ui/userPrefs.js
Normal file
58
src/ui/userPrefs.js
Normal file
@@ -0,0 +1,58 @@
|
||||
function userPreferenceManager(options) {
|
||||
|
||||
options.dbName = options.dbName || 'user-prefs';
|
||||
options.storeName = options.storeName || 'user-prefs';
|
||||
|
||||
if (!('indexedDB' in window)) {
|
||||
return { error: 'indexedDB not supported' };
|
||||
}
|
||||
|
||||
this.storeName = options.storeName;
|
||||
this.dbName = options.dbName;
|
||||
|
||||
const db = idb.open(dbName, 1, (upgradeDB) => {
|
||||
if (!upgradeDb.objectStoreNames.contains(options.storeName)) {
|
||||
upgradeDB.createObjectStore(options.storeName, {keyPath: 'preference'});
|
||||
}
|
||||
}
|
||||
|
||||
this.prototype.addPref = (prefName, preference, cb) => {addPref(db, {preference: prefName, ... preference}, options, cb)};
|
||||
this.prototype.updatePref = (prefName, preference, cb) => {updatePref(db, {preference: prefName, ... preference}, options, cb)};
|
||||
this.prototype.deletePref = (prefName, cb) => {deletePref(db, prefName, options, cb)};
|
||||
this.prototype.getPref = (prefName, cb) => {getPref(db, prefName, options, cb)};
|
||||
this.prototype.new = () => {return new userPreferenceManager(options)};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function addPref(db, preference, options, cb) {
|
||||
db.then((dbSnap) => {
|
||||
var tx = dbSnap.transaction(options.storeName, 'readwrite');
|
||||
tx.objectStore(options.storeName).add(preference);
|
||||
return tx.complete;
|
||||
}).then(cb);
|
||||
}
|
||||
|
||||
function updatePref(db, preference, options, cb) {
|
||||
db.then((dbSnap) => {
|
||||
var tx = dbSnap.transaction(options.storeName, 'readwrite');
|
||||
tx.objectStore(options.storeName).put(preference);
|
||||
return tx.complete;
|
||||
}).then(cb);
|
||||
}
|
||||
|
||||
function deletePref(db, prefName, options, cb) {
|
||||
db.then((dbSnap) => {
|
||||
var tx = dbSnap.transaction(options.storeName, 'readwrite');
|
||||
tx.objectStore(options.storeName).delete(prefName);
|
||||
return tx.complete;
|
||||
}).then(cb);
|
||||
}
|
||||
|
||||
function getPref(db, prefName, options, cb) {
|
||||
db.then((dbSnap) => {
|
||||
var tx = dbSnap.transaction(options.storeName, 'readwrite');
|
||||
var store = tx.objectStore(options.storeName, 'readwrite');
|
||||
return store.get(prefName);
|
||||
}).then(cb);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user