/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2014, 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.io.plugin; import org.apache.sis.test.DependsOnMethod; import org.geotoolkit.image.io.SpatialImageReadParam; import org.geotoolkit.image.iterator.PixelIterator; import org.geotoolkit.image.iterator.PixelIteratorFactory; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ShortBuffer; import java.nio.file.Files; import java.nio.file.Path; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; /** * Unit tests for VI3G reader. We'll make an simple image which each pixel value is its position in a 1D buffer. * * Ex : if we are on pixel (x, y), its value is : y * image.width() + x; * * @author Alexis Manin (Geomatys) */ public class VI3GReaderTest extends org.geotoolkit.test.TestBase { private static final short MAX_VALUE = 10000; private static final int SIZE = VI3GReader.WIDTH * VI3GReader.HEIGHT; private static Path TEMP_IMG; private static final Rectangle SOURCE_REGION = new Rectangle(5, 3, 6, 4); @BeforeClass public static void init() throws IOException { TEMP_IMG = Files.createTempFile("test", ".vi3g"); final ByteBuffer bb = ByteBuffer.allocate(8192); final ShortBuffer sb = bb.asShortBuffer(); int idx = 0; try (final OutputStream stream = Files.newOutputStream(TEMP_IMG); final DataOutputStream writer = new DataOutputStream(stream)) { while (idx < SIZE) { sb.rewind(); final int limit = Math.min(sb.limit(), SIZE - idx); while (limit > sb.position()) { sb.put((short) (idx++ % 10000)); } writer.write(bb.array(), 0, limit * 2); } } } @AfterClass public static void destroy() throws IOException { Files.delete(TEMP_IMG); } @Test public void serviceLoadingTest() { ImageIO.scanForPlugins(); final Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("vi3g"); while (readers.hasNext()) { if (readers.next() instanceof VI3GReader) return; } Assert.fail("VI3G reader cannot be found by ImageIO !"); } /** * Test the capacity of the reader to decode all VI3G image in full resolution. * @throws java.io.IOException If temporary image file has been corrupted. */ @Test public void readFullyTest() throws IOException { final VI3GReader reader = new VI3GReader(new VI3GReader.Spi()); reader.setInput(TEMP_IMG); final BufferedImage read = reader.read(0); final PixelIterator pxIt = PixelIteratorFactory.createDefaultIterator(read); int expected = 0; while (pxIt.next()) { Assert.assertEquals("A pixel value is invalid !", expected++ % 10000, pxIt.getSample()); } Assert.assertEquals("Image has not been fully read !", SIZE, expected); } /** * Test the capacity of the reader to decode a rectangle of source image, at full resolution. * @throws java.io.IOException If temporary image file has been corrupted. */ @DependsOnMethod("readFullyTest") @Test public void readRegion() throws IOException { final VI3GReader reader = new VI3GReader(new VI3GReader.Spi()); final SpatialImageReadParam readParam = reader.getDefaultReadParam(); readParam.setSourceRegion(SOURCE_REGION); reader.setInput(TEMP_IMG); final BufferedImage read = reader.read(0, readParam); Assert.assertEquals("Read image width is invalid !", SOURCE_REGION.width, read.getWidth()); Assert.assertEquals("Read image height is invalid !", SOURCE_REGION.height, read.getHeight()); final PixelIterator pxIt = PixelIteratorFactory.createRowMajorIterator(read); final int widthPad = VI3GReader.WIDTH - SOURCE_REGION.width - SOURCE_REGION.x; int expected = SOURCE_REGION.y * VI3GReader.WIDTH - widthPad; // When we change line, we must add an offset to expected value. int previousY = -1; while (pxIt.next()) { if (previousY < pxIt.getY()) { expected += SOURCE_REGION.x + widthPad; previousY = pxIt.getY(); } Assert.assertEquals("Pixel value at ("+pxIt.getX()+", "+pxIt.getY()+") is invalid !", expected++ % MAX_VALUE, pxIt.getSample()); } } /** * Test the capacity of the reader to decode entire source image, at a degraded resolution. * @throws java.io.IOException If temporary image file has been corrupted. */ @DependsOnMethod("readFullyTest") @Test public void readSubsampled() throws IOException { final VI3GReader reader = new VI3GReader(new VI3GReader.Spi()); final SpatialImageReadParam readParam = reader.getDefaultReadParam(); reader.setInput(TEMP_IMG); // Subsampling without offset final int xSubsampling = 5; final int ySubsampling = 3; readParam.setSourceSubsampling(xSubsampling, ySubsampling, 0, 0); BufferedImage read = reader.read(0, readParam); Assert.assertEquals("Read image width is invalid !", VI3GReader.WIDTH / 5, read.getWidth()); Assert.assertEquals("Read image height is invalid !", VI3GReader.HEIGHT / 3, read.getHeight()); PixelIterator pxIt = PixelIteratorFactory.createRowMajorIterator(read); int expected = -1; // When we change line, we must add an offset to expected value. int previousY = -1; while (pxIt.next()) { if (previousY < pxIt.getY()) { // We reset expected value to the one we should get at the beginning of current line. previousY = pxIt.getY(); expected = (previousY * ySubsampling) * VI3GReader.WIDTH; } else { expected += xSubsampling; } Assert.assertEquals("Pixel value at ("+pxIt.getX()+", "+pxIt.getY()+") is invalid !", expected % MAX_VALUE, pxIt.getSample()); } // Subsampling with an offset final int xOffset = 2; final int yOffset = 1; readParam.setSourceSubsampling(xSubsampling, ySubsampling, xOffset, yOffset); read = reader.read(0, readParam); Assert.assertEquals("Read image width is invalid !", Math.round((VI3GReader.WIDTH - xOffset) / 5.0), read.getWidth()); Assert.assertEquals("Read image height is invalid !", Math.round((VI3GReader.HEIGHT - yOffset) / 3.0), read.getHeight()); pxIt = PixelIteratorFactory.createRowMajorIterator(read); expected = -1; previousY = -1; while (pxIt.next()) { if (previousY < pxIt.getY()) { // We reset expected value to the one we should get at the beginning of current line. previousY = pxIt.getY(); expected = (yOffset + (previousY * ySubsampling)) * VI3GReader.WIDTH + xOffset; } else { expected += xSubsampling; } Assert.assertEquals("Pixel value at ("+pxIt.getX()+", "+pxIt.getY()+") is invalid !", expected % MAX_VALUE, pxIt.getSample()); } } /** * Test the capacity of the reader to decode entire source image, at a degraded resolution. * @throws java.io.IOException If temporary image file has been corrupted. */ @DependsOnMethod({"readRegion", "readSubsampled"}) @Test public void readSubSampledRegion() throws IOException { final VI3GReader reader = new VI3GReader(new VI3GReader.Spi()); final SpatialImageReadParam readParam = reader.getDefaultReadParam(); reader.setInput(TEMP_IMG); readParam.setSourceRegion(SOURCE_REGION); // Subsampling with an offset final int xSubsampling = 2; final int ySubsampling = 2; final int xOffset = 1; final int yOffset = 1; readParam.setSourceSubsampling(xSubsampling, ySubsampling, xOffset, yOffset); final BufferedImage read = reader.read(0, readParam); Assert.assertEquals("Read image width is invalid !", 3, read.getWidth()); Assert.assertEquals("Read image height is invalid !", 2, read.getHeight()); final int firstPxValue = (SOURCE_REGION.y + yOffset) * VI3GReader.WIDTH + SOURCE_REGION.x + xOffset; final int[] expectedValues = new int[]{ firstPxValue, firstPxValue + xSubsampling, firstPxValue + xSubsampling*2, firstPxValue + (ySubsampling * VI3GReader.WIDTH), firstPxValue + (ySubsampling * VI3GReader.WIDTH) + xSubsampling, firstPxValue + (ySubsampling * VI3GReader.WIDTH) + xSubsampling*2 }; final PixelIterator pxIt = PixelIteratorFactory.createRowMajorIterator(read); int expectedIndex = 0; while (pxIt.next()) { Assert.assertEquals("Pixel value at ("+pxIt.getX()+", "+pxIt.getY()+") is invalid !", expectedValues[expectedIndex++] % 10000, pxIt.getSample()); } } }