/* ChibiPaint Copyright (c) 2006-2008 Marc Schefer This file is part of ChibiPaint. ChibiPaint 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. ChibiPaint 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 ChibiPaint. If not, see <http://www.gnu.org/licenses/>. */ package com.chibipaint.util; public class CPColor implements Cloneable { public int rgb; public int hue, saturation, value; public CPColor() { setRgb(0); } public CPColor(int rgb) { setRgb(rgb); } public CPColor(int hue, int saturation, int value) { setHsv(hue, saturation, value); } public void setRgb(int rgb) { this.rgb = rgb; rgbToHsv(); } public void setHsv(int hue, int value, int saturation) { this.hue = hue; this.saturation = saturation; this.value = value; hsvToRgb(); } void rgbToHsv() { int r = rgb >> 16; int g = rgb >> 8 & 0xff; int b = rgb & 0xff; // Value value = Math.max(r, Math.max(g, b)); // Saturation int mini = Math.min(r, Math.min(g, b)); if (value == 0) saturation = 0; else saturation = (int) ((float) (value - mini) / (float) value * 255.f); // Hue if (saturation == 0) hue = 0; else { float cr = (float) (value - r) / (float) (value - mini); float cg = (float) (value - g) / (float) (value - mini); float cb = (float) (value - b) / (float) (value - mini); float _hue = 0; if (value == r) _hue = cb - cg; if (value == g) _hue = 2 + cr - cb; if (value == b) _hue = 4 + cg - cr; _hue *= 60; if (_hue < 0) _hue += 360; hue = (int) _hue; } } void hsvToRgb() { // no saturation means it's just a shade of grey if (saturation == 0) rgb = value << 16 | value << 8 | value; float f = hue / 60.f; f = f - (float) Math.floor(f); float s = saturation / 255.f; int m = (int) (value * (1 - s)); int n = (int) (value * (1 - s * f)); int k = (int) (value * (1 - s * (1 - f))); switch (hue / 60) { case 0: rgb = value << 16 | k << 8 | m; break; case 1: rgb = n << 16 | value << 8 | m; break; case 2: rgb = m << 16 | value << 8 | k; break; case 3: rgb = m << 16 | n << 8 | value; break; case 4: rgb = k << 16 | m << 8 | value; break; case 5: rgb = value << 16 | m << 8 | n; break; default: rgb = 0; // invalid hue break; } } public void setHue(int hue) { this.hue = hue; hsvToRgb(); } public void setSaturation(int saturation) { this.saturation = saturation; hsvToRgb(); } public void setValue(int value) { this.value = value; hsvToRgb(); } public int getRgb() { return rgb; } public int getHue() { return hue; } public int getSaturation() { return saturation; } public int getValue() { return value; } @Override public Object clone() { try { return super.clone(); } catch (Exception ignored) { throw new Error("Uh oh"); } } public void copyFrom(CPColor c) { rgb = c.rgb; hue = c.hue; saturation = c.saturation; value = c.value; } public boolean isEqual(CPColor color) { return rgb == color.rgb && hue == color.hue && saturation == color.saturation && value == color.value; } }