Statistics
| Revision:

gvsig-raster / org.gvsig.raster / tags / 2.0.0 / org.gvsig.raster.lib / org.gvsig.raster.lib.impl / src / main / java / org / gvsig / raster / impl / store / properties / DataStoreColorTable.java @ 1708

History | View | Annotate | Download (27.8 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.raster.impl.store.properties;
23

    
24
import java.awt.Color;
25
import java.util.ArrayList;
26
import java.util.Arrays;
27
import java.util.List;
28

    
29
import org.gvsig.fmap.dal.coverage.datastruct.ColorItem;
30
import org.gvsig.fmap.dal.coverage.store.props.ColorTable;
31
import org.gvsig.jgdal.GdalColorEntry;
32
import org.gvsig.jgdal.GdalColorTable;
33
import org.gvsig.jgdal.GdalException;
34
import org.gvsig.raster.impl.datastruct.ColorItemImpl;
35
import org.gvsig.tools.ToolsLocator;
36
import org.gvsig.tools.dynobject.DynStruct;
37
import org.gvsig.tools.persistence.PersistenceManager;
38
import org.gvsig.tools.persistence.PersistentState;
39
import org.gvsig.tools.persistence.exception.PersistenceException;
40
/**
41
 * Paleta para raster. Esta consta de los valores RGB de la paleta que son
42
 * almacenados en un vector donde cada elemento contiene en su interior el RGB
43
 * completo y del vector de rangos.
44
 *
45
 * @version 04/07/2007
46
 * @author Nacho Brodin (nachobrodin@gmail.com)
47
 * @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es)
48
 */
49
public class DataStoreColorTable implements ColorTable, Cloneable {
50
        public static final String      PERSISTENT_NAME        = "DataStoreColorTable_Persistent";
51
    public static final String      PERSISTENT_DESCRIPTION = "DataStoreColorTable Persistent";
52
    
53
        /**
54
         * Flag de activaci?n de la paleta cuando se visualiza o exporta.
55
         */
56
        private boolean                          paletteActive     = true;
57
        /**
58
         * Lista de ColorItem donde estaran todos los valores de la paleta segun
59
         * el interfaz
60
         */
61
        protected ArrayList<ColorItem>   colorItems        = null;
62
        /**
63
         * Booleano que define si se interpolaran los valores de la paleta.
64
         */
65
        protected boolean                interpolated      = true;
66
        /**
67
         * Lista de rangos para paletas decimales
68
         */
69
        protected double[]               range             = null;
70
        /**
71
         * Lista de valores RGB
72
         */
73
        protected byte[][]               paletteByBand     = null;
74
        /**
75
         * Nombre de la clase asociada a la entrada
76
         */
77
        protected String[]               nameClass         = null;
78
        /**
79
         * Nombre de la paleta
80
         */
81
        protected String                 name              = null;
82

    
83
        /**
84
         * Ruta del fichero a la cual se asocia la paleta. Las bandas de un
85
         * GeoRasterMultiFile han de saber a que paleta van asociadas.
86
         */
87
        protected String                 filePath          = null;
88
        private int                      errorColor        = 8;
89

    
90
        /**
91
         * Constructor vac?o.
92
         * @param uri
93
         */
94
        public DataStoreColorTable() {
95
                this.name = "";
96
        }
97

    
98
        /**
99
         * Constructor. Asigna el nombre de la paleta.
100
         * @param name
101
         */
102
        public DataStoreColorTable(String name) {
103
                this.name = name;
104
        }
105
        
106
        /**
107
         * Constructor de copia
108
         * @param fp
109
         */
110
        public DataStoreColorTable(ColorTable fp){
111
                if (fp == null)
112
                        return;
113
                DataStoreColorTable palette = null;
114
                if(fp instanceof DataStoreColorTable)
115
                        palette = (DataStoreColorTable)fp;
116
                else
117
                        return;
118
                this.range = palette.getRange();
119
                this.paletteActive = true;
120
                this.paletteByBand = palette.getColorTableByBand();
121
                this.nameClass = palette.getNameClass();
122
                this.name = palette.getName();
123
                this.filePath = palette.getFilePath();
124
                this.colorItems = palette.getColorItems();
125
                this.interpolated = palette.isInterpolated();
126
        }
127

    
128
        /*
129
         * (non-Javadoc)
130
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#setName(java.lang.String)
131
         */
132
        public void setName(String name) {
133
                this.name = name;
134
        }
135

    
136
        /*
137
         * (non-Javadoc)
138
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#getName()
139
         */
140
        public String getName() {
141
                return name;
142
        }
143

    
144
        /*
145
         * (non-Javadoc)
146
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#createPaletteFromColorItems(java.util.ArrayList, boolean)
147
         */
148
        public void createPaletteFromColorItems(ArrayList<ColorItem> colorItems, boolean compress) {
149
                this.colorItems = colorItems;
150

    
151
                // Ordena la paleta
152
                sortPalette(colorItems);
153

    
154
                // Mira que valores se pueden descartar y asi dejamos la paleta reducida
155
                // para poder hacer interpolaciones
156
                if (compress)
157
                        compressPalette(colorItems);
158

    
159
                // Genera la paleta final para poder ser usada
160
                applyPalette(colorItems);
161

    
162
                // Borra valores duplicados
163
                removeDuplicatedValues();
164
        }
165

    
166
        private boolean isEqualColor(Color c1, Color c2, int error) {
167
                if ((c2 == null) && (c1 != null))
168
                        return false;
169
                if ((c1 == null) && (c2 != null))
170
                        return false;
171
                if (c2.getRed() < (c1.getRed() - error))
172
                        return false;
173
                if (c2.getGreen() < (c1.getGreen() - error))
174
                        return false;
175
                if (c2.getBlue() < (c1.getBlue() - error))
176
                        return false;
177
                if (c2.getAlpha() < (c1.getAlpha() - error))
178
                        return false;
179

    
180
                if (c2.getRed() > (c1.getRed() + error))
181
                        return false;
182
                if (c2.getGreen() > (c1.getGreen() + error))
183
                        return false;
184
                if (c2.getBlue() > (c1.getBlue() + error))
185
                        return false;
186
                if (c2.getAlpha() > (c1.getAlpha() + error))
187
                        return false;
188

    
189
                return true;
190
        }
191

    
192
        /**
193
         * Informa de si el color c3 se encuentra en un rango valido entre c1 y c2.
194
         * Para colores con nombre de clase se devolver? false para no eliminar nunca
195
         * ese item. Para colores con interpolacion distinta al 50% tambien
196
         * devolveremos false.
197
         * @param c1
198
         * @param c2
199
         * @param c3
200
         * @return
201
         */
202
        private boolean isCorrectColor(ColorItem c1, ColorItem c2, ColorItem c3) {
203
                if ((c3.getNameClass() != null) && (c3.getNameClass().length() > 0))
204
                        return false;
205
                if (c3.getInterpolated() != 50)
206
                        return false;
207
                if (c2.getInterpolated() != 50)
208
                        return false;
209

    
210
                double max = c2.getValue() - c1.getValue();
211
                int r = c1.getColor().getRed() + (int) (((c2.getColor().getRed() - c1.getColor().getRed()) * (c3.getValue() - c1.getValue())) / max);
212
                int g = c1.getColor().getGreen() + (int) (((c2.getColor().getGreen() - c1.getColor().getGreen()) * (c3.getValue() - c1.getValue())) / max);
213
                int b = c1.getColor().getBlue() + (int) (((c2.getColor().getBlue() - c1.getColor().getBlue()) * (c3.getValue() - c1.getValue())) / max);
214
                int a = c1.getColor().getAlpha() + (int) (((c2.getColor().getAlpha() - c1.getColor().getAlpha()) * (c3.getValue() - c1.getValue())) / max);
215
                Color aux = new Color(r & 0xff, g & 0xff, b & 0xff, a & 0xff);
216

    
217
                return isEqualColor(c3.getColor(), aux, errorColor);
218
        }
219

    
220
        private boolean canDelete(int first, int last) {
221
                if (first >= getColorItems().size())
222
                        return false;
223
                if (last >= getColorItems().size())
224
                        return false;
225
                ColorItem c1 = (ColorItem) getColorItems().get(first);
226
                ColorItem c2 = (ColorItem) getColorItems().get(last);
227
                for (int i = (first + 1); i < last; i++) {
228
                        if (!isCorrectColor(c1, c2, (ColorItem) getColorItems().get(i)))
229
                                return false;
230
                }
231
                return true;
232
        }
233

    
234
        /**
235
         * Borra valores duplicados de la paleta. Solo aquellos que coincidan en valor
236
         * y color.
237
         */
238
        public void removeDuplicatedValues() {
239
                for (int i = colorItems.size() - 2 ; i >= 0; i--) {
240
                        if ((i + 1) >= colorItems.size())
241
                                continue;
242
                        ColorItem colorItem = (ColorItem) colorItems.get(i + 1);
243
                        ColorItem colorItem2 = (ColorItem) colorItems.get(i);
244
                        // Si el valor es distinto no lo borramos
245
                        if (colorItem.getValue() != colorItem2.getValue())
246
                                continue;
247
                        // Si el color es distinto no lo borramos
248
                        if (!colorItem.getColor().equals(colorItem2.getColor()))
249
                                continue;
250
                        // Borraremos siempre el valor que no tenga nombre de clase, es un
251
                        // dato importante
252
                        if ((colorItem.getNameClass() == null) || (colorItem.getNameClass().length() == 0)) {
253
                                colorItems.remove(i + 1);
254
                                continue;
255
                        }
256
                        if ((colorItem2.getNameClass() == null) || (colorItem2.getNameClass().length() == 0)) {
257
                                colorItems.remove(i);
258
                                continue;
259
                        }
260
                        // Borramos solo uno de los dos si el nombre coincide
261
                        if ((colorItem.getNameClass() != null) || (colorItem.getNameClass().equals(colorItem2.getNameClass()))) {
262
                                colorItems.remove(i);
263
                                continue;
264
                        }
265
                }
266
        }
267

    
268
        /*
269
         * (non-Javadoc)
270
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#hasAlpha()
271
         */
272
        public boolean hasAlpha() {
273
                for (int i = 0; i<colorItems.size(); i++) {
274
                        ColorItem colorItem = (ColorItem) colorItems.get(i);
275
                        if (colorItem.getColor().getAlpha() != 255)
276
                                return true;
277
                }
278
                return false;
279
        }
280
        
281
        /*
282
         * (non-Javadoc)
283
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#compressPalette()
284
         */
285
        public void compressPalette() {
286
                compressPalette(colorItems);
287
        }
288

    
289
        /**
290
         * Informa de si una tabla de color se puede comprimir
291
         * @return
292
         */
293
        @SuppressWarnings("unchecked")
294
        public boolean isCompressible() {
295
                ArrayList cloneList = (ArrayList) getColorItems().clone();
296
                compressPalette(cloneList);
297
                return (cloneList.size() != getColorItems().size());
298
        }
299

    
300
        /**
301
         * Coge el array pasado por parametro y lo intenta comprimir
302
         * @param colorItems
303
         */
304
        private void compressPalette(ArrayList<ColorItem> colorItems) {
305
                removeDuplicatedValues();
306
                int size = -1;
307

    
308
                while (size != colorItems.size()) {
309
                        int init = 0;
310
                        int posMax = 2;
311

    
312
                        size = colorItems.size();
313
                        while (init < colorItems.size()) {
314
                                if ((posMax < colorItems.size()) && canDelete(init, posMax)) {
315
                                        posMax++;
316
                                        continue;
317
                                }
318
                                if ((init + 2) < posMax) {
319
                                        if (canDelete(init, posMax - 1))
320
                                                for (int i = (posMax - 2); i > init; i--)
321
                                                        if (i < colorItems.size())
322
                                                                colorItems.remove(i);
323
                                }
324
                                init++;
325
                                posMax = init + 2;
326
                        }
327
                }
328
        }
329

    
330
        /**
331
         * Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario
332
         * para los ficheros que tienen una paleta asignada, como los gif, y que son
333
         * tratados por Gdal. Se pasa la tabla de color le?da desde gdal y se crea
334
         * directamente un objeto Palette.
335
         * @param table
336
         */
337
        public void createPaletteFromGdalColorTable(GdalColorTable table) {
338
                try {
339
                        colorItems = new ArrayList<ColorItem>();
340
                        for (int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++) {
341
                                GdalColorEntry entry = table.getColorEntryAsRGB(iEntry);
342

    
343
                                ColorItem colorItem = new ColorItemImpl();
344
                                colorItem.setNameClass("");
345
                                colorItem.setValue(iEntry);
346
                                colorItem.setColor(new Color(        (int) (entry.c1 & 0xff),
347
                                                                                                                                                        (int) (entry.c2 & 0xff),
348
                                                                                                                                                        (int) (entry.c3 & 0xff),
349
                                                                                                                                                        (int) (entry.c4 & 0xff)));
350

    
351
                                colorItems.add(colorItem);
352
                        }
353
                } catch (GdalException ex) {
354
                        // No se crea la paleta
355
                }
356
                sortPalette(colorItems);
357

    
358
                setInterpolated(false);
359
                //compressPalette();
360
                applyPalette(colorItems);
361
        }
362

    
363
        /*
364
         * (non-Javadoc)
365
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#getColorTableByBand()
366
         */
367
        public byte[][] getColorTableByBand() {
368
                return paletteByBand;
369
        }
370

    
371

    
372
        /**
373
         * Asigna una paleta
374
         * @param palette Paleta
375
         */
376
        public void setColorTable(int[] palette) {
377
                paletteByBand = new byte[palette.length][3];
378
                for (int i = 0; i < palette.length; i++) {
379
                        paletteByBand[i][0] = (byte)((palette[i] & 0x00ff0000) >> 16);
380
                        paletteByBand[i][1] = (byte)((palette[i] & 0x0000ff00) >> 8);
381
                        paletteByBand[i][2] = (byte)(palette[i] & 0x000000ff);
382
                }
383
        }
384

    
385
        /**
386
         * Obtiene los nombres de las clases de la paleta
387
         * @return Array de cadenas. Cada una corresponde con un nombre de clase
388
         * que corresponde a cada rango de tipos.
389
         */
390
        public String[] getNameClass() {
391
                return nameClass;
392
        }
393

    
394
        /**
395
         * Asigna los nombres de las clases de la paleta
396
         * @param names Array de cadenas. Cada una corresponde con un nombre de clase
397
         * que corresponde a cada rango de tipos.
398
         */
399
        public void setNameClass(String[] names) {
400
                nameClass = names;
401
        }
402

    
403
        /**
404
         * Obtiene la ruta del fichero al que va asociada la paleta.
405
         * @return Ruta del fichero al que va asociada la paleta.
406
         */
407
        public String getFilePath() {
408
                return filePath;
409
        }
410

    
411
        /**
412
         * Asigna la ruta del fichero al que va asociada la paleta.
413
         * @param Ruta del fichero al que va asociada la paleta.
414
         */
415
        public void setFilePath(String filePath) {
416
                this.filePath = filePath;
417
        }
418

    
419
        /*
420
         * (non-Javadoc)
421
         * @see java.lang.Object#clone()
422
         */
423
        public Object clone() {
424
                DataStoreColorTable clone = null;
425
                try {
426
                        clone = (DataStoreColorTable) super.clone();
427
                } catch (CloneNotSupportedException e) {
428
                }
429

    
430
                if (colorItems != null) {
431
                        clone.colorItems = new ArrayList<ColorItem>();
432
                        for (int i = 0; i < colorItems.size(); i++) {
433
                                clone.colorItems.add((ColorItemImpl) ((ColorItemImpl) colorItems.get(i)).clone());
434
                        }
435
                }
436

    
437
                clone.interpolated = interpolated;
438

    
439
                if (filePath != null)
440
                        clone.filePath = new String(filePath);
441

    
442
                if (name != null)
443
                        clone.name = new String(name);
444

    
445
                if (nameClass != null) {
446
                        clone.nameClass = new String[nameClass.length];
447
                        for (int i = 0; i < nameClass.length; i++)
448
                                clone.nameClass[i] = nameClass[i];
449
                }
450

    
451
                if (paletteByBand != null) {
452
                        clone.paletteByBand = (byte[][]) paletteByBand.clone();
453
                        for (int i = 0; i < paletteByBand.length; i++)
454
                                clone.paletteByBand[i] = (byte[]) paletteByBand[i].clone();
455
                }
456

    
457
                if (range != null)
458
                        clone.range = (double[]) range.clone();
459

    
460
                return clone;
461
        }
462

    
463
        /**
464
         * Devuelve un color de interpolacion entre dos colores
465
         * @param value
466
         * @param pos
467
         * @return
468
         */
469
        private Color interpolatedColor(double value, int pos) {
470
                if (colorItems.size() <= 0)
471
                        return Color.black;
472

    
473
                if ((pos + 1) == colorItems.size())
474
                        return ((ColorItem) colorItems.get(pos)).getColor();
475

    
476
                if (value <= ((ColorItem) colorItems.get(0)).getValue())
477
                        return ((ColorItem) colorItems.get(0)).getColor();
478

    
479
                ColorItem item1 = (ColorItem) colorItems.get(pos);
480
                ColorItem item2 = (ColorItem) colorItems.get(pos + 1);
481

    
482
                double percValue = ((value - item1.getValue()) * 100) / (item2.getValue() - item1.getValue());
483

    
484
                Color halfColor = new Color(
485
                                (item2.getColor().getRed() + item1.getColor().getRed()) >> 1,
486
                                (item2.getColor().getGreen() + item1.getColor().getGreen()) >> 1,
487
                                (item2.getColor().getBlue() + item1.getColor().getBlue()) >> 1,
488
                                (item2.getColor().getAlpha() + item1.getColor().getAlpha()) >> 1);
489

    
490
                Color color1, color2;
491
                double perc1, perc2;
492

    
493
                if (percValue > item2.getInterpolated()) {
494
                        color1 = halfColor;
495
                        color2 = item2.getColor();
496
                        perc1 = item2.getInterpolated();
497
                        perc2 = 100;
498
                } else {
499
                        color1 = item1.getColor();
500
                        color2 = halfColor;
501
                        perc1 = 0;
502
                        perc2 = item2.getInterpolated();
503
                }
504

    
505
                double percNew = (percValue - perc1) / (perc2 - perc1);
506

    
507
                Color newColor = new Color(
508
                                (int) (color1.getRed() + ((color2.getRed() - color1.getRed()) * percNew)) & 0xff,
509
                                (int) (color1.getGreen() + ((color2.getGreen() - color1.getGreen()) * percNew)) & 0xff,
510
                                (int) (color1.getBlue() + ((color2.getBlue() - color1.getBlue()) * percNew)) & 0xff,
511
                                (int) (color1.getAlpha() + ((color2.getAlpha() - color1.getAlpha()) * percNew)) & 0xff);
512

    
513

    
514
                return newColor;
515
        }
516

    
517
        /*
518
         * TODO: RENDIMIENTO: Incluir una heuristica que dado un valor se compare con
519
         * el valor de la mitad de la tabla y si es menor se empieza a recorrer desde
520
         * el principio sino se empieza a recorrer desde la mitad de la tabla hasta
521
         * abajo. Esto hace que se reduzca la tabla a la mitad de valores haciendo
522
         * solo una comparaci?n.
523
         */
524
        /*
525
         * (non-Javadoc)
526
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#getRGBAByBand(double)
527
         */
528
        public byte[] getRGBAByBand(double value) {
529
                for (int i = 1; i <= range.length; i++) {
530
                        if (i < range.length) {
531
                                if (value < range[i])
532
                                        return paletteByBand[i - 1];
533
                        } else {
534
                                return paletteByBand[i - 1];
535
                        }
536
                }
537
                return new byte[4];
538
        }
539

    
540
        /*
541
         * TODO: Usar el m?todo Quicksort para ordenar
542
         */
543
        /**
544
         * Ordena el ColorItems de manera ascendente. De momento se usa el m?todo de
545
         * ordenaci?n por burbuja.
546
         */
547
        private void sortPalette(ArrayList<ColorItem> colorItems) {
548
                for (int i = 0; i < colorItems.size(); i++) {
549
                        for (int j = i + 1; j < colorItems.size(); j++) {
550
                                if (((ColorItem) colorItems.get(j)).getValue() < ((ColorItem) colorItems.get(i)).getValue()) {
551
                                        ColorItem aux = (ColorItem) colorItems.get(i);
552
                                        colorItems.set(i, colorItems.get(j));
553
                                        colorItems.set(j, aux);
554
                                }
555
                        }
556
                }
557
        }
558

    
559
        /**
560
         * Genera una paleta intermedia para acelerar los calculos.
561
         */
562
        private void applyPalette(ArrayList<ColorItem> colorItems) {
563
                ArrayList<ColorItem> arrayColors = new ArrayList<ColorItem>();
564

    
565
                paletteByBand = new byte[0][3];
566
                range = new double[0];
567
                nameClass = new String[0];
568

    
569
                if (colorItems.size() == 0)
570
                        return;
571

    
572
                // Nos preparamos para hacer las particiones, sabiendo el minimo y maximo
573
                double min = ((ColorItem) colorItems.get(0)).getValue();
574
                double max = ((ColorItem) colorItems.get(colorItems.size() - 1)).getValue();
575

    
576
                if (min > max) {
577
                        double aux = max;
578
                        max = min;
579
                        min = aux;
580
                }
581

    
582
                Color color = Color.white;
583
                Color colorOld = null;
584

    
585
                // Hacemos las particiones, metiendo cada item calculado en un array
586
                int defaultColors = colorItems.size();//RasterLibrary.defaultNumberOfColors;
587
                for (int i = 0; i < defaultColors; i++) {
588
                        double value = min + ((i * (max - min)) / (defaultColors - 1));
589
                        int pos = 0;
590
                        for (int j = 1; j <= colorItems.size(); j++) {
591
                                if (j < colorItems.size()) {
592
                                        if (value < ((ColorItem) colorItems.get(j)).getValue()) {
593
                                                pos = j - 1;
594
                                                break;
595
                                        }
596
                                } else {
597
                                        pos = j - 1;
598
                                        break;
599
                                }
600
                        }
601

    
602
                        // Calculamos el color que corresponde, tanto interpolado como no
603
                        if (interpolated) {
604
                                color = interpolatedColor(value, pos);
605
                        } else {
606
                                if ((pos + 1) < colorItems.size()) {
607
                                        double min2 = ((ColorItem) colorItems.get(pos)).getValue();
608
                                        double max2 = ((ColorItem) colorItems.get(pos + 1)).getValue();
609
                                        if ((min2 + ((max2 - min2) * ((ColorItem) colorItems.get(pos + 1)).getInterpolated() / 100)) < value)
610
                                                pos++;
611
                                }
612
                                color = ((ColorItem) colorItems.get(pos)).getColor();
613
                        }
614

    
615
                        if (!isEqualColor(color, colorOld, 0)) {
616
                                ColorItem colorItem = new ColorItemImpl();
617
                                colorItem.setValue(value);
618
                                colorItem.setColor(color);
619
                                arrayColors.add(colorItem);
620
                        }
621

    
622
                        colorOld = color;
623
                }
624

    
625
                // Una vez tenemos una paleta de 256 colores o inferior, rellenamos
626
                // los siguientes valores para hacer busquedas rapidas.
627

    
628
                paletteByBand = new byte[arrayColors.size()][4];
629
                range = new double[arrayColors.size()];
630
                nameClass = new String[arrayColors.size()];
631

    
632
                for (int i = 0; i < arrayColors.size(); i++) {
633
                        paletteByBand[i][0] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getRed();
634
                        paletteByBand[i][1] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getGreen();
635
                        paletteByBand[i][2] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getBlue();
636
                        paletteByBand[i][3] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getAlpha();
637
                        range[i] = ((ColorItem) arrayColors.get(i)).getValue();
638
                        nameClass[i] = ((ColorItem) arrayColors.get(i)).getNameClass();
639
                }
640
        }
641

    
642
        public double[] getRange() {
643
                return range;
644
        }
645

    
646
        public void setRange(double[] range) {
647
                this.range = range;
648
        }
649

    
650
        /*
651
         * (non-Javadoc)
652
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#getColorItems()
653
         */
654
        public ArrayList<ColorItem> getColorItems() {
655
                return colorItems;
656
        }
657

    
658
        /*
659
         * (non-Javadoc)
660
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#isInterpolated()
661
         */
662
        public boolean isInterpolated() {
663
                return interpolated;
664
        }
665

    
666
        /*
667
         * (non-Javadoc)
668
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#setInterpolated(boolean)
669
         */
670
        public void setInterpolated(boolean interpolated) {
671
                this.interpolated = interpolated;
672
                applyPalette(colorItems);
673
        }
674

    
675
        /*
676
         * (non-Javadoc)
677
         * @see java.lang.Object#hashCode()
678
         */
679
        public int hashCode() {
680
                final int PRIME = 31;
681
                int result = 1;
682
                result = PRIME * result + ((colorItems == null) ? 0 : colorItems.hashCode());
683
                result = PRIME * result + errorColor;
684
                result = PRIME * result + ((filePath == null) ? 0 : filePath.hashCode());
685
                result = PRIME * result + (interpolated ? 1231 : 1237);
686
                result = PRIME * result + ((name == null) ? 0 : name.hashCode());
687
                result = PRIME * result + DataStoreColorTable.hashCode(nameClass);
688
                result = PRIME * result + DataStoreColorTable.hashCode(paletteByBand);
689
                result = PRIME * result + DataStoreColorTable.hashCode(range);
690
                return result;
691
        }
692

    
693
        private static int hashCode(Object[] array) {
694
                final int PRIME = 31;
695
                if (array == null)
696
                        return 0;
697
                int result = 1;
698
                for (int index = 0; index < array.length; index++) {
699
                        result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
700
                }
701
                return result;
702
        }
703

    
704
        private static int hashCode(double[] array) {
705
                final int PRIME = 31;
706
                if (array == null)
707
                        return 0;
708
                int result = 1;
709
                for (int index = 0; index < array.length; index++) {
710
                        long temp = Double.doubleToLongBits(array[index]);
711
                        result = PRIME * result + (int) (temp ^ (temp >>> 32));
712
                }
713
                return result;
714
        }
715

    
716
        /*
717
         * (non-Javadoc)
718
         * @see java.lang.Object#equals(java.lang.Object)
719
         */
720
        public boolean equals(Object obj) {
721
                if (this == obj)
722
                        return true;
723
                if (obj == null)
724
                        return false;
725
                if (getClass() != obj.getClass())
726
                        return false;
727
                final DataStoreColorTable other = (DataStoreColorTable) obj;
728

    
729
                if ( ((colorItems == null) && (other.colorItems != null)) ||
730
                                ((colorItems != null) && (other.colorItems == null)) )
731
                        return false;
732

    
733
                if (colorItems != null) {
734
                        if (colorItems.size() != other.colorItems.size())
735
                                return false;
736
                        for (int i = 0; i < colorItems.size(); i++) {
737
                                if (!((ColorItem) colorItems.get(i)).equals(other.colorItems.get(i)))
738
                                        return false;
739
                        }
740
                }
741

    
742
                if (filePath == null) {
743
                        if (other.filePath != null)
744
                                return false;
745
                } else if (!filePath.equals(other.filePath))
746
                        return false;
747
                if (name == null) {
748
                        if (other.name != null)
749
                                return false;
750
                } else if (!name.equals(other.name))
751
                        return false;
752

    
753
                if (nameClass != null) {
754
                        if (other.nameClass == null)
755
                                return false;
756

    
757
                        if (nameClass.length != other.nameClass.length)
758
                                return false;
759

    
760
                        for (int i = 0; i < nameClass.length; i++) {
761
                                if (nameClass[i] != null) {
762
                                        if (!nameClass[i].equals(other.nameClass[i]))
763
                                                return false;
764
                                } else {
765
                                        if (other.nameClass[i] != null)
766
                                                return false;
767
                                }
768
                        }
769
                }
770

    
771
                if ( ((paletteByBand == null) && (other.paletteByBand != null)) ||
772
                                ((paletteByBand != null) && (other.paletteByBand == null)) )
773
                        return false;
774

    
775
                if (paletteByBand != null) {
776
                        for (int i = 0; i < paletteByBand.length; i++) {
777
                                for (int j = 0; j < paletteByBand[i].length; j++) {
778
                                        if (paletteByBand[i][j] != other.paletteByBand[i][j])
779
                                                return false;
780
                                }
781
                        }
782
                }
783

    
784
                if (!Arrays.equals(range, other.range))
785
                        return false;
786

    
787
                if ( ((colorItems == null) && (other.colorItems != null)) ||
788
                                ((colorItems != null) && (other.colorItems == null)) )
789
                        return false;
790

    
791
                return true;
792
        }
793

    
794
        /**
795
         * Establece la tabla de color actual en los rangos de limite especificados
796
         * por parametros, distribuyendolo proporcionalmente.
797
         * @param min
798
         * @param max
799
         * @param compress
800
         */
801
        public void createColorTableInRange(double min, double max, boolean compress) {
802
                ColorItem colorItem;
803
                double max2 = Double.NEGATIVE_INFINITY;
804
                double min2 = Double.POSITIVE_INFINITY;
805

    
806
                if (min > max) {
807
                        double aux = min;
808
                        min = max;
809
                        max = aux;
810
                }
811

    
812
                ArrayList<ColorItem> arrayList = new ArrayList<ColorItem>();
813
                ArrayList<ColorItem> items = getColorItems();
814

    
815
                // Actualizamos el maximo y minimo del array
816
                for (int i = 0; i < items.size(); i++) {
817
                        colorItem = (ColorItem) items.get(i);
818
                        if (colorItem.getValue() > max2)
819
                                max2 = colorItem.getValue();
820
                        if (colorItem.getValue() < min2)
821
                                min2 = colorItem.getValue();
822
                }
823

    
824
                // A?adir el minimo
825
                if (items.size() > 0)
826
                        colorItem = (ColorItem) items.get(0);
827
                else {
828
                        colorItem = new ColorItemImpl();
829
                        colorItem.setValue(0);
830
                        colorItem.setColor(Color.black);
831
                }
832

    
833
                arrayList.add(colorItem);
834

    
835
                for (int i = 0; i < items.size(); i++) {
836
                        colorItem = (ColorItem) items.get(i);
837
                        colorItem.setValue(min + (((colorItem.getValue() - min2) * (max - min)) / (max2 - min2)));
838
                        arrayList.add(colorItem);
839
                }
840

    
841
                // A?adir el maximo
842
                if (items.size() > 0)
843
                        colorItem = (ColorItem) items.get(items.size() - 1);
844
                else {
845
                        colorItem = new ColorItemImpl();
846
                        colorItem.setValue(255);
847
                        colorItem.setColor(Color.white);
848
                }
849
                arrayList.add(colorItem);
850

    
851
                createPaletteFromColorItems(arrayList, compress);
852
        }
853
        
854
        /*
855
         * (non-Javadoc)
856
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#isPaletteActive()
857
         */
858
        public boolean isPaletteActive() {
859
                return paletteActive;
860
        }
861

    
862
        /*
863
         * (non-Javadoc)
864
         * @see org.gvsig.fmap.dal.coverage.store.props.ColorTable#setPaletteActive(boolean)
865
         */
866
        public void setPaletteActive(boolean paletteActive) {
867
                this.paletteActive = paletteActive;
868
        }
869
        
870
        @SuppressWarnings("unchecked")
871
        public void loadFromState(PersistentState state)
872
                        throws PersistenceException {
873
                paletteActive = state.getBoolean("paletteActive");
874
                interpolated = state.getBoolean("interpolated");
875
                errorColor = state.getInt("errorColor");
876
                filePath = state.getString("filePath");
877
                name = state.getString("name");
878
                
879
                List<Double> range = state.getList("range");
880
                if(range != null) {
881
                        this.range = new double[range.size()];
882
                        for (int i = 0; i < range.size(); i++) {
883
                                this.range[i] = range.get(i).doubleValue();
884
                        }
885
                }
886
                
887
                List<String> nameClass = state.getList("nameClass");
888
                if(nameClass != null) {
889
                        this.nameClass = new String[nameClass.size()];
890
                        nameClass.toArray(this.nameClass);
891
                }
892
                
893
                List<ColorItem> colorItems = state.getList("colorItems");
894
                if(colorItems != null) {
895
                        this.colorItems = new ArrayList<ColorItem>();
896
                        this.colorItems.addAll(colorItems);
897
                }
898
                
899
                List<String> aux = state.getList("paletteByBand");
900
                if(aux != null) {
901
                        this.paletteByBand = new byte[aux.size()][3];
902
                        for (int i = 0; i < paletteByBand.length; i++) {
903
                                String[] values = aux.get(i).split("#");
904
                                paletteByBand[i][0] = Byte.valueOf(values[0]).byteValue();
905
                                paletteByBand[i][1] = Byte.valueOf(values[1]).byteValue();
906
                                paletteByBand[i][2] = Byte.valueOf(values[2]).byteValue();
907
                        }
908
                }
909
        }
910

    
911
        public void saveToState(PersistentState state) throws PersistenceException {
912
                state.set("paletteActive", paletteActive);                
913
                state.set("interpolated", interpolated);
914
                state.set("errorColor", errorColor);        
915
                state.set("filePath", filePath);        
916
                state.set("name", name);        
917
                state.set("range", range);        
918
                state.set("nameClass", nameClass);        
919
                state.set("colorItems", colorItems);
920
                
921
                ArrayList<String> list = new ArrayList<String>();
922
                if(paletteByBand != null) {
923
                        for (int i = 0; i < paletteByBand.length; i++) {
924
                                list.add(paletteByBand[i][0] + "#" + paletteByBand[i][1] + "#" + paletteByBand[i][2]);
925
                        }
926
                        state.set("paletteByBand", list);
927
                } else {
928
                        state.setNull("paletteByBand");
929
                }
930
        }        
931
        
932
        public static void registerPersistence() {
933
                PersistenceManager manager = ToolsLocator.getPersistenceManager();
934
                DynStruct definition = manager.getDefinition(PERSISTENT_NAME);
935
                if( definition == null ) {
936
                        definition = manager.addDefinition(
937
                                        DataStoreColorTable.class,
938
                                        PERSISTENT_NAME,
939
                                        PERSISTENT_DESCRIPTION,
940
                                        null, 
941
                                        null
942
                        );
943
                        definition.addDynFieldBoolean("paletteActive").setMandatory(true);
944
                        definition.addDynFieldBoolean("interpolated").setMandatory(true);
945
                        definition.addDynFieldInt("errorColor").setMandatory(false);
946
                        definition.addDynFieldString("filePath").setMandatory(false);
947
                        definition.addDynFieldString("name").setMandatory(false);
948
                        definition.addDynFieldList("range").setClassOfItems(Double.class).setMandatory(false);
949
                        definition.addDynFieldList("nameClass").setClassOfItems(String.class).setMandatory(false);
950
                        definition.addDynFieldList("colorItems").setClassOfItems(ColorItem.class).setMandatory(false);
951
                        definition.addDynFieldList("paletteByBand").setClassOfItems(String.class).setMandatory(false);
952
                }
953
        }
954
        
955
}