root / tags / v1_1_Build_1003 / libraries / libCq_CMS_praster / src / org / cresques / io / datastruct / Palette.java @ 12271
History | View | Annotate | Download (13.2 KB)
1 |
/*
|
---|---|
2 |
* Cresques Mapping Suite. Graphic Library for constructing mapping applications.
|
3 |
*
|
4 |
* Copyright (C) 2004-5.
|
5 |
*
|
6 |
* This program is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU General Public License
|
8 |
* as published by the Free Software Foundation; either version 2
|
9 |
* of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This program is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 |
* GNU General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU General Public License
|
17 |
* along with this program; if not, write to the Free Software
|
18 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
19 |
*
|
20 |
* For more information, contact:
|
21 |
*
|
22 |
* cresques@gmail.com
|
23 |
*/
|
24 |
package org.cresques.io.datastruct; |
25 |
|
26 |
import org.cresques.io.data.RasterBuf; |
27 |
import org.cresques.util.Utilities; |
28 |
|
29 |
import es.gva.cit.jgdal.GdalColorEntry; |
30 |
import es.gva.cit.jgdal.GdalColorTable; |
31 |
import es.gva.cit.jgdal.GdalException; |
32 |
|
33 |
/**
|
34 |
* Paleta para raster. Esta consta de los valores RGB de la paleta que son almacenados en un vector de
|
35 |
* enteros donde cada elemento entero contiene en su interior el RGB completo y del vector de rangos.
|
36 |
* Dependiendo de si el tipo de rango es entero o decimal este estar? almacenado en un vector de rangos
|
37 |
* entero (intRange) o enun vector de rangos double (doubleRange). El tipo de dato del rango quedar?
|
38 |
* almacenado en la variable type.
|
39 |
* @author Nacho Brodin (brodin_ign@gva.es)
|
40 |
*/
|
41 |
public class Palette{ |
42 |
/**
|
43 |
* Tipo de dato de la paleta
|
44 |
* <UL>
|
45 |
* <LI>TYPE_INT = Valido para byte, short e int</LI>
|
46 |
* <LI>TYPE_DOUBLE = Valido para float y double</LI>
|
47 |
* </UL>
|
48 |
*/
|
49 |
private int type = RasterBuf.TYPE_UNDEFINED; |
50 |
/**
|
51 |
* Lista de rangos para paletas enteras
|
52 |
*/
|
53 |
private int[] intRange = null; |
54 |
/**
|
55 |
* Lista de rangos para paletas decimales
|
56 |
*/
|
57 |
private double[] doubleRange = null; |
58 |
/**
|
59 |
* Lista de valores RGB
|
60 |
*/
|
61 |
private int[] palette = null; |
62 |
/**
|
63 |
* Heuristica para paletas enteras. Esta heuristica simple consiste en el valor
|
64 |
* intermedio de la tabla, de esta forma reduce la tabla a la mitad.
|
65 |
*/
|
66 |
private int intHeuristica = Integer.MAX_VALUE; |
67 |
/**
|
68 |
* Heuristica para paletas decimales. Esta heuristica simple consiste en el valor
|
69 |
* intermedio de la tabla, de esta forma reduce la tabla a la mitad.
|
70 |
*/
|
71 |
private double doubleHeuristica = Double.MAX_VALUE; |
72 |
/**
|
73 |
* Nombre de la clase asociada a la entrada
|
74 |
*/
|
75 |
private String[] nameClass = null; |
76 |
|
77 |
private String name = null; |
78 |
|
79 |
public Palette(){}
|
80 |
|
81 |
/**
|
82 |
* Constructor. Asigna el nombre de la paleta.
|
83 |
* @param name
|
84 |
*/
|
85 |
public Palette(String name){ |
86 |
this.name = name;
|
87 |
} |
88 |
|
89 |
/**
|
90 |
* Asigna el nombre de la paleta
|
91 |
* @param Nombre de la paleta
|
92 |
*/
|
93 |
public void addName(String name){ |
94 |
this.name = name;
|
95 |
} |
96 |
|
97 |
/**
|
98 |
* Obtiene el nombre de la paleta
|
99 |
* @return Nombre de la paleta
|
100 |
*/
|
101 |
public String getName(){ |
102 |
return name;
|
103 |
} |
104 |
|
105 |
/**
|
106 |
* Obtiene el valor RGB interpolado para un clave entera pasada por par?metro
|
107 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta
|
108 |
* @return valor RGB
|
109 |
*/
|
110 |
public int getInterpolateRGB2(double value){ |
111 |
int maxGrad = 127; |
112 |
int init = 1; |
113 |
int color = 0; |
114 |
double beginValue = 0; |
115 |
double nextValue = 0; |
116 |
for(int i = init; i <= doubleRange.length; i++){ |
117 |
if(i < doubleRange.length){
|
118 |
if(value > doubleRange[i]){
|
119 |
color = palette[i - 1];
|
120 |
beginValue = doubleRange[i - 1];
|
121 |
nextValue = doubleRange[i]; |
122 |
break;
|
123 |
} |
124 |
}else{
|
125 |
color = palette[i - 1];
|
126 |
beginValue = doubleRange[i - 1];
|
127 |
nextValue = 0;
|
128 |
break;
|
129 |
} |
130 |
} |
131 |
int[] colorBegin = Utilities.getARGBFromIntToIntArray(color); |
132 |
|
133 |
int max = Math.max(Math.max(colorBegin[0], colorBegin[1]), colorBegin[2]); |
134 |
|
135 |
double distance = Math.abs(beginValue - nextValue); |
136 |
double absValue = Math.abs(value - nextValue); |
137 |
|
138 |
int newBand = 0; |
139 |
if(distance != 0) |
140 |
newBand = (int)Math.round((absValue * maxGrad) / distance); |
141 |
|
142 |
int[] res = new int[3]; |
143 |
|
144 |
if((max + maxGrad) > 255){ |
145 |
for(int i = 0; i < 3; i++) |
146 |
if(colorBegin[i] == max){
|
147 |
res[i] = max - newBand; |
148 |
break;
|
149 |
}else
|
150 |
res[i] = colorBegin[i]; |
151 |
}else{
|
152 |
for(int i = 0; i < 3; i++) |
153 |
if(colorBegin[i] == max){
|
154 |
res[i] = max + newBand; |
155 |
break;
|
156 |
}else
|
157 |
res[i] = colorBegin[i]; |
158 |
} |
159 |
|
160 |
return Utilities.getIntFromARGB(colorBegin[3], res[0], res[1], res[2]); |
161 |
} |
162 |
|
163 |
/**
|
164 |
* Obtiene el valor RGB interpolado para un clave entera pasada por par?metro
|
165 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta
|
166 |
* @return valor RGB
|
167 |
*/
|
168 |
public int getInterpolateRGB2(int value){ |
169 |
int maxGrad = 127; |
170 |
int init = 1; |
171 |
int color = 0; |
172 |
int beginValue = 0; |
173 |
int nextValue = 0; |
174 |
for(int i = init; i <= intRange.length; i++){ |
175 |
if(i < intRange.length){
|
176 |
if(value > intRange[i]){
|
177 |
color = palette[i - 1];
|
178 |
beginValue = intRange[i - 1];
|
179 |
nextValue = intRange[i]; |
180 |
break;
|
181 |
} |
182 |
}else{
|
183 |
color = palette[i - 1];
|
184 |
beginValue = intRange[i - 1];
|
185 |
nextValue = 0;
|
186 |
break;
|
187 |
} |
188 |
} |
189 |
int[] colorBegin = Utilities.getARGBFromIntToIntArray(color); |
190 |
|
191 |
int max = Math.max(Math.max(colorBegin[0], colorBegin[1]), colorBegin[2]); |
192 |
|
193 |
int distance = Math.abs(beginValue - nextValue); |
194 |
int absValue = Math.abs(value - nextValue); |
195 |
|
196 |
int newBand = 0; |
197 |
if(distance != 0) |
198 |
newBand = (absValue * maxGrad) / distance; |
199 |
|
200 |
int[] res = new int[3]; |
201 |
|
202 |
if((max + maxGrad) > 255){ |
203 |
for(int i = 0; i < 3; i++) |
204 |
if(colorBegin[i] == max){
|
205 |
res[i] = max - newBand; |
206 |
break;
|
207 |
}else
|
208 |
res[i] = colorBegin[i]; |
209 |
}else{
|
210 |
for(int i = 0; i < 3; i++) |
211 |
if(colorBegin[i] == max){
|
212 |
res[i] = max + newBand; |
213 |
break;
|
214 |
}else
|
215 |
res[i] = colorBegin[i]; |
216 |
} |
217 |
|
218 |
return Utilities.getIntFromARGB(colorBegin[3], res[0], res[1], res[2]); |
219 |
} |
220 |
|
221 |
|
222 |
/**
|
223 |
* Obtiene el valor RGB interpolado para un clave entera pasada por par?metro
|
224 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta
|
225 |
* @return valor RGB
|
226 |
*/
|
227 |
public int getInterpolateRGB(int value){ |
228 |
int init = 1; |
229 |
int color = 0; |
230 |
int beginValue = 0; |
231 |
int nextValue = 0; |
232 |
int nextColor = 0; |
233 |
for(int i = init; i <= intRange.length; i++){ |
234 |
if(i < intRange.length){
|
235 |
if(value > intRange[i]){
|
236 |
color = palette[i - 1];
|
237 |
beginValue = intRange[i - 1];
|
238 |
nextValue = intRange[i]; |
239 |
nextColor = palette[i]; |
240 |
break;
|
241 |
} |
242 |
}else{
|
243 |
color = palette[i - 1];
|
244 |
beginValue = intRange[i - 1];
|
245 |
nextValue = intRange[0];
|
246 |
nextColor = palette[0];
|
247 |
break;
|
248 |
} |
249 |
} |
250 |
int[] colorBegin = Utilities.getARGBFromIntToIntArray(color); |
251 |
int[] colorEnd = Utilities.getARGBFromIntToIntArray(nextColor); |
252 |
|
253 |
int dif = Math.abs(beginValue - nextValue); |
254 |
double difR = Math.abs(colorBegin[0] - colorEnd[0]) / (double)dif; |
255 |
double difG = Math.abs(colorBegin[1] - colorEnd[1]) / (double)dif; |
256 |
double difB = Math.abs(colorBegin[2] - colorEnd[2]) / (double)dif; |
257 |
|
258 |
int[] res = new int[3]; |
259 |
res[0] = (int)(colorBegin[0] + difR * (value - colorBegin[0])); |
260 |
res[1] = (int)(colorBegin[1] + difG * (value - colorBegin[1])); |
261 |
res[2] = (int)(colorBegin[2] + difB * (value - colorBegin[2])); |
262 |
|
263 |
return Utilities.getIntFromARGB(colorBegin[3], res[0], res[1], res[2]); |
264 |
} |
265 |
|
266 |
/**
|
267 |
* Obtiene el valor RGB para un clave entera pasada por par?metro
|
268 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta
|
269 |
* @return valor RGB
|
270 |
*/
|
271 |
public int getRGB(int value){ |
272 |
int init = 1; |
273 |
/*if(value > intHeuristica)
|
274 |
init = intRange.length >> 1;*/
|
275 |
for(int i = init; i <= intRange.length; i++) |
276 |
if(i < intRange.length){
|
277 |
if(value > intRange[i])
|
278 |
return palette[i - 1]; |
279 |
}else{
|
280 |
return palette[i - 1]; |
281 |
} |
282 |
return 0; |
283 |
} |
284 |
|
285 |
/**
|
286 |
* Obtiene el valor RGB para un clave decimal pasada por par?metro
|
287 |
* @param value clave de la cual se quiere obtener el valor RGB de la paleta
|
288 |
* @return valor RGB
|
289 |
*/
|
290 |
public int getRGB(double value){ |
291 |
int init = 1; |
292 |
/*if(value > doubleHeuristica)
|
293 |
init = doubleRange.length >> 1;*/
|
294 |
for(int i = init; i <= doubleRange.length; i++) |
295 |
if(i < doubleRange.length){
|
296 |
if(value > doubleRange[i])
|
297 |
return palette[i - 1]; |
298 |
}else{
|
299 |
return palette[i - 1]; |
300 |
} |
301 |
return 0; |
302 |
} |
303 |
|
304 |
/**
|
305 |
* Genera una paleta a partir de una tabla de entradas de la forma
|
306 |
* <UL>
|
307 |
* <LI>(String) Nombre de la clase</LI>
|
308 |
* <LI>(Integer) Rojo</LI>
|
309 |
* <LI>(Integer) Verde</LI>
|
310 |
* <LI>(Integer) Azul</LI>
|
311 |
* <LI>(Double) Valor</LI>
|
312 |
* </UL>
|
313 |
* @param entries
|
314 |
*/
|
315 |
public void createPaletteFromTable(Object[][] entries, int type){ |
316 |
this.type = type;
|
317 |
nameClass = new String[entries.length]; |
318 |
palette = new int[entries.length]; |
319 |
if(type <= RasterBuf.TYPE_INT){
|
320 |
intRange = new int[entries.length]; |
321 |
intHeuristica = (int)((Double)entries[(entries.length >> 1)][4]).doubleValue(); |
322 |
}else{
|
323 |
doubleRange = new double[entries.length]; |
324 |
doubleHeuristica = ((Double)entries[(entries.length >> 1)][4]).doubleValue(); |
325 |
} |
326 |
for(int entry = 0; entry < entries.length; entry++){ |
327 |
//palette[entry] = 0xff000000;
|
328 |
for(int value = 0; value < entries[entry].length; value++){ |
329 |
switch(value){
|
330 |
case 0: nameClass[entry] = (String)entries[entry][value]; |
331 |
break;
|
332 |
case 1: palette[entry] |= ((((Integer)entries[entry][value]).intValue() & 0x000000ff) << 16); |
333 |
break;
|
334 |
case 2: palette[entry] |= ((((Integer)entries[entry][value]).intValue() & 0x000000ff) << 8); |
335 |
break;
|
336 |
case 3: palette[entry] |= (((Integer)entries[entry][value]).intValue() & 0x000000ff); |
337 |
break;
|
338 |
case 4: if(type <= RasterBuf.TYPE_INT) |
339 |
intRange[entry] = ((Double)entries[entry][value]).intValue();
|
340 |
else
|
341 |
doubleRange[entry] = ((Double)entries[entry][value]).doubleValue();
|
342 |
break;
|
343 |
case 5: palette[entry] |= ((((Integer)entries[entry][value]).intValue() & 0x000000ff) << 24); |
344 |
break;
|
345 |
} |
346 |
} |
347 |
} |
348 |
} |
349 |
|
350 |
/**
|
351 |
* Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario para los ficheros
|
352 |
* que tienen un paleta asignada, como los gif, y que son tratados por Gdal. Se pasa la tabla
|
353 |
* de color le?da desde gdal y se crea directamente un objeto Palette.
|
354 |
* @param table
|
355 |
*/
|
356 |
public void createPaletteFromGdalColorTable(GdalColorTable table){ |
357 |
try{
|
358 |
type = RasterBuf.TYPE_BYTE; |
359 |
nameClass = new String[table.getColorEntryCount()]; |
360 |
palette = new int[table.getColorEntryCount()]; |
361 |
intRange = new int[table.getColorEntryCount()]; |
362 |
|
363 |
int cont = table.getColorEntryCount() - 1; |
364 |
for(int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++){ |
365 |
GdalColorEntry entry = table.getColorEntryAsRGB(iEntry); |
366 |
nameClass[cont] = "";
|
367 |
palette[cont] = 0x00000000;
|
368 |
palette[cont] |= ((entry.c4 & 0x000000ff) << 24); |
369 |
palette[cont] |= ((entry.c1 & 0x000000ff) << 16); |
370 |
palette[cont] |= ((entry.c2 & 0x000000ff) << 8); |
371 |
palette[cont] |= (entry.c3 & 0x000000ff);
|
372 |
intRange[cont] = iEntry; |
373 |
cont --; |
374 |
} |
375 |
}catch(GdalException ex){
|
376 |
//No se crea la paleta
|
377 |
} |
378 |
} |
379 |
|
380 |
/**
|
381 |
* Carga una paleta desde un fichero XML
|
382 |
* @param file nombre del fichero
|
383 |
* @param palette Nombre de la paleta
|
384 |
*/
|
385 |
public void loadPaletteFromXML(String file, String palette){ |
386 |
//TODO: Implemetar cargar paleta desde el directorio gvSIG
|
387 |
} |
388 |
|
389 |
/**
|
390 |
* Carga una paleta desde el fichero .rmf asociado a la imagen
|
391 |
* @param file nombre del fichero de imagen
|
392 |
*/
|
393 |
public void loadPaletteFromRMF(String file){ |
394 |
//TODO: Implemetar cargar paleta desde .rmf
|
395 |
} |
396 |
|
397 |
/**
|
398 |
* Salva una paleta desde al fichero .rmf asociado a la imagen
|
399 |
* @param file nombre del fichero de imagen
|
400 |
*/
|
401 |
public void savePaletteToRMF(String file){ |
402 |
//TODO: Implemetar salvar paleta a .rmf
|
403 |
} |
404 |
|
405 |
/**
|
406 |
* Obtiene la paleta
|
407 |
* @return Paleta
|
408 |
*/
|
409 |
public int[] getPalette() { |
410 |
return palette;
|
411 |
} |
412 |
|
413 |
/**
|
414 |
* Asigna una paleta
|
415 |
* @param palette Paleta
|
416 |
*/
|
417 |
public void setPalette(int[] palette) { |
418 |
this.palette = palette;
|
419 |
} |
420 |
|
421 |
/**
|
422 |
* Obtiene el tipo del rango de la paleta que corresponde con los tipos de rasterBuf
|
423 |
* @return Tipo de rango, entero o double
|
424 |
*/
|
425 |
public int getType() { |
426 |
return type;
|
427 |
} |
428 |
|
429 |
/**
|
430 |
* Asigna el tipo del rango de la paleta que corresponde con los tipos de rasterBuf
|
431 |
* @param Tipo de rango, entero o double
|
432 |
*/
|
433 |
public void setType(int type) { |
434 |
this.type = type;
|
435 |
} |
436 |
|
437 |
/**
|
438 |
* Asigna los rangos si el tipo es decimal
|
439 |
* @param rangos
|
440 |
*/
|
441 |
public void setDoubleRange(double[] value) { |
442 |
doubleRange = value; |
443 |
} |
444 |
|
445 |
/**
|
446 |
* Asigna los rangos si el tipo es entero
|
447 |
* @param values
|
448 |
*/
|
449 |
public void setIntRange(int[] values) { |
450 |
intRange = values; |
451 |
} |
452 |
|
453 |
/**
|
454 |
* Obtiene los rangos si el tipo es decimal
|
455 |
* @return rangos
|
456 |
*/
|
457 |
public double[] getDoubleRange() { |
458 |
return doubleRange;
|
459 |
} |
460 |
|
461 |
/**
|
462 |
* Obtiene los rangos si el tipo es entero
|
463 |
* @return rangos
|
464 |
*/
|
465 |
public int[] getIntRange() { |
466 |
return intRange;
|
467 |
} |
468 |
|
469 |
|
470 |
/**
|
471 |
* Obtiene los nombres de las clases de la paleta
|
472 |
* @return Array de cadenas. Cada una corresponde con un nombre de clase
|
473 |
* que corresponde a cada rango de tipos.
|
474 |
*/
|
475 |
public String[] getNameClass() { |
476 |
return nameClass;
|
477 |
} |
478 |
|
479 |
/**
|
480 |
* Asigna los nombres de las clases de la paleta
|
481 |
* @param names Array de cadenas. Cada una corresponde con un nombre de clase
|
482 |
* que corresponde a cada rango de tipos.
|
483 |
*/
|
484 |
public void setNameClass(String[] names) { |
485 |
nameClass = names; |
486 |
} |
487 |
|
488 |
|
489 |
} |