[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / pictures / IptcParse.cpp
blobdc66f2772d8c7a5816c43f101cdb9af68e79760e
1 /*
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.
7 */
9 //--------------------------------------------------------------------------
10 // Module to pull IPTC information out of various types of digital images.
11 //--------------------------------------------------------------------------
13 //--------------------------------------------------------------------------
14 // Process IPTC data.
15 //--------------------------------------------------------------------------
17 #include "IptcParse.h"
19 #include "ExifParse.h"
21 #ifdef TARGET_WINDOWS
22 #include <windows.h>
23 #else
24 #include <string.h>
25 #endif
27 #include <stdio.h>
29 #ifndef min
30 #define min(a,b) (a)>(b)?(b):(a)
31 #endif
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
72 // - Length 4 bytes
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
106 // Skip header
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
112 dataLen = *pos++;
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
124 // Skip header
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));
139 pos += 2;
140 if (signature != 0x1C01 && signature != 0x1C02)
141 break;
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;
149 // Process tag here
150 char *tag = NULL;
151 if (signature == 0x1C02)
153 switch (type)
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;
180 default:
181 printf("IptcParse: Unrecognised IPTC tag: 0x%02x", type);
182 break;
186 if (tag)
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);
197 if (maxLen > 2)
199 strcat(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
208 pos += length;
210 return true;