/* * Moonlight|3D Copyright (C) 2005 The Moonlight|3D team * * 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; either version 2.1 of the License, or (at your option) * any later version. * * 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. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Created on Aug 21, 2005 */ package eu.moonlight3d.colour; /** * \package eu.moonlight3d.colour * * This is an assortment of utility classes for colour processing. * * This package is part of the core program. */ /** * A class representing colour values. It contains various methods * for converting colour values betweeen different standard colour * spaces and representations. * * @author gregor */ public class Colour implements Cloneable { /** * The colour's red value */ public double red; /** * The colour's green value */ public double green; /** * The colour's blue value */ public double blue; /** * The colour's alpha value */ public double alpha; /** * Integer RGBA values used for storing discreet values, usually in the * range of 0-255 for 8 bit colour depth. * * @author gregor */ public class RGB { /** * The colour's red value */ public int red; /** * The colour's green value */ public int green; /** * The colour's blue value */ public int blue; /** * The colour's alpha value */ public int alpha; } /** * Default constructor */ public Colour() { red=0; green=0; blue=0; alpha=0; } /** * Constructor initializing the instance from its arguments * * @param red red value * @param green green value * @param blue blue value * @param alpha alpha value */ public Colour(double red, double green, double blue, double alpha) { this.red=red; this.green=green; this.blue=blue; this.alpha=alpha; } /** * Constructor initializing the instance from its arguments. Alpha * is initialized to 1. * * @param red red value * @param green green value * @param blue blue value * @param alpha alpha value */ public Colour(double red, double green, double blue) { this.red=red; this.green=green; this.blue=blue; this.alpha=1; } @Override public Colour clone() { Colour c=new Colour(); c.red=red; c.green=green; c.blue=blue; c.alpha=alpha; return c; } /** * Set the colour components from linear RGB integer values that * are scaled from 0 to 255. * * @param r red component * @param g green component * @param b blue component * @param a alpha component */ public void setFromLinearRGBA8(int r, int g, int b, int a) { red=r/255.0; green=g/255.0; blue=b/255.0; alpha=a/255.0; } /** * Set the colour components from linear RGB integer values that * are scaled from 0 to 255. * * @param rgb tuple of RGB components */ public void setFromLinearRGBA8(RGB rgb) { setFromLinearRGBA8(rgb.red,rgb.green,rgb.blue,rgb.alpha); } /** * Conversion from sRGB to linear (CIE xy) color space for a * single coordinate. Formula taken from Wikipedia article * on sRGB. * * @param srgb the sRGB value for the color coordinate * @return linear floating point value in CIE coordinate system */ private double fromsRGB(int srgb) { if(srgb < .04045*255) { return srgb*(1/12.92/255); } else { return Math.pow((srgb+(255*.055))*(1/1.055/255), 2.4f); } } /** * Set colour from sRGB colour components that are scaled from 0 * to 255. * * @param rgb the tuple of sRGB colour components */ public void setFromsRGB8(RGB rgb) { red=fromsRGB(rgb.red); green=fromsRGB(rgb.green); blue=fromsRGB(rgb.blue); alpha=fromsRGB(rgb.alpha); } /** * Set colour from sRGB colour components that are scaled from 0 * to 255. * * @param red red component in sRGB space * @param green green component in sRGB space * @param blue blue component in sRGB space * @param alpha alpha component in sRGB space */ public void setFromsRGB8(int red, int green, int blue, int alpha) { this.red=fromsRGB(red); this.green=fromsRGB(green); this.blue=fromsRGB(blue); this.alpha=fromsRGB(alpha); } /** * Get a integer tuple of the colour components in linear RGB * scaled from 0 to 256. * * @return RGB tuple with linear RGB values */ public RGB getLinearRGB8() { RGB rgb=new RGB(); rgb.red=(int)red*255; if(rgb.red>255) { rgb.red=255; } rgb.green=(int)green*255; if(rgb.green>255) { rgb.green=255; } rgb.blue=(int)blue*255; if(rgb.blue>255) { rgb.blue=255; } rgb.alpha=(int)alpha*255; if(rgb.alpha>255) { rgb.alpha=255; } return rgb; } /** * Convert a single color coodinate from linear RGB color space to * sRGB. Formula taken from Wikipedia article on sRGB. * * @param linear linear RGB space coordinate value * @return sRGB color space value of that coordinate */ private int tosRGB(double linear) { int value; if(linear<(0.04045/12.92)) { value=(int)Math.round(linear*255*12.92); } else { value=(int)Math.round(1.055*255*Math.pow(linear,1/2.4)-(255*.055)); } if(value>255) { value=255; } return value; } /** * Get a RGB tuple of the colour converted to the sRGB colour space. * * @return RGB tuple with the colour values in sRGB space */ public RGB getsRGB8() { RGB rgb=new RGB(); rgb.red=tosRGB(red); rgb.green=tosRGB(green); rgb.blue=tosRGB(blue); rgb.alpha=tosRGB(alpha); return rgb; } /** * Set the colour from the given HSV triple * * @param hue new hue * @param saturation new saturation * @param value new value */ public void setFromHSV(double hue, double saturation, double value) { int hi; if(hue==1) { hi=5; } else { hi=((int)(hue*6)%6); } double f=hue*6-hi; double p=value*(1-saturation); double q=value*(1-f*saturation); double t=value*(1-(1-f)*saturation); if(p>1) { System.out.println("p>1"); p=1; } if(q>1) { System.out.println("q>1"); q=1; } if(t>1) { System.out.println("t>1: " + t); t=1; } 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: red=p; green=q; blue=value; break; case 4: red=t; green=p; blue=value; break; case 5: red=value; green=p; blue=q; break; } } /** * Find the maximum colour component * * @return maximum colour component */ private double findHSVMax() { double max=red; if(green>max) { max=green; } if(blue>max) { max=blue; } return max; } /** * Find the minimal colour component * * @return miniimal colour component */ private double findHSVMin() { double min=red; if(green