Statistics
| Revision:

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

History | View | Annotate | Download (20.8 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
        private static int hashCode(Object[] array) {
41
                final int PRIME = 31;
42
                if (array == null)
43
                        return 0;
44
                int result = 1;
45
                for (int index = 0; index < array.length; index++) {
46
                        result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
47
                }
48
                return result;
49
        }
50

    
51
        private static int hashCode(double[] array) {
52
                final int PRIME = 31;
53
                if (array == null)
54
                        return 0;
55
                int result = 1;
56
                for (int index = 0; index < array.length; index++) {
57
                        long temp = Double.doubleToLongBits(array[index]);
58
                        result = PRIME * result + (int) (temp ^ (temp >>> 32));
59
                }
60
                return result;
61
        }
62

    
63
        /**
64
         * Lista de ColorItem donde estaran todos los valores de la paleta segun
65
         * el interfaz
66
         */
67
        protected ArrayList   colorItems        = null;
68

    
69
        /**
70
         * Booleano que define si se interpolaran los valores de la paleta.
71
         */
72
        protected boolean   interpolated      = true;
73

    
74
        /**
75
         * Lista de rangos para paletas decimales
76
         */
77

    
78
        protected double[]  range             = null;
79
        /**
80
         * Lista de valores RGB
81
         */
82
        protected byte[][]  paletteByBand     = null;
83

    
84
        /**
85
         * Nombre de la clase asociada a la entrada
86
         */
87
        protected String[]  nameClass         = null;
88

    
89
        /**
90
         * Lista con todas las transparencias de la paleta
91
         */
92
        protected ArrayList transparencyRange = new ArrayList();
93

    
94
        /**
95
         * Nombre de la paleta
96
         */
97
        protected String    name              = null;
98

    
99
        /**
100
         * Ruta del fichero a la cual se asocia la paleta. Las bandas de un
101
         * GeoRasterMultiFile han de saber a que paleta van asociadas.
102
         */
103
        protected String    filePath          = null;
104

    
105
        /**
106
         * Constructor vac?o.
107
         * @param name
108
         */
109
        public ColorTable() {
110
                this.name = "";
111
        }
112

    
113
        /**
114
         * Constructor. Asigna el nombre de la paleta.
115
         * @param name
116
         */
117
        public ColorTable(String name) {
118
                this.name = name;
119
        }
120

    
121
        /**
122
         * Asigna el nombre de la paleta
123
         * @param Nombre de la paleta
124
         */
125
        public void setName(String name) {
126
                this.name = name;
127
        }
128

    
129
        /**
130
         * Obtiene el nombre de la paleta
131
         * @return Nombre de la paleta
132
         */
133
        public String getName() {
134
                return name;
135
        }
136

    
137
//        static int total = 0;
138
        public void createPaletteFromColorItems(ArrayList colorItems, boolean compress) {
139
                this.colorItems = colorItems;
140

    
141
                // Ordena la paleta
142
                sortPalette(colorItems);
143
/*
144
                System.out.println(name);
145
                System.out.println("----- Sin comprimir (" + colorItems.size() + ") -----");
146
*/
147
/*
148
                if (name.equals("MDT1")) {
149
                        for (int i=0; i<colorItems.size(); i++) {
150
                                ColorItem c1 = ((ColorItem) colorItems.get(i));
151
                                Color co = c1.getColor();
152
                                System.out.println(c1.getValue() + ": " + co.getRed() + "," + co.getGreen() + "," + co.getBlue() + "," + co.getAlpha());
153
                        }
154
                }
155
*/
156
                // Mira que valores se pueden descartar y asi dejamos la paleta reducida
157
                // para poder hacer interpolaciones
158
                if (compress)
159
                        compressPalette(colorItems);
160
/*
161
                System.out.println("------ Comprimido (" + colorItems.size() + ") ------");
162
                total += colorItems.size();
163
                System.out.println("------ Total (" + total + ")----");
164
*/
165
/*
166
                if (name.equals("MDT1")) {
167
                        for (int i=0; i<colorItems.size(); i++) {
168
                                ColorItem c1 = ((ColorItem) colorItems.get(i));
169
                                Color co = c1.getColor();
170
                                System.out.println(c1.getValue() + ": " + co.getRed() + "," + co.getGreen() + "," + co.getBlue() + "," + co.getAlpha());
171
                        }
172
                }
173
*/
174
                // Genera la paleta final para poder ser usada
175
                applyPalette(colorItems);
176
        }
177

    
178
        private int error = 8;
179
        private boolean isEqualColor(Color c1, Color c2) {
180
                if (c2.getRed() < (c1.getRed() - error)) return false;
181
                if (c2.getGreen() < (c1.getGreen() - error)) return false;
182
                if (c2.getBlue() < (c1.getBlue() - error)) return false;
183
                if (c2.getAlpha() < (c1.getAlpha() - error)) return false;
184

    
185
                if (c2.getRed() > (c1.getRed() + error)) return false;
186
                if (c2.getGreen() > (c1.getGreen() + error)) return false;
187
                if (c2.getBlue() > (c1.getBlue() + error)) return false;
188
                if (c2.getAlpha() > (c1.getAlpha() + error)) return false;
189

    
190
                return true;
191
        }
192

    
193
        /**
194
         * Informa de si el color c3 se encuentra en un rango valido entre c1 y c2.
195
         * Para colores con nombre de clase se devolver? false para no eliminar nunca
196
         * ese item.
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

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

    
213
                return isEqualColor(c3.getColor(), aux);
214
        }
215

    
216
        private boolean canDelete(int first, int last) {
217
                ColorItem c1 = (ColorItem) colorItems.get(first);
218
                ColorItem c2 = (ColorItem) colorItems.get(last);
219
                for (int i = (first + 1); i < last; i++) {
220
                        if (!isCorrectColor(c1, c2, (ColorItem) colorItems.get(i)))
221
                                return false;
222
                }
223
                return true;
224
        }
225

    
226
        public void compressPalette() {
227
                compressPalette(colorItems);
228
        }
229

    
230
        public boolean isCompressible() {
231
                ArrayList cloneList = (ArrayList) colorItems.clone();
232
                compressPalette(cloneList);
233
                return (cloneList.size() != colorItems.size());
234
        }
235

    
236
        private void compressPalette(ArrayList colorItems) {
237
                int size = -1;
238

    
239
                while (size != colorItems.size()) {
240
                        int init = 0;
241
                        int posMax = 2;
242

    
243
                        size = colorItems.size();
244
                        while (init < colorItems.size()) {
245
                                if ((posMax < colorItems.size()) && canDelete(init, posMax)) {
246
                                        posMax++;
247
                                        continue;
248
                                }
249
                                if ((init + 2) < posMax) {
250
                                        if (canDelete(init, posMax - 1))
251
                                                for (int i = (posMax - 2); i > init; i--)
252
                                                        if (i < colorItems.size())
253
                                                                colorItems.remove(i);
254
                                }
255
                                init++;
256
                                posMax = init + 2;
257
                        }
258
                }
259
        }
260

    
261
        /**
262
         * Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario
263
         * para los ficheros que tienen una paleta asignada, como los gif, y que son
264
         * tratados por Gdal. Se pasa la tabla de color le?da desde gdal y se crea
265
         * directamente un objeto Palette.
266
         * @param table
267
         */
268
        public void createPaletteFromGdalColorTable(GdalColorTable table) {
269
                try {
270
                        colorItems = new ArrayList();
271
                        for (int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++) {
272
                                GdalColorEntry entry = table.getColorEntryAsRGB(iEntry);
273

    
274
                                ColorItem colorItem = new ColorItem();
275
                                colorItem.setNameClass("");
276
                                colorItem.setValue(iEntry);
277
                                colorItem.setColor(new Color(        (int) (entry.c1 & 0xff),
278
                                                                                                                                                        (int) (entry.c2 & 0xff),
279
                                                                                                                                                        (int) (entry.c3 & 0xff),
280
                                                                                                                                                        (int) (entry.c4 & 0xff)));
281

    
282
                                colorItems.add(colorItem);
283
                        }
284
                } catch (GdalException ex) {
285
                        // No se crea la paleta
286
                }
287
                sortPalette(colorItems);
288
                //compressPalette();
289
                applyPalette(colorItems);
290
        }
291

    
292
        /**
293
         * Obtiene la transparencia por rangos asociada a la tabla de color actual.
294
         * @return Lista de objetos TransparencyRange
295
         */
296
        public ArrayList getTransparencyRanges() {
297
                return transparencyRange;
298
        }
299

    
300
        /**
301
         * Obtiene la tabla de color
302
         * @return Paleta
303
         */
304
/*
305
        public int[] getColorTable() {
306
                return palette;
307
        }
308
*/
309

    
310
        /**
311
         * Obtiene la tabla de color por banda
312
         * @return Paleta
313
         */
314
        public byte[][] getColorTableByBand() {
315
                return paletteByBand;
316
        }
317

    
318

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

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

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

    
350
        /**
351
         * Obtiene la ruta del fichero al que va asociada la paleta.
352
         * @return Ruta del fichero al que va asociada la paleta.
353
         */
354
        public String getFilePath() {
355
                return filePath;
356
        }
357

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

    
366
        /**
367
         * Obtiene los rangos de transparencia que tiene la paleta. Estos se obtienen
368
         * en un array de objetos TransparencyRange. Cada uno de ellos representa un
369
         * rango de pixeles
370
         * @return ArrayList
371
         */
372
        public ArrayList getTransparencyRange() {
373
                return transparencyRange;
374
        }
375

    
376
        /*
377
         * (non-Javadoc)
378
         * @see java.lang.Object#clone()
379
         */
380
        public Object clone() {
381
                ColorTable clone = null;
382
                try {
383
                        clone = (ColorTable) super.clone();
384
                } catch (CloneNotSupportedException e) {
385
                }
386

    
387
                if (colorItems != null) {
388
                        clone.colorItems = new ArrayList();
389
                        for (int i = 0; i < colorItems.size(); i++) {
390
                                clone.colorItems.add(((ColorItem) colorItems.get(i)).clone());
391
                        }
392
                }
393

    
394
                if (filePath != null)
395
                        clone.filePath = new String(filePath);
396

    
397
                if (name != null)
398
                        clone.name = new String(name);
399

    
400
                if (nameClass != null) {
401
                        clone.nameClass = new String[nameClass.length];
402
                        for (int i = 0; i < nameClass.length; i++)
403
                                clone.nameClass[i] = new String(nameClass[i]);
404
                }
405

    
406
                if (paletteByBand != null) {
407
                        clone.paletteByBand = (byte[][]) paletteByBand.clone();
408
                        for (int i = 0; i < paletteByBand.length; i++)
409
                                clone.paletteByBand[i] = (byte[]) paletteByBand[i].clone();
410
                }
411

    
412
                if (range != null)
413
                        clone.range = (double[]) range.clone();
414

    
415
                if (transparencyRange != null) {
416
                        clone.transparencyRange = new ArrayList();
417
                        for (int i = 0; i < transparencyRange.size(); i++) {
418
                                clone.transparencyRange.add(((TransparencyRange) transparencyRange.get(i)).clone());
419
                        }
420
                }
421

    
422
                return clone;
423
        }
424

    
425
        /**
426
         * Devuelve un color de interpolacion entre dos colores
427
         * @param value
428
         * @param pos
429
         * @return
430
         */
431
        private Color interpolatedColor(double value, int pos) {
432
                if ((pos + 1) == colorItems.size())
433
                        return ((ColorItem) colorItems.get(pos)).getColor();
434

    
435
                ColorItem item1 = (ColorItem) colorItems.get(pos);
436
                ColorItem item2 = (ColorItem) colorItems.get(pos + 1);
437

    
438
                double percValue = ((value - item1.getValue()) * 100) / (item2.getValue() - item1.getValue());
439

    
440
                Color halfColor = new Color(
441
                                (item2.getColor().getRed() + item1.getColor().getRed()) >> 1,
442
                                (item2.getColor().getGreen() + item1.getColor().getGreen()) >> 1,
443
                                (item2.getColor().getBlue() + item1.getColor().getBlue()) >> 1,
444
                                (item2.getColor().getAlpha() + item1.getColor().getAlpha()) >> 1);
445

    
446
                Color color1, color2;
447
                int perc1, perc2;
448

    
449
                if (percValue > item1.getInterpolated()) {
450
                        color1 = halfColor;
451
                        color2 = item2.getColor();
452
                        perc1 = item1.getInterpolated();
453
                        perc2 = 100;
454
                } else {
455
                        color1 = item1.getColor();
456
                        color2 = halfColor;
457
                        perc1 = 0;
458
                        perc2 = item1.getInterpolated();
459
                }
460

    
461
                double percNew = (percValue - perc1) / (perc2 - perc1);
462

    
463
                Color newColor = new Color(
464
                                (int) (color1.getRed() + ((color2.getRed() - color1.getRed()) * percNew)) & 0xff,
465
                                (int) (color1.getGreen() + ((color2.getGreen() - color1.getGreen()) * percNew)) & 0xff,
466
                                (int) (color1.getBlue() + ((color2.getBlue() - color1.getBlue()) * percNew)) & 0xff,
467
                                (int) (color1.getAlpha() + ((color2.getAlpha() - color1.getAlpha()) * percNew)) & 0xff);
468

    
469

    
470
                return newColor;
471
        }
472

    
473
        /*
474
         * TODO: RENDIMIENTO: Incluir una heuristica que dado un valor se compare con
475
         * el valor de la mitad de la tabla y si es menor se empieza a recorrer desde
476
         * el principio sino se empieza a recorrer desde la mitad de la tabla hasta
477
         * abajo. Esto hace que se reduzca la tabla a la mitad de valores haciendo
478
         * solo una comparaci?n.
479
         */
480
        /**
481
         * Obtiene el valor RGB para un clave entera pasada por par?metro
482
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
483
         * @return valor RGB
484
         */
485
        public byte[] getRGBByBand(double value) {
486
                for (int i = 1; i <= range.length; i++) {
487
                        if (i < range.length) {
488
                                if (value < range[i])
489
                                        return paletteByBand[i - 1];
490
                        } else {
491
                                return paletteByBand[i - 1];
492
                        }
493
                }
494
                return new byte[4];
495
        }
496

    
497
        /*
498
         * TODO: Usar el m?todo Quicksort para ordenar
499
         */
500
        /**
501
         * Ordena el ColorItems de manera ascendente. De momento se usa el m?todo de
502
         * ordenaci?n por burbuja.
503
         */
504
        private void sortPalette(ArrayList colorItems) {
505
                for (int i = 0; i < colorItems.size(); i++) {
506
                        for (int j = i + 1; j < colorItems.size(); j++) {
507
                                if (((ColorItem) colorItems.get(j)).getValue() < ((ColorItem) colorItems.get(i)).getValue()) {
508
                                        Object aux = colorItems.get(i);
509
                                        colorItems.set(i, colorItems.get(j));
510
                                        colorItems.set(j, aux);
511
                                }
512
                        }
513
                }
514
        }
515

    
516
        /**
517
         * Genera una paleta intermedia para acelerar los calculos.
518
         */
519
        private void applyPalette(ArrayList colorItems) {
520
                ArrayList arrayColors = new ArrayList();
521

    
522
                paletteByBand = new byte[0][3];
523
                range = new double[0];
524
                nameClass = new String[0];
525

    
526
                if (colorItems.size()==0)
527
                        return;
528

    
529
                // Nos preparamos para hacer las particiones, sabiendo el minimo y maximo
530
                double min = ((ColorItem) colorItems.get(0)).getValue();
531
                double max = ((ColorItem) colorItems.get(colorItems.size() - 1)).getValue();
532

    
533
                if (min > max) {
534
                        double aux = max;
535
                        max = min;
536
                        min = aux;
537
                }
538

    
539
                Color color = Color.white;
540
                Color colorOld = null;
541

    
542
                // Hacemos las particiones, metiendo cada item calculado en un array
543
                int defaultColors = RasterLibrary.defaultNumberOfColors;
544
                for (int i = 0; i < defaultColors; i++) {
545
                        double value = min + ((i * (max - min)) / (defaultColors - 1));
546
                        int pos = 0;
547
                        for (int j = 1; j <= colorItems.size(); j++) {
548
                                if (j < colorItems.size()) {
549
                                        if (value < ((ColorItem) colorItems.get(j)).getValue()) {
550
                                                pos = j - 1;
551
                                                break;
552
                                        }
553
                                } else {
554
                                        pos = j - 1;
555
                                        break;
556
                                }
557
                        }
558

    
559
                        // Calculamos el color que corresponde, tanto interpolado como no
560
                        if (interpolated) {
561
                                color = interpolatedColor(value, pos);
562
                        } else {
563
                                if ((pos + 1) < colorItems.size()) {
564
                                        if ((((ColorItem) colorItems.get(pos)).getValue() + ((ColorItem) colorItems.get(pos + 1)).getValue()) / 2 < value)
565
                                                pos++;
566
                                }
567
                                color = ((ColorItem) colorItems.get(pos)).getColor();
568
                        }
569

    
570
                        if (!color.equals(colorOld)) {
571
                                ColorItem colorItem = new ColorItem();
572
                                colorItem.setNameClass("");
573
                                colorItem.setValue(value);
574
                                colorItem.setColor(color);
575
                                arrayColors.add(colorItem);
576
                        }
577

    
578
                        colorOld = color;
579
                }
580

    
581
                // Una vez tenemos una paleta de 256 colores o inferior, rellenamos
582
                // los siguientes valores para hacer busquedas rapidas.
583

    
584
                paletteByBand = new byte[arrayColors.size()][3];
585
                range = new double[arrayColors.size()];
586
                nameClass = new String[arrayColors.size()];
587

    
588
                transparencyRange.clear();
589
                for (int i = 0; i < arrayColors.size(); i++) {
590
                        paletteByBand[i][0] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getRed();
591
                        paletteByBand[i][1] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getGreen();
592
                        paletteByBand[i][2] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getBlue();
593
                        range[i] = ((ColorItem) arrayColors.get(i)).getValue();
594
                        nameClass[i] = ((ColorItem) arrayColors.get(i)).getNameClass();
595
                        if (((ColorItem) arrayColors.get(i)).getColor().getAlpha() != 255) {
596
                                TransparencyRange r = new TransparencyRange();
597
                                r.setRed(new int[] { ((ColorItem) arrayColors.get(i)).getColor().getRed(), ((ColorItem) arrayColors.get(i)).getColor().getRed() });
598
                                r.setGreen(new int[] { ((ColorItem) arrayColors.get(i)).getColor().getGreen(), ((ColorItem) arrayColors.get(i)).getColor().getGreen() });
599
                                r.setBlue(new int[] { ((ColorItem) arrayColors.get(i)).getColor().getBlue(), ((ColorItem) arrayColors.get(i)).getColor().getBlue() });
600
                                r.setAlpha(((ColorItem) arrayColors.get(i)).getColor().getAlpha());
601
                                r.setAnd(true);
602
                                r.loadStrEntryFromValues();
603
                                transparencyRange.add(r);
604
                        }
605
                }
606
        }
607

    
608
        public double[] getRange() {
609
                return range;
610
        }
611

    
612
        public void setRange(double[] range) {
613
                this.range = range;
614
        }
615

    
616
        public ArrayList getColorItems() {
617
                return colorItems;
618
        }
619

    
620
        /**
621
         * Nos indica si la paleta la ha generado con valores interpolados o no.
622
         * @return
623
         */
624
        public boolean isInterpolated() {
625
                return interpolated;
626
        }
627

    
628
        /**
629
         * Definir si la paleta tendra los valores interpolados o no
630
         * @param interpolated
631
         */
632
        public void setInterpolated(boolean interpolated) {
633
                this.interpolated = interpolated;
634
                applyPalette(colorItems);
635
        }
636

    
637
        /*
638
         * (non-Javadoc)
639
         * @see java.lang.Object#hashCode()
640
         */
641
        public int hashCode() {
642
                final int PRIME = 31;
643
                int result = 1;
644
                result = PRIME * result + ((colorItems == null) ? 0 : colorItems.hashCode());
645
                result = PRIME * result + error;
646
                result = PRIME * result + ((filePath == null) ? 0 : filePath.hashCode());
647
                result = PRIME * result + (interpolated ? 1231 : 1237);
648
                result = PRIME * result + ((name == null) ? 0 : name.hashCode());
649
                result = PRIME * result + ColorTable.hashCode(nameClass);
650
                result = PRIME * result + ColorTable.hashCode(paletteByBand);
651
                result = PRIME * result + ColorTable.hashCode(range);
652
                result = PRIME * result + ((transparencyRange == null) ? 0 : transparencyRange.hashCode());
653
                return result;
654
        }
655

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

    
669
                if ( ((colorItems == null) && (other.colorItems != null)) ||
670
                                ((colorItems != null) && (other.colorItems == null)) )
671
                        return false;
672

    
673
                if (colorItems != null) {
674
                        if (colorItems.size() != other.colorItems.size())
675
                                return false;
676
                        for (int i = 0; i < colorItems.size(); i++) {
677
                                if (!((ColorItem) colorItems.get(i)).equals(other.colorItems.get(i)))
678
                                        return false;
679
                        }
680
                }
681

    
682
                if (error != other.error)
683
                        return false;
684
                if (filePath == null) {
685
                        if (other.filePath != null)
686
                                return false;
687
                } else if (!filePath.equals(other.filePath))
688
                        return false;
689
                if (name == null) {
690
                        if (other.name != null)
691
                                return false;
692
                } else if (!name.equals(other.name))
693
                        return false;
694
                if (!Arrays.equals(nameClass, other.nameClass))
695
                        return false;
696

    
697
                if ( ((paletteByBand == null) && (other.paletteByBand != null)) ||
698
                                ((paletteByBand != null) && (other.paletteByBand == null)) )
699
                        return false;
700

    
701
                if (paletteByBand != null) {
702
                        for (int i = 0; i < paletteByBand.length; i++) {
703
                                for (int j = 0; j < paletteByBand[i].length; j++) {
704
                                        if (paletteByBand[i][j] != other.paletteByBand[i][j])
705
                                                return false;
706
                                }
707
                        }
708
                }
709

    
710
                if (!Arrays.equals(range, other.range))
711
                        return false;
712

    
713
                if ( ((colorItems == null) && (other.colorItems != null)) ||
714
                                ((colorItems != null) && (other.colorItems == null)) )
715
                        return false;
716

    
717
                if (transparencyRange != null) {
718
                        if (transparencyRange.size() != other.transparencyRange.size())
719
                                return false;
720
                        for (int i = 0; i < transparencyRange.size(); i++) {
721
                                if (!((TransparencyRange) transparencyRange.get(i)).equals(other.transparencyRange.get(i)))
722
                                        return false;
723
                        }
724
                }
725

    
726
                return true;
727
        }
728
}