Skip to content

Commit

Permalink
Merge pull request #813 from jampukka/feature/tiffreader-int16
Browse files Browse the repository at this point in the history
WCS client TIFFReader: add short[] variants of readStrip and readTile
  • Loading branch information
ZakarFin authored Feb 22, 2022
2 parents 97d6c41 + 598303f commit 2008ee7
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 2 deletions.
63 changes: 61 additions & 2 deletions service-wcs/src/main/java/org/oskari/wcs/geotiff/TIFFReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public IFD getIFD(int i) {
return ifds.get(i);
}

public void readStrip(int ifdIdx, int stripIdx, float[] dst) {
public float[] readStrip(int ifdIdx, int stripIdx, float[] dst) {
IFD ifd = ifds.get(ifdIdx);

if (ifd.getStripOffsets() == null) {
Expand All @@ -84,6 +84,35 @@ public void readStrip(int ifdIdx, int stripIdx, float[] dst) {
.order(bb.order())
.asFloatBuffer()
.get(dst);

return dst;
}

public short[] readStrip(int ifdIdx, int stripIdx, short[] dst) {
IFD ifd = ifds.get(ifdIdx);

if (ifd.getStripOffsets() == null) {
throw new IllegalArgumentException("Specified IFD is not striped");
}

for (int sf : ifd.getSampleFormat()) {
if (sf != 1 && sf != 2) {
throw new IllegalArgumentException("Specified IFD sampleFormat is not (un)signed integer");
}
}

for (int bps : ifd.getBitsPerSample()) {
if (bps != 16) {
throw new IllegalArgumentException("Specified IFD bits per sample is not 16");
}
}

ByteBuffer.wrap(getStripData(ifd, stripIdx, null))
.order(bb.order())
.asShortBuffer()
.get(dst);

return dst;
}

private byte[] getStripData(IFD ifd, int stripIdx, byte[] data)
Expand All @@ -107,7 +136,7 @@ private byte[] getStripData(IFD ifd, int stripIdx, byte[] data)
return data;
}

public void readTile(int ifdIdx, int tileIdx, float[] dst)
public float[] readTile(int ifdIdx, int tileIdx, float[] dst)
throws IllegalArgumentException {
IFD ifd = ifds.get(ifdIdx);

Expand All @@ -125,6 +154,36 @@ public void readTile(int ifdIdx, int tileIdx, float[] dst)
.order(bb.order())
.asFloatBuffer()
.get(dst);

return dst;
}

public short[] readTile(int ifdIdx, int tileIdx, short[] dst)
throws IllegalArgumentException {
IFD ifd = ifds.get(ifdIdx);

if (ifd.getTileOffsets() == null) {
throw new IllegalArgumentException("Specified IFD is not tiled");
}

for (int sf : ifd.getSampleFormat()) {
if (sf != 1 && sf != 2) {
throw new IllegalArgumentException("Specified IFD sampleFormat is not (un)signed integer");
}
}

for (int bps : ifd.getBitsPerSample()) {
if (bps != 16) {
throw new IllegalArgumentException("Specified IFD bits per sample is not 16");
}
}

ByteBuffer.wrap(getTileData(ifd, tileIdx, null))
.order(bb.order())
.asShortBuffer()
.get(dst);

return dst;
}

private byte[] getTileData(IFD ifd, int tileIdx, byte[] data)
Expand Down
100 changes: 100 additions & 0 deletions service-wcs/src/test/java/org/oskari/wcs/geotiff/TIFFReaderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package org.oskari.wcs.geotiff;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import org.junit.Test;

public class TIFFReaderTest {

@Test
public void tiled_Int16_neg_32500() throws IOException {
// gdal_create -outsize 512 512 -ot Int16 -co TILED=YES -co BLOCKXSIZE=256 -co BLOCKYSIZE=256 -burn -32500 int16_neg_32500.tif
int expectedValue = -32500;

TIFFReader r = new TIFFReader(readResource("int16_neg_32500.tif"));
IFD ifd = r.getIFD(0);
assertEquals(1, r.getIFDCount());
assertEquals(1, ifd.getBitsPerSample().length);
assertEquals(2, ifd.getSampleFormat()[0]);
assertEquals(16, ifd.getBitsPerSample()[0]);
assertEquals(256, ifd.getTileWidth());
assertEquals(256, ifd.getTileHeight());
assertEquals(512, ifd.getWidth());
assertEquals(512, ifd.getHeight());

short[] expected = new short[256 * 256];
Arrays.fill(expected, (short) expectedValue);
for (int tileIndex = 0; tileIndex < 4; tileIndex++) {
short[] actual = r.readTile(0, tileIndex, new short[256 * 256]);
assertArrayEquals(expected, actual);
}
}

@Test
public void tiled_UInt16_65500() throws IOException {
// gdal_create -outsize 512 512 -ot UInt16 -co TILED=YES -co BLOCKXSIZE=256 -co BLOCKYSIZE=256 -burn 65500 uint16_65500.tif
int expectedValue = 65500;

TIFFReader r = new TIFFReader(readResource("uint16_65500.tif"));
IFD ifd = r.getIFD(0);
assertEquals(1, r.getIFDCount());
assertEquals(1, ifd.getBitsPerSample().length);
assertEquals(1, ifd.getSampleFormat()[0]);
assertEquals(16, ifd.getBitsPerSample()[0]);
assertEquals(256, ifd.getTileWidth());
assertEquals(256, ifd.getTileHeight());
assertEquals(512, ifd.getWidth());
assertEquals(512, ifd.getHeight());

short[] expected = new short[256 * 256];
Arrays.fill(expected, (short) expectedValue);
for (int tileIndex = 0; tileIndex < 4; tileIndex++) {
short[] actual = r.readTile(0, tileIndex, new short[256 * 256]);
assertEquals(expectedValue, actual[0] & 0xFFFF);
assertArrayEquals(expected, actual);
}
}

@Test
public void tiled_Float32_neg_1337_125() throws IOException {
// gdal_create -outsize 512 512 -ot Float32 -co TILED=YES -co BLOCKXSIZE=256 -co BLOCKYSIZE=256 -burn -1337.125 float32_neg_1337_125.tif
float expectedValue = -1337.125f;

TIFFReader r = new TIFFReader(readResource("float32_neg_1337_125.tif"));
IFD ifd = r.getIFD(0);
assertEquals(1, r.getIFDCount());
assertEquals(1, ifd.getBitsPerSample().length);
assertEquals(3, ifd.getSampleFormat()[0]);
assertEquals(32, ifd.getBitsPerSample()[0]);
assertEquals(256, ifd.getTileWidth());
assertEquals(256, ifd.getTileHeight());
assertEquals(512, ifd.getWidth());
assertEquals(512, ifd.getHeight());

float[] expected = new float[256 * 256];
Arrays.fill(expected, expectedValue);
for (int tileIndex = 0; tileIndex < 4; tileIndex++) {
float[] actual = r.readTile(0, tileIndex, new float[256 * 256]);
assertArrayEquals(expected, actual, 0.0f);
}
}

private byte[] readResource(String res) throws IOException {
try (InputStream in = getClass().getClassLoader().getResourceAsStream(res)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int n;
while ((n = in.read(buf, 0, buf.length)) != -1) {
baos.write(buf, 0, n);
}
return baos.toByteArray();
}
}

}
Binary file not shown.
Binary file not shown.
Binary file added service-wcs/src/test/resources/uint16_65500.tif
Binary file not shown.

0 comments on commit 2008ee7

Please sign in to comment.