Statistics
| Revision:

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

History | View | Annotate | Download (19 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
                ColorItem c1 = (ColorItem) getColorItems().get(first);
188
                ColorItem c2 = (ColorItem) getColorItems().get(last);
189
                for (int i = (first + 1); i < last; i++) {
190
                        if (!isCorrectColor(c1, c2, (ColorItem) getColorItems().get(i)))
191
                                return false;
192
                }
193
                return true;
194
        }
195

    
196
        public void compressPalette() {
197
                compressPalette(colorItems);
198
        }
199

    
200
        public boolean isCompressible() {
201
                ArrayList cloneList = (ArrayList) getColorItems().clone();
202
                compressPalette(cloneList);
203
                return (cloneList.size() != getColorItems().size());
204
        }
205

    
206
        private void compressPalette(ArrayList colorItems) {
207
                int size = -1;
208

    
209
                while (size != colorItems.size()) {
210
                        int init = 0;
211
                        int posMax = 2;
212

    
213
                        size = colorItems.size();
214
                        while (init < colorItems.size()) {
215
                                if ((posMax < colorItems.size()) && canDelete(init, posMax)) {
216
                                        posMax++;
217
                                        continue;
218
                                }
219
                                if ((init + 2) < posMax) {
220
                                        if (canDelete(init, posMax - 1))
221
                                                for (int i = (posMax - 2); i > init; i--)
222
                                                        if (i < colorItems.size())
223
                                                                colorItems.remove(i);
224
                                }
225
                                init++;
226
                                posMax = init + 2;
227
                        }
228
                }
229
        }
230

    
231
        /**
232
         * Crea una paleta a partir de un objeto GdalColorTable. Esto es necesario
233
         * para los ficheros que tienen una paleta asignada, como los gif, y que son
234
         * tratados por Gdal. Se pasa la tabla de color le?da desde gdal y se crea
235
         * directamente un objeto Palette.
236
         * @param table
237
         */
238
        public void createPaletteFromGdalColorTable(GdalColorTable table) {
239
                try {
240
                        colorItems = new ArrayList();
241
                        for (int iEntry = 0; iEntry < table.getColorEntryCount(); iEntry++) {
242
                                GdalColorEntry entry = table.getColorEntryAsRGB(iEntry);
243

    
244
                                ColorItem colorItem = new ColorItem();
245
                                colorItem.setNameClass("");
246
                                colorItem.setValue(iEntry);
247
                                colorItem.setColor(new Color(        (int) (entry.c1 & 0xff),
248
                                                                                                                                                        (int) (entry.c2 & 0xff),
249
                                                                                                                                                        (int) (entry.c3 & 0xff),
250
                                                                                                                                                        (int) (entry.c4 & 0xff)));
251

    
252
                                colorItems.add(colorItem);
253
                        }
254
                } catch (GdalException ex) {
255
                        // No se crea la paleta
256
                }
257
                sortPalette(colorItems);
258
                //compressPalette();
259
                applyPalette(colorItems);
260
        }
261

    
262
        /**
263
         * Obtiene la tabla de color por banda
264
         * @return Paleta
265
         */
266
        public byte[][] getColorTableByBand() {
267
                return paletteByBand;
268
        }
269

    
270

    
271
        /**
272
         * Asigna una paleta
273
         * @param palette Paleta
274
         */
275
        public void setColorTable(int[] palette) {
276
                paletteByBand = new byte[palette.length][3];
277
                for (int i = 0; i < palette.length; i++) {
278
                        paletteByBand[i][0] = (byte)((palette[i] & 0x00ff0000) >> 16);
279
                        paletteByBand[i][1] = (byte)((palette[i] & 0x0000ff00) >> 8);
280
                        paletteByBand[i][2] = (byte)(palette[i] & 0x000000ff);
281
                }
282
        }
283

    
284
        /**
285
         * Obtiene los nombres de las clases de la paleta
286
         * @return Array de cadenas. Cada una corresponde con un nombre de clase
287
         * que corresponde a cada rango de tipos.
288
         */
289
        public String[] getNameClass() {
290
                return nameClass;
291
        }
292

    
293
        /**
294
         * Asigna los nombres de las clases de la paleta
295
         * @param names Array de cadenas. Cada una corresponde con un nombre de clase
296
         * que corresponde a cada rango de tipos.
297
         */
298
        public void setNameClass(String[] names) {
299
                nameClass = names;
300
        }
301

    
302
        /**
303
         * Obtiene la ruta del fichero al que va asociada la paleta.
304
         * @return Ruta del fichero al que va asociada la paleta.
305
         */
306
        public String getFilePath() {
307
                return filePath;
308
        }
309

    
310
        /**
311
         * Asigna la ruta del fichero al que va asociada la paleta.
312
         * @param Ruta del fichero al que va asociada la paleta.
313
         */
314
        public void setFilePath(String filePath) {
315
                this.filePath = filePath;
316
        }
317

    
318
        /*
319
         * (non-Javadoc)
320
         * @see java.lang.Object#clone()
321
         */
322
        public Object clone() {
323
                ColorTable clone = null;
324
                try {
325
                        clone = (ColorTable) super.clone();
326
                } catch (CloneNotSupportedException e) {
327
                }
328

    
329
                if (colorItems != null) {
330
                        clone.colorItems = new ArrayList();
331
                        for (int i = 0; i < colorItems.size(); i++) {
332
                                clone.colorItems.add(((ColorItem) colorItems.get(i)).clone());
333
                        }
334
                }
335
                
336
                clone.interpolated = interpolated;
337

    
338
                if (filePath != null)
339
                        clone.filePath = new String(filePath);
340

    
341
                if (name != null)
342
                        clone.name = new String(name);
343

    
344
                if (nameClass != null) {
345
                        clone.nameClass = new String[nameClass.length];
346
                        for (int i = 0; i < nameClass.length; i++)
347
                                clone.nameClass[i] = new String(nameClass[i]);
348
                }
349

    
350
                if (paletteByBand != null) {
351
                        clone.paletteByBand = (byte[][]) paletteByBand.clone();
352
                        for (int i = 0; i < paletteByBand.length; i++)
353
                                clone.paletteByBand[i] = (byte[]) paletteByBand[i].clone();
354
                }
355

    
356
                if (range != null)
357
                        clone.range = (double[]) range.clone();
358

    
359
                return clone;
360
        }
361

    
362
        /**
363
         * Devuelve un color de interpolacion entre dos colores
364
         * @param value
365
         * @param pos
366
         * @return
367
         */
368
        private Color interpolatedColor(double value, int pos) {
369
                if (colorItems.size() <= 0)
370
                        return Color.black;
371

    
372
                if ((pos + 1) == colorItems.size())
373
                        return ((ColorItem) colorItems.get(pos)).getColor();
374

    
375
                if (value <= ((ColorItem) colorItems.get(0)).getValue())
376
                        return ((ColorItem) colorItems.get(0)).getColor();
377

    
378
                ColorItem item1 = (ColorItem) colorItems.get(pos);
379
                ColorItem item2 = (ColorItem) colorItems.get(pos + 1);
380

    
381
                double percValue = ((value - item1.getValue()) * 100) / (item2.getValue() - item1.getValue());
382

    
383
                Color halfColor = new Color(
384
                                (item2.getColor().getRed() + item1.getColor().getRed()) >> 1,
385
                                (item2.getColor().getGreen() + item1.getColor().getGreen()) >> 1,
386
                                (item2.getColor().getBlue() + item1.getColor().getBlue()) >> 1,
387
                                (item2.getColor().getAlpha() + item1.getColor().getAlpha()) >> 1);
388

    
389
                Color color1, color2;
390
                double perc1, perc2;
391

    
392
                if (percValue > item2.getInterpolated()) {
393
                        color1 = halfColor;
394
                        color2 = item2.getColor();
395
                        perc1 = item2.getInterpolated();
396
                        perc2 = 100;
397
                } else {
398
                        color1 = item1.getColor();
399
                        color2 = halfColor;
400
                        perc1 = 0;
401
                        perc2 = item2.getInterpolated();
402
                }
403

    
404
                double percNew = (percValue - perc1) / (perc2 - perc1);
405

    
406
                Color newColor = new Color(
407
                                (int) (color1.getRed() + ((color2.getRed() - color1.getRed()) * percNew)) & 0xff,
408
                                (int) (color1.getGreen() + ((color2.getGreen() - color1.getGreen()) * percNew)) & 0xff,
409
                                (int) (color1.getBlue() + ((color2.getBlue() - color1.getBlue()) * percNew)) & 0xff,
410
                                (int) (color1.getAlpha() + ((color2.getAlpha() - color1.getAlpha()) * percNew)) & 0xff);
411

    
412

    
413
                return newColor;
414
        }
415

    
416
        /*
417
         * TODO: RENDIMIENTO: Incluir una heuristica que dado un valor se compare con
418
         * el valor de la mitad de la tabla y si es menor se empieza a recorrer desde
419
         * el principio sino se empieza a recorrer desde la mitad de la tabla hasta
420
         * abajo. Esto hace que se reduzca la tabla a la mitad de valores haciendo
421
         * solo una comparaci?n.
422
         */
423
        /**
424
         * Obtiene el valor RGB para un clave entera pasada por par?metro
425
         * @param value clave de la cual se quiere obtener el valor RGB de la paleta
426
         * @return valor RGB
427
         */
428
        public byte[] getRGBAByBand(double value) {
429
                for (int i = 1; i <= range.length; i++) {
430
                        if (i < range.length) {
431
                                if (value < range[i])
432
                                        return paletteByBand[i - 1];
433
                        } else {
434
                                return paletteByBand[i - 1];
435
                        }
436
                }
437
                return new byte[4];
438
        }
439

    
440
        /*
441
         * TODO: Usar el m?todo Quicksort para ordenar
442
         */
443
        /**
444
         * Ordena el ColorItems de manera ascendente. De momento se usa el m?todo de
445
         * ordenaci?n por burbuja.
446
         */
447
        private void sortPalette(ArrayList colorItems) {
448
                for (int i = 0; i < colorItems.size(); i++) {
449
                        for (int j = i + 1; j < colorItems.size(); j++) {
450
                                if (((ColorItem) colorItems.get(j)).getValue() < ((ColorItem) colorItems.get(i)).getValue()) {
451
                                        Object aux = colorItems.get(i);
452
                                        colorItems.set(i, colorItems.get(j));
453
                                        colorItems.set(j, aux);
454
                                }
455
                        }
456
                }
457
        }
458

    
459
        /**
460
         * Genera una paleta intermedia para acelerar los calculos.
461
         */
462
        private void applyPalette(ArrayList colorItems) {
463
                ArrayList arrayColors = new ArrayList();
464

    
465
                paletteByBand = new byte[0][3];
466
                range = new double[0];
467
                nameClass = new String[0];
468

    
469
                if (colorItems.size()==0)
470
                        return;
471

    
472
                // Nos preparamos para hacer las particiones, sabiendo el minimo y maximo
473
                double min = ((ColorItem) colorItems.get(0)).getValue();
474
                double max = ((ColorItem) colorItems.get(colorItems.size() - 1)).getValue();
475

    
476
                if (min > max) {
477
                        double aux = max;
478
                        max = min;
479
                        min = aux;
480
                }
481

    
482
                Color color = Color.white;
483
                Color colorOld = null;
484

    
485
                // Hacemos las particiones, metiendo cada item calculado en un array
486
                int defaultColors = RasterLibrary.defaultNumberOfColors;
487
                for (int i = 0; i < defaultColors; i++) {
488
                        double value = min + ((i * (max - min)) / (defaultColors - 1));
489
                        int pos = 0;
490
                        for (int j = 1; j <= colorItems.size(); j++) {
491
                                if (j < colorItems.size()) {
492
                                        if (value < ((ColorItem) colorItems.get(j)).getValue()) {
493
                                                pos = j - 1;
494
                                                break;
495
                                        }
496
                                } else {
497
                                        pos = j - 1;
498
                                        break;
499
                                }
500
                        }
501

    
502
                        // Calculamos el color que corresponde, tanto interpolado como no
503
                        if (interpolated) {
504
                                color = interpolatedColor(value, pos);
505
                        } else {
506
                                if ((pos + 1) < colorItems.size()) {
507
                                        double min2 = ((ColorItem) colorItems.get(pos)).getValue();
508
                                        double max2 = ((ColorItem) colorItems.get(pos + 1)).getValue();
509
                                        if ((min2 + ((max2 - min2) * ((ColorItem) colorItems.get(pos + 1)).getInterpolated() / 100)) < value)
510
                                                pos++;
511
                                }
512
                                color = ((ColorItem) colorItems.get(pos)).getColor();
513
                        }
514

    
515
                        if (!isEqualColor(color, colorOld, 0)) {
516
                                ColorItem colorItem = new ColorItem();
517
                                colorItem.setNameClass("");
518
                                colorItem.setValue(value);
519
                                colorItem.setColor(color);
520
                                arrayColors.add(colorItem);
521
                        }
522

    
523
                        colorOld = color;
524
                }
525

    
526
                // Una vez tenemos una paleta de 256 colores o inferior, rellenamos
527
                // los siguientes valores para hacer busquedas rapidas.
528

    
529
                paletteByBand = new byte[arrayColors.size()][4];
530
                range = new double[arrayColors.size()];
531
                nameClass = new String[arrayColors.size()];
532

    
533
                for (int i = 0; i < arrayColors.size(); i++) {
534
                        paletteByBand[i][0] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getRed();
535
                        paletteByBand[i][1] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getGreen();
536
                        paletteByBand[i][2] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getBlue();
537
                        paletteByBand[i][3] = (byte) ((ColorItem) arrayColors.get(i)).getColor().getAlpha();
538
                        range[i] = ((ColorItem) arrayColors.get(i)).getValue();
539
                        nameClass[i] = ((ColorItem) arrayColors.get(i)).getNameClass();
540
                }
541
        }
542

    
543
        public double[] getRange() {
544
                return range;
545
        }
546

    
547
        public void setRange(double[] range) {
548
                this.range = range;
549
        }
550

    
551
        /**
552
         * Devuelve un ArrayList con cada ColorItem de la tabla de color
553
         * @return
554
         */
555
        public ArrayList getColorItems() {
556
                return colorItems;
557
        }
558

    
559
        /**
560
         * Nos indica si la paleta la ha generado con valores interpolados o no.
561
         * @return
562
         */
563
        public boolean isInterpolated() {
564
                return interpolated;
565
        }
566

    
567
        /**
568
         * Definir si la paleta tendra los valores interpolados o no
569
         * @param interpolated
570
         */
571
        public void setInterpolated(boolean interpolated) {
572
                this.interpolated = interpolated;
573
                applyPalette(colorItems);
574
        }
575

    
576
        /*
577
         * (non-Javadoc)
578
         * @see java.lang.Object#hashCode()
579
         */
580
        public int hashCode() {
581
                final int PRIME = 31;
582
                int result = 1;
583
                result = PRIME * result + ((colorItems == null) ? 0 : colorItems.hashCode());
584
                result = PRIME * result + errorColor;
585
                result = PRIME * result + ((filePath == null) ? 0 : filePath.hashCode());
586
                result = PRIME * result + (interpolated ? 1231 : 1237);
587
                result = PRIME * result + ((name == null) ? 0 : name.hashCode());
588
                result = PRIME * result + ColorTable.hashCode(nameClass);
589
                result = PRIME * result + ColorTable.hashCode(paletteByBand);
590
                result = PRIME * result + ColorTable.hashCode(range);
591
                return result;
592
        }
593

    
594
        private static int hashCode(Object[] array) {
595
                final int PRIME = 31;
596
                if (array == null)
597
                        return 0;
598
                int result = 1;
599
                for (int index = 0; index < array.length; index++) {
600
                        result = PRIME * result + (array[index] == null ? 0 : array[index].hashCode());
601
                }
602
                return result;
603
        }
604

    
605
        private static int hashCode(double[] array) {
606
                final int PRIME = 31;
607
                if (array == null)
608
                        return 0;
609
                int result = 1;
610
                for (int index = 0; index < array.length; index++) {
611
                        long temp = Double.doubleToLongBits(array[index]);
612
                        result = PRIME * result + (int) (temp ^ (temp >>> 32));
613
                }
614
                return result;
615
        }
616
        
617
        /*
618
         * (non-Javadoc)
619
         * @see java.lang.Object#equals(java.lang.Object)
620
         */
621
        public boolean equals(Object obj) {
622
                if (this == obj)
623
                        return true;
624
                if (obj == null)
625
                        return false;
626
                if (getClass() != obj.getClass())
627
                        return false;
628
                final ColorTable other = (ColorTable) obj;
629

    
630
                if ( ((colorItems == null) && (other.colorItems != null)) ||
631
                                ((colorItems != null) && (other.colorItems == null)) )
632
                        return false;
633

    
634
                if (colorItems != null) {
635
                        if (colorItems.size() != other.colorItems.size())
636
                                return false;
637
                        for (int i = 0; i < colorItems.size(); i++) {
638
                                if (!((ColorItem) colorItems.get(i)).equals(other.colorItems.get(i)))
639
                                        return false;
640
                        }
641
                }
642

    
643
                if (filePath == null) {
644
                        if (other.filePath != null)
645
                                return false;
646
                } else if (!filePath.equals(other.filePath))
647
                        return false;
648
                if (name == null) {
649
                        if (other.name != null)
650
                                return false;
651
                } else if (!name.equals(other.name))
652
                        return false;
653

    
654
                if (nameClass != null) {
655
                        if (nameClass.length != other.nameClass.length)
656
                                return false;
657

    
658
                        for (int i = 0; i < nameClass.length; i++) {
659
                                if (!nameClass[i].equals(other.nameClass[i]))
660
                                        return false;
661
                        }
662
                }
663

    
664
                if ( ((paletteByBand == null) && (other.paletteByBand != null)) ||
665
                                ((paletteByBand != null) && (other.paletteByBand == null)) )
666
                        return false;
667

    
668
                if (paletteByBand != null) {
669
                        for (int i = 0; i < paletteByBand.length; i++) {
670
                                for (int j = 0; j < paletteByBand[i].length; j++) {
671
                                        if (paletteByBand[i][j] != other.paletteByBand[i][j])
672
                                                return false;
673
                                }
674
                        }
675
                }
676

    
677
                if (!Arrays.equals(range, other.range))
678
                        return false;
679

    
680
                if ( ((colorItems == null) && (other.colorItems != null)) ||
681
                                ((colorItems != null) && (other.colorItems == null)) )
682
                        return false;
683

    
684
                return true;
685
        }
686
}