/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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.*; /** * ColorRoutines * * @version 1.0 * @author Hans Bickel */ 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); } }