Revision 11472

View differences:

trunk/libraries/libRaster/src-test/org/gvsig/raster/buffer/TestBufferInterpolation.java
53 53
	private String path = baseDir + "03AUG23153350-M2AS-000000122423_01_P001-BROWSE.jpg";
54 54
	private RasterDataset f = null;	
55 55
	private BufferFactory ds = null;
56
	private int size = 50;
56 57
	
57 58
	private String fileNeighbour1 = baseDir + "neighbour50x50.tif";
58 59
	private String fileBilinear1 = baseDir + "bilinear50x50.tif";
59 60
	private String fileInverseDistance1 = baseDir + "inverseDistance50x50.tif";
61
	private String fileBSpline1 = baseDir + "bspline50x50.tif";
62
	private String fileBicubicSpline1 = baseDir + "bicubicspline50x50.tif";
60 63
	
61
	private String fileNeighbour = "/tmp/f1.tif";
62
	private String fileBilinear = "/tmp/f2.tif";
63
	private String fileInverseDistance = "/tmp/f3.tif";
64
	private String fileNeighbour = "/tmp/neighbour.tif";
65
	private String fileBilinear = "/tmp/bilinear.tif";
66
	private String fileInverseDistance = "/tmp/invdistance.tif";
67
	private String fileBSpline = "/tmp/bspline.tif";
68
	private String fileBicubicSpline = "/tmp/bicubicspline.tif";
64 69
	
65 70
	static {
66 71
		RasterLibrary.wakeUp();
......
88 93
		ds.setAreaOfInterest(0, 0, f.getWidth(), f.getHeight());
89 94
		RasterBuffer buf = (RasterBuffer)ds.getRasterBuf();
90 95
		
91
		IBuffer b1 = buf.getAdjustedWindow(50, 50, IQueryableRaster.INTERPOLATION_NearestNeighbour);
92
		IBuffer b2 = buf.getAdjustedWindow(50, 50, IQueryableRaster.INTERPOLATION_Bilinear);
93
		IBuffer b3 = buf.getAdjustedWindow(50, 50, IQueryableRaster.INTERPOLATION_InverseDistance);
94 96
		try {
97
			IBuffer b1 = buf.getAdjustedWindow(size, size, BufferInterpolation.INTERPOLATION_NearestNeighbour);
95 98
			convertBufferToTif(fileNeighbour, f.getExtent(), b1);
96
			convertBufferToTif(fileBilinear, f.getExtent(), b2);
97
			convertBufferToTif(fileInverseDistance, f.getExtent(), b3);
99
			b1 = buf.getAdjustedWindow(size, size, BufferInterpolation.INTERPOLATION_Bilinear);
100
			convertBufferToTif(fileBilinear, f.getExtent(), b1);
101
			b1 = buf.getAdjustedWindow(size, size, BufferInterpolation.INTERPOLATION_InverseDistance);
102
			convertBufferToTif(fileInverseDistance, f.getExtent(), b1);
103
			b1 = buf.getAdjustedWindow(size, size, BufferInterpolation.INTERPOLATION_BSpline);
104
			convertBufferToTif(fileBSpline, f.getExtent(), b1);
105
			b1 = buf.getAdjustedWindow(size, size, BufferInterpolation.INTERPOLATION_BicubicSpline);
106
			convertBufferToTif(fileBicubicSpline, f.getExtent(), b1);
98 107
		} catch (IOException e) {
99 108
			e.printStackTrace();
100 109
		}
......
104 113
		compareResult(fileNeighbour, fileNeighbour1);
105 114
		compareResult(fileBilinear, fileBilinear1);
106 115
		compareResult(fileInverseDistance, fileInverseDistance1);
116
		compareResult(fileBSpline, fileBSpline1);
117
		//compareResult(fileBicubicSpline, fileBicubicSpline1);
107 118
		File file1 = new File(fileNeighbour);
108 119
		File file2 = new File(fileBilinear);
109 120
		File file3 = new File(fileInverseDistance);
121
		File file4 = new File(fileBSpline);
122
		//File file5 = new File(fileBicubicSpline);
110 123
		if(file1.exists())
111 124
			file1.delete();
112 125
		if(file2.exists())
113 126
			file2.delete();
114 127
		if(file3.exists())
115 128
			file3.delete();
129
		if(file4.exists())
130
			file4.delete();
131
		//if(file5.exists())
132
		//	file5.delete();
116 133
	}
117 134
	
118 135
	/**
trunk/libraries/libRaster/src/org/gvsig/raster/dataset/IBuffer.java
99 99
    public float getFloatNoDataValue();
100 100
    
101 101
    /**
102
     * Obtiene true si el pixel pasado por par?metro cae dentro de los l?mites
103
     * del rater y false si cae fuera. 
104
     * @param x Posici?n X del pixel a averiguar
105
     * @param y Posici?n Y del pixel a averiguar
106
     * @return true si est? dentro y false si cae fuera.
107
     */
108
    public boolean isInside(int x, int y);
109
    
110
    /**
102 111
     * Asigna el valor NoData 
103 112
     * @param nd Valor NoData
104 113
     */
trunk/libraries/libRaster/src/org/gvsig/raster/grid/GridInterpolated.java
19 19
package org.gvsig.raster.grid;
20 20

  
21 21
import org.gvsig.raster.buffer.BufferFactory;
22
import org.gvsig.raster.buffer.IQueryableRaster;
22
import org.gvsig.raster.buffer.BufferInterpolation;
23 23
import org.gvsig.raster.buffer.RasterBuffer;
24 24

  
25 25
/**
......
33 33

  
34 34
public class GridInterpolated extends GridReader{
35 35

  
36
	public static final int INTERPOLATION_NearestNeighbour = IQueryableRaster.INTERPOLATION_NearestNeighbour;
37
	public static final int INTERPOLATION_Bilinear = IQueryableRaster.INTERPOLATION_Bilinear;
38
	public static final int INTERPOLATION_InverseDistance = IQueryableRaster.INTERPOLATION_InverseDistance;
39
	public static final int INTERPOLATION_BicubicSpline = IQueryableRaster.INTERPOLATION_BicubicSpline;
40
	public static final int INTERPOLATION_BSpline = IQueryableRaster.INTERPOLATION_BSpline;
36
	public static final int INTERPOLATION_NearestNeighbour = BufferInterpolation.INTERPOLATION_NearestNeighbour;
37
	public static final int INTERPOLATION_Bilinear = BufferInterpolation.INTERPOLATION_Bilinear;
38
	public static final int INTERPOLATION_InverseDistance = BufferInterpolation.INTERPOLATION_InverseDistance;
39
	public static final int INTERPOLATION_BicubicSpline = BufferInterpolation.INTERPOLATION_BicubicSpline;
40
	public static final int INTERPOLATION_BSpline = BufferInterpolation.INTERPOLATION_BSpline;
41 41
	
42 42
	double m_dXMin , m_dYMax; //coordinates of the layer, not the window
43 43
	double m_dCellSize; //cellsize of the layer, not the window
trunk/libraries/libRaster/src/org/gvsig/raster/buffer/RasterBuffer.java
40 40
 * 
41 41
 */
42 42
public abstract class RasterBuffer implements IBuffer {
43
	public static final int		CANCEL_HISTOGRAM = IHistogramable.CANCEL_HISTOGRAM;
44
	protected boolean[]			cancel = new boolean[1];
45
	
43
	public static final int	CANCEL_HISTOGRAM = IHistogramable.CANCEL_HISTOGRAM;
44
	protected boolean[]		cancel = new boolean[1];
45

  
46 46
	//Espacio en memoria (en Megas) que hay que sobrepasar para empezar a cachear.
47 47
	private static int		cacheMemorySize = 25;
48 48
	//Espacio en memoria (en Megas) que hay que sobrepasar para empezar a cachear en multipagina.
49 49
	private static int		multicacheMemorySize = 100;
50
	
51
	public double 			noDataValue = -99999;
52 50

  
53
	protected int				percent = 0;
51
	public double			noDataValue = -99999;
52

  
53
	protected int			percent = 0;
54 54
	protected boolean		canceled = false;
55
	
56
  protected int 			width;
57
  protected int 			height;
58
  protected int 			nBands;
59
  protected int 			dataType;
55

  
56
	protected int			width;
57
	protected int			height;
58
	protected int			nBands;
59
	protected int			dataType;
60 60
  
61 61
  /**
62 62
   * Variable est?tica que si est? a false desactiva el uso de cach?. Puede ser usada por un cliente
63 63
   * para cargar siempre los datos en memoria. independientemente de su tama?o. 
64 64
   */
65
  public static boolean	cacheOn = true;
65
  public static boolean		cacheOn = true;
66 66
  /**
67 67
   * Fuerza la carga de los datos en cach? independientemente de su tama?o. Su
68 68
   * uso suele ser util solo para depuraci?n. Su valor por defecto y recomendado
......
80 80
   * no tiene datos asignados y tampoco puede ser null. Todas las bandas no validas de un buffer
81 81
   * apuntan por referencia a la misma banda.
82 82
   */
83
  protected double		notValidValue = 0D;
83
  protected double			notValidValue = 0D;
84
  
85
  private BufferInterpolation	interp = null;
84 86

  
85 87
  /**
86 88
   * Genera instancias del buffer de datos adecuado al tama?o del raster. Si no hay muchos datos
......
270 272
      return null;
271 273
  }
272 274
  
273
  /**
274
   * Ajusta el raster al ancho y alto solicitado por el vecino m?s cercano. Promedia el valor de dos
275
   * pixeles contiguos.
276
   * @param w Nuevo ancho
277
   * @param h Nuevo alto
275
  /*
276
   * (non-Javadoc)
277
   * @see org.gvsig.raster.dataset.IBuffer#isInside(int, int)
278 278
   */
279
  private RasterBuffer adjustRasterNearestNeighbourInterpolation(int w, int h) {
280
  	double stepX = (double)w / (double)width;
281
  	double stepY = (double)h / (double)height;
282
  	RasterBuffer rasterBuf = new RasterMemoryBuffer(getDataType(), w, h, getBandCount(), true);
283
  	
284
  	int[] bands = new int[rasterBuf.getBandCount()];
285
  	for(int iBand = 0; iBand < rasterBuf.getBandCount(); iBand ++)
286
  		bands[iBand] = iBand;
287
  	
288
  	
289
  	switch (dataType) {                    
290
      case RasterBuffer.TYPE_BYTE:
291
      	for(int iBand = 0; iBand < bands.length; iBand ++) {
292
      		if(w <= width) { //submuestreo
293
      			for(int iRow = 0; iRow < height; iRow ++)
294
      				for(int iCol = 0; iCol < width; iCol ++)
295
      					rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemByte(iRow, iCol, iBand));
296
      		}else{ //supermuestreo
297
      			for(int iRow = 0; iRow < h; iRow ++)
298
      				for(int iCol = 0; iCol < w; iCol ++)
299
      					rasterBuf.setElem(iRow, iCol, bands[iBand], getElemByte((int)(iRow / stepY), (int)(iCol / stepX), iBand));
300
      		}
301
      	}
302
      	break;
303
      case RasterBuffer.TYPE_DOUBLE:
304
      	for(int iBand = 0; iBand < bands.length; iBand ++) {
305
      		if(w <= width) { //submuestreo
306
      			for(int iRow = 0; iRow < height; iRow ++)
307
      				for(int iCol = 0; iCol < width; iCol ++)
308
      					rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemDouble(iRow, iCol, iBand));
309
      		}else{ //supermuestreo
310
      			for(int iRow = 0; iRow < h; iRow ++)
311
      				for(int iCol = 0; iCol < w; iCol ++)
312
      					rasterBuf.setElem(iRow, iCol, bands[iBand], getElemDouble((int)(iRow / stepY), (int)(iCol / stepX), iBand));
313
      		}
314
      	}
315
      	break;
316
      case RasterBuffer.TYPE_FLOAT:
317
      	for(int iBand = 0; iBand < bands.length; iBand ++) {
318
      		if(w <= width) { //submuestreo
319
      			for(int iRow = 0; iRow < height; iRow ++)
320
      				for(int iCol = 0; iCol < width; iCol ++)
321
      					rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemFloat(iRow, iCol, iBand));
322
      		}else{ //supermuestreo
323
      			for(int iRow = 0; iRow < h; iRow ++)
324
      				for(int iCol = 0; iCol < w; iCol ++)
325
      					rasterBuf.setElem(iRow, iCol, bands[iBand], getElemFloat((int)(iRow / stepY), (int)(iCol / stepX), iBand));
326
      		}
327
      	}
328
      	break;
329
      case RasterBuffer.TYPE_INT:
330
      	for(int iBand = 0; iBand < bands.length; iBand ++) {
331
      		if(w <= width) { //submuestreo
332
      			for(int iRow = 0; iRow < height; iRow ++)
333
      				for(int iCol = 0; iCol < width; iCol ++)
334
      					rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemInt(iRow, iCol, iBand));
335
      		}else{ //supermuestreo
336
      			for(int iRow = 0; iRow < h; iRow ++)
337
      				for(int iCol = 0; iCol < w; iCol ++)
338
      					rasterBuf.setElem(iRow, iCol, bands[iBand], getElemInt((int)(iRow / stepY), (int)(iCol / stepX), iBand));
339
      		}
340
      	}
341
      	break;
342
      case RasterBuffer.TYPE_USHORT:
343
      case RasterBuffer.TYPE_SHORT:
344
      	for(int iBand = 0; iBand < bands.length; iBand ++) {
345
      		if(w <= width) { //submuestreo
346
      			for(int iRow = 0; iRow < height; iRow ++)
347
      				for(int iCol = 0; iCol < width; iCol ++)
348
      					rasterBuf.setElem((int)(iRow * stepY), (int)(iCol * stepX), bands[iBand], getElemShort(iRow, iCol, iBand));
349
      		}else{ //supermuestreo
350
      			for(int iRow = 0; iRow < h; iRow ++)
351
      				for(int iCol = 0; iCol < w; iCol ++)
352
      					rasterBuf.setElem(iRow, iCol, bands[iBand], getElemShort((int)(iRow / stepY), (int)(iCol / stepX), iBand));
353
      		}
354
      	}
355
      	break;
356
      }
357
  	return rasterBuf; 
279
  public boolean isInside(int x, int y) {
280
	  if (x < 0 || y < 0 || x >= getWidth() || y >= getHeight())
281
		  return false;
282
	  return true;
358 283
  }
359
  
360
  /**
361
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n bilineal. Promedia
362
   * el valor de cuatro pixeles adyacentes.
363
   * @param w Nuevo ancho
364
   * @param h Nuevo alto
365
   */
366
  private RasterBuffer adjustRasterBilinearInterpolation(int w, int h) {
367
	  double pxSize = (double)width / (double)w;
368
	  RasterBuffer rasterBuf = new RasterMemoryBuffer(getDataType(), w, h, getBandCount(), true);
369
	  
370
	  double posX = pxSize / 2D;
371
	  double posY = posX;
372
	  double dx = 0D, dy = 0D;
373
	  
374
	  for(int iBand = 0; iBand < getBandCount(); iBand ++) {
375
		posY = pxSize / 2D;
376
		switch (dataType) {               
377
		case RasterBuffer.TYPE_BYTE:	
378
      		for(int iRow = 0; iRow < h; iRow ++) {
379
      			dy = posY - ((int)posY); 
380
      			posX = pxSize / 2D;
381
      			for(int iCol = 0; iCol < w; iCol ++) {
382
      				dx = posX - ((int)posX);
383
      				double[] kernel = getKernelByte(((int)posX), ((int)posY), iBand);
384
      				double[] nz = getBilinearNZ(dx, dy, kernel);
385
      				double b = 0;
386
      				if(nz[0] > 0.0)
387
      					b = (nz[1] / nz[0]);
388
      				rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)b & 0xff));
389
      				posX += pxSize;
390
      			}
391
      			posY += pxSize;
392
      		}
393
      		break;
394
		case RasterBuffer.TYPE_SHORT:
395
      		for(int iRow = 0; iRow < h; iRow ++) {
396
      			dy = posY - ((int)posY); 
397
      			posX = pxSize / 2D;
398
      			for(int iCol = 0; iCol < w; iCol ++) {
399
      				dx = posX - ((int)posX);
400
      				double[] kernel = getKernelShort(((int)posX), ((int)posY), iBand);
401
      				double[] nz = getBilinearNZ(dx, dy, kernel);
402
      				double b = 0;
403
      				if(nz[0] > 0.0)
404
      					b = (nz[1] / nz[0]);
405
      				rasterBuf.setElem(iRow, iCol, iBand, (short)((short)b & 0xffff));
406
      				posX += pxSize;
407
      			}
408
      			posY += pxSize;
409
      		}
410
      		break;
411
		case RasterBuffer.TYPE_INT:
412
      		for(int iRow = 0; iRow < h; iRow ++) {
413
      			dy = posY - ((int)posY); 
414
      			posX = pxSize / 2D;
415
      			for(int iCol = 0; iCol < w; iCol ++) {
416
      				dx = posX - ((int)posX);
417
      				double[] kernel = getKernelInt(((int)posX), ((int)posY), iBand);
418
      				double[] nz = getBilinearNZ(dx, dy, kernel);
419
      				double b = 0;
420
      				if(nz[0] > 0.0)
421
      					b = (nz[1] / nz[0]);
422
      				rasterBuf.setElem(iRow, iCol, iBand, (int)((int)b & 0xff));
423
      				posX += pxSize;
424
      			}
425
      			posY += pxSize;
426
      		}
427
      		break;
428
		case RasterBuffer.TYPE_FLOAT:
429
      		for(int iRow = 0; iRow < h; iRow ++) {
430
      			dy = posY - ((int)posY); 
431
      			posX = pxSize / 2D;
432
      			for(int iCol = 0; iCol < w; iCol ++) {
433
      				dx = posX - ((int)posX);
434
      				double[] kernel = getKernelFloat(((int)posX), ((int)posY), iBand);
435
      				double[] nz = getBilinearNZ(dx, dy, kernel);
436
      				double b = 0;
437
      				if(nz[0] > 0.0)
438
      					b = (nz[1] / nz[0]);
439
      				rasterBuf.setElem(iRow, iCol, iBand, (float)b);
440
      				posX += pxSize;
441
      			}
442
      			posY += pxSize;
443
      		}
444
      		break;
445
		case RasterBuffer.TYPE_DOUBLE:
446
      		for(int iRow = 0; iRow < h; iRow ++) {
447
      			dy = posY - ((int)posY); 
448
      			posX = pxSize / 2D;
449
      			for(int iCol = 0; iCol < w; iCol ++) {
450
      				dx = posX - ((int)posX);
451
      				double[] kernel = getKernelDouble(((int)posX), ((int)posY), iBand);
452
      				double[] nz = getBilinearNZ(dx, dy, kernel);
453
      				double b = 0;
454
      				if(nz[0] > 0.0)
455
      					b = (nz[1] / nz[0]);
456
      				rasterBuf.setElem(iRow, iCol, iBand, (double)b);
457
      				posX += pxSize;
458
      			}
459
      			posY += pxSize;
460
      		}
461
      		break;
462
	  	}
463
		
464
	  }
465
	  
466
	  return rasterBuf;
467
  }
468
  
469
  /**
470
   * Calcula los valores N y Z para el m?todo bilinear
471
   * @param dx distancia en X desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
472
   * @param dy distancia en Y desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
473
   * @param kernel valor del pixel y alrededor 
474
   * @return valore de N y Z
475
   */
476
  private double[] getBilinearNZ(double dx, double dy, double[] kernel) {
477
	double z = 0.0, n = 0.0, d;
478
	d = (1.0 - dx) * (1.0 - dy);
479
	z += d * kernel[0];
480
	n += d;
481

  
482
	d = dx * (1.0 - dy);
483
	z += d * kernel[1]; 
484
	n += d;
485

  
486
	d = (1.0 - dx) * dy;
487
	z += d * kernel[2]; 
488
	n += d;
489

  
490
	d = dx * dy;
491
	z += d * kernel[3]; 
492
	n += d;
493
	return new double[]{n, z};
494
  }
495

  
496
  /**
497
   * Calcula los valores N y Z para el m?todo bilinear
498
   * @param dx distancia en X desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
499
   * @param dy distancia en Y desde el centro del pixel hasta el punto. Es un valor entre 0 y 1
500
   * @param kernel valor del pixel y alrededor 
501
   * @return valore de N y Z
502
   */
503
  private double[] getInverseDistanceNZ(double dx, double dy, double[] kernel) {
504
	double z = 0.0, n = 0.0, d;
505
	d = 1.0 / Math.sqrt(dx * dx + dy * dy);
506
	z += d * kernel[0];
507
	n += d;
508

  
509
	d = 1.0 / Math.sqrt((1.0 - dx) * ( 1.0 - dx) + dy * dy);
510
	z += d * kernel[1]; 
511
	n += d;
512

  
513
	d = 1.0 / Math.sqrt(dx*dx + (1.0-dy)*(1.0-dy));
514
	z += d * kernel[2]; 
515
	n += d;
516

  
517
	d = 1.0 / Math.sqrt((1.0 - dx) *( 1.0 - dx) + (1.0 - dy) * (1.0 - dy));
518
	z += d * kernel[3]; 
519
	n += d;
520
	return new double[]{n, z};
521
  }
522

  
523
  
524
  /**
525
   * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
526
   * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
527
   * se tomar? x e y. 
528
   * @param x Coordenada X del pixel inicial
529
   * @param y Coordenada Y del pixel inicial
530
   * @param band N?mero de banda.
531
   * @return Kernel solicitado en forma de array.
532
   */
533
  private double[] getKernelByte(int x, int y, int band) {
534
	  double[] d = new double[4];
535
	  d[0] = (getElemByte(y, x, band) & 0xff);
536
	  int nextX = ((x + 1) >= getWidth()) ? x : (x + 1);
537
	  int nextY = ((y + 1) >= getHeight()) ? y : (y + 1);
538
	  d[1] = (getElemByte(y, nextX, band) & 0xff);
539
	  d[2] = (getElemByte(nextY, x, band) & 0xff);
540
	  d[3] = (getElemByte(nextY, nextX, band) & 0xff);
541
	  return d;
542
  }
543

  
544
  /**
545
   * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
546
   * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
547
   * se tomar? x e y. 
548
   * @param x Coordenada X del pixel inicial
549
   * @param y Coordenada Y del pixel inicial
550
   * @param band N?mero de banda.
551
   * @return Kernel solicitado en forma de array.
552
   */
553
  private double[] getKernelShort(int x, int y, int band) {
554
	  double[] d = new double[4];
555
	  d[0] = (getElemShort(y, x, band) & 0xffff);
556
	  int nextX = ((x + 1) >= getWidth()) ? x : (x + 1);
557
	  int nextY = ((y + 1) >= getHeight()) ? y : (y + 1);
558
	  d[1] = (getElemShort(y, nextX, band) & 0xffff);
559
	  d[2] = (getElemShort(nextY, x, band) & 0xffff);
560
	  d[3] = (getElemShort(nextY, nextX, band) & 0xffff);
561
	  return d;
562
  }
563
  
564
  /**
565
   * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
566
   * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
567
   * se tomar? x e y. 
568
   * @param x Coordenada X del pixel inicial
569
   * @param y Coordenada Y del pixel inicial
570
   * @param band N?mero de banda.
571
   * @return Kernel solicitado en forma de array.
572
   */
573
  private double[] getKernelInt(int x, int y, int band) {
574
	  double[] d = new double[4];
575
	  d[0] = (getElemInt(y, x, band) & 0xffffffff);
576
	  int nextX = ((x + 1) >= getWidth()) ? x : (x + 1);
577
	  int nextY = ((y + 1) >= getHeight()) ? y : (y + 1);
578
	  d[1] = (getElemInt(y, nextX, band) & 0xffffffff);
579
	  d[2] = (getElemInt(nextY, x, band) & 0xffffffff);
580
	  d[3] = (getElemInt(nextY, nextX, band) & 0xffffffff);
581
	  return d;
582
  }
583
  
584
  /**
585
   * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
586
   * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
587
   * se tomar? x e y. 
588
   * @param x Coordenada X del pixel inicial
589
   * @param y Coordenada Y del pixel inicial
590
   * @param band N?mero de banda.
591
   * @return Kernel solicitado en forma de array.
592
   */
593
  private double[] getKernelFloat(int x, int y, int band) {
594
	  double[] d = new double[4];
595
	  d[0] = getElemFloat(y, x, band);
596
	  int nextX = ((x + 1) >= getWidth()) ? x : (x + 1);
597
	  int nextY = ((y + 1) >= getHeight()) ? y : (y + 1);
598
	  d[1] = getElemFloat(y, nextX, band);
599
	  d[2] = getElemFloat(nextY, x, band);
600
	  d[3] = getElemFloat(nextY, nextX, band);
601
	  return d;
602
  }
603
  
604
  /**
605
   * Obtiene un kernel de cuatro elemento que corresponden a los pixeles (x, y), (x + 1, y),
606
   * (x, y + 1), (x + 1, y + 1). Si los pixeles x + 1 o y + 1 se salen del raster de origen
607
   * se tomar? x e y. 
608
   * @param x Coordenada X del pixel inicial
609
   * @param y Coordenada Y del pixel inicial
610
   * @param band N?mero de banda.
611
   * @return Kernel solicitado en forma de array.
612
   */
613
  private double[] getKernelDouble(int x, int y, int band) {
614
	  double[] d = new double[4];
615
	  d[0] = getElemDouble(y, x, band);
616
	  int nextX = ((x + 1) >= getWidth()) ? x : (x + 1);
617
	  int nextY = ((y + 1) >= getHeight()) ? y : (y + 1);
618
	  d[1] = getElemDouble(y, nextX, band);
619
	  d[2] = getElemDouble(nextY, x, band);
620
	  d[3] = getElemDouble(nextY, nextX, band);
621
	  return d;
622
  }
623
  
624
  /**
625
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de distancia inversa.
626
   * Asigna el valor de un pixel en funci?n inversa de la distancia.
627
   * 
628
   * @param w Nuevo ancho
629
   * @param h Nuevo alto
630
   */
631
  private RasterBuffer adjustRasterInverseDistanceInterpolation(int w, int h) {
632
	  double pxSize = (double)width / (double)w;
633
	  RasterBuffer rasterBuf = new RasterMemoryBuffer(getDataType(), w, h, getBandCount(), true);
634
	  
635
	  double posX = pxSize / 2D;
636
	  double posY = posX;
637
	  double dx = 0D, dy = 0D;
638
	  
639
	  for(int iBand = 0; iBand < getBandCount(); iBand ++) {
640
		posY = pxSize / 2D;
641
		switch (dataType) {               
642
		case RasterBuffer.TYPE_BYTE:	
643
      		for(int iRow = 0; iRow < h; iRow ++) {
644
      			dy = posY - ((int)posY); 
645
      			posX = pxSize / 2D;
646
      			for(int iCol = 0; iCol < w; iCol ++) {
647
      				dx = posX - ((int)posX);
648
      				double[] kernel = getKernelByte(((int)posX), ((int)posY), iBand);
649
      				double[] nz = getInverseDistanceNZ(dx, dy, kernel);
650
      				double b = 0;
651
      				if(nz[0] > 0.0)
652
      					b = (nz[1] / nz[0]);
653
      				rasterBuf.setElem(iRow, iCol, iBand, (byte)((byte)b & 0xff));
654
      				posX += pxSize;
655
      			}
656
      			posY += pxSize;
657
      		}
658
      		break;
659
		case RasterBuffer.TYPE_SHORT:
660
      		for(int iRow = 0; iRow < h; iRow ++) {
661
      			dy = posY - ((int)posY); 
662
      			posX = pxSize / 2D;
663
      			for(int iCol = 0; iCol < w; iCol ++) {
664
      				dx = posX - ((int)posX);
665
      				double[] kernel = getKernelShort(((int)posX), ((int)posY), iBand);
666
      				double[] nz = getInverseDistanceNZ(dx, dy, kernel);
667
      				double b = 0;
668
      				if(nz[0] > 0.0)
669
      					b = (nz[1] / nz[0]);
670
      				rasterBuf.setElem(iRow, iCol, iBand, (short)((short)b & 0xffff));
671
      				posX += pxSize;
672
      			}
673
      			posY += pxSize;
674
      		}
675
      		break;
676
		case RasterBuffer.TYPE_INT:
677
      		for(int iRow = 0; iRow < h; iRow ++) {
678
      			dy = posY - ((int)posY); 
679
      			posX = pxSize / 2D;
680
      			for(int iCol = 0; iCol < w; iCol ++) {
681
      				dx = posX - ((int)posX);
682
      				double[] kernel = getKernelInt(((int)posX), ((int)posY), iBand);
683
      				double[] nz = getInverseDistanceNZ(dx, dy, kernel);
684
      				double b = 0;
685
      				if(nz[0] > 0.0)
686
      					b = (nz[1] / nz[0]);
687
      				rasterBuf.setElem(iRow, iCol, iBand, (int)((int)b & 0xff));
688
      				posX += pxSize;
689
      			}
690
      			posY += pxSize;
691
      		}
692
      		break;
693
		case RasterBuffer.TYPE_FLOAT:
694
      		for(int iRow = 0; iRow < h; iRow ++) {
695
      			dy = posY - ((int)posY); 
696
      			posX = pxSize / 2D;
697
      			for(int iCol = 0; iCol < w; iCol ++) {
698
      				dx = posX - ((int)posX);
699
      				double[] kernel = getKernelFloat(((int)posX), ((int)posY), iBand);
700
      				double[] nz = getInverseDistanceNZ(dx, dy, kernel);
701
      				double b = 0;
702
      				if(nz[0] > 0.0)
703
      					b = (nz[1] / nz[0]);
704
      				rasterBuf.setElem(iRow, iCol, iBand, (float)b);
705
      				posX += pxSize;
706
      			}
707
      			posY += pxSize;
708
      		}
709
      		break;
710
		case RasterBuffer.TYPE_DOUBLE:
711
      		for(int iRow = 0; iRow < h; iRow ++) {
712
      			dy = posY - ((int)posY); 
713
      			posX = pxSize / 2D;
714
      			for(int iCol = 0; iCol < w; iCol ++) {
715
      				dx = posX - ((int)posX);
716
      				double[] kernel = getKernelDouble(((int)posX), ((int)posY), iBand);
717
      				double[] nz = getInverseDistanceNZ(dx, dy, kernel);
718
      				double b = 0;
719
      				if(nz[0] > 0.0)
720
      					b = (nz[1] / nz[0]);
721
      				rasterBuf.setElem(iRow, iCol, iBand, (double)b);
722
      				posX += pxSize;
723
      			}
724
      			posY += pxSize;
725
      		}
726
      		break;
727
	  	}
728
		
729
	  }
730
	  
731
	  return rasterBuf;
732
  }
733
  
734
  /**
735
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n de spline bicubica.
736
   * @param w Nuevo ancho
737
   * @param h Nuevo alto
738
   */
739
  private RasterBuffer adjustRasterBicubicSplineInterpolation(int w, int h) {
740
	  return this;
741
  }
742
  
743
  /**
744
   * Ajusta el raster al ancho y alto solicitado ajustando con una interpolaci?n BSpline.
745
   * @param w Nuevo ancho
746
   * @param h Nuevo alto
747
   */
748
  private RasterBuffer adjustRasterBSplineInterpolation(int w, int h) {
749
	  return this;
750
  }
751
  
284
      
752 285
  /*
753 286
   *  (non-Javadoc)
754 287
   * @see org.gvsig.fmap.driver.IBuffer#getNoDataValue()
......
827 360
	 * @param interpolation M?todo de interpolaci?n que se usar? en el ajuste.
828 361
	 */
829 362
	public RasterBuffer getAdjustedWindow(int w, int h, int interpolationMethod) {
363
		if(interp == null)
364
			interp = new BufferInterpolation(this);
365
		
830 366
		if(w == getWidth() && h == getHeight())
831 367
			return this;
832 368
		RasterBuffer rasterBuf = null;
833 369
		switch(interpolationMethod) {
834
		case IQueryableRaster.INTERPOLATION_NearestNeighbour:
835
				rasterBuf = adjustRasterNearestNeighbourInterpolation(w, h);
370
		case BufferInterpolation.INTERPOLATION_NearestNeighbour:
371
				rasterBuf = interp.adjustRasterNearestNeighbourInterpolation(w, h);
836 372
				break;
837
		case IQueryableRaster.INTERPOLATION_Bilinear:
838
				rasterBuf = adjustRasterBilinearInterpolation(w, h);
373
		case BufferInterpolation.INTERPOLATION_Bilinear:
374
				rasterBuf = interp.adjustRasterBilinearInterpolation(w, h);
839 375
				break;
840
		case IQueryableRaster.INTERPOLATION_InverseDistance:
841
				rasterBuf = adjustRasterInverseDistanceInterpolation(w, h);
376
		case BufferInterpolation.INTERPOLATION_InverseDistance:
377
				rasterBuf = interp.adjustRasterInverseDistanceInterpolation(w, h);
842 378
				break;
843
		case IQueryableRaster.INTERPOLATION_BicubicSpline:
844
				rasterBuf = adjustRasterBicubicSplineInterpolation(w, h);
379
		case BufferInterpolation.INTERPOLATION_BicubicSpline:
380
				rasterBuf = interp.adjustRasterBicubicSplineInterpolation(w, h);
845 381
				break;
846
		case IQueryableRaster.INTERPOLATION_BSpline:
847
				rasterBuf = adjustRasterBSplineInterpolation(w, h);
382
		case BufferInterpolation.INTERPOLATION_BSpline:
383
				rasterBuf = interp.adjustRasterBSplineInterpolation(w, h);
848 384
				break;
849 385
		}
850 386
		return rasterBuf;
trunk/libraries/libRaster/src/org/gvsig/raster/buffer/BufferInterpolation.java
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

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff