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.
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 working codepen for this example.
Related to this you can see here an example of how to generate black-white or grayscale images with Javascript and canvas.
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
Hey Daniel! Thanks for this tutorial. Any idea how can we restrict the size of the uploaded picture?
Hi Andrew! Check it out here: https://www.js-craft.io/blog/restrict-image-upload-size-javascript/