Example #1
0
        public static I <float> HsvToRgb(this I <float> image)
        {
            if (image.Channels != 3 || (image.Format.PixelChannels != PixelChannels.Unknown && image.Format.PixelChannels != PixelChannels.Hsv))
            {
                throw new ArgumentException("HSV input image required");
            }

            if (image.Format.ColorSpace != ColorSpace.Hsv && image.Format.ColorSpace != ColorSpace.Unknown)
            {
                throw new Exception("Wrong color-space of input image. Hsv expected.");
            }

            var            r = CreateRgbF32(image.Height, image.Width);
            Range <double> r0 = r.Format.ChannelRanges[0], r1 = r.Format.ChannelRanges[1], r2 = r.Format.ChannelRanges[2];

            int h = 0;
            var f = 0.0;
            var p = 0.0;
            var q = 0.0;
            var t = 0.0;

            for (int y = 0; y < r.Height; ++y)
            {
                for (int x = 0; x < r.Width; ++x)
                {
                    // Calculation of auxiliary variables h, f, p, q and t
                    h = (int)(image[y, x, 0] / 60.0);
                    f = image[y, x, 0] / 60.0 - h;
                    p = image[y, x, 2] * (1 - image[y, x, 1]);
                    q = image[y, x, 2] * (1 - image[y, x, 1] * f);
                    t = image[y, x, 2] * (1 - image[y, x, 1] * (1 - f));
                    // Calculation of color channel 0 (R), 1 (G) and 2 (B)
                    if (h == 0 || h == 6)
                    {
                        r[y, x, 0] = (float)r0.Clamp(image[y, x, 2]);
                        r[y, x, 1] = (float)r1.Clamp(t);
                        r[y, x, 2] = (float)r2.Clamp(p);
                    }
                    else if (h == 1)
                    {
                        r[y, x, 0] = (float)r0.Clamp(q);
                        r[y, x, 1] = (float)r1.Clamp(image[y, x, 2]);
                        r[y, x, 2] = (float)r2.Clamp(p);
                    }
                    else if (h == 2)
                    {
                        r[y, x, 0] = (float)r0.Clamp(p);
                        r[y, x, 1] = (float)r1.Clamp(image[y, x, 2]);
                        r[y, x, 2] = (float)r2.Clamp(t);
                    }
                    else if (h == 3)
                    {
                        r[y, x, 0] = (float)r0.Clamp(p);
                        r[y, x, 1] = (float)r1.Clamp(q);
                        r[y, x, 2] = (float)r2.Clamp(image[y, x, 2]);
                    }
                    else if (h == 4)
                    {
                        r[y, x, 0] = (float)r0.Clamp(t);
                        r[y, x, 1] = (float)r1.Clamp(p);
                        r[y, x, 2] = (float)r2.Clamp(image[y, x, 2]);
                    }
                    else if (h == 5)
                    {
                        r[y, x, 0] = (float)r0.Clamp(image[y, x, 2]);
                        r[y, x, 1] = (float)r1.Clamp(p);
                        r[y, x, 2] = (float)r2.Clamp(q);
                    }
                }
            }
            return(r);
        }
Example #2
0
        public static I <float> RgbToHsv(this I <float> image)
        {
            if (image.Channels != 3 || (image.Format.PixelChannels != PixelChannels.Unknown && image.Format.PixelChannels != PixelChannels.Rgb))
            {
                throw new ArgumentException("RGB input image required");
            }

            if (image.Format.ColorSpace != ColorSpace.Srgb && image.Format.ColorSpace != ColorSpace.Unknown)
            {
                throw new Exception("Wrong color-space of input image. SRgb expected.");
            }

            var            r = CreateHsvF32(image.Height, image.Width);
            Range <double> r0 = r.Format.ChannelRanges[0], r1 = r.Format.ChannelRanges[1], r2 = r.Format.ChannelRanges[2];

            var max  = 0.0;
            var min  = 0.0;
            var diff = 0.0;

            for (int y = 0; y < r.Height; ++y)
            {
                for (int x = 0; x < r.Width; ++x)
                {
                    // Calculation of max(R,G,B), min(R,G,B) and max(R,G,B) - min(R,G,B)
                    max  = Math.Max(Math.Max(image[y, x, 0], image[y, x, 1]), image[y, x, 2]);
                    min  = Math.Min(Math.Min(image[y, x, 0], image[y, x, 1]), image[y, x, 2]);
                    diff = max - min;
                    // Calculation of color channel 0 (H)
                    if (max == min)
                    {
                        r[y, x, 0] = 0;
                    }
                    else if (max == image[y, x, 0])
                    {
                        r[y, x, 0] = (float)(60.0 * (image[y, x, 1] - image[y, x, 2]) / diff);
                    }
                    else if (max == image[y, x, 1])
                    {
                        r[y, x, 0] = (float)(60.0 * (2.0 + (image[y, x, 2] - image[y, x, 0]) / diff));
                    }
                    else if (max == image[y, x, 2])
                    {
                        r[y, x, 0] = (float)(60.0 * (4.0 + (image[y, x, 0] - image[y, x, 1]) / diff));
                    }
                    if (r[y, x, 0] < 0)
                    {
                        r[y, x, 0] = r[y, x, 0] + 360;
                    }
                    r[y, x, 0] = (float)r0.Clamp(r[y, x, 0]);
                    // Calculation of color channel 1 (S)
                    if (max == 0)
                    {
                        r[y, x, 1] = 0;
                    }
                    else
                    {
                        r[y, x, 1] = (float)r1.Clamp(diff / max);
                    }
                    // Calculation of color channel 2 (V)
                    r[y, x, 2] = (float)r2.Clamp(max);
                }
            }
            return(r);
        }
Example #3
0
        public static I <float> LuvToXyz(this I <float> image)
        {
            if (image.Channels != 3 || (image.Format.PixelChannels != PixelChannels.Unknown && image.Format.PixelChannels != PixelChannels.Luv))
            {
                throw new ArgumentException("LUV input image required");
            }

            if (image.Format.ColorSpace != ColorSpace.Luv && image.Format.ColorSpace != ColorSpace.Unknown)
            {
                throw new Exception("Wrong color-space of input image. Luv expected.");
            }

            var            r = CreateXyzF32(image.Height, image.Width);
            Range <double> r0 = r.Format.ChannelRanges[0], r1 = r.Format.ChannelRanges[1], r2 = r.Format.ChannelRanges[2];

            var Yn = 1.0;
            var Un = 0.1977;
            var Vn = 0.4683;
            var s  = 0.0;
            var t  = 0.0;

            for (int y = 0; y < r.Height; ++y)
            {
                for (int x = 0; x < r.Width; ++x)
                {
                    // Calculation of color channel 1 (Y) via old channel 0 (L)
                    if (image[y, x, 0] > 8.0)
                    {
                        r[y, x, 1] = (float)(r1.Clamp(Yn * Math.Pow(((image[y, x, 0] + 16.0) / 116.0), 3.0)));
                    }
                    else
                    {
                        r[y, x, 1] = (float)(r1.Clamp(Yn * image[y, x, 0] * Math.Pow((3.0 / 29.0), 3.0)));
                    }
                    // Calculation of auxiliary variables s and t via old channels 0 (L), 1 (u) and 2 (v)
                    s = image[y, x, 1] / (13.0 * image[y, x, 0]) + Un;
                    t = image[y, x, 2] / (13.0 * image[y, x, 0]) + Vn;
                    // Calculation of color channel 0 (X) via new channel 1 (Y) and auxiliary variables s and t
                    r[y, x, 0] = (float)(r0.Clamp(r[y, x, 1] * ((9.0 * s) / (4.0 * t))));
                    // Calculation of color channel 2 (Z) via new channel 1 (Y) and auxiliary variables s and t
                    r[y, x, 2] = (float)(r2.Clamp(r[y, x, 1] * ((12.0 - 3.0 * s - 20.0 * t) / (4.0 * t))));
                }
            }
            return(r);
        }
Example #4
0
        public static I <float> XyzToLuv(this I <float> image)
        {
            if (image.Channels != 3 || (image.Format.PixelChannels != PixelChannels.Unknown && image.Format.PixelChannels != PixelChannels.Xyz))
            {
                throw new ArgumentException("XYZ input image required");
            }

            if (image.Format.ColorSpace != ColorSpace.Xyz && image.Format.ColorSpace != ColorSpace.Unknown)
            {
                throw new Exception("Wrong color-space of input image. Xyz expected.");
            }

            var            r = CreateLuvF32(image.Height, image.Width);
            Range <double> r0 = r.Format.ChannelRanges[0], r1 = r.Format.ChannelRanges[1], r2 = r.Format.ChannelRanges[2];

            var Yn          = 1.0;
            var Un          = 0.1977;
            var Vn          = 0.4683;
            var denominator = 0.0;
            var s           = 0.0;
            var t           = 0.0;

            for (int y = 0; y < r.Height; ++y)
            {
                for (int x = 0; x < r.Width; ++x)
                {
                    // Calculation of color channel 0 (L) via old channel 1 (Y)
                    if ((image[y, x, 1] / Yn) > Math.Pow((6.0 / 29.0), 3.0))
                    {
                        r[y, x, 0] = (float)(r0.Clamp(116.0 * Math.Pow((image[y, x, 1] / Yn), (1.0 / 3.0)) - 16.0));
                    }
                    else
                    {
                        r[y, x, 0] = (float)(r0.Clamp(Math.Pow((29.0 / 3.0), 3.0) * (image[y, x, 1] / Yn)));
                    }
                    // Calculation of auxiliary variables s and t via old channels 0 (X), 1 (Y) and 2 (Z)
                    denominator = image[y, x, 0] + 15.0 * image[y, x, 1] + 3.0 * image[y, x, 2];
                    s           = (4.0 * image[y, x, 0]) / denominator;
                    t           = (9.0 * image[y, x, 1]) / denominator;
                    // Calculation of color channel 1 (u) via new channel 0 (L) and auxiliary variable s
                    r[y, x, 1] = (float)(r1.Clamp(13.0 * r[y, x, 0] * (s - Un)));
                    // Calculation of color channel 2 (v) via new channel 0 (L) and auxiliary variable t
                    r[y, x, 2] = (float)(r2.Clamp(13.0 * r[y, x, 0] * (t - Vn)));
                }
            }
            return(r);
        }
Example #5
0
        public static I <float> LabToXyz(this I <float> image)
        {
            if (image.Channels != 3 || (image.Format.PixelChannels != PixelChannels.Unknown && image.Format.PixelChannels != PixelChannels.Lab))
            {
                throw new ArgumentException("LAB input image required");
            }

            if (image.Format.ColorSpace != ColorSpace.Lab && image.Format.ColorSpace != ColorSpace.Unknown)
            {
                throw new Exception("Wrong color-space of input image. Lab expected.");
            }

            var            r = CreateXyzF32(image.Height, image.Width);
            Range <double> r0 = r.Format.ChannelRanges[0], r1 = r.Format.ChannelRanges[1], r2 = r.Format.ChannelRanges[2];

            var Xn = 0.95;
            var Yn = 1.0;
            var Zn = 1.09;

            for (int y = 0; y < r.Height; ++y)
            {
                for (int x = 0; x < r.Width; ++x)
                {
                    var gyyn = (1.0 / 116.0) * (image[y, x, 0] + 16.0);
                    // Calculation of color channel 1 (Y) via old channel 0 (L)
                    r[y, x, 1] = (float)(r1.Clamp(Yn * LabToXyzFunc(gyyn)));
                    // Calculation of color channel 0 (X) via old channels 0 (L) and 1 (a)
                    r[y, x, 0] = (float)(r0.Clamp(Xn * LabToXyzFunc(gyyn + image[y, x, 1] / 500.0)));
                    // Calculation of color channel 2 (Z) via old channels 0 (L) and 2 (b)
                    r[y, x, 2] = (float)(r2.Clamp(Zn * LabToXyzFunc(gyyn - image[y, x, 2] / 200.0)));
                }
            }
            return(r);
        }
Example #6
0
        public static I <float> XyzToLab(this I <float> image)
        {
            if (image.Channels != 3 || (image.Format.PixelChannels != PixelChannels.Unknown && image.Format.PixelChannels != PixelChannels.Xyz))
            {
                throw new ArgumentException("XYZ input image required");
            }

            if (image.Format.ColorSpace != ColorSpace.Xyz && image.Format.ColorSpace != ColorSpace.Unknown)
            {
                throw new Exception("Wrong color-space of input image. Xyz expected.");
            }

            var            r = CreateLabF32(image.Height, image.Width);
            Range <double> r0 = r.Format.ChannelRanges[0], r1 = r.Format.ChannelRanges[1], r2 = r.Format.ChannelRanges[2];

            // For normalization of X,Y,Z to D65 white point
            var Xn = 0.95;
            var Yn = 1.0;
            var Zn = 1.09;

            for (int y = 0; y < r.Height; ++y)
            {
                for (int x = 0; x < r.Width; ++x)
                {
                    // Calculation of color channel 0 (L) via old channel 1 (Y)
                    r[y, x, 0] = (float)(r0.Clamp(116.0 * XyzToLabFunc(image[y, x, 1] / Yn) - 16.0));
                    // Calculation of color channel 1 (a) via old channels 0 (X) and 1 (Y)
                    r[y, x, 1] = (float)(r1.Clamp(500.0 * (XyzToLabFunc(image[y, x, 0] / Xn) - XyzToLabFunc(image[y, x, 1] / Yn))));
                    // Calculation of color channel 2 (b) via old channels 1 (Y) and 2 (Z)
                    r[y, x, 2] = (float)(r2.Clamp(200.0 * (XyzToLabFunc(image[y, x, 1] / Yn) - XyzToLabFunc(image[y, x, 2] / Zn))));
                }
            }
            return(r);
        }