Skip to content

Commit

Permalink
Dithering module added (#617)
Browse files Browse the repository at this point in the history
  • Loading branch information
aashna27 authored and jywarren committed Jan 6, 2019
1 parent 52c9c35 commit 2aa7e9b
Show file tree
Hide file tree
Showing 8 changed files with 4,724 additions and 4,459 deletions.
9,028 changes: 4,577 additions & 4,451 deletions dist/image-sequencer.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/image-sequencer.min.js

Large diffs are not rendered by default.

28 changes: 21 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/Modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = {
'convolution': require('./modules/Convolution'),
'crop': require('./modules/Crop'),
'decode-qr': require('./modules/DecodeQr'),
'dither': require('./modules/Dither'),
'draw-rectangle': require('./modules/DrawRectangle'),
'dynamic': require('./modules/Dynamic'),
'edge-detect': require('./modules/EdgeDetect'),
Expand Down
70 changes: 70 additions & 0 deletions src/modules/Dither/Dither.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module.exports = function Dither(pixels, type) {
type = type || "none";
var bayerThresholdMap = [
[ 15, 135, 45, 165 ],
[ 195, 75, 225, 105 ],
[ 60, 180, 30, 150 ],
[ 240, 120, 210, 90 ]
];

var lumR = [];
var lumG = [];
var lumB = [];
for (var i=0; i<256; i++) {
lumR[i] = i*0.299;
lumG[i] = i*0.587;
lumB[i] = i*0.114;
}
var threshold = 129;
var imageDataLength = pixels.data.length; //imageData.data.length;

// Greyscale luminance (sets r pixels to luminance of rgb)
for (var i = 0; i <= imageDataLength; i += 4) {
pixels.data[i] = Math.floor(lumR[pixels.data[i]] + lumG[pixels.data[i+1]] + lumB[pixels.data[i+2]]);
}

var w = pixels.shape[0];
var newPixel, err;

for (var currentPixel = 0; currentPixel <= imageDataLength; currentPixel+=4) {

if (type === "none") {
// No dithering
pixels.data[currentPixel] = pixels.data[currentPixel] < threshold ? 0 : 255;
} else if (type === "bayer") {
// 4x4 Bayer ordered dithering algorithm
var x = currentPixel/4 % w;
var y = Math.floor(currentPixel/4 / w);
var map = Math.floor( (pixels.data[currentPixel] + bayerThresholdMap[x%4][y%4]) / 2 );
pixels.data[currentPixel] = (map < threshold) ? 0 : 255;
} else if (type === "floydsteinberg") {
// Floyd–Steinberg dithering algorithm
newPixel = pixels.data[currentPixel] < 129 ? 0 : 255;
err = Math.floor((pixels.data[currentPixel] - newPixel) / 16);
pixels.data[currentPixel] = newPixel;

pixels.data[currentPixel + 4 ] += err*7;
pixels.data[currentPixel + 4*w - 4 ] += err*3;
pixels.data[currentPixel + 4*w ] += err*5;
pixels.data[currentPixel + 4*w + 4 ] += err*1;
} else {
// Bill Atkinson's dithering algorithm
newPixel = pixels.data[currentPixel] < threshold ? 0 : 255;
err = Math.floor((pixels.data[currentPixel] - newPixel) / 8);
pixels.data[currentPixel] = newPixel;

pixels.data[currentPixel + 4 ] += err;
pixels.data[currentPixel + 8 ] += err;
pixels.data[currentPixel + 4*w - 4 ] += err;
pixels.data[currentPixel + 4*w ] += err;
pixels.data[currentPixel + 4*w + 4 ] += err;
pixels.data[currentPixel + 8*w ] += err;
}

// Set g and b pixels equal to r
pixels.data[currentPixel + 1] = pixels.data[currentPixel + 2] = pixels.data[currentPixel];
}
return pixels;

}

37 changes: 37 additions & 0 deletions src/modules/Dither/Module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module.exports = function Dither(options, UI){

var output;

function draw(input,callback,progressObj){

progressObj.stop(true);
progressObj.overrideFlag = true;

var step = this;

function extraManipulation(pixels) {
pixels = require('./Dither')(pixels, options.dither)
return pixels
}

function output(image, datauri, mimetype){
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };

}

return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}
4 changes: 4 additions & 0 deletions src/modules/Dither/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
]
13 changes: 13 additions & 0 deletions src/modules/Dither/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "Dither",
"description": "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.<a href='https://en.wikipedia.org/wiki/Dither'>Read more</a>",
"inputs": {
"dither": {
"type": "select",
"desc": "Name of the Dithering Algorithm",
"default": "none",
"values": ["none","floydsteinberg","bayer","Atkinson"]
}
}
}

0 comments on commit 2aa7e9b

Please sign in to comment.