NielsLeenheer / CanvasDither

Black and white dithering algorithms for the Canvas element
MIT License
25 stars 6 forks source link

Documentation extension? #1

Open GarkGarcia opened 6 years ago

GarkGarcia commented 6 years ago

I could be wrong, but it appears that this module is not limited to images retrieved from a <canvas> element: I believe it works for any ImageData object.

Even thought the ImageData() constructor is tightly related to <canvas> elements, it could be useful for developers making use of other image-processing modules (particularly the more general-purposed ones), such as Jimp, react-imgpro, EasyImage , etc, to include a little bit of documentation regarding this aspect of the module.

I realize there's actually no difference on regards to the usage of the module, but perhaps it could be useful for newcomers and beginner coders to be able to quickly identify this module as a "general dithering" library instead of "canvas dithering" library. Not too big a deal anyway.

NielsLeenheer commented 6 years ago

I haven't really considered using this for other image processing libraries, but that certainly can be done. Not sure yet about react-imgpro and EasyImage, I still have to look at their source code. But Jimp is certainly possible.

The only thing I would have to do is create a helper library that translates from a Jimp bitmap object to an ImageData object and back again. That would be pretty simple, because they both use pretty much the same structure, except that Jimp uses a Buffer for the data and ImageData an Uint8ClampedArray.

It would look something like this:


let Jimp = require("jimp");
let Dither = require('canvas-dither');
let { ToImageData, ToBitmap } = require('jimp-imagedata');

Jimp.read("image.jpg").then(function (image) {
    image.bitmap = 
        ToBitmap(
            Dither.atkinson(
                ToImageData(
                    image.bitmap
                )
            )
        )

    // use image here
})
GarkGarcia commented 6 years ago

I did image.bitmap = Dither.floydsteinberg(image.bitmap) and it worked just fine for me:

let Jimp = require("jimp");
let Dither = require('canvas-dither');

Jimp.read("image.jpg").then(function (image) {
    image.bitmap = Dither.floydsteinberg(image.bitmap);
    image.do_anything_else_related_to_jimp()
    .write("output.png")
})

Is there something wrong about it?

NielsLeenheer commented 6 years ago

Yes, that works because a Buffer and Uint8ClampedArray are pretty much compatible with each other. There are some incompatibilities, but Dither is pretty simple, so it doesn't run into those. But this may not work for just any library that manipulates the ImageData object.

GarkGarcia commented 6 years ago

Got it! I believe this does the job:

// Provided that the ImageData class is supported on the device, simply do the following.
// Otherwise you'll need to implement it first.
ImageData.prototype.toJimp = function() {
    return new Jimp(this.width, this.height, (err, img) => {
        if (err) {
            throw err;
        } else {
            img.bitmap.data = Buffer.from(this.data);
        }
    })
}

Jimp.prototype.toImgData = function() {
    return new ImageData(new Uint8ClampedArray(this.bitmap.data), this.bitmap.width, this.bitmap.height);
}

// Example of usage:
Jimp.read("something.jpg", (err, image) => {
    let ditheredImg = Dither.floydsteinberg(image.toImgData()).toJimp()
    // Do your Jimpy stuff here.
    ditheredImg.write('output.png');
});

I think I'll extend this a bit and make it a small module for quickly converting from common JavaScript image data-types (such as ImageData, ImageBitmap, etc.).