/** * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.md file. */ package org.mule.module.hue; import org.mule.util.StringUtils; import java.awt.*; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * A set of utilities to convert between CIE XYX and RGB */ public class ColourUtils { private static final Map<String, Color> COLOUR_MAP; static { COLOUR_MAP = loadColourMap(); } private static Map<String, java.awt.Color> loadColourMap() { try { final Map<String, java.awt.Color> colorMap = new HashMap<String, Color>(); for (final Field f : java.awt.Color.class.getFields()) { if (f.getType() == java.awt.Color.class) { final java.awt.Color c = (java.awt.Color) f.get(null); colorMap.put(f.getName().toUpperCase(), c); } } return colorMap; } catch (final IllegalAccessException iae) { throw new RuntimeException(iae); } } final static double[] scaleValues(double min, double max, double... vals) { double[] result = new double[vals.length]; double scaleFactor = max - min; for (int x = 0; x < vals.length; x++) { result[x] = ((vals[x] - min) / scaleFactor); } return result; } public static double[] colorToXyz(Color color) { return rgbToXyz(color.getRed(), color.getGreen(), color.getBlue()); } public static double[] rgbToXyz(int r, int g, int b) { double[] rgb = scaleValues(0, 255, r, g, b); double red = rgb[0]; double green = rgb[1]; double blue = rgb[2]; //Apply a gamma correction to the RGB values, which makes the color more vivid double _red = (red > 0.04045f) ? Math.pow((red + 0.055f) / (1.0f + 0.055f), 2.4f) : (red / 12.92f); double _green = (green > 0.04045f) ? Math.pow((green + 0.055f) / (1.0f + 0.055f), 2.4f) : (green / 12.92f); double _blue = (blue > 0.04045f) ? Math.pow((blue + 0.055f) / (1.0f + 0.055f), 2.4f) : (blue / 12.92f); //Convert the RGB values to XYZ using the Wide RGB D65 conversion formula double X = _red * 0.649926f + _green * 0.103455f + _blue * 0.197109f; double Y = _red * 0.234327f + _green * 0.743075f + _blue * 0.022598f; double Z = _red * 0.0000000f + _green * 0.053077f + _blue * 1.035763f; return new double[]{X, Y, Z}; } public static double[] XyzToXy(double... vals) { double[] result = new double[2]; result[0] = vals[0] / (vals[0] + vals[1] + vals[2]); result[1] = vals[1] / (vals[0] + vals[1] + vals[2]); return result; } /** * Decode an HTML color string like '#F567BA;' into a {@link Color} * * @param colourString The string to decode * @return The decoded color * @throws IllegalArgumentException if the color sequence is not valid */ public static Color decodeHtmlColorString(String colourString) { Color color; if (colourString.startsWith("#")) { colourString = colourString.substring(1); } if (colourString.endsWith(";")) { colourString = colourString.substring(0, colourString.length() - 1); } int red, green, blue; switch (colourString.length()) { case 6 : red = Integer.parseInt(colourString.substring(0, 2), 16); green = Integer.parseInt(colourString.substring(2, 4), 16); blue = Integer.parseInt(colourString.substring(4, 6), 16); color = new Color(red, green, blue); break; case 3 : red = 17 * Integer.parseInt(colourString.substring(0, 1), 16); green = 17 * Integer.parseInt(colourString.substring(1, 2), 16); blue = 17 * Integer.parseInt(colourString.substring(2, 3), 16); color = new Color(red, green, blue); break; case 1 : red = green = blue = 17 * Integer.parseInt(colourString.substring(0, 1), 16); color = new Color(red, green, blue); break; default : throw new IllegalArgumentException("Invalid color: " + colourString); } return color; } public static java.awt.Color parseColour(final String colourString) { if (StringUtils.equalsIgnoreCase(colourString, "on")) { return java.awt.Color.WHITE; } else if (StringUtils.equalsIgnoreCase(colourString, "off")) { return java.awt.Color.BLACK; } else if (StringUtils.startsWith(colourString, "#")) { return ColourUtils.decodeHtmlColorString(colourString); } final java.awt.Color color = COLOUR_MAP.get(StringUtils.upperCase(colourString)); if (color == null) { throw new IllegalArgumentException("Invalid color: " + colourString); } else { return color; } } public static List<Double> getXYForColour(String colour) { Color c = parseColour(colour); List<Double> xyList = new ArrayList<Double>(2); double[] xyz = colorToXyz(c); double[] xy = XyzToXy(xyz); xyList.add(xy[0]); xyList.add(xy[1]); return xyList; } }