You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2010/09/10 18:33:42 UTC

svn commit: r995859 [13/30] - in /commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan: ./ color/ common/ common/byteSources/ common/mylzw/ formats/bmp/ formats/bmp/pixelparsers/ formats/bmp/writers/ formats/gif/ formats/ico/ formats/jpeg/ f...

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java Fri Sep 10 16:33:35 2010
@@ -36,408 +36,408 @@ import org.apache.sanselan.util.ParamMap
 
 public class IPTCParser extends BinaryFileParser implements IPTCConstants
 {
-	private static final int APP13_BYTE_ORDER = BYTE_ORDER_NETWORK;
+    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);
-			}
+    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();
-		}
+            blockData = baos.toByteArray();
+        }
 
-		return blockData;
-	}
+        return blockData;
+    }
 
 }

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java Fri Sep 10 16:33:35 2010
@@ -23,32 +23,32 @@ import java.util.Comparator;
  */
 public class IPTCRecord
 {
-	public final IPTCType iptcType;
-	public final String value;
+    public final IPTCType iptcType;
+    public final String value;
 
-	public IPTCRecord(IPTCType iptcType, String value)
-	{
-		this.iptcType = iptcType;
-		this.value = value;
-	}
+    public IPTCRecord(IPTCType iptcType, String value)
+    {
+        this.iptcType = iptcType;
+        this.value = value;
+    }
 
-	public String getValue()
-	{
-		return value;
-	}
+    public String getValue()
+    {
+        return value;
+    }
 
-	public String getIptcTypeName()
-	{
-		return iptcType.name;
-	}
+    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;
-		}
-	};
+    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

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java Fri Sep 10 16:33:35 2010
@@ -20,23 +20,23 @@ import org.apache.sanselan.formats.jpeg.
 
 public class IPTCType implements JpegConstants, IPTCConstants
 {
-	public final int type;
-	public final String name;
+    public final int type;
+    public final String name;
 
-	public IPTCType(int type, String name)
-	{
-		this.type = type;
-		this.name = name;
-	}
+    public IPTCType(int type, String name)
+    {
+        this.type = type;
+        this.name = name;
+    }
 
-	public String toString()
-	{
-		return name + " (" + type + ")";
-	}
+    public String toString()
+    {
+        return name + " (" + type + ")";
+    }
 
-	public static IPTCType getUnknown(int type)
-	{
-		return new IPTCType(type, "Unknown");
-	}
+    public static IPTCType getUnknown(int type)
+    {
+        return new IPTCType(type, "Unknown");
+    }
 
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java Fri Sep 10 16:33:35 2010
@@ -22,22 +22,22 @@ 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);
-		}
-	}
+    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);
-	}
+    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

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java Fri Sep 10 16:33:35 2010
@@ -39,219 +39,219 @@ import org.apache.sanselan.formats.jpeg.
  * <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 newData
-	 *            structure 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 newData
-	 *            structure 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 newData
-	 *            structure 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 newData
-	 *            structure 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, }));
-		}
+    /**
+     * 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 newData
+     *            structure 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 newData
+     *            structure 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 newData
+     *            structure 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 newData
+     *            structure 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);
-	}
+        writeSegments(os, newPieces);
+    }
 
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java Fri Sep 10 16:33:35 2010
@@ -22,35 +22,35 @@ import java.util.List;
 
 public class PhotoshopApp13Data implements IPTCConstants
 {
-	private final List records;
-	private final List rawBlocks;
+    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;
-	}
+    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;
+    }
 
 }

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/APPNSegment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/APPNSegment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/APPNSegment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/APPNSegment.java Fri Sep 10 16:33:35 2010
@@ -24,15 +24,15 @@ import org.apache.sanselan.formats.jpeg.
 
 public class APPNSegment extends GenericSegment
 {
-	public APPNSegment(int marker, int marker_length, InputStream is)
-			throws ImageReadException, IOException
-	{
-		super(marker, marker_length, is);
-	}
+    public APPNSegment(int marker, int marker_length, InputStream is)
+            throws ImageReadException, IOException
+    {
+        super(marker, marker_length, is);
+    }
 
-	public String getDescription()
-	{
-		return "APPN (APP" + (marker - JpegImageParser.JPEG_APP0_Marker)
-				+ ") (" + getSegmentType() + ")";
-	}
+    public String getDescription()
+    {
+        return "APPN (APP" + (marker - JpegImageParser.JPEG_APP0_Marker)
+                + ") (" + getSegmentType() + ")";
+    }
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java Fri Sep 10 16:33:35 2010
@@ -28,55 +28,55 @@ import org.apache.sanselan.formats.jpeg.
 
 public class App13Segment extends APPNSegment
 {
-	protected final JpegImageParser parser;
+    protected final JpegImageParser parser;
 
-	// public final ArrayList elements = new ArrayList();
-	// public final boolean isIPTCJpegSegment;
+    // public final ArrayList elements = new ArrayList();
+    // public final boolean isIPTCJpegSegment;
 
-	public App13Segment(JpegImageParser parser, int marker, byte segmentData[])
-			throws ImageReadException, IOException
-	{
-		this(parser, marker, segmentData.length, new ByteArrayInputStream(
-				segmentData));
-	}
-
-	public App13Segment(JpegImageParser parser, int marker, int marker_length,
-			InputStream is) throws ImageReadException, IOException
-	{
-		super(marker, marker_length, is);
-		this.parser = parser;
-
-		// isIPTCJpegSegment = new IPTCParser().isIPTCJpegSegment(bytes);
-		// if (isIPTCJpegSegment)
-		// {
-		// /*
-		// * 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.
-		// */
-		// boolean verbose = false;
-		// boolean strict = false;
-		// elements.addAll(new IPTCParser().parseIPTCJPEGSegment(bytes,
-		// verbose, strict));
-		// }
-	}
-
-	public boolean isPhotoshopJpegSegment() throws ImageReadException, IOException
-	{
-		return new IPTCParser().isPhotoshopJpegSegment(bytes);
-	}
-
-	public PhotoshopApp13Data parsePhotoshopSegment(Map params)
-			throws ImageReadException, IOException
-	{
-		/*
-		 * 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.
-		 */
-		if (!new IPTCParser().isPhotoshopJpegSegment(bytes))
-			return null;
+    public App13Segment(JpegImageParser parser, int marker, byte segmentData[])
+            throws ImageReadException, IOException
+    {
+        this(parser, marker, segmentData.length, new ByteArrayInputStream(
+                segmentData));
+    }
+
+    public App13Segment(JpegImageParser parser, int marker, int marker_length,
+            InputStream is) throws ImageReadException, IOException
+    {
+        super(marker, marker_length, is);
+        this.parser = parser;
+
+        // isIPTCJpegSegment = new IPTCParser().isIPTCJpegSegment(bytes);
+        // if (isIPTCJpegSegment)
+        // {
+        // /*
+        // * 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.
+        // */
+        // boolean verbose = false;
+        // boolean strict = false;
+        // elements.addAll(new IPTCParser().parseIPTCJPEGSegment(bytes,
+        // verbose, strict));
+        // }
+    }
+
+    public boolean isPhotoshopJpegSegment() throws ImageReadException, IOException
+    {
+        return new IPTCParser().isPhotoshopJpegSegment(bytes);
+    }
+
+    public PhotoshopApp13Data parsePhotoshopSegment(Map params)
+            throws ImageReadException, IOException
+    {
+        /*
+         * 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.
+         */
+        if (!new IPTCParser().isPhotoshopJpegSegment(bytes))
+            return null;
 
-		return new IPTCParser().parsePhotoshopSegment(bytes, params);
-	}
+        return new IPTCParser().parsePhotoshopSegment(bytes, params);
+    }
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App2Segment.java Fri Sep 10 16:33:35 2010
@@ -25,55 +25,55 @@ import org.apache.sanselan.formats.jpeg.
 
 public class App2Segment extends APPNSegment implements Comparable
 {
-	public final byte icc_bytes[];
-	public final int cur_marker, num_markers;
+    public final byte icc_bytes[];
+    public final int cur_marker, num_markers;
 
-	public App2Segment(int marker, byte segmentData[])
-			throws ImageReadException, IOException
-	{
-		this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
-	}
-
-	public App2Segment(int marker, int marker_length, InputStream is2)
-			throws ImageReadException, IOException
-	{
-		super(marker, marker_length, is2);
-
-		if (startsWith(bytes, JpegImageParser.icc_profile_label))
-		{
-			InputStream is = new ByteArrayInputStream(bytes);
-
-			readAndVerifyBytes(is, JpegImageParser.icc_profile_label,
-					"Not a Valid App2 Segment: missing ICC Profile label");
-
-			cur_marker = readByte("cur_marker", is, "Not a valid App2 Marker");
-			num_markers = readByte("num_markers", is, "Not a valid App2 Marker");
-
-			marker_length -= JpegImageParser.icc_profile_label.length;
-			marker_length -= (1 + 1);
-
-			icc_bytes = readByteArray("App2 Data", marker_length, is,
-					"Invalid App2 Segment: insufficient data");
-		}
-		else
-		{
-			//			debugByteArray("Unknown APP2 Segment Type", bytes);
-			cur_marker = -1;
-			num_markers = -1;
-			icc_bytes = null;
-		}
-	}
-
-	public int compareTo(Object o)
-	{
-		App2Segment other = (App2Segment) o;
-		return cur_marker - other.cur_marker;
-	}
-
-	//	public String getDescription()
-	//	{
-	//		return "APPN (APP"
-	//				+ (marker - JpegImageParser.JPEG_APP0)
-	//				+ ") (" + getDescription() + ")";
-	//	}
+    public App2Segment(int marker, byte segmentData[])
+            throws ImageReadException, IOException
+    {
+        this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
+    }
+
+    public App2Segment(int marker, int marker_length, InputStream is2)
+            throws ImageReadException, IOException
+    {
+        super(marker, marker_length, is2);
+
+        if (startsWith(bytes, JpegImageParser.icc_profile_label))
+        {
+            InputStream is = new ByteArrayInputStream(bytes);
+
+            readAndVerifyBytes(is, JpegImageParser.icc_profile_label,
+                    "Not a Valid App2 Segment: missing ICC Profile label");
+
+            cur_marker = readByte("cur_marker", is, "Not a valid App2 Marker");
+            num_markers = readByte("num_markers", is, "Not a valid App2 Marker");
+
+            marker_length -= JpegImageParser.icc_profile_label.length;
+            marker_length -= (1 + 1);
+
+            icc_bytes = readByteArray("App2 Data", marker_length, is,
+                    "Invalid App2 Segment: insufficient data");
+        }
+        else
+        {
+            //            debugByteArray("Unknown APP2 Segment Type", bytes);
+            cur_marker = -1;
+            num_markers = -1;
+            icc_bytes = null;
+        }
+    }
+
+    public int compareTo(Object o)
+    {
+        App2Segment other = (App2Segment) o;
+        return cur_marker - other.cur_marker;
+    }
+
+    //    public String getDescription()
+    //    {
+    //        return "APPN (APP"
+    //                + (marker - JpegImageParser.JPEG_APP0)
+    //                + ") (" + getDescription() + ")";
+    //    }
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/GenericSegment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/GenericSegment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/GenericSegment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/GenericSegment.java Fri Sep 10 16:33:35 2010
@@ -24,40 +24,40 @@ import org.apache.sanselan.ImageReadExce
 
 public abstract class GenericSegment extends Segment
 {
-	public final byte bytes[];
+    public final byte bytes[];
 
-	public GenericSegment(int marker, int marker_length, InputStream is)
-			throws ImageReadException, IOException
-	{
-		super(marker, marker_length);
-
-		bytes = readByteArray("Segment Data", marker_length, is,
-				"Invalid Segment: insufficient data");
-	}
-
-	public GenericSegment(int marker, byte bytes[]) throws ImageReadException,
-			IOException
-	{
-		super(marker, bytes.length);
-
-		this.bytes = bytes;
-	}
-
-	public void dump(PrintWriter pw)
-	{
-		dump(pw, 0);
-	}
-
-	public void dump(PrintWriter pw, int start)
-	{
-		for (int i = 0; (i < 50) && ((i + start) < bytes.length); i++)
-		{
-			debugNumber(pw, "\t" + (i + start), bytes[i + start]);
-		}
-	}
-
-	//	public String getDescription()
-	//	{
-	//		return "Unknown";
-	//	}
+    public GenericSegment(int marker, int marker_length, InputStream is)
+            throws ImageReadException, IOException
+    {
+        super(marker, marker_length);
+
+        bytes = readByteArray("Segment Data", marker_length, is,
+                "Invalid Segment: insufficient data");
+    }
+
+    public GenericSegment(int marker, byte bytes[]) throws ImageReadException,
+            IOException
+    {
+        super(marker, bytes.length);
+
+        this.bytes = bytes;
+    }
+
+    public void dump(PrintWriter pw)
+    {
+        dump(pw, 0);
+    }
+
+    public void dump(PrintWriter pw, int start)
+    {
+        for (int i = 0; (i < 50) && ((i + start) < bytes.length); i++)
+        {
+            debugNumber(pw, "\t" + (i + start), bytes[i + start]);
+        }
+    }
+
+    //    public String getDescription()
+    //    {
+    //        return "Unknown";
+    //    }
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/JFIFSegment.java Fri Sep 10 16:33:35 2010
@@ -25,58 +25,58 @@ import org.apache.sanselan.formats.jpeg.
 
 public class JFIFSegment extends Segment implements JpegConstants
 {
-	public final int jfifMajorVersion;
-	public final int jfifMinorVersion;
-	public final int densityUnits;
-	public final int xDensity;
-	public final int yDensity;
-
-	public final int xThumbnail;
-	public final int yThumbnail;
-	public final int thumbnailSize;
-
-	public String getDescription()
-	{
-		return "JFIF (" + getSegmentType() + ")";
-	}
-
-	public JFIFSegment(int marker, byte segmentData[])
-			throws ImageReadException, IOException
-	{
-		this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
-	}
-
-	public JFIFSegment(int marker, int marker_length, InputStream is)
-			throws ImageReadException, IOException
-	{
-		super(marker, marker_length);
-
-		byte signature[] = readBytes(is, JFIF0_SIGNATURE.length);
-		if (!compareByteArrays(signature, JFIF0_SIGNATURE)
-				&& !compareByteArrays(signature, JFIF0_SIGNATURE_ALTERNATIVE))
-			throw new ImageReadException(
-					"Not a Valid JPEG File: missing JFIF string");
-
-		jfifMajorVersion = readByte("JFIF_major_version", is,
-				"Not a Valid JPEG File");
-		jfifMinorVersion = readByte("JFIF_minor_version", is,
-				"Not a Valid JPEG File");
-		densityUnits = readByte("density_units", is, "Not a Valid JPEG File");
-		xDensity = read2Bytes("x_density", is, "Not a Valid JPEG File");
-		yDensity = read2Bytes("y_density", is, "Not a Valid JPEG File");
-
-		xThumbnail = readByte("x_thumbnail", is, "Not a Valid JPEG File");
-		yThumbnail = readByte("y_thumbnail", is, "Not a Valid JPEG File");
-		thumbnailSize = xThumbnail * yThumbnail;
-		if (thumbnailSize > 0)
-		{
-			skipBytes(is, thumbnailSize,
-					"Not a Valid JPEG File: missing thumbnail");
-
-		}
-
-		if (getDebug())
-			System.out.println("");
-	}
+    public final int jfifMajorVersion;
+    public final int jfifMinorVersion;
+    public final int densityUnits;
+    public final int xDensity;
+    public final int yDensity;
+
+    public final int xThumbnail;
+    public final int yThumbnail;
+    public final int thumbnailSize;
+
+    public String getDescription()
+    {
+        return "JFIF (" + getSegmentType() + ")";
+    }
+
+    public JFIFSegment(int marker, byte segmentData[])
+            throws ImageReadException, IOException
+    {
+        this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
+    }
+
+    public JFIFSegment(int marker, int marker_length, InputStream is)
+            throws ImageReadException, IOException
+    {
+        super(marker, marker_length);
+
+        byte signature[] = readBytes(is, JFIF0_SIGNATURE.length);
+        if (!compareByteArrays(signature, JFIF0_SIGNATURE)
+                && !compareByteArrays(signature, JFIF0_SIGNATURE_ALTERNATIVE))
+            throw new ImageReadException(
+                    "Not a Valid JPEG File: missing JFIF string");
+
+        jfifMajorVersion = readByte("JFIF_major_version", is,
+                "Not a Valid JPEG File");
+        jfifMinorVersion = readByte("JFIF_minor_version", is,
+                "Not a Valid JPEG File");
+        densityUnits = readByte("density_units", is, "Not a Valid JPEG File");
+        xDensity = read2Bytes("x_density", is, "Not a Valid JPEG File");
+        yDensity = read2Bytes("y_density", is, "Not a Valid JPEG File");
+
+        xThumbnail = readByte("x_thumbnail", is, "Not a Valid JPEG File");
+        yThumbnail = readByte("y_thumbnail", is, "Not a Valid JPEG File");
+        thumbnailSize = xThumbnail * yThumbnail;
+        if (thumbnailSize > 0)
+        {
+            skipBytes(is, thumbnailSize,
+                    "Not a Valid JPEG File: missing thumbnail");
+
+        }
+
+        if (getDebug())
+            System.out.println("");
+    }
 
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOFNSegment.java Fri Sep 10 16:33:35 2010
@@ -25,51 +25,51 @@ import org.apache.sanselan.formats.jpeg.
 
 public class SOFNSegment extends Segment
 {
-	public final int width, height;
-	public final int numberOfComponents;
-	public final int precision;
-
-	public SOFNSegment(int marker, byte segmentData[])
-			throws ImageReadException, IOException
-	{
-		this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
-	}
-
-	public SOFNSegment(int marker, int marker_length, InputStream is)
-			throws ImageReadException, IOException
-	{
-		super(marker, marker_length);
-
-		if (getDebug())
-			System.out.println("SOF0Segment marker_length: " + marker_length);
-
-		{
-			precision = readByte("Data_precision", is, "Not a Valid JPEG File");
-			height = read2Bytes("Image_height", is, "Not a Valid JPEG File");
-			width = read2Bytes("Image_Width", is, "Not a Valid JPEG File");
-			numberOfComponents = readByte("Number_of_components", is,
-					"Not a Valid JPEG File");
-
-			// ignore the rest of the segment for now...
-			skipBytes(is, marker_length - 6,
-					"Not a Valid JPEG File: SOF0 Segment");
-
-			//				int Each_component1 = read_byte("Each_component1", is,
-			//						"Not a Valid JPEG File");
-			//				int Each_component2 = read_byte("Each_component2", is,
-			//						"Not a Valid JPEG File");
-			//				int Each_component3 = read_byte("Each_component3", is,
-			//						"Not a Valid JPEG File");
-		}
-
-		if (getDebug())
-			System.out.println("");
-	}
-
-	public String getDescription()
-	{
-		return "SOFN (SOF" + (marker - JpegImageParser.SOF0Marker) + ") ("
-				+ getSegmentType() + ")";
-	}
+    public final int width, height;
+    public final int numberOfComponents;
+    public final int precision;
+
+    public SOFNSegment(int marker, byte segmentData[])
+            throws ImageReadException, IOException
+    {
+        this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
+    }
+
+    public SOFNSegment(int marker, int marker_length, InputStream is)
+            throws ImageReadException, IOException
+    {
+        super(marker, marker_length);
+
+        if (getDebug())
+            System.out.println("SOF0Segment marker_length: " + marker_length);
+
+        {
+            precision = readByte("Data_precision", is, "Not a Valid JPEG File");
+            height = read2Bytes("Image_height", is, "Not a Valid JPEG File");
+            width = read2Bytes("Image_Width", is, "Not a Valid JPEG File");
+            numberOfComponents = readByte("Number_of_components", is,
+                    "Not a Valid JPEG File");
+
+            // ignore the rest of the segment for now...
+            skipBytes(is, marker_length - 6,
+                    "Not a Valid JPEG File: SOF0 Segment");
+
+            //                int Each_component1 = read_byte("Each_component1", is,
+            //                        "Not a Valid JPEG File");
+            //                int Each_component2 = read_byte("Each_component2", is,
+            //                        "Not a Valid JPEG File");
+            //                int Each_component3 = read_byte("Each_component3", is,
+            //                        "Not a Valid JPEG File");
+        }
+
+        if (getDebug())
+            System.out.println("");
+    }
+
+    public String getDescription()
+    {
+        return "SOFN (SOF" + (marker - JpegImageParser.SOF0Marker) + ") ("
+                + getSegmentType() + ")";
+    }
 
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOSSegment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOSSegment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOSSegment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/SOSSegment.java Fri Sep 10 16:33:35 2010
@@ -24,77 +24,77 @@ import org.apache.sanselan.util.Debug;
 
 public class SOSSegment extends Segment
 {
-	//	public final int width, height;
-	//	public final int Number_of_components;
-	//	public final int Precision;
-
-	//		public final byte bytes[];
-	//		public final int cur_marker, num_markers;
-
-	public SOSSegment(int marker, int marker_length, InputStream is)
-			throws ImageReadException, IOException
-	{
-		super(marker, marker_length);
-
-		if (getDebug())
-			System.out.println("SOSSegment marker_length: " + marker_length);
-
-		Debug.debug("SOS", marker_length);
-		//		{
-		int number_of_components_in_scan = readByte(
-				"number_of_components_in_scan", is, "Not a Valid JPEG File");
-		Debug.debug("number_of_components_in_scan",
-				number_of_components_in_scan);
-
-		for (int i = 0; i < number_of_components_in_scan; i++)
-		{
-			int scan_component_selector = readByte("scan_component_selector",
-					is, "Not a Valid JPEG File");
-			Debug.debug("scan_component_selector", scan_component_selector);
-
-			int ac_dc_entrooy_coding_table_selector = readByte(
-					"ac_dc_entrooy_coding_table_selector", is,
-					"Not a Valid JPEG File");
-			Debug.debug("ac_dc_entrooy_coding_table_selector",
-					ac_dc_entrooy_coding_table_selector);
-		}
-
-		int start_of_spectral_selection = readByte(
-				"start_of_spectral_selection", is, "Not a Valid JPEG File");
-		Debug.debug("start_of_spectral_selection", start_of_spectral_selection);
-		int end_of_spectral_selection = readByte("end_of_spectral_selection",
-				is, "Not a Valid JPEG File");
-		Debug.debug("end_of_spectral_selection", end_of_spectral_selection);
-		int successive_approximation_bit_position = readByte(
-				"successive_approximation_bit_position", is,
-				"Not a Valid JPEG File");
-		Debug.debug("successive_approximation_bit_position",
-				successive_approximation_bit_position);
-
-		//			height = read2Bytes("Image_height", is, "Not a Valid JPEG File");
-		//			width = read2Bytes("Image_Width", is, "Not a Valid JPEG File");
-		//			Number_of_components = read_byte("Number_of_components", is,
-		//					"Not a Valid JPEG File");
-		//
-		//			// ignore the rest of the segment for now...
-		//			skipBytes(is, marker_length - 6,
-		//					"Not a Valid JPEG File: SOF0 Segment");
-		//
-		//			//				int Each_component1 = read_byte("Each_component1", is,
-		//			//						"Not a Valid JPEG File");
-		//			//				int Each_component2 = read_byte("Each_component2", is,
-		//			//						"Not a Valid JPEG File");
-		//			//				int Each_component3 = read_byte("Each_component3", is,
-		//			//						"Not a Valid JPEG File");
-		//		}
-
-		if (getDebug())
-			System.out.println("");
-	}
-
-	public String getDescription()
-	{
-		return "SOS (" + getSegmentType() + ")";
-	}
+    //    public final int width, height;
+    //    public final int Number_of_components;
+    //    public final int Precision;
+
+    //        public final byte bytes[];
+    //        public final int cur_marker, num_markers;
+
+    public SOSSegment(int marker, int marker_length, InputStream is)
+            throws ImageReadException, IOException
+    {
+        super(marker, marker_length);
+
+        if (getDebug())
+            System.out.println("SOSSegment marker_length: " + marker_length);
+
+        Debug.debug("SOS", marker_length);
+        //        {
+        int number_of_components_in_scan = readByte(
+                "number_of_components_in_scan", is, "Not a Valid JPEG File");
+        Debug.debug("number_of_components_in_scan",
+                number_of_components_in_scan);
+
+        for (int i = 0; i < number_of_components_in_scan; i++)
+        {
+            int scan_component_selector = readByte("scan_component_selector",
+                    is, "Not a Valid JPEG File");
+            Debug.debug("scan_component_selector", scan_component_selector);
+
+            int ac_dc_entrooy_coding_table_selector = readByte(
+                    "ac_dc_entrooy_coding_table_selector", is,
+                    "Not a Valid JPEG File");
+            Debug.debug("ac_dc_entrooy_coding_table_selector",
+                    ac_dc_entrooy_coding_table_selector);
+        }
+
+        int start_of_spectral_selection = readByte(
+                "start_of_spectral_selection", is, "Not a Valid JPEG File");
+        Debug.debug("start_of_spectral_selection", start_of_spectral_selection);
+        int end_of_spectral_selection = readByte("end_of_spectral_selection",
+                is, "Not a Valid JPEG File");
+        Debug.debug("end_of_spectral_selection", end_of_spectral_selection);
+        int successive_approximation_bit_position = readByte(
+                "successive_approximation_bit_position", is,
+                "Not a Valid JPEG File");
+        Debug.debug("successive_approximation_bit_position",
+                successive_approximation_bit_position);
+
+        //            height = read2Bytes("Image_height", is, "Not a Valid JPEG File");
+        //            width = read2Bytes("Image_Width", is, "Not a Valid JPEG File");
+        //            Number_of_components = read_byte("Number_of_components", is,
+        //                    "Not a Valid JPEG File");
+        //
+        //            // ignore the rest of the segment for now...
+        //            skipBytes(is, marker_length - 6,
+        //                    "Not a Valid JPEG File: SOF0 Segment");
+        //
+        //            //                int Each_component1 = read_byte("Each_component1", is,
+        //            //                        "Not a Valid JPEG File");
+        //            //                int Each_component2 = read_byte("Each_component2", is,
+        //            //                        "Not a Valid JPEG File");
+        //            //                int Each_component3 = read_byte("Each_component3", is,
+        //            //                        "Not a Valid JPEG File");
+        //        }
+
+        if (getDebug())
+            System.out.println("");
+    }
+
+    public String getDescription()
+    {
+        return "SOS (" + getSegmentType() + ")";
+    }
 
 }
\ No newline at end of file

Modified: commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java
URL: http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java?rev=995859&r1=995858&r2=995859&view=diff
==============================================================================
--- commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java (original)
+++ commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/Segment.java Fri Sep 10 16:33:35 2010
@@ -22,126 +22,126 @@ import org.apache.sanselan.common.Binary
 
 public abstract class Segment extends BinaryFileParser
 {
-	public final int marker;
-	public final int length;
+    public final int marker;
+    public final int length;
 
-	public Segment(int marker, int length)
-	{
-		//		super();
-
-		this.marker = marker;
-		this.length = length;
-	}
-
-	public void dump(PrintWriter pw)
-	{
-	}
-
-	public abstract String getDescription();
-
-	public String toString()
-	{
-		return "[Segment: " + getDescription() + "]";
-	}
-
-	public String getSegmentType()
-	{
-
-		switch (marker)
-		{
-			case 0xffc0 :
-				return "Start Of Frame, Baseline DCT, Huffman coding";
-			case 0xffc1 :
-				return "Start Of Frame, Extended sequential DCT, Huffman coding";
-			case 0xffc2 :
-				return "Start Of Frame, Progressive DCT, Huffman coding";
-			case 0xffc3 :
-				return "Start Of Frame, Lossless (sequential), Huffman coding";
-
-			case 0xffc5 :
-				return "Start Of Frame, Differential sequential DCT, Huffman coding";
-			case 0xffc6 :
-				return "Start Of Frame, Differential progressive DCT, Huffman coding";
-			case 0xffc7 :
-				return "Start Of Frame, Differential lossless (sequential), Huffman coding";
-
-			case 0xffc8 :
-				return "Start Of Frame, Reserved for JPEG extensions, arithmetic coding";
-			case 0xffc9 :
-				return "Start Of Frame, Extended sequential DCT, arithmetic coding";
-			case 0xffca :
-				return "Start Of Frame, Progressive DCT, arithmetic coding";
-			case 0xffcb :
-				return "Start Of Frame, Lossless (sequential), arithmetic coding";
-
-			case 0xffcd :
-				return "Start Of Frame, Differential sequential DCT, arithmetic coding";
-			case 0xffce :
-				return "Start Of Frame, Differential progressive DCT, arithmetic coding";
-			case 0xffcf :
-				return "Start Of Frame, Differential lossless (sequential), arithmetic coding";
-
-			case 0xffc4 :
-				return "Define Huffman table(s)";
-			case 0xffcc :
-				return "Define arithmetic coding conditioning(s)";
-
-			case 0xffd0 :
-				return "Restart with modulo 8 count 0";
-			case 0xffd1 :
-				return "Restart with modulo 8 count 1";
-			case 0xffd2 :
-				return "Restart with modulo 8 count 2";
-			case 0xffd3 :
-				return "Restart with modulo 8 count 3";
-			case 0xffd4 :
-				return "Restart with modulo 8 count 4";
-			case 0xffd5 :
-				return "Restart with modulo 8 count 5";
-			case 0xffd6 :
-				return "Restart with modulo 8 count 6";
-			case 0xffd7 :
-				return "Restart with modulo 8 count 7";
-
-			case 0xffd8 :
-				return "Start of image";
-			case 0xffd9 :
-				return "End of image";
-			case 0xffda :
-				return "Start of scan";
-			case 0xffdb :
-				return "Define quantization table(s)";
-			case 0xffdc :
-				return "Define number of lines";
-			case 0xffdd :
-				return "Define restart interval";
-			case 0xffde :
-				return "Define hierarchical progression";
-			case 0xffdf :
-				return "Expand reference component(s)";
-				//			case 0xffd8 :
-				//				return "Reserved for application segments";
-				//			case 0xffd8 :
-				//				return "Reserved for JPEG extensions";
-			case 0xfffe :
-				return "Comment";
-			case 0xff01 :
-				return "For temporary private use in arithmetic coding";
-				//			case 0xffd8 :
-				//				return "Reserved";
-
-			default :
-		}
-
-		if ((marker >= 0xff02) && (marker <= 0xffbf))
-			return "Reserved";
-		if ((marker >= 0xffe0) && (marker <= 0xffef))
-			return "APP" + (marker - 0xffe0);
-		if ((marker >= 0xfff0) && (marker <= 0xfffd))
-			return "JPG" + (marker - 0xffe0);
+    public Segment(int marker, int length)
+    {
+        //        super();
+
+        this.marker = marker;
+        this.length = length;
+    }
+
+    public void dump(PrintWriter pw)
+    {
+    }
+
+    public abstract String getDescription();
+
+    public String toString()
+    {
+        return "[Segment: " + getDescription() + "]";
+    }
+
+    public String getSegmentType()
+    {
+
+        switch (marker)
+        {
+            case 0xffc0 :
+                return "Start Of Frame, Baseline DCT, Huffman coding";
+            case 0xffc1 :
+                return "Start Of Frame, Extended sequential DCT, Huffman coding";
+            case 0xffc2 :
+                return "Start Of Frame, Progressive DCT, Huffman coding";
+            case 0xffc3 :
+                return "Start Of Frame, Lossless (sequential), Huffman coding";
+
+            case 0xffc5 :
+                return "Start Of Frame, Differential sequential DCT, Huffman coding";
+            case 0xffc6 :
+                return "Start Of Frame, Differential progressive DCT, Huffman coding";
+            case 0xffc7 :
+                return "Start Of Frame, Differential lossless (sequential), Huffman coding";
+
+            case 0xffc8 :
+                return "Start Of Frame, Reserved for JPEG extensions, arithmetic coding";
+            case 0xffc9 :
+                return "Start Of Frame, Extended sequential DCT, arithmetic coding";
+            case 0xffca :
+                return "Start Of Frame, Progressive DCT, arithmetic coding";
+            case 0xffcb :
+                return "Start Of Frame, Lossless (sequential), arithmetic coding";
+
+            case 0xffcd :
+                return "Start Of Frame, Differential sequential DCT, arithmetic coding";
+            case 0xffce :
+                return "Start Of Frame, Differential progressive DCT, arithmetic coding";
+            case 0xffcf :
+                return "Start Of Frame, Differential lossless (sequential), arithmetic coding";
+
+            case 0xffc4 :
+                return "Define Huffman table(s)";
+            case 0xffcc :
+                return "Define arithmetic coding conditioning(s)";
+
+            case 0xffd0 :
+                return "Restart with modulo 8 count 0";
+            case 0xffd1 :
+                return "Restart with modulo 8 count 1";
+            case 0xffd2 :
+                return "Restart with modulo 8 count 2";
+            case 0xffd3 :
+                return "Restart with modulo 8 count 3";
+            case 0xffd4 :
+                return "Restart with modulo 8 count 4";
+            case 0xffd5 :
+                return "Restart with modulo 8 count 5";
+            case 0xffd6 :
+                return "Restart with modulo 8 count 6";
+            case 0xffd7 :
+                return "Restart with modulo 8 count 7";
+
+            case 0xffd8 :
+                return "Start of image";
+            case 0xffd9 :
+                return "End of image";
+            case 0xffda :
+                return "Start of scan";
+            case 0xffdb :
+                return "Define quantization table(s)";
+            case 0xffdc :
+                return "Define number of lines";
+            case 0xffdd :
+                return "Define restart interval";
+            case 0xffde :
+                return "Define hierarchical progression";
+            case 0xffdf :
+                return "Expand reference component(s)";
+                //            case 0xffd8 :
+                //                return "Reserved for application segments";
+                //            case 0xffd8 :
+                //                return "Reserved for JPEG extensions";
+            case 0xfffe :
+                return "Comment";
+            case 0xff01 :
+                return "For temporary private use in arithmetic coding";
+                //            case 0xffd8 :
+                //                return "Reserved";
+
+            default :
+        }
+
+        if ((marker >= 0xff02) && (marker <= 0xffbf))
+            return "Reserved";
+        if ((marker >= 0xffe0) && (marker <= 0xffef))
+            return "APP" + (marker - 0xffe0);
+        if ((marker >= 0xfff0) && (marker <= 0xfffd))
+            return "JPG" + (marker - 0xffe0);
 
-		return "Unknown";
+        return "Unknown";
 
-	}
+    }
 
 }
\ No newline at end of file