Statistics
| Revision:

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
}