You are viewing a plain text version of this content. The canonical link for it is here.
Posted to sanselan-commits@incubator.apache.org by cm...@apache.org on 2008/08/24 20:47:31 UTC
svn commit: r688558 [1/2] - in /incubator/sanselan/trunk: ./
src/main/java/org/apache/sanselan/common/
src/main/java/org/apache/sanselan/formats/jpeg/
src/main/java/org/apache/sanselan/formats/jpeg/iptc/
src/main/java/org/apache/sanselan/formats/jpeg/s...
Author: cmchen
Date: Sun Aug 24 13:47:30 2008
New Revision: 688558
URL: http://svn.apache.org/viewvc?rev=688558&view=rev
Log:
* Started shift towards moving field-level parsing into BinaryInputStream and BinaryOutputStream.
* Fixed a png unit test that used a piece of Java 1.6 syntax.
* Added unit tests around the new IPTC functionality.
* Added IPTC remove/update/insert functionality.
* Rewrote the IPTC parsing support.
Added:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java (with props)
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/IptcBaseTest.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/IptcDumpTest.java (with props)
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/iptc/IptcUpdateTest.java (with props)
Removed:
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/IptcElement.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/IptcType.java
Modified:
incubator/sanselan/trunk/RELEASE_NOTES
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/segments/App13Segment.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/xmp/JpegRewriter.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldType.java
incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/fieldtypes/FieldTypeASCII.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/SanselanTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/JpegReadTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpBaseTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpDumpTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/jpeg/xmp/JpegXmpRewriteTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/png/PngBaseTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/png/PngMultipleRoundtripTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpDumpTest.java
incubator/sanselan/trunk/src/test/java/org/apache/sanselan/formats/xmp/XmpUpdateTest.java
Modified: incubator/sanselan/trunk/RELEASE_NOTES
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/RELEASE_NOTES?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/RELEASE_NOTES (original)
+++ incubator/sanselan/trunk/RELEASE_NOTES Sun Aug 24 13:47:30 2008
@@ -15,6 +15,11 @@
Release 0.95
------------
+ * Started shift towards moving field-level parsing into BinaryInputStream and BinaryOutputStream.
+ * Fixed a png unit test that used a piece of Java 1.6 syntax.
+ * Added unit tests around the new IPTC functionality.
+ * Added IPTC remove/update/insert functionality.
+ * Rewrote the IPTC parsing support.
* Added improved support for reading and writing iTXt, tEXt, zTXt Png chunks.
Added a unit test that demonstrates the feature.
* Found a new regression wherein DeflaterOutputStream needs to be closed.
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryFileFunctions.java Sun Aug 24 13:47:30 2008
@@ -445,8 +445,6 @@
int byte0 = 0xff & bytes[index + 0];
int byte1 = 0xff & bytes[index + 1];
- // return convert2BytesToShort(name, byte0, byte1, byteOrder);
-
int result;
if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
@@ -540,11 +538,14 @@
}
public final byte[] readBytearray(String name, byte bytes[], int start,
- int count)
+ int count) throws ImageReadException
{
if (bytes.length < (start + count))
- return null;
-
+ {
+ throw new ImageReadException("Invalid read. bytes.length: " + bytes.length+ ", start: " + start + ", count: " + count);
+ // return null;
+ }
+
byte result[] = new byte[count];
System.arraycopy(bytes, start, result, 0, count);
@@ -554,12 +555,12 @@
return result;
}
- protected final byte[] getByteArrayTail(String name, byte bytes[], int count)
+ protected final byte[] getByteArrayTail(String name, byte bytes[], int count) throws ImageReadException
{
return readBytearray(name, bytes, count, bytes.length - count);
}
- protected final byte[] getBytearrayHead(String name, byte bytes[], int count)
+ protected final byte[] getBytearrayHead(String name, byte bytes[], int count) throws ImageReadException
{
return readBytearray(name, bytes, 0, bytes.length - count);
}
@@ -592,11 +593,7 @@
public final boolean compareByteArrays(byte a[], byte b[])
{
if (a.length != b.length)
- {
- // System.out.println("length mismatch: " + a.length + " != "
- // + b.length);
return false;
- }
return compareByteArrays(a, 0, b, 0, a.length);
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryInputStream.java Sun Aug 24 13:47:30 2008
@@ -16,6 +16,7 @@
*/
package org.apache.sanselan.common;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
@@ -38,6 +39,12 @@
private final InputStream is;
+ public BinaryInputStream(byte bytes[], int byteOrder)
+ {
+ this.byteOrder = byteOrder;
+ this.is = new ByteArrayInputStream(bytes);
+ }
+
public BinaryInputStream(InputStream is, int byteOrder)
{
this.byteOrder = byteOrder;
@@ -161,7 +168,7 @@
this.debugByteArray("expected", expected);
debugNumber("data[" + i + "]", b);
- // debugNumber("expected[" + i + "]", expected[i]);
+ // debugNumber("expected[" + i + "]", expected[i]);
throw new ImageReadException(exception);
}
@@ -203,7 +210,7 @@
{
int count = 0;
for (int i = 0; count < 3; i++)
- // while(count<3)
+ // while(count<3)
{
int b = is.read();
if (b < 0)
@@ -289,21 +296,22 @@
if (length == 4)
byte3 = bytes[start + 3];
- // return convert4BytesToInt(name, byte0, byte1, byte2, byte3, byteOrder);
+ // return convert4BytesToInt(name, byte0, byte1, byte2, byte3,
+ // byteOrder);
int result;
if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
result = ((0xff & byte0) << 24) + ((0xff & byte1) << 16)
+ ((0xff & byte2) << 8) + ((0xff & byte3) << 0);
- // result = (( byte0) << 24) + ((byte1) << 16)
- // + (( byte2) << 8) + (( byte3) << 0);
+ // result = (( byte0) << 24) + ((byte1) << 16)
+ // + (( byte2) << 8) + (( byte3) << 0);
else
// intel, little endian
result = ((0xff & byte3) << 24) + ((0xff & byte2) << 16)
+ ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
- // result = (( byte3) << 24) + (( byte2) << 16)
- // + (( byte1) << 8) + (( byte0) << 0);
+ // result = (( byte3) << 24) + (( byte2) << 16)
+ // + (( byte1) << 8) + (( byte0) << 0);
if (debug)
debugNumber(name, result, 4);
@@ -346,7 +354,7 @@
byte byte0 = bytes[start + 0];
byte byte1 = bytes[start + 1];
- // return convert2BytesToShort(name, byte0, byte1, byteOrder);
+ // return convert2BytesToShort(name, byte0, byte1, byteOrder);
int result;
@@ -381,9 +389,9 @@
result[i] = convertByteArrayToShort(name, start + i * 2, bytes,
byteOrder);
- // byte byte0 = bytes[start + i * 2];
- // byte byte1 = bytes[start + i * 2 + 1];
- // result[i] = convertBytesToShort(name, byte0, byte1, byteOrder);
+ // byte byte0 = bytes[start + i * 2];
+ // byte byte1 = bytes[start + i * 2 + 1];
+ // result[i] = convertBytesToShort(name, byte0, byte1, byteOrder);
}
return result;
@@ -449,6 +457,34 @@
return result;
}
+ public final byte[] readByteArray(int length, String error)
+ throws ImageReadException, IOException
+ {
+ boolean verbose = false;
+ boolean strict = true;
+ return readByteArray(length, error, verbose, strict);
+ }
+
+ public final byte[] readByteArray(int length, String error,
+ boolean verbose, boolean strict) throws ImageReadException,
+ IOException
+ {
+ byte bytes[] = new byte[length];
+ int total = 0;
+ int read;
+ while ((read = read(bytes, total, length - total)) > 0)
+ total += read;
+ if (total < length)
+ {
+ if (strict)
+ throw new ImageReadException(error);
+ else if(verbose)
+ System.out.println(error);
+ return null;
+ }
+ return bytes;
+ }
+
protected final byte[] getBytearrayTail(String name, byte bytes[], int count)
{
return readBytearray(name, bytes, count, bytes.length - count);
@@ -539,6 +575,50 @@
return convertByteArrayToShort(name, bytes, byteOrder);
}
+ public final int read1ByteInteger(String exception)
+ throws ImageReadException, IOException
+ {
+ int byte0 = is.read();
+ if (byte0 < 0)
+ throw new ImageReadException(exception);
+
+ return 0xff & byte0;
+ }
+
+ public final int read2ByteInteger(String exception)
+ throws ImageReadException, IOException
+ {
+ int byte0 = is.read();
+ int byte1 = is.read();
+ if (byte0 < 0 || byte1 < 0)
+ throw new ImageReadException(exception);
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ return ((0xff & byte0) << 8) + ((0xff & byte1) << 0);
+ else
+ // intel, little endian
+ return ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
+ }
+
+ public final int read4ByteInteger(String exception)
+ throws ImageReadException, IOException
+ {
+ int byte0 = is.read();
+ int byte1 = is.read();
+ int byte2 = is.read();
+ int byte3 = is.read();
+ if (byte0 < 0 || byte1 < 0 || byte2 < 0 || byte3 < 0)
+ throw new ImageReadException(exception);
+
+ if (byteOrder == BYTE_ORDER_MOTOROLA) // motorola, big endian
+ return ((0xff & byte0) << 24) + ((0xff & byte1) << 16)
+ + ((0xff & byte2) << 8) + ((0xff & byte3) << 0);
+ else
+ // intel, little endian
+ return ((0xff & byte3) << 24) + ((0xff & byte2) << 16)
+ + ((0xff & byte1) << 8) + ((0xff & byte0) << 0);
+ }
+
protected final void printCharQuad(String msg, int i)
{
System.out.println(msg + ": '" + (char) (0xff & (i >> 24))
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/common/BinaryOutputStream.java Sun Aug 24 13:47:30 2008
@@ -106,10 +106,42 @@
writeNBytes(value, 2);
}
+ public final void write4ByteInteger(int value) throws ImageWriteException,
+ IOException
+ {
+ if (byteOrder == BYTE_ORDER_MOTOROLA)
+ {
+ write(0xff & (value >> 24));
+ write(0xff & (value >> 16));
+ write(0xff & (value >> 8));
+ write(0xff & value);
+ } else
+ {
+ write(0xff & value);
+ write(0xff & (value >> 8));
+ write(0xff & (value >> 16));
+ write(0xff & (value >> 24));
+ }
+ }
+
+ public final void write2ByteInteger(int value) throws ImageWriteException,
+ IOException
+ {
+ if (byteOrder == BYTE_ORDER_MOTOROLA)
+ {
+ write(0xff & (value >> 8));
+ write(0xff & value);
+ } else
+ {
+ write(0xff & value);
+ write(0xff & (value >> 8));
+ }
+ }
+
public final void writeByteArray(byte bytes[]) throws IOException
{
os.write(bytes, 0, bytes.length);
- count+=bytes.length;
+ count += bytes.length;
}
private byte[] convertValueToByteArray(int value, int n)
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegConstants.java Sun Aug 24 13:47:30 2008
@@ -16,8 +16,10 @@
*/
package org.apache.sanselan.formats.jpeg;
-public interface JpegConstants
-{
+import org.apache.sanselan.formats.jpeg.iptc.IPTCType;
+
+
+public interface JpegConstants {
public static final int MAX_SEGMENT_SIZE = 0xffff;
public static final byte JFIF0_SIGNATURE[] = new byte[] { 0x4a, // J
@@ -70,6 +72,7 @@
public static final byte SOI[] = new byte[] { (byte) 0xff, (byte) 0xd8 };
public static final byte EOI[] = new byte[] { (byte) 0xff, (byte) 0xd9 };
+
public static final int SOS_Marker = (0xff00) | (0xda);
public static final int JPEG_APP0 = 0xE0;
@@ -122,148 +125,5 @@
public static final byte CONST_8BIM[] = { 0xff & '8', 0xff & 'B',
0xff & 'I', 0xff & 'M', };
- public static final byte IPTCPrefix[] = { 0x1C, 0x02, };
- public static final IptcType IPTC_TYPE_RecordVersion = new IptcType(0,
- "RecordVersion");
- public static final IptcType IPTC_TYPE_ObjectTypeReference = new IptcType(
- 3, "ObjectTypeReference");
- public static final IptcType IPTC_TYPE_ObjectAttributeReference = new IptcType(
- 4, "ObjectAttributeReference");
- public static final IptcType IPTC_TYPE_ObjectName = new IptcType(5,
- "ObjectName");
- public static final IptcType IPTC_TYPE_EditStatus = new IptcType(7,
- "EditStatus");
- public static final IptcType IPTC_TYPE_EditorialUpdate = new IptcType(8,
- "EditorialUpdate");
- public static final IptcType IPTC_TYPE_Urgency = new IptcType(10, "Urgency");
- public static final IptcType IPTC_TYPE_SubjectReference = new IptcType(12,
- "SubjectReference");
- public static final IptcType IPTC_TYPE_Category = new IptcType(15,
- "Category");
- public static final IptcType IPTC_TYPE_SupplementalCategory = new IptcType(
- 20, "SupplementalCategory");
- public static final IptcType IPTC_TYPE_FixtureIdentifier = new IptcType(22,
- "FixtureIdentifier");
- public static final IptcType IPTC_TYPE_Keywords = new IptcType(25,
- "Keywords");
- public static final IptcType IPTC_TYPE_ContentLocationCode = new IptcType(
- 26, "ContentLocationCode");
- public static final IptcType IPTC_TYPE_ContentLocationName = new IptcType(
- 27, "ContentLocationName");
- public static final IptcType IPTC_TYPE_ReleaseDate = new IptcType(30,
- "ReleaseDate");
- public static final IptcType IPTC_TYPE_ReleaseTime = new IptcType(35,
- "ReleaseTime");
- public static final IptcType IPTC_TYPE_ExpirationDate = new IptcType(37,
- "ExpirationDate");
- public static final IptcType IPTC_TYPE_ExpirationTime = new IptcType(38,
- "ExpirationTime");
- public static final IptcType IPTC_TYPE_SpecialInstructions = new IptcType(
- 40, "SpecialInstructions");
- public static final IptcType IPTC_TYPE_ActionAdvised = new IptcType(42,
- "ActionAdvised");
- public static final IptcType IPTC_TYPE_ReferenceService = new IptcType(45,
- "ReferenceService");
- public static final IptcType IPTC_TYPE_ReferenceDate = new IptcType(47,
- "ReferenceDate");
- public static final IptcType IPTC_TYPE_ReferenceNumber = new IptcType(50,
- "ReferenceNumber");
- public static final IptcType IPTC_TYPE_DateCreated = new IptcType(55,
- "DateCreated");
- public static final IptcType IPTC_TYPE_TimeCreated = new IptcType(60,
- "TimeCreated");
- public static final IptcType IPTC_TYPE_DigitalCreationDate = new IptcType(
- 62, "DigitalCreationDate");
- public static final IptcType IPTC_TYPE_DigitalCreationTime = new IptcType(
- 63, "DigitalCreationTime");
- public static final IptcType IPTC_TYPE_OriginatingProgram = new IptcType(
- 65, "OriginatingProgram");
- public static final IptcType IPTC_TYPE_ProgramVersion = new IptcType(70,
- "ProgramVersion");
- public static final IptcType IPTC_TYPE_ObjectCycle = new IptcType(75,
- "ObjectCycle");
- public static final IptcType IPTC_TYPE_Byline = new IptcType(80, "By-line");
- public static final IptcType IPTC_TYPE_BylineTitle = new IptcType(85,
- "By-lineTitle");
- public static final IptcType IPTC_TYPE_City = new IptcType(90, "City");
- public static final IptcType IPTC_TYPE_Sublocation = new IptcType(92,
- "Sublocation");
- public static final IptcType IPTC_TYPE_Province_State = new IptcType(95,
- "Province/State");
- public static final IptcType IPTC_TYPE_Country_PrimaryLocationCode = new IptcType(
- 100, "Country/PrimaryLocationCode");
- public static final IptcType IPTC_TYPE_Country_PrimaryLocationName = new IptcType(
- 101, "Country/PrimaryLocationName");
- public static final IptcType IPTC_TYPE_OriginalTransmission_Reference = new IptcType(
- 103, "OriginalTransmission,Reference");
- public static final IptcType IPTC_TYPE_Headline = new IptcType(105,
- "Headline");
- public static final IptcType IPTC_TYPE_Credit = new IptcType(110, "Credit");
- public static final IptcType IPTC_TYPE_Source = new IptcType(115, "Source");
- public static final IptcType IPTC_TYPE_CopyrightNotice = new IptcType(116,
- "CopyrightNotice");
- public static final IptcType IPTC_TYPE_Contact = new IptcType(118,
- "Contact");
- public static final IptcType IPTC_TYPE_Caption_Abstract = new IptcType(120,
- "Caption/Abstract");
- public static final IptcType IPTC_TYPE_Writer_Editor = new IptcType(122,
- "Writer/Editor");
- public static final IptcType IPTC_TYPE_RasterizedCaption = new IptcType(
- 125, "RasterizedCaption");
- public static final IptcType IPTC_TYPE_ImageType = new IptcType(130,
- "ImageType");
- public static final IptcType IPTC_TYPE_ImageOrientation = new IptcType(131,
- "ImageOrientation");
- public static final IptcType IPTC_TYPE_LanguageIdentifier = new IptcType(
- 135, "LanguageIdentifier");
- public static final IptcType IPTC_TYPE_AudioType = new IptcType(150,
- "AudioType");
- public static final IptcType IPTC_TYPE_AudioSamplingRate = new IptcType(
- 151, "AudioSamplingRate");
- public static final IptcType IPTC_TYPE_AudioSamplingResolution = new IptcType(
- 152, "AudioSamplingResolution");
- public static final IptcType IPTC_TYPE_AudioDuration = new IptcType(153,
- "AudioDuration");
- public static final IptcType IPTC_TYPE_AudioOutcue = new IptcType(154,
- "AudioOutcue");
- public static final IptcType IPTC_TYPE_ObjectDataPreview_FileFormat = new IptcType(
- 200, "ObjectDataPreview,FileFormat");
- public static final IptcType IPTC_TYPE_ObjectDataPreview_FileFormatVersion = new IptcType(
- 201, "ObjectDataPreview,FileFormatVersion");
- public static final IptcType IPTC_TYPE_ObjectDataPreviewData = new IptcType(
- 202, "ObjectDataPreviewData");
- // --
- public static final IptcType IPTC_TYPE_Unknown = new IptcType(-1, "Unknown");
-
- public static final IptcType IPTC_TYPES[] = { IPTC_TYPE_RecordVersion,
- IPTC_TYPE_ObjectTypeReference, IPTC_TYPE_ObjectAttributeReference,
- IPTC_TYPE_ObjectName, IPTC_TYPE_EditStatus,
- IPTC_TYPE_EditorialUpdate, IPTC_TYPE_Urgency,
- IPTC_TYPE_SubjectReference, IPTC_TYPE_Category,
- IPTC_TYPE_SupplementalCategory, IPTC_TYPE_FixtureIdentifier,
- IPTC_TYPE_Keywords, IPTC_TYPE_ContentLocationCode,
- IPTC_TYPE_ContentLocationName, IPTC_TYPE_ReleaseDate,
- IPTC_TYPE_ReleaseTime, IPTC_TYPE_ExpirationDate,
- IPTC_TYPE_ExpirationTime, IPTC_TYPE_SpecialInstructions,
- IPTC_TYPE_ActionAdvised, IPTC_TYPE_ReferenceService,
- IPTC_TYPE_ReferenceDate, IPTC_TYPE_ReferenceNumber,
- IPTC_TYPE_DateCreated, IPTC_TYPE_TimeCreated,
- IPTC_TYPE_DigitalCreationDate, IPTC_TYPE_DigitalCreationTime,
- IPTC_TYPE_OriginatingProgram, IPTC_TYPE_ProgramVersion,
- IPTC_TYPE_ObjectCycle, IPTC_TYPE_Byline, IPTC_TYPE_BylineTitle,
- IPTC_TYPE_City, IPTC_TYPE_Sublocation, IPTC_TYPE_Province_State,
- IPTC_TYPE_Country_PrimaryLocationCode,
- IPTC_TYPE_Country_PrimaryLocationName,
- IPTC_TYPE_OriginalTransmission_Reference, IPTC_TYPE_Headline,
- IPTC_TYPE_Credit, IPTC_TYPE_Source, IPTC_TYPE_CopyrightNotice,
- IPTC_TYPE_Contact, IPTC_TYPE_Caption_Abstract,
- IPTC_TYPE_Writer_Editor, IPTC_TYPE_RasterizedCaption,
- IPTC_TYPE_ImageType, IPTC_TYPE_ImageOrientation,
- IPTC_TYPE_LanguageIdentifier, IPTC_TYPE_AudioType,
- IPTC_TYPE_AudioSamplingRate, IPTC_TYPE_AudioSamplingResolution,
- IPTC_TYPE_AudioDuration, IPTC_TYPE_AudioOutcue,
- IPTC_TYPE_ObjectDataPreview_FileFormat,
- IPTC_TYPE_ObjectDataPreview_FileFormatVersion,
- IPTC_TYPE_ObjectDataPreviewData, };
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageMetadata.java Sun Aug 24 13:47:30 2008
@@ -22,44 +22,33 @@
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.IImageMetadata;
-import org.apache.sanselan.common.ImageMetadata;
import org.apache.sanselan.formats.tiff.TiffField;
import org.apache.sanselan.formats.tiff.TiffImageData;
import org.apache.sanselan.formats.tiff.TiffImageMetadata;
import org.apache.sanselan.formats.tiff.constants.TagInfo;
import org.apache.sanselan.util.Debug;
-public class JpegImageMetadata implements IImageMetadata
-{
- public static class Photoshop extends ImageMetadata
- {
- }
-
- private final Photoshop photoshop;
+public class JpegImageMetadata implements IImageMetadata {
+ private final JpegPhotoshopMetadata photoshop;
private final TiffImageMetadata exif;
- public JpegImageMetadata(final Photoshop photoshop,
- final TiffImageMetadata exif)
- {
+ public JpegImageMetadata(final JpegPhotoshopMetadata photoshop,
+ final TiffImageMetadata exif) {
this.photoshop = photoshop;
this.exif = exif;
}
- public TiffImageMetadata getExif()
- {
+ public TiffImageMetadata getExif() {
return exif;
}
- public Photoshop getPhotoshop()
- {
+ public JpegPhotoshopMetadata getPhotoshop() {
return photoshop;
}
- public TiffField findEXIFValue(TagInfo tagInfo)
- {
+ public TiffField findEXIFValue(TagInfo tagInfo) {
ArrayList items = getItems();
- for (int i = 0; i < items.size(); i++)
- {
+ for (int i = 0; i < items.size(); i++) {
Object o = items.get(i);
if (!(o instanceof TiffImageMetadata.Item))
continue;
@@ -74,14 +63,12 @@
}
public BufferedImage getEXIFThumbnail() throws ImageReadException,
- IOException
- {
+ IOException {
ArrayList dirs = exif.getDirectories();
- for (int i = 0; i < dirs.size(); i++)
- {
+ for (int i = 0; i < dirs.size(); i++) {
TiffImageMetadata.Directory dir = (TiffImageMetadata.Directory) dirs
.get(i);
- // Debug.debug("dir", dir);
+ // Debug.debug("dir", dir);
BufferedImage image = dir.getThumbnail();
if (null != image)
return image;
@@ -90,14 +77,12 @@
return null;
}
- public TiffImageData getRawImageData()
- {
+ public TiffImageData getRawImageData() {
ArrayList dirs = exif.getDirectories();
- for (int i = 0; i < dirs.size(); i++)
- {
+ for (int i = 0; i < dirs.size(); i++) {
TiffImageMetadata.Directory dir = (TiffImageMetadata.Directory) dirs
.get(i);
- // Debug.debug("dir", dir);
+ // Debug.debug("dir", dir);
TiffImageData rawImageData = dir.getTiffImageData();
if (null != rawImageData)
return rawImageData;
@@ -106,8 +91,7 @@
return null;
}
- public ArrayList getItems()
- {
+ public ArrayList getItems() {
ArrayList result = new ArrayList();
if (null != exif)
@@ -121,13 +105,11 @@
private static final String newline = System.getProperty("line.separator");
- public String toString()
- {
+ public String toString() {
return toString(null);
}
- public String toString(String prefix)
- {
+ public String toString(String prefix) {
if (prefix == null)
prefix = "";
@@ -136,21 +118,19 @@
result.append(prefix);
if (null == exif)
result.append("No Exif metadata.");
- else
- {
+ else {
result.append("Exif metadata:");
result.append(newline);
result.append(exif.toString("\t"));
}
- // if (null != exif && null != photoshop)
+ // if (null != exif && null != photoshop)
result.append(newline);
result.append(prefix);
if (null == photoshop)
result.append("No Photoshop (IPTC) metadata.");
- else
- {
+ else {
result.append("Photoshop (IPTC) metadata:");
result.append(newline);
result.append(photoshop.toString("\t"));
@@ -159,8 +139,7 @@
return result.toString();
}
- public void dump()
- {
+ public void dump() {
Debug.debug(this.toString());
}
Modified: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java?rev=688558&r1=688557&r2=688558&view=diff
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java (original)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegImageParser.java Sun Aug 24 13:47:30 2008
@@ -34,6 +34,9 @@
import org.apache.sanselan.ImageReadException;
import org.apache.sanselan.common.IImageMetadata;
import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCRecord;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCParser;
+import org.apache.sanselan.formats.jpeg.iptc.PhotoshopApp13Data;
import org.apache.sanselan.formats.jpeg.segments.App13Segment;
import org.apache.sanselan.formats.jpeg.segments.App2Segment;
import org.apache.sanselan.formats.jpeg.segments.GenericSegment;
@@ -304,12 +307,12 @@
{
TiffImageMetadata exif = getExifMetadata(byteSource, params);
- JpegImageMetadata.Photoshop photoshop = getPhotoshopMetadata(byteSource);
+ JpegPhotoshopMetadata photoshop = getPhotoshopMetadata(byteSource,
+ params);
if (null == exif && null == photoshop)
return null;
-
JpegImageMetadata result = new JpegImageMetadata(photoshop, exif);
return result;
@@ -447,6 +450,49 @@
return result[0];
}
+ public boolean hasIptcSegment(ByteSource byteSource)
+ throws ImageReadException, IOException
+ {
+ final boolean result[] = { false, };
+
+ JpegUtils.Visitor visitor = new JpegUtils.Visitor() {
+ // return false to exit before reading image data.
+ public boolean beginSOS()
+ {
+ return false;
+ }
+
+ public void visitSOS(int marker, byte markerBytes[],
+ byte imageData[])
+ {
+ }
+
+ // return false to exit traversal.
+ public boolean visitSegment(int marker, byte markerBytes[],
+ int markerLength, byte markerLengthBytes[],
+ byte segmentData[]) throws ImageReadException, IOException
+ {
+ if (marker == 0xffd9)
+ return false;
+
+ if (marker == JPEG_APP13_Marker)
+ {
+ if (new IPTCParser().isPhotoshopJpegSegment(segmentData))
+ {
+ result[0] = true;
+ return false;
+ }
+ }
+
+ return true;
+ }
+ };
+
+ new JpegUtils().traverseJFIF(byteSource, visitor);
+
+ return result[0];
+ }
+
public boolean hasXmpSegment(ByteSource byteSource)
throws ImageReadException, IOException
{
@@ -497,10 +543,11 @@
* File containing image data.
* @param params
* Map of optional parameters, defined in SanselanConstants.
- * @return Xmp Xml as String, if present. Otherwise, returns null..
+ * @return Xmp Xml as String, if present. Otherwise, returns null..
*/
public String getXmpXml(ByteSource byteSource, Map params)
- throws ImageReadException, IOException {
+ throws ImageReadException, IOException
+ {
final List result = new ArrayList();
@@ -547,8 +594,8 @@
return (String) result.get(0);
}
- private JpegImageMetadata.Photoshop getPhotoshopMetadata(
- ByteSource byteSource) throws ImageReadException, IOException
+ public JpegPhotoshopMetadata getPhotoshopMetadata(ByteSource byteSource,
+ Map params) throws ImageReadException, IOException
{
ArrayList segments = readSegments(byteSource,
new int[] { JPEG_APP13_Marker, }, false);
@@ -556,22 +603,23 @@
if ((segments == null) || (segments.size() < 1))
return null;
- JpegImageMetadata.Photoshop result = new JpegImageMetadata.Photoshop();
+ PhotoshopApp13Data photoshopApp13Data = null;
for (int i = 0; i < segments.size(); i++)
{
App13Segment segment = (App13Segment) segments.get(i);
- ArrayList elements = segment.elements;
+ PhotoshopApp13Data data = segment.parsePhotoshopSegment(params);
+ if (data != null && photoshopApp13Data != null)
+ throw new ImageReadException(
+ "Jpeg contains more than one Photoshop App13 segment.");
- for (int j = 0; j < elements.size(); j++)
- {
- IptcElement element = (IptcElement) elements.get(j);
- result.add(element.getIptcTypeName(), element.getValue());
- }
+ photoshopApp13Data = data;
}
- return result;
+ if(null==photoshopApp13Data)
+ return null;
+ return new JpegPhotoshopMetadata(photoshopApp13Data);
}
public Dimension getImageSize(ByteSource byteSource, Map params)
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,40 @@
+/**
+ *
+ */
+package org.apache.sanselan.formats.jpeg;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sanselan.common.ImageMetadata;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCConstants;
+import org.apache.sanselan.formats.jpeg.iptc.IPTCRecord;
+import org.apache.sanselan.formats.jpeg.iptc.PhotoshopApp13Data;
+import org.apache.sanselan.util.Debug;
+
+public class JpegPhotoshopMetadata extends ImageMetadata implements
+ IPTCConstants
+{
+
+ public final PhotoshopApp13Data photoshopApp13Data;
+
+ public JpegPhotoshopMetadata(final PhotoshopApp13Data photoshopApp13Data)
+ {
+ this.photoshopApp13Data = photoshopApp13Data;
+
+ List records = photoshopApp13Data.getRecords();
+ Collections.sort(records, IPTCRecord.COMPARATOR);
+ for (int j = 0; j < records.size(); j++)
+ {
+ IPTCRecord element = (IPTCRecord) records.get(j);
+ if (element.iptcType.type != IPTC_TYPE_RECORD_VERSION.type)
+ add(element.getIptcTypeName(), element.getValue());
+ }
+ }
+
+ public void dump()
+ {
+ Debug.debug(this.toString());
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/JpegPhotoshopMetadata.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,23 @@
+/**
+ *
+ */
+package org.apache.sanselan.formats.jpeg.iptc;
+
+public class IPTCBlock
+{
+ public final int blockType;
+ public final byte[] blockNameBytes;
+ public final byte[] blockData;
+
+ public IPTCBlock(int blockType, byte[] blockNameBytes, byte[] blockData)
+ {
+ this.blockData = blockData;
+ this.blockNameBytes = blockNameBytes;
+ this.blockType = blockType;
+ }
+
+ public boolean isIPTCBlock()
+ {
+ return blockType == IPTCParser.IMAGE_RESOURCE_BLOCK_IPTC_DATA;
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCBlock.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.formats.jpeg.iptc;
+
+public interface IPTCConstants
+{
+
+ // public static final byte PhotoshopIdentificationString[] =
+ // "Photoshop 3.0"
+ // .getBytes();
+ public static final byte PHOTOSHOP_IDENTIFICATION_STRING[] = { 0xff & 'P',
+ 0xff & 'h', 0xff & 'o', 0xff & 't', 0xff & 'o', 0xff & 's',
+ 0xff & 'h', 0xff & 'o', 0xff & 'p', 0xff & ' ', 0xff & '3',
+ 0xff & '.', 0xff & '0', 0, };
+ public static final byte CONST_8BIM[] = { 0xff & '8', 0xff & 'B',
+ 0xff & 'I', 0xff & 'M', };
+
+ public static final byte IPTCPrefix[] = { 0x1C, 0x02, };
+
+
+ public static final int IPTC_NON_EXTENDED_RECORD_MAXIMUM_SIZE = 32767;
+
+ public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP2_INFO = 0x03e8;
+ public static final int IMAGE_RESOURCE_BLOCK_MACINTOSH_PRINT_INFO = 0x03e9;
+ public static final int IMAGE_RESOURCE_BLOCK_XML_DATA = 0x03ea;
+ public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP2_COLOR_TABLE = 0x03eb;
+ public static final int IMAGE_RESOURCE_BLOCK_RESOLUTION_INFO = 0x03ed;
+ public static final int IMAGE_RESOURCE_BLOCK_ALPHA_CHANNELS_NAMES = 0x03ee;
+ public static final int IMAGE_RESOURCE_BLOCK_DISPLAY_INFO = 0x03ef;
+ public static final int IMAGE_RESOURCE_BLOCK_PSTRING_CAPTION = 0x03f0;
+ public static final int IMAGE_RESOURCE_BLOCK_BORDER_INFORMATION = 0x03f1;
+ public static final int IMAGE_RESOURCE_BLOCK_BACKGROUND_COLOR = 0x03f2;
+ public static final int IMAGE_RESOURCE_BLOCK_PRINT_FLAGS = 0x03f3;
+ public static final int IMAGE_RESOURCE_BLOCK_BW_HALFTONING_INFO = 0x03f4;
+ public static final int IMAGE_RESOURCE_BLOCK_COLOR_HALFTONING_INFO = 0x03f5;
+ public static final int IMAGE_RESOURCE_BLOCK_DUOTONE_HALFTONING_INFO = 0x03f6;
+ public static final int IMAGE_RESOURCE_BLOCK_BW_TRANSFER_FUNC = 0x03f7;
+ public static final int IMAGE_RESOURCE_BLOCK_COLOR_TRANSFER_FUNCS = 0x03f8;
+ public static final int IMAGE_RESOURCE_BLOCK_DUOTONE_TRANSFER_FUNCS = 0x03f9;
+ public static final int IMAGE_RESOURCE_BLOCK_DUOTONE_IMAGE_INFO = 0x03fa;
+ public static final int IMAGE_RESOURCE_BLOCK_EFFECTIVE_BW = 0x03fb;
+ public static final int IMAGE_RESOURCE_BLOCK_OBSOLETE_PHOTOSHOP_TAG1 = 0x03fc;
+ public static final int IMAGE_RESOURCE_BLOCK_EPS_OPTIONS = 0x03fd;
+ public static final int IMAGE_RESOURCE_BLOCK_QUICK_MASK_INFO = 0x03fe;
+ public static final int IMAGE_RESOURCE_BLOCK_OBSOLETE_PHOTOSHOP_TAG2 = 0x03ff;
+ public static final int IMAGE_RESOURCE_BLOCK_LAYER_STATE_INFO = 0x0400;
+ public static final int IMAGE_RESOURCE_BLOCK_WORKING_PATH = 0x0401;
+ public static final int IMAGE_RESOURCE_BLOCK_LAYERS_GROUP_INFO = 0x0402;
+ public static final int IMAGE_RESOURCE_BLOCK_OBSOLETE_PHOTOSHOP_TAG3 = 0x0403;
+ public static final int IMAGE_RESOURCE_BLOCK_IPTC_DATA = 0x0404;
+ public static final int IMAGE_RESOURCE_BLOCK_RAW_IMAGE_MODE = 0x0405;
+ public static final int IMAGE_RESOURCE_BLOCK_JPEG_QUALITY = 0x0406;
+ public static final int IMAGE_RESOURCE_BLOCK_GRID_GUIDES_INFO = 0x0408;
+ public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP_BGR_THUMBNAIL = 0x0409;
+ public static final int IMAGE_RESOURCE_BLOCK_COPYRIGHT_FLAG = 0x040a;
+ public static final int IMAGE_RESOURCE_BLOCK_URL = 0x040b;
+ public static final int IMAGE_RESOURCE_BLOCK_PHOTOSHOP_THUMBNAIL = 0x040c;
+ public static final int IMAGE_RESOURCE_BLOCK_GLOBAL_ANGLE = 0x040d;
+ public static final int IMAGE_RESOURCE_BLOCK_COLOR_SAMPLERS_RESOURCE = 0x040e;
+ public static final int IMAGE_RESOURCE_BLOCK_ICC_PROFILE = 0x040f;
+ public static final int IMAGE_RESOURCE_BLOCK_WATERMARK = 0x0410;
+ public static final int IMAGE_RESOURCE_BLOCK_ICC_UNTAGGED = 0x0411;
+ public static final int IMAGE_RESOURCE_BLOCK_EFFECTS_VISIBLE = 0x0412;
+ public static final int IMAGE_RESOURCE_BLOCK_SPOT_HALFTONE = 0x0413;
+ public static final int IMAGE_RESOURCE_BLOCK_IDS_BASE_VALUE = 0x0414;
+ public static final int IMAGE_RESOURCE_BLOCK_UNICODE_ALPHA_NAMES = 0x0415;
+ public static final int IMAGE_RESOURCE_BLOCK_INDEXED_COLOUR_TABLE_COUNT = 0x0416;
+ public static final int IMAGE_RESOURCE_BLOCK_TRANSPARENT_INDEX = 0x0417;
+ public static final int IMAGE_RESOURCE_BLOCK_GLOBAL_ALTITUDE = 0x0419;
+ public static final int IMAGE_RESOURCE_BLOCK_SLICES = 0x041a;
+ public static final int IMAGE_RESOURCE_BLOCK_WORKFLOW_URL = 0x041b;
+ public static final int IMAGE_RESOURCE_BLOCK_JUMP_TO_XPEP = 0x041c;
+ public static final int IMAGE_RESOURCE_BLOCK_ALPHA_IDENTIFIERS = 0x041d;
+ public static final int IMAGE_RESOURCE_BLOCK_URL_LIST = 0x041e;
+ public static final int IMAGE_RESOURCE_BLOCK_VERSION_INFO = 0x0421;
+ public static final int IMAGE_RESOURCE_BLOCK_EXIFINFO = 0x0422;
+ public static final int IMAGE_RESOURCE_BLOCK_EXIF_INFO2 = 0x0423;
+ public static final int IMAGE_RESOURCE_BLOCK_XMP = 0x0424;
+ public static final int IMAGE_RESOURCE_BLOCK_CAPTION_DIGEST = 0x0425;
+ public static final int IMAGE_RESOURCE_BLOCK_PRINT_SCALE = 0x0426;
+ public static final int IMAGE_RESOURCE_BLOCK_PIXEL_ASPECT_RATIO = 0x0428;
+ public static final int IMAGE_RESOURCE_BLOCK_LAYER_COMPS = 0x0429;
+ public static final int IMAGE_RESOURCE_BLOCK_ALTERNATE_DUOTONE_COLORS = 0x042a;
+ public static final int IMAGE_RESOURCE_BLOCK_ALTERNATE_SPOT_COLORS = 0x042b;
+ public static final int IMAGE_RESOURCE_BLOCK_CLIPPING_PATH_NAME = 0x0bb7;
+ public static final int IMAGE_RESOURCE_BLOCK_PRINT_FLAGS_INFO = 0x2710;
+
+// public static final int IPTC_RECORD_PREFIX = 0x1c02;
+ public static final int IPTC_RECORD_TAG_MARKER = 0x1c;
+ public static final int IPTC_ENVELOPE_RECORD_NUMBER = 0x01;
+ public static final int IPTC_APPLICATION_2_RECORD_NUMBER = 0x02;
+
+ public static final IPTCType IPTC_TYPE_RECORD_VERSION = new IPTCType(0,
+ "RecordVersion");
+ public static final IPTCType IPTC_TYPE_OBJECT_TYPE_REFERENCE = new IPTCType(
+ 3, "ObjectTypeReference");
+ public static final IPTCType IPTC_TYPE_OBJECT_ATTRIBUTE_REFERENCE = new IPTCType(
+ 4, "ObjectAttributeReference");
+ public static final IPTCType IPTC_TYPE_OBJECT_NAME = new IPTCType(5,
+ "ObjectName");
+ public static final IPTCType IPTC_TYPE_EDIT_STATUS = new IPTCType(7,
+ "EditStatus");
+ public static final IPTCType IPTC_TYPE_EDITORIAL_UPDATE = new IPTCType(8,
+ "EditorialUpdate");
+ public static final IPTCType IPTC_TYPE_URGENCY = new IPTCType(10, "Urgency");
+ public static final IPTCType IPTC_TYPE_SUBJECT_REFERENCE = new IPTCType(12,
+ "SubjectReference");
+ public static final IPTCType IPTC_TYPE_CATEGORY = new IPTCType(15,
+ "Category");
+ public static final IPTCType IPTC_TYPE_SUPPLEMENTAL_CATEGORY = new IPTCType(
+ 20, "SupplementalCategory");
+ public static final IPTCType IPTC_TYPE_FIXTURE_IDENTIFIER = new IPTCType(
+ 22, "FixtureIdentifier");
+ public static final IPTCType IPTC_TYPE_KEYWORDS = new IPTCType(25,
+ "Keywords");
+ public static final IPTCType IPTC_TYPE_CONTENT_LOCATION_CODE = new IPTCType(
+ 26, "ContentLocationCode");
+ public static final IPTCType IPTC_TYPE_CONTENT_LOCATION_NAME = new IPTCType(
+ 27, "ContentLocationName");
+ public static final IPTCType IPTC_TYPE_RELEASE_DATE = new IPTCType(30,
+ "ReleaseDate");
+ public static final IPTCType IPTC_TYPE_RELEASE_TIME = new IPTCType(35,
+ "ReleaseTime");
+ public static final IPTCType IPTC_TYPE_EXPIRATION_DATE = new IPTCType(37,
+ "ExpirationDate");
+ public static final IPTCType IPTC_TYPE_EXPIRATION_TIME = new IPTCType(38,
+ "ExpirationTime");
+ public static final IPTCType IPTC_TYPE_SPECIAL_INSTRUCTIONS = new IPTCType(
+ 40, "SpecialInstructions");
+ public static final IPTCType IPTC_TYPE_ACTION_ADVISED = new IPTCType(42,
+ "ActionAdvised");
+ public static final IPTCType IPTC_TYPE_REFERENCE_SERVICE = new IPTCType(45,
+ "ReferenceService");
+ public static final IPTCType IPTC_TYPE_REFERENCE_DATE = new IPTCType(47,
+ "ReferenceDate");
+ public static final IPTCType IPTC_TYPE_REFERENCE_NUMBER = new IPTCType(50,
+ "ReferenceNumber");
+ public static final IPTCType IPTC_TYPE_DATE_CREATED = new IPTCType(55,
+ "DateCreated");
+ public static final IPTCType IPTC_TYPE_TIME_CREATED = new IPTCType(60,
+ "TimeCreated");
+ public static final IPTCType IPTC_TYPE_DIGITAL_CREATION_DATE = new IPTCType(
+ 62, "DigitalCreationDate");
+ public static final IPTCType IPTC_TYPE_DIGITAL_CREATION_TIME = new IPTCType(
+ 63, "DigitalCreationTime");
+ public static final IPTCType IPTC_TYPE_ORIGINATING_PROGRAM = new IPTCType(
+ 65, "OriginatingProgram");
+ public static final IPTCType IPTC_TYPE_PROGRAM_VERSION = new IPTCType(70,
+ "ProgramVersion");
+ public static final IPTCType IPTC_TYPE_OBJECT_CYCLE = new IPTCType(75,
+ "ObjectCycle");
+ public static final IPTCType IPTC_TYPE_BYLINE = new IPTCType(80, "By-line");
+ public static final IPTCType IPTC_TYPE_BYLINE_TITLE = new IPTCType(85,
+ "By-lineTitle");
+ public static final IPTCType IPTC_TYPE_CITY = new IPTCType(90, "City");
+ public static final IPTCType IPTC_TYPE_SUBLOCATION = new IPTCType(92,
+ "Sublocation");
+ public static final IPTCType IPTC_TYPE_PROVINCE_STATE = new IPTCType(95,
+ "Province/State");
+ public static final IPTCType IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_CODE = new IPTCType(
+ 100, "Country/PrimaryLocationCode");
+ public static final IPTCType IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_NAME = new IPTCType(
+ 101, "Country/PrimaryLocationName");
+ public static final IPTCType IPTC_TYPE_ORIGINAL_TRANSMISSION_REFERENCE = new IPTCType(
+ 103, "OriginalTransmission,Reference");
+ public static final IPTCType IPTC_TYPE_HEADLINE = new IPTCType(105,
+ "Headline");
+ public static final IPTCType IPTC_TYPE_CREDIT = new IPTCType(110, "Credit");
+ public static final IPTCType IPTC_TYPE_SOURCE = new IPTCType(115, "Source");
+ public static final IPTCType IPTC_TYPE_COPYRIGHT_NOTICE = new IPTCType(116,
+ "CopyrightNotice");
+ public static final IPTCType IPTC_TYPE_CONTACT = new IPTCType(118,
+ "Contact");
+ public static final IPTCType IPTC_TYPE_CAPTION_ABSTRACT = new IPTCType(120,
+ "Caption/Abstract");
+ public static final IPTCType IPTC_TYPE_WRITER_EDITOR = new IPTCType(122,
+ "Writer/Editor");
+ public static final IPTCType IPTC_TYPE_RASTERIZED_CAPTION = new IPTCType(
+ 125, "RasterizedCaption");
+ public static final IPTCType IPTC_TYPE_IMAGE_TYPE = new IPTCType(130,
+ "ImageType");
+ public static final IPTCType IPTC_TYPE_IMAGE_ORIENTATION = new IPTCType(
+ 131, "ImageOrientation");
+ public static final IPTCType IPTC_TYPE_LANGUAGE_IDENTIFIER = new IPTCType(
+ 135, "LanguageIdentifier");
+ public static final IPTCType IPTC_TYPE_AUDIO_TYPE = new IPTCType(150,
+ "AudioType");
+ public static final IPTCType IPTC_TYPE_AUDIO_SAMPLING_RATE = new IPTCType(
+ 151, "AudioSamplingRate");
+ public static final IPTCType IPTC_TYPE_AUDIO_SAMPLING_RESOLUTION = new IPTCType(
+ 152, "AudioSamplingResolution");
+ public static final IPTCType IPTC_TYPE_AUDIO_DURATION = new IPTCType(153,
+ "AudioDuration");
+ public static final IPTCType IPTC_TYPE_AUDIO_OUTCUE = new IPTCType(154,
+ "AudioOutcue");
+ public static final IPTCType IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT = new IPTCType(
+ 200, "ObjectDataPreview,FileFormat");
+ public static final IPTCType IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT_VERSION = new IPTCType(
+ 201, "ObjectDataPreview,FileFormatVersion");
+ public static final IPTCType IPTC_TYPE_OBJECT_DATA_PREVIEW_DATA = new IPTCType(
+ 202, "ObjectDataPreviewData");
+ // --
+ // public static final IPTCType IPTC_TYPE_UNKNOWN = new IPTCType(-1,
+ // "Unknown");
+
+ public static final IPTCType IPTC_TYPES[] = { IPTC_TYPE_RECORD_VERSION,
+ IPTC_TYPE_OBJECT_TYPE_REFERENCE,
+ IPTC_TYPE_OBJECT_ATTRIBUTE_REFERENCE, IPTC_TYPE_OBJECT_NAME,
+ IPTC_TYPE_EDIT_STATUS, IPTC_TYPE_EDITORIAL_UPDATE,
+ IPTC_TYPE_URGENCY, IPTC_TYPE_SUBJECT_REFERENCE, IPTC_TYPE_CATEGORY,
+ IPTC_TYPE_SUPPLEMENTAL_CATEGORY, IPTC_TYPE_FIXTURE_IDENTIFIER,
+ IPTC_TYPE_KEYWORDS, IPTC_TYPE_CONTENT_LOCATION_CODE,
+ IPTC_TYPE_CONTENT_LOCATION_NAME, IPTC_TYPE_RELEASE_DATE,
+ IPTC_TYPE_RELEASE_TIME, IPTC_TYPE_EXPIRATION_DATE,
+ IPTC_TYPE_EXPIRATION_TIME, IPTC_TYPE_SPECIAL_INSTRUCTIONS,
+ IPTC_TYPE_ACTION_ADVISED, IPTC_TYPE_REFERENCE_SERVICE,
+ IPTC_TYPE_REFERENCE_DATE, IPTC_TYPE_REFERENCE_NUMBER,
+ IPTC_TYPE_DATE_CREATED, IPTC_TYPE_TIME_CREATED,
+ IPTC_TYPE_DIGITAL_CREATION_DATE, IPTC_TYPE_DIGITAL_CREATION_TIME,
+ IPTC_TYPE_ORIGINATING_PROGRAM, IPTC_TYPE_PROGRAM_VERSION,
+ IPTC_TYPE_OBJECT_CYCLE, IPTC_TYPE_BYLINE, IPTC_TYPE_BYLINE_TITLE,
+ IPTC_TYPE_CITY, IPTC_TYPE_SUBLOCATION, IPTC_TYPE_PROVINCE_STATE,
+ IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_CODE,
+ IPTC_TYPE_COUNTRY_PRIMARY_LOCATION_NAME,
+ IPTC_TYPE_ORIGINAL_TRANSMISSION_REFERENCE, IPTC_TYPE_HEADLINE,
+ IPTC_TYPE_CREDIT, IPTC_TYPE_SOURCE, IPTC_TYPE_COPYRIGHT_NOTICE,
+ IPTC_TYPE_CONTACT, IPTC_TYPE_CAPTION_ABSTRACT,
+ IPTC_TYPE_WRITER_EDITOR, IPTC_TYPE_RASTERIZED_CAPTION,
+ IPTC_TYPE_IMAGE_TYPE, IPTC_TYPE_IMAGE_ORIENTATION,
+ IPTC_TYPE_LANGUAGE_IDENTIFIER, IPTC_TYPE_AUDIO_TYPE,
+ IPTC_TYPE_AUDIO_SAMPLING_RATE, IPTC_TYPE_AUDIO_SAMPLING_RESOLUTION,
+ IPTC_TYPE_AUDIO_DURATION, IPTC_TYPE_AUDIO_OUTCUE,
+ IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT,
+ IPTC_TYPE_OBJECT_DATA_PREVIEW_FILE_FORMAT_VERSION,
+ IPTC_TYPE_OBJECT_DATA_PREVIEW_DATA, };
+
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCConstants.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,444 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.sanselan.formats.jpeg.iptc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.SanselanConstants;
+import org.apache.sanselan.common.BinaryFileParser;
+import org.apache.sanselan.common.BinaryInputStream;
+import org.apache.sanselan.common.BinaryOutputStream;
+import org.apache.sanselan.util.Debug;
+import org.apache.sanselan.util.ParamMap;
+
+public class IPTCParser extends BinaryFileParser implements IPTCConstants
+{
+ private static final int APP13_BYTE_ORDER = BYTE_ORDER_NETWORK;
+
+ public IPTCParser()
+ {
+ setByteOrder(BYTE_ORDER_NETWORK);
+ }
+
+ public boolean isPhotoshopJpegSegment(byte segmentData[])
+ {
+
+ if (!compareByteArrays(segmentData, 0, PHOTOSHOP_IDENTIFICATION_STRING,
+ 0, PHOTOSHOP_IDENTIFICATION_STRING.length))
+ return false;
+
+ int index = PHOTOSHOP_IDENTIFICATION_STRING.length;
+ if (index + CONST_8BIM.length > segmentData.length)
+ return false;
+
+ if (!compareByteArrays(segmentData, index, CONST_8BIM, 0,
+ CONST_8BIM.length))
+ return false;
+
+ return true;
+ }
+
+ /*
+ * In practice, App13 segments are only used for Photoshop/IPTC metadata.
+ * However, we should not treat App13 signatures without Photoshop's
+ * signature as Photoshop/IPTC segments.
+ *
+ * A Photoshop/IPTC App13 segment begins with the Photoshop Identification
+ * string.
+ *
+ * There follows 0-N blocks (Photoshop calls them "Image Resource Blocks").
+ *
+ * Each block has the following structure:
+ *
+ * 1. 4-byte type. This is always "8BIM" for blocks in a Photoshop App13
+ * segment. 2. 2-byte id. IPTC data is stored in blocks with id 0x0404, aka.
+ * IPTC_NAA_RECORD_IMAGE_RESOURCE_ID 3. Block name as a Pascal String. This
+ * is padded to have an even length. 4. 4-byte size (in bytes). 5. Block
+ * data. This is also padded to have an even length.
+ *
+ * The block data consists of a 0-N records. A record has the following
+ * structure:
+ *
+ * 1. 2-byte prefix. The value is always 0x1C02 2. 1-byte record type. The
+ * record types are documented by the IPTC. See IPTCConstants. 3. 2-byte
+ * record size (in bytes). 4. Record data, "record size" bytes long.
+ *
+ * Record data (unlike block data) is NOT padded to have an even length.
+ *
+ * Record data, for IPTC record, should always be ISO-8859-1.
+ *
+ * The exception is the first record in the block, which must always be a
+ * record version record, whose value is a two-byte number; the value is
+ * 0x02.
+ *
+ * Some IPTC blocks are missing this first "record version" record, so we
+ * don't require it.
+ */
+ public PhotoshopApp13Data parsePhotoshopSegment(byte bytes[], Map params)
+ throws ImageReadException, IOException
+ {
+ boolean strict = ParamMap.getParamBoolean(params,
+ SanselanConstants.PARAM_KEY_STRICT, false);
+ boolean verbose = ParamMap.getParamBoolean(params,
+ SanselanConstants.PARAM_KEY_VERBOSE, false);
+
+ return parsePhotoshopSegment(bytes, verbose, strict);
+ }
+
+ public PhotoshopApp13Data parsePhotoshopSegment(byte bytes[],
+ boolean verbose, boolean strict) throws ImageReadException,
+ IOException
+ {
+ ArrayList records = new ArrayList();
+
+ List allBlocks = parseAllBlocks(bytes, verbose, strict);
+
+ for (int i = 0; i < allBlocks.size(); i++)
+ {
+ IPTCBlock block = (IPTCBlock) allBlocks.get(i);
+
+ // Ignore everything but IPTC data.
+ if (!block.isIPTCBlock())
+ continue;
+
+ records.addAll(parseIPTCBlock(block.blockData, verbose));
+ }
+
+ return new PhotoshopApp13Data(records, allBlocks);
+ }
+
+ protected List parseIPTCBlock(byte bytes[], boolean verbose)
+ throws ImageReadException, IOException
+ {
+ ArrayList elements = new ArrayList();
+
+ int index = 0;
+ // Integer recordVersion = null;
+ while (index + 1 < bytes.length)
+ {
+ int tagMarker = 0xff & bytes[index++];
+ if (verbose)
+ Debug.debug("tagMarker", tagMarker + " (0x"
+ + Integer.toHexString(tagMarker) + ")");
+
+ if (tagMarker != IPTC_RECORD_TAG_MARKER)
+ {
+ if (verbose)
+ System.out
+ .println("Unexpected record tag marker in IPTC data.");
+ return elements;
+ }
+
+ int recordNumber = 0xff & bytes[index++];
+ if (verbose)
+ Debug.debug("recordNumber", recordNumber + " (0x"
+ + Integer.toHexString(recordNumber) + ")");
+
+ if (recordNumber != IPTC_APPLICATION_2_RECORD_NUMBER)
+ continue;
+
+ // int recordPrefix = convertByteArrayToShort("recordPrefix", index,
+ // bytes);
+ // if (verbose)
+ // Debug.debug("recordPrefix", recordPrefix + " (0x"
+ // + Integer.toHexString(recordPrefix) + ")");
+ // index += 2;
+ //
+ // if (recordPrefix != IPTC_RECORD_PREFIX)
+ // {
+ // if (verbose)
+ // System.out
+ // .println("Unexpected record prefix in IPTC data!");
+ // return elements;
+ // }
+
+ // throw new ImageReadException(
+ // "Unexpected record prefix in IPTC data.");
+
+ int recordType = 0xff & bytes[index];
+ if (verbose)
+ Debug.debug("recordType", recordType + " (0x"
+ + Integer.toHexString(recordType) + ")");
+ index++;
+
+ int recordSize = convertByteArrayToShort("recordSize", index, bytes);
+ index += 2;
+
+ boolean extendedDataset = recordSize > IPTC_NON_EXTENDED_RECORD_MAXIMUM_SIZE;
+ int dataFieldCountLength = recordSize & 0x7fff;
+ if (extendedDataset && verbose)
+ Debug.debug("extendedDataset. dataFieldCountLength: "
+ + dataFieldCountLength);
+ if (extendedDataset) // ignore extended dataset and everything
+ // after.
+ return elements;
+
+ byte recordData[] = readBytearray("recordData", bytes, index,
+ recordSize);
+ index += recordSize;
+
+
+// Debug.debug("recordSize", recordSize + " (0x"
+// + Integer.toHexString(recordSize) + ")");
+
+ if (recordType == 0)
+ {
+ if (verbose)
+ System.out.println("ignore record version record! "
+ + elements.size());
+ // ignore "record version" record;
+ continue;
+ }
+ // if (recordVersion == null)
+ // {
+ // // The first record in a JPEG/Photoshop IPTC block must be
+ // // the record version.
+ // if (recordType != 0)
+ // throw new ImageReadException("Missing record version: "
+ // + recordType);
+ // recordVersion = new Integer(convertByteArrayToShort(
+ // "recordNumber", recordData));
+ //
+ // if (recordSize != 2)
+ // throw new ImageReadException(
+ // "Invalid record version record size: " + recordSize);
+ //
+ // // JPEG/Photoshop IPTC metadata is always in Record version
+ // // 2
+ // if (recordVersion.intValue() != 2)
+ // throw new ImageReadException(
+ // "Invalid IPTC record version: " + recordVersion);
+ //
+ // // Debug.debug("recordVersion", recordVersion);
+ // continue;
+ // }
+
+ String value = new String(recordData, "ISO-8859-1");
+
+ IPTCType iptcType = IPTCTypeLookup.getIptcType(recordType);
+
+ // Debug.debug("iptcType", iptcType);
+ // debugByteArray("iptcData", iptcData);
+ // Debug.debug();
+
+ // if (recordType == IPTC_TYPE_CREDIT.type
+ // || recordType == IPTC_TYPE_OBJECT_NAME.type)
+ // {
+ // this.debugByteArray("recordData", recordData);
+ // Debug.debug("index", IPTC_TYPE_CREDIT.name);
+ // }
+
+ IPTCRecord element = new IPTCRecord(iptcType, value);
+ elements.add(element);
+ }
+
+ return elements;
+ }
+
+ protected List parseAllBlocks(byte bytes[], boolean verbose, boolean strict)
+ throws ImageReadException, IOException
+ {
+ List blocks = new ArrayList();
+
+ BinaryInputStream bis = new BinaryInputStream(bytes, APP13_BYTE_ORDER);
+
+ // Note that these are unsigned quantities. Name is always an even
+ // number of bytes (including the 1st byte, which is the size.)
+
+ byte[] idString = bis.readByteArray(
+ PHOTOSHOP_IDENTIFICATION_STRING.length,
+ "App13 Segment missing identification string");
+ if (!compareByteArrays(idString, PHOTOSHOP_IDENTIFICATION_STRING))
+ throw new ImageReadException("Not a Photoshop App13 Segment");
+
+ // int index = PHOTOSHOP_IDENTIFICATION_STRING.length;
+
+ while (true)
+ {
+ byte[] imageResourceBlockSignature = bis
+ .readByteArray(CONST_8BIM.length,
+ "App13 Segment missing identification string",
+ false, false);
+ if (null == imageResourceBlockSignature)
+ break;
+ if (!compareByteArrays(imageResourceBlockSignature, CONST_8BIM))
+ throw new ImageReadException(
+ "Invalid Image Resource Block Signature");
+
+ int blockType = bis
+ .read2ByteInteger("Image Resource Block missing type");
+ if (verbose)
+ Debug.debug("blockType", blockType + " (0x"
+ + Integer.toHexString(blockType) + ")");
+
+ int blockNameLength = bis
+ .read1ByteInteger("Image Resource Block missing name length");
+ if (verbose && blockNameLength > 0)
+ Debug.debug("blockNameLength", blockNameLength + " (0x"
+ + Integer.toHexString(blockNameLength) + ")");
+ byte[] blockNameBytes;
+ if (blockNameLength == 0)
+ {
+ bis.read1ByteInteger("Image Resource Block has invalid name");
+ blockNameBytes = new byte[0];
+ } else
+ {
+ blockNameBytes = bis.readByteArray(blockNameLength,
+ "Invalid Image Resource Block name", verbose, strict);
+ if (null == blockNameBytes)
+ break;
+
+ if (blockNameLength % 2 == 0)
+ bis
+ .read1ByteInteger("Image Resource Block missing padding byte");
+ }
+
+ int blockSize = bis
+ .read4ByteInteger("Image Resource Block missing size");
+ if (verbose)
+ Debug.debug("blockSize", blockSize + " (0x"
+ + Integer.toHexString(blockSize) + ")");
+
+ byte[] blockData = bis.readByteArray(blockSize,
+ "Invalid Image Resource Block data", verbose, strict);
+ if (null == blockData)
+ break;
+
+ blocks.add(new IPTCBlock(blockType, blockNameBytes, blockData));
+
+ if ((blockSize % 2) != 0)
+ bis
+ .read1ByteInteger("Image Resource Block missing padding byte");
+ }
+
+ return blocks;
+ }
+
+ // private void writeIPTCRecord(BinaryOutputStream bos, )
+
+ public byte[] writePhotoshopApp13Segment(PhotoshopApp13Data data)
+ throws IOException, ImageWriteException
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ BinaryOutputStream bos = new BinaryOutputStream(os);
+
+ bos.write(PHOTOSHOP_IDENTIFICATION_STRING);
+
+ List blocks = data.getRawBlocks();
+ for (int i = 0; i < blocks.size(); i++)
+ {
+ IPTCBlock block = (IPTCBlock) blocks.get(i);
+
+ bos.write(CONST_8BIM);
+
+ if (block.blockType < 0 || block.blockType > 0xffff)
+ throw new ImageWriteException("Invalid IPTC block type.");
+ bos.write2ByteInteger(block.blockType);
+
+ if (block.blockNameBytes.length > 255)
+ throw new ImageWriteException("IPTC block name is too long: "
+ + block.blockNameBytes.length);
+ bos.write(block.blockNameBytes.length);
+ bos.write(block.blockNameBytes);
+ if (block.blockNameBytes.length % 2 == 0)
+ bos.write(0); // pad to even size, including length byte.
+
+ if (block.blockData.length > IPTC_NON_EXTENDED_RECORD_MAXIMUM_SIZE)
+ throw new ImageWriteException("IPTC block data is too long: "
+ + block.blockData.length);
+ bos.write4ByteInteger(block.blockData.length);
+ bos.write(block.blockData);
+ if (block.blockData.length % 2 == 1)
+ bos.write(0); // pad to even size
+
+ }
+
+ bos.flush();
+ return os.toByteArray();
+ }
+
+ public byte[] writeIPTCBlock(List elements) throws ImageWriteException,
+ IOException
+ {
+ byte blockData[];
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ BinaryOutputStream bos = new BinaryOutputStream(baos,
+ getByteOrder());
+
+ // first, right record version record
+ bos.write(IPTC_RECORD_TAG_MARKER);
+ bos.write(IPTC_APPLICATION_2_RECORD_NUMBER);
+ bos.write(IPTC_TYPE_RECORD_VERSION.type); // record version record type.
+ bos.write2Bytes(2); // record version record size
+ bos.write2Bytes(2); // record version value
+
+ // make a copy of the list.
+ elements = new ArrayList(elements);
+
+ // sort the list. Records must be in numerical order.
+ Comparator comparator = new Comparator() {
+ public int compare(Object o1, Object o2)
+ {
+ IPTCRecord e1 = (IPTCRecord) o1;
+ IPTCRecord e2 = (IPTCRecord) o2;
+ return e2.iptcType.type - e1.iptcType.type;
+ }
+ };
+ Collections.sort(elements, comparator);
+ // TODO: make sure order right
+
+ // write the list.
+ for (int i = 0; i < elements.size(); i++)
+ {
+ IPTCRecord element = (IPTCRecord) elements.get(i);
+
+ if(element.iptcType.type == IPTC_TYPE_RECORD_VERSION.type)
+ continue; // ignore
+
+ bos.write(IPTC_RECORD_TAG_MARKER);
+ bos.write(IPTC_APPLICATION_2_RECORD_NUMBER);
+ if (element.iptcType.type < 0 || element.iptcType.type > 0xff)
+ throw new ImageWriteException("Invalid record type: "
+ + element.iptcType.type);
+ bos.write(element.iptcType.type);
+
+ byte recordData[] = element.value.getBytes("ISO-8859-1");
+ if (!new String(recordData, "ISO-8859-1").equals(element.value))
+ throw new ImageWriteException(
+ "Invalid record value, not ISO-8859-1");
+
+ bos.write2Bytes(recordData.length);
+ bos.write(recordData);
+ }
+
+ blockData = baos.toByteArray();
+ }
+
+ return blockData;
+ }
+
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.formats.jpeg.iptc;
+
+import java.util.Comparator;
+
+public class IPTCRecord
+{
+ public final IPTCType iptcType;
+ public final String value;
+
+ public IPTCRecord(IPTCType iptcType, String value)
+ {
+ this.iptcType = iptcType;
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ public String getIptcTypeName()
+ {
+ return iptcType.name;
+ }
+
+ public static final Comparator COMPARATOR = new Comparator() {
+ public int compare(Object o1, Object o2)
+ {
+ IPTCRecord e1 = (IPTCRecord) o1;
+ IPTCRecord e2 = (IPTCRecord) o2;
+ return e1.iptcType.type - e2.iptcType.type;
+ }
+ };
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCRecord.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.formats.jpeg.iptc;
+
+import org.apache.sanselan.formats.jpeg.JpegConstants;
+
+public class IPTCType implements JpegConstants, IPTCConstants {
+ public final int type;
+ public final String name;
+
+ public IPTCType(int type, String name) {
+ this.type = type;
+ this.name = name;
+ }
+
+ public String toString() {
+ return name + " (" + type + ")";
+ }
+
+ public static IPTCType getUnknown(int type)
+ {
+ return new IPTCType(type, "Unknown");
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCType.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.formats.jpeg.iptc;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class IPTCTypeLookup implements IPTCConstants {
+
+ private static final Map IPTC_TYPE_MAP = new HashMap();
+ static {
+ for (int i = 0; i < IPTC_TYPES.length; i++) {
+ IPTCType iptcType = IPTC_TYPES[i];
+ Integer key = new Integer(iptcType.type);
+ IPTC_TYPE_MAP.put(key, iptcType);
+ }
+ }
+
+ public static final IPTCType getIptcType(int type) {
+ Integer key = new Integer(type);
+ if (!IPTC_TYPE_MAP.containsKey(key))
+ return IPTCType.getUnknown(type);
+ return (IPTCType) IPTC_TYPE_MAP.get(key);
+ }
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/IPTCTypeLookup.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.formats.jpeg.iptc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.common.byteSources.ByteSource;
+import org.apache.sanselan.common.byteSources.ByteSourceArray;
+import org.apache.sanselan.common.byteSources.ByteSourceFile;
+import org.apache.sanselan.common.byteSources.ByteSourceInputStream;
+import org.apache.sanselan.formats.jpeg.xmp.JpegRewriter;
+import org.apache.sanselan.util.Debug;
+
+/**
+ * Interface for Exif write/update/remove functionality for Jpeg/JFIF images.
+ * <p>
+ * <p>
+ * See the source of the IPTCUpdateExample class for example usage.
+ *
+ * @see org.apache.sanselan.sampleUsage.WriteIPTCExample
+ */
+public class JpegIptcRewriter extends JpegRewriter implements IPTCConstants
+{
+
+ /**
+ * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ * <p>
+ *
+ * @param src
+ * Image file.
+ * @param os
+ * OutputStream to write the image to.
+ *
+ * @see java.io.File
+ * @see java.io.OutputStream
+ */
+ public void removeIPTC(File src, OutputStream os)
+ throws ImageReadException, IOException, ImageWriteException
+ {
+ ByteSource byteSource = new ByteSourceFile(src);
+ removeIPTC(byteSource, os);
+ }
+
+ /**
+ * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ * <p>
+ *
+ * @param src
+ * Byte array containing Jpeg image data.
+ * @param os
+ * OutputStream to write the image to.
+ */
+ public void removeIPTC(byte src[], OutputStream os)
+ throws ImageReadException, IOException, ImageWriteException
+ {
+ ByteSource byteSource = new ByteSourceArray(src);
+ removeIPTC(byteSource, os);
+ }
+
+ /**
+ * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ * <p>
+ *
+ * @param src
+ * InputStream containing Jpeg image data.
+ * @param os
+ * OutputStream to write the image to.
+ */
+ public void removeIPTC(InputStream src, OutputStream os)
+ throws ImageReadException, IOException, ImageWriteException
+ {
+ ByteSource byteSource = new ByteSourceInputStream(src, null);
+ removeIPTC(byteSource, os);
+ }
+
+ /**
+ * Reads a Jpeg image, removes all IPTC data from the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ * <p>
+ *
+ * @param byteSource
+ * ByteSource containing Jpeg image data.
+ * @param os
+ * OutputStream to write the image to.
+ */
+ public void removeIPTC(ByteSource byteSource, OutputStream os)
+ throws ImageReadException, IOException, ImageWriteException
+ {
+ JFIFPieces jfifPieces = analyzeJFIF(byteSource);
+ List oldPieces = jfifPieces.pieces;
+ List photoshopApp13Segments = findPhotoshopApp13Segments(oldPieces);
+
+ if (photoshopApp13Segments.size() > 1)
+ throw new ImageReadException(
+ "Image contains more than one Photoshop App13 segment.");
+ List newPieces = removePhotoshopApp13Segments(oldPieces);
+ if (photoshopApp13Segments.size() == 1)
+ {
+ JFIFPieceSegment oldSegment = (JFIFPieceSegment) photoshopApp13Segments
+ .get(0);
+ Map params = new HashMap();
+ PhotoshopApp13Data oldData = new IPTCParser()
+ .parsePhotoshopSegment(oldSegment.segmentData, params);
+ List newBlocks = oldData.getNonIptcBlocks();
+ List newRecords = new ArrayList();
+ PhotoshopApp13Data newData = new PhotoshopApp13Data(newRecords,
+ newBlocks);
+ byte segmentBytes[] = new IPTCParser()
+ .writePhotoshopApp13Segment(newData);
+ JFIFPieceSegment newSegment = new JFIFPieceSegment(
+ oldSegment.marker, segmentBytes);
+ newPieces.add(oldPieces.indexOf(oldSegment), newSegment);
+ }
+ writeSegments(os, newPieces);
+ }
+
+ /**
+ * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ *
+ * @param src
+ * Byte array containing Jpeg image data.
+ * @param os
+ * OutputStream to write the image to.
+ * @param xmpXml
+ * String containing IPTC data.
+ */
+ public void writeIPTC(byte src[], OutputStream os,
+ PhotoshopApp13Data newData) throws ImageReadException, IOException,
+ ImageWriteException
+ {
+ ByteSource byteSource = new ByteSourceArray(src);
+ writeIPTC(byteSource, os, newData);
+ }
+
+ /**
+ * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ *
+ * @param src
+ * InputStream containing Jpeg image data.
+ * @param os
+ * OutputStream to write the image to.
+ * @param xmpXml
+ * String containing IPTC data.
+ */
+ public void writeIPTC(InputStream src, OutputStream os,
+ PhotoshopApp13Data newData) throws ImageReadException, IOException,
+ ImageWriteException
+ {
+ ByteSource byteSource = new ByteSourceInputStream(src, null);
+ writeIPTC(byteSource, os, newData);
+ }
+
+ /**
+ * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ *
+ * @param src
+ * Image file.
+ * @param os
+ * OutputStream to write the image to.
+ * @param xmpXml
+ * String containing IPTC data.
+ */
+ public void writeIPTC(File src, OutputStream os, PhotoshopApp13Data newData)
+ throws ImageReadException, IOException, ImageWriteException
+ {
+ ByteSource byteSource = new ByteSourceFile(src);
+ writeIPTC(byteSource, os, newData);
+ }
+
+ /**
+ * Reads a Jpeg image, replaces the IPTC data in the App13 segment but
+ * leaves the other data in that segment (if present) unchanged and writes
+ * the result to a stream.
+ *
+ * @param byteSource
+ * ByteSource containing Jpeg image data.
+ * @param os
+ * OutputStream to write the image to.
+ * @param xmpXml
+ * String containing IPTC data.
+ */
+ public void writeIPTC(ByteSource byteSource, OutputStream os,
+ PhotoshopApp13Data newData) throws ImageReadException, IOException,
+ ImageWriteException
+ {
+ JFIFPieces jfifPieces = analyzeJFIF(byteSource);
+ List oldPieces = jfifPieces.pieces;
+ List photoshopApp13Segments = findPhotoshopApp13Segments(oldPieces);
+
+ if (photoshopApp13Segments.size() > 1)
+ throw new ImageReadException(
+ "Image contains more than one Photoshop App13 segment.");
+ List newPieces = removePhotoshopApp13Segments(oldPieces);
+
+ {
+ // discard old iptc blocks.
+ List newBlocks = newData.getNonIptcBlocks();
+ byte[] newBlockBytes = new IPTCParser().writeIPTCBlock(newData
+ .getRecords());
+
+ int blockType = IMAGE_RESOURCE_BLOCK_IPTC_DATA;
+ byte[] blockNameBytes = new byte[0];
+ IPTCBlock newBlock = new IPTCBlock(blockType, blockNameBytes,
+ newBlockBytes);
+ newBlocks.add(newBlock);
+
+ newData = new PhotoshopApp13Data(newData.getRecords(), newBlocks);
+
+ byte segmentBytes[] = new IPTCParser()
+ .writePhotoshopApp13Segment(newData);
+ JFIFPieceSegment newSegment = new JFIFPieceSegment(
+ JPEG_APP13_Marker, segmentBytes);
+
+ newPieces = insertAfterLastAppSegments(newPieces, Arrays
+ .asList(new JFIFPieceSegment[] { newSegment, }));
+ }
+
+ writeSegments(os, newPieces);
+ }
+
+}
\ No newline at end of file
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/JpegIptcRewriter.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java
URL: http://svn.apache.org/viewvc/incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java?rev=688558&view=auto
==============================================================================
--- incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java (added)
+++ incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java Sun Aug 24 13:47:30 2008
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.sanselan.formats.jpeg.iptc;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.SanselanConstants;
+import org.apache.sanselan.common.BinaryFileParser;
+import org.apache.sanselan.common.BinaryOutputStream;
+import org.apache.sanselan.util.Debug;
+import org.apache.sanselan.util.ParamMap;
+
+public class PhotoshopApp13Data implements IPTCConstants
+{
+ private final List records;
+ private final List rawBlocks;
+
+ public PhotoshopApp13Data(List records, List rawBlocks)
+ {
+ this.rawBlocks = rawBlocks;
+ this.records = records;
+ }
+
+ public List getRecords()
+ {
+ return new ArrayList(records);
+ }
+
+ public List getRawBlocks()
+ {
+ return new ArrayList(rawBlocks);
+ }
+
+ public List getNonIptcBlocks()
+ {
+ List result = new ArrayList();
+ for (int i = 0; i < rawBlocks.size(); i++)
+ {
+ IPTCBlock block = (IPTCBlock) rawBlocks.get(i);
+ if (!block.isIPTCBlock())
+ result.add(block);
+ }
+ return result;
+ }
+
+}
Propchange: incubator/sanselan/trunk/src/main/java/org/apache/sanselan/formats/jpeg/iptc/PhotoshopApp13Data.java
------------------------------------------------------------------------------
svn:eol-style = native