svn-gvsig-desktop / trunk / libraries / libRaster / src / org / gvsig / raster / buffer / BufferInterpolation.java @ 11472
History | View | Annotate | Download (29.4 KB)
1 |
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|
2 |
*
|
3 |
* Copyright (C) 2007 IVER T.I. and Generalitat Valenciana.
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
18 |
*/
|
19 |
package org.gvsig.raster.buffer; |
20 |
|
21 |
import org.gvsig.raster.dataset.IBuffer; |
22 |
|
23 |
/**
|
24 |
* Clase que contiene la funcionalidad para poder interpolar un buffer de datos
|
25 |
* por distintos m?todos.
|
26 |
*
|
27 |
* @version 07/05/2007
|
28 |
* @author Nacho Brodin (nachobrodin@gmail.com)
|
29 |
*
|
30 |
*/
|
31 |
public class BufferInterpolation { |
32 |
public final static int INTERPOLATION_Undefined = 0; |
33 |
public final static int INTERPOLATION_NearestNeighbour = 1; |
34 |
public final static int INTERPOLATION_Bilinear = 2; |
35 |
public final static int INTERPOLATION_InverseDistance = 3; |
36 |
public final static int INTERPOLATION_BicubicSpline = 4; |
37 |
public final static int INTERPOLATION_BSpline = 5; |
38 |
|
39 |
private RasterBuffer buffer = null; |
40 |
|
41 |
/**
|
42 |
* Constructor. Asigna un RasterBuffer.
|
43 |
* @param buf
|
44 |
*/
|
45 |
public BufferInterpolation(RasterBuffer buf) {
|
46 |
this.buffer = buf;
|
47 |
} |
48 |
|
49 |
/**
|
50 |
* Ajusta el raster al ancho y alto solicitado por el vecino m?s cercano. Promedia el valor de dos
|
51 |
* pixeles contiguos.
|
52 |
* @param w Nuevo ancho
|
53 |
* @param h Nuevo alto
|
54 |
*/
|
55 |
public RasterBuffer adjustRasterNearestNeighbourInterpolation(int w, int h) { |
56 |
double stepX = (double)w / (double)buffer.width; |
57 |
double stepY = (double)h / (double)buffer.height; |
58 |
RasterBuffer rasterBuf = new RasterMemoryBuffer(buffer.getDataType(), w, h, buffer.getBandCount(), true); |
59 |
|
60 |
int[] bands = new int[rasterBuf.getBandCount()]; |
61 |
for(int iBand = 0; iBand < rasterBuf.getBandCount(); iBand ++) |
62 |
bands[iBand] = iBand; |
63 |
|
64 |
|
65 |
switch (buffer.dataType) {
|
66 |
case RasterBuffer.TYPE_BYTE:
|
67 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
68 |
if(w <= buffer.width) { //submuestreo |
69 |
for(int iRow = 0; iRow < buffer.height; iRow ++) |
70 |
for(int iCol = 0; iCol < buffer.width; iCol ++) |
71 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], buffer.getElemByte(iRow, iCol, iBand)); |
72 |
}else{ //supermuestreo |
73 |
for(int iRow = 0; iRow < h; iRow ++) |
74 |
for(int iCol = 0; iCol < w; iCol ++) |
75 |
rasterBuf.setElem(iRow, iCol, bands[iBand], buffer.getElemByte((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
76 |
} |
77 |
} |
78 |
break;
|
79 |
case RasterBuffer.TYPE_DOUBLE:
|
80 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
81 |
if(w <= buffer.width) { //submuestreo |
82 |
for(int iRow = 0; iRow < buffer.height; iRow ++) |
83 |
for(int iCol = 0; iCol < buffer.width; iCol ++) |
84 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], buffer.getElemDouble(iRow, iCol, iBand)); |
85 |
}else{ //supermuestreo |
86 |
for(int iRow = 0; iRow < h; iRow ++) |
87 |
for(int iCol = 0; iCol < w; iCol ++) |
88 |
rasterBuf.setElem(iRow, iCol, bands[iBand], buffer.getElemDouble((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
89 |
} |
90 |
} |
91 |
break;
|
92 |
case RasterBuffer.TYPE_FLOAT:
|
93 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
94 |
if(w <= buffer.width) { //submuestreo |
95 |
for(int iRow = 0; iRow < buffer.height; iRow ++) |
96 |
for(int iCol = 0; iCol < buffer.width; iCol ++) |
97 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], buffer.getElemFloat(iRow, iCol, iBand)); |
98 |
}else{ //supermuestreo |
99 |
for(int iRow = 0; iRow < h; iRow ++) |
100 |
for(int iCol = 0; iCol < w; iCol ++) |
101 |
rasterBuf.setElem(iRow, iCol, bands[iBand], buffer.getElemFloat((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
102 |
} |
103 |
} |
104 |
break;
|
105 |
case RasterBuffer.TYPE_INT:
|
106 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
107 |
if(w <= buffer.width) { //submuestreo |
108 |
for(int iRow = 0; iRow < buffer.height; iRow ++) |
109 |
for(int iCol = 0; iCol < buffer.width; iCol ++) |
110 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], buffer.getElemInt(iRow, iCol, iBand)); |
111 |
}else{ //supermuestreo |
112 |
for(int iRow = 0; iRow < h; iRow ++) |
113 |
for(int iCol = 0; iCol < w; iCol ++) |
114 |
rasterBuf.setElem(iRow, iCol, bands[iBand], buffer.getElemInt((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
115 |
} |
116 |
} |
117 |
break;
|
118 |
case RasterBuffer.TYPE_USHORT:
|
119 |
case RasterBuffer.TYPE_SHORT:
|
120 |
for(int iBand = 0; iBand < bands.length; iBand ++) { |
121 |
if(w <= buffer.width) { //submuestreo |
122 |
for(int iRow = 0; iRow < buffer.height; iRow ++) |
123 |
for(int iCol = 0; iCol < buffer.width; iCol ++) |
124 |
rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], buffer.getElemShort(iRow, iCol, iBand)); |
125 |
}else{ //supermuestreo |
126 |
for(int iRow = 0; iRow < h; iRow ++) |
127 |
for(int iCol = 0; iCol < w; iCol ++) |
128 |
rasterBuf.setElem(iRow, iCol, bands[iBand], buffer.getElemShort((int)(iRow / stepY), (int)(iCol / stepX), iBand)); |
129 |
} |
130 |
} |
131 |
break;
|
132 |
} |
133 |
return rasterBuf;
|
134 |
} |
135 |
|
136 |
/**
|
137 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n bilineal. Promedia
|
138 |
* el valor de cuatro pixeles adyacentes.
|
139 |
* <P>
|
140 |
* Para cada pixel del raster A:(x, y) obtiene el B:(x + 1, y), C:(x, y + 1), D:(x + 1, y + 1)
|
141 |
* Para cada valor del kernel se calcula un valor 'd' que es un peso dependiendo de su posici?n.
|
142 |
* Este peso depende de la posici?n del pixel destino dentro del origen. La posici?n del pixel destino
|
143 |
* en el origen es un valor decimal que puede ir de 0 a 1. Si est? muy pegado a la esquina superior
|
144 |
* izquierda estar? cercano a 0 y si est? muy pegado a la esquina inferior derecha estar? cercano a 1.
|
145 |
* Este valor est? representado por 'dx' y 'dy'.
|
146 |
* </P>
|
147 |
* <P>
|
148 |
* Los pesos aplicados son a
|
149 |
* <UL>
|
150 |
* <LI>A (1-dx) * (1-dy)</LI>
|
151 |
* <LI>B dx * (1-dy)</LI>
|
152 |
* <LI>C (1-dx) * dy</LI>
|
153 |
* <LI>D dx * dy</LI>
|
154 |
* </UL>
|
155 |
* La variable 'z' contiene el valor acumulado de cada peso por el valor del pixel.
|
156 |
* La variable 'n' contiene el valor acumulado de los pesos de los cuatro pixeles.
|
157 |
* El valor final del pixel ser? 'z/n', es decir un promedio del valor de los cuatro teniendo
|
158 |
* en cuenta el peso de cada uno.
|
159 |
* </P>
|
160 |
* @param w Nuevo ancho del buffer de salida
|
161 |
* @param h Nuevo alto del buffer de salida
|
162 |
*/
|
163 |
public RasterBuffer adjustRasterBilinearInterpolation(int w, int h) { |
164 |
double pxSize = (double)buffer.width / (double)w; |
165 |
RasterBuffer rasterBuf = new RasterMemoryBuffer(buffer.getDataType(), w, h, buffer.getBandCount(), true); |
166 |
|
167 |
double posX = pxSize / 2D; |
168 |
double posY = posX;
|
169 |
double dx = 0D, dy = 0D; |
170 |
|
171 |
for(int iBand = 0; iBand < buffer.getBandCount(); iBand ++) { |
172 |
posY = pxSize / 2D;
|
173 |
switch (buffer.dataType) {
|
174 |
case RasterBuffer.TYPE_BYTE:
|
175 |
for(int iRow = 0; iRow < h; iRow ++) { |
176 |
dy = posY - ((int)posY);
|
177 |
posX = pxSize / 2D;
|
178 |
for(int iCol = 0; iCol < w; iCol ++) { |
179 |
dx = posX - ((int)posX);
|
180 |
double[] kernel = getKernelByte(((int)posX), ((int)posY), iBand); |
181 |
rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)getBilinearValue(dx, dy, kernel) & 0xff)); |
182 |
posX += pxSize; |
183 |
} |
184 |
posY += pxSize; |
185 |
} |
186 |
break;
|
187 |
case RasterBuffer.TYPE_SHORT:
|
188 |
for(int iRow = 0; iRow < h; iRow ++) { |
189 |
dy = posY - ((int)posY);
|
190 |
posX = pxSize / 2D;
|
191 |
for(int iCol = 0; iCol < w; iCol ++) { |
192 |
dx = posX - ((int)posX);
|
193 |
double[] kernel = getKernelShort(((int)posX), ((int)posY), iBand); |
194 |
rasterBuf.setElem(iRow, iCol, iBand, (short)((short)getBilinearValue(dx, dy, kernel) & 0xffff)); |
195 |
posX += pxSize; |
196 |
} |
197 |
posY += pxSize; |
198 |
} |
199 |
break;
|
200 |
case RasterBuffer.TYPE_INT:
|
201 |
for(int iRow = 0; iRow < h; iRow ++) { |
202 |
dy = posY - ((int)posY);
|
203 |
posX = pxSize / 2D;
|
204 |
for(int iCol = 0; iCol < w; iCol ++) { |
205 |
dx = posX - ((int)posX);
|
206 |
double[] kernel = getKernelInt(((int)posX), ((int)posY), iBand); |
207 |
rasterBuf.setElem(iRow, iCol, iBand, (int)((int)getBilinearValue(dx, dy, kernel) & 0xff)); |
208 |
posX += pxSize; |
209 |
} |
210 |
posY += pxSize; |
211 |
} |
212 |
break;
|
213 |
case RasterBuffer.TYPE_FLOAT:
|
214 |
for(int iRow = 0; iRow < h; iRow ++) { |
215 |
dy = posY - ((int)posY);
|
216 |
posX = pxSize / 2D;
|
217 |
for(int iCol = 0; iCol < w; iCol ++) { |
218 |
dx = posX - ((int)posX);
|
219 |
double[] kernel = getKernelInt(((int)posX), ((int)posY), iBand); |
220 |
rasterBuf.setElem(iRow, iCol, iBand, (float)getBilinearValue(dx, dy, kernel));
|
221 |
posX += pxSize; |
222 |
} |
223 |
posY += pxSize; |
224 |
} |
225 |
break;
|
226 |
case RasterBuffer.TYPE_DOUBLE:
|
227 |
for(int iRow = 0; iRow < h; iRow ++) { |
228 |
dy = posY - ((int)posY);
|
229 |
posX = pxSize / 2D;
|
230 |
for(int iCol = 0; iCol < w; iCol ++) { |
231 |
dx = posX - ((int)posX);
|
232 |
double[] kernel = getKernelInt(((int)posX), ((int)posY), iBand); |
233 |
rasterBuf.setElem(iRow, iCol, iBand, (double)getBilinearValue(dx, dy, kernel));
|
234 |
posX += pxSize; |
235 |
} |
236 |
posY += pxSize; |
237 |
} |
238 |
break;
|
239 |
} |
240 |
|
241 |
} |
242 |
|
243 |
return rasterBuf;
|
244 |
} |
245 |
|
246 |
/**
|
247 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de distancia inversa.
|
248 |
* Asigna el valor de un pixel en funci?n inversa de la distancia.
|
249 |
* <P>
|
250 |
* Para cada pixel del raster A:(x, y) obtiene el B:(x + 1, y), C:(x, y + 1), D:(x + 1, y + 1)
|
251 |
* Para cada valor del kernel se calcula un valor 'd' que es un peso dependiendo de su posici?n.
|
252 |
* Este peso ser? dependiente de la posici?n del pixel destino dentro del origen. La posici?n del pixel destino
|
253 |
* en el origen es un valor decimal que puede ir de 0 a 1. Si est? muy pegado a la esquina superior
|
254 |
* izquierda estar? cercano a 0 y si est? muy pegado a la esquina inferior derecha estar? cercano a 1.
|
255 |
* Este valor est? representado por 'dx' y 'dy'. En este caso, y a diferencia del m?todo
|
256 |
* bilinear el peso vendr? representado por la inversa de la distancia entre la posici?n
|
257 |
* dentro del pixel y el origen del mismo.
|
258 |
* </P>
|
259 |
* <P>
|
260 |
* Los pesos aplicados son a
|
261 |
* <UL>
|
262 |
* <LI>A 1 / sqrt((1-dx) * (1-dy))</LI>
|
263 |
* <LI>B 1 / sqrt(dx * (1-dy))</LI>
|
264 |
* <LI>C 1 / sqrt((1-dx) * dy)</LI>
|
265 |
* <LI>D 1 / sqrt(dx * dy)</LI>
|
266 |
* </UL>
|
267 |
* La variable 'z' contiene el valor acumulado de cada peso por el valor del pixel.
|
268 |
* La variable 'n' contiene el valor acumulado de los pesos de los cuatro pixeles.
|
269 |
* El valor final del pixel ser? 'z/n', es decir un promedio del valor de los cuatro teniendo
|
270 |
* en cuenta el peso de cada uno.
|
271 |
* </P>
|
272 |
* @param w Nuevo ancho del buffer de salida
|
273 |
* @param h Nuevo alto del buffer de salida
|
274 |
*/
|
275 |
public RasterBuffer adjustRasterInverseDistanceInterpolation(int w, int h) { |
276 |
double pxSize = (double)buffer.width / (double)w; |
277 |
RasterBuffer rasterBuf = new RasterMemoryBuffer(buffer.getDataType(), w, h, buffer.getBandCount(), true); |
278 |
|
279 |
double posX = pxSize / 2D; |
280 |
double posY = posX;
|
281 |
double dx = 0D, dy = 0D; |
282 |
|
283 |
for(int iBand = 0; iBand < buffer.getBandCount(); iBand ++) { |
284 |
posY = pxSize / 2D;
|
285 |
switch (buffer.dataType) {
|
286 |
case RasterBuffer.TYPE_BYTE:
|
287 |
for(int iRow = 0; iRow < h; iRow ++) { |
288 |
dy = posY - ((int)posY);
|
289 |
posX = pxSize / 2D;
|
290 |
for(int iCol = 0; iCol < w; iCol ++) { |
291 |
dx = posX - ((int)posX);
|
292 |
double[] kernel = getKernelByte(((int)posX), ((int)posY), iBand); |
293 |
rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)getInverseDistanceValue(dx, dy, kernel) & 0xff)); |
294 |
posX += pxSize; |
295 |
} |
296 |
posY += pxSize; |
297 |
} |
298 |
break;
|
299 |
case RasterBuffer.TYPE_SHORT:
|
300 |
for(int iRow = 0; iRow < h; iRow ++) { |
301 |
dy = posY - ((int)posY);
|
302 |
posX = pxSize / 2D;
|
303 |
for(int iCol = 0; iCol < w; iCol ++) { |
304 |
dx = posX - ((int)posX);
|
305 |
double[] kernel = getKernelShort(((int)posX), ((int)posY), iBand); |
306 |
rasterBuf.setElem(iRow, iCol, iBand, (short)((short)getInverseDistanceValue(dx, dy, kernel) & 0xffff)); |
307 |
posX += pxSize; |
308 |
} |
309 |
posY += pxSize; |
310 |
} |
311 |
break;
|
312 |
case RasterBuffer.TYPE_INT:
|
313 |
for(int iRow = 0; iRow < h; iRow ++) { |
314 |
dy = posY - ((int)posY);
|
315 |
posX = pxSize / 2D;
|
316 |
for(int iCol = 0; iCol < w; iCol ++) { |
317 |
dx = posX - ((int)posX);
|
318 |
double[] kernel = getKernelInt(((int)posX), ((int)posY), iBand); |
319 |
rasterBuf.setElem(iRow, iCol, iBand, (int)((int)getInverseDistanceValue(dx, dy, kernel) & 0xff)); |
320 |
posX += pxSize; |
321 |
} |
322 |
posY += pxSize; |
323 |
} |
324 |
break;
|
325 |
case RasterBuffer.TYPE_FLOAT:
|
326 |
for(int iRow = 0; iRow < h; iRow ++) { |
327 |
dy = posY - ((int)posY);
|
328 |
posX = pxSize / 2D;
|
329 |
for(int iCol = 0; iCol < w; iCol ++) { |
330 |
dx = posX - ((int)posX);
|
331 |
double[] kernel = getKernelFloat(((int)posX), ((int)posY), iBand); |
332 |
rasterBuf.setElem(iRow, iCol, iBand, (float)getInverseDistanceValue(dx, dy, kernel));
|
333 |
posX += pxSize; |
334 |
} |
335 |
posY += pxSize; |
336 |
} |
337 |
break;
|
338 |
case RasterBuffer.TYPE_DOUBLE:
|
339 |
for(int iRow = 0; iRow < h; iRow ++) { |
340 |
dy = posY - ((int)posY);
|
341 |
posX = pxSize / 2D;
|
342 |
for(int iCol = 0; iCol < w; iCol ++) { |
343 |
dx = posX - ((int)posX);
|
344 |
double[] kernel = getKernelDouble(((int)posX), ((int)posY), iBand); |
345 |
rasterBuf.setElem(iRow, iCol, iBand, (double)getInverseDistanceValue(dx, dy, kernel));
|
346 |
posX += pxSize; |
347 |
} |
348 |
posY += pxSize; |
349 |
} |
350 |
break;
|
351 |
} |
352 |
|
353 |
} |
354 |
|
355 |
return rasterBuf;
|
356 |
} |
357 |
|
358 |
/**
|
359 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n BSpline. Promedia
|
360 |
* el valor de cuatro pixeles adyacentes.
|
361 |
* @param w Nuevo ancho
|
362 |
* @param h Nuevo alto
|
363 |
*/
|
364 |
public RasterBuffer adjustRasterBSplineInterpolation(int w, int h) { |
365 |
double pxSize = (double)buffer.width / (double)w; |
366 |
RasterBuffer rasterBuf = new RasterMemoryBuffer(buffer.getDataType(), w, h, buffer.getBandCount(), true); |
367 |
|
368 |
double posX = pxSize / 2D; |
369 |
double posY = posX;
|
370 |
double dx = 0D, dy = 0D; |
371 |
|
372 |
for(int iBand = 0; iBand < buffer.getBandCount(); iBand ++) { |
373 |
posY = pxSize / 2D;
|
374 |
switch (buffer.dataType) {
|
375 |
case RasterBuffer.TYPE_BYTE:
|
376 |
for(int iRow = 0; iRow < h; iRow ++) { |
377 |
dy = posY - ((int)posY);
|
378 |
posX = pxSize / 2D;
|
379 |
for(int iCol = 0; iCol < w; iCol ++) { |
380 |
dx = posX - ((int)posX);
|
381 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
382 |
if(kernel == null) { |
383 |
double[] k = getKernelByte(((int)posX), ((int)posY), iBand); |
384 |
rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)getBilinearValue(dx, dy, k) & 0xff)); |
385 |
} else
|
386 |
rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)getBSplineValue(dx, dy, kernel) & 0xff)); |
387 |
posX += pxSize; |
388 |
} |
389 |
posY += pxSize; |
390 |
} |
391 |
break;
|
392 |
case RasterBuffer.TYPE_SHORT:
|
393 |
for(int iRow = 0; iRow < h; iRow ++) { |
394 |
dy = posY - ((int)posY);
|
395 |
posX = pxSize / 2D;
|
396 |
for(int iCol = 0; iCol < w; iCol ++) { |
397 |
dx = posX - ((int)posX);
|
398 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
399 |
if(kernel == null) { |
400 |
double[] k = getKernelShort(((int)posX), ((int)posY), iBand); |
401 |
rasterBuf.setElem(iRow, iCol, iBand, (short)((short)getBilinearValue(dx, dy, k) & 0xffff)); |
402 |
} else
|
403 |
rasterBuf.setElem(iRow, iCol, iBand, (short)((short)getBSplineValue(dx, dy, kernel) & 0xffff)); |
404 |
posX += pxSize; |
405 |
} |
406 |
posY += pxSize; |
407 |
} |
408 |
break;
|
409 |
case RasterBuffer.TYPE_INT:
|
410 |
for(int iRow = 0; iRow < h; iRow ++) { |
411 |
dy = posY - ((int)posY);
|
412 |
posX = pxSize / 2D;
|
413 |
for(int iCol = 0; iCol < w; iCol ++) { |
414 |
dx = posX - ((int)posX);
|
415 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
416 |
if(kernel == null) { |
417 |
double[] k = getKernelInt(((int)posX), ((int)posY), iBand); |
418 |
rasterBuf.setElem(iRow, iCol, iBand, (int)((int)getBilinearValue(dx, dy, k) & 0xffffffff)); |
419 |
} else
|
420 |
rasterBuf.setElem(iRow, iCol, iBand, (int)((int)getBSplineValue(dx, dy, kernel) & 0xffffffff)); |
421 |
posX += pxSize; |
422 |
} |
423 |
posY += pxSize; |
424 |
} |
425 |
break;
|
426 |
case RasterBuffer.TYPE_FLOAT:
|
427 |
for(int iRow = 0; iRow < h; iRow ++) { |
428 |
dy = posY - ((int)posY);
|
429 |
posX = pxSize / 2D;
|
430 |
for(int iCol = 0; iCol < w; iCol ++) { |
431 |
dx = posX - ((int)posX);
|
432 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
433 |
if(kernel == null) { |
434 |
double[] k = getKernelFloat(((int)posX), ((int)posY), iBand); |
435 |
rasterBuf.setElem(iRow, iCol, iBand, (float)getBilinearValue(dx, dy, k));
|
436 |
} else
|
437 |
rasterBuf.setElem(iRow, iCol, iBand, (float)getBSplineValue(dx, dy, kernel));
|
438 |
posX += pxSize; |
439 |
} |
440 |
posY += pxSize; |
441 |
} |
442 |
break;
|
443 |
case RasterBuffer.TYPE_DOUBLE:
|
444 |
for(int iRow = 0; iRow < h; iRow ++) { |
445 |
dy = posY - ((int)posY);
|
446 |
posX = pxSize / 2D;
|
447 |
for(int iCol = 0; iCol < w; iCol ++) { |
448 |
dx = posX - ((int)posX);
|
449 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
450 |
if(kernel == null) { |
451 |
double[] k = getKernelDouble(((int)posX), ((int)posY), iBand); |
452 |
rasterBuf.setElem(iRow, iCol, iBand, (double)getBilinearValue(dx, dy, k));
|
453 |
} else
|
454 |
rasterBuf.setElem(iRow, iCol, iBand, (double)getBSplineValue(dx, dy, kernel));
|
455 |
posX += pxSize; |
456 |
} |
457 |
posY += pxSize; |
458 |
} |
459 |
break;
|
460 |
} |
461 |
|
462 |
} |
463 |
|
464 |
return rasterBuf;
|
465 |
} |
466 |
|
467 |
/**
|
468 |
* Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de spline bicubica.
|
469 |
* @param w Nuevo ancho
|
470 |
* @param h Nuevo alto
|
471 |
*/
|
472 |
public RasterBuffer adjustRasterBicubicSplineInterpolation(int w, int h) { |
473 |
double pxSize = (double)buffer.width / (double)w; |
474 |
RasterBuffer rasterBuf = new RasterMemoryBuffer(buffer.getDataType(), w, h, buffer.getBandCount(), true); |
475 |
|
476 |
double posX = pxSize / 2D; |
477 |
double posY = posX;
|
478 |
double dx = 0D, dy = 0D; |
479 |
|
480 |
for(int iBand = 0; iBand < buffer.getBandCount(); iBand ++) { |
481 |
posY = pxSize / 2D;
|
482 |
switch (buffer.dataType) {
|
483 |
case RasterBuffer.TYPE_BYTE:
|
484 |
for(int iRow = 0; iRow < h; iRow ++) { |
485 |
dy = posY - ((int)posY);
|
486 |
posX = pxSize / 2D;
|
487 |
for(int iCol = 0; iCol < w; iCol ++) { |
488 |
dx = posX - ((int)posX);
|
489 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
490 |
if(kernel == null) { |
491 |
double[] k = getKernelByte(((int)posX), ((int)posY), iBand); |
492 |
rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)getBilinearValue(dx, dy, k) & 0xff)); |
493 |
} else
|
494 |
rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)getBicubicSplineValue(dx, dy, kernel) & 0xff)); |
495 |
posX += pxSize; |
496 |
} |
497 |
posY += pxSize; |
498 |
} |
499 |
break;
|
500 |
case RasterBuffer.TYPE_SHORT:
|
501 |
for(int iRow = 0; iRow < h; iRow ++) { |
502 |
dy = posY - ((int)posY);
|
503 |
posX = pxSize / 2D;
|
504 |
for(int iCol = 0; iCol < w; iCol ++) { |
505 |
dx = posX - ((int)posX);
|
506 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
507 |
if(kernel == null) { |
508 |
double[] k = getKernelShort(((int)posX), ((int)posY), iBand); |
509 |
rasterBuf.setElem(iRow, iCol, iBand, (short)((short)getBilinearValue(dx, dy, k) & 0xffff)); |
510 |
} else
|
511 |
rasterBuf.setElem(iRow, iCol, iBand, (short)((short)getBicubicSplineValue(dx, dy, kernel) & 0xffff)); |
512 |
posX += pxSize; |
513 |
} |
514 |
posY += pxSize; |
515 |
} |
516 |
break;
|
517 |
case RasterBuffer.TYPE_INT:
|
518 |
for(int iRow = 0; iRow < h; iRow ++) { |
519 |
dy = posY - ((int)posY);
|
520 |
posX = pxSize / 2D;
|
521 |
for(int iCol = 0; iCol < w; iCol ++) { |
522 |
dx = posX - ((int)posX);
|
523 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
524 |
if(kernel == null) { |
525 |
double[] k = getKernelInt(((int)posX), ((int)posY), iBand); |
526 |
rasterBuf.setElem(iRow, iCol, iBand, (int)((int)getBilinearValue(dx, dy, k) & 0xffffffff)); |
527 |
} else
|
528 |
rasterBuf.setElem(iRow, iCol, iBand, (int)((int)getBicubicSplineValue(dx, dy, kernel) & 0xffffffff)); |
529 |
posX += pxSize; |
530 |
} |
531 |
posY += pxSize; |
532 |
} |
533 |
break;
|
534 |
case RasterBuffer.TYPE_FLOAT:
|
535 |
for(int iRow = 0; iRow < h; iRow ++) { |
536 |
dy = posY - ((int)posY);
|
537 |
posX = pxSize / 2D;
|
538 |
for(int iCol = 0; iCol < w; iCol ++) { |
539 |
dx = posX - ((int)posX);
|
540 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
541 |
if(kernel == null) { |
542 |
double[] k = getKernelFloat(((int)posX), ((int)posY), iBand); |
543 |
rasterBuf.setElem(iRow, iCol, iBand, (float)getBilinearValue(dx, dy, k));
|
544 |
} else
|
545 |
rasterBuf.setElem(iRow, iCol, iBand, (float)getBicubicSplineValue(dx, dy, kernel));
|
546 |
posX += pxSize; |
547 |
} |
548 |
posY += pxSize; |
549 |
} |
550 |
break;
|
551 |
case RasterBuffer.TYPE_DOUBLE:
|
552 |
for(int iRow = 0; iRow < h; iRow ++) { |
553 |
dy = posY - ((int)posY);
|
554 |
posX = pxSize / 2D;
|
555 |
for(int iCol = 0; iCol < w; iCol ++) { |
556 |
dx = posX - ((int)posX);
|
557 |
double[][] kernel = get4x4Submatrix(((int)posX), ((int)posY), iBand); |
558 |
if(kernel == null) { |
559 |
double[] k = getKernelDouble(((int)posX), ((int)posY), iBand); |
560 |
rasterBuf.setElem(iRow, iCol, iBand, (double)getBilinearValue(dx, dy, k));
|
561 |
} else
|
562 |
rasterBuf.setElem(iRow, iCol, iBand, (double)getBicubicSplineValue(dx, dy, kernel));
|
563 |
posX += pxSize; |
564 |
} |
565 |
posY += pxSize; |
566 |
} |
567 |
break;
|
568 |
} |
569 |
|
570 |
} |
571 |
|
572 |
return rasterBuf;
|
573 |
} |
574 |
|
575 |
/**
|
576 |
*
|
577 |
* @param dx
|
578 |
* @param dy
|
579 |
* @param kernel
|
580 |
* @return
|
581 |
*/
|
582 |
private double getBicubicSplineValue(double dx, double dy, double[][] kernel) { |
583 |
int i;
|
584 |
double a0, a2, a3, b1, b2, b3;
|
585 |
double[] c = new double[4]; |
586 |
|
587 |
for(i = 0; i < 4; i++) { |
588 |
a0 = kernel[0][i] - kernel[1][i]; |
589 |
a2 = kernel[2][i] - kernel[1][i]; |
590 |
a3 = kernel[3][i] - kernel[1][i]; |
591 |
|
592 |
b1 = -a0 / 3.0 + a2 - a3 / 6.0; |
593 |
b2 = a0 / 2.0 + a2 / 2.0; |
594 |
b3 = -a0 / 6.0 - a2 / 2.0 + a3 / 6.0; |
595 |
|
596 |
c[i] = kernel[1][i] + b1 * dx + b2 * (dx * dx) + b3 * (dx * dx * dx);
|
597 |
} |
598 |
|
599 |
a0 = c[0] - c[1]; |
600 |
a2 = c[2] - c[1]; |
601 |
a3 = c[3] - c[1]; |
602 |
|
603 |
b1 = -a0 / 3.0 + a2 - a3 / 6.0; |
604 |
b2 = a0 / 2.0 + a2 / 2.0; |
605 |
b3 = -a0 / 6.0 - a2 / 2.0 + a3 / 6.0; |
606 |
|
607 |
return( c[1] + b1 * dy + b2 * (dy * dy) + b3 * (dy * dy * dy) ); |
608 |
} |
609 |
|
610 |
/**
|
611 |
*
|
612 |
* @param dx
|
613 |
* @param dy
|
614 |
* @param kernel
|
615 |
* @return
|
616 |
*/
|
617 |
private double getBSplineValue(double dx, double dy, double[][] kernel) { |
618 |
int i = 0, ix = 0, iy = 0; |
619 |
double px = 0, py = 0, z = 0; |
620 |
double[] Rx = new double[4]; |
621 |
double[] Ry = new double[4]; |
622 |
|
623 |
for(i = 0, px = -1.0 - dx, py = -1.0 - dy; i < 4; i++, px++, py++){ |
624 |
Rx[i] = 0.0;
|
625 |
Ry[i] = 0.0;
|
626 |
|
627 |
if( (z = px + 2.0) > 0.0 ) |
628 |
Rx[i] += z * z * z; |
629 |
if( (z = px + 1.0) > 0.0 ) |
630 |
Rx[i] += -4.0 * z * z * z;
|
631 |
if( (z = px + 0.0) > 0.0 ) |
632 |
Rx[i] += 6.0 * z * z * z;
|
633 |
if( (z = px - 1.0) > 0.0 ) |
634 |
Rx[i] += -4.0 * z * z * z;
|
635 |
if( (z = py + 2.0) > 0.0 ) |
636 |
Ry[i] += z * z * z; |
637 |
if( (z = py + 1.0) > 0.0 ) |
638 |
Ry[i] += -4.0 * z * z * z;
|
639 |
if( (z = py + 0.0) > 0.0 ) |
640 |
Ry[i] += 6.0 * z * z * z;
|
641 |
if( (z = py - 1.0) > 0.0 ) |
642 |
Ry[i] += -4.0 * z * z * z;
|
643 |
|
644 |
Rx[i] /= 6.0;
|
645 |
Ry[i] /= 6.0;
|
646 |
} |
647 |
|
648 |
for(iy = 0, z = 0.0; iy < 4; iy++) { |
649 |
for(ix = 0; ix < 4; ix++) { |
650 |
z += kernel[ix][iy] * Rx[ix] * Ry[iy]; |
651 |
} |
652 |
} |
653 |
return z;
|
654 |
} |
655 |
|
656 |
/**
|
657 |
* Calcula los valores N y Z para el m?todo bilinear y obtiene el valor del pixel como
|
658 |
* Z / N
|
659 |
* @param dx distancia en X desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
|
660 |
* @param dy distancia en Y desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
|
661 |
* @param kernel valor del pixel y alrededor
|
662 |
* @return valor del pixel
|
663 |
*/
|
664 |
private double getBilinearValue(double dx, double dy, double[] kernel) { |
665 |
double z = 0.0, n = 0.0, d; |
666 |
d = (1.0 - dx) * (1.0 - dy); |
667 |
z += d * kernel[0];
|
668 |
n += d; |
669 |
|
670 |
d = dx * (1.0 - dy);
|
671 |
z += d * kernel[1];
|
672 |
n += d; |
673 |
|
674 |
d = (1.0 - dx) * dy;
|
675 |
z += d * kernel[2];
|
676 |
n += d; |
677 |
|
678 |
d = dx * dy; |
679 |
z += d * kernel[3];
|
680 |
n += d; |
681 |
|
682 |
double b = 0; |
683 |
if(n > 0.0) |
684 |
b = (z / n); |
685 |
return b;
|
686 |
} |
687 |
|
688 |
/**
|
689 |
* Calcula los valores N y Z para el m?todo de distancia inversa y calcula el valor del
|
690 |
* pixel como Z / N.
|
691 |
* @param dx distancia en X desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
|
692 |
* @param dy distancia en Y desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
|
693 |
* @param kernel valor del pixel y alrededor
|
694 |
* @return valor del pixel
|
695 |
*/
|
696 |
private double getInverseDistanceValue(double dx, double dy, double[] kernel) { |
697 |
double z = 0.0, n = 0.0, d; |
698 |
d = 1.0 / Math.sqrt(dx * dx + dy * dy); |
699 |
z += d * kernel[0];
|
700 |
n += d; |
701 |
|
702 |
d = 1.0 / Math.sqrt((1.0 - dx) * ( 1.0 - dx) + dy * dy); |
703 |
z += d * kernel[1];
|
704 |
n += d; |
705 |
|
706 |
d = 1.0 / Math.sqrt(dx*dx + (1.0-dy)*(1.0-dy)); |
707 |
z += d * kernel[2];
|
708 |
n += d; |
709 |
|
710 |
d = 1.0 / Math.sqrt((1.0 - dx) *( 1.0 - dx) + (1.0 - dy) * (1.0 - dy)); |
711 |
z += d * kernel[3];
|
712 |
n += d; |
713 |
|
714 |
double b = 0; |
715 |
if(n > 0.0) |
716 |
b = (z / n); |
717 |
return b;
|
718 |
} |
719 |
|
720 |
/**
|
721 |
* Obtiene un kernel de 4x4 elementos. Si alguno de los elementos se sale de la imagen
|
722 |
* , por ejemplo en los bordes devuelve null.
|
723 |
* @param x
|
724 |
* @param y
|
725 |
* @param band
|
726 |
* @return
|
727 |
*/
|
728 |
private double[][] get4x4Submatrix(int x, int y, int band) { |
729 |
int ix, iy, px, py;
|
730 |
double[][] z_xy = new double[4][4]; |
731 |
|
732 |
for(iy = 0, py = y - 1; iy < 4; iy++, py++) { |
733 |
for(ix = 0, px = x - 1; ix < 4; ix++, px++) { |
734 |
if (!buffer.isInside(px, py))
|
735 |
return null; |
736 |
else {
|
737 |
switch(buffer.getDataType()) {
|
738 |
case IBuffer.TYPE_BYTE: z_xy[ix][iy] = (buffer.getElemByte(py, px, band) & 0xff); break; |
739 |
case IBuffer.TYPE_SHORT: z_xy[ix][iy] = (buffer.getElemShort(py, px, band) & 0xffff); break; |
740 |
case IBuffer.TYPE_INT: z_xy[ix][iy] = (buffer.getElemInt(py, px, band) & 0xffffffff); break; |
741 |
case IBuffer.TYPE_FLOAT: z_xy[ix][iy] = buffer.getElemFloat(py, px, band); break; |
742 |
case IBuffer.TYPE_DOUBLE: z_xy[ix][iy] = buffer.getElemDouble(py, px, band); break; |
743 |
} |
744 |
} |
745 |
} |
746 |
} |
747 |
return z_xy;
|
748 |
} |
749 |
|
750 |
/**
|
751 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
752 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
753 |
* se tomar? x e y.
|
754 |
* @param x Coordenada X del pixel inicial
|
755 |
* @param y Coordenada Y del pixel inicial
|
756 |
* @param band N?mero de banda.
|
757 |
* @return Kernel solicitado en forma de array.
|
758 |
*/
|
759 |
private double[] getKernelByte(int x, int y, int band) { |
760 |
double[] d = new double[4]; |
761 |
d[0] = (buffer.getElemByte(y, x, band) & 0xff); |
762 |
int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1); |
763 |
int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1); |
764 |
d[1] = (buffer.getElemByte(y, nextX, band) & 0xff); |
765 |
d[2] = (buffer.getElemByte(nextY, x, band) & 0xff); |
766 |
d[3] = (buffer.getElemByte(nextY, nextX, band) & 0xff); |
767 |
return d;
|
768 |
} |
769 |
|
770 |
/**
|
771 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
772 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
773 |
* se tomar? x e y.
|
774 |
* @param x Coordenada X del pixel inicial
|
775 |
* @param y Coordenada Y del pixel inicial
|
776 |
* @param band N?mero de banda.
|
777 |
* @return Kernel solicitado en forma de array.
|
778 |
*/
|
779 |
private double[] getKernelShort(int x, int y, int band) { |
780 |
double[] d = new double[4]; |
781 |
d[0] = (buffer.getElemShort(y, x, band) & 0xffff); |
782 |
int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1); |
783 |
int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1); |
784 |
d[1] = (buffer.getElemShort(y, nextX, band) & 0xffff); |
785 |
d[2] = (buffer.getElemShort(nextY, x, band) & 0xffff); |
786 |
d[3] = (buffer.getElemShort(nextY, nextX, band) & 0xffff); |
787 |
return d;
|
788 |
} |
789 |
|
790 |
/**
|
791 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
792 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
793 |
* se tomar? x e y.
|
794 |
* @param x Coordenada X del pixel inicial
|
795 |
* @param y Coordenada Y del pixel inicial
|
796 |
* @param band N?mero de banda.
|
797 |
* @return Kernel solicitado en forma de array.
|
798 |
*/
|
799 |
private double[] getKernelInt(int x, int y, int band) { |
800 |
double[] d = new double[4]; |
801 |
d[0] = (buffer.getElemInt(y, x, band) & 0xffffffff); |
802 |
int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1); |
803 |
int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1); |
804 |
d[1] = (buffer.getElemInt(y, nextX, band) & 0xffffffff); |
805 |
d[2] = (buffer.getElemInt(nextY, x, band) & 0xffffffff); |
806 |
d[3] = (buffer.getElemInt(nextY, nextX, band) & 0xffffffff); |
807 |
return d;
|
808 |
} |
809 |
|
810 |
/**
|
811 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
812 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
813 |
* se tomar? x e y.
|
814 |
* @param x Coordenada X del pixel inicial
|
815 |
* @param y Coordenada Y del pixel inicial
|
816 |
* @param band N?mero de banda.
|
817 |
* @return Kernel solicitado en forma de array.
|
818 |
*/
|
819 |
private double[] getKernelFloat(int x, int y, int band) { |
820 |
double[] d = new double[4]; |
821 |
d[0] = buffer.getElemFloat(y, x, band);
|
822 |
int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1); |
823 |
int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1); |
824 |
d[1] = buffer.getElemFloat(y, nextX, band);
|
825 |
d[2] = buffer.getElemFloat(nextY, x, band);
|
826 |
d[3] = buffer.getElemFloat(nextY, nextX, band);
|
827 |
return d;
|
828 |
} |
829 |
|
830 |
/**
|
831 |
* Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
|
832 |
* (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
|
833 |
* se tomar? x e y.
|
834 |
* @param x Coordenada X del pixel inicial
|
835 |
* @param y Coordenada Y del pixel inicial
|
836 |
* @param band N?mero de banda.
|
837 |
* @return Kernel solicitado en forma de array.
|
838 |
*/
|
839 |
private double[] getKernelDouble(int x, int y, int band) { |
840 |
double[] d = new double[4]; |
841 |
d[0] = buffer.getElemDouble(y, x, band);
|
842 |
int nextX = ((x + 1) >= buffer.getWidth()) ? x : (x + 1); |
843 |
int nextY = ((y + 1) >= buffer.getHeight()) ? y : (y + 1); |
844 |
d[1] = buffer.getElemDouble(y, nextX, band);
|
845 |
d[2] = buffer.getElemDouble(nextY, x, band);
|
846 |
d[3] = buffer.getElemDouble(nextY, nextX, band);
|
847 |
return d;
|
848 |
} |
849 |
} |