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/07 07:29:07 UTC

svn commit: r609525 - in /incubator/sanselan/trunk/src: main/java/org/apache/sanselan/formats/jpeg/ main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ main/java/org/apache/sanselan/formats/tiff/ main/java/org/apache/sanselan/formats/tiff/constants...

Author: cmchen
Date: Sun Jan  6 23:29:04 2008
New Revision: 609525

URL: http://svn.apache.org/viewvc?rev=609525&view=rev
Log:
completely refactored the tiff write process.

Added:
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy2.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputItem.java   (with props)
Modified:
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.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/TagConstantsUtils.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagInfo.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/constants/TiffTagConstants.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldType.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/ImageDataInfo.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterBase.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossless.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputDirectory.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputField.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSet.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSummary.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/ExifRewriteTest.java

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=609525&r1=609524&r2=609525&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 Sun Jan  6 23:29:04 2008
@@ -24,6 +24,7 @@
 import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.sanselan.ImageFormat;
@@ -337,6 +338,11 @@
 		byte bytes[] = getExifRawData(byteSource);
 		if (null == bytes)
 			return null;
+
+		if(params==null)
+			params = new HashMap();
+		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/jpeg/exifRewrite/ExifRewriter.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/exifRewrite/ExifRewriter.java Sun Jan  6 23:29:04 2008
@@ -20,7 +20,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.sanselan.ImageReadException;
@@ -32,11 +31,9 @@
 import org.apache.sanselan.formats.jpeg.segments.GenericSegment;
 import org.apache.sanselan.formats.jpeg.segments.UnknownSegment;
 import org.apache.sanselan.formats.tiff.TiffImageMetadata;
-import org.apache.sanselan.formats.tiff.TiffImageParser;
-import org.apache.sanselan.formats.tiff.write.TiffImageWriterLossy;
 import org.apache.sanselan.formats.tiff.write.TiffImageWriterBase;
 import org.apache.sanselan.formats.tiff.write.TiffImageWriterLossless;
-import org.apache.sanselan.formats.tiff.write.TiffOutputDirectory;
+import org.apache.sanselan.formats.tiff.write.TiffImageWriterLossy2;
 import org.apache.sanselan.formats.tiff.write.TiffOutputSet;
 import org.apache.sanselan.util.Debug;
 
@@ -146,45 +143,45 @@
 		writeSegmentsReplacingExif(os, pieces, null);
 	}
 
-//	public void rewriteExifMetadataLossless(ByteSource byteSource,
-//			OutputStream os, Map params) throws ImageReadException,
-//			IOException, ImageWriteException
-//	{
-//
-//		rewriteExifMetadata(MODE_LOSSLESS, byteSource, os, params);
-//	}
-//
-//	public void rewriteExifMetadataLossy(ByteSource byteSource,
-//			OutputStream os, Map params) throws ImageReadException,
-//			IOException, ImageWriteException
-//	{
-//
-//		rewriteExifMetadata(MODE_LOSSY, byteSource, os, params);
-//	}
-//
-//	private void rewriteExifMetadata(int mode, ByteSource byteSource,
-//			OutputStream os, Map params) throws ImageReadException,
-//			IOException, ImageWriteException
-//	{
-//		JFIFPieces jfifPieces = analyzeJFIF(byteSource);
-//		ArrayList pieces = jfifPieces.pieces;
-//		GenericSegment exifSegment = jfifPieces.exifSegment;
-//
-//		byte exifBytes[] = exifSegment.bytes;
-//		exifBytes = getBytearrayTail("trimmed exif bytes", exifBytes, 6);
-//
-//		TiffImageMetadata exifMetadata = (TiffImageMetadata) new TiffImageParser()
-//				.getMetadata(exifBytes, params);
-//
-//		byte newBytes[] = writeExifSegment(mode, exifMetadata, true);
-//		//		exifSegment.bytes = newBytes;
-//
-//		//		ArrayList segments = readSegments(byteSource, null, false, true);
-//
-//		//		TiffImageMetadata exif = getExifMetadata(byteSource, params);
-//
-//		writeSegmentsReplacingExif(os, pieces, newBytes);
-//	}
+	//	public void rewriteExifMetadataLossless(ByteSource byteSource,
+	//			OutputStream os, Map params) throws ImageReadException,
+	//			IOException, ImageWriteException
+	//	{
+	//
+	//		rewriteExifMetadata(MODE_LOSSLESS, byteSource, os, params);
+	//	}
+	//
+	//	public void rewriteExifMetadataLossy(ByteSource byteSource,
+	//			OutputStream os, Map params) throws ImageReadException,
+	//			IOException, ImageWriteException
+	//	{
+	//
+	//		rewriteExifMetadata(MODE_LOSSY, byteSource, os, params);
+	//	}
+	//
+	//	private void rewriteExifMetadata(int mode, ByteSource byteSource,
+	//			OutputStream os, Map params) throws ImageReadException,
+	//			IOException, ImageWriteException
+	//	{
+	//		JFIFPieces jfifPieces = analyzeJFIF(byteSource);
+	//		ArrayList pieces = jfifPieces.pieces;
+	//		GenericSegment exifSegment = jfifPieces.exifSegment;
+	//
+	//		byte exifBytes[] = exifSegment.bytes;
+	//		exifBytes = getBytearrayTail("trimmed exif bytes", exifBytes, 6);
+	//
+	//		TiffImageMetadata exifMetadata = (TiffImageMetadata) new TiffImageParser()
+	//				.getMetadata(exifBytes, params);
+	//
+	//		byte newBytes[] = writeExifSegment(mode, exifMetadata, true);
+	//		//		exifSegment.bytes = newBytes;
+	//
+	//		//		ArrayList segments = readSegments(byteSource, null, false, true);
+	//
+	//		//		TiffImageMetadata exif = getExifMetadata(byteSource, params);
+	//
+	//		writeSegmentsReplacingExif(os, pieces, newBytes);
+	//	}
 
 	//	public void updateExifMetadata(ByteSource byteSource, OutputStream os,
 	//			ArrayList outputDirectories, Map params) throws ImageReadException,
@@ -227,7 +224,7 @@
 			OutputStream os, TiffOutputSet outputSet)
 			throws ImageReadException, IOException, ImageWriteException
 	{
-		List outputDirectories = outputSet.getDirectories();
+		//		List outputDirectories = outputSet.getDirectories();
 		JFIFPieces jfifPieces = analyzeJFIF(byteSource);
 		ArrayList pieces = jfifPieces.pieces;
 		GenericSegment exifSegment = jfifPieces.exifSegment;
@@ -235,10 +232,9 @@
 		byte exifBytes[] = exifSegment.bytes;
 		exifBytes = getBytearrayTail("trimmed exif bytes", exifBytes, 6);
 
-		int byteOrder = outputSet.byteOrder;
+		//		int byteOrder = outputSet.byteOrder;
 
-		byte newBytes[] = writeExifSegment(mode, byteOrder, outputDirectories,
-				true);
+		byte newBytes[] = writeExifSegment(mode, outputSet, true);
 
 		writeSegmentsReplacingExif(os, pieces, newBytes);
 	}
@@ -297,34 +293,35 @@
 		if (exif == null)
 			return null;
 
-		int byteOrder = exif.contents.header.byteOrder;
+		//		int byteOrder = exif.contents.header.byteOrder;
 
-		ArrayList outputDirectories = new ArrayList();
-		ArrayList srcDirs = exif.getDirectories();
-		for (int i = 0; i < srcDirs.size(); i++)
-		{
-			TiffImageMetadata.Directory srcDir = (TiffImageMetadata.Directory) srcDirs
-					.get(i);
-			//			Debug.debug("srcDir", srcDir);
-
-			//			TiffOutputDirectory outputDirectory = translate(srcDir, byteOrder);
-			TiffOutputDirectory outputDirectory = srcDir
-					.getOutputDirectory(byteOrder);
-			outputDirectories.add(outputDirectory);
-		}
+		TiffOutputSet outputSet = exif.getOutputSet();
+		//		TiffOutputSet outputSet = new TiffOutputSet(byteOrder);
+		////		ArrayList outputDirectories = new ArrayList();
+		//		ArrayList srcDirs = exif.getDirectories();
+		//		for (int i = 0; i < srcDirs.size(); i++)
+		//		{
+		//			TiffImageMetadata.Directory srcDir = (TiffImageMetadata.Directory) srcDirs
+		//					.get(i);
+		//			//			Debug.debug("srcDir", srcDir);
+		//
+		//			//			TiffOutputDirectory outputDirectory = translate(srcDir, byteOrder);
+		//			TiffOutputDirectory outputDirectory = srcDir
+		//					.getOutputDirectory(byteOrder);
+		//			outputSet.add(outputDirectory);
+		//		}
 
-		return writeExifSegment(mode, byteOrder, outputDirectories,
-				includeEXIFPrefix);
+		return writeExifSegment(mode, outputSet, includeEXIFPrefix);
 	}
 
-//	private byte[] writeExifSegment(int mode, TiffOutputSet outputSet,
-//			boolean includeEXIFPrefix) throws IOException, ImageWriteException
-//	{
-//		List outputDirectories = outputSet.getDirectories();
-//
-//		return writeExifSegment(mode, outputSet.byteOrder, outputDirectories,
-//				includeEXIFPrefix);
-//	}
+	//	private byte[] writeExifSegment(int mode, TiffOutputSet outputSet,
+	//			boolean includeEXIFPrefix) throws IOException, ImageWriteException
+	//	{
+	//		List outputDirectories = outputSet.getDirectories();
+	//
+	//		return writeExifSegment(mode, outputSet.byteOrder, outputDirectories,
+	//				includeEXIFPrefix);
+	//	}
 
 	//
 	//	public byte[] writeExifSegmentLossy(List outputDirectories, int byteOrder,
@@ -344,23 +341,23 @@
 	//				includeEXIFPrefix);
 	//	}
 
-	private byte[] writeExifSegment(int mode, int byteOrder,
-			List outputDirectories, boolean includeEXIFPrefix)
-			throws IOException, ImageWriteException
+	private byte[] writeExifSegment(int mode, TiffOutputSet outputSet,
+			boolean includeEXIFPrefix) throws IOException, ImageWriteException
 	{
 		TiffImageWriterBase writer;
 		if (mode == MODE_LOSSLESS)
-			writer = new TiffImageWriterLossless(byteOrder);
+			writer = new TiffImageWriterLossless(outputSet.byteOrder);
 		else if (mode == MODE_LOSSY)
-			writer = new TiffImageWriterLossy(byteOrder);
+			writer = new TiffImageWriterLossy2(outputSet.byteOrder);
+//		writer = new TiffImageWriterLossy(outputSet.byteOrder);
 		else
 			throw new ImageWriteException("Unknown TIFF write mode.");
 
-		return writeExifSegment(writer, outputDirectories, includeEXIFPrefix);
+		return writeExifSegment(writer, outputSet, includeEXIFPrefix);
 	}
 
 	private byte[] writeExifSegment(TiffImageWriterBase writer,
-			List outputDirectories, boolean includeEXIFPrefix)
+			TiffOutputSet outputSet, boolean includeEXIFPrefix)
 			throws IOException, ImageWriteException
 	{
 		ByteArrayOutputStream os = new ByteArrayOutputStream();
@@ -372,7 +369,7 @@
 			os.write(0);
 		}
 
-		writer.writeDirectories(os, outputDirectories);
+		writer.writeDirectories(os, outputSet);
 
 		return os.toByteArray();
 	}

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=609525&r1=609524&r2=609525&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 Sun Jan  6 23:29:04 2008
@@ -47,8 +47,8 @@
 			result.append("\t");
 			result.append("[" + entryOffset + "]: ");
 			result.append(entry.tagInfo.name);
-			result.append(" (" + entry.tagInfo.tag + ", 0x"
-					+ Integer.toHexString(entry.tagInfo.tag) + ")");
+			result.append(" (" + entry.tag + ", 0x"
+					+ Integer.toHexString(entry.tag) + ")");
 			result.append(", " + entry.fieldType.name);
 			result.append(", " + entry.fieldType.getRawBytes(entry).length);
 			result.append(": " + entry.getValueDescription());

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=609525&r1=609524&r2=609525&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 Sun Jan  6 23:29:04 2008
@@ -30,6 +30,7 @@
 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
 {
@@ -168,6 +169,10 @@
 
 		int valueLength = getValueLengthInBytes();
 
+//		Debug.debug("fillInValue tagInfo", tagInfo);
+//		Debug.debug("fillInValue valueOffset", valueOffset);
+//		Debug.debug("fillInValue valueLength", valueLength);
+		
 		byte bytes[] = byteSource.getBlock(valueOffset, valueLength);
 		setOversizeValue(bytes);
 	}

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=609525&r1=609524&r2=609525&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 Sun Jan  6 23:29:04 2008
@@ -26,6 +26,7 @@
 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
 {
@@ -133,6 +134,7 @@
 			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=609525&r1=609524&r2=609525&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 Sun Jan  6 23:29:04 2008
@@ -140,6 +140,7 @@
 
 //		Debug.debug("dirType", dirType);
 //		Debug.debug("offset", offset);
+//		Debug.debug("entryCount", entryCount);
 
 		for (int i = 0; i < entryCount; i++)
 		{
@@ -147,7 +148,8 @@
 			int type = read2Bytes("Type", is, "Not a Valid TIFF File");
 			int length = read4Bytes("Length", is, "Not a Valid TIFF File");
 
-//			Debug.debug("tag", tag);
+//			Debug.debug("tag", tag + " (0x" + Integer.toHexString(tag) + ")");
+			
 			
 			byte valueOffsetBytes[] = readByteArray("ValueOffset", 4, is,
 					"Not a Valid TIFF File");
@@ -480,6 +482,10 @@
 						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);

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagConstantsUtils.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagConstantsUtils.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagConstantsUtils.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagConstantsUtils.java Sun Jan  6 23:29:04 2008
@@ -16,7 +16,8 @@
  */
 package org.apache.sanselan.formats.tiff.constants;
 
-public class TagConstantsUtils
+
+public class TagConstantsUtils implements TiffDirectoryConstants
 {
 
 	public static TagInfo[] mergeTagLists(TagInfo lists[][])
@@ -35,6 +36,14 @@
 		}
 
 		return result;
+	}
+
+	public static ExifDirectoryType getExifDirectoryType(int type)
+	{
+		for (int i = 0; i < EXIF_DIRECTORIES.length; i++)
+			if (EXIF_DIRECTORIES[i].directoryType == type)
+				return EXIF_DIRECTORIES[i];
+		return EXIF_DIRECTORY_UNKNOWN;
 	}
 
 }

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagInfo.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagInfo.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagInfo.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TagInfo.java Sun Jan  6 23:29:04 2008
@@ -80,6 +80,11 @@
 		return o;
 	}
 
+	public String getDescription()
+	{
+		return tag + " (0x" + Integer.toHexString(tag) + ": " + name + "): ";
+	}
+
 	public String toString()
 	{
 		return "[TagInfo. tag: " + tag + " (0x" + Integer.toHexString(tag)

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=609525&r1=609524&r2=609525&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 Sun Jan  6 23:29:04 2008
@@ -78,4 +78,15 @@
 	public static final ExifDirectoryType EXIF_DIRECTORY_GPS = new ExifDirectoryType(
 			DIRECTORY_TYPE_GPS, "GPS IFD");
 
+	public static final ExifDirectoryType EXIF_DIRECTORIES[] = {
+			TIFF_DIRECTORY_ROOT, EXIF_DIRECTORY_EXIF_IFD, TIFF_DIRECTORY_IFD0,
+			EXIF_DIRECTORY_IFD0, TIFF_DIRECTORY_IFD1, EXIF_DIRECTORY_IFD1,
+			TIFF_DIRECTORY_IFD2, EXIF_DIRECTORY_IFD2,
+			EXIF_DIRECTORY_INTEROP_IFD, EXIF_DIRECTORY_MAKER_NOTES,
+			EXIF_DIRECTORY_SUB_IFD, EXIF_DIRECTORY_SUB_IFD1,
+			EXIF_DIRECTORY_SUB_IFD2,
+//EXIF_DIRECTORY_UNKNOWN,
+			EXIF_DIRECTORY_GPS,
+	};
+	
 }

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffTagConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffTagConstants.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffTagConstants.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffTagConstants.java Sun Jan  6 23:29:04 2008
@@ -78,7 +78,7 @@
 	public static final TagInfo TIFF_TAG_MODEL = new TagInfo("Model", 0x110,
 			FIELD_TYPE_DESCRIPTION_ASCII, -1, TIFF_DIRECTORY_ROOT);
 
-	public static final TagInfo TIFF_TAG_STRIP_OFFSETS = new TagInfo(
+	public static final TagInfo TIFF_TAG_STRIP_OFFSETS = new TagInfo.Offset(
 			"Strip Offsets", 0x111, FIELD_TYPE_DESCRIPTION_SHORT_OR_LONG, -1,
 			TIFF_DIRECTORY_ROOT);
 
@@ -199,7 +199,7 @@
 			"Tile Length", 0x143, FIELD_TYPE_DESCRIPTION_SHORT_OR_LONG, 1,
 			TIFF_DIRECTORY_ROOT);
 
-	public static final TagInfo TIFF_TAG_TILE_OFFSETS = new TagInfo(
+	public static final TagInfo TIFF_TAG_TILE_OFFSETS = new TagInfo.Offset(
 			"Tile Offsets", 0x144, FIELD_TYPE_DESCRIPTION_LONG, -1,
 			TIFF_DIRECTORY_ROOT);
 
@@ -248,7 +248,7 @@
 	public static final TagInfo TIFF_TAG_JPEG_PROC = new TagInfo("JPEGProc",
 			0x200, FIELD_TYPE_DESCRIPTION_SHORT, 1, TIFF_DIRECTORY_ROOT);
 
-	public static final TagInfo TIFF_TAG_JPEG_INTERCHANGE_FORMAT = new TagInfo(
+	public static final TagInfo TIFF_TAG_JPEG_INTERCHANGE_FORMAT = new TagInfo.Offset(
 			"JPEGInterchange Format", 0x201, FIELD_TYPE_DESCRIPTION_LONG, 1,
 			TIFF_DIRECTORY_ROOT);
 

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldType.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldType.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldType.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldType.java Sun Jan  6 23:29:04 2008
@@ -20,6 +20,7 @@
 import org.apache.sanselan.common.BinaryFileFunctions;
 import org.apache.sanselan.formats.tiff.TiffField;
 import org.apache.sanselan.formats.tiff.constants.TiffConstants;
+import org.apache.sanselan.formats.tiff.write.TiffImageWriterLossy;
 
 public abstract class FieldType extends BinaryFileFunctions
 		implements
@@ -38,6 +39,18 @@
 	public boolean isLocalValue(TiffField entry)
 	{
 		return ((length > 0) && ((length * entry.length) <= TIFF_ENTRY_MAX_VALUE_LENGTH));
+	}
+
+	//	public static final byte[] STUB_LOCAL_VALUE  = new byte[TIFF_ENTRY_MAX_VALUE_LENGTH];
+
+	public static final byte[] getStubLocalValue()
+	{
+		return new byte[TIFF_ENTRY_MAX_VALUE_LENGTH];
+	}
+
+	public final byte[] getStubValue(int count)
+	{
+		return new byte[count * length];
 	}
 
 	public String getDisplayValue(TiffField entry)

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/ImageDataInfo.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/ImageDataInfo.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/ImageDataInfo.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/ImageDataInfo.java Sun Jan  6 23:29:04 2008
@@ -23,6 +23,7 @@
 	public final int imageDataByteCounts[];
 	public final TiffOutputField imageDataOffsetsField;
 	public final int totalLength;
+	public final TiffOutputItem outputItems[];
 
 	public ImageDataInfo(final byte[][] imageData,
 			final int[] imageDataOffsets, final int[] imageDataByteCounts,
@@ -33,6 +34,15 @@
 		this.imageDataByteCounts = imageDataByteCounts;
 		this.imageDataOffsetsField = imageDataOffsetsField;
 		this.totalLength = totalLength;
+
+		outputItems = new TiffOutputItem[imageData.length];
+		for (int i = 0; i < imageData.length; i++)
+		{
+			TiffOutputItem item = new TiffOutputItem.Value("TIFF image data",
+					imageData[i]);
+			outputItems[i] = item;
+		}
+
 	}
 
 }

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=609525&r1=609524&r2=609525&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 Sun Jan  6 23:29:04 2008
@@ -21,13 +21,13 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.sanselan.ImageWriteException;
 import org.apache.sanselan.common.BinaryConstants;
 import org.apache.sanselan.formats.tiff.constants.TiffConstants;
-import org.apache.sanselan.util.Debug;
 
 public abstract class TiffImageWriterBase
 		implements
@@ -48,8 +48,16 @@
 		this.byteOrder = byteOrder;
 	}
 
-	public abstract void writeDirectories(OutputStream os, List directories)
-			throws IOException, ImageWriteException;
+	protected final static int imageDataPaddingLength(int dataLength)
+	{
+		return (4 - (dataLength % 4)) % 4;
+	}
+
+	public abstract void writeDirectories(OutputStream os,
+			TiffOutputSet outputSet) throws IOException, ImageWriteException;
+
+	//	public abstract void writeDirectories(OutputStream os, List directories)
+	//	throws IOException, ImageWriteException;
 
 	protected TiffOutputSummary validateDirectories(List directories)
 			throws ImageWriteException
@@ -115,25 +123,34 @@
 				//				dirMap.put(arg0, arg1)
 			}
 
+			HashSet fieldTags = new HashSet();
 			ArrayList fields = directory.getFields();
 			for (int j = 0; j < fields.size(); j++)
 			{
 				TiffOutputField field = (TiffOutputField) fields.get(j);
-				if (field.tagInfo.tag == EXIF_TAG_EXIF_OFFSET.tag)
+
+				Integer fieldKey = new Integer(field.tag);
+				if (fieldTags.contains(fieldKey))
+					throw new ImageWriteException("Tag ("
+							+ field.tagInfo.getDescription()
+							+ ") appears twice in directory.");
+				fieldTags.add(fieldKey);
+
+				if (field.tag == EXIF_TAG_EXIF_OFFSET.tag)
 				{
 					if (exifDirectoryOffsetField != null)
 						throw new ImageWriteException(
 								"More than one Exif directory offset field.");
 					exifDirectoryOffsetField = field;
 				}
-				else if (field.tagInfo.tag == EXIF_TAG_INTEROP_OFFSET.tag)
+				else if (field.tag == EXIF_TAG_INTEROP_OFFSET.tag)
 				{
 					if (interoperabilityDirectoryOffsetField != null)
 						throw new ImageWriteException(
 								"More than one Interoperability directory offset field.");
 					interoperabilityDirectoryOffsetField = field;
 				}
-				else if (field.tagInfo.tag == EXIF_TAG_GPSINFO.tag)
+				else if (field.tag == EXIF_TAG_GPSINFO.tag)
 				{
 					if (gpsDirectoryOffsetField != null)
 						throw new ImageWriteException(
@@ -169,8 +186,8 @@
 				.get(new Integer(DIRECTORY_TYPE_ROOT));
 
 		// prepare results
-		TiffOutputSummary result = new TiffOutputSummary(rootDirectory,
-				directoryTypeMap);
+		TiffOutputSummary result = new TiffOutputSummary(byteOrder,
+				rootDirectory, directoryTypeMap);
 
 		// make sure offset fields and offset'd directories correspond.
 		if (exifDirectory == null && exifDirectoryOffsetField != null)

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossless.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossless.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossless.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossless.java Sun Jan  6 23:29:04 2008
@@ -36,6 +36,12 @@
 		super(byteOrder);
 	}
 
+	public void writeDirectories(OutputStream os, TiffOutputSet outputSet)
+			throws IOException, ImageWriteException
+	{
+		writeDirectories(os, outputSet.getDirectories());
+	}
+
 	public void writeDirectories(OutputStream os, List directories)
 			throws IOException, ImageWriteException
 	{
@@ -52,27 +58,26 @@
 		//		PointerDirectoriesInfo pointerDirectoriesInfo = pointerDirectoriesStep(directories);
 		/**/
 
-//		//        final int imageDataOffset = 
-//		calculateLengthsAndOffsetsStep(directories);
-//
-//		/**/
-//
-//		updateDirectoryPointersStep(pointerDirectoriesInfo);
-//
-//		/**/
-//
-//		//        updateImageDataOffsetsStep(imageDataInfo, imageDataOffset);
-//		/**/
-//
-//		DebugOutputStream dos = null;
-//		//        DebugOutputStream dos = new DebugOutputStream(os);
-//		//        os = dos;
-//		BinaryOutputStream bos = new BinaryOutputStream(os, byteOrder);
-//
-//		/**/
-//
-//		writeStep(bos, directories, dos);
-
+		//		//        final int imageDataOffset = 
+		//		calculateLengthsAndOffsetsStep(directories);
+		//
+		//		/**/
+		//
+		//		updateDirectoryPointersStep(pointerDirectoriesInfo);
+		//
+		//		/**/
+		//
+		//		//        updateImageDataOffsetsStep(imageDataInfo, imageDataOffset);
+		//		/**/
+		//
+		//		DebugOutputStream dos = null;
+		//		//        DebugOutputStream dos = new DebugOutputStream(os);
+		//		//        os = dos;
+		//		BinaryOutputStream bos = new BinaryOutputStream(os, byteOrder);
+		//
+		//		/**/
+		//
+		//		writeStep(bos, directories, dos);
 	}
 
 	//    public byte[][] getStrips(BufferedImage src, int fSamplesPerPixel,

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy.java Sun Jan  6 23:29:04 2008
@@ -327,11 +327,6 @@
 		bos.write4Bytes(foffsetToFirstIFD);
 	}
 
-	static int imageDataPaddingLength(int dataLength)
-	{
-		return (4 - (dataLength % 4)) % 4;
-	}
-
 	private TiffOutputDirectory findDirectoryByType(List directories, int type)
 	{
 		for (int i = 0; i < directories.size(); i++)
@@ -344,6 +339,12 @@
 		return null;
 	}
 
+	public void writeDirectories(OutputStream os, TiffOutputSet outputSet)
+			throws IOException, ImageWriteException
+	{
+		writeDirectories(os, outputSet.getDirectories());
+	}
+
 	public void writeDirectories(OutputStream os, List directories)
 			throws IOException, ImageWriteException
 	{
@@ -403,7 +404,7 @@
 			// fields must be written in ascending order.
 			directory.sortFields();
 
-			directory.offset = offset;
+			directory.setOffset(offset);
 
 			if (directory.type == TiffDirectory.DIRECTORY_TYPE_EXIF
 					|| directory.type == TiffDirectory.DIRECTORY_TYPE_GPS

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy2.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy2.java?rev=609525&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy2.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy2.java Sun Jan  6 23:29:04 2008
@@ -0,0 +1,163 @@
+/*
+ * 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.write;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.common.BinaryOutputStream;
+import org.apache.sanselan.util.Debug;
+import org.apache.sanselan.util.DebugOutputStream;
+
+public class TiffImageWriterLossy2 extends TiffImageWriterBase
+{
+
+	public TiffImageWriterLossy2()
+	{
+	}
+
+	public TiffImageWriterLossy2(int byteOrder)
+	{
+		super(byteOrder);
+	}
+
+	public void writeDirectories(OutputStream os, TiffOutputSet outputSet)
+			throws IOException, ImageWriteException
+	{
+		List directories = outputSet.getDirectories();
+
+		TiffOutputSummary outputSummary = validateDirectories(directories);
+
+		List outputItems = outputSet.getOutputItems(outputSummary);
+
+		updateOffsetsStep(outputItems);
+
+		//		calculateLengthsAndOffsetsStep(directories);
+
+		outputSummary.updateOffsets(byteOrder);
+
+		//		DebugOutputStream dos = null;
+		BinaryOutputStream bos = new BinaryOutputStream(os, byteOrder);
+
+		writeStep(bos, outputItems
+		//				, dos
+		);
+
+	}
+
+	private void updateOffsetsStep(List outputItems) throws IOException,
+			ImageWriteException
+	{
+		int offset = TIFF_HEADER_SIZE;
+
+		for (int i = 0; i < outputItems.size(); i++)
+		{
+			TiffOutputItem outputItem = (TiffOutputItem) outputItems.get(i);
+
+			outputItem.setOffset(offset);
+			int itemLength = outputItem.getItemLength();
+			offset += itemLength;
+
+			int remainder = imageDataPaddingLength(itemLength);
+			offset += remainder;
+		}
+	}
+
+	private void writeStep(BinaryOutputStream bos, List outputItems
+	//	    		,
+	//	            DebugOutputStream dos
+	) throws IOException, ImageWriteException
+	{
+//		DebugOutputStream dos = new DebugOutputStream(bos);
+//		bos = new BinaryOutputStream(dos, byteOrder);
+
+		writeImageFileHeader(bos);
+
+		//	        long count, lastCount = 0;
+
+		//	        if (null != dos)
+		//	        {
+		//	            count = dos.count();
+		//	            Debug.debug("image header" + " start: " + lastCount + ", end: "
+		//	                    + dos.count() + ", length: " + (count - lastCount));
+		//	            lastCount = count;
+		//	        }
+
+		int offset = TIFF_HEADER_SIZE;
+//		if (dos.count() != offset)
+//			throw new ImageWriteException("output mismatch! dos.count(): "
+//					+ dos.count() + ", offset: " + offset);
+		for (int i = 0; i < outputItems.size(); i++)
+		{
+			TiffOutputItem outputItem = (TiffOutputItem) outputItems.get(i);
+
+//			if (outputItem.getOffset() != offset)
+//				throw new ImageWriteException("output mismatch! dos.count(): "
+//						+ dos.count() + ", offset: " + offset);
+
+//			Debug.debug("writing item", outputItem.getItemDescription()
+//					+ " (offset: " + offset + ")");
+
+			outputItem.writeItem(bos);
+
+			int length = outputItem.getItemLength();
+			offset += length;
+			int remainder = imageDataPaddingLength(length);
+			offset += remainder;
+			for (int j = 0; j < remainder; j++)
+				bos.write(0);
+
+//			if (dos.count() != offset)
+//				throw new ImageWriteException("output mismatch! dos.count(): "
+//						+ dos.count() + ", offset: " + offset);
+		}
+
+		//	        for (int i = 0; i < directories.size(); i++)
+		//	        {
+		//	            TiffOutputDirectory directory = (TiffOutputDirectory) directories
+		//	                    .get(i);
+		//	            directory.write(bos);
+		//	
+		//	            if (null != dos)
+		//	            {
+		//	                count = dos.count();
+		//	                Debug.debug("directory("
+		//	                        + TiffDirectory.description(directory.type) + ")"
+		//	                        + " start: " + lastCount + ", end: " + dos.count()
+		//	                        + ", length: " + (count - lastCount)
+		//	                        + ", expected length: " + directory.totalLength);
+		//	                lastCount = count;
+		//	            }
+		//	        }
+	}
+
+	private void writeImageFileHeader(BinaryOutputStream bos)
+			throws IOException, ImageWriteException
+	{
+		bos.write(byteOrder);
+		bos.write(byteOrder);
+
+		bos.write2Bytes(42); // tiffVersion
+
+		int foffsetToFirstIFD = TIFF_HEADER_SIZE;
+
+		bos.write4Bytes(foffsetToFirstIFD);
+	}
+
+}

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffImageWriterLossy2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputDirectory.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputDirectory.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputDirectory.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputDirectory.java Sun Jan  6 23:29:04 2008
@@ -20,22 +20,28 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.List;
 
 import org.apache.sanselan.ImageWriteException;
 import org.apache.sanselan.common.BinaryOutputStream;
 import org.apache.sanselan.formats.tiff.RawTiffImageData;
 import org.apache.sanselan.formats.tiff.TiffDirectory;
-import org.apache.sanselan.formats.tiff.constants.AllTagConstants;
+import org.apache.sanselan.formats.tiff.constants.TagConstantsUtils;
 import org.apache.sanselan.formats.tiff.constants.TagInfo;
-
-public final class TiffOutputDirectory implements AllTagConstants
+import org.apache.sanselan.formats.tiff.constants.TiffConstants;
+import org.apache.sanselan.formats.tiff.fieldtypes.FieldType;
+import org.apache.sanselan.util.Debug;
+
+public final class TiffOutputDirectory extends TiffOutputItem
+		implements
+			TiffConstants
 {
 	public static final int UNDEFINED_VALUE = -1;
 
 	public final int type;
 	public int internalLength = UNDEFINED_VALUE;
 	public int totalLength = UNDEFINED_VALUE;
-	public int offset = UNDEFINED_VALUE;
+	//	public int offset = UNDEFINED_VALUE;
 	private final ArrayList fields = new ArrayList();
 
 	private TiffOutputDirectory nextDirectory = null;
@@ -65,7 +71,7 @@
 		for (int i = 0; i < fields.size(); i++)
 		{
 			TiffOutputField field = (TiffOutputField) fields.get(i);
-			if (field.tagInfo.tag == tagInfo.tag)
+			if (field.tag == tagInfo.tag)
 				return field;
 		}
 		return null;
@@ -80,7 +86,7 @@
 				TiffOutputField e1 = (TiffOutputField) o1;
 				TiffOutputField e2 = (TiffOutputField) o2;
 
-				return e1.tagInfo.tag - e2.tagInfo.tag;
+				return e1.tag - e2.tag;
 			}
 		};
 		Collections.sort(fields, comparator);
@@ -99,9 +105,8 @@
 		tiffImageDataInfoStep(byteOrder);
 		jpegImageDataInfoStep(byteOrder);
 
-		internalLength = TiffImageWriterLossy.TIFF_ENTRY_LENGTH * fields.size()
-				+ TiffImageWriterLossy.TIFF_DIRECTORY_HEADER_LENGTH
-				+ TiffImageWriterLossy.TIFF_DIRECTORY_FOOTER_LENGTH;
+		internalLength = TIFF_ENTRY_LENGTH * fields.size()
+				+ TIFF_DIRECTORY_HEADER_LENGTH + TIFF_DIRECTORY_FOOTER_LENGTH;
 
 		totalLength = internalLength;
 
@@ -113,16 +118,16 @@
 
 		if (null != imageDataInfo)
 		{
-			int imageDataOffset = offset + totalLength;
+			int imageDataOffset = getOffset() + totalLength;
 			totalLength += imageDataInfo.totalLength;
 			updateTiffImageDataOffsetsStep(imageDataOffset, byteOrder);
 		}
 
 		if (null != rawJpegImageData)
 		{
-			int imageDataOffset = offset + totalLength;
+			int imageDataOffset = getOffset() + totalLength;
 			totalLength += rawJpegImageData.length;
-			totalLength += TiffImageWriterLossy
+			totalLength += TiffImageWriterBase
 					.imageDataPaddingLength(rawJpegImageData.length);
 			updateJpegImageDataOffsetsStep(imageDataOffset, byteOrder);
 		}
@@ -134,6 +139,67 @@
 		return TiffDirectory.description(type);
 	}
 
+	public void writeItem(BinaryOutputStream bos) throws IOException,
+			ImageWriteException
+	{
+		// Write Directory Field Count
+		bos.write2Bytes(fields.size()); // DirectoryFieldCount
+
+		// Write Fields
+		for (int i = 0; i < fields.size(); i++)
+		{
+			TiffOutputField field = (TiffOutputField) fields.get(i);
+			field.writeSimple(bos);
+
+//			Debug.debug("\t" + "writing field (" + field.tag + ", 0x" + Integer.toHexString(field.tag) + ")", field.tagInfo);
+//			if(field.tagInfo.isOffset())
+//				Debug.debug("\t\tOFFSET!", field.bytes);
+		}
+
+		int nextDirectoryOffset = 0;
+		if (nextDirectory != null)
+			nextDirectoryOffset = nextDirectory.getOffset();
+
+		// Write nextDirectoryOffset
+		if (nextDirectoryOffset == UNDEFINED_VALUE)
+			bos.write4Bytes(0);
+		else
+			bos.write4Bytes(nextDirectoryOffset);
+
+		//		// Write Seperate Values
+		//		for (int i = 0; i < fields.size(); i++)
+		//		{
+		//			TiffOutputField field = (TiffOutputField) fields.get(i);
+		//			field.writeSeperateValue(bos);
+		//		}
+
+		//		if (null != rawTiffImageData)
+		//		{
+		//			byte imageData[][] = rawTiffImageData.getRawImageData();
+		//			for (int i = 0; i < imageData.length; i++)
+		//			{
+		//				bos.writeByteArray(imageData[i]);
+		//				int imageDataByteCount = imageData[i].length;
+		//
+		//				int remainder = TiffImageWriterBase
+		//						.imageDataPaddingLength(imageDataByteCount);
+		//				for (int j = 0; j < remainder; j++)
+		//					bos.write(0);
+		//			}
+		//		}
+		//
+		//		if (null != rawJpegImageData)
+		//		{
+		//			//				byte imageData[][] = rawJpegImageData.getRawImageData();
+		//			bos.writeByteArray(rawJpegImageData);
+		//			int remainder = TiffImageWriterBase
+		//					.imageDataPaddingLength(rawJpegImageData.length);
+		//			for (int j = 0; j < remainder; j++)
+		//				bos.write(0);
+		//		}
+
+	}
+
 	public void write(BinaryOutputStream bos) throws IOException,
 			ImageWriteException
 	{
@@ -145,7 +211,7 @@
 		//			Debug.debug("dir write fields", fields.size());
 		//			Debug.debug("dir write nextDirectoryOffset", nextDirectoryOffset);
 
-		int nextSeperateValueOffset = offset + internalLength;
+		int nextSeperateValueOffset = getOffset() + internalLength;
 
 		//			Debug.debug("writing directory", description());
 		//			Debug.debug("writing fields.size()", fields.size());
@@ -163,9 +229,9 @@
 		}
 
 		int nextDirectoryOffset = 0;
-		if(nextDirectory!=null)
-			nextDirectoryOffset = nextDirectory.offset;
-		
+		if (nextDirectory != null)
+			nextDirectoryOffset = nextDirectory.getOffset();
+
 		// Write nextDirectoryOffset
 		if (nextDirectoryOffset == UNDEFINED_VALUE)
 			bos.write4Bytes(0);
@@ -187,7 +253,7 @@
 				bos.writeByteArray(imageData[i]);
 				int imageDataByteCount = imageData[i].length;
 
-				int remainder = TiffImageWriterLossy
+				int remainder = TiffImageWriterBase
 						.imageDataPaddingLength(imageDataByteCount);
 				for (int j = 0; j < remainder; j++)
 					bos.write(0);
@@ -198,7 +264,7 @@
 		{
 			//				byte imageData[][] = rawJpegImageData.getRawImageData();
 			bos.writeByteArray(rawJpegImageData);
-			int remainder = TiffImageWriterLossy
+			int remainder = TiffImageWriterBase
 					.imageDataPaddingLength(rawJpegImageData.length);
 			for (int j = 0; j < remainder; j++)
 				bos.write(0);
@@ -229,7 +295,7 @@
 			imageDataByteCounts[i] = imageData[i].length;
 			totalLength += imageData[i].length;
 
-			totalLength += TiffImageWriterLossy
+			totalLength += TiffImageWriterBase
 					.imageDataPaddingLength(imageData[i].length);
 		}
 
@@ -237,35 +303,32 @@
 		{
 			TagInfo tagInfo;
 			if (stripsNotTiles)
-				tagInfo = TiffImageWriterLossy.TIFF_TAG_STRIP_OFFSETS;
+				tagInfo = TIFF_TAG_STRIP_OFFSETS;
 			else
-				tagInfo = TiffImageWriterLossy.TIFF_TAG_TILE_OFFSETS;
+				tagInfo = TIFF_TAG_TILE_OFFSETS;
 
 			imageDataOffsetsField = findField(tagInfo);
 			if (null == imageDataOffsetsField)
 			{
 				imageDataOffsetsField = new TiffOutputField(tagInfo,
-						TiffImageWriterLossy.FIELD_TYPE_LONG,
-						imageDataOffsets.length,
-						TiffImageWriterLossy.FIELD_TYPE_LONG.writeData(
-								imageDataOffsets, byteOrder));
+						FIELD_TYPE_LONG, imageDataOffsets.length,
+						FIELD_TYPE_LONG.writeData(imageDataOffsets, byteOrder));
 				add(imageDataOffsetsField);
 			}
 		}
 		{
 			TagInfo tagInfo;
 			if (stripsNotTiles)
-				tagInfo = TiffImageWriterLossy.TIFF_TAG_STRIP_BYTE_COUNTS;
+				tagInfo = TIFF_TAG_STRIP_BYTE_COUNTS;
 			else
-				tagInfo = TiffImageWriterLossy.TIFF_TAG_TILE_BYTE_COUNTS;
+				tagInfo = TIFF_TAG_TILE_BYTE_COUNTS;
 
-			byte data[] = TiffImageWriterLossy.FIELD_TYPE_LONG.writeData(
-					imageDataByteCounts, byteOrder);
+			byte data[] = FIELD_TYPE_LONG.writeData(imageDataByteCounts,
+					byteOrder);
 
 			TiffOutputField field = findField(tagInfo);
 			if (null == field)
-				add(new TiffOutputField(tagInfo,
-						TiffImageWriterLossy.FIELD_TYPE_LONG,
+				add(new TiffOutputField(tagInfo, FIELD_TYPE_LONG,
 						imageDataByteCounts.length, data));
 			else
 				field.setData(data);
@@ -278,6 +341,18 @@
 
 	TiffOutputField jpegImageDataOffsetField = null;
 
+	private byte rawJpegImageData[] = null;
+
+	public void setRawJpegImageData(byte rawJpegImageData[])
+	{
+		this.rawJpegImageData = rawJpegImageData;
+	}
+
+	public byte[] getRawJpegImageData()
+	{
+		return rawJpegImageData;
+	}
+
 	private void jpegImageDataInfoStep(int byteOrder)
 	{
 		if (null == rawJpegImageData)
@@ -289,32 +364,26 @@
 
 		// Append imageData-related fields to first directory
 		{
-			TagInfo tagInfo = TiffImageWriterLossy.TIFF_TAG_JPEG_INTERCHANGE_FORMAT;
+			TagInfo tagInfo = TIFF_TAG_JPEG_INTERCHANGE_FORMAT;
 
 			jpegImageDataOffsetField = findField(tagInfo);
 			if (null == jpegImageDataOffsetField)
 			{
 				jpegImageDataOffsetField = new TiffOutputField(tagInfo,
-						TiffImageWriterLossy.FIELD_TYPE_LONG, 1,
-						TiffImageWriterLossy.FIELD_TYPE_LONG.writeData(
-								new int[]{
-									0,
-								}, byteOrder));
+						FIELD_TYPE_LONG, 1, FIELD_TYPE_LONG.getStubValue(1));
 				add(jpegImageDataOffsetField);
 			}
 		}
 		{
-			TagInfo tagInfo = TiffImageWriterLossy.TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH;
+			TagInfo tagInfo = TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH;
 
-			byte data[] = TiffImageWriterLossy.FIELD_TYPE_LONG.writeData(
-					new int[]{
-						rawJpegImageData.length,
-					}, byteOrder);
+			byte data[] = FIELD_TYPE_LONG.writeData(new int[]{
+				rawJpegImageData.length,
+			}, byteOrder);
 
 			TiffOutputField field = findField(tagInfo);
 			if (null == field)
-				add(new TiffOutputField(tagInfo,
-						TiffImageWriterLossy.FIELD_TYPE_LONG, 1, data));
+				add(new TiffOutputField(tagInfo, FIELD_TYPE_LONG, 1, data));
 			else
 				field.setData(data);
 		}
@@ -330,23 +399,21 @@
 			imageDataInfo.imageDataOffsets[i] = currentOffset;
 			currentOffset += imageDataInfo.imageDataByteCounts[i];
 
-			currentOffset += TiffImageWriterLossy
+			currentOffset += TiffImageWriterBase
 					.imageDataPaddingLength(imageDataInfo.imageDataByteCounts[i]);
 		}
 
-		imageDataInfo.imageDataOffsetsField
-				.setData(TiffImageWriterLossy.FIELD_TYPE_LONG.writeData(
-						imageDataInfo.imageDataOffsets, byteOrder));
+		imageDataInfo.imageDataOffsetsField.setData(FIELD_TYPE_LONG.writeData(
+				imageDataInfo.imageDataOffsets, byteOrder));
 		//			}
 	}
 
 	private void updateJpegImageDataOffsetsStep(final int imageDataOffset,
 			int byteOrder) throws IOException, ImageWriteException
 	{
-		jpegImageDataOffsetField.setData(TiffImageWriterLossy.FIELD_TYPE_LONG
-				.writeData(new int[]{
-					imageDataOffset,
-				}, byteOrder));
+		jpegImageDataOffsetField.setData(FIELD_TYPE_LONG.writeData(new int[]{
+			imageDataOffset,
+		}, byteOrder));
 	}
 
 	private RawTiffImageData rawTiffImageData = null;
@@ -361,18 +428,6 @@
 		return rawTiffImageData;
 	}
 
-	private byte rawJpegImageData[] = null;
-
-	public void setRawJpegImageData(byte rawJpegImageData[])
-	{
-		this.rawJpegImageData = rawJpegImageData;
-	}
-
-	public byte[] getRawJpegImageData()
-	{
-		return rawJpegImageData;
-	}
-
 	//		public static final Comparator COMPARATOR = new Comparator()
 	//		{
 	//			public int compare(Object o1, Object o2)
@@ -382,4 +437,170 @@
 	//				return e1.offset - e2.offset;
 	//			}
 	//		};
+
+	public int getItemLength()
+	{
+		return TIFF_ENTRY_LENGTH * fields.size() + TIFF_DIRECTORY_HEADER_LENGTH
+				+ TIFF_DIRECTORY_FOOTER_LENGTH;
+	}
+
+	public String getItemDescription()
+	{
+		ExifDirectoryType dirType = TagConstantsUtils
+				.getExifDirectoryType(type);
+		return "Directory: " + dirType.name + " (" + type + ")";
+	}
+
+	private void removeFieldIfPresent(TagInfo tagInfo)
+	{
+		TiffOutputField field = findField(tagInfo);
+		if (null != field)
+			fields.remove(field);
+	}
+
+	protected List getOutputItems(TiffOutputSummary outputSummary)
+	{
+		// first validate directory fields.
+		
+		removeFieldIfPresent(TIFF_TAG_JPEG_INTERCHANGE_FORMAT);
+		removeFieldIfPresent(TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
+
+		TiffOutputField jpegOffsetField = null;
+		if (null != rawJpegImageData)
+		{
+			jpegOffsetField = new TiffOutputField(
+					TIFF_TAG_JPEG_INTERCHANGE_FORMAT, FIELD_TYPE_LONG, 1,
+					FieldType.getStubLocalValue());
+			add(jpegOffsetField);
+
+			TiffOutputField jpegLengthField = new TiffOutputField(
+					TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, FIELD_TYPE_LONG,
+					1, FieldType.getStubLocalValue());
+			add(jpegLengthField);
+
+			byte lengthValue[] = FIELD_TYPE_LONG.writeData(new int[]{
+				rawJpegImageData.length,
+			}, outputSummary.byteOrder);
+			jpegLengthField.setData(lengthValue);
+		}
+
+		// --------------------------------------------------------------
+
+		removeFieldIfPresent(TIFF_TAG_STRIP_OFFSETS);
+		removeFieldIfPresent(TIFF_TAG_STRIP_BYTE_COUNTS);
+		removeFieldIfPresent(TIFF_TAG_TILE_OFFSETS);
+		removeFieldIfPresent(TIFF_TAG_TILE_BYTE_COUNTS);
+
+		TiffOutputField imageDataOffsetField;
+		ImageDataInfo imageDataInfo = null;
+		if (null != rawTiffImageData)
+		{
+			boolean stripsNotTiles = rawTiffImageData.stripsNotTiles();
+
+			TagInfo offsetTag;
+			TagInfo byteCountsTag;
+			if (stripsNotTiles)
+			{
+				offsetTag = TIFF_TAG_STRIP_OFFSETS;
+				byteCountsTag = TIFF_TAG_STRIP_BYTE_COUNTS;
+			}
+			else
+			{
+				offsetTag = TIFF_TAG_TILE_OFFSETS;
+				byteCountsTag = TIFF_TAG_TILE_BYTE_COUNTS;
+			}
+
+			// --------
+
+			byte imageData[][] = rawTiffImageData.getRawImageData();
+
+			int imageDataOffsets[] = null;
+			int imageDataByteCounts[] = null;
+			//			TiffOutputField imageDataOffsetsField = null;
+
+			imageDataOffsets = new int[imageData.length];
+			imageDataByteCounts = new int[imageData.length];
+
+			int imageDataTotalLength = 0;
+			for (int i = 0; i < imageData.length; i++)
+			{
+				imageDataByteCounts[i] = imageData[i].length;
+				imageDataTotalLength += imageData[i].length;
+
+				imageDataTotalLength += TiffImageWriterBase
+						.imageDataPaddingLength(imageData[i].length);
+			}
+
+			// --------
+
+			// Append imageData-related fields to first directory
+			imageDataOffsetField = new TiffOutputField(offsetTag,
+					FIELD_TYPE_LONG, imageDataOffsets.length, FIELD_TYPE_LONG
+							.writeData(imageDataOffsets,
+									outputSummary.byteOrder));
+			add(imageDataOffsetField);
+
+			// --------
+
+			byte data[] = FIELD_TYPE_LONG.writeData(imageDataByteCounts,
+					outputSummary.byteOrder);
+			TiffOutputField byteCountsField = new TiffOutputField(
+					byteCountsTag, FIELD_TYPE_LONG, imageDataByteCounts.length,
+					data);
+			add(byteCountsField);
+
+			// --------
+
+			imageDataInfo = new ImageDataInfo(imageData, imageDataOffsets,
+					imageDataByteCounts, imageDataOffsetField,
+					imageDataTotalLength);
+		}
+
+		// --------------------------------------------------------------
+
+		List result = new ArrayList();
+		result.add(this);
+		sortFields();
+
+		//		public void calculateLengths(int byteOrder) throws IOException,
+		//		ImageWriteException
+		//{
+		//	tiffImageDataInfoStep(byteOrder);
+		//	jpegImageDataInfoStep(byteOrder);
+		//
+		//	internalLength = TIFF_ENTRY_LENGTH * fields.size()
+		//			+ TIFF_DIRECTORY_HEADER_LENGTH
+		//			+ TIFF_DIRECTORY_FOOTER_LENGTH;
+		//
+		//	totalLength = internalLength;
+		//
+		for (int i = 0; i < fields.size(); i++)
+		{
+			TiffOutputField field = (TiffOutputField) fields.get(i);
+			if (field.isLocalValue())
+				continue;
+
+			TiffOutputItem item = field.getSeperateValue();
+			result.add(item);
+//			outputSummary.add(item, field);
+		}
+
+		if (null != imageDataInfo)
+		{
+			for (int i = 0; i < imageDataInfo.outputItems.length; i++)
+				result.add(imageDataInfo.outputItems[i]);
+
+			outputSummary.addTiffImageData(imageDataInfo);
+		}
+
+		if (null != rawJpegImageData)
+		{
+			TiffOutputItem item = new TiffOutputItem.Value("JPEG image data",
+					rawJpegImageData);
+			result.add(item);
+			outputSummary.add(item, jpegOffsetField);
+		}
+
+		return result;
+	}
 }

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputField.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputField.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputField.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputField.java Sun Jan  6 23:29:04 2008
@@ -33,6 +33,8 @@
 
 	public byte bytes[];
 
+	private final TiffOutputItem separateValueItem;
+
 	public TiffOutputField(TagInfo tagInfo, FieldType tagtype, int count,
 			byte bytes[])
 	{
@@ -47,9 +49,18 @@
 		this.fieldType = tagtype;
 		this.count = count;
 		this.bytes = bytes;
+
+		if (isLocalValue())
+			separateValueItem = null;
+		else
+		{
+			String name = "Field Seperate value (" + tagInfo.getDescription()
+					+ ")";
+			separateValueItem = new TiffOutputItem.Value(name, bytes);
+		}
 	}
 
-	public static final TiffOutputField createOffsetField(TagInfo tagInfo,
+	protected static final TiffOutputField createOffsetField(TagInfo tagInfo,
 			int byteOrder)
 	{
 		return new TiffOutputField(tagInfo, FIELD_TYPE_LONG, 1, FIELD_TYPE_LONG
@@ -58,7 +69,37 @@
 				}, byteOrder));
 	}
 
-	public int writeDirectoryEntry(BinaryOutputStream bos,
+	protected void writeSimple(BinaryOutputStream bos) throws IOException,
+			ImageWriteException
+	{
+		bos.write2Bytes(tag);
+		bos.write2Bytes(fieldType.type);
+		bos.write4Bytes(count);
+
+		if (isLocalValue())
+		{
+			if (separateValueItem != null)
+				throw new ImageWriteException("Unexpected separate value item.");
+
+			bos.writeByteArray(bytes);
+			int remainder = TIFF_ENTRY_MAX_VALUE_LENGTH - bytes.length;
+			for (int i = 0; i < remainder; i++)
+				bos.write(0);
+		}
+		else
+		{
+			if (separateValueItem == null)
+				throw new ImageWriteException("Missing separate value item.");
+
+			bos.write4Bytes(separateValueItem.getOffset());
+
+			int written = bytes.length;
+			if ((written % 2) != 0)
+				written++;
+		}
+	}
+
+	protected int writeDirectoryEntry(BinaryOutputStream bos,
 			int seperateValuesOffset) throws ImageWriteException, IOException
 	{
 		bos.write2Bytes(tag);
@@ -68,7 +109,7 @@
 		//		if(fieldType.type == TiffConstants.FIELD_TYPE_ASCII.type)
 		//			Debug.debug("ascii bytes", bytes);
 
-		if (bytes.length <= TIFF_ENTRY_MAX_VALUE_LENGTH)
+		if (isLocalValue())
 		{
 			bos.writeByteArray(bytes);
 			int remainder = TIFF_ENTRY_MAX_VALUE_LENGTH - bytes.length;
@@ -88,9 +129,19 @@
 		}
 	}
 
-	public int getSeperateValueLength()
+	protected TiffOutputItem getSeperateValue()
+	{
+		return separateValueItem;
+	}
+
+	protected boolean isLocalValue()
+	{
+		return bytes.length <= TIFF_ENTRY_MAX_VALUE_LENGTH;
+	}
+
+	protected int getSeperateValueLength()
 	{
-		if (bytes.length <= TIFF_ENTRY_MAX_VALUE_LENGTH)
+		if (isLocalValue())
 			return 0;
 		else
 		{
@@ -102,10 +153,10 @@
 		}
 	}
 
-	public int writeSeperateValue(BinaryOutputStream bos)
+	protected int writeSeperateValue(BinaryOutputStream bos)
 			throws ImageWriteException, IOException
 	{
-		if (bytes.length <= TIFF_ENTRY_MAX_VALUE_LENGTH)
+		if (isLocalValue())
 			return 0;
 
 		bos.writeByteArray(bytes);
@@ -119,9 +170,16 @@
 		return written;
 	}
 
-	public void setData(byte bytes[])
+	protected void setData(byte bytes[])
 	{
+		if (this.bytes.length != bytes.length)
+			throw new Error("Bug. Locality disrupted! "
+					+ tagInfo.getDescription());
+		boolean wasLocalValue = isLocalValue();
 		this.bytes = bytes;
+		if (isLocalValue() != wasLocalValue)
+			throw new Error("Bug. Locality disrupted! "
+					+ tagInfo.getDescription());
 	}
 
 	private static final String newline = System.getProperty("line.separator");

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputItem.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputItem.java?rev=609525&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputItem.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputItem.java Sun Jan  6 23:29:04 2008
@@ -0,0 +1,81 @@
+/*
+ * 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.write;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.common.BinaryOutputStream;
+import org.apache.sanselan.formats.tiff.RawTiffImageData;
+import org.apache.sanselan.formats.tiff.TiffDirectory;
+import org.apache.sanselan.formats.tiff.constants.AllTagConstants;
+import org.apache.sanselan.formats.tiff.constants.TagInfo;
+
+ abstract class TiffOutputItem implements AllTagConstants
+{
+	public static final int UNDEFINED_VALUE = -1;
+
+	private int offset = UNDEFINED_VALUE;
+
+	protected int getOffset()
+	{
+		return offset;
+	}
+
+	protected void setOffset(int offset)
+	{
+		this.offset = offset;
+	}
+
+	public abstract int getItemLength();
+
+	public abstract String getItemDescription();
+
+	public abstract void writeItem(BinaryOutputStream bos) throws IOException,
+			ImageWriteException;
+
+	public static class Value extends TiffOutputItem
+	{
+		private final byte bytes[];
+		private final String name;
+
+		public Value(final String name, final byte[] bytes)
+		{
+			this.name = name;
+			this.bytes = bytes;
+		}
+
+		public int getItemLength()
+		{
+			return bytes.length;
+		}
+
+		public String getItemDescription()
+		{
+			return name;
+		}
+
+		public void writeItem(BinaryOutputStream bos) throws IOException,
+				ImageWriteException
+		{
+			bos.write(bytes);
+		}
+	}
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputItem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSet.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSet.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSet.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSet.java Sun Jan  6 23:29:04 2008
@@ -34,6 +34,21 @@
 		this.byteOrder = byteOrder;
 	}
 
+	protected List getOutputItems(TiffOutputSummary outputSummary)
+	{
+		List result = new ArrayList();
+
+		for (int i = 0; i < directories.size(); i++)
+		{
+			TiffOutputDirectory directory = (TiffOutputDirectory) directories
+					.get(i);
+
+			result.addAll(directory.getOutputItems(outputSummary));
+		}
+
+		return result;
+	}
+
 	public void addDirectory(TiffOutputDirectory directory)
 			throws ImageWriteException
 	{

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSummary.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSummary.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSummary.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/write/TiffOutputSummary.java Sun Jan  6 23:29:04 2008
@@ -16,83 +16,82 @@
  */
 package org.apache.sanselan.formats.tiff.write;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.sanselan.ImageWriteException;
 import org.apache.sanselan.formats.tiff.constants.TiffConstants;
 
 class TiffOutputSummary implements TiffConstants
 {
+	public final int byteOrder;
 	public final TiffOutputDirectory rootDirectory;
 	public final Map directoryTypeMap;
 
-	public TiffOutputSummary(final TiffOutputDirectory rootDirectory,
-			final Map directoryTypeMap)
+	public TiffOutputSummary(final int byteOrder,
+			final TiffOutputDirectory rootDirectory, final Map directoryTypeMap)
 	{
+		this.byteOrder = byteOrder;
 		this.rootDirectory = rootDirectory;
 		this.directoryTypeMap = directoryTypeMap;
 	}
 
-	private static class Offset
+	private static class OffsetItem
 	{
-		public final TiffOutputDirectory directory;
-		public final TiffOutputField directoryOffsetField;
+		public final TiffOutputItem item;
+		public final TiffOutputField itemOffsetField;
 
-		public Offset(final TiffOutputDirectory directory,
-				final TiffOutputField directoryOffsetField)
+		public OffsetItem(final TiffOutputItem item,
+				final TiffOutputField itemOffsetField)
 		{
 			super();
-			this.directoryOffsetField = directoryOffsetField;
-			this.directory = directory;
+			this.itemOffsetField = itemOffsetField;
+			this.item = item;
 		}
 	}
 
-	private List offsets = new ArrayList();
+	private List offsetItems = new ArrayList();
 
-	public void add(final TiffOutputDirectory directory,
-			final TiffOutputField directoryOffsetField)
+	public void add(final TiffOutputItem item,
+			final TiffOutputField itemOffsetField)
 	{
-		offsets.add(new Offset(directory, directoryOffsetField));
+		offsetItems.add(new OffsetItem(item, itemOffsetField));
 	}
 
 	public void updateOffsets(int byteOrder)
 	{
-		for (int i = 0; i < offsets.size(); i++)
+		for (int i = 0; i < offsetItems.size(); i++)
 		{
-			Offset offset = (Offset) offsets.get(i);
+			OffsetItem offset = (OffsetItem) offsetItems.get(i);
 
 			byte value[] = FIELD_TYPE_LONG.writeData(new int[]{
-				offset.directory.offset,
+				offset.item.getOffset(),
 			}, byteOrder);
-			offset.directoryOffsetField.setData(value);
+			offset.itemOffsetField.setData(value);
+		}
+
+		for (int i = 0; i < imageDataItems.size(); i++)
+		{
+			ImageDataInfo imageDataInfo = (ImageDataInfo) imageDataItems.get(i);
+
+			for (int j = 0; j < imageDataInfo.imageData.length; j++)
+			{
+				TiffOutputItem item = imageDataInfo.outputItems[j];
+				imageDataInfo.imageDataOffsets[j] = item.getOffset();
+			}
+
+			imageDataInfo.imageDataOffsetsField.setData(FIELD_TYPE_LONG
+					.writeData(imageDataInfo.imageDataOffsets, byteOrder));
 		}
 	}
 
-	//	public PointerDirectoriesInfo(
-	//){}
-	//	
-	//	public final TiffOutputField exifDirectoryOffsetField;
-	//	public final TiffOutputDirectory exifDirectory;
-	//	public final TiffOutputField gpsDirectoryOffsetField;
-	//	public final TiffOutputDirectory gpsDirectory;
-	//	public final TiffOutputField interoperabilityDirectoryOffsetField;
-	//	public final TiffOutputDirectory interoperabilityDirectory;
-	//
-	//	public PointerDirectoriesInfo(
-	//			final TiffOutputField exifDirectoryOffsetField,
-	//			final TiffOutputDirectory exifDirectory,
-	//			final TiffOutputField gpsDirectoryOffsetField,
-	//			final TiffOutputDirectory gpsDirectory,
-	//			final TiffOutputField interoperabilityDirectoryOffsetField,
-	//			final TiffOutputDirectory interoperabilityDirectory)
-	//	{
-	//		this.exifDirectoryOffsetField = exifDirectoryOffsetField;
-	//		this.exifDirectory = exifDirectory;
-	//		this.gpsDirectoryOffsetField = gpsDirectoryOffsetField;
-	//		this.gpsDirectory = gpsDirectory;
-	//		this.interoperabilityDirectoryOffsetField = interoperabilityDirectoryOffsetField;
-	//		this.interoperabilityDirectory = interoperabilityDirectory;
-	//	}
+	private List imageDataItems = new ArrayList();
+
+	public void addTiffImageData(final ImageDataInfo imageDataInfo)
+	{
+		offsetItems.add(imageDataInfo);
+	}
 
 }

Modified: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/ExifRewriteTest.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/ExifRewriteTest.java?rev=609525&r1=609524&r2=609525&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/ExifRewriteTest.java (original)
+++ incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/ExifRewriteTest.java Sun Jan  6 23:29:04 2008
@@ -90,7 +90,7 @@
 				IOException, ImageWriteException;
 	}
 
-	public void rewrite(Rewriter rewriter) throws IOException,
+	public void rewrite(Rewriter rewriter, String name) throws IOException,
 			ImageReadException, ImageWriteException
 	{
 		List images = getImagesWithExifData();
@@ -115,12 +115,12 @@
 			//			Photoshop photoshop = metadata.getPhotoshop();
 
 			TiffOutputSet outputSet = oldExifMetadata.getOutputSet();
-//			outputSet.dump();
+			//			outputSet.dump();
 
 			ByteArrayOutputStream baos = new ByteArrayOutputStream();
 			rewriter.rewrite(byteSource, baos, outputSet);
 			byte bytes[] = baos.toByteArray();
-			File tempFile = File.createTempFile("test", ".jpg");
+			File tempFile = File.createTempFile(name + "_", ".jpg");
 			Debug.debug("tempFile", tempFile);
 			//			tempFile.deleteOnExit();
 			IOUtils.writeToFile(bytes, tempFile);
@@ -135,7 +135,7 @@
 			assertNotNull(newMetadata);
 			TiffImageMetadata newExifMetadata = newMetadata.getExif();
 			assertNotNull(newExifMetadata);
-//			newMetadata.dump();
+			//			newMetadata.dump();
 
 			compare(oldExifMetadata, newExifMetadata);
 		}
@@ -155,25 +155,42 @@
 			}
 		};
 
-		rewrite(rewriter);
+		rewrite(rewriter, "lossy");
 	}
 
-//	public void testRewriteLossless() throws IOException, ImageReadException,
-//			ImageWriteException
-//	{
-//		Rewriter rewriter = new Rewriter()
-//		{
-//			public void rewrite(ByteSource byteSource, OutputStream os,
-//					TiffOutputSet outputSet) throws ImageReadException,
-//					IOException, ImageWriteException
-//			{
-//				new ExifRewriter().updateExifMetadataLossless(byteSource, os,
-//						outputSet);
-//			}
-//		};
-//
-//		rewrite(rewriter);
-//	}
+	//	public void testRewriteLossy2() throws IOException, ImageReadException,
+	//			ImageWriteException
+	//	{
+	//		Rewriter rewriter = new Rewriter()
+	//		{
+	//			public void rewrite(ByteSource byteSource, OutputStream os,
+	//					TiffOutputSet outputSet) throws ImageReadException,
+	//					IOException, ImageWriteException
+	//			{
+	//				new ExifRewriter().updateExifMetadataLossy2(byteSource, os,
+	//						outputSet);
+	//			}
+	//		};
+	//
+	//		rewrite(rewriter, "lossy2");
+	//	}
+
+	//	public void testRewriteLossless() throws IOException, ImageReadException,
+	//			ImageWriteException
+	//	{
+	//		Rewriter rewriter = new Rewriter()
+	//		{
+	//			public void rewrite(ByteSource byteSource, OutputStream os,
+	//					TiffOutputSet outputSet) throws ImageReadException,
+	//					IOException, ImageWriteException
+	//			{
+	//				new ExifRewriter().updateExifMetadataLossless(byteSource, os,
+	//						outputSet);
+	//			}
+	//		};
+	//
+	//		rewrite(rewriter, "lossless");
+	//	}
 
 	private Hashtable makeDirectoryMap(ArrayList directories)
 	{
@@ -224,7 +241,7 @@
 		{
 			Integer dirType = (Integer) oldDirectoryTypes.get(i);
 
-			//			Debug.debug("dirType", dirType);
+//			Debug.debug("dirType", dirType);
 
 			TiffImageMetadata.Directory oldDirectory = (TiffImageMetadata.Directory) oldDirectoryMap
 					.get(dirType);
@@ -236,11 +253,19 @@
 			ArrayList oldItems = oldDirectory.getItems();
 			ArrayList newItems = newDirectory.getItems();
 
+//			Debug.debug("oldItems.size()", oldItems.size());
+//			Debug.debug("newItems.size()", newItems.size());
+//			dump("oldItems", oldItems);
+//			dump("newItems", newItems);
+
 			assertTrue(oldItems.size() == newItems.size());
 
 			Hashtable oldFieldMap = makeFieldMap(oldItems);
 			Hashtable newFieldMap = makeFieldMap(newItems);
 
+			//			Debug.debug("oldItems.size()", oldItems.size());
+			//			Debug.debug("oldFieldMap.keySet().size()", oldFieldMap.keySet().size());
+
 			assertEquals(oldItems.size(), oldFieldMap.keySet().size());
 			//			assertEquals(oldFieldMap.keySet(), newFieldMap.keySet());
 			//			assertEquals(oldFieldMap.keySet(), newFieldMap.keySet());
@@ -258,7 +283,9 @@
 				TiffField oldField = (TiffField) oldFieldMap.get(fieldTag);
 				TiffField newField = (TiffField) newFieldMap.get(fieldTag);
 
-				//				Debug.debug("fieldTag", fieldTag);
+//				Debug.debug("fieldTag", fieldTag);
+//				Debug.debug("oldField", oldField);
+//				Debug.debug("fieldTag", fieldTag);
 
 				//				fieldTag.
 				assertNotNull(oldField);
@@ -296,5 +323,13 @@
 		assertEquals(a.length, b.length);
 		for (int i = 0; i < a.length; i++)
 			assertEquals(a[i], b[i]);
+	}
+
+	private void dump(String name, List list)
+	{
+		Debug.debug(name, list.size());
+		for (int i = 0; i < list.size(); i++)
+			Debug.debug("\t" + list.get(i));
+		Debug.debug();
 	}
 }