将HSV循环代码从Delphi转换为C#

将HSV循环代码从Delphi转换为C#

本文介绍了将HSV循环代码从Delphi转换为C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我试图转换一个函数来创建一个从Delphi到C#的HSV循环,但结果不是以正确的方式。 我的目标是为Windows Phone 7做一个应用程序,我只使用WP7.1 SDK,加上 WriteableBitmapEx 库。 Delphi代码: FUNCTION CreateHueSaturationCircle(CONST size:INTEGER; CONST ValueLevel:INTEGER; CONST BackgroundColor:TColor):TBitmap ; VAR dSquared:INTEGER; H,S,V:INTEGER; i:INTEGER; j:INTEGER; 半径:INTEGER; RadiusSquared:INTEGER; row:pRGBTripleArray; X:INTEGER; Y:INTEGER; BEGIN 结果:= TBitmap.Create; RESULT.PixelFormat:= pf24bit; RESULT.Width:= size; RESULT.Height:= size; //用背景颜色填充 RESULT.Canvas.Brush.Color:= BackGroundColor; RESULT.Canvas.FillRect(RESULT.Canvas.ClipRect); 半径:= size DIV 2; RadiusSquared:= Radius * Radius; V:= ValueLevel; FOR j:= 0 TO RESULT.Height - 1 DO BEGIN Y:= Size - 1 - j - Radius; {center is Radius offset} row:= RESULT.Scanline [Size -1-j]; FOR i:= 0 TO RESULT.Width - 1 DO BEGIN X:= i - Radius; dSquared:= X * X + Y * Y; IF dSquared< = RadiusSquared THEN BEGIN S:= ROUND((255 * SQRT(dSquared))/ Radius); H:= ROUND(180 *(1 + ArcTan2(X,Y)/ PI)); // 0..360 degrees //移动90度,沿X轴发生H = 0(红色) H:= H + 90; IF H> 360 THEN H:= H - 360; row [i]:= HSVtoRGBTriple(H,S,V) END END; END; END; 功能HSVtoRGBTriple(CONST H,S,V:INTEGER):TRGBTriple; CONST divisor:INTEGER = 255 * 60; VAR f:INTEGER; hTemp:INTEGER; p,q,t:INTEGER; VS:INTEGER; BEGIN 如果S = 0 THEN 结果:= RGBtoRGBTriple(V,V,V)//无色:灰色阴影 ELSE BEGIN //有彩色 IF H = 360 THEN hTemp:= 0 ELSE hTemp:= H; f:= hTemp MOD 60; // f is IN [0,59] hTemp:= hTemp DIV 60; // h现在为IN [0,6) VS:= V * S; p:= V - VS DIV 255; // p = v *(1-s) q:= V - (VS * f)DIV除数; // q = v *(1-s * f) t:= V-(VS *(60-f))DIV除数; // t = v *(1 - s *(1 - f)) CASE hTemp OF 0:RESULT:= RGBtoRGBTriple(V,t,p) 1:RESULT:= RGBtoRGBTriple(q,V,p); 2:RESULT:= RGBtoRGBTriple(p,V,t); 3:RESULT:= RGBtoRGBTriple(p,q,V); 4:RESULT:= RGBtoRGBTriple(t,p,V); 5:RESULT:= RGBtoRGBTriple(V,p,q); ELSE 结果:= RGBtoRGBTriple(0,0,0)//永远不会发生; //避免编译器警告 END END END Delphi代码的结果: 我的C#代码: public struct HSV { public float h; public float s; public float v; } public void createHsvCircle() { int size = 300; wb = new WriteableBitmap(size,size); wb.Clear(GraphicsUtils.WhiteColor); int radius = size / 2; int radiusSquared = radius * radius; int x; int y; int dSquared; HSV hsv; hsv.v = 255F; for(int j = 0; j< size; j ++) { y = size - 1 - for(int i = 0; i { x = i - radius; dSquared = x * x + y * y; if(dSquared { hsv.s =(float)Math.Round((255 * Math.Sqrt(dSquared))/ radius); hsv.h =(float)Math.Round(180 *(1 + Math.Atan2(y,x)/ Math.PI)); hsv.h + = 90; if(hsv.h> 360) { hsv.h - = 360; } 颜色color = GraphicsUtils.HsvToRgb(hsv); wb.SetPixel(i,j,color); } } } wb.Invalidate(); } public static Color HsvToRgb(float h,float s,float v) { h = h / 360; if(s> 0) { if(h> = 1) h = 0; h = 6 * h; int hueFloor =(int)Math.Floor(h); byte a =(byte)Math.Round(RGB_MAX * v *(1.0 - s)); byte b =(byte)Math.Round(RGB_MAX * v *(1.0 - (s *(h - hueFloor)))); byte c =(byte)Math.Round(RGB_MAX * v *(1.0 - (s *(1.0 - (h-hueFloor))))) byte d =(byte)Math.Round(RGB_MAX * v); switch(hueFloor) { case 0:return Color.FromArgb(RGB_MAX,d,c,a); case 1:return Color.FromArgb(RGB_MAX,b,d,a); case 2:return Color.FromArgb(RGB_MAX,a,d,c); case 3:return Color.FromArgb(RGB_MAX,a,b,d); case 4:return Color.FromArgb(RGB_MAX,c,a,d); case 5:return Color.FromArgb(RGB_MAX,d,a,b); 默认值:return Color.FromArgb(RGB_MAX,0,0,0); } } else { byte d =(byte)(v * RGB_MAX); return Color.FromArgb(255,d,d,d); } } public static Color HsvToRgb(HSV hsv) { return HsvToRgb(hsv.h,hsv.s,hsv.v) ; } 我的c#结果: 我做错了? 提前感谢。 b $ b 从@Aybe的好的答案,我可以从HSV whell做一个工作版本。 这是WP7的工作代码SDK: public const double PI = 3.14159265358979323846264338327950288d; public void createHsvCircle(double value = 1.0d) { if(value< 0.0d || value> 1.0d) throw new ArgumentOutOfRangeException 值); var size = 1024; wb = new WriteableBitmap(size,size); //用白色填充。 var white = Colors.White; for(int index = 0; index< wb.Pixels.Length; index ++) { wb.Pixels [index] = 0xFF& 24 |白色R& 16 |白色G< 8 |白B. } var cx = size / 2; var cy = size / 2; var radius = cx; var radiusSquared = radius * radius; for(int i = 0; i { for(int j = 0; j< size; j ++) { var x = i-cx; var y = j - cy; var distance =(double)x * x + y * y; if(distance< = radiusSquared)// in circle { var angle = 180.0d *(1 + Math.Atan2(x,y)/ PI); //移动90度,因此沿X轴发生H = 0(红色) angle + = 90.0d; if(angle> 360.0d) { angle - = 360.0d; } var hue = angle / 360.0d; // hue必须为0到1. var saturation = Math.Sqrt(distance)/ radius; //饱和度必须为0到1。 var hsv = new HSV(hue,saturation,value); var rgb = RGB.FromHsv(hsv.H,hsv.S,hsv.V); wb.Pixels [j * size + i] = 0xFF< 24 | rgb.R } } } wb.Invalidate(); } public static RGB FromHsv(double hue,double saturation,double value) { if(hue< 0.0d || hue> 1.0d ) throw new ArgumentOutOfRangeException(hue); if(饱和度< 0.0d ||饱和度> 1.0d) throw new ArgumentOutOfRangeException(saturation); if(value< 0.0d || value> 1.0d) throw new ArgumentOutOfRangeException(value); if(saturation == 0.0d) { var b1 =(byte)(value * 255); return new RGB(b1,b1,b1); } double r; double g; double b; var h = hue * 6.0d; if(h == 6.0d) { h = 0.0d; } int i =(int)Math.Floor(h); var v1 = value *(1.0d - saturation); var v2 = value *(1.0d - saturation *(h - i)); var v3 = value *(1.0d - saturation *(1.0d - (h - i))); switch(i) { case 0: r = value; g = v3; b = v1; break; case 1: r = v2; g = value; b = v1; break; case 2: r = v1; g = value; b = v3; break; case 3: r = v1; g = v2; b = value; break; case 4: r = v3; g = v1; b = value; break; 默认值: r = value; g = v1; b = v2; break; } r = r * 255.0d; if(r> 255.0d) { r = 255.0d; } g = g * 255.0d; if(g> 255.0d) { g = 255.0d; } b = b * 255.0d; if(b> 255.0d) { b = 255.0d; } return new RGB((byte)r,(byte)g,(byte)b); } 现在,新结果: 谢谢!花了一个小时左右,我在这个过程中学到了一些东西... $ b $ b 现在的代码:(适用于任何大小) 这是HSL,但我给了你的URL有你的其他algos。 使用System; using System.Diagnostics; using System.Runtime.InteropServices; 使用System.Windows; 使用System.Windows.Media; 使用System.Windows.Media.Imaging; namespace ColorWheel { ///< summary> /// MainWindow.xaml的交互逻辑 ///< / summary> public partial MainWindow:Window { public MainWindow() { InitializeComponent(); } private void BuildWheel() { var width = 1024; var height = width; var cx = width / 2; var cy = height / 2; var colors = new int [width * height]; var gray = Colors.Gray.ToBgr32(); for(int index = 0; index< colors.Length; index ++)colors [index] = grey; var radius = cx; var radiusSquared = radius * radius; for(int i = 0; i { for(int j = 0; j< width; j ++) { var x = j-cx; var y = i - cy; var distanceSquared =(double)x * x + y * y; if(distanceSquared { var h = Math.Atan2(x,y).ToDegrees()+ 180.0d; // Angle var s = 1.0d; var l =(1.0d - ((1.0d / radiusSquared)* distanceSquared)); // 1 - (distance normalized) var hsl = new HSL((float)h,(float)s,(float)l); var rgb = RGB.FromHsl(hsl.H,hsl.S,hsl.L); colors [i * width + j] = rgb.R } } } var bitmap = new WriteableBitmap(width,height,96,96,PixelFormats.Bgr32,null); bitmap.WritePixels(new Int32Rect(0,0,width,height),colors,width * 4,0); image.Source = bitmap; } private void Window_Loaded(object sender,RoutedEventArgs e) { BuildWheel(); } } public static class Helpers { public static double ToDegrees(this double radians) { return radians * 57.2957795130823; // radians *(180.0d / Math.PI)} public static double ToRadians(this double degrees) { return degrees * 0.0174532925199433; // degrees *(Math.PI / 180.0d)} } public static class ColorExtensions { public static Color FromBgr32颜色) { return Color.FromRgb((byte)((color& 0xFF0000)>> 16),(byte)((color& 0xFF00)> (字节)(颜色& 0xFF)); } public static int ToBgr32(this Color color) { return color.R< 16 |颜色G< 8 |颜色B. } } ///< summary> ///表示HSL空间中的颜色。 ///< / summary> [StructLayout(LayoutKind.Sequential)] public struct HSL { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly double _h; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly double _s; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly double _l; ///< summary> ///返回此实例的完全限定类型名称。 ///< / summary> ///< returns> A< see cref =T:System.String/>包含完全限定类型名称。 < / returns> ///< filterpriority> 2< / filterpriority> public override string ToString() { return string.Format(H:{0},S:{1},L:{2},_h,_s,_l) ; } ///< summary> ///创建一个新实例< see cref =HSL/> 。 ///< / summary> ///< param name =h>值< see cref =H/>零件。 < / param> ///< param name =s>值< see cref =S/>零件。 < / param> ///< param name =l>值< see cref =L/>零件。 < / param> public HSL(double h,double s,double l) { _h = h; _s = s; _l = l; } ///< summary> ///获取色调组件的值。 ///< / summary> public double H { get {return _h; } } ///< summary> ///获取饱和度组件的值。 ///< / summary> public double S { get {return _s; } } ///< summary> ///获取亮度组件的值。 ///< / summary> public double L { get {return _l; } } public override bool Equals(object obj) { if(ReferenceEquals(null,obj))return false; if(obj.GetType()!= typeof(HSL))return false; return Equals((HSL)obj); } public bool Equals(HSL other) { return other._h.Equals(_h)&& other._l.Equals(_l)&&& other._s.Equals(_s); } ///< summary> ///创建一个新实例< see cref =HSL/> ,从RGB值。 ///< / summary> ///< param name =red>红色分量的值。 < / param> ///< param name =green>绿色组件的值。 < / param> ///< param name =blue>蓝色分量的值。 < / param> ///< returns> < see cref =HSL/>实例创建。 < / returns> public static HSL FromRGB(字节红色,字节绿色,字节蓝色) { var r1 = red / 255.0d; var g1 = green / 255.0d; var b1 = blue / 255.0d; var min = Math.Min(r1,Math.Min(g1,b1)); var max = Math.Max(r1,Math.Max(g1,b1)); var l =(max + min)/2.0d; var s = 0.0d; var h = 0.0d; if(min == max) { h = 0.0d; s = 0.0d; } else { if(l { s =(max - min)/(max + min) } else if(l> = 0.5d) { s =(max-min)/(2.0d-max-min); } if(r1 == max) { h =(g1 - b1)/(max - min); } else if(g1 == max) { h = 2.0d +(b1 - r1)/(max - min); } else if(b1 == max) { h = 4.0d +(r1 - g1)/(max - min); } } h * = 60.0d; if(h< 0.0d) h + = 360.0d; return new HSL(h,s,l); } ///< summary> ///返回此实例的哈希码。 ///< / summary> ///< returns>作为此实例的哈希码的32位有符号整数。 < / returns> ///< filterpriority> 2< / filterpriority> public override int GetHashCode() { unchecked { var result = _h.GetHashCode(); result =(result * 397)^ _l.GetHashCode(); result =(result * 397)^ _s.GetHashCode(); return result; } } public static BitmapSource GetHslPalette(int width = 360,int height = 100) { // HSL调色板图像像在Photoshop,等... var pixels = new int [width * height]; const double saturation = 1.0d; for(var y = 0; y< height; y ++) { for(var x = 0; x { var hue =(1.0d / width)* x * 360.0d; var lightness = 1.0d - ((1.0f / height)* y); var rgb = RGB.FromHsl(hue,saturation,lightness); pixels [y * width + x] = 0xFF< 24 | rgb.R } } return BitmapSource.Create(width,height,96,96,PixelFormats.Pbgra32,null,pixels,width * 4); } public static bool operator ==(HSL left,HSL right) { return left.Equals(right); } public static bool operator!=(HSL left,HSL right) { return!left.Equals(right); } } ///< summary> ///表示RGB空间中的颜色。 ///< / summary> [StructLayout(LayoutKind.Sequential)] public struct RGB { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly byte _r; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly byte _g; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly byte _b; ///< summary> ///创建一个新实例< see cref =RGB/> 。 ///< / summary> ///< param name =r>红色成分的值。 < / param> ///< param name =g>绿色部件的值。 < / param> ///< param name =b>蓝色分量的值。 < / param> public RGB(byte r,byte g,byte b) { _r = r; _g = g; _b = b; } ///< summary> ///返回此实例的完全限定类型名称。 ///< / summary> ///< returns> A< see cref =T:System.String/>包含完全限定类型名称。 < / returns> ///< filterpriority> 2< / filterpriority> public override string ToString() { return string.Format(R:{0},G:{1},B:{2},_r,_g,_b) ; } ///< summary> ///获取红色组件的值。 ///< / summary> public byte R { get {return _r; } } ///< summary> ///获取绿色组件的值。 ///< / summary> public byte G { get {return _g; } } ///< summary> ///获取蓝色组件的值。 ///< / summary> public byte B { get {return _b; } } public override bool Equals(object obj) { if(ReferenceEquals(null,obj))return false; if(obj.GetType()!= typeof(RGB))return false; return Equals((RGB)obj); } public bool等于(RGB其他) { return other._b == _b&& other._g == _g&&& other._r == _r; } ///< summary> ///创建一个新实例< see cref =RGB/> ,从HSL值。 ///< / summary> ///< param name =hue>色相,从0.0到360.0。 < / param> ///< param name =saturation>饱和度,从0.0到1.0。 < / param> ///< param name =lightness>亮度,从0.0到1.0。 < / param> ///< returns> < see cref =RGB/>实例创建。 < / returns> public static RGB FromHsl(double hue,double saturation,double lightness) { if(hue< 0.0d || hue> 360.0d)throw new ArgumentOutOfRangeException(hue) ; if(饱和度< 0.0d ||饱和度> 1.0d)throw new ArgumentOutOfRangeException(saturation); if(lightness< 0.0d || lightness> 1.0d)throw new ArgumentOutOfRangeException(lightness); if(saturation == 0.0d) { var b1 =(byte)(lightness * 255); return new RGB(b1,b1,b1); } var t2 = 0.0d; if(lightness< 0.5d) t2 = lightness *(1.0d + saturation); else if(lightness> = 0.5d) t2 = lightness + saturation - lightness * saturation; var t1 = 2.0d * lightness - t2; var h = hue / 360.0d; var tr = h + 1.0d / 3.0d; var tg = h; var tb = h - 1.0d / 3.0d; tr = tr 1.0d? tr-1.0d:tr; tg = tg< 0.0d? tg + 1.0d:tg> 1.0d? tg - 1.0d:tg; tb = tb< 0.0d? tb + 1.0d: 1.0d? tb-1.0d:tb; double r; if(6.0d * tr r = t1 +(t2-t1)* 6.0d * tr; else if(2.0d * tr r = t2; else if(3.0d * tr r = t1 +(t2-t1)*((2.0d / 3.0d)-tr)* 6.0d; else r = t1; double g; if(6.0d * tg g = t1 +(t2-t1)* 6.0d * tg; else if(2.0d * tg g = t2; else if(3.0d * tg g = t1 +(t2-t1)*((2.0d / 3.0d)-tg)* 6.0d; else g = t1; double b; if(6.0d * tb b = t1 +(t2-t1)* 6.0d * tb; else if(2.0d * tb b = t2; else if(3.0d * tb b = t1 +(t2-t1)*((2.0d / 3.0d)-Tb)* 6.0d; else b = t1; 返回新的RGB((字节)(r * 255),(字节)(g * 255),(字节)(b * 255) } ///< summary> ///返回此实例的哈希码。 ///< / summary> ///< returns>作为此实例的哈希码的32位有符号整数。 < / returns> ///< filterpriority> 2< / filterpriority> public override int GetHashCode() { unchecked { var result = _b.GetHashCode(); result =(result * 397)^ _g.GetHashCode(); result =(result * 397)^ _r.GetHashCode(); return result; } } public static bool operator ==(RGB left,RGB right) { return left.Equals(right); } public static bool operator!=(RGB left,RGB right) { return!left.Equals(right); } } } I'm trying to convert an function to create a HSV Circle from Delphi to C#, but the result is not being in a correct way.My target is to do an app for Windows Phone 7, and I'm only using the WP7.1 SDK, plus WriteableBitmapEx library.Delphi Code:FUNCTION CreateHueSaturationCircle(CONST size: INTEGER; CONST ValueLevel: INTEGER; CONST BackgroundColor: TColor): TBitmap;VAR dSquared: INTEGER; H,S,V: INTEGER; i: INTEGER; j: INTEGER; Radius: INTEGER; RadiusSquared: INTEGER; row: pRGBTripleArray; X: INTEGER; Y: INTEGER;BEGIN RESULT := TBitmap.Create; RESULT.PixelFormat := pf24bit; RESULT.Width := size; RESULT.Height := size; // Fill with background color RESULT.Canvas.Brush.Color := BackGroundColor; RESULT.Canvas.FillRect(RESULT.Canvas.ClipRect); Radius := size DIV 2; RadiusSquared := Radius * Radius; V := ValueLevel; FOR j := 0 TO RESULT.Height - 1 DO BEGIN Y := Size - 1 - j - Radius; {Center is Radius offset} row := RESULT.Scanline[Size - 1 - j]; FOR i := 0 TO RESULT.Width - 1 DO BEGIN X := i - Radius; dSquared := X * X + Y * Y; IF dSquared <= RadiusSquared THEN BEGIN S := ROUND((255 * SQRT(dSquared)) / Radius); H := ROUND(180 * (1 + ArcTan2(X, Y) / PI)); // 0..360 degrees // Shift 90 degrees so H=0 (red) occurs along "X" axis H := H + 90; IF H > 360 THEN H := H - 360; row[i] := HSVtoRGBTriple(H,S,V) END END; END;END;FUNCTION HSVtoRGBTriple(CONST H,S,V: INTEGER): TRGBTriple;CONST divisor: INTEGER = 255 * 60;VAR f: INTEGER; hTemp: INTEGER; p,q,t: INTEGER; VS: INTEGER;BEGIN IF S = 0 THEN RESULT := RGBtoRGBTriple(V, V, V) // achromatic: shades of gray ELSE BEGIN // chromatic color IF H = 360 THEN hTemp := 0 ELSE hTemp := H; f := hTemp MOD 60; // f is IN [0, 59] hTemp := hTemp DIV 60; // h is now IN [0,6) VS := V * S; p := V - VS DIV 255; // p = v * (1 - s) q := V - (VS*f) DIV divisor; // q = v * (1 - s*f) t := V - (VS*(60 - f)) DIV divisor; // t = v * (1 - s * (1 - f)) CASE hTemp OF 0: RESULT := RGBtoRGBTriple(V, t, p); 1: RESULT := RGBtoRGBTriple(q, V, p); 2: RESULT := RGBtoRGBTriple(p, V, t); 3: RESULT := RGBtoRGBTriple(p, q, V); 4: RESULT := RGBtoRGBTriple(t, p, V); 5: RESULT := RGBtoRGBTriple(V, p, q); ELSE RESULT := RGBtoRGBTriple(0,0,0) // should never happen; // avoid compiler warning END ENDEND The results from Delphi code:My C# code: public struct HSV { public float h; public float s; public float v; } public void createHsvCircle() { int size = 300; wb = new WriteableBitmap(size, size); wb.Clear(GraphicsUtils.WhiteColor); int radius = size / 2; int radiusSquared = radius * radius; int x; int y; int dSquared; HSV hsv; hsv.v = 255F; for (int j = 0; j < size; j++) { y = size - 1 - j - radius; for (int i = 0; i < size; i++) { x = i - radius; dSquared = x * x + y * y; if (dSquared <= radiusSquared) { hsv.s = (float) Math.Round((255 * Math.Sqrt(dSquared)) / radius); hsv.h = (float) Math.Round(180 * (1 + Math.Atan2(y, x) / Math.PI)); hsv.h += 90; if (hsv.h > 360) { hsv.h -= 360; } Color color = GraphicsUtils.HsvToRgb(hsv); wb.SetPixel(i, j, color); } } } wb.Invalidate(); } public static Color HsvToRgb(float h, float s, float v) { h = h / 360; if (s > 0) { if (h >= 1) h = 0; h = 6 * h; int hueFloor = (int)Math.Floor(h); byte a = (byte)Math.Round(RGB_MAX * v * (1.0 - s)); byte b = (byte)Math.Round(RGB_MAX * v * (1.0 - (s * (h - hueFloor)))); byte c = (byte)Math.Round(RGB_MAX * v * (1.0 - (s * (1.0 - (h - hueFloor))))); byte d = (byte)Math.Round(RGB_MAX * v); switch (hueFloor) { case 0: return Color.FromArgb(RGB_MAX, d, c, a); case 1: return Color.FromArgb(RGB_MAX, b, d, a); case 2: return Color.FromArgb(RGB_MAX, a, d, c); case 3: return Color.FromArgb(RGB_MAX, a, b, d); case 4: return Color.FromArgb(RGB_MAX, c, a, d); case 5: return Color.FromArgb(RGB_MAX, d, a, b); default: return Color.FromArgb(RGB_MAX, 0, 0, 0); } } else { byte d = (byte)(v * RGB_MAX); return Color.FromArgb(255, d, d, d); } } public static Color HsvToRgb(HSV hsv) { return HsvToRgb(hsv.h, hsv.s, hsv.v); } My c# result:What I'm doing it wrong?Thanks in advance.EDITED WITH SOLUTIONWith the great answer from @Aybe, I could do a working version from HSV whell.This is the working code for WP7 SDK: public const double PI = 3.14159265358979323846264338327950288d; public void createHsvCircle(double value = 1.0d) { if (value < 0.0d || value > 1.0d) throw new ArgumentOutOfRangeException("value"); var size = 1024; wb = new WriteableBitmap(size, size); // fill with white. var white = Colors.White; for (int index = 0; index < wb.Pixels.Length; index++) { wb.Pixels[index] = 0xFF << 24 | white.R << 16 | white.G << 8 | white.B; } var cx = size / 2; var cy = size / 2; var radius = cx; var radiusSquared = radius * radius; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { var x = i - cx; var y = j - cy; var distance = (double)x * x + y * y; if (distance <= radiusSquared) // In circle { var angle = 180.0d * (1 + Math.Atan2(x, y) / PI); // shift 90 degrees so H=0 (red) occurs along "X" axis angle += 90.0d; if (angle > 360.0d) { angle -= 360.0d; } var hue = angle / 360.0d; // hue must be into 0 to 1. var saturation = Math.Sqrt(distance) / radius; // saturation must be into 0 to 1. var hsv = new HSV(hue, saturation, value); var rgb = RGB.FromHsv(hsv.H, hsv.S, hsv.V); wb.Pixels[j * size + i] = 0xFF << 24 | rgb.R << 16 | rgb.G << 8 | rgb.B; } } } wb.Invalidate(); } public static RGB FromHsv(double hue, double saturation, double value) { if (hue < 0.0d || hue > 1.0d) throw new ArgumentOutOfRangeException("hue"); if (saturation < 0.0d || saturation > 1.0d) throw new ArgumentOutOfRangeException("saturation"); if (value < 0.0d || value > 1.0d) throw new ArgumentOutOfRangeException("value"); if (saturation == 0.0d) { var b1 = (byte)(value * 255); return new RGB(b1, b1, b1); } double r; double g; double b; var h = hue * 6.0d; if (h == 6.0d) { h = 0.0d; } int i = (int)Math.Floor(h); var v1 = value * (1.0d - saturation); var v2 = value * (1.0d - saturation * (h - i)); var v3 = value * (1.0d - saturation * (1.0d - (h - i))); switch (i) { case 0: r = value; g = v3; b = v1; break; case 1: r = v2; g = value; b = v1; break; case 2: r = v1; g = value; b = v3; break; case 3: r = v1; g = v2; b = value; break; case 4: r = v3; g = v1; b = value; break; default: r = value; g = v1; b = v2; break; } r = r * 255.0d; if (r > 255.0d) { r = 255.0d; } g = g * 255.0d; if (g > 255.0d) { g = 255.0d; } b = b * 255.0d; if (b > 255.0d) { b = 255.0d; } return new RGB((byte)r, (byte)g, (byte)b); }And now, the new result:Thanks! 解决方案 After spending an hour or so, I learned a few things in the process ...Now the code : (works for any size)This is HSL but I gave you the url where you have other algos.using System;using System.Diagnostics;using System.Runtime.InteropServices;using System.Windows;using System.Windows.Media;using System.Windows.Media.Imaging;namespace ColorWheel{ /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void BuildWheel() { var width = 1024; var height = width; var cx = width/2; var cy = height/2; var colors = new int[width*height]; var gray = Colors.Gray.ToBgr32(); for (int index = 0; index < colors.Length; index++) colors[index] = gray; var radius = cx; var radiusSquared = radius*radius; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { var x = j - cx; var y = i - cy; var distanceSquared = (double) x*x + y*y; if (distanceSquared <= radiusSquared) // In circle { var h = Math.Atan2(x, y).ToDegrees() + 180.0d; // Angle var s = 1.0d; var l = (1.0d - ((1.0d/radiusSquared)*distanceSquared)); // 1 - (distance normalized) var hsl = new HSL((float) h, (float) s, (float) l); var rgb = RGB.FromHsl(hsl.H, hsl.S, hsl.L); colors[i*width + j] = rgb.R << 16 | rgb.G << 8 | rgb.B; } } } var bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr32, null); bitmap.WritePixels(new Int32Rect(0, 0, width, height), colors, width*4, 0); image.Source = bitmap; } private void Window_Loaded(object sender, RoutedEventArgs e) { BuildWheel(); } } public static class Helpers { public static double ToDegrees(this double radians) { return radians*57.2957795130823; // radians * (180.0d / Math.PI) } public static double ToRadians(this double degrees) { return degrees*0.0174532925199433; // degrees * (Math.PI / 180.0d) } } public static class ColorExtensions { public static Color FromBgr32(this Int32 color) { return Color.FromRgb((byte) ((color & 0xFF0000) >> 16), (byte) ((color & 0xFF00) >> 8), (byte) (color & 0xFF)); } public static int ToBgr32(this Color color) { return color.R << 16 | color.G << 8 | color.B; } } /// <summary> /// Represents a color in an HSL space. /// </summary> [StructLayout(LayoutKind.Sequential)] public struct HSL { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly double _h; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly double _s; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly double _l; /// <summary> /// Returns the fully qualified type name of this instance. /// </summary> /// <returns> A <see cref="T:System.String" /> containing a fully qualified type name. </returns> /// <filterpriority>2</filterpriority> public override string ToString() { return string.Format("H: {0}, S: {1}, L: {2}", _h, _s, _l); } /// <summary> /// Create a new instance of <see cref="HSL" /> . /// </summary> /// <param name="h"> Value of <see cref="H" /> component. </param> /// <param name="s"> Value of <see cref="S" /> component. </param> /// <param name="l"> Value of <see cref="L" /> component. </param> public HSL(double h, double s, double l) { _h = h; _s = s; _l = l; } /// <summary> /// Gets the value of the hue component. /// </summary> public double H { get { return _h; } } /// <summary> /// Gets the value of the saturation component. /// </summary> public double S { get { return _s; } } /// <summary> /// Gets the value of the lightness component. /// </summary> public double L { get { return _l; } } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof (HSL)) return false; return Equals((HSL) obj); } public bool Equals(HSL other) { return other._h.Equals(_h) && other._l.Equals(_l) && other._s.Equals(_s); } /// <summary> /// Create a new instance of <see cref="HSL" /> , from RGB values. /// </summary> /// <param name="red"> Value of the red component. </param> /// <param name="green"> Value of the green component. </param> /// <param name="blue"> Value of the blue component. </param> /// <returns> <see cref="HSL" /> instance created. </returns> public static HSL FromRGB(byte red, byte green, byte blue) { var r1 = red/255.0d; var g1 = green/255.0d; var b1 = blue/255.0d; var min = Math.Min(r1, Math.Min(g1, b1)); var max = Math.Max(r1, Math.Max(g1, b1)); var l = (max + min)/2.0d; var s = 0.0d; var h = 0.0d; if (min == max) { h = 0.0d; s = 0.0d; } else { if (l < 0.5d) { s = (max - min)/(max + min); } else if (l >= 0.5d) { s = (max - min)/(2.0d - max - min); } if (r1 == max) { h = (g1 - b1)/(max - min); } else if (g1 == max) { h = 2.0d + (b1 - r1)/(max - min); } else if (b1 == max) { h = 4.0d + (r1 - g1)/(max - min); } } h *= 60.0d; if (h < 0.0d) h += 360.0d; return new HSL(h, s, l); } /// <summary> /// Returns the hash code for this instance. /// </summary> /// <returns> A 32-bit signed integer that is the hash code for this instance. </returns> /// <filterpriority>2</filterpriority> public override int GetHashCode() { unchecked { var result = _h.GetHashCode(); result = (result*397) ^ _l.GetHashCode(); result = (result*397) ^ _s.GetHashCode(); return result; } } public static BitmapSource GetHslPalette(int width = 360, int height = 100) { // Creates an HSL palette image like in Photoshop, etc ... var pixels = new int[width*height]; const double saturation = 1.0d; for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var hue = (1.0d/width)*x*360.0d; var lightness = 1.0d - ((1.0f/height)*y); var rgb = RGB.FromHsl(hue, saturation, lightness); pixels[y*width + x] = 0xFF << 24 | rgb.R << 16 | rgb.G << 8 | rgb.B; } } return BitmapSource.Create(width, height, 96, 96, PixelFormats.Pbgra32, null, pixels, width*4); } public static bool operator ==(HSL left, HSL right) { return left.Equals(right); } public static bool operator !=(HSL left, HSL right) { return !left.Equals(right); } } /// <summary> /// Represents a color in an RGB space. /// </summary> [StructLayout(LayoutKind.Sequential)] public struct RGB { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly byte _r; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly byte _g; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly byte _b; /// <summary> /// Create a new instance of <see cref="RGB" /> . /// </summary> /// <param name="r"> Value of red component. </param> /// <param name="g"> Value of green component. </param> /// <param name="b"> Value of blue component. </param> public RGB(byte r, byte g, byte b) { _r = r; _g = g; _b = b; } /// <summary> /// Returns the fully qualified type name of this instance. /// </summary> /// <returns> A <see cref="T:System.String" /> containing a fully qualified type name. </returns> /// <filterpriority>2</filterpriority> public override string ToString() { return string.Format("R: {0}, G: {1}, B: {2}", _r, _g, _b); } /// <summary> /// Gets the value of the red component. /// </summary> public byte R { get { return _r; } } /// <summary> /// Gets the value of the green component. /// </summary> public byte G { get { return _g; } } /// <summary> /// Gets the value of the blue component. /// </summary> public byte B { get { return _b; } } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof (RGB)) return false; return Equals((RGB) obj); } public bool Equals(RGB other) { return other._b == _b && other._g == _g && other._r == _r; } /// <summary> /// Create a new instance of <see cref="RGB" /> , from HSL values. /// </summary> /// <param name="hue"> Hue, from 0.0 to 360.0. </param> /// <param name="saturation"> Saturation, from 0.0 to 1.0. </param> /// <param name="lightness"> Lightness, from 0.0 to 1.0. </param> /// <returns> <see cref="RGB" /> instance created. </returns> public static RGB FromHsl(double hue, double saturation, double lightness) { if (hue < 0.0d || hue > 360.0d) throw new ArgumentOutOfRangeException("hue"); if (saturation < 0.0d || saturation > 1.0d) throw new ArgumentOutOfRangeException("saturation"); if (lightness < 0.0d || lightness > 1.0d) throw new ArgumentOutOfRangeException("lightness"); if (saturation == 0.0d) { var b1 = (byte) (lightness*255); return new RGB(b1, b1, b1); } var t2 = 0.0d; if (lightness < 0.5d) t2 = lightness*(1.0d + saturation); else if (lightness >= 0.5d) t2 = lightness + saturation - lightness*saturation; var t1 = 2.0d*lightness - t2; var h = hue/360.0d; var tr = h + 1.0d/3.0d; var tg = h; var tb = h - 1.0d/3.0d; tr = tr < 0.0d ? tr + 1.0d : tr > 1.0d ? tr - 1.0d : tr; tg = tg < 0.0d ? tg + 1.0d : tg > 1.0d ? tg - 1.0d : tg; tb = tb < 0.0d ? tb + 1.0d : tb > 1.0d ? tb - 1.0d : tb; double r; if (6.0d*tr < 1.0d) r = t1 + (t2 - t1)*6.0d*tr; else if (2.0d*tr < 1.0d) r = t2; else if (3.0d*tr < 2.0d) r = t1 + (t2 - t1)*((2.0d/3.0d) - tr)*6.0d; else r = t1; double g; if (6.0d*tg < 1.0d) g = t1 + (t2 - t1)*6.0d*tg; else if (2.0d*tg < 1.0d) g = t2; else if (3.0d*tg < 2.0d) g = t1 + (t2 - t1)*((2.0d/3.0d) - tg)*6.0d; else g = t1; double b; if (6.0d*tb < 1.0d) b = t1 + (t2 - t1)*6.0d*tb; else if (2.0d*tb < 1.0d) b = t2; else if (3.0d*tb < 2.0d) b = t1 + (t2 - t1)*((2.0d/3.0d) - tb)*6.0d; else b = t1; return new RGB((byte) (r*255), (byte) (g*255), (byte) (b*255)); } /// <summary> /// Returns the hash code for this instance. /// </summary> /// <returns> A 32-bit signed integer that is the hash code for this instance. </returns> /// <filterpriority>2</filterpriority> public override int GetHashCode() { unchecked { var result = _b.GetHashCode(); result = (result*397) ^ _g.GetHashCode(); result = (result*397) ^ _r.GetHashCode(); return result; } } public static bool operator ==(RGB left, RGB right) { return left.Equals(right); } public static bool operator !=(RGB left, RGB right) { return !left.Equals(right); } }} 这篇关于将HSV循环代码从Delphi转换为C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
09-18 00:18