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 / convolution / ConvolutionOperation.java @ 43835

History | View | Annotate | Download (25.9 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.convolution;
24

    
25
import java.util.ArrayList;
26
import java.util.Iterator;
27
import java.util.List;
28

    
29
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
30
import org.gvsig.raster.lib.buffer.api.Band;
31
import org.gvsig.raster.lib.buffer.api.BufferLocator;
32
import org.gvsig.raster.lib.buffer.api.BufferManager;
33
import org.gvsig.raster.lib.buffer.api.Kernel;
34
import org.gvsig.raster.lib.buffer.api.NoData;
35
import org.gvsig.raster.lib.buffer.api.exceptions.BandException;
36
import org.gvsig.raster.lib.buffer.api.exceptions.BufferException;
37
import org.gvsig.raster.lib.buffer.api.exceptions.BufferOperationException;
38
import org.gvsig.raster.lib.buffer.api.operations.OperationFactory;
39
import org.gvsig.raster.lib.buffer.spi.exceptions.ProcessingOperationException;
40
import org.gvsig.raster.lib.buffer.spi.operations.AbstractSpecifiedBandsOperation;
41
import org.gvsig.tools.locator.LocatorException;
42

    
43

    
44
/**
45
 * @author fdiaz
46
 *
47
 */
48
public class ConvolutionOperation extends AbstractSpecifiedBandsOperation{
49

    
50

    
51
    static final public String AVERAGE_OPERATOR_STRING= "AVERAGE";
52
    static final public String LOW_PASS_OPERATOR_STRING= "LOW_PASS";
53
    static final public String HIGH_PASS_OPERATOR_STRING= "HIGH_PASS";
54
    static final public String GAUSS_OPERATOR_STRING= "GAUSS";
55
    static final public String CUSTOM_OPERATOR_STRING= "CUSTOM";
56

    
57
    static public String OPERATOR_PARAM = "operator";
58
    static public String CUSTOM_KERNEL_PARAM = "custom_kernel";
59
    static public String SHARPNESS_PARAM = "sharpness";
60
    static public String SIDE_WINDOW_PARAM = "side_window";
61

    
62
    private String operator;
63
    private int sideWindow;
64
    private int halfSideWindow;
65
    private double sharpness;
66
    private RowProcessor[] rowProcessors;
67
    private Kernel kernelOperator;
68

    
69
    // Kernels:------------------------------------------
70
    static final double        gauss3x3[][]    = {{1,4,1},{4,12,4},{1,4,1}};
71
    static final double        gauss5x5[][]    = {{1,2,3,2,1},{2,7,11,7,2},{3,11,17,11,3},{2,7,11,7,2},{1,2,3,2,1}};
72
    static final double        gauss7x7[][]    = {{1,1,2,2,2,1,1},{1,2,2,4,2,2,1},{2,2,4,8,4,2,2},{2,4,8,16,8,4,2},{2,2,4,8,4,2,2},{1,2,2,4,2,2,1},{1,1,2,2,2,1,1}};
73
    static final double        gauss7x7aux[][] = {{0,0,0.0003,0.0006,0.0003,0,0},{0,0.0011,0.0079,0.0153,0.0079,0.0011,0},{0.0003,0.0079,0.0563,0.1082,0.0563,0.0079,0.0003},{0.0006,0.0153,0.1082,0.2079,0.1082,0.0153,0.0006},{0.0003,0.0079,0.0563,0.1082,0.0563,0.0079,0.0003},{0,0.0011,0.0079,0.0153,0.0079,0.0011,0},{0,0,0.0003,0.0006,0.0003,0,0}};
74
    static final double        lowpass3x3[][]  = {{0,1,0},{1,6,1},{0,1,0}};
75
    static final double        lowpass5x5[][]  = {{1,1,1,1,1},{1,4,4,4,1},{1,4,12,4,1},{1,4,4,4,1},{1,1,1,1,1}};
76
    static final double        media3x3[][]    = {{1,1,1},{1,1,1},{1,1,1}};
77
    static final double        media5x5[][]    = {{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1},{1,1,1,1,1}};
78
    static final double        media7x7[][]    = {{1,1,1,1,1,1,1},{1,1,1,1,1,1,1},{1,1,1,1,1,1,1},{1,1,1,1,1,1,1},{1,1,1,1,1,1,1},{1,1,1,1,1,1,1},{1,1,1,1,1,1,1}};
79
    static final double        highpass3x3[][] = {{-1,-1,-1},{-1,9,-1},{-1,-1,-1}};
80

    
81
    /**
82
     * @param factory
83
     *
84
     */
85
    public ConvolutionOperation(OperationFactory factory) {
86
        this.factory = factory;
87
    }
88

    
89
    @Override
90
    public void preProcess() throws BufferOperationException {
91
        super.preProcess();
92
        BufferManager manager = BufferLocator.getBufferManager();
93

    
94
        if(this.parameters.getDynClass().getDynField(SIDE_WINDOW_PARAM)!=null) {
95
            sideWindow = (Integer)this.parameters.getDynValue(SIDE_WINDOW_PARAM);
96
        } else {
97
            sideWindow = 3;
98
        };
99
        halfSideWindow = (int)(sideWindow/2);
100

    
101

    
102
        if(this.parameters.getDynClass().getDynField(SHARPNESS_PARAM)!=null) {
103
            sharpness = (Double)this.parameters.getDynValue(SHARPNESS_PARAM);
104
        } else {
105
            sharpness = 0;
106
        };
107

    
108
        if(this.parameters.getDynClass().getDynField(OPERATOR_PARAM)!=null) {
109
            operator = (String)this.parameters.getDynValue(OPERATOR_PARAM);
110
        } else {
111
            operator = AVERAGE_OPERATOR_STRING;
112
        };
113

    
114
        switch (operator) {
115
        case AVERAGE_OPERATOR_STRING:
116
            switch (sideWindow) {
117
            case 3:
118
                kernelOperator = manager.createKernel(media3x3,9);
119
                break;
120
            case 5:
121
                kernelOperator = manager.createKernel(media5x5,25);
122
                break;
123
            case 7:
124
                kernelOperator = manager.createKernel(media7x7,49);
125
                break;
126
            default:
127
                throw new IllegalArgumentException("Kernel side isn't valid for the selected operator.");
128
            }
129
            break;
130
        case LOW_PASS_OPERATOR_STRING:
131
            switch (sideWindow) {
132
            case 3:
133
                kernelOperator = manager.createKernel(lowpass3x3,10);
134
                break;
135
            case 5:
136
                kernelOperator = manager.createKernel(lowpass5x5);
137
                break;
138
            default:
139
                throw new IllegalArgumentException("Kernel side isn't valid for the selected operator.");
140
            }
141
            break;
142
        case HIGH_PASS_OPERATOR_STRING:
143
            switch (sideWindow) {
144
            case 3:
145
                double[][] h = new double[3][3];
146
                for (int i = 0; i < h.length; i++) {
147
                    for (int j = 0; j < h[i].length; j++) {
148
                        h[i][j] = highpass3x3[i][j];
149
                    }
150
                }
151
                h[1][1] = 29 - (sharpness * 20.9) / 100;
152

    
153
                kernelOperator = manager.createKernel(h);
154
                break;
155
            default:
156
                throw new IllegalArgumentException("Kernel side isn't valid for the selected operator.");
157
            }
158
            break;
159
        case GAUSS_OPERATOR_STRING:
160
            switch (sideWindow) {
161
            case 3:
162
                kernelOperator = manager.createKernel(gauss3x3,34);
163
                break;
164
            case 5:
165
                kernelOperator = manager.createKernel(gauss5x5,121);
166
                break;
167
            case 7:
168
                kernelOperator = manager.createKernel(gauss7x7aux);
169
                break;
170
            default:
171
                throw new IllegalArgumentException("Kernel side isn't valid for the selected operator.");
172
            }
173
            break;
174
        case CUSTOM_OPERATOR_STRING:
175
            if(this.parameters.getDynClass().getDynField(CUSTOM_KERNEL_PARAM)!=null) {
176
                kernelOperator = (Kernel)this.parameters.getDynValue(CUSTOM_KERNEL_PARAM);
177
            } else {
178
                throw new IllegalArgumentException("A Kernel is needed for the selected operator.");
179
            };
180
            if(kernelOperator==null || kernelOperator.getSide()!=sideWindow){
181
                throw new IllegalArgumentException("Kernel side incorrect.");
182
            };
183
            break;
184
        }
185

    
186
        int bands = this.buffer.getBandCount();
187
        NoData[] noData = this.buffer.getBandNoData();
188
        if (copyUnprocessedBands) {
189
            try {
190
                this.outputBuffer =
191
                    manager.createBuffer(this.buffer.getRows(), this.buffer.getColumns(), this.buffer.getBandTypes(),
192
                        this.buffer.getBandNoData(), this.buffer.getProjection(), this.buffer.getEnvelope());
193
            } catch (LocatorException | BufferException | CreateEnvelopeException e) {
194
                throw new ProcessingOperationException(e);
195
            }
196
        } else {
197
            List<NoData> noDatas = new ArrayList<NoData>();
198
            List<Integer> types = new ArrayList<Integer>();
199
            for (int band = 0; band < bands; band++) {
200
                if (isProcessableBand(band)) {
201
                    if(this.buffer.getBandNoData()[band].isDefined()){
202
                        noDatas.add(manager.createNoData(0, 0));
203
                    } else {
204
                        noDatas.add(null);
205
                    }
206
                    types.add(BufferManager.TYPE_BYTE);
207
                }
208
            }
209
            int[] typesInt = new int[types.size()];
210
            for (Iterator<Integer> iterator = types.iterator(); iterator.hasNext();) {
211
                int i = 0;
212
                Integer type = (Integer) iterator.next();
213
                typesInt[i] = type.intValue();
214
            }
215
            try {
216
                this.outputBuffer =
217
                    manager.createBuffer(this.buffer.getRows(), this.buffer.getColumns(), typesInt,
218
                        noDatas.toArray(new NoData[0]), this.buffer.getProjection(), this.buffer.getEnvelope());
219
            } catch (LocatorException | BufferException | CreateEnvelopeException e) {
220
                throw new ProcessingOperationException(e);
221
            }
222
        }
223

    
224
        rowProcessors = new RowProcessor[bands];
225
        for (int band = 0; band < noData.length; band++) {
226
            if (isProcessableBand(band)) {
227
                int bandType = this.buffer.getBand(band).getDataType();
228
                switch (bandType) {
229
                case BufferManager.TYPE_BYTE:
230
                    rowProcessors[band] = new ByteRowProcessor(band);
231
                    break;
232
                case BufferManager.TYPE_USHORT:
233
                    rowProcessors[band] = new UShortRowProcessor(band);
234
                    break;
235
                case BufferManager.TYPE_SHORT:
236
                    rowProcessors[band] = new ShortRowProcessor(band);
237
                    break;
238
                case BufferManager.TYPE_INT:
239
                    rowProcessors[band] = new IntRowProcessor(band);
240
                    break;
241
                case BufferManager.TYPE_FLOAT:
242
                    rowProcessors[band] = new FloatRowProcessor(band);
243
                    break;
244
                case BufferManager.TYPE_DOUBLE:
245
                    rowProcessors[band] = new DoubleRowProcessor(band);
246
                    break;
247
                default:
248
                    throw new IllegalArgumentException("Unknow type of band '" + band + "'");
249
                }
250
            }
251
        }
252
        }
253

    
254
    @Override
255
    public void process() throws ProcessingOperationException {
256
        super.process();
257
        for (int band=0; band<this.buffer.getBandCount(); band++){
258
            if (bandsToProcess.contains(band)) {
259
                Band bufferBand = this.buffer.getBand(band);
260
                Band outputBufferBand = this.outputBuffer.getBand(band);
261

    
262
                for (int row = 0; row < this.buffer.getRows(); row++) {
263
                    Object rowBuffer = bufferBand.createRowBuffer();
264
                    bufferBand.fetchRow(row, rowBuffer);
265
                    List<Object> bundle = new ArrayList<Object>();
266
                    //FIXME: Solo se procesan aquellas filas en las que se pueden crear kernels, el resto ?qu? hacer? (ver abajo)
267
                    if ((row - halfSideWindow >= 0) && (row + halfSideWindow < this.buffer.getRows())) {
268
                        for (int r = Math.max(row - halfSideWindow, 0); r <= Math.min(row + halfSideWindow,
269
                            this.buffer.getRows()-1); r++) {
270
                            Object bundleRow = bufferBand.createRowBuffer();
271
                            bufferBand.fetchRow(r, bundleRow);
272
                            bundle.add(bundleRow);
273
                        }
274

    
275
                        Object outputRowBuffer = outputBufferBand.createRowBuffer();
276
                        // outputBufferBand.fetchRow(row, outputRowBuffer);
277

    
278
                        rowProcessors[band].processRow(rowBuffer, bundle, outputRowBuffer);
279

    
280
                        outputBufferBand.putRow(row, outputRowBuffer);
281
                    } else {
282
                        // FIXME: Si son de tipo BYTE, las copio, si no, no hacemos nada
283
                        if(this.buffer.getBandTypes()[band]==BufferManager.TYPE_BYTE){
284
                            outputBufferBand.putRow(row, rowBuffer);
285
                        }
286
                    }
287
                }
288
            } else {
289
                if(copyUnprocessedBands){
290
                    try {
291
                        this.outputBuffer.getBand(band).copyFrom(this.buffer.getBand(band));
292
                    } catch (BandException e) {
293
                        throw new ProcessingOperationException(e);
294
                    }
295
                }
296
            }
297
        }
298
    }
299

    
300
    @Override
301
    public void postProcess()  throws BufferOperationException {
302
        super.postProcess();
303
    }
304

    
305
    interface RowProcessor {
306
        void processRow(Object inputRow, List<Object> bundleRow, Object outputRow);
307
        Number processValue(Kernel kernel);
308
    };
309

    
310
    private abstract class AbstractRowProcessor implements RowProcessor {
311
        int band;
312
        NoData noData;
313

    
314
        public AbstractRowProcessor(int band) {
315
            this.band = band;
316
            noData = buffer.getBand(band).getNoData();
317
        }
318

    
319
        @Override
320
        public Number processValue(Kernel kernel) {
321

    
322
            double resultConvolution = kernelOperator.convolution(kernel);
323
            if (resultConvolution > 255) {
324
                resultConvolution = 255;
325
            } else if (resultConvolution < 0) {
326
                resultConvolution = 0;
327
            }
328
          return (byte)(resultConvolution);
329
        }
330
    }
331

    
332
    private class ByteRowProcessor extends AbstractRowProcessor {
333

    
334

    
335
        public ByteRowProcessor(int band) {
336
            super(band);
337
        }
338

    
339
        @Override
340
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
341
            byte[] inputByteRow = (byte[])inputRow;
342
            byte[] outputByteRow = (byte[])outputRow;
343
            for (int i = 0; i < inputByteRow.length; i++) {
344
                // FIXME: Solo se procesan aquellas columnas en las que se pueden crear kernels, el resto ?se copian?
345
                if ((i - halfSideWindow >= 0) && (i + halfSideWindow < inputByteRow.length)) {
346
                    double[][] k = new double[sideWindow][sideWindow];
347
                    int r=0;
348
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
349
                        int c=0;
350
                        byte[] row = (byte[]) iterator.next();
351
                        for (int column = Math.max(i - halfSideWindow, 0); column <= Math.min(i + halfSideWindow,
352
                            inputByteRow.length-1); column++) {
353
                            byte value = ((Byte) row[column]).byteValue();
354
                            if (noData.isDefined() && noData.getValue().equals(value)) {
355
                                //FIXME: Si es noData, deber?a no influir en el resultado
356
                                // ?Que valor poner en el kernel?
357
                                k[r][c] = 0;
358
                            } else {
359
                                k[r][c] = (double)(0xFF & value);
360
                            }
361
                            c++;
362
                        }
363
                        r++;
364
                    }
365
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
366
                    if(noData.isDefined() && noData.getValue().equals(inputByteRow[i])){
367
                        outputByteRow[i] = inputByteRow[i];
368
                    } else {
369
                        outputByteRow[i] = processValue(kernel).byteValue();
370
                    }
371
                } else {
372
                    outputByteRow[i] = inputByteRow[i];
373
                }
374
            }
375
        }
376
    }
377

    
378
    private class ShortRowProcessor extends AbstractRowProcessor {
379

    
380
        public ShortRowProcessor(int band) {
381
            super(band);
382
        }
383

    
384
        @Override
385
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
386
            Number[] inputShortRow = (Number[])inputRow;
387
            byte[] outputByteRow = (byte[])outputRow;
388
            for (int i = 0; i < inputShortRow.length; i++) {
389
                //Solo se procesan aquellas columnas en las que se pueden crear kernels, el resto se copian
390
                if ((i - halfSideWindow >= 0) && (i + halfSideWindow < inputShortRow.length)) {
391
                    double[][] k = new double[sideWindow][sideWindow];
392
                    int r=0;
393
                    int c=0;
394
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
395
                        short[] row = (short[]) iterator.next();
396
                        for (int column = Math.max(i - halfSideWindow, 0); column <= Math.min(i + halfSideWindow,
397
                            inputShortRow.length-1); column++) {
398
                            double value = ((Short) row[c]).shortValue();
399
                            if (noData.isDefined() && noData.getValue().equals(value)) {
400
                                //FIXME: Si es noData, deber?a no influir en el resultado
401
                                // ?Que valor poner en el kernel?
402
                                k[r][c] = 0;
403
                            } else {
404
                                k[r][c] = value;
405
                            }
406
                        }
407
                    }
408
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
409
                    outputByteRow[i] = processValue(kernel).byteValue();
410
                } else {
411
                    outputByteRow[i] = ((Short)inputShortRow[i]).byteValue();
412
                }
413
            }
414
        }
415

    
416
    }
417

    
418
    private class UShortRowProcessor extends AbstractRowProcessor {
419

    
420
        public UShortRowProcessor(int band) {
421
            super(band);
422
        }
423

    
424
        @Override
425
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
426

    
427
            Number[] inputShortRow = (Number[]) inputRow;
428
            byte[] outputByteRow = (byte[]) outputRow;
429
            for (int i = 0; i < inputShortRow.length; i++) {
430
                // Solo se procesan aquellas columnas en las que se pueden crear
431
                // kernels, el resto se copian
432
                if ((i - halfSideWindow >= 0) && (i + halfSideWindow < inputShortRow.length)) {
433
                    double[][] k = new double[sideWindow][sideWindow];
434
                    int r = 0;
435
                    int c = 0;
436
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
437
                        short[] row = (short[]) iterator.next();
438
                        for (int column = Math.max(i - halfSideWindow, 0); column <= Math.min(i + halfSideWindow,
439
                            inputShortRow.length-1); column++) {
440
                            double value = 0xFFFF & ((Short) row[c]).shortValue();
441
                            if (noData.isDefined() && noData.getValue().equals(value)) {
442
                                // FIXME: Si es noData, deber?a no influir en el
443
                                // resultado
444
                                // ?Que valor poner en el kernel?
445
                                k[r][c] = 0;
446
                            } else {
447
                                k[r][c] = value;
448
                            }
449
                        }
450
                    }
451
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
452
                    outputByteRow[i] = processValue(kernel).byteValue();
453
                } else {
454
                    outputByteRow[i] = ((Short) inputShortRow[i]).byteValue();
455
                }
456
            }
457
        }
458
    }
459

    
460
    private class IntRowProcessor extends AbstractRowProcessor {
461

    
462

    
463
        public IntRowProcessor(int band) {
464
            super(band);
465
        }
466

    
467
        @Override
468
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
469
            Number[] inputIntRow = (Number[])inputRow;
470
            byte[] outputByteRow = (byte[]) outputRow;
471
            for (int i = 0; i < inputIntRow.length; i++) {
472
                // Solo se procesan aquellas columnas en las que se pueden crear
473
                // kernels, el resto se copian
474
                if ((i - halfSideWindow >= 0) && (i + halfSideWindow < inputIntRow.length)) {
475
                    double[][] k = new double[sideWindow][sideWindow];
476
                    int r = 0;
477
                    int c = 0;
478
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
479
                        int[] row = (int[]) iterator.next();
480
                        for (int column = Math.max(i - halfSideWindow, 0); column <= Math.min(i + halfSideWindow,
481
                            inputIntRow.length-1); column++) {
482
                            double value = ((Integer) row[c]).intValue();
483
                            if (noData.isDefined() && noData.getValue().equals(value)) {
484
                                // FIXME: Si es noData, deber?a no influir en el
485
                                // resultado
486
                                // ?Que valor poner en el kernel?
487
                                k[r][c] = 0;
488
                            } else {
489
                                k[r][c] = value;
490
                            }
491
                        }
492
                    }
493
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
494
                    outputByteRow[i] = processValue(kernel).byteValue();
495
                } else {
496
                    outputByteRow[i] = ((Integer) inputIntRow[i]).byteValue();
497
                }
498
            }
499
        }
500
    }
501
    private class FloatRowProcessor extends AbstractRowProcessor {
502

    
503

    
504
        public FloatRowProcessor(int band) {
505
            super(band);
506
        }
507

    
508
        @Override
509
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
510
            Number[] inputFloatRow = (Number[])inputRow;
511
            byte[] outputByteRow = (byte[]) outputRow;
512
            for (int i = 0; i < inputFloatRow.length; i++) {
513
                // Solo se procesan aquellas columnas en las que se pueden crear
514
                // kernels, el resto se copian
515
                if ((i - halfSideWindow >= 0) && (i + halfSideWindow < inputFloatRow.length)) {
516
                    double[][] k = new double[sideWindow][sideWindow];
517
                    int r = 0;
518
                    int c = 0;
519
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
520
                        float[] row = (float[]) iterator.next();
521
                        for (int column = Math.max(i - halfSideWindow, 0); column <= Math.min(i + halfSideWindow,
522
                            inputFloatRow.length-1); column++) {
523
                            Float value = ((Float) row[c]).floatValue();
524
                            if (noData.isDefined() && noData.getValue().equals(value)) {
525
                                // FIXME: Si es noData, deber?a no influir en el
526
                                // resultado
527
                                // ?Que valor poner en el kernel?
528
                                k[r][c] = 0;
529
                            } else {
530
                                k[r][c] = value;
531
                            }
532
                        }
533
                    }
534
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
535
                    outputByteRow[i] = processValue(kernel).byteValue();
536
                } else {
537
                    outputByteRow[i] = ((Float) inputFloatRow[i]).byteValue();
538
                }
539
            }
540
        }
541
    }
542
    private class DoubleRowProcessor extends AbstractRowProcessor {
543

    
544

    
545
        public DoubleRowProcessor(int band) {
546
            super(band);
547
        }
548

    
549
        @Override
550
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
551
            Number[] inputDoubleRow = (Number[])inputRow;
552
            byte[] outputByteRow = (byte[]) outputRow;
553
            for (int i = 0; i < inputDoubleRow.length; i++) {
554
                // Solo se procesan aquellas columnas en las que se pueden crear
555
                // kernels, el resto se copian
556
                if ((i - halfSideWindow >= 0) && (i + halfSideWindow < inputDoubleRow.length)) {
557
                    double[][] k = new double[sideWindow][sideWindow];
558
                    int r = 0;
559
                    int c = 0;
560
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
561
                        double[] row = (double[]) iterator.next();
562
                        for (int column = Math.max(i - halfSideWindow, 0); column <= Math.min(i + halfSideWindow,
563
                            inputDoubleRow.length-1); column++) {
564
                            Double value = ((Double) row[c]).doubleValue();
565
                            if (noData.isDefined() && noData.getValue().equals(value)) {
566
                                // FIXME: Si es noData, deber?a no influir en el resultado
567
                                // ?Que valor poner en el kernel?
568
                                k[r][c] = 0;
569
                            } else {
570
                                k[r][c] = value;
571
                            }
572
                        }
573
                    }
574
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
575
                    outputByteRow[i] = processValue(kernel).byteValue();
576
                } else {
577
                    outputByteRow[i] = ((Double) inputDoubleRow[i]).byteValue();
578
                }
579
            }
580
        }
581
    }
582
}