2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 //--------------------------------------------------------------------------
10 // Module to pull IPTC information out of various types of digital images.
11 //--------------------------------------------------------------------------
13 //--------------------------------------------------------------------------
15 //--------------------------------------------------------------------------
17 #include "IptcParse.h"
19 #include "ExifParse.h"
30 #define min(a,b) (a)>(b)?(b):(a)
33 // Supported IPTC entry types
34 #define IPTC_RECORD_VERSION 0x00
35 #define IPTC_SUPLEMENTAL_CATEGORIES 0x14
36 #define IPTC_KEYWORDS 0x19
37 #define IPTC_CAPTION 0x78
38 #define IPTC_AUTHOR 0x7A
39 #define IPTC_HEADLINE 0x69
40 #define IPTC_SPECIAL_INSTRUCTIONS 0x28
41 #define IPTC_CATEGORY 0x0F
42 #define IPTC_BYLINE 0x50
43 #define IPTC_BYLINE_TITLE 0x55
44 #define IPTC_CREDIT 0x6E
45 #define IPTC_SOURCE 0x73
46 #define IPTC_COPYRIGHT_NOTICE 0x74
47 #define IPTC_OBJECT_NAME 0x05
48 #define IPTC_CITY 0x5A
49 #define IPTC_STATE 0x5F
50 #define IPTC_COUNTRY 0x65
51 #define IPTC_TRANSMISSION_REFERENCE 0x67
52 #define IPTC_DATE 0x37
53 #define IPTC_URGENCY 0x0A
54 #define IPTC_COUNTRY_CODE 0x64
55 #define IPTC_REFERENCE_SERVICE 0x2D
56 #define IPTC_TIME_CREATED 0x3C
57 #define IPTC_SUB_LOCATION 0x5C
58 #define IPTC_IMAGE_TYPE 0x82
61 //--------------------------------------------------------------------------
62 // Process IPTC marker. Return FALSE if unable to process marker.
64 // IPTC block consists of:
65 // - Marker: 1 byte (0xED)
66 // - Block length: 2 bytes
67 // - IPTC Signature: 14 bytes ("Photoshop 3.0\0")
68 // - 8BIM Signature 4 bytes ("8BIM")
69 // - IPTC Block start 2 bytes (0x04, 0x04)
70 // - IPTC Header length 1 byte
71 // - IPTC header Header is padded to even length, counting the length byte
73 // - IPTC Data which consists of a number of entries, each of which has the following format:
74 // - Signature 2 bytes (0x1C02)
75 // - Entry type 1 byte (for defined entry types, see #defines above)
76 // - entry length 2 bytes
77 // - entry data 'entry length' bytes
79 //--------------------------------------------------------------------------
80 bool CIptcParse::Process (const unsigned char* const Data
, const unsigned short itemlen
, IPTCInfo_t
*info
)
82 if (!info
) return false;
84 const char IptcSignature1
[] = "Photoshop 3.0";
85 const char IptcSignature2
[] = "8BIM";
86 const char IptcSignature3
[] = {0x04, 0x04};
88 // Check IPTC signatures
89 const char* pos
= (const char*)(Data
+ sizeof(short)); // position data pointer after length field
90 const char* maxpos
= (const char*)(Data
+itemlen
);
91 unsigned char headerLen
= 0;
92 unsigned char dataLen
= 0;
93 memset(info
, 0, sizeof(IPTCInfo_t
));
95 if (itemlen
< 25) return false;
97 if (memcmp(pos
, IptcSignature1
, strlen(IptcSignature1
)-1) != 0) return false;
98 pos
+= sizeof(IptcSignature1
); // move data pointer to the next field
100 if (memcmp(pos
, IptcSignature2
, strlen(IptcSignature2
)-1) != 0) return false;
101 pos
+= sizeof(IptcSignature2
)-1; // move data pointer to the next field
103 while (memcmp(pos
, IptcSignature3
, sizeof(IptcSignature3
)) != 0) { // loop on valid Photoshop blocks
105 pos
+= sizeof(IptcSignature3
); // move data pointer to the Header Length
107 headerLen
= *pos
; // get header length and move data pointer to the next field
108 pos
+= (headerLen
& 0xfe) + 2; // move data pointer to the next field (Header is padded to even length, counting the length byte)
110 pos
+= 3; // move data pointer to length, assume only one byte, TODO: use all 4 bytes
113 pos
+= dataLen
; // skip data section
115 if (memcmp(pos
, IptcSignature2
, sizeof(IptcSignature2
) - 1) != 0) return false;
116 pos
+= sizeof(IptcSignature2
) - 1; // move data pointer to the next field
119 pos
+= sizeof(IptcSignature3
); // move data pointer to the next field
120 if (pos
>= maxpos
) return false;
122 // IPTC section found
125 headerLen
= *pos
++; // get header length and move data pointer to the next field
126 pos
+= headerLen
+ 1 - (headerLen
% 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
128 if (pos
+ 4 >= maxpos
) return false;
130 pos
+= 4; // move data pointer to the next field
132 // Now read IPTC data
133 while (pos
< (const char*)(Data
+ itemlen
-5))
135 if (pos
+ 5 > maxpos
) return false;
137 short signature
= (*pos
<< 8) + (*(pos
+1));
140 if (signature
!= 0x1C01 && signature
!= 0x1C02)
143 unsigned char type
= *pos
++;
144 unsigned short length
= (*pos
<< 8) + (*(pos
+1));
145 pos
+= 2; // Skip tag length
147 if (pos
+ length
> maxpos
) return false;
151 if (signature
== 0x1C02)
155 case IPTC_RECORD_VERSION
: tag
= info
->RecordVersion
; break;
156 case IPTC_SUPLEMENTAL_CATEGORIES
: tag
= info
->SupplementalCategories
; break;
157 case IPTC_KEYWORDS
: tag
= info
->Keywords
; break;
158 case IPTC_CAPTION
: tag
= info
->Caption
; break;
159 case IPTC_AUTHOR
: tag
= info
->Author
; break;
160 case IPTC_HEADLINE
: tag
= info
->Headline
; break;
161 case IPTC_SPECIAL_INSTRUCTIONS
: tag
= info
->SpecialInstructions
; break;
162 case IPTC_CATEGORY
: tag
= info
->Category
; break;
163 case IPTC_BYLINE
: tag
= info
->Byline
; break;
164 case IPTC_BYLINE_TITLE
: tag
= info
->BylineTitle
; break;
165 case IPTC_CREDIT
: tag
= info
->Credit
; break;
166 case IPTC_SOURCE
: tag
= info
->Source
; break;
167 case IPTC_COPYRIGHT_NOTICE
: tag
= info
->CopyrightNotice
; break;
168 case IPTC_OBJECT_NAME
: tag
= info
->ObjectName
; break;
169 case IPTC_CITY
: tag
= info
->City
; break;
170 case IPTC_STATE
: tag
= info
->State
; break;
171 case IPTC_COUNTRY
: tag
= info
->Country
; break;
172 case IPTC_TRANSMISSION_REFERENCE
: tag
= info
->TransmissionReference
; break;
173 case IPTC_DATE
: tag
= info
->Date
; break;
174 case IPTC_URGENCY
: tag
= info
->Urgency
; break;
175 case IPTC_REFERENCE_SERVICE
: tag
= info
->ReferenceService
; break;
176 case IPTC_COUNTRY_CODE
: tag
= info
->CountryCode
; break;
177 case IPTC_TIME_CREATED
: tag
= info
->TimeCreated
; break;
178 case IPTC_SUB_LOCATION
: tag
= info
->SubLocation
; break;
179 case IPTC_IMAGE_TYPE
: tag
= info
->ImageType
; break;
181 printf("IptcParse: Unrecognised IPTC tag: 0x%02x", type
);
188 if (type
!= IPTC_KEYWORDS
|| *tag
== 0)
190 strncpy(tag
, pos
, min(length
, MAX_IPTC_STRING
- 1));
191 tag
[min(length
, MAX_IPTC_STRING
- 1)] = 0;
193 else if (type
== IPTC_KEYWORDS
)
195 // there may be multiple keywords - lets join them
196 size_t maxLen
= MAX_IPTC_STRING
- strlen(tag
);
200 strncat(tag
, pos
, min(length
, maxLen
- 3));
203 /* if (id == SLIDESHOW_IPTC_CAPTION)
205 CExifParse::FixComment(m_IptcInfo[id]); // Ensure comment is printable