/* JAI-Ext - OpenSource Java Advanced Image Extensions Library
* http://www.geo-solutions.it/
* Copyright 2014 GeoSolutions
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.geosolutions.jaiext.warp;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.io.IOException;
import javax.media.jai.BorderExtender;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.ROI;
import javax.media.jai.RenderedOp;
import javax.media.jai.TiledImage;
import javax.media.jai.Warp;
import it.geosolutions.jaiext.range.Range;
import it.geosolutions.jaiext.range.RangeFactory;
import it.geosolutions.jaiext.stats.Statistics;
import it.geosolutions.jaiext.stats.Statistics.StatsType;
import it.geosolutions.jaiext.stats.StatisticsDescriptor;
import it.geosolutions.jaiext.testclasses.TestBase;
import it.geosolutions.rendered.viewer.RenderedImageBrowser;
/**
* Test class which extends the jt-utilities TestBase class and provide utility methods for testing the various classes. The tests can be made with
* nearest-neighbor, bilinear, bicubic and a general type of interpolation. All the tests can be executed with and without ROI and No Data.
*
* It is possible to see the result of each operation by adding the following parameters:
* <ul>
* <li>-DJAI.Ext.Interactive=true(false default)</li>
* <li>-DJAI.Ext.TestSelection=0(No ROI No NODATA,default), 2(ROI No NODATA), 4(NODATA No ROI), 5(NODATA ROI)</li>
* <li>-DJAI.Ext.InterpolationType=0(Nearest,default), 1(Bilinear), 2(Bicubic), 3(General interpolation, in this case Bicubic)</li>
* </ul>
*
*/
public class TestWarp extends TestBase {
/** Angle rotation for the warp transformation */
protected final static double ANGLE_ROTATION = 45d;
/** Warp object used in tests */
protected static Warp warpObj;
/** Default number of images to test */
protected static final int NUM_IMAGES = 6;
/** Images to test */
protected static RenderedImage[] images;
/** No data value for Byte images */
protected static byte noDataValueB;
/** Interpolation to test */
protected static InterpolationType interpType;
/** No data value for UShort images */
protected static short noDataValueU;
/** No data value for Short images */
protected static short noDataValueS;
/** No data value for Integer images */
protected static int noDataValueI;
/** No data value for Float images */
protected static float noDataValueF;
/** No data value for Double images */
protected static double noDataValueD;
/**
* General method for testing a RenderedImage with the selected interpolation, warp object and with or without ROI and No Data.
*/
public void testWarp(RenderedImage source, boolean noDataUsed, boolean roiUsed, Warp warpObj,
Number noDataValue, InterpolationType interpType, TestSelection testSelect) {
// Image data type
int dataType = source.getSampleModel().getDataType();
// ROI
ROI roi = null;
if (roiUsed) {
roi = roiCreation();
}
// Hints used for image expansion
RenderingHints hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
BorderExtender.createInstance(BorderExtender.BORDER_COPY));
RenderedOp destinationIMG = null;
// Interpolator variable
Interpolation interp;
// Interpolators
switch (interpType) {
case NEAREST_INTERP:
// Nearest-Neighbor
interp = new javax.media.jai.InterpolationNearest();
break;
case BILINEAR_INTERP:
// Bilinear
interp = new javax.media.jai.InterpolationBilinear(DEFAULT_SUBSAMPLE_BITS);
break;
case BICUBIC_INTERP:
// Bicubic
interp = new javax.media.jai.InterpolationBicubic(DEFAULT_SUBSAMPLE_BITS);
break;
case GENERAL_INTERP:
// Bicubic
interp = new javax.media.jai.InterpolationBicubic(DEFAULT_SUBSAMPLE_BITS);
break;
default:
throw new IllegalArgumentException("Wrong interpolation type");
}
// Warp operation
double[] background = new double[] {destinationNoData};
destinationIMG = WarpDescriptor.create(source, warpObj, interp, background, roi, hints);
if (INTERACTIVE && dataType == DataBuffer.TYPE_BYTE
&& TEST_SELECTOR == testSelect.getType()) {
RenderedImageBrowser.showChain(destinationIMG, false, roiUsed);
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
} else {
// Forcing to retrieve an array of all the image tiles
destinationIMG.getTiles();
}
// Control if the operation has been correctly performed.
// Check if the final image dimensions are more than 0
assertTrue(destinationIMG.getHeight() > 0);
assertTrue(destinationIMG.getWidth() > 0);
// Check if the finalImage dimensions are correct
Rectangle inputRect = new Rectangle(source.getMinX(), source.getMinY(), source.getWidth(),
source.getHeight());
Rectangle outputRect = warpObj.mapSourceRect(inputRect);
assertEquals(destinationIMG.getMinX(), outputRect.x);
assertEquals(destinationIMG.getMinY(), outputRect.y);
assertEquals(destinationIMG.getHeight(), outputRect.width);
assertEquals(destinationIMG.getWidth(), outputRect.height);
// check the destination image ROI
if(roiUsed) {
Object roiProperty = destinationIMG.getProperty("ROI");
assertThat(roiProperty, instanceOf(ROI.class));
ROI destRoi = (ROI) roiProperty;
// we have warped the ROI
RenderedImage roiImage = destRoi.getAsImage();
assertThat(roiImage, instanceOf(RenderedOp.class));
RenderedOp roiOp = (RenderedOp) roiImage;
switch (interpType) {
case NEAREST_INTERP:
assertThat(getWarpOperation(roiOp), instanceOf(WarpNearestOpImage.class));
break;
case BILINEAR_INTERP:
assertThat(getWarpOperation(roiOp), instanceOf(WarpBilinearOpImage.class));
break;
case BICUBIC_INTERP:
case GENERAL_INTERP:
assertThat(getWarpOperation(roiOp), instanceOf(WarpBicubicOpImage.class));
break;
default:
throw new IllegalArgumentException("Wrong interpolation type");
}
}
// Control if the final image has some data
destinationNoData = 10;
StatsType[] stats = new StatsType[] { StatsType.MEAN };
Range noData;
switch (dataType) {
case DataBuffer.TYPE_BYTE:
noData = RangeFactory.create((byte) destinationNoData, true, (byte) destinationNoData,
true);
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
noData = RangeFactory.create((short) destinationNoData, true,
(short) destinationNoData, true);
break;
case DataBuffer.TYPE_INT:
noData = RangeFactory.create((int) destinationNoData, true, (int) destinationNoData,
true);
break;
case DataBuffer.TYPE_FLOAT:
noData = RangeFactory.create((float) destinationNoData, true,
(float) destinationNoData, true, true);
break;
case DataBuffer.TYPE_DOUBLE:
noData = RangeFactory.create(destinationNoData, true, destinationNoData, true, true);
break;
default:
throw new IllegalArgumentException("Wrong data type");
}
RenderedOp statistics = StatisticsDescriptor.create(destinationIMG, 1, 1, roi, noData,
false, new int[] { 0 }, stats, null, null, null, hints);
Statistics[][] result = (Statistics[][]) statistics.getProperty(Statistics.STATS_PROPERTY);
// Image disposal
destinationIMG.dispose();
double mean = (Double) result[0][0].getResult();
long num = (long) result[0][0].getNumSamples();
assertTrue(num > 0);
assertTrue(mean != destinationNoData);
// Image disposal
statistics.dispose();
}
private RenderedImage getWarpOperation(RenderedOp roiOp) {
String name = roiOp.getOperationName();
if("binarize".equals(name)) {
return roiOp.getSourceImage(0);
} else {
return roiOp.getRendering();
}
}
/**
* Test without ROI and without NoData
*/
public void testImage(InterpolationType interpType) {
boolean roiUsed = false;
boolean noDataUsed = false;
TestSelection testSelect = TestSelection.NO_ROI_ONLY_DATA;
testWarp(images[0], noDataUsed, roiUsed, warpObj, noDataValueB, interpType, testSelect);
testWarp(images[1], noDataUsed, roiUsed, warpObj, noDataValueU, interpType, testSelect);
testWarp(images[2], noDataUsed, roiUsed, warpObj, noDataValueS, interpType, testSelect);
testWarp(images[3], noDataUsed, roiUsed, warpObj, noDataValueI, interpType, testSelect);
testWarp(images[4], noDataUsed, roiUsed, warpObj, noDataValueF, interpType, testSelect);
testWarp(images[5], noDataUsed, roiUsed, warpObj, noDataValueD, interpType, testSelect);
}
/**
* Test with ROI and without NoData
*/
public void testImageROI(InterpolationType interpType) {
boolean roiUsed = true;
boolean noDataUsed = false;
TestSelection testSelect = TestSelection.ROI_ONLY_DATA;
testWarp(images[0], noDataUsed, roiUsed, warpObj, noDataValueB, interpType, testSelect);
testWarp(images[1], noDataUsed, roiUsed, warpObj, noDataValueU, interpType, testSelect);
testWarp(images[2], noDataUsed, roiUsed, warpObj, noDataValueS, interpType, testSelect);
testWarp(images[3], noDataUsed, roiUsed, warpObj, noDataValueI, interpType, testSelect);
testWarp(images[4], noDataUsed, roiUsed, warpObj, noDataValueF, interpType, testSelect);
testWarp(images[5], noDataUsed, roiUsed, warpObj, noDataValueD, interpType, testSelect);
}
/**
* Test without ROI and with NoData
*/
public void testImageNoData(InterpolationType interpType) {
boolean roiUsed = false;
boolean noDataUsed = true;
TestSelection testSelect = TestSelection.NO_ROI_NO_DATA;
testWarp(images[0], noDataUsed, roiUsed, warpObj, noDataValueB, interpType, testSelect);
testWarp(images[1], noDataUsed, roiUsed, warpObj, noDataValueU, interpType, testSelect);
testWarp(images[2], noDataUsed, roiUsed, warpObj, noDataValueS, interpType, testSelect);
testWarp(images[3], noDataUsed, roiUsed, warpObj, noDataValueI, interpType, testSelect);
testWarp(images[4], noDataUsed, roiUsed, warpObj, noDataValueF, interpType, testSelect);
testWarp(images[5], noDataUsed, roiUsed, warpObj, noDataValueD, interpType, testSelect);
}
/**
* Test with ROI and with NoData
*/
public void testImageNoDataROI(InterpolationType interpType) {
boolean roiUsed = true;
boolean noDataUsed = true;
TestSelection testSelect = TestSelection.ROI_NO_DATA;
testWarp(images[0], noDataUsed, roiUsed, warpObj, noDataValueB, interpType, testSelect);
testWarp(images[1], noDataUsed, roiUsed, warpObj, noDataValueU, interpType, testSelect);
testWarp(images[2], noDataUsed, roiUsed, warpObj, noDataValueS, interpType, testSelect);
testWarp(images[3], noDataUsed, roiUsed, warpObj, noDataValueI, interpType, testSelect);
testWarp(images[4], noDataUsed, roiUsed, warpObj, noDataValueF, interpType, testSelect);
testWarp(images[5], noDataUsed, roiUsed, warpObj, noDataValueD, interpType, testSelect);
}
/**
* Final method for closing the input images
*/
public static void finalStuff() {
// Creation of the images
if (images != null) {
((TiledImage) images[0]).dispose();
((TiledImage) images[1]).dispose();
((TiledImage) images[2]).dispose();
((TiledImage) images[3]).dispose();
((TiledImage) images[4]).dispose();
((TiledImage) images[5]).dispose();
}
}
}