Determine image overall lightness

Solved by me:

    public static double CalculateAverageLightness(Bitmap bm)
    {
        double lum = 0;
        var tmpBmp = new Bitmap(bm);
        var width = bm.Width;
        var height = bm.Height;
        var bppModifier = bm.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4;

        var srcData = tmpBmp.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadOnly, bm.PixelFormat);
        var stride = srcData.Stride;
        var scan0 = srcData.Scan0;

        //Luminance (standard, objective): (0.2126*R) + (0.7152*G) + (0.0722*B)
        //Luminance (perceived option 1): (0.299*R + 0.587*G + 0.114*B)
        //Luminance (perceived option 2, slower to calculate): sqrt( 0.299*R^2 + 0.587*G^2 + 0.114*B^2 )

        unsafe
        {
            byte* p = (byte*)(void*)scan0;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int idx = (y * stride) + x * bppModifier;
                    lum += (0.299*p[idx + 2] + 0.587*p[idx + 1] + 0.114*p[idx]);
                }
            }
        }

        tmpBmp.UnlockBits(srcData);
        tmpBmp.Dispose();
        var avgLum = lum / (width * height);


        return avgLum/255.0;
    }

I think all you can do is measure every pixel in the image and take an average. If thats too slow for your purposes then I would suggest taking an evenly distributed sample of pixels and using that to calculate an average. You could also limit the pixels to the area where you need to draw the text.

You can load the image as a Bitmap (http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.aspx) and use the GetPixel method to actually get the colour values.

How you assess the brightness is entirely up to you. I would suggest a simpler approach (say just taking the highest colour value) may actually be better as some users will perceive colour differently to the human norm (colour-blindness etc).

Tags:

C#

.Net

Imaging