user3657517
user3657517

Reputation: 35

greyscale canvas - make canvas color to black and white

I am using this js: http://www.jqueryscript.net/other/jQuery-Image-Processing-Plugin-With-Canvas-Tancolor.html

What this plugin is doing, it is converting my canvas to black and white and saving it in an IMG tag on my web page.

Here is the javascript this plugin is using:

(function ($) {  
    $.fn.tancolor = function(options) {
        var settings = $.extend({
            mode: 'grayscale',
            r_weight: 0.34,
            g_weight: 0.5,
            b_weight: 0.16,
            r_intensity: 1,
            g_intensity: 1,
            b_intensity: 1,
            load: null
        }, options );

        var r_weight;
        var g_weight;
        var b_weight;
        var r_intensity;
        var g_intensity;
        var b_intensity;

        // settings value
        switch(settings.mode){
            case 'grayscale':
                r_weight = 0.34;
                g_weight = 0.5;
                b_weight = 0.16;
                r_intensity = 1;
                g_intensity = 1;
                b_intensity = 1;
                break;
            case 'red':
                r_weight = 0.34;
                g_weight = 0.5;
                b_weight = 0.16;
                r_intensity = 255;
                g_intensity = 1;
                b_intensity = 1;
                break;
            case 'green':
                r_weight = 0.34;
                g_weight = 0.5;
                b_weight = 0.16;
                r_intensity = 1;
                g_intensity = 255;
                b_intensity = 1;
                break;
            case 'blue':
                r_weight = 0.34;
                g_weight = 0.5;
                b_weight = 0.16;
                r_intensity = 1;
                g_intensity = 1;
                b_intensity = 255;
                break;
            default:
                r_weight = settings.r_weight;
                g_weight = settings.g_weight;
                b_weight = settings.b_weight;
                r_intensity = settings.r_intensity;
                g_intensity = settings.g_intensity;
                b_intensity = settings.b_intensity;
                break;
        }

        // convert image to canvas
        var img = document.getElementById($(this).attr("id"));
        if(settings.load){
            img.src = settings.load;
            return;
        }
        var canvas = convertImageToCanvas(img);
        var ctx = canvas.getContext("2d");
        var imageData = ctx.getImageData(0, 0, img.width, img.height)
        $(this).replaceWith(canvas);

        // Processing image data
        var data = imageData.data;
        for(var i = 0; i < data.length; i += 4) {
            var brightness = r_weight * data[i] + g_weight * data[i + 1] + b_weight * data[i + 2];
            // red
            data[i] = r_intensity * brightness;
            // green
            data[i + 1] = g_intensity * brightness;
            // blue
            data[i + 2] = b_intensity * brightness;
        }
        ctx.putImageData(imageData, 0, 0);

        $('#'+$(this).attr("id")).each(function(i,e){ 
             var img = e.toDataURL("image/png"); 
             $(e).replaceWith( $('<img src="' + img + '"/>').attr({width: $(e).attr("width"), height: $(e).attr("height"), style: $(e).attr("style") }) ) });

        // Converts image to canvas; returns new canvas element
        function convertImageToCanvas(image) {
        var canvas = document.createElement("canvas");
        canvas.width = image.width;
        canvas.height = image.height;
            if(image.id) {
                canvas.id = image.id;
            }
            if(image.className) {
                canvas.className = image.className;
            }
        canvas.getContext("2d").drawImage(image, 0, 0);

        return canvas;
        }

        // Converts canvas to an image
        function convertCanvasToImage(canvas) {
        var image = new Image();
        image.src = canvas.toDataURL("image/png");
        return image;
        }
    };
}(jQuery));

What I actually want is just convert my canvas to black and white but saving it in canvas tag only on web page and not as IMG tag as I am than after downloading the greyscale canvas merging with another canvas from the app.

Any help will be appreciated.

Thanks

Upvotes: 1

Views: 4358

Answers (1)

Kaiido
Kaiido

Reputation: 136707

To grayscale a non-transparent image, on compatible browsers, you could simply [if Safari didn't had a strange bug with that, you should have been able to] use the context.globalCompositeOperation property and set it to 'luminosity' after you've drawn a solid color, before falling to the getImageData solution :

var img = new Image();
var ctx = canvas.getContext('2d');
img.onload = function() {
  // set the canvas' size
  canvas.width = this.width;
  canvas.height = this.height;
  // first fill a rect
  ctx.fillStyle = 'white'
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // set the gCO
  ctx.globalCompositeOperation = 'luminosity';
  // if the browser doesn't support Blend Modes
  console.log(ctx.globalCompositeOperation)
  if (ctx.globalCompositeOperation !== 'luminosity')
    fallback(this);
  else {
    // draw the image
    ctx.drawImage(this, 0, 0);
    // reset the gCO
    ctx.globalCompositeOperation = 'source-over';
  }
}
img.crossOrigin = "anonymous";
img.src = "https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png";

function fallback(img) {
  // first remove our black rectangle
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  //draw the image
  ctx.drawImage(img, 0, 0);
  // get the image data
  var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  var d = imgData.data;
  // loop through all pixels
  // each pixel is decomposed in its 4 rgba values
  for (var i = 0; i < d.length; i += 4) {
    // get the medium of the 3 first values
    var med = (d[i] + d[i + 1] + d[i + 2]) / 3;
    // set it to each value
    d[i] = d[i + 1] = d[i + 2] = med;
  }
  // redraw the new computed image
  ctx.putImageData(imgData, 0, 0);
}
<canvas id="canvas"></canvas>

But since Safari has a bug and that the gCO solution (which is faster, but I don't think it's important for you) remove the transparent pixels, here is just the previous fallback, which is a simpler code than the one you got. I hope you'll be able to read it.

var img = new Image();
    var ctx = canvas.getContext('2d');
    img.onload = function() {
      // set the canvas' size
      canvas.width = this.width;
      canvas.height = this.height;
      //draw the image
      ctx.drawImage(this, 0, 0);
      // get the image data
      var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      var d = imgData.data;
      // loop through all pixels
      // each pixel is decomposed in its 4 rgba values
      for (var i = 0; i < d.length; i += 4) {
        // get the medium of the 3 first values ( (r+g+b)/3 )
        var med = (d[i] + d[i + 1] + d[i + 2]) / 3;
        // set it to each value (r = g = b = med)
        d[i] = d[i + 1] = d[i + 2] = med;
        // we don't touch the alpha
      }
      // redraw the new computed image
      ctx.putImageData(imgData, 0, 0);

    }
    img.crossOrigin = "anonymous";
    img.src = "https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png";
<canvas id="canvas"></canvas>

Upvotes: 2

Related Questions