/* 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.mosaic; import it.geosolutions.jaiext.JAIExt; import it.geosolutions.jaiext.range.Range; import it.geosolutions.jaiext.range.RangeFactory; import it.geosolutions.jaiext.testclasses.TestBase; import java.awt.RenderingHints; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import javax.media.jai.ImageLayout; import javax.media.jai.JAI; import javax.media.jai.PlanarImage; import javax.media.jai.RenderedOp; import javax.media.jai.operator.MosaicType; import javax.media.jai.operator.NullDescriptor; import javax.media.jai.operator.TranslateDescriptor; import org.junit.BeforeClass; import org.junit.Test; /** * This test class is used for compare the timing between the new MosaicDescriptor and . No Roi, No Data range or Alpha channels are used. If the user * wants to change the number of the benchmark cycles or of the not benchmark cycles, should only pass the new values to the JAI.Ext.BenchmarkCycles * or JAI.Ext.NotBenchmarkCycles parameters. Inside this test class the tests are executed in the same manner: * <ul> * <li>Selection of the descriptor (New or Old MosaicDescriptor)</li> * <li>Selection of the mosaic type (Overlay or Blend)</li> * <li>statistic calculation (if the cycle belongs to the benchmark cycles)</li> * </ul> * The MosaicType can be chosen by setting the JAI.Ext.MosaicBlend boolean JVM parameter: false for OVERLAY, true for BLEND. * The selection of the old or new descriptor must be done by setting to true or false the JVM parameter JAI.Ext.OldDescriptor. * If the user wants to use the accelerated code, the JVM parameter JAI.Ext.Acceleration must be set to true. */ public class ComparisonTest extends TestBase{ /** Number of benchmark iterations (Default 1) */ private final static Integer BENCHMARK_ITERATION = Integer.getInteger( "JAI.Ext.BenchmarkCycles", 1); /** Number of not benchmark iterations (Default 0) */ private final static int NOT_BENCHMARK_ITERATION = Integer.getInteger( "JAI.Ext.NotBenchmarkCycles", 0); /** Boolean indicating if the old descriptor must be used */ private final static boolean OLD_DESCRIPTOR = Boolean.getBoolean("JAI.Ext.OldDescriptor"); /** Boolean indicating if the native acceleration must be used */ private final static boolean NATIVE_ACCELERATION = Boolean .getBoolean("JAI.Ext.Acceleration"); /** Boolean for selecting one of the 2 MosaicType(Default Overlay) */ private final static boolean MOSAIC_TYPE = Boolean.getBoolean( "JAI.Ext.MosaicBlend"); /** Boolean indicating if a No Data Range must be used */ private final static boolean RANGE_USED = Boolean.getBoolean("JAI.Ext.RangeUsed"); /** Value indicating No Data for the destination image */ private static double destinationNoData = 0; /** Image to elaborate */ private static RenderedImage[] images; /** RenderingHints used for selecting the borderExtender */ private static RenderingHints hints; private static Range[] rangeND; @BeforeClass public static void initialSetup() { // Selection of the images // image creation byte value1 = 50; byte value2 = 100; RenderedImage image1 = getSyntheticImage(value1); RenderedImage image2 = getSyntheticImage(value2); int width = image1.getWidth(); // layout creation (same height of the source images, doubled width) ImageLayout layout = new ImageLayout(0, 0, image1.getWidth() + image2.getWidth(), image1.getHeight()); hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout); // translation of the first image RenderedImage image3 = TranslateDescriptor.create(image1, width * 0.1F, 0F, null, hints); // No op for the second image RenderedImage image4 = NullDescriptor.create(image2, hints); // array creation images = new RenderedImage[2]; images[0] = image4; images[1] = image3; //Range creation if selected rangeND= null; if(RANGE_USED){ Range range = RangeFactory.create((byte)100,true,(byte)100,true); rangeND = new Range[]{range, range}; } if(OLD_DESCRIPTOR){ JAIExt.registerJAIDescriptor("Mosaic"); } } @Test public void testNearestNewMosaicDescriptor() { if(!OLD_DESCRIPTOR){ testMosaic(OLD_DESCRIPTOR, MOSAIC_TYPE); } } @Test public void testNearestOldMosaicDescriptor() { if(OLD_DESCRIPTOR){ testMosaic(OLD_DESCRIPTOR, MOSAIC_TYPE); } } public void testMosaic(boolean old, boolean blend) { MosaicType mosaicType; String description = ""; if (old) { description = "Old Mosaic"; if(NATIVE_ACCELERATION){ description+=" accelerated "; System.setProperty("com.sun.media.jai.disableMediaLib", "false"); }else{ System.setProperty("com.sun.media.jai.disableMediaLib", "true"); } } else { description = "New Mosaic"; System.setProperty("com.sun.media.jai.disableMediaLib", "true"); } String mosaic = ""; if (!blend) { mosaicType = javax.media.jai.operator.MosaicDescriptor.MOSAIC_TYPE_OVERLAY; mosaic = "Mosaic Type Overlay"; } else { mosaicType = javax.media.jai.operator.MosaicDescriptor.MOSAIC_TYPE_BLEND; mosaic = "Mosaic Type Blend"; } // Total cycles number int totalCycles = BENCHMARK_ITERATION + NOT_BENCHMARK_ITERATION; // Image with the interpolator PlanarImage imageMosaic = null; long mean = 0; long max = Long.MIN_VALUE; long min = Long.MAX_VALUE; // Cycle for calculating the mean, maximum and minimum calculation time for (int i = 0; i < totalCycles; i++) { // creation of the image with the selected interpolator if (old) { // background values and threshold double[] background = { destinationNoData, destinationNoData }; double[][] threshold = { { 0 }, { 0 } }; imageMosaic = javax.media.jai.operator.MosaicDescriptor.create(images, mosaicType, null, null, threshold, background, hints); } else { double[] destnodata = { destinationNoData, destinationNoData }; imageMosaic = MosaicDescriptor.create(images, mosaicType, null, null, null, destnodata, rangeND, hints); } // Total calculation time long start = System.nanoTime(); imageMosaic.getTiles(); long end = System.nanoTime() - start; // If the the first NOT_BENCHMARK_ITERATION cycles has been done, then the mean, maximum and minimum values are stored if (i > NOT_BENCHMARK_ITERATION - 1) { if (i == NOT_BENCHMARK_ITERATION) { mean = end; } else { mean = mean + end; } if (end > max) { max = end; } if (end < min) { min = end; } } // For every cycle the cache is flushed such that all the tiles must be recalculates JAI.getDefaultInstance().getTileCache().flush(); } // Mean values double meanValue = mean / BENCHMARK_ITERATION * 1E-6; // Max and Min values stored as double double maxD = max * 1E-6; double minD = min * 1E-6; // Comparison between the mean times System.out.println("\n" + mosaic); // Output print of the System.out.println("\nMean value for " + description + "Descriptor : " + meanValue + " msec."); System.out.println("Maximum value for " + description + "Descriptor : " + maxD + " msec."); System.out.println("Minimum value for " + description + "Descriptor : " + minD + " msec."); //Final Image disposal if(imageMosaic instanceof RenderedOp){ ((RenderedOp)imageMosaic).dispose(); } } public static RenderedImage getSyntheticImage(byte value) { final float width = 512; final float height = 512; ParameterBlock pb = new ParameterBlock(); Byte[] array = new Byte[] { value, (byte) (value + 1), (byte) (value + 2) }; pb.add(width); pb.add(height); pb.add(array); // Create the constant operation. return JAI.create("constant", pb); } }