Skip to content

Commit 8707591

Browse files
committed
Supporting predictor 2 for 32bit data, int and float
1 parent 619e49b commit 8707591

File tree

11 files changed

+168
-14
lines changed

11 files changed

+168
-14
lines changed

plugin/tiff/src/main/java/it/geosolutions/imageioimpl/plugins/tiff/TIFFDeflateDecompressor.java

+52-8
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@
7373
*/
7474
package it.geosolutions.imageioimpl.plugins.tiff;
7575

76-
import it.geosolutions.imageio.plugins.tiff.BaselineTIFFTagSet;
77-
import it.geosolutions.imageio.plugins.tiff.TIFFDecompressor;
78-
7976
import java.io.IOException;
8077
import java.nio.ByteOrder;
8178
import java.util.Arrays;
@@ -84,6 +81,9 @@
8481

8582
import javax.imageio.IIOException;
8683

84+
import it.geosolutions.imageio.plugins.tiff.BaselineTIFFTagSet;
85+
import it.geosolutions.imageio.plugins.tiff.TIFFDecompressor;
86+
8787
public class TIFFDeflateDecompressor extends TIFFDecompressor {
8888

8989
private static final boolean DEBUG = false;
@@ -116,7 +116,7 @@ public synchronized void decodeRaw(byte[] b,
116116
if (predictor == BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) {
117117
int len = bitsPerSample.length;
118118
final int bps = bitsPerSample[0];
119-
if (bps != 8 && bps != 16) {
119+
if (bps != 8 && bps != 16 && bps != 32) {
120120
throw new IIOException
121121
(bps + "-bit samples " +
122122
"are not supported for Horizontal " +
@@ -205,8 +205,8 @@ else if(bitsPerSample[0]==16) {
205205
for (int j = 0; j < srcHeight; j++) {
206206
int count = dstOffset + samplesPerPixel * (j * srcWidth + 1) * 2;
207207
for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {
208-
int curr=(((int)buf[count]) & 0xFF) + (buf[count+1]<<8);
209-
int prev=(((int)buf[count-samplesPerPixel*2]) & 0xFF)+(buf[count+1-samplesPerPixel*2]<<8);
208+
int curr=(((int)buf[count]) & 0xFF) | (buf[count+1]<<8);
209+
int prev=(((int)buf[count-samplesPerPixel*2]) & 0xFF) | (buf[count+1-samplesPerPixel*2]<<8);
210210
curr+=prev;
211211
buf[count]=(byte)curr;
212212
buf[count+1]=(byte)(curr>>8);
@@ -219,8 +219,8 @@ else if(bitsPerSample[0]==16) {
219219
for (int j = 0; j < srcHeight; j++) {
220220
int count = dstOffset + samplesPerPixel * (j * srcWidth + 1) * 2;
221221
for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {
222-
int curr=(((int)buf[count+1]) & 0xFF) + (buf[count]<<8);
223-
int prev=(((int)buf[count+1-samplesPerPixel*2]) & 0xFF)+(buf[count-samplesPerPixel*2]<<8);
222+
int curr=(((int)buf[count+1]) & 0xFF) | (buf[count]<<8);
223+
int prev=(((int)buf[count+1-samplesPerPixel*2]) & 0xFF) | (buf[count-samplesPerPixel*2]<<8);
224224
curr+=prev;
225225
buf[count+1]=(byte)curr;
226226
buf[count]=(byte)(curr>>8);
@@ -229,6 +229,43 @@ else if(bitsPerSample[0]==16) {
229229
}
230230
}
231231
}
232+
else if(bitsPerSample[0]==32) {
233+
if (stream.getByteOrder() == ByteOrder.LITTLE_ENDIAN) {
234+
for (int j = 0; j < srcHeight; j++) {
235+
int count = dstOffset + samplesPerPixel * (j * srcWidth + 1) * 4;
236+
int pbase = count - samplesPerPixel * 4;
237+
int prev = readIntegerFromBuffer(buf, pbase, pbase + 1, pbase + 2, pbase + 3);
238+
for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {
239+
int curr = readIntegerFromBuffer(buf, count, count +1, count +2, count + 3);
240+
int sum = curr + prev;
241+
buf[count] = (byte) (sum & 0xFF);
242+
buf[count + 1] = (byte) ((sum >> 8) & 0xFF);
243+
buf[count + 2] = (byte) ((sum >> 16) & 0xFF);
244+
buf[count + 3] = (byte) ((sum >> 24) & 0xFF) ;
245+
count += 4;
246+
prev = sum;
247+
}
248+
}
249+
}
250+
else
251+
{
252+
for (int j = 0; j < srcHeight; j++) {
253+
int count = dstOffset + samplesPerPixel * (j * srcWidth + 1) * 4;
254+
int pbase = count - samplesPerPixel * 4;
255+
int prev = readIntegerFromBuffer(buf, pbase + 3, pbase + 2, pbase + 1, pbase);
256+
for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {
257+
int curr = readIntegerFromBuffer(buf, count + 3, count + 2, count + 1, count);
258+
int sum = curr + prev;
259+
buf[count + 3] = (byte) (sum & 0xFF);
260+
buf[count + 2] = (byte) (sum >> 8 & 0xFF);
261+
buf[count + 1] = (byte) (sum >> 16 & 0xFF);
262+
buf[count] = (byte) (sum >> 24 & 0xFF);
263+
count += 4;
264+
prev = sum;
265+
}
266+
}
267+
}
268+
}
232269
else throw new IIOException("Unexpected branch of Horizontal differencing Predictor, bps="+bitsPerSample[0]);
233270
} else if (predictor == BaselineTIFFTagSet.PREDICTOR_FLOATING_POINT) {
234271
int bytesPerSample = bitsPerSample[0] / 8;
@@ -277,4 +314,11 @@ else if(bitsPerSample[0]==16) {
277314
}
278315
}
279316
}
317+
318+
private final int readIntegerFromBuffer(byte[] buf, int offset1, int offset2, int offset3, int offset4) {
319+
return (buf[offset1] & 0xFF)
320+
| ((buf[offset2] & 0xFF) << 8)
321+
| ((buf[offset3] & 0xFF) << 16)
322+
| ((buf[offset4] & 0xFF) << 24);
323+
}
280324
}

plugin/tiff/src/main/java/it/geosolutions/imageioimpl/plugins/tiff/TIFFLZWDecompressor.java

+46-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public void decodeRaw(byte[] b,
136136
BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING) {
137137
int len = bitsPerSample.length;
138138
final int bps=bitsPerSample[0];
139-
if (bps != 8 && bps != 16) {
139+
if (bps != 8 && bps != 16 && bps != 32) {
140140
throw new IIOException
141141
(bps + "-bit samples "+
142142
"are not supported for Horizontal "+
@@ -272,6 +272,43 @@ else if(bitsPerSample[0]==16) {
272272
}
273273
}
274274
}
275+
else if(bitsPerSample[0]==32) {
276+
if (stream.getByteOrder() == ByteOrder.LITTLE_ENDIAN) {
277+
for (int j = 0; j < srcHeight; j++) {
278+
int count = dstOffset + samplesPerPixel * (j * srcWidth + 1) * 4;
279+
int prevBase = count - samplesPerPixel * 4;
280+
int prev = readIntegerFromBuffer(dstData, prevBase, prevBase + 1, prevBase + 2, prevBase + 3);
281+
for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {
282+
int curr = readIntegerFromBuffer(dstData, count, count + 1, count + 2, count + 3);
283+
int sum = curr + prev;
284+
dstData[count] = (byte) (sum & 0xFF);
285+
dstData[count + 1] = (byte) ((sum >> 8) & 0xFF);
286+
dstData[count + 2] = (byte) ((sum >> 16) & 0xFF);
287+
dstData[count + 3] = (byte) ((sum >> 24) & 0xFF) ;
288+
count += 4;
289+
prev = sum;
290+
}
291+
}
292+
}
293+
else
294+
{
295+
for (int j = 0; j < srcHeight; j++) {
296+
int count = dstOffset + samplesPerPixel * (j * srcWidth + 1) * 4;
297+
int prevBase = count - samplesPerPixel * 4;
298+
int prev = readIntegerFromBuffer(dstData, prevBase + 3, prevBase + 2, prevBase +1, prevBase);
299+
for (int i = samplesPerPixel; i < srcWidth * samplesPerPixel; i++) {
300+
int curr = readIntegerFromBuffer(dstData, count + 3, count + 2, count +1, count);
301+
int sum = curr + prev;
302+
dstData[count + 3] = (byte) (sum & 0xFF);
303+
dstData[count + 2] = (byte) (sum >> 8 & 0xFF);
304+
dstData[count + 1] = (byte) (sum >> 16 & 0xFF);
305+
dstData[count] = (byte) (sum >> 24 & 0xFF);
306+
count += 4;
307+
prev = sum;
308+
}
309+
}
310+
}
311+
}
275312
else throw new IIOException("Unexpected branch of Horizontal differencing Predictor, bps="+bitsPerSample[0]);
276313
}
277314

@@ -382,5 +419,13 @@ public int getNextCode() {
382419
return 257;
383420
}
384421
}
422+
423+
private final int readIntegerFromBuffer(byte[] buf, int offset1, int offset2, int offset3, int offset4) {
424+
return (buf[offset1] & 0xFF)
425+
| ((buf[offset2] & 0xFF) << 8)
426+
| ((buf[offset3] & 0xFF) << 16)
427+
| ((buf[offset4] & 0xFF) << 24);
428+
}
429+
385430
}
386431

plugin/tiff/src/test/java/it/geosolutions/imageio/tiff/TIFFReadTest.java

+70-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.awt.Rectangle;
2121
import java.awt.image.BufferedImage;
2222
import java.awt.image.ColorModel;
23+
import java.awt.image.DataBuffer;
2324
import java.awt.image.RenderedImage;
2425
import java.awt.image.SampleModel;
2526
import java.io.File;
@@ -641,6 +642,65 @@ public void readDeflateWithHorizontalDifferencingPredictorOn16Bits() throws IOEx
641642
assertImagesEqual(readTiff("test.tif"), readTiff("deflatetest.tif"));
642643
}
643644

645+
@Test
646+
public void readDeflatePredictor2On32BitsInt() throws IOException {
647+
// This image has been created from test.tif using the command:
648+
// gdal_translate -OT UInt32 -co COMPRESS=DEFLATE -co PREDICTOR=2 test.tif deflate32_p2.tif
649+
assertImagesEqual(readTiff("test.tif"), readTiff("deflate32_p2.tif"));
650+
}
651+
652+
@Test
653+
public void readDeflatePredictor2On32BitsIntBigEndian() throws IOException {
654+
// This image has been created from test.tif using the command:
655+
// gdal_translate -ot UInt32 -co COMPRESS=DEFLATE -co PREDICTOR=2 test.tif
656+
// --config GDAL_TIFF_ENDIANNESS BIG deflate32_p2_bigendian.tif
657+
assertImagesEqual(readTiff("test.tif"), readTiff("deflate32_p2_bigendian.tif"));
658+
}
659+
660+
@Test
661+
public void reaLzwPredictor2On32BitsInt() throws IOException {
662+
// This image has been created from test.tif using the command:
663+
// gdal_translate -OT UInt32 -co COMPRESS=LZW -co PREDICTOR=2 test.tif lzw32_p2.tif
664+
assertImagesEqual(readTiff("test.tif"), readTiff("lzw32_p2.tif"));
665+
}
666+
667+
@Test
668+
public void readLzwPredictor2On32BitsIntBigEndian() throws IOException {
669+
// This image has been created from test.tif using the command:
670+
// gdal_translate -ot UInt32 -co COMPRESS=LZW -co PREDICTOR=2 test.tif --config GDAL_TIFF_ENDIANNESS BIG lzw32_p2_bigendian.tif
671+
assertImagesEqual(readTiff("test.tif"), readTiff("lzw32_p2_bigendian.tif"));
672+
}
673+
674+
@Test
675+
public void readDeflatePredictor2On32BitsFloat() throws IOException {
676+
// This image has been created from test.tif using the command:
677+
// gdal_translate -ot Float32 -co COMPRESS=DEFLATE -co PREDICTOR=2 test.tif deflate32f_p2.tif
678+
assertImagesEqual(readTiff("test.tif"), readTiff("deflate32f_p2.tif"));
679+
}
680+
681+
@Test
682+
public void readDeflatePredictor2On32BitsFloatBigEndian() throws IOException {
683+
// This image has been created from test.tif using the command:
684+
// gdal_translate -ot Float32 -co COMPRESS=DEFLATE -co PREDICTOR=2 --config
685+
// GDAL_TIFF_ENDIANNESS BIG test.tif deflate32f_p2_bigendian.tif
686+
assertImagesEqual(readTiff("test.tif"), readTiff("deflate32f_p2_bigendian.tif"));
687+
}
688+
689+
@Test
690+
public void readLzwPredictor2On32BitsFloat() throws IOException {
691+
// This image has been created from test.tif using the command:
692+
// gdal_translate -ot Float32 -co COMPRESS=LZW -co PREDICTOR=2 test.tif lzw32f_p2.tif
693+
assertImagesEqual(readTiff("test.tif"), readTiff("lzw32f_p2.tif"));
694+
}
695+
696+
@Test
697+
public void readLzwPredictor2On32BitsFloatBigEndian() throws IOException {
698+
// This image has been created from test.tif using the command:
699+
// gdal_translate -ot Float32 -co COMPRESS=LZW -co PREDICTOR=2 --config
700+
// GDAL_TIFF_ENDIANNESS BIG test.tif lzw32f_p2_bigendian.tif
701+
assertImagesEqual(readTiff("test.tif"), readTiff("lzw32f_p2_bigendian.tif"));
702+
}
703+
644704
@Test
645705
public void readDeflateWithFloatingPointPredictor() throws IOException {
646706
// This image has been created from test.tif using the command:
@@ -655,14 +715,19 @@ private void assertImagesEqual(BufferedImage expected, BufferedImage actual) {
655715
int h = expected.getRaster().getHeight();
656716
assertArrayEquals(
657717
"Rasters are different",
658-
toByteArray(expected.getRaster().getDataElements(0, 0, w, h, null)),
659-
toByteArray(actual.getRaster().getDataElements(0, 0, w, h, null)));
718+
toByteArray(expected.getSampleModel().getDataType(), expected.getRaster().getDataElements(0, 0, w, h, null)),
719+
toByteArray(actual.getSampleModel().getDataType(), actual.getRaster().getDataElements(0, 0, w, h, null)));
660720
}
661721

662-
private byte[] toByteArray(Object arr) {
663-
byte[] result = new byte[Array.getLength(arr)];
722+
private int[] toByteArray(int dataType, Object arr) {
723+
int[] result = new int[Array.getLength(arr)];
664724
for (int i = 0; i < result.length; i++) {
665-
result[i] = ((Number) Array.get(arr, i)).byteValue();
725+
Number value = (Number) Array.get(arr, i);
726+
if (dataType == DataBuffer.TYPE_BYTE) {
727+
result[i] = value.byteValue() & 0xFF;
728+
} else {
729+
result[i] = value.intValue();
730+
}
666731
}
667732
return result;
668733
}

0 commit comments

Comments
 (0)