Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Color different image parts javascript

I have an img tag. The image inserted has different parts:Image I want to be able to color each white part alone. I tried using this function:

function getPixels(img)
{
    canvas.width = img.width;
    canvas.height = img.height;

    ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height);
    originalPixels = ctx.getImageData(0, 0, img.width, img.height);
    currentPixels = ctx.getImageData(0, 0, img.width, img.height);

    img.onload = null;
}

function hexToRGB(hex)
{
  console.log(hex)
    var long = parseInt(hex.replace(/^#/, ""), 16);
    return {
        R: (long >>> 16) & 0xff,
        G: (long >>> 8) & 0xff,
        B: long & 0xff
    };
}

function changeColor(a,b,c)
{
    if(!originalPixels) return; // Check if image has loaded
    var newColor = {R: eval(a), G: eval(b), B: eval(c)};

    for(var I = 0, L = originalPixels.data.length; I < L; I += 4)
    {
        if(currentPixels.data[I + 3] > 0) // If it's not a transparent pixel
        {
          console.log(currentPixels.data[I + 3])
           if ((currentPixels.data[I]!=0 && currentPixels.data[I+1]!=0 && currentPixels.data[I+2]!=0)) {
            currentPixels.data[I] = newColor.R;
            currentPixels.data[I + 1] = newColor.G;
            currentPixels.data[I + 2] = newColor.B;
           }
        }
    }
    console.log(newColor)
    ctx.putImageData(currentPixels, 0, 0);
    mug.src = canvas.toDataURL("image/png");
}

function valueToHex(c) {

  var hex1 = c.toString(16);

  return hex1


}

But this is the output: output

I had the idea to make a condition in which i can detect all the white pixels color them and stop when a black pixel is detected, so it doesn't go out of line, and then i can color each white part of the image of a different color. But i didn't know how to do it as i'm really new to the pixel field. Could you help me please?

like image 270
Nour Hariz Avatar asked Jan 27 '26 08:01

Nour Hariz


1 Answers

If you want to be able to do this with any image and color, consider implementing a Flood fill algorithm. In short, it's the same algorithm used by the "bucket" fill tool in most paint programs, which fills connected, similarly-colored areas. In your case, you would give the algorithm a starting coordinate for each closed white region you want to fill into a different color.

Here is a sample implementation with your image:

const img = document.querySelector("img");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

const THRESHOLD = 50;

// make sure image has been decoded and is ready to use
img.decode().then(() => {
    ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, canvas.width, canvas.height);
    fillColor(ctx, 50, 50, "#0000ff", THRESHOLD);
    fillColor(ctx, 65, 100, "#0099ff", THRESHOLD);
    fillColor(ctx, 250, 50, "#0000ff", THRESHOLD);
    fillColor(ctx, 235, 100, "#0099ff", THRESHOLD);
})

function hexToRGB(hex) {
  var long = parseInt(hex.replace(/^#/, ""), 16);
  return [(long >>> 16) & 0xff, (long >>> 8) & 0xff, long & 0xff];
}

function fillColor(ctx, x, y, color, threshold = 0) {
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const newDataBuffer = imageData.data.slice(0);
  const oldRGBA = getRGBAFromCoord(x, y);
  const newRGB = hexToRGB(color);

  function getCoordinateStartIndex(x, y) {
    return (x << 2) + (y * imageData.width << 2);
  }

  function getRGBAFromIndex(startIndex) {
    return newDataBuffer.slice(startIndex, startIndex + 4);
  }

  function getRGBAFromCoord(x, y) {
    const startIndex = getCoordinateStartIndex(x, y);
    return getRGBAFromIndex(startIndex);
  }

  function updateColorAtIndex(startIndex) {
    newDataBuffer.set(newRGB, startIndex);
  }

  function colorsWithinThreshold([r1, g1, b1, a1], [r2, g2, b2, a2]) {
    const r = r1 - r2,
      g = g1 - g2,
      b = b1 - b2,
      a = a1 - a2;
    return r * r + g * g + b * b + a * a <= threshold * threshold << 2;
  }

  if (
    oldRGBA[0] === newRGB[0] &&
    oldRGBA[1] === newRGB[1] &&
    oldRGBA[2] === newRGB[2] &&
    oldRGBA[3] === newRGB[3]
  ) {
    return;
  }

  const fillQueue = [
    [x, y]
  ];

  while (fillQueue.length != 0) {
    const [curX, curY] = fillQueue.pop();
    const curPixelStartIndex = getCoordinateStartIndex(curX, curY);
    updateColorAtIndex(curPixelStartIndex);

    const nextCoords = [
      [curX - 1, curY],
      [curX + 1, curY],
      [curX, curY - 1],
      [curX, curY + 1],
    ];
    for (const [nextX, nextY] of nextCoords) {
      if (nextX < 0 || nextX >= imageData.width || nextY < 0 || nextY >= imageData.height) continue;

      const nextColor = getRGBAFromCoord(nextX, nextY);
      if (colorsWithinThreshold(nextColor, oldRGBA)) {
        fillQueue.push([nextX, nextY]);
      }
    }
  }

  const newImageData = new ImageData(newDataBuffer, imageData.width, imageData.height);
  ctx.putImageData(newImageData, 0, 0);
}
<canvas width="300" height="150"></canvas>
<img width="600" height="300" hidden src="data:image/png;base64,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">

Note: this gets considerably slower as the canvas grows in size. So if you experience performance issues, either shrink the size of your canvas and resize the image once it's a PNG, or try implementing Flood fill in WebAssembly.

However, if you need it for this picture only, then since the only white in the image is contained within the eyes, you can greatly simplify the fillColor() function to just look for and update any white pixel:

function fillColor(ctx, color) {
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const newRGB = hexToRGB(color);

    function getRGBAFromIndex(startIndex) {
        return imageData.data.slice(startIndex, startIndex + 4);
    }

    // copy the buffer of pixel data
    const newDataBuffer = imageData.data.slice(0);

    for (let i = 0; i < newDataBuffer.length; i += 4) {
        const [r, g, b, a] = getRGBAFromIndex(i);
        // check if pixel is white
        if (r === 255 && g === 255 && b === 255 && a === 255) {
            // update pixel to new color into the copy
            newDataBuffer.set(newRGB, i);
        }
    }

    // paint the new image data
    const newImageData = new ImageData(newDataBuffer, imageData.width, imageData.height);
    ctx.putImageData(newImageData, 0, 0);
}
like image 157
Dennis Kats Avatar answered Jan 28 '26 21:01

Dennis Kats



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!