1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
/*
* Copyright (C) 2005-2007 Team XboxMediaCenter
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
//--------------------------------------------------------------------------
// Module to pull IPTC information out of various types of digital images.
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// Process IPTC data.
//--------------------------------------------------------------------------
#ifndef _LINUX
#include <windows.h>
#else
#include <string.h>
#define min(a,b) (a)>(b)?(b):(a)
#endif
#include <stdio.h>
#include "IptcParse.h"
#include "ExifParse.h"
// Supported IPTC entry types
#define IPTC_SUPLEMENTAL_CATEGORIES 0x14
#define IPTC_KEYWORDS 0x19
#define IPTC_CAPTION 0x78
#define IPTC_AUTHOR 0x7A
#define IPTC_HEADLINE 0x69
#define IPTC_SPECIAL_INSTRUCTIONS 0x28
#define IPTC_CATEGORY 0x0F
#define IPTC_BYLINE 0x50
#define IPTC_BYLINE_TITLE 0x55
#define IPTC_CREDIT 0x6E
#define IPTC_SOURCE 0x73
#define IPTC_COPYRIGHT_NOTICE 0x74
#define IPTC_OBJECT_NAME 0x05
#define IPTC_CITY 0x5A
#define IPTC_STATE 0x5F
#define IPTC_COUNTRY 0x65
#define IPTC_TRANSMISSION_REFERENCE 0x67
#define IPTC_DATE 0x37
#define IPTC_COPYRIGHT 0x0A
#define IPTC_COUNTRY_CODE 0x64
#define IPTC_REFERENCE_SERVICE 0x2D
//--------------------------------------------------------------------------
// Process IPTC marker. Return FALSE if unable to process marker.
//
// IPTC block consists of:
// - Marker: 1 byte (0xED)
// - Block length: 2 bytes
// - IPTC Signature: 14 bytes ("Photoshop 3.0\0")
// - 8BIM Signature 4 bytes ("8BIM")
// - IPTC Block start 2 bytes (0x04, 0x04)
// - IPTC Header length 1 byte
// - IPTC header Header is padded to even length, counting the length byte
// - Length 4 bytes
// - IPTC Data which consists of a number of entries, each of which has the following format:
// - Signature 2 bytes (0x1C02)
// - Entry type 1 byte (for defined entry types, see #defines above)
// - entry length 2 bytes
// - entry data 'entry length' bytes
//
//--------------------------------------------------------------------------
bool CIptcParse::Process (const unsigned char* const Data, const unsigned short itemlen, IPTCInfo_t *info)
{
if (!info) return false;
const char IptcSignature1[] = "Photoshop 3.0";
const char IptcSignature2[] = "8BIM";
const char IptcSignature3[] = {0x04, 0x04};
// Check IPTC signatures
char* pos = (char*)(Data + sizeof(short)); // position data pointer after length field
if (memcmp(pos, IptcSignature1, strlen(IptcSignature1)) != 0) return false;
pos += strlen(IptcSignature1) + 1; // move data pointer to the next field
if (memcmp(pos, IptcSignature2, strlen(IptcSignature2)) != 0) return false;
pos += strlen(IptcSignature2); // move data pointer to the next field
if (memcmp(pos, IptcSignature3, sizeof(IptcSignature3)) != 0) return false;
pos += sizeof(IptcSignature3); // move data pointer to the next field
// IPTC section found
// Skip header
unsigned char headerLen = *pos++; // get header length and move data pointer to the next field
pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
// Get length (Motorola format)
unsigned long length = CExifParse::Get32(pos);
pos += 4; // move data pointer to the next field
// Now read IPTC data
while (pos < (char*)(Data + itemlen-5))
{
short signature = (*pos << 8) + (*(pos+1));
pos += sizeof(short);
if (signature != 0x1C02)
break;
unsigned char type = *pos++;
unsigned short length = (*pos << 8) + (*(pos+1));
pos += sizeof(short); // Skip tag length
// Process tag here
char *tag = NULL;
switch (type)
{
case IPTC_SUPLEMENTAL_CATEGORIES: tag = info->SupplementalCategories; break;
case IPTC_KEYWORDS: tag = info->Keywords; break;
case IPTC_CAPTION: tag = info->Caption; break;
case IPTC_AUTHOR: tag = info->Author; break;
case IPTC_HEADLINE: tag = info->Headline; break;
case IPTC_SPECIAL_INSTRUCTIONS: tag = info->SpecialInstructions; break;
case IPTC_CATEGORY: tag = info->Category; break;
case IPTC_BYLINE: tag = info->Byline; break;
case IPTC_BYLINE_TITLE: tag = info->BylineTitle; break;
case IPTC_CREDIT: tag = info->Credit; break;
case IPTC_SOURCE: tag = info->Source; break;
case IPTC_COPYRIGHT_NOTICE: tag = info->CopyrightNotice; break;
case IPTC_OBJECT_NAME: tag = info->ObjectName; break;
case IPTC_CITY: tag = info->City; break;
case IPTC_STATE: tag = info->State; break;
case IPTC_COUNTRY: tag = info->Country; break;
case IPTC_TRANSMISSION_REFERENCE: tag = info->TransmissionReference; break;
case IPTC_DATE: tag = info->Date; break;
case IPTC_COPYRIGHT: tag = info->Copyright; break;
case IPTC_REFERENCE_SERVICE: tag = info->ReferenceService; break;
case IPTC_COUNTRY_CODE: tag = info->CountryCode; break;
default:
printf("IptcParse: Unrecognised IPTC tag: 0x%02x", type);
break;
}
if (tag)
{
if (type != IPTC_KEYWORDS || *tag == 0)
{
strncpy(tag, pos, min(length, MAX_IPTC_STRING - 1));
tag[min(length, MAX_IPTC_STRING - 1)] = 0;
}
else if (type == IPTC_KEYWORDS)
{
// there may be multiple keywords - lets join them
size_t maxLen = MAX_IPTC_STRING - strlen(tag);
if (maxLen > 2)
strcat(tag, ", ");
strncat(tag, pos, min(length, MAX_IPTC_STRING - maxLen - 3));
}
/* if (id == SLIDE_IPTC_CAPTION)
{
CExifParse::FixComment(m_IptcInfo[id]); // Ensure comment is printable
}*/
}
pos += length;
}
return true;
}
|