CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3

Thread: Lum from RGB?

  1. #1
    Guest

    Lum from RGB?

    Does anyone know if there's a formula for calculating a color's luminosity from its RGB values?


  2. #2

    Re: Lum from RGB?

    Try this:

    /////////////////////////////////////////////////////////////////////////////
    // Conversion routines: RGB to HLS (Red-Green-Blue to Hue-Luminosity-Saturation).
    // See Microsoft KnowledgeBase article Q29240.

    #define HLSMAX 240 // H,L, and S vary over 0-HLSMAX
    #define RGBMAX 255 // R,G, and B vary over 0-RGBMAX
    // HLSMAX BEST IF DIVISIBLE BY 6
    // RGBMAX, HLSMAX must each fit in a byte (255).

    #define UNDEFINED (HLSMAX * 2 / 3) // Hue is undefined if Saturation is 0
    // (grey-scale). This value determines
    // where the Hue scrollbar is initially
    // set for achromatic colors.

    // Convert RGB to HLS.
    /* static */ void Generic::RGBtoHLS(COLORREF crRGB, WORD& wH, WORD& wL, WORD& wS)
    {
    // Get R, G, and B out of COLORREF.
    WORD wR(GetRValue(crRGB));
    WORD wG(GetGValue(crRGB));
    WORD wB(GetBValue(crRGB));

    // Calculate "lightness".
    BYTE byMax(static_cast<BYTE> (max(max(wR, wG), wB)));
    BYTE byMin(static_cast<BYTE> (min(min(wR, wG), wB)));

    wL = static_cast<WORD> ((((byMax + byMin) * HLSMAX) + RGBMAX) / (2 * RGBMAX));

    // r=g=b --> achromatic case.
    if (byMax == byMin) {
    wS = 0;
    wH = UNDEFINED;
    }
    else {
    // Chromatic case.

    // Saturation.
    if (wL <= (HLSMAX / 2)) {
    wS = static_cast<WORD> ((((byMax - byMin) * HLSMAX) + ((byMax+byMin) / 2)) / (byMax + byMin));
    }
    else {
    wS = static_cast<WORD> ((((byMax - byMin) * HLSMAX) + ((2 * RGBMAX - byMax - byMin) / 2)) / (2 * RGBMAX - byMax - byMin));
    }

    // Hue.
    WORD wRdelta(static_cast<WORD> ((((byMax - wR) * (HLSMAX / 6)) + ((byMax - byMin) / 2)) / (byMax - byMin)));
    WORD wGdelta(static_cast<WORD> ((((byMax - wG) * (HLSMAX / 6)) + ((byMax - byMin) / 2)) / (byMax - byMin)));
    WORD wBdelta(static_cast<WORD> ((((byMax - wB) * (HLSMAX / 6)) + ((byMax - byMin) / 2)) / (byMax - byMin)));

    if (wR == byMax) {
    wH = static_cast<WORD> (wBdelta - wGdelta);
    }
    else if (wG == byMax) {
    wH = static_cast<WORD> ((HLSMAX / 3) + wRdelta - wBdelta);
    }
    else {
    // B == byMax
    wH = static_cast<WORD> (((2 * HLSMAX) / 3) + wGdelta - wRdelta);
    }

    if (wH < 0) {
    wH += HLSMAX;
    }

    if (wH > HLSMAX) {
    wH -= HLSMAX;
    }
    }
    }

    // Convert HLS to RGB.
    /* static */ COLORREF Generic::HLStoRGB(WORD wH, WORD wL, WORD wS)
    {
    WORD wR(0);
    WORD wG(0);
    WORD wB(0);

    // Achromatic case.
    if (0 == wS) {
    wR = static_cast<WORD> ((wL * RGBMAX) / HLSMAX);
    wG = static_cast<WORD> ((wL * RGBMAX) / HLSMAX);
    wB = static_cast<WORD> ((wL * RGBMAX) / HLSMAX);

    if (UNDEFINED != wH) {
    _ASSERTE(! "ERROR");
    }
    }
    else {
    // Chromatic case.
    WORD Magic1(0);
    WORD Magic2(0);

    // Set up magic numbers.
    if (wL <= HLSMAX / 2) {
    Magic2 = static_cast<WORD> ((wL * (HLSMAX + wS) + (HLSMAX / 2)) / HLSMAX);
    }
    else {
    Magic2 = static_cast<WORD> (wL + wS - ((wL * wS) + (HLSMAX / 2)) / HLSMAX);
    }

    Magic1 = static_cast<WORD> (2 * wL - Magic2);

    // Get RGB, change units from HLSMAX to RGBMAX.
    wR = static_cast<WORD> ((HueToRGB(Magic1, Magic2, static_cast<WORD> (wH + (HLSMAX / static_cast<WORD> (3)))) * RGBMAX + (HLSMAX / static_cast<WORD> (2))) / HLSMAX);
    wG = static_cast<WORD> ((HueToRGB(Magic1, Magic2, static_cast<WORD> (wH)) * RGBMAX + (HLSMAX / static_cast<WORD> (2))) / HLSMAX);
    wB = static_cast<WORD> ((HueToRGB(Magic1, Magic2, static_cast<WORD> (wH - (HLSMAX / static_cast<WORD> (3)))) * RGBMAX + (HLSMAX / static_cast<WORD> (2))) / HLSMAX);
    }

    return RGB(wR,wG,wB);
    }

    // Utility routine for HLStoRGB.
    /* static */ WORD Generic::HueToRGB(WORD w1, WORD w2, WORD wH)
    {
    // Range check: note values passed add/subtract thirds of range.
    if (wH < 0) {
    wH += HLSMAX;
    }

    if (wH > HLSMAX) {
    wH -= HLSMAX;
    }

    // Return r, g, or b value from this tridrant.
    if (wH < HLSMAX / 6) {
    return static_cast<WORD> (w1 + (((w2 - w1) * wH + (HLSMAX / 12)) / (HLSMAX / 6)));
    }


    if (wH < HLSMAX / 2) {
    return w2;
    }

    if (wH < (HLSMAX * 2) / 3) {
    return static_cast<WORD> (w1 + (((w2 - w1) * (((HLSMAX * 2) / 3) - wH) + (HLSMAX / 12)) / (HLSMAX / 6)));
    }
    else {
    return w1;
    }
    }


    LA Leonard - Definitive Solutions, Inc.

  3. #3
    Guest

    Re: Lum from RGB?

    Thanks; what you supplied was extremely helpful.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured