/* 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.crop; import static org.junit.Assert.*; 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; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.io.IOException; import javax.media.jai.JAI; import javax.media.jai.ParameterBlockJAI; import javax.media.jai.ROI; import javax.media.jai.ROIShape; import javax.media.jai.RenderedOp; import javax.media.jai.TileCache; import javax.media.jai.operator.SubtractDescriptor; import org.junit.BeforeClass; import org.junit.Test; import com.sun.media.jai.util.SunTileCache; /** * This test class compares the old Crop operation implementation with the new one. The optional presence of No Data and ROI is tested. Also the * capability of the new Crop operator to maintain (if present) the hints related to the tile cache is tested. This class can also show the result of * the crop operation without No Data and Roi, with ROI only and with ROI and NoData together by setting the JVM JAI.Ext interactive parameter to * true, and setting the JVM integer parameter respectively to 0,1 or 2. */ public class CropImageTest extends TestBase { /** No data value used for the tests */ private final static byte noDataValue = 50; /** Source image */ private static RenderedImage source; /** Destination no data array to use for filling the source NoData Values */ private static double[] destNoData; @BeforeClass public static void initialSetup() { source = createTestImage(DataBuffer.TYPE_BYTE, DEFAULT_WIDTH, DEFAULT_HEIGHT, noDataValue, false); destNoData = new double[] { 127 }; } @Test public void testCropImagePB() { // Parameterblock creation ParameterBlock pb = buildParameterBlock(source, false, false, false); ParameterBlock pbNew = buildParameterBlock(source, true, false, false); // Images creation RenderedOp cropped = JAI.create("crop", pb); RenderedOp jaiextCropped = JAI.create("Crop", pbNew); // Test on the selected image assertImageEquals(cropped, jaiextCropped); // Display Image if (INTERACTIVE && TEST_SELECTOR == 0) { RenderedImageBrowser.showChain(jaiextCropped, false, false); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void testCropImageROI() { // Parameterblock creation ParameterBlock pb = buildParameterBlock(source, false, false, false); ParameterBlock pbNew = buildParameterBlock(source, true, true, false); // Images creation RenderedOp cropped = JAI.create("crop", pb); RenderedOp jaiextCropped = JAI.create("Crop", pbNew); // Check if the presence of the ROI reduces the image bounds Rectangle boundOld = cropped.getBounds(); Rectangle boundNew = jaiextCropped.getBounds(); boolean contained = boundNew.getMinX() >= boundOld.getMinX() && boundNew.getMinY() >= boundOld.getMinY() && boundNew.getMaxX() <= boundOld.getMaxX() && boundNew.getMaxY() <= boundOld.getMaxY(); assertTrue(contained); // Display Image if (INTERACTIVE && TEST_SELECTOR == 1) { RenderedImageBrowser.showChain(jaiextCropped, false, true); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void testCropImageROINoData() { // Parameterblock creation ParameterBlock pb = buildParameterBlock(source, false, false, false); ParameterBlock pbNew = buildParameterBlock(source, true, true, true); // Images creation RenderedOp cropped = JAI.create("crop", pb); RenderedOp jaiextCropped = JAI.create("Crop", pbNew); Rectangle boundOld = cropped.getBounds(); Rectangle boundNew = jaiextCropped.getBounds(); // Check if the presence of the ROI reduces the image bounds boolean contained = boundNew.getMinX() >= boundOld.getMinX() && boundNew.getMinY() >= boundOld.getMinY() && boundNew.getMaxX() <= boundOld.getMaxX() && boundNew.getMaxY() <= boundOld.getMaxY(); assertTrue(contained); // Check if the NoData values are taken into account int tileMinX = jaiextCropped.getMinTileX(); int tileMinY = jaiextCropped.getMinTileY(); Raster tile = jaiextCropped.getTile(tileMinX, tileMinY); int tileMinXpix = tile.getMinX(); int tileMinYpix = tile.getMinY(); int tileMaxXpix = tile.getWidth() + tileMinXpix; int tileMaxYpix = tile.getHeight() + tileMinYpix; boolean destinationNoDataFound = false; for (int i = tileMinXpix; i < tileMaxXpix; i++) { for (int j = tileMinYpix; j < tileMaxYpix; j++) { int value = tile.getSample(i, j, 0); if (value == (int) destNoData[0]) { destinationNoDataFound = true; break; } } if (destinationNoDataFound) { break; } } // Display Image if (INTERACTIVE && TEST_SELECTOR == 2) { RenderedImageBrowser.showChain(jaiextCropped, false, true); try { System.in.read(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void testTileCache() { // Creation of the Tile Cache TileCache tc = new SunTileCache(); // Addition of the TileCache hints RenderingHints hints = new RenderingHints(JAI.KEY_TILE_CACHE, tc); // Parameterblock creation ParameterBlock pb = buildParameterBlock(source, true, false, false); // Crop operation RenderedOp jaiextCropped = JAI.create("Crop", pb, hints); // force to compute the image jaiextCropped.getColorModel(); // Check if the Tile Cache used is the same assertSame(tc, jaiextCropped.getRenderingHint(JAI.KEY_TILE_CACHE)); } @Test public void testNullTileCache() { // Addition of Null TileCache hints RenderingHints hints = new RenderingHints(JAI.KEY_TILE_CACHE, null); // Parameterblock creation ParameterBlock pb = buildParameterBlock(source, true, false, false); // Crop operation RenderedOp jaiCropped = JAI.create("Crop", pb, hints); // force to compute the image jaiCropped.getColorModel(); // Check if the Tile Cache is not present assertNull(jaiCropped.getRenderingHint(JAI.KEY_TILE_CACHE)); } @Test public void testNullTileCacheDescriptor() { // Addition of Null TileCache hints RenderingHints hints = new RenderingHints(JAI.KEY_TILE_CACHE, null); // Crop operation(with the descriptor) RenderedOp cropped = CropDescriptor.create(source, 10f, 10f, 20f, 20f, null, null, null, hints); // force to compute the image cropped.getColorModel(); // Check if the Tile Cache is not present assertNull(cropped.getRenderingHint(JAI.KEY_TILE_CACHE)); } // Utility method for checking if two images are equals private void assertImageEquals(RenderedOp first, RenderedOp second) { // Calculation of the image difference RenderedOp difference = SubtractDescriptor.create(first, second, null); // Selection of the Statistics StatsType[] statsType = new StatsType[] { StatsType.EXTREMA }; // Calculation of the statistics RenderedOp stats = StatisticsDescriptor.create(difference, 1, 1, null, null, false, new int[] { 0, 1, 2 }, statsType, null); Statistics[][] results = (Statistics[][]) stats.getProperty(Statistics.STATS_PROPERTY); // Check if the Maximum and minimum for each band are equals for (int i = 0; i < results.length; i++) { double[] data = (double[]) results[i][0].getResult(); assertEquals(data[0], data[1], 0.0); } } // Utility method for creating the image parameter blocks private ParameterBlock buildParameterBlock(RenderedImage source, boolean newDescriptor, boolean roiUsed, boolean noDataUsed) { // Creation of the parameterBlock associated with its operation ParameterBlockJAI pb; if (newDescriptor) { pb = new ParameterBlockJAI("Crop"); } else { pb = new ParameterBlockJAI("crop"); } // Setting of the source pb.setSource("source0", source); // Setting of the parameters pb.setParameter("x", (float) 0); pb.setParameter("y", (float) 0); pb.setParameter("width", (float) 20); pb.setParameter("height", (float) 20); if (newDescriptor) { // If ROI is present, then it is added if (roiUsed) { ROI roi = new ROIShape(new Rectangle(5, 5, 10, 10)); pb.setParameter("ROI", roi); } // If NoData is present, then it is added if (noDataUsed) { Range noData = RangeFactory.create(noDataValue, true, noDataValue, true); pb.setParameter("NoData", noData); pb.setParameter("destNoData", destNoData); } } return pb; } }