You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
535 lines
16 KiB
Java
535 lines
16 KiB
Java
package digisoft.custom.awt;
|
|
|
|
import java.awt.Color;
|
|
|
|
/**
|
|
* @author Zom-B
|
|
* @since 1.0
|
|
* @date 2005/10/03
|
|
*/
|
|
public class Color3f {
|
|
|
|
private static final float MIN_CLIP_LEVEL = -0.003921568627450980392156862745098f;
|
|
private static final float MAX_CLIP_LEVEL = 1.003921568627450980392156862745098f;
|
|
public float r;
|
|
public float g;
|
|
public float b;
|
|
|
|
/**
|
|
* Create the color opaque black
|
|
*/
|
|
public Color3f() {
|
|
this(0f, 0f, 0f);
|
|
}
|
|
|
|
/**
|
|
* Create an opaque color from packed RGB triple
|
|
*
|
|
* @param i
|
|
* @since 1.0
|
|
*/
|
|
public Color3f(int i) {
|
|
b = (i & 0xFF) / 255f;
|
|
g = ((i >>= 8) & 0xFF) / 255f;
|
|
r = (i >> 8 & 0xFF) / 255f;
|
|
}
|
|
|
|
/**
|
|
* Create an opaque color defined gray shade
|
|
*
|
|
* @param i
|
|
* @since 1.0
|
|
*/
|
|
public Color3f(float i) {
|
|
this(i, i, i);
|
|
}
|
|
|
|
/**
|
|
* Create an opaque defined color
|
|
*
|
|
* @param r
|
|
* @param g
|
|
* @param b
|
|
*/
|
|
public Color3f(float r, float g, float b) {
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b;
|
|
}
|
|
|
|
/**
|
|
* Create an opaque defined color
|
|
*
|
|
* @param r
|
|
* @param g
|
|
* @param b
|
|
*/
|
|
public Color3f(int r, int g, int b) {
|
|
this.r = r / 255f;
|
|
this.g = g / 255f;
|
|
this.b = b / 255f;
|
|
}
|
|
|
|
/**
|
|
* @param color
|
|
* @since 1.0
|
|
*/
|
|
public Color3f(Color color) {
|
|
r = color.getRed() / 255f;
|
|
g = color.getGreen() / 255f;
|
|
b = color.getBlue() / 255f;
|
|
}
|
|
|
|
/**
|
|
* @param color
|
|
* @since 1.0
|
|
*/
|
|
public Color3f(Color3f color) {
|
|
r = color.r;
|
|
g = color.g;
|
|
b = color.b;
|
|
}
|
|
|
|
public void set(Color3f c) {
|
|
r = c.r;
|
|
g = c.g;
|
|
b = c.b;
|
|
}
|
|
|
|
public void set(int r, int g, int b) {
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b;
|
|
}
|
|
|
|
public float getGrayValue() {
|
|
return 0.299f * r + 0.587f * g + 0.114f * b;
|
|
}
|
|
|
|
public void addSelf(int i) {
|
|
b += (i & 0xFF) / 255f;
|
|
g += ((i >>= 8) & 0xFF) / 255f;
|
|
r += (i >> 8 & 0xFF) / 255f;
|
|
}
|
|
|
|
public Color3f scale(float f) {
|
|
return new Color3f(r * f, g * f, b * f);
|
|
}
|
|
|
|
public void scaleSelf(float f) {
|
|
r *= f;
|
|
g *= f;
|
|
b *= f;
|
|
}
|
|
|
|
public Color3f interpolateLinear(Color3f c, float f) {
|
|
return new Color3f( //
|
|
r + (c.r - r) * f, //
|
|
g + (c.g - g) * f, //
|
|
b + (c.b - b) * f);
|
|
}
|
|
|
|
public void interpolateLinearSelf(Color3f c, float f) {
|
|
r = r + (c.r - r) * f;
|
|
g = g + (c.g - g) * f;
|
|
b = b + (c.b - b) * f;
|
|
}
|
|
|
|
public Color3f gamma(float gammaFactor) {
|
|
return new Color3f( //
|
|
(float) Math.pow(r, gammaFactor), //
|
|
(float) Math.pow(g, gammaFactor), //
|
|
(float) Math.pow(b, gammaFactor));
|
|
}
|
|
|
|
/**
|
|
* Converts the components of this color, as specified by the HSB model, to
|
|
* an equivalent set of values for the default RGB model.
|
|
* <p>
|
|
* The <code>saturation</code> and <code>brightness</code> components should
|
|
* be floating-point values between zero and one (numbers in the range
|
|
* 0.0-1.0). The <code>hue</code> component can be any floating-point
|
|
* number. The floor of this number is subtracted from it to create a
|
|
* fraction between 0 and 1. This fractional number is then virtually
|
|
* multiplied by 360 to produce the hue angle in the HSB color model.
|
|
* <p>
|
|
*
|
|
* @param hsb
|
|
* the Color3f containing the components hue, saturation,
|
|
* brightness and alpha in the fields of red, green, blue and
|
|
* alpha, respectively
|
|
* @return the Color3f with the RGB value of the color with the indicated
|
|
* hue, saturation, brightness and alpha.
|
|
*
|
|
* @see java.awt.Color#HSB2RGB(float, float, float)
|
|
* @see java.awt.Color#getRGB()
|
|
* @see java.awt.Color#Color(int)
|
|
* @see java.awt.image.ColorModel#getRGBdefault()
|
|
* @since 1.0
|
|
*/
|
|
public Color3f hsb2Rgb() {
|
|
if (g == 0) {
|
|
return new Color3f(b, b, b);
|
|
}
|
|
Color3f out = new Color3f(0, 0, 0);
|
|
float hue6 = (r - (float) Math.floor(r)) * 6;
|
|
float hue_f = hue6 - (float) java.lang.Math.floor(hue6);
|
|
float p = b * (1 - g);
|
|
switch ((int) hue6) {
|
|
case 0:
|
|
case 6: {
|
|
out.r = b;
|
|
out.g = b * (1 - g * (1 - hue_f));
|
|
out.b = p;
|
|
break;
|
|
}
|
|
case 1: {
|
|
out.r = b * (1 - g * hue_f);
|
|
out.g = b;
|
|
out.b = p;
|
|
break;
|
|
}
|
|
case 2: {
|
|
out.r = p;
|
|
out.g = b;
|
|
out.b = b * (1 - g * (1 - hue_f));
|
|
break;
|
|
}
|
|
case 3: {
|
|
out.r = p;
|
|
out.g = b * (1 - g * hue_f);
|
|
out.b = b;
|
|
}
|
|
break;
|
|
case 4: {
|
|
out.r = b * (1 - g * (1 - hue_f));
|
|
out.g = p;
|
|
out.b = b;
|
|
break;
|
|
}
|
|
case 5: {
|
|
out.r = b;
|
|
out.g = p;
|
|
out.b = b * (1 - g * hue_f);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Converts the components of this color, as specified by the default RGB
|
|
* model, to an equivalent set of values for hue, saturation, and brightness
|
|
* that are the three components of the HSB model.
|
|
*
|
|
* @see java.awt.Color#RGB2HSB(int, int, int, float[])
|
|
* @see java.awt.Color#getRGB()
|
|
* @see java.awt.Color#Color(int)
|
|
* @see java.awt.image.ColorModel#getRGBdefault()
|
|
* @since JDK1.0
|
|
*/
|
|
public Color3f rgb2Hsb() {
|
|
float cmax = r > g ? r : g;
|
|
if (b > cmax) {
|
|
cmax = b;
|
|
}
|
|
float cmin = r < g ? r : g;
|
|
if (b < cmin) {
|
|
cmin = b;
|
|
}
|
|
float dist = cmax - cmin;
|
|
|
|
Color3f out = new Color3f(0f, 0f, 0f);
|
|
|
|
out.b = cmax;
|
|
out.g = cmax != 0 ? dist / cmax : 0;
|
|
|
|
if (out.g == 0) {
|
|
out.r = 0;
|
|
} else {
|
|
if (r == cmax) {
|
|
if (g >= b) {
|
|
out.r = (g - b) / dist;
|
|
} else {
|
|
out.r = 6.0f + (g - b) / dist;
|
|
}
|
|
} else if (g == cmax) {
|
|
out.r = 2.0f + (b - r) / dist;
|
|
} else {
|
|
out.r = 4.0f + (r - g) / dist;
|
|
}
|
|
out.r /= 6.0f;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Converts the components of this color, as specified by the default RGB
|
|
* model, to an equivalent set of values for hue, saturation, and brightness
|
|
* that are the three components of the HSB model.
|
|
*
|
|
* @see java.awt.Color#RGB2HSB(int, int, int, float[])
|
|
* @see java.awt.Color#getRGB()
|
|
* @see java.awt.Color#Color(int)
|
|
* @see java.awt.image.ColorModel#getRGBdefault()
|
|
* @since JDK1.0
|
|
*/
|
|
public void rgb2HsbSelf() {
|
|
float cmax = r > g ? r : g;
|
|
if (b > cmax) {
|
|
cmax = b;
|
|
}
|
|
float cmin = r < g ? r : g;
|
|
if (b < cmin) {
|
|
cmin = b;
|
|
}
|
|
float dist = cmax - cmin;
|
|
|
|
float g = cmax != 0 ? dist / cmax : 0;
|
|
|
|
if (g == 0) {
|
|
r = 0;
|
|
} else {
|
|
if (r == cmax) {
|
|
if (this.g >= b) {
|
|
r = (this.g - b) / dist;
|
|
} else {
|
|
r = 6.0f + (this.g - b) / dist;
|
|
}
|
|
} else if (this.g == cmax) {
|
|
r = 2.0f + (b - r) / dist;
|
|
} else {
|
|
r = 4.0f + (r - this.g) / dist;
|
|
}
|
|
r /= 6.0f;
|
|
}
|
|
b = cmax;
|
|
this.g = g;
|
|
}
|
|
|
|
/**
|
|
* Convert RGB to YPbPr (the floating point version of YCbCr).
|
|
*
|
|
* @return R=Y in [0, 1]; G=Pb in [-0.5 0.5]; B=Pr in [-0.5 0.5]
|
|
* @since 1.0
|
|
*/
|
|
public Color3f rgb2YPbPr() {
|
|
return new Color3f( //
|
|
+0.29900000000000000000f * r + 0.58700000000000000000f * g + 0.114000000000000000000f * b, //
|
|
-0.16873589164785553047f * r - 0.33126410835214446952f * g + 0.500000000000000000000f * b, //
|
|
+0.50000000000000000000f * r - 0.41868758915834522111f * g - 0.081312410841654778888f * b);
|
|
}
|
|
|
|
/**
|
|
* Convert RGB to YPbPr (the floating point version of YCbCr).
|
|
*
|
|
* @return R=Y in [0, 1]; G=Pb in [-0.5 0.5]; B=Pr in [-0.5 0.5]
|
|
* @since 1.0
|
|
*/
|
|
public void rgb2YPbPrSelf() {
|
|
float r = +0.29900000000000000000f * this.r + 0.58700000000000000000f * g + 0.114000000000000000000f * b;
|
|
float g = -0.16873589164785553047f * this.r - 0.33126410835214446952f * this.g + 0.500000000000000000000f * b;
|
|
b = +0.50000000000000000000f * this.r - 0.41868758915834522111f * this.g - 0.081312410841654778888f * b;
|
|
this.r = r;
|
|
this.g = g;
|
|
}
|
|
|
|
/**
|
|
* Convert YPbPr (the floating point version of YCbCr) to RGB. Inputs: R=Y
|
|
* in [0 1]; G=Pb in [-0.5 0.5]; B=Pr in [-0.5 0.5]
|
|
*
|
|
* @return RGB colors
|
|
* @since 1.0
|
|
*/
|
|
public Color3f tPbPr2Rgb() {
|
|
return new Color3f( //
|
|
r /* ***************************** */ + 1.40200000000000000000f * b, //
|
|
r - 0.34413628620102214650f * g - 0.71413628620102214645f * b, //
|
|
r + 1.77200000000000000000f * g /*
|
|
* **********************
|
|
* ******
|
|
*/);
|
|
}
|
|
|
|
/**
|
|
* Convert RGB to YUV (the colorspace used by PAL TV).
|
|
*
|
|
* @return R=Y in [0, 1]; G=U in [-0.5 0.5]; B=V in [-0.5 0.5]
|
|
* @since 1.0
|
|
*/
|
|
public Color3f rgb2Yuv() {
|
|
return new Color3f( //
|
|
+0.29900000000000000000f * r + 0.58700000000000000000f * g + 0.11400000000000000000f * b, //
|
|
-0.14713769751693002257f * r - 0.28886230248306997742f * g + 0.43600000000000000000f * b, //
|
|
+0.61500000000000000000f * r - 0.51498573466476462197f * g - 0.10001426533523537803f * b);
|
|
}
|
|
|
|
/**
|
|
* Convert YUV (the colorspace used in PAL TV) to RGB. Inputs: R=Y in [0 1];
|
|
* G=U in [-0.5 0.5]; B=V in [-0.5 0.5]
|
|
*
|
|
* @return RGB colors
|
|
* @since 1.0
|
|
*/
|
|
public Color3f yuv2Rgb() {
|
|
return new Color3f( //
|
|
r /* ***************************** */ + 1.13983739837398373980f * b, //
|
|
r - 0.39465170435897035149f * g - 0.58059860666749768007f * b, //
|
|
r + 2.03211009174311926600f * g /*
|
|
* **********************
|
|
* ******
|
|
*/);
|
|
}
|
|
|
|
/**
|
|
* Convert RGB to YUV (the colorspace used by PAL TV).
|
|
*
|
|
* @return R=Y in [0, 1]; G=U in [-0.5 0.5]; B=V in [-0.5 0.5]
|
|
* @since 1.0
|
|
*/
|
|
public Color3f rgb2YiQ() {
|
|
return new Color3f( //
|
|
+0.29900000000000000000f * r + 0.58700000000000000000f * g + 0.11400000000000000000f * b, //
|
|
+0.59571613491277455268f * r - 0.27445283783925646357f * g - 0.32126329707351808911f * b, //
|
|
+0.21145640212011786639f * r - 0.52259104529161116836f * g + 0.31113464317149330198f * b);
|
|
}
|
|
|
|
/**
|
|
* Convert YIQ (the colorspace used in NTSC TV) to RGB. Inputs: R=Y in [0
|
|
* 1]; G=I in [-0.5 0.5]; B=Q in [-0.5 0.5]
|
|
*
|
|
* @return RGB colors
|
|
* @since 1.0
|
|
*/
|
|
public Color3f yiq2Rgb() {
|
|
return new Color3f( //
|
|
r + 0.95629483232089399045f * g + 0.62102512544472871408f * b, //
|
|
r - 0.27212147408397731948f * g - 0.64738095351761572226f * b, //
|
|
r - 1.10698990856712821590f * g + 1.70461497549882932850f * b);
|
|
}
|
|
|
|
/**
|
|
* Convert RGB to XYZ (the CIE 1931 color space).
|
|
*
|
|
* @return R=Y in [0, 1]; G=U in [0 1]; B=V in [0 1]
|
|
* @since 1.0
|
|
*/
|
|
public Color3f rgb2Xyz() {
|
|
return new Color3f( //
|
|
+0.43030294260923249074f * r + 0.34163640134469669562f * g + 0.17822777850125160973f * b, //
|
|
+0.22187495478288550304f * r + 0.70683393381661385301f * g + 0.071291111400500643890f * b, //
|
|
+0.020170450434807773004f * r + 0.12958622119971253972f * g + 0.93866630010659181124f * b);
|
|
}
|
|
|
|
/**
|
|
* Convert XYZ (the CIE 1931 color space) to RGB. Inputs: R=X in [0 1]; G=Y
|
|
* in [0 1]; B=z in [0 1]
|
|
*
|
|
* @return RGB colors
|
|
* @since 1.0
|
|
*/
|
|
public Color3f xyz2Rgb() {
|
|
return new Color3f( //
|
|
+2.0608465608465608465f * r - 0.93738977072310405639f * g - 0.32010582010582010580f * b, //
|
|
-1.1415343915343915346f * r + 2.2094356261022927693f * g + 0.048941798941798941806f * b, //
|
|
+0.080687830687830687828f * r - 0.27204585537918871252f * g + 1.2711640211640211641f * b);
|
|
}
|
|
|
|
public Color3f clip() {
|
|
float ra = r;
|
|
float ga = g;
|
|
float ba = b;
|
|
|
|
if (ra < 0) {
|
|
ra = 0;
|
|
} else if (ra > 1) {
|
|
ra = 1;
|
|
}
|
|
if (ga < 0) {
|
|
ga = 0;
|
|
} else if (ga > 1) {
|
|
ga = 1;
|
|
}
|
|
if (ba < 0) {
|
|
ba = 0;
|
|
} else if (ba > 1) {
|
|
ba = 1;
|
|
}
|
|
|
|
return new Color3f(ra, ga, ba);
|
|
}
|
|
|
|
public Color3f showClip() {
|
|
if (r < Color3f.MIN_CLIP_LEVEL || r > Color3f.MAX_CLIP_LEVEL || g < Color3f.MIN_CLIP_LEVEL || g > Color3f.MAX_CLIP_LEVEL || b < Color3f.MIN_CLIP_LEVEL
|
|
|| b > Color3f.MAX_CLIP_LEVEL) {
|
|
return new Color3f(0.5f, 0.5f, 0.5f);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public boolean isClipping() {
|
|
return r < Color3f.MIN_CLIP_LEVEL || r > Color3f.MAX_CLIP_LEVEL || g < Color3f.MIN_CLIP_LEVEL || g > Color3f.MAX_CLIP_LEVEL
|
|
|| b < Color3f.MIN_CLIP_LEVEL || b > Color3f.MAX_CLIP_LEVEL;
|
|
}
|
|
|
|
/**
|
|
* Converts this color to a color understood by the java.awt package.
|
|
*
|
|
* @return an instance of java.awt.Color with the color attributes clamped
|
|
* to {black,white}
|
|
* @see java.awt.Color
|
|
* @since 1.0
|
|
*/
|
|
public Color toColor() {
|
|
float ra = r;
|
|
float ga = g;
|
|
float ba = b;
|
|
|
|
if (ra < 0) {
|
|
ra = 0;
|
|
} else if (ra > 1) {
|
|
ra = 1;
|
|
}
|
|
if (ga < 0) {
|
|
ga = 0;
|
|
} else if (ga > 1) {
|
|
ga = 1;
|
|
}
|
|
if (ba < 0) {
|
|
ba = 0;
|
|
} else if (ba > 1) {
|
|
ba = 1;
|
|
}
|
|
|
|
return new java.awt.Color(ra, ga, ba);
|
|
}
|
|
|
|
public int getRGB() {
|
|
int ra = (int) (r * 255 + 0.5);
|
|
int ga = (int) (g * 255 + 0.5);
|
|
int ba = (int) (b * 255 + 0.5);
|
|
|
|
if (ra < 0) {
|
|
ra = 0;
|
|
} else if (ra > 255) {
|
|
ra = 255;
|
|
}
|
|
if (ga < 0) {
|
|
ga = 0;
|
|
} else if (ga > 255) {
|
|
ga = 255;
|
|
}
|
|
if (ba < 0) {
|
|
ba = 0;
|
|
} else if (ba > 255) {
|
|
ba = 255;
|
|
}
|
|
|
|
return ba + (ga + (ra << 8) << 8);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return super.getClass().getSimpleName() + "[" + r + ", " + g + ", " + b + "]";
|
|
}
|
|
}
|