Statistics
| Revision:

svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / org.gvsig.desktop.library / org.gvsig.raster / org.gvsig.raster.lib / org.gvsig.raster.lib.buffer.impl / src / main / java / org / gvsig / raster / lib / buffer / impl / operations / tailtrim / TailTrimOperation.java @ 43864

History | View | Annotate | Download (14.8 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2017 gvSIG Association
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., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.raster.lib.buffer.impl.operations.tailtrim;
24

    
25
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
26
import org.gvsig.raster.lib.buffer.api.Band;
27
import org.gvsig.raster.lib.buffer.api.BufferLocator;
28
import org.gvsig.raster.lib.buffer.api.BufferManager;
29
import org.gvsig.raster.lib.buffer.api.NoData;
30
import org.gvsig.raster.lib.buffer.api.exceptions.BandException;
31
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
32
import org.gvsig.raster.lib.buffer.api.exceptions.BufferOperationException;
33
import org.gvsig.raster.lib.buffer.api.operations.OperationFactory;
34
import org.gvsig.raster.lib.buffer.api.statistics.Statistics;
35
import org.gvsig.raster.lib.buffer.spi.exceptions.ProcessingOperationException;
36
import org.gvsig.raster.lib.buffer.spi.operations.AbstractSpecifiedBandsOperation;
37
import org.gvsig.tools.locator.LocatorException;
38

    
39

    
40
/**
41
 * @author fdiaz
42
 *
43
 */
44
public class TailTrimOperation extends AbstractSpecifiedBandsOperation{
45

    
46
    static public String STATISTICS_PARAM = "statistics";
47
    static public String TAIL_TRIM_PERCENT_PARAM = "tail_trim_percent";
48

    
49
    private Statistics statistics;
50
    private double tailTrimPercent;
51
    private RowProcessor[] rowProcessors;
52

    
53
    /**
54
     * @param factory
55
     *
56
     */
57
    public TailTrimOperation(OperationFactory factory) {
58
        super(factory);
59
    }
60

    
61
    @SuppressWarnings("unchecked")
62
    @Override
63
    public void preProcess() throws BufferOperationException {
64
        super.preProcess();
65
        BufferManager manager = BufferLocator.getBufferManager();
66

    
67
        statistics = (Statistics) this.getParameter(STATISTICS_PARAM, null);
68
        if (statistics == null) {
69
            statistics = this.getInputBuffer().getStatistics(null);
70
        };
71
        tailTrimPercent = (double) this.getParameter(TAIL_TRIM_PERCENT_PARAM, 0);
72
        tailTrimPercent = (tailTrimPercent>100)?100:tailTrimPercent;
73
        tailTrimPercent = (tailTrimPercent<0)?0:tailTrimPercent;
74

    
75
        //FIXME: Falta la gesti?n del par?metro copyUnprocessedBands, de momento se copian sin tenerlo en cuenta
76

    
77
        int bands = this.getInputBuffer().getBandCount();
78
        rowProcessors = new RowProcessor[bands];
79
        int [] bandTypes = new int[bands];
80
        for (int i = 0; i < bandTypes.length; i++) {
81
            bandTypes[i] = this.getInputBuffer().getBandTypes()[i];
82
        }
83
        NoData[] noData = this.getInputBuffer().getBandNoData();
84
        NoData[] resultNoData = new NoData[noData.length];
85
        for (int band = 0; band < noData.length; band++) {
86
            int bandType = this.getInputBuffer().getBand(band).getDataType();
87
            switch (bandType) {
88
            case BufferManager.TYPE_BYTE:
89
                rowProcessors[band] = new ByteRowProcessor(band);
90
                if (isProcessableBand(band)) {
91
                    if (noData[band].isDefined()) {
92
                        resultNoData[band] = noData[band];
93
                    } else {
94
                        resultNoData[band] = manager.createNoData((byte) 0, (byte) 0);
95
                    }
96
                }
97
                break;
98
            case BufferManager.TYPE_USHORT:
99
                rowProcessors[band] = new UShortRowProcessor(band);
100
                if (isProcessableBand(band)) {
101
                    if (noData[band].isDefined()) {
102
                        resultNoData[band] = noData[band];
103
                    } else {
104
                        resultNoData[band] = manager.createNoData((int) 0, (int) 0);
105
                    }
106
                }
107
                break;
108
            case BufferManager.TYPE_SHORT:
109
                rowProcessors[band] = new ShortRowProcessor(band);
110
                if (isProcessableBand(band)) {
111
                    if (noData[band].isDefined()) {
112
                        resultNoData[band] = noData[band];
113
                    } else {
114
                        resultNoData[band] = manager.createNoData(Short.MIN_VALUE, Short.MIN_VALUE);
115
                    }
116
                }
117
                break;
118
            case BufferManager.TYPE_INT:
119
                rowProcessors[band] = new IntRowProcessor(band);
120
                if (isProcessableBand(band)) {
121
                    if (noData[band].isDefined()) {
122
                        resultNoData[band] = noData[band];
123
                    } else {
124
                        resultNoData[band] = manager.createNoData(Integer.MIN_VALUE, Integer.MIN_VALUE);
125
                    }
126
                }
127
                break;
128
            case BufferManager.TYPE_FLOAT:
129
                rowProcessors[band] = new FloatRowProcessor(band);
130
                if (isProcessableBand(band)) {
131
                    if (noData[band].isDefined()) {
132
                        resultNoData[band] = noData[band];
133
                    } else {
134
                        resultNoData[band] = manager.createNoData(Float.MIN_VALUE, Float.MIN_VALUE);
135
                    }
136
                }
137
                break;
138
            case BufferManager.TYPE_DOUBLE:
139
                rowProcessors[band] = new DoubleRowProcessor(band);
140
                if (isProcessableBand(band)) {
141
                    if (noData[band].isDefined()) {
142
                        resultNoData[band] = noData[band];
143
                    } else {
144
                        resultNoData[band] = manager.createNoData(Double.MIN_VALUE, Double.MIN_VALUE);
145
                    }
146
                }
147
                break;
148
            default:
149
                throw new IllegalArgumentException("Unknow type of band '"+band+"'");
150
            }
151

    
152
        }
153

    
154
        try {
155
            this.setOutputBuffer(manager.createBuffer(
156
                this.getInputBuffer().getRows(),
157
                this.getInputBuffer().getColumns(),
158
                bandTypes,
159
                resultNoData,
160
                this.getInputBuffer().getProjection(),
161
                this.getInputBuffer().getEnvelope()));
162
        } catch (LocatorException | BufferException | CreateEnvelopeException e) {
163
            throw new BufferOperationException(e);
164
        }
165
    }
166

    
167
    @Override
168
    public void process() throws ProcessingOperationException {
169
        super.process();
170
        for (int band=0; band<this.getInputBuffer().getBandCount(); band++){
171
            if (getBandsToProcess().contains(band)) {
172
                Band bufferBand = this.getInputBuffer().getBand(band);
173
                Band outputBufferBand = this.getOutputBuffer().getBand(band);
174

    
175
                for (int row = 0; row < this.getInputBuffer().getRows(); row++) {
176
                    Object rowBuffer = bufferBand.createRowBuffer();
177
                    bufferBand.fetchRow(row, rowBuffer);
178

    
179
                    Object outputRowBuffer = outputBufferBand.createRowBuffer();
180
                    outputBufferBand.fetchRow(row, outputRowBuffer);
181

    
182
                    rowProcessors[band].processRow(rowBuffer, outputRowBuffer);
183

    
184
                    outputBufferBand.putRow(row, outputRowBuffer);
185
                }
186
            } else {
187
                try {
188
                    this.getOutputBuffer().getBand(band).copyFrom(this.getInputBuffer().getBand(band));
189
                } catch (BandException e) {
190
                    throw new ProcessingOperationException(e);
191
                }
192
            }
193
        }
194
    }
195

    
196
    @Override
197
    public void postProcess()  throws BufferOperationException {
198
        super.postProcess();
199
    }
200

    
201
    interface RowProcessor {
202
        void processRow(Object inputRow, Object outputRow);
203
        Number processValue(Number value);
204
    };
205

    
206
    private abstract class AbstractRowProcessor implements RowProcessor {
207
        int band;
208
        double minValue;
209
        double maxValue;
210
        NoData noData;
211
//        NoData outputNoData;
212

    
213
        public AbstractRowProcessor(int band) {
214
            this.band = band;
215
            noData = getInputBuffer().getBand(band).getNoData();
216
//            outputNoData = outputBuffer.getBand(band).getNoData();
217

    
218
            double[][] tailTrim = statistics.getTailTrimValue(tailTrimPercent);
219
            minValue = tailTrim[this.band][0];
220
            maxValue = tailTrim[this.band][1];
221
        }
222

    
223
    }
224

    
225
    private class ByteRowProcessor extends AbstractRowProcessor {
226

    
227

    
228
        public ByteRowProcessor(int band) {
229
            super(band);
230
        }
231

    
232
        @Override
233
        public void processRow(Object inputRow, Object outputRow) {
234
            byte[] inputByteRow = (byte[])inputRow;
235
            byte[] outputByteRow = (byte[])outputRow;
236
            for (int i = 0; i < inputByteRow.length; i++) {
237
                outputByteRow[i] = processValue(inputByteRow[i]).byteValue();
238
            }
239
        }
240

    
241
        @Override
242
        public Number processValue(Number value) {
243
            if(noData.isDefined() && noData.getValue().equals(value)){
244
                return getOutputBuffer().getBand(band).getNoData().getValue();
245
            }
246

    
247
            int iValue = 0xFF & ((Byte) value).byteValue();
248

    
249
            if(iValue < minValue || iValue > maxValue){
250
                return getOutputBuffer().getBand(band).getNoData().getValue();
251
            } else {
252
                return value;
253
            }
254
        }
255

    
256
    }
257

    
258
    private class ShortRowProcessor extends AbstractRowProcessor {
259

    
260
        public ShortRowProcessor(int band) {
261
            super(band);
262
        }
263

    
264
        @Override
265
        public void processRow(Object inputRow, Object outputRow) {
266
            short[] inputShortRow = (short[])inputRow;
267
            short[] outputShortRow = (short[])outputRow;
268
            for (int i = 0; i < inputShortRow.length; i++) {
269
                outputShortRow[i] = processValue(inputShortRow[i]).shortValue();
270
            }
271
        }
272

    
273
        @Override
274
        public Number processValue(Number value) {
275
            if(noData.isDefined() && noData.getValue().equals(value)){
276
                return getOutputBuffer().getBand(band).getNoData().getValue();
277
            }
278

    
279
            int iValue = ((Short) value).shortValue();
280

    
281
            if(iValue < minValue || iValue > maxValue){
282
                return getOutputBuffer().getBand(band).getNoData().getValue();
283
            } else {
284
                return value;
285
            }
286
        }
287

    
288
    }
289

    
290
    private class UShortRowProcessor extends AbstractRowProcessor {
291

    
292
        public UShortRowProcessor(int band) {
293
            super(band);
294
        }
295

    
296
        @Override
297
        public void processRow(Object inputRow, Object outputRow) {
298
            short[] inputShortRow = (short[])inputRow;
299
            short[] outputShortRow = (short[])outputRow;
300
            for (int i = 0; i < inputShortRow.length; i++) {
301
                outputShortRow[i] = processValue(inputShortRow[i]).shortValue();
302
            }
303
        }
304

    
305
        @Override
306
        public Number processValue(Number value) {
307
            if(noData.isDefined() && noData.getValue().equals(value)){
308
                return getOutputBuffer().getBand(band).getNoData().getValue();
309
            }
310

    
311
            int iValue = 0xFFFF & ((Short) value).shortValue();
312

    
313
            if(iValue < minValue || iValue > maxValue){
314
                return getOutputBuffer().getBand(band).getNoData().getValue();
315
            } else {
316
                return value;
317
            }
318
        }
319

    
320
    }
321

    
322
    private class IntRowProcessor extends AbstractRowProcessor {
323

    
324
        public IntRowProcessor(int band) {
325
            super(band);
326
        }
327

    
328
        @Override
329
        public void processRow(Object inputRow, Object outputRow) {
330
            int[] inputByteRow = (int[])inputRow;
331
            int[] outputByteRow = (int[])outputRow;
332
            for (int i = 0; i < inputByteRow.length; i++) {
333
                outputByteRow[i] = processValue(inputByteRow[i]).intValue();
334
            }
335
        }
336

    
337
        @Override
338
        public Number processValue(Number value) {
339
            if(noData.isDefined() && noData.getValue().equals(value)){
340
                return getOutputBuffer().getBand(band).getNoData().getValue();
341
            }
342
            int iValue = value.intValue();
343

    
344
            if(iValue < minValue || iValue > maxValue){
345
                return getOutputBuffer().getBand(band).getNoData().getValue();
346
            } else {
347
                return value;
348
            }
349
        }
350

    
351
    }
352
    private class FloatRowProcessor extends AbstractRowProcessor {
353

    
354
        public FloatRowProcessor(int band) {
355
            super(band);
356
        }
357

    
358
        @Override
359
        public void processRow(Object inputRow, Object outputRow) {
360
            float[] inputFloatRow = (float[])inputRow;
361
            float[] outputFloatRow = (float[])outputRow;
362
            for (int i = 0; i < inputFloatRow.length; i++) {
363
                outputFloatRow[i] = processValue(inputFloatRow[i]).floatValue();
364
            }
365
        }
366

    
367
        @Override
368
        public Number processValue(Number value) {
369
            if(noData.isDefined() && noData.getValue().equals(value)){
370
                return getOutputBuffer().getBand(band).getNoData().getValue();
371
            }
372
            float fValue = value.floatValue();
373

    
374
            if(fValue < minValue || fValue > maxValue){
375
                return getOutputBuffer().getBand(band).getNoData().getValue();
376
            } else {
377
                return value;
378
            }
379
        }
380

    
381
    }
382
    private class DoubleRowProcessor extends AbstractRowProcessor {
383

    
384

    
385
        public DoubleRowProcessor(int band) {
386
            super(band);
387
        }
388

    
389
        @Override
390
        public void processRow(Object inputRow, Object outputRow) {
391
            double[] inputByteRow = (double[])inputRow;
392
            double[] outputByteRow = (double[])outputRow;
393
            for (int i = 0; i < inputByteRow.length; i++) {
394
                outputByteRow[i] = processValue(inputByteRow[i]).doubleValue();
395
            }
396
        }
397

    
398
        @Override
399
        public Number processValue(Number value) {
400
            if(noData.isDefined() && noData.getValue().equals(value)){
401
                return getOutputBuffer().getBand(band).getNoData().getValue();
402
            }
403
            double fValue = value.doubleValue();
404

    
405
            if(fValue < minValue || fValue > maxValue){
406
                return getOutputBuffer().getBand(band).getNoData().getValue();
407
            } else {
408
                return value;
409
            }
410
        }
411
    }
412

    
413
}