1

I'm trying to create a filter for canvas which draws a monochrome version of an image. I'm drawing the image, then iterating through the image data, then changing those rgb values to a gray, then placing the image data into the canvas. I need help on how to create the gray shade from the rgb values. I want a javascript solution.

My code:

function toGray(vals) {
  var r = vals[0]
  var g = vals[1]
  var b = vals[2]
  // Return gray shade
}
function filter() {
  var c = document.getElementById("canvas1");
  var ctx = c.getContext("2d");
  var img = document.createElement('img')
  img.src = 'shaq.png'
  img.onload = function() {
    ctx.drawImage(img, 0, 0, c.width, c.height);
    var imgData = ctx.getImageData(0, 0, c.width, c.height);
    var i;
    for (i = 0; i < imgData.data.length; i += 4) {
      var rgblist = [imgData.data[i], imgData.data[i+1], imgData.data[i+2]]
      var filtered = toGray(rgblist)
      imgData.data[i] = filtered[0]
      imgData.data[i+1] = filtered[1]
      imgData.data[i+2] = filtered[2]
    }
    ctx.putImageData(imgData, 0, 0);
  }
}
canvas {
  position: absolute;
  bottom: 10px;
  left: 0;
  width: 100vw;
  height: 100vh;
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>filter</title>
    <link href="style.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <canvas id="canvas1"></canvas>
    <script src="codes.js"></script>
    <script src="filter.js"></script>
    <script src="script.js"></script>
  </body>
</html>
Shiv
  • 370
  • 1
  • 14
  • 1
    Does this answer your question? [Converting RGB to grayscale/intensity](https://stackoverflow.com/questions/687261/converting-rgb-to-grayscale-intensity) – Sean Feb 05 '22 at 04:41

2 Answers2

1

Just find the average of the rgb values, then insert that as the red, green, and blue values to create gray.

Your new toGray function would be:

function toGray(vals) {
  var r = vals[0]
  var g = vals[1]
  var b = vals[2]
  return (r+g+b)/3
}
Shiv
  • 370
  • 1
  • 14
1

There are three algorithms for converting color to grayscale basically.

lightness, average, luminosity method

  1. The lightness method averages the most prominent and least prominent colors:

    (max(R, G, B) + min(R, G, B)) / 2

  2. The average method simply averages the values: (R + G + B) / 3

  3. The luminosity method is a more sophisticated version of the average method. It also averages the values, but it forms a weighted average to account for human perception. We’re more sensitive to green than other colors, so green is weighted most heavily. The formula for luminosity is 0.21 R + 0.72 G + 0.07 B

According to the above calculation formula, the function will be:

function toGray(vals) {
  var r = vals[0];
  var g = vals[1];
  var b = vals[2];
  return Math.round((Math.min(r, g, b) + Math.max(r, g, b)) / 2);
  // return Math.round((r + g + b) / 3);
  // return Math.round(0.21 * r + 0.72 * g + 0.07 * b);
}

And your filter function will look like this:

function filter() {
  .....
      var filtered = toGray(rgblist)
      imgData.data[i] = filtered
      imgData.data[i+1] = filtered
      imgData.data[i+2] = filtered
    
  ....
}