/******************************************************************************* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 ); } }