This project has moved. For the latest updates, please go here.

Quantization & Unique (Dominant) Colors

Aug 18, 2014 at 4:09 PM
I'm trying to reduce the colors of an image to 8 dominant colors, and I have a picture of a rainbow here:


I've got code like this:
var qSettings = new QuantizeSettings { Colors = 8, DitherMethod = DitherMethod.No, ColorSpace = ImageMagick.ColorSpace.RGB};
No matter what combination I try (changing the ColorSpace, modifying TreeDepth, etc.), it will always merge at least two of the bars together. usually red and orange or dark blue and violet.

I was using MagickNet, but I just switched to to see if that would help anything. It didn't. Why does Quantize do that? Do you have any advice or suggestions?
Aug 18, 2014 at 4:58 PM
I have determined that the following IM command produces the same incorrect result:

convert rainbow.png -dither None -colors 8 test2.png

So I don't think the issue is with MagickNet, but I don't know how to get ImageMagic or MagickNet to do what I want. Any help would be appreciated.
Aug 18, 2014 at 5:11 PM
To further this, I've found that Quantize inherently does not pick primary colors. I just wish there was some better way to figure this out. Photoshop can do it easily:

Mode -> Indexed
8 colors
Local Selective Palette
Nothing Forced

That generates a perfect specimen. I just want to do the same thing, but Quantize is ruining it by picking what it thinks is best to represent the image and choosing poorly.
Aug 18, 2014 at 9:20 PM
Edited Aug 18, 2014 at 9:21 PM
If you want to use the most dominant colors you are probably better of using the map method:
// Read source image.
using (MagickImage image = new MagickImage(@"D:\images\png\rainbow.png"))
  // Create collection to store top 8 colors.
  using (MagickImageCollection colors = new MagickImageCollection())
    // Get the histogram of the image (key = color, value = count).
    Dictionary<MagickColor, int> histogram = image.Histogram();

    // Add the 'top 8 colors' to the collection.
    foreach (MagickColor color in (from c in histogram
                                   orderby c.Value descending
                                   select c.Key).Take(8))
      colors.Add(new MagickImage(color, 1, 1));

    QuantizeSettings settings = new QuantizeSettings
      // Due to a bug you have to set it to null instead of DitherMethod.No.
      // This will be fixed in next release.
      DitherMethod = null

    // Create a color map with the 'top 8 colors'.
    using (MagickImage colorMap = colors.AppendHorizontally())
      // Map image to the colors in the color map.
      image.Map(colorMap, settings);

  // Save output
Aug 18, 2014 at 10:28 PM
Well, that works great for the rainbow, but fails for all my other "normal" cases, like a room scene or a grassy hill, where it just returns all browns or greens and nothing else. My ultimate goal is to be able to pull the perceived dominant colors like here:
Aug 19, 2014 at 11:20 AM
Maybe you should ask your question here: They might have some better ideas. I will help you translate it once we get the 'correct' command line arguments.