4

I've been trying to convert this JavaScript code that gets the dominant color from an image, so far with no success. I get errors with the colorCount & color variables. I don't know the suitable & equivalent data types to use for these variables. Here is my code:

public string dominantColor(Bitmap img)
{
       int[] colorCount = new int[0];
       int maxCount = 0;
       string dominantColor = "";

       // data is an array of a series of 4 one-byte values representing the rgba values of each pixel
       Bitmap Bmp = new Bitmap(img);

       BitmapData BmpData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadOnly, Bmp.PixelFormat);
       byte[] data = new byte[BmpData.Stride * Bmp.Height];


       for (int i = 0; i < data.Length; i += 4) 
       {
            // ignore transparent pixels
            if (data[i+3] == 0)
                continue;

            string color = data[i] + "." + data[i+1] + "," + data[i+2];
            // ignore white
            if (color == "255,255,255")
               continue;

            if (colorCount[color] != 0)
               colorCount[color] = colorCount[color] + 1;
            else
               colorCount[color] = 0;

            // keep track of the color that appears the most times
            if (colorCount[color] > maxCount)
            {
                 maxCount = colorCount[color];
                 dominantColor = color.ToString;
            }
       }

       string rgb = dominantColor.Split(",");
       return rgb;   
}
5
  • 3
    And what exactly is the problem? Could you explain a bit more? Commented May 13, 2012 at 20:45
  • I get errors with the colorCount & color variables Which error exactly? Commented May 13, 2012 at 20:56
  • @Fuex I get conversion errors from string to int. Basically, I'm not sure if I used the right data type for the color variable, I've tried different data types, but I still get the conversion errors. Commented May 13, 2012 at 21:15
  • 1. colorCount has no string indexer; 2. colorCount is array of int with 0 length, so colorCount[color] throws error Commented May 13, 2012 at 21:19
  • I think this line: int[] colorCount = new int[0] and this line: string color = data[i] + "." + data[i+1] + "," + data[i+2]; are the source of the errors. Commented May 13, 2012 at 21:29

1 Answer 1

4

I'll give you a complete managed version of your code:

static Color dominantColor(Bitmap img)
{
    Hashtable colorCount = new Hashtable();
    int maxCount = 0;
    Color dominantColor = Color.White;

    for (int i = 0; i < img.Width; i++)
    {
        for (int j = 0; j < img.Height; j++)
        {
            var color = img.GetPixel(i, j);

            if (color.A == 0)
                continue;

            // ignore white
            if (color.Equals(Color.White))
                continue;

            if (colorCount[color] != null)
                colorCount[color] = (int)colorCount[color] + 1;
            else
                colorCount.Add(color, 0);

            // keep track of the color that appears the most times
            if ((int)colorCount[color] > maxCount)
            {
                maxCount = (int)colorCount[color];
                dominantColor = color;
            }
        }
    }

    return dominantColor;
}

So what is the difference here? - I use a Hashtable instead of your array (you never redefine the dimension of it - and the best way to use an extensible object from JavaScript is a Hashtable) - I prefer to use the already included structure Color (which saves 4 bytes for Alpha, Red, Green, Blue) - I also do the comparisons and return this structure (then you are free to do whatever you want to do - in JavaScript using those strings is just a workaround because the browser is just giving you such RGB(a) strings)

What is another problem in your code is the line containing byte[] data = new byte[BmpData.Stride * Bmp.Height]; - Your array is created and initialized but with no data (.NET will erase all previous data resulting in a lot of zeros). Therefore you will not anywhere.

Drawback of my version is that it is indeed very small (this is where your lockbits are coming into play). I can give you a non-managed version (using the lockbits and an unsafe-block) if you want to. Depends if performance matters a lot for you and if you are interested!

Sign up to request clarification or add additional context in comments.

5 Comments

this: colorCount.Add(color, 0); have to be: colorCount.Add(color, 1);
Yes, this is true but it doesn't matter where you start since colors which are never found wont be in the hashtable and every color has to start at the same number (which is 0 in this case).
as you write, it doesn't metter, because, whats biggest in 0 base will be biggest in 1 base too, it just scratch my eyes... but as I watch the original code, it will always return 0, dont?
the original one or my version? The original one will always return zero because the array wasn't assigned correctly (he is just going through an empty array resulting in no counts at all - so yeah).
yes I write about the original one... even the array will be defined correctly, != 0 will be never true, so every item will be 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.