2 * Copyright (C) 2005-2007 Team XboxMediaCenter
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 //--------------------------------------------------------------------------
23 // Module to pull IPTC information out of various types of digital images.
24 //--------------------------------------------------------------------------
26 //--------------------------------------------------------------------------
28 //--------------------------------------------------------------------------
33 #define min(a,b) (a)>(b)?(b):(a)
36 #include "IptcParse.h"
37 #include "ExifParse.h"
39 // Supported IPTC entry types
40 #define IPTC_RECORD_VERSION 0x00
41 #define IPTC_SUPLEMENTAL_CATEGORIES 0x14
42 #define IPTC_KEYWORDS 0x19
43 #define IPTC_CAPTION 0x78
44 #define IPTC_AUTHOR 0x7A
45 #define IPTC_HEADLINE 0x69
46 #define IPTC_SPECIAL_INSTRUCTIONS 0x28
47 #define IPTC_CATEGORY 0x0F
48 #define IPTC_BYLINE 0x50
49 #define IPTC_BYLINE_TITLE 0x55
50 #define IPTC_CREDIT 0x6E
51 #define IPTC_SOURCE 0x73
52 #define IPTC_COPYRIGHT_NOTICE 0x74
53 #define IPTC_OBJECT_NAME 0x05
54 #define IPTC_CITY 0x5A
55 #define IPTC_STATE 0x5F
56 #define IPTC_COUNTRY 0x65
57 #define IPTC_TRANSMISSION_REFERENCE 0x67
58 #define IPTC_DATE 0x37
59 #define IPTC_URGENCY 0x0A
60 #define IPTC_COUNTRY_CODE 0x64
61 #define IPTC_REFERENCE_SERVICE 0x2D
62 #define IPTC_TIME_CREATED 0x3C
63 #define IPTC_SUB_LOCATION 0x5C
64 #define IPTC_IMAGE_TYPE 0x82
67 //--------------------------------------------------------------------------
68 // Process IPTC marker. Return FALSE if unable to process marker.
70 // IPTC block consists of:
71 // - Marker: 1 byte (0xED)
72 // - Block length: 2 bytes
73 // - IPTC Signature: 14 bytes ("Photoshop 3.0\0")
74 // - 8BIM Signature 4 bytes ("8BIM")
75 // - IPTC Block start 2 bytes (0x04, 0x04)
76 // - IPTC Header length 1 byte
77 // - IPTC header Header is padded to even length, counting the length byte
79 // - IPTC Data which consists of a number of entries, each of which has the following format:
80 // - Signature 2 bytes (0x1C02)
81 // - Entry type 1 byte (for defined entry types, see #defines above)
82 // - entry length 2 bytes
83 // - entry data 'entry length' bytes
85 //--------------------------------------------------------------------------
86 bool CIptcParse::Process (const unsigned char* const Data, const unsigned short itemlen, IPTCInfo_t *info)
88 if (!info) return false;
90 const char IptcSignature1[] = "Photoshop 3.0";
91 const char IptcSignature2[] = "8BIM";
92 const char IptcSignature3[] = {0x04, 0x04};
94 // Check IPTC signatures
95 char* pos = (char*)(Data + sizeof(short)); // position data pointer after length field
96 char* maxpos = (char*)(Data+itemlen);
97 unsigned char headerLen = 0;
98 unsigned char dataLen = 0;
99 memset(info, 0, sizeof(IPTCInfo_t));
101 if (itemlen < 25) return false;
103 if (memcmp(pos, IptcSignature1, strlen(IptcSignature1)-1) != 0) return false;
104 pos += sizeof(IptcSignature1); // move data pointer to the next field
106 if (memcmp(pos, IptcSignature2, strlen(IptcSignature2)-1) != 0) return false;
107 pos += sizeof(IptcSignature2)-1; // move data pointer to the next field
109 while (memcmp(pos, IptcSignature3, sizeof(IptcSignature3)) != 0) { // loop on valid Photoshop blocks
111 pos += sizeof(IptcSignature3); // move data pointer to the Header Length
113 headerLen = *pos; // get header length and move data pointer to the next field
114 pos += (headerLen & 0xfe) + 2; // move data pointer to the next field (Header is padded to even length, counting the length byte)
116 pos += 3; // move data pointer to length, assume only one byte, TODO: use all 4 bytes
119 pos += dataLen; // skip data section
121 if (memcmp(pos, IptcSignature2, sizeof(IptcSignature2) - 1) != 0) return false;
122 pos += sizeof(IptcSignature2) - 1; // move data pointer to the next field
125 pos += sizeof(IptcSignature3); // move data pointer to the next field
126 if (pos >= maxpos) return false;
128 // IPTC section found
131 headerLen = *pos++; // get header length and move data pointer to the next field
132 pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
134 if (pos + 4 >= maxpos) return false;
136 pos += 4; // move data pointer to the next field
138 // Now read IPTC data
139 while (pos < (char*)(Data + itemlen-5))
141 if (pos + 5 > maxpos) return false;
143 short signature = (*pos << 8) + (*(pos+1));
146 if (signature != 0x1C01 && signature != 0x1C02)
149 unsigned char type = *pos++;
150 unsigned short length = (*pos << 8) + (*(pos+1));
151 pos += 2; // Skip tag length
153 if (pos + length > maxpos) return false;
157 if (signature == 0x1C02)
161 case IPTC_RECORD_VERSION: tag = info->RecordVersion; break;
162 case IPTC_SUPLEMENTAL_CATEGORIES: tag = info->SupplementalCategories; break;
163 case IPTC_KEYWORDS: tag = info->Keywords; break;
164 case IPTC_CAPTION: tag = info->Caption; break;
165 case IPTC_AUTHOR: tag = info->Author; break;
166 case IPTC_HEADLINE: tag = info->Headline; break;
167 case IPTC_SPECIAL_INSTRUCTIONS: tag = info->SpecialInstructions; break;
168 case IPTC_CATEGORY: tag = info->Category; break;
169 case IPTC_BYLINE: tag = info->Byline; break;
170 case IPTC_BYLINE_TITLE: tag = info->BylineTitle; break;
171 case IPTC_CREDIT: tag = info->Credit; break;
172 case IPTC_SOURCE: tag = info->Source; break;
173 case IPTC_COPYRIGHT_NOTICE: tag = info->CopyrightNotice; break;
174 case IPTC_OBJECT_NAME: tag = info->ObjectName; break;
175 case IPTC_CITY: tag = info->City; break;
176 case IPTC_STATE: tag = info->State; break;
177 case IPTC_COUNTRY: tag = info->Country; break;
178 case IPTC_TRANSMISSION_REFERENCE: tag = info->TransmissionReference; break;
179 case IPTC_DATE: tag = info->Date; break;
180 case IPTC_URGENCY: tag = info->Urgency; break;
181 case IPTC_REFERENCE_SERVICE: tag = info->ReferenceService; break;
182 case IPTC_COUNTRY_CODE: tag = info->CountryCode; break;
183 case IPTC_TIME_CREATED: tag = info->TimeCreated; break;
184 case IPTC_SUB_LOCATION: tag = info->SubLocation; break;
185 case IPTC_IMAGE_TYPE: tag = info->ImageType; break;
187 printf("IptcParse: Unrecognised IPTC tag: 0x%02x", type);
194 if (type != IPTC_KEYWORDS || *tag == 0)
196 strncpy(tag, pos, min(length, MAX_IPTC_STRING - 1));
197 tag[min(length, MAX_IPTC_STRING - 1)] = 0;
199 else if (type == IPTC_KEYWORDS)
201 // there may be multiple keywords - lets join them
202 size_t maxLen = MAX_IPTC_STRING - strlen(tag);
206 strncat(tag, pos, min(length, maxLen - 3));
209 /* if (id == SLIDE_IPTC_CAPTION)
211 CExifParse::FixComment(m_IptcInfo[id]); // Ensure comment is printable