/// <summary> /// Returns the nearest color in the palette /// </summary> public Color GetNearestColor(Color[] palette, Color color, ColorMatchMode colorMatchMode, float threshold, ColorEntry[] colorOperations, bool enableColorAdjustments, ColorAdjustments colorAdjustments) { if (colorOperations != null && colorOperations.Length > 0) { HSLColor hsl = ColorConversion.GetHSLFromRGB(color.r, color.g, color.b); for (int k = 0; k < colorOperations.Length; k++) { switch (colorMatchMode) { case ColorMatchMode.RGB: { float dr = colorOperations[k].color.r < color.r ? color.r - colorOperations[k].color.r : colorOperations[k].color.r - color.r; float dg = colorOperations[k].color.g < color.g ? color.g - colorOperations[k].color.g : colorOperations[k].color.g - color.g; float db = colorOperations[k].color.b < color.b ? color.b - colorOperations[k].color.b : colorOperations[k].color.b - color.b; if (dr <= threshold && dg <= threshold && db <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; case ColorMatchMode.Red: { float dr = colorOperations[k].color.r < color.r ? color.r - colorOperations[k].color.r : colorOperations[k].color.r - color.r; if (dr <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; case ColorMatchMode.Green: { float dg = colorOperations[k].color.g < color.g ? color.g - colorOperations[k].color.g : colorOperations[k].color.g - color.g; if (dg <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; case ColorMatchMode.Blue: { float db = colorOperations[k].color.b < color.b ? color.b - colorOperations[k].color.b : colorOperations[k].color.b - color.b; if (db <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; case ColorMatchMode.HSL: { HSLColor hslOp = ColorConversion.GetHSLFromRGB(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b); float dh = hslOp.h < hsl.h ? hsl.h - hslOp.h : hslOp.h - hsl.h; float ds = hslOp.s < hsl.s ? hsl.s - hslOp.s : hslOp.s - hsl.s; float dl = hslOp.l < hsl.l ? hsl.l - hslOp.l : hslOp.l - hsl.l; if (dh <= threshold && ds <= threshold && dl <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; case ColorMatchMode.Hue: { float hue = ColorConversion.GetHue(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b); float dh = hue < hsl.h ? hsl.h - hue : hue - hsl.h; if (dh <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; case ColorMatchMode.Saturation: { float sat = ColorConversion.GetSaturation(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b); float ds = sat < hsl.s ? hsl.s - sat : sat - hsl.s; if (ds <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; case ColorMatchMode.Lightness: { float l = ColorConversion.GetLightness(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b); float dl = l < hsl.l ? hsl.l - l : l - hsl.l; if (dl <= threshold) { if (colorOperations[k].operation == ColorOperation.Preserve) { return(color); } else if (colorOperations[k].operation == ColorOperation.Replace) { return(colorOperations[k].replaceColor); } } } break; } } } float md = float.MaxValue; Color nearest = color; switch (colorMatchMode) { case ColorMatchMode.RGB: { for (int c = 0; c < palette.Length; c++) { float dr = (palette[c].r - color.r) * 0.299f; float dg = (palette[c].g - color.g) * 0.587f; float db = (palette[c].b - color.b) * 0.114f; float d = dr * dr + dg * dg + db * db; if (d < md) { md = d; nearest = palette[c]; } } } break; case ColorMatchMode.Red: { for (int c = 0; c < palette.Length; c++) { float dr = palette[c].r - color.r; float d = dr * dr; if (d < md) { md = d; nearest = palette[c]; } } } break; case ColorMatchMode.Green: { for (int c = 0; c < palette.Length; c++) { float dg = palette[c].g - color.g; float d = dg * dg; if (d < md) { md = d; nearest = palette[c]; } } } break; case ColorMatchMode.Blue: { for (int c = 0; c < palette.Length; c++) { float db = palette[c].b - color.b; float d = db * db; if (d < md) { md = d; nearest = palette[c]; } } } break; case ColorMatchMode.HSL: { HSLColor hsl = ColorConversion.GetHSLFromRGB(color.r, color.g, color.b); for (int c = 0; c < palette.Length; c++) { HSLColor paletteHSL = ColorConversion.GetHSLFromRGB(palette[c].r, palette[c].g, palette[c].b); float dh = (paletteHSL.h - hsl.h); float ds = (paletteHSL.s - hsl.s); float dl = (paletteHSL.l - hsl.l); float d = dh * dh + ds * ds + dl * dl; if (d < md) { md = d; nearest = palette[c]; } } } break; case ColorMatchMode.Hue: { float h = ColorConversion.GetHue(color.r, color.g, color.b); for (int c = 0; c < palette.Length; c++) { float paletteH = ColorConversion.GetHue(palette[c].r, palette[c].g, palette[c].b); float dh = (paletteH - h); float d = dh * dh; if (d < md) { md = d; nearest = palette[c]; } } } break; case ColorMatchMode.Saturation: { float s = ColorConversion.GetSaturation(color.r, color.g, color.b); for (int c = 0; c < palette.Length; c++) { float paletteS = ColorConversion.GetSaturation(palette[c].r, palette[c].g, palette[c].b); float dh = (paletteS - s); float d = dh * dh; if (d < md) { md = d; nearest = palette[c]; } } } break; case ColorMatchMode.Lightness: { float l = ColorConversion.GetLightness(color.r, color.g, color.b); for (int c = 0; c < palette.Length; c++) { float paletteL = ColorConversion.GetLightness(palette[c].r, palette[c].g, palette[c].b); float dh = (paletteL - l); float d = dh * dh; if (d < md) { md = d; nearest = palette[c]; } } } break; } nearest.a = color.a; color = nearest; if (enableColorAdjustments) { if (colorAdjustments.applyLUT && colorAdjustments.LUT != null) { color = ApplyLUT(color, colorAdjustments.LUT); } // vibrance float vibrance = colorAdjustments.vibrance; if (vibrance > 0) { float maxComponent = color.r > color.g ? color.r : color.g; maxComponent = color.b > maxComponent ? color.b : maxComponent; float minComponent = color.r < color.g ? color.r : color.g; minComponent = color.b < minComponent ? color.b : minComponent; float sat = maxComponent - minComponent; if (sat < 0) { sat = 0; } else if (sat > 1f) { sat = 1f; } float luma = color.GetLuma(); color.r *= 1f + vibrance * (1f - sat) * (color.r - luma); color.g *= 1f + vibrance * (1f - sat) * (color.g - luma); color.b *= 1f + vibrance * (1f - sat) * (color.b - luma); } // tinting float tintAmount = colorAdjustments.tintAmount; if (tintAmount > 0) { Color tintedColor = new Color(color.r * colorAdjustments.tintColor.r, color.g * colorAdjustments.tintColor.g, color.b * colorAdjustments.tintColor.b); color = Color.Lerp(color, tintedColor, tintAmount); } // contrast float contrast = colorAdjustments.contrast + 1f; if (contrast != 1f) { color.r = (color.r - 0.5f) * contrast + 0.5f; color.g = (color.g - 0.5f) * contrast + 0.5f; color.b = (color.b - 0.5f) * contrast + 0.5f; } // brightness float brightness = colorAdjustments.brightness + 1f; if (brightness != 1f) { color.r *= brightness; color.g *= brightness; color.b *= brightness; } } return(color); }
Color GetTransformedColor(Color originalColor) { switch (currentBrush) { case Brush.Darken: { if (originalColor.a == 0) { return(originalColor); } HSLColor hsl = ColorConversion.GetHSLFromRGB(originalColor.r, originalColor.g, originalColor.b); hsl.l -= 0.05f; if (hsl.l < 0.01f) { hsl.l = 0.01f; } return(ColorConversion.GetColorFromHSL(hsl.h, hsl.s, hsl.l)); } case Brush.Lighten: { if (originalColor.a == 0) { return(originalColor); } HSLColor hsl = ColorConversion.GetHSLFromRGB(originalColor.r, originalColor.g, originalColor.b); hsl.l += 0.05f; if (hsl.l > 0.99f) { hsl.l = 0.99f; } return(ColorConversion.GetColorFromHSL(hsl.h, hsl.s, hsl.l)); } case Brush.Dry: { if (originalColor.a == 0) { return(originalColor); } HSLColor hsl = ColorConversion.GetHSLFromRGB(originalColor.r, originalColor.g, originalColor.b); hsl.s -= 0.05f; if (hsl.s < 0.01f) { hsl.s = 0.01f; } return(ColorConversion.GetColorFromHSL(hsl.h, hsl.s, hsl.l)); } case Brush.Vivid: { if (originalColor.a == 0) { return(originalColor); } HSLColor hsl = ColorConversion.GetHSLFromRGB(originalColor.r, originalColor.g, originalColor.b); hsl.s += 0.05f; if (hsl.s > 0.99f) { hsl.s = 0.99f; } return(ColorConversion.GetColorFromHSL(hsl.h, hsl.s, hsl.l)); } case Brush.Noise: { if (originalColor.a == 0) { return(originalColor); } HSLColor hsl = ColorConversion.GetHSLFromRGB(originalColor.r, originalColor.g, originalColor.b); hsl.l += Random.value * 0.1f - 0.05f; if (hsl.l > 0.99f) { hsl.l = 0.99f; } else if (hsl.l < 0.01f) { hsl.l = 0.01f; } return(ColorConversion.GetColorFromHSL(hsl.h, hsl.s, hsl.l)); } case Brush.NoiseTone: { if (originalColor.a == 0) { return(originalColor); } HSLColor hsl = ColorConversion.GetHSLFromRGB(originalColor.r, originalColor.g, originalColor.b); hsl.h += Random.value * 0.1f - 0.05f; if (hsl.h > 0.99f) { hsl.l = 0.99f; } else if (hsl.h < 0.01f) { hsl.h = 0.01f; } return(ColorConversion.GetColorFromHSL(hsl.h, hsl.s, hsl.l)); } case Brush.Gradient: { HSLColor hsl = ColorConversion.GetHSLFromRGB(_brushColor.r, _brushColor.g, _brushColor.b); int distance = Mathf.Max(Mathf.Abs(startTexelPos.x - currentTexelPos.x), Mathf.Abs(startTexelPos.y - currentTexelPos.y)); if (distance > 0) { hsl.l -= 0.05f * distance; if (hsl.l < 0.01f) { hsl.l = 0.01f; } return(ColorConversion.GetColorFromHSL(hsl.h, hsl.s, hsl.l)); } return(_brushColor); } } return(_brushColor); }