JSFiddle - React, Tailwind, and code Playground

by Minko Gechev

HTML

<video id="vid" width="400" height="300" style="visibility: hidden;"></video>
<canvas id="can" width="400" height="300"></canvas>

JavaScript

function $(id) {
    return document.getElementById(id);
}

Filters = {};

Filters.getPixels = function(img) {
  var c = this.getCanvas(img.width, img.height);
  var ctx = c.getContext('2d');
  ctx.drawImage(img, 0, 0);
  return ctx.getImageData(0,0,c.width,c.height);
};

Filters.getCanvas = function(w,h) {
  var c = document.createElement('canvas');
  c.width = w;
  c.height = h;
  return c;
};

Filters.filterImage = function(filter, image, var_args) {
  var args = [this.getPixels(image)];
  for (var i=2; i<arguments.length; i++) {
    args.push(arguments[i]);
  }
  return filter.apply(null, args);
};

Filters.grayscale = function(pixels, args) {
  var d = pixels.data;
  for (var i=0; i<d.length; i+=4) {
    var r = d[i];
    var g = d[i+1];
    var b = d[i+2];
    // CIE luminance for the RGB
    // The human eye is bad at seeing red and blue, so we de-emphasize them.
    var v = 0.2126*r + 0.7152*g + 0.0722*b;
    d[i] = d[i+1] = d[i+2] = v
  }
  return pixels;
};

Filters.threshold = function(pixels, threshold) {
  var d = pixels.data;
  for (var i=0; i<d.length; i+=4) {
    var r = d[i];
    var g = d[i+1];
    var b = d[i+2];
    var v = (0.2126*r + 0.7152*g + 0.0722*b >= threshold) ? 255 : 0;
    d[i] = d[i+1] = d[i+2] = v
  }
  return pixels;
};

var vid = $('vid'),
    can = $('can'),
    c = can.getContext('2d');

navigator.webkitGetUserMedia({ video: true }, function (stream) {
    vid.src = webkitURL.createObjectURL(stream);
    vid.play();
});

setInterval(function () {
    var data = Filters.filterImage(Filters.grayscale, vid);
    c.putImageData(data, 0, 0);
    data = Filters.filterImage(Filters.threshold, can, 128);
    c.putImageData(data, 0, 0);
}, 20);