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 / edgedetection / firstderivative / FirstDerivativeOperation.java @ 43803

History | View | Annotate | Download (24 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.edgedetection.firstderivative;
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 FirstDerivativeOperation extends AbstractSpecifiedBandsOperation{
49

    
50
    static final public String SOBEL_OPERATOR_STRING= "SOBEL";
51
    static final public String ROBERTS_OPERATOR_STRING= "ROBERTS";
52
    static final public String PREWITT_OPERATOR_STRING= "PREWITT";
53
    static final public String FREICHEN_OPERATOR_STRING= "FREICHEN";
54

    
55
    static public String OPERATOR_PARAM = "operator";
56
    static public String UMBRAL_PARAM = "umbral";
57
    static public String COMPARE_PARAM = "compare";
58

    
59
    private String operator;
60
    private int umbral;
61
    private boolean compare;
62
    private RowProcessor[] rowProcessors;
63
    private Kernel operatorH;
64
    private Kernel operatorV;
65

    
66
    static final private int SIDE_WINDOW = 3;
67
    static final private int HALF_SIDE_WINDOW = 1;
68

    
69

    
70
    // Kernels:------------------------------------------
71
    static final double     sobelH[][]      = {{-1,0,1},{-2,0,2},{-1,0,1}};
72
    static final double     sobelV[][]      = {{-1,-2,-1},{0,0,0},{1,2,1}};
73

    
74
    static final double     robertsH[][]    = {{0,0,-1},{0,1,0},{0,0,0}};
75
    static final double     robertsV[][]    = {{-1,0,0},{0,1,0},{0,0,0}};
76

    
77
    static final double     prewittH[][]    = {{1,0,-1},{1,0,-1},{1,0,-1}};
78
    static final double     prewittV[][]    = {{-1,-1,-1},{0,0,0},{1,1,1}};
79
    static final double     sqr2            = Math.sqrt(2);
80
//    static final double     freiChenH[][]   = {{-1,-sqr2,-1},{0,0,0},{1,sqr2,1}};
81
//    static final double     freiChenV[][]   = {{-1,0,1},{-sqr2,0,sqr2},{-1,0,1}};
82

    
83
    static final double     freiChenH[][]   = {{-1,-1.4D,-1},{0,0,0},{1,1.4D,1}};
84
    static final double     freiChenV[][]   = {{-1,0,1},{-1.4D,0,1.4D},{-1,0,1}};
85

    
86

    
87
    /**
88
     * @param factory
89
     *
90
     */
91
    public FirstDerivativeOperation(OperationFactory factory) {
92
        this.factory = factory;
93
    }
94

    
95
    @Override
96
    public void preProcess() throws BufferOperationException {
97
        super.preProcess();
98
        BufferManager manager = BufferLocator.getBufferManager();
99

    
100
        if(this.parameters.getDynClass().getDynField(OPERATOR_PARAM)!=null) {
101
            operator = (String)this.parameters.getDynValue(OPERATOR_PARAM);
102
        } else {
103
            operator = SOBEL_OPERATOR_STRING;
104
        };
105

    
106
        switch (operator) {
107
        case SOBEL_OPERATOR_STRING:
108
            operatorH = manager.createKernel(sobelH);
109
            operatorV = manager.createKernel(sobelV);
110
            break;
111
        case ROBERTS_OPERATOR_STRING:
112
            operatorH = manager.createKernel(robertsH);
113
            operatorV = manager.createKernel(robertsV);
114
            break;
115
        case PREWITT_OPERATOR_STRING:
116
            operatorH = manager.createKernel(prewittH);
117
            operatorV = manager.createKernel(prewittV);
118
            break;
119
        case FREICHEN_OPERATOR_STRING:
120
            operatorH = manager.createKernel(freiChenH);
121
            operatorV = manager.createKernel(freiChenV);
122
            break;
123
        }
124

    
125
        if(this.parameters.getDynClass().getDynField(COMPARE_PARAM)!=null) {
126
            compare = (Boolean)this.parameters.getDynValue(COMPARE_PARAM);
127
        } else {
128
            compare = false;
129
        };
130
        if(this.parameters.getDynClass().getDynField(UMBRAL_PARAM)!=null) {
131
            umbral = (Integer)this.parameters.getDynValue(UMBRAL_PARAM);
132
        } else {
133
            umbral = 0;
134
        };
135

    
136
        int bands = this.buffer.getBandCount();
137
        NoData[] noData = this.buffer.getBandNoData();
138
        if (copyUnprocessedBands) {
139
            try {
140
                this.outputBuffer =
141
                    manager.createBuffer(this.buffer.getRows(), this.buffer.getColumns(), this.buffer.getBandTypes(),
142
                        this.buffer.getBandNoData(), this.buffer.getProjection(), this.buffer.getEnvelope());
143
            } catch (LocatorException | BufferException | CreateEnvelopeException e) {
144
                throw new ProcessingOperationException(e);
145
            }
146
        } else {
147
            List<NoData> noDatas = new ArrayList<NoData>();
148
            List<Integer> types = new ArrayList<Integer>();
149
            for (int band = 0; band < bands; band++) {
150
                if (isProcessableBand(band)) {
151
                    if(this.buffer.getBandNoData()[band].isDefined()){
152
                        noDatas.add(manager.createNoData(0, 0));
153
                    } else {
154
                        noDatas.add(null);
155
                    }
156
                    types.add(BufferManager.TYPE_BYTE);
157
                }
158
            }
159
            int[] typesInt = new int[types.size()];
160
            for (Iterator<Integer> iterator = types.iterator(); iterator.hasNext();) {
161
                int i = 0;
162
                Integer type = (Integer) iterator.next();
163
                typesInt[i] = type.intValue();
164
            }
165
            try {
166
                this.outputBuffer =
167
                    manager.createBuffer(this.buffer.getRows(), this.buffer.getColumns(), typesInt,
168
                        noDatas.toArray(new NoData[0]), this.buffer.getProjection(), this.buffer.getEnvelope());
169
            } catch (LocatorException | BufferException | CreateEnvelopeException e) {
170
                throw new ProcessingOperationException(e);
171
            }
172
        }
173

    
174
        rowProcessors = new RowProcessor[bands];
175
        for (int band = 0; band < noData.length; band++) {
176
            if (isProcessableBand(band)) {
177
                int bandType = this.buffer.getBand(band).getDataType();
178
                switch (bandType) {
179
                case BufferManager.TYPE_BYTE:
180
                    rowProcessors[band] = new ByteRowProcessor(band);
181
                    break;
182
                case BufferManager.TYPE_USHORT:
183
                    rowProcessors[band] = new UShortRowProcessor(band);
184
                    break;
185
                case BufferManager.TYPE_SHORT:
186
                    rowProcessors[band] = new ShortRowProcessor(band);
187
                    break;
188
                case BufferManager.TYPE_INT:
189
                    rowProcessors[band] = new IntRowProcessor(band);
190
                    break;
191
                case BufferManager.TYPE_FLOAT:
192
                    rowProcessors[band] = new FloatRowProcessor(band);
193
                    break;
194
                case BufferManager.TYPE_DOUBLE:
195
                    rowProcessors[band] = new DoubleRowProcessor(band);
196
                    break;
197
                default:
198
                    throw new IllegalArgumentException("Unknow type of band '" + band + "'");
199
                }
200
            }
201
        }
202
        }
203

    
204
    @Override
205
    public void process() throws ProcessingOperationException {
206
        super.process();
207
        for (int band=0; band<this.buffer.getBandCount(); band++){
208
            if (bandsToProcess.contains(band)) {
209
                Band bufferBand = this.buffer.getBand(band);
210
                Band outputBufferBand = this.outputBuffer.getBand(band);
211

    
212
                for (int row = 0; row < this.buffer.getRows(); row++) {
213
                    Object rowBuffer = bufferBand.createRowBuffer();
214
                    bufferBand.fetchRow(row, rowBuffer);
215
                    List<Object> bundle = new ArrayList<Object>();
216
                    //FIXME: Solo se procesan aquellas filas en las que se pueden crear kernels, el resto ?qu? hacer? (ver abajo)
217
                    if ((row - HALF_SIDE_WINDOW >= 0) && (row + HALF_SIDE_WINDOW < this.buffer.getRows())) {
218
                        for (int r = Math.max(row - HALF_SIDE_WINDOW, 0); r <= Math.min(row + HALF_SIDE_WINDOW,
219
                            this.buffer.getRows()-1); r++) {
220
                            Object bundleRow = bufferBand.createRowBuffer();
221
                            bufferBand.fetchRow(r, bundleRow);
222
                            bundle.add(bundleRow);
223
                        }
224

    
225
                        Object outputRowBuffer = outputBufferBand.createRowBuffer();
226
                        // outputBufferBand.fetchRow(row, outputRowBuffer);
227

    
228
                        rowProcessors[band].processRow(rowBuffer, bundle, outputRowBuffer);
229

    
230
                        outputBufferBand.putRow(row, outputRowBuffer);
231
                    } else {
232
                        // FIXME: Si son de tipo BYTE, las copio, si no, no hacemos nada
233
                        if(this.buffer.getBandTypes()[band]==BufferManager.TYPE_BYTE){
234
                            outputBufferBand.putRow(row, rowBuffer);
235
                        }
236
                    }
237
                }
238
            } else {
239
                if(copyUnprocessedBands){
240
                    try {
241
                        this.outputBuffer.getBand(band).copyFrom(this.buffer.getBand(band));
242
                    } catch (BandException e) {
243
                        throw new ProcessingOperationException(e);
244
                    }
245
                }
246
            }
247
        }
248
    }
249

    
250
    @Override
251
    public void postProcess()  throws BufferOperationException {
252
        super.postProcess();
253
    }
254

    
255
    /**
256
     * @param band
257
     * @return
258
     */
259
    private boolean isProcessableBand(int band) {
260
        return bandsToProcess.contains(band);
261
    }
262

    
263

    
264
    interface RowProcessor {
265
        void processRow(Object inputRow, List<Object> bundleRow, Object outputRow);
266
        Number processValue(Kernel kernel);
267
    };
268

    
269
    private abstract class AbstractRowProcessor implements RowProcessor {
270
        int band;
271
        NoData noData;
272

    
273
        public AbstractRowProcessor(int band) {
274
            this.band = band;
275
            noData = buffer.getBand(band).getNoData();
276
        }
277

    
278
        @Override
279
        public Number processValue(Kernel kernel) {
280

    
281
            int convoResult[] = new int[4];
282
            int out;
283

    
284
            convoResult[0] = (int) operatorH.convolution(kernel);
285
            convoResult[1] = (int) operatorV.convolution(kernel);
286

    
287
            if (compare) {
288
                if (convoResult[0] > convoResult[1])
289
                    out = convoResult[0];
290
                else
291
                    out = convoResult[1];
292
            } else {
293
                out = (int) Math.sqrt(Math.pow(convoResult[0], 2) + Math.pow(convoResult[1], 2));
294
            }
295

    
296
            if (umbral > 0) {
297
                if (out >= (255 - umbral))
298
                    out = 255;
299
                else
300
                    out = 0;
301
            } else {
302
                if (out < 0)
303
                    out = 0;
304
                else if (out > 255)
305
                    out = 255;
306
            }
307

    
308
          return (byte)(out);
309
        }
310
    }
311

    
312
    private class ByteRowProcessor extends AbstractRowProcessor {
313

    
314

    
315
        public ByteRowProcessor(int band) {
316
            super(band);
317
        }
318

    
319
        @Override
320
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
321
            byte[] inputByteRow = (byte[])inputRow;
322
            byte[] outputByteRow = (byte[])outputRow;
323
            for (int i = 0; i < inputByteRow.length; i++) {
324
                // FIXME: Solo se procesan aquellas columnas en las que se pueden crear kernels, el resto ?se copian?
325
                if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputByteRow.length)) {
326
                    double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW];
327
                    int r=0;
328
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
329
                        int c=0;
330
                        byte[] row = (byte[]) iterator.next();
331
                        for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW,
332
                            inputByteRow.length-1); column++) {
333
                            byte value = ((Byte) row[column]).byteValue();
334
                            if (noData.isDefined() && noData.getValue().equals(value)) {
335
                                //FIXME: Si es noData, deber?a no influir en el resultado
336
                                // ?Que valor poner en el kernel?
337
                                k[r][c] = 0;
338
                            } else {
339
                                k[r][c] = (double)(0xFF & value);
340
                            }
341
                            c++;
342
                        }
343
                        r++;
344
                    }
345
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
346
                    if(noData.isDefined() && noData.getValue().equals(inputByteRow[i])){
347
                        outputByteRow[i] = inputByteRow[i];
348
                    } else {
349
                        outputByteRow[i] = processValue(kernel).byteValue();
350
                    }
351
                } else {
352
                    outputByteRow[i] = inputByteRow[i];
353
                }
354
            }
355
        }
356
    }
357

    
358
    private class ShortRowProcessor extends AbstractRowProcessor {
359

    
360
        public ShortRowProcessor(int band) {
361
            super(band);
362
        }
363

    
364
        @Override
365
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
366
            Number[] inputShortRow = (Number[])inputRow;
367
            byte[] outputByteRow = (byte[])outputRow;
368
            for (int i = 0; i < inputShortRow.length; i++) {
369
                //Solo se procesan aquellas columnas en las que se pueden crear kernels, el resto se copian
370
                if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputShortRow.length)) {
371
                    double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW];
372
                    int r=0;
373
                    int c=0;
374
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
375
                        short[] row = (short[]) iterator.next();
376
                        for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW,
377
                            inputShortRow.length-1); column++) {
378
                            double value = ((Short) row[c]).shortValue();
379
                            if (noData.isDefined() && noData.getValue().equals(value)) {
380
                                //FIXME: Si es noData, deber?a no influir en el resultado
381
                                // ?Que valor poner en el kernel?
382
                                k[r][c] = 0;
383
                            } else {
384
                                k[r][c] = value;
385
                            }
386
                        }
387
                    }
388
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
389
                    outputByteRow[i] = processValue(kernel).byteValue();
390
                } else {
391
                    outputByteRow[i] = ((Short)inputShortRow[i]).byteValue();
392
                }
393
            }
394
        }
395

    
396
    }
397

    
398
    private class UShortRowProcessor extends AbstractRowProcessor {
399

    
400
        public UShortRowProcessor(int band) {
401
            super(band);
402
        }
403

    
404
        @Override
405
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
406

    
407
            Number[] inputShortRow = (Number[]) inputRow;
408
            byte[] outputByteRow = (byte[]) outputRow;
409
            for (int i = 0; i < inputShortRow.length; i++) {
410
                // Solo se procesan aquellas columnas en las que se pueden crear
411
                // kernels, el resto se copian
412
                if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputShortRow.length)) {
413
                    double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW];
414
                    int r = 0;
415
                    int c = 0;
416
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
417
                        short[] row = (short[]) iterator.next();
418
                        for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW,
419
                            inputShortRow.length-1); column++) {
420
                            double value = 0xFFFF & ((Short) row[c]).shortValue();
421
                            if (noData.isDefined() && noData.getValue().equals(value)) {
422
                                // FIXME: Si es noData, deber?a no influir en el
423
                                // resultado
424
                                // ?Que valor poner en el kernel?
425
                                k[r][c] = 0;
426
                            } else {
427
                                k[r][c] = value;
428
                            }
429
                        }
430
                    }
431
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
432
                    outputByteRow[i] = processValue(kernel).byteValue();
433
                } else {
434
                    outputByteRow[i] = ((Short) inputShortRow[i]).byteValue();
435
                }
436
            }
437
        }
438
    }
439

    
440
    private class IntRowProcessor extends AbstractRowProcessor {
441

    
442

    
443
        public IntRowProcessor(int band) {
444
            super(band);
445
        }
446

    
447
        @Override
448
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
449
            Number[] inputIntRow = (Number[])inputRow;
450
            byte[] outputByteRow = (byte[]) outputRow;
451
            for (int i = 0; i < inputIntRow.length; i++) {
452
                // Solo se procesan aquellas columnas en las que se pueden crear
453
                // kernels, el resto se copian
454
                if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputIntRow.length)) {
455
                    double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW];
456
                    int r = 0;
457
                    int c = 0;
458
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
459
                        int[] row = (int[]) iterator.next();
460
                        for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW,
461
                            inputIntRow.length-1); column++) {
462
                            double value = ((Integer) row[c]).intValue();
463
                            if (noData.isDefined() && noData.getValue().equals(value)) {
464
                                // FIXME: Si es noData, deber?a no influir en el
465
                                // resultado
466
                                // ?Que valor poner en el kernel?
467
                                k[r][c] = 0;
468
                            } else {
469
                                k[r][c] = value;
470
                            }
471
                        }
472
                    }
473
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
474
                    outputByteRow[i] = processValue(kernel).byteValue();
475
                } else {
476
                    outputByteRow[i] = ((Integer) inputIntRow[i]).byteValue();
477
                }
478
            }
479
        }
480
    }
481
    private class FloatRowProcessor extends AbstractRowProcessor {
482

    
483

    
484
        public FloatRowProcessor(int band) {
485
            super(band);
486
        }
487

    
488
        @Override
489
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
490
            Number[] inputFloatRow = (Number[])inputRow;
491
            byte[] outputByteRow = (byte[]) outputRow;
492
            for (int i = 0; i < inputFloatRow.length; i++) {
493
                // Solo se procesan aquellas columnas en las que se pueden crear
494
                // kernels, el resto se copian
495
                if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputFloatRow.length)) {
496
                    double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW];
497
                    int r = 0;
498
                    int c = 0;
499
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
500
                        float[] row = (float[]) iterator.next();
501
                        for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW,
502
                            inputFloatRow.length-1); column++) {
503
                            Float value = ((Float) row[c]).floatValue();
504
                            if (noData.isDefined() && noData.getValue().equals(value)) {
505
                                // FIXME: Si es noData, deber?a no influir en el
506
                                // resultado
507
                                // ?Que valor poner en el kernel?
508
                                k[r][c] = 0;
509
                            } else {
510
                                k[r][c] = value;
511
                            }
512
                        }
513
                    }
514
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
515
                    outputByteRow[i] = processValue(kernel).byteValue();
516
                } else {
517
                    outputByteRow[i] = ((Float) inputFloatRow[i]).byteValue();
518
                }
519
            }
520
        }
521
    }
522
    private class DoubleRowProcessor extends AbstractRowProcessor {
523

    
524

    
525
        public DoubleRowProcessor(int band) {
526
            super(band);
527
        }
528

    
529
        @Override
530
        public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) {
531
            Number[] inputDoubleRow = (Number[])inputRow;
532
            byte[] outputByteRow = (byte[]) outputRow;
533
            for (int i = 0; i < inputDoubleRow.length; i++) {
534
                // Solo se procesan aquellas columnas en las que se pueden crear
535
                // kernels, el resto se copian
536
                if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputDoubleRow.length)) {
537
                    double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW];
538
                    int r = 0;
539
                    int c = 0;
540
                    for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) {
541
                        double[] row = (double[]) iterator.next();
542
                        for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW,
543
                            inputDoubleRow.length-1); column++) {
544
                            Double value = ((Double) row[c]).doubleValue();
545
                            if (noData.isDefined() && noData.getValue().equals(value)) {
546
                                // FIXME: Si es noData, deber?a no influir en el resultado
547
                                // ?Que valor poner en el kernel?
548
                                k[r][c] = 0;
549
                            } else {
550
                                k[r][c] = value;
551
                            }
552
                        }
553
                    }
554
                    Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
555
                    outputByteRow[i] = processValue(kernel).byteValue();
556
                } else {
557
                    outputByteRow[i] = ((Double) inputDoubleRow[i]).byteValue();
558
                }
559
            }
560
        }
561
    }
562
}