Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libRaster / src / org / gvsig / raster / datastruct / ColorTable.java @ 17500

History | View | Annotate | Download (22 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.raster.datastruct;
20

    
21
import java.awt.Color;
22
import java.util.ArrayList;
23
import java.util.Arrays;
24

    
25
import org.gvsig.raster.RasterLibrary;
26

    
27
import es.gva.cit.jgdal.GdalColorEntry;
28
import es.gva.cit.jgdal.GdalColorTable;
29
import es.gva.cit.jgdal.GdalException;
30
/**
31
 * Paleta para raster. Esta consta de los valores RGB de la paleta que son
32
 * almacenados en un vector donde cada elemento contiene en su interior el RGB
33
 * completo y del vector de rangos.
34
 *
35
 * @version 04/07/2007
36
 * @author Nacho Brodin (nachobrodin@gmail.com)
37
 * @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es)
38
 */
39
public class ColorTable implements Cloneable {
40
        /**
41
         * Lista de ColorItem donde estaran todos los valores de la paleta segun
42
         * el interfaz
43
         */
44
        protected ArrayList   colorItems        = null;
45

    
46
        /**
47
         * Booleano que define si se interpolaran los valores de la paleta.
48
         */
49
        protected boolean     interpolated      = true;
50

    
51
        /**
52
         * Lista de rangos para paletas decimales
53
         */
54

    
55
        protected double[]    range             = null;
56
        /**
57
         * Lista de valores RGB
58
         */
59
        protected byte[][]    paletteByBand     = null;
60

    
61
        /**
62
         * Nombre de la clase asociada a la entrada
63
         */
64
        protected String[]    nameClass         = null;
65

    
66
        /**
67
         * Nombre de la paleta
68
         */
69
        protected String      name              = null;
70

    
71
        /**
72
         * Ruta del fichero a la cual se asocia la paleta. Las bandas de un
73
         * GeoRasterMultiFile han de saber a que paleta van asociadas.
74
         */
75
        protected String      filePath          = null;
76

    
77
        private int           errorColor        = 8;
78

    
79
        /**
80
         * Constructor vac?o.
81
         * @param name
82
         */
83
        public ColorTable() {
84
                this.name = "";
85
        }
86

    
87
        /**
88
         * Constructor. Asigna el nombre de la paleta.
89
         * @param name
90
         */
91
        public ColorTable(String name) {
92
                this.name = name;
93
        }
94

    
95
        /**
96
         * Asigna el nombre de la paleta
97
         * @param Nombre de la paleta
98
         */
99
        public void setName(String name) {
100
                this.name = name;
101
        }
102

    
103
        /**
104
         * Obtiene el nombre de la paleta
105
         * @return Nombre de la paleta
106
         */
107
        public String getName() {
108
                return name;
109
        }
110

    
111
        /**
112
         * Crea una paleta a traves de una lista de colores y se le puede especificar
113
         * si queremos que la comprima o no.
114
         * @param colorItems
115
         * @param compress
116
         */
117
        public void createPaletteFromColorItems(ArrayList colorItems, boolean compress) {
118
                this.colorItems = colorItems;
119

    
120
                // Ordena la paleta
121
                sortPalette(colorItems);
122

    
123
                // Mira que valores se pueden descartar y asi dejamos la paleta reducida
124
                // para poder hacer interpolaciones
125
                if (compress)
126
                        compressPalette(colorItems);
127

    
128
                // Genera la paleta final para poder ser usada
129
                applyPalette(colorItems);
130
        }
131

    
132
        private boolean isEqualColor(Color c1, Color c2, int error) {
133
                if ((c2 == null) && (c1 != null))
134
                        return false;
135
                if ((c1 == null) && (c2 != null))
136
                        return false;
137
                if (c2.getRed() < (c1.getRed() - error))
138
                        return false;
139
                if (c2.getGreen() < (c1.getGreen() - error))
140
                        return false;
141
                if (c2.getBlue() < (c1.getBlue() - error))
142
                        return false;
143
                if (c2.getAlpha() < (c1.getAlpha() - error))
144
                        return false;
145

    
146
                if (c2.getRed() > (c1.getRed() + error))
147
                        return false;
148
                if (c2.getGreen() > (c1.getGreen() + error))
149
                        return false;
150
                if (c2.getBlue() > (c1.getBlue() + error))
151
                        return false;
152
                if (c2.getAlpha() > (c1.getAlpha() + error))
153
                        return false;
154

    
155
                return true;
156
        }
157

    
158
        /**
159
         * Informa de si el color c3 se encuentra en un rango valido entre c1 y c2.
160
         * Para colores con nombre de clase se devolver? false para no eliminar nunca
161
         * ese item. Para colores con interpolacion distinta al 50% tambien
162
         * devolveremos false.
163
         * @param c1
164
         * @param c2
165
         * @param c3
166
         * @return
167
         */
168
        private boolean isCorrectColor(ColorItem c1, ColorItem c2, ColorItem c3) {
169
                if ((c3.getNameClass() != null) && (c3.getNameClass().length() > 0))
170
                        return false;
171
                if (c3.getInterpolated() != 50)
172
                        return false;
173
                if (c2.getInterpolated() != 50)
174
                        return false;
175

    
176
                double max = c2.getValue() - c1.getValue();
177
                int r = c1.getColor().getRed() + (int) (((c2.getColor().getRed() - c1.getColor().getRed()) * (c3.getValue() - c1.getValue())) / max);
178
                int g = c1.getColor().getGreen() + (int) (((c2.getColor().getGreen() - c1.getColor().getGreen()) * (c3.getValue() - c1.getValue())) / max);
179
                int b = c1.getColor().getBlue() + (int) (((c2.getColor().getBlue() - c1.getColor().getBlue()) * (c3.getValue() - c1.getValue())) / max);
180
                int a = c1.getColor().getAlpha() + (int) (((c2.getColor().getAlpha() - c1.getColor().getAlpha()) * (c3.getValue() - c1.getValue())) / max);
181
                Color aux = new Color(r & 0xff, g & 0xff, b & 0xff, a & 0xff);
182

    
183
                return isEqualColor(c3.getColor(), aux, errorColor);
184
        }
185

    
186
        private boolean canDelete(int first, int last) {
187
                if (first >= getColorItems().size())
188
                        return false;
189
                if (last >= getColorItems().size())
190
                        return false;
191
                ColorItem c1 = (ColorItem) getColorItems().get(first);
192
                ColorItem c2 = (ColorItem) getColorItems().get(last);
193
                for (int i = (first + 1); i < last; i++) {
194
                        if (!isCorrectColor(c1, c2, (ColorItem) getColorItems().get(i)))
195
                                return false;
196
                }
197
                return true;
198
        }
199

    
200
        /**
201
         * Borra valores duplicados de la paleta. Solo aquellos que coincidan en valor
202
         * y color.
203
         */
204
        public void removeDuplicatedValues() {
205
                for (int i = colorItems.size() - 2 ; i >= 0; i--) {
206
                        if ((i + 1) >= colorItems.size())
207
                                continue;
208
                        ColorItem colorItem = (ColorItem) colorItems.get(i + 1);
209
                        ColorItem colorItem2 = (ColorItem) colorItems.get(i);
210
                        // Si hay un valor duplicado, miramos si lo podemos borrar
211
                        if (colorItem.getValue() == colorItem2.getValue()) {
212
                                // Si el color es distinto no lo borramos
213
                                if (!colorItem.getColor().equals(colorItem2.getColor()))
214
                                        continue;
215
                                // Borraremos siempre el valor que no tenga nombre de clase, es un
216
                                // dato importante
217
                                if ((colorItem.getNameClass() == null) || (colorItem.getNameClass().length() == 0))
218
                                        colorItems.remove(i + 1);
219
                                else
220
                                        if ((colorItem2.getNameClass() == null) || (colorItem2.getNameClass().length() == 0))
221
                                                colorItems.remove(i);
222
                        }
223
                }
224
        }
225

    
226
        /**
227
         * Comprime la actual tabla de color
228
         */
229
        public void compressPalette() {
230
                compressPalette(colorItems);
231
        }
232

    
233
        /**
234
         * Informa de si una tabla de color se puede comprimir
235
         * @return
236
         */
237
        public boolean isCompressible() {
238
                ArrayList cloneList = (ArrayList) getColorItems().clone();
239
                compressPalette(cloneList);
240
                return (cloneList.size() != getColorItems().size());
241
        }
242

    
243
        /**
244
         * Coge el array pasado por parametro y lo intenta comprimir
245
         * @param colorItems
246
         */
247
        private void compressPalette(ArrayList colorItems) {
248
                removeDuplicatedValues();
249
                int size = -1;
250

    
251
                while (size != colorItems.size()) {
252
                        int init = 0;
253
                        int posMax = 2;
254

    
255
                        size = colorItems.size();
256
                        while (init < colorItems.size()) {
257
                                if ((posMax < colorItems.size()) && canDelete(init, posMax)) {
258
                                        posMax++;
259
                                        continue;
260
                                }
261
                                if ((init + 2) < posMax) {
262
                                        if (canDelete(init, posMax - 1))
263
                                                for (int i = (posMax - 2); i > init; i--)
264
                                                        if (i < colorItems.size())
265
                                                                colorItems.remove(i);
266
                                }
267
                                init++;
268
                                posMax = init + 2;
269
                        }
270
                }
271
        }
272

    
273
        /**
274
         * Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario
275
         * para los ficheros que tienen una paleta asignada, como los gif, y que son
276
         * tratados por Gdal. Se pasa la tabla de color le?da desde gdal y se crea
277
         * directamente un objeto Palette.
278
         * @param table
279
         */
280
        public void createPaletteFromGdalColorTable(GdalColorTable table) {
281
                try {
282
                        colorItems = new ArrayList();
283
                        for (int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++) {
284
                                GdalColorEntry entry = table.getColorEntryAsRGB(iEntry);
285

    
286
                                ColorItem colorItem = new ColorItem();
287
                                colorItem.setNameClass("");
288
                                colorItem.setValue(iEntry);
289
                                colorItem.setColor(new Color(        (int) (entry.c1 & 0xff),
290
                                                                                                                                                        (int) (entry.c2 & 0xff),
291
                                                                                                                                                        (int) (entry.c3 & 0xff),
292
                                                                                                                                                        (int) (entry.c4 & 0xff)));
293

    
294
                                colorItems.add(colorItem);
295
                        }
296
                } catch (GdalException ex) {
297
                        // No se crea la paleta
298
                }
299
                sortPalette(colorItems);
300

    
301
                setInterpolated(false);
302
                //compressPalette();
303
                applyPalette(colorItems);
304
        }
305

    
306
        /**
307
         * Obtiene la tabla de color por banda
308
         * @return Paleta
309
         */
310
        public byte[][] getColorTableByBand() {
311
                return paletteByBand;
312
        }
313

    
314

    
315
        /**
316
         * Asigna una paleta
317
         * @param palette Paleta
318
         */
319
        public void setColorTable(int[] palette) {
320
                paletteByBand = new byte[palette.length][3];
321
                for (int i = 0; i < palette.length; i++) {
322
                        paletteByBand[i][0] = (byte)((palette[i] & 0x00ff0000) >> 16);
323
                        paletteByBand[i][1] = (byte)((palette[i] & 0x0000ff00) >> 8);
324
                        paletteByBand[i][2] = (byte)(palette[i] & 0x000000ff);
325
                }
326
        }
327

    
328
        /**
329
         * Obtiene los nombres de las clases de la paleta
330
         * @return Array de cadenas. Cada una corresponde con un nombre de clase
331
         * que corresponde a cada rango de tipos.
332
         */
333
        public String[] getNameClass() {
334
                return nameClass;
335
        }
336

    
337
        /**
338
         * Asigna los nombres de las clases de la paleta
339
         * @param names Array de cadenas. Cada una corresponde con un nombre de clase
340
         * que corresponde a cada rango de tipos.
341
         */
342
        public void setNameClass(String[] names) {
343
                nameClass = names;
344
        }
345

    
346
        /**
347
         * Obtiene la ruta del fichero al que va asociada la paleta.
348
         * @return Ruta del fichero al que va asociada la paleta.
349
         */
350
        public String getFilePath() {
351
                return filePath;
352
        }
353

    
354
        /**
355
         * Asigna la ruta del fichero al que va asociada la paleta.
356
         * @param Ruta del fichero al que va asociada la paleta.
357
         */
358
        public void setFilePath(String filePath) {
359
                this.filePath = filePath;
360
        }
361

    
362
        /*
363
         * (non-Javadoc)
364
         * @see java.lang.Object#clone()
365
         */
366
        public Object clone() {
367
                ColorTable clone = null;
368
                try {
369
                        clone = (ColorTable) super.clone();
370
                } catch (CloneNotSupportedException e) {
371
                }
372

    
373
                if (colorItems != null) {
374
                        clone.colorItems = new ArrayList();
375
                        for (int i = 0; i < colorItems.size(); i++) {
376
                                clone.colorItems.add((ColorItem) ((ColorItem) colorItems.get(i)).clone());
377
                        }
378
                }
379

    
380
                clone.interpolated = interpolated;
381

    
382
                if (filePath != null)
383
                        clone.filePath = new String(filePath);
384

    
385
                if (name != null)
386
                        clone.name = new String(name);
387

    
388
                if (nameClass != null) {
389
                        clone.nameClass = new String[nameClass.length];
390
                        for (int i = 0; i < nameClass.length; i++)
391
                                clone.nameClass[i] = nameClass[i];
392
                }
393

    
394
                if (paletteByBand != null) {
395
                        clone.paletteByBand = (byte[][]) paletteByBand.clone();
396
                        for (int i = 0; i < paletteByBand.length; i++)
397
                                clone.paletteByBand[i] = (byte[]) paletteByBand[i].clone();
398
                }
399

    
400
                if (range != null)
401
                        clone.range = (double[]) range.clone();
402

    
403
                return clone;
404
        }
405

    
406
        /**
407
         * Devuelve un color de interpolacion entre dos colores
408
         * @param value
409
         * @param pos
410
         * @return
411
         */
412
        private Color interpolatedColor(double value, int pos) {
413
                if (colorItems.size() <= 0)
414
                        return Color.black;
415

    
416
                if ((pos + 1) == colorItems.size())
417
                        return ((ColorItem) colorItems.get(pos)).getColor();
418

    
419
                if (value <= ((ColorItem) colorItems.get(0)).getValue())
420
                        return ((ColorItem) colorItems.get(0)).getColor();
421

    
422
                ColorItem item1 = (ColorItem) colorItems.get(pos);
423
                ColorItem item2 = (ColorItem) colorItems.get(pos + 1);
424

    
425
                double percValue = ((value - item1.getValue()) * 100) / (item2.getValue() - item1.getValue());
426

    
427
                Color halfColor = new Color(
428
                                (item2.getColor().getRed() + item1.getColor().getRed()) >> 1,
429
                                (item2.getColor().getGreen() + item1.getColor().getGreen()) >> 1,
430
                                (item2.getColor().getBlue() + item1.getColor().getBlue()) >> 1,
431
                                (item2.getColor().getAlpha() + item1.getColor().getAlpha()) >> 1);
432

    
433
                Color color1, color2;
434
                double perc1, perc2;
435

    
436
                if (percValue > item2.getInterpolated()) {
437
                        color1 = halfColor;
438
                        color2 = item2.getColor();
439
                        perc1 = item2.getInterpolated();
440
                        perc2 = 100;
441
                } else {
442
                        color1 = item1.getColor();
443
                        color2 = halfColor;
444
                        perc1 = 0;
445
                        perc2 = item2.getInterpolated();
446
                }
447

    
448
                double percNew = (percValue - perc1) / (perc2 - perc1);
449

    
450
                Color newColor = new Color(
451
                                (int) (color1.getRed() + ((color2.getRed() - color1.getRed()) * percNew)) & 0xff,
452
                                (int) (color1.getGreen() + ((color2.getGreen() - color1.getGreen()) * percNew)) & 0xff,
453
                                (int) (color1.getBlue() + ((color2.getBlue() - color1.getBlue()) * percNew)) & 0xff,
454
                                (int) (color1.getAlpha() + ((color2.getAlpha() - color1.getAlpha()) * percNew)) & 0xff);
455

    
456

    
457
                return newColor;
458
        }
459

    
460
        /*
461
         * TODO: RENDIMIENTO: Incluir una heuristica que dado un valor se compare con
462
         * el valor de la mitad de la tabla y si es menor se empieza a recorrer desde
463
         * el principio sino se empieza a recorrer desde la mitad de la tabla hasta
464
         * abajo. Esto hace que se reduzca la tabla a la mitad de valores haciendo
465
         * solo una comparaci?n.
466
         */
467
        /**
468
         * Obtiene el valor RGB para un clave entera pasada por par?metro
469
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
470
         * @return valor RGB
471
         */
472
        public byte[] getRGBAByBand(double value) {
473
                for (int i = 1; i <= range.length; i++) {
474
                        if (i < range.length) {
475
                                if (value < range[i])
476
                                        return paletteByBand[i - 1];
477
                        } else {
478
                                return paletteByBand[i - 1];
479
                        }
480
                }
481
                return new byte[4];
482
        }
483

    
484
        /*
485
         * TODO: Usar el m?todo Quicksort para ordenar
486
         */
487
        /**
488
         * Ordena el ColorItems de manera ascendente. De momento se usa el m?todo de
489
         * ordenaci?n por burbuja.
490
         */
491
        private void sortPalette(ArrayList colorItems) {
492
                for (int i = 0; i < colorItems.size(); i++) {
493
                        for (int j = i + 1; j < colorItems.size(); j++) {
494
                                if (((ColorItem) colorItems.get(j)).getValue() < ((ColorItem) colorItems.get(i)).getValue()) {
495
                                        ColorItem aux = (ColorItem) colorItems.get(i);
496
                                        colorItems.set(i, colorItems.get(j));
497
                                        colorItems.set(j, aux);
498
                                }
499
                        }
500
                }
501
        }
502

    
503
        /**
504
         * Genera una paleta intermedia para acelerar los calculos.
505
         */
506
        private void applyPalette(ArrayList colorItems) {
507
                ArrayList arrayColors = new ArrayList();
508

    
509
                paletteByBand = new byte[0][3];
510
                range = new double[0];
511
                nameClass = new String[0];
512

    
513
                if (colorItems.size() == 0)
514
                        return;
515

    
516
                // Nos preparamos para hacer las particiones, sabiendo el minimo y maximo
517
                double min = ((ColorItem) colorItems.get(0)).getValue();
518
                double max = ((ColorItem) colorItems.get(colorItems.size() - 1)).getValue();
519

    
520
                if (min > max) {
521
                        double aux = max;
522
                        max = min;
523
                        min = aux;
524
                }
525

    
526
                Color color = Color.white;
527
                Color colorOld = null;
528

    
529
                // Hacemos las particiones, metiendo cada item calculado en un array
530
                int defaultColors = RasterLibrary.defaultNumberOfColors;
531
                for (int i = 0; i < defaultColors; i++) {
532
                        double value = min + ((i * (max - min)) / (defaultColors - 1));
533
                        int pos = 0;
534
                        for (int j = 1; j <= colorItems.size(); j++) {
535
                                if (j < colorItems.size()) {
536
                                        if (value < ((ColorItem) colorItems.get(j)).getValue()) {
537
                                                pos = j - 1;
538
                                                break;
539
                                        }
540
                                } else {
541
                                        pos = j - 1;
542
                                        break;
543
                                }
544
                        }
545

    
546
                        // Calculamos el color que corresponde, tanto interpolado como no
547
                        if (interpolated) {
548
                                color = interpolatedColor(value, pos);
549
                        } else {
550
                                if ((pos + 1) < colorItems.size()) {
551
                                        double min2 = ((ColorItem) colorItems.get(pos)).getValue();
552
                                        double max2 = ((ColorItem) colorItems.get(pos + 1)).getValue();
553
                                        if ((min2 + ((max2 - min2) * ((ColorItem) colorItems.get(pos + 1)).getInterpolated() / 100)) < value)
554
                                                pos++;
555
                                }
556
                                color = ((ColorItem) colorItems.get(pos)).getColor();
557
                        }
558

    
559
                        if (!isEqualColor(color, colorOld, 0)) {
560
                                ColorItem colorItem = new ColorItem();
561
                                colorItem.setValue(value);
562
                                colorItem.setColor(color);
563
                                arrayColors.add(colorItem);
564
                        }
565

    
566
                        colorOld = color;
567
                }
568

    
569
                // Una vez tenemos una paleta de 256 colores o inferior, rellenamos
570
                // los siguientes valores para hacer busquedas rapidas.
571

    
572
                paletteByBand = new byte[arrayColors.size()][4];
573
                range = new double[arrayColors.size()];
574
                nameClass = new String[arrayColors.size()];
575

    
576
                for (int i = 0; i < arrayColors.size(); i++) {
577
                        paletteByBand[i][0] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getRed();
578
                        paletteByBand[i][1] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getGreen();
579
                        paletteByBand[i][2] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getBlue();
580
                        paletteByBand[i][3] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getAlpha();
581
                        range[i] = ((ColorItem) arrayColors.get(i)).getValue();
582
                        nameClass[i] = ((ColorItem) arrayColors.get(i)).getNameClass();
583
                }
584
        }
585

    
586
        public double[] getRange() {
587
                return range;
588
        }
589

    
590
        public void setRange(double[] range) {
591
                this.range = range;
592
        }
593

    
594
        /**
595
         * Devuelve un ArrayList con cada ColorItem de la tabla de color
596
         * @return
597
         */
598
        public ArrayList getColorItems() {
599
                return colorItems;
600
        }
601

    
602
        /**
603
         * Nos indica si la paleta la ha generado con valores interpolados o no.
604
         * @return
605
         */
606
        public boolean isInterpolated() {
607
                return interpolated;
608
        }
609

    
610
        /**
611
         * Definir si la paleta tendra los valores interpolados o no
612
         * @param interpolated
613
         */
614
        public void setInterpolated(boolean interpolated) {
615
                this.interpolated = interpolated;
616
                applyPalette(colorItems);
617
        }
618

    
619
        /*
620
         * (non-Javadoc)
621
         * @see java.lang.Object#hashCode()
622
         */
623
        public int hashCode() {
624
                final int PRIME = 31;
625
                int result = 1;
626
                result = PRIME * result + ((colorItems == null) ? 0 : colorItems.hashCode());
627
                result = PRIME * result + errorColor;
628
                result = PRIME * result + ((filePath == null) ? 0 : filePath.hashCode());
629
                result = PRIME * result + (interpolated ? 1231 : 1237);
630
                result = PRIME * result + ((name == null) ? 0 : name.hashCode());
631
                result = PRIME * result + ColorTable.hashCode(nameClass);
632
                result = PRIME * result + ColorTable.hashCode(paletteByBand);
633
                result = PRIME * result + ColorTable.hashCode(range);
634
                return result;
635
        }
636

    
637
        private static int hashCode(Object[] array) {
638
                final int PRIME = 31;
639
                if (array == null)
640
                        return 0;
641
                int result = 1;
642
                for (int index = 0; index < array.length; index++) {
643
                        result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
644
                }
645
                return result;
646
        }
647

    
648
        private static int hashCode(double[] array) {
649
                final int PRIME = 31;
650
                if (array == null)
651
                        return 0;
652
                int result = 1;
653
                for (int index = 0; index < array.length; index++) {
654
                        long temp = Double.doubleToLongBits(array[index]);
655
                        result = PRIME * result + (int) (temp ^ (temp >>> 32));
656
                }
657
                return result;
658
        }
659

    
660
        /*
661
         * (non-Javadoc)
662
         * @see java.lang.Object#equals(java.lang.Object)
663
         */
664
        public boolean equals(Object obj) {
665
                if (this == obj)
666
                        return true;
667
                if (obj == null)
668
                        return false;
669
                if (getClass() != obj.getClass())
670
                        return false;
671
                final ColorTable other = (ColorTable) obj;
672

    
673
                if ( ((colorItems == null) && (other.colorItems != null)) ||
674
                                ((colorItems != null) && (other.colorItems == null)) )
675
                        return false;
676

    
677
                if (colorItems != null) {
678
                        if (colorItems.size() != other.colorItems.size())
679
                                return false;
680
                        for (int i = 0; i < colorItems.size(); i++) {
681
                                if (!((ColorItem) colorItems.get(i)).equals(other.colorItems.get(i)))
682
                                        return false;
683
                        }
684
                }
685

    
686
                if (filePath == null) {
687
                        if (other.filePath != null)
688
                                return false;
689
                } else if (!filePath.equals(other.filePath))
690
                        return false;
691
                if (name == null) {
692
                        if (other.name != null)
693
                                return false;
694
                } else if (!name.equals(other.name))
695
                        return false;
696

    
697
                if (nameClass != null) {
698
                        if (other.nameClass == null)
699
                                return false;
700

    
701
                        if (nameClass.length != other.nameClass.length)
702
                                return false;
703

    
704
                        for (int i = 0; i < nameClass.length; i++) {
705
                                if (nameClass[i] != null) {
706
                                        if (!nameClass[i].equals(other.nameClass[i]))
707
                                                return false;
708
                                } else {
709
                                        if (other.nameClass[i] != null)
710
                                                return false;
711
                                }
712
                        }
713
                }
714

    
715
                if ( ((paletteByBand == null) && (other.paletteByBand != null)) ||
716
                                ((paletteByBand != null) && (other.paletteByBand == null)) )
717
                        return false;
718

    
719
                if (paletteByBand != null) {
720
                        for (int i = 0; i < paletteByBand.length; i++) {
721
                                for (int j = 0; j < paletteByBand[i].length; j++) {
722
                                        if (paletteByBand[i][j] != other.paletteByBand[i][j])
723
                                                return false;
724
                                }
725
                        }
726
                }
727

    
728
                if (!Arrays.equals(range, other.range))
729
                        return false;
730

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

    
735
                return true;
736
        }
737

    
738
        /**
739
         * Establece la tabla de color actual en los rangos de limite especificados
740
         * por parametros, distribuyendolo proporcionalmente.
741
         * @param min
742
         * @param max
743
         * @param compress
744
         */
745
        public void createColorTableInRange(double min, double max, boolean compress) {
746
                ColorItem colorItem;
747
                double max2 = Double.NEGATIVE_INFINITY;
748
                double min2 = Double.POSITIVE_INFINITY;
749

    
750
                if (min > max) {
751
                        double aux = min;
752
                        min = max;
753
                        max = aux;
754
                }
755

    
756
                ArrayList arrayList = new ArrayList();
757
                ArrayList items = getColorItems();
758

    
759
                // Actualizamos el maximo y minimo del array
760
                for (int i = 0; i < items.size(); i++) {
761
                        colorItem = (ColorItem) items.get(i);
762
                        if (colorItem.getValue() > max2)
763
                                max2 = colorItem.getValue();
764
                        if (colorItem.getValue() < min2)
765
                                min2 = colorItem.getValue();
766
                }
767

    
768
                // A?adir el minimo
769
                if (items.size() > 0)
770
                        colorItem = (ColorItem) items.get(0);
771
                else {
772
                        colorItem = new ColorItem();
773
                        colorItem.setValue(0);
774
                        colorItem.setColor(Color.black);
775
                }
776

    
777
                arrayList.add(colorItem);
778

    
779
                for (int i = 0; i < items.size(); i++) {
780
                        colorItem = (ColorItem) items.get(i);
781
                        colorItem.setValue(min + (((colorItem.getValue() - min2) * (max - min)) / (max2 - min2)));
782
                        arrayList.add(colorItem);
783
                }
784

    
785
                // A?adir el maximo
786
                if (items.size() > 0)
787
                        colorItem = (ColorItem) items.get(items.size() - 1);
788
                else {
789
                        colorItem = new ColorItem();
790
                        colorItem.setValue(255);
791
                        colorItem.setColor(Color.white);
792
                }
793
                arrayList.add(colorItem);
794

    
795
                createPaletteFromColorItems(arrayList, compress);
796
        }
797
}