04 Nov 2025

Building a Fast Color Picker - Finding the Closest Pixel Match in Images

... views

Ever wondered how color picker tools find the exact pixel that matches your target color? Let’s dive into a simple but effective algorithm that can power many web-based color extraction tools and more!

The Problem

You have an image loaded in your web application, and you want to find the pixel that most closely matches a specific color. Sounds simple, but when you’re dealing with 140,000+ pixels, you need an efficient approach.

For example, imagine an online art tool where a user clicks on a palette color, and the app instantly highlights the closest matching area in their uploaded photo.

Prerequisites concepts

  • HTML5 Canvas
    • HTML5 Canvas is indeed like a digital painting easel in your browser where you can perform computational calculations to extract detailed information about images at the pixel level.
  • Euclidean distance
    • $distance = √[(r₁-r₂)² + (g₁-g₂)² + (b₁-b₂)²]$
  • RBGA colors.

Thinking process

We want to make a function which inputs the image and the target color and return the (x,y) coordinates for the closet color matching to the target color.

If we can somehow get all the pixels to show their RGB values and go to each pixel of the image and check the closeness of each pixel RGB value to the target color, then we can choose the one with the least difference (0 is the magical number here!!) and return its coordinates. Job done right? Pretty much, if we can answer these 2 questions.

  1. How do we get all pixels to show their RGB values?
  2. What is closeness to target color?

If you have basic idea of geometry, and you plot all the colors as their RGB values in a 3-dimensional plane, 2 similar colors, says shades of blue will have a shorter Euclidean distance than one shade of blue and red. So we can use this argument to define closeness between 2 colors.

Now, how do we get all pixels to show their RGB values?, it depends where you are loading the image. If it’s on a JavaScript based browser, you can use HTM5 canvas object to help you. For other platforms, similar tools exist, you just need to find those. Trivial problem.

Validating our thoughts

By now, we have a solid mental model on how to solve this main problem. Let’s do a simple dry-run on a very trivial image.

In order to visualize, consider a 2x2 matrix, think of these to be pixels of an image.

rgb(255, 107, 107)rgb(70, 130, 180)
rgb(50, 205, 50)rgb(255, 215, 0)

Now we want to find the closet color in the above image(or RGB matrix) to this one - rgb(173, 216, 230)

So what we do is go to each and every pixel and check the closeness or Euclidean distance to the target color.

$x=0, y=0$ → $distance = √[(255-173)² + (107-216)² + (107-230)²]$ ≈ $183.7$
$x=0, y=1$ → $distance = √[(70-173)² + (130-216)² + (180-230)²]$ ≈ $143.2$
$x=1, y=0$ → $distance = √[(50-173)² + (205-216)² + (50-230)²]$ ≈ $218.3$
$x=1, y=1$ → $distance = √[(255-173)² + (215-216)² + (0-230)²]$ ≈ $244.2$

Since $143.2$ is smaller than all other distances we’ve got, so the color at $x=0, y=1$ seems to be the closet to our target color.

But how do we verify it our algorithm is correct? Well, we can use our eyes and see that.

Since the target color and the color at $x=0, y=1$ look shades of each other, we can successfully conclude that your algorithm is correct. Yay!

Since, we’ve taken a very bad image for the example, our distances were quite large, but in an actual image, the target color would be in the image to essentially the distance should be 0 or very small

Fun Fact: Our algorithm is essentially a 1-Nearest Neighbor (1-NN) search in RGB color space.

Let’s code this out, for a JavaScript browser.

1-Nearest Neighbor Search in RGB space in a JavaScript environment

Lets write 2 functions

  1. To calculate Euclidean distance between 2 colors
  2. Find the coordinates of nearest color to target color
const calculateColorDistanceRGB = (rgb1: rgb, rgb2: rgb): number => {
let distance:number = Math.sqrt(
	Math.pow(rgb2.r - rgb1.r, 2) +
	Math.pow(rgb2.g - rgb1.g, 2) +
	Math.pow(rgb2.b - rgb1.b, 2)
	);
return distance;
}
function findNearestColorCoordinates(
targetColor: rgb
img: HTMLImageElement // Multiple ways to get the HTMLImageElement
): { x:number, y:number } {
	const canvas = document.createElement("canvas");
	const ctx = canvas.getContext("2d", { willReadFrequently: true });
	ctx.drawImage(img, 0, 0, img.width, img.height);
	const imageData = ctx.getImageData(0, 0, img.width, img.height);
	const data: Uint8ClampedArray = imageData.data;

	let closetDistance: number = Infinity;
	let closestIndex: number = -1;
	let x: number = -1;
	let y: number = -1;

	for (let i = 0; i < data.length; i += 4) {
	const r: number = data[i];
	const g: number = data[i + 1];
	const b: number = data[i + 2];

	const dist = calculateColorDistanceRGB({ r: r, g: g, b: b }, rgbColor);

		if (dist < closetDistance) {
			closetDistance = dist;
			closestIndex = i / 4;
		}
	}

	x = closestIndex % width;
	y = Math.floor(closestIndex / width);

	if (x !== -1 && y !== -1) {
		return { x: x, y: y };
	}
	else {
		return undefined;
	}
}

Let’s talk about the 2nd function - findNearestColorCoordinates. It basically

  • Draws the image on a canvas, which is then used to get details image. It gives use the color of each pixel in the image. But here’s the tricky part, it gives us the color information in a crazy & stupid way.

    • What we get is a flat array of RGB values, where each r, g, b are items of the array, and this is for all pixels, so essentially what we have is
      • [R,G,B,A,R,G,B,A,R,G,B,A,R,G,B,A,R,G,B,A,R,G,B,A,......]
    • For the matrix (very lovely image), we would get
      • [255,107,107,255,70,130,180,255,50,205,50,255,255,215,0,255]
    • Alpha value for solid colors is 255
    • Multiple way to deal with this array, I’ll explain have I’ve done.
  • Travels each pixel, When you’ve to travelling to each pixel, just skip 4 items so reach the next pixel’s RGBA values

    • for (let i = 0; i < data.length; i += 4)
  • As you travel, keep updating the closetDistance and closetIndex as and when you encounter a shorter distance between targetColor and pixels in the image

  • Once the travelling is over, and you have the close pixel with you, you need to return the $x,y$ coordinates. Since now, you have the pixel in a 1D space, you need to find its fitting in the 2D space, which is where that pixel would be in the image (image is 2D).

  • $$ x = index \bmod width, \quad y = \left\lfloor \frac{index}{width} \right\rfloor $$

    • consider your matrix again, the 2nd pixel (1st index of array) was our find, now to convert it to $x,y$ coordinates we $$ x = 1 \bmod 2, \quad y = \left\lfloor \frac{1}{2} \right\rfloor $$ $$ x = 0, \quad y = 1 $$

The Bottom Line

Sometimes the simplest solution is the best solution. This 1-NN approach gives you fast, practical color matching that works great for interactive web applications. It’s not perfect, but it gets the job done efficiently - and in web development, that often matters more than theoretical perfection.