svn-gvsig-desktop / tags / v1_1_Build_1007 / libraries / libCq_CMS_praster / src / org / cresques / io / datastruct / Palette.java @ 12478
History | View | Annotate | Download (13.2 KB)
1 | 8026 | nacho | /*
|
---|---|---|---|
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 | 10645 | nacho | private String name = null; |
78 | 8026 | nacho | |
79 | 10645 | nacho | public Palette(){}
|
80 | |||
81 | 8026 | nacho | /**
|
82 | 10645 | nacho | * 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 | 8026 | nacho | * 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 | } |