Compare commits

..

5 Commits

Author SHA1 Message Date
Harsh Khandeparkar
a091bd9ab8 Merge branch 'main' into user-prefs 2019-06-23 15:05:12 +05:30
Harsh Khandeparkar
3e645f9f7d error handling 2019-03-29 14:47:46 +00:00
Harsh Khandeparkar
4b9d67ca4a docs 2019-03-28 21:04:27 +00:00
Harsh Khandeparkar
a2cd5bafd6 create API 2019-03-28 20:27:55 +00:00
Harsh Khandeparkar
e505ef6c25 Create userPrefs.js 2019-03-28 19:36:18 +00:00
26 changed files with 1041 additions and 3814 deletions

View File

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

View File

@@ -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.

View File

@@ -232,7 +232,6 @@
var sequencer;
})
</script>
<script async src="../node_modules/opencv.js/opencv.js" type="text/javascript"></script>
</body>

View File

@@ -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;

View File

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

View File

@@ -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;

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -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'),

View File

@@ -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;
};

View File

@@ -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
};
};

View File

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

View File

@@ -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"
}

View File

@@ -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;

View File

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

View File

@@ -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": ""
}
}
}

View File

@@ -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
};
};

View File

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

View File

@@ -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"
}

View File

@@ -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 {

View File

@@ -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;

View File

@@ -40,5 +40,6 @@
"desc": "Enter the font size in pixels.",
"default": "12"
}
}
},
"only": "browser"
}

58
src/ui/userPrefs.js Normal file
View 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);
}

View File

@@ -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();
});
});

1432
yarn.lock

File diff suppressed because it is too large Load Diff