/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.image.interpolation;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import javax.media.jai.InterpolationBicubic;
import javax.media.jai.InterpolationBicubic2;
import javax.media.jai.RasterFactory;
import org.geotoolkit.image.iterator.PixelIterator;
import org.geotoolkit.image.iterator.PixelIteratorFactory;
import org.junit.Assert;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* <p>BiCubic Interpolation test.<br/>
*
* Test 2 made of biCubic interpolation.<br/>
*
* All interpolation values are compared to JAI interpolation results.</p>
*
* @author Remi Marechal (Geomatys).
*/
public class BiCubicTest extends InterpolationTest {
/**
* Raster attributes.
*/
private int miny, minx, width, height;
/**
* Raster use for biCubic test.
*/
private WritableRaster rastertest;
public BiCubicTest() {
miny = -1;
minx = -2;
width = 4;
height = 4;
}
/**
* <p>Test interpolate method from biCubic class.<br/><br/>
*
* Verify that interpolation at Integer pixel position equal pixel position value.<br/>
*/
@Test
public void globalTest() {
double val = -55;
width = 8;
height = 8;
rastertest = RasterFactory.createBandedRaster(DataBuffer.TYPE_DOUBLE, width, height, 1, new Point(minx, miny));
for (int y = miny; y < miny + height; y++) {
for (int x = minx; x < minx + width; x++) {
rastertest.setSample(x, y, 0, val++);
}
}
pixIterator = PixelIteratorFactory.createDefaultIterator(rastertest);
interpol = new BiCubicInterpolation1(pixIterator);
double interpolVal;
for (int y = miny+1; y < miny + height-2; y++) {
for (int x = minx+1; x < minx + width-2; x++) {
//-- interpolation verification at center pixel position.
interpolVal = interpol.interpolate(x, y, 0);
assertTrue(Math.abs(rastertest.getSampleDouble(x, y, 0) - interpolVal) <= 1E-12);
interpolVal = interpol.interpolate(x, y)[0];
assertTrue("At : ("+x+", "+y+ "Expected : "+(rastertest.getSampleDouble(x, y, 0))+" found : "+interpolVal, Math.abs(rastertest.getSampleDouble(x, y, 0) - interpolVal) <= 1E-12);
}
}
pixIterator.rewind();
interpol = new BiCubicInterpolation2(pixIterator);
for (int y = miny+1; y < miny + height-2; y++) {
for (int x = minx+1; x < minx + width-2; x++) {
//-- interpolation verification at center pixel position.
interpolVal = interpol.interpolate(x, y, 0);
assertTrue(Math.abs(rastertest.getSampleDouble(x, y, 0) - interpolVal) <= 1E-12);
interpolVal = interpol.interpolate(x, y)[0];
assertTrue("At : ("+x+", "+y+ "Expected : "+(rastertest.getSampleDouble(x, y, 0))+" found : "+interpolVal, Math.abs(rastertest.getSampleDouble(x, y, 0) - interpolVal) <= 1E-12);
}
}
}
/**
* Compare interpolation values with JAI library biCubic interpolation results.
*/
@Test
public void minAndMaxTest() throws InterruptedException {
width = 4;
height = 4;
//fill first band
rastertest = RasterFactory.createBandedRaster(DataBuffer.TYPE_DOUBLE, width, height, 3, new Point(minx, miny));
rastertest.setSample(-2, -1, 0, 1);
rastertest.setSample(-1, -1, 0, 1);
rastertest.setSample( 0, -1, 0, 1);
rastertest.setSample( 1, -1, 0, 1);
rastertest.setSample(-2, 0, 0, 1);
rastertest.setSample(-1, 0, 0, 2);
rastertest.setSample(-0, 0, 0, 2);
rastertest.setSample( 1, 0, 0, 1);
rastertest.setSample(-2, 1, 0, 1);
rastertest.setSample(-1, 1, 0, 2);
rastertest.setSample( 0, 1, 0, 2);
rastertest.setSample( 1, 1, 0, 1);
rastertest.setSample(-2, 2, 0, 1);
rastertest.setSample(-1, 2, 0, 1);
rastertest.setSample( 0, 2, 0, 1);
rastertest.setSample( 1, 2, 0, 1);
//fill second band
rastertest.setSample(-2, -1, 1, 2);
rastertest.setSample(-1, -1, 1, 2);
rastertest.setSample( 0, -1, 1, 2);
rastertest.setSample( 1, -1, 1, 2);
rastertest.setSample(-2, 0, 1, 2);
rastertest.setSample(-1, 0, 1, 1);
rastertest.setSample(-0, 0, 1, 1);
rastertest.setSample( 1, 0, 1, 2);
rastertest.setSample(-2, 1, 1, 2);
rastertest.setSample(-1, 1, 1, 1);
rastertest.setSample( 0, 1, 1, 1);
rastertest.setSample( 1, 1, 1, 2);
rastertest.setSample(-2, 2, 1, 2);
rastertest.setSample(-1, 2, 1, 2);
rastertest.setSample( 0, 2, 1, 2);
rastertest.setSample( 1, 2, 1, 2);
// fill third band
double val = 32;
for (int y = miny; y<miny+height; y++) {
for (int x = minx; x<minx+width; x++) {
rastertest.setSample(x, y, 2, val++);
}
}
//test about classic bicubic interpolation
checkBicubicInterpolation(rastertest, false);
//test about other made bicubic interpolation
checkBicubicInterpolation(rastertest, true);
}
/**
* test get min max values on raster corner.
*/
@Test
public void testFail() {
rastertest = RasterFactory.createBandedRaster(DataBuffer.TYPE_DOUBLE, width, height, 1, new Point(minx, miny));
pixIterator = PixelIteratorFactory.createDefaultIterator(rastertest);
interpol = new BiCubicInterpolation1(pixIterator);
//lower corner
try {
interpol.getMinMaxValue(new Rectangle(-2, -3, 3, 3));
Assert.fail("test should had failed");
} catch(Exception e) {
//ok
}
//lower right corner
try {
interpol.getMinMaxValue(new Rectangle(2, -3, 3, 3));
Assert.fail("test should had failed");
} catch(Exception e) {
//ok
}
//upper left corner
try {
interpol.getMinMaxValue(new Rectangle(-3, 3, 3, 3));
Assert.fail("test should had failed");
} catch(Exception e) {
//ok
}
//upper corner
try {
interpol.getMinMaxValue(new Rectangle(1, 2, 3, 3));
Assert.fail("test should had failed");
} catch(Exception e) {
//ok
}
}
/**
* Compare biCubic interpolation results from Jai library {@link javax.media.jai.Interpolation}
* and from biCubic interpolation {@link BiCubicInterpolation}.
*
* @param raster tested raster.
* @param keys define type of biCubic interpolation.
*/
private void checkBicubicInterpolation(Raster raster, boolean keys) {
final int numBand = raster.getNumBands();
final int minX = raster.getMinX();
final int minY = raster.getMinY();
final int rW = raster.getWidth();
final int rH = raster.getHeight();
double[] jaiInter;
javax.media.jai.Interpolation jaiInterpol = (keys) ? new InterpolationBicubic2(8) : new InterpolationBicubic(8);
PixelIterator pixelIterator = PixelIteratorFactory.createDefaultIterator(raster);
interpol = (keys) ? new BiCubicInterpolation2(pixelIterator) : new BiCubicInterpolation1(pixelIterator);
double x, y, tolerance;
for(int b = 0; b < numBand; b++) {
for (int ny = 0; ny < 100; ny++) {
for (int nx = 0; nx < 100; nx++) {
x = minX + 1 + nx * 0.01;
y = minY + 1 + ny * 0.01;
jaiInter = getJAIInterpolate(jaiInterpol, raster, x, y, rW, rH, numBand);
for (int b2 = 0; b2 <numBand; b2++) {
//-- to simulate pixel center
double inter = interpol.interpolate(x, y, b2);
tolerance = ((inter + jaiInter[b2]) / 2) * 1E-2;//1%
assertEquals("checkBicubicInterpolation at position : ("+x+", "+y+", "+b2+") : ", jaiInter[b2], inter, tolerance);
}
}
}
}
}
/**
* Find interpolation value at x, y coordinate for each raster band.
*
* @param jaiInterpol interpolation type from jai library.
* @param raster raster which contain data.
* @param x interpolation X coordinate.
* @param y interpolation Y coordinate.
* @param rasterWidth raster width.
* @param rasterHeight raster height.
* @param rasterNumBand raster number bands.
* @return double table which contain interpolation value at x, y coordinate for each raster band.
*/
private double[] getJAIInterpolate(javax.media.jai.Interpolation jaiInterpol, Raster raster, double x, double y, int rasterWidth, int rasterHeight, int rasterNumBand){
int mx = (int) x;
int my = (int) y;
if (x < mx) mx--;
if (y < my) my--;
//-- ajust area interpolation on x, y center.
mx -= rasterWidth / 2 - 1;
my -= rasterHeight / 2 - 1;
float ix = (float) (x-mx-1);
float iy = (float) (y-my-1);
final double[] jaiResult = new double[rasterNumBand];
final double[][] interpolSample = new double[4][4];
for (int b = 0; b<rasterNumBand; b++) {
for (int idy = my; idy < my + 4; idy++) {
for (int idx = mx; idx < mx + 4; idx++) {
interpolSample[idy - my][idx - mx] = raster.getSampleDouble(idx, idy, b);
}
}
jaiResult[b] = jaiInterpol.interpolate(interpolSample, (float) ix, (float) iy);
}
return jaiResult;
}
}