8

I don't know if this is possible, I've never really used html canvas, but I am aware of

var imgPixels = canvasContext.getImageData(0, 0, canvas.width, canvas.height);

but how do I use this to get for example all the pixels with a certain color and change these pixels to white? So let's say I have a pixel colored red:

if(pixel==red){
    pixel = white;
}

that's the simple version of what I would like but not sure how to do that...

anyone any ideas?

alex
  • 479,566
  • 201
  • 878
  • 984
Lennart
  • 1,560
  • 5
  • 20
  • 38

2 Answers2

9

Do something like this (here's the canvas cheat sheet):

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

const { width, height } = canvas;

const gradient = context.createLinearGradient(0, 0, 0, height);
gradient.addColorStop(0.25, "#FF0000");
gradient.addColorStop(0.75, "#000000");

context.fillStyle = gradient;

context.fillRect(0, 0, width, height);

setTimeout(() => {
    const image = context.getImageData(0, 0, width, height);
    const { data } = image;
    const { length } = data;

    for (let i = 0; i < length; i += 4) { // red, green, blue, and alpha
        const r = data[i + 0];
        const g = data[i + 1];
        const b = data[i + 2];
        const a = data[i + 3];

        if (r === 255 && g === 0 && b === 0 && a === 255) { // pixel is red
            data[i + 1] = 255; // green is set to 100%
            data[i + 2] = 255; // blue is set to 100%
            // resulting color is white
        }
    }

    context.putImageData(image, 0, 0);
}, 5000);
<p>Wait for 5 seconds....</p>
<canvas width="120" height="120"></canvas>

Hope that helps.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • Thanks for the js fiddle, but i cant get it to work with an image, its probably a nooby mistake, but could you take a look at it please? http://jsfiddle.net/36M6W/1/ – Lennart Oct 20 '12 at 21:51
  • First of all you're loading your image from imageshack. Images loaded like this may not be modified. Doing so violates the same origin policy. That's why you may not manipulate individual pixels on jsfiddle. – Aadit M Shah Oct 21 '12 at 01:57
  • Next the condition `r === 255 && g === 0 && b === 0 & a === 255` only checks if the color is exactly `#FF0000`. That color may not be present in your image at all. Instead another shade of red may be there. What you want to do is check for a range of numbers. I tried the following condition and it works decently well: `r / g > 2 && r / b > 2`. – Aadit M Shah Oct 21 '12 at 02:00
4

When you get the getImageData(), you have an object with data, width and height.

You can loop over data, which contains the pixel data. It's available in chunks of 4, which are red, green, blue and alpha respectively.

Therefore, your code could look for red pixels (you have to decide what makes a red pixel) and set the red, green and blue all on (to change it to white). You can then use putImageData() to replace the canvas with the updated pixel data.

// You will need to do this with an image that doesn't violate Same Origin Policy.
var imgSrc = "image.png";
var image = new Image;

image.addEventListener("load", function() {

    var canvas = document.getElementsByTagName("canvas")[0];
    var ctx = canvas.getContext("2d");

    canvas.width = image.width;
    canvas.height = image.height;

    ctx.drawImage(image, 0, 0);

    var imageData = ctx.getImageData(0, 0, image.width, image.height);
    var pixels = imageData.data;
    var i;

    for (i = 0; i < pixels.length; i += 4) {
        // Is this pixel *red* ?
        if (pixels[i] > 100) {
            pixels[i] = 255;
            pixels[i + 1] = 255;
            pixels[i + 2] = 255;
        }
    }

    ctx.putImageData(pixels);

});

image.src = imgSrc;​
alex
  • 479,566
  • 201
  • 878
  • 984
  • I can't find documentation on `setImageData`? Did you mean [`putImageData`](https://developer.mozilla.org/en-US/docs/DOM/CanvasRenderingContext2D#putImageData%28%29) – Paul S. Oct 20 '12 at 21:24
  • @PaulS Yes, my memory had failed me :) – alex Oct 20 '12 at 21:33