how to change the color of an image in a HTML5 Canvas without changing its pattern

I want to change the background color of this image while keeping the form, the effects and the contour of the image.

<canvas id="canvas01" width="1200" height="800"></canvas>
<script>
    function drawImage(imageObj,x, y, width, height){
        var canvas = document.getElementById('canvas01');
        var context = canvas.getContext('2d');
        context.drawImage(imageObj, x, y, width, height);
    }
    var image = new Image();
    image.onload = function(){
        drawImage(this, 400, 100, 320, 450);
    };
    image.src ="images/658FFBC6.png";
</script>

It's difficult to "recolor" an image using the canvas's default RGBA color scheme. So this demo converts the RGB data to the HSL color scheme. This allows the "color" (hue) to be changed without affecting the other components of the pixel (S=saturation of the color, L=lightness of the color).

Global composite operations

The 2D context property ctx.globalCompositeOperation is very useful for a wide range of image processing tasks. For more on globalCompositeOperation at MDN

You can convert the image into a canvas, that way you can edit it.

function imageToCanvas(image){
    const c = document.createElement("canvas");
    c.width = image.width;
    c.height = image.height;
    c.ctx = c.getContext("2d"); // attach context to the canvas for eaasy reference
    c.ctx.drawImage(image,0,0);
    return c;
}

You can use the globalCompositeOperation = "color" to colour the image

function colorImage(image,color){ // image is a canvas image
     image.ctx.fillStyle = color;
     image.ctx.globalCompositeOperation = "color";
     image.ctx.fillRect(0,0,image.width,image.height);
     image.ctx.globalCompositeOperation = "source-over";
     return image;
}

Unfortunately this also overwrites the alpha pixels so you need to use the original image as a mask to restore the alpha pixels.

function maskImage(dest,source){
     dest.ctx.globalCompositeOperation = "destination-in";
     dest.ctx.drawImage(source,0,0);
     dest.ctx.globalCompositeOperation = "source-over";
     return dest;
}

And then you have a coloured image

Example.

In he example I colour the image in a range of colours and added a function to restore the canvas copy of the image back to the original. If you get the image from the page as an element then use naturalWidth and naturalHeight as the width and height properties may not match the image resolution.

const ctx = canvas.getContext("2d");
const image = new Image;
var colCopy;
image.src = "https://i.stack.imgur.com/Kk1qd.png";
image.onload = () => {
  colCopy = imageToCanvas(image);
  const scale = canvas.height / image.naturalHeight; 
  ctx.scale(scale, scale);
  ctx.drawImage(colCopy, 0, 0);
  for (var i = 32; i < 360; i += 32) {
    restoreImage(colCopy, image);
    colorImage(colCopy, "hsl(" + i + ",100%,50%)");
    maskImage(colCopy, image);
    ctx.drawImage(colCopy, 150 * i / 16, 0);
  }
}



function imageToCanvas(image) {
  const c = document.createElement("canvas");
  c.width = image.naturalWidth;
  c.height = image.naturalHeight;
  c.ctx = c.getContext("2d"); // attach context to the canvas for easy reference
  c.ctx.drawImage(image, 0, 0);
  return c;
}

function restoreImage(dest, source) {
  dest.ctx.clearRect(0, 0, dest.width, dest.height);
  dest.ctx.drawImage(source, 0, 0);
  return dest;
}

function colorImage(dest, color) { // image is a canvas image
  dest.ctx.fillStyle = color;
  dest.ctx.globalCompositeOperation = "color";
  dest.ctx.fillRect(0, 0, dest.width, dest.height);
  dest.ctx.globalCompositeOperation = "source-over";
  return dest;
}

function maskImage(dest, source) {
  dest.ctx.globalCompositeOperation = "destination-in";
  dest.ctx.drawImage(source, 0, 0);
  dest.ctx.globalCompositeOperation = "source-over";
  return dest;
}
canvas {
  border: 2px solid black;
}
<canvas id="canvas" width=600></canvas>

To grayscale the colors of an image with HTML5 Canvas, we can iterate over all of the pixels in the image, calculate the brightness of each, and then set the red, green, and blue components equal to the brightness. Note: The getImageData() method requires that the image is hosted on a web server with the same domain as the code executing it. If

You can combine filters on a single line of code before performing your draw operation, like this:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = document.getElementById('source');

ctx.filter = 'hue-rotate(120deg) grayscale(10%) brightness(150%)';
ctx.drawImage(image, 10, 10, 180, 120);
<canvas id="canvas"></canvas>
<div style="display:none;">
  <img id="source"
       src="https://interactive-examples.mdn.mozilla.net/media/examples/gecko-320-213.jpg">
</div>

Description. To set the color of an HTML5 Canvas line, we can use the strokeStyle property of the canvas context, which can be set to a color string such as red, green, or blue, a hex value such as #FF0000 or #555, or an RGB value such as rgb(255, 0, 0).

Some images can make your page harder to read. An image in the background can interfere with the text, so the page can be much harder to read. Good images don’t make good backgrounds. A good picture draws the eye and calls attention to it. The job of a background image is to fade into the background. If you want people to look at a picture

How to fill whole HTML5 <canvas> with one color.. I saw some solutions such as this to change background color using CSS but this is not a good solution since the canvas remains transparent, the only thing that changes is the color of the space it occupies.

Specify the image on your computer or phone, select the colors you want to replace, click OK button at the bottom of this page, wait a few seconds and download the finished result. Pink rose without changes and examples of pink color replacement to: purple, blue, turquoise, green and yellow color: To create the above examples, were used the following settings: " Color that should be replaced " – "pink", " Replace the selected color with " – "purple" color (for the next processing "blue

Comments
  • see this fiddle:jsfiddle.net/pHwmL/1 . related to the thread stackoverflow.com/questions/10069171/…
  • Are you talking about changing the background color your the image, which in your case is transparent, or the global color the image? Like make your green T-shirt in red.
  • i already tried this before, the thing is, the canvas itself contains a lot of images, so i just want to tint one of the image in the canvas and not the whole canvas. thank you Suchit Kumar..
  • i'm talking about changing the color of the T-shirt (Like make it red or blue), but i have to keep the effect and the shape of the Tshirt. Thank you Allan Raquin
  • Yes it works but I have another issue with some colors for example if I choose the HSL code of a color for example (white hsl(0, 0%, 100%)) i don't get the white color but a way different color. How can i deal with this ? Thank you K3N
  • @M.Chaymae yeah, it's a problem with the HSL model. If there is no chroma data (ie. sat=0) it won't work. However, you can get around using lightness (L) combined with color-dodge blending mode for white t's, and color-burn when you need black t's. I updated the answer.
  • i have another question, your code worked perfectly however i found a problem when i try to draw multiple image on the same canvas it looks like this ibb.co/dCgpjk. How can i remove those gray rectangles in your code. Once again Thank you so much for your help !
  • @M.Chaymae you can use the clipping step (the last step in the code above, see code below the comment // clip). It is assumed of course that the image being used is having a alpha-channel (transparent background).
  • I did as u told me but I have a problem ... I have multiple image on the same canvas so one of these images appears and the others no but this time without the gray rectangle .. I don't know it doesnt appear like the image but without the gray rectangles
  • do you have any idea howa can use this code for multiple images ? I want to add more images to my canvas and color them all in once