Statistics
| Revision:

svn-gvsig-desktop / tags / v1_1_Build_1000 / libraries / libCq_CMS_praster / src / org / cresques / io / datastruct / Palette.java @ 11885

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
}