/contrib/metadata-extractor/trunk/src/com/drew/metadata/iptc/IptcDirectory.java |
---|
0,0 → 1,97 |
/* |
* This is public domain software - that is, you can do whatever you want |
* with it, and include it software that is licensed under the GNU or the |
* BSD license, or whatever other licence you choose, including proprietary |
* closed source licenses. I do ask that you leave this header in tact. |
* |
* If you make modifications to this code that you think would benefit the |
* wider community, please send me a copy and I'll post it on my site. |
* |
* If you make use of this code, I'd appreciate hearing about it. |
* drew@drewnoakes.com |
* Latest version of this software kept at |
* http://drewnoakes.com/ |
* |
* Created by dnoakes on 26-Nov-2002 01:26:39 using IntelliJ IDEA. |
*/ |
package com.drew.metadata.iptc; |
import com.drew.metadata.Directory; |
import java.util.HashMap; |
/** |
* |
*/ |
public class IptcDirectory extends Directory |
{ |
public static final int TAG_RECORD_VERSION = 0x0200; |
public static final int TAG_CAPTION = 0x0278; |
public static final int TAG_WRITER = 0x027a; |
public static final int TAG_HEADLINE = 0x0269; |
public static final int TAG_SPECIAL_INSTRUCTIONS = 0x0228; |
public static final int TAG_BY_LINE = 0x0250; |
public static final int TAG_BY_LINE_TITLE = 0x0255; |
public static final int TAG_CREDIT = 0x026e; |
public static final int TAG_SOURCE = 0x0273; |
public static final int TAG_OBJECT_NAME = 0x0205; |
public static final int TAG_DATE_CREATED = 0x0237; |
public static final int TAG_CITY = 0x025a; |
public static final int TAG_PROVINCE_OR_STATE = 0x025f; |
public static final int TAG_COUNTRY_OR_PRIMARY_LOCATION = 0x0265; |
public static final int TAG_ORIGINAL_TRANSMISSION_REFERENCE = 0x0267; |
public static final int TAG_CATEGORY = 0x020f; |
public static final int TAG_SUPPLEMENTAL_CATEGORIES = 0x0214; |
public static final int TAG_URGENCY = 0x0200 | 10; |
public static final int TAG_KEYWORDS = 0x0200 | 25; |
public static final int TAG_COPYRIGHT_NOTICE = 0x0274; |
public static final int TAG_RELEASE_DATE = 0x0200 | 30; |
public static final int TAG_RELEASE_TIME = 0x0200 | 35; |
public static final int TAG_TIME_CREATED = 0x0200 | 60; |
public static final int TAG_ORIGINATING_PROGRAM = 0x0200 | 65; |
protected static final HashMap tagNameMap = new HashMap(); |
static |
{ |
tagNameMap.put(new Integer(TAG_RECORD_VERSION), "Directory Version"); |
tagNameMap.put(new Integer(TAG_CAPTION), "Caption/Abstract"); |
tagNameMap.put(new Integer(TAG_WRITER), "Writer/Editor"); |
tagNameMap.put(new Integer(TAG_HEADLINE), "Headline"); |
tagNameMap.put(new Integer(TAG_SPECIAL_INSTRUCTIONS), "Special Instructions"); |
tagNameMap.put(new Integer(TAG_BY_LINE), "By-line"); |
tagNameMap.put(new Integer(TAG_BY_LINE_TITLE), "By-line Title"); |
tagNameMap.put(new Integer(TAG_CREDIT), "Credit"); |
tagNameMap.put(new Integer(TAG_SOURCE), "Source"); |
tagNameMap.put(new Integer(TAG_OBJECT_NAME), "Object Name"); |
tagNameMap.put(new Integer(TAG_DATE_CREATED), "Date Created"); |
tagNameMap.put(new Integer(TAG_CITY), "City"); |
tagNameMap.put(new Integer(TAG_PROVINCE_OR_STATE), "Province/State"); |
tagNameMap.put(new Integer(TAG_COUNTRY_OR_PRIMARY_LOCATION), "Country/Primary Location"); |
tagNameMap.put(new Integer(TAG_ORIGINAL_TRANSMISSION_REFERENCE), "Original Transmission Reference"); |
tagNameMap.put(new Integer(TAG_CATEGORY), "Category"); |
tagNameMap.put(new Integer(TAG_SUPPLEMENTAL_CATEGORIES), "Supplemental Category(s)"); |
tagNameMap.put(new Integer(TAG_URGENCY), "Urgency"); |
tagNameMap.put(new Integer(TAG_KEYWORDS), "Keywords"); |
tagNameMap.put(new Integer(TAG_COPYRIGHT_NOTICE), "Copyright Notice"); |
tagNameMap.put(new Integer(TAG_RELEASE_DATE), "Release Date"); |
tagNameMap.put(new Integer(TAG_RELEASE_TIME), "Release Time"); |
tagNameMap.put(new Integer(TAG_TIME_CREATED), "Time Created"); |
tagNameMap.put(new Integer(TAG_ORIGINATING_PROGRAM), "Originating Program"); |
} |
public IptcDirectory() |
{ |
this.setDescriptor(new IptcDescriptor(this)); |
} |
public String getName() |
{ |
return "Iptc"; |
} |
protected HashMap getTagNameMap() |
{ |
return tagNameMap; |
} |
} |
/contrib/metadata-extractor/trunk/src/com/drew/metadata/iptc/IptcProcessingException.java |
---|
0,0 → 1,51 |
/* |
* ExifProcessingException.java |
* |
* This class is public domain software - that is, you can do whatever you want |
* with it, and include it software that is licensed under the GNU or the |
* BSD license, or whatever other licence you choose, including proprietary |
* closed source licenses. I do ask that you leave this header in tact. |
* |
* If you make modifications to this code that you think would benefit the |
* wider community, please send me a copy and I'll post it on my site. |
* |
* If you make use of this code, I'd appreciate hearing about it. |
* drew@drewnoakes.com |
* Latest version of this software kept at |
* http://drewnoakes.com/ |
* |
* Created on 29 April 2002, 00:33 |
*/ |
package com.drew.metadata.iptc; |
import com.drew.metadata.MetadataException; |
/** |
* The exception type raised during reading of Iptc data in the instance of |
* unexpected data conditions. |
* @author Drew Noakes http://drewnoakes.com |
*/ |
public class IptcProcessingException extends MetadataException |
{ |
/** |
* Constructs an instance of <code>ExifProcessingException</code> with the |
* specified detail message. |
* @param message the detail message |
*/ |
public IptcProcessingException(String message) |
{ |
super(message); |
} |
/** |
* Constructs an instance of <code>IptcProcessingException</code> with the |
* specified detail message and inner exception. |
* @param message the detail message |
* @param cause an inner exception |
*/ |
public IptcProcessingException(String message, Throwable cause) |
{ |
super(message, cause); |
} |
} |
/contrib/metadata-extractor/trunk/src/com/drew/metadata/iptc/IptcDescriptor.java |
---|
0,0 → 1,36 |
/* |
* This is public domain software - that is, you can do whatever you want |
* with it, and include it software that is licensed under the GNU or the |
* BSD license, or whatever other licence you choose, including proprietary |
* closed source licenses. I do ask that you leave this header in tact. |
* |
* If you make modifications to this code that you think would benefit the |
* wider community, please send me a copy and I'll post it on my site. |
* |
* If you make use of this code, I'd appreciate hearing about it. |
* drew@drewnoakes.com |
* Latest version of this software kept at |
* http://drewnoakes.com/ |
* |
* Created by dnoakes on 21-Nov-2002 17:58:19 using IntelliJ IDEA. |
*/ |
package com.drew.metadata.iptc; |
import com.drew.metadata.Directory; |
import com.drew.metadata.TagDescriptor; |
/** |
* |
*/ |
public class IptcDescriptor extends TagDescriptor |
{ |
public IptcDescriptor(Directory directory) |
{ |
super(directory); |
} |
public String getDescription(int tagType) |
{ |
return _directory.getString(tagType); |
} |
} |
/contrib/metadata-extractor/trunk/src/com/drew/metadata/iptc/test/withIptc.jpg |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/contrib/metadata-extractor/trunk/src/com/drew/metadata/iptc/test/IptcReaderTest.java |
---|
0,0 → 1,69 |
/* |
* This is public domain software - that is, you can do whatever you want |
* with it, and include it software that is licensed under the GNU or the |
* BSD license, or whatever other licence you choose, including proprietary |
* closed source licenses. I do ask that you leave this header in tact. |
* |
* If you make modifications to this code that you think would benefit the |
* wider community, please send me a copy and I'll post it on my site. |
* |
* If you make use of this code, I'd appreciate hearing about it. |
* drew@drewnoakes.com |
* Latest version of this software kept at |
* http://drewnoakes.com/ |
* |
* Created by dnoakes on 22-Nov-2002 08:26:26 using IntelliJ IDEA. |
*/ |
package com.drew.metadata.iptc.test; |
import com.drew.metadata.Directory; |
import com.drew.metadata.Metadata; |
import com.drew.metadata.MetadataReader; |
import com.drew.metadata.iptc.IptcDirectory; |
import com.drew.metadata.iptc.IptcReader; |
import junit.framework.TestCase; |
import java.io.File; |
/** |
* |
*/ |
public class IptcReaderTest extends TestCase |
{ |
public IptcReaderTest(String s) |
{ |
super(s); |
} |
public void testDescription_City() throws Exception |
{ |
File iptcFile = new File("src/com/drew/metadata/iptc/test/withIptc.jpg"); |
MetadataReader reader = new IptcReader(iptcFile); |
Metadata metadata = reader.extract(); |
assertTrue(metadata.containsDirectory(IptcDirectory.class)); |
Directory directory = metadata.getDirectory(IptcDirectory.class); |
assertEquals("City", directory.getDescription(IptcDirectory.TAG_CITY)); |
} |
public void testDescription_Caption() throws Exception |
{ |
File iptcFile = new File("src/com/drew/metadata/iptc/test/withIptc.jpg"); |
MetadataReader reader = new IptcReader(iptcFile); |
Metadata metadata = reader.extract(); |
assertTrue(metadata.containsDirectory(IptcDirectory.class)); |
Directory directory = metadata.getDirectory(IptcDirectory.class); |
assertEquals("Caption", directory.getDescription(IptcDirectory.TAG_CAPTION)); |
} |
public void testDescription_Category() throws Exception |
{ |
File iptcFile = new File("src/com/drew/metadata/iptc/test/withIptc.jpg"); |
MetadataReader reader = new IptcReader(iptcFile); |
Metadata metadata = reader.extract(); |
assertTrue(metadata.containsDirectory(IptcDirectory.class)); |
Directory directory = metadata.getDirectory(IptcDirectory.class); |
assertEquals("Supl. Category2 Supl. Category1 Cat", directory.getDescription(IptcDirectory.TAG_CATEGORY)); |
} |
// TODO Wrap more tests around the Iptc reader |
} |
/contrib/metadata-extractor/trunk/src/com/drew/metadata/iptc/test/withIptcPhotoshop6.jpg |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/contrib/metadata-extractor/trunk/src/com/drew/metadata/iptc/IptcReader.java |
---|
0,0 → 1,225 |
/* |
* This is public domain software - that is, you can do whatever you want |
* with it, and include it software that is licensed under the GNU or the |
* BSD license, or whatever other licence you choose, including proprietary |
* closed source licenses. I do ask that you leave this header in tact. |
* |
* If you make modifications to this code that you think would benefit the |
* wider community, please send me a copy and I'll post it on my site. |
* |
* If you make use of this code, I'd appreciate hearing about it. |
* drew@drewnoakes.com |
* Latest version of this software kept at |
* http://drewnoakes.com/ |
* |
* Created by dnoakes on 12-Nov-2002 19:00:03 using IntelliJ IDEA. |
*/ |
package com.drew.metadata.iptc; |
import com.drew.imaging.jpeg.JpegProcessingException; |
import com.drew.imaging.jpeg.JpegSegmentReader; |
import com.drew.metadata.Directory; |
import com.drew.metadata.Metadata; |
import com.drew.metadata.MetadataException; |
import com.drew.metadata.MetadataReader; |
import java.io.File; |
import java.io.InputStream; |
import java.util.Date; |
/** |
* |
*/ |
public class IptcReader implements MetadataReader |
{ |
/* |
public static final int DIRECTORY_IPTC = 2; |
public static final int ENVELOPE_RECORD = 1; |
public static final int APPLICATION_RECORD_2 = 2; |
public static final int APPLICATION_RECORD_3 = 3; |
public static final int APPLICATION_RECORD_4 = 4; |
public static final int APPLICATION_RECORD_5 = 5; |
public static final int APPLICATION_RECORD_6 = 6; |
public static final int PRE_DATA_RECORD = 7; |
public static final int DATA_RECORD = 8; |
public static final int POST_DATA_RECORD = 9; |
*/ |
/** |
* The Iptc data segment. |
*/ |
private final byte[] _data; |
/** |
* Creates a new IptcReader for the specified Jpeg jpegFile. |
*/ |
public IptcReader(File jpegFile) throws JpegProcessingException |
{ |
this(new JpegSegmentReader(jpegFile).readSegment(JpegSegmentReader.SEGMENT_APPD)); |
} |
/** Creates an IptcReader for a JPEG stream. |
* |
* @param is JPEG stream. Stream will be closed. |
*/ |
public IptcReader(InputStream is) throws JpegProcessingException |
{ |
this(new JpegSegmentReader(is).readSegment(JpegSegmentReader.SEGMENT_APPD)); |
} |
public IptcReader(byte[] data) |
{ |
_data = data; |
} |
/** |
* Performs the Exif data extraction, returning a new instance of <code>Metadata</code>. |
*/ |
public Metadata extract() |
{ |
return extract(new Metadata()); |
} |
/** |
* Performs the Exif data extraction, adding found values to the specified |
* instance of <code>Metadata</code>. |
*/ |
public Metadata extract(Metadata metadata) |
{ |
if (_data == null) { |
return metadata; |
} |
Directory directory = metadata.getDirectory(IptcDirectory.class); |
// find start of data |
int offset = 0; |
try { |
while (offset < _data.length - 1 && get32Bits(offset) != 0x1c02) { |
offset++; |
} |
} catch (MetadataException e) { |
directory.addError("Couldn't find start of Iptc data (invalid segment)"); |
return metadata; |
} |
// for each tag |
while (offset < _data.length) { |
// identifies start of a tag |
if (_data[offset] != 0x1c) { |
break; |
} |
// we need at least five bytes left to read a tag |
if ((offset + 5) >= _data.length) { |
break; |
} |
offset++; |
int directoryType; |
int tagType; |
int tagByteCount; |
try { |
directoryType = _data[offset++]; |
tagType = _data[offset++]; |
tagByteCount = get32Bits(offset); |
} catch (MetadataException e) { |
directory.addError("Iptc data segment ended mid-way through tag descriptor"); |
return metadata; |
} |
offset += 2; |
if ((offset + tagByteCount) > _data.length) { |
directory.addError("data for tag extends beyond end of iptc segment"); |
break; |
} |
processTag(directory, directoryType, tagType, offset, tagByteCount); |
offset += tagByteCount; |
} |
return metadata; |
} |
/** |
* Returns an int calculated from two bytes of data at the specified offset (MSB, LSB). |
* @param offset position within the data buffer to read first byte |
* @return the 32 bit int value, between 0x0000 and 0xFFFF |
*/ |
private int get32Bits(int offset) throws MetadataException |
{ |
if (offset >= _data.length) { |
throw new MetadataException("Attempt to read bytes from outside Iptc data buffer"); |
} |
return ((_data[offset] & 255) << 8) | (_data[offset + 1] & 255); |
} |
/** |
* This method serves as marsheller of objects for dataset. It converts from IPTC |
* octets to relevant java object. |
*/ |
private void processTag(Directory directory, int directoryType, int tagType, int offset, int tagByteCount) |
{ |
int tagIdentifier = tagType | (directoryType << 8); |
switch (tagIdentifier) { |
case IptcDirectory.TAG_RECORD_VERSION: |
// short |
short shortValue = (short)((_data[offset] << 8) | _data[offset + 1]); |
directory.setInt(tagIdentifier, shortValue); |
return; |
case IptcDirectory.TAG_URGENCY: |
// byte |
directory.setInt(tagIdentifier, _data[offset]); |
return; |
case IptcDirectory.TAG_RELEASE_DATE: |
case IptcDirectory.TAG_DATE_CREATED: |
// Date object |
if (tagByteCount >= 8) { |
String dateStr = new String(_data, offset, tagByteCount); |
try { |
int year = Integer.parseInt(dateStr.substring(0, 4)); |
int month = Integer.parseInt(dateStr.substring(4, 6)) - 1; |
int day = Integer.parseInt(dateStr.substring(6, 8)); |
Date date = (new java.util.GregorianCalendar(year, month, day)).getTime(); |
directory.setDate(tagIdentifier, date); |
return; |
} catch (NumberFormatException e) { |
// fall through and we'll store whatever was there as a String |
} |
} |
case IptcDirectory.TAG_RELEASE_TIME: |
case IptcDirectory.TAG_TIME_CREATED: |
// time... |
default: |
// fall through |
} |
// If no special handling by now, treat it as a string |
String str; |
if (tagByteCount < 1) { |
str = ""; |
} else { |
str = new String(_data, offset, tagByteCount); |
} |
if (directory.containsTag(tagIdentifier)) { |
String[] oldStrings; |
String[] newStrings; |
try { |
oldStrings = directory.getStringArray(tagIdentifier); |
} catch (MetadataException e) { |
oldStrings = null; |
} |
if (oldStrings == null) { |
newStrings = new String[1]; |
} else { |
newStrings = new String[oldStrings.length + 1]; |
for (int i = 0; i < oldStrings.length; i++) { |
newStrings[i] = oldStrings[i]; |
} |
} |
newStrings[newStrings.length - 1] = str; |
directory.setStringArray(tagIdentifier, newStrings); |
} else { |
directory.setString(tagIdentifier, str); |
} |
} |
} |