source: josm/trunk/src/com/drew/metadata/iptc/IptcReader.java@ 7152

Last change on this file since 7152 was 6127, checked in by bastiK, 11 years ago

applied #8895 - Upgrade metadata-extractor to v. 2.6.4 (patch by ebourg)

File size: 7.2 KB
Line 
1/*
2 * Copyright 2002-2012 Drew Noakes
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * More information about this project is available at:
17 *
18 * http://drewnoakes.com/code/exif/
19 * http://code.google.com/p/metadata-extractor/
20 */
21package com.drew.metadata.iptc;
22
23import com.drew.lang.BufferBoundsException;
24import com.drew.lang.BufferReader;
25import com.drew.lang.annotations.NotNull;
26import com.drew.metadata.Directory;
27import com.drew.metadata.Metadata;
28import com.drew.metadata.MetadataReader;
29
30import java.util.Date;
31
32/**
33 * Decodes IPTC binary data, populating a <code>Metadata</code> object with tag values in an <code>IptcDirectory</code>.
34 *
35 * @author Drew Noakes http://drewnoakes.com
36 */
37public class IptcReader implements MetadataReader
38{
39 // TODO consider breaking the IPTC section up into multiple directories and providing segregation of each IPTC directory
40/*
41 public static final int DIRECTORY_IPTC = 2;
42
43 public static final int ENVELOPE_RECORD = 1;
44 public static final int APPLICATION_RECORD_2 = 2;
45 public static final int APPLICATION_RECORD_3 = 3;
46 public static final int APPLICATION_RECORD_4 = 4;
47 public static final int APPLICATION_RECORD_5 = 5;
48 public static final int APPLICATION_RECORD_6 = 6;
49 public static final int PRE_DATA_RECORD = 7;
50 public static final int DATA_RECORD = 8;
51 public static final int POST_DATA_RECORD = 9;
52*/
53
54 /** Performs the IPTC data extraction, adding found values to the specified instance of <code>Metadata</code>. */
55 public void extract(@NotNull final BufferReader reader, @NotNull final Metadata metadata)
56 {
57 IptcDirectory directory = metadata.getOrCreateDirectory(IptcDirectory.class);
58
59 int offset = 0;
60
61/*
62 // find start-of-segment marker (potentially need to skip some ASCII photoshop header info)
63 try {
64 while (offset < data.length - 1 && reader.getUInt16(offset) != 0x1c01 && reader.getUInt16(offset) != 0x1c02)
65 offset++;
66 } catch (BufferBoundsException e) {
67 directory.addError("Couldn't find start of IPTC data (invalid segment)");
68 return;
69 }
70*/
71
72 // for each tag
73 while (offset < reader.getLength()) {
74
75 // identifies start of a tag
76 short startByte;
77 try {
78 startByte = reader.getUInt8(offset);
79 } catch (BufferBoundsException e) {
80 directory.addError("Unable to read starting byte of IPTC tag");
81 break;
82 }
83
84 if (startByte != 0x1c) {
85 directory.addError("Invalid start to IPTC tag");
86 break;
87 }
88
89 // we need at least five bytes left to read a tag
90 if (offset + 5 >= reader.getLength()) {
91 directory.addError("Too few bytes remain for a valid IPTC tag");
92 break;
93 }
94
95 offset++;
96
97 int directoryType;
98 int tagType;
99 int tagByteCount;
100 try {
101 directoryType = reader.getUInt8(offset++);
102 tagType = reader.getUInt8(offset++);
103 tagByteCount = reader.getUInt16(offset);
104 offset += 2;
105 } catch (BufferBoundsException e) {
106 directory.addError("IPTC data segment ended mid-way through tag descriptor");
107 return;
108 }
109
110 if (offset + tagByteCount > reader.getLength()) {
111 directory.addError("Data for tag extends beyond end of IPTC segment");
112 break;
113 }
114
115 try {
116 processTag(reader, directory, directoryType, tagType, offset, tagByteCount);
117 } catch (BufferBoundsException e) {
118 directory.addError("Error processing IPTC tag");
119 break;
120 }
121
122 offset += tagByteCount;
123 }
124 }
125
126 private void processTag(@NotNull BufferReader reader, @NotNull Directory directory, int directoryType, int tagType, int offset, int tagByteCount) throws BufferBoundsException
127 {
128 int tagIdentifier = tagType | (directoryType << 8);
129
130 switch (tagIdentifier) {
131 case IptcDirectory.TAG_APPLICATION_RECORD_VERSION:
132 // short
133 int shortValue = reader.getUInt16(offset);
134 directory.setInt(tagIdentifier, shortValue);
135 return;
136 case IptcDirectory.TAG_URGENCY:
137 // byte
138 directory.setInt(tagIdentifier, reader.getUInt8(offset));
139 return;
140 case IptcDirectory.TAG_RELEASE_DATE:
141 case IptcDirectory.TAG_DATE_CREATED:
142 // Date object
143 if (tagByteCount >= 8) {
144 String dateStr = reader.getString(offset, tagByteCount);
145 try {
146 int year = Integer.parseInt(dateStr.substring(0, 4));
147 int month = Integer.parseInt(dateStr.substring(4, 6)) - 1;
148 int day = Integer.parseInt(dateStr.substring(6, 8));
149 Date date = new java.util.GregorianCalendar(year, month, day).getTime();
150 directory.setDate(tagIdentifier, date);
151 return;
152 } catch (NumberFormatException e) {
153 // fall through and we'll store whatever was there as a String
154 }
155 }
156 case IptcDirectory.TAG_RELEASE_TIME:
157 case IptcDirectory.TAG_TIME_CREATED:
158 // time...
159 default:
160 // fall through
161 }
162
163 // If we haven't returned yet, treat it as a string
164 String str;
165 if (tagByteCount < 1) {
166 str = "";
167 } else {
168 str = reader.getString(offset, tagByteCount, System.getProperty("file.encoding")); // "ISO-8859-1"
169 }
170
171 if (directory.containsTag(tagIdentifier)) {
172 // this fancy string[] business avoids using an ArrayList for performance reasons
173 String[] oldStrings = directory.getStringArray(tagIdentifier);
174 String[] newStrings;
175 if (oldStrings == null) {
176 newStrings = new String[1];
177 } else {
178 newStrings = new String[oldStrings.length + 1];
179 System.arraycopy(oldStrings, 0, newStrings, 0, oldStrings.length);
180 }
181 newStrings[newStrings.length - 1] = str;
182 directory.setStringArray(tagIdentifier, newStrings);
183 } else {
184 directory.setString(tagIdentifier, str);
185 }
186 }
187}
Note: See TracBrowser for help on using the repository browser.