Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libRaster / src / org / gvsig / raster / grid / filter / enhancement / LinearStretchParams.java @ 33221

History | View | Annotate | Download (12.5 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2007 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.grid.filter.enhancement;
20

    
21
import org.gvsig.raster.dataset.FileNotOpenException;
22
import org.gvsig.raster.dataset.io.RasterDriverException;
23
import org.gvsig.raster.dataset.properties.DatasetListStatistics;
24
import org.gvsig.raster.hierarchy.IStatistics;
25
/**
26
 * Par?metros necesarios para el filtro de realce por tramos. Contiene
27
 * informaci?n de cada tramo. Valores m?ximos y m?nimos reales y correspondencia
28
 * a RGB de cada tramo.
29
 * 
30
 * Tambi?n contiene los valores calculados en el preproceso de escala y
31
 * desplazamiento para cada banda.
32
 * 
33
 * @version 27/02/2008
34
 * @author Nacho Brodin nachobrodin@gmail.com
35
 */
36
public class LinearStretchParams {
37
        
38
        public class Stretch {
39
                /**
40
                 * Valores de los datos de entrada correspondientes al m?nimo y al m?ximo de 
41
                 * cada tramo. Estos tendr?n un rango entre el m?nimo y el m?ximo en cada banda
42
                 * de la imagen. 
43
                 */
44
                public double[]        stretchIn           = null;
45
                /**
46
                 * Valores de los datos de salida correspondientes al m?nimo y al m?ximo de 
47
                 * cada tramo. Estos tendr?n un rango entre 0 y 255.
48
                 */
49
                public int[]           stretchOut          = null;
50
                /**
51
                 * Porcentajes de recorte de colas (Valores de entrada)
52
                 */
53
                public double          tailTrimMin         = 0;
54
                public double          tailTrimMax         = 0;
55
                /**
56
                 * Valores de recorte de colas (Valores de salida calculados por el filtro TailTrim)
57
                 */
58
                public double          tailTrimValueMin    = 0;
59
                public double          tailTrimValueMax    = 0;
60
                /**
61
                 * Valores de escala a calcular por el filtro lineal por tramos.
62
                 * Cada elemento del array es un tramo.
63
                 */
64
                public double[]        scale               = null;
65
                /**
66
                 * Valores de desplazamiento a calcular por el filtro lineal por tramos.
67
                 * Cada elemento del array es un tramo.
68
                 */
69
                public double[]        offset              = null;
70
                /**
71
                 * Valores m?ximos y m?nimos
72
                 */
73
                public double          maxValue            = 0;
74
                public double          minValue            = 0;
75
                
76
                /**
77
                 * Funcion grafica que se ha usado para generar el LinearStretchParams
78
                 * 0 - Lineal
79
                 * 1 - Exponencial / Logaritmica
80
                 * 2 - Raiz cuadrada / Cuadrada
81
                 * 3 - Level slice
82
                 */
83
                public int functionType = 0;
84

    
85
                /**
86
                 * Valor de la gr?fica para la funci?n. No se usa en una gr?fica lineal.
87
                 */
88
                public double valueFunction = 0.0;
89
                
90
                /**
91
                 * Aplica el recorte de colas sobre los extremos de los m?ximos y m?nimos de entrada.
92
                 * La aplicaci?n de esta funci?n considera que ya se han calculado los valores con 
93
                 * loadTailTrimValues.
94
                 */
95
                public void applyTrimToStretchs() {
96
                        if(stretchIn != null && stretchIn.length >= 2) {
97
                                minValue = stretchIn[0] = tailTrimValueMin;
98
                                maxValue = stretchIn[stretchIn.length - 1] = tailTrimValueMax;
99
                        }
100
                }
101
                
102
                /**
103
                 * Aplica el eliminado de extremos. Para ello utiliza el segundo m?ximo y m?nimo de entrada.
104
                 */
105
                /*public void applyRemoveEndsToStretchs(double secondMin, double secondMax) {
106
                        if(stretchIn != null && stretchIn.length >= 2) {
107
                                minValue = stretchIn[0] = secondMin;
108
                                maxValue = stretchIn[stretchIn.length - 1] = secondMax;
109
                        }
110
                }*/
111
                
112
                /**
113
                 * Consulta si tiene alg?n valor el recorte de colas
114
                 * @return true si tiene valor el recorte de colas y false si no lo tiene
115
                 */
116
                public boolean hasTailTrim() {
117
                        return (tailTrimMin != 0 || tailTrimMax != 0);
118
                }
119
                
120
                /**
121
                 * Calcula la escala y el desplazamiento teniendo en cuenta que
122
                 * ya tenga todos los valores de entrada asignados.
123
                 *
124
                 */
125
                public void calcLinearScaleAndOffset() {
126
                        if(stretchIn != null && stretchOut != null) {
127
                                //simplifyStretch();
128
                                scale = new double[stretchIn.length - 1];
129
                                offset = new double[stretchIn.length - 1];
130
                                for (int i = 0; i < scale.length; i++) {
131
                                        double rgbRange = (stretchOut[i + 1] - stretchOut[i]);
132
                                        if((stretchIn[i + 1] - stretchIn[i]) == 0)
133
                                                scale[i] = 0;
134
                                        else
135
                                                scale[i] = rgbRange / (stretchIn[i + 1] - stretchIn[i]);
136
                                        offset[i] = stretchOut[i];
137
                                }
138
                        }
139
                }
140
                
141
                /**
142
                 * Elimina puntos redundantes en stretchIn y stretchOut
143
                 */
144
//                private void simplifyStretch() {
145
//                        boolean simplified = false;
146
//                        for (int i = 0; i < (stretchIn.length - 1); i++) {
147
//                                if(stretchIn[i] == stretchIn[i + 1]) {
148
//                                        double[] auxIn = new double[stretchIn.length -1];
149
//                                        int[] auxOut = new int[stretchIn.length -1];
150
//                                        for (int j = 0; j < auxIn.length; j++) {
151
//                                                if(j < i) {
152
//                                                        auxIn[j] = stretchIn[j];
153
//                                                        auxOut[j] = stretchOut[j];
154
//                                                } else {
155
//                                                        auxIn[j] = stretchIn[j + 1];
156
//                                                        auxOut[j] = stretchOut[j + 1];
157
//                                                }
158
//                                                        
159
//                                        }
160
//                                        stretchIn = auxIn;
161
//                                        stretchOut = auxOut;
162
//                                        simplified = true;
163
//                                }
164
//                        }
165
//                        if(simplified)
166
//                                simplifyStretch();
167
//                }
168
                
169
                /**
170
                 * Asigna el m?ximo y el m?nimo
171
                 * @param stats
172
                 * @param type
173
                 * @param band
174
                 */
175
                public void setMaxMin(DatasetListStatistics stats, int band, boolean rgb) {
176
                        try {
177
                                if (rgb) {
178
                                        if (stats.getMinByteUnsigned() != null)
179
                                                minValue = stats.getMinByteUnsigned()[band];
180
                                        if (stats.getMaxByteUnsigned() != null)
181
                                                maxValue = stats.getMaxByteUnsigned()[band];
182
                                } else {
183
                                        if (stats.getMin() != null) {
184
                                                minValue = stats.getMin()[band];
185
                                        }
186
                                        if (stats.getMax() != null) {
187
                                                maxValue = stats.getMax()[band];
188
                                        }
189
                                }
190
                                if (stretchIn == null) {
191
                                        stretchIn = new double[] { minValue, maxValue };
192
                                } else {
193
                                        stretchIn[0] = minValue;
194
                                        stretchIn[stretchIn.length - 1] = maxValue;
195
                                }
196
                        } catch (ArrayIndexOutOfBoundsException ex) {
197
                                // No se asigna el m?ximo o m?nimo
198
                        }
199
                }
200
                
201
                /**
202
                 * Aplica el eliminado de extremos. Para ello utiliza el segundo m?ximo y m?nimo de entrada.
203
                 */
204
                public void applyRemoveEndsToStretchs(DatasetListStatistics stats, boolean rgb, int band) {
205
                        if(stretchIn == null)
206
                                return;
207
                        try {
208
                                if(rgb) {
209
                                        if(stats.getSecondMinByteUnsigned() != null)
210
                                                stretchIn[0] = minValue = stats.getSecondMinByteUnsigned()[band];
211
                                        if(stats.getSecondMaxByteUnsigned() != null)
212
                                                stretchIn[stretchIn.length - 1] = maxValue = stats.getSecondMaxByteUnsigned()[band];
213
                                } else {
214
                                        if(stats.getSecondMin() != null)
215
                                                stretchIn[0] = minValue = stats.getSecondMin()[band];
216
                                        if(stats.getMax() != null)
217
                                                stretchIn[stretchIn.length - 1] = maxValue = stats.getSecondMax()[band];
218
                                }
219
                        } catch (ArrayIndexOutOfBoundsException ex) {
220
                                //No se asigna el m?ximo o m?nimo 
221
                        }
222
                }
223
        }
224

    
225
        public Stretch             red               = new Stretch();
226
        public Stretch             green             = new Stretch();
227
        public Stretch             blue              = new Stretch();
228
        public boolean             rgb               = false;
229
                        
230
        /**
231
         * Consulta si tiene alg?n valor el recorte de colas
232
         * @return true si tiene valor el recorte de colas y false si no lo tiene
233
         */
234
        public boolean hasTailTrim() {
235
                return (red.hasTailTrim() ||
236
                                green.hasTailTrim() ||
237
                                blue.hasTailTrim());
238
        }
239
        
240
        /**
241
         * Obtiene la lista de valores de recorte. Este formato es que el que necesita el
242
         * filtro TailTrim para calcular el valor del porcentaje recorte.
243
         * @return double
244
         */
245
        public double[] getTailTrimList() {
246
                return new double[]{
247
                                red.tailTrimMin, green.tailTrimMin, blue.tailTrimMin, 
248
                                red.tailTrimMax, green.tailTrimMax,        blue.tailTrimMax};
249
        }
250
        
251
        /**
252
         * Carga los valores de recorte calculados por el filtro TailTrim que ya deber?a haber
253
         * sido aplicado. Estos valores estar?n salvados en DatasetListStatistics.
254
         * @param stats
255
         */
256
        public void loadTailTrimValues(DatasetListStatistics stats) {
257
                double[][] result;
258
                result = (double[][]) stats.getTailTrimValue(red.tailTrimMin);
259
                if (result != null)
260
                        red.tailTrimValueMin = result[0][0];
261
                result = (double[][]) stats.getTailTrimValue(red.tailTrimMax);
262
                if (result != null)
263
                        red.tailTrimValueMax = result[0][1];
264
                result = (double[][]) stats.getTailTrimValue(green.tailTrimMin);
265
                if (result != null && result.length >= 2)
266
                        green.tailTrimValueMin = result[1][0];
267
                result = (double[][]) stats.getTailTrimValue(green.tailTrimMax);
268
                if (result != null && result.length >= 2)
269
                        green.tailTrimValueMax = result[1][1];
270
                result = (double[][]) stats.getTailTrimValue(blue.tailTrimMin);
271
                if (result != null && result.length >= 3)
272
                        blue.tailTrimValueMin = result[2][0];
273
                result = (double[][]) stats.getTailTrimValue(blue.tailTrimMax);
274
                if (result != null && result.length >= 3)
275
                        blue.tailTrimValueMax = result[2][1];
276
        }
277
        
278
        /**
279
         * Aplica el recorte de colas sobre los extremos de los m?ximos y m?nimos de entrada.
280
         * La aplicaci?n de esta funci?n considera que ya se han calculado los valores con 
281
         * loadTailTrimValues.
282
         */
283
        public void applyTrimToStretchs() {
284
                red.applyTrimToStretchs();
285
                green.applyTrimToStretchs();
286
                blue.applyTrimToStretchs();
287
        }
288
        
289
        /**
290
         * Calcula la escala y el desplazamiento teniendo en cuenta que
291
         * ya tenga todos los valores de entrada asignados.
292
         */
293
        public void calcLinearScaleAndOffset() {
294
                red.calcLinearScaleAndOffset();
295
                green.calcLinearScaleAndOffset();
296
                blue.calcLinearScaleAndOffset();
297
        }
298
        
299
        /**
300
         * Asigna el m?ximo y el m?nimo
301
         * @param stats
302
         * @param type
303
         * @param band
304
         */
305
        public void setMaxMin(DatasetListStatistics stats, int[] renderBands) {
306
                if (renderBands[0] > -1)
307
                        red.setMaxMin(stats, renderBands[0], rgb);
308
                if (renderBands[1] > -1)
309
                        green.setMaxMin(stats, renderBands[1], rgb);
310
                if (renderBands[2] > -1)
311
                        blue.setMaxMin(stats, renderBands[2], rgb);
312
        }
313
        
314
        /**
315
         * Aplica el eliminado de extremos. Para ello utiliza el segundo m?ximo y m?nimo de entrada.
316
         */
317
        public void applyRemoveEndsToStretchs(DatasetListStatistics stats, int[] renderBands) {
318
                if (renderBands[0] > -1)
319
                        red.applyRemoveEndsToStretchs(stats, rgb, renderBands[0]);
320
                if (renderBands[1] > -1)
321
                        green.applyRemoveEndsToStretchs(stats, rgb, renderBands[1]);
322
                if (renderBands[2] > -1)
323
                        blue.applyRemoveEndsToStretchs(stats, rgb, renderBands[2]);
324
        }
325
        
326
        /**
327
         * Obtiene un objeto LinearStretchParams para una aplicaci?n de realce lineal estandar, es decir, el rango
328
         * de datos de salida es 0-255 y con solo un tramo para los datos. 
329
         * @param nBands N?mero de bandas
330
         * @param tailTrim Recorte de colas
331
         * @param stats Estad?sticas
332
         * @return LinearStretchParams
333
         * @throws FileNotOpenException
334
         * @throws RasterDriverException
335
         */
336
        public static LinearStretchParams createStandardParam(int[] renderBands, double tailTrim, IStatistics stats, boolean rgb) throws FileNotOpenException, RasterDriverException {
337
                LinearStretchParams leParams = new LinearStretchParams();
338
                leParams.rgb = rgb;
339
                try {
340
                        stats.calcFullStatistics();
341
                } catch (InterruptedException e) {
342
                        return null;
343
                }
344
                if (renderBands[0] >= 0) {
345
                        if (rgb)
346
                                leParams.red.stretchIn = new double[] { stats.getMinByteUnsigned()[0], stats.getMaxByteUnsigned()[0] };
347
                        else
348
                                leParams.red.stretchIn = new double[] { stats.getMin()[renderBands[0]], stats.getMax()[renderBands[0]] };
349
                }
350
                leParams.red.stretchOut = new int[] { 0, 255 };
351
                leParams.red.tailTrimMin = tailTrim;
352
                leParams.red.tailTrimMax = tailTrim;
353
                if (renderBands[1] >= 0) {
354
                        if (rgb)
355
                                leParams.green.stretchIn = new double[] { stats.getMinByteUnsigned()[0], stats.getMaxByteUnsigned()[0] };
356
                        else
357
                                leParams.green.stretchIn = new double[] { stats.getMin()[renderBands[1]], stats.getMax()[renderBands[1]] };
358
                }
359
                leParams.green.stretchOut = new int[] { 0, 255 };
360
                leParams.green.tailTrimMin = tailTrim;
361
                leParams.green.tailTrimMax = tailTrim;
362
                if (renderBands[2] >= 0) {
363
                        if (rgb)
364
                                leParams.blue.stretchIn = new double[] { stats.getMinByteUnsigned()[0], stats.getMaxByteUnsigned()[0] };
365
                        else
366
                                leParams.blue.stretchIn = new double[] { stats.getMin()[renderBands[2]], stats.getMax()[renderBands[2]] };
367
                }
368
                leParams.blue.stretchOut = new int[] { 0, 255 };
369
                leParams.blue.tailTrimMin = tailTrim;
370
                leParams.blue.tailTrimMax = tailTrim;
371
                return leParams;
372
        }
373
}