private float MinimizeError( PaletteGenerator generator, List <PaletteEntry> ramp, Range <float> range, Func <PaletteParameters, float, float> function) { const int count = 20; const int iterations = 3; List <Tuple <float, float> > errors = null; int index = -1; for (int i = 0; i < iterations; i++) { errors = Errors(generator, ramp, range, count, function); float min = errors.Min(x => x.Item2); index = errors.FindIndex(x => x.Item2 == min); // Get the indices above and below the minimum value int step = Math.Max(1, (int)(count * 0.3f) / 2); int startIndex = Math.Max(0, index - step); startIndex = Math.Min(count - step * 2, startIndex); int endIndex = startIndex + step * 2; range = new Range <float>(errors[startIndex].Item1, errors[endIndex].Item1); } return(errors[index].Item1); }
public GeneratedColorPalette( PaletteGenerator generator, PaletteParameters parameters) { // Adjust base color up if black level is too close to it XnaHSL baseColor = AdjustBaseColor(parameters.BaseColor, generator.BlackLevel); // Tint just a little toward yellow based on yellow light XnaHSL untintedBaseColor = baseColor; if (baseColor.Saturation > 0) { baseColor = baseColor.LerpHue(60, parameters.YellowLight * 0.075f); } XnaHSL highlight, specular; GetHighlight(baseColor, generator, parameters, out highlight, out specular); XnaHSL shadow, darkest; GetShadow(untintedBaseColor, generator, parameters, out shadow, out darkest); // Set the calculated values BaseColor = baseColor; Darkest = darkest; Shadow = shadow; Highlight = highlight; Specular = specular; ReducedDepth = parameters.ReducedDepth; }
private List <Tuple <float, float> > Errors( PaletteParameters parameters, List <PaletteEntry> ramp, Range <float> range, int count, Func <PaletteGenerator, float, float> function) { PaletteGenerator copyGenerator = (PaletteGenerator)Clone(); PaletteParameters copyParameters = (PaletteParameters)parameters.Clone(); float interval = (range.Maximum - range.Minimum) / count; var errors = new List <Tuple <float, float> >(); for (int i = 0; i <= count; i++) { float value = range.Minimum + interval * i; function(copyGenerator, value); // Kind of necessary for user facing values // Minimize error on blue shadow copyParameters.MinimizeBlueError(copyGenerator, ramp); // Minimize error on yellow light copyParameters.MinimizeYellowError(copyGenerator, ramp); var palette = copyGenerator.GetPalette(copyParameters); float error = palette.GetError(ramp); errors.Add(Tuple.Create(value, error)); } return(errors); }
internal void MinimizeBlueError(PaletteGenerator generator, List <PaletteEntry> ramp) { var range = BlueRange(); Func <PaletteParameters, float, float> function = (PaletteParameters parameters, float value) => parameters.BlueShadow = value; float minimum = MinimizeError(generator, ramp, range, function); BlueShadow = minimum; }
internal void MinimizeYellowError(PaletteGenerator generator, List <PaletteEntry> ramp) { var range = YellowRange(); Func <PaletteParameters, float, float> function = (PaletteParameters parameters, float value) => parameters.YellowLight = value; float minimum = MinimizeError(generator, ramp, range, function); YellowLight = minimum; }
internal PaletteRamp(string name, Color darkestColor) { Name = name; _BaseColorIndex = 0; _Colors = new List <Color>(); _Adjustments = new List <ColorVector>(); Generator = new PaletteGenerator(); BlueYellowAdjustments = true; SetBlackLevel(darkestColor); }
public override void CopyFrom(TactileDataContent other) { CheckSameClass(other); var source = (PaletteRamp)other; Name = source.Name; _BaseColorIndex = source._BaseColorIndex; _Colors = new List <Color>(source._Colors); _Adjustments = new List <ColorVector>(source._Adjustments); Generator = (PaletteGenerator)source.Generator.Clone(); BlueYellowAdjustments = source.BlueYellowAdjustments; }
private static void GetHighlight( XnaHSL baseHSL, PaletteGenerator generator, PaletteParameters parameters, out XnaHSL highlight, out XnaHSL specular) { Color baseSpecular = PaletteGenerator.BaseSpecularColor(baseHSL.GetColor()); // Tint yellow XnaHSL specularHSL = new XnaHSL(baseSpecular); // If greyscale, simply treat the hue as yellow if (float.IsNaN(specularHSL.Hue)) { specularHSL = specularHSL.SetHue(60); } specularHSL = specularHSL.LerpHue(60, parameters.YellowLight); specularHSL = specularHSL.SetSaturation(MathHelper.Lerp( specularHSL.Saturation, 1f, parameters.YellowLight)); specularHSL = specularHSL.SetLightness(MathHelper.Lerp( specularHSL.Lightness, Math.Max(0.5f, specularHSL.Lightness), parameters.YellowLight)); // Add specular specularHSL = specularHSL.SetLightness(MathHelper.Lerp( specularHSL.Lightness, 1f, generator.Specularity)); // Reduce the lightness if the base color is darker than the generator color if (generator.BaseLightness > 0 && baseHSL.Lightness < generator.BaseLightness) { float lightnessDiff = generator.BaseLightness - baseHSL.Lightness; specularHSL = specularHSL.SetLightness(specularHSL.Lightness - (lightnessDiff)); } float highlightAmount = 0.5f; // If the base color is sufficiently bright, lighten the specular // to keep the contrast from getting too low float lightnessRatio = (baseHSL.Lightness - 0.5f) * 2f; if (lightnessRatio > 0) { specularHSL = specularHSL.SetLightness( MathHelper.Lerp(specularHSL.Lightness, 1f, lightnessRatio)); highlightAmount = MathHelper.Lerp(0.5f, 1f, lightnessRatio); } // Get highlight XnaHSL highlightHSL = XnaHSL.Lerp(baseHSL, specularHSL, highlightAmount); highlight = highlightHSL; specular = specularHSL; }
private static void GetShadow( XnaHSL baseHSL, PaletteGenerator generator, PaletteParameters parameters, out XnaHSL shadow, out XnaHSL darkest) { XnaHSL blackHSL = new XnaHSL( baseHSL.Hue, baseHSL.Saturation * generator.ShadowAmount, generator.BlackLevel, baseHSL.Alpha); // If the base color is sufficiently bright, lighten the darker shades float lightnessRatio = (baseHSL.Lightness - 0.5f) * 2f; if (lightnessRatio > 0) { blackHSL = blackHSL.SetSaturation(blackHSL.Saturation * (1f - lightnessRatio * 0.95f)); float blackLuma = Color_Util.GetLuma(blackHSL.GetColor()); // Increase the lightness by more if it's a color with a low // luma to lightness ratio float lumaRatio = 1f; if (blackLuma > 0) { lumaRatio = blackHSL.Lightness / blackLuma; } blackHSL = blackHSL.SetLightness( MathHelper.Lerp(blackHSL.Lightness, MathHelper.Lerp(blackHSL.Lightness, 1f, 0.25f), lightnessRatio * lumaRatio)); } // Tint black and shadow blue blackHSL = blackHSL.LerpHue(240, parameters.BlueShadow); blackHSL = blackHSL.SetSaturation(MathHelper.Lerp(blackHSL.Saturation, 1f, parameters.BlueShadow / 4f)); XnaHSL shadowHSL = XnaHSL.Lerp(blackHSL, baseHSL, generator.ShadowAmount); shadowHSL = shadowHSL.SetSaturation(MathHelper.Lerp(blackHSL.Saturation, baseHSL.Saturation, 0.5f)); shadowHSL = shadowHSL.SetHue(blackHSL.Hue); shadowHSL = shadowHSL.LerpHue(baseHSL.Hue, 0.25f); shadow = shadowHSL; darkest = blackHSL; }
private List <Tuple <float, float> > Errors( PaletteGenerator generator, List <PaletteEntry> ramp, Range <float> range, int count, Func <PaletteParameters, float, float> function) { PaletteParameters copyParameters = (PaletteParameters)Clone(); float interval = (range.Maximum - range.Minimum) / count; var errors = new List <Tuple <float, float> >(); for (int i = 0; i <= count; i++) { float value = range.Minimum + interval * i; function(copyParameters, value); var palette = generator.GetPalette(copyParameters); float error = palette.GetError(ramp); errors.Add(Tuple.Create(value, error)); } return(errors); }
private PaletteGenerator(PaletteGenerator source) { CopyFrom(source); }