colorsrangergbcielab

What are the ranges of coordinates in the CIELAB color space?


I have the following piece of code:

public List<Tuple<double, double, double>> GetNormalizedPixels(Bitmap image)
{
    System.Drawing.Imaging.BitmapData data = image.LockBits(
        new Rectangle(0, 0, image.Width, image.Height),
        System.Drawing.Imaging.ImageLockMode.ReadOnly,
        image.PixelFormat);

    int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8;

    var result = new List<Tuple<double, double, double>>();

    unsafe
    {
        for (int y = 0; y < data.Height; ++y)
        {
            byte* row = (byte*)data.Scan0 + (y * data.Stride);

            for (int x = 0; x < data.Width; ++x)
            {
                Color c = Color.FromArgb(
                    row[x * pixelSize + 3],
                    row[x * pixelSize + 2],
                    row[x * pixelSize + 1],
                    row[x * pixelSize]);

                // (*)
                result.Add(Tuple.Create(
                    1.0 * c.R / 255,
                    1.0 * c.G / 255,
                    1.0 * c.B / 255);
            }
        }
    }

    image.UnlockBits(data);

    return result;
}

The key fragment (*) is this:

result.Add(Tuple.Create(
    1.0 * c.R / 255,
    1.0 * c.G / 255,
    1.0 * c.B / 255);

which adds a pixel with its components scaled to range [0, 1] to be further used in classification tasks with different classifiers. Some of them require the attributes to be normalized like this, others don't care - hence this function.

However, what should I do when I'd like to classify pixels in a different colour space than RGB, like L*a*b*? While values of all coordinates in RGB colour space fall into range [0,256) in L*a*b* colour space a* and b* are said to be unbounded.

So when changing the fragment (*) to:

Lab lab = c.ToLab();

result.Add(Tuple.Create(
    1.0 * lab.L / 100,
    1.0 * lab.A / ?,
    1.0 * lab.B / ?);

(ToLab is an extension method, implemented using appropriate algorithms from here)

what should I put for the question marks?


Solution

  • In practice the number of all possible RGB colours is finite, so the L*a*b* space is bounded. It is easy to find the ranges of coordinates with the following simple program:

    Color c;
    
    double maxL = double.MinValue;
    double maxA = double.MinValue;
    double maxB = double.MinValue;
    double minL = double.MaxValue;
    double minA = double.MaxValue;
    double minB = double.MaxValue;
    
    for (int r = 0; r < 256; ++r)
        for (int g = 0; g < 256; ++g)
            for (int b = 0; b < 256; ++b)
            {
                c = Color.FromArgb(r, g, b);
    
                Lab lab = c.ToLab();
    
                maxL = Math.Max(maxL, lab.L);
                maxA = Math.Max(maxA, lab.A);
                maxB = Math.Max(maxB, lab.B);
                minL = Math.Min(minL, lab.L);
                minA = Math.Min(minA, lab.A);
                minB = Math.Min(minB, lab.B);
            }
    
    Console.WriteLine("maxL = " + maxL + ", maxA = " + maxA + ", maxB = " + maxB);
    Console.WriteLine("minL = " + minL + ", minA = " + minA + ", minB = " + minB);
    

    or a similar one using any other language.

    So, CIELAB space coordinate ranges are as follows:

    L in [0, 100]

    A in [-86.185, 98.254]

    B in [-107.863, 94.482]

    and the answer is:

    Lab lab = c.ToLab();
    
    result.Add(Tuple.Create(
        1.0 * lab.L / 100,
        1.0 * (lab.A + 86.185) / 184.439,
        1.0 * (lab.B + 107.863) / 202.345);