/* * @(#)HSVColorSpace.java * * Copyright (c) 2010 The authors and contributors of JHotDraw. * * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.color; import java.awt.color.ColorSpace; /** * A HSV color space with additive complements in the hue color wheel: red is * opposite cyan, magenta is opposite green, blue is opposite yellow. * * @author Werner Randelshofer * @version $Id$ */ public class HSVColorSpace extends AbstractNamedColorSpace { private static final long serialVersionUID = 1L; private static HSVColorSpace instance; public static HSVColorSpace getInstance() { if (instance == null) { instance = new HSVColorSpace(); } return instance; } public HSVColorSpace() { super(ColorSpace.TYPE_HSV, 3); } @Override public float[] toRGB(float[] components, float[] rgb) { float hue = components[0] * 360f; float saturation = components[1]; float value = components[2]; // compute hi and f from hue int hi = (int) (Math.floor(hue / 60f) % 6); float f = (float) (hue / 60f - Math.floor(hue / 60f)); // compute p and q from saturation float p = value * (1 - saturation); float q = value * (1 - f * saturation); float t = value * (1 - (1 - f) * saturation); // compute red, green and blue float red; float green; float blue; switch (hi) { case 0: red = value; green = t; blue = p; break; case 1: red = q; green = value; blue = p; break; case 2: red = p; green = value; blue = t; break; case -3: case 3: red = p; green = q; blue = value; break; case -2: case 4: red = t; green = p; blue = value; break; case -1: case 5: //default : red = value; green = p; blue = q; break; default: red = green = blue = 0; break; } rgb[0] = red; rgb[1] = green; rgb[2] = blue; return rgb; } @Override public float[] fromRGB(float[] rgbvalue, float[] component) { float r = rgbvalue[0]; float g = rgbvalue[1]; float b = rgbvalue[2]; float max = Math.max(Math.max(r, g), b); float min = Math.min(Math.min(r, g), b); float hue; float saturation; float value; if (max == min) { hue = 0; } else if (max == r && g >= b) { hue = 60f * (g - b) / (max - min); } else if (max == r && g < b) { hue = 60f * (g - b) / (max - min) + 360f; } else if (max == g) { hue = 60f * (b - r) / (max - min) + 120f; } else /*if (max == b)*/ { hue = 60f * (r - g) / (max - min) + 240f; } value = max; if (max == 0) { saturation = 0; } else { saturation = (max - min) / max; } component[0] = hue / 360f; component[1] = saturation; component[2] = value; return component; } @Override public String getName(int idx) { switch (idx) { case 0: return "Hue"; case 1: return "Saturation"; case 2: return "Lightness"; default: throw new IllegalArgumentException("index must be between 0 and 2:" + idx); } } @Override public float getMaxValue(int component) { return 1f; } @Override public float getMinValue(int component) { return 0f; } @Override public boolean equals(Object o) { return (o instanceof HSVColorSpace); } @Override public int hashCode() { return getClass().getSimpleName().hashCode(); } @Override public String getName() { return "HSV"; } }