495 lines
10 KiB
Java
495 lines
10 KiB
Java
/*
|
|
* Copyright (c) 2002-2008 LWJGL Project
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of 'LWJGL' nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
package org.lwjgl.util;
|
|
import java.io.Serializable;
|
|
import java.nio.ByteBuffer;
|
|
|
|
/**
|
|
* A mutable Color class
|
|
* @author $Author$
|
|
* @version $Revision$
|
|
* $Id$
|
|
*/
|
|
public final class Color implements ReadableColor, Serializable, WritableColor {
|
|
|
|
static final long serialVersionUID = 1L;
|
|
|
|
/** Color components, publicly accessible */
|
|
private byte red, green, blue, alpha;
|
|
|
|
/**
|
|
* Constructor for Color.
|
|
*/
|
|
public Color() {
|
|
this(0, 0, 0, 255);
|
|
}
|
|
|
|
/**
|
|
* Constructor for Color. Alpha defaults to 255.
|
|
*/
|
|
public Color(int r, int g, int b) {
|
|
this(r, g, b, 255);
|
|
}
|
|
|
|
/**
|
|
* Constructor for Color. Alpha defaults to 255.
|
|
*/
|
|
public Color(byte r, byte g, byte b) {
|
|
this(r, g, b, (byte) 255);
|
|
}
|
|
|
|
/**
|
|
* Constructor for Color.
|
|
*/
|
|
public Color(int r, int g, int b, int a) {
|
|
set(r, g, b, a);
|
|
}
|
|
|
|
/**
|
|
* Constructor for Color.
|
|
*/
|
|
public Color(byte r, byte g, byte b, byte a) {
|
|
set(r, g, b, a);
|
|
}
|
|
|
|
/**
|
|
* Constructor for Color
|
|
*/
|
|
public Color(ReadableColor c) {
|
|
setColor(c);
|
|
}
|
|
|
|
/**
|
|
* Set a color
|
|
*/
|
|
public void set(int r, int g, int b, int a) {
|
|
red = (byte) r;
|
|
green = (byte) g;
|
|
blue = (byte) b;
|
|
alpha = (byte) a;
|
|
}
|
|
|
|
/**
|
|
* Set a color
|
|
*/
|
|
public void set(byte r, byte g, byte b, byte a) {
|
|
this.red = r;
|
|
this.green = g;
|
|
this.blue = b;
|
|
this.alpha = a;
|
|
}
|
|
|
|
/**
|
|
* Set a color
|
|
*/
|
|
public void set(int r, int g, int b) {
|
|
set(r, g, b, 255);
|
|
}
|
|
|
|
/**
|
|
* Set a color
|
|
*/
|
|
public void set(byte r, byte g, byte b) {
|
|
set(r, g, b, (byte) 255);
|
|
}
|
|
|
|
/**
|
|
* Accessor
|
|
*/
|
|
public int getRed() {
|
|
return red & 0xFF;
|
|
}
|
|
|
|
/**
|
|
* Accessor
|
|
*/
|
|
public int getGreen() {
|
|
return green & 0xFF;
|
|
}
|
|
|
|
/**
|
|
* Accessor
|
|
*/
|
|
public int getBlue() {
|
|
return blue & 0xFF;
|
|
}
|
|
|
|
/**
|
|
* Accessor
|
|
*/
|
|
public int getAlpha() {
|
|
return alpha & 0xFF;
|
|
}
|
|
|
|
/**
|
|
* Set the Red component
|
|
*/
|
|
public void setRed(int red) {
|
|
this.red = (byte) red;
|
|
}
|
|
|
|
/**
|
|
* Set the Green component
|
|
*/
|
|
public void setGreen(int green) {
|
|
this.green = (byte) green;
|
|
}
|
|
|
|
/**
|
|
* Set the Blue component
|
|
*/
|
|
public void setBlue(int blue) {
|
|
this.blue = (byte) blue;
|
|
}
|
|
|
|
/**
|
|
* Set the Alpha component
|
|
*/
|
|
public void setAlpha(int alpha) {
|
|
this.alpha = (byte) alpha;
|
|
}
|
|
|
|
/**
|
|
* Set the Red component
|
|
*/
|
|
public void setRed(byte red) {
|
|
this.red = red;
|
|
}
|
|
|
|
/**
|
|
* Set the Green component
|
|
*/
|
|
public void setGreen(byte green) {
|
|
this.green = green;
|
|
}
|
|
|
|
/**
|
|
* Set the Blue component
|
|
*/
|
|
public void setBlue(byte blue) {
|
|
this.blue = blue;
|
|
}
|
|
|
|
/**
|
|
* Set the Alpha component
|
|
*/
|
|
public void setAlpha(byte alpha) {
|
|
this.alpha = alpha;
|
|
}
|
|
|
|
/**
|
|
* Stringify
|
|
*/
|
|
public String toString() {
|
|
return "Color [" + getRed() + ", " + getGreen() + ", " + getBlue() + ", " + getAlpha() + "]";
|
|
}
|
|
|
|
/**
|
|
* Equals
|
|
*/
|
|
public boolean equals(Object o) {
|
|
return (o != null)
|
|
&& (o instanceof ReadableColor)
|
|
&& (((ReadableColor) o).getRed() == this.getRed())
|
|
&& (((ReadableColor) o).getGreen() == this.getGreen())
|
|
&& (((ReadableColor) o).getBlue() == this.getBlue())
|
|
&& (((ReadableColor) o).getAlpha() == this.getAlpha());
|
|
}
|
|
|
|
/**
|
|
* Hashcode
|
|
*/
|
|
public int hashCode() {
|
|
return (red << 24) | (green << 16) | (blue << 8) | alpha;
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#getAlphaByte()
|
|
*/
|
|
public byte getAlphaByte() {
|
|
return alpha;
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#getBlueByte()
|
|
*/
|
|
public byte getBlueByte() {
|
|
return blue;
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#getGreenByte()
|
|
*/
|
|
public byte getGreenByte() {
|
|
return green;
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#getRedByte()
|
|
*/
|
|
public byte getRedByte() {
|
|
return red;
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#writeRGBA(java.nio.ByteBuffer)
|
|
*/
|
|
public void writeRGBA(ByteBuffer dest) {
|
|
dest.put(red);
|
|
dest.put(green);
|
|
dest.put(blue);
|
|
dest.put(alpha);
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#writeRGB(java.nio.ByteBuffer)
|
|
*/
|
|
public void writeRGB(ByteBuffer dest) {
|
|
dest.put(red);
|
|
dest.put(green);
|
|
dest.put(blue);
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#writeABGR(java.nio.ByteBuffer)
|
|
*/
|
|
public void writeABGR(ByteBuffer dest) {
|
|
dest.put(alpha);
|
|
dest.put(blue);
|
|
dest.put(green);
|
|
dest.put(red);
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#writeARGB(java.nio.ByteBuffer)
|
|
*/
|
|
public void writeARGB(ByteBuffer dest) {
|
|
dest.put(alpha);
|
|
dest.put(red);
|
|
dest.put(green);
|
|
dest.put(blue);
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#writeBGR(java.nio.ByteBuffer)
|
|
*/
|
|
public void writeBGR(ByteBuffer dest) {
|
|
dest.put(blue);
|
|
dest.put(green);
|
|
dest.put(red);
|
|
}
|
|
|
|
/* (Overrides)
|
|
* @see com.shavenpuppy.jglib.ReadableColor#writeBGRA(java.nio.ByteBuffer)
|
|
*/
|
|
public void writeBGRA(ByteBuffer dest) {
|
|
dest.put(blue);
|
|
dest.put(green);
|
|
dest.put(red);
|
|
dest.put(alpha);
|
|
}
|
|
|
|
/**
|
|
* Read a color from a byte buffer
|
|
* @param src The source buffer
|
|
*/
|
|
public void readRGBA(ByteBuffer src) {
|
|
red = src.get();
|
|
green = src.get();
|
|
blue = src.get();
|
|
alpha = src.get();
|
|
}
|
|
|
|
/**
|
|
* Read a color from a byte buffer
|
|
* @param src The source buffer
|
|
*/
|
|
public void readRGB(ByteBuffer src) {
|
|
red = src.get();
|
|
green = src.get();
|
|
blue = src.get();
|
|
}
|
|
|
|
/**
|
|
* Read a color from a byte buffer
|
|
* @param src The source buffer
|
|
*/
|
|
public void readARGB(ByteBuffer src) {
|
|
alpha = src.get();
|
|
red = src.get();
|
|
green = src.get();
|
|
blue = src.get();
|
|
}
|
|
|
|
/**
|
|
* Read a color from a byte buffer
|
|
* @param src The source buffer
|
|
*/
|
|
public void readBGRA(ByteBuffer src) {
|
|
blue = src.get();
|
|
green = src.get();
|
|
red = src.get();
|
|
alpha = src.get();
|
|
}
|
|
|
|
/**
|
|
* Read a color from a byte buffer
|
|
* @param src The source buffer
|
|
*/
|
|
public void readBGR(ByteBuffer src) {
|
|
blue = src.get();
|
|
green = src.get();
|
|
red = src.get();
|
|
}
|
|
|
|
/**
|
|
* Read a color from a byte buffer
|
|
* @param src The source buffer
|
|
*/
|
|
public void readABGR(ByteBuffer src) {
|
|
alpha = src.get();
|
|
blue = src.get();
|
|
green = src.get();
|
|
red = src.get();
|
|
}
|
|
|
|
/**
|
|
* Set this color's color by copying another color
|
|
* @param src The source color
|
|
*/
|
|
public void setColor(ReadableColor src) {
|
|
red = src.getRedByte();
|
|
green = src.getGreenByte();
|
|
blue = src.getBlueByte();
|
|
alpha = src.getAlphaByte();
|
|
}
|
|
|
|
/**
|
|
* HSB to RGB conversion, pinched from java.awt.Color.
|
|
* @param hue (0..1.0f)
|
|
* @param saturation (0..1.0f)
|
|
* @param brightness (0..1.0f)
|
|
*/
|
|
public void fromHSB(float hue, float saturation, float brightness) {
|
|
if (saturation == 0.0F) {
|
|
red = green = blue = (byte) (brightness * 255F + 0.5F);
|
|
} else {
|
|
float f3 = (hue - (float) Math.floor(hue)) * 6F;
|
|
float f4 = f3 - (float) Math.floor(f3);
|
|
float f5 = brightness * (1.0F - saturation);
|
|
float f6 = brightness * (1.0F - saturation * f4);
|
|
float f7 = brightness * (1.0F - saturation * (1.0F - f4));
|
|
switch ((int) f3) {
|
|
case 0 :
|
|
red = (byte) (brightness * 255F + 0.5F);
|
|
green = (byte) (f7 * 255F + 0.5F);
|
|
blue = (byte) (f5 * 255F + 0.5F);
|
|
break;
|
|
case 1 :
|
|
red = (byte) (f6 * 255F + 0.5F);
|
|
green = (byte) (brightness * 255F + 0.5F);
|
|
blue = (byte) (f5 * 255F + 0.5F);
|
|
break;
|
|
case 2 :
|
|
red = (byte) (f5 * 255F + 0.5F);
|
|
green = (byte) (brightness * 255F + 0.5F);
|
|
blue = (byte) (f7 * 255F + 0.5F);
|
|
break;
|
|
case 3 :
|
|
red = (byte) (f5 * 255F + 0.5F);
|
|
green = (byte) (f6 * 255F + 0.5F);
|
|
blue = (byte) (brightness * 255F + 0.5F);
|
|
break;
|
|
case 4 :
|
|
red = (byte) (f7 * 255F + 0.5F);
|
|
green = (byte) (f5 * 255F + 0.5F);
|
|
blue = (byte) (brightness * 255F + 0.5F);
|
|
break;
|
|
case 5 :
|
|
red = (byte) (brightness * 255F + 0.5F);
|
|
green = (byte) (f5 * 255F + 0.5F);
|
|
blue = (byte) (f6 * 255F + 0.5F);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* RGB to HSB conversion, pinched from java.awt.Color.
|
|
* The HSB value is returned in dest[] if dest[] is supplied.
|
|
* Values range from 0..1
|
|
* @param dest Destination floats, or null
|
|
* @return dest, or a new float array
|
|
*/
|
|
public float[] toHSB(float dest[]) {
|
|
int r = getRed();
|
|
int g = getGreen();
|
|
int b = getBlue();
|
|
if (dest == null)
|
|
dest = new float[3];
|
|
int l = r <= g ? g : r;
|
|
if (b > l)
|
|
l = b;
|
|
int i1 = r >= g ? g : r;
|
|
if (b < i1)
|
|
i1 = b;
|
|
float brightness = l / 255F;
|
|
float saturation;
|
|
if (l != 0)
|
|
saturation = (float) (l - i1) / (float) l;
|
|
else
|
|
saturation = 0.0F;
|
|
float hue;
|
|
if (saturation == 0.0F) {
|
|
hue = 0.0F;
|
|
} else {
|
|
float f3 = (float) (l - r) / (float) (l - i1);
|
|
float f4 = (float) (l - g) / (float) (l - i1);
|
|
float f5 = (float) (l - b) / (float) (l - i1);
|
|
if (r == l)
|
|
hue = f5 - f4;
|
|
else if (g == l)
|
|
hue = (2.0F + f3) - f5;
|
|
else
|
|
hue = (4F + f4) - f3;
|
|
hue /= 6F;
|
|
if (hue < 0.0F)
|
|
hue++;
|
|
}
|
|
dest[0] = hue;
|
|
dest[1] = saturation;
|
|
dest[2] = brightness;
|
|
return dest;
|
|
}
|
|
|
|
}
|