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