/// <summary> /// Return a Bitmap created from the given CIELab color values /// </summary> /// <param name="source"></param> /// <returns></returns> public Bitmap GetBitmapFromCIELABImage(CIELab[] s, int width, int height) { // create map Bitmap b = new Bitmap(width, height, PixelFormat.Format32bppPArgb); // iterate pixels for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // get CIE XYZ mapping for pixel and then convert this to CIE Lab double CIE_X, CIE_Y, CIE_Z; CIELab cie = s[y * width + x]; RgbaHls.CIELAB_2_CIEXYZ(cie.L, cie.a, cie.b, out CIE_X, out CIE_Y, out CIE_Z); // convert back to RGB Color c = RgbaHls.CIEXYZ_2_RGB(CIE_X, CIE_Y, CIE_Z); // insert into bitmap b.SetPixel(x, y, c); } } // return bitmap return(b); }
/// <summary> /// Return a new system color from the given hsla values /// </summary> /// <param name="h"></param> /// <param name="s"></param> /// <param name="l"></param> /// <param name="alpha"></param> /// <returns></returns> public static Color ColorFromHSLA(double h, double s, double l, double a) { RgbaHls c = new RgbaHls(); c.FromHSLA(h, s, l, a); return(c.GetSystemColor()); }
// // Set color from HSL and alpha values // public void FromHSLA(double hv, double sv, double lv, double av) { // clamp all values to correct range h = Math.Min(360.0f, Math.Max(0.0, hv)); s = Math.Min(1.0f, Math.Max(0.0, sv)); l = Math.Min(1.0f, Math.Max(0.0, lv)); a = Math.Min(1.0f, Math.Max(0.0, av)); // calculate new RGB values RgbaHls.HSL2RGB(ref r, ref g, ref b, h, s, l); }
// // Set color from RGBA values // public void FromRGBA(double rv, double gv, double bv, double av) { // clamp all values to correct range r = Math.Min(1.0f, Math.Max(0.0, rv)); g = Math.Min(1.0f, Math.Max(0.0, gv)); b = Math.Min(1.0f, Math.Max(0.0, bv)); a = Math.Min(1.0f, Math.Max(0.0, av)); // calculate new HSL values RgbaHls.RGB2HSL(r, g, b, ref h, ref s, ref l); }
/// <summary> /// Return and a CIE Lab color mapping of the source image. Alpha is ignored. Also returns the /// min/max CIE L value found in the image. /// </summary> /// <param name="source"></param> /// <returns></returns> public CIELab[] GetCIELABImage(Bitmap source, out double minL, out double maxL) { // init L limits minL = double.MaxValue; maxL = double.MinValue; // create map CIELab[] map = new CIELab[source.Width * source.Height]; // iterate pixels for (int y = 0; y < source.Height; y++) { for (int x = 0; x < source.Width; x++) { // get CIE XYZ mapping for pixel and then convert this to CIE Lab double CIE_X, CIE_Y, CIE_Z; RgbaHls.RGB_2_CIEXYZ(source.GetPixel(x, y), out CIE_X, out CIE_Y, out CIE_Z); double CIE_L, CIE_a, CIE_b; RgbaHls.CIEXYZ_2_CIELAB(CIE_X, CIE_Y, CIE_Z, out CIE_L, out CIE_a, out CIE_b); // insert into map map[y * source.Width + x] = new CIELab(CIE_L, CIE_a, CIE_b); // update L limits minL = Math.Min(minL, CIE_L); maxL = Math.Max(maxL, CIE_L); } } // return mapping return(map); }
/// <summary> /// Given a CIELab array ( obtained with GetCIELABImage ) this calculate the chromaticity distance of /// each pixel fro the 'typical' red eye CIELAB color. Also returns the Min/Max chromaticity distances found /// </summary> /// <returns></returns> public double[] GetChromaticityDistanceMap(CIELab[] map, int width, int height, out double minDistance, out double maxDistance) { // initialize min/max minDistance = double.MaxValue; maxDistance = double.MinValue; // create return array double[] cdMap = new double[width * height]; // iterate pixels for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // get distance for this pixel double c = RgbaHls.ChromaticityDistance(map[y * width + x].a, kA_REDEYE, map[y * width + x].b, kB_REDEYE); // assign to map cdMap[y * width + x] = c; // update min/max minDistance = Math.Min(minDistance, c); maxDistance = Math.Max(maxDistance, c); } } // return chromaticty map return(cdMap); }
/// <summary> /// Return an array of hue, saturation, luminance, alpha ( 0..1 ) of the source image. /// Hue = [ ( x + y * width ) * 4 + 0 ] /// Sat = [ ( x + y * width ) * 4 + 1 ] /// Lum = [ ( x + y * width ) * 4 + 2 ] /// Alpha = [ ( x + y * width ) * 4 + 3 ] /// /// </summary> /// <param name="source"></param> /// <returns></returns> public static float[] GetHSLAImage(Bitmap source) { // sanity check if (source == null) return null; // create output array 4 floats per pixel float[] a = new float[source.Width * source.Height * 4]; // lock down source image unsafe { BitmapData bd = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb); // get source pixel pointers byte* sp = (byte*)(void*)bd.Scan0; // iterate pixels for (int y = 0; y < source.Height; y++) { for (int x = 0; x < source.Width; x++) { // pixels are arrange BGRA ! Color c = Color.FromArgb(sp[y * bd.Stride + x * 4 + 3], // A sp[y * bd.Stride + x * 4 + 2], // R sp[y * bd.Stride + x * 4 + 1], // G sp[y * bd.Stride + x * 4 + 0]); // B // Get HSLA RgbaHls hlsa = new RgbaHls(c); // write values as float into array a[(x + y * source.Width) * 4 + 0] = (float)hlsa.H; a[(x + y * source.Width) * 4 + 1] = (float)hlsa.S; a[(x + y * source.Width) * 4 + 2] = (float)hlsa.L; a[(x + y * source.Width) * 4 + 3] = (float)hlsa.A; } } // unlock bitmap source.UnlockBits(bd); } // return float array return a; }
public RgbaHls( RgbaHls a ) { this.FromHSLA( a.H, a.S, a.L, a.A ); }
/// <summary> /// Return a new system color from the given hsla values /// </summary> /// <param name="h"></param> /// <param name="s"></param> /// <param name="l"></param> /// <param name="alpha"></param> /// <returns></returns> public static Color ColorFromHSLA( double h, double s, double l, double a ) { RgbaHls c = new RgbaHls(); c.FromHSLA( h,s,l,a ); return c.GetSystemColor(); }
public RgbaHls(RgbaHls a) { this.FromHSLA(a.H, a.S, a.L, a.A); }