001: /*
002: *
003: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025:
026: package com.sun.pisces;
027:
028: public class GradientColorMap {
029:
030: public static final int CYCLE_NONE = 0;
031: public static final int CYCLE_REPEAT = 1;
032: public static final int CYCLE_REFLECT = 2;
033:
034: public int cycleMethod;
035:
036: private static final int LG_RAMP_SIZE = 8;
037: private static final int RAMP_SIZE = 1 << LG_RAMP_SIZE;
038: public int[] fractions = null;
039: public int[] rgba = null;
040: public int[] colors = null;
041:
042: // private static void printArray(int[] arr, String name) {
043: // System.out.print(name + " = {");
044: // System.out.print(arr[0]);
045: // for (int i = 1; i < arr.length; i++) {
046: // System.out.print(", " + arr[i]);
047: // }
048: // System.out.println("}");
049: // }
050:
051: public GradientColorMap(int[] fractions, int[] rgba, int cycleMethod) {
052: this .cycleMethod = cycleMethod;
053:
054: // System.out.println("GCM ctor:");
055: // printArray(fractions, "fractions before");
056: // printArray(rgba, "rgba before");
057:
058: int numStops = fractions.length;
059: if (fractions[0] != 0) {
060: int[] nfractions = new int[numStops + 1];
061: int[] nrgba = new int[numStops + 1];
062: System.arraycopy(fractions, 0, nfractions, 1, numStops);
063: System.arraycopy(rgba, 0, nrgba, 1, numStops);
064: nfractions[0] = 0;
065: nrgba[0] = rgba[0];
066: fractions = nfractions;
067: rgba = nrgba;
068: ++numStops;
069: }
070:
071: if (fractions[numStops - 1] != 0x10000) {
072: int[] nfractions = new int[numStops + 1];
073: int[] nrgba = new int[numStops + 1];
074: System.arraycopy(fractions, 0, nfractions, 0, numStops);
075: System.arraycopy(rgba, 0, nrgba, 0, numStops);
076: nfractions[numStops] = 0x10000;
077: nrgba[numStops] = rgba[numStops - 1];
078: fractions = nfractions;
079: rgba = nrgba;
080: }
081:
082: // printArray(fractions, "fractions after");
083: // printArray(rgba, "rgba after");
084:
085: this .fractions = new int[fractions.length];
086: System.arraycopy(fractions, 0, this .fractions, 0,
087: fractions.length);
088: this .rgba = new int[rgba.length];
089: System.arraycopy(rgba, 0, this .rgba, 0, rgba.length);
090:
091: createRamp(fractions, rgba);
092: }
093:
094: private int pad(int frac) {
095: switch (cycleMethod) {
096: case CYCLE_NONE:
097: if (frac < 0) {
098: return 0;
099: } else if (frac > 0xffff) {
100: return 0xffff;
101: } else {
102: return frac;
103: }
104:
105: case CYCLE_REPEAT:
106: return frac & 0xffff;
107:
108: case CYCLE_REFLECT:
109: if (frac < 0) {
110: frac = -frac;
111: }
112: frac = frac & 0x1ffff;
113: if (frac > 0xffff) {
114: frac = 0x1ffff - frac;
115: }
116: return frac;
117:
118: default:
119: throw new RuntimeException("Unknown cycle method: "
120: + cycleMethod);
121: }
122: }
123:
124: private void accumColor(int frac, int[] fractions, int[] r,
125: int[] g, int[] b, int[] a, int[] red, int[] green,
126: int[] blue, int[] alpha) {
127: int numStops = fractions.length;
128: int stop = -1;
129: for (int i = 0; i < numStops; i++) {
130: if (fractions[i] > frac) {
131: stop = i;
132: break;
133: }
134: }
135:
136: frac -= fractions[stop - 1];
137: int delta = fractions[stop] - fractions[stop - 1];
138:
139: red[0] += r[stop - 1] + (frac * (r[stop] - r[stop - 1]))
140: / delta;
141: green[0] += g[stop - 1] + (frac * (g[stop] - g[stop - 1]))
142: / delta;
143: blue[0] += b[stop - 1] + (frac * (b[stop] - b[stop - 1]))
144: / delta;
145: alpha[0] += a[stop - 1] + (frac * (a[stop] - a[stop - 1]))
146: / delta;
147: }
148:
149: private int getColorAA(int frac, int[] fractions, int[] r, int[] g,
150: int[] b, int[] a, int[] red, int[] green, int[] blue,
151: int[] alpha) {
152: int delta = 256;
153: int step = 1;
154: int total = 0;
155: for (int i = -delta; i <= delta; i += step) {
156: int f = pad(frac + i);
157: accumColor(f, fractions, r, g, b, a, red, green, blue,
158: alpha);
159: ++total;
160: }
161:
162: alpha[0] /= total;
163: red[0] /= total;
164: green[0] /= total;
165: blue[0] /= total;
166:
167: return (alpha[0] << 24) | (red[0] << 16) | (green[0] << 8)
168: | blue[0];
169: }
170:
171: private void createRamp(int[] fractions, int[] rgba) {
172: this .colors = new int[RAMP_SIZE];
173:
174: int[] alpha = new int[1];
175: int[] red = new int[1];
176: int[] green = new int[1];
177: int[] blue = new int[1];
178:
179: int numStops = fractions.length;
180: int[] a = new int[numStops];
181: int[] r = new int[numStops];
182: int[] g = new int[numStops];
183: int[] b = new int[numStops];
184:
185: for (int i = 0; i < numStops; i++) {
186: a[i] = (rgba[i] >> 24) & 0xff;
187: r[i] = (rgba[i] >> 16) & 0xff;
188: g[i] = (rgba[i] >> 8) & 0xff;
189: b[i] = rgba[i] & 0xff;
190: }
191:
192: for (int i = 0; i < RAMP_SIZE; i++) {
193: red[0] = green[0] = blue[0] = alpha[0] = 0;
194: colors[i] = getColorAA(i << (16 - LG_RAMP_SIZE), fractions,
195: r, g, b, a, red, green, blue, alpha);
196: }
197: }
198:
199: public int getColor(int frac) {
200: frac = pad(frac);
201: frac >>= 16 - LG_RAMP_SIZE;
202: return colors[frac];
203: }
204: }
|