Friday, 26 January, 2024 UTC


Summary

Let's see how to build a small Javascript app where we will load an image, invert the colors in the image, and download the resulting image.
The final app is shown in the below video:
Uploading the image
The first step will be to upload the image from your local drive. I've written a full tutorial about how to use URL.createObjectURL() to upload images in Javascript so I will not go into too many details about this.
Will have just some basic HTML:
<input id="inp" type='file' accept='image/*' capture='camera'/>
<img id="img" />
Alongside the needed Javascript for previewing the uploaded image:
const input = document.querySelector('#inp')
const img = document.querySelector('#img')

input.addEventListener('change', () => {
  const url = window.URL.createObjectURL(input.files[0])
  img.src = url
})
Drawing the uploaded image in the canvas
We will use a HTML canvas in order to manipulate the colors of the uploaded image.
Therefore will add a canvas element in the HTML.
<canvas id="can" width="200" height="200">
In order to draw on the canvas, we will need to access its Javascript context object.
The context can be used to do all kinds of manipulations or draw shapes. So, we will use the drawImage() method to put the content of the image on the canvas:
const input = document.querySelector('#inp')
const img = document.querySelector('#img')
const link = document.querySelector('#lnk')
const canvas = document.querySelector('#can')
const ctx = canvas.getContext('2d')

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

img.onload = ()=> {
  ctx.drawImage(img, 0, 0)
}
Note the drawImage() will be called only on the onload event of the image, or we will get an empty white image. By the way I've also wrote about how to make this image responsive by redrawing the canvas on resize.
At this point the app will draw on the canvas the same image we upload:
Inverting the colors of the canvas using Javascript
The next step will be to do the reversing of the colors. While we can do this also with CSS filters this time we will use the above Javascript context object.
We will first get an imageData object that looks something like this:
These are rgba values, so every four records refer to a one-pixel value containing:
  • red (range: 0-255)
  • green (range: 0-255)
  • blue (range: 0-255)
  • alpha (range: 0-255)
So we can invert each pixel value, by doing 255 - old value. In code, it will look like this:
img.onload = ()=> {
  ctx.drawImage(img, 0, 0)
  const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
  imgData.data = reverseColors(imgData)
  ctx.putImageData(imgData, 0, 0)
  link.href = canvas.toDataURL()
}

let reverseColors = ({data}) => {
  console.log(data)
  for (i = 0; i < data.length; i += 4) {
    data[i] = 255 - data[i];
    data[i + 1] = 255 - data[i + 1];
    data[i + 2] = 255 - data[i + 2];
    data[i + 3] = 255;
  }
  return data
}
Downloading the image with the reverted colors
The final step is to add the save image link. For this, we will use the download attribute of the link tags.
Will first add a basic link with the download attribute:
<a id='lnk' download>Save the img</a>
And in the Javascript, will set its href to the image with the reverted colors:
link.href = canvas.toDataURL()
You can see here the full code here and the running example on Github pages.