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;