5

How can I set the colour of every pixel in a image to it's closest colour match from a list of colours in RGB format (no alpha), that can be of any length, in C#?

It's basically creating a custom BitmapPalette, but since you can't do that (Trust me, I've tried everything possible for that), I need an alternative.

Does anyone know a way to do this?

bzlm
  • 9,626
  • 6
  • 65
  • 92
  • 2
    Are you asking about the way to calculate the "closest colour match"? Or how to set pixels in an image? Or (god/SO forbid) both? – bzlm Nov 18 '11 at 18:17
  • I know how to get and set pixels in a image, But I need to know how to set every pixel to its closest match from a list of colours, like a BitmapPalette. So yes, finding the closest colour match. –  Nov 18 '11 at 18:18
  • Probably it depends on what do you mean by `closest colour match` – Snowbear Nov 18 '11 at 18:20
  • 1
    What I mean by closest colour match is what colours will make it look the most like the original picture while using only those colours. –  Nov 18 '11 at 18:22
  • 2
    SO has several question with the same idea. Like this: http://stackoverflow.com/questions/1720528/what-is-the-best-argorithm-for-finding-the-closest-color-in-an-array-to-another – Snowbear Nov 18 '11 at 18:29
  • I've tried many algorithms, like the distance algorithm, but they always return mismatched colours that always screw up so badly that when I put in a flower when it came out it looked like randomly coloured TV static. I need a better algorithm. –  Nov 18 '11 at 18:35
  • 3
    Working with palettes was important 15 years ago. Those days are over, good riddance. Use the GIF encoder if you have to. – Hans Passant Nov 18 '11 at 18:44
  • The March 1995 issue of C/C++ Users Journal had an article, *Octree Color Quantization*, by Ian Ashdown. As I recall, I used that code to convert some images for a game I was working on back then. It explained things quite well, and was not difficult to implement. You might check out the archive at ftp://ftp.drdobbs.com/sourcecode/cuj/1995/. The March 95 archive has the code. I haven't been able to find the article text. – Jim Mischel Nov 18 '11 at 19:23

2 Answers2

3

Boy...I hope you loves your maths...

This is a tough question. To determine the "closeness of fit" between two colors, you first must understand the color space/color model in which your are working. The RGB color model (not counting the alpha channel) is essentially Euclidean in nature: each color maps to a point in 3D space. Ergo, the putative distance between two colors, C1 and C2 is

Distance = SQRT( (C1red - C2red)2 +  (C1green - C2green)2 +  (C1blue - C2blue)2 )

WRT "normal" human visual perception, this is not necessarily correct. To take that into account gets much more complicated.

Try these two papers as jumping-off points:

The Color FAQ also provide many links to other colorspace resources.

Some more links at http://www.golden-gryphon.com/software/misc/color-links.html

Here's a paper on color differences that might help also: http://www.axiphos.com/Reports/ColorDifferences.pdf

Bruce Lindbloom's web site has lots of stuff as well, including a color difference calculator, that works in the CIE color space (which has provision for distance computations).

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
1

ColorMine is open source C# library that has methods for converting between color spaces and comparing via a couple delta-e methods

For example, this will give you a similarity score based on the most common delta-E method (Cie76)

var a = new Rgb { R = 23, G = 117, B = 114 }
var b = new Rgb { R = 113, G = 27, B = 11 }
var deltaE = a.Compare(b,new Cie1976Comparison());
Joe Zack
  • 3,268
  • 2
  • 31
  • 37