You are viewing a plain text version of this content. The canonical link for it is here.
Posted to sanselan-commits@incubator.apache.org by cm...@apache.org on 2008/01/11 05:41:02 UTC
svn commit: r611055 - in
/incubator/sanselan/trunk/src/main/java/org/apache/sanselan: ./
formats/jpeg/ formats/tiff/ formats/tiff/constants/
formats/tiff/datareaders/ formats/tiff/write/
Author: cmchen
Date: Thu Jan 10 21:41:01 2008
New Revision: 611055
URL: http://svn.apache.org/viewvc?rev=611055&view=rev
Log:
Thorough refactor of the Tiff Image Parser. All in preparation for making EXIF rewrite possible.
Added:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffReader.java (with props)
Modified:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/RawTiffImageData.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffContents.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageMetadata.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffDirectoryConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterBase.java
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/SanselanConstants.java Thu Jan 10 21:41:01 2008
@@ -63,15 +63,15 @@
public static final String BUFFERED_IMAGE_FACTORY = "BUFFERED_IMAGE_FACTORY";
- /**
- * Parameter key. Indicates whether to read embedded thumbnails.
- * <p>
- * Only applies to read EXIF metadata from JPEG/JFIF files.
- * <p>
- * Valid values: Boolean.TRUE and Boolean.FALSE.
- * <p>
- * @see TiffConstants
- */
- public static final String PARAM_KEY_READ_THUMBNAILS = "READ_THUMBNAILS";
+// /**
+// * Parameter key. Indicates whether to read embedded thumbnails.
+// * <p>
+// * Only applies to read EXIF metadata from JPEG/JFIF files.
+// * <p>
+// * Valid values: Boolean.TRUE and Boolean.FALSE.
+// * <p>
+// * @see TiffConstants
+// */
+// public static final String PARAM_KEY_READ_THUMBNAILS = "READ_THUMBNAILS";
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java Thu Jan 10 21:41:01 2008
@@ -17,8 +17,10 @@
package org.apache.sanselan.formats.jpeg;
import java.awt.image.BufferedImage;
+import java.io.IOException;
import java.util.ArrayList;
+import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.common.ImageMetadata;
import org.apache.sanselan.formats.tiff.RawTiffImageData;
@@ -71,7 +73,7 @@
return null;
}
- public BufferedImage getEXIFThumbnail()
+ public BufferedImage getEXIFThumbnail() throws ImageReadException, IOException
{
ArrayList dirs = exif.getDirectories();
for (int i = 0; i < dirs.size(); i++)
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java Thu Jan 10 21:41:01 2008
@@ -341,8 +341,8 @@
if(params==null)
params = new HashMap();
- if (!params.containsKey(PARAM_KEY_READ_THUMBNAILS))
- params.put(PARAM_KEY_READ_THUMBNAILS, Boolean.TRUE);
+// if (!params.containsKey(PARAM_KEY_READ_THUMBNAILS))
+// params.put(PARAM_KEY_READ_THUMBNAILS, Boolean.TRUE);
return (TiffImageMetadata) new TiffImageParser().getMetadata(bytes,
params);
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/RawTiffImageData.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/RawTiffImageData.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/RawTiffImageData.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/RawTiffImageData.java Thu Jan 10 21:41:01 2008
@@ -3,15 +3,28 @@
*/
package org.apache.sanselan.formats.tiff;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.formats.tiff.datareaders.DataReader;
+import org.apache.sanselan.formats.tiff.datareaders.DataReaderStrips;
+import org.apache.sanselan.formats.tiff.datareaders.DataReaderTiled;
+import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
+
public abstract class RawTiffImageData
{
public static class Tiles extends RawTiffImageData
{
public final byte tiles[][];
+ private final int tileWidth, tileLength;
- public Tiles(final byte tiles[][])
+ public Tiles(final byte tiles[][], final int tileWidth,
+ final int tileLength)
{
this.tiles = tiles;
+ this.tileWidth = tileWidth;
+ this.tileLength = tileLength;
}
public byte[][] getRawImageData()
@@ -23,15 +36,28 @@
{
return false;
}
+
+ public DataReader getDataReader(ArrayList entries,
+ PhotometricInterpreter photometricInterpreter,
+ int bitsPerPixel, int bitsPerSample[], int predictor,
+ int samplesPerPixel, int width, int height, int compression)
+ throws IOException, ImageReadException
+ {
+ return new DataReaderTiled(photometricInterpreter, tileWidth,
+ tileLength, bitsPerPixel, bitsPerSample, predictor,
+ samplesPerPixel, width, height, compression, this);
+ }
}
public static class Strips extends RawTiffImageData
{
public final byte strips[][];
+ public final int rowsPerStrip;
- public Strips(final byte strips[][])
+ public Strips(final byte strips[][], final int rowsPerStrip)
{
this.strips = strips;
+ this.rowsPerStrip = rowsPerStrip;
}
public byte[][] getRawImageData()
@@ -43,24 +69,26 @@
{
return true;
}
- }
- // public static class Jpeg extends RawImageData
- // {
- // public final byte data[][];
- //
- // public Jpeg(final byte data[])
- // {
- // this.data = data;
- // }
- //
- // public byte[] getRawImageData()
- // {
- // return data;
- // }
- // }
+ public DataReader getDataReader(ArrayList entries,
+ PhotometricInterpreter photometricInterpreter,
+ int bitsPerPixel, int bitsPerSample[], int predictor,
+ int samplesPerPixel, int width, int height, int compression)
+ throws IOException, ImageReadException
+ {
+ return new DataReaderStrips(photometricInterpreter,
+ bitsPerPixel, bitsPerSample, predictor, samplesPerPixel,
+ width, height, compression, rowsPerStrip, this);
+ }
+ }
public abstract byte[][] getRawImageData();
public abstract boolean stripsNotTiles();
+
+ public abstract DataReader getDataReader(ArrayList entries,
+ PhotometricInterpreter photometricInterpreter, int bitsPerPixel,
+ int bitsPerSample[], int predictor, int samplesPerPixel, int width,
+ int height, int compression) throws IOException, ImageReadException;
+
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffContents.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffContents.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffContents.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffContents.java Thu Jan 10 21:41:01 2008
@@ -64,7 +64,7 @@
return result;
}
- public TiffField findField(TagInfo tag)
+ public TiffField findField(TagInfo tag) throws ImageReadException
{
for (int i = 0; i < directories.size(); i++)
{
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffDirectory.java Thu Jan 10 21:41:01 2008
@@ -16,8 +16,10 @@
*/
package org.apache.sanselan.formats.tiff;
+import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Map;
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.byteSources.ByteSource;
@@ -27,6 +29,7 @@
public class TiffDirectory extends TiffElement implements TiffConstants
//extends BinaryFileFunctions
{
+
public String description()
{
return TiffDirectory.description(type);
@@ -105,8 +108,8 @@
return new ArrayList(entries);
}
- public void fillInValues(ByteSource byteSource) throws ImageReadException,
- IOException
+ protected void fillInValues(ByteSource byteSource)
+ throws ImageReadException, IOException
{
for (int i = 0; i < entries.size(); i++)
{
@@ -126,7 +129,7 @@
}
- public boolean hasJpegImageData()
+ public boolean hasJpegImageData() throws ImageReadException
{
if (null != findField(TIFF_TAG_JPEG_INTERCHANGE_FORMAT))
return true;
@@ -134,7 +137,7 @@
return false;
}
- public boolean hasTiffImageData()
+ public boolean hasTiffImageData() throws ImageReadException
{
if (null != findField(TIFF_TAG_TILE_OFFSETS))
return true;
@@ -145,7 +148,29 @@
return false;
}
- public TiffField findField(TagInfo tag)
+ public BufferedImage getTiffImage() throws ImageReadException, IOException
+ {
+ Map params = null;
+ return getTiffImage(params);
+ }
+
+ public BufferedImage getTiffImage(Map params) throws ImageReadException,
+ IOException
+ {
+ if (null == rawTiffImageData)
+ return null;
+
+ return new TiffImageParser().getBufferedImage(this, params);
+ }
+
+ public TiffField findField(TagInfo tag) throws ImageReadException
+ {
+ boolean failIfMissing = false;
+ return findField(tag, failIfMissing);
+ }
+
+ public TiffField findField(TagInfo tag, boolean failIfMissing)
+ throws ImageReadException
{
if (entries == null)
return null;
@@ -157,6 +182,10 @@
return field;
}
+ if (failIfMissing)
+ throw new ImageReadException("Missing expected field: "
+ + tag.getDescription());
+
return null;
}
@@ -178,8 +207,8 @@
private ArrayList getRawImageDataElements(TiffField offsetsField,
TiffField byteCountsField) throws ImageReadException
{
- int offsets[] = offsetsField.getValueAsIntArray();
- int byteCounts[] = byteCountsField.getValueAsIntArray();
+ int offsets[] = offsetsField.getIntArrayValue();
+ int byteCounts[] = byteCountsField.getIntArrayValue();
if (offsets.length != byteCounts.length)
throw new ImageReadException("offsets.length(" + offsets.length
@@ -238,12 +267,37 @@
if ((jpegInterchangeFormat != null)
&& (jpegInterchangeFormatLength != null))
{
- int offset = jpegInterchangeFormat.getValueAsIntArray()[0];
- int byteCount = jpegInterchangeFormatLength.getValueAsIntArray()[0];
+ int offset = jpegInterchangeFormat.getIntArrayValue()[0];
+ int byteCount = jpegInterchangeFormatLength.getIntArrayValue()[0];
return new ImageDataElement(offset, byteCount);
}
else
throw new ImageReadException("Couldn't find image data.");
}
+
+ private RawTiffImageData rawTiffImageData = null;
+
+ public void setRawTiffImageData(RawTiffImageData rawImageData)
+ {
+ this.rawTiffImageData = rawImageData;
+ }
+
+ public RawTiffImageData getRawTiffImageData()
+ {
+ return rawTiffImageData;
+ }
+
+ private byte rawJpegImageData[] = null;
+
+ public void setRawJpegImageData(byte bytes[])
+ {
+ this.rawJpegImageData = bytes;
+ }
+
+ public byte[] getRawJpegImageData()
+ {
+ return rawJpegImageData;
+ }
+
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffField.java Thu Jan 10 21:41:01 2008
@@ -30,7 +30,6 @@
import org.apache.sanselan.formats.tiff.constants.TagInfo;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.fieldtypes.FieldType;
-import org.apache.sanselan.util.Debug;
public class TiffField implements TiffConstants
{
@@ -169,10 +168,10 @@
int valueLength = getValueLengthInBytes();
-// Debug.debug("fillInValue tagInfo", tagInfo);
-// Debug.debug("fillInValue valueOffset", valueOffset);
-// Debug.debug("fillInValue valueLength", valueLength);
-
+ // Debug.debug("fillInValue tagInfo", tagInfo);
+ // Debug.debug("fillInValue valueOffset", valueOffset);
+ // Debug.debug("fillInValue valueLength", valueLength);
+
byte bytes[] = byteSource.getBlock(valueOffset, valueLength);
setOversizeValue(bytes);
}
@@ -517,11 +516,12 @@
// });
//
//
- public int[] getValueAsIntArray()
+
+ public int[] getIntArrayValue() throws ImageReadException
{
Object o = getValue();
- if (o == null)
- return null;
+ // if (o == null)
+ // return null;
if (o instanceof Number)
return new int[]{
@@ -544,6 +544,108 @@
return result;
}
- return null;
+ throw new ImageReadException("Unknown value: " + o + " for: "
+ + tagInfo.getDescription());
+ // return null;
+ }
+
+ public double[] getDoubleArrayValue() throws ImageReadException
+ {
+ Object o = getValue();
+ // if (o == null)
+ // return null;
+
+ if (o instanceof Number)
+ {
+ return new double[]{
+ ((Number) o).doubleValue()
+ };
+ }
+ else if (o instanceof Number[])
+ {
+ Number numbers[] = (Number[]) o;
+ double result[] = new double[numbers.length];
+ for (int i = 0; i < numbers.length; i++)
+ result[i] = numbers[i].doubleValue();
+ return result;
+ }
+ else if (o instanceof int[])
+ {
+ int numbers[] = (int[]) o;
+ double result[] = new double[numbers.length];
+ for (int i = 0; i < numbers.length; i++)
+ result[i] = numbers[i];
+ return result;
+ }
+ else if (o instanceof float[])
+ {
+ float numbers[] = (float[]) o;
+ double result[] = new double[numbers.length];
+ for (int i = 0; i < numbers.length; i++)
+ result[i] = numbers[i];
+ return result;
+ }
+ else if (o instanceof double[])
+ {
+ double numbers[] = (double[]) o;
+ double result[] = new double[numbers.length];
+ for (int i = 0; i < numbers.length; i++)
+ result[i] = numbers[i];
+ return result;
+ }
+
+ throw new ImageReadException("Unknown value: " + o + " for: "
+ + tagInfo.getDescription());
+ // return null;
+ }
+
+ public int getIntValueOrArraySum() throws ImageReadException
+ {
+ Object o = getValue();
+ // if (o == null)
+ // return -1;
+
+ if (o instanceof Number)
+ return ((Number) o).intValue();
+ else if (o instanceof Number[])
+ {
+ Number numbers[] = (Number[]) o;
+ int sum = 0;
+ for (int i = 0; i < numbers.length; i++)
+ sum += numbers[i].intValue();
+ return sum;
+ }
+ else if (o instanceof int[])
+ {
+ int numbers[] = (int[]) o;
+ int sum = 0;
+ for (int i = 0; i < numbers.length; i++)
+ sum += numbers[i];
+ return sum;
+ }
+
+ throw new ImageReadException("Unknown value: " + o + " for: "
+ + tagInfo.getDescription());
+ // return -1;
+ }
+
+ public int getIntValue() throws ImageReadException
+ {
+ Object o = getValue();
+ if (o == null)
+ throw new ImageReadException("Missing value: "
+ + tagInfo.getDescription());
+
+ return ((Number) o).intValue();
+ }
+
+ public double getDoubleValue() throws ImageReadException
+ {
+ Object o = getValue();
+ if (o == null)
+ throw new ImageReadException("Missing value: "
+ + tagInfo.getDescription());
+
+ return ((Number) o).doubleValue();
}
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageMetadata.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageMetadata.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageMetadata.java Thu Jan 10 21:41:01 2008
@@ -17,8 +17,10 @@
package org.apache.sanselan.formats.tiff;
import java.awt.image.BufferedImage;
+import java.io.IOException;
import java.util.ArrayList;
+import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.ImageWriteException;
import org.apache.sanselan.common.ImageMetadata;
import org.apache.sanselan.formats.tiff.constants.TagInfo;
@@ -26,7 +28,6 @@
import org.apache.sanselan.formats.tiff.write.TiffOutputDirectory;
import org.apache.sanselan.formats.tiff.write.TiffOutputField;
import org.apache.sanselan.formats.tiff.write.TiffOutputSet;
-import org.apache.sanselan.util.Debug;
public class TiffImageMetadata extends ImageMetadata
{
@@ -41,7 +42,7 @@
implements
ImageMetadata.IImageMetadataItem
{
- private BufferedImage thumbnail = null;
+ // private BufferedImage thumbnail = null;
public final int type;
@@ -58,46 +59,62 @@
add(new TiffImageMetadata.Item(entry));
}
- public void setThumbnail(BufferedImage thumbnail)
- {
- this.thumbnail = thumbnail;
- }
-
- public BufferedImage getThumbnail()
- {
- return thumbnail;
- }
-
- private RawTiffImageData rawTiffImageData = null;
-
- public void setRawTiffImageData(RawTiffImageData rawImageData)
- {
- this.rawTiffImageData = rawImageData;
- }
+ // public void setThumbnail(BufferedImage thumbnail)
+ // {
+ // this.thumbnail = thumbnail;
+ // }
+ //
+ // public BufferedImage getThumbnail()
+ // {
+ // return thumbnail;
+ // }
+
+ public BufferedImage getThumbnail() throws ImageReadException,
+ IOException
+ {
+ return directory.getTiffImage();
+ }
+
+ // private RawTiffImageData rawTiffImageData = null;
+ //
+ // public void setRawTiffImageData(RawTiffImageData rawImageData)
+ // {
+ // this.rawTiffImageData = rawImageData;
+ // }
+ //
+ // public RawTiffImageData getRawTiffImageData()
+ // {
+ // return rawTiffImageData;
+ // }
public RawTiffImageData getRawTiffImageData()
{
- return rawTiffImageData;
+ return directory.getRawTiffImageData();
}
- private byte rawJpegImageData[] = null;
-
- public void setRawJpegImageData(byte bytes[])
- {
- this.rawJpegImageData = bytes;
- }
+ // private byte rawJpegImageData[] = null;
+ //
+ // public void setRawJpegImageData(byte bytes[])
+ // {
+ // this.rawJpegImageData = bytes;
+ // }
+ //
+ // public byte[] getRawJpegImageData()
+ // {
+ // return rawJpegImageData;
+ // }
public byte[] getRawJpegImageData()
{
- return rawJpegImageData;
+ return directory.getRawJpegImageData();
}
public String toString(String prefix)
{
return (prefix != null ? prefix : "") + directory.description()
+ ": " //
- + (rawTiffImageData != null ? " (tiffImageData)" : "") //
- + (rawJpegImageData != null ? " (jpegImageData)" : "") //
+ + (getRawTiffImageData() != null ? " (tiffImageData)" : "") //
+ + (getRawJpegImageData() != null ? " (jpegImageData)" : "") //
+ "\n" + super.toString(prefix) + "\n";
}
@@ -134,7 +151,6 @@
dstDir.setRawTiffImageData(getRawTiffImageData());
dstDir.setRawJpegImageData(getRawJpegImageData());
-
return dstDir;
}
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageParser.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffImageParser.java Thu Jan 10 21:41:01 2008
@@ -20,7 +20,6 @@
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -34,14 +33,8 @@
import org.apache.sanselan.ImageWriteException;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.common.byteSources.ByteSource;
-import org.apache.sanselan.common.byteSources.ByteSourceArray;
-import org.apache.sanselan.common.byteSources.ByteSourceFile;
-import org.apache.sanselan.formats.tiff.TiffDirectory.ImageDataElement;
-import org.apache.sanselan.formats.tiff.constants.TagInfo;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.datareaders.DataReader;
-import org.apache.sanselan.formats.tiff.datareaders.DataReaderStrips;
-import org.apache.sanselan.formats.tiff.datareaders.DataReaderTiled;
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterBiLevel;
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterCIELAB;
@@ -51,7 +44,6 @@
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterRGB;
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterYCbCr;
import org.apache.sanselan.formats.tiff.write.TiffImageWriterLossy;
-import org.apache.sanselan.util.Debug;
public class TiffImageParser extends ImageParser implements TiffConstants
{
@@ -88,297 +80,34 @@
};
}
- private TiffHeader readTiffHeader(InputStream is,
- FormatCompliance formatCompliance) throws ImageReadException,
- IOException
- {
- int BYTE_ORDER_1 = readByte("BYTE_ORDER_1", is, "Not a Valid TIFF File");
- int BYTE_ORDER_2 = readByte("BYTE_ORDER_2", is, "Not a Valid TIFF File");
- setByteOrder(BYTE_ORDER_1, BYTE_ORDER_2);
-
- int tiffVersion = read2Bytes("tiffVersion", is, "Not a Valid TIFF File");
- if (tiffVersion != 42)
- throw new ImageReadException("Unknown Tiff Version: " + tiffVersion);
-
- int offsetToFirstIFD = read4Bytes("offsetToFirstIFD", is,
- "Not a Valid TIFF File");
-
- skipBytes(is, offsetToFirstIFD - 8,
- "Not a Valid TIFF File: couldn't find IFDs");
-
- if (debug)
- System.out.println("");
-
- return new TiffHeader(BYTE_ORDER_1, tiffVersion, offsetToFirstIFD);
-
- }
-
- private boolean keepField(int Tag, int tags[])
- {
- if (tags == null)
- return true;
-
- for (int i = 0; i < tags.length; i++)
- {
- if (tags[i] == Tag)
- return true;
- }
-
- return false;
- }
-
- private static final int TAG_ICC_PROFILE = 34675;
-
- private TiffDirectory readDirectory(InputStream is, int dirType,
- int offset, int tags[], int maxEntriesToMatch)
- throws ImageReadException, IOException
- {
- ArrayList result = new ArrayList();
-
- int entryCount = read2Bytes("DirectoryEntryCount", is,
- "Not a Valid TIFF File");
-
-// Debug.debug("dirType", dirType);
-// Debug.debug("offset", offset);
-// Debug.debug("entryCount", entryCount);
-
- for (int i = 0; i < entryCount; i++)
- {
- int tag = read2Bytes("Tag", is, "Not a Valid TIFF File");
- int type = read2Bytes("Type", is, "Not a Valid TIFF File");
- int length = read4Bytes("Length", is, "Not a Valid TIFF File");
-
-// Debug.debug("tag", tag + " (0x" + Integer.toHexString(tag) + ")");
-
-
- byte valueOffsetBytes[] = readByteArray("ValueOffset", 4, is,
- "Not a Valid TIFF File");
- int valueOffset = convertByteArrayToInt("ValueOffset",
- valueOffsetBytes);
-
- if (keepField(tag, tags))
- {
- TiffField entry = new TiffField(tag, dirType, type, length,
- valueOffset, valueOffsetBytes, getByteOrder());
- result.add(entry);
-
- if (debug)
- for (int j = 0; j < 4; j++)
- System.out
- .println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
-
- if ((maxEntriesToMatch > 0)
- && (result.size() >= maxEntriesToMatch))
- {
- return new TiffDirectory(dirType, result, offset, -1);
- }
- }
-
- }
-
- int nextDirectoryOffset = read4Bytes("nextDirectoryOffset", is,
- "Not a Valid TIFF File");
- if (debug)
- System.out.println("");
-
-// Debug.debug();
-
- return new TiffDirectory(dirType, result, offset, nextDirectoryOffset);
- }
-
- private TiffContents readDirectories(ByteSource byteSource, int tags[],
- FormatCompliance formatCompliance) throws ImageReadException,
- IOException
- {
- return readDirectories(byteSource, tags, -1, -1, formatCompliance);
- }
-
- private TiffContents readDirectories(ByteSource byteSource, int tags[],
- int maxDirectoriesToRead, int maxEntriesToMatch,
- FormatCompliance formatCompliance) throws ImageReadException,
- IOException
- {
- TiffHeader tiffHeader;
- InputStream is = null;
- try
- {
- is = byteSource.getInputStream();
- tiffHeader = readTiffHeader(is, formatCompliance);
- }
- finally
- {
- try
- {
- if (is != null)
- is.close();
- }
- catch (Exception e)
- {
- Debug.debug(e);
- }
- }
-
- ArrayList directories = new ArrayList();
-
- int offset = tiffHeader.offsetToFirstIFD;
- for (int count = 0; (offset > 0)
- && ((maxDirectoriesToRead < 1) || (directories.size() < maxDirectoriesToRead)); count++)
- {
- int dirType;
- if (0 == count)
- dirType = TiffDirectory.DIRECTORY_TYPE_ROOT;
- else
- dirType = TiffDirectory.DIRECTORY_TYPE_SUB;
-
- TiffDirectory directory = readSingleDirectory(byteSource, dirType,
- offset, formatCompliance);
- if (directory.entries.size() > 0)
- directories.add(directory);
- offset = directory.nextDirectoryOffset;
- }
-
- return new TiffContents(tiffHeader, directories);
-
- }
-
- private TiffDirectory readSingleDirectory(ByteSource byteSource,
- int dirType, int offset, FormatCompliance formatCompliance)
- throws ImageReadException, IOException
- {
- int tags[] = null;
- int maxEntriesToMatch = -1;
- return readSingleDirectory(byteSource, dirType, offset, tags,
- maxEntriesToMatch, formatCompliance);
- }
-
- private TiffDirectory readSingleDirectory(ByteSource byteSource,
- int dirType, int offset, int tags[], int maxEntriesToMatch,
- FormatCompliance formatCompliance) throws ImageReadException,
- IOException
- {
- InputStream is = null;
- try
- {
- is = byteSource.getInputStream();
- if (offset > 0)
- is.skip(offset);
-
- TiffDirectory directory = readDirectory(is, dirType, offset, tags,
- maxEntriesToMatch);
-
- directory.fillInValues(byteSource);
-
- return directory;
- }
- finally
- {
- try
- {
- if (is != null)
- is.close();
- }
- catch (Exception e)
- {
- Debug.debug(e);
- }
- }
- }
-
public byte[] getICCProfileBytes(ByteSource byteSource)
throws ImageReadException, IOException
{
- int FieldTypes[] = new int[]{
- TAG_ICC_PROFILE,
- };
-
- TiffContents contents = readDirectories(byteSource, FieldTypes, -1, 1,
- getDefaultFormatCompliance());
- if (contents == null)
- throw new ImageReadException("TIFF missing contents");
-
- ArrayList directories = contents.directories;
-
- if ((directories == null) || (directories.size() < 1))
- return null;
- // throw new ImageReadException("TIFF missing directories");
-
- TiffDirectory directory = (TiffDirectory) directories.get(0);
- ArrayList entries = directory.entries;
-
- if ((entries == null) || (entries.size() != 1))
- throw new ImageReadException("TIFF missing entries");
-
- TiffField de = (TiffField) entries.get(0);
- byte bytes[] = de.oversizeValue;
- return (bytes);
-
- }
-
- private TiffField findField(ArrayList directories, int tag)
- throws ImageReadException, IOException
- {
- if ((directories == null) || (directories.size() < 1))
- throw new ImageReadException("TIFF missing directories");
-
- TiffDirectory directory = (TiffDirectory) directories.get(0);
- ArrayList entries = directory.entries;
-
- if ((entries == null) || (entries.size() < 1))
- throw new ImageReadException("TIFF missing entries");
+ FormatCompliance formatCompliance = getDefaultFormatCompliance();
+ Map params = null;
+ TiffContents contents = new TiffReader().readFirstDirectory(byteSource,
+ params, false, formatCompliance);
+ TiffDirectory directory = (TiffDirectory) contents.directories.get(0);
- for (int i = 0; i < entries.size(); i++)
- {
- TiffField field = (TiffField) entries.get(i);
- if (field.tag == tag)
- return field;
- }
-
- return null;
- }
-
- private TiffField findField(ArrayList entries, TagInfo tag)
- {
- if (entries == null)
+ TiffField field = directory.findField(EXIF_TAG_ICC_PROFILE);
+ if (null == field)
return null;
-
- for (int i = 0; i < entries.size(); i++)
- {
- TiffField field = (TiffField) entries.get(i);
- if (field.tag == tag.tag)
- return field;
- }
-
- return null;
+ return (byte[]) field.oversizeValue;
}
public Dimension getImageSize(ByteSource byteSource)
throws ImageReadException, IOException
{
- int fieldTypes[] = new int[]{
- TIFF_TAG_IMAGE_WIDTH.tag, TIFF_TAG_IMAGE_LENGTH.tag,
- };
+ FormatCompliance formatCompliance = getDefaultFormatCompliance();
+ Map params = null;
+ TiffContents contents = new TiffReader().readFirstDirectory(byteSource,
+ params, false, formatCompliance);
+ TiffDirectory directory = (TiffDirectory) contents.directories.get(0);
- TiffContents contents = readDirectories(byteSource, fieldTypes, -1, 2,
- getDefaultFormatCompliance());
- if (contents == null)
- throw new ImageReadException("TIFF missing contents");
+ int width = directory.findField(TIFF_TAG_IMAGE_WIDTH).getIntValue();
+ int height = directory.findField(TIFF_TAG_IMAGE_LENGTH).getIntValue();
- ArrayList directories = contents.directories;
-
- TiffField widthField = findField(directories, TIFF_TAG_IMAGE_WIDTH.tag);
- TiffField heightField = findField(directories,
- TIFF_TAG_IMAGE_LENGTH.tag);
-
- if ((widthField == null) || (heightField == null))
- throw new ImageReadException("TIFF image has invalid size.");
-
- Number width = (Number) widthField.getValue();
- Number height = (Number) heightField.getValue();
-
- if ((width == null) || (height == null))
- throw new ImageReadException("TIFF image missing size info.");
-
- return new Dimension(width.intValue(), height.intValue());
+ return new Dimension(width, height);
}
public byte[] embedICCProfile(byte image[], byte profile[])
@@ -391,39 +120,12 @@
return false;
}
- public TiffContents readDirectories(byte bytes[])
- throws ImageReadException, IOException
- {
- return readDirectories(new ByteSourceArray(bytes), null,
- getDefaultFormatCompliance());
- }
-
- public TiffContents readDirectories(File file) throws ImageReadException,
- IOException
- {
- return readDirectories(new ByteSourceFile(file), null,
- getDefaultFormatCompliance());
- }
-
- private boolean readThumbnails(Map params)
- {
- if (params == null)
- return false;
- Object o = params.get(PARAM_KEY_READ_THUMBNAILS);
- if (o == null)
- return false;
- if (!(o instanceof Boolean))
- return false;
- return o.equals(Boolean.TRUE);
- }
-
public IImageMetadata getMetadata(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
- TiffContents contents = readDirectories(byteSource, null,
- getDefaultFormatCompliance());
- if (contents == null)
- throw new ImageReadException("TIFF missing contents");
+ FormatCompliance formatCompliance = getDefaultFormatCompliance();
+ TiffContents contents = new TiffReader().readContents(byteSource,
+ params, formatCompliance);
ArrayList directories = contents.directories;
@@ -436,61 +138,11 @@
TiffImageMetadata.Directory metadataDirectory = new TiffImageMetadata.Directory(
dir);
- if (readThumbnails(params))
- {
- if (dir.hasTiffImageData())
- {
- BufferedImage thumbnail = getBufferedImage(byteSource, dir,
- null);
- metadataDirectory.setThumbnail(thumbnail);
-
- RawTiffImageData rawImageData = getTiffRawImageData(
- byteSource, dir);
- metadataDirectory.setRawTiffImageData(rawImageData);
- }
- if (dir.hasJpegImageData())
- {
- // BufferedImage thumbnail = getBufferedImage(byteSource, dir,
- // null);
- // metadataDirectory.setThumbnail(thumbnail);
-
- byte rawJpegImageData[] = getJpegRawImageData(byteSource,
- dir);
- metadataDirectory.setRawJpegImageData(rawJpegImageData);
- }
- }
-
ArrayList entries = dir.getDirectoryEntrys();
for (int j = 0; j < entries.size(); j++)
{
TiffField entry = (TiffField) entries.get(j);
-
- if (entry.tag == TiffConstants.EXIF_TAG_EXIF_OFFSET.tag
- || entry.tag == TiffConstants.EXIF_TAG_GPSINFO.tag
- || entry.tag == TiffConstants.EXIF_TAG_INTEROP_OFFSET.tag)
- {
- int offset = ((Number) entry.getValue()).intValue();
- int dirType;
- if (entry.tag == TiffConstants.EXIF_TAG_EXIF_OFFSET.tag)
- dirType = TiffDirectory.DIRECTORY_TYPE_EXIF;
- else if (entry.tag == TiffConstants.EXIF_TAG_GPSINFO.tag)
- dirType = TiffDirectory.DIRECTORY_TYPE_GPS;
- else if (entry.tag == TiffConstants.EXIF_TAG_INTEROP_OFFSET.tag)
- dirType = TiffDirectory.DIRECTORY_TYPE_INTEROPERABILITY;
- else
- throw new ImageReadException(
- "Unknown subdirectory type.");
-
-// Debug.debug("extra dir");
-// Debug.debug("extra dir dirType", dirType);
-// Debug.debug("extra dir offset", offset+ " (0x" + Integer.toHexString(offset) + ")");
-
- TiffDirectory extraDir = readSingleDirectory(byteSource,
- dirType, offset, getDefaultFormatCompliance());
- directories.add(i + 1, extraDir);
- }
-
metadataDirectory.add(entry);
}
@@ -500,168 +152,34 @@
return result;
}
- private double[] getValueAsDoubleArray(TiffField field)
- {
- if (field == null)
- return null;
-
- Object o = field.getValue();
- if (o == null)
- return null;
-
- if (o instanceof Number)
- {
- return new double[]{
- ((Number) o).doubleValue()
- };
- }
- else if (o instanceof Number[])
- {
- Number numbers[] = (Number[]) o;
- double result[] = new double[numbers.length];
- for (int i = 0; i < numbers.length; i++)
- result[i] = numbers[i].doubleValue();
- return result;
- }
- else if (o instanceof int[])
- {
- int numbers[] = (int[]) o;
- double result[] = new double[numbers.length];
- for (int i = 0; i < numbers.length; i++)
- result[i] = numbers[i];
- return result;
- }
- else if (o instanceof float[])
- {
- float numbers[] = (float[]) o;
- double result[] = new double[numbers.length];
- for (int i = 0; i < numbers.length; i++)
- result[i] = numbers[i];
- return result;
- }
- else if (o instanceof double[])
- {
- double numbers[] = (double[]) o;
- double result[] = new double[numbers.length];
- for (int i = 0; i < numbers.length; i++)
- result[i] = numbers[i];
- return result;
- }
-
- return null;
- }
-
- private int[] getValueAsIntArray(TiffField field)
- {
- if (field == null)
- return null;
-
- Object o = field.getValue();
- if (o == null)
- return null;
-
- if (o instanceof Number)
- return new int[]{
- ((Number) o).intValue()
- };
- else if (o instanceof Number[])
- {
- Number numbers[] = (Number[]) o;
- int result[] = new int[numbers.length];
- for (int i = 0; i < numbers.length; i++)
- result[i] = numbers[i].intValue();
- return result;
- }
- else if (o instanceof int[])
- {
- int numbers[] = (int[]) o;
- int result[] = new int[numbers.length];
- for (int i = 0; i < numbers.length; i++)
- result[i] = numbers[i];
- return result;
- }
-
- return null;
- }
-
- private int getValueOrArraySum(TiffField field)
- {
- if (field == null)
- return -1;
-
- Object o = field.getValue();
- if (o == null)
- return -1;
-
- if (o instanceof Number)
- return ((Number) o).intValue();
- else if (o instanceof Number[])
- {
- Number numbers[] = (Number[]) o;
- int sum = 0;
- for (int i = 0; i < numbers.length; i++)
- sum += numbers[i].intValue();
- return sum;
- }
- else if (o instanceof int[])
- {
- int numbers[] = (int[]) o;
- int sum = 0;
- for (int i = 0; i < numbers.length; i++)
- sum += numbers[i];
- return sum;
- }
-
- return -1;
- }
-
public ImageInfo getImageInfo(ByteSource byteSource)
throws ImageReadException, IOException
{
- int FieldTypes[] = new int[]{
- TIFF_TAG_IMAGE_WIDTH.tag, TIFF_TAG_IMAGE_LENGTH.tag,
- TIFF_TAG_RESOLUTION_UNIT.tag, TIFF_TAG_XRESOLUTION.tag,
- TIFF_TAG_YRESOLUTION.tag, TIFF_TAG_BITS_PER_SAMPLE.tag,
- TIFF_TAG_COLOR_MAP.tag, TIFF_TAG_SAMPLES_PER_PIXEL.tag,
- TIFF_TAG_COMPRESSION.tag,
- };
-
- TiffContents contents = readDirectories(byteSource, FieldTypes, -1, -1,
- getDefaultFormatCompliance());
- if (contents == null)
- throw new ImageReadException("TIFF missing contents");
-
- ArrayList dirs = contents.directories;
- if ((dirs == null) || (dirs.size() < 1))
- throw new ImageReadException("TIFF image missing directories");
-
- TiffDirectory directory = (TiffDirectory) dirs.get(0);
-
- ArrayList entries = directory.entries;
-
- if (entries == null)
- throw new ImageReadException("TIFF missing entries");
-
- TiffField widthField = findField(entries, TIFF_TAG_IMAGE_WIDTH);
- TiffField heightField = findField(entries, TIFF_TAG_IMAGE_LENGTH);
+ FormatCompliance formatCompliance = getDefaultFormatCompliance();
+ Map params = null;
+ TiffContents contents = new TiffReader().readFirstDirectory(byteSource,
+ params, false, formatCompliance);
+ TiffDirectory directory = (TiffDirectory) contents.directories.get(0);
+
+ TiffField widthField = directory.findField(TIFF_TAG_IMAGE_WIDTH, true);
+ TiffField heightField = directory
+ .findField(TIFF_TAG_IMAGE_LENGTH, true);
if ((widthField == null) || (heightField == null))
throw new ImageReadException("TIFF image missing size info.");
- int height = ((Number) heightField.getValue()).intValue();
- int width = ((Number) widthField.getValue()).intValue();
+ int height = heightField.getIntValue();
+ int width = widthField.getIntValue();
//-------------------
- TiffField resolutionUnitField = findField(entries,
- TIFF_TAG_RESOLUTION_UNIT);
+ TiffField resolutionUnitField = directory
+ .findField(TIFF_TAG_RESOLUTION_UNIT);
int resolutionUnit = 2; // Inch
if ((resolutionUnitField != null)
&& (resolutionUnitField.getValue() != null))
- {
- resolutionUnit = ((Number) resolutionUnitField.getValue())
- .intValue();
- }
+ resolutionUnit = resolutionUnitField.getIntValue();
+
double unitsPerInch = -1;
switch (resolutionUnit)
{
@@ -677,8 +195,8 @@
break;
}
- TiffField xResolutionField = findField(entries, TIFF_TAG_XRESOLUTION);
- TiffField yResolutionField = findField(entries, TIFF_TAG_YRESOLUTION);
+ TiffField xResolutionField = directory.findField(TIFF_TAG_XRESOLUTION);
+ TiffField yResolutionField = directory.findField(TIFF_TAG_YRESOLUTION);
int physicalWidthDpi = -1;
float physicalWidthInch = -1;
@@ -690,16 +208,16 @@
if ((xResolutionField != null)
&& (xResolutionField.getValue() != null))
{
- double XResolutionPixelsPerUnit = ((Number) xResolutionField
- .getValue()).doubleValue();
+ double XResolutionPixelsPerUnit = xResolutionField
+ .getDoubleValue();
physicalWidthDpi = (int) (XResolutionPixelsPerUnit / unitsPerInch);
physicalWidthInch = (float) ((double) width / (XResolutionPixelsPerUnit * unitsPerInch));
}
if ((yResolutionField != null)
&& (yResolutionField.getValue() != null))
{
- double YResolutionPixelsPerUnit = ((Number) yResolutionField
- .getValue()).doubleValue();
+ double YResolutionPixelsPerUnit = yResolutionField
+ .getDoubleValue();
physicalHeightDpi = (int) (YResolutionPixelsPerUnit / unitsPerInch);
physicalHeightInch = (float) ((double) height / (YResolutionPixelsPerUnit * unitsPerInch));
}
@@ -707,18 +225,13 @@
//-------------------
- TiffField bitsPerSampleField = findField(entries,
- TIFF_TAG_BITS_PER_SAMPLE);
- // TiffField samplesPerPixelField = findField(entries,
- // TIFF_TAG_SAMPLES_PER_PIXEL);
+ TiffField bitsPerSampleField = directory
+ .findField(TIFF_TAG_BITS_PER_SAMPLE);
int bitsPerSample = -1;
-
if ((bitsPerSampleField != null)
&& (bitsPerSampleField.getValue() != null))
- {
- bitsPerSample = getValueOrArraySum(bitsPerSampleField);
- }
+ bitsPerSample = bitsPerSampleField.getIntValueOrArraySum();
int bitsPerPixel = bitsPerSample; // assume grayscale;
// dunno if this handles colormapped images correctly.
@@ -726,6 +239,7 @@
//-------------------
ArrayList comments = new ArrayList();
+ ArrayList entries = directory.entries;
for (int i = 0; i < entries.size(); i++)
{
TiffField field = (TiffField) entries.get(i);
@@ -746,14 +260,14 @@
boolean isTransparent = false; // TODO: wrong
boolean usesPalette = false;
- TiffField colorMapField = findField(entries, TIFF_TAG_COLOR_MAP);
+ TiffField colorMapField = directory.findField(TIFF_TAG_COLOR_MAP);
if (colorMapField != null)
usesPalette = true;
int colorType = ImageInfo.COLOR_TYPE_RGB;
- int compression = getTagAsNumber(entries, TIFF_TAG_COMPRESSION)
- .intValue();
+ int compression = directory.findField(TIFF_TAG_COMPRESSION)
+ .getIntValue();
String compressionAlgorithm;
switch (compression)
@@ -799,258 +313,132 @@
public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
throws ImageReadException, IOException
{
- pw.println("tiff.dumpImageFile");
-
- {
- ImageInfo imageData = getImageInfo(byteSource);
- if (imageData == null)
- return false;
-
- imageData.toString(pw, "");
- }
-
- pw.println("");
-
try
{
- TiffContents contents = readDirectories(byteSource, null, -1, -1,
- getDefaultFormatCompliance());
- if (contents == null)
- return false;
-
- ArrayList directories = contents.directories;
-
- if (directories == null)
- return false;
+ pw.println("tiff.dumpImageFile");
- for (int d = 0; d < directories.size(); d++)
{
- TiffDirectory directory = (TiffDirectory) directories.get(d);
-
- ArrayList entries = directory.entries;
-
- if (entries == null)
+ ImageInfo imageData = getImageInfo(byteSource);
+ if (imageData == null)
return false;
- Debug.debug("directory offset", directory.offset);
- Debug.debug("directory offset", directory.offset);
-
- for (int i = 0; i < entries.size(); i++)
- {
- TiffField field = (TiffField) entries.get(i);
-
- field.dump(pw, d + "");
- }
+ imageData.toString(pw, "");
}
pw.println("");
- }
- catch (Exception e)
- {
- Debug.debug(e);
- pw.println("");
- return false;
- }
-
- return true;
- }
-
- private Number getTagAsNumber(ArrayList entries, TagInfo tag)
- throws ImageReadException, IOException
- {
- TiffField entry = findField(entries, tag);
- if (entry == null)
- throw new ImageReadException("Tiff: Missing Tag: " + tag.name
- + " (" + tag.tag + ")");
- Object o = entry.getValue();
-
- // Debug.debug("getTagAsNumber:" + entry.tagInfo.name, o);
- // Debug.debug("getTagAsNumber:" + entry.tagInfo.name, Debug.getType(o));
-
- Number result = (Number) o;
+ // try
+ {
+ FormatCompliance formatCompliance = getDefaultFormatCompliance();
+ Map params = null;
+ TiffContents contents = new TiffReader().readContents(
+ byteSource, params, formatCompliance);
- if (debug)
- this.debugNumber(tag.name + " (" + tag.tag + ")",
- result.intValue(), 4);
+ ArrayList directories = contents.directories;
- return result;
- }
+ if (directories == null)
+ return false;
- private int getTagAsValueOrArraySum(ArrayList entries, TagInfo tag)
- throws ImageReadException, IOException
- {
- TiffField entry = findField(entries, tag);
- if (entry == null)
- throw new ImageReadException("Tiff: Missing Tag: " + tag.name
- + " (" + tag.tag + ")");
+ for (int d = 0; d < directories.size(); d++)
+ {
+ TiffDirectory directory = (TiffDirectory) directories
+ .get(d);
- int result = getValueOrArraySum(entry);
+ ArrayList entries = directory.entries;
- if (debug)
- this.debugNumber(tag.name + " (" + tag.tag + ")", result, 4);
+ if (entries == null)
+ return false;
- return result;
- }
+ // Debug.debug("directory offset", directory.offset);
- private double[] getTagAsDoubleArray(ArrayList entries, TagInfo tag,
- boolean throwExceptionIfMissing) throws ImageReadException,
- IOException
- {
- TiffField entry = findField(entries, tag);
- if (entry == null)
- {
- if (throwExceptionIfMissing)
- throw new ImageReadException("Tiff: Missing Tag: " + tag.name
- + " (" + tag.tag + ")");
- else
- return null;
- }
+ for (int i = 0; i < entries.size(); i++)
+ {
+ TiffField field = (TiffField) entries.get(i);
- double result[] = getValueAsDoubleArray(entry);
+ field.dump(pw, d + "");
+ }
+ }
- return result;
- }
+ pw.println("");
+ }
+ // catch (Exception e)
+ // {
+ // Debug.debug(e);
+ // pw.println("");
+ // return false;
+ // }
- private int[] getTagAsIntArray(ArrayList entries, TagInfo tag,
- boolean throwExceptionIfMissing) throws ImageReadException,
- IOException
- {
- TiffField entry = findField(entries, tag);
- if (entry == null)
- {
- if (throwExceptionIfMissing)
- throw new ImageReadException("Tiff: Missing Tag: " + tag.name
- + " (" + tag.tag + ")");
- else
- return null;
+ return true;
}
-
- int result[] = getValueAsIntArray(entry);
-
- if (debug)
- this.debugNumberArray(tag.name + " (" + tag.tag + ")", result, 4);
-
- return result;
- }
-
- private int dumpOptionalNumberTag(ArrayList entries, TagInfo tag)
- {
- TiffField entry = findField(entries, tag);
-
- if (entry != null)
+ finally
{
- Object o = entry.getValue();
- if (o instanceof Number)
- {
- int value = ((Number) o).intValue();
- // System.out.println(tag.name + ": " + value);
- return value;
- }
+ pw.println("");
}
- return -1;
}
public FormatCompliance getFormatCompliance(ByteSource byteSource)
throws ImageReadException, IOException
{
- FormatCompliance result = new FormatCompliance(byteSource
- .getDescription());
-
- readDirectories(byteSource, null, -1, -1, result);
-
- return result;
+ FormatCompliance formatCompliance = getDefaultFormatCompliance();
+ Map params = null;
+ new TiffReader().readContents(byteSource, params, formatCompliance);
+ return formatCompliance;
}
public BufferedImage getBufferedImage(ByteSource byteSource, Map params)
throws ImageReadException, IOException
{
- TiffContents contents = readDirectories(byteSource, null, -1, -1,
- getDefaultFormatCompliance());
- if (contents == null)
- throw new ImageReadException("TIFF missing contents");
-
- ArrayList directories = contents.directories;
-
- if ((directories == null) || (directories.size() < 1))
- throw new ImageReadException("TIFF missing TiffDirectories");
-
- TiffDirectory directory = (TiffDirectory) directories.get(0);
-
- return getBufferedImage(byteSource, directory, params);
- }
-
- public RawTiffImageData getTiffRawImageData(ByteSource byteSource,
- TiffDirectory directory) throws ImageReadException, IOException
- {
- ArrayList elements = directory.getTiffRawImageDataElements();
- byte result[][] = new byte[elements.size()][];
- for (int i = 0; i < elements.size(); i++)
- {
- TiffDirectory.ImageDataElement element = (TiffDirectory.ImageDataElement) elements
- .get(i);
- result[i] = byteSource.getBlock(element.offset, element.length);
- }
-
- if (directory.imageDataInStrips())
- return new RawTiffImageData.Strips(result);
- else
- return new RawTiffImageData.Tiles(result);
- }
-
- public byte[] getJpegRawImageData(ByteSource byteSource,
- TiffDirectory directory) throws ImageReadException, IOException
- {
- ImageDataElement element = directory.getJpegRawImageDataElement();
- byte result[] = byteSource.getBlock(element.offset, element.length);
+ FormatCompliance formatCompliance = getDefaultFormatCompliance();
+ TiffContents contents = new TiffReader().readFirstDirectory(byteSource,
+ params, true, formatCompliance);
+ TiffDirectory directory = (TiffDirectory) contents.directories.get(0);
+ BufferedImage result = directory.getTiffImage(params);
+ if (null == result)
+ throw new ImageReadException("TIFF does not contain an image.");
return result;
}
- public BufferedImage getBufferedImage(ByteSource byteSource,
- TiffDirectory directory, Map params) throws ImageReadException,
- IOException
+ protected BufferedImage getBufferedImage(TiffDirectory directory, Map params)
+ throws ImageReadException, IOException
{
ArrayList entries = directory.entries;
if (entries == null)
throw new ImageReadException("TIFF missing entries");
- // this.setDebug(true);
+ int photometricInterpretation = directory.findField(
+ TIFF_TAG_PHOTOMETRIC_INTERPRETATION, true).getIntValue();
+ int compression = directory.findField(TIFF_TAG_COMPRESSION, true)
+ .getIntValue();
+ int width = directory.findField(TIFF_TAG_IMAGE_WIDTH, true)
+ .getIntValue();
+ int height = directory.findField(TIFF_TAG_IMAGE_LENGTH, true)
+ .getIntValue();
+ int samplesPerPixel = directory.findField(TIFF_TAG_SAMPLES_PER_PIXEL,
+ true).getIntValue();
+ int bitsPerSample[] = directory.findField(TIFF_TAG_BITS_PER_SAMPLE,
+ true).getIntArrayValue();
+ // TODO: why are we using bits per sample twice? is there a bits per pixel tag?
+ int bitsPerPixel = directory.findField(TIFF_TAG_BITS_PER_SAMPLE, true)
+ .getIntValueOrArraySum();
- TiffField imageWidthField = findField(entries, TIFF_TAG_IMAGE_WIDTH);
- if (imageWidthField == null)
- throw new ImageReadException(
- "Tiff: Missing Tag: TIFF_TAG_IMAGE_WIDTH");
- TiffField imageLengthField = findField(entries, TIFF_TAG_IMAGE_LENGTH);
- if (imageLengthField == null)
- throw new ImageReadException(
- "Tiff: Missing Tag: TIFF_TAG_IMAGE_LENGTH");
-
- int photometricInterpretation = getTagAsNumber(entries,
- TIFF_TAG_PHOTOMETRIC_INTERPRETATION).intValue();
- int compression = getTagAsNumber(entries, TIFF_TAG_COMPRESSION)
- .intValue();
- int width = getTagAsNumber(entries, TIFF_TAG_IMAGE_WIDTH).intValue();
- int height = getTagAsNumber(entries, TIFF_TAG_IMAGE_LENGTH).intValue();
- int samplesPerPixel = getTagAsNumber(entries,
- TIFF_TAG_SAMPLES_PER_PIXEL).intValue();
- int bitsPerSample[] = getTagAsIntArray(entries,
- TIFF_TAG_BITS_PER_SAMPLE, true);
- int bitsPerPixel = getTagAsValueOrArraySum(entries,
- TIFF_TAG_BITS_PER_SAMPLE);
+ // int bitsPerPixel = getTagAsValueOrArraySum(entries,
+ // TIFF_TAG_BITS_PER_SAMPLE);
- int predictor;
+ int predictor = -1;
{
// dumpOptionalNumberTag(entries, TIFF_TAG_FILL_ORDER);
// dumpOptionalNumberTag(entries, TIFF_TAG_FREE_BYTE_COUNTS);
// dumpOptionalNumberTag(entries, TIFF_TAG_FREE_OFFSETS);
// dumpOptionalNumberTag(entries, TIFF_TAG_ORIENTATION);
// dumpOptionalNumberTag(entries, TIFF_TAG_PLANAR_CONFIGURATION);
- predictor = dumpOptionalNumberTag(entries, TIFF_TAG_PREDICTOR);
+ TiffField predictorField = directory.findField(TIFF_TAG_PREDICTOR);
+ if (null != predictorField)
+ predictor = predictorField.getIntValueOrArraySum();
}
if (samplesPerPixel != bitsPerSample.length)
- throw new ImageReadException("Tiff: fSamplesPerPixel ("
+ throw new ImageReadException("Tiff: samplesPerPixel ("
+ samplesPerPixel + ")!=fBitsPerSample.length ("
+ bitsPerSample.length + ")");
@@ -1059,26 +447,27 @@
.getColorBufferedImage(width, height, hasAlpha);
PhotometricInterpreter photometricInterpreter = getPhotometricInterpreter(
- entries, photometricInterpretation, bitsPerPixel,
+ directory, photometricInterpretation, bitsPerPixel,
bitsPerSample, predictor, samplesPerPixel, width, height);
- // this.setDebug(false);
+ RawTiffImageData imageData = directory.getRawTiffImageData();
- DataReader dataReader = getDataReader(entries, photometricInterpreter,
- bitsPerPixel, bitsPerSample, predictor, samplesPerPixel, width,
- height, compression);
+ DataReader dataReader = imageData.getDataReader(entries,
+ photometricInterpreter, bitsPerPixel, bitsPerSample, predictor,
+ samplesPerPixel, width, height, compression);
- dataReader.readImageData(result, byteSource);
+ dataReader.readImageData(result);
photometricInterpreter.dumpstats();
return result;
}
- private PhotometricInterpreter getPhotometricInterpreter(ArrayList entries,
- int photometricInterpretation, int bitsPerPixel,
- int bitsPerSample[], int predictor, int samplesPerPixel, int width,
- int height) throws IOException, ImageReadException
+ private PhotometricInterpreter getPhotometricInterpreter(
+ TiffDirectory directory, int photometricInterpretation,
+ int bitsPerPixel, int bitsPerSample[], int predictor,
+ int samplesPerPixel, int width, int height) throws IOException,
+ ImageReadException
{
switch (photometricInterpretation)
{
@@ -1091,8 +480,8 @@
height, invert);
case 3 : // Palette
{
- int[] colorMap = getTagAsIntArray(entries, TIFF_TAG_COLOR_MAP,
- false);
+ int colorMap[] = directory.findField(TIFF_TAG_COLOR_MAP, true)
+ .getIntArrayValue();
int expected_colormap_size = 3 * (1 << bitsPerPixel);
@@ -1112,17 +501,21 @@
bitsPerSample, predictor, width, height);
case 6 : //
{
- double[] fYCbCrCoefficients = getTagAsDoubleArray(entries,
- TIFF_TAG_YCBCR_COEFFICIENTS, false);
- int[] fYCbCrPositioning = getTagAsIntArray(entries,
- TIFF_TAG_YCBCR_POSITIONING, false);
- int[] fYCbCrSubSampling = getTagAsIntArray(entries,
- TIFF_TAG_YCBCR_SUB_SAMPLING, false);
- double[] referenceBlackWhite = getTagAsDoubleArray(entries,
- TIFF_TAG_REFERENCE_BLACK_WHITE, false);
+ double yCbCrCoefficients[] = directory.findField(
+ TIFF_TAG_YCBCR_COEFFICIENTS, true)
+ .getDoubleArrayValue();
+
+ int yCbCrPositioning[] = directory.findField(
+ TIFF_TAG_YCBCR_POSITIONING, true).getIntArrayValue();
+ int yCbCrSubSampling[] = directory.findField(
+ TIFF_TAG_YCBCR_SUB_SAMPLING, true).getIntArrayValue();
+
+ double referenceBlackWhite[] = directory.findField(
+ TIFF_TAG_REFERENCE_BLACK_WHITE, true)
+ .getDoubleArrayValue();
- return new PhotometricInterpreterYCbCr(fYCbCrCoefficients,
- fYCbCrPositioning, fYCbCrSubSampling,
+ return new PhotometricInterpreterYCbCr(yCbCrCoefficients,
+ yCbCrPositioning, yCbCrSubSampling,
referenceBlackWhite, samplesPerPixel, bitsPerSample,
predictor, width, height);
}
@@ -1143,78 +536,6 @@
"TIFF: Unknown fPhotometricInterpretation: "
+ photometricInterpretation);
}
- }
-
- private DataReader getDataReader(ArrayList entries,
- PhotometricInterpreter photometricInterpreter, int bitsPerPixel,
- int bitsPerSample[], int predictor, int samplesPerPixel, int width,
- int height, int compression) throws IOException, ImageReadException
- {
- int[] tileOffsets = getTagAsIntArray(entries, TIFF_TAG_TILE_OFFSETS,
- false);
- int[] tileByteCounts = getTagAsIntArray(entries,
- TIFF_TAG_TILE_BYTE_COUNTS, false);
-
- int[] stripOffsets = getTagAsIntArray(entries, TIFF_TAG_STRIP_OFFSETS,
- false);
- int[] stripByteCounts = getTagAsIntArray(entries,
- TIFF_TAG_STRIP_BYTE_COUNTS, false);
-
- TiffField tileWidthField = findField(entries, TIFF_TAG_TILE_WIDTH);
- TiffField tileLengthField = findField(entries, TIFF_TAG_TILE_LENGTH);
-
- if ((tileOffsets != null) && (tileByteCounts != null))
- {
- if (tileOffsets.length != tileByteCounts.length)
- throw new ImageReadException("Tiff: fTileOffsets.length ("
- + tileOffsets.length + ")!=fTileByteCounts.length ("
- + tileByteCounts.length + ")");
-
- int tileWidth = getTagAsNumber(entries, TIFF_TAG_TILE_WIDTH)
- .intValue();
- int tileLength = getTagAsNumber(entries, TIFF_TAG_TILE_LENGTH)
- .intValue();
-
- return new DataReaderTiled(photometricInterpreter, tileOffsets,
- tileByteCounts, tileWidth, tileLength, bitsPerPixel,
- bitsPerSample, predictor, samplesPerPixel, width, height,
- compression, getByteOrder());
- }
- else if ((tileWidthField != null) && (tileLengthField != null)
- && (stripOffsets != null) && (stripByteCounts != null))
- {
- if (stripOffsets.length != stripByteCounts.length)
- throw new ImageReadException("Tiff: fStripOffsets.length ("
- + stripOffsets.length + ")!=fStripByteCounts.length ("
- + stripByteCounts.length + ")");
-
- int tileWidth = getTagAsNumber(entries, TIFF_TAG_TILE_WIDTH)
- .intValue();
- int tileLength = getTagAsNumber(entries, TIFF_TAG_TILE_LENGTH)
- .intValue();
-
- return new DataReaderTiled(photometricInterpreter, stripOffsets,
- stripByteCounts, tileWidth, tileLength, bitsPerPixel,
- bitsPerSample, predictor, samplesPerPixel, width, height,
- compression, getByteOrder());
- }
- else if ((stripOffsets != null) && (stripByteCounts != null))
- {
- int rowsPerStrip = getTagAsNumber(entries, TIFF_TAG_ROWS_PER_STRIP)
- .intValue();
-
- if (stripOffsets.length != stripByteCounts.length)
- throw new ImageReadException("Tiff: fStripOffsets.length ("
- + stripOffsets.length + ")!=fStripByteCounts.length ("
- + stripByteCounts.length + ")");
-
- return new DataReaderStrips(photometricInterpreter, bitsPerPixel,
- bitsPerSample, predictor, samplesPerPixel, width, height,
- stripOffsets, stripByteCounts, compression, rowsPerStrip,
- getByteOrder());
- }
- else
- throw new ImageReadException("Tiff: Neither Strip nor Tile.");
}
public void writeImage(BufferedImage src, OutputStream os, Map params)
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffReader.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffReader.java?rev=611055&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffReader.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffReader.java Thu Jan 10 21:41:01 2008
@@ -0,0 +1,381 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.formats.tiff;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.sanselan.FormatCompliance;
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.common.BinaryFileParser;
+import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.formats.tiff.TiffDirectory.ImageDataElement;
+import org.apache.sanselan.formats.tiff.constants.TiffConstants;
+import org.apache.sanselan.util.Debug;
+
+public class TiffReader extends BinaryFileParser implements TiffConstants
+{
+
+ private TiffHeader readTiffHeader(ByteSource byteSource,
+ FormatCompliance formatCompliance) throws ImageReadException,
+ IOException
+ {
+ InputStream is = null;
+ try
+ {
+ is = byteSource.getInputStream();
+ return readTiffHeader(is, formatCompliance);
+ }
+ finally
+ {
+ try
+ {
+ if (is != null)
+ is.close();
+ }
+ catch (Exception e)
+ {
+ Debug.debug(e);
+ }
+ }
+ }
+
+ private TiffHeader readTiffHeader(InputStream is,
+ FormatCompliance formatCompliance) throws ImageReadException,
+ IOException
+ {
+ int BYTE_ORDER_1 = readByte("BYTE_ORDER_1", is, "Not a Valid TIFF File");
+ int BYTE_ORDER_2 = readByte("BYTE_ORDER_2", is, "Not a Valid TIFF File");
+ setByteOrder(BYTE_ORDER_1, BYTE_ORDER_2);
+
+ int tiffVersion = read2Bytes("tiffVersion", is, "Not a Valid TIFF File");
+ if (tiffVersion != 42)
+ throw new ImageReadException("Unknown Tiff Version: " + tiffVersion);
+
+ int offsetToFirstIFD = read4Bytes("offsetToFirstIFD", is,
+ "Not a Valid TIFF File");
+
+ skipBytes(is, offsetToFirstIFD - 8,
+ "Not a Valid TIFF File: couldn't find IFDs");
+
+ if (debug)
+ System.out.println("");
+
+ return new TiffHeader(BYTE_ORDER_1, tiffVersion, offsetToFirstIFD);
+ }
+
+ private void readDirectories(ByteSource byteSource,
+ FormatCompliance formatCompliance, Listener listener)
+ throws ImageReadException, IOException
+ {
+ TiffHeader tiffHeader = readTiffHeader(byteSource, formatCompliance);
+ if (!listener.setTiffHeader(tiffHeader))
+ return;
+
+ int offset = tiffHeader.offsetToFirstIFD;
+ int dirType = TiffDirectory.DIRECTORY_TYPE_ROOT;
+
+ readDirectory(byteSource, offset, dirType, formatCompliance, listener);
+ }
+
+ private void readDirectory(ByteSource byteSource, int offset, int dirType,
+ FormatCompliance formatCompliance, Listener listener)
+ throws ImageReadException, IOException
+ {
+ boolean ignoreNextDirectory = false;
+ readDirectory(byteSource, offset, dirType, formatCompliance, listener,
+ ignoreNextDirectory);
+ }
+
+ private void readDirectory(ByteSource byteSource, int offset, int dirType,
+ FormatCompliance formatCompliance, Listener listener,
+ boolean ignoreNextDirectory) throws ImageReadException, IOException
+ {
+ InputStream is = null;
+ try
+ {
+ is = byteSource.getInputStream();
+ if (offset > 0)
+ is.skip(offset);
+
+ ArrayList fields = new ArrayList();
+
+ int entryCount = read2Bytes("DirectoryEntryCount", is,
+ "Not a Valid TIFF File");
+
+ // Debug.debug("dirType", dirType);
+ // Debug.debug("offset", offset);
+ // Debug.debug("entryCount", entryCount);
+
+ for (int i = 0; i < entryCount; i++)
+ {
+ int tag = read2Bytes("Tag", is, "Not a Valid TIFF File");
+ int type = read2Bytes("Type", is, "Not a Valid TIFF File");
+ int length = read4Bytes("Length", is, "Not a Valid TIFF File");
+
+ // Debug.debug("tag", tag + " (0x" + Integer.toHexString(tag) + ")");
+
+ byte valueOffsetBytes[] = readByteArray("ValueOffset", 4, is,
+ "Not a Valid TIFF File");
+ int valueOffset = convertByteArrayToInt("ValueOffset",
+ valueOffsetBytes);
+
+ // if (keepField(tag, tags))
+ // {
+ TiffField field = new TiffField(tag, dirType, type, length,
+ valueOffset, valueOffsetBytes, getByteOrder());
+
+ field.fillInValue(byteSource);
+
+ fields.add(field);
+
+ if (!listener.addField(field))
+ return;
+ }
+
+ int nextDirectoryOffset = read4Bytes("nextDirectoryOffset", is,
+ "Not a Valid TIFF File");
+ // Debug.debug("nextDirectoryOffset", nextDirectoryOffset);
+
+ TiffDirectory directory = new TiffDirectory(dirType, fields,
+ offset, nextDirectoryOffset);
+
+ if (listener.readImageData())
+ {
+ if (directory.hasTiffImageData())
+ {
+ RawTiffImageData rawImageData = getTiffRawImageData(
+ byteSource, directory);
+ directory.setRawTiffImageData(rawImageData);
+ }
+ if (directory.hasJpegImageData())
+ {
+ byte rawJpegImageData[] = getJpegRawImageData(byteSource,
+ directory);
+ directory.setRawJpegImageData(rawJpegImageData);
+ }
+ }
+
+ if (!listener.addDirectory(directory))
+ return;
+
+ if (listener.readOffsetDirectories())
+ {
+ for (int j = 0; j < fields.size(); j++)
+ {
+ TiffField entry = (TiffField) fields.get(j);
+
+ if (entry.tag == TiffConstants.EXIF_TAG_EXIF_OFFSET.tag
+ || entry.tag == TiffConstants.EXIF_TAG_GPSINFO.tag
+ || entry.tag == TiffConstants.EXIF_TAG_INTEROP_OFFSET.tag)
+ ;
+ else
+ continue;
+
+ int subDirectoryOffset = ((Number) entry.getValue())
+ .intValue();
+ int subDirectoryType;
+ if (entry.tag == TiffConstants.EXIF_TAG_EXIF_OFFSET.tag)
+ subDirectoryType = TiffDirectory.DIRECTORY_TYPE_EXIF;
+ else if (entry.tag == TiffConstants.EXIF_TAG_GPSINFO.tag)
+ subDirectoryType = TiffDirectory.DIRECTORY_TYPE_GPS;
+ else if (entry.tag == TiffConstants.EXIF_TAG_INTEROP_OFFSET.tag)
+ subDirectoryType = TiffDirectory.DIRECTORY_TYPE_INTEROPERABILITY;
+ else
+ throw new ImageReadException(
+ "Unknown subdirectory type.");
+
+ readDirectory(byteSource, subDirectoryOffset,
+ subDirectoryType, formatCompliance, listener, true);
+ }
+ }
+
+ if (!ignoreNextDirectory && directory.nextDirectoryOffset > 0)
+ {
+ readDirectory(byteSource, directory.nextDirectoryOffset,
+ dirType + 1, formatCompliance, listener);
+ }
+ }
+ finally
+ {
+ try
+ {
+ if (is != null)
+ is.close();
+ }
+ catch (Exception e)
+ {
+ Debug.debug(e);
+ }
+ }
+ }
+
+ public static interface Listener
+ {
+ public boolean setTiffHeader(TiffHeader tiffHeader);
+
+ public boolean addDirectory(TiffDirectory directory);
+
+ public boolean addField(TiffField field);
+
+ public boolean readImageData();
+
+ public boolean readOffsetDirectories();
+ }
+
+ private static class Collector implements Listener
+ {
+ private TiffHeader tiffHeader = null;
+ private ArrayList directories = new ArrayList();
+ private ArrayList fields = new ArrayList();
+
+ public boolean setTiffHeader(TiffHeader tiffHeader)
+ {
+ this.tiffHeader = tiffHeader;
+ return true;
+ }
+
+ public boolean addDirectory(TiffDirectory directory)
+ {
+ directories.add(directory);
+ return true;
+ }
+
+ public boolean addField(TiffField field)
+ {
+ fields.add(field);
+ return true;
+ }
+
+ public boolean readImageData()
+ {
+ return true;
+ }
+
+ public boolean readOffsetDirectories()
+ {
+ return true;
+ }
+
+ public TiffContents getContents()
+ {
+ return new TiffContents(tiffHeader, directories);
+ }
+ }
+
+ private static class FirstDirectoryCollector extends Collector
+ {
+ private final boolean readImageData;
+
+ public FirstDirectoryCollector(final boolean readImageData)
+ {
+ this.readImageData = readImageData;
+ }
+
+ public boolean addDirectory(TiffDirectory directory)
+ {
+ super.addDirectory(directory);
+ return false;
+ }
+
+ public boolean readImageData()
+ {
+ return true;
+ }
+ }
+
+ public TiffContents readFirstDirectory(ByteSource byteSource, Map params,
+ boolean readImageData, FormatCompliance formatCompliance)
+ throws ImageReadException, IOException
+ {
+ Collector collector = new FirstDirectoryCollector(readImageData);
+ read(byteSource, params, formatCompliance, collector);
+ TiffContents contents = collector.getContents();
+ if (contents.directories.size() < 1)
+ throw new ImageReadException(
+ "Image did not contain any directories.");
+ return contents;
+ }
+
+ public TiffContents readContents(ByteSource byteSource, Map params,
+ FormatCompliance formatCompliance) throws ImageReadException,
+ IOException
+ {
+ Collector collector = new Collector();
+ read(byteSource, params, formatCompliance, collector);
+ TiffContents contents = collector.getContents();
+ return contents;
+ }
+
+ public void read(ByteSource byteSource, Map params,
+ FormatCompliance formatCompliance, Listener listener)
+ throws ImageReadException, IOException
+ {
+ // TiffContents contents =
+ readDirectories(byteSource, formatCompliance, listener);
+ }
+
+ private RawTiffImageData getTiffRawImageData(ByteSource byteSource,
+ TiffDirectory directory) throws ImageReadException, IOException
+ {
+ ArrayList elements = directory.getTiffRawImageDataElements();
+ byte result[][] = new byte[elements.size()][];
+ for (int i = 0; i < elements.size(); i++)
+ {
+ TiffDirectory.ImageDataElement element = (TiffDirectory.ImageDataElement) elements
+ .get(i);
+ result[i] = byteSource.getBlock(element.offset, element.length);
+ }
+
+ if (directory.imageDataInStrips())
+ {
+ TiffField rowsPerStripField = directory
+ .findField(TIFF_TAG_ROWS_PER_STRIP);
+ if (null == rowsPerStripField)
+ throw new ImageReadException("Can't find rows per strip field.");
+ int rowsPerStrip = rowsPerStripField.getIntValue();
+
+ return new RawTiffImageData.Strips(result, rowsPerStrip);
+ }
+ else
+ {
+ TiffField tileWidthField = directory.findField(TIFF_TAG_TILE_WIDTH);
+ if (null == tileWidthField)
+ throw new ImageReadException("Can't find tile width field.");
+ int tileWidth = tileWidthField.getIntValue();
+
+ TiffField tileLengthField = directory
+ .findField(TIFF_TAG_TILE_LENGTH);
+ if (null == tileLengthField)
+ throw new ImageReadException("Can't find tile length field.");
+ int tileLength = tileLengthField.getIntValue();
+
+ return new RawTiffImageData.Tiles(result, tileWidth, tileLength);
+ }
+ }
+
+ private byte[] getJpegRawImageData(ByteSource byteSource,
+ TiffDirectory directory) throws ImageReadException, IOException
+ {
+ ImageDataElement element = directory.getJpegRawImageDataElement();
+ byte result[] = byteSource.getBlock(element.offset, element.length);
+ return result;
+ }
+
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/TiffReader.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffDirectoryConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffDirectoryConstants.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffDirectoryConstants.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffDirectoryConstants.java Thu Jan 10 21:41:01 2008
@@ -22,6 +22,7 @@
public static final int DIRECTORY_TYPE_UNKNOWN = -1;
public static final int DIRECTORY_TYPE_ROOT = 0;
public static final int DIRECTORY_TYPE_SUB = 1;
+ public static final int DIRECTORY_TYPE_SUB0 = 1;
public static final int DIRECTORY_TYPE_SUB1 = 2;
public static final int DIRECTORY_TYPE_SUB2 = 3;
public static final int DIRECTORY_TYPE_THUMBNAIL = 2;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java Thu Jan 10 21:41:01 2008
@@ -25,7 +25,6 @@
import org.apache.sanselan.common.BinaryConstants;
import org.apache.sanselan.common.BitInputStream;
import org.apache.sanselan.common.PackBits;
-import org.apache.sanselan.common.byteSources.ByteSource;
import org.apache.sanselan.common.mylzw.MyLZWDecompressor;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
@@ -39,21 +38,18 @@
protected final int predictor;
protected final int samplesPerPixel;
- protected final int byteOrder;
-
- public DataReader(PhotometricInterpreter fPhotometricInterpreter,
- int fBitsPerSample[], int Predictor, int fSamplesPerPixel,
- int byteOrder)
+ public DataReader(PhotometricInterpreter photometricInterpreter,
+ int bitsPerSample[], int predictor, int samplesPerPixel)
{
- this.photometricInterpreter = fPhotometricInterpreter;
- this.bitsPerSample = fBitsPerSample;
- this.samplesPerPixel = fSamplesPerPixel;
- this.predictor = Predictor;
- this.byteOrder = byteOrder;
- last = new int[fSamplesPerPixel];
+ this.photometricInterpreter = photometricInterpreter;
+ this.bitsPerSample = bitsPerSample;
+ this.samplesPerPixel = samplesPerPixel;
+ this.predictor = predictor;
+ last = new int[samplesPerPixel];
}
- public abstract void readImageData(BufferedImage bi, ByteSource byteSource)
+// public abstract void readImageData(BufferedImage bi, ByteSource byteSource)
+ public abstract void readImageData(BufferedImage bi)
throws ImageReadException, IOException;
protected int[] getSamplesAsBytes(BitInputStream bis)
@@ -116,12 +112,12 @@
int LZWMinimumCodeSize = 8;
- MyLZWDecompressor fMyLzwDecompressor = new MyLZWDecompressor(
+ MyLZWDecompressor myLzwDecompressor = new MyLZWDecompressor(
LZWMinimumCodeSize, BYTE_ORDER_NETWORK);
- fMyLzwDecompressor.setTiffLZWMode();
+ myLzwDecompressor.setTiffLZWMode();
- byte[] result = fMyLzwDecompressor
+ byte[] result = myLzwDecompressor
.decompress(is, expected_size);
return result;
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java Thu Jan 10 21:41:01 2008
@@ -22,41 +22,41 @@
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.BitInputStream;
-import org.apache.sanselan.common.byteSources.ByteSource;
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
-public class DataReaderStrips extends DataReader
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.formats.tiff.RawTiffImageData;
+import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
+
+public final class DataReaderStrips extends DataReader
{
private final int bitsPerPixel;
-
private final int width, height;
-
- private final int stripOffsets[];
- private final int stripByteCounts[];
private final int compression;
private final int rowsPerStrip;
- public DataReaderStrips(PhotometricInterpreter fPhotometricInterpreter,
- int fBitsPerPixel, int fBitsPerSample[], int Predictor,
- int fSamplesPerPixel, int width, int height, int fStripOffsets[],
- int fStripByteCounts[], int fCompression, int fRowsPerStrip,
- int byteOrder)
+ private final RawTiffImageData.Strips imageData;
+
+ public DataReaderStrips(PhotometricInterpreter photometricInterpreter,
+ int bitsPerPixel, int bitsPerSample[], int predictor,
+ int samplesPerPixel, int width, int height, int compression,
+ int rowsPerStrip, RawTiffImageData.Strips imageData)
{
- super(fPhotometricInterpreter, fBitsPerSample, Predictor,
- fSamplesPerPixel, byteOrder);
+ super(photometricInterpreter, bitsPerSample, predictor, samplesPerPixel);
- this.bitsPerPixel = fBitsPerPixel;
+ this.bitsPerPixel = bitsPerPixel;
this.width = width;
this.height = height;
- this.stripOffsets = fStripOffsets;
- this.stripByteCounts = fStripByteCounts;
- this.compression = fCompression;
- this.rowsPerStrip = fRowsPerStrip;
-
+ this.compression = compression;
+ this.rowsPerStrip = rowsPerStrip;
+ this.imageData = imageData;
}
- public void interpretStrip(BufferedImage bi, byte bytes[],
+ private void interpretStrip(BufferedImage bi, byte bytes[],
int pixels_per_strip) throws ImageReadException, IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
@@ -85,29 +85,24 @@
}
}
- int x = 0, y = 0;
+ private int x = 0, y = 0;
- public void readImageData(BufferedImage bi, ByteSource byteSource)
- throws ImageReadException, IOException
+ public void readImageData(BufferedImage bi) throws ImageReadException,
+ IOException
{
-
- for (int strip = 0; strip < stripOffsets.length; strip++)
+ for (int strip = 0; strip < imageData.strips.length; strip++)
{
- int rows_remaining = height - (strip * rowsPerStrip);
- int rows_in_this_strip = Math.min(rows_remaining, rowsPerStrip);
- int pixels_per_strip = rows_in_this_strip * width;
- int bytes_per_strip = ((pixels_per_strip * bitsPerPixel) + 7) / 8;
-
- int fStripOffset = stripOffsets[strip];
- int fStripByteCount = stripByteCounts[strip];
+ int rowsRemaining = height - (strip * rowsPerStrip);
+ int rowsInThisStrip = Math.min(rowsRemaining, rowsPerStrip);
+ int pixelsPerStrip = rowsInThisStrip * width;
+ int bytesPerStrip = ((pixelsPerStrip * bitsPerPixel) + 7) / 8;
- byte compressed[] = byteSource.getBlock(fStripOffset,
- fStripByteCount);
+ byte compressed[] = imageData.strips[strip];
byte decompressed[] = decompress(compressed, compression,
- bytes_per_strip);
+ bytesPerStrip);
- interpretStrip(bi, decompressed, pixels_per_strip);
+ interpretStrip(bi, decompressed, pixelsPerStrip);
}
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java Thu Jan 10 21:41:01 2008
@@ -22,60 +22,64 @@
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.BitInputStream;
-import org.apache.sanselan.common.byteSources.ByteSource;
import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
-public class DataReaderTiled extends DataReader
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.formats.tiff.RawTiffImageData;
+import org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
+
+public final class DataReaderTiled extends DataReader
{
private final int tileWidth;
private final int tileLength;
- private final int tileOffsets[];
- private final int tileByteCounts[];
- // private final int predictor;
private final int bitsPerPixel;
private final int width, height;
private final int compression;
- public DataReaderTiled(PhotometricInterpreter fPhotometricInterpreter,
- int fTileOffsets[], int fTileByteCounts[], int TileWidth,
- int TileLength, int fBitsPerPixel, int fBitsPerSample[],
- int Predictor, int fSamplesPerPixel, int width, int height,
- int fCompression, int byteOrder)
+ private final RawTiffImageData.Tiles imageData;
+
+ public DataReaderTiled(PhotometricInterpreter photometricInterpreter,
+ int tileWidth, int tileLength, int bitsPerPixel,
+ int bitsPerSample[], int predictor, int samplesPerPixel,
+ int width, int height, int compression,
+ RawTiffImageData.Tiles imageData)
{
- super(fPhotometricInterpreter, fBitsPerSample, Predictor,
- fSamplesPerPixel, byteOrder);
+ super(photometricInterpreter, bitsPerSample, predictor,
+ samplesPerPixel);
- this.tileOffsets = fTileOffsets;
- this.tileByteCounts = fTileByteCounts;
- this.tileWidth = TileWidth;
- this.tileLength = TileLength;
+ this.tileWidth = tileWidth;
+ this.tileLength = tileLength;
- this.bitsPerPixel = fBitsPerPixel;
- // this.predictor = Predictor;
+ this.bitsPerPixel = bitsPerPixel;
this.width = width;
this.height = height;
- this.compression = fCompression;
+ this.compression = compression;
+
+ this.imageData = imageData;
}
- private void interpretTile(BufferedImage bi, byte bytes[], int start_x,
- int start_y) throws ImageReadException, IOException
+ private void interpretTile(BufferedImage bi, byte bytes[], int startX,
+ int startY) throws ImageReadException, IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
BitInputStream bis = new BitInputStream(bais);
- int pixels_per_tile = tileWidth * tileLength;
+ int pixelsPerTile = tileWidth * tileLength;
- int tile_x = 0, tile_y = 0;
+ int tileX = 0, tileY = 0;
- for (int i = 0; i < pixels_per_tile; i++)
+ for (int i = 0; i < pixelsPerTile; i++)
{
- int x = tile_x + start_x;
- int y = tile_y + start_y;
+ int x = tileX + startX;
+ int y = tileY + startY;
int samples[] = getSamplesAsBytes(bis);
@@ -85,38 +89,34 @@
photometricInterpreter.interpretPixel(bi, samples, x, y);
}
- tile_x++;
+ tileX++;
- if (tile_x >= tileWidth)
+ if (tileX >= tileWidth)
{
- tile_x = 0;
- tile_y++;
+ tileX = 0;
+ tileY++;
bis.flushCache();
- if (tile_y >= tileLength)
+ if (tileY >= tileLength)
break;
}
}
}
- public void readImageData(BufferedImage bi, ByteSource byteSource)
- throws ImageReadException, IOException
+ public void readImageData(BufferedImage bi) throws ImageReadException,
+ IOException
{
- int bits_per_row = tileWidth * bitsPerPixel;
- int bytes_per_row = (bits_per_row + 7) / 8;
- int bytes_per_tile = bytes_per_row * tileLength;
+ int bitsPerRow = tileWidth * bitsPerPixel;
+ int bytesPerRow = (bitsPerRow + 7) / 8;
+ int bytesPerTile = bytesPerRow * tileLength;
int x = 0, y = 0;
- for (int tile = 0; tile < tileOffsets.length; tile++)
+ for (int tile = 0; tile < imageData.tiles.length; tile++)
{
- int fTileOffset = tileOffsets[tile];
- int fTileByteCount = tileByteCounts[tile];
-
- byte compressed[] = byteSource
- .getBlock(fTileOffset, fTileByteCount);
+ byte compressed[] = imageData.tiles[tile];
byte decompressed[] = decompress(compressed, compression,
- bytes_per_tile);
+ bytesPerTile);
interpretTile(bi, decompressed, x, y);
@@ -131,4 +131,4 @@
}
}
-}
\ No newline at end of file
+}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterBase.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterBase.java?rev=611055&r1=611054&r2=611055&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterBase.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterBase.java Thu Jan 10 21:41:01 2008
@@ -461,7 +461,7 @@
}
- RawTiffImageData rawTiffImageData = new RawTiffImageData.Strips(strips);
+ RawTiffImageData rawTiffImageData = new RawTiffImageData.Strips(strips, rowsPerStrip);
directory.setRawTiffImageData(rawTiffImageData);
write(os, outputSet);