views:

152

answers:

3

I want to develop a basic tool like the one featured here. I will be taking screenshots of a number of web pages and from there I wish to take the top five most popular colours and from there somehow decide whether the colours are a good match.

I want to write this tool in C# and after a bit of research I discovered lockbits. My first idea was to take an image and then get the colour of each pixel, but I am unsure as to whether this will give me the results I desire and how to make six lists of the most popular colours.

Can anyone here provide advice as to how I would create a program to do something similar to the program above, that will take in an image and will select the top five colours used in the image?

+2  A: 

The easiest way, as you said is:

  • Read in each pixel and store them in a collection.

  • The top five colours used would be the values that occur the most.

That's how I'd have ago at first trying something like this.

To further this work, you could take in colour ranges, so using RGB values (Red, Green, Blue) assign a colour to a certain approximation of colour.

For example, say that same image was used, the light blue values would get stored together, then an average could be taken of these to give the most common (yet average) light blue in the scene.

Repeat for the other pixels.

As for the scaling - the example website uses dull/bright values. A simple scale value could be used. Consider a medium red in RGB:

0.7, 0.0, 0.0

You could scale this by adding/multiplying a value. Keep the values within the limit of 0 to 1 however. As for what the scaling value should be, experimant. The higher it is, the duller/brighter the colour will become.

Finglas
I should add, that when using bmp images, reading in a single pixel and processing it is fairly straightforward, so throwing together a prototype using some of the suggestions you get in this should be fairly do-able.
Finglas
@Dockers, the platform is C#/.NET. Because of this all common files have a single API, GetPixel/SetPixel with X/Y.
Dykam
+6  A: 

Well.. Use a thumbnail image (16x16, 32x32 etc) and select from it the colors like

updated code:

    private void button1_Click(object sender, EventArgs e)
    {
        int thumbSize = 32;
        Dictionary<Color, int> colors = new Dictionary<Color, int>();

        Bitmap thumbBmp = 
            new Bitmap(pictureBox1.BackgroundImage.GetThumbnailImage(
                thumbSize, thumbSize, ThumbnailCallback, IntPtr.Zero));

        //just for test
        pictureBox2.Image = thumbBmp;            

        for (int i = 0; i < thumbSize; i++)
        {
            for (int j = 0; j < thumbSize; j++)
            {
                Color col = thumbBmp.GetPixel(i, j);
                if (colors.ContainsKey(col))
                    colors[col]++;
                else
                    colors.Add(col, 1);
            }                
        }

        List<KeyValuePair<Color, int>> keyValueList = 
            new List<KeyValuePair<Color, int>>(colors);

        keyValueList.Sort(
            delegate(KeyValuePair<Color, int> firstPair,
            KeyValuePair<Color, int> nextPair)
            {
                return nextPair.Value.CompareTo(firstPair.Value);
            });

        string top10Colors = "";
        for (int i = 0; i < 10; i++)
        {
            top10Colors += string.Format("\n {0}. {1} > {2}",
                i, keyValueList[i].Key.ToString(), keyValueList[i].Value);
            flowLayoutPanel1.Controls[i].BackColor = keyValueList[i].Key;
        }
        MessageBox.Show("Top 10 Colors: " + top10Colors);
    }

    public bool ThumbnailCallback() { return false; }

alt text

serhio
I didn't consider using a thumbnail, good stuff.
Finglas
That is genius! I never would have thought of doing that. I can't test the code just yet because my laptop is broke but I'll accept the answer any way. Thank you very much!
EnderMB
+1  A: 

This is an example of how to create a histogram (or a frequency table in another words) where you can take a look on the details on how to go about processing the image.

But my main recommendation is not to use RGB (unless the website you're looking at has mostly plain colors), but use HSB instead. The "H" (hue) component will give you a better indication of the colors used no matter how bright or dark they are.

Padu Merloti
any code samples or links to getting HSB values?
Mark Redman
the framework provides the .GetHue(), .GetSaturation() and .GetBrightness() for any given Color object.There's a very good post around here explaining with details:http://stackoverflow.com/questions/2942/hsl-in-net
Padu Merloti