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/08/24 20:47:31 UTC

svn commit: r688558 [1/2] - in /incubator/sanselan/trunk: ./ src/main/java/org/apache/sanselan/common/ src/main/java/org/apache/sanselan/formats/jpeg/ src/main/java/org/apache/sanselan/formats/jpeg/iptc/ src/main/java/org/apache/sanselan/formats/jpeg/s...

Author: cmchen
Date: Sun Aug 24 13:47:30 2008
New Revision: 688558

URL: http://svn.apache.org/viewvc?rev=688558&view=rev
Log:
* Started shift towards moving field-level parsing into BinaryInputStream and BinaryOutputStream.
 * Fixed a png unit test that used a piece of Java 1.6 syntax.
 * Added unit tests around the new IPTC functionality.
 * Added IPTC remove/update/insert functionality.
 * Rewrote the IPTC parsing support.

Added:
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java   (with props)
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java   (with props)
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/IptcBaseTest.java   (with props)
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/IptcDumpTest.java   (with props)
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/IptcUpdateTest.java   (with props)
Removed:
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/IptcElement.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/IptcType.java
Modified:
    incubator/sanselan/trunk/RELEASE_NOTES
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegRewriter.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/fieldtypes/FieldTypeASCII.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/SanselanTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/JpegReadTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpRewriteTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/png/PngBaseTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/png/PngMultipleRoundtripTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpUpdateTest.java

Modified: incubator/sanselan/trunk/RELEASE_NOTES
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/RELEASE_NOTES?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/RELEASE_NOTES (original)
+++ incubator/sanselan/trunk/RELEASE_NOTES Sun Aug 24 13:47:30 2008
@@ -15,6 +15,11 @@
 Release 0.95
 ------------
 
+ * Started shift towards moving field-level parsing into BinaryInputStream and BinaryOutputStream.
+ * Fixed a png unit test that used a piece of Java 1.6 syntax.
+ * Added unit tests around the new IPTC functionality.
+ * Added IPTC remove/update/insert functionality.
+ * Rewrote the IPTC parsing support.  
  * Added improved support for reading and writing iTXt, tEXt, zTXt Png chunks.
  	Added a unit test that demonstrates the feature.
  * Found a new regression wherein DeflaterOutputStream needs to be closed.

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java Sun Aug 24 13:47:30 2008
@@ -445,8 +445,6 @@
 		int byte0 = 0xff & bytes[index + 0];
 		int byte1 = 0xff & bytes[index + 1];
 
-		// return convert2BytesToShort(name, byte0, byte1, byteOrder);
-
 		int result;
 
 		if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
@@ -540,11 +538,14 @@
 	}
 
 	public final byte[] readBytearray(String name, byte bytes[], int start,
-			int count)
+			int count) throws ImageReadException
 	{
 		if (bytes.length < (start + count))
-			return null;
-
+		{
+			throw new ImageReadException("Invalid read. bytes.length: " + bytes.length+ ", start: " + start + ", count: " + count);
+			// return null;
+		}
+		
 		byte result[] = new byte[count];
 		System.arraycopy(bytes, start, result, 0, count);
 
@@ -554,12 +555,12 @@
 		return result;
 	}
 
-	protected final byte[] getByteArrayTail(String name, byte bytes[], int count)
+	protected final byte[] getByteArrayTail(String name, byte bytes[], int count) throws ImageReadException
 	{
 		return readBytearray(name, bytes, count, bytes.length - count);
 	}
 
-	protected final byte[] getBytearrayHead(String name, byte bytes[], int count)
+	protected final byte[] getBytearrayHead(String name, byte bytes[], int count) throws ImageReadException
 	{
 		return readBytearray(name, bytes, 0, bytes.length - count);
 	}
@@ -592,11 +593,7 @@
 	public final boolean compareByteArrays(byte a[], byte b[])
 	{
 		if (a.length != b.length)
-		{
-			// System.out.println("length mismatch: " + a.length + " != "
-			// + b.length);
 			return false;
-		}
 
 		return compareByteArrays(a, 0, b, 0, a.length);
 	}

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java Sun Aug 24 13:47:30 2008
@@ -16,6 +16,7 @@
  */
 package org.apache.sanselan.common;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.RandomAccessFile;
@@ -38,6 +39,12 @@
 
 	private final InputStream is;
 
+	public BinaryInputStream(byte bytes[], int byteOrder)
+	{
+		this.byteOrder = byteOrder;
+		this.is = new ByteArrayInputStream(bytes);
+	}
+
 	public BinaryInputStream(InputStream is, int byteOrder)
 	{
 		this.byteOrder = byteOrder;
@@ -161,7 +168,7 @@
 
 				this.debugByteArray("expected", expected);
 				debugNumber("data[" + i + "]", b);
-				//				debugNumber("expected[" + i + "]", expected[i]);
+				// debugNumber("expected[" + i + "]", expected[i]);
 
 				throw new ImageReadException(exception);
 			}
@@ -203,7 +210,7 @@
 	{
 		int count = 0;
 		for (int i = 0; count < 3; i++)
-		//		while(count<3)
+		// while(count<3)
 		{
 			int b = is.read();
 			if (b < 0)
@@ -289,21 +296,22 @@
 		if (length == 4)
 			byte3 = bytes[start + 3];
 
-		//		return convert4BytesToInt(name, byte0, byte1, byte2, byte3, byteOrder);
+		// return convert4BytesToInt(name, byte0, byte1, byte2, byte3,
+		// byteOrder);
 
 		int result;
 
 		if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
 			result = ((0xff & byte0) << 24) + ((0xff & byte1) << 16)
 					+ ((0xff & byte2) << 8) + ((0xff & byte3) << 0);
-		//		result = (( byte0) << 24) + ((byte1) << 16)
-		//		+ (( byte2) << 8) + (( byte3) << 0);
+		// result = (( byte0) << 24) + ((byte1) << 16)
+		// + (( byte2) << 8) + (( byte3) << 0);
 		else
 			// intel, little endian
 			result = ((0xff & byte3) << 24) + ((0xff & byte2) << 16)
 					+ ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
-		//		result = (( byte3) << 24) + (( byte2) << 16)
-		//		+ (( byte1) << 8) + (( byte0) << 0);
+		// result = (( byte3) << 24) + (( byte2) << 16)
+		// + (( byte1) << 8) + (( byte0) << 0);
 
 		if (debug)
 			debugNumber(name, result, 4);
@@ -346,7 +354,7 @@
 		byte byte0 = bytes[start + 0];
 		byte byte1 = bytes[start + 1];
 
-		//		return convert2BytesToShort(name, byte0, byte1, byteOrder);
+		// return convert2BytesToShort(name, byte0, byte1, byteOrder);
 
 		int result;
 
@@ -381,9 +389,9 @@
 			result[i] = convertByteArrayToShort(name, start + i * 2, bytes,
 					byteOrder);
 
-			//			byte byte0 = bytes[start + i * 2];
-			//			byte byte1 = bytes[start + i * 2 + 1];
-			//			result[i] = convertBytesToShort(name, byte0, byte1, byteOrder);
+			// byte byte0 = bytes[start + i * 2];
+			// byte byte1 = bytes[start + i * 2 + 1];
+			// result[i] = convertBytesToShort(name, byte0, byte1, byteOrder);
 		}
 
 		return result;
@@ -449,6 +457,34 @@
 		return result;
 	}
 
+	public final byte[] readByteArray(int length, String error)
+			throws ImageReadException, IOException
+	{
+		boolean verbose = false;
+		boolean strict = true;
+		return readByteArray(length, error, verbose, strict);
+	}
+
+	public final byte[] readByteArray(int length, String error,
+			boolean verbose, boolean strict) throws ImageReadException,
+			IOException
+	{
+		byte bytes[] = new byte[length];
+		int total = 0;
+		int read;
+		while ((read = read(bytes, total, length - total)) > 0)
+			total += read;
+		if (total < length)
+		{
+			if (strict)
+				throw new ImageReadException(error);
+			else if(verbose)
+				System.out.println(error);
+			return null;
+		}
+		return bytes;
+	}
+
 	protected final byte[] getBytearrayTail(String name, byte bytes[], int count)
 	{
 		return readBytearray(name, bytes, count, bytes.length - count);
@@ -539,6 +575,50 @@
 		return convertByteArrayToShort(name, bytes, byteOrder);
 	}
 
+	public final int read1ByteInteger(String exception)
+			throws ImageReadException, IOException
+	{
+		int byte0 = is.read();
+		if (byte0 < 0)
+			throw new ImageReadException(exception);
+
+		return 0xff & byte0;
+	}
+
+	public final int read2ByteInteger(String exception)
+			throws ImageReadException, IOException
+	{
+		int byte0 = is.read();
+		int byte1 = is.read();
+		if (byte0 < 0 || byte1 < 0)
+			throw new ImageReadException(exception);
+
+		if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+			return ((0xff & byte0) << 8) + ((0xff & byte1) << 0);
+		else
+			// intel, little endian
+			return ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
+	}
+
+	public final int read4ByteInteger(String exception)
+			throws ImageReadException, IOException
+	{
+		int byte0 = is.read();
+		int byte1 = is.read();
+		int byte2 = is.read();
+		int byte3 = is.read();
+		if (byte0 < 0 || byte1 < 0 || byte2 < 0 || byte3 < 0)
+			throw new ImageReadException(exception);
+
+		if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+			return ((0xff & byte0) << 24) + ((0xff & byte1) << 16)
+					+ ((0xff & byte2) << 8) + ((0xff & byte3) << 0);
+		else
+			// intel, little endian
+			return ((0xff & byte3) << 24) + ((0xff & byte2) << 16)
+					+ ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
+	}
+	
 	protected final void printCharQuad(String msg, int i)
 	{
 		System.out.println(msg + ": '" + (char) (0xff & (i >> 24))

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java Sun Aug 24 13:47:30 2008
@@ -106,10 +106,42 @@
 		writeNBytes(value, 2);
 	}
 
+	public final void write4ByteInteger(int value) throws ImageWriteException,
+			IOException
+	{
+		if (byteOrder == BYTE_ORDER_MOTOROLA)
+		{
+			write(0xff & (value >> 24));
+			write(0xff & (value >> 16));
+			write(0xff & (value >> 8));
+			write(0xff & value);
+		} else
+		{
+			write(0xff & value);
+			write(0xff & (value >> 8));
+			write(0xff & (value >> 16));
+			write(0xff & (value >> 24));
+		}
+	}
+
+	public final void write2ByteInteger(int value) throws ImageWriteException,
+			IOException
+	{
+		if (byteOrder == BYTE_ORDER_MOTOROLA)
+		{
+			write(0xff & (value >> 8));
+			write(0xff & value);
+		} else
+		{
+			write(0xff & value);
+			write(0xff & (value >> 8));
+		}
+	}
+
 	public final void writeByteArray(byte bytes[]) throws IOException
 	{
 		os.write(bytes, 0, bytes.length);
-		count+=bytes.length;
+		count += bytes.length;
 	}
 
 	private byte[] convertValueToByteArray(int value, int n)

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java Sun Aug 24 13:47:30 2008
@@ -16,8 +16,10 @@
  */
 package org.apache.sanselan.formats.jpeg;
 
-public interface JpegConstants
-{
+import org.apache.sanselan.formats.jpeg.iptc.IPTCType;
+
+
+public interface JpegConstants {
 	public static final int MAX_SEGMENT_SIZE = 0xffff;
 
 	public static final byte JFIF0_SIGNATURE[] = new byte[] { 0x4a, // J
@@ -70,6 +72,7 @@
 
 	public static final byte SOI[] = new byte[] { (byte) 0xff, (byte) 0xd8 };
 	public static final byte EOI[] = new byte[] { (byte) 0xff, (byte) 0xd9 };
+
 	public static final int SOS_Marker = (0xff00) | (0xda);
 
 	public static final int JPEG_APP0 = 0xE0;
@@ -122,148 +125,5 @@
 	public static final byte CONST_8BIM[] = { 0xff & '8', 0xff & 'B',
 			0xff & 'I', 0xff & 'M', };
 
-	public static final byte IPTCPrefix[] = { 0x1C, 0x02, };
 
-	public static final IptcType IPTC_TYPE_RecordVersion = new IptcType(0,
-			"RecordVersion");
-	public static final IptcType IPTC_TYPE_ObjectTypeReference = new IptcType(
-			3, "ObjectTypeReference");
-	public static final IptcType IPTC_TYPE_ObjectAttributeReference = new IptcType(
-			4, "ObjectAttributeReference");
-	public static final IptcType IPTC_TYPE_ObjectName = new IptcType(5,
-			"ObjectName");
-	public static final IptcType IPTC_TYPE_EditStatus = new IptcType(7,
-			"EditStatus");
-	public static final IptcType IPTC_TYPE_EditorialUpdate = new IptcType(8,
-			"EditorialUpdate");
-	public static final IptcType IPTC_TYPE_Urgency = new IptcType(10, "Urgency");
-	public static final IptcType IPTC_TYPE_SubjectReference = new IptcType(12,
-			"SubjectReference");
-	public static final IptcType IPTC_TYPE_Category = new IptcType(15,
-			"Category");
-	public static final IptcType IPTC_TYPE_SupplementalCategory = new IptcType(
-			20, "SupplementalCategory");
-	public static final IptcType IPTC_TYPE_FixtureIdentifier = new IptcType(22,
-			"FixtureIdentifier");
-	public static final IptcType IPTC_TYPE_Keywords = new IptcType(25,
-			"Keywords");
-	public static final IptcType IPTC_TYPE_ContentLocationCode = new IptcType(
-			26, "ContentLocationCode");
-	public static final IptcType IPTC_TYPE_ContentLocationName = new IptcType(
-			27, "ContentLocationName");
-	public static final IptcType IPTC_TYPE_ReleaseDate = new IptcType(30,
-			"ReleaseDate");
-	public static final IptcType IPTC_TYPE_ReleaseTime = new IptcType(35,
-			"ReleaseTime");
-	public static final IptcType IPTC_TYPE_ExpirationDate = new IptcType(37,
-			"ExpirationDate");
-	public static final IptcType IPTC_TYPE_ExpirationTime = new IptcType(38,
-			"ExpirationTime");
-	public static final IptcType IPTC_TYPE_SpecialInstructions = new IptcType(
-			40, "SpecialInstructions");
-	public static final IptcType IPTC_TYPE_ActionAdvised = new IptcType(42,
-			"ActionAdvised");
-	public static final IptcType IPTC_TYPE_ReferenceService = new IptcType(45,
-			"ReferenceService");
-	public static final IptcType IPTC_TYPE_ReferenceDate = new IptcType(47,
-			"ReferenceDate");
-	public static final IptcType IPTC_TYPE_ReferenceNumber = new IptcType(50,
-			"ReferenceNumber");
-	public static final IptcType IPTC_TYPE_DateCreated = new IptcType(55,
-			"DateCreated");
-	public static final IptcType IPTC_TYPE_TimeCreated = new IptcType(60,
-			"TimeCreated");
-	public static final IptcType IPTC_TYPE_DigitalCreationDate = new IptcType(
-			62, "DigitalCreationDate");
-	public static final IptcType IPTC_TYPE_DigitalCreationTime = new IptcType(
-			63, "DigitalCreationTime");
-	public static final IptcType IPTC_TYPE_OriginatingProgram = new IptcType(
-			65, "OriginatingProgram");
-	public static final IptcType IPTC_TYPE_ProgramVersion = new IptcType(70,
-			"ProgramVersion");
-	public static final IptcType IPTC_TYPE_ObjectCycle = new IptcType(75,
-			"ObjectCycle");
-	public static final IptcType IPTC_TYPE_Byline = new IptcType(80, "By-line");
-	public static final IptcType IPTC_TYPE_BylineTitle = new IptcType(85,
-			"By-lineTitle");
-	public static final IptcType IPTC_TYPE_City = new IptcType(90, "City");
-	public static final IptcType IPTC_TYPE_Sublocation = new IptcType(92,
-			"Sublocation");
-	public static final IptcType IPTC_TYPE_Province_State = new IptcType(95,
-			"Province/State");
-	public static final IptcType IPTC_TYPE_Country_PrimaryLocationCode = new IptcType(
-			100, "Country/PrimaryLocationCode");
-	public static final IptcType IPTC_TYPE_Country_PrimaryLocationName = new IptcType(
-			101, "Country/PrimaryLocationName");
-	public static final IptcType IPTC_TYPE_OriginalTransmission_Reference = new IptcType(
-			103, "OriginalTransmission,Reference");
-	public static final IptcType IPTC_TYPE_Headline = new IptcType(105,
-			"Headline");
-	public static final IptcType IPTC_TYPE_Credit = new IptcType(110, "Credit");
-	public static final IptcType IPTC_TYPE_Source = new IptcType(115, "Source");
-	public static final IptcType IPTC_TYPE_CopyrightNotice = new IptcType(116,
-			"CopyrightNotice");
-	public static final IptcType IPTC_TYPE_Contact = new IptcType(118,
-			"Contact");
-	public static final IptcType IPTC_TYPE_Caption_Abstract = new IptcType(120,
-			"Caption/Abstract");
-	public static final IptcType IPTC_TYPE_Writer_Editor = new IptcType(122,
-			"Writer/Editor");
-	public static final IptcType IPTC_TYPE_RasterizedCaption = new IptcType(
-			125, "RasterizedCaption");
-	public static final IptcType IPTC_TYPE_ImageType = new IptcType(130,
-			"ImageType");
-	public static final IptcType IPTC_TYPE_ImageOrientation = new IptcType(131,
-			"ImageOrientation");
-	public static final IptcType IPTC_TYPE_LanguageIdentifier = new IptcType(
-			135, "LanguageIdentifier");
-	public static final IptcType IPTC_TYPE_AudioType = new IptcType(150,
-			"AudioType");
-	public static final IptcType IPTC_TYPE_AudioSamplingRate = new IptcType(
-			151, "AudioSamplingRate");
-	public static final IptcType IPTC_TYPE_AudioSamplingResolution = new IptcType(
-			152, "AudioSamplingResolution");
-	public static final IptcType IPTC_TYPE_AudioDuration = new IptcType(153,
-			"AudioDuration");
-	public static final IptcType IPTC_TYPE_AudioOutcue = new IptcType(154,
-			"AudioOutcue");
-	public static final IptcType IPTC_TYPE_ObjectDataPreview_FileFormat = new IptcType(
-			200, "ObjectDataPreview,FileFormat");
-	public static final IptcType IPTC_TYPE_ObjectDataPreview_FileFormatVersion = new IptcType(
-			201, "ObjectDataPreview,FileFormatVersion");
-	public static final IptcType IPTC_TYPE_ObjectDataPreviewData = new IptcType(
-			202, "ObjectDataPreviewData");
-	// --
-	public static final IptcType IPTC_TYPE_Unknown = new IptcType(-1, "Unknown");
-
-	public static final IptcType IPTC_TYPES[] = { IPTC_TYPE_RecordVersion,
-			IPTC_TYPE_ObjectTypeReference, IPTC_TYPE_ObjectAttributeReference,
-			IPTC_TYPE_ObjectName, IPTC_TYPE_EditStatus,
-			IPTC_TYPE_EditorialUpdate, IPTC_TYPE_Urgency,
-			IPTC_TYPE_SubjectReference, IPTC_TYPE_Category,
-			IPTC_TYPE_SupplementalCategory, IPTC_TYPE_FixtureIdentifier,
-			IPTC_TYPE_Keywords, IPTC_TYPE_ContentLocationCode,
-			IPTC_TYPE_ContentLocationName, IPTC_TYPE_ReleaseDate,
-			IPTC_TYPE_ReleaseTime, IPTC_TYPE_ExpirationDate,
-			IPTC_TYPE_ExpirationTime, IPTC_TYPE_SpecialInstructions,
-			IPTC_TYPE_ActionAdvised, IPTC_TYPE_ReferenceService,
-			IPTC_TYPE_ReferenceDate, IPTC_TYPE_ReferenceNumber,
-			IPTC_TYPE_DateCreated, IPTC_TYPE_TimeCreated,
-			IPTC_TYPE_DigitalCreationDate, IPTC_TYPE_DigitalCreationTime,
-			IPTC_TYPE_OriginatingProgram, IPTC_TYPE_ProgramVersion,
-			IPTC_TYPE_ObjectCycle, IPTC_TYPE_Byline, IPTC_TYPE_BylineTitle,
-			IPTC_TYPE_City, IPTC_TYPE_Sublocation, IPTC_TYPE_Province_State,
-			IPTC_TYPE_Country_PrimaryLocationCode,
-			IPTC_TYPE_Country_PrimaryLocationName,
-			IPTC_TYPE_OriginalTransmission_Reference, IPTC_TYPE_Headline,
-			IPTC_TYPE_Credit, IPTC_TYPE_Source, IPTC_TYPE_CopyrightNotice,
-			IPTC_TYPE_Contact, IPTC_TYPE_Caption_Abstract,
-			IPTC_TYPE_Writer_Editor, IPTC_TYPE_RasterizedCaption,
-			IPTC_TYPE_ImageType, IPTC_TYPE_ImageOrientation,
-			IPTC_TYPE_LanguageIdentifier, IPTC_TYPE_AudioType,
-			IPTC_TYPE_AudioSamplingRate, IPTC_TYPE_AudioSamplingResolution,
-			IPTC_TYPE_AudioDuration, IPTC_TYPE_AudioOutcue,
-			IPTC_TYPE_ObjectDataPreview_FileFormat,
-			IPTC_TYPE_ObjectDataPreview_FileFormatVersion,
-			IPTC_TYPE_ObjectDataPreviewData, };
 }

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java Sun Aug 24 13:47:30 2008
@@ -22,44 +22,33 @@
 
 import org.apache.sanselan.ImageReadException;
 import org.apache.sanselan.common.IImageMetadata;
-import org.apache.sanselan.common.ImageMetadata;
 import org.apache.sanselan.formats.tiff.TiffField;
 import org.apache.sanselan.formats.tiff.TiffImageData;
 import org.apache.sanselan.formats.tiff.TiffImageMetadata;
 import org.apache.sanselan.formats.tiff.constants.TagInfo;
 import org.apache.sanselan.util.Debug;
 
-public class JpegImageMetadata implements IImageMetadata
-{
-	public static class Photoshop extends ImageMetadata
-	{
-	}
-
-	private final Photoshop photoshop;
+public class JpegImageMetadata implements IImageMetadata {
+	private final JpegPhotoshopMetadata photoshop;
 	private final TiffImageMetadata exif;
 
-	public JpegImageMetadata(final Photoshop photoshop,
-			final TiffImageMetadata exif)
-	{
+	public JpegImageMetadata(final JpegPhotoshopMetadata photoshop,
+			final TiffImageMetadata exif) {
 		this.photoshop = photoshop;
 		this.exif = exif;
 	}
 
-	public TiffImageMetadata getExif()
-	{
+	public TiffImageMetadata getExif() {
 		return exif;
 	}
 
-	public Photoshop getPhotoshop()
-	{
+	public JpegPhotoshopMetadata getPhotoshop() {
 		return photoshop;
 	}
 
-	public TiffField findEXIFValue(TagInfo tagInfo)
-	{
+	public TiffField findEXIFValue(TagInfo tagInfo) {
 		ArrayList items = getItems();
-		for (int i = 0; i < items.size(); i++)
-		{
+		for (int i = 0; i < items.size(); i++) {
 			Object o = items.get(i);
 			if (!(o instanceof TiffImageMetadata.Item))
 				continue;
@@ -74,14 +63,12 @@
 	}
 
 	public BufferedImage getEXIFThumbnail() throws ImageReadException,
-			IOException
-	{
+			IOException {
 		ArrayList dirs = exif.getDirectories();
-		for (int i = 0; i < dirs.size(); i++)
-		{
+		for (int i = 0; i < dirs.size(); i++) {
 			TiffImageMetadata.Directory dir = (TiffImageMetadata.Directory) dirs
 					.get(i);
-			//			Debug.debug("dir", dir);
+			// Debug.debug("dir", dir);
 			BufferedImage image = dir.getThumbnail();
 			if (null != image)
 				return image;
@@ -90,14 +77,12 @@
 		return null;
 	}
 
-	public TiffImageData getRawImageData()
-	{
+	public TiffImageData getRawImageData() {
 		ArrayList dirs = exif.getDirectories();
-		for (int i = 0; i < dirs.size(); i++)
-		{
+		for (int i = 0; i < dirs.size(); i++) {
 			TiffImageMetadata.Directory dir = (TiffImageMetadata.Directory) dirs
 					.get(i);
-			//			Debug.debug("dir", dir);
+			// Debug.debug("dir", dir);
 			TiffImageData rawImageData = dir.getTiffImageData();
 			if (null != rawImageData)
 				return rawImageData;
@@ -106,8 +91,7 @@
 		return null;
 	}
 
-	public ArrayList getItems()
-	{
+	public ArrayList getItems() {
 		ArrayList result = new ArrayList();
 
 		if (null != exif)
@@ -121,13 +105,11 @@
 
 	private static final String newline = System.getProperty("line.separator");
 
-	public String toString()
-	{
+	public String toString() {
 		return toString(null);
 	}
 
-	public String toString(String prefix)
-	{
+	public String toString(String prefix) {
 		if (prefix == null)
 			prefix = "";
 
@@ -136,21 +118,19 @@
 		result.append(prefix);
 		if (null == exif)
 			result.append("No Exif metadata.");
-		else
-		{
+		else {
 			result.append("Exif metadata:");
 			result.append(newline);
 			result.append(exif.toString("\t"));
 		}
 
-		//		if (null != exif && null != photoshop)
+		// if (null != exif && null != photoshop)
 		result.append(newline);
 
 		result.append(prefix);
 		if (null == photoshop)
 			result.append("No Photoshop (IPTC) metadata.");
-		else
-		{
+		else {
 			result.append("Photoshop (IPTC) metadata:");
 			result.append(newline);
 			result.append(photoshop.toString("\t"));
@@ -159,8 +139,7 @@
 		return result.toString();
 	}
 
-	public void dump()
-	{
+	public void dump() {
 		Debug.debug(this.toString());
 	}
 

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=688558&r1=688557&r2=688558&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 Aug 24 13:47:30 2008
@@ -34,6 +34,9 @@
 import org.apache.sanselan.ImageReadException;
 import org.apache.sanselan.common.IImageMetadata;
 import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCRecord;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCParser;
+import org.apache.sanselan.formats.jpeg.iptc.PhotoshopApp13Data;
 import org.apache.sanselan.formats.jpeg.segments.App13Segment;
 import org.apache.sanselan.formats.jpeg.segments.App2Segment;
 import org.apache.sanselan.formats.jpeg.segments.GenericSegment;
@@ -304,12 +307,12 @@
 	{
 		TiffImageMetadata exif = getExifMetadata(byteSource, params);
 
-		JpegImageMetadata.Photoshop photoshop = getPhotoshopMetadata(byteSource);
+		JpegPhotoshopMetadata photoshop = getPhotoshopMetadata(byteSource,
+				params);
 
 		if (null == exif && null == photoshop)
 			return null;
 
-		
 		JpegImageMetadata result = new JpegImageMetadata(photoshop, exif);
 
 		return result;
@@ -447,6 +450,49 @@
 		return result[0];
 	}
 
+	public boolean hasIptcSegment(ByteSource byteSource)
+			throws ImageReadException, IOException
+	{
+		final boolean result[] = { false, };
+
+		JpegUtils.Visitor visitor = new JpegUtils.Visitor() {
+			// return false to exit before reading image data.
+			public boolean beginSOS()
+			{
+				return false;
+			}
+
+			public void visitSOS(int marker, byte markerBytes[],
+					byte imageData[])
+			{
+			}
+
+			// return false to exit traversal.
+			public boolean visitSegment(int marker, byte markerBytes[],
+					int markerLength, byte markerLengthBytes[],
+					byte segmentData[]) throws ImageReadException, IOException
+			{
+				if (marker == 0xffd9)
+					return false;
+
+				if (marker == JPEG_APP13_Marker)
+				{
+					if (new IPTCParser().isPhotoshopJpegSegment(segmentData))
+					{
+						result[0] = true;
+						return false;
+					}
+				}
+
+				return true;
+			}
+		};
+
+		new JpegUtils().traverseJFIF(byteSource, visitor);
+
+		return result[0];
+	}
+
 	public boolean hasXmpSegment(ByteSource byteSource)
 			throws ImageReadException, IOException
 	{
@@ -497,10 +543,11 @@
 	 *            File containing image data.
 	 * @param params
 	 *            Map of optional parameters, defined in SanselanConstants.
-	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 * @return Xmp Xml as String, if present. Otherwise, returns null..
 	 */
 	public String getXmpXml(ByteSource byteSource, Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 
 		final List result = new ArrayList();
 
@@ -547,8 +594,8 @@
 		return (String) result.get(0);
 	}
 
-	private JpegImageMetadata.Photoshop getPhotoshopMetadata(
-			ByteSource byteSource) throws ImageReadException, IOException
+	public JpegPhotoshopMetadata getPhotoshopMetadata(ByteSource byteSource,
+			Map params) throws ImageReadException, IOException
 	{
 		ArrayList segments = readSegments(byteSource,
 				new int[] { JPEG_APP13_Marker, }, false);
@@ -556,22 +603,23 @@
 		if ((segments == null) || (segments.size() < 1))
 			return null;
 
-		JpegImageMetadata.Photoshop result = new JpegImageMetadata.Photoshop();
+		PhotoshopApp13Data photoshopApp13Data = null;
 
 		for (int i = 0; i < segments.size(); i++)
 		{
 			App13Segment segment = (App13Segment) segments.get(i);
 
-			ArrayList elements = segment.elements;
+			PhotoshopApp13Data data = segment.parsePhotoshopSegment(params);
+			if (data != null && photoshopApp13Data != null)
+				throw new ImageReadException(
+						"Jpeg contains more than one Photoshop App13 segment.");
 
-			for (int j = 0; j < elements.size(); j++)
-			{
-				IptcElement element = (IptcElement) elements.get(j);
-				result.add(element.getIptcTypeName(), element.getValue());
-			}
+			photoshopApp13Data = data;
 		}
 
-		return result;
+		if(null==photoshopApp13Data)
+			return null;
+		return new JpegPhotoshopMetadata(photoshopApp13Data);
 	}
 
 	public Dimension getImageSize(ByteSource byteSource, Map params)

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,40 @@
+/**
+ * 
+ */
+package org.apache.sanselan.formats.jpeg;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sanselan.common.ImageMetadata;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCConstants;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCRecord;
+import org.apache.sanselan.formats.jpeg.iptc.PhotoshopApp13Data;
+import org.apache.sanselan.util.Debug;
+
+public class JpegPhotoshopMetadata extends ImageMetadata implements
+		IPTCConstants
+{
+
+	public final PhotoshopApp13Data photoshopApp13Data;
+
+	public JpegPhotoshopMetadata(final PhotoshopApp13Data photoshopApp13Data)
+	{
+		this.photoshopApp13Data = photoshopApp13Data;
+
+		List records = photoshopApp13Data.getRecords();
+		Collections.sort(records, IPTCRecord.COMPARATOR);
+		for (int j = 0; j < records.size(); j++)
+		{
+			IPTCRecord element = (IPTCRecord) records.get(j);
+			if (element.iptcType.type != IPTC_TYPE_RECORD_VERSION.type)
+				add(element.getIptcTypeName(), element.getValue());
+		}
+	}
+
+	public void dump()
+	{
+		Debug.debug(this.toString());
+	}
+
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,23 @@
+/**
+ * 
+ */
+package org.apache.sanselan.formats.jpeg.iptc;
+
+public class IPTCBlock
+{
+	public final int blockType;
+	public final byte[] blockNameBytes;
+	public final byte[] blockData;
+
+	public IPTCBlock(int blockType, byte[] blockNameBytes, byte[] blockData)
+	{
+		this.blockData = blockData;
+		this.blockNameBytes = blockNameBytes;
+		this.blockType = blockType;
+	}
+
+	public boolean isIPTCBlock()
+	{
+		return blockType == IPTCParser.IMAGE_RESOURCE_BLOCK_IPTC_DATA;
+	}
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,251 @@
+/*
+ * 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.jpeg.iptc;
+
+public interface IPTCConstants
+{
+
+	// public static final byte PhotoshopIdentificationString[] =
+	// "Photoshop 3.0"
+	// .getBytes();
+	public static final byte PHOTOSHOP_IDENTIFICATION_STRING[] = { 0xff & 'P',
+			0xff & 'h', 0xff & 'o', 0xff & 't', 0xff & 'o', 0xff & 's',
+			0xff & 'h', 0xff & 'o', 0xff & 'p', 0xff & ' ', 0xff & '3',
+			0xff & '.', 0xff & '0', 0, };
+	public static final byte CONST_8BIM[] = { 0xff & '8', 0xff & 'B',
+			0xff & 'I', 0xff & 'M', };
+
+	public static final byte IPTCPrefix[] = { 0x1C, 0x02, };
+
+	
+	public static final int IPTC_NON_EXTENDED_RECORD_MAXIMUM_SIZE = 32767;
+	
+	public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP2_INFO = 0x03e8;
+	public static final int IMAGE_RESOURCE_BLOCK_MACINTOSH_PRINT_INFO = 0x03e9;
+	public static final int IMAGE_RESOURCE_BLOCK_XML_DATA = 0x03ea;
+	public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP2_COLOR_TABLE = 0x03eb;
+	public static final int IMAGE_RESOURCE_BLOCK_RESOLUTION_INFO = 0x03ed;
+	public static final int IMAGE_RESOURCE_BLOCK_ALPHA_CHANNELS_NAMES = 0x03ee;
+	public static final int IMAGE_RESOURCE_BLOCK_DISPLAY_INFO = 0x03ef;
+	public static final int IMAGE_RESOURCE_BLOCK_PSTRING_CAPTION = 0x03f0;
+	public static final int IMAGE_RESOURCE_BLOCK_BORDER_INFORMATION = 0x03f1;
+	public static final int IMAGE_RESOURCE_BLOCK_BACKGROUND_COLOR = 0x03f2;
+	public static final int IMAGE_RESOURCE_BLOCK_PRINT_FLAGS = 0x03f3;
+	public static final int IMAGE_RESOURCE_BLOCK_BW_HALFTONING_INFO = 0x03f4;
+	public static final int IMAGE_RESOURCE_BLOCK_COLOR_HALFTONING_INFO = 0x03f5;
+	public static final int IMAGE_RESOURCE_BLOCK_DUOTONE_HALFTONING_INFO = 0x03f6;
+	public static final int IMAGE_RESOURCE_BLOCK_BW_TRANSFER_FUNC = 0x03f7;
+	public static final int IMAGE_RESOURCE_BLOCK_COLOR_TRANSFER_FUNCS = 0x03f8;
+	public static final int IMAGE_RESOURCE_BLOCK_DUOTONE_TRANSFER_FUNCS = 0x03f9;
+	public static final int IMAGE_RESOURCE_BLOCK_DUOTONE_IMAGE_INFO = 0x03fa;
+	public static final int IMAGE_RESOURCE_BLOCK_EFFECTIVE_BW = 0x03fb;
+	public static final int IMAGE_RESOURCE_BLOCK_OBSOLETE_PHOTOSHOP_TAG1 = 0x03fc;
+	public static final int IMAGE_RESOURCE_BLOCK_EPS_OPTIONS = 0x03fd;
+	public static final int IMAGE_RESOURCE_BLOCK_QUICK_MASK_INFO = 0x03fe;
+	public static final int IMAGE_RESOURCE_BLOCK_OBSOLETE_PHOTOSHOP_TAG2 = 0x03ff;
+	public static final int IMAGE_RESOURCE_BLOCK_LAYER_STATE_INFO = 0x0400;
+	public static final int IMAGE_RESOURCE_BLOCK_WORKING_PATH = 0x0401;
+	public static final int IMAGE_RESOURCE_BLOCK_LAYERS_GROUP_INFO = 0x0402;
+	public static final int IMAGE_RESOURCE_BLOCK_OBSOLETE_PHOTOSHOP_TAG3 = 0x0403;
+	public static final int IMAGE_RESOURCE_BLOCK_IPTC_DATA = 0x0404;
+	public static final int IMAGE_RESOURCE_BLOCK_RAW_IMAGE_MODE = 0x0405;
+	public static final int IMAGE_RESOURCE_BLOCK_JPEG_QUALITY = 0x0406;
+	public static final int IMAGE_RESOURCE_BLOCK_GRID_GUIDES_INFO = 0x0408;
+	public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP_BGR_THUMBNAIL = 0x0409;
+	public static final int IMAGE_RESOURCE_BLOCK_COPYRIGHT_FLAG = 0x040a;
+	public static final int IMAGE_RESOURCE_BLOCK_URL = 0x040b;
+	public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP_THUMBNAIL = 0x040c;
+	public static final int IMAGE_RESOURCE_BLOCK_GLOBAL_ANGLE = 0x040d;
+	public static final int IMAGE_RESOURCE_BLOCK_COLOR_SAMPLERS_RESOURCE = 0x040e;
+	public static final int IMAGE_RESOURCE_BLOCK_ICC_PROFILE = 0x040f;
+	public static final int IMAGE_RESOURCE_BLOCK_WATERMARK = 0x0410;
+	public static final int IMAGE_RESOURCE_BLOCK_ICC_UNTAGGED = 0x0411;
+	public static final int IMAGE_RESOURCE_BLOCK_EFFECTS_VISIBLE = 0x0412;
+	public static final int IMAGE_RESOURCE_BLOCK_SPOT_HALFTONE = 0x0413;
+	public static final int IMAGE_RESOURCE_BLOCK_IDS_BASE_VALUE = 0x0414;
+	public static final int IMAGE_RESOURCE_BLOCK_UNICODE_ALPHA_NAMES = 0x0415;
+	public static final int IMAGE_RESOURCE_BLOCK_INDEXED_COLOUR_TABLE_COUNT = 0x0416;
+	public static final int IMAGE_RESOURCE_BLOCK_TRANSPARENT_INDEX = 0x0417;
+	public static final int IMAGE_RESOURCE_BLOCK_GLOBAL_ALTITUDE = 0x0419;
+	public static final int IMAGE_RESOURCE_BLOCK_SLICES = 0x041a;
+	public static final int IMAGE_RESOURCE_BLOCK_WORKFLOW_URL = 0x041b;
+	public static final int IMAGE_RESOURCE_BLOCK_JUMP_TO_XPEP = 0x041c;
+	public static final int IMAGE_RESOURCE_BLOCK_ALPHA_IDENTIFIERS = 0x041d;
+	public static final int IMAGE_RESOURCE_BLOCK_URL_LIST = 0x041e;
+	public static final int IMAGE_RESOURCE_BLOCK_VERSION_INFO = 0x0421;
+	public static final int IMAGE_RESOURCE_BLOCK_EXIFINFO = 0x0422;
+	public static final int IMAGE_RESOURCE_BLOCK_EXIF_INFO2 = 0x0423;
+	public static final int IMAGE_RESOURCE_BLOCK_XMP = 0x0424;
+	public static final int IMAGE_RESOURCE_BLOCK_CAPTION_DIGEST = 0x0425;
+	public static final int IMAGE_RESOURCE_BLOCK_PRINT_SCALE = 0x0426;
+	public static final int IMAGE_RESOURCE_BLOCK_PIXEL_ASPECT_RATIO = 0x0428;
+	public static final int IMAGE_RESOURCE_BLOCK_LAYER_COMPS = 0x0429;
+	public static final int IMAGE_RESOURCE_BLOCK_ALTERNATE_DUOTONE_COLORS = 0x042a;
+	public static final int IMAGE_RESOURCE_BLOCK_ALTERNATE_SPOT_COLORS = 0x042b;
+	public static final int IMAGE_RESOURCE_BLOCK_CLIPPING_PATH_NAME = 0x0bb7;
+	public static final int IMAGE_RESOURCE_BLOCK_PRINT_FLAGS_INFO = 0x2710;
+
+//	public static final int IPTC_RECORD_PREFIX = 0x1c02;
+	public static final int IPTC_RECORD_TAG_MARKER = 0x1c;
+	public static final int IPTC_ENVELOPE_RECORD_NUMBER = 0x01;
+	public static final int IPTC_APPLICATION_2_RECORD_NUMBER = 0x02;
+
+	public static final IPTCType IPTC_TYPE_RECORD_VERSION = new IPTCType(0,
+			"RecordVersion");
+	public static final IPTCType IPTC_TYPE_OBJECT_TYPE_REFERENCE = new IPTCType(
+			3, "ObjectTypeReference");
+	public static final IPTCType IPTC_TYPE_OBJECT_ATTRIBUTE_REFERENCE = new IPTCType(
+			4, "ObjectAttributeReference");
+	public static final IPTCType IPTC_TYPE_OBJECT_NAME = new IPTCType(5,
+			"ObjectName");
+	public static final IPTCType IPTC_TYPE_EDIT_STATUS = new IPTCType(7,
+			"EditStatus");
+	public static final IPTCType IPTC_TYPE_EDITORIAL_UPDATE = new IPTCType(8,
+			"EditorialUpdate");
+	public static final IPTCType IPTC_TYPE_URGENCY = new IPTCType(10, "Urgency");
+	public static final IPTCType IPTC_TYPE_SUBJECT_REFERENCE = new IPTCType(12,
+			"SubjectReference");
+	public static final IPTCType IPTC_TYPE_CATEGORY = new IPTCType(15,
+			"Category");
+	public static final IPTCType IPTC_TYPE_SUPPLEMENTAL_CATEGORY = new IPTCType(
+			20, "SupplementalCategory");
+	public static final IPTCType IPTC_TYPE_FIXTURE_IDENTIFIER = new IPTCType(
+			22, "FixtureIdentifier");
+	public static final IPTCType IPTC_TYPE_KEYWORDS = new IPTCType(25,
+			"Keywords");
+	public static final IPTCType IPTC_TYPE_CONTENT_LOCATION_CODE = new IPTCType(
+			26, "ContentLocationCode");
+	public static final IPTCType IPTC_TYPE_CONTENT_LOCATION_NAME = new IPTCType(
+			27, "ContentLocationName");
+	public static final IPTCType IPTC_TYPE_RELEASE_DATE = new IPTCType(30,
+			"ReleaseDate");
+	public static final IPTCType IPTC_TYPE_RELEASE_TIME = new IPTCType(35,
+			"ReleaseTime");
+	public static final IPTCType IPTC_TYPE_EXPIRATION_DATE = new IPTCType(37,
+			"ExpirationDate");
+	public static final IPTCType IPTC_TYPE_EXPIRATION_TIME = new IPTCType(38,
+			"ExpirationTime");
+	public static final IPTCType IPTC_TYPE_SPECIAL_INSTRUCTIONS = new IPTCType(
+			40, "SpecialInstructions");
+	public static final IPTCType IPTC_TYPE_ACTION_ADVISED = new IPTCType(42,
+			"ActionAdvised");
+	public static final IPTCType IPTC_TYPE_REFERENCE_SERVICE = new IPTCType(45,
+			"ReferenceService");
+	public static final IPTCType IPTC_TYPE_REFERENCE_DATE = new IPTCType(47,
+			"ReferenceDate");
+	public static final IPTCType IPTC_TYPE_REFERENCE_NUMBER = new IPTCType(50,
+			"ReferenceNumber");
+	public static final IPTCType IPTC_TYPE_DATE_CREATED = new IPTCType(55,
+			"DateCreated");
+	public static final IPTCType IPTC_TYPE_TIME_CREATED = new IPTCType(60,
+			"TimeCreated");
+	public static final IPTCType IPTC_TYPE_DIGITAL_CREATION_DATE = new IPTCType(
+			62, "DigitalCreationDate");
+	public static final IPTCType IPTC_TYPE_DIGITAL_CREATION_TIME = new IPTCType(
+			63, "DigitalCreationTime");
+	public static final IPTCType IPTC_TYPE_ORIGINATING_PROGRAM = new IPTCType(
+			65, "OriginatingProgram");
+	public static final IPTCType IPTC_TYPE_PROGRAM_VERSION = new IPTCType(70,
+			"ProgramVersion");
+	public static final IPTCType IPTC_TYPE_OBJECT_CYCLE = new IPTCType(75,
+			"ObjectCycle");
+	public static final IPTCType IPTC_TYPE_BYLINE = new IPTCType(80, "By-line");
+	public static final IPTCType IPTC_TYPE_BYLINE_TITLE = new IPTCType(85,
+			"By-lineTitle");
+	public static final IPTCType IPTC_TYPE_CITY = new IPTCType(90, "City");
+	public static final IPTCType IPTC_TYPE_SUBLOCATION = new IPTCType(92,
+			"Sublocation");
+	public static final IPTCType IPTC_TYPE_PROVINCE_STATE = new IPTCType(95,
+			"Province/State");
+	public static final IPTCType IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_CODE = new IPTCType(
+			100, "Country/PrimaryLocationCode");
+	public static final IPTCType IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_NAME = new IPTCType(
+			101, "Country/PrimaryLocationName");
+	public static final IPTCType IPTC_TYPE_ORIGINAL_TRANSMISSION_REFERENCE = new IPTCType(
+			103, "OriginalTransmission,Reference");
+	public static final IPTCType IPTC_TYPE_HEADLINE = new IPTCType(105,
+			"Headline");
+	public static final IPTCType IPTC_TYPE_CREDIT = new IPTCType(110, "Credit");
+	public static final IPTCType IPTC_TYPE_SOURCE = new IPTCType(115, "Source");
+	public static final IPTCType IPTC_TYPE_COPYRIGHT_NOTICE = new IPTCType(116,
+			"CopyrightNotice");
+	public static final IPTCType IPTC_TYPE_CONTACT = new IPTCType(118,
+			"Contact");
+	public static final IPTCType IPTC_TYPE_CAPTION_ABSTRACT = new IPTCType(120,
+			"Caption/Abstract");
+	public static final IPTCType IPTC_TYPE_WRITER_EDITOR = new IPTCType(122,
+			"Writer/Editor");
+	public static final IPTCType IPTC_TYPE_RASTERIZED_CAPTION = new IPTCType(
+			125, "RasterizedCaption");
+	public static final IPTCType IPTC_TYPE_IMAGE_TYPE = new IPTCType(130,
+			"ImageType");
+	public static final IPTCType IPTC_TYPE_IMAGE_ORIENTATION = new IPTCType(
+			131, "ImageOrientation");
+	public static final IPTCType IPTC_TYPE_LANGUAGE_IDENTIFIER = new IPTCType(
+			135, "LanguageIdentifier");
+	public static final IPTCType IPTC_TYPE_AUDIO_TYPE = new IPTCType(150,
+			"AudioType");
+	public static final IPTCType IPTC_TYPE_AUDIO_SAMPLING_RATE = new IPTCType(
+			151, "AudioSamplingRate");
+	public static final IPTCType IPTC_TYPE_AUDIO_SAMPLING_RESOLUTION = new IPTCType(
+			152, "AudioSamplingResolution");
+	public static final IPTCType IPTC_TYPE_AUDIO_DURATION = new IPTCType(153,
+			"AudioDuration");
+	public static final IPTCType IPTC_TYPE_AUDIO_OUTCUE = new IPTCType(154,
+			"AudioOutcue");
+	public static final IPTCType IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT = new IPTCType(
+			200, "ObjectDataPreview,FileFormat");
+	public static final IPTCType IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT_VERSION = new IPTCType(
+			201, "ObjectDataPreview,FileFormatVersion");
+	public static final IPTCType IPTC_TYPE_OBJECT_DATA_PREVIEW_DATA = new IPTCType(
+			202, "ObjectDataPreviewData");
+	// --
+	// public static final IPTCType IPTC_TYPE_UNKNOWN = new IPTCType(-1,
+	// "Unknown");
+
+	public static final IPTCType IPTC_TYPES[] = { IPTC_TYPE_RECORD_VERSION,
+			IPTC_TYPE_OBJECT_TYPE_REFERENCE,
+			IPTC_TYPE_OBJECT_ATTRIBUTE_REFERENCE, IPTC_TYPE_OBJECT_NAME,
+			IPTC_TYPE_EDIT_STATUS, IPTC_TYPE_EDITORIAL_UPDATE,
+			IPTC_TYPE_URGENCY, IPTC_TYPE_SUBJECT_REFERENCE, IPTC_TYPE_CATEGORY,
+			IPTC_TYPE_SUPPLEMENTAL_CATEGORY, IPTC_TYPE_FIXTURE_IDENTIFIER,
+			IPTC_TYPE_KEYWORDS, IPTC_TYPE_CONTENT_LOCATION_CODE,
+			IPTC_TYPE_CONTENT_LOCATION_NAME, IPTC_TYPE_RELEASE_DATE,
+			IPTC_TYPE_RELEASE_TIME, IPTC_TYPE_EXPIRATION_DATE,
+			IPTC_TYPE_EXPIRATION_TIME, IPTC_TYPE_SPECIAL_INSTRUCTIONS,
+			IPTC_TYPE_ACTION_ADVISED, IPTC_TYPE_REFERENCE_SERVICE,
+			IPTC_TYPE_REFERENCE_DATE, IPTC_TYPE_REFERENCE_NUMBER,
+			IPTC_TYPE_DATE_CREATED, IPTC_TYPE_TIME_CREATED,
+			IPTC_TYPE_DIGITAL_CREATION_DATE, IPTC_TYPE_DIGITAL_CREATION_TIME,
+			IPTC_TYPE_ORIGINATING_PROGRAM, IPTC_TYPE_PROGRAM_VERSION,
+			IPTC_TYPE_OBJECT_CYCLE, IPTC_TYPE_BYLINE, IPTC_TYPE_BYLINE_TITLE,
+			IPTC_TYPE_CITY, IPTC_TYPE_SUBLOCATION, IPTC_TYPE_PROVINCE_STATE,
+			IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_CODE,
+			IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_NAME,
+			IPTC_TYPE_ORIGINAL_TRANSMISSION_REFERENCE, IPTC_TYPE_HEADLINE,
+			IPTC_TYPE_CREDIT, IPTC_TYPE_SOURCE, IPTC_TYPE_COPYRIGHT_NOTICE,
+			IPTC_TYPE_CONTACT, IPTC_TYPE_CAPTION_ABSTRACT,
+			IPTC_TYPE_WRITER_EDITOR, IPTC_TYPE_RASTERIZED_CAPTION,
+			IPTC_TYPE_IMAGE_TYPE, IPTC_TYPE_IMAGE_ORIENTATION,
+			IPTC_TYPE_LANGUAGE_IDENTIFIER, IPTC_TYPE_AUDIO_TYPE,
+			IPTC_TYPE_AUDIO_SAMPLING_RATE, IPTC_TYPE_AUDIO_SAMPLING_RESOLUTION,
+			IPTC_TYPE_AUDIO_DURATION, IPTC_TYPE_AUDIO_OUTCUE,
+			IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT,
+			IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT_VERSION,
+			IPTC_TYPE_OBJECT_DATA_PREVIEW_DATA, };
+
+}

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,444 @@
+/*
+ * 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.jpeg.iptc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.SanselanConstants;
+import org.apache.sanselan.common.BinaryFileParser;
+import org.apache.sanselan.common.BinaryInputStream;
+import org.apache.sanselan.common.BinaryOutputStream;
+import org.apache.sanselan.util.Debug;
+import org.apache.sanselan.util.ParamMap;
+
+public class IPTCParser extends BinaryFileParser implements IPTCConstants
+{
+	private static final int APP13_BYTE_ORDER = BYTE_ORDER_NETWORK;
+
+	public IPTCParser()
+	{
+		setByteOrder(BYTE_ORDER_NETWORK);
+	}
+
+	public boolean isPhotoshopJpegSegment(byte segmentData[])
+	{
+
+		if (!compareByteArrays(segmentData, 0, PHOTOSHOP_IDENTIFICATION_STRING,
+				0, PHOTOSHOP_IDENTIFICATION_STRING.length))
+			return false;
+
+		int index = PHOTOSHOP_IDENTIFICATION_STRING.length;
+		if (index + CONST_8BIM.length > segmentData.length)
+			return false;
+
+		if (!compareByteArrays(segmentData, index, CONST_8BIM, 0,
+				CONST_8BIM.length))
+			return false;
+
+		return true;
+	}
+
+	/*
+	 * In practice, App13 segments are only used for Photoshop/IPTC metadata.
+	 * However, we should not treat App13 signatures without Photoshop's
+	 * signature as Photoshop/IPTC segments.
+	 * 
+	 * A Photoshop/IPTC App13 segment begins with the Photoshop Identification
+	 * string.
+	 * 
+	 * There follows 0-N blocks (Photoshop calls them "Image Resource Blocks").
+	 * 
+	 * Each block has the following structure:
+	 * 
+	 * 1. 4-byte type. This is always "8BIM" for blocks in a Photoshop App13
+	 * segment. 2. 2-byte id. IPTC data is stored in blocks with id 0x0404, aka.
+	 * IPTC_NAA_RECORD_IMAGE_RESOURCE_ID 3. Block name as a Pascal String. This
+	 * is padded to have an even length. 4. 4-byte size (in bytes). 5. Block
+	 * data. This is also padded to have an even length.
+	 * 
+	 * The block data consists of a 0-N records. A record has the following
+	 * structure:
+	 * 
+	 * 1. 2-byte prefix. The value is always 0x1C02 2. 1-byte record type. The
+	 * record types are documented by the IPTC. See IPTCConstants. 3. 2-byte
+	 * record size (in bytes). 4. Record data, "record size" bytes long.
+	 * 
+	 * Record data (unlike block data) is NOT padded to have an even length.
+	 * 
+	 * Record data, for IPTC record, should always be ISO-8859-1.
+	 * 
+	 * The exception is the first record in the block, which must always be a
+	 * record version record, whose value is a two-byte number; the value is
+	 * 0x02.
+	 * 
+	 * Some IPTC blocks are missing this first "record version" record, so we
+	 * don't require it.
+	 */
+	public PhotoshopApp13Data parsePhotoshopSegment(byte bytes[], Map params)
+			throws ImageReadException, IOException
+	{
+		boolean strict = ParamMap.getParamBoolean(params,
+				SanselanConstants.PARAM_KEY_STRICT, false);
+		boolean verbose = ParamMap.getParamBoolean(params,
+				SanselanConstants.PARAM_KEY_VERBOSE, false);
+
+		return parsePhotoshopSegment(bytes, verbose, strict);
+	}
+
+	public PhotoshopApp13Data parsePhotoshopSegment(byte bytes[],
+			boolean verbose, boolean strict) throws ImageReadException,
+			IOException
+	{
+		ArrayList records = new ArrayList();
+
+		List allBlocks = parseAllBlocks(bytes, verbose, strict);
+
+		for (int i = 0; i < allBlocks.size(); i++)
+		{
+			IPTCBlock block = (IPTCBlock) allBlocks.get(i);
+
+			// Ignore everything but IPTC data.
+			if (!block.isIPTCBlock())
+				continue;
+
+			records.addAll(parseIPTCBlock(block.blockData, verbose));
+		}
+
+		return new PhotoshopApp13Data(records, allBlocks);
+	}
+
+	protected List parseIPTCBlock(byte bytes[], boolean verbose)
+			throws ImageReadException, IOException
+	{
+		ArrayList elements = new ArrayList();
+
+		int index = 0;
+		// Integer recordVersion = null;
+		while (index + 1 < bytes.length)
+		{
+			int tagMarker = 0xff & bytes[index++];
+			if (verbose)
+				Debug.debug("tagMarker", tagMarker + " (0x"
+						+ Integer.toHexString(tagMarker) + ")");
+
+			if (tagMarker != IPTC_RECORD_TAG_MARKER)
+			{
+				if (verbose)
+					System.out
+							.println("Unexpected record tag marker in IPTC data.");
+				return elements;
+			}
+
+			int recordNumber = 0xff & bytes[index++];
+			if (verbose)
+				Debug.debug("recordNumber", recordNumber + " (0x"
+						+ Integer.toHexString(recordNumber) + ")");
+
+			if (recordNumber != IPTC_APPLICATION_2_RECORD_NUMBER)
+				continue;
+
+			// int recordPrefix = convertByteArrayToShort("recordPrefix", index,
+			// bytes);
+			// if (verbose)
+			// Debug.debug("recordPrefix", recordPrefix + " (0x"
+			// + Integer.toHexString(recordPrefix) + ")");
+			// index += 2;
+			//
+			// if (recordPrefix != IPTC_RECORD_PREFIX)
+			// {
+			// if (verbose)
+			// System.out
+			// .println("Unexpected record prefix in IPTC data!");
+			// return elements;
+			// }
+
+			// throw new ImageReadException(
+			// "Unexpected record prefix in IPTC data.");
+
+			int recordType = 0xff & bytes[index];
+			if (verbose)
+				Debug.debug("recordType", recordType + " (0x"
+						+ Integer.toHexString(recordType) + ")");
+			index++;
+
+			int recordSize = convertByteArrayToShort("recordSize", index, bytes);
+			index += 2;
+
+			boolean extendedDataset = recordSize > IPTC_NON_EXTENDED_RECORD_MAXIMUM_SIZE;
+			int dataFieldCountLength = recordSize & 0x7fff;
+			if (extendedDataset && verbose)
+				Debug.debug("extendedDataset. dataFieldCountLength: "
+						+ dataFieldCountLength);
+			if (extendedDataset) // ignore extended dataset and everything
+				// after.
+				return elements;
+
+			byte recordData[] = readBytearray("recordData", bytes, index,
+					recordSize);
+			index += recordSize;
+
+
+//			Debug.debug("recordSize", recordSize + " (0x"
+//					+ Integer.toHexString(recordSize) + ")");
+			
+			if (recordType == 0)
+			{
+				if (verbose)
+					System.out.println("ignore record version record! "
+							+ elements.size());
+				// ignore "record version" record;
+				continue;
+			}
+			// if (recordVersion == null)
+			// {
+			// // The first record in a JPEG/Photoshop IPTC block must be
+			// // the record version.
+			// if (recordType != 0)
+			// throw new ImageReadException("Missing record version: "
+			// + recordType);
+			// recordVersion = new Integer(convertByteArrayToShort(
+			// "recordNumber", recordData));
+			//
+			// if (recordSize != 2)
+			// throw new ImageReadException(
+			// "Invalid record version record size: " + recordSize);
+			//
+			// // JPEG/Photoshop IPTC metadata is always in Record version
+			// // 2
+			// if (recordVersion.intValue() != 2)
+			// throw new ImageReadException(
+			// "Invalid IPTC record version: " + recordVersion);
+			//
+			// // Debug.debug("recordVersion", recordVersion);
+			// continue;
+			// }
+
+			String value = new String(recordData, "ISO-8859-1");
+
+			IPTCType iptcType = IPTCTypeLookup.getIptcType(recordType);
+
+			// Debug.debug("iptcType", iptcType);
+			// debugByteArray("iptcData", iptcData);
+			// Debug.debug();
+
+			// if (recordType == IPTC_TYPE_CREDIT.type
+			// || recordType == IPTC_TYPE_OBJECT_NAME.type)
+			// {
+			// this.debugByteArray("recordData", recordData);
+			// Debug.debug("index", IPTC_TYPE_CREDIT.name);
+			// }
+
+			IPTCRecord element = new IPTCRecord(iptcType, value);
+			elements.add(element);
+		}
+
+		return elements;
+	}
+
+	protected List parseAllBlocks(byte bytes[], boolean verbose, boolean strict)
+			throws ImageReadException, IOException
+	{
+		List blocks = new ArrayList();
+
+		BinaryInputStream bis = new BinaryInputStream(bytes, APP13_BYTE_ORDER);
+
+		// Note that these are unsigned quantities. Name is always an even
+		// number of bytes (including the 1st byte, which is the size.)
+
+		byte[] idString = bis.readByteArray(
+				PHOTOSHOP_IDENTIFICATION_STRING.length,
+				"App13 Segment missing identification string");
+		if (!compareByteArrays(idString, PHOTOSHOP_IDENTIFICATION_STRING))
+			throw new ImageReadException("Not a Photoshop App13 Segment");
+
+		// int index = PHOTOSHOP_IDENTIFICATION_STRING.length;
+
+		while (true)
+		{
+			byte[] imageResourceBlockSignature = bis
+					.readByteArray(CONST_8BIM.length,
+							"App13 Segment missing identification string",
+							false, false);
+			if (null == imageResourceBlockSignature)
+				break;
+			if (!compareByteArrays(imageResourceBlockSignature, CONST_8BIM))
+				throw new ImageReadException(
+						"Invalid Image Resource Block Signature");
+
+			int blockType = bis
+					.read2ByteInteger("Image Resource Block missing type");
+			if (verbose)
+				Debug.debug("blockType", blockType + " (0x"
+						+ Integer.toHexString(blockType) + ")");
+
+			int blockNameLength = bis
+					.read1ByteInteger("Image Resource Block missing name length");
+			if (verbose && blockNameLength > 0)
+				Debug.debug("blockNameLength", blockNameLength + " (0x"
+						+ Integer.toHexString(blockNameLength) + ")");
+			byte[] blockNameBytes;
+			if (blockNameLength == 0)
+			{
+				bis.read1ByteInteger("Image Resource Block has invalid name");
+				blockNameBytes = new byte[0];
+			} else
+			{
+				blockNameBytes = bis.readByteArray(blockNameLength,
+						"Invalid Image Resource Block name", verbose, strict);
+				if (null == blockNameBytes)
+					break;
+
+				if (blockNameLength % 2 == 0)
+					bis
+							.read1ByteInteger("Image Resource Block missing padding byte");
+			}
+
+			int blockSize = bis
+					.read4ByteInteger("Image Resource Block missing size");
+			if (verbose)
+				Debug.debug("blockSize", blockSize + " (0x"
+						+ Integer.toHexString(blockSize) + ")");
+
+			byte[] blockData = bis.readByteArray(blockSize,
+					"Invalid Image Resource Block data", verbose, strict);
+			if (null == blockData)
+				break;
+
+			blocks.add(new IPTCBlock(blockType, blockNameBytes, blockData));
+
+			if ((blockSize % 2) != 0)
+				bis
+						.read1ByteInteger("Image Resource Block missing padding byte");
+		}
+
+		return blocks;
+	}
+
+	// private void writeIPTCRecord(BinaryOutputStream bos, )
+
+	public byte[] writePhotoshopApp13Segment(PhotoshopApp13Data data)
+			throws IOException, ImageWriteException
+	{
+		ByteArrayOutputStream os = new ByteArrayOutputStream();
+		BinaryOutputStream bos = new BinaryOutputStream(os);
+
+		bos.write(PHOTOSHOP_IDENTIFICATION_STRING);
+
+		List blocks = data.getRawBlocks();
+		for (int i = 0; i < blocks.size(); i++)
+		{
+			IPTCBlock block = (IPTCBlock) blocks.get(i);
+
+			bos.write(CONST_8BIM);
+
+			if (block.blockType < 0 || block.blockType > 0xffff)
+				throw new ImageWriteException("Invalid IPTC block type.");
+			bos.write2ByteInteger(block.blockType);
+
+			if (block.blockNameBytes.length > 255)
+				throw new ImageWriteException("IPTC block name is too long: "
+						+ block.blockNameBytes.length);
+			bos.write(block.blockNameBytes.length);
+			bos.write(block.blockNameBytes);
+			if (block.blockNameBytes.length % 2 == 0)
+				bos.write(0); // pad to even size, including length byte.
+
+			if (block.blockData.length > IPTC_NON_EXTENDED_RECORD_MAXIMUM_SIZE)
+				throw new ImageWriteException("IPTC block data is too long: "
+						+ block.blockData.length);
+			bos.write4ByteInteger(block.blockData.length);
+			bos.write(block.blockData);
+			if (block.blockData.length % 2 == 1)
+				bos.write(0); // pad to even size
+
+		}
+
+		bos.flush();
+		return os.toByteArray();
+	}
+
+	public byte[] writeIPTCBlock(List elements) throws ImageWriteException,
+			IOException
+	{
+		byte blockData[];
+		{
+			ByteArrayOutputStream baos = new ByteArrayOutputStream();
+			BinaryOutputStream bos = new BinaryOutputStream(baos,
+					getByteOrder());
+
+			// first, right record version record
+			bos.write(IPTC_RECORD_TAG_MARKER);
+			bos.write(IPTC_APPLICATION_2_RECORD_NUMBER);
+			bos.write(IPTC_TYPE_RECORD_VERSION.type); // record version record type.
+			bos.write2Bytes(2); // record version record size
+			bos.write2Bytes(2); // record version value
+
+			// make a copy of the list.
+			elements = new ArrayList(elements);
+
+			// sort the list. Records must be in numerical order.
+			Comparator comparator = new Comparator() {
+				public int compare(Object o1, Object o2)
+				{
+					IPTCRecord e1 = (IPTCRecord) o1;
+					IPTCRecord e2 = (IPTCRecord) o2;
+					return e2.iptcType.type - e1.iptcType.type;
+				}
+			};
+			Collections.sort(elements, comparator);
+			// TODO: make sure order right
+
+			// write the list.
+			for (int i = 0; i < elements.size(); i++)
+			{
+				IPTCRecord element = (IPTCRecord) elements.get(i);
+				
+				if(element.iptcType.type == IPTC_TYPE_RECORD_VERSION.type)
+					continue; // ignore
+				
+				bos.write(IPTC_RECORD_TAG_MARKER);
+				bos.write(IPTC_APPLICATION_2_RECORD_NUMBER);
+				if (element.iptcType.type < 0 || element.iptcType.type > 0xff)
+					throw new ImageWriteException("Invalid record type: "
+							+ element.iptcType.type);
+				bos.write(element.iptcType.type);
+
+				byte recordData[] = element.value.getBytes("ISO-8859-1");
+				if (!new String(recordData, "ISO-8859-1").equals(element.value))
+					throw new ImageWriteException(
+							"Invalid record value, not ISO-8859-1");
+
+				bos.write2Bytes(recordData.length);
+				bos.write(recordData);
+			}
+
+			blockData = baos.toByteArray();
+		}
+		
+		return blockData;
+	}
+
+}

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,51 @@
+/*
+ * 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.jpeg.iptc;
+
+import java.util.Comparator;
+
+public class IPTCRecord
+{
+	public final IPTCType iptcType;
+	public final String value;
+
+	public IPTCRecord(IPTCType iptcType, String value)
+	{
+		this.iptcType = iptcType;
+		this.value = value;
+	}
+
+	public String getValue()
+	{
+		return value;
+	}
+
+	public String getIptcTypeName()
+	{
+		return iptcType.name;
+	}
+
+	public static final Comparator COMPARATOR = new Comparator() {
+		public int compare(Object o1, Object o2)
+		{
+			IPTCRecord e1 = (IPTCRecord) o1;
+			IPTCRecord e2 = (IPTCRecord) o2;
+			return e1.iptcType.type - e2.iptcType.type;
+		}
+	};
+
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,39 @@
+/*
+ * 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.jpeg.iptc;
+
+import org.apache.sanselan.formats.jpeg.JpegConstants;
+
+public class IPTCType implements JpegConstants, IPTCConstants {
+	public final int type;
+	public final String name;
+
+	public IPTCType(int type, String name) {
+		this.type = type;
+		this.name = name;
+	}
+
+	public String toString() {
+		return name + " (" + type + ")";
+	}
+	
+	public static IPTCType getUnknown(int type)
+	{
+		return new IPTCType(type, "Unknown");
+	}
+
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,39 @@
+/*
+ * 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.jpeg.iptc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class IPTCTypeLookup implements IPTCConstants {
+
+	private static final Map IPTC_TYPE_MAP = new HashMap();
+	static {
+		for (int i = 0; i < IPTC_TYPES.length; i++) {
+			IPTCType iptcType = IPTC_TYPES[i];
+			Integer key = new Integer(iptcType.type);
+			IPTC_TYPE_MAP.put(key, iptcType);
+		}
+	}
+
+	public static final IPTCType getIptcType(int type) {
+		Integer key = new Integer(type);
+		if (!IPTC_TYPE_MAP.containsKey(key))
+			return IPTCType.getUnknown(type);
+		return (IPTCType) IPTC_TYPE_MAP.get(key);
+	}
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,259 @@
+/*
+ * 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.jpeg.iptc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.common.byteSources.ByteSourceArray;
+import org.apache.sanselan.common.byteSources.ByteSourceFile;
+import org.apache.sanselan.common.byteSources.ByteSourceInputStream;
+import org.apache.sanselan.formats.jpeg.xmp.JpegRewriter;
+import org.apache.sanselan.util.Debug;
+
+/**
+ * Interface for Exif write/update/remove functionality for Jpeg/JFIF images.
+ * <p>
+ * <p>
+ * See the source of the IPTCUpdateExample class for example usage.
+ * 
+ * @see org.apache.sanselan.sampleUsage.WriteIPTCExample
+ */
+public class JpegIptcRewriter extends JpegRewriter implements IPTCConstants
+{
+
+	/**
+	 * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * <p>
+	 * 
+	 * @param src
+	 *            Image file.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 * 
+	 * @see java.io.File
+	 * @see java.io.OutputStream
+	 */
+	public void removeIPTC(File src, OutputStream os)
+			throws ImageReadException, IOException, ImageWriteException
+	{
+		ByteSource byteSource = new ByteSourceFile(src);
+		removeIPTC(byteSource, os);
+	}
+
+	/**
+	 * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * <p>
+	 * 
+	 * @param src
+	 *            Byte array containing Jpeg image data.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 */
+	public void removeIPTC(byte src[], OutputStream os)
+			throws ImageReadException, IOException, ImageWriteException
+	{
+		ByteSource byteSource = new ByteSourceArray(src);
+		removeIPTC(byteSource, os);
+	}
+
+	/**
+	 * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * <p>
+	 * 
+	 * @param src
+	 *            InputStream containing Jpeg image data.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 */
+	public void removeIPTC(InputStream src, OutputStream os)
+			throws ImageReadException, IOException, ImageWriteException
+	{
+		ByteSource byteSource = new ByteSourceInputStream(src, null);
+		removeIPTC(byteSource, os);
+	}
+
+	/**
+	 * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * <p>
+	 * 
+	 * @param byteSource
+	 *            ByteSource containing Jpeg image data.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 */
+	public void removeIPTC(ByteSource byteSource, OutputStream os)
+			throws ImageReadException, IOException, ImageWriteException
+	{
+		JFIFPieces jfifPieces = analyzeJFIF(byteSource);
+		List oldPieces = jfifPieces.pieces;
+		List photoshopApp13Segments = findPhotoshopApp13Segments(oldPieces);
+
+		if (photoshopApp13Segments.size() > 1)
+			throw new ImageReadException(
+					"Image contains more than one Photoshop App13 segment.");
+		List newPieces = removePhotoshopApp13Segments(oldPieces);
+		if (photoshopApp13Segments.size() == 1)
+		{
+			JFIFPieceSegment oldSegment = (JFIFPieceSegment) photoshopApp13Segments
+					.get(0);
+			Map params = new HashMap();
+			PhotoshopApp13Data oldData = new IPTCParser()
+					.parsePhotoshopSegment(oldSegment.segmentData, params);
+			List newBlocks = oldData.getNonIptcBlocks();
+			List newRecords = new ArrayList();
+			PhotoshopApp13Data newData = new PhotoshopApp13Data(newRecords,
+					newBlocks);
+			byte segmentBytes[] = new IPTCParser()
+					.writePhotoshopApp13Segment(newData);
+			JFIFPieceSegment newSegment = new JFIFPieceSegment(
+					oldSegment.marker, segmentBytes);
+			newPieces.add(oldPieces.indexOf(oldSegment), newSegment);
+		}
+		writeSegments(os, newPieces);
+	}
+
+	/**
+	 * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * 
+	 * @param src
+	 *            Byte array containing Jpeg image data.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 * @param xmpXml
+	 *            String containing IPTC data.
+	 */
+	public void writeIPTC(byte src[], OutputStream os,
+			PhotoshopApp13Data newData) throws ImageReadException, IOException,
+			ImageWriteException
+	{
+		ByteSource byteSource = new ByteSourceArray(src);
+		writeIPTC(byteSource, os, newData);
+	}
+
+	/**
+	 * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * 
+	 * @param src
+	 *            InputStream containing Jpeg image data.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 * @param xmpXml
+	 *            String containing IPTC data.
+	 */
+	public void writeIPTC(InputStream src, OutputStream os,
+			PhotoshopApp13Data newData) throws ImageReadException, IOException,
+			ImageWriteException
+	{
+		ByteSource byteSource = new ByteSourceInputStream(src, null);
+		writeIPTC(byteSource, os, newData);
+	}
+
+	/**
+	 * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * 
+	 * @param src
+	 *            Image file.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 * @param xmpXml
+	 *            String containing IPTC data.
+	 */
+	public void writeIPTC(File src, OutputStream os, PhotoshopApp13Data newData)
+			throws ImageReadException, IOException, ImageWriteException
+	{
+		ByteSource byteSource = new ByteSourceFile(src);
+		writeIPTC(byteSource, os, newData);
+	}
+
+	/**
+	 * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+	 * leaves the other data in that segment (if present) unchanged and writes
+	 * the result to a stream.
+	 * 
+	 * @param byteSource
+	 *            ByteSource containing Jpeg image data.
+	 * @param os
+	 *            OutputStream to write the image to.
+	 * @param xmpXml
+	 *            String containing IPTC data.
+	 */
+	public void writeIPTC(ByteSource byteSource, OutputStream os,
+			PhotoshopApp13Data newData) throws ImageReadException, IOException,
+			ImageWriteException
+	{
+		JFIFPieces jfifPieces = analyzeJFIF(byteSource);
+		List oldPieces = jfifPieces.pieces;
+		List photoshopApp13Segments = findPhotoshopApp13Segments(oldPieces);
+
+		if (photoshopApp13Segments.size() > 1)
+			throw new ImageReadException(
+					"Image contains more than one Photoshop App13 segment.");
+		List newPieces = removePhotoshopApp13Segments(oldPieces);
+
+		{
+			// discard old iptc blocks.
+			List newBlocks = newData.getNonIptcBlocks();
+			byte[] newBlockBytes = new IPTCParser().writeIPTCBlock(newData
+					.getRecords());
+			
+			int blockType = IMAGE_RESOURCE_BLOCK_IPTC_DATA;
+			byte[] blockNameBytes = new byte[0];
+			IPTCBlock newBlock = new IPTCBlock(blockType, blockNameBytes,
+					newBlockBytes);
+			newBlocks.add(newBlock);
+			
+			newData = new PhotoshopApp13Data(newData.getRecords(), newBlocks);
+
+			byte segmentBytes[] = new IPTCParser()
+					.writePhotoshopApp13Segment(newData);
+			JFIFPieceSegment newSegment = new JFIFPieceSegment(
+					JPEG_APP13_Marker, segmentBytes);
+
+			newPieces = insertAfterLastAppSegments(newPieces, Arrays
+					.asList(new JFIFPieceSegment[] { newSegment, }));
+		}
+
+		writeSegments(os, newPieces);
+	}
+
+}
\ No newline at end of file

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,69 @@
+/*
+ * 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.jpeg.iptc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.SanselanConstants;
+import org.apache.sanselan.common.BinaryFileParser;
+import org.apache.sanselan.common.BinaryOutputStream;
+import org.apache.sanselan.util.Debug;
+import org.apache.sanselan.util.ParamMap;
+
+public class PhotoshopApp13Data implements IPTCConstants
+{
+	private final List records;
+	private final List rawBlocks;
+
+	public PhotoshopApp13Data(List records, List rawBlocks)
+	{
+		this.rawBlocks = rawBlocks;
+		this.records = records;
+	}
+
+	public List getRecords()
+	{
+		return new ArrayList(records);
+	}
+
+	public List getRawBlocks()
+	{
+		return new ArrayList(rawBlocks);
+	}
+
+	public List getNonIptcBlocks()
+	{
+		List result = new ArrayList();
+		for (int i = 0; i < rawBlocks.size(); i++)
+		{
+			IPTCBlock block = (IPTCBlock) rawBlocks.get(i);
+			if (!block.isIPTCBlock())
+				result.add(block);
+		}
+		return result;
+	}
+
+}

Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java
------------------------------------------------------------------------------
    svn:eol-style = native