/*
* 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.IOException;
import java.nio.ByteBuffer;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
/**
* Unit tests for HGT 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 HGTReaderTest extends org.geotoolkit.test.TestBase {
private static Path TEMP_DIR;
private static Path TEMP_IMG;
private static final int IMG_WIDTH = 11;
private static final Rectangle SOURCE_REGION = new Rectangle(5, 3, 6, 4);
@BeforeClass
public static void init() throws IOException {
TEMP_DIR = Files.createTempDirectory("hgtTests");
final int size = IMG_WIDTH * IMG_WIDTH;
final ByteBuffer buffer = ByteBuffer.allocate(size*(Short.SIZE/Byte.SIZE));
for (int i = 0 ; i < size; i++) {
buffer.putShort((short)i);
}
TEMP_IMG = Files.createFile(TEMP_DIR.resolve("N00E000.hgt"));
Files.write(TEMP_IMG, buffer.array());
}
@AfterClass
public static void destroy() throws IOException {
Files.walkFileTree(TEMP_DIR, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return super.postVisitDirectory(dir, exc);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return super.visitFile(file, attrs);
}
});
}
/**
* Test the capacity of the reader to decode full HGT image in full resolution.
* @throws java.io.IOException If temporary image file has been corrupted.
*/
@Test
public void readFullyTest() throws IOException {
final HGTReader reader = new HGTReader(new HGTReader.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++, pxIt.getSample());
}
}
/**
* 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 HGTReader reader = new HGTReader(new HGTReader.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);
int expected = SOURCE_REGION.y * IMG_WIDTH;
// 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;
previousY = pxIt.getY();
}
Assert.assertEquals("Pixel value at ("+pxIt.getX()+", "+pxIt.getY()+") is invalid !", expected++, 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 HGTReader reader = new HGTReader(new HGTReader.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 !", 3, read.getWidth());
Assert.assertEquals("Read image height is invalid !", 4, 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) * IMG_WIDTH;
} else {
expected += xSubsampling;
}
Assert.assertEquals("Pixel value at ("+pxIt.getX()+", "+pxIt.getY()+") is invalid !", expected, 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 !", 2, read.getWidth());
Assert.assertEquals("Read image height is invalid !", 4, 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)) * IMG_WIDTH + xOffset;
} else {
expected += xSubsampling;
}
Assert.assertEquals("Pixel value at ("+pxIt.getX()+", "+pxIt.getY()+") is invalid !", expected, 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 HGTReader reader = new HGTReader(new HGTReader.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) * IMG_WIDTH + SOURCE_REGION.x + xOffset;
final int[] expectedValues = new int[]{
firstPxValue,
firstPxValue + xSubsampling,
firstPxValue + xSubsampling*2,
firstPxValue + (ySubsampling * IMG_WIDTH),
firstPxValue + (ySubsampling * IMG_WIDTH) + xSubsampling,
firstPxValue + (ySubsampling * IMG_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++], pxIt.getSample());
}
}
}