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 2007/11/17 21:58:40 UTC

svn commit: r596008 [11/15] - in /incubator/sanselan/trunk/src: main/java/org/apache/sanselan/ main/java/org/apache/sanselan/color/ main/java/org/apache/sanselan/common/ main/java/org/apache/sanselan/common/byteSources/ main/java/org/apache/sanselan/co...

Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/TiffImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/TiffImageParser.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/TiffImageParser.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/TiffImageParser.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,1222 @@
+/*
+ * 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.cmc.sanselan.formats.tiff;
+
+import java.awt.Dimension;
+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.Map;
+import java.util.Vector;
+
+import org.cmc.sanselan.FormatCompliance;
+import org.cmc.sanselan.ImageFormat;
+import org.cmc.sanselan.ImageInfo;
+import org.cmc.sanselan.ImageParser;
+import org.cmc.sanselan.ImageReadException;
+import org.cmc.sanselan.ImageWriteException;
+import org.cmc.sanselan.common.IImageMetadata;
+import org.cmc.sanselan.common.byteSources.ByteSource;
+import org.cmc.sanselan.common.byteSources.ByteSourceArray;
+import org.cmc.sanselan.common.byteSources.ByteSourceFile;
+import org.cmc.sanselan.formats.tiff.TiffDirectory.ImageDataElement;
+import org.cmc.sanselan.formats.tiff.datareaders.DataReader;
+import org.cmc.sanselan.formats.tiff.datareaders.DataReaderStrips;
+import org.cmc.sanselan.formats.tiff.datareaders.DataReaderTiled;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterBiLevel;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterCIELAB;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterCMYK;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterLogLUV;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterPalette;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterRGB;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreterYCbCr;
+import org.cmc.sanselan.formats.tiff.write.TiffImageWriter;
+import org.cmc.sanselan.util.Debug;
+
+public class TiffImageParser extends ImageParser implements TiffConstants
+{
+	public TiffImageParser()
+	{
+		//		setDebug(true);
+	}
+
+	public String getName()
+	{
+		return "Tiff-Custom";
+	}
+
+	public String getDefaultExtension()
+	{
+		return DEFAULT_EXTENSION;
+	}
+
+	private static final String DEFAULT_EXTENSION = ".tif";
+
+	private static final String ACCEPTED_EXTENSIONS[] = {
+			".tif", ".tiff",
+	};
+
+	protected String[] getAcceptedExtensions()
+	{
+		return ACCEPTED_EXTENSIONS;
+	}
+
+	protected ImageFormat[] getAcceptedTypes()
+	{
+		return new ImageFormat[]{
+			ImageFormat.IMAGE_FORMAT_TIFF, //
+		};
+	}
+
+	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
+	{
+		Vector result = new Vector();
+
+		int entryCount = read2Bytes("DirectoryEntryCount", is,
+				"Not a Valid TIFF File");
+
+		//		Debug.debug();
+		//		Debug.debug("readDirectory 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");
+
+			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, type, length, valueOffset,
+						valueOffsetBytes, getByteOrder());
+				result.add(entry);
+
+				//				Debug.debug("read field tag", tag + ", 0x"
+				//						+ Integer.toHexString(tag));
+
+				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("");
+
+		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);
+			}
+		}
+
+		Vector directories = new Vector();
+
+		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();
+			//			Debug.debug("readSingleDirectory offset", offset);
+			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");
+
+		Vector directories = contents.directories;
+
+		if ((directories == null) || (directories.size() < 1))
+			return null;
+		//			throw new ImageReadException("TIFF missing directories");
+
+		TiffDirectory directory = (TiffDirectory) directories.get(0);
+		Vector 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(Vector directories, int tag)
+			throws ImageReadException, IOException
+	{
+		if ((directories == null) || (directories.size() < 1))
+			throw new ImageReadException("TIFF missing directories");
+
+		TiffDirectory directory = (TiffDirectory) directories.get(0);
+		Vector entries = directory.entries;
+
+		if ((entries == null) || (entries.size() < 1))
+			throw new ImageReadException("TIFF missing entries");
+
+		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(Vector entries, TagInfo tag)
+	{
+		if (entries == null)
+			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;
+	}
+
+	public Dimension getImageSize(ByteSource byteSource)
+			throws ImageReadException, IOException
+	{
+		int fieldTypes[] = new int[]{
+				TIFF_TAG_ImageWidth.tag, TIFF_TAG_ImageLength.tag,
+		};
+
+		TiffContents contents = readDirectories(byteSource, fieldTypes, -1, 2,
+				getDefaultFormatCompliance());
+		if (contents == null)
+			throw new ImageReadException("TIFF missing contents");
+
+		Vector directories = contents.directories;
+
+		TiffField widthField = findField(directories, TIFF_TAG_ImageWidth.tag);
+		TiffField heightField = findField(directories, TIFF_TAG_ImageLength.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());
+	}
+
+	public byte[] embedICCProfile(byte image[], byte profile[])
+	{
+		return null;
+	}
+
+	public boolean embedICCProfile(File src, File dst, byte profile[])
+	{
+		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");
+
+		Vector directories = contents.directories;
+
+		TiffImageMetadata result = new TiffImageMetadata(contents);
+
+		for (int i = 0; i < directories.size(); i++)
+		{
+			TiffDirectory dir = (TiffDirectory) directories.get(i);
+
+			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);
+				}
+			}
+
+			Vector entries = dir.getDirectoryEntrys();
+
+			for (int j = 0; j < entries.size(); j++)
+			{
+				TiffField entry = (TiffField) entries.get(j);
+
+				if (entry.tag == TiffConstants.TIFF_TAG_Exif_IFD_Pointer.tag
+						|| entry.tag == TiffConstants.TIFF_TAG_GPSInfo_IFD_Pointer.tag
+						|| entry.tag == TiffConstants.TIFF_TAG_Interoperability_IFD_Pointer.tag)
+				{
+					int offset = ((Number) entry.getValue()).intValue();
+					int dirType;
+					if (entry.tag == TiffConstants.TIFF_TAG_Exif_IFD_Pointer.tag)
+						dirType = TiffDirectory.DIRECTORY_TYPE_EXIF;
+					else if (entry.tag == TiffConstants.TIFF_TAG_GPSInfo_IFD_Pointer.tag)
+						dirType = TiffDirectory.DIRECTORY_TYPE_GPS;
+					else if (entry.tag == TiffConstants.TIFF_TAG_Interoperability_IFD_Pointer.tag)
+						dirType = TiffDirectory.DIRECTORY_TYPE_INTEROPERABILITY;
+					else
+						throw new ImageReadException(
+								"Unknown subdirectory type.");
+
+					//					Debug.debug();
+					//					Debug.debug("extra dir child of ", dir.description());
+					//					Debug.debug("extra dir offset", offset);
+					//					Debug.debug("extra dir type", TiffDirectory.description(dirType));
+					TiffDirectory extraDir = readSingleDirectory(byteSource,
+							dirType, offset, getDefaultFormatCompliance());
+					//					Debug.debug("extraDir", extraDir);
+					//					directories.add(extraDir);
+					directories.insertElementAt(extraDir, i + 1);
+				}
+
+				metadataDirectory.add(entry);
+			}
+
+			result.add(metadataDirectory);
+		}
+
+		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_ImageWidth.tag, TIFF_TAG_ImageLength.tag,
+				TIFF_TAG_ResolutionUnit.tag, TIFF_TAG_XResolution.tag,
+				TIFF_TAG_YResolution.tag, TIFF_TAG_BitsPerSample.tag,
+				TIFF_TAG_ColorMap.tag, TIFF_TAG_SamplesPerPixel.tag,
+				TIFF_TAG_Compression.tag,
+		};
+
+		TiffContents contents = readDirectories(byteSource, FieldTypes, -1, -1,
+				getDefaultFormatCompliance());
+		if (contents == null)
+			throw new ImageReadException("TIFF missing contents");
+
+		Vector dirs = contents.directories;
+		if ((dirs == null) || (dirs.size() < 1))
+			throw new ImageReadException("TIFF image missing directories");
+
+		TiffDirectory directory = (TiffDirectory) dirs.get(0);
+
+		Vector entries = directory.entries;
+
+		if (entries == null)
+			throw new ImageReadException("TIFF missing entries");
+
+		TiffField widthField = findField(entries, TIFF_TAG_ImageWidth);
+		TiffField heightField = findField(entries, TIFF_TAG_ImageLength);
+
+		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();
+
+		//-------------------
+
+		TiffField resolutionUnitField = findField(entries,
+				TIFF_TAG_ResolutionUnit);
+		int resolutionUnit = 2; // Inch
+		if ((resolutionUnitField != null)
+				&& (resolutionUnitField.getValue() != null))
+		{
+			resolutionUnit = ((Number) resolutionUnitField.getValue())
+					.intValue();
+		}
+		double unitsPerInch = -1;
+		switch (resolutionUnit)
+		{
+			case 1 :
+				break;
+			case 2 : // Inch
+				unitsPerInch = 1.0;
+				break;
+			case 3 : // Meter
+				unitsPerInch = 0.0254;
+				break;
+			default :
+				break;
+
+		}
+		TiffField xResolutionField = findField(entries, TIFF_TAG_XResolution);
+		TiffField yResolutionField = findField(entries, TIFF_TAG_YResolution);
+
+		int physicalWidthDpi = -1;
+		float physicalWidthInch = -1;
+		int physicalHeightDpi = -1;
+		float physicalHeightInch = -1;
+
+		if (unitsPerInch > 0)
+		{
+			if ((xResolutionField != null)
+					&& (xResolutionField.getValue() != null))
+			{
+				double XResolutionPixelsPerUnit = ((Number) xResolutionField
+						.getValue()).doubleValue();
+				physicalWidthDpi = (int) (XResolutionPixelsPerUnit / unitsPerInch);
+				physicalWidthInch = (float) ((double) width / (XResolutionPixelsPerUnit * unitsPerInch));
+			}
+			if ((yResolutionField != null)
+					&& (yResolutionField.getValue() != null))
+			{
+				double YResolutionPixelsPerUnit = ((Number) yResolutionField
+						.getValue()).doubleValue();
+				physicalHeightDpi = (int) (YResolutionPixelsPerUnit / unitsPerInch);
+				physicalHeightInch = (float) ((double) height / (YResolutionPixelsPerUnit * unitsPerInch));
+			}
+		}
+
+		//-------------------
+
+		TiffField bitsPerSampleField = findField(entries,
+				TIFF_TAG_BitsPerSample);
+//		TiffField samplesPerPixelField = findField(entries,
+//				TIFF_TAG_SamplesPerPixel);
+
+		int bitsPerSample = -1;
+
+		if ((bitsPerSampleField != null)
+				&& (bitsPerSampleField.getValue() != null))
+		{
+			bitsPerSample = getValueOrArraySum(bitsPerSampleField);
+		}
+
+		int bitsPerPixel = bitsPerSample; // assume grayscale;
+		// dunno if this handles colormapped images correctly.
+
+		//-------------------
+
+		Vector comments = new Vector();
+		for (int i = 0; i < entries.size(); i++)
+		{
+			TiffField field = (TiffField) entries.get(i);
+			String comment = field.toString();
+			comments.add(comment);
+		}
+
+		ImageFormat format = ImageFormat.IMAGE_FORMAT_TIFF;
+		String formatName = "TIFF Tag-based Image File Format";
+		String mimeType = "image/tiff";
+		// we ought to count images, but don't yet.
+		int numberOfImages = -1;
+		// not accurate ... only reflects first
+		boolean isProgressive = false;
+		// is TIFF ever interlaced/progressive?
+
+		String formatDetails = "Tiff v." + contents.header.tiffVersion;
+
+		boolean isTransparent = false; // TODO: wrong
+		boolean usesPalette = false;
+		TiffField colorMapField = findField(entries, TIFF_TAG_ColorMap);
+		if (colorMapField != null)
+			usesPalette = true;
+
+		int colorType = ImageInfo.COLOR_TYPE_RGB;
+
+		int compression = getTagAsNumber(entries, TIFF_TAG_Compression)
+				.intValue();
+		String compressionAlgorithm;
+
+		switch (compression)
+		{
+			case TIFF_COMPRESSION_UNCOMPRESSED_1 :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_NONE;
+				break;
+			case TIFF_COMPRESSION_CCITT_1D :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_CCITT_1D;
+				break;
+			case TIFF_COMPRESSION_CCITT_GROUP_3 :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_CCITT_GROUP_3;
+				break;
+			case TIFF_COMPRESSION_CCITT_GROUP_4 :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_CCITT_GROUP_4;
+				break;
+			case TIFF_COMPRESSION_LZW :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_LZW;
+				break;
+			case TIFF_COMPRESSION_JPEG :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_JPEG;
+				break;
+			case TIFF_COMPRESSION_UNCOMPRESSED_2 :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_NONE;
+				break;
+			case TIFF_COMPRESSION_PACKBITS :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_PACKBITS;
+				break;
+			default :
+				compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_UNKNOWN;
+				break;
+		}
+
+		ImageInfo result = new ImageInfo(formatDetails, bitsPerPixel, comments,
+				format, formatName, height, mimeType, numberOfImages,
+				physicalHeightDpi, physicalHeightInch, physicalWidthDpi,
+				physicalWidthInch, width, isProgressive, isTransparent,
+				usesPalette, colorType, compressionAlgorithm);
+
+		return result;
+	}
+
+	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;
+
+			Vector directories = contents.directories;
+
+			if (directories == null)
+				return false;
+
+			for (int d = 0; d < directories.size(); d++)
+			{
+				TiffDirectory directory = (TiffDirectory) directories.get(d);
+
+				Vector entries = directory.entries;
+
+				if (entries == 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 + "");
+				}
+			}
+
+			pw.println("");
+		}
+		catch (Exception e)
+		{
+			Debug.debug(e);
+			pw.println("");
+			return false;
+		}
+
+		return true;
+	}
+
+	private Number getTagAsNumber(Vector 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;
+
+		if (debug)
+			this.debugNumber(tag.name + " (" + tag.tag + ")",
+					result.intValue(), 4);
+
+		return result;
+	}
+
+	private int getTagAsValueOrArraySum(Vector entries, TagInfo tag)
+			throws ImageReadException, IOException
+	{
+		TiffField entry = findField(entries, tag);
+		if (entry == null)
+			throw new ImageReadException("Tiff: Missing Tag: " + tag.name
+					+ " (" + tag.tag + ")");
+
+		int result = getValueOrArraySum(entry);
+
+		if (debug)
+			this.debugNumber(tag.name + " (" + tag.tag + ")", result, 4);
+
+		return result;
+	}
+
+	private double[] getTagAsDoubleArray(Vector 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;
+		}
+
+		double result[] = getValueAsDoubleArray(entry);
+
+		return result;
+	}
+
+	private int[] getTagAsIntArray(Vector 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;
+		}
+
+		int result[] = getValueAsIntArray(entry);
+
+		if (debug)
+			this.debugNumberArray(tag.name + " (" + tag.tag + ")", result, 4);
+
+		return result;
+	}
+
+	private int dumpOptionalNumberTag(Vector entries, TagInfo tag)
+	{
+		TiffField entry = findField(entries, tag);
+
+		if (entry != null)
+		{
+			Object o = entry.getValue();
+			if (o instanceof Number)
+			{
+				int value = ((Number) o).intValue();
+				System.out.println(tag.name + ": " + value);
+				return value;
+			}
+		}
+		return -1;
+	}
+
+	public FormatCompliance getFormatCompliance(ByteSource byteSource)
+			throws ImageReadException, IOException
+	{
+		FormatCompliance result = new FormatCompliance(byteSource
+				.getDescription());
+
+		readDirectories(byteSource, null, -1, -1, result);
+
+		return result;
+	}
+
+	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");
+
+		Vector 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
+	{
+		Vector 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);
+		return result;
+	}
+
+	public BufferedImage getBufferedImage(ByteSource byteSource,
+			TiffDirectory directory, Map params) throws ImageReadException,
+			IOException
+	{
+		Vector entries = directory.entries;
+
+		if (entries == null)
+			throw new ImageReadException("TIFF missing entries");
+
+		//			this.setDebug(true);
+
+		TiffField imageWidthField = findField(entries, TIFF_TAG_ImageWidth);
+		if (imageWidthField == null)
+			throw new ImageReadException(
+					"Tiff: Missing Tag: TIFF_TAG_ImageWidth");
+		TiffField imageLengthField = findField(entries, TIFF_TAG_ImageLength);
+		if (imageLengthField == null)
+			throw new ImageReadException(
+					"Tiff: Missing Tag: TIFF_TAG_ImageLength");
+
+		int photometricInterpretation = getTagAsNumber(entries,
+				TIFF_TAG_PhotometricInterpretation).intValue();
+		int compression = getTagAsNumber(entries, TIFF_TAG_Compression)
+				.intValue();
+		int width = getTagAsNumber(entries, TIFF_TAG_ImageWidth).intValue();
+		int height = getTagAsNumber(entries, TIFF_TAG_ImageLength).intValue();
+		int samplesPerPixel = getTagAsNumber(entries, TIFF_TAG_SamplesPerPixel)
+				.intValue();
+		int bitsPerSample[] = getTagAsIntArray(entries, TIFF_TAG_BitsPerSample,
+				true);
+		int bitsPerPixel = getTagAsValueOrArraySum(entries,
+				TIFF_TAG_BitsPerSample);
+
+		int predictor;
+		{
+			dumpOptionalNumberTag(entries, TIFF_TAG_FillOrder);
+			dumpOptionalNumberTag(entries, TIFF_TAG_FreeByteCounts);
+			dumpOptionalNumberTag(entries, TIFF_TAG_FreeOffsets);
+			dumpOptionalNumberTag(entries, TIFF_TAG_Orientation);
+			dumpOptionalNumberTag(entries, TIFF_TAG_PlanarConfiguration);
+			predictor = dumpOptionalNumberTag(entries, TIFF_TAG_Predictor);
+		}
+
+		if (samplesPerPixel != bitsPerSample.length)
+			throw new ImageReadException("Tiff: fSamplesPerPixel ("
+					+ samplesPerPixel + ")!=fBitsPerSample.length ("
+					+ bitsPerSample.length + ")");
+
+		BufferedImage result = getBufferedImageFactory(params)
+				.getColorBufferedImage(width, height);
+
+		PhotometricInterpreter photometricInterpreter = getPhotometricInterpreter(
+				entries, photometricInterpretation, bitsPerPixel,
+				bitsPerSample, predictor, samplesPerPixel, width, height);
+
+		//			this.setDebug(false);
+
+		DataReader dataReader = getDataReader(entries, photometricInterpreter,
+				bitsPerPixel, bitsPerSample, predictor, samplesPerPixel, width,
+				height, compression);
+
+		dataReader.readImageData(result, byteSource);
+
+		photometricInterpreter.dumpstats();
+
+		return result;
+	}
+
+	private PhotometricInterpreter getPhotometricInterpreter(Vector entries,
+			int photometricInterpretation, int bitsPerPixel,
+			int bitsPerSample[], int predictor, int samplesPerPixel, int width,
+			int height) throws IOException, ImageReadException
+	{
+		switch (photometricInterpretation)
+		{
+			case 0 :
+			case 1 :
+				boolean invert = photometricInterpretation == 0;
+
+				return new PhotometricInterpreterBiLevel(bitsPerPixel,
+						samplesPerPixel, bitsPerSample, predictor, width,
+						height, invert);
+			case 3 : // Palette
+			{
+				int[] colorMap = getTagAsIntArray(entries, TIFF_TAG_ColorMap,
+						false);
+
+				int expected_colormap_size = 3 * (1 << bitsPerPixel);
+
+				if (colorMap.length != expected_colormap_size)
+					throw new ImageReadException("Tiff: fColorMap.length ("
+							+ colorMap.length + ")!=expected_colormap_size ("
+							+ expected_colormap_size + ")");
+
+				return new PhotometricInterpreterPalette(samplesPerPixel,
+						bitsPerSample, predictor, width, height, colorMap);
+			}
+			case 2 : // RGB
+				return new PhotometricInterpreterRGB(samplesPerPixel,
+						bitsPerSample, predictor, width, height);
+			case 5 : // CMYK
+				return new PhotometricInterpreterCMYK(samplesPerPixel,
+						bitsPerSample, predictor, width, height);
+			case 6 : // 
+			{
+				double[] fYCbCrCoefficients = getTagAsDoubleArray(entries,
+						TIFF_TAG_YCbCrCoefficients, false);
+				int[] fYCbCrPositioning = getTagAsIntArray(entries,
+						TIFF_TAG_YCbCrPositioning, false);
+				int[] fYCbCrSubSampling = getTagAsIntArray(entries,
+						TIFF_TAG_YCbCrSubSampling, false);
+				double[] referenceBlackWhite = getTagAsDoubleArray(entries,
+						TIFF_TAG_ReferenceBlackWhite, false);
+
+				return new PhotometricInterpreterYCbCr(fYCbCrCoefficients,
+						fYCbCrPositioning, fYCbCrSubSampling,
+						referenceBlackWhite, samplesPerPixel, bitsPerSample,
+						predictor, width, height);
+			}
+
+			case 8 :
+				return new PhotometricInterpreterCIELAB(samplesPerPixel,
+						bitsPerSample, predictor, width, height);
+
+			case 32844 :
+			case 32845 : {
+				boolean yonly = (photometricInterpretation == 32844);
+				return new PhotometricInterpreterLogLUV(samplesPerPixel,
+						bitsPerSample, predictor, width, height, yonly);
+			}
+
+			default :
+				throw new ImageReadException(
+						"TIFF: Unknown fPhotometricInterpretation: "
+								+ photometricInterpretation);
+		}
+	}
+
+	private DataReader getDataReader(Vector 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_TileOffsets,
+				false);
+		int[] tileByteCounts = getTagAsIntArray(entries,
+				TIFF_TAG_TileByteCounts, false);
+
+		int[] stripOffsets = getTagAsIntArray(entries, TIFF_TAG_StripOffsets,
+				false);
+		int[] stripByteCounts = getTagAsIntArray(entries,
+				TIFF_TAG_StripByteCounts, false);
+
+		TiffField tileWidthField = findField(entries, TIFF_TAG_TileWidth);
+		TiffField tileLengthField = findField(entries, TIFF_TAG_TileLength);
+
+		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_TileWidth)
+					.intValue();
+			int tileLength = getTagAsNumber(entries, TIFF_TAG_TileLength)
+					.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_TileWidth)
+					.intValue();
+			int tileLength = getTagAsNumber(entries, TIFF_TAG_TileLength)
+					.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_RowsPerStrip)
+					.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)
+			throws ImageWriteException, IOException
+	{
+		new TiffImageWriter().writeImage(src, os, params);
+	}
+
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/TiffImageParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReader.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReader.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReader.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReader.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,145 @@
+/*
+ * 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.cmc.sanselan.formats.tiff.datareaders;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.cmc.sanselan.ImageReadException;
+import org.cmc.sanselan.common.BinaryConstants;
+import org.cmc.sanselan.common.BitInputStream;
+import org.cmc.sanselan.common.PackBits;
+import org.cmc.sanselan.common.byteSources.ByteSource;
+import org.cmc.sanselan.common.mylzw.MyLZWDecompressor;
+import org.cmc.sanselan.formats.tiff.TiffConstants;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
+
+public abstract class DataReader implements TiffConstants, BinaryConstants
+{
+	protected final PhotometricInterpreter photometricInterpreter;
+	protected final int bitsPerSample[];
+	protected final int last[];
+
+	protected final int predictor;
+	protected final int samplesPerPixel;
+
+	protected final int byteOrder;
+
+	public DataReader(PhotometricInterpreter fPhotometricInterpreter,
+			int fBitsPerSample[], int Predictor, int fSamplesPerPixel,
+			int byteOrder)
+	{
+		this.photometricInterpreter = fPhotometricInterpreter;
+		this.bitsPerSample = fBitsPerSample;
+		this.samplesPerPixel = fSamplesPerPixel;
+		this.predictor = Predictor;
+		this.byteOrder = byteOrder;
+		last = new int[fSamplesPerPixel];
+	}
+
+	public abstract void readImageData(BufferedImage bi, ByteSource byteSource)
+			throws ImageReadException, IOException;
+
+	protected int[] getSamplesAsBytes(BitInputStream bis)
+			throws ImageReadException, IOException
+	{
+		int result[] = new int[bitsPerSample.length];
+		for (int i = 0; i < bitsPerSample.length; i++)
+		{
+			int bits = bitsPerSample[i];
+			int sample = bis.readBits(bits);
+			if (bits < 8)
+			{
+				int sign = sample & 1;
+				sample = sample << (8 - bits); // scale to byte.
+				if (sign > 0)
+					sample = sample | ((1 << (8 - bits)) - 1); // extend to byte
+			}
+			else if (bits > 8)
+			{
+				sample = sample >> (bits - 8); // extend to byte.
+			}
+			result[i] = sample;
+		}
+
+		return result;
+	}
+
+	protected int[] applyPredictor(int samples[], int x)
+	{
+		if (predictor == 2) // Horizontal differencing.
+		{
+			for (int i = 0; i < samples.length; i++)
+			{
+				if (x > 0)
+				{
+					samples[i] = 0xff & (samples[i] + last[i]);
+				}
+				last[i] = samples[i];
+			}
+		}
+
+		return samples;
+	}
+
+	private int count = 0;
+
+	protected byte[] decompress(byte compressed[], int compression,
+			int expected_size) throws ImageReadException, IOException
+	{
+		switch (compression)
+		{
+			case 1 : // None;
+				return compressed;
+			case 2 : // CCITT Group 3 1-Dimensional Modified Huffman run-length encoding.
+				throw new ImageReadException("Tiff: unknown compression: "
+						+ compression);
+			case TIFF_COMPRESSION_LZW : // LZW
+			{
+				InputStream is = new ByteArrayInputStream(compressed);
+
+				int LZWMinimumCodeSize = 8;
+
+				MyLZWDecompressor fMyLzwDecompressor = new MyLZWDecompressor(
+						LZWMinimumCodeSize, BYTE_ORDER_NETWORK);
+
+				fMyLzwDecompressor.setTiffLZWMode();
+
+				byte[] result = fMyLzwDecompressor
+						.decompress(is, expected_size);
+
+				return result;
+			}
+
+			case TIFF_COMPRESSION_PACKBITS : // Packbits
+			{
+				byte unpacked[] = new PackBits().decompress(compressed,
+						expected_size);
+				count++;
+
+				return unpacked;
+			}
+
+			default :
+				throw new ImageReadException("Tiff: unknown compression: "
+						+ compression);
+		}
+	}
+
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderStrips.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderStrips.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderStrips.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderStrips.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,115 @@
+/*
+ * 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.cmc.sanselan.formats.tiff.datareaders;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.cmc.sanselan.ImageReadException;
+import org.cmc.sanselan.common.BitInputStream;
+import org.cmc.sanselan.common.byteSources.ByteSource;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
+
+public 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)
+	{
+		super(fPhotometricInterpreter, fBitsPerSample, Predictor,
+				fSamplesPerPixel, byteOrder);
+
+		this.bitsPerPixel = fBitsPerPixel;
+		this.width = width;
+		this.height = height;
+		this.stripOffsets = fStripOffsets;
+		this.stripByteCounts = fStripByteCounts;
+		this.compression = fCompression;
+		this.rowsPerStrip = fRowsPerStrip;
+
+	}
+
+	public void interpretStrip(BufferedImage bi, byte bytes[],
+			int pixels_per_strip) throws ImageReadException, IOException
+	{
+		ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+		BitInputStream bis = new BitInputStream(bais);
+
+		for (int i = 0; i < pixels_per_strip; i++)
+		{
+			int samples[] = getSamplesAsBytes(bis);
+
+			if ((x < width) && (y < height))
+			{
+				samples = applyPredictor(samples, x);
+
+				photometricInterpreter.interpretPixel(bi, samples, x, y);
+			}
+
+			x++;
+			if (x >= width)
+			{
+				x = 0;
+				y++;
+				bis.flushCache();
+				if (y >= height)
+					break;
+			}
+		}
+	}
+
+	int x = 0, y = 0;
+
+	public void readImageData(BufferedImage bi, ByteSource byteSource)
+			throws ImageReadException, IOException
+	{
+
+		for (int strip = 0; strip < stripOffsets.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];
+
+			byte compressed[] = byteSource.getBlock(fStripOffset,
+					fStripByteCount);
+
+			byte decompressed[] = decompress(compressed, compression,
+					bytes_per_strip);
+
+			interpretStrip(bi, decompressed, pixels_per_strip);
+
+		}
+	}
+
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderStrips.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderTiled.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderTiled.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderTiled.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderTiled.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,134 @@
+/*
+ * 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.cmc.sanselan.formats.tiff.datareaders;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.cmc.sanselan.ImageReadException;
+import org.cmc.sanselan.common.BitInputStream;
+import org.cmc.sanselan.common.byteSources.ByteSource;
+import org.cmc.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
+
+public 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)
+	{
+		super(fPhotometricInterpreter, fBitsPerSample, Predictor,
+				fSamplesPerPixel, byteOrder);
+
+		this.tileOffsets = fTileOffsets;
+		this.tileByteCounts = fTileByteCounts;
+		this.tileWidth = TileWidth;
+		this.tileLength = TileLength;
+
+		this.bitsPerPixel = fBitsPerPixel;
+//		this.predictor = Predictor;
+		this.width = width;
+		this.height = height;
+		this.compression = fCompression;
+	}
+
+	private void interpretTile(BufferedImage bi, byte bytes[], int start_x,
+			int start_y) throws ImageReadException, IOException
+	{
+		ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+		BitInputStream bis = new BitInputStream(bais);
+
+		int pixels_per_tile = tileWidth * tileLength;
+
+		int tile_x = 0, tile_y = 0;
+
+		for (int i = 0; i < pixels_per_tile; i++)
+		{
+
+			int x = tile_x + start_x;
+			int y = tile_y + start_y;
+
+			int samples[] = getSamplesAsBytes(bis);
+
+			if ((x < width) && (y < height))
+			{
+				samples = applyPredictor(samples, x);
+				photometricInterpreter.interpretPixel(bi, samples, x, y);
+			}
+
+			tile_x++;
+
+			if (tile_x >= tileWidth)
+			{
+				tile_x = 0;
+				tile_y++;
+				bis.flushCache();
+				if (tile_y >= tileLength)
+					break;
+			}
+
+		}
+	}
+
+	public void readImageData(BufferedImage bi, ByteSource byteSource)
+			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 x = 0, y = 0;
+
+		for (int tile = 0; tile < tileOffsets.length; tile++)
+		{
+			int fTileOffset = tileOffsets[tile];
+			int fTileByteCount = tileByteCounts[tile];
+
+			byte compressed[] = byteSource
+					.getBlock(fTileOffset, fTileByteCount);
+
+			byte decompressed[] = decompress(compressed, compression,
+					bytes_per_tile);
+
+			interpretTile(bi, decompressed, x, y);
+
+			x += tileWidth;
+			if (x >= width)
+			{
+				x = 0;
+				y += tileLength;
+				if (y >= height)
+					break;
+			}
+
+		}
+	}
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/datareaders/DataReaderTiled.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,233 @@
+package org.cmc.sanselan.formats.tiff.debug;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.cmc.sanselan.formats.tiff.TiffField;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldType;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeASCII;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeByte;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeDouble;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeFloat;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeLong;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeRational;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeShort;
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldTypeUnknown;
+import org.cmc.sanselan.util.Debug;
+
+public class TiffConst
+{
+	public static class ExifDirectory
+	{
+		public final String name;
+
+		public ExifDirectory(final String name)
+		{
+			this.name = name;
+		}
+	}
+
+	public static final int TIFF_COMPRESSION_UNCOMPRESSED_1 = 1;
+	public static final int TIFF_COMPRESSION_UNCOMPRESSED = TIFF_COMPRESSION_UNCOMPRESSED_1;
+	public static final int TIFF_COMPRESSION_CCITT_1D = 2;
+	public static final int TIFF_COMPRESSION_CCITT_GROUP_3 = 3;
+	public static final int TIFF_COMPRESSION_CCITT_GROUP_4 = 4;
+	public static final int TIFF_COMPRESSION_LZW = 5;
+	public static final int TIFF_COMPRESSION_JPEG = 6;
+	public static final int TIFF_COMPRESSION_UNCOMPRESSED_2 = 32771;
+	public static final int TIFF_COMPRESSION_PACKBITS = 32773;
+
+	public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0;
+	public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1;
+	public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2;
+	public static final int PHOTOMETRIC_INTERPRETATION_RGB_PALETTE = 3;
+	public static final int PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK = 4;
+	public static final int PHOTOMETRIC_INTERPRETATION_CMYK = 5;
+	public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6;
+	public static final int PHOTOMETRIC_INTERPRETATION_CIELAB = 8;
+
+	public static final FieldTypeByte FIELD_TYPE_BYTE = new FieldTypeByte(1,
+			"Byte");
+
+	public static final FieldTypeASCII FIELD_TYPE_ASCII = new FieldTypeASCII(2,
+			"ASCII");
+
+	public static final FieldTypeShort FIELD_TYPE_SHORT = new FieldTypeShort(3,
+			"Short");
+
+	public static final FieldTypeLong FIELD_TYPE_LONG = new FieldTypeLong(4,
+			"Long");
+
+	public static final FieldTypeRational FIELD_TYPE_RATIONAL = new FieldTypeRational(
+			5, "Rational");
+
+	public static final FieldType FIELD_TYPE_SBYTE = new FieldTypeByte(6,
+			"SByte");
+	public static final FieldType FIELD_TYPE_UNDEFINED = new FieldTypeByte(7,
+			"Undefined");
+	public static final FieldType FIELD_TYPE_SSHORT = new FieldTypeShort(8,
+			"SShort");
+
+	public static final FieldType FIELD_TYPE_SLONG = new FieldTypeLong(9,
+			"SLong");
+
+	public static final FieldType FIELD_TYPE_SRATIONAL = new FieldTypeRational(
+			10, "SRational");
+
+	public static final FieldType FIELD_TYPE_FLOAT = new FieldTypeFloat();
+
+	public static final FieldType FIELD_TYPE_DOUBLE = new FieldTypeDouble();
+
+	public static final FieldType FIELD_TYPE_UNKNOWN = new FieldTypeUnknown();
+
+	public static final FieldType FIELD_TYPES[] = {
+			FIELD_TYPE_BYTE, FIELD_TYPE_ASCII, FIELD_TYPE_SHORT,
+			FIELD_TYPE_LONG, FIELD_TYPE_RATIONAL, FIELD_TYPE_SBYTE,
+			FIELD_TYPE_UNDEFINED, FIELD_TYPE_SSHORT, FIELD_TYPE_SLONG,
+			FIELD_TYPE_SRATIONAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE,
+	};
+
+	public static final FieldType FIELD_TYPE_ANY[] = FIELD_TYPES;
+
+	public static class TagInfo2
+	{
+		protected static final int LENGTH_UNKNOWN = -1;
+
+		public TagInfo2(String name, int tag, FieldType dataType, int length,
+				ExifDirectory exifDirectory)
+		{
+			this(name, tag, dataType, length);
+		}
+
+		public TagInfo2(String name, int tag, FieldType dataType, int length)
+		{
+			this(name, tag, new FieldType[]{
+				dataType
+			}, length, null);
+		}
+
+		public TagInfo2(String name, int tag, FieldType dataType,
+				String lengthDescription)
+		{
+			this(name, tag, new FieldType[]{
+				dataType
+			}, LENGTH_UNKNOWN, lengthDescription);
+		}
+
+		public TagInfo2(String name, int tag, FieldType dataTypes[], int length)
+		{
+			this(name, tag, dataTypes, length, null);
+		}
+
+		public TagInfo2(String name, int tag, FieldType dataTypes[],
+				String lengthDescription)
+		{
+			this(name, tag, dataTypes, LENGTH_UNKNOWN, lengthDescription);
+		}
+
+		public TagInfo2(String name, int tag, FieldType dataType)
+		{
+			this(name, tag, dataType, LENGTH_UNKNOWN);
+		}
+
+		public final String name;
+		public final int tag;
+		public final FieldType dataTypes[];
+		public final int length;
+		public final String lengthDescription;
+
+		public TagInfo2(String name, int tag, FieldType dataTypes[],
+				int length, String lengthDescription)
+		{
+			this.name = name;
+			this.tag = tag;
+			this.dataTypes = dataTypes;
+			this.length = length;
+			this.lengthDescription = lengthDescription;
+		}
+
+		public Object getValue(TiffField entry)
+		{
+			Object o = entry.fieldType.getSimpleValue(entry);
+			return o;
+		}
+
+		public String toString()
+		{
+			return "[TagInfo. tag: " + tag + ", name: " + name + "]";
+		}
+
+	}
+
+	public static class TagInfo2Date extends TagInfo2
+	{
+		public TagInfo2Date(String name, int tag, FieldType dataType, int length)
+		{
+			super(name, tag, dataType, length);
+		}
+		//
+		//		public TagInfo2Date(String name, int tag, FieldType dataType,
+		//				String lengthDescription)
+		//		{
+		//			this(name, tag, new FieldType[]{
+		//				dataType
+		//			}, LENGTH_UNKNOWN, lengthDescription);
+		//		}
+		//
+		//		public TagInfo2Date(String name, int tag, FieldType dataTypes[], int length)
+		//		{
+		//			this(name, tag, dataTypes, length, null);
+		//		}
+		//
+		//		public TagInfo2Date(String name, int tag, FieldType dataTypes[],
+		//				String lengthDescription)
+		//		{
+		//			this(name, tag, dataTypes, LENGTH_UNKNOWN, lengthDescription);
+		//		}
+		//
+		//		public TagInfo2Date(String name, int tag, FieldType dataType)
+		//		{
+		//			this(name, tag, dataType, LENGTH_UNKNOWN);
+		//		}
+
+		private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat(
+				"yyyy:MM:dd HH:mm:ss");
+		private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat(
+				"yyyy:MM:dd:HH:mm:ss");
+
+		public Object getValue(TiffField entry)
+		{
+			Object o = entry.fieldType.getSimpleValue(entry);
+
+			String s = (String) o;
+			try
+			{
+				Date date = DATE_FORMAT_1.parse(s);
+				return date;
+			}
+			catch (Exception e)
+			{
+				//		Debug.debug(e);
+			}
+			try
+			{
+				Date date = DATE_FORMAT_2.parse(s);
+				return date;
+			}
+			catch (Exception e)
+			{
+				Debug.debug(e);
+			}
+
+			return o;
+		}
+
+		public String toString()
+		{
+			return "[TagInfo. tag: " + tag + ", name: " + name + " (data)"
+					+ "]";
+		}
+	}
+
+}

Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst1.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst1.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst1.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst1.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,180 @@
+package org.cmc.sanselan.formats.tiff.debug;
+
+import org.cmc.sanselan.formats.tiff.fieldtypes.FieldType;
+
+public class TiffConst1 extends TiffConst
+{
+
+	public static final TagInfo2 TAG_INFO_NEW_SUB_FILE_TYPE = new TagInfo2(
+			"NewSubfileType", 254, FIELD_TYPE_LONG, 1);
+	public static final TagInfo2 TAG_INFO_SUB_FILE_TYPE = new TagInfo2(
+			"SubfileType", 255, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_IMAGE_WIDTH = new TagInfo2(
+			"ImageWidth", 256, new FieldType[]{
+					FIELD_TYPE_SHORT, FIELD_TYPE_LONG
+			}, 1);
+	public static final TagInfo2 TAG_INFO_IMAGE_LENGTH = new TagInfo2(
+			"ImageLength", 257, new FieldType[]{
+					FIELD_TYPE_SHORT, FIELD_TYPE_LONG
+			}, 1);
+	public static final TagInfo2 TAG_INFO_BITS_PER_SAMPLE = new TagInfo2(
+			"BitsPerSample", 258, FIELD_TYPE_SHORT, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_COMPRESSION = new TagInfo2(
+			"Compression", 259, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_PHOTOMETRIC_INTERPRETATION = new TagInfo2(
+			"PhotometricInterpretation", 262, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_THRESHHOLDING = new TagInfo2(
+			"Threshholding", 263, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_CELL_WIDTH = new TagInfo2(
+			"CellWidth", 264, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_CELL_LENGTH = new TagInfo2(
+			"CellLength", 265, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_FILL_ORDER = new TagInfo2(
+			"FillOrder", 266, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_DOCUMENT_NAME = new TagInfo2(
+			"DocumentName", 269, FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_IMAGE_DESCRIPTION = new TagInfo2(
+			"ImageDescription", 270, FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_MAKE = new TagInfo2("Make", 271,
+			FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_MODEL = new TagInfo2("Model", 272,
+			FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_STRIP_OFFSETS = new TagInfo2(
+			"StripOffsets", 273, new FieldType[]{
+					FIELD_TYPE_SHORT, FIELD_TYPE_LONG
+			}, "StripsPerImage");
+	public static final TagInfo2 TAG_INFO_ORIENTATION = new TagInfo2(
+			"Orientation", 274, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_SAMPLES_PER_PIXEL = new TagInfo2(
+			"SamplesPerPixel", 277, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_ROWS_PER_STRIP = new TagInfo2(
+			"RowsPerStrip", 278, new FieldType[]{
+					FIELD_TYPE_SHORT, FIELD_TYPE_LONG
+			}, 1);
+	public static final TagInfo2 TAG_INFO_STRIP_BYTE_COUNTS = new TagInfo2(
+			"StripByteCounts", 279, new FieldType[]{
+					FIELD_TYPE_LONG, FIELD_TYPE_SHORT
+			}, "StripsPerImage");
+	public static final TagInfo2 TAG_INFO_MIN_SAMPLE_VALUE = new TagInfo2(
+			"MinSampleValue", 280, FIELD_TYPE_SHORT, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_MAX_SAMPLE_VALUE = new TagInfo2(
+			"MaxSampleValue", 281, FIELD_TYPE_SHORT, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_X_RESOLUTION = new TagInfo2(
+			"XResolution", 282, FIELD_TYPE_RATIONAL, 1);
+	public static final TagInfo2 TAG_INFO_Y_RESOLUTION = new TagInfo2(
+			"YResolution", 283, FIELD_TYPE_RATIONAL, 1);
+	public static final TagInfo2 TAG_INFO_PLANAR_CONFIGURATION = new TagInfo2(
+			"PlanarConfiguration", 284, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_PAGE_NAME = new TagInfo2("PageName",
+			285, FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_X_POSITION = new TagInfo2(
+			"XPosition", 286, FIELD_TYPE_RATIONAL);
+	public static final TagInfo2 TAG_INFO_Y_POSITION = new TagInfo2(
+			"YPosition", 287, FIELD_TYPE_RATIONAL);
+	public static final TagInfo2 TAG_INFO_FREE_OFFSETS = new TagInfo2(
+			"FreeOffsets", 288, FIELD_TYPE_LONG);
+	public static final TagInfo2 TAG_INFO_FREE_BYTE_COUNTS = new TagInfo2(
+			"FreeByteCounts", 289, FIELD_TYPE_LONG);
+	public static final TagInfo2 TAG_INFO_GRAY_RESPONSE_UNIT = new TagInfo2(
+			"GrayResponseUnit", 290, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_GRAY_RESPONSE_CURVE = new TagInfo2(
+			"GrayResponseCurve", 291, FIELD_TYPE_SHORT, "2**BitsPerSample");
+	public static final TagInfo2 TAG_INFO_T4_OPTIONS = new TagInfo2(
+			"T4Options", 292, FIELD_TYPE_LONG, 1);
+	public static final TagInfo2 TAG_INFO_T6_OPTIONS = new TagInfo2(
+			"T6Options", 293, FIELD_TYPE_LONG, 1);
+	public static final TagInfo2 TAG_INFO_RESOLUTION_UNIT = new TagInfo2(
+			"ResolutionUnit", 296, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_PAGE_NUMBER = new TagInfo2(
+			"PageNumber", 297, FIELD_TYPE_SHORT, 2);
+	public static final TagInfo2 TAG_INFO_TRANSFER_FUNCTION = new TagInfo2(
+			"TransferFunction", 301, FIELD_TYPE_SHORT,
+			"{1 or SamplesPerPixel}* 2** BitsPerSample");
+	public static final TagInfo2 TAG_INFO_SOFTWARE = new TagInfo2("Software",
+			305, FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_DATE_TIME = new TagInfo2Date(
+			"DateTime", 306, FIELD_TYPE_ASCII, 20);
+	public static final TagInfo2 TAG_INFO_ARTIST = new TagInfo2("Artist", 315,
+			FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_HOST_COMPUTER = new TagInfo2(
+			"HostComputer", 316, FIELD_TYPE_ASCII);
+	public static final TagInfo2 TAG_INFO_PREDICTOR = new TagInfo2("Predictor",
+			317, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_WHITE_POINT = new TagInfo2(
+			"WhitePoint", 318, FIELD_TYPE_RATIONAL, 2);
+	public static final TagInfo2 TAG_INFO_PRIMARY_CHROMATICITIES = new TagInfo2(
+			"PrimaryChromaticities", 319, FIELD_TYPE_RATIONAL, 6);
+	public static final TagInfo2 TAG_INFO_COLOR_MAP = new TagInfo2("ColorMap",
+			320, FIELD_TYPE_SHORT, "3 * (2**BitsPerSample)");
+	public static final TagInfo2 TAG_INFO_HALFTONE_HINTS = new TagInfo2(
+			"HalftoneHints", 321, FIELD_TYPE_SHORT, 2);
+	public static final TagInfo2 TAG_INFO_TILE_WIDTH = new TagInfo2(
+			"TileWidth", 322, new FieldType[]{
+					FIELD_TYPE_SHORT, FIELD_TYPE_LONG
+			}, 1);
+	public static final TagInfo2 TAG_INFO_TILE_LENGTH = new TagInfo2(
+			"TileLength", 323, new FieldType[]{
+					FIELD_TYPE_SHORT, FIELD_TYPE_LONG
+			}, 1);
+	public static final TagInfo2 TAG_INFO_TILE_OFFSETS = new TagInfo2(
+			"TileOffsets", 324, FIELD_TYPE_LONG, "TilesPerImage");
+	public static final TagInfo2 TAG_INFO_TILE_BYTE_COUNTS = new TagInfo2(
+			"TileByteCounts", 325, new FieldType[]{
+					FIELD_TYPE_SHORT, FIELD_TYPE_LONG
+			}, "TilesPerImage");
+	public static final TagInfo2 TAG_INFO_INK_SET = new TagInfo2("InkSet", 332,
+			FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_INK_NAMES = new TagInfo2("InkNames",
+			333, FIELD_TYPE_ASCII,
+			"total number of characters in all ink name strings, including zeros");
+	public static final TagInfo2 TAG_INFO_NUMBER_OF_INKS = new TagInfo2(
+			"NumberOfInks", 334, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_DOT_RANGE = new TagInfo2("DotRange",
+			336, new FieldType[]{
+					FIELD_TYPE_BYTE, FIELD_TYPE_SHORT
+			}, "2, or 2* NumberOfInks");
+	public static final TagInfo2 TAG_INFO_TARGET_PRINTER = new TagInfo2(
+			"TargetPrinter", 337, FIELD_TYPE_ASCII, "any");
+	public static final TagInfo2 TAG_INFO_EXTRA_SAMPLES = new TagInfo2(
+			"ExtraSamples", 338, FIELD_TYPE_BYTE,
+			"number of extra components per pixel");
+	public static final TagInfo2 TAG_INFO_SAMPLE_FORMAT = new TagInfo2(
+			"SampleFormat", 339, FIELD_TYPE_SHORT, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_S_MIN_SAMPLE_VALUE = new TagInfo2(
+			"SMinSampleValue", 340, FIELD_TYPE_ANY, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_S_MAX_SAMPLE_VALUE = new TagInfo2(
+			"SMaxSampleValue", 341, FIELD_TYPE_ANY, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_TRANSFER_RANGE = new TagInfo2(
+			"TransferRange", 342, FIELD_TYPE_SHORT, 6);
+	public static final TagInfo2 TAG_INFO_JPEG_PROC = new TagInfo2("JPEGProc",
+			512, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_JPEG_INTERCHANGE_FORMAT = new TagInfo2(
+			"JPEGInterchangeFormat", 513, FIELD_TYPE_LONG, 1);
+	public static final TagInfo2 TAG_INFO_JPEG_INTERCHANGE_FORMAT_LENGTH = new TagInfo2(
+			"JPEGInterchangeFormatLength", 514, FIELD_TYPE_LONG, 1);
+	public static final TagInfo2 TAG_INFO_JPEG_RESTART_INTERVAL = new TagInfo2(
+			"JPEGRestartInterval", 515, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_JPEG_LOSSLESS_PREDICTORS = new TagInfo2(
+			"JPEGLosslessPredictors", 517, FIELD_TYPE_SHORT, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_JPEG_POINT_TRANSFORMS = new TagInfo2(
+			"JPEGPointTransforms", 518, FIELD_TYPE_SHORT, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_JPEG_Q_TABLES = new TagInfo2(
+			"JPEGQTables", 519, FIELD_TYPE_LONG, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_JPEG_DC_TABLES = new TagInfo2(
+			"JPEGDCTables", 520, FIELD_TYPE_LONG, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_JPEG_AC_TABLES = new TagInfo2(
+			"JPEGACTables", 521, FIELD_TYPE_LONG, "SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_YCBCR_COEFFICIENTS = new TagInfo2(
+			"YCbCrCoefficients", 529, FIELD_TYPE_RATIONAL, 3);
+	public static final TagInfo2 TAG_INFO_YCBCR_SUBSAMPLING = new TagInfo2(
+			"YCbCrSubSampling", 530, FIELD_TYPE_SHORT, 2);
+	public static final TagInfo2 TAG_INFO_YCBCR_POSITIONING = new TagInfo2(
+			"YCbCrPositioning", 531, FIELD_TYPE_SHORT, 1);
+	public static final TagInfo2 TAG_INFO_REFERENCE_BLACK_WHITE = new TagInfo2(
+			"ReferenceBlackWhite", 532, FIELD_TYPE_LONG, "2*SamplesPerPixel");
+	public static final TagInfo2 TAG_INFO_COPYRIGHT = new TagInfo2("Copyright",
+			33432, FIELD_TYPE_ASCII, "Any");
+
+}
+
+/**/

Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst1.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst2.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst2.java?rev=596008&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst2.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst2.java Sat Nov 17 13:58:22 2007
@@ -0,0 +1,131 @@
+package org.cmc.sanselan.formats.tiff.debug;
+
+public class TiffConst2
+{
+	/*
+
+	 between Exif Tags and Flashpix Property Set (1) (TIFF Tags)
+	 Exif FPX
+	 Tag Code Field Name
+	 Dec Hex
+	 Property Set Group Name
+	 ImageWidth 256 100 - - -
+	 ImageLength 257 101 - - -
+	 BitsPerSample 258 102 - - -
+	 Compression 259 103 - - -
+	 PhotometricInterpretation 262 106 - - -
+	 ImageDescription 270 10E Image Info Content Description Caption text
+	 Make 271 10F Image Info Camera Information Camera manufacturer name
+	 Model 272 110 Image Info Camera Information Camera model name
+	 StripOffsets 273 111 - - -
+	 Orientation 274 112 Transform - Spatial Orientation
+	 SamplesPerPixel 277 115 - - -
+	 RowsPerStrip 278 116 - - -
+	 StripByteCounts 279 117 - - -
+	 XResolution 282 11A Image Contents Primary description Default display width
+	 YResolution 283 11B Image Contents Primary description Default display height
+	 PlanarConfiguration 284 11C - - -
+	 ResolutionUnit 296 128 Image Contents Primary description Display height/width units
+	 TransferFunction 301 12D - - -
+	 Software 305 131 Image Info File source Software Name
+	 DateTime 306 132 Ignore Ignore Ignore
+	 Artist 315 13B Image Info Intellectual Property Authorship
+	 WhitePoint 318 13E - - -
+	 PrimaryChromaticities 319 13F - - -
+	 YCbCrCoefficients 529 211 - - -
+	 YCbCrSubSampling 530 212 - - -
+	 YCbCrPositioning 531 213 Ignore Ignore Ignore
+	 ReferenceBlackWhite 532 214 - - -
+	 Copyright 33432 8298 Image Info Intellectual Property Copyright message
+	 Exif IFD Pointer 34665 8769 - - -
+	 GPS Info IFD Pointer 34853 8825 - - -
+	 JEITA CP-3451
+	 - 129 -
+	 Table 50 Conversion between Exif Tags and Flashpix Property Set (2) (Exif Private Tags)
+	 Exif FPX
+	 Tag Code Field Name
+	 Dec Hex
+	 Property Set Group Name
+	 ExposureTime 33434 829A Image Info Per Picture Camera Setting Exposure time
+	 FNumber 33437 829D Image Info Per Picture Camera Setting F-number
+	 ExposureProgram 34850 8822 Image Info Per Picture Camera Setting Exposure program
+	 SpectralSensitivity 34852 8824 Image Info Digital Camera Characterization Spectral sensitivity
+	 ISOSpeedRatings 34855 8827 Image Info Digital Camera Characterization ISO speed ratings
+	 OECF 34857 8829 Image Info Digital Camera Characterization OECF
+	 ExifVersion 36864 9000 - - -
+	 DateTimeOriginal 36867 9003 Image Info Content Description Date of the original image
+	 Image Info Per Picture Camera Setting Capture date
+	 DateTimeDigitized 36868 9004 Summary Info - Create date/time
+	 ComponentsConfiguration 37121 9101 Ignore Ignore Ignore
+	 CompressedBitsPerPixel 37122 9102 Ignore Ignore Ignore
+	 ShutterSpeedValue 37377 9201 Image Info Per Picture Camera Setting Exposure time
+	 ApertureValue 37378 9202 Image Info Per Picture Camera Setting F-number
+	 BrightnessValue 37379 9203 Image Info Per Picture Camera Setting Brightness value
+	 ExposureBiasValue 37380 9204 Image Info Per Picture Camera Setting Exposure bias value
+	 MaxApertureValue 37381 9205 Image Info Per Picture Camera Setting Maximum aperture value
+	 SubjectDistance 37382 9206 Image Info Per Picture Camera Setting Subject distance
+	 MeteringMode 37383 9207 Image Info Per Picture Camera Setting Metering mode
+	 LightSource 37384 9208 Image Info Per Picture Camera Setting Scene illuminant
+	 Flash 37385 9209 Image Info Per Picture Camera Setting Flash
+	 Image Info Per Picture Camera Setting Flash return
+	 FocalLength 37386 920A Image Info Per Picture Camera Setting Focal length
+	 MakerNote 37500 927C - - -
+	 UserComment 37510 9286 Image Info Content description Content description note
+	 SubSecTime 37520 9290 Ignore Ignore Ignore
+	 SubSecTimeOriginal 37521 9291 Image Info Content Description Date of the original image
+	 Image Info Per Picture Camera Setting Capture date
+	 SubSecTimeDigitized 37522 9292 Summary Info - Create date/time
+	 FlashpixVersion 40960 A000 - - -
+	 ColorSpace 40961 A001 Image Contents resolution description Subimage color
+	 PixelXDimension 40962 A002 Image Contents Primary description Highest resolution width
+	 PixelYDimension 40963 A003 Image Contents Primary description Highest resolution height
+	 RelatedSoundFile 40964 A004 - - -
+	 FlashEnergy 41483 A20B Image Info Per Picture Camera Setting Flash Energy
+	 SpatialFrequencyResponse 41484 A20C Image Info Digital Camera Characterization Spatial frequency response
+	 FocalplaneXResolution 41486 A20E Image Info Digital Camera Characterization Focal plane X resolution
+	 FocalplaneYResolution 41487 A20F Image Info Digital Camera Characterization Focal plane Y resolution
+	 FocalplaneResolutionUnit 41488 A210 Image Info Digital Camera Characterization Focal plane resolution unit
+	 SubjectLocation 41492 A214 Image Info Per Picture Camera Setting Subject location
+	 ExposureIndex 41493 A215 Image Info Per Picture Camera Setting Exposure index
+	 SensingMethod 41495 A217 Image Info Digital Camera Characterization Sensing method
+	 FileSource 41728 A300 Image Info File Source File source
+	 SceneType 41729 A301 Image Info File Source Scene type
+	 CFAPattern 41730 A302 Image Info Digital Camera Characterization CFA pattern
+	 JEITA CP-3451
+	 - 130 -
+	 Table 51 Conversion between Exif Tags and Flashpix Property Set (3) (GPS Info Tags)
+	 Exif FPX
+	 Tag Code Field Name
+	 Dec Hex
+	 Property Set Group Name
+	 GPSVersionID 0 0 GPS Info extension - GPSVersionID
+	 GPSLatitudeRef 1 1 GPS Info extension - GPSLatitudeRef
+	 GPSLatitude 2 2 GPS Info extension - GPSLatitude
+	 GPSLongitudeRef 3 3 GPS Info extension - GPSLongitudeRef
+	 GPSLongitude 4 4 GPS Info extension - GPSLongitude
+	 GPSAltitudeRef 5 5 GPS Info extension - GPSAltitudeRef
+	 GPSAltitude 6 6 GPS Info extension - GPSAltitude
+	 GPSTimeStamp 7 7 GPS Info extension - GPSTimeStamp
+	 GPSSatellites 8 8 GPS Info extension - GPSSatellites
+	 GPSStatus 9 9 GPS Info extension - GPSStatus
+	 GPSMeasureMode 10 A GPS Info extension - GPSMeasureMode
+	 GPSDOP 11 B GPS Info extension - GPSDOP
+	 GPSSpeedRef 12 C GPS Info extension - GPSSpeedRef
+	 GPSSpeed 13 D GPS Info extension - GPSSpeed
+	 GPSTrackRef 14 E GPS Info extension - GPSTrackRef
+	 GPSTrack 15 F GPS Info extension - GPSTrack
+	 GPSImgDirectionRef 16 10 GPS Info extension - GPSImgDirectionRef
+	 GPSImgDirection 17 11 GPS Info extension - GPSImgDirection
+	 GPSMapDatum 18 12 GPS Info extension - GPSMapDatum
+	 GPSDestLatitudeRef 19 13 GPS Info extension - GPSDestLatitudeRef
+	 GPSDestLatitude 20 14 GPS Info extension - GPSDestLatitude
+	 GPSDestLongitudeRef 21 15 GPS Info extension - GPSDestLongitudeRef
+	 GPSDestLongitude 22 16 GPS Info extension - GPSDestLongitude
+	 GPSDestBearingRef 23 17 GPS Info extension - GPSDestBearingRef
+	 GPSDestBearing 24 18 GPS Info extension - GPSDestBearing
+	 GPSDestDistanceRef 25 19 GPS Info extension - GPSDestDistanceRef
+	 GPSDestDistance 26 1A GPS Info extension - GPSDestDistance
+
+	 /**/
+
+}

Propchange: incubator/sanselan/trunk/src/main/java/org/cmc/sanselan/formats/tiff/debug/TiffConst2.java
------------------------------------------------------------------------------
    svn:eol-style = native