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 @ 43864
History | View | Annotate | Download (23.2 KB)
1 | 43803 | fdiaz | /* 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 | 43864 | jjdelcerro | super(factory);
|
93 | 43803 | fdiaz | } |
94 | |||
95 | @Override
|
||
96 | public void preProcess() throws BufferOperationException { |
||
97 | super.preProcess();
|
||
98 | BufferManager manager = BufferLocator.getBufferManager(); |
||
99 | |||
100 | 43864 | jjdelcerro | operator = (String) this.getParameter(OPERATOR_PARAM, SOBEL_OPERATOR_STRING); |
101 | |||
102 | 43803 | fdiaz | switch (operator) {
|
103 | case SOBEL_OPERATOR_STRING:
|
||
104 | operatorH = manager.createKernel(sobelH); |
||
105 | operatorV = manager.createKernel(sobelV); |
||
106 | break;
|
||
107 | case ROBERTS_OPERATOR_STRING:
|
||
108 | operatorH = manager.createKernel(robertsH); |
||
109 | operatorV = manager.createKernel(robertsV); |
||
110 | break;
|
||
111 | case PREWITT_OPERATOR_STRING:
|
||
112 | operatorH = manager.createKernel(prewittH); |
||
113 | operatorV = manager.createKernel(prewittV); |
||
114 | break;
|
||
115 | case FREICHEN_OPERATOR_STRING:
|
||
116 | operatorH = manager.createKernel(freiChenH); |
||
117 | operatorV = manager.createKernel(freiChenV); |
||
118 | break;
|
||
119 | } |
||
120 | |||
121 | 43864 | jjdelcerro | compare = (boolean) this.getParameter(COMPARE_PARAM, false); |
122 | umbral = (int) this.getParameter(UMBRAL_PARAM, 0); |
||
123 | 43803 | fdiaz | |
124 | 43864 | jjdelcerro | int bands = this.getInputBuffer().getBandCount(); |
125 | NoData[] noData = this.getInputBuffer().getBandNoData(); |
||
126 | if (mustCopyUnprocessedBands()) {
|
||
127 | 43803 | fdiaz | try {
|
128 | 43864 | jjdelcerro | this.setOutputBuffer(
|
129 | manager.createBuffer( |
||
130 | this.getInputBuffer().getRows(),
|
||
131 | this.getInputBuffer().getColumns(),
|
||
132 | this.getInputBuffer().getBandTypes(),
|
||
133 | this.getInputBuffer().getBandNoData(),
|
||
134 | this.getInputBuffer().getProjection(),
|
||
135 | this.getInputBuffer().getEnvelope()));
|
||
136 | 43803 | fdiaz | } catch (LocatorException | BufferException | CreateEnvelopeException e) {
|
137 | throw new ProcessingOperationException(e); |
||
138 | } |
||
139 | } else {
|
||
140 | try {
|
||
141 | 43864 | jjdelcerro | this.setOutputBuffer(
|
142 | manager.createBuffer( |
||
143 | this.getInputBuffer().getRows(),
|
||
144 | this.getInputBuffer().getColumns(),
|
||
145 | this.getProcessableBandTypesAsArray(),
|
||
146 | this.getProcessableBandNoDatasAsArray(),
|
||
147 | this.getInputBuffer().getProjection(),
|
||
148 | this.getInputBuffer().getEnvelope()));
|
||
149 | 43803 | fdiaz | } catch (LocatorException | BufferException | CreateEnvelopeException e) {
|
150 | throw new ProcessingOperationException(e); |
||
151 | } |
||
152 | } |
||
153 | |||
154 | rowProcessors = new RowProcessor[bands];
|
||
155 | for (int band = 0; band < noData.length; band++) { |
||
156 | if (isProcessableBand(band)) {
|
||
157 | 43864 | jjdelcerro | int bandType = this.getInputBuffer().getBand(band).getDataType(); |
158 | 43803 | fdiaz | switch (bandType) {
|
159 | case BufferManager.TYPE_BYTE:
|
||
160 | rowProcessors[band] = new ByteRowProcessor(band);
|
||
161 | break;
|
||
162 | case BufferManager.TYPE_USHORT:
|
||
163 | rowProcessors[band] = new UShortRowProcessor(band);
|
||
164 | break;
|
||
165 | case BufferManager.TYPE_SHORT:
|
||
166 | rowProcessors[band] = new ShortRowProcessor(band);
|
||
167 | break;
|
||
168 | case BufferManager.TYPE_INT:
|
||
169 | rowProcessors[band] = new IntRowProcessor(band);
|
||
170 | break;
|
||
171 | case BufferManager.TYPE_FLOAT:
|
||
172 | rowProcessors[band] = new FloatRowProcessor(band);
|
||
173 | break;
|
||
174 | case BufferManager.TYPE_DOUBLE:
|
||
175 | rowProcessors[band] = new DoubleRowProcessor(band);
|
||
176 | break;
|
||
177 | default:
|
||
178 | throw new IllegalArgumentException("Unknow type of band '" + band + "'"); |
||
179 | } |
||
180 | } |
||
181 | } |
||
182 | } |
||
183 | |||
184 | @Override
|
||
185 | public void process() throws ProcessingOperationException { |
||
186 | super.process();
|
||
187 | 43864 | jjdelcerro | for (int band=0; band<this.getInputBuffer().getBandCount(); band++){ |
188 | if (getBandsToProcess().contains(band)) {
|
||
189 | Band bufferBand = this.getInputBuffer().getBand(band);
|
||
190 | Band outputBufferBand = this.getOutputBuffer().getBand(band);
|
||
191 | 43803 | fdiaz | |
192 | 43864 | jjdelcerro | for (int row = 0; row < this.getInputBuffer().getRows(); row++) { |
193 | 43803 | fdiaz | Object rowBuffer = bufferBand.createRowBuffer();
|
194 | bufferBand.fetchRow(row, rowBuffer); |
||
195 | 43864 | jjdelcerro | List<Object> bundle = new ArrayList<>(); |
196 | 43803 | fdiaz | //FIXME: Solo se procesan aquellas filas en las que se pueden crear kernels, el resto ?qu? hacer? (ver abajo)
|
197 | 43864 | jjdelcerro | if ((row - HALF_SIDE_WINDOW >= 0) && (row + HALF_SIDE_WINDOW < this.getInputBuffer().getRows())) { |
198 | 43803 | fdiaz | for (int r = Math.max(row - HALF_SIDE_WINDOW, 0); r <= Math.min(row + HALF_SIDE_WINDOW, |
199 | 43864 | jjdelcerro | this.getInputBuffer().getRows()-1); r++) { |
200 | 43803 | fdiaz | Object bundleRow = bufferBand.createRowBuffer();
|
201 | bufferBand.fetchRow(r, bundleRow); |
||
202 | bundle.add(bundleRow); |
||
203 | } |
||
204 | |||
205 | Object outputRowBuffer = outputBufferBand.createRowBuffer();
|
||
206 | // outputBufferBand.fetchRow(row, outputRowBuffer);
|
||
207 | |||
208 | rowProcessors[band].processRow(rowBuffer, bundle, outputRowBuffer); |
||
209 | |||
210 | outputBufferBand.putRow(row, outputRowBuffer); |
||
211 | } else {
|
||
212 | // FIXME: Si son de tipo BYTE, las copio, si no, no hacemos nada
|
||
213 | 43864 | jjdelcerro | if(this.getInputBuffer().getBandTypes()[band]==BufferManager.TYPE_BYTE){ |
214 | 43803 | fdiaz | outputBufferBand.putRow(row, rowBuffer); |
215 | } |
||
216 | } |
||
217 | } |
||
218 | } else {
|
||
219 | 43864 | jjdelcerro | if(mustCopyUnprocessedBands()){
|
220 | 43803 | fdiaz | try {
|
221 | 43864 | jjdelcerro | this.getOutputBuffer().getBand(band).copyFrom(this.getInputBuffer().getBand(band)); |
222 | 43803 | fdiaz | } catch (BandException e) {
|
223 | throw new ProcessingOperationException(e); |
||
224 | } |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | } |
||
229 | |||
230 | @Override
|
||
231 | public void postProcess() throws BufferOperationException { |
||
232 | super.postProcess();
|
||
233 | } |
||
234 | |||
235 | interface RowProcessor { |
||
236 | void processRow(Object inputRow, List<Object> bundleRow, Object outputRow); |
||
237 | Number processValue(Kernel kernel); |
||
238 | }; |
||
239 | |||
240 | private abstract class AbstractRowProcessor implements RowProcessor { |
||
241 | int band;
|
||
242 | NoData noData; |
||
243 | |||
244 | public AbstractRowProcessor(int band) { |
||
245 | this.band = band;
|
||
246 | 43864 | jjdelcerro | noData = getInputBuffer().getBand(band).getNoData(); |
247 | 43803 | fdiaz | } |
248 | |||
249 | @Override
|
||
250 | public Number processValue(Kernel kernel) { |
||
251 | |||
252 | int convoResult[] = new int[4]; |
||
253 | int out;
|
||
254 | |||
255 | convoResult[0] = (int) operatorH.convolution(kernel); |
||
256 | convoResult[1] = (int) operatorV.convolution(kernel); |
||
257 | |||
258 | if (compare) {
|
||
259 | if (convoResult[0] > convoResult[1]) |
||
260 | out = convoResult[0];
|
||
261 | else
|
||
262 | out = convoResult[1];
|
||
263 | } else {
|
||
264 | out = (int) Math.sqrt(Math.pow(convoResult[0], 2) + Math.pow(convoResult[1], 2)); |
||
265 | } |
||
266 | |||
267 | if (umbral > 0) { |
||
268 | if (out >= (255 - umbral)) |
||
269 | out = 255;
|
||
270 | else
|
||
271 | out = 0;
|
||
272 | } else {
|
||
273 | if (out < 0) |
||
274 | out = 0;
|
||
275 | else if (out > 255) |
||
276 | out = 255;
|
||
277 | } |
||
278 | |||
279 | return (byte)(out); |
||
280 | } |
||
281 | } |
||
282 | |||
283 | private class ByteRowProcessor extends AbstractRowProcessor { |
||
284 | |||
285 | |||
286 | public ByteRowProcessor(int band) { |
||
287 | super(band);
|
||
288 | } |
||
289 | |||
290 | @Override
|
||
291 | public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) { |
||
292 | byte[] inputByteRow = (byte[])inputRow; |
||
293 | byte[] outputByteRow = (byte[])outputRow; |
||
294 | for (int i = 0; i < inputByteRow.length; i++) { |
||
295 | // FIXME: Solo se procesan aquellas columnas en las que se pueden crear kernels, el resto ?se copian?
|
||
296 | if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputByteRow.length)) { |
||
297 | double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW]; |
||
298 | int r=0; |
||
299 | for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) { |
||
300 | int c=0; |
||
301 | byte[] row = (byte[]) iterator.next(); |
||
302 | for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW, |
||
303 | inputByteRow.length-1); column++) {
|
||
304 | byte value = ((Byte) row[column]).byteValue(); |
||
305 | if (noData.isDefined() && noData.getValue().equals(value)) {
|
||
306 | //FIXME: Si es noData, deber?a no influir en el resultado
|
||
307 | // ?Que valor poner en el kernel?
|
||
308 | k[r][c] = 0;
|
||
309 | } else {
|
||
310 | k[r][c] = (double)(0xFF & value); |
||
311 | } |
||
312 | c++; |
||
313 | } |
||
314 | r++; |
||
315 | } |
||
316 | Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
|
||
317 | if(noData.isDefined() && noData.getValue().equals(inputByteRow[i])){
|
||
318 | outputByteRow[i] = inputByteRow[i]; |
||
319 | } else {
|
||
320 | outputByteRow[i] = processValue(kernel).byteValue(); |
||
321 | } |
||
322 | } else {
|
||
323 | outputByteRow[i] = inputByteRow[i]; |
||
324 | } |
||
325 | } |
||
326 | } |
||
327 | } |
||
328 | |||
329 | private class ShortRowProcessor extends AbstractRowProcessor { |
||
330 | |||
331 | public ShortRowProcessor(int band) { |
||
332 | super(band);
|
||
333 | } |
||
334 | |||
335 | @Override
|
||
336 | public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) { |
||
337 | Number[] inputShortRow = (Number[])inputRow; |
||
338 | byte[] outputByteRow = (byte[])outputRow; |
||
339 | for (int i = 0; i < inputShortRow.length; i++) { |
||
340 | //Solo se procesan aquellas columnas en las que se pueden crear kernels, el resto se copian
|
||
341 | if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputShortRow.length)) { |
||
342 | double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW]; |
||
343 | int r=0; |
||
344 | int c=0; |
||
345 | for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) { |
||
346 | short[] row = (short[]) iterator.next(); |
||
347 | for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW, |
||
348 | inputShortRow.length-1); column++) {
|
||
349 | double value = ((Short) row[c]).shortValue(); |
||
350 | if (noData.isDefined() && noData.getValue().equals(value)) {
|
||
351 | //FIXME: Si es noData, deber?a no influir en el resultado
|
||
352 | // ?Que valor poner en el kernel?
|
||
353 | k[r][c] = 0;
|
||
354 | } else {
|
||
355 | k[r][c] = value; |
||
356 | } |
||
357 | } |
||
358 | } |
||
359 | Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
|
||
360 | outputByteRow[i] = processValue(kernel).byteValue(); |
||
361 | } else {
|
||
362 | outputByteRow[i] = ((Short)inputShortRow[i]).byteValue();
|
||
363 | } |
||
364 | } |
||
365 | } |
||
366 | |||
367 | } |
||
368 | |||
369 | private class UShortRowProcessor extends AbstractRowProcessor { |
||
370 | |||
371 | public UShortRowProcessor(int band) { |
||
372 | super(band);
|
||
373 | } |
||
374 | |||
375 | @Override
|
||
376 | public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) { |
||
377 | |||
378 | Number[] inputShortRow = (Number[]) inputRow; |
||
379 | byte[] outputByteRow = (byte[]) outputRow; |
||
380 | for (int i = 0; i < inputShortRow.length; i++) { |
||
381 | // Solo se procesan aquellas columnas en las que se pueden crear
|
||
382 | // kernels, el resto se copian
|
||
383 | if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputShortRow.length)) { |
||
384 | double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW]; |
||
385 | int r = 0; |
||
386 | int c = 0; |
||
387 | for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) { |
||
388 | short[] row = (short[]) iterator.next(); |
||
389 | for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW, |
||
390 | inputShortRow.length-1); column++) {
|
||
391 | double value = 0xFFFF & ((Short) row[c]).shortValue(); |
||
392 | if (noData.isDefined() && noData.getValue().equals(value)) {
|
||
393 | // FIXME: Si es noData, deber?a no influir en el
|
||
394 | // resultado
|
||
395 | // ?Que valor poner en el kernel?
|
||
396 | k[r][c] = 0;
|
||
397 | } else {
|
||
398 | k[r][c] = value; |
||
399 | } |
||
400 | } |
||
401 | } |
||
402 | Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
|
||
403 | outputByteRow[i] = processValue(kernel).byteValue(); |
||
404 | } else {
|
||
405 | outputByteRow[i] = ((Short) inputShortRow[i]).byteValue();
|
||
406 | } |
||
407 | } |
||
408 | } |
||
409 | } |
||
410 | |||
411 | private class IntRowProcessor extends AbstractRowProcessor { |
||
412 | |||
413 | |||
414 | public IntRowProcessor(int band) { |
||
415 | super(band);
|
||
416 | } |
||
417 | |||
418 | @Override
|
||
419 | public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) { |
||
420 | Number[] inputIntRow = (Number[])inputRow; |
||
421 | byte[] outputByteRow = (byte[]) outputRow; |
||
422 | for (int i = 0; i < inputIntRow.length; i++) { |
||
423 | // Solo se procesan aquellas columnas en las que se pueden crear
|
||
424 | // kernels, el resto se copian
|
||
425 | if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputIntRow.length)) { |
||
426 | double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW]; |
||
427 | int r = 0; |
||
428 | int c = 0; |
||
429 | for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) { |
||
430 | int[] row = (int[]) iterator.next(); |
||
431 | for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW, |
||
432 | inputIntRow.length-1); column++) {
|
||
433 | double value = ((Integer) row[c]).intValue(); |
||
434 | if (noData.isDefined() && noData.getValue().equals(value)) {
|
||
435 | // FIXME: Si es noData, deber?a no influir en el
|
||
436 | // resultado
|
||
437 | // ?Que valor poner en el kernel?
|
||
438 | k[r][c] = 0;
|
||
439 | } else {
|
||
440 | k[r][c] = value; |
||
441 | } |
||
442 | } |
||
443 | } |
||
444 | Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
|
||
445 | outputByteRow[i] = processValue(kernel).byteValue(); |
||
446 | } else {
|
||
447 | outputByteRow[i] = ((Integer) inputIntRow[i]).byteValue();
|
||
448 | } |
||
449 | } |
||
450 | } |
||
451 | } |
||
452 | private class FloatRowProcessor extends AbstractRowProcessor { |
||
453 | |||
454 | |||
455 | public FloatRowProcessor(int band) { |
||
456 | super(band);
|
||
457 | } |
||
458 | |||
459 | @Override
|
||
460 | public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) { |
||
461 | Number[] inputFloatRow = (Number[])inputRow; |
||
462 | byte[] outputByteRow = (byte[]) outputRow; |
||
463 | for (int i = 0; i < inputFloatRow.length; i++) { |
||
464 | // Solo se procesan aquellas columnas en las que se pueden crear
|
||
465 | // kernels, el resto se copian
|
||
466 | if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputFloatRow.length)) { |
||
467 | double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW]; |
||
468 | int r = 0; |
||
469 | int c = 0; |
||
470 | for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) { |
||
471 | float[] row = (float[]) iterator.next(); |
||
472 | for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW, |
||
473 | inputFloatRow.length-1); column++) {
|
||
474 | Float value = ((Float) row[c]).floatValue(); |
||
475 | if (noData.isDefined() && noData.getValue().equals(value)) {
|
||
476 | // FIXME: Si es noData, deber?a no influir en el
|
||
477 | // resultado
|
||
478 | // ?Que valor poner en el kernel?
|
||
479 | k[r][c] = 0;
|
||
480 | } else {
|
||
481 | k[r][c] = value; |
||
482 | } |
||
483 | } |
||
484 | } |
||
485 | Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
|
||
486 | outputByteRow[i] = processValue(kernel).byteValue(); |
||
487 | } else {
|
||
488 | outputByteRow[i] = ((Float) inputFloatRow[i]).byteValue();
|
||
489 | } |
||
490 | } |
||
491 | } |
||
492 | } |
||
493 | private class DoubleRowProcessor extends AbstractRowProcessor { |
||
494 | |||
495 | |||
496 | public DoubleRowProcessor(int band) { |
||
497 | super(band);
|
||
498 | } |
||
499 | |||
500 | @Override
|
||
501 | public void processRow(Object inputRow, List<Object> bundleRow, Object outputRow) { |
||
502 | Number[] inputDoubleRow = (Number[])inputRow; |
||
503 | byte[] outputByteRow = (byte[]) outputRow; |
||
504 | for (int i = 0; i < inputDoubleRow.length; i++) { |
||
505 | // Solo se procesan aquellas columnas en las que se pueden crear
|
||
506 | // kernels, el resto se copian
|
||
507 | if ((i - HALF_SIDE_WINDOW >= 0) && (i + HALF_SIDE_WINDOW < inputDoubleRow.length)) { |
||
508 | double[][] k = new double[SIDE_WINDOW][SIDE_WINDOW]; |
||
509 | int r = 0; |
||
510 | int c = 0; |
||
511 | for (Iterator<Object> iterator = bundleRow.iterator(); iterator.hasNext();) { |
||
512 | double[] row = (double[]) iterator.next(); |
||
513 | for (int column = Math.max(i - HALF_SIDE_WINDOW, 0); column <= Math.min(i + HALF_SIDE_WINDOW, |
||
514 | inputDoubleRow.length-1); column++) {
|
||
515 | Double value = ((Double) row[c]).doubleValue(); |
||
516 | if (noData.isDefined() && noData.getValue().equals(value)) {
|
||
517 | // FIXME: Si es noData, deber?a no influir en el resultado
|
||
518 | // ?Que valor poner en el kernel?
|
||
519 | k[r][c] = 0;
|
||
520 | } else {
|
||
521 | k[r][c] = value; |
||
522 | } |
||
523 | } |
||
524 | } |
||
525 | Kernel kernel = BufferLocator.getBufferManager().createKernel(k);
|
||
526 | outputByteRow[i] = processValue(kernel).byteValue(); |
||
527 | } else {
|
||
528 | outputByteRow[i] = ((Double) inputDoubleRow[i]).byteValue();
|
||
529 | } |
||
530 | } |
||
531 | } |
||
532 | } |
||
533 | } |