Make BitInputStream sensitive to byte order.
Allows 48 BPP TIFF files to load.
Jira issue key: SANSELAN-66
Submitted by: Piyush Kapoor <pkapoor at adobe dot com>
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/sanselan/trunk@1301903 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/commons/sanselan/SanselanConstants.java b/src/main/java/org/apache/commons/sanselan/SanselanConstants.java
index 3e57544..6cf9320 100644
--- a/src/main/java/org/apache/commons/sanselan/SanselanConstants.java
+++ b/src/main/java/org/apache/commons/sanselan/SanselanConstants.java
@@ -123,4 +123,12 @@
* Valid values: PixelDensity
*/
public static final String PARAM_KEY_PIXEL_DENSITY = "PIXEL_DENSITY";
+
+ /**
+ * Parameter key. Used in Tiff operations to use the byte order
+ * of the Tiff image.
+ * <p>
+ * Valid values: any Integer
+ */
+ public static final String BYTE_ORDER = "BYTE_ORDER";
}
diff --git a/src/main/java/org/apache/commons/sanselan/common/BinaryFileParser.java b/src/main/java/org/apache/commons/sanselan/common/BinaryFileParser.java
index a86ccb7..6975971 100644
--- a/src/main/java/org/apache/commons/sanselan/common/BinaryFileParser.java
+++ b/src/main/java/org/apache/commons/sanselan/common/BinaryFileParser.java
@@ -57,7 +57,7 @@
this.byteOrder = byteOrder;
}
- protected int getByteOrder()
+ public int getByteOrder()
{
return byteOrder;
}
diff --git a/src/main/java/org/apache/commons/sanselan/common/BitInputStream.java b/src/main/java/org/apache/commons/sanselan/common/BitInputStream.java
index bf2a622..49fef0b 100644
--- a/src/main/java/org/apache/commons/sanselan/common/BitInputStream.java
+++ b/src/main/java/org/apache/commons/sanselan/common/BitInputStream.java
@@ -21,13 +21,14 @@
public class BitInputStream extends InputStream implements BinaryConstants
{
- // TODO should be byte order conscious, ie TIFF for reading
- // samples size<8 - shuoldn't that effect their order within byte?
+
private final InputStream is;
+ private final int byteOrder;
- public BitInputStream(InputStream is)
+ public BitInputStream(InputStream is, int byteOrder)
{
this.is = is;
+ this.byteOrder = byteOrder;
// super(is);
}
@@ -88,25 +89,53 @@
bytes_read++;
return is.read();
}
+
+ /**
+ * Taking default order of the Tiff to be
+ * Little Endian and reversing the bytes in the end
+ * if its Big Endian.This is done because majority (may be all)
+ * of the files will be of Little Endian.
+ */
+ if(byteOrder == BYTE_ORDER_BIG_ENDIAN) {
+ if (count == 16)
+ {
+ bytes_read += 2;
+ return (is.read() << 8) | (is.read() << 0);
+ }
- if (count == 16)
- {
- bytes_read += 2;
- return (is.read() << 8) | (is.read() << 0);
- }
+ if (count == 24)
+ {
+ bytes_read += 3;
+ return (is.read() << 16) | (is.read() << 8) | (is.read() << 0);
+ }
- if (count == 24)
+ if (count == 32)
+ {
+ bytes_read += 4;
+ return (is.read() << 24) | (is.read() << 16) | (is.read() << 8)
+ | (is.read() << 0);
+ }
+ }
+ else
{
- bytes_read += 3;
- return (is.read() << 16) | (is.read() << 8) | (is.read() << 0);
- }
-
- if (count == 32)
- {
- bytes_read += 4;
- return (is.read() << 24) | (is.read() << 16) | (is.read() << 8)
- | (is.read() << 0);
- }
+ if(count == 16)
+ {
+ bytes_read +=2;
+ return ((is.read() << 0) | (is.read() << 8));
+ }
+
+ if(count == 24)
+ {
+ bytes_read += 3;
+ return ((is.read() << 0) | (is.read() << 8) | (is.read() << 16));
+ }
+
+ if(count == 32)
+ {
+ bytes_read += 4;
+ return ((is.read() << 0) | (is.read() << 8) | (is.read() << 16) | (is.read() << 24));
+ }
+ }
throw new IOException("BitInputStream: unknown error");
}
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageData.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageData.java
index c86540f..800bed0 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageData.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageData.java
@@ -55,12 +55,12 @@
public DataReader getDataReader(TiffDirectory directory,
PhotometricInterpreter photometricInterpreter,
int bitsPerPixel, int bitsPerSample[], int predictor,
- int samplesPerPixel, int width, int height, int compression)
+ int samplesPerPixel, int width, int height, int compression, int byteOrder)
throws IOException, ImageReadException
{
return new DataReaderTiled(directory, photometricInterpreter,
tileWidth, tileLength, bitsPerPixel, bitsPerSample,
- predictor, samplesPerPixel, width, height, compression, this);
+ predictor, samplesPerPixel, width, height, compression, byteOrder, this);
}
// public TiffElement[] getElements()
@@ -95,12 +95,12 @@
public DataReader getDataReader(TiffDirectory directory,
PhotometricInterpreter photometricInterpreter,
int bitsPerPixel, int bitsPerSample[], int predictor,
- int samplesPerPixel, int width, int height, int compression)
+ int samplesPerPixel, int width, int height, int compression, int byteorder)
throws IOException, ImageReadException
{
return new DataReaderStrips(directory, photometricInterpreter,
bitsPerPixel, bitsPerSample, predictor, samplesPerPixel,
- width, height, compression, rowsPerStrip, this);
+ width, height, compression,byteorder, rowsPerStrip, this);
}
// public TiffElement[] getElements()
@@ -119,7 +119,7 @@
public abstract DataReader getDataReader(TiffDirectory directory,
PhotometricInterpreter photometricInterpreter, int bitsPerPixel,
int bitsPerSample[], int predictor, int samplesPerPixel, int width,
- int height, int compression) throws IOException, ImageReadException;
+ int height, int compression, int byteOrder) throws IOException, ImageReadException;
public static class Data extends TiffElement.DataElement
{
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageParser.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageParser.java
index 64a4a6b..8c0836b 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageParser.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageParser.java
@@ -24,6 +24,7 @@
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -441,9 +442,14 @@
throws ImageReadException, IOException
{
FormatCompliance formatCompliance = FormatCompliance.getDefault();
- TiffContents contents = new TiffReader(isStrict(params))
- .readFirstDirectory(byteSource, params, true, formatCompliance);
+ TiffReader reader = new TiffReader(isStrict(params));
+ int byteOrder = reader.getByteOrder();
+ TiffContents contents = reader.readFirstDirectory(byteSource, params, true, formatCompliance);
TiffDirectory directory = contents.directories.get(0);
+ if(params == null) {
+ params = new HashMap<String, Integer>();
+ }
+ params.put(BYTE_ORDER, byteOrder);
BufferedImage result = directory.getTiffImage(params);
if (null == result)
throw new ImageReadException("TIFF does not contain an image.");
@@ -472,7 +478,17 @@
throws ImageReadException, IOException
{
List<TiffField> entries = directory.entries;
-
+
+ int byteOrder = BYTE_ORDER_LITTLE_ENDIAN; //taking little endian to be default
+ if(params != null){
+ if(params.containsKey(BYTE_ORDER)) {
+ Object obj = params.get(BYTE_ORDER);
+ if(obj instanceof Integer) {
+ Integer a = (Integer)obj;
+ byteOrder = a.intValue();
+ }
+ }
+ }
if (entries == null)
throw new ImageReadException("TIFF missing entries");
@@ -528,7 +544,7 @@
DataReader dataReader = imageData.getDataReader(directory,
photometricInterpreter, bitsPerPixel, bitsPerSample, predictor,
- samplesPerPixel, width, height, compression);
+ samplesPerPixel, width, height, compression, byteOrder);
dataReader.readImageData(imageBuilder);
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderStrips.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderStrips.java
index 4b8a9a7..4611223 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderStrips.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderStrips.java
@@ -32,6 +32,7 @@
private final int bitsPerPixel;
private final int compression;
private final int rowsPerStrip;
+ private final int byteOrder;
private final TiffImageData.Strips imageData;
@@ -39,7 +40,7 @@
PhotometricInterpreter photometricInterpreter,
int bitsPerPixel, int bitsPerSample[], int predictor,
int samplesPerPixel, int width, int height, int compression,
- int rowsPerStrip, TiffImageData.Strips imageData)
+ int byteOrder, int rowsPerStrip, TiffImageData.Strips imageData)
{
super(directory, photometricInterpreter, bitsPerSample, predictor, samplesPerPixel, width, height);
@@ -47,13 +48,14 @@
this.compression = compression;
this.rowsPerStrip = rowsPerStrip;
this.imageData = imageData;
+ this.byteOrder = byteOrder;
}
private void interpretStrip(ImageBuilder imageBuilder, byte bytes[],
int pixels_per_strip) throws ImageReadException, IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- BitInputStream bis = new BitInputStream(bais);
+ BitInputStream bis = new BitInputStream(bais, byteOrder);
if (y >= height) {
return;
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderTiled.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderTiled.java
index 55f416b..e75a358 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderTiled.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/datareaders/DataReaderTiled.java
@@ -35,6 +35,7 @@
private final int bitsPerPixel;
private final int compression;
+ private final int byteOrder;
private final TiffImageData.Tiles imageData;
@@ -42,7 +43,7 @@
PhotometricInterpreter photometricInterpreter,
int tileWidth, int tileLength, int bitsPerPixel,
int bitsPerSample[], int predictor, int samplesPerPixel, int width,
- int height, int compression, TiffImageData.Tiles imageData)
+ int height, int compression, int byteOrder, TiffImageData.Tiles imageData)
{
super(directory, photometricInterpreter, bitsPerSample, predictor, samplesPerPixel, width, height);
@@ -53,13 +54,14 @@
this.compression = compression;
this.imageData = imageData;
+ this.byteOrder = byteOrder;
}
private void interpretTile(ImageBuilder imageBuilder, byte bytes[], int startX,
int startY) throws ImageReadException, IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- BitInputStream bis = new BitInputStream(bais);
+ BitInputStream bis = new BitInputStream(bais, byteOrder);
int pixelsPerTile = tileWidth * tileLength;