Click here to Skip to main content
12,823,312 members (46,745 online)
Click here to Skip to main content
Add your own
alternative version


32 bookmarked
Posted 17 Sep 2008

Generating a Website Color Scheme from an Image

, 17 Sep 2008 CPOL
How can a color scheme be extracted from an image? The problem with determining a color scheme is that there are too many colors in the image, yet the algorithm to convert the image must find a set of colors that most accurately represents the original. Atalasoft provides the code right here.

Editorial Note

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.


The next time you’re trying to put together a color scheme for a web site, take a look at your digital photos. If you find one you like, it’s simple to find the most common colors in the image using DotImage and a little code.

The algorithm for finding the most common colors in a photo is simple, and I’ll go through the steps and show you the code.

Step 1: Convert the Image to Use an 8-bit Palette

Digital photos from your camera are stored as 24-bit color. This means that each pixel uses 24 bits to represent a color: 8 bits each for red, green and blue. The problem with trying to find a color scheme is that there are way too many colors in the image. The algorithm to convert it to an 8-bit palette must find a set of 256 colors that most accurately represents the original. This means that colors will be clustered based on how similar they are to each other. Luckily, you don’t need to know this algorithm, because here’s the code using DotImage:

private AtalaImage ConvertTo8BitPaletteImage(AtalaImage image)
    AtalaImage img8bpp = image;
    if (image.PixelFormat != PixelFormat.Pixel8bppIndexed)
        img8bpp = image.GetChangedPixelFormat(PixelFormat.Pixel8bppIndexed);
    return img8bpp;

Step 2: Count Up How Many Pixels of Each Color You Have

Now that we’ve narrowed it down to just the 256 most common colors, we can now see how many pixels of each color we have. This frequency count is called a histogram, and it’s also simple to create:

private int[] GetColorFrequency(AtalaImage img)
    Histogram h = new Histogram(img);
    return h.GetChannelHistogram(0);

In a 24-bit color image, a channel represents each of the constituent colors (red, green and blue). However, in an 8-bit palette image, there is only one channel, and the number stored in it is the index into the palette. The int[] that is returned by this function is a 256-element array where each element at an index represents the number of pixels with the color associated with that index in the palette. For example, if the 0th element of the Palette is white, then the 0th element of the channel histogram is the number of white pixels.

Step 3: Sort the Colors in the Palette by Frequency

This is mostly handled by .NET’s Array.Sort(). We just need a Color array with the colors and an array of integers that represents the sort order. The frequency array we created in step two is the sort order we want, so we just need to make an array of colors from the palette. Here’s the code:

private Color[] SortColorsByFrequency(AtalaImage image, int[] colorFrequency)
    // make an array of Color object from the entries
    // in the palette
    Palette p = image.Palette; 
    Color[] colors = new Color[p.Colors];
    for (int i = 0; i < p.Colors; ++i)
        colors[i] = p.GetEntry(i);

    // sort the array of colors based on frequency
    Array.Sort(colorFrequency, colors);

    return colors;

Step 4: Define a Distance Functions for Colors

Even this array of colors will have many colors that are near each other. To get a list of colors that are different enough, we need functions that can tell us if two colors are different (based on a tolerance) and if a color is not within tolerance of a list of colors. Here’s the code:

private bool WithinTolerance(Color c1, Color c2, double tolerance)
    double maxDistance = 255 * 255 * 3;
    int toleranceDistance = (int)(tolerance * maxDistance);

    int distance = (int)Math.Pow((double)(c1.R - c2.R), 2);
    distance += (int)Math.Pow((double)(c1.G - c2.G), 2);
    distance += (int)Math.Pow((double)(c1.B - c2.B), 2);

    return (bool)(distance <= toleranceDistance);

The function, WithinTolerance, takes two colors and a tolerance. The tolerance is a real number from 0 (meaning it has to be an exact match) to 1.0, which means 100% tolerance and all colors match each other. By experimenting, I saw that .01 (or 1%) was a good value to use. I defined the difference between two colors as the sum of the squares of the differences in red, green and blue.

Here’s a function that returns true if color is not within tolerance of any color in a list.

private bool ColorIsDifferent(Color color, List<Color> colorList)
    foreach (Color c in colorList)
        if (WithinTolerance(c, color, .01)) {
            return false;
    return true;
Color Scheme

Step 5: Loop through All of Our Colors and Pick Out the Top Ones

private List<Color> GetTopUniqueColors(Color[] colors, int maxColors)
    List<Color> uniqueColors = new List<Color>();

    for (int i = 0; i < colors.Length && uniqueColors.Count < maxColors; ++i)
        // read the colors from the end of the array
        // since they are sorted in increasing order of frequency
        Color color = colors[colors.Length - 1 - i];
        if (ColorIsDifferent(color, uniqueColors))

    return uniqueColors;

The return value of this function is the list of the top colors in the image.

I have put together a web site that uses this algorithm to generate a color scheme from an image you can upload. You can reach it here:

The full code for the website is available there as well.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Lou Franco
Atalasoft, Inc.
United States United States
Lou Franco is the Director of Engineering at Atalasoft, provider of the leading .NET Imaging SDK (DotImage) and the Document Viewer for SharePoint (Vizit).

You may also be interested in...

Comments and Discussions

QuestionDownload files Pin
Rekhash20-Mar-13 2:43
memberRekhash20-Mar-13 2:43 
Generallink download Pin
ClaudioMichelizza22-Feb-11 1:53
memberClaudioMichelizza22-Feb-11 1:53 
GeneralHi Pin
Nitin Sawant20-Oct-08 4:12
memberNitin Sawant20-Oct-08 4:12 
GeneralGood article Pin
dotnetgreen24-Sep-08 3:52
memberdotnetgreen24-Sep-08 3:52 
GeneralRe: Good article Pin
Lou Franco24-Sep-08 4:22
memberLou Franco24-Sep-08 4:22 
GeneralNice, but I suggest Octree Quantization Pin
Dan C.17-Sep-08 10:09
memberDan C.17-Sep-08 10:09 
I was trying to come up with a solution to this problem a few months ago and came up with a slightly different idea.

Instead of using existing libraries to reduce the color space and then further processing the result, I decided to use a more direct (and possibly more accurate) technique and just use Octree Quantization directly. You could then quantize to any desired number of colors.

I used this code as the starting point for my implementation (not sure about any rights to reproduce) :[^]

Of course, there are several web sites out there that already do this; but it's nice to roll your own out, especially if you want to add more features, such as making sure that the colors that are picked fit in some desired pattern (i.e. complementary, monochromatic, triad, compound, etc) and/or include some fixed colors that you want to use.
GeneralRe: Nice, but I suggest Octree Quantization Pin
Lou Franco17-Sep-08 10:19
memberLou Franco17-Sep-08 10:19 
GeneralRe: Nice, but I suggest Octree Quantization Pin
Dan C.23-Sep-08 7:23
memberDan C.23-Sep-08 7:23 
GeneralVery Cool Pin
merlin98117-Sep-08 8:44
membermerlin98117-Sep-08 8:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170308.1 | Last Updated 17 Sep 2008
Article Copyright 2008 by Lou Franco
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid