How to Convert an Image to Grayscale with JavaScript
Grayscale images are composed exclusively of shades of gray. They are commonly stored with 8 bits per sampled pixel, which allows 256 different intensities to be recorded.
Converting an image to grayscale has some usages:
- File size reduction: an 8-bit grayscale image often requires less data for storage than a 24-bit color image.
- Image processing: many image processing algorithms work on grayscale images rather than color images.
- Aesthetics: a monochrome grayscale image can evoke a special feeling which a color image cannot give.
A sample image converted to grayscale:
In this article, we are going to talk about three ways to convert an image to grayscale with JavaScript.
- CSS
- Canvas
- Dynamic Web TWAIN, a document-scanning SDK
Build an HTML5 Page to Convert Images to Grayscale
Create a new HTML5 page with the following template and then let’s add the color conversion function to it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Convert an Image to Grayscale</title>
<style>
</style>
</head>
<body>
<div class="home">
<h2>Convert an Image to Grayscale</h2>
<button id="convertButton">Convert</button>
</div>
<script>
</script>
</body>
</html>
Load an Image File
Add an input
element for selecting files and use a button element to trigger it. The image file will be loaded into two image elements, one for displaying the converted result and one for storing the original image.
HTML:
<button id="loadFileButton">Load a File</button>
<input style="display:none;" type="file" id="file" onchange="loadImageFromFile();" accept=".jpg,.jpeg,.png,.bmp" />
<div class="imageContainer">
<img id="image"/>
<img id="imageHidden"/>
</div>
<style>
.imageContainer {
max-width: 50%;
}
#image {
max-width: 100%;
}
#imageHidden {
display: none;
}
</style>
JavaScript:
function loadImageFromFile(){
let fileInput = document.getElementById("file");
let files = fileInput.files;
if (files.length == 0) {
return;
}
let file = files[0];
fileReader = new FileReader();
fileReader.onload = function(e){
document.getElementById("image").src = e.target.result;
document.getElementById("imageHidden").src = e.target.result;
};
fileReader.onerror = function () {
console.warn('oops, something went wrong.');
};
fileReader.readAsDataURL(file);
}
Display an Image in Grayscale with CSS
We can use the CSS property filter
to make an HTML element display in grayscale:
document.getElementById("image").style.filter = "grayscale(1)";
It can make any HTML element in grayscale but if we need to save the image in grayscale, we cannot use this approach.
Convert an Image to Grayscale with Canvas
HTML5 provides a canvas
element which provides a way to manipulate image data. Unlike CSS which only changes the visual effect, we can use it to actually get an image converted in grayscale.
-
Add a hidden
canvas
element to the page.<canvas id="canvasHidden"></canvas> <style> #canvasHidden { display: none; } </style>
-
Add a
select
element to select which conversion method to use.<label> Method: <select id="methodSelect"> <option>CSS</option> <option>Canvas</option> </select> </label>
-
Convert an image to grayscale with
canvas
when the selected method is “Canvas”.let method = document.getElementById("methodSelect").selectedIndex; if (method == 0) { convertWithCSS(); }else if (method == 1){ document.getElementById("image").style.filter = ""; convertWithCanvas(); }
Details of converting an image to grayscale with canvas.
-
Set the canvas’s size to match the image’s size.
const image = document.getElementById("image"); const canvas = document.getElementById("canvasHidden"); canvas.width = image.naturalWidth; canvas.height = image.naturalHeight;
-
Get the context of the canvas to perform actions.
const context = canvas.getContext("2d");
-
Draw the image onto the canvas.
context.drawImage(image, 0, 0);
-
Get the
ImageData
of the image:const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
ImageData
stores the pixel values in aUint8ClampedArray
in the RGBA order, with integer values between 0 and 255 (inclusive). The order goes by rows from the top-left pixel to the bottom-right. -
Create a function to get the gray value from the RGB values.
//https://github.com/image-js/image-js/blob/9ab86a86f6c13a9a7d14c62566c1396c3c6f54f4/src/image/transform/greyAlgorithms.js function RGBToGrayScale(red,green,blue){ //return red * 0.2126 + green * 0.7152 + blue * 0.0722; return (red * 6966 + green * 23436 + blue * 2366) >> 15; }
There are many ways to calculate the gray value. Here, we use
Rec. 709 luma coefficients
for the conversion. The calculation speed is optimized using multiplication with integer and bit shifting. -
Iterate all the pixels and set the RGB values as the gray value we calculated.
const pixels = imageData.data; //[r,g,b,a,...] for (var i = 0; i < pixels.length; i += 4) { const red = pixels[i]; const green = pixels[i + 1]; const blue = pixels[i + 2]; const grayscale = RGBToGrayScale(red, green, blue) pixels[i] = grayscale; pixels[i + 1] = grayscale; pixels[i + 2] = grayscale; }
-
Put back the
ImageData
.context.putImageData(imageData, 0, 0);
-
Display the converted image.
document.getElementById("image").src = canvas.toDataURL();
Convert an Image to Grayscale with Dynamic Web TWAIN
Dynamic Web TWAIN is a document scanning SDK making it possible to scan documents in the browser. It provides various image processing methods. We can use its ConvertToGrayScale method to convert an image to grayscale.
The advantage of using it is that it can be used to batch process a large volume of images as the processing is done using a native process. The output image file also has a smaller size as native image libraries like libpng are used to optimize the size.
Here are the steps to use it:
-
Include Dynamic Web TWAIN in the page.
<script src="https://unpkg.com/dwt@18.4.2/dist/dynamsoft.webtwain.min.js"></script>
-
Initialize an instance of Web TWAIN and use it to convert the images. You can apply for its license here.
let DWObject; Dynamsoft.DWT.AutoLoad = false; Dynamsoft.DWT.ProductKey = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; //one-day trial Dynamsoft.DWT.ResourcesPath = "https://unpkg.com/dwt@18.4.2/dist"; async function convertWithDWT(){ if (!DWObject) { await initDWT(); } DWObject.RemoveAllImages(); let response = await fetch(document.getElementById("imageHidden").src); let buffer = await response.arrayBuffer(); DWObject.LoadImageFromBinary(buffer, function(){ DWObject.ConvertToGrayScale(0, function(){ document.getElementById("image").src = DWObject.GetImageURL(0); }, function(errorCode, errorString){ console.log(errorString); }); }, function(errorCode, errorString){ console.log(errorString); }) } function initDWT(){ return new Promise((resolve, reject) => { const title = document.querySelector("h2").innerText; document.querySelector("h2").innerText = "Loading Dynamic Web TWAIN..."; Dynamsoft.DWT.CreateDWTObjectEx( { WebTwainId: 'dwtcontrol' }, function(obj) { DWObject = obj; document.querySelector("h2").innerText = title; resolve(); }, function(err) { console.log(err); document.querySelector("h2").innerText = "Failed to load Dynamic Web TWAIN"; reject(err); } ); }) }
Getting Started With Dynamic Web TWAIN
Source Code
You can find all the code and an online demo in the following repo: