Emmanuel
Emmanuel

Reputation: 162

Converting a simple JavaScript code

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;   
}

Upvotes: 4

Views: 179

Answers (1)

Florian Rappl
Florian Rappl

Reputation: 3189

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!

Upvotes: 4

Related Questions