Adding easier to use interface for blend module and different blend modes (#1453)

* Bump data-uri-to-buffer from 2.0.1 to 3.0.0

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

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

* add blend modes

* fix toCliString test

* add docs link for blend modes

* fix crop module

* undo last commit

* minor change

* change default to custom

* add docs link

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Harsh Khandeparkar <34770591+HarshKhandeparkar@users.noreply.github.com>
Co-authored-by: Jeffrey Warren <jeff@unterbahn.com>
This commit is contained in:
Rishabh Shukla
2020-01-18 02:17:47 +05:30
committed by Jeffrey Warren
parent 1fa8c6b8c1
commit c22c6c70d0
4 changed files with 95 additions and 15 deletions

View File

@@ -78,7 +78,8 @@ This module is used for averaging all the pixels of the image.
## blend-module
This module is used for blending two images .
This module is used for blending two images. For More info read: _[wiki](https://en.wikipedia.org/wiki/Blend_modes)_
#### Usage
```js
@@ -88,8 +89,12 @@ This module is used for blending two images .
```
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 ] })
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
* blendMode: Blending mode to use for blending two images by default it uses the given function
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
[More info for different blend modes can be found here](http://docs.gimp.org/en/gimp-concepts-layer-modes.html)
## Blob Analysis

View File

@@ -4,6 +4,7 @@ module.exports = function Blend(options, UI, util) {
options.func = options.blend || defaults.blend;
options.offset = options.offset || defaults.offset;
options.blendMode = options.blendMode || defaults.blendMode;
var output;
@@ -29,22 +30,79 @@ module.exports = function Blend(options, UI, util) {
callback();
}
// see http://docs.gimp.org/en/gimp-concepts-layer-modes.html for other blend modes
const multiply_mode = function (i, m) {
return ~~( (i * m) / 255 );
};
const divide_mode = function (i, m) {
return ~~( (256 * i) / (m + 1) );
};
const overlay_mode = function (i, m) {
return ~~( (i / 255) * (i + ((2 * m) / 255) * (255 - i)) );
};
const screen_mode = function (i, m) {
return ~~( 255 - ((255 - m) * (255 - i)) / 255 );
};
const sof_light_mode = function (i, m) {
var Rs = screen_mode(i, m);
return ~~( ((((255 - i) * m) + Rs) * i) / 255 );
};
const color_dodge = function (i, m) {
return ~~( (256 * i) / (255 - m + 1) );
};
const burn_mode = function (i, m) {
return ~~( 255 - (256 * (255 - i)) / (m + 1));
};
const grain_extract_mode = function (i, m) {
return ~~( i - m + 128 );
};
const grain_merge_mode = function (i, m) {
return ~~( i + m - 128 );
};
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
// Convert to runnable code.
if (typeof options.func === 'string') eval('options.func = ' + options.func);
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
let p = options.firstImagePixels;
return options.func(
r2, g2, b2, a2,
p.get(x, y, 0),
p.get(x, y, 1),
p.get(x, y, 2),
p.get(x, y, 3),
x,
y
);
let r1 = p.get(x, y, 0),
g1 = p.get(x, y, 1),
b1 = p.get(x, y, 2),
a1 = p.get(x, y, 3);
const blends = {
'Color Dodge': () => [color_dodge(r2, r1), color_dodge(g2, g1), color_dodge(b2, b1), 255],
'Multiply': () => [multiply_mode(r2, r1), multiply_mode(g2, g1), multiply_mode(b2, b1), multiply_mode(a2, a1)],
'Divide': () => [divide_mode(r2, r1), divide_mode(g2, g1), divide_mode(b2, b1), 255],
'Overlay': () => [overlay_mode(r2, r1), overlay_mode(g2, g1), overlay_mode(b2, b1), 255],
'Screen': () => [screen_mode(r2, r1), screen_mode(g2, g1), screen_mode(b2, b1), 255],
'Soft Light': () => [sof_light_mode(r2, r1), sof_light_mode(g2, g1), sof_light_mode(b2, b1), 255],
'Color Burn': () => [burn_mode(r2, r1), burn_mode(g2, g1), burn_mode(b2, b1), 255],
'Grain Extract': () => [grain_extract_mode(r2, r1), grain_extract_mode(g2, g1), grain_extract_mode(b2, b1), 255],
'Grain Merge': () => [grain_merge_mode(r2, r1), grain_merge_mode(g2, g1), grain_merge_mode(b2, b1), 255]
};
if(options.blendMode == 'custom')
return options.func(
r2, g2, b2, a2, r1, g1, b1, a1
);
else {
return blends[options.blendMode]();
}
}
function output(image, datauri, mimetype, wasmSuccess) {

View File

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

View File

@@ -192,7 +192,7 @@ test('getStep(offset) returns the step at offset distance relative to current st
});
test('toCliString() returns the CLI command for the sequence', function(t) {
t.deepEqual(sequencer.toCliString(), 'sequencer -i [PATH] -s "channel channel channel channel invert brightness average brightness invert blend" -d \'{"channel":"green","brightness":"1","offset":-2}\'', 'works correctly');
t.deepEqual(sequencer.toCliString(), 'sequencer -i [PATH] -s "channel channel channel channel invert brightness average brightness invert blend" -d \'{"channel":"green","brightness":"1","offset":-2,"blendMode":"custom"}\'', 'works correctly');
t.end();
});