/*******************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tiny Look and Feel * * (C) Copyright 2003 - 2007 Hans Bickel * * For
* licensing information and credits, please refer to the * comment in file
* de.muntjak.tinylookandfeel.TinyLookAndFeel * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
package de.muntjak.tinylookandfeel.controlpanel;
import java.awt.Color;
/**
* ColorRoutines
*
* @version 1.0
* @author Hans Bickel
*/
@SuppressWarnings (
{ "all" } )
public class ColorRoutines
{
private static final int RGB = 1;
private static final int RBG = 2;
private static final int GBR = 3;
private static final int GRB = 4;
private static final int BRG = 5;
private static final int BGR = 6;
private boolean preserveGrey;
private int chue, csat, cbri;
private int fr, fg, fb;
int hi, lo, md;
boolean hiIsR, hiIsG, hiIsB;
boolean mdIsR, mdIsG, mdIsB;
boolean loIsR, loIsG, loIsB;
public ColorRoutines ( Color c )
{
setHSB ( c.getRed (), c.getGreen (), c.getBlue () );
}
public ColorRoutines ( int hue, int sat, int bri, boolean preserveGrey )
{
chue = hue;
csat = sat;
cbri = bri;
this.preserveGrey = preserveGrey;
Color c = Color.getHSBColor ( ( float ) ( ( double ) chue / 360.0 ), 1.0f,
1.0f );
fr = c.getRed ();
fg = c.getGreen ();
fb = c.getBlue ();
// sort colors - 6 options
if ( fr >= fg && fg >= fb )
{
hi = fr;
md = fg;
lo = fb;
hiIsR = true;
mdIsG = true;
loIsB = true;
}
else if ( fr >= fb && fb >= fg )
{
hi = fr;
md = fb;
lo = fg;
hiIsR = true;
mdIsB = true;
loIsG = true;
}
else if ( fg >= fr && fr >= fb )
{
hi = fg;
md = fr;
lo = fb;
hiIsG = true;
mdIsR = true;
loIsB = true;
}
else if ( fg >= fb && fb >= fr )
{
hi = fg;
md = fb;
lo = fr;
hiIsG = true;
mdIsB = true;
loIsR = true;
}
else if ( fb >= fg && fg >= fr )
{
hi = fb;
md = fg;
lo = fr;
hiIsB = true;
mdIsG = true;
loIsR = true;
}
else if ( fb >= fr && fr >= fg )
{
hi = fb;
md = fr;
lo = fg;
hiIsB = true;
mdIsR = true;
loIsG = true;
}
}
private void setHSB ( int r, int g, int b )
{
chue = getHue ( r, g, b );
csat = getSaturation ( r, g, b );
cbri = getBrightness ( r, g, b );
}
public static Color getAverage ( Color c1, Color c2 )
{
int r = ( int ) Math.round ( ( c1.getRed () + c2.getRed () ) / 2.0 );
int g = ( int ) Math.round ( ( c1.getGreen () + c2.getGreen () ) / 2.0 );
int b = ( int ) Math.round ( ( c1.getBlue () + c2.getBlue () ) / 2.0 );
return new Color ( r, g, b );
}
// i >= 0 <= d
// c1 ist Einblendfarbe
// c2 ist Hintergrundfarbe
public static Color getGradient ( Color c1, Color c2, int d, int i )
{
if ( i == 0 )
return c1;
if ( i == d )
return c2;
double d2 = i * 1.1 / d;
double d1 = 1.0 - d2;
int r = ( int ) Math.round ( c1.getRed () * d1 + c2.getRed () * d2 );
int g = ( int ) Math.round ( c1.getGreen () * d1 + c2.getGreen () * d2 );
int b = ( int ) Math.round ( c1.getBlue () * d1 + c2.getBlue () * d2 );
return new Color ( r, g, b );
}
public static Color getMaxSaturation ( Color c, int memH )
{
int r = c.getRed ();
int g = c.getGreen ();
int b = c.getBlue ();
if ( r == g && r == b )
return c;
int ta = 0, tb = 0, tc = 0;
int mapping = RGB;
if ( r >= g && r >= b )
{
tc = r;
if ( g == b )
{
ta = g;
tb = b;
mapping = RGB;
}
else if ( g > b )
{
ta = g;
tb = b;
mapping = RGB;
}
else
{
tb = g;
ta = b;
mapping = RBG;
}
}
else if ( g >= r && g >= b )
{
tc = g;
if ( r == b )
{
ta = r;
tb = b;
mapping = GRB;
}
else if ( r > b )
{
ta = r;
tb = b;
mapping = GRB;
}
else
{
tb = r;
ta = b;
mapping = GBR;
}
}
else if ( b >= r && b >= g )
{
tc = b;
if ( r == g )
{
ta = r;
tb = g;
mapping = BRG;
}
else if ( r > g )
{
ta = r;
tb = g;
mapping = BRG;
}
else
{
tb = r;
ta = g;
mapping = BGR;
}
}
if ( tb == 0 )
{
return c;
}
int nc = Math.min ( 255, tc + tb );
int nb = Math.max ( 0, tc + tb - 255 );
int na = ta;
int h = 0, mh = 0;
int ba = 0, delta = 360;
Color rc = null;
switch ( mapping )
{
case RGB :
h = getHue ( nc, na, nb );
mh = h;
while ( h != memH && na < 256 )
{
h = getHue ( nc, ++na, nb );
if ( na == 256 )
break;
if ( h == memH )
{
return new Color ( nc, na, nb );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nc, na, nb );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
if ( h != memH )
{
h = getHue ( nc, na, nb );
mh = h;
na = ta;
while ( h != memH && na >= 0 )
{
h = getHue ( nc, --na, nb );
if ( na == -1 )
break;
if ( h == memH )
{
return new Color ( nc, na, nb );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nc, na, nb );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
}
if ( na == 256 | na == -1 )
{
na = ba;
}
rc = new Color ( nc, na, nb );
break;
case RBG :
h = getHue ( nc, nb, na );
mh = h;
while ( h != memH && na < 256 )
{
h = getHue ( nc, nb, ++na );
if ( na == 256 )
break;
if ( h == memH )
{
return new Color ( nc, nb, na );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nc, nb, na );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
if ( h != memH )
{
h = getHue ( nc, na, nb );
mh = h;
na = ta;
while ( h != memH && na >= 0 )
{
h = getHue ( nc, nb, --na );
if ( na == -1 )
break;
if ( h == memH )
{
return new Color ( nc, nb, na );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nc, nb, na );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
}
if ( na == 256 | na == -1 )
{
na = ba;
}
rc = new Color ( nc, nb, na );
break;
case GBR :
h = getHue ( nb, nc, na );
mh = h;
while ( h != memH && na < 256 )
{
h = getHue ( nb, nc, ++na );
if ( na == 256 )
break;
if ( h == memH )
{
return new Color ( nb, nc, na );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nb, nc, na );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
if ( h != memH )
{
h = getHue ( nc, na, nb );
mh = h;
na = ta;
while ( h != memH && na >= 0 )
{
h = getHue ( nb, nc, --na );
if ( na == -1 )
break;
if ( h == memH )
{
return new Color ( nb, nc, na );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nb, nc, na );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
}
if ( na == 256 | na == -1 )
{
na = ba;
}
rc = new Color ( nb, nc, na );
break;
case GRB :
h = getHue ( na, nc, nb );
mh = h;
while ( h != memH && na < 256 )
{
h = getHue ( ++na, nc, nb );
if ( na == 256 )
break;
if ( h == memH )
{
return new Color ( na, nc, nb );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( na, nc, nb );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
if ( h != memH )
{
h = getHue ( nc, na, nb );
mh = h;
na = ta;
while ( h != memH && na >= 0 )
{
h = getHue ( --na, nc, nb );
if ( na == -1 )
break;
if ( h == memH )
{
return new Color ( na, nc, nb );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( na, nc, nb );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
}
if ( na == 256 | na == -1 )
{
na = ba;
}
rc = new Color ( na, nc, nb );
break;
case BRG :
h = getHue ( na, nb, nc );
mh = h;
while ( h != memH && na < 256 )
{
h = getHue ( ++na, nb, nc );
if ( na == 256 )
break;
if ( h == memH )
{
return new Color ( na, nb, nc );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( na, nb, nc );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
if ( h != memH )
{
h = getHue ( nc, na, nb );
mh = h;
na = ta;
while ( h != memH && na >= 0 )
{
h = getHue ( --na, nb, nc );
if ( na == -1 )
break;
if ( h == memH )
{
return new Color ( na, nb, nc );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( na, nb, nc );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
}
if ( na == 256 | na == -1 )
{
na = ba;
}
rc = new Color ( na, nb, nc );
break;
case BGR :
h = getHue ( nb, na, nc );
mh = h;
while ( h != memH && na < 256 )
{
h = getHue ( nb, ++na, nc );
if ( na == 256 )
break;
if ( h == memH )
{
return new Color ( nb, na, nc );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nb, na, nc );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
if ( h != memH )
{
h = getHue ( nc, na, nb );
mh = h;
na = ta;
while ( h != memH && na >= 0 )
{
h = getHue ( nb, --na, nc );
if ( na == -1 )
break;
if ( h == memH )
{
return new Color ( nb, na, nc );
}
else if ( ( mh < memH && h > memH ) || ( mh > memH && h < memH ) )
{
return new Color ( nb, na, nc );
}
else if ( Math.abs ( h - memH ) < delta )
{
delta = Math.abs ( h - memH );
ba = na;
}
mh = h;
}
}
if ( na == 256 | na == -1 )
{
na = ba;
}
rc = new Color ( nb, na, nc );
break;
}
return rc;
}
public static float getGreyValue ( Color c )
{
int r = c.getRed ();
int g = c.getGreen ();
int b = c.getBlue ();
int ta = 0, tb = 0, tc = 0;
if ( r >= g && r >= b )
{
if ( r == 0 )
return 0; // black
tc = r;
if ( g >= b )
{
ta = g;
tb = b;
}
else
{
tb = g;
ta = b;
}
}
else if ( g >= r && g >= b )
{
tc = g;
if ( r >= b )
{
ta = r;
tb = b;
}
else
{
tb = r;
ta = b;
}
}
else if ( b >= r && b >= g )
{
tc = b;
if ( r >= g )
{
ta = r;
tb = g;
}
else
{
tb = r;
ta = g;
}
}
return ( float ) ( ( tc + tb ) / 2.0 );
}
public static int getBrightness ( Color c )
{
int r = c.getRed ();
int g = c.getGreen ();
int b = c.getBlue ();
return getBrightness ( r, g, b );
}
public static int getBrightness ( int r, int g, int b )
{
if ( r >= g && r >= b )
{
return ( int ) Math.round ( 100 * r / 255.0 );
}
else if ( g >= r && g >= b )
{
return ( int ) Math.round ( 100 * g / 255.0 );
}
else if ( b >= r && b >= g )
{
return ( int ) Math.round ( 100 * b / 255.0 );
}
return -1;
}
public static int getSaturation ( Color c )
{
int r = c.getRed ();
int g = c.getGreen ();
int b = c.getBlue ();
return getSaturation ( r, g, b );
}
public static int getSaturation ( int r, int g, int b )
{
int ta = 0, tb = 0, tc = 0;
if ( r >= g && r >= b )
{
if ( r == 0 )
return 0; // black
tc = r;
if ( g >= b )
{
ta = g;
tb = b;
}
else
{
tb = g;
ta = b;
}
}
else if ( g >= r && g >= b )
{
tc = g;
if ( r >= b )
{
ta = r;
tb = b;
}
else
{
tb = r;
ta = b;
}
}
else if ( b >= r && b >= g )
{
tc = b;
if ( r >= g )
{
ta = r;
tb = g;
}
else
{
tb = r;
ta = g;
}
}
return 100 - ( int ) Math.round ( 100.0 * tb / tc );
}
public static int getHue ( Color c )
{
int r = c.getRed ();
int g = c.getGreen ();
int b = c.getBlue ();
return getHue ( r, g, b );
}
public static int calculateHue ( Color c )
{
float f[] = Color
.RGBtoHSB ( c.getRed (), c.getGreen (), c.getBlue (), null );
return ( int ) Math.round ( 360.0 * f [ 0 ] );
}
public static int getHue ( int r, int g, int b )
{
int ta = 0, tb = 0, tc = 0;
int mapping = RGB;
if ( r >= g && r >= b )
{
tc = r;
if ( g == b )
{
return 0;
}
else if ( g > b )
{
ta = g;
tb = b;
mapping = RGB;
}
else
{
tb = g;
ta = b;
mapping = RBG;
}
}
else if ( g >= r && g >= b )
{
tc = g;
if ( r == b )
{
return 120;
}
else if ( r > b )
{
ta = r;
tb = b;
mapping = GRB;
}
else
{
tb = r;
ta = b;
mapping = GBR;
}
}
else if ( b >= r && b >= g )
{
tc = b;
if ( r == g )
{
return 240;
}
else if ( r > g )
{
ta = r;
tb = g;
mapping = BRG;
}
else
{
tb = r;
ta = g;
mapping = BGR;
}
}
// normalize
double na = ( ta * 255.0 / tc );
double nb = ( tb * 255.0 / tc );
double val = ( ( na - nb ) * 255.0 / ( 255 - nb ) );
int w = ( int ) Math.round ( 60 * val / 255.0 );
switch ( mapping )
{
case RGB :
return w; // 0 - 60
case RBG :
return 360 - w; // 300 - 360
case GBR :
return 120 + w; // 120 - 180
case GRB :
return 120 - w; // 60 - 120
case BRG :
return 240 + w; // 240 - 300
case BGR :
return 240 - w; // 180 - 240
default :
return -1;
}
}
public static Color getHSB ( int h, int s, int b )
{
double cr = 0, cg = 0, cb = 0;
int mapping = RGB;
if ( h == 360 )
h = 0;
// compute hue
int winkel = h / 60;
int amount = h % 60;
switch ( winkel )
{
case 0 : // 0 - 60
cr = 255;
cg = ( 255 * amount / 60.0 );
mapping = RGB;
break;
case 1 : // 60 - 120
cg = 255;
cr = 255 - ( 255 * amount / 60.0 );
mapping = GBR;
break;
case 2 : // 120 - 180
cg = 255;
cb = ( 255 * amount / 60.0 );
mapping = GBR;
break;
case 3 : // 180 - 240
cb = 255;
cg = 255 - ( 255 * amount / 60.0 );
mapping = BRG;
break;
case 4 : // 240 - 300
cb = 255;
cr = ( 255 * amount / 60.0 );
mapping = BRG;
break;
case 5 : // 300 - 360
cr = 255;
cb = 255 - ( 255 * amount / 60.0 );
mapping = RGB;
break;
}
// compute brightness
cr = ( cr * b / 100.0 );
cg = ( cg * b / 100.0 );
cb = ( cb * b / 100.0 );
// compute saturation
int d = 100 - s;
switch ( mapping )
{
case RGB :
cg += ( ( cr - cg ) * d / 100.0 );
cb += ( ( cr - cb ) * d / 100.0 );
break;
case GBR :
cr += ( ( cg - cr ) * d / 100.0 );
cb += ( ( cg - cb ) * d / 100.0 );
break;
case BRG :
cr += ( ( cb - cr ) * d / 100.0 );
cg += ( ( cb - cg ) * d / 100.0 );
break;
}
return new Color ( ( int ) Math.round ( cr ), ( int ) Math.round ( cg ),
( int ) Math.round ( cb ) );
}
// Parameter: the original icon pixel
public int colorize ( int r, int g, int b, int a )
{
if ( cbri == 100 )
{
return colorToInt ( 255, 255, 255, a );
}
else if ( cbri == -100 )
{
return colorToInt ( 0, 0, 0, a );
}
// first calculate the grey value
int hi1 = r;
if ( g >= r && g >= b )
hi1 = g;
else if ( b >= r && b >= g )
hi1 = b;
int lo1 = r;
if ( g <= r && g <= b )
lo1 = g;
else if ( b <= r && b <= g )
lo1 = b;
int grey = ( hi1 + lo1 ) / 2; // floor
// compute with cbri
if ( cbri < 0 )
{
grey += grey * cbri / 100;
}
else if ( cbri > 0 )
{
grey += ( 255 - grey ) * cbri / 100;
}
// if in-colors are equal and preserveGrey is true,
// return grey values
if ( preserveGrey )
{
if ( r == g && r == b )
{
return colorToInt ( grey, grey, grey, a );
}
}
// now calculate the output colors
// csat = 0 => output = grey
// grey = 127 => output = full saturation
int hr = 0;
int hg = 0;
int hb = 0;
int diff = 0;
if ( grey >= 127 )
{
diff = 255 - grey;
}
else
{
diff = grey;
}
// hi value is always 255
if ( hiIsR )
{
hr = grey + diff * csat / 100;
}
else if ( hiIsG )
{
hg = grey + diff * csat / 100;
}
else if ( hiIsB )
{
hb = grey + diff * csat / 100;
}
// md value is between 0 and 255
if ( mdIsR )
{
if ( grey >= 127 )
{
diff = fr + ( 255 - fr ) * ( grey - 127 ) / 128 - grey;
}
else
{
diff = fr * grey / 127 - grey;
}
hr = grey + diff * csat / 100;
}
else if ( mdIsG )
{
if ( grey >= 127 )
{
diff = fg + ( 255 - fg ) * ( grey - 127 ) / 128 - grey;
}
else
{
diff = fg * grey / 127 - grey;
}
hg = grey + diff * csat / 100;
}
else if ( mdIsB )
{
if ( grey >= 127 )
{
diff = fb + ( 255 - fb ) * ( grey - 127 ) / 128 - grey;
}
else
{
diff = fb * grey / 127 - grey;
}
hb = grey + diff * csat / 100;
}
diff = grey - ( 255 - grey );
if ( diff < 0 )
diff = 0;
diff = grey - diff;
// lo value = 0
if ( loIsR )
{
hr = grey - diff * csat / 100;
}
else if ( loIsG )
{
hg = grey - diff * csat / 100;
}
else if ( loIsB )
{
hb = grey - diff * csat / 100;
}
return colorToInt ( hr, hg, hb, a );
}
public static Color getInverseColor ( Color c )
{
int r = 255 - c.getRed ();
int g = 255 - c.getGreen ();
int b = 255 - c.getBlue ();
return new Color ( r, g, b );
}
public static Color getRandomColor ()
{
int r = ( int ) ( Math.random () * 255 );
int g = ( int ) ( Math.random () * 255 );
int b = ( int ) ( Math.random () * 255 );
return new Color ( r, g, b );
}
public static Color getAlphaColor ( Color c, int a )
{
int r = c.getRed ();
int g = c.getGreen ();
int b = c.getBlue ();
return new Color ( r, g, b, a );
}
protected static int colorToInt ( Color c, int a )
{
return c.getBlue () + c.getGreen () * 256 + c.getRed () * ( 256 * 256 ) + a
* ( 256 * 256 * 256 );
}
protected static int colorToInt ( int r, int g, int b, int a )
{
return b + g * 256 + r * ( 256 * 256 ) + a * ( 256 * 256 * 256 );
}
public static Color lighten ( Color c, int amount )
{
if ( amount < 0 )
return c;
if ( amount > 100 )
amount = 100;
int dr = ( int ) Math.round ( ( 255 - c.getRed () ) * amount / 100.0 );
int dg = ( int ) Math.round ( ( 255 - c.getGreen () ) * amount / 100.0 );
int db = ( int ) Math.round ( ( 255 - c.getBlue () ) * amount / 100.0 );
return new Color ( c.getRed () + dr, c.getGreen () + dg, c.getBlue () + db,
c.getAlpha () );
}
public static Color darken ( Color c, int amount )
{
if ( amount < 0 || amount > 100 )
return c;
int r = ( int ) Math.round ( c.getRed () * ( 100 - amount ) / 100.0 );
int g = ( int ) Math.round ( c.getGreen () * ( 100 - amount ) / 100.0 );
int b = ( int ) Math.round ( c.getBlue () * ( 100 - amount ) / 100.0 );
return new Color ( r, g, b, c.getAlpha () );
}
public static Color lighten ( int grey, int amount )
{
if ( amount < 0 || amount > 100 )
return new Color ( grey, grey, grey );
int val = ( 255 - grey ) * amount / 100 + grey;
return new Color ( val, val, val );
}
public static Color darken ( int grey, int amount )
{
if ( amount < 0 || amount > 100 )
return new Color ( grey, grey, grey );
int val = grey * ( 100 - amount ) / 100;
return new Color ( val, val, val );
}
}