šŸ“• Build AI Agents using LangGraph.js is now out!

Generating black-white and grayscale images with Javascript and canvas

In today's article, we will build a simple app where we can upload an image, and using Javascript and the canvas element we will get a black-white plus a grayscale version of that image.

black-white and grayscale images with Javascript and canvas

I will not get into too many details about the initial setup of the project. For a better understanding, I encourage you to read the posts about how to upload an image and generate its preview, and invert the colors of a picture on a canvas.

So, we will start with this HTML code:

<input id="inp" type='file' accept='image/*' capture='camera'/>
<img id="img" />
<canvas id="can-bw" width="200" height="200"></canvas>
<canvas id="can-bwg" width="200" height="200"></canvas>

And from this Javascript:

const input = document.querySelector('#inp')
const img = document.querySelector('#img')
const ID_BLACK_WHITE_CANVAS = 'can-bw'
const ID_GRAY_CANVAS = 'can-bwg'

input.addEventListener('change', () => {
  const url = URL.createObjectURL(input.files[0])
  img.src = url
})

img.onload = ()=> {
  setupCanvas(ID_BLACK_WHITE_CANVAS, toBlackAndWhite)
  setupCanvas(ID_GRAY_CANVAS, toBlackWhiteGray)
}

const setupCanvas = (id, pFunction)=> {
  const canvas = document.getElementById(id)
  const ctx = canvas.getContext('2d')
  ctx.drawImage(img, 0, 0)
  processCanvas(canvas, ctx, pFunction)
}

const processCanvas = (canvas, ctx, pFunction)=> {
  const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
  imgData.data = processImgData(imgData, pFunction)
  ctx.putImageData(imgData, 0, 0)
}

const processImgData = ({data}, pFunction) => {
  // use the pFunction to process the image
  return data
}

const toBlackAndWhite = () => {
  // to be implemented
}

const toBlackWhiteGray = (red, green, blue) => {
  // to be implemented
}

For the time being what this code does is just display the same picture we initially upload in the two canvases:
black-white and grayscale images with Javascript and canvas

By the way, if you want to add CSS styles on the upload button I've written a tutorial about this.

The data that arrives in the processImgData() is the result of ctx.getImageData(). As we have seen in the example with inverting the colors of a picture each set of 4 items from the data parameter represents an RGBA set for a pixel from the image. So, we can do something like this:

const processImgData = ({data}, pFunction) => {
  for (i = 0; i < data.length; i += 4) {
    data[i] //  red (0-255)
    data[i + 1] //  green (0-255)
    data[i + 2] //  blue (0-255)
    data[i + 3] //  alpha (0-255, 0 = transparent, 255 = fully visible)
  }
  return data
}

Therefore we need to find a way to convert the RGBA values to just one black/white/gray value.

The key points here are the toBlackAndWhite() and toBlackWhiteGray() functions, which are not yet implemented.

A toBlackWhiteGray() function can look like this:

const toBlackAndWhite = (red, green, blue) => {
  const count = red + green + blue
  const colour = count < 383 ? 0 : 255
  return colour
}

While the toBlackWhiteGray() function can look like this:

const toBlackWhiteGray = (red, green, blue) => {
  const count = red + green + blue
  let colour = 0
  if (count > 510) colour = 255
  else if (count > 255) colour = 127.5
  return colour
}

Of course, we can tweak the way we interpret the gray color, and could add a more complex grayscale to the function.

Finally, with these functions implemented, we can now replace a color pixel with the result of one of these functions:

const processImgData = ({data}, pFunction) => {
  for (i = 0; i < data.length; i += 4) {
    const color = pFunction(data[i], data[i+1], data[i+2])
    data[i] = color
    data[i + 1] = color
    data[i + 2] = color
    data[i + 3] = 255
  }
  return data
}

You can see here the full working codepen for this example.

I will leave it as homework to you to implement the functionality of downloading the resulting images. Hint, you can use the download attribute of links for this.

šŸ“– Build a full trivia game app with LangChain

Learn by doing with this FREE ebook! This 35-page guide walks you through every step of building your first fully functional AI-powered app using JavaScript and LangChain.js

šŸ“– Build a full trivia game app with LangChain

Learn by doing with this FREE ebook! This 35-page guide walks you through every step of building your first fully functional AI-powered app using JavaScript and LangChain.js


Leave a Reply

Your email address will not be published. Required fields are marked *