Example #1
0
        /*  Built-in test program which displays the x, y, and Z and RGB
         *  values for black body spectra from 1000 to 10000 degrees kelvin.
         *  When run, this program should produce the following output:
         *
         *  Temperature       x      y      z       R     G     B
         *  -----------    ------ ------ ------   ----- ----- -----
         *     1000 K      0.6528 0.3444 0.0028   1.000 0.007 0.000 (Approximation)
         *     1500 K      0.5857 0.3931 0.0212   1.000 0.126 0.000 (Approximation)
         *     2000 K      0.5267 0.4133 0.0600   1.000 0.234 0.010
         *     2500 K      0.4770 0.4137 0.1093   1.000 0.349 0.067
         *     3000 K      0.4369 0.4041 0.1590   1.000 0.454 0.151
         *     3500 K      0.4053 0.3907 0.2040   1.000 0.549 0.254
         *     4000 K      0.3805 0.3768 0.2428   1.000 0.635 0.370
         *     4500 K      0.3608 0.3636 0.2756   1.000 0.710 0.493
         *     5000 K      0.3451 0.3516 0.3032   1.000 0.778 0.620
         *     5500 K      0.3325 0.3411 0.3265   1.000 0.837 0.746
         *     6000 K      0.3221 0.3318 0.3461   1.000 0.890 0.869
         *     6500 K      0.3135 0.3237 0.3628   1.000 0.937 0.988
         *     7000 K      0.3064 0.3166 0.3770   0.907 0.888 1.000
         *     7500 K      0.3004 0.3103 0.3893   0.827 0.839 1.000
         *     8000 K      0.2952 0.3048 0.4000   0.762 0.800 1.000
         *     8500 K      0.2908 0.3000 0.4093   0.711 0.766 1.000
         *     9000 K      0.2869 0.2956 0.4174   0.668 0.738 1.000
         *     9500 K      0.2836 0.2918 0.4246   0.632 0.714 1.000
         *    10000 K      0.2807 0.2884 0.4310   0.602 0.693 1.000
         */

        int DoJob()
        {
            double       t, x = 0, y = 0, z = 0, r = 0, g = 0, b = 0;
            colourSystem cs = colourSystem.SMPTEsystem;

            Console.WriteLine("Temperature       x      y      z       R     G     B\n");
            Console.WriteLine("-----------    ------ ------ ------   ----- ----- -----\n");

            for (t = 1000; t <= 10000; t += 500)
            {
                bbTemp = t;
                spectrum_to_xyz(bb_spectrum, ref x, ref y, ref z);
                xyz_to_rgb(cs, x, y, z, ref r, ref g, ref b);
                Console.WriteLine("  {0,5:0} K      %.4f %.4f %.4f   ", t, x, y, z);
                if (constrain_rgb(ref r, ref g, ref b))
                {
                    norm_rgb(ref r, ref g, ref b);
                    Console.WriteLine("%.3f %.3f %.3f (Approximation)\n", r, g, b);
                }
                else
                {
                    norm_rgb(ref r, ref g, ref b);
                    Console.WriteLine("%.3f %.3f %.3f\n", r, g, b);
                }
            }
            return(0);
        }
Example #2
0
        /*                          GAMMA_CORRECT_RGB
         *
         *  Transform linear RGB values to nonlinear RGB values. Rec.
         *  709 is ITU-R Recommendation BT. 709 (1990) ``Basic
         *  Parameter Values for the HDTV Standard for the Studio and
         *  for International Programme Exchange'', formerly CCIR Rec.
         *  709. For details see
         *
         *     http://www.poynton.com/ColorFAQ.html
         *     http://www.poynton.com/GammaFAQ.html
         */

        void gamma_correct(colourSystem cs, ref double c)
        {
            double gamma;

            gamma = cs.gamma;

            if (gamma == GAMMA_REC709)
            {
                /* Rec. 709 gamma correction. */
                double cc = 0.018;

                if (c < cc)
                {
                    c *= ((1.099 * Math.Pow(cc, 0.45)) - 0.099) / cc;
                }
                else
                {
                    c = (1.099 * Math.Pow(c, 0.45)) - 0.099;
                }
            }
            else
            {
                /* Nonlinear colour = (Linear colour)^(1/gamma) */
                c = Math.Pow(c, 1.0 / gamma);
            }
        }
Example #3
0
        /*                             XYZ_TO_RGB
         *
         *  Given an additive tricolour system CS, defined by the CIE x
         *  and y chromaticities of its three primaries (z is derived
         *  trivially as 1-(x+y)), and a desired chromaticity (XC, YC,
         *  ZC) in CIE space, determine the contribution of each
         *  primary in a linear combination which sums to the desired
         *  chromaticity.  If the  requested chromaticity falls outside
         *  the Maxwell  triangle (colour gamut) formed by the three
         *  primaries, one of the r, g, or b weights will be negative.
         *
         *  Caller can use constrain_rgb() to desaturate an
         *  outside-gamut colour to the closest representation within
         *  the available gamut and/or norm_rgb to normalise the RGB
         *  components so the largest nonzero component has value 1.
         *
         */

        void xyz_to_rgb(colourSystem cs,
                        double xc, double yc, double zc,
                        ref double r, ref double g, ref double b)
        {
            double xr, yr, zr, xg, yg, zg, xb, yb, zb;
            double xw, yw, zw;
            double rx, ry, rz, gx, gy, gz, bx, by, bz;
            double rw, gw, bw;

            xr = cs.xRed; yr = cs.yRed; zr = 1 - (xr + yr);
            xg = cs.xGreen; yg = cs.yGreen; zg = 1 - (xg + yg);
            xb = cs.xBlue; yb = cs.yBlue; zb = 1 - (xb + yb);

            xw = cs.xWhite; yw = cs.yWhite; zw = 1 - (xw + yw);

            /* xyz -> rgb matrix, before scaling to white. */

            rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg);
            gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb);
            bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr);

            /* White scaling factors.
             * Dividing by yw scales the white luminance to unity, as conventional. */

            rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw;
            gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw;
            bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw;

            /* xyz -> rgb matrix, correctly scaled to white. */

            rx = rx / rw; ry = ry / rw; rz = rz / rw;
            gx = gx / gw; gy = gy / gw; gz = gz / gw;
            bx = bx / bw; by = by / bw; bz = bz / bw;

            /* rgb of the desired point */

            r = (rx * xc) + (ry * yc) + (rz * zc);
            g = (gx * xc) + (gy * yc) + (gz * zc);
            b = (bx * xc) + (by * yc) + (bz * zc);
        }
Example #4
0
 void gamma_correct_rgb(colourSystem cs, ref double r, ref double g, ref double b)
 {
     gamma_correct(cs, ref r);
     gamma_correct(cs, ref g);
     gamma_correct(cs, ref b);
 }