Revision 12504 trunk/libraries/libRaster/src/org/gvsig/raster/datastruct/ColorTable.java
ColorTable.java | ||
---|---|---|
18 | 18 |
*/ |
19 | 19 |
package org.gvsig.raster.datastruct; |
20 | 20 |
|
21 |
import java.awt.Color; |
|
21 | 22 |
import java.util.ArrayList; |
22 | 23 |
|
23 |
import org.gvsig.raster.dataset.IBuffer;
|
|
24 |
import org.gvsig.raster.RasterLibrary;
|
|
24 | 25 |
|
25 | 26 |
import es.gva.cit.jgdal.GdalColorEntry; |
26 | 27 |
import es.gva.cit.jgdal.GdalColorTable; |
27 | 28 |
import es.gva.cit.jgdal.GdalException; |
28 | 29 |
/** |
29 | 30 |
* Paleta para raster. Esta consta de los valores RGB de la paleta que son |
30 |
* almacenados en un vector de enteros donde cada elemento entero contiene en su |
|
31 |
* interior el RGB completo y del vector de rangos. Dependiendo de si el tipo de |
|
32 |
* rango es entero o decimal este estar? almacenado en un vector de rangos |
|
33 |
* entero (intRange) o en un vector de rangos double (doubleRange). El tipo de |
|
34 |
* dato del rango quedar? almacenado en la variable type. |
|
31 |
* almacenados en un vector donde cada elemento contiene en su interior el RGB |
|
32 |
* completo y del vector de rangos. |
|
35 | 33 |
* |
34 |
* @version 04/07/2007 |
|
36 | 35 |
* @author Nacho Brodin (nachobrodin@gmail.com) |
36 |
* @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es) |
|
37 | 37 |
*/ |
38 | 38 |
public class ColorTable implements Cloneable { |
39 | 39 |
/** |
40 |
* Tipo de dato de la paleta |
|
41 |
* <UL> |
|
42 |
* <LI>TYPE_INT = Valido para byte, short e int</LI> |
|
43 |
* <LI>TYPE_DOUBLE = Valido para float y double</LI> |
|
44 |
* </UL> |
|
40 |
* Lista de ColorItem donde estaran todos los valores de la paleta segun |
|
41 |
* el interfaz |
|
45 | 42 |
*/ |
46 |
protected int type = IBuffer.TYPE_UNDEFINED; |
|
43 |
private ArrayList colorItems = null; |
|
44 |
|
|
47 | 45 |
/** |
48 |
* Lista de rangos para paletas enteras
|
|
46 |
* Booleano que define si se interpolaran los valores de la paleta.
|
|
49 | 47 |
*/ |
50 |
protected int[] intRange = null; |
|
48 |
protected boolean interpolated = true; |
|
49 |
|
|
51 | 50 |
/** |
52 | 51 |
* Lista de rangos para paletas decimales |
53 | 52 |
*/ |
54 |
protected double[] doubleRange = null; |
|
53 |
|
|
54 |
protected double[] range = null; |
|
55 | 55 |
/** |
56 | 56 |
* Lista de valores RGB |
57 | 57 |
*/ |
58 |
protected int[] palette = null; |
|
59 |
protected byte[][] paletteByBand = null; |
|
58 |
protected byte[][] paletteByBand = null; |
|
60 | 59 |
|
61 | 60 |
/** |
62 | 61 |
* Nombre de la clase asociada a la entrada |
63 | 62 |
*/ |
64 |
protected String[] nameClass = null; |
|
63 |
protected String[] nameClass = null; |
|
64 |
|
|
65 | 65 |
/** |
66 |
* Lista con todas las transparencias de la paleta |
|
67 |
*/ |
|
68 |
protected ArrayList transparencyRange = new ArrayList(); |
|
69 |
|
|
70 |
/** |
|
66 | 71 |
* Nombre de la paleta |
67 | 72 |
*/ |
68 |
protected String name = null; |
|
73 |
protected String name = null; |
|
74 |
|
|
69 | 75 |
/** |
70 |
* Ruta del fichero a la cual se asocia la paleta. Las bandas de un GeoRasterMultiFile
|
|
71 |
* han de saber a que paleta van asociadas. |
|
76 |
* Ruta del fichero a la cual se asocia la paleta. Las bandas de un |
|
77 |
* GeoRasterMultiFile han de saber a que paleta van asociadas.
|
|
72 | 78 |
*/ |
73 |
protected String filePath = null;
|
|
79 |
protected String filePath = null;
|
|
74 | 80 |
|
75 |
private ArrayList range = new ArrayList(); |
|
81 |
/** |
|
82 |
* Constructor vac?o. |
|
83 |
* @param name |
|
84 |
*/ |
|
85 |
public ColorTable() { |
|
86 |
this.name = ""; |
|
87 |
} |
|
76 | 88 |
|
77 |
public ColorTable() {} |
|
78 |
|
|
79 | 89 |
/** |
80 | 90 |
* Constructor. Asigna el nombre de la paleta. |
81 | 91 |
* @param name |
... | ... | |
100 | 110 |
return name; |
101 | 111 |
} |
102 | 112 |
|
103 |
/* |
|
104 |
* TODO: RENDIMIENTO: Incluir una heuristica que dado un valor se compare con el |
|
105 |
* valor de la mitad de la tabla y si es menor se empieza a recorrer desde el principio |
|
106 |
* sino se empieza a recorrer desde la mitad de la tabla hasta abajo. Esto hace |
|
107 |
* que se reduzca la tabla a la mitad de valores haciendo solo una comparaci?n. |
|
108 |
*/ |
|
109 |
/** |
|
110 |
* Obtiene el valor RGB para un clave entera pasada por par?metro |
|
111 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta |
|
112 |
* @return valor RGB |
|
113 |
*/ |
|
114 |
public int getRGB(int value) { |
|
115 |
int init = 1; |
|
116 |
for(int i = init; i <= intRange.length; i++) { |
|
117 |
if(i < intRange.length) { |
|
118 |
if(value > intRange[i]) |
|
119 |
return palette[i - 1]; |
|
120 |
}else{ |
|
121 |
return palette[i - 1]; |
|
113 |
public void createPaletteFromColorItems(ArrayList colorItems) { |
|
114 |
this.colorItems = colorItems; |
|
115 |
|
|
116 |
// Ordena la paleta |
|
117 |
sortPalette(); |
|
118 |
|
|
119 |
// System.out.println(name); |
|
120 |
// System.out.println("----- Sin comprimir (" + colorItems.size() + ") -----"); |
|
121 |
/* |
|
122 |
if (name.equals("MDT1")) { |
|
123 |
for (int i=0; i<colorItems.size(); i++) { |
|
124 |
ColorItem c1 = ((ColorItem) colorItems.get(i)); |
|
125 |
Color co = c1.getColor(); |
|
126 |
System.out.println(c1.getValue() + ": " + co.getRed() + "," + co.getGreen() + "," + co.getBlue() + "," + co.getAlpha()); |
|
122 | 127 |
} |
123 | 128 |
} |
124 |
return 0; |
|
125 |
} |
|
129 |
*/ |
|
130 |
// Mira que valores se pueden descartar y asi dejamos la paleta reducida |
|
131 |
// para poder hacer interpolaciones |
|
132 |
compressPalette(); |
|
126 | 133 |
|
127 |
/** |
|
128 |
* Obtiene el valor RGB para un clave entera pasada por par?metro |
|
129 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta |
|
130 |
* @return valor RGB |
|
131 |
*/ |
|
132 |
public byte[] getRGBByBand(int value) { |
|
133 |
int init = 1; |
|
134 |
for(int i = init; i <= intRange.length; i++) { |
|
135 |
if(i < intRange.length) { |
|
136 |
if(value > intRange[i]) |
|
137 |
return paletteByBand[i - 1]; |
|
138 |
}else{ |
|
139 |
return paletteByBand[i - 1]; |
|
134 |
// System.out.println("------ Comprimido (" + colorItems.size() + ") ------"); |
|
135 |
/* |
|
136 |
if (name.equals("MDT1")) { |
|
137 |
for (int i=0; i<colorItems.size(); i++) { |
|
138 |
ColorItem c1 = ((ColorItem) colorItems.get(i)); |
|
139 |
Color co = c1.getColor(); |
|
140 |
System.out.println(c1.getValue() + ": " + co.getRed() + "," + co.getGreen() + "," + co.getBlue() + "," + co.getAlpha()); |
|
140 | 141 |
} |
141 | 142 |
} |
142 |
return new byte[4]; |
|
143 |
*/ |
|
144 |
// Genera la paleta final para poder ser usada |
|
145 |
applyPalette(); |
|
143 | 146 |
} |
144 | 147 |
|
145 |
/** |
|
146 |
* Obtiene el valor RGB para un clave decimal pasada por par?metro |
|
147 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta |
|
148 |
* @return valor RGB |
|
149 |
*/ |
|
150 |
public int getRGB(double value) { |
|
151 |
int init = 1; |
|
152 |
for(int i = init; i <= doubleRange.length; i++) |
|
153 |
if(i < doubleRange.length) { |
|
154 |
if(value > doubleRange[i]) |
|
155 |
return palette[i - 1]; |
|
156 |
}else{ |
|
157 |
return palette[i - 1]; |
|
158 |
} |
|
159 |
return 0; |
|
148 |
int error = 8; |
|
149 |
private boolean isEqualColor(Color c1, Color c2) { |
|
150 |
if (c2.getRed() < (c1.getRed() - error)) return false; |
|
151 |
if (c2.getGreen() < (c1.getGreen() - error)) return false; |
|
152 |
if (c2.getBlue() < (c1.getBlue() - error)) return false; |
|
153 |
if (c2.getAlpha() < (c1.getAlpha() - error)) return false; |
|
154 |
|
|
155 |
if (c2.getRed() > (c1.getRed() + error)) return false; |
|
156 |
if (c2.getGreen() > (c1.getGreen() + error)) return false; |
|
157 |
if (c2.getBlue() > (c1.getBlue() + error)) return false; |
|
158 |
if (c2.getAlpha() > (c1.getAlpha() + error)) return false; |
|
159 |
|
|
160 |
return true; |
|
160 | 161 |
} |
161 | 162 |
|
162 |
/** |
|
163 |
* Obtiene el valor RGB para un clave entera pasada por par?metro |
|
164 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta |
|
165 |
* @return valor RGB |
|
166 |
*/ |
|
167 |
public byte[] getRGBByBand(double value) { |
|
168 |
int init = 1; |
|
169 |
for(int i = init; i <= doubleRange.length; i++) { |
|
170 |
if(i < doubleRange.length) { |
|
171 |
if(value > doubleRange[i]) |
|
172 |
return paletteByBand[i - 1]; |
|
173 |
}else{ |
|
174 |
return paletteByBand[i - 1]; |
|
163 |
private boolean isCorrectColor(ColorItem c1, ColorItem c2, ColorItem c3) { |
|
164 |
double max = c2.getValue()-c1.getValue(); |
|
165 |
int r = c1.getColor().getRed() + (int) (((c2.getColor().getRed() - c1.getColor().getRed()) * (c3.getValue() - c1.getValue())) / max); |
|
166 |
int g = c1.getColor().getGreen() + (int) (((c2.getColor().getGreen() - c1.getColor().getGreen()) * (c3.getValue() - c1.getValue())) / max); |
|
167 |
int b = c1.getColor().getBlue() + (int) (((c2.getColor().getBlue() - c1.getColor().getBlue()) * (c3.getValue() - c1.getValue())) / max); |
|
168 |
int a = c1.getColor().getAlpha() + (int) (((c2.getColor().getAlpha() - c1.getColor().getAlpha()) * (c3.getValue() - c1.getValue())) / max); |
|
169 |
Color aux = new Color(r & 0xff, g & 0xff, b & 0xff, a & 0xff); |
|
170 |
|
|
171 |
return isEqualColor(c3.getColor(), aux); |
|
172 |
} |
|
173 |
|
|
174 |
private boolean canDelete(int first, int last) { |
|
175 |
ColorItem c1 = (ColorItem) colorItems.get(first); |
|
176 |
ColorItem c2 = (ColorItem) colorItems.get(last); |
|
177 |
for (int i = (first + 1); i < last; i++) { |
|
178 |
if (!isCorrectColor(c1, c2, (ColorItem) colorItems.get(i))) |
|
179 |
return false; |
|
180 |
} |
|
181 |
return true; |
|
182 |
} |
|
183 |
|
|
184 |
private void compressPalette() { |
|
185 |
int init = 0; |
|
186 |
int posMax = 2; |
|
187 |
while (init < colorItems.size()) { |
|
188 |
if ((posMax < colorItems.size()) && canDelete(init, posMax)) { |
|
189 |
posMax++; |
|
190 |
continue; |
|
175 | 191 |
} |
192 |
if ((init + 2) < posMax) { |
|
193 |
if (canDelete(init, posMax - 1)) |
|
194 |
for (int i = (posMax - 2); i > init; i--) |
|
195 |
if (i < colorItems.size()) |
|
196 |
colorItems.remove(i); |
|
197 |
} |
|
198 |
init++; |
|
199 |
posMax = init + 2; |
|
176 | 200 |
} |
177 |
return new byte[4]; |
|
178 | 201 |
} |
179 | 202 |
|
180 | 203 |
/** |
181 |
* Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario para los ficheros |
|
182 |
* que tienen un paleta asignada, como los gif, y que son tratados por Gdal. Se pasa la tabla |
|
183 |
* de color le?da desde gdal y se crea directamente un objeto Palette. |
|
204 |
* Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario |
|
205 |
* para los ficheros que tienen una paleta asignada, como los gif, y que son |
|
206 |
* tratados por Gdal. Se pasa la tabla de color le?da desde gdal y se crea |
|
207 |
* directamente un objeto Palette. |
|
184 | 208 |
* @param table |
185 | 209 |
*/ |
186 | 210 |
public void createPaletteFromGdalColorTable(GdalColorTable table) { |
187 |
try{ |
|
188 |
type = IBuffer.TYPE_BYTE; |
|
189 |
nameClass = new String[table.getColorEntryCount()]; |
|
190 |
palette = new int[table.getColorEntryCount()]; |
|
191 |
paletteByBand = new byte[table.getColorEntryCount()][4]; |
|
192 |
intRange = new int[table.getColorEntryCount()]; |
|
211 |
try { |
|
212 |
colorItems = new ArrayList(); |
|
213 |
for (int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++) { |
|
214 |
GdalColorEntry entry = table.getColorEntryAsRGB(iEntry); |
|
193 | 215 |
|
194 |
int cont = table.getColorEntryCount() - 1; |
|
195 |
for(int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++) { |
|
196 |
GdalColorEntry entry = table.getColorEntryAsRGB(iEntry); |
|
197 |
nameClass[cont] = ""; |
|
198 |
palette[cont] = 0x00000000; |
|
199 |
palette[cont] |= ((entry.c4 & 0x000000ff) << 24); |
|
200 |
palette[cont] |= ((entry.c1 & 0x000000ff) << 16); |
|
201 |
palette[cont] |= ((entry.c2 & 0x000000ff) << 8); |
|
202 |
palette[cont] |= (entry.c3 & 0x000000ff); |
|
203 |
if(entry.c4 != 255) { |
|
204 |
TransparencyRange r = new TransparencyRange(); |
|
205 |
r.setRed(new int[]{entry.c1 & 0xffff, entry.c1 & 0xffff}); |
|
206 |
r.setGreen(new int[]{entry.c2 & 0xffff, entry.c2 & 0xffff}); |
|
207 |
r.setBlue(new int[]{entry.c3 & 0xffff, entry.c3 & 0xffff}); |
|
208 |
r.setAnd(true); |
|
209 |
r.loadStrEntryFromValues(); |
|
210 |
range.add(r); |
|
211 |
} |
|
212 |
paletteByBand[cont][0] = (byte)(entry.c1 & 0xffff); |
|
213 |
paletteByBand[cont][1] = (byte)(entry.c2 & 0xffff); |
|
214 |
paletteByBand[cont][2] = (byte)(entry.c3 & 0xffff); |
|
215 |
intRange[cont] = iEntry; |
|
216 |
cont --; |
|
217 |
} |
|
218 |
}catch(GdalException ex) { |
|
219 |
//No se crea la paleta |
|
216 |
ColorItem colorItem = new ColorItem(); |
|
217 |
colorItem.setNameClass(""); |
|
218 |
colorItem.setValue(iEntry); |
|
219 |
colorItem.setColor(new Color( (int) (entry.c1 & 0xff), |
|
220 |
(int) (entry.c2 & 0xff), |
|
221 |
(int) (entry.c3 & 0xff), |
|
222 |
(int) (entry.c4 & 0xff))); |
|
223 |
|
|
224 |
colorItems.add(colorItem); |
|
225 |
} |
|
226 |
} catch (GdalException ex) { |
|
227 |
// No se crea la paleta |
|
220 | 228 |
} |
229 |
sortPalette(); |
|
230 |
applyPalette(); |
|
221 | 231 |
} |
222 | 232 |
|
223 | 233 |
/** |
... | ... | |
225 | 235 |
* @return Lista de objetos TransparencyRange |
226 | 236 |
*/ |
227 | 237 |
public ArrayList getTransparencyRanges() { |
228 |
return range;
|
|
238 |
return transparencyRange;
|
|
229 | 239 |
} |
230 | 240 |
|
231 | 241 |
/** |
... | ... | |
248 | 258 |
* Obtiene la tabla de color |
249 | 259 |
* @return Paleta |
250 | 260 |
*/ |
261 |
/* |
|
251 | 262 |
public int[] getColorTable() { |
252 | 263 |
return palette; |
253 | 264 |
} |
265 |
*/ |
|
254 | 266 |
|
255 | 267 |
/** |
256 | 268 |
* Obtiene la tabla de color por banda |
... | ... | |
260 | 272 |
return paletteByBand; |
261 | 273 |
} |
262 | 274 |
|
275 |
|
|
263 | 276 |
/** |
264 | 277 |
* Asigna una paleta |
265 | 278 |
* @param palette Paleta |
266 | 279 |
*/ |
267 | 280 |
public void setColorTable(int[] palette) { |
268 |
this.palette = palette; |
|
269 | 281 |
paletteByBand = new byte[palette.length][3]; |
270 | 282 |
for (int i = 0; i < palette.length; i++) { |
271 | 283 |
paletteByBand[i][0] = (byte)((palette[i] & 0x00ff0000) >> 16); |
... | ... | |
275 | 287 |
} |
276 | 288 |
|
277 | 289 |
/** |
278 |
* Obtiene el tipo del rango de la paleta que corresponde con los tipos de rasterBuf |
|
279 |
* @return Tipo de rango, entero o double |
|
280 |
*/ |
|
281 |
public int getType() { |
|
282 |
return type; |
|
283 |
} |
|
284 |
|
|
285 |
/** |
|
286 |
* Asigna el tipo del rango de la paleta que corresponde con los tipos de rasterBuf |
|
287 |
* @param Tipo de rango, entero o double |
|
288 |
*/ |
|
289 |
public void setType(int type) { |
|
290 |
this.type = type; |
|
291 |
} |
|
292 |
|
|
293 |
/** |
|
294 |
* Asigna los rangos si el tipo es decimal |
|
295 |
* @param rangos |
|
296 |
*/ |
|
297 |
public void setDoubleRange(double[] value) { |
|
298 |
doubleRange = value; |
|
299 |
} |
|
300 |
|
|
301 |
/** |
|
302 |
* Asigna los rangos si el tipo es entero |
|
303 |
* @param values |
|
304 |
*/ |
|
305 |
public void setIntRange(int[] values) { |
|
306 |
intRange = values; |
|
307 |
} |
|
308 |
|
|
309 |
/** |
|
310 |
* Obtiene los rangos si el tipo es decimal |
|
311 |
* @return rangos |
|
312 |
*/ |
|
313 |
public double[] getDoubleRange() { |
|
314 |
return doubleRange; |
|
315 |
} |
|
316 |
|
|
317 |
/** |
|
318 |
* Obtiene los rangos si el tipo es entero |
|
319 |
* @return rangos |
|
320 |
*/ |
|
321 |
public int[] getIntRange() { |
|
322 |
return intRange; |
|
323 |
} |
|
324 |
|
|
325 |
|
|
326 |
/** |
|
327 | 290 |
* Obtiene los nombres de las clases de la paleta |
328 | 291 |
* @return Array de cadenas. Cada una corresponde con un nombre de clase |
329 | 292 |
* que corresponde a cada rango de tipos. |
... | ... | |
364 | 327 |
* @return ArrayList |
365 | 328 |
*/ |
366 | 329 |
public ArrayList getTransparencyRange() { |
367 |
return range;
|
|
330 |
return transparencyRange;
|
|
368 | 331 |
} |
369 | 332 |
|
370 | 333 |
/* |
... | ... | |
378 | 341 |
} catch (CloneNotSupportedException e) { |
379 | 342 |
} |
380 | 343 |
|
381 |
if (doubleRange != null) |
|
382 |
clone.doubleRange = (double[]) doubleRange.clone(); |
|
383 |
|
|
384 | 344 |
if (filePath != null) |
385 | 345 |
clone.filePath = new String(filePath); |
386 | 346 |
|
387 |
if (intRange != null) |
|
388 |
clone.intRange = (int[]) intRange.clone(); |
|
389 |
|
|
390 | 347 |
if (name != null) |
391 | 348 |
clone.name = new String(name); |
392 | 349 |
|
... | ... | |
396 | 353 |
clone.nameClass[i] = new String(nameClass[i]); |
397 | 354 |
} |
398 | 355 |
|
399 |
if (palette != null) |
|
400 |
clone.palette = (int[]) palette.clone(); |
|
401 |
|
|
402 | 356 |
if (paletteByBand != null) { |
403 | 357 |
clone.paletteByBand = (byte[][]) paletteByBand.clone(); |
404 | 358 |
for (int i = 0; i < paletteByBand.length; i++) |
405 | 359 |
clone.paletteByBand[i] = (byte[]) paletteByBand[i].clone(); |
406 | 360 |
} |
407 | 361 |
|
408 |
if (range != null) { |
|
409 |
clone.range = new ArrayList(); |
|
410 |
for (int i = 0; i < range.size(); i++) |
|
411 |
clone.range.add(((TransparencyRange) range.get(i)).clone()); |
|
362 |
return clone; |
|
363 |
} |
|
364 |
|
|
365 |
/** |
|
366 |
* Devuelve un color de interpolacion entre dos colores |
|
367 |
* @param value |
|
368 |
* @param pos |
|
369 |
* @return |
|
370 |
*/ |
|
371 |
private Color interpolatedColor(double value, int pos) { |
|
372 |
if ((pos + 1) == colorItems.size()) |
|
373 |
return ((ColorItem) colorItems.get(pos)).getColor(); |
|
374 |
|
|
375 |
ColorItem item1 = (ColorItem) colorItems.get(pos); |
|
376 |
ColorItem item2 = (ColorItem) colorItems.get(pos + 1); |
|
377 |
|
|
378 |
double percValue = ((value - item1.getValue()) * 100) / (item2.getValue() - item1.getValue()); |
|
379 |
|
|
380 |
Color halfColor = new Color( |
|
381 |
(item2.getColor().getRed() + item1.getColor().getRed()) >> 1, |
|
382 |
(item2.getColor().getGreen() + item1.getColor().getGreen()) >> 1, |
|
383 |
(item2.getColor().getBlue() + item1.getColor().getBlue()) >> 1, |
|
384 |
(item2.getColor().getAlpha() + item1.getColor().getAlpha()) >> 1); |
|
385 |
|
|
386 |
Color color1, color2; |
|
387 |
int perc1, perc2; |
|
388 |
|
|
389 |
if (percValue > item1.getInterpolated()) { |
|
390 |
color1 = halfColor; |
|
391 |
color2 = item2.getColor(); |
|
392 |
perc1 = item1.getInterpolated(); |
|
393 |
perc2 = 100; |
|
394 |
} else { |
|
395 |
color1 = item1.getColor(); |
|
396 |
color2 = halfColor; |
|
397 |
perc1 = 0; |
|
398 |
perc2 = item1.getInterpolated(); |
|
412 | 399 |
} |
413 | 400 |
|
414 |
return clone; |
|
401 |
double percNew = (percValue - perc1) / (perc2 - perc1); |
|
402 |
|
|
403 |
Color newColor = new Color( |
|
404 |
(int) (color1.getRed() + ((color2.getRed() - color1.getRed()) * percNew)) & 0xff, |
|
405 |
(int) (color1.getGreen() + ((color2.getGreen() - color1.getGreen()) * percNew)) & 0xff, |
|
406 |
(int) (color1.getBlue() + ((color2.getBlue() - color1.getBlue()) * percNew)) & 0xff, |
|
407 |
(int) (color1.getAlpha() + ((color2.getAlpha() - color1.getAlpha()) * percNew)) & 0xff); |
|
408 |
|
|
409 |
|
|
410 |
return newColor; |
|
415 | 411 |
} |
412 |
|
|
413 |
/* |
|
414 |
* TODO: RENDIMIENTO: Incluir una heuristica que dado un valor se compare con el |
|
415 |
* valor de la mitad de la tabla y si es menor se empieza a recorrer desde el principio |
|
416 |
* sino se empieza a recorrer desde la mitad de la tabla hasta abajo. Esto hace |
|
417 |
* que se reduzca la tabla a la mitad de valores haciendo solo una comparaci?n. |
|
418 |
*/ |
|
419 |
/** |
|
420 |
* Obtiene el valor RGB para un clave entera pasada por par?metro |
|
421 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta |
|
422 |
* @return valor RGB |
|
423 |
*/ |
|
424 |
public byte[] getRGBByBand(double value) { |
|
425 |
int init = 1; |
|
426 |
for (int i = init; i <= range.length; i++) { |
|
427 |
if (i < range.length) { |
|
428 |
if (value < range[i]) |
|
429 |
return paletteByBand[i - 1]; |
|
430 |
} else { |
|
431 |
return paletteByBand[i - 1]; |
|
432 |
} |
|
433 |
} |
|
434 |
return new byte[4]; |
|
435 |
} |
|
436 |
|
|
437 |
/** |
|
438 |
* Ordena el ColorItems de manera ascendente. De momento se usa el m?todo de |
|
439 |
* ordenaci?n por burbuja. |
|
440 |
*/ |
|
441 |
// TODO: Usar el m?todo Quicksort para ordenar |
|
442 |
private void sortPalette() { |
|
443 |
for (int i = 0; i < colorItems.size(); i++) { |
|
444 |
for (int j = i + 1; j < colorItems.size(); j++) { |
|
445 |
if (((ColorItem) colorItems.get(j)).getValue() < ((ColorItem) colorItems.get(i)).getValue()) { |
|
446 |
Object aux = colorItems.get(i); |
|
447 |
colorItems.set(i, colorItems.get(j)); |
|
448 |
colorItems.set(j, aux); |
|
449 |
} |
|
450 |
} |
|
451 |
} |
|
452 |
} |
|
453 |
|
|
454 |
/** |
|
455 |
* Genera una paleta intermedia para acelerar los calculos. |
|
456 |
*/ |
|
457 |
private void applyPalette() { |
|
458 |
ArrayList arrayColors = new ArrayList(); |
|
459 |
|
|
460 |
paletteByBand = new byte[0][3]; |
|
461 |
range = new double[0]; |
|
462 |
nameClass = new String[0]; |
|
463 |
|
|
464 |
if (colorItems.size()==0) |
|
465 |
return; |
|
466 |
|
|
467 |
// Nos preparamos para hacer las particiones, sabiendo el minimo y maximo |
|
468 |
double min = ((ColorItem) colorItems.get(0)).getValue(); |
|
469 |
double max = ((ColorItem) colorItems.get(colorItems.size() - 1)).getValue(); |
|
470 |
|
|
471 |
if (min > max) { |
|
472 |
double aux = max; |
|
473 |
max = min; |
|
474 |
min = aux; |
|
475 |
} |
|
476 |
|
|
477 |
Color color = Color.white; |
|
478 |
Color colorOld = null; |
|
479 |
|
|
480 |
// Hacemos las particiones, metiendo cada item calculado en un array |
|
481 |
int defaultColors = RasterLibrary.defaultNumberOfColors; |
|
482 |
for (int i = 0; i < defaultColors; i++) { |
|
483 |
double value = min + ((i * (max - min)) / (defaultColors - 1)); |
|
484 |
|
|
485 |
int pos = 0; |
|
486 |
for (int j = 1; j <= colorItems.size(); j++) { |
|
487 |
if (j < colorItems.size()) { |
|
488 |
if (value < ((ColorItem) colorItems.get(j)).getValue()) { |
|
489 |
pos = j - 1; |
|
490 |
break; |
|
491 |
} |
|
492 |
} else { |
|
493 |
pos = j - 1; |
|
494 |
break; |
|
495 |
} |
|
496 |
} |
|
497 |
|
|
498 |
// Calculamos el color que corresponde, tanto interpolado como no |
|
499 |
if (interpolated) |
|
500 |
color = interpolatedColor(value, pos); |
|
501 |
else |
|
502 |
color = ((ColorItem) colorItems.get(pos)).getColor(); |
|
503 |
|
|
504 |
if (!color.equals(colorOld)) { |
|
505 |
ColorItem colorItem = new ColorItem(); |
|
506 |
colorItem.setNameClass(""); |
|
507 |
colorItem.setValue(value); |
|
508 |
colorItem.setColor(color); |
|
509 |
arrayColors.add(colorItem); |
|
510 |
} |
|
511 |
|
|
512 |
colorOld = color; |
|
513 |
} |
|
514 |
|
|
515 |
// Una vez tenemos una paleta de 256 colores o inferior, rellenamos |
|
516 |
// los siguientes valores para hacer busquedas rapidas. |
|
517 |
|
|
518 |
paletteByBand = new byte[arrayColors.size()][3]; |
|
519 |
range = new double[arrayColors.size()]; |
|
520 |
nameClass = new String[arrayColors.size()]; |
|
521 |
|
|
522 |
transparencyRange.clear(); |
|
523 |
for (int i = 0; i < arrayColors.size(); i++) { |
|
524 |
paletteByBand[i][0] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getRed(); |
|
525 |
paletteByBand[i][1] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getGreen(); |
|
526 |
paletteByBand[i][2] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getBlue(); |
|
527 |
range[i] = ((ColorItem) arrayColors.get(i)).getValue(); |
|
528 |
nameClass[i] = ((ColorItem) arrayColors.get(i)).getNameClass(); |
|
529 |
if (((ColorItem) arrayColors.get(i)).getColor().getAlpha() != 255) { |
|
530 |
TransparencyRange r = new TransparencyRange(); |
|
531 |
r.setRed(new int[] { ((ColorItem) arrayColors.get(i)).getColor().getRed(), ((ColorItem) arrayColors.get(i)).getColor().getRed() }); |
|
532 |
r.setGreen(new int[] { ((ColorItem) arrayColors.get(i)).getColor().getGreen(), ((ColorItem) arrayColors.get(i)).getColor().getGreen() }); |
|
533 |
r.setBlue(new int[] { ((ColorItem) arrayColors.get(i)).getColor().getBlue(), ((ColorItem) arrayColors.get(i)).getColor().getBlue() }); |
|
534 |
r.setAlpha(((ColorItem) arrayColors.get(i)).getColor().getAlpha()); |
|
535 |
r.setAnd(true); |
|
536 |
r.loadStrEntryFromValues(); |
|
537 |
transparencyRange.add(r); |
|
538 |
} |
|
539 |
} |
|
540 |
} |
|
541 |
|
|
542 |
public double[] getRange() { |
|
543 |
return range; |
|
544 |
} |
|
545 |
|
|
546 |
public void setRange(double[] range) { |
|
547 |
this.range = range; |
|
548 |
} |
|
549 |
|
|
550 |
public ArrayList getColorItems() { |
|
551 |
return colorItems; |
|
552 |
} |
|
553 |
|
|
554 |
public boolean isInterpolated() { |
|
555 |
return interpolated; |
|
556 |
} |
|
557 |
|
|
558 |
public void setInterpolated(boolean interpolated) { |
|
559 |
this.interpolated = interpolated; |
|
560 |
applyPalette(); |
|
561 |
} |
|
416 | 562 |
} |
Also available in: Unified diff