/* Copyright (c) 2012 Jesper Öqvist <jesper@llbit.se>
*
* This file is part of Chunky.
*
* Chunky is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chunky 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Chunky. If not, see <http://www.gnu.org/licenses/>.
*/
package se.llbit.math;
import javafx.scene.paint.Color;
import org.apache.commons.math3.util.FastMath;
import se.llbit.chunky.renderer.scene.Scene;
/**
* Collection of utility methods for converting between different color representations.
*
* @author Jesper Öqvist <jesper@llbit.se>
*/
public final class ColorUtil {
private ColorUtil() {
}
/**
* @param c RGB color vector
* @return INT RGB value corresponding to the given color vector
*/
public static int getRGB(Vector3 c) {
return (0xFF << 24) |
((int) (255 * c.x + .5) << 16) |
((int) (255 * c.y + .5) << 8) |
(int) (255 * c.z + .5);
}
/**
* @return INT RGB value corresponding to the given color
*/
public static int getRGB(float r, float g, float b) {
return 0xFF000000 |
((int) (255 * r + .5f) << 16) |
((int) (255 * g + .5f) << 8) |
(int) (255 * b + .5f);
}
/**
* @return INT RGB value corresponding to the given color
*/
public static int getRGB(double r, double g, double b) {
return 0xFF000000 |
((int) (255 * r + .5) << 16) |
((int) (255 * g + .5) << 8) |
(int) (255 * b + .5);
}
/**
* @return INT ARGB value corresponding to the given color
*/
public static int getArgb(float r, float g, float b, float a) {
return ((int) (255 * a + .5f) << 24) |
((int) (255 * r + .5f) << 16) |
((int) (255 * g + .5f) << 8) |
(int) (255 * b + .5f);
}
/**
* @param c RGBA color vector
* @return INT ARGB value corresponding to the given color vector
*/
public static int getArgb(Vector4 c) {
return ((int) (255 * c.w + .5f) << 24) |
((int) (255 * c.x + .5f) << 16) |
((int) (255 * c.y + .5f) << 8) |
(int) (255 * c.z + .5f);
}
/**
* @param c RGB color vector
* @return INT RGB value corresponding to the given color vector
*/
public static int getRGB(Vector4 c) {
return 0xFF000000 |
((int) (255 * c.x + .5f) << 16) |
((int) (255 * c.y + .5f) << 8) |
(int) (255 * c.z + .5f);
}
/**
* @return INT ARGB value corresponding to the given color
*/
public static int getArgb(double r, double g, double b, double a) {
return ((int) (255 * a + .5) << 24) |
((int) (255 * r + .5) << 16) |
((int) (255 * g + .5) << 8) |
(int) (255 * b + .5);
}
/**
* Get the RGB color components from an INT RGB value.
*/
public static void getRGBComponents(int irgb, float[] frgb) {
frgb[0] = (0xFF & (irgb >> 16)) / 255.f;
frgb[1] = (0xFF & (irgb >> 8)) / 255.f;
frgb[2] = (0xFF & irgb) / 255.f;
}
/**
* Get the RGB color components from an INT RGB value.
*/
public static void getRGBComponents(int irgb, Vector4 v) {
v.x = (0xFF & (irgb >> 16)) / 255.f;
v.y = (0xFF & (irgb >> 8)) / 255.f;
v.z = (0xFF & irgb) / 255.f;
}
/**
* Get the RGB color components from an INT RGB value.
*/
public static void getRGBComponents(int irgb, double[] frgb) {
frgb[0] = (0xFF & (irgb >> 16)) / 255.0;
frgb[1] = (0xFF & (irgb >> 8)) / 255.0;
frgb[2] = (0xFF & irgb) / 255.0;
}
/**
* Get the RGBA color components from an INT ARGB value.
*/
public static void getRGBAComponents(int irgb, float[] frgb) {
frgb[3] = (irgb >>> 24) / 255.f;
frgb[0] = (0xFF & (irgb >> 16)) / 255.f;
frgb[1] = (0xFF & (irgb >> 8)) / 255.f;
frgb[2] = (0xFF & irgb) / 255.f;
}
/**
* Get the RGBA color components from an INT ARGB value.
*/
public static void getRGBAComponents(int irgb, Vector4 v) {
v.w = (irgb >>> 24) / 255.f;
v.x = (0xFF & (irgb >> 16)) / 255.f;
v.y = (0xFF & (irgb >> 8)) / 255.f;
v.z = (0xFF & irgb) / 255.f;
}
/**
* Get the RGBA color components from an INT ARGB value.
*/
public static void getRGBAComponents(int irgb, Vector3 v) {
v.x = (0xFF & (irgb >> 16)) / 255.f;
v.y = (0xFF & (irgb >> 8)) / 255.f;
v.z = (0xFF & irgb) / 255.f;
}
/**
* Get the RGBA color components from an INT ARGB value.
*/
public static void getRGBAComponents(int irgb, double[] frgb) {
frgb[3] = (irgb >>> 24) / 255.0;
frgb[0] = (0xFF & (irgb >> 16)) / 255.0;
frgb[1] = (0xFF & (irgb >> 8)) / 255.0;
frgb[2] = (0xFF & irgb) / 255.0;
}
/**
* @return Get INT RGB value corresponding to the given color
*/
public static int getRGB(float[] frgb) {
return 0xFF000000 |
((int) (255 * frgb[0] + .5f) << 16) |
((int) (255 * frgb[1] + .5f) << 8) |
(int) (255 * frgb[2] + .5f);
}
/**
* @return Get INT RGB value corresponding to the given color
*/
public static int getRGB(double[] frgb) {
return 0xFF000000 |
((int) (255 * frgb[0] + .5) << 16) |
((int) (255 * frgb[1] + .5) << 8) |
(int) (255 * frgb[2] + .5);
}
/**
* Transform from xyY colorspace to XYZ colorspace.
*/
public static void xyYtoXYZ(Vector3 in, Vector3 out) {
if (in.y <= Ray.EPSILON) {
out.set(0, 0, 0);
return;
}
double f = (in.z / in.y);
out.x = in.x * f;
out.z = (1 - in.x - in.y) * f;
out.y = in.z;
}
/**
* http://www.w3.org/Graphics/Color/sRGB
*/
public static void XYZtoRGB(Vector3 in, Vector3 out) {
out.x = 3.2410 * in.x - 1.5374 * in.y - 0.4986 * in.z;
out.y = -0.9692 * in.x + 1.8760 * in.y + 0.0416 * in.z;
out.z = 0.0556 * in.x - 0.2040 * in.y + 1.0570 * in.z;
}
/**
* Convert color components to linear color space
*/
public static void toLinear(float[] components) {
for (int i = 0; i < components.length; ++i) {
components[i] = (float) FastMath.pow(components[i], Scene.DEFAULT_GAMMA);
}
}
public static String toString(double r, double g, double b) {
int rgb = getRGB(r, g, b);
return String.format("%02X%02X%02X", (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
}
public static String toString(Vector3 color) {
int rgb = getRGB(color.x, color.y, color.z);
return String.format("%02X%02X%02X", (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
}
public static void RGBfromHSL(Vector3 rgb, double hue, double saturation, double lightness) {
double c = Math.min(1, (1 - Math.abs(2 * lightness - 1)) * saturation);
double h = hue * 6;
double x = c * (1 - Math.abs(h % 2 - 1));
if (h < 1) {
rgb.set(c, x, 0);
} else if (h < 2) {
rgb.set(x, c, 0);
} else if (h < 3) {
rgb.set(0, c, x);
} else if (h < 4) {
rgb.set(0, x, c);
} else if (h < 5) {
rgb.set(x, 0, c);
} else {
rgb.set(c, 0, x);
}
double m = Math.max(0, lightness - 0.5 * c);
rgb.x += m;
rgb.y += m;
rgb.z += m;
}
public static Vector3 RGBfromHSL(double hue, double saturation, double lightness) {
double c = Math.min(1, (1 - Math.abs(2 * lightness - 1)) * saturation);
double h = hue * 6;
double x = c * (1 - Math.abs(h % 2 - 1));
Vector3 rgb;
if (h < 1) {
rgb = new Vector3(c, x, 0);
} else if (h < 2) {
rgb = new Vector3(x, c, 0);
} else if (h < 3) {
rgb = new Vector3(0, c, x);
} else if (h < 4) {
rgb = new Vector3(0, x, c);
} else if (h < 5) {
rgb = new Vector3(x, 0, c);
} else {
rgb = new Vector3(c, 0, x);
}
double m = Math.max(0, lightness - 0.5 * c);
rgb.x += m;
rgb.y += m;
rgb.z += m;
return rgb;
}
public static java.awt.Color toAWT(Vector3 color) {
return new java.awt.Color((float) color.x, (float) color.y, (float) color.z);
}
public static void fromString(String text, int radix, Vector3 color)
throws NumberFormatException {
int rgb = Integer.parseInt(text, radix);
ColorUtil.getRGBAComponents(rgb, color);
}
public static javafx.scene.paint.Color toFx(Vector3 color) {
return new javafx.scene.paint.Color(color.x, color.y, color.z, 1);
}
public static Vector3 fromFx(javafx.scene.paint.Color color) {
return new Vector3(color.getRed(), color.getGreen(), color.getBlue());
}
public static Color toFx(int argb) {
double[] rgba = new double[4];
getRGBAComponents(argb, rgba);
return Color.color(rgba[0], rgba[1], rgba[2], rgba[3]);
}
}