Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An example of the Floyd–Steinberg applied to images in Javascript.
<html>
<head>
<title>Dithering Test</title>
</head>
<body>
<canvas></canvas>
<script>
var canvas = document.getElementsByTagName("canvas")[0];
var ctx = canvas.getContext('2d');
var id = ctx.getImageData(0, 0, 1, 1);
var img;
var image_data;
id.data[3] = 255;
function clip(x) {
return x < 0 ? 0 : (x > 255 ? 255 : x)
}
function setPixel(x, y, color) {
var index = (x + y * image_data.width) * 4;
image_data.data[index+0] = parseInt(color[0]+0.5);
image_data.data[index+1] = parseInt(color[1]+0.5);
image_data.data[index+2] = parseInt(color[2]+0.5);
image_data.data[index+3] = 255;
}
function color_diff(one, two) {
return [(one[0] - two[0]), (one[1] - two[1]), (one[2] - two[2])];
}
function color_add_err(x, y, err_red, err_green, err_blue) {
var index = (x + y * image_data.width) * 4;
image_data.data[index+0] = clip(image_data.data[index+0]+err_red)
image_data.data[index+1] = clip(image_data.data[index+1]+err_green)
image_data.data[index+2] = clip(image_data.data[index+2]+err_blue)
image_data.data[index+3] = 255;
}
function find_closest_palette_color(pixel) {
return (0.2126*pixel[0] + 0.7152*pixel[1] + 0.0722*pixel[2]) > 128 ? [255,255,255] : [0,0,0];
}
function get_pixel(x, y) {
var index = (x + y * image_data.width) * 4;
return [ image_data.data[index+0], image_data.data[index+1], image_data.data[index+2] ];
}
function rgb2bin(img_name) {
img = new Image();
img.src = img_name;
img.onload = function(){
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0, img.width, img.height);
image_data = ctx.getImageData(0, 0, img.width, img.height);
var oldpixel;
var newpixel;
var quant_error;
var err_red, err_green, err_blue;
for (var y = 0; y < img.height; y++) {
for (var x = 0; x < img.width; x++) {
oldpixel = get_pixel(x, y);
newpixel = find_closest_palette_color(oldpixel);
setPixel(x, y, newpixel);
quant_error = color_diff(oldpixel, newpixel);
err_red = quant_error[0];
err_green = quant_error[1];
err_blue = quant_error[2];
if (x+1 < img.width)
color_add_err(x+1, y, (7/16) * err_red, (7/16) * err_green, (7/16) * err_blue);
if (x-1 > 0 && y+1 < img.height)
color_add_err(x-1, y+1, (3/16) * err_red, (3/16) * err_green, (3/16) * err_blue);
if (y+1 < img.height)
color_add_err(x, y+1, (5/16) * err_red, (5/16) * err_green, (5/16) * err_blue);
if (x+1 < img.width)
color_add_err(x+1, y+1, (1/16) * err_red, (1/16) * err_green, (1/16) * err_blue);
}
}
ctx.putImageData(image_data, 0, 0);
}
}
document.body.onload = function(){rgb2bin(prompt("Enter image location"));}
</script>
</body>
</html>
@74togo

This comment has been minimized.

Copy link
Owner Author

@74togo 74togo commented Sep 5, 2013

Note, sharpening an image before doing this makes it look better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment