/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2017, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.filter.function.color; import java.awt.Color; /** * Support class for color functions, represents a color in HSL space (based on * http://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/) * * @author Andrea Aime - GeoSolutions */ class HSLColor { double hue; double saturation; double lightness; double alpha; /** * Builds a color based on HSLA components * @param hue * @param saturation * @param lightness * @param alpha */ public HSLColor(double hue, double saturation, double lightness) { this(hue, saturation, lightness, 1d); } /** * Builds a color based on HSLA components * @param hue * @param saturation * @param lightness * @param alpha */ public HSLColor(double hue, double saturation, double lightness, double alpha) { this.hue = hue; this.saturation = saturation; this.lightness = lightness; this.alpha = alpha; } /** * Builds the HSL representation of a color * * @param color */ public HSLColor(Color color) { double r = color.getRed() / 255d; double g = color.getGreen() / 255d; double b = color.getBlue() / 255d; alpha = color.getAlpha() / 255d; // min and max rgb double min = Math.min(r, Math.min(g, b)); double max = Math.max(r, Math.max(g, b)); // luminance lightness = (max + min) / 2; // saturation saturation = 0; if (max == min) { saturation = 0; } else if (lightness <= .5f) { saturation = (max - min) / (max + min); } else { saturation = (max - min) / (2 - max - min); } // hue hue = 0; if (max == min) { hue = 0; } else if (max == r) { hue = ((60 * (g - b) / (max - min)) + 360) % 360; } else if (max == g) { hue = (60 * (b - r) / (max - min)) + 120; } else if (max == b) { hue = (60 * (r - g) / (max - min)) + 240; } } public void setHue(double hue) { this.hue = hue; } public void setSaturation(double saturation) { if(saturation < 0) { this.saturation = 0; } else if(saturation > 1) { this.saturation = 1; } else { this.saturation = saturation; } } public void setLightness(double lightness) { this.lightness = lightness; } public void setAlpha(double alpha) { this.alpha = alpha; } public double getHue() { return hue; } public double getSaturation() { return saturation; } public double getLightness() { return lightness; } public double getAlpha() { return alpha; } /** * Turns the HSL representation into a RGB one * * @return */ public Color toRGB() { double q = 0; if (lightness < 0.5) { q = lightness * (1 + saturation); } else { q = (lightness + saturation) - (saturation * lightness); } double p = 2 * lightness - q; double r = Math.max(0, hueToRGB(p, q, hue / 360 + (1f / 3f))); double g = Math.max(0, hueToRGB(p, q, hue / 360)); double b = Math.max(0, hueToRGB(p, q, hue / 360 - (1f / 3f))); r = Math.min(r, 1.0f); g = Math.min(g, 1.0f); b = Math.min(b, 1.0f); return new Color((int) Math.round(r * 255), (int) Math.round(g * 255), (int) Math.round(b * 255), (int) Math.round(alpha * 255)); } private double hueToRGB(double p, double q, double h) { if (h < 0) { h += 1; } else if (h > 1) { h -= 1; } if (6 * h < 1) { return p + ((q - p) * 6 * h); } if (2 * h < 1) { return q; } if (3 * h < 2) { return p + ((q - p) * 6 * ((2.0f / 3.0f) - h)); } return p; } @Override public String toString() { return "HSLColor [" + hue + "," + saturation + "," + lightness + "," + alpha + "]"; } }