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/07/27 18:59:47 UTC

svn commit: r680163 - in /incubator/sanselan/trunk/src: main/java/org/apache/sanselan/ main/java/org/apache/sanselan/formats/bmp/ main/java/org/apache/sanselan/formats/gif/ main/java/org/apache/sanselan/formats/ico/ main/java/org/apache/sanselan/format...

Author: cmchen
Date: Sun Jul 27 11:59:46 2008
New Revision: 680163

URL: http://svn.apache.org/viewvc?rev=680163&view=rev
Log:
Added xmp-extraction to Tiff and Gif parsers.

Added:
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifBaseTest.java   (with props)
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifReadTest.java   (with props)
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java   (with props)
Modified:
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.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/TiffImageParser.java
    incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/constants/TiffTagConstants.java
    incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java Sun Jul 27 11:59:46 2008
@@ -44,14 +44,16 @@
 import org.apache.sanselan.util.Debug;
 
 public abstract class ImageParser extends BinaryFileParser implements
-		SanselanConstants {
+		SanselanConstants
+{
 
-	public static final ImageParser[] getAllImageParsers() {
+	public static final ImageParser[] getAllImageParsers()
+	{
 		ImageParser result[] = { new JpegImageParser(), new TiffImageParser(),
 				new PngImageParser(), new BmpImageParser(),
 				new GifImageParser(), new PsdImageParser(),
 				new PNMImageParser(), new IcoImageParser(),
-				//new JBig2ImageParser(),
+		// new JBig2ImageParser(),
 		// new TgaImageParser(),
 		};
 
@@ -59,7 +61,8 @@
 	}
 
 	public final IImageMetadata getMetadata(ByteSource byteSource)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getMetadata(byteSource, null);
 	}
 
@@ -67,22 +70,26 @@
 			throws ImageReadException, IOException;
 
 	public final IImageMetadata getMetadata(byte bytes[])
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getMetadata(bytes);
 	}
 
 	public final IImageMetadata getMetadata(byte bytes[], Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getMetadata(new ByteSourceArray(bytes), params);
 	}
 
 	public final IImageMetadata getMetadata(File file)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getMetadata(file, null);
 	}
 
 	public final IImageMetadata getMetadata(File file, Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		if (debug)
 			System.out.println(getName() + ".getMetadata" + ": "
 					+ file.getName());
@@ -97,17 +104,20 @@
 			throws ImageReadException, IOException;
 
 	public final ImageInfo getImageInfo(ByteSource byteSource)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getImageInfo(byteSource, null);
 	}
 
 	public final ImageInfo getImageInfo(byte bytes[], Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getImageInfo(new ByteSourceArray(bytes), params);
 	}
 
 	public final ImageInfo getImageInfo(File file, Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		if (!canAcceptExtension(file))
 			return null;
 
@@ -115,17 +125,20 @@
 	}
 
 	public FormatCompliance getFormatCompliance(ByteSource byteSource)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return null;
 	}
 
 	public final FormatCompliance getFormatCompliance(byte bytes[])
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getFormatCompliance(new ByteSourceArray(bytes));
 	}
 
 	public final FormatCompliance getFormatCompliance(File file)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		if (!canAcceptExtension(file))
 			return null;
 
@@ -133,7 +146,8 @@
 	}
 
 	public ArrayList getAllBufferedImages(ByteSource byteSource)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		BufferedImage bi = getBufferedImage(byteSource, null);
 
 		ArrayList result = new ArrayList();
@@ -144,12 +158,14 @@
 	}
 
 	public final ArrayList getAllBufferedImages(byte bytes[])
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getAllBufferedImages(new ByteSourceArray(bytes));
 	}
 
 	public final ArrayList getAllBufferedImages(File file)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		if (!canAcceptExtension(file))
 			return null;
 
@@ -201,12 +217,14 @@
 			Map params) throws ImageReadException, IOException;
 
 	public final BufferedImage getBufferedImage(byte bytes[], Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getBufferedImage(new ByteSourceArray(bytes), params);
 	}
 
 	public final BufferedImage getBufferedImage(File file, Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		if (!canAcceptExtension(file))
 			return null;
 
@@ -214,10 +232,13 @@
 	}
 
 	public void writeImage(BufferedImage src, OutputStream os, Map params)
-			throws ImageWriteException, IOException {
-		try {
+			throws ImageWriteException, IOException
+	{
+		try
+		{
 			os.close(); // we are obligated to close stream.
-		} catch (Exception e) {
+		} catch (Exception e)
+		{
 			Debug.debug(e);
 		}
 
@@ -226,23 +247,27 @@
 	}
 
 	public final Dimension getImageSize(byte bytes[])
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getImageSize(bytes, null);
 	}
 
 	public final Dimension getImageSize(byte bytes[], Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getImageSize(new ByteSourceArray(bytes), params);
 	}
 
 	public final Dimension getImageSize(File file) throws ImageReadException,
-			IOException {
+			IOException
+	{
 
 		return getImageSize(file, null);
 	}
 
 	public final Dimension getImageSize(File file, Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 
 		if (!canAcceptExtension(file))
 			return null;
@@ -253,23 +278,30 @@
 	public abstract Dimension getImageSize(ByteSource byteSource, Map params)
 			throws ImageReadException, IOException;
 
+	public abstract String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException;
+
 	public final byte[] getICCProfileBytes(byte bytes[])
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getICCProfileBytes(bytes, null);
 	}
 
 	public final byte[] getICCProfileBytes(byte bytes[], Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getICCProfileBytes(new ByteSourceArray(bytes), params);
 	}
 
 	public final byte[] getICCProfileBytes(File file)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return getICCProfileBytes(file, null);
 	}
 
 	public final byte[] getICCProfileBytes(File file, Map params)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		if (!canAcceptExtension(file))
 			return null;
 
@@ -283,12 +315,14 @@
 			throws ImageReadException, IOException;
 
 	public final String dumpImageFile(byte bytes[]) throws ImageReadException,
-			IOException {
+			IOException
+	{
 		return dumpImageFile(new ByteSourceArray(bytes));
 	}
 
 	public final String dumpImageFile(File file) throws ImageReadException,
-			IOException {
+			IOException
+	{
 		if (!canAcceptExtension(file))
 			return null;
 
@@ -299,7 +333,8 @@
 	}
 
 	public final String dumpImageFile(ByteSource byteSource)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		StringWriter sw = new StringWriter();
 		PrintWriter pw = new PrintWriter(sw);
 
@@ -311,7 +346,8 @@
 	}
 
 	public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
-			throws ImageReadException, IOException {
+			throws ImageReadException, IOException
+	{
 		return false;
 	}
 
@@ -325,7 +361,8 @@
 
 	protected abstract ImageFormat[] getAcceptedTypes();
 
-	public boolean canAcceptType(ImageFormat type) {
+	public boolean canAcceptType(ImageFormat type)
+	{
 		ImageFormat types[] = getAcceptedTypes();
 
 		for (int i = 0; i < types.length; i++)
@@ -334,17 +371,20 @@
 		return false;
 	}
 
-	protected final boolean canAcceptExtension(File file) {
+	protected final boolean canAcceptExtension(File file)
+	{
 		return canAcceptExtension(file.getName());
 	}
 
-	protected final boolean canAcceptExtension(String filename) {
+	protected final boolean canAcceptExtension(String filename)
+	{
 		String exts[] = getAcceptedExtensions();
 		if (exts == null)
 			return true;
 
 		int index = filename.lastIndexOf('.');
-		if (index >= 0) {
+		if (index >= 0)
+		{
 			String ext = filename.substring(index);
 			ext = ext.toLowerCase();
 
@@ -355,7 +395,8 @@
 		return false;
 	}
 
-	protected IBufferedImageFactory getBufferedImageFactory(Map params) {
+	protected IBufferedImageFactory getBufferedImageFactory(Map params)
+	{
 		if (params == null)
 			return new SimpleBufferedImageFactory();
 
@@ -368,7 +409,8 @@
 		return new SimpleBufferedImageFactory();
 	}
 
-	public static final boolean isStrict(Map params) {
+	public static final boolean isStrict(Map params)
+	{
 		if (params == null || !params.containsKey(PARAM_KEY_STRICT))
 			return false;
 		return ((Boolean) params.get(PARAM_KEY_STRICT)).booleanValue();

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/Sanselan.java Sun Jul 27 11:59:46 2008
@@ -621,6 +621,7 @@
 		throw new ImageReadException("Can't parse this format.");
 	}
 
+
 	/**
 	 * Determines the width and height of an image.
 	 * <p>
@@ -715,6 +716,112 @@
 
 		return imageParser.getImageSize(byteSource, params);
 	}
+	
+
+	/**
+	 * Determines the width and height of an image.
+	 * <p>
+	 * 
+	 * @param is
+	 *            InputStream from which to read image data.
+	 * @param filename
+	 *            Filename associated with image data (optional).
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public static String getXmpXml(InputStream is, String filename)
+			throws ImageReadException, IOException {
+		return getXmpXml(is, filename, null);
+	}
+
+	/**
+	 * Determines the width and height of an image.
+	 * <p>
+	 * 
+	 * @param is
+	 *            InputStream from which to read image data.
+	 * @param filename
+	 *            Filename associated with image data (optional).
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public static String getXmpXml(InputStream is, String filename,
+			Map params) throws ImageReadException, IOException {
+		return getXmpXml(new ByteSourceInputStream(is, filename), params);
+	}
+
+	/**
+	 * Determines the width and height of an image.
+	 * <p>
+	 * 
+	 * @param bytes
+	 *            Byte array containing an image file.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public static String getXmpXml(byte bytes[])
+			throws ImageReadException, IOException {
+		return getXmpXml(bytes, null);
+	}
+
+	/**
+	 * Determines the width and height of an image.
+	 * <p>
+	 * 
+	 * @param bytes
+	 *            Byte array containing an image file.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public static String getXmpXml(byte bytes[], Map params)
+			throws ImageReadException, IOException {
+		return getXmpXml(new ByteSourceArray(bytes), params);
+	}
+
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public static String getXmpXml(File file) throws ImageReadException,
+			IOException {
+		return getXmpXml(file, null);
+	}
+
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public static String getXmpXml(File file, Map params)
+			throws ImageReadException, IOException {
+		return getXmpXml(new ByteSourceFile(file), params);
+	}
+
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public static String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException {
+		ImageParser imageParser = getImageParser(byteSource);
+
+		return imageParser.getXmpXml(byteSource, params);
+	}
 
 	/**
 	 * Parses the metadata of an image. This metadata depends on the format of

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/bmp/BmpImageParser.java Sun Jul 27 11:59:46 2008
@@ -655,4 +655,20 @@
 		}
 	}
 
+
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException {
+		return null;
+	}
+
 }
\ No newline at end of file

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/gif/GifImageParser.java Sun Jul 27 11:59:46 2008
@@ -25,8 +25,10 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.sanselan.FormatCompliance;
@@ -222,10 +224,11 @@
 	private final static int GRAPHIC_CONTROL_EXTENSION = (0x2100 | 0xf9);
 	private final static int COMMENT_EXTENSION = 0xfe;
 	private final static int PLAIN_TEXT_EXTENSION = 0x01;
+	private final static int XMP_EXTENSION = 0xff;
 	private final static int TERMINATOR_BYTE = 0x3b;
 
 	private ArrayList readBlocks(GIFHeaderInfo ghi, InputStream is,
-			boolean stop_before_image_data, FormatCompliance formatCompliance)
+			boolean stopBeforeImageData, FormatCompliance formatCompliance)
 			throws ImageReadException, IOException
 	{
 		ArrayList result = new ArrayList();
@@ -233,7 +236,7 @@
 		while (true)
 		{
 			int code = is.read();
-			// this.debugNumber("code: ", code);
+//			 this.debugNumber("code: ", code);
 
 			switch (code)
 			{
@@ -242,8 +245,10 @@
 
 			case IMAGE_SEPARATOR:
 				ImageDescriptor id = readImageDescriptor(ghi, code, is,
-						stop_before_image_data, formatCompliance);
+						stopBeforeImageData, formatCompliance);
 				result.add(id);
+//				if(stopBeforeImageData)
+//					return result;
 
 				break;
 
@@ -262,13 +267,7 @@
 					result.add(gce);
 					break;
 
-				case COMMENT_EXTENSION: {
-					GenericGIFBlock block = readGenericGIFBlock(is,
-							complete_code);
-					result.add(block);
-					break;
-				}
-
+				case COMMENT_EXTENSION:
 				case PLAIN_TEXT_EXTENSION: {
 					GenericGIFBlock block = readGenericGIFBlock(is,
 							complete_code);
@@ -330,7 +329,7 @@
 	}
 
 	private ImageDescriptor readImageDescriptor(GIFHeaderInfo ghi,
-			int blockCode, InputStream is, boolean stop_before_image_data,
+			int blockCode, InputStream is, boolean stopBeforeImageData,
 			FormatCompliance formatCompliance) throws ImageReadException,
 			IOException
 	{
@@ -379,7 +378,7 @@
 					formatCompliance);
 
 		byte imageData[] = null;
-		if (!stop_before_image_data)
+		if (!stopBeforeImageData)
 		{
 			int LZWMinimumCodeSize = is.read();
 
@@ -461,23 +460,22 @@
 	{
 		for (int i = 0; i < v.size(); i++)
 		{
-			GIFBlock fGIFBlock = (GIFBlock) v.get(i);
-			if (fGIFBlock.blockCode == code)
-				return fGIFBlock;
+			GIFBlock gifBlock = (GIFBlock) v.get(i);
+			if (gifBlock.blockCode == code)
+				return gifBlock;
 		}
 		return null;
 	}
 
 	private ImageContents readFile(ByteSource byteSource,
-			boolean stop_before_image_data) throws ImageReadException,
-			IOException
+			boolean stopBeforeImageData) throws ImageReadException, IOException
 	{
-		return readFile(byteSource, stop_before_image_data, FormatCompliance
+		return readFile(byteSource, stopBeforeImageData, FormatCompliance
 				.getDefault());
 	}
 
 	private ImageContents readFile(ByteSource byteSource,
-			boolean stop_before_image_data, FormatCompliance formatCompliance)
+			boolean stopBeforeImageData, FormatCompliance formatCompliance)
 			throws ImageReadException, IOException
 	{
 		InputStream is = null;
@@ -492,7 +490,7 @@
 				globalColorTable = readColorTable(is,
 						ghi.sizeOfGlobalColorTable, formatCompliance);
 
-			ArrayList blocks = readBlocks(ghi, is, stop_before_image_data,
+			ArrayList blocks = readBlocks(ghi, is, stopBeforeImageData,
 					formatCompliance);
 
 			ImageContents result = new ImageContents(ghi, globalColorTable,
@@ -652,10 +650,10 @@
 			pw.println("gif.blocks: " + blocks.blocks.size());
 			for (int i = 0; i < blocks.blocks.size(); i++)
 			{
-				GIFBlock fGIFBlock = (GIFBlock) blocks.blocks.get(i);
+				GIFBlock gifBlock = (GIFBlock) blocks.blocks.get(i);
 				this.debugNumber(pw, "\t" + i + " ("
-						+ fGIFBlock.getClass().getName() + ")",
-						fGIFBlock.blockCode, 4);
+						+ gifBlock.getClass().getName() + ")",
+						gifBlock.blockCode, 4);
 			}
 
 		}
@@ -1045,4 +1043,107 @@
 		bos.close();
 		os.close();
 	}
+
+	private static final byte XMP_APPLICATION_ID_AND_AUTH_CODE[] = { 0x58, // X
+			0x4D, // M
+			0x50, // P
+			0x20, //
+			0x44, // D
+			0x61, // a
+			0x74, // t
+			0x61, // a
+			0x58, // X
+			0x4D, // M
+			0x50, // P
+	};
+
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present. Otherwise, returns null..
+	 */
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException
+	{
+
+		InputStream is = null;
+		try
+		{
+			is = byteSource.getInputStream();
+
+			FormatCompliance formatCompliance = null;
+			GIFHeaderInfo ghi = readHeader(is, formatCompliance);
+
+
+			byte globalColorTable[] = null;
+			if (ghi.globalColorTableFlag)
+				globalColorTable = readColorTable(is,
+						ghi.sizeOfGlobalColorTable, formatCompliance);
+			
+			ArrayList blocks = readBlocks(ghi, is, true, formatCompliance);
+
+			List result = new ArrayList();
+			for (int i = 0; i < blocks.size(); i++)
+			{
+				GIFBlock block = (GIFBlock) blocks.get(i);
+				if (block.blockCode != XMP_EXTENSION)
+					continue;
+
+				GenericGIFBlock genericBlock = (GenericGIFBlock) block;
+
+				byte blockBytes[] = genericBlock.appendSubBlocks();
+				if (blockBytes.length < XMP_APPLICATION_ID_AND_AUTH_CODE.length)
+					continue;
+				if (!compareByteArrays(blockBytes, 0,
+						XMP_APPLICATION_ID_AND_AUTH_CODE, 0,
+						XMP_APPLICATION_ID_AND_AUTH_CODE.length))
+					continue;
+				
+//				this.debugByteArray("xmp block bytes", blockBytes);
+				byte GIF_MAGIC_TRAILER[] = new byte[256];
+				for(int magic=0;magic<=0xff;magic++)
+					GIF_MAGIC_TRAILER[magic] = (byte) (0xff-magic);
+				
+				if (blockBytes.length < XMP_APPLICATION_ID_AND_AUTH_CODE.length + GIF_MAGIC_TRAILER.length)
+					continue;
+				if (!compareByteArrays(blockBytes, blockBytes.length-GIF_MAGIC_TRAILER.length,
+						GIF_MAGIC_TRAILER, 0,
+						GIF_MAGIC_TRAILER.length))
+					throw new ImageReadException("XMP block in GIF missing magic trailer.");
+				
+				try
+				{
+					// XMP is UTF-8 encoded xml.
+					String xml = new String(blockBytes, XMP_APPLICATION_ID_AND_AUTH_CODE.length, blockBytes.length
+							- (XMP_APPLICATION_ID_AND_AUTH_CODE.length + GIF_MAGIC_TRAILER.length), "utf-8");
+					result.add(xml);
+				} catch (UnsupportedEncodingException e)
+				{
+					throw new ImageReadException("Invalid XMP Block in GIF.");
+				}
+			}
+			
+			if(result.size()<1)
+				return null;
+			if(result.size()>1)
+				throw new ImageReadException("More than one XMP Block in GIF.");
+			return (String) result.get(0);
+
+		} finally
+		{
+			try
+			{
+				is.close();
+			} catch (Exception e)
+			{
+				Debug.debug(e);
+			}
+
+		}
+	}
 }
\ No newline at end of file

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/ico/IcoImageParser.java Sun Jul 27 11:59:46 2008
@@ -539,4 +539,18 @@
 	//		return true;
 	//	}
 
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException {
+		return null;
+	}
 }
\ No newline at end of file

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=680163&r1=680162&r2=680163&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 Jul 27 11:59:46 2008
@@ -309,6 +309,7 @@
 		if (null == exif && null == photoshop)
 			return null;
 
+		
 		JpegImageMetadata result = new JpegImageMetadata(photoshop, exif);
 
 		return result;
@@ -488,14 +489,19 @@
 		return result[0];
 	}
 
-	/*
-	 * Locates the XMP XML if present.
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
 	 * 
-	 * returns null if no XMP segment is found.
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
 	 */
-	public String getXmpXml(ByteSource byteSource) throws ImageReadException,
-			IOException
-	{
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException {
+
 		final List result = new ArrayList();
 
 		JpegUtils.Visitor visitor = new JpegUtils.Visitor() {

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/png/PngImageParser.java Sun Jul 27 11:59:46 2008
@@ -845,4 +845,20 @@
 	{
 		new PngWriter(params).writeImage(src, os, params);
 	}
+	
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException {
+		// TODO: implement.
+		return null;
+	}
 }

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/pnm/PNMImageParser.java Sun Jul 27 11:59:46 2008
@@ -313,4 +313,18 @@
 		writer.writeImage(src, os, params);
 	}
 
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException {
+		return null;
+	}
 }
\ No newline at end of file

Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/psd/PsdImageParser.java Sun Jul 27 11:59:46 2008
@@ -733,4 +733,19 @@
 
 	}
 
+	/**
+	 * Extracts embedded XML metadata as XML string.
+	 * <p>
+	 * 
+	 * @param file
+	 *            File containing image data.
+	 * @param params
+	 *            Map of optional parameters, defined in SanselanConstants.
+	 * @return Xmp Xml as String, if present.  Otherwise, returns null..
+	 */
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException {
+		// TODO: implement.
+		return null;
+	}
 }
\ No newline at end of file

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=680163&r1=680162&r2=680163&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 Jul 27 11:59:46 2008
@@ -34,7 +34,8 @@
 import org.apache.sanselan.formats.tiff.fieldtypes.FieldType;
 import org.apache.sanselan.util.Debug;
 
-public class TiffField implements TiffConstants {
+public class TiffField implements TiffConstants
+{
 	public final TagInfo tagInfo;
 	public final FieldType fieldType;
 
@@ -49,7 +50,8 @@
 	public final int byteOrder;
 
 	public TiffField(int tag, int directoryType, int type, int Length,
-			int ValueOffset, byte ValueOffsetBytes[], int byteOrder) {
+			int ValueOffset, byte ValueOffsetBytes[], int byteOrder)
+	{
 
 		this.tag = tag;
 		this.directoryType = directoryType;
@@ -65,20 +67,25 @@
 
 	private int sortHint = -1;
 
-	public boolean isLocalValue() {
+	public boolean isLocalValue()
+	{
 		return fieldType.isLocalValue(this);
 	}
 
-	public int getBytesLength() throws ImageReadException {
+	public int getBytesLength() throws ImageReadException
+	{
 		return fieldType.getBytesLength(this);
 	}
 
-	public final class OversizeValueElement extends TiffElement {
-		public OversizeValueElement(int offset, int length) {
+	public final class OversizeValueElement extends TiffElement
+	{
+		public OversizeValueElement(int offset, int length)
+		{
 			super(offset, length);
 		}
 
-		public String getElementDescription(boolean verbose) {
+		public String getElementDescription(boolean verbose)
+		{
 			if (verbose)
 				return null;
 
@@ -87,19 +94,23 @@
 		}
 	}
 
-	public TiffElement getOversizeValueElement() {
+	public TiffElement getOversizeValueElement()
+	{
 		if (fieldType.isLocalValue(this))
 			return null;
 
 		return new OversizeValueElement(valueOffset, oversizeValue.length);
 	}
 
-	public void setOversizeValue(byte bytes[]) {
+	public void setOversizeValue(byte bytes[])
+	{
 		this.oversizeValue = bytes;
 	}
 
-	private static FieldType getFieldType(int value) {
-		for (int i = 0; i < FIELD_TYPES.length; i++) {
+	private static FieldType getFieldType(int value)
+	{
+		for (int i = 0; i < FIELD_TYPES.length; i++)
+		{
 			FieldType fieldType = FIELD_TYPES[i];
 			if (fieldType.type == value)
 				return fieldType;
@@ -109,7 +120,8 @@
 	}
 
 	private static TagInfo getTag(int directoryType, int tag,
-			List possibleMatches) {
+			List possibleMatches)
+	{
 		if (possibleMatches.size() < 1)
 			return null;
 		// else if (possibleMatches.size() == 1)
@@ -119,7 +131,8 @@
 		// }
 
 		// first search for exact match.
-		for (int i = 0; i < possibleMatches.size(); i++) {
+		for (int i = 0; i < possibleMatches.size(); i++)
+		{
 			TagInfo tagInfo = (TagInfo) possibleMatches.get(i);
 			if (tagInfo.directoryType == EXIF_DIRECTORY_UNKNOWN)
 				// pass
@@ -151,7 +164,8 @@
 		}
 
 		// accept an inexact match.
-		for (int i = 0; i < possibleMatches.size(); i++) {
+		for (int i = 0; i < possibleMatches.size(); i++)
+		{
 			TagInfo tagInfo = (TagInfo) possibleMatches.get(i);
 
 			if (tagInfo.directoryType == EXIF_DIRECTORY_UNKNOWN)
@@ -166,7 +180,8 @@
 		}
 
 		// accept a wildcard match.
-		for (int i = 0; i < possibleMatches.size(); i++) {
+		for (int i = 0; i < possibleMatches.size(); i++)
+		{
 			TagInfo tagInfo = (TagInfo) possibleMatches.get(i);
 
 			if (tagInfo.directoryType == EXIF_DIRECTORY_UNKNOWN)
@@ -254,12 +269,14 @@
 		// return TIFF_TAG_UNKNOWN;
 	}
 
-	private static TagInfo getTag(int directoryType, int tag) {
+	private static TagInfo getTag(int directoryType, int tag)
+	{
 		Object key = new Integer(tag);
 
 		List possibleMatches = (List) EXIF_TAG_MAP.get(key);
 
-		if (null == possibleMatches) {
+		if (null == possibleMatches)
+		{
 			return TIFF_TAG_UNKNOWN;
 		}
 
@@ -267,59 +284,71 @@
 		return result;
 	}
 
-	private int getValueLengthInBytes() {
+	private int getValueLengthInBytes()
+	{
 		int unit_length = fieldType.length;
 		int valueLength = unit_length * length;
 
-//		Debug.debug("getValueLengthInBytes unit_length", unit_length);
-//		Debug.debug("getValueLengthInBytes length", length);
+		// Debug.debug("getValueLengthInBytes unit_length", unit_length);
+		// Debug.debug("getValueLengthInBytes length", length);
 
 		return valueLength;
 	}
 
 	public void fillInValue(ByteSource byteSource) throws ImageReadException,
-			IOException {
+			IOException
+	{
 		if (fieldType.isLocalValue(this))
 			return;
 
 		int valueLength = getValueLengthInBytes();
 
-//		Debug.debug("fillInValue tag", tag);
-//		Debug.debug("fillInValue tagInfo", tagInfo);
-//		Debug.debug("fillInValue valueOffset", valueOffset);
-//		Debug.debug("fillInValue valueLength", valueLength);
+		// Debug.debug("fillInValue tag", tag);
+		// Debug.debug("fillInValue tagInfo", tagInfo);
+		// Debug.debug("fillInValue valueOffset", valueOffset);
+		// Debug.debug("fillInValue valueLength", valueLength);
 
 		byte bytes[] = byteSource.getBlock(valueOffset, valueLength);
 		setOversizeValue(bytes);
 	}
 
-	public String getValueDescription() {
-		try {
+	public String getValueDescription()
+	{
+		try
+		{
 			return getValueDescription(getValue());
-		} catch (ImageReadException e) {
+		} catch (ImageReadException e)
+		{
 			return "Invalid value: " + e.getMessage();
 		}
 	}
 
-	private String getValueDescription(Object o) {
+	private String getValueDescription(Object o)
+	{
 		if (o == null)
 			return null;
 
-		if (o instanceof Number) {
+		if (o instanceof Number)
+		{
 			return o.toString();
-		} else if (o instanceof String) {
+		} else if (o instanceof String)
+		{
 			return "'" + o.toString().trim() + "'";
-		} else if (o instanceof Date) {
+		} else if (o instanceof Date)
+		{
 			DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
 			return df.format((Date) o);
-		} else if (o instanceof Object[]) {
+		} else if (o instanceof Object[])
+		{
 			Object objects[] = (Object[]) o;
 			StringBuffer result = new StringBuffer();
 
-			for (int i = 0; i < objects.length; i++) {
+			for (int i = 0; i < objects.length; i++)
+			{
 				Object object = objects[i];
 
-				if (i > 50) {
+				if (i > 50)
+				{
 					result.append("... (" + objects.length + ")");
 					break;
 				}
@@ -344,14 +373,17 @@
 		// }
 		// return result.toString();
 		// }
-		else if (o instanceof int[]) {
+		else if (o instanceof int[])
+		{
 			int values[] = (int[]) o;
 			StringBuffer result = new StringBuffer();
 
-			for (int i = 0; i < values.length; i++) {
+			for (int i = 0; i < values.length; i++)
+			{
 				int value = values[i];
 
-				if (i > 50) {
+				if (i > 50)
+				{
 					result.append("... (" + values.length + ")");
 					break;
 				}
@@ -360,14 +392,17 @@
 				result.append("" + value);
 			}
 			return result.toString();
-		} else if (o instanceof long[]) {
+		} else if (o instanceof long[])
+		{
 			long values[] = (long[]) o;
 			StringBuffer result = new StringBuffer();
 
-			for (int i = 0; i < values.length; i++) {
+			for (int i = 0; i < values.length; i++)
+			{
 				long value = values[i];
 
-				if (i > 50) {
+				if (i > 50)
+				{
 					result.append("... (" + values.length + ")");
 					break;
 				}
@@ -376,14 +411,17 @@
 				result.append("" + value);
 			}
 			return result.toString();
-		} else if (o instanceof double[]) {
+		} else if (o instanceof double[])
+		{
 			double values[] = (double[]) o;
 			StringBuffer result = new StringBuffer();
 
-			for (int i = 0; i < values.length; i++) {
+			for (int i = 0; i < values.length; i++)
+			{
 				double value = values[i];
 
-				if (i > 50) {
+				if (i > 50)
+				{
 					result.append("... (" + values.length + ")");
 					break;
 				}
@@ -392,14 +430,17 @@
 				result.append("" + value);
 			}
 			return result.toString();
-		} else if (o instanceof byte[]) {
+		} else if (o instanceof byte[])
+		{
 			byte values[] = (byte[]) o;
 			StringBuffer result = new StringBuffer();
 
-			for (int i = 0; i < values.length; i++) {
+			for (int i = 0; i < values.length; i++)
+			{
 				byte value = values[i];
 
-				if (i > 50) {
+				if (i > 50)
+				{
 					result.append("... (" + values.length + ")");
 					break;
 				}
@@ -408,14 +449,17 @@
 				result.append("" + value);
 			}
 			return result.toString();
-		} else if (o instanceof char[]) {
+		} else if (o instanceof char[])
+		{
 			char values[] = (char[]) o;
 			StringBuffer result = new StringBuffer();
 
-			for (int i = 0; i < values.length; i++) {
+			for (int i = 0; i < values.length; i++)
+			{
 				char value = values[i];
 
-				if (i > 50) {
+				if (i > 50)
+				{
 					result.append("... (" + values.length + ")");
 					break;
 				}
@@ -424,14 +468,17 @@
 				result.append("" + value);
 			}
 			return result.toString();
-		} else if (o instanceof float[]) {
+		} else if (o instanceof float[])
+		{
 			float values[] = (float[]) o;
 			StringBuffer result = new StringBuffer();
 
-			for (int i = 0; i < values.length; i++) {
+			for (int i = 0; i < values.length; i++)
+			{
 				float value = values[i];
 
-				if (i > 50) {
+				if (i > 50)
+				{
 					result.append("... (" + values.length + ")");
 					break;
 				}
@@ -460,15 +507,18 @@
 		return "Unknown: " + o.getClass().getName();
 	}
 
-	public void dump() {
+	public void dump()
+	{
 		dump(new PrintWriter(new OutputStreamWriter(System.out)));
 	}
 
-	public void dump(PrintWriter pw) {
+	public void dump(PrintWriter pw)
+	{
 		dump(pw, null);
 	}
 
-	public void dump(PrintWriter pw, String prefix) {
+	public void dump(PrintWriter pw, String prefix)
+	{
 		if (prefix != null)
 			pw.print(prefix + ": ");
 
@@ -489,12 +539,14 @@
 	// Debug.debug("byteOrder", byteOrder);
 	// }
 
-	public String getDescriptionWithoutValue() {
+	public String getDescriptionWithoutValue()
+	{
 		return tag + " (0x" + Integer.toHexString(tag) + ": " + tagInfo.name
 				+ "): ";
 	}
 
-	public String toString() {
+	public String toString()
+	{
 		StringBuffer result = new StringBuffer();
 
 		result.append(tag + " (0x" + Integer.toHexString(tag) + ": "
@@ -505,24 +557,28 @@
 		return result.toString();
 	}
 
-	public String getTagName() {
+	public String getTagName()
+	{
 		if (tagInfo == TIFF_TAG_UNKNOWN)
 			return tagInfo.name + " (0x" + Integer.toHexString(tag) + ")";
 		return tagInfo.name;
 	}
 
-	public String getFieldTypeName() {
+	public String getFieldTypeName()
+	{
 		return fieldType.name;
 	}
 
 	public static final String Attribute_Tag = "Tag";
 
-	public Object getValue() throws ImageReadException {
+	public Object getValue() throws ImageReadException
+	{
 		// System.out.print("getValue");
 		return tagInfo.getValue(this);
 	}
 
-	public String getStringValue() throws ImageReadException {
+	public String getStringValue() throws ImageReadException
+	{
 		Object o = getValue();
 		if (o == null)
 			return null;
@@ -533,16 +589,19 @@
 	}
 
 	private static final Map makeTagMap(TagInfo tags[],
-			boolean ignoreDuplicates, String name) {
+			boolean ignoreDuplicates, String name)
+	{
 		// make sure to use the thread-safe version; this is shared state.
 		Map map = new Hashtable();
 
-		for (int i = 0; i < tags.length; i++) {
+		for (int i = 0; i < tags.length; i++)
+		{
 			TagInfo tag = tags[i];
 			Object key = new Integer(tag.tag);
 
 			List tagList = (List) map.get(key);
-			if (tagList == null) {
+			if (tagList == null)
+			{
 				tagList = new ArrayList();
 				map.put(key, tagList);
 			}
@@ -598,20 +657,23 @@
 	//
 	//	
 
-	public int[] getIntArrayValue() throws ImageReadException {
+	public int[] getIntArrayValue() throws ImageReadException
+	{
 		Object o = getValue();
 		// if (o == null)
 		// return null;
 
 		if (o instanceof Number)
 			return new int[] { ((Number) o).intValue() };
-		else if (o instanceof Number[]) {
+		else if (o instanceof Number[])
+		{
 			Number numbers[] = (Number[]) o;
 			int result[] = new int[numbers.length];
 			for (int i = 0; i < numbers.length; i++)
 				result[i] = numbers[i].intValue();
 			return result;
-		} else if (o instanceof int[]) {
+		} else if (o instanceof int[])
+		{
 			int numbers[] = (int[]) o;
 			int result[] = new int[numbers.length];
 			for (int i = 0; i < numbers.length; i++)
@@ -624,32 +686,38 @@
 		// return null;
 	}
 
-	public double[] getDoubleArrayValue() throws ImageReadException {
+	public double[] getDoubleArrayValue() throws ImageReadException
+	{
 		Object o = getValue();
 		// if (o == null)
 		// return null;
 
-		if (o instanceof Number) {
+		if (o instanceof Number)
+		{
 			return new double[] { ((Number) o).doubleValue() };
-		} else if (o instanceof Number[]) {
+		} else if (o instanceof Number[])
+		{
 			Number numbers[] = (Number[]) o;
 			double result[] = new double[numbers.length];
 			for (int i = 0; i < numbers.length; i++)
 				result[i] = numbers[i].doubleValue();
 			return result;
-		} else if (o instanceof int[]) {
+		} else if (o instanceof int[])
+		{
 			int numbers[] = (int[]) o;
 			double result[] = new double[numbers.length];
 			for (int i = 0; i < numbers.length; i++)
 				result[i] = numbers[i];
 			return result;
-		} else if (o instanceof float[]) {
+		} else if (o instanceof float[])
+		{
 			float numbers[] = (float[]) o;
 			double result[] = new double[numbers.length];
 			for (int i = 0; i < numbers.length; i++)
 				result[i] = numbers[i];
 			return result;
-		} else if (o instanceof double[]) {
+		} else if (o instanceof double[])
+		{
 			double numbers[] = (double[]) o;
 			double result[] = new double[numbers.length];
 			for (int i = 0; i < numbers.length; i++)
@@ -662,20 +730,23 @@
 		// return null;
 	}
 
-	public int getIntValueOrArraySum() throws ImageReadException {
+	public int getIntValueOrArraySum() throws ImageReadException
+	{
 		Object o = getValue();
 		// if (o == null)
 		// return -1;
 
 		if (o instanceof Number)
 			return ((Number) o).intValue();
-		else if (o instanceof Number[]) {
+		else if (o instanceof Number[])
+		{
 			Number numbers[] = (Number[]) o;
 			int sum = 0;
 			for (int i = 0; i < numbers.length; i++)
 				sum += numbers[i].intValue();
 			return sum;
-		} else if (o instanceof int[]) {
+		} else if (o instanceof int[])
+		{
 			int numbers[] = (int[]) o;
 			int sum = 0;
 			for (int i = 0; i < numbers.length; i++)
@@ -688,7 +759,8 @@
 		// return -1;
 	}
 
-	public int getIntValue() throws ImageReadException {
+	public int getIntValue() throws ImageReadException
+	{
 		Object o = getValue();
 		if (o == null)
 			throw new ImageReadException("Missing value: "
@@ -697,7 +769,8 @@
 		return ((Number) o).intValue();
 	}
 
-	public double getDoubleValue() throws ImageReadException {
+	public double getDoubleValue() throws ImageReadException
+	{
 		Object o = getValue();
 		if (o == null)
 			throw new ImageReadException("Missing value: "
@@ -706,11 +779,18 @@
 		return ((Number) o).doubleValue();
 	}
 
-	public int getSortHint() {
+	public byte[] getByteArrayValue() throws ImageReadException
+	{
+		return fieldType.getRawBytes(this);
+	}
+
+	public int getSortHint()
+	{
 		return sortHint;
 	}
 
-	public void setSortHint(int sortHint) {
+	public void setSortHint(int sortHint)
+	{
 		this.sortHint = sortHint;
 	}
 }
\ No newline at end of file

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=680163&r1=680162&r2=680163&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 Jul 27 11:59:46 2008
@@ -22,6 +22,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Map;
 
@@ -306,6 +307,33 @@
 		return result;
 	}
 
+	
+
+	public String getXmpXml(ByteSource byteSource, Map params)
+			throws ImageReadException, IOException
+	{
+		FormatCompliance formatCompliance = FormatCompliance.getDefault();
+		TiffContents contents = new TiffReader(isStrict(params)).readDirectories(byteSource,
+				false, formatCompliance);
+		TiffDirectory directory = (TiffDirectory) contents.directories.get(0);
+
+		TiffField xmpField = directory.findField(TIFF_TAG_XMP, false);
+		if(xmpField==null)
+			return null;
+		
+		byte bytes[] = xmpField.getByteArrayValue();
+		
+		try
+		{
+			// segment data is UTF-8 encoded xml.
+			String xml = new String(bytes, "utf-8");
+			return xml;
+		} catch (UnsupportedEncodingException e)
+		{
+			throw new ImageReadException("Invalid JPEG XMP Segment.");
+		}
+	}
+
 	public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
 			throws ImageReadException, IOException
 	{

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=680163&r1=680162&r2=680163&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 Jul 27 11:59:46 2008
@@ -299,6 +299,9 @@
 	public static final TagInfo TIFF_TAG_COPYRIGHT = new TagInfo("Copyright",
 			0x8298, FIELD_TYPE_DESCRIPTION_ASCII, -1, TIFF_DIRECTORY_ROOT);
 
+	public static final TagInfo TIFF_TAG_XMP = new TagInfo("XMP",
+			0x2BC, FIELD_TYPE_DESCRIPTION_BYTE, -1, TIFF_DIRECTORY_ROOT);
+
 	// TODO:
 	//	public static final TagInfo2 TIFF_TAG_UNKNOWN = null;
 	public static final TagInfo TIFF_TAG_UNKNOWN = new TagInfo.Unknown(
@@ -338,7 +341,9 @@
 			TIFF_TAG_JPEG_DCTABLES, TIFF_TAG_JPEG_ACTABLES,
 			TIFF_TAG_YCBCR_COEFFICIENTS, TIFF_TAG_YCBCR_SUB_SAMPLING,
 			TIFF_TAG_YCBCR_POSITIONING, TIFF_TAG_REFERENCE_BLACK_WHITE,
-			TIFF_TAG_COPYRIGHT
+			TIFF_TAG_COPYRIGHT,
+			//
+			TIFF_TAG_XMP,
 	};
 
 }
\ No newline at end of file

Added: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifBaseTest.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifBaseTest.java?rev=680163&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifBaseTest.java (added)
+++ incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifBaseTest.java Sun Jul 27 11:59:46 2008
@@ -0,0 +1,57 @@
+/*
+ * 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.gif;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.sanselan.ImageFormat;
+import org.apache.sanselan.ImageInfo;
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.Sanselan;
+import org.apache.sanselan.SanselanTest;
+import org.apache.sanselan.common.IImageMetadata;
+import org.apache.sanselan.util.Debug;
+
+public abstract class GifBaseTest extends SanselanTest
+{
+
+	private static boolean isGif(File file) throws IOException,
+			ImageReadException
+	{
+		ImageFormat format = Sanselan.guessFormat(file);
+		return format == ImageFormat.IMAGE_FORMAT_GIF;
+	}
+
+	private static final ImageFilter IMAGE_FILTER = new ImageFilter() {
+		public boolean accept(File file) throws IOException, ImageReadException
+		{
+			return isGif(file);
+		}
+	};
+
+	protected List getGifImages() throws IOException, ImageReadException
+	{
+		return getTestImages(IMAGE_FILTER);
+	}
+
+
+}

Propchange: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifBaseTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifReadTest.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifReadTest.java?rev=680163&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifReadTest.java (added)
+++ incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifReadTest.java Sun Jul 27 11:59:46 2008
@@ -0,0 +1,62 @@
+/*
+ * 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.gif;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.sanselan.ImageFormat;
+import org.apache.sanselan.ImageInfo;
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.Sanselan;
+import org.apache.sanselan.SanselanTest;
+import org.apache.sanselan.common.IImageMetadata;
+import org.apache.sanselan.util.Debug;
+
+public class GifReadTest extends GifBaseTest
+{
+
+	public void test() throws IOException, ImageReadException,
+			ImageWriteException
+	{
+		Debug.debug("start");
+
+		List images = getGifImages();
+		for (int i = 0; i < images.size(); i++)
+		{
+			if (i % 10 == 0)
+				Debug.purgeMemory();
+
+			File imageFile = (File) images.get(i);
+			Debug.debug("imageFile", imageFile);
+
+			IImageMetadata metadata = Sanselan.getMetadata(imageFile);
+//			assertNotNull(metadata);
+
+			ImageInfo imageInfo = Sanselan.getImageInfo(imageFile);
+			assertNotNull(imageInfo);
+
+			BufferedImage image = Sanselan.getBufferedImage(imageFile);
+			assertNotNull(image);
+		}
+	}
+
+}

Propchange: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/gif/GifReadTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java?rev=680163&r1=680162&r2=680163&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java (original)
+++ incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java Sun Jul 27 11:59:46 2008
@@ -19,7 +19,9 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.sanselan.ImageReadException;
 import org.apache.sanselan.ImageWriteException;
@@ -45,7 +47,8 @@
 			Debug.debug();
 
 			ByteSource byteSource = new ByteSourceFile(imageFile);
-			String xmpXml = new JpegImageParser().getXmpXml(byteSource);
+			Map params = new HashMap();
+			String xmpXml = new JpegImageParser().getXmpXml(byteSource, params );
 			assertNotNull(xmpXml);
 
 			Debug.debug("xmpXml", xmpXml);

Added: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java?rev=680163&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java (added)
+++ incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java Sun Jul 27 11:59:46 2008
@@ -0,0 +1,62 @@
+/*
+ * 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.xmp;
+
+import java.io.File;
+import java.io.IOException;
+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.Sanselan;
+import org.apache.sanselan.SanselanTest;
+import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.common.byteSources.ByteSourceFile;
+import org.apache.sanselan.formats.jpeg.JpegImageParser;
+import org.apache.sanselan.util.Debug;
+
+public class XmpDumpTest extends SanselanTest
+{
+
+	public void test() throws IOException, ImageReadException,
+			ImageWriteException
+	{
+		List images = getTestImages();
+		for (int i = 0; i < images.size(); i++)
+		{
+			if (i % 10 == 0)
+				Debug.purgeMemory();
+
+			File imageFile = (File) images.get(i);
+			Debug.debug("imageFile", imageFile);
+			Debug.debug();
+
+			String xmpXml = Sanselan.getXmpXml(imageFile);
+			if(null==xmpXml)
+				continue;
+			
+			assertNotNull(xmpXml);
+
+			Debug.debug("xmpXml", xmpXml);
+			Debug.debug();
+		}
+	}
+
+}

Propchange: incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java
------------------------------------------------------------------------------
    svn:eol-style = native