Statistics
| Revision:

root / trunk / libraries / libCq_CMS_praster / src / org / cresques / io / datastruct / Palette.java @ 8026

History | View | Annotate | Download (12.7 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
        
78
        /**
79
         * Obtiene el valor RGB interpolado para un clave entera pasada por par?metro
80
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
81
         * @return valor RGB
82
         */
83
        public int getInterpolateRGB2(double value){
84
                int maxGrad = 127;
85
                int init = 1;
86
                int color = 0;
87
                double beginValue = 0;
88
                double nextValue = 0;
89
                for(int i = init; i <= doubleRange.length; i++){
90
                        if(i < doubleRange.length){
91
                                if(value > doubleRange[i]){
92
                                        color = palette[i - 1];
93
                                        beginValue = doubleRange[i - 1];
94
                                        nextValue = doubleRange[i];
95
                                        break;
96
                                }
97
                        }else{
98
                                color = palette[i - 1];
99
                                beginValue = doubleRange[i - 1];
100
                                nextValue = 0;
101
                                break;
102
                        }
103
                }
104
                int[] colorBegin = Utilities.getARGBFromIntToIntArray(color);
105
                
106
                int max = Math.max(Math.max(colorBegin[0], colorBegin[1]), colorBegin[2]);
107
                
108
                double distance = Math.abs(beginValue - nextValue);
109
                double absValue = Math.abs(value - nextValue);
110
                
111
                int newBand = 0;
112
                if(distance != 0)
113
                        newBand = (int)Math.round((absValue * maxGrad) / distance);
114
                
115
                int[] res = new int[3];
116
                
117
                if((max + maxGrad) > 255){
118
                        for(int i = 0; i < 3; i++)
119
                                if(colorBegin[i] == max){
120
                                        res[i] = max - newBand;
121
                                        break;
122
                                }else
123
                                        res[i] = colorBegin[i];
124
                }else{
125
                        for(int i = 0; i < 3; i++)
126
                                if(colorBegin[i] == max){
127
                                        res[i] = max + newBand;
128
                                        break;
129
                                }else
130
                                        res[i] = colorBegin[i];
131
                }
132
                
133
                return Utilities.getIntFromARGB(colorBegin[3], res[0], res[1], res[2]);
134
        }
135
        
136
        /**
137
         * Obtiene el valor RGB interpolado para un clave entera pasada por par?metro
138
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
139
         * @return valor RGB
140
         */
141
        public int getInterpolateRGB2(int value){
142
                int maxGrad = 127;
143
                int init = 1;
144
                int color = 0;
145
                int beginValue = 0;
146
                int nextValue = 0;
147
                for(int i = init; i <= intRange.length; i++){
148
                        if(i < intRange.length){
149
                                if(value > intRange[i]){
150
                                        color = palette[i - 1];
151
                                        beginValue = intRange[i - 1];
152
                                        nextValue = intRange[i];
153
                                        break;
154
                                }
155
                        }else{
156
                                color = palette[i - 1];
157
                                beginValue = intRange[i - 1];
158
                                nextValue = 0;
159
                                break;
160
                        }
161
                }
162
                int[] colorBegin = Utilities.getARGBFromIntToIntArray(color);
163
                
164
                int max = Math.max(Math.max(colorBegin[0], colorBegin[1]), colorBegin[2]);
165
                
166
                int distance = Math.abs(beginValue - nextValue);
167
                int absValue = Math.abs(value - nextValue);
168
                
169
                int newBand = 0;
170
                if(distance != 0)
171
                        newBand = (absValue * maxGrad) / distance;
172
                
173
                int[] res = new int[3];
174
                
175
                if((max + maxGrad) > 255){
176
                        for(int i = 0; i < 3; i++)
177
                                if(colorBegin[i] == max){
178
                                        res[i] = max - newBand;
179
                                        break;
180
                                }else
181
                                        res[i] = colorBegin[i];
182
                }else{
183
                        for(int i = 0; i < 3; i++)
184
                                if(colorBegin[i] == max){
185
                                        res[i] = max + newBand;
186
                                        break;
187
                                }else
188
                                        res[i] = colorBegin[i];
189
                }
190
                
191
                return Utilities.getIntFromARGB(colorBegin[3], res[0], res[1], res[2]);
192
        }
193
        
194
        
195
        /**
196
         * Obtiene el valor RGB interpolado para un clave entera pasada por par?metro
197
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
198
         * @return valor RGB
199
         */
200
        public int getInterpolateRGB(int value){
201
                int init = 1;
202
                int color = 0;
203
                int beginValue = 0;
204
                int nextValue = 0;
205
                int nextColor = 0;
206
                for(int i = init; i <= intRange.length; i++){
207
                        if(i < intRange.length){
208
                                if(value > intRange[i]){
209
                                        color = palette[i - 1];
210
                                        beginValue = intRange[i - 1];
211
                                        nextValue = intRange[i];
212
                                        nextColor = palette[i];
213
                                        break;
214
                                }
215
                        }else{
216
                                color = palette[i - 1];
217
                                beginValue = intRange[i - 1];
218
                                nextValue = intRange[0];
219
                                nextColor = palette[0];
220
                                break;
221
                        }
222
                }
223
                int[] colorBegin = Utilities.getARGBFromIntToIntArray(color);
224
                int[] colorEnd = Utilities.getARGBFromIntToIntArray(nextColor);
225
                
226
                int dif = Math.abs(beginValue - nextValue);
227
                double difR = Math.abs(colorBegin[0] - colorEnd[0]) / (double)dif;
228
                double difG = Math.abs(colorBegin[1] - colorEnd[1]) / (double)dif;
229
                double difB = Math.abs(colorBegin[2] - colorEnd[2]) / (double)dif;
230
                
231
                int[] res = new int[3];
232
                res[0] = (int)(colorBegin[0] + difR * (value - colorBegin[0]));
233
                res[1] = (int)(colorBegin[1] + difG * (value - colorBegin[1]));
234
                res[2] = (int)(colorBegin[2] + difB * (value - colorBegin[2]));
235
                
236
                return Utilities.getIntFromARGB(colorBegin[3], res[0], res[1], res[2]);
237
        }
238
        
239
        /**
240
         * Obtiene el valor RGB para un clave entera pasada por par?metro
241
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
242
         * @return valor RGB
243
         */
244
        public int getRGB(int value){
245
                int init = 1;
246
                /*if(value > intHeuristica)
247
                        init = intRange.length >> 1;*/
248
                for(int i = init; i <= intRange.length; i++)
249
                        if(i < intRange.length){
250
                                if(value > intRange[i])
251
                                        return palette[i - 1];
252
                        }else{
253
                                return palette[i - 1];
254
                        }
255
                return 0;
256
        }
257
        
258
        /**
259
         * Obtiene el valor RGB para un clave decimal pasada por par?metro
260
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
261
         * @return valor RGB
262
         */
263
        public int getRGB(double value){
264
                int init = 1;
265
                /*if(value > doubleHeuristica)
266
                        init = doubleRange.length >> 1;*/
267
                for(int i = init; i <= doubleRange.length; i++)
268
                        if(i < doubleRange.length){
269
                                if(value > doubleRange[i])
270
                                        return palette[i - 1];
271
                        }else{
272
                                return palette[i - 1];
273
                        }
274
                return 0;
275
        }
276
        
277
        /**
278
         * Genera una paleta a partir de una tabla de entradas de la forma
279
         * <UL>
280
         * <LI>(String) Nombre de la clase</LI>
281
         * <LI>(Integer) Rojo</LI>
282
         * <LI>(Integer) Verde</LI>
283
         * <LI>(Integer) Azul</LI>
284
         * <LI>(Double) Valor</LI>
285
         * </UL>
286
         * @param entries
287
         */
288
        public void createPaletteFromTable(Object[][] entries, int type){
289
                this.type = type;
290
                nameClass = new String[entries.length];
291
                palette = new int[entries.length];
292
                if(type <= RasterBuf.TYPE_INT){
293
                        intRange = new int[entries.length];
294
                        intHeuristica = (int)((Double)entries[(entries.length >> 1)][4]).doubleValue();
295
                }else{
296
                        doubleRange = new double[entries.length];
297
                        doubleHeuristica = ((Double)entries[(entries.length >> 1)][4]).doubleValue();
298
                }
299
                for(int entry = 0; entry < entries.length; entry++){
300
                        //palette[entry] = 0xff000000;
301
                        for(int value = 0; value < entries[entry].length; value++){
302
                                switch(value){
303
                                case 0: nameClass[entry] = (String)entries[entry][value];
304
                                                break;
305
                                case 1: palette[entry] |= ((((Integer)entries[entry][value]).intValue() & 0x000000ff) << 16);
306
                                                break;
307
                                case 2: palette[entry] |= ((((Integer)entries[entry][value]).intValue() & 0x000000ff) << 8);
308
                                                break;
309
                                case 3: palette[entry] |= (((Integer)entries[entry][value]).intValue() & 0x000000ff);
310
                                                break;
311
                                case 4: if(type <= RasterBuf.TYPE_INT)
312
                                                        intRange[entry] = ((Double)entries[entry][value]).intValue();
313
                                                else
314
                                                        doubleRange[entry] = ((Double)entries[entry][value]).doubleValue();
315
                                                break;
316
                                case 5: palette[entry] |= ((((Integer)entries[entry][value]).intValue() & 0x000000ff) << 24);
317
                                                break;
318
                                }
319
                        }
320
                }
321
        }
322
        
323
        /**
324
         * Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario para los ficheros
325
         * que tienen un paleta asignada, como los gif, y que son tratados por Gdal. Se pasa la tabla
326
         * de color le?da desde gdal y se crea directamente un objeto Palette. 
327
         * @param table
328
         */
329
        public void createPaletteFromGdalColorTable(GdalColorTable table){
330
                try{
331
                        type = RasterBuf.TYPE_BYTE;
332
                        nameClass = new String[table.getColorEntryCount()];
333
                        palette = new int[table.getColorEntryCount()];
334
                        intRange = new int[table.getColorEntryCount()];
335
                        
336
                        int cont = table.getColorEntryCount() - 1;
337
                    for(int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++){
338
                            GdalColorEntry entry = table.getColorEntryAsRGB(iEntry);
339
                            nameClass[cont] = "";
340
                            palette[cont] = 0x00000000;
341
                            palette[cont] |= ((entry.c4 & 0x000000ff) << 24);
342
                            palette[cont] |= ((entry.c1 & 0x000000ff) << 16);
343
                            palette[cont] |= ((entry.c2 & 0x000000ff) << 8);
344
                            palette[cont] |= (entry.c3 & 0x000000ff);
345
                            intRange[cont] = iEntry;
346
                            cont --;
347
                    }
348
                }catch(GdalException ex){
349
                        //No se crea la paleta
350
                }
351
        }
352
        
353
        /**
354
         * Carga una paleta desde un fichero XML
355
         * @param file nombre del fichero
356
         * @param palette Nombre de la paleta
357
         */
358
        public void loadPaletteFromXML(String file, String palette){
359
                //TODO: Implemetar cargar paleta desde el directorio gvSIG
360
        }
361
        
362
        /**
363
         * Carga una paleta desde el fichero .rmf asociado a la imagen
364
         * @param file nombre del fichero de imagen
365
         */
366
        public void loadPaletteFromRMF(String file){
367
                //TODO: Implemetar cargar paleta desde .rmf
368
        }
369
        
370
        /**
371
         * Salva una paleta desde al fichero .rmf asociado a la imagen
372
         * @param file nombre del fichero de imagen
373
         */
374
        public void savePaletteToRMF(String file){
375
                //TODO: Implemetar salvar paleta a .rmf
376
        }
377

    
378
        /**
379
         * Obtiene la paleta
380
         * @return Paleta
381
         */
382
        public int[] getPalette() {
383
                return palette;
384
        }
385

    
386
        /**
387
         * Asigna una paleta
388
         * @param palette Paleta
389
         */
390
        public void setPalette(int[] palette) {
391
                this.palette = palette;
392
        }
393

    
394
        /**
395
         * Obtiene el tipo del rango de la paleta que corresponde con los tipos de rasterBuf
396
         * @return Tipo de rango, entero o double
397
         */
398
        public int getType() {
399
                return type;
400
        }
401
        
402
        /**
403
         * Asigna el tipo del rango de la paleta que corresponde con los tipos de rasterBuf
404
         * @param Tipo de rango, entero o double
405
         */
406
        public void setType(int type) {
407
                this.type = type;
408
        }
409

    
410
        /**
411
         * Asigna los rangos si el tipo es decimal
412
         * @param rangos
413
         */
414
        public void setDoubleRange(double[] value) {
415
                doubleRange = value;
416
        }
417

    
418
        /**
419
         * Asigna los rangos si el tipo es entero
420
         * @param values
421
         */
422
        public void setIntRange(int[] values) {
423
                intRange = values;
424
        }
425

    
426
        /**
427
         * Obtiene los rangos si el tipo es decimal
428
         * @return rangos
429
         */
430
        public double[] getDoubleRange() {
431
                return doubleRange;
432
        }
433

    
434
        /**
435
         * Obtiene los rangos si el tipo es entero
436
         * @return rangos
437
         */
438
        public int[] getIntRange() {
439
                return intRange;
440
        }
441

    
442
        
443
        /**
444
         * Obtiene los nombres de las clases de la paleta
445
         * @return Array de cadenas. Cada una corresponde con un nombre de clase
446
         * que corresponde a cada rango de tipos.
447
         */
448
        public String[] getNameClass() {
449
                return nameClass;
450
        }
451
        
452
        /**
453
         * Asigna los nombres de las clases de la paleta
454
         * @param names Array de cadenas. Cada una corresponde con un nombre de clase
455
         * que corresponde a cada rango de tipos.
456
         */
457
        public void setNameClass(String[] names) {
458
                nameClass = names;
459
        }
460
        
461
        
462
}