/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2016, 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.metadata.landsat;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.logging.Logging;
import org.geotoolkit.image.internal.ImageUtils;
import org.geotoolkit.image.internal.PhotometricInterpretation;
import org.geotoolkit.image.internal.SampleType;
import org.geotoolkit.image.io.large.ImageCacheConfiguration;
import org.geotoolkit.image.io.large.LargeCache;
import org.geotoolkit.image.io.large.WritableLargeRenderedImage;
import org.geotoolkit.image.iterator.PixelIterator;
import org.geotoolkit.image.iterator.PixelIteratorFactory;
import org.geotoolkit.lang.Setup;
import junit.framework.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Improve {@link WritableLargeRenderedImage} {@link LargeCache} comportement.
*
* @author Alexis Manin (Geomatys).
* @author Remi Marechal (Geomatys).
*/
public final strictfp class WritableLargeRenderedImageTests {
/**
* {@link Logger} to show times number and time length of a test loop.
*
* @see #test()
*/
private static final Logger LOGGER = Logging.getLogger(WritableLargeRenderedImageTests.class.getCanonicalName());
/**
* Define test image size.
*
* @see #WritableLargeRenderedImageTests()
*/
private final static int IMG_SIZE = 5000; //-- increase this attribut to improve LargeCache comportement
/**
* Init providers.
*/
@BeforeClass
public static void init() {
ImageIO.scanForPlugins();
Setup.initialize(null);
ImageCacheConfiguration.setCacheMemorySize("3m");
LargeCache.getInstance().setMemoryCapacity((long) 3E6);
}
/**
* Fill and rewrite {@link WritableLargeRenderedImage} many times to stimulate
* {@link LargeCache} and thrad safe comportement.
*
* @throws InterruptedException if problem during multi-thread pixel working.
* @throws ExecutionException
*/
@Test
public void test() throws InterruptedException, ExecutionException {
WritableLargeRenderedImage outPutImageTest = ImageUtils.createRGBLargeImage(IMG_SIZE, IMG_SIZE, SampleType.BYTE);
WritableLargeRenderedImage inputTestImg = ImageUtils.createLargeImage(IMG_SIZE, IMG_SIZE, SampleType.BYTE, 1, PhotometricInterpretation.GRAYSCALE, null);
final ExecutorService poule = Executors.newFixedThreadPool(3);
for (int nb = 0, nbTimes = 1; nb < nbTimes; nb++) { //-- to improve comportement increase nbTimes attribut.
final long t = System.currentTimeMillis();
//-- assigned default test value.
final byte value = (byte) (StrictMath.random() * 255);
//-- fill input image by value.
final PixelIterator It = PixelIteratorFactory.createDefaultWriteableIterator(inputTestImg, inputTestImg);
while (It.next()) {
It.setSample(value);
}
final pixelWork band0Pix = new pixelWork(inputTestImg, outPutImageTest, 0);
final pixelWork band2Pix = new pixelWork(inputTestImg, outPutImageTest, 2);
final pixelWork band1Pix = new pixelWork(inputTestImg, outPutImageTest, 1);
final ArrayList<Future> futurList = new ArrayList<Future>();
futurList.add(poule.submit(band0Pix));
futurList.add(poule.submit(band1Pix));
futurList.add(poule.submit(band2Pix));
for (Future futurList1 : futurList) {
futurList1.get(); //-- block program in attempt to end of multiple processes.
}
//-- verify result pertinency
final PixelIterator createDefaultIterator = PixelIteratorFactory.createDefaultIterator(outPutImageTest);
while (createDefaultIterator.next()) {
Assert.assertEquals("unexpected byte value : at x = "+createDefaultIterator.getX()
+", y = "+createDefaultIterator.getY(), (value & 0xFF), (createDefaultIterator.getSample() & 0xFF));
}
LOGGER.log(Level.INFO, "iteration nb : "+nb+", time : "+(System.currentTimeMillis() - t));
}
poule.shutdown();
poule.awaitTermination(10, TimeUnit.SECONDS);
}
/**
* Implement {@link Callable} interface to effectuate multi-threading image filling.
*/
private class pixelWork implements Callable<Object> {
/**
* Input image which will be rewriting into output image.
*/
private final WritableLargeRenderedImage input;
/**
* Output thread image.
*/
private final WritableLargeRenderedImage output;
/**
* Band index where {@link #input} is rewriting into
*/
private final int outPutBandIndex;
/**
* Build a rewriting thread.
*
* @param input source image.
* @param output destination filled image.
* @param bandIndex band index of the destination image which will be filled.
*/
public pixelWork(final WritableLargeRenderedImage input,
final WritableLargeRenderedImage output,
final int bandIndex) {
ArgumentChecks.ensureNonNull("input", input);
ArgumentChecks.ensureNonNull("output", output);
ArgumentChecks.ensurePositive("band Index", bandIndex);
this.input = input;
this.output = output;
this.outPutBandIndex = bandIndex;
}
/**
* Rewrite {@link #input} into {@link #output} image at {@link #outPutBandIndex} band index.
*
* @return {@code null}.
* @throws Exception
*/
@Override
public Object call() throws Exception {
final PixelIterator inputPix = PixelIteratorFactory.createDefaultIterator(input);
final PixelIterator outPutPix = PixelIteratorFactory.createDefaultWriteableIterator(output, output);
int currentb = 0;
while (outPutPix.next()) {
if (currentb++ == outPutBandIndex) {
inputPix.next();
outPutPix.setSampleDouble(inputPix.getSampleDouble());
}
if (currentb == outPutPix.getNumBands()) {
currentb = 0;
}
}
return null;
}
}
}