fredmeister77 fredmeister77 - 3 months ago 60
Javascript Question

How do I apply an ImageData pixel transformation in Darkroom.JS?

I am attempting to write a Darkroom.JS plugin that will transform white space in images to transparency.

I have used this answer (solely canvas based) to write this code:

(function() {
'use strict';

var Transparency = Darkroom.Transformation.extend({
applyTransformation: function(canvas, image, next) {
console.log(canvas);
console.log(image);
var context = canvas.getContext("2d");
var upperContext = $('.upper-canvas').get(0).getContext("2d");

var imageData = context.getImageData(0, 0, image.getWidth(), image.getHeight());

//var upperImageData = upperContext.createImageData(image.getWidth(), image.getHeight());

console.log("apply transformation called");

for(var i = 0, n = imageData.data.length; i < n; i +=4){
var r = imageData.data[i],
g = imageData.data[i+1],
b = imageData.data[i+2];

if(r >= 230 && g >= 230 && b >= 230){
imageData.data[i] = 0;
imageData.data[i+1] = 0;
imageData.data[i+2] = 0;
imageData.data[i+3] = 1;
}
};

context.putImageData(imageData, 0, 0);
upperContext.putImageData(imageData, 0, 0);


//canvas.renderAll();

next();
}
});

Darkroom.plugins['transparency'] = Darkroom.Plugin.extend({

defaults: {
clearWhiteSpace: function() {
this.darkroom.applyTransformation(
new Transparency()
);
}
},

initialize: function InitializeDarkroomTransparencyPlugin() {
var buttonGroup = this.darkroom.toolbar.createButtonGroup();

this.destroyButton = buttonGroup.createButton({
image: 'wand' //Magic Wand by John O'Shea from the Noun Project
});

this.destroyButton.addEventListener('click', this.options.clearWhiteSpace.bind(this));
},
});

})();


(I should also note I based the structure of the plugin off of the existing rotate plugin)

The code does get called, and I do not currently have it in the code (for performance reasons) but a log statement indicated that the if block where the pixel editing is done also gets called.

To verify, I presently have the pixels set to fully opacity and black (instead of transparent so that I can see the effects of editing).

Also, I noticed that Darkroom.JS seems to generate two canvas objects, an upper canvas and lower canvas. The object passed to the transform function is the "lower canvas" object, so I even tried using jQuery to grab the "upper" one and set the image data on that, to no avail.

What am I missing?

Answer

I was focusing my search for an answer far too much on Darkroom.JS. Darkroom.JS is just a layer on top of Fabric.JS, and this answer holds the key: fabric js or imagick remove white from image

I actually used the second answer and it works perfectly:

So there is a filter in Fabric.js that does just that.

http://fabricjs.com/docs/fabric.Image.filters.RemoveWhite.html

var filter = new fabric.Image.filters.RemoveWhite({ threshold: 40,
distance: 140 }); image.filters.push(filter); image.applyFilters(canvas.renderAll.bind(canvas));

Here is my completed code (with some extraneous details removed to simplify):

       fabric.Image.fromURL(imgData.URL, function(logoImg){

            canvas.add(logoImg);

            var threshold = 40;

            var whitespace = function(){
                var filter = new fabric.Image.filters.RemoveWhite({
                  threshold: threshold,
                  distance: 140
                });

                threshold+=20;

                logoImg.filters.push(filter);
                logoImg.applyFilters(canvas.renderAll.bind(canvas));
            };
       });