Jump to content

drosen

Newbies
  • Posts

    1
  • Joined

  • Last visited

Everything posted by drosen

  1. I'm using some of the PdN code within my own application to do a few graphical adjustments on-the-fly, and ran into this issue. The adjusted gradients did not look very good after applying the hue/saturation/lightness effect. This thread helped a lot. Using Tanel's suggestions and ennixo's code, I made the necessary modifications to the PdN 3.36 code to apply an accurate HSL adjustment. Thanks ennixo and Tanel! In UnaryPixelOps.cs, change the code for class HueSaturationLightness to: [serializable] public class HueSaturationLightness : UnaryPixelOp { private int hueDelta; private int satFactor; private UnaryPixelOp blendOp; public HueSaturationLightness(int hueDelta, int satDelta, int lightness) { //this.hueDelta = hueDelta; this.hueDelta = hueDelta * (HslHelper.MAX6 / 360); this.satFactor = (int)Math.Round((satDelta * 1024) / (double)100); if (lightness == 0) { //blendOp = new UnaryPixelOps.Identity(); blendOp = null; } else if (lightness > 0) { blendOp = new UnaryPixelOps.BlendConstant(ColorBgra.FromBgra(255, 255, 255, (byte)Math.Round((lightness * 255) / (double)100))); } else // if (lightness < 0) { blendOp = new UnaryPixelOps.BlendConstant(ColorBgra.FromBgra(0, 0, 0, (byte)Math.Round((-lightness * 255) / (double)100))); } } public override ColorBgra Apply(ColorBgra color) { ColorBgra origColor = color; // adjust hue if (hueDelta != 0) { //HsvColor hsvColor = HsvColor.FromColor(color.ToColor()); //int hue = hsvColor.Hue; // //hue += hueDelta; // //while (hue < 0) //{ // hue += 360; //} // //while (hue > 360) //{ // hue -= 360; //} // //hsvColor.Hue = hue; //ColorBgra color = ColorBgra.FromColor(hsvColor.ToColor()); int h, s, l; HslHelper.GetHSL(color.R, color.G, color.B, out h, out s, out l); h += hueDelta; while (h < 0) h += HslHelper.MAX6; while (h >= HslHelper.MAX6) h -= HslHelper.MAX6; HslHelper.GetRGB(h, s, l, out color.R, out color.G, out color.; } //adjust saturation if (satFactor != 1024) { //byte intensity = color.GetIntensityByte(); double intensity = color.GetIntensity() * (double)255; color.R = Utility.ClampToByte((int)Math.Round(intensity * (double)1024 + (color.R - intensity) * (double)satFactor) >> 10); color.G = Utility.ClampToByte((int)Math.Round(intensity * (double)1024 + (color.G - intensity) * (double)satFactor) >> 10); color.B = Utility.ClampToByte((int)Math.Round(intensity * (double)1024 + (color.B - intensity) * (double)satFactor) >> 10); } // adjust lightness if (blendOp != null) color = blendOp.Apply(color); // set alpha color.A = origColor.A; return color; } } Create a new file HslHelper.cs with this, slightly modified from ennixo's code: using System; namespace PaintDotNet { /// /// Lookup tables as a singleton /// public class HslLookup { #region Tableaux /// /// Scales a byte to a float [0..1] /// = (double)i / 255d; /// public readonly double[] Scale255To1Float; /// /// Scales a number [0..4080] to [0..255] /// = (byte)Math.Round((double)i / 16d); /// public readonly byte[] Scale4080To255Byte; #endregion #region Initialisation /// /// Initializes tables /// private HslLookup() { Scale255To1Float = new double[256]; Scale4080To255Byte = new byte[4081]; for (int i = 0; i < 4081; ++i) { Scale4080To255Byte[i] = (byte)Math.Round((double)i / 16d); } for (int i = 0; i < 256; ++i) { Scale255To1Float[i] = (double)i / 255d; } } #endregion #region Static /// /// Singleton of Lookup /// public static readonly HslLookup Current; /// /// Initializes the singleton /// static HslLookup() { Current = new HslLookup(); } #endregion } /// /// HSL/RGB converter /// public static class HslHelper { #region Constants public const int SCALESHIFT = 4; public const int MAX = 255 << SCALESHIFT; public const int HALF = MAX >> 1; private const int MAX2 = MAX << 1; private const int MAX4 = MAX << 2; public const int MAX6 = MAX2 + MAX4; private const int ONESIXTH = MAX / 6; private const int ONETHIRD = MAX / 3; private const int TWOTHIRD = MAX2 / 3; #endregion /// /// Converts an RGB color to an HSL color with scaled numbers /// /// Red 0..255 /// Green 0..255 /// Blue 0..255 /// Hue 0..24480 /// Saturation 0..4080 /// Lightness 0..4080 public static void GetHSL(byte rB, byte gB, byte bB, out int h, out int s, out int l) { int r = rB << SCALESHIFT; int g = gB << SCALESHIFT; int b = bB << SCALESHIFT; int min = r; if (min > g) min = g; if (min > min = b; int max = r; if (max < g) max = g; if (max < max = b; int delta = max - min; l = (max + min) >> 1; if (max == 0 || delta == 0) { s = 0; h = 0; } else { if (l == 0) { s = MAX; } else if (l < HALF) { s = ((delta * MAX) / l) >> 1; } else { s = (((delta * MAX) / (MAX - l))) >> 1; } if (r == max) { h = ((g - * MAX) / delta; } else if (g == max) { h = MAX2 + (((b - r) * MAX) / delta); } else { h = MAX4 + (((r - g) * MAX) / delta); } if (h < 0) { h += MAX6; } } } /// /// Converts an HSL color with scaled numbers to an RGB color /// /// Hue 0..24480 /// Saturation 0..4080 /// Lightness 0..4080 /// Red 0..255 /// Green 0..255 /// Blue 0..255 public static void GetRGB(int h, int s, int l, out byte rB, out byte gB, out byte bB) { HslLookup lut = HslLookup.Current; int q, p, hk, r, g, b; if (l < HALF) { q = (int)(((l * (MAX + s)) * 0x8081L) >> (23 + SCALESHIFT)); } else { q = (l + s) - (int)((((l * s)) * 0x8081L) >> (23 + SCALESHIFT)); } p = (l << 1) - q; hk = (h * 10923) >> 16; r = hk + ONETHIRD; g = hk; b = hk - ONETHIRD; if (r > MAX) r -= MAX; if (b < 0) b += MAX; if (r < ONESIXTH) { r = p + (int)((((q - p) * 6 * r) * 0x8081L) >> (23 + SCALESHIFT)); } else if (r < HALF) { r = q; } else if (r < TWOTHIRD) { r = p + (int)((((q - p) * 6 * (TWOTHIRD - r)) * 0x8081L) >> (23 + SCALESHIFT)); } else { r = p; } if (g < ONESIXTH) { g = p + (int)((((q - p) * 6 * g) * 0x8081L) >> (23 + SCALESHIFT)); } else if (g < HALF) { g = q; } else if (g < TWOTHIRD) { g = p + (int)((((q - p) * 6 * (TWOTHIRD - g)) * 0x8081L) >> (23 + SCALESHIFT)); } else { g = p; } if (b < ONESIXTH) { b = p + (int)((((q - p) * 6 * * 0x8081L) >> (23 + SCALESHIFT)); } else if (b < HALF) { b = q; } else if (b < TWOTHIRD) { b = p + (int)((((q - p) * 6 * (TWOTHIRD - ) * 0x8081L) >> (23 + SCALESHIFT)); } else { b = p; } rB = lut.Scale4080To255Byte[r]; gB = lut.Scale4080To255Byte[g]; bB = lut.Scale4080To255Byte[b]; } } }
×
×
  • Create New...