1 //--------------------------------------------------------------------------
2 // Process IPTC data and XMP data.
3 //--------------------------------------------------------------------------
4 #include "jhead.h"
5
6 // IPTC entry types known to Jhead (there's many more defined)
7 #define IPTC_RECORD_VERSION 0x00
8 #define IPTC_SUPLEMENTAL_CATEGORIES 0x14
9 #define IPTC_KEYWORDS 0x19
10 #define IPTC_CAPTION 0x78
11 #define IPTC_AUTHOR 0x7A
12 #define IPTC_HEADLINE 0x69
13 #define IPTC_SPECIAL_INSTRUCTIONS 0x28
14 #define IPTC_CATEGORY 0x0F
15 #define IPTC_BYLINE 0x50
16 #define IPTC_BYLINE_TITLE 0x55
17 #define IPTC_CREDIT 0x6E
18 #define IPTC_SOURCE 0x73
19 #define IPTC_COPYRIGHT_NOTICE 0x74
20 #define IPTC_OBJECT_NAME 0x05
21 #define IPTC_CITY 0x5A
22 #define IPTC_STATE 0x5F
23 #define IPTC_COUNTRY 0x65
24 #define IPTC_TRANSMISSION_REFERENCE 0x67
25 #define IPTC_DATE 0x37
26 #define IPTC_COPYRIGHT 0x0A
27 #define IPTC_COUNTRY_CODE 0x64
28 #define IPTC_REFERENCE_SERVICE 0x2D
29 #define IPTC_TIME_CREATED 0x3C
30 #define IPTC_SUB_LOCATION 0x5C
31 #define IPTC_IMAGE_TYPE 0x82
32
33 //--------------------------------------------------------------------------
34 // Process and display IPTC marker.
35 //
36 // IPTC block consists of:
37 // - Marker: 1 byte (0xED)
38 // - Block length: 2 bytes
39 // - IPTC Signature: 14 bytes ("Photoshop 3.0\0")
40 // - 8BIM Signature 4 bytes ("8BIM")
41 // - IPTC Block start 2 bytes (0x04, 0x04)
42 // - IPTC Header length 1 byte
43 // - IPTC header Header is padded to even length, counting the length byte
44 // - Length 4 bytes
45 // - IPTC Data which consists of a number of entries, each of which has the following format:
46 // - Signature 2 bytes (0x1C02)
47 // - Entry type 1 byte (for defined entry types, see #defines above)
48 // - entry length 2 bytes
49 // - entry data 'entry length' bytes
50 //
51 //--------------------------------------------------------------------------
show_IPTC(unsigned char * Data,unsigned int itemlen)52 void show_IPTC (unsigned char* Data, unsigned int itemlen)
53 {
54 const char IptcSig1[] = "Photoshop 3.0";
55 const char IptcSig2[] = "8BIM";
56 const char IptcSig3[] = {0x04, 0x04};
57
58 unsigned char * pos = Data + sizeof(short); // position data pointer after length field
59 unsigned char * maxpos = Data+itemlen;
60 char headerLen = 0;
61
62 if (itemlen < 25) goto corrupt;
63
64 // Check IPTC signatures
65 if (memcmp(pos, IptcSig1, sizeof(IptcSig1)-1) != 0) goto badsig;
66 pos += sizeof(IptcSig1); // move data pointer to the next field
67
68 if (memcmp(pos, IptcSig2, sizeof(IptcSig2)-1) != 0) goto badsig;
69 pos += sizeof(IptcSig2)-1; // move data pointer to the next field
70
71 if (memcmp(pos, IptcSig3, sizeof(IptcSig3)) != 0){
72 badsig:
73 if (ShowTags){
74 ErrNonfatal("IPTC type signature mismatch\n",0,0);
75 }
76 return;
77 }
78 pos += sizeof(IptcSig3); // move data pointer to the next field
79
80 if (pos >= maxpos) goto corrupt;
81
82 // IPTC section found
83
84 // Skip header
85 headerLen = *pos++; // get header length and move data pointer to the next field
86 pos += headerLen + 1 - (headerLen % 2); // move data pointer to the next field (Header is padded to even length, counting the length byte)
87
88 if (pos+4 >= maxpos) goto corrupt;
89
90 // Get length (from motorola format)
91 //length = (*pos << 24) | (*(pos+1) << 16) | (*(pos+2) << 8) | *(pos+3);
92
93 pos += 4; // move data pointer to the next field
94
95 printf("======= IPTC data: =======\n");
96
97 // Now read IPTC data
98 while (pos < (Data + itemlen-5)) {
99 short signature;
100 unsigned char type = 0;
101 short length = 0;
102 char * description = NULL;
103
104 if (pos+5 > maxpos) goto corrupt;
105
106 signature = (*pos << 8) + (*(pos+1));
107 pos += 2;
108
109 if (signature != 0x1C02){
110 break;
111 }
112
113 type = *pos++;
114 length = (*pos << 8) + (*(pos+1));
115 pos += 2; // Skip tag length
116
117 if (pos+length > maxpos) goto corrupt;
118 // Process tag here
119 switch (type) {
120 case IPTC_RECORD_VERSION:
121 printf("Record vers. : %d\n", (*pos << 8) + (*(pos+1)));
122 break;
123
124 case IPTC_SUPLEMENTAL_CATEGORIES: description = "SuplementalCategories"; break;
125 case IPTC_KEYWORDS: description = "Keywords"; break;
126 case IPTC_CAPTION: description = "Caption"; break;
127 case IPTC_AUTHOR: description = "Author"; break;
128 case IPTC_HEADLINE: description = "Headline"; break;
129 case IPTC_SPECIAL_INSTRUCTIONS: description = "Spec. Instr."; break;
130 case IPTC_CATEGORY: description = "Category"; break;
131 case IPTC_BYLINE: description = "Byline"; break;
132 case IPTC_BYLINE_TITLE: description = "Byline Title"; break;
133 case IPTC_CREDIT: description = "Credit"; break;
134 case IPTC_SOURCE: description = "Source"; break;
135 case IPTC_COPYRIGHT_NOTICE: description = "(C)Notice"; break;
136 case IPTC_OBJECT_NAME: description = "Object Name"; break;
137 case IPTC_CITY: description = "City"; break;
138 case IPTC_STATE: description = "State"; break;
139 case IPTC_COUNTRY: description = "Country"; break;
140 case IPTC_TRANSMISSION_REFERENCE: description = "OriginalTransmissionReference"; break;
141 case IPTC_DATE: description = "DateCreated"; break;
142 case IPTC_COPYRIGHT: description = "(C)Flag"; break;
143 case IPTC_REFERENCE_SERVICE: description = "Country Code"; break;
144 case IPTC_COUNTRY_CODE: description = "Ref. Service"; break;
145 case IPTC_TIME_CREATED: description = "Time Created"; break;
146 case IPTC_SUB_LOCATION: description = "Sub Location"; break;
147 case IPTC_IMAGE_TYPE: description = "Image type"; break;
148
149 default:
150 if (ShowTags){
151 printf("Unrecognised IPTC tag: %d\n", type );
152 }
153 break;
154 }
155 if (description != NULL) {
156 char TempBuf[32];
157 memset(TempBuf, 0, sizeof(TempBuf));
158 memset(TempBuf, ' ', 14);
159 memcpy(TempBuf, description, strlen(description));
160 strcat(TempBuf, ":");
161 printf("%s %*.*s\n", TempBuf, length, length, pos);
162 }
163 pos += length;
164 }
165 return;
166 corrupt:
167 ErrNonfatal("Pointer corruption in IPTC\n",0,0);
168 }
169
170
171
172 //--------------------------------------------------------------------------
173 // Dump contents of XMP section
174 //--------------------------------------------------------------------------
ShowXmp(Section_t XmpSection)175 void ShowXmp(Section_t XmpSection)
176 {
177 unsigned char * Data;
178 char OutLine[101];
179 int OutLineChars;
180 int NonBlank;
181 unsigned a;
182 NonBlank = 0;
183 Data = XmpSection.Data;
184 OutLineChars = 0;
185
186
187 for (a=0;a<XmpSection.Size;a++){
188 if (Data[a] >= 32 && Data[a] < 128){
189 OutLine[OutLineChars++] = Data[a];
190 if (Data[a] != ' ') NonBlank |= 1;
191 }else{
192 if (Data[a] != '\n'){
193 OutLine[OutLineChars++] = '?';
194 }
195 }
196 if (Data[a] == '\n' || OutLineChars >= 100){
197 OutLine[OutLineChars] = 0;
198 if (NonBlank){
199 puts(OutLine);
200 }
201 NonBlank = (NonBlank & 1) << 1;
202 OutLineChars = 0;
203 }
204 }
205 }
206