Statistics
| Revision:

gvsig-raster / org.gvsig.raster / branches / org.gvsig.raster.2.4 / org.gvsig.raster / org.gvsig.raster.lib / org.gvsig.raster.lib.legend / org.gvsig.raster.lib.legend.impl / src / main / java / org / gvsig / raster / lib / legend / impl / DefaultRasterLegend.java @ 6900

History | View | Annotate | Download (50.2 KB)

1
package org.gvsig.raster.lib.legend.impl;
2

    
3
import java.awt.Graphics;
4
import java.awt.Image;
5
import java.awt.geom.AffineTransform;
6
import java.awt.geom.NoninvertibleTransformException;
7
import java.awt.image.BufferedImage;
8
import java.util.ArrayList;
9
import java.util.List;
10

    
11
import org.cresques.cts.ICoordTrans;
12
import org.slf4j.Logger;
13
import org.slf4j.LoggerFactory;
14

    
15
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
16
import org.gvsig.fmap.geom.GeometryLocator;
17
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
18
import org.gvsig.fmap.geom.exception.CreateGeometryException;
19
import org.gvsig.fmap.geom.primitive.Envelope;
20
import org.gvsig.fmap.geom.primitive.Point;
21
import org.gvsig.fmap.mapcontext.ViewPort;
22
import org.gvsig.fmap.mapcontext.raster.api.legend.ChangeColorInterpretationEvent;
23
import org.gvsig.fmap.mapcontext.raster.api.legend.ChangePaletteBandEvent;
24
import org.gvsig.fmap.mapcontext.raster.api.legend.ChangePaletteEvent;
25
import org.gvsig.fmap.mapcontext.raster.api.legend.RasterLegendEvent;
26
import org.gvsig.fmap.mapcontext.raster.api.legend.listeners.RasterLegendChangedListener;
27
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
28
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
29
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
30
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
31
import org.gvsig.raster.lib.buffer.api.Band;
32
import org.gvsig.raster.lib.buffer.api.Buffer;
33
import org.gvsig.raster.lib.buffer.api.FilterList;
34
import org.gvsig.raster.lib.buffer.api.NoData;
35
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
36
import org.gvsig.raster.lib.legend.api.RasterLegend;
37
import org.gvsig.raster.lib.legend.api.Transparency;
38
import org.gvsig.raster.lib.legend.api.colorinterpretation.ColorInterpretation;
39
import org.gvsig.raster.lib.legend.api.colorinterpretation.ColorInterpretationNotification;
40
import org.gvsig.raster.lib.legend.api.colortable.ColorTable;
41
import org.gvsig.tools.ToolsLocator;
42
import org.gvsig.tools.dispose.DisposeUtils;
43
import org.gvsig.tools.dynobject.DynStruct;
44
import org.gvsig.tools.locator.LocatorException;
45
import org.gvsig.tools.observer.Observable;
46
import org.gvsig.tools.persistence.PersistenceManager;
47
import org.gvsig.tools.persistence.PersistentState;
48
import org.gvsig.tools.persistence.exception.PersistenceException;
49
import org.gvsig.tools.swing.api.ToolsSwingLocator;
50
import org.gvsig.tools.task.SimpleTaskStatus;
51
import org.gvsig.tools.task.TaskStatusManager;
52

    
53
/**
54
 * Default implementation of {@link RasterLegend}. This object can draw buffers
55
 * with a {@link ColorInterpretation}, {@link ColorTable} and {@link FilterList}
56
 *
57
 *
58
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
59
 *
60
 */
61
public class DefaultRasterLegend implements RasterLegend {
62

    
63
    private static final Logger LOG = LoggerFactory.getLogger(DefaultRasterLegend.class);
64

    
65
    private ColorInterpretation colorInterpretation;
66
    private Transparency transparency;
67
    private FilterList filters;
68
    private boolean transparentNoData;
69

    
70
    private List<RasterLegendChangedListener> listeners =
71
        new ArrayList<RasterLegendChangedListener>();
72

    
73
    /**
74
     * Persistence definition name
75
     */
76
    public static final String PERSISTENT_NAME = "RasterLegendPersistence";
77
    /**
78
     * Description of persistence definition
79
     */
80
    public static final String PERSISTENT_DESCRIPTION = "Persistence definition of raster legend";
81

    
82
    private final static String COLOR_INTERPRETATION_PERSISTENCE_FIELD = "colorInterpretation";
83
    private final static String FILTERS_PERSISTENCE_FIELD = "filters";
84

    
85
    /**
86
     * Empty constructor
87
     */
88
    public DefaultRasterLegend() {
89

    
90
    }
91

    
92
    /**
93
     * Default {@link RasterLegend} constructor
94
     *
95
     * @param colorInterpretation
96
     *            Color interpretation of legend
97
     */
98
    public DefaultRasterLegend(ColorInterpretation colorInterpretation) {
99
        setColorInterpretation(colorInterpretation);
100
    }
101

    
102
    /**
103
     * Default {@link RasterLegend} constructor
104
     *
105
     * @param colorTable
106
     *            Color table of legend
107
     * @param colorInterpretation
108
     *            Color interpretation of legend
109
     * @param transparency
110
     *            Transparency of legend
111
     * @param filters
112
     *            Filters of legend
113
     */
114
    public DefaultRasterLegend(ColorInterpretation colorInterpretation,
115
        Transparency transparency, FilterList filters) {
116
        this(colorInterpretation);
117
        this.transparency = transparency;
118
        this.filters = filters;
119
    }
120

    
121
    @Override
122
    public void draw(Graphics graphics, Buffer buffer, ViewPort viewPort,
123
        SimpleTaskStatus taskStatus) {
124

    
125
        boolean isMyTask = false;
126
        if (taskStatus == null) {
127
            TaskStatusManager taskStatusManager = ToolsLocator.getTaskStatusManager();
128
            taskStatus =
129
                taskStatusManager.createDefaultSimpleTaskStatus("_drawing_buffer_XxellipsisxX");
130
            taskStatus.setAutoremove(true);
131
            taskStatus.add();
132
            isMyTask = true;
133
        } else {
134
            taskStatus.push();
135
        }
136

    
137
        taskStatus.setIndeterminate();
138

    
139
        if (this.colorInterpretation == null || !this.colorInterpretation.hasInterpretation()
140
            || this.colorInterpretation.isUndefined()) {
141
            taskStatus.abort();
142
            throw new IllegalStateException(
143
                "To draw buffer, raster legend has to have a color interpretation");
144
        }
145

    
146
        // Check if viewport projection is the same as buffer projection
147
        Buffer clip = null;
148
        Buffer interpolated = null;
149
        Buffer converted = null;
150
        Buffer interpolated2 = null;
151
        Buffer bufferToDraw = buffer;
152
        try {
153
            if (bufferToDraw != null && bufferToDraw.getColumns()>0 && bufferToDraw.getRows()>0) {
154

    
155
                if (!viewPort.getProjection().equals(bufferToDraw.getProjection())) {
156

    
157
                    // Convert extension to check if envelopes intersect
158
                    ICoordTrans coordTrans = viewPort.getProjection().getCT(bufferToDraw.getProjection());
159
                    ICoordTrans invertedCoordTrans = bufferToDraw.getProjection().getCT(viewPort.getProjection());
160
                    Envelope convertedEnvelope = viewPort.getAdjustedEnvelope().convert(coordTrans);
161
                    double viewPortPixelSizeX = viewPort.getAdjustedEnvelope().getLength(0) / viewPort.getImageWidth();
162
                    double viewPortPixelSizeY = viewPort.getAdjustedEnvelope().getLength(1) / viewPort.getImageHeight();
163
                    if (!convertedEnvelope.intersects(bufferToDraw.getEnvelope())) {
164
                        return;
165
                    }
166
                    try {
167
                        // Clip buffer with doubled converted envelope
168
                        clip = bufferToDraw.clip(convertedEnvelope);
169
                        Envelope bufferEnvelopeInViewPortCoords = clip.getEnvelope().convert(invertedCoordTrans);
170

    
171
                        double widthPixel = bufferEnvelopeInViewPortCoords.getLength(0) / viewPortPixelSizeX;
172
                        double heightPixel = bufferEnvelopeInViewPortCoords.getLength(1) / viewPortPixelSizeY;
173

    
174
                        interpolated =
175
                            clip.createInterpolated((int) Math.floor(heightPixel), (int) Math.floor(widthPixel),
176
                                Buffer.INTERPOLATION_NearestNeighbour, taskStatus);
177
                        // Convert interpolated clipped buffer
178
                        converted = interpolated.convert(invertedCoordTrans, taskStatus);
179

    
180
                        widthPixel = getWidthPixel(converted.getEnvelope(), viewPortPixelSizeX);
181
                        heightPixel = getHeightPixel(converted.getEnvelope(), viewPortPixelSizeY);
182

    
183
                        interpolated2 =
184
                            converted.createInterpolated((int) Math.floor(heightPixel), (int) Math.floor(widthPixel),
185
                                Buffer.INTERPOLATION_NearestNeighbour, taskStatus);
186

    
187
                        bufferToDraw = interpolated2;
188

    
189
                    } catch (BufferException | LocatorException | CreateEnvelopeException e) {
190
                        LOG.warn("Buffer can not be clipped, converted or interpolated", e);
191
                        taskStatus.abort();
192
                        return;
193
                    }
194
                } else if (viewPort.getAdjustedEnvelope().intersects(bufferToDraw.getEnvelope())) {
195

    
196
                    double widthPixel = 0;
197
                    double heightPixel = 0;
198
                    try {
199
                        // Clip and interpolate buffer with view port envelope
200
                        if (!bufferToDraw.getEnvelope().equals(viewPort.getAdjustedEnvelope())) {
201
                            clip = bufferToDraw.clip(viewPort.getAdjustedEnvelope());
202
                            bufferToDraw = clip;
203
                        }
204
                        widthPixel =
205
                            getWidthPixel(bufferToDraw.getEnvelope(), viewPort.getAdjustedEnvelope().getLength(0)
206
                                / viewPort.getImageWidth());
207
                        heightPixel =
208
                            getHeightPixel(bufferToDraw.getEnvelope(), viewPort.getAdjustedEnvelope().getLength(1)
209
                                / viewPort.getImageHeight());
210

    
211
                        interpolated =
212
                            bufferToDraw.createInterpolated((int) Math.floor(heightPixel),
213
                                (int) Math.floor(widthPixel), Buffer.INTERPOLATION_NearestNeighbour, taskStatus);
214
                        bufferToDraw = interpolated;
215
                    } catch (BufferException e) {
216
                        LOG.warn(
217
                            "Buffer can not be interpolated with [rows: {} , columns: {}, method: {}]",
218
                            new String[] { String.valueOf((int) Math.floor(heightPixel)),
219
                                String.valueOf((int) Math.floor(widthPixel)),
220
                                String.valueOf(Buffer.INTERPOLATION_NearestNeighbour) });
221
                        taskStatus.abort();
222
                        return;
223
                    }
224
                } else {
225
                    // Do nothing view port envelope does not intersect with
226
                    // buffer
227
                    return;
228
                }
229
            }
230

    
231
            if (bufferToDraw != null && bufferToDraw.getColumns()>0 && bufferToDraw.getRows()>0) {
232

    
233
                // Draw buffer
234
                Image image = null;
235
                if (this.colorInterpretation.isPalette()) {
236
                    // Draw buffer with table color
237
                    image = drawPaletteBuffer(graphics, bufferToDraw, colorInterpretation, transparency, filters);
238
                } else if (this.colorInterpretation.hasAnyGrayBand()) {
239
                    // Draw buffer with gray scale
240
                    image = drawGrayBuffer(graphics, bufferToDraw, transparency, filters);
241
//                } else if (this.colorInterpretation.isRGBA() || this.colorInterpretation.isRGB()
242
//                    || this.colorInterpretation.isBGR() || this.colorInterpretation.hasRGBBands()) {
243
                } else if (this.colorInterpretation.hasAnyRGBBand()) {
244
                    // Draw RGB, RGBA or BGR buffer without color table
245
                    image = drawRGBBuffer(graphics, bufferToDraw, colorInterpretation, transparency, filters);
246
                } else if (this.colorInterpretation.hasAnyHSLBand()) {
247
                    // Draw HSL buffer without color table
248
                    image = drawHSLBuffer(graphics, bufferToDraw, colorInterpretation, transparency, filters);
249
                } else if (this.colorInterpretation.hasAnyCMYKBand()) {
250
                    // Draw CMYK buffer without color table
251
                    image = drawCMYKBuffer(graphics, bufferToDraw, colorInterpretation, transparency, filters);
252
                } else if (this.colorInterpretation.hasAnyYCBCRBand()) {
253
                    // Draw YCBCR buffer without color table
254
                    image = drawYCBCRBuffer(graphics, bufferToDraw, colorInterpretation, transparency, filters);
255
                }
256

    
257
                // Calculate where image has to be drawn
258
                double x = bufferToDraw.getEnvelope().getMinimum(0);
259
                double y = bufferToDraw.getEnvelope().getMaximum(1);
260
                AffineTransform affineTransform =
261
                    calculateAffineTransform(viewPort.getAdjustedEnvelope(), viewPort.getImageWidth(),
262
                        viewPort.getImageHeight());
263

    
264
                Point point;
265
                try {
266
                    point = GeometryLocator.getGeometryManager().createPoint(x, y, SUBTYPES.GEOM2D);
267
                    point.transform(affineTransform.createInverse());
268
                    graphics.drawImage(image, (int) Math.floor(point.getX()), (int) Math.floor(point.getY()), null);
269
                } catch (CreateGeometryException | NoninvertibleTransformException e) {
270
                    LOG.warn("Can not calculate the point of buffer in viewport image", e);
271
                    taskStatus.abort();
272
                    return;
273
                }
274
            }
275
        } catch (LocatorException | CreateEnvelopeException e1) {
276
            LOG.warn("Can not calculate the envelope of buffer", e1);
277
            taskStatus.abort();
278
            return;
279
        } finally {
280
            if (clip != null) {
281
                DisposeUtils.dispose(clip);
282
                clip = null;
283
            }
284
            if (interpolated != null) {
285
                DisposeUtils.dispose(interpolated);
286
                interpolated = null;
287
            }
288
            if (converted != null) {
289
                DisposeUtils.dispose(converted);
290
                converted = null;
291
            }
292
            if (interpolated2 != null) {
293
                DisposeUtils.dispose(interpolated2);
294
                interpolated2 = null;
295
            }
296
            if (bufferToDraw == null && bufferToDraw != buffer) {
297
                DisposeUtils.dispose(bufferToDraw);
298
                bufferToDraw = null;
299
            }
300

    
301
            if (!isMyTask) {
302
                taskStatus.pop();
303
            }
304
        }
305
    }
306

    
307
    private AffineTransform calculateAffineTransform(Envelope envelope, double imageWidth,
308
        double imageHeight) {
309
        double pixelSizeX = envelope.getLength(0) / imageWidth;
310
        double rotationX = 0;
311
        double x = envelope.getMinimum(0);
312
        double rotationY = 0;
313
        double pixelSizeY = -envelope.getLength(1) / imageHeight;
314
        double y = envelope.getMaximum(1);
315
        return new AffineTransform(pixelSizeX, rotationY, rotationX, pixelSizeY, x, y);
316
    }
317

    
318
    private double getWidthPixel(Envelope envelope, double dist1pixel) {
319
        double widthEnvelope = envelope.getLength(0);
320
        return widthEnvelope / dist1pixel;
321
    }
322

    
323
    private double getHeightPixel(Envelope envelope, double dist1pixel) {
324
        double heightEnvelope = envelope.getLength(1);
325
        return heightEnvelope / dist1pixel;
326
    }
327

    
328

    
329

    
330
    private Image drawRGBBuffer(Graphics graphics, Buffer buffer,
331
        ColorInterpretation colorInterpretation, Transparency transparency, FilterList filters) {
332

    
333
        BufferedImage image = null;
334

    
335
        if (colorInterpretation.isRGB() || colorInterpretation.isRGBA() || colorInterpretation.hasAnyRGBBand()) {
336
            image = ToolsSwingLocator.getToolsSwingManager().createBufferedImage(buffer.getColumns(), buffer.getRows(),
337
                    BufferedImage.TYPE_INT_ARGB);
338
        } else if (colorInterpretation.isBGR()) {
339
            image = ToolsSwingLocator.getToolsSwingManager().createBufferedImage(buffer.getColumns(), buffer.getRows(),
340
                BufferedImage.TYPE_INT_BGR);
341
        }
342

    
343
        if (image == null) {
344
            throw new IllegalStateException(
345
                "Color interpretation is not RGB,RGBA or BGR and buffer was be drawn without color table");
346
        }
347

    
348
        int redBandIndex = colorInterpretation.getBand(ColorInterpretation.RED_BAND);
349
        int greenBandIndex = colorInterpretation.getBand(ColorInterpretation.GREEN_BAND);
350
        int blueBandIndex = colorInterpretation.getBand(ColorInterpretation.BLUE_BAND);
351

    
352
        Band redBand = null;
353
        if(redBandIndex>=0){
354
            redBand = buffer.getBand(redBandIndex);
355
        }
356
        Band greenBand = null;
357
        if(greenBandIndex>=0){
358
            greenBand = buffer.getBand(greenBandIndex);
359
        }
360
        Band blueBand = null;
361
        if(blueBandIndex>=0){
362
            blueBand = buffer.getBand(blueBandIndex);
363
        }
364
        Band alphaBand = null;
365
        if (colorInterpretation.hasAlphaBand()) {
366
            int alphaBandIndex =
367
                colorInterpretation.getBand(ColorInterpretation.ALPHA_BAND);
368
            alphaBand = buffer.getBand(alphaBandIndex);
369
        }
370
//        Statistics statistics = buffer.getStatistics(null);
371
//        double[] max = statistics.getMax(); //Para pruebas con el rango de cada banda
372
//        double[] min = statistics.getMin(); //Para pruebas con el rango de cada banda
373
//        double maximum = statistics.getMaximun();  //Para pruebas con el rango conjunto de todas las bandas
374
//        double minimum = statistics.getMinimun(); //Para pruebas con el rango conjunto de todas las bandas
375

    
376

    
377
        for (int i = 0; i < buffer.getRows(); i++) {
378
            for (int j = 0; j < buffer.getColumns(); j++) {
379
//                Number redValue = (Number) redBand.get(i, j);
380
//                Number greenValue = (Number) greenBand.get(i, j);
381
//                Number blueValue = (Number) blueBand.get(i, j);
382

    
383
                /*FIXME:
384
                 * Aqu? necesitamos pasar los valores originales de la capa al rango de valores del tipo byte.
385
                 * Para hacer esto tendr?amos varias opciones:
386
                 *
387
                 * 1.- Como hace el raster viejo, una conversi?n lineal entre el rango de valores de la capa [MIN, MAX]
388
                 *     y el rango de valores de tipo byte [0 - 255] para lo cual necesitar?amos llamar aqu? a las estad?sticas.
389
                 *
390
                 * 2.- Una conversi?n lineal entre el rango de valores del tipo del Number concreto (p. ej. Short [-32768 - 32767],
391
                 *     Int [-2^31 - 2^31-1], etc...) y el rango de valores de tipo byte [0 - 255], pero cuando los valores
392
                 *     fueran relativamente peque?os se concentrar?an todos en el 0 y la capa saldr?a completamente negra.
393
                 *
394
                 * 3.- Una conversi?n logaritmica entre el rango de valores del tipo del Number concreto (p. ej. Short [-32768 - 32767],
395
                 *     Int [-2^31 - 2^31-1], etc...) y el rango de valores de tipo byte [0 - 255], esto evitar?a la
396
                 *     concentraci?n de la mayor?a de valores en el 0.
397
                 *
398
                 * 4.- Y una mejor opci?n ser?a la conversi?n (linear o logaritm?tca, por decidir) entre el rango de valores
399
                 *     del "sensor" con el que se han tomado los datos y el rango de valores de tipo byte [0 - 255], pero
400
                 *     , por lo menos por ahora, no tenemos informaci?n sobre el sensor.
401
                 *
402
                 * Hago pruebas de las tres primeras opciones, comentarizando dos y dejando activa la otra,
403
                 * pero es algo a pensar con detenimiento.
404
                 */
405

    
406
                int alphaByteValue = 255;
407
                int redByteValue = 0;
408
                if(redBand!=null){
409
                    Number redValue = (Number) redBand.get(i, j);
410
                    NoData noData = redBand.getNoData();
411
                    if(noData != null){
412
                        if(redValue.equals(noData.getValue())){
413
                            alphaByteValue = 0;
414
                            redByteValue = 0;
415
                        } else {
416
                            alphaByteValue = 255;
417
                            redByteValue = logarithmicConversionToByteRange(redValue);
418
                        }
419
                    } else {
420
                        redByteValue = logarithmicConversionToByteRange(redValue);
421
                    }
422
//                byte redByteValue = logarithmicConversionToByte(redValue,max[redBandIndex]);
423
//                byte redByteValue = linearConversionToByte(redValue);
424
//                    redByteValue = proportionalConversionToByte(redValue, max[redBandIndex], min[redBandIndex]);
425
//                byte redByteValue = proportionalConversionToByte(redValue, maximum, minimum); //1
426
                }
427
                int greenByteValue = 0;
428
                if(greenBand!=null){
429
                    Number greenValue = (Number) greenBand.get(i, j);
430
                    NoData noData = greenBand.getNoData();
431
                    if(noData != null){
432
                        if(greenValue.equals(noData.getValue())){
433
                            alphaByteValue = 0;
434
                            greenByteValue = 0;
435
                        } else {
436
                            alphaByteValue = 255;
437
                            greenByteValue = logarithmicConversionToByteRange(greenValue);
438
                        }
439
                    } else {
440
                        greenByteValue = logarithmicConversionToByteRange(greenValue);
441
                    }
442
//                byte greenByteValue = logarithmicConversionToByte(greenValue,max[greenBandIndex]);
443
//                byte greenByteValue = linearConversionToByte(greenValue);
444
//                    greenByteValue = proportionalConversionToByte(greenValue, max[greenBandIndex], min[greenBandIndex]);
445
//                byte greenByteValue = proportionalConversionToByte(greenValue, maximum, minimum);
446
                }
447
                int blueByteValue = 0;
448
                if(blueBand!=null){
449
                    Number blueValue = (Number) blueBand.get(i, j);
450
                    NoData noData = blueBand.getNoData();
451
                    if(noData != null){
452
                        if(blueValue.equals(noData.getValue())){
453
                            alphaByteValue = 0;
454
                            blueByteValue = 0;
455
                        } else {
456
                            alphaByteValue = 255;
457
                            blueByteValue = logarithmicConversionToByteRange(blueValue);
458
                        }
459
                    } else {
460
                        blueByteValue = logarithmicConversionToByteRange(blueValue);
461
                    }
462

    
463

    
464
//                byte blueByteValue = logarithmicConversionToByte(blueValue,max[blueBandIndex]);
465
//                byte blueByteValue = linearConversionToByte(blueValue);
466
//                    blueByteValue = proportionalConversionToByte(blueValue, max[blueBandIndex], min[blueBandIndex]);
467
//                byte blueByteValue = proportionalConversionToByte(blueValue, maximum, minimum);
468
                }
469

    
470

    
471
                if (alphaByteValue!=0 && alphaBand != null) {
472
                    Number alphaValue = (Number) alphaBand.get(i, j);
473
                    int alphaBandIndex = colorInterpretation.getBand(ColorInterpretation.ALPHA_BAND);
474
//                    alphaByteValue = logarithmicConversionToByte(alphaValue);
475
                    NoData noData = alphaBand.getNoData();
476
                    if(noData != null){
477
                        if(alphaValue.equals(noData.getValue())){
478
                            alphaByteValue = 0;
479
                        } else {
480
                            alphaByteValue = logarithmicConversionToByteRange(alphaValue);
481
                        }
482
                    } else {
483
                        alphaByteValue = logarithmicConversionToByteRange(alphaValue);
484
                    }
485

    
486
//                    alphaByteValue = logarithmicConversionToByte(alphaValue,max[alphaBandIndex]);
487
//                    alphaByteValue = linearConversionToByte(alphaValue);
488
//                    alphaByteValue = proportionalConversionToByte(alphaValue, max[alphaBandIndex], min[alphaBandIndex]);
489
//                    alphaByteValue = proportionalConversionToByte(alphaValue, maximum, minimum);
490
//                    LOG.info("alphaValue = "+alphaValue+ " alphaByteValue = "+alphaByteValue);
491
                }
492

    
493
                if (alphaByteValue!=0 && transparency != null) {
494
                    // Apply defined transparency ranges
495

    
496
                    int newAlpha =
497
                        transparency.getTransparencyRangeAlpha(redByteValue,
498
                            greenByteValue, blueByteValue);
499
                    alphaByteValue = getNewAlpha(alphaByteValue, newAlpha);
500

    
501
                    // Apply general transparency
502
                    int transparencyValue = transparency.getAlpha();
503
                    alphaByteValue = getNewAlpha(alphaByteValue, transparencyValue);
504
                }
505

    
506
                if (filters != null) {
507
                    // TODO Apply filters
508
                }
509

    
510
                int intRGB = 0;
511
                if (colorInterpretation.hasAnyRGBBand()) {//colorInterpretation.isRGB() || colorInterpretation.isRGBA()) {
512
                    intRGB = (((byte)alphaByteValue & 0xFF) << 24) | // alpha
513
                        (((byte)redByteValue & 0xFF) << 16) | // red
514
                        (((byte)greenByteValue & 0xFF) << 8) | // green
515
                        (((byte)blueByteValue & 0xFF)); // blue String.format("%X", b)
516
//                    intRGB = ((alphaByteValue & 0xFF) << 24) | // alpha
517
//                        ((redByteValue & 0xFF) << 16) | // red
518
//                        ((greenByteValue & 0xFF) << 8) | // green
519
//                        ((blueByteValue & 0xFF) << 0); // blue String.format("%X", b)
520
                } else if (colorInterpretation.isBGR()) {
521
                    intRGB = (((byte)blueByteValue & 0xFF) << 16 | // blue
522
                        (((byte)greenByteValue & 0xFF) << 8) | // green
523
                        (((byte)redByteValue & 0xFF))); // red
524

    
525
                }
526
                image.setRGB(j, i, intRGB);
527
            }
528
        }
529
        return image;
530
    }
531

    
532
    /**
533
     * Conversi?n logaritmica de los valores del dominio de entrada a valores del dominio de BYTE
534
     * para poder ser representados en RGB.
535
     *
536
     * @param n
537
     * @return
538
     */
539
    private int logarithmicConversionToByteRange(Number n) {
540
        int b = 0;
541
        if (n instanceof Byte) {
542
            b = n.byteValue();
543
            if(b<0){
544
                b=256+b;
545
            }
546
        } else if (n instanceof Short) {
547
            // Because Math.log(Short.MAX_VALUE-Short.MIN_VALUE)/Math.log(256) = 2;
548
            b = (new Double(Math.round(Math.pow(n.shortValue(), 1d / 2d)))).intValue();
549
        } else if (n instanceof Integer) {
550
            // Because
551
            // Math.log(Integer.MAX_VALUE/256-Integer.MIN_VALUE/256)/Math.log(256) = 4;
552
            b = (new Double(Math.round(Math.pow(n.intValue(), 1d / 4d)))).intValue();
553
        } else if (n instanceof Float) {
554
            // Because Math.log(Float.MAX_VALUE-Float.MIN_VALUE)/Math.log(256) = 16;
555
            double root = 16d; // Math.log(Float.MAX_VALUE-Float.MIN_VALUE)/Math.log(256);
556
            b = (new Double(Math.round(Math.pow(n.floatValue(), 1d / root)))).intValue();
557
        } else if (n instanceof Double) {
558
            // Because Math.log(Double.MAX_VALUE-Double.MIN_VALUE)/Math.log(256) = 128;
559
            double root = 128d;
560
            b = (new Double(Math.round(Math.pow(n.doubleValue(), 1d / root)))).intValue();
561
        }
562
        return b;
563
    }
564

    
565
    /**
566
     * Conversi?n logaritmica de los valores del dominio de entrada a valores del dominio de BYTE
567
     * para poder ser representados en RGB.
568
     * Aplica un factor de correcci?n que depende de los valores de entrada.
569
     *
570
     * @param n
571
     * @param max
572
     * @return
573
     */
574
    private int logarithmicConversionToByteRange(Number n, double max) {
575
        int b = 0;
576
        if (n instanceof Byte) {
577
            b = n.byteValue();
578
            if(b<0){
579
                b=256+b;
580
            }
581
        } else if (n instanceof Short) {
582
            short value = n.shortValue();
583
            double factor = Short.MAX_VALUE / max;
584
            // Because Math.log(Short.MAX_VALUE-Short.MIN_VALUE)/Math.log(256) = 2;
585
            double root = 2d;
586
            b = (new Double(Math.round(Math.pow(value, 1d / root)*factor))).intValue();
587
        } else if (n instanceof Integer) {
588
            int value = n.intValue();
589
            double factor = Integer.MAX_VALUE / max;
590
            // Because Math.log(Integer.MAX_VALUE/256-Integer.MIN_VALUE/256)/Math.log(256) = 4;
591
            double root = 4d;
592
            b = (new Double(Math.round(Math.pow(value, 1d / root)*factor))).intValue();
593
        } else if (n instanceof Float) {
594
            float value = n.floatValue();
595
            double factor = Float.MAX_VALUE / max;
596
            // Because Math.log(Float.MAX_VALUE-Float.MIN_VALUE)/Math.log(256) = 16;
597
            double root = 16d;
598
            b = (new Double(Math.round(Math.pow(value, 1d / root)*factor))).intValue();
599
        } else if (n instanceof Double) {
600
            double value = n.doubleValue();
601
            double factor = Double.MAX_VALUE / max;
602
            // Because Math.log(Double.MAX_VALUE-Double.MIN_VALUE)/Math.log(256) = 128;
603
            double root = 128d;
604
            b = (new Double(Math.round(Math.pow(value, 1d / root)*factor))).intValue();
605
        }
606
        return b;
607
    }
608

    
609
    /**
610
     * Conversi?n lineal de los valores del dominio de entrada a valores del dominio de BYTE
611
     * para poder ser representados en RGB.
612
     *
613
     * @param n
614
     * @return
615
     */
616
    private int linearConversionToByteRange(Number n){
617
        int b=0;
618
        if(n instanceof Byte){
619
            b = n.byteValue();
620
            if(b<0){
621
                b=256+b;
622
            }
623

    
624
        } else if(n instanceof Short){
625
            // 65536/256 = 256
626
            b = (new Double(n.shortValue()/256)).intValue();
627
        } else if(n instanceof Integer){
628
            //  (Integer.MAX_VALUE-Integer.MIN_VALUE)/256 = 16777215
629
            b = (new Double(n.intValue()/16777215)).intValue();
630
        } else if(n instanceof Float){
631
            //  (Float.MAX_VALUE-Float.MIN_VALUE)/256 = 1.3292279E36
632
            b = (new Double(n.floatValue()/1.3292279E36)).intValue();
633
        } else if(n instanceof Double){
634
            //  (Double.MAX_VALUE-Double.MIN_VALUE)/256 = 7.022238808055921E305;
635
            b = (new Double(n.doubleValue()/7.022238808055921E305)).intValue();
636
        }
637
        return b;
638
    }
639

    
640
    /**
641
     * Conversi?n lineal de los valores de entrada a valores del dominio de BYTE
642
     * para poder ser representados en RGB.
643
     * Depende del rango de valores del buffer a representar.
644
     *
645
     * @param n
646
     * @param maximum
647
     * @param minimum
648
     * @return
649
     */
650
    private int proportionalConversionToByteRange(Number n, double maximum, double minimum){
651
        int b=0;
652
        double ratio = (maximum-minimum)/256;
653
        if(n instanceof Byte){
654
            b = n.byteValue();
655
            if(b<0){
656
                b=256+b;
657
            }
658
        } else if(n instanceof Short){
659
            // 65536/256 = 256
660
            b = (new Double((n.shortValue()-minimum)/ratio)).intValue();
661
        } else if(n instanceof Integer){
662
            //  (Integer.MAX_VALUE-Integer.MIN_VALUE)/256 = 16777215
663
            b = (new Double((n.intValue()-minimum)/ratio)).intValue();
664
        } else if(n instanceof Float){
665
            //  (Float.MAX_VALUE-Float.MIN_VALUE)/256 = 1.3292279E36
666
            b = (new Double((n.floatValue()-minimum)/ratio)).intValue();
667
        } else if(n instanceof Double){
668
            //  (Double.MAX_VALUE-Double.MIN_VALUE)/256 = 7.022238808055921E305;
669
            b = (new Double((n.doubleValue()-minimum)/ratio)).intValue();
670
        }
671
        return b;
672
    }
673

    
674

    
675
    private Image drawHSLBuffer(Graphics graphics, Buffer buffer,
676
        ColorInterpretation colorInterpretation,Transparency transparency,
677
        FilterList filters) {
678

    
679
        BufferedImage image = null;
680

    
681
        image = ToolsSwingLocator.getToolsSwingManager().createBufferedImage(buffer.getColumns(), buffer.getRows(),
682
            BufferedImage.TYPE_INT_ARGB);
683

    
684
        int hueBandIndex = colorInterpretation.getBand(ColorInterpretation.HUE_BAND);
685
        int saturationBandIndex = colorInterpretation.getBand(ColorInterpretation.SATURATION_BAND);
686
        int lightBandIndex = colorInterpretation.getBand(ColorInterpretation.LIGHTNESS_BAND);
687

    
688

    
689
        Band hueBand = buffer.getBand(hueBandIndex);
690
        Band saturationBand = buffer.getBand(saturationBandIndex);
691
        Band lightBand = buffer.getBand(lightBandIndex);
692

    
693

    
694
        for (int i = 0; i < buffer.getRows(); i++) {
695
            for (int j = 0; j < buffer.getColumns(); j++) {
696
                Number hueValue = (Number) hueBand.get(i, j);
697
                Number saturationValue = (Number) saturationBand.get(i, j);
698
                Number lightValue = (Number) lightBand.get(i, j);
699

    
700
                Number[] rgbaValues=ColorUtils.fromHSLtoRGBA(hueValue.floatValue(), saturationValue.floatValue(), lightValue.floatValue());
701

    
702
                Integer alphaValue =rgbaValues[3].intValue();
703
                if (transparency != null) {
704
                    // Apply defined transparency ranges
705

    
706
                    alphaValue = alphaValue.byteValue() & 0xFF;
707
                    int newAlpha =
708
                        transparency.getTransparencyRangeAlpha(rgbaValues[0].byteValue(),
709
                            rgbaValues[1].byteValue(), rgbaValues[2].byteValue());
710
                    alphaValue = getNewAlpha(alphaValue.intValue(), newAlpha);
711

    
712
                    // Apply general transparency
713
                    int transparencyValue = transparency.getAlpha();
714
                    alphaValue = getNewAlpha(alphaValue.intValue(), transparencyValue);
715
                }
716

    
717
                if (filters != null) {
718
                    // TODO Apply filters
719
                }
720

    
721
                int intRGB = 0;
722
                intRGB = ((alphaValue.byteValue() & 0xFF) << 24) | // alpha
723
                    ((rgbaValues[0].byteValue() & 0xFF) << 16) | // red
724
                    ((rgbaValues[1].byteValue() & 0xFF) << 8) | // green
725
                    ((rgbaValues[2].byteValue() & 0xFF) << 0); // blue
726
                image.setRGB(j, i, intRGB);
727
            }
728
        }
729
        return image;
730
    }
731

    
732
    private Image drawCMYKBuffer(Graphics graphics, Buffer buffer,
733
        ColorInterpretation colorInterpretation,Transparency transparency,
734
        FilterList filters) {
735

    
736
        BufferedImage image = null;
737

    
738
        image = ToolsSwingLocator.getToolsSwingManager().createBufferedImage(buffer.getColumns(), buffer.getRows(),
739
            BufferedImage.TYPE_INT_ARGB);
740

    
741
        int cyanBandIndex = colorInterpretation.getBand(ColorInterpretation.CYAN_BAND);
742
        int magentaBandIndex = colorInterpretation.getBand(ColorInterpretation.MAGENTA_BAND);
743
        int yellowBandIndex = colorInterpretation.getBand(ColorInterpretation.YELLOW_BAND);
744
        int blackBandIndex = colorInterpretation.getBand(ColorInterpretation.BLACK_BAND);
745

    
746

    
747
        Band cyanBand = buffer.getBand(cyanBandIndex);
748
        Band magentaBand = buffer.getBand(magentaBandIndex);
749
        Band yellowBand = buffer.getBand(yellowBandIndex);
750
        Band blackBand = buffer.getBand(blackBandIndex);
751

    
752
        for (int i = 0; i < buffer.getRows(); i++) {
753
            for (int j = 0; j < buffer.getColumns(); j++) {
754
                Number cyanValue = (Number) cyanBand.get(i, j);
755
                Number magentaValue = (Number) magentaBand.get(i, j);
756
                Number yellowValue = (Number) yellowBand.get(i, j);
757
                Number blackValue = (Number) blackBand.get(i, j);
758

    
759

    
760

    
761
                Number[] rgbValues=ColorUtils.fromCMYKtoRGB(
762
                    cyanValue.floatValue(),
763
                    magentaValue.floatValue(),
764
                    yellowValue.floatValue(),
765
                    blackValue.floatValue()
766
                    );
767

    
768
                Integer alphaValue =255;
769
                if (transparency != null) {
770
                    // Apply defined transparency ranges
771

    
772
                    alphaValue = alphaValue.byteValue() & 0xFF;
773
                    int newAlpha =
774
                        transparency.getTransparencyRangeAlpha(rgbValues[0].byteValue(),
775
                            rgbValues[1].byteValue(), rgbValues[2].byteValue());
776
                    alphaValue = getNewAlpha(alphaValue.intValue(), newAlpha);
777

    
778
                    // Apply general transparency
779
                    int transparencyValue = transparency.getAlpha();
780
                    alphaValue = getNewAlpha(alphaValue.intValue(), transparencyValue);
781
                }
782

    
783
                if (filters != null) {
784
                    // TODO Apply filters
785
                }
786

    
787
                int intRGB = 0;
788
                intRGB = ((alphaValue.byteValue() & 0xFF) << 24) | // alpha
789
                    ((rgbValues[0].byteValue() & 0xFF) << 16) | // red
790
                    ((rgbValues[1].byteValue() & 0xFF) << 8) | // green
791
                    ((rgbValues[2].byteValue() & 0xFF) << 0); // blue
792
                image.setRGB(j, i, intRGB);
793
            }
794
        }
795
        return image;
796
    }
797

    
798
    private Image drawYCBCRBuffer(Graphics graphics, Buffer buffer,
799
        ColorInterpretation colorInterpretation,Transparency transparency,
800
        FilterList filters) {
801

    
802
        BufferedImage image = null;
803

    
804
        image = ToolsSwingLocator.getToolsSwingManager().createBufferedImage(buffer.getColumns(), buffer.getRows(),
805
            BufferedImage.TYPE_INT_ARGB);
806

    
807
        int yIndex = colorInterpretation.getBand(ColorInterpretation.YCBCR_Y_BAND);
808
        int cbBandIndex = colorInterpretation.getBand(ColorInterpretation.YCBCR_CB_BAND);
809
        int crBandIndex = colorInterpretation.getBand(ColorInterpretation.YCBCR_CR_BAND);
810

    
811

    
812
        Band yBand = buffer.getBand(yIndex);
813
        Band cbBand = buffer.getBand(cbBandIndex);
814
        Band crBand = buffer.getBand(crBandIndex);
815

    
816
        for (int i = 0; i < buffer.getRows(); i++) {
817
            for (int j = 0; j < buffer.getColumns(); j++) {
818
                Number yValue = (Number) yBand.get(i, j);
819
                Number cbValue = (Number) cbBand.get(i, j);
820
                Number crValue = (Number) crBand.get(i, j);
821

    
822
                Number[] rgbValues=ColorUtils.fromYCBCRtoRGB(
823
                    yValue.floatValue(),
824
                    cbValue.floatValue(),
825
                    crValue.floatValue()
826
                    );
827

    
828
                Integer alphaValue =255;
829
                if (transparency != null) {
830
                    // Apply defined transparency ranges
831

    
832
                    alphaValue = alphaValue.byteValue() & 0xFF;
833
                    int newAlpha =
834
                        transparency.getTransparencyRangeAlpha(rgbValues[0].byteValue(),
835
                            rgbValues[1].byteValue(), rgbValues[2].byteValue());
836
                    alphaValue = getNewAlpha(alphaValue.intValue(), newAlpha);
837

    
838
                    // Apply general transparency
839
                    int transparencyValue = transparency.getAlpha();
840
                    alphaValue = getNewAlpha(alphaValue.intValue(), transparencyValue);
841
                }
842

    
843
                if (filters != null) {
844
                    // TODO Apply filters
845
                }
846

    
847
                int intRGB = 0;
848
                intRGB = ((alphaValue.byteValue() & 0xFF) << 24) | // alpha
849
                    ((rgbValues[0].byteValue() & 0xFF) << 16) | // red
850
                    ((rgbValues[1].byteValue() & 0xFF) << 8) | // green
851
                    ((rgbValues[2].byteValue() & 0xFF) << 0); // blue
852
                image.setRGB(j, i, intRGB);
853
            }
854
        }
855
        return image;
856
    }
857

    
858
    /**
859
     * Method to draw gray buffers
860
     * @param graphics
861
     * @param buffer
862
     * @param filters
863
     * @return
864
     */
865
    private Image drawGrayBuffer(Graphics graphics, Buffer buffer, Transparency transparency, FilterList filters) {
866

    
867
        BufferedImage image = null;
868

    
869
        image = ToolsSwingLocator.getToolsSwingManager().createBufferedImage(buffer.getColumns(), buffer.getRows(),
870
            BufferedImage.TYPE_INT_ARGB);
871

    
872
        Band greyBand = buffer.getBand(0);
873

    
874
//        Statistics statistics = buffer.getStatistics(null);
875
//        double maximum = statistics.getMaximun();// ver drawRGBBuffer
876
//        double minimum = statistics.getMinimun();
877

    
878

    
879
        for (int i = 0; i < buffer.getRows(); i++) {
880
            for (int j = 0; j < buffer.getColumns(); j++) {
881
                int greyByteValue = 0;
882
                int alphaByteValue = (byte)255;
883
                Number greyValue = (Number) greyBand.get(i, j);
884
                NoData noData = greyBand.getNoData();
885
                if(noData != null){
886
                    if(greyValue.equals(noData.getValue())){
887
                        alphaByteValue = 0;
888
                        greyByteValue = 0;
889
                    } else {
890
                        alphaByteValue = 255;
891
                        greyByteValue = logarithmicConversionToByteRange(greyValue);
892
                    }
893
                } else {
894
                    greyByteValue = logarithmicConversionToByteRange(greyValue);
895
                }
896
//                byte greyByteValue = linearConversionToByte(greyValue);
897
//                byte greyByteValue = proportionalConversionToByte(greyValue, maximum, minimum); // 1
898
//                byte greyByteValue = logarithmicConversionToByte(greyValue);
899
//                byte greyByteValue = logarithmicConversionToByte(greyValue, maximum);
900

    
901
                if (alphaByteValue != 0 && transparency != null) {
902
                    // Apply defined transparency ranges
903

    
904
//                    alphaByteValue = alphaValue.byteValue() & 0xFF;
905
                    int newAlpha = transparency.getTransparencyRangeAlpha(greyByteValue, greyByteValue, greyByteValue);
906
                    alphaByteValue = getNewAlpha(alphaByteValue, newAlpha);
907

    
908
                    // Apply general transparency
909
                    int transparencyValue = transparency.getAlpha();
910
                    alphaByteValue = getNewAlpha(alphaByteValue, transparencyValue);
911
                }
912

    
913
                if (filters != null) {
914
                    // TODO Apply filters
915
                }
916

    
917
                int intARGB = (((byte)alphaByteValue & 0xFF) << 24) | // alpha
918
                    (((byte)greyByteValue & 0xFF)<< 16) | // red
919
                    (((byte)greyByteValue & 0xFF)<< 8) | // green
920
                    (((byte)greyByteValue & 0xFF)); // blue
921

    
922
                image.setRGB(j, i, intARGB);
923
            }
924
        }
925
        return image;
926
    }
927

    
928
    private Image drawPaletteBuffer(Graphics graphics, Buffer buffer, ColorInterpretation colorInterpretation,
929
        Transparency transparency, FilterList filters) {
930

    
931
        BufferedImage image = ToolsSwingLocator.getToolsSwingManager().createBufferedImage(buffer.getColumns(), buffer.getRows(),
932
            BufferedImage.TYPE_INT_ARGB);
933

    
934
        for (int i = 0; i < buffer.getRows(); i++) {
935
            for (int j = 0; j < buffer.getColumns(); j++) {
936

    
937
                Object value = buffer.getBand(colorInterpretation.getPaletteBand()).get(i, j);
938
                byte[] rgba = colorInterpretation.getPalette().getRGBA(value);
939

    
940
                if (transparency != null) {
941
                    // Apply defined transparency ranges
942
                    int alpha = rgba[3] & 0xFF;
943
                    int newAlpha =
944
                        transparency.getTransparencyRangeAlpha(rgba[0], rgba[1], rgba[2]);
945
                    alpha = getNewAlpha(alpha, newAlpha);
946

    
947
                    // Apply general transparency
948
                    int transparencyValue = transparency.getAlpha();
949
                    rgba[3] = (byte) getNewAlpha(alpha, transparencyValue);
950
                }
951

    
952
                if (filters != null) {
953
                    // TODO Apply filters
954
                }
955

    
956
                int intARGB = ((rgba[3] & 0xFF) << 24) | // alpha
957
                    ((rgba[0] & 0xFF) << 16) | // red
958
                    ((rgba[1] & 0xFF) << 8) | // green
959
                    ((rgba[2] & 0xFF) << 0); // blue
960

    
961
                image.setRGB(j, i, intARGB);
962
            }
963
        }
964
        return image;
965
    }
966

    
967
    private int getNewAlpha(int alpha, int newAlpha) {
968
        return (int) Math.round(alpha * (newAlpha / 255d));
969
    }
970

    
971
    @Override
972
    public ColorInterpretation getColorInterpretation() {
973
        return this.colorInterpretation;
974
    }
975

    
976
    @Override
977
    public void setColorInterpretation(ColorInterpretation colorInterpretation) {
978
        if(this.colorInterpretation!=null){
979
            this.colorInterpretation.deleteObserver(this);
980
        }
981
        this.colorInterpretation = colorInterpretation;
982
        this.colorInterpretation.addObserver(this);
983
    }
984

    
985
    @Override
986
    public FilterList getFilters() {
987
        return this.filters;
988
    }
989

    
990
    @Override
991
    public void setFilters(FilterList filterList) {
992
        this.filters = filterList;
993
    }
994

    
995
    /**
996
     *
997
     */
998
    public static void registerPersistence() {
999
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1000
        DynStruct definition = manager.getDefinition(PERSISTENT_NAME);
1001
        if (definition == null) {
1002
            definition =
1003
                manager.addDefinition(DefaultRasterLegend.class, PERSISTENT_NAME,
1004
                    PERSISTENT_DESCRIPTION, null, null);
1005
            definition.addDynFieldObject(COLOR_INTERPRETATION_PERSISTENCE_FIELD).setMandatory(false)
1006
                .setClassOfValue(ColorInterpretation.class);
1007
            definition.addDynFieldObject(FILTERS_PERSISTENCE_FIELD).setMandatory(false)
1008
                .setClassOfValue(FilterList.class);
1009
        }
1010
    }
1011

    
1012
    @Override
1013
    public void saveToState(PersistentState state) throws PersistenceException {
1014
        state.set(COLOR_INTERPRETATION_PERSISTENCE_FIELD, this.getColorInterpretation());
1015
        state.set(FILTERS_PERSISTENCE_FIELD, this.filters);
1016
    }
1017

    
1018
    @Override
1019
    public void loadFromState(PersistentState state) throws PersistenceException {
1020
        this.setColorInterpretation((ColorInterpretation) state
1021
            .get(COLOR_INTERPRETATION_PERSISTENCE_FIELD));
1022
        this.setFilters((FilterList) state.get(FILTERS_PERSISTENCE_FIELD));
1023
    }
1024

    
1025
    @Override
1026
    public void setTransparency(Transparency transparency) {
1027
        this.transparency = transparency;
1028
    }
1029

    
1030
    @Override
1031
    public Transparency getTransparency() {
1032
        return this.transparency;
1033
    }
1034

    
1035
    @Override
1036
    public ISymbol getDefaultSymbol() {
1037
        return null;
1038
    }
1039

    
1040
    @Override
1041
    public Object clone() throws CloneNotSupportedException {
1042
        DefaultRasterLegend cloned = (DefaultRasterLegend) super.clone();
1043

    
1044
        ColorInterpretation clonedColorInterpretation = (ColorInterpretation)this.getColorInterpretation().clone();
1045
        cloned.setColorInterpretation(clonedColorInterpretation);
1046
        //FIXME:
1047
        //cloned.setTransparency((Transparency)this.getTransparency().clone());
1048
        //cloned.setFilters(getFilters());
1049

    
1050
        return cloned;
1051
    }
1052

    
1053
    @Override
1054
    public ILegend cloneLegend() {
1055
        try {
1056
            return (RasterLegend)this.clone();
1057
        } catch (Exception e) {
1058
            throw new RuntimeException("Can't clone the legend", e);
1059
        }
1060
    }
1061

    
1062

    
1063
    @Override
1064
    public void fireDefaultSymbolChangedEvent(SymbolLegendEvent event) {
1065

    
1066
        for (int i = 0; i < listeners.size(); i++) {
1067
            ((LegendContentsChangedListener) listeners.get(i))
1068
                    .symbolChanged(event);
1069
        }
1070
    }
1071

    
1072
    @Override
1073
    public LegendContentsChangedListener[] getListeners() {
1074
        return (LegendContentsChangedListener[]) listeners
1075
                .toArray(new LegendContentsChangedListener[listeners.size()]);
1076
    }
1077

    
1078

    
1079

    
1080
    @Override
1081
    public void setTransparentNoData(boolean noDataTransparent) {
1082
        this.transparentNoData=noDataTransparent;
1083

    
1084
    }
1085

    
1086
    @Override
1087
    public boolean areTransparentNoData() {
1088
        return this.transparentNoData;
1089
    }
1090

    
1091
    @Override
1092
    public void update(Observable observable, Object notification) {
1093
        if (notification instanceof ColorInterpretationNotification) {
1094
            String type = ((ColorInterpretationNotification) notification).getType();
1095
            if(type.equals(ColorInterpretationNotification.CHANGED_COLOR_INTERPRETATION_VALUE)
1096
               || type.equals(ColorInterpretationNotification.ADDED_COLOR_INTERPRETATION)
1097
               || type.equals(ColorInterpretationNotification.COPIED_FROM_COLOR_INTERPRETATION)){
1098
            fireColorinterpretationChangedEvent(new ChangeColorInterpretationEvent(
1099
                (String[])((ColorInterpretationNotification) notification).getValue(0),
1100
                (String[])((ColorInterpretationNotification) notification).getValue(1)));
1101
            }
1102
            if (type.equals(ColorInterpretationNotification.SETTED_PALETTE)) {
1103
                fireColorinterpretationChangedEvent(new ChangePaletteEvent(
1104
                    (ColorTable) ((ColorInterpretationNotification) notification).getValue(0),
1105
                    (ColorTable) ((ColorInterpretationNotification) notification).getValue(1)));
1106
            }
1107
            if (type.equals(ColorInterpretationNotification.CHANGED_PALETTE)) {
1108
                fireColorinterpretationChangedEvent(new ChangePaletteEvent(
1109
                    (ColorTable) ((ColorInterpretationNotification) notification).getValue(0),
1110
                    (ColorTable) ((ColorInterpretationNotification) notification).getValue(0)));
1111
            }
1112

    
1113
            if (type.equals(ColorInterpretationNotification.SETTED_PALETTE_BAND)) {
1114
                fireColorinterpretationChangedEvent(new ChangePaletteBandEvent(
1115
                    (int) ((ColorInterpretationNotification) notification).getValue(0),
1116
                    (int) ((ColorInterpretationNotification) notification).getValue(1)));
1117
            }
1118
        }
1119
    }
1120

    
1121
    public void fireColorinterpretationChangedEvent(RasterLegendEvent event) {
1122

    
1123
        for (int i = 0; i < listeners.size(); i++) {
1124
            ((RasterLegendChangedListener) listeners.get(i)).colorInterpretationChanged(event);
1125
        }
1126
    }
1127

    
1128
    @Override
1129
    public void addLegendListener(LegendContentsChangedListener listener) {
1130
        if(listener instanceof RasterLegendChangedListener){
1131
            addLegendListener((RasterLegendChangedListener)listener);
1132
            return;
1133
        }
1134
        throw new UnsupportedOperationException("Raster layer can't be listened by a no RasterLegendChangedListener");
1135

    
1136
    }
1137

    
1138
    @Override
1139
    public void removeLegendListener(LegendContentsChangedListener listener) {
1140
        if(listener instanceof RasterLegendChangedListener){
1141
            removeLegendListener((RasterLegendChangedListener)listener);
1142
            return;
1143
        }
1144
        throw new UnsupportedOperationException("Raster layer can't be listened by a no RasterLegendChangedListener");
1145

    
1146
    }
1147

    
1148
    private void addLegendListener(RasterLegendChangedListener listener) {
1149
        if (listener != null && !listeners.contains(listener))
1150
            listeners.add(listener);
1151
    }
1152

    
1153
    private void removeLegendListener(RasterLegendChangedListener listener) {
1154
        listeners.remove(listener);
1155
    }
1156
}