In today’s digital development, black and white images are becoming more and more rare in our daily life. Although black and white images are not as true and aesthetic as color pictures, they can highlight the seriousness and sense of time, and have more commemorative significance. This article will introduce how to front-end color bitmap to black and white, for interested partners reference.

This is the 11th day of my participation in Gwen Challenge

Implementation approach

Don’t say a word. Just do it.

A bitmap is an image made up of tiny squares (pixels) :

Each pixel grid in the figure above represents a color value that we usergbaR represents red, G represents green, B represents blue, and A represents transparency.

Therefore, we need to convert the RGBA of each pixel in the bitmap to the corresponding gray-scale RGBA.

How do you calculate that?

We adopt the mean value method: add r, G and B and take the average value as the RGB and alpha of the new color value to unify as opaque.

For example, convert red rgba(255,0,0,1) to black and white rgba(85,85,85,1)

Next, we need to take all the RGBA color values of the position map image.

Gets the color value of the image

Here we need to use a method ctx.getimageData (sx, SY, SW, sh): represents the image data of an area from the CavAS2D context. Sx and SY represent the starting point of the image in this area, while SW and SH represent the size of the image in this area.

How do we get the RGBA color value of an image?

  • Draw this image to the canvas
  • Render context with the aid of Canvas2DgetImageDataMethod to obtain data
<img src="./wife.png" alt="">
<canvas id="canvas"></canvas>
<script>
    var img = document.querySelector('img');
    var canvas = document.querySelector('#canvas');

    img.onload = function(){
        var naturalImgSize = [img.naturalWidth,img.naturalHeight];

        var ctx = canvas.getContext("2d");
        canvas.width = naturalImgSize[0];
        canvas.height = naturalImgSize[1];
        ctx.drawImage(img,0.0);

        / / get imageData
        var imgData = ctx.getImageData(0.0.254.419);
        // Prints the data
        console.log(imgData)
    }
</script>
Copy the code

Here’s what we got:Height and width are the pixel sizes of the image (254px * 419px), and data is a one-dimensional array of the rGBA color values of the image.

For example, we have a 2px by 2px red image:

From left to right and top to bottom, it has 4 pixels, each containing rGBA 4 values (one byte represents a value, ranging from 0 to 255, i.e. 00000000-11111111). So each pixel takes up 4 positions.

The red image rgba data value corresponds to a one-dimensional array contains four 255,0,0,255, namely,0,0,255,255,0,0,255,255,0,0,255,255,0,0,255 [255].

After the example, go back to the Unit8ClampedArray array we got. Its length is the pixel width and height of the image * 4:254 *419*4 = 425704.

The expansion is just one by one0-255.Data points of:

Perform the conversion

In the last video, we got the image data, and now we need to perform the grayscale conversion. As mentioned before, we use the mean value method.

We need to iterate over the above array, then synchronize the converted values to a new array, and generate a new imageData from the new array and render it to the canvas.

// Define a new array
let newArr = [];
imgData.data.forEach((colorVal,i) = >{
    if(i % 4= = =0) {// Get the RGB mean value
        const average = Math.round((imgData.data[i]+imgData.data[i+1]+imgData.data[i+2) /3);
        newArr[i] = newArr[i+1] = newArr[i+2] = average;
        // The alpha value is 255
        newArr[i+3] = 255; }})// Create a imgData object
var newImgData = ctx.createImageData(254.419)
// Add the converted data to the new imageData object
newImgData.data.set(newArr);

// Draw the new imageData onto the canvas
ctx.putImageData(newImgData, 0.0);
Copy the code

After all this is done, we can see:

Now that we have converted the image to gray, let’s save the image on the Canvas as an image file:

canvas.toBlob(blob= >{
    var a = document.createElement("a");
    var file = new File([blob], "wife.jpeg");
    a.href = URL.createObjectURL(file);
    a.download = "wife.jpg";
    a.click()
},"image/jpeg")
Copy the code

See that we successfully saved the image locally:

conclusion

Color to black and white is basically over here, we use getImageData’s ability to directly manipulate RGBA data in the front end.

With this ability, some operations such as image rotation, image horizontal, vertical axisymmetric conversion and so on usually need to use the client software such as PS to complete, in the front can also be completed, because the essence of these operations is just to change the image pixel point arrangement. It is well explained by the diagram:

The original:

Rotate 90 degrees to the right:

Horizontal axial symmetry:

To summarize the steps for converting color bitmaps to black:

  • Draws the image file associated with image to a canvas
  • Gets the imageData data for the canvas image
  • Calculate the AVERAGE value of the RGBA portion of the imageData data and populate it into your new array
  • Populate the new array with a new ImageData object
  • Draw the new ImageData object back to the Canvas element
  • The Canvas is converted to a file object and saved locally

Finally, thank you for reading. If you have any questions about the content of this article, please leave a comment and give advice. If this article helped you, please give it a thumbs up. Thank you.