@@ -21,68 +21,78 @@ struct IIMtag {
2121 const char * name; // Attribute name we use
2222 const char * anothername; // Optional second name
2323 bool repeatable; // May repeat
24+ unsigned int maxlen; // Maximum length (if nonzero)
2425};
2526
2627static IIMtag iimtag[] = {
27- { 3 , " IPTC:ObjectTypeReference" , NULL , false },
28- { 4 , " IPTC:ObjectAttributeReference" , NULL , true },
29- { 5 , " IPTC:ObjectName" , NULL , false },
30- { 7 , " IPTC:EditStatus" , NULL , false },
31- { 10 , " IPTC:Urgency" , NULL , false }, // deprecated by IPTC
32- { 12 , " IPTC:SubjectReference" , NULL , true },
33- { 15 , " IPTC:Category" , NULL , false },
34- { 20 , " IPTC:SupplementalCategories" , NULL , true }, // deprecated by IPTC
35- { 22 , " IPTC:FixtureIdentifier" , NULL , false },
36- { 25 , " Keywords" , NULL , true },
37- { 26 , " IPTC:ContentLocationCode" , NULL , true },
38- { 27 , " IPTC:ContentLocationName" , NULL , true },
39- { 30 , " IPTC:ReleaseDate" , NULL , false },
40- { 35 , " IPTC:ReleaseTime" , NULL , false },
41- { 37 , " IPTC:ExpirationDate" , NULL , false },
42- { 38 , " IPTC:ExpirationTime" , NULL , false },
43- { 40 , " IPTC:Instructions" , NULL , false },
44- { 45 , " IPTC:ReferenceService" , NULL , true },
45- { 47 , " IPTC:ReferenceDate" , NULL , false },
46- { 50 , " IPTC:ReferenceNumber" , NULL , true },
47- { 55 , " IPTC:DateCreated" , NULL , false },
48- { 60 , " IPTC:TimeCreated" , NULL , false },
49- { 62 , " IPTC:DigitalCreationDate" , NULL , false },
50- { 63 , " IPTC:DigitalCreationTime" , NULL , false },
51- { 65 , " IPTC:OriginatingProgram" , " Software" , false },
52- { 70 , " IPTC:ProgramVersion" , NULL , false },
53- { 80 , " IPTC:Creator" , " Artist" , true }, // sometimes called "byline"
54- { 85 , " IPTC:AuthorsPosition" , NULL , true }, // sometimes "byline title"
55- { 90 , " IPTC:City" , NULL , false },
56- { 92 , " IPTC:Sublocation" , NULL , false },
57- { 95 , " IPTC:State" , NULL , false }, // sometimes "Province/State"
58- { 100 , " IPTC:CountryCode" , NULL , false },
59- { 101 , " IPTC:Country" , NULL , false },
60- { 103 , " IPTC:TransmissionReference" , NULL , false },
61- { 105 , " IPTC:Headline" , NULL , false },
62- { 110 , " IPTC:Provider" , NULL , false }, // aka Credit
63- { 115 , " IPTC:Source" , NULL , false },
64- { 116 , " IPTC:CopyrightNotice" , " Copyright" , false },
65- { 118 , " IPTC:Contact" , NULL , false },
66- { 120 , " IPTC:Caption" , " ImageDescription" , false },
67- { 121 , " IPTC:LocalCaption" , NULL , false },
68- { 122 , " IPTC:CaptionWriter" , NULL , false }, // aka Writer/Editor
28+ { 3 , " IPTC:ObjectTypeReference" , NULL , false , 67 },
29+ { 4 , " IPTC:ObjectAttributeReference" , NULL , true , 68 },
30+ { 5 , " IPTC:ObjectName" , NULL , false , 64 },
31+ { 7 , " IPTC:EditStatus" , NULL , false , 64 },
32+ { 10 , " IPTC:Urgency" , NULL , false , 1 }, // deprecated by IPTC
33+ { 12 , " IPTC:SubjectReference" , NULL , true , 236 },
34+ { 15 , " IPTC:Category" , NULL , false , 3 },
35+ { 20 , " IPTC:SupplementalCategories" , NULL , true , 32 }, // deprecated by IPTC
36+ { 22 , " IPTC:FixtureIdentifier" , NULL , false , 32 },
37+ { 25 , " IPTC: Keywords" , NULL , true , 64 },
38+ { 26 , " IPTC:ContentLocationCode" , NULL , true , 3 },
39+ { 27 , " IPTC:ContentLocationName" , NULL , true , 64 },
40+ { 30 , " IPTC:ReleaseDate" , NULL , false , 8 },
41+ { 35 , " IPTC:ReleaseTime" , NULL , false , 11 },
42+ { 37 , " IPTC:ExpirationDate" , NULL , false , 8 },
43+ { 38 , " IPTC:ExpirationTime" , NULL , false , 11 },
44+ { 40 , " IPTC:Instructions" , NULL , false , 256 },
45+ { 45 , " IPTC:ReferenceService" , NULL , true , 10 },
46+ { 47 , " IPTC:ReferenceDate" , NULL , false , 8 },
47+ { 50 , " IPTC:ReferenceNumber" , NULL , true , 8 },
48+ { 55 , " IPTC:DateCreated" , NULL , false , 8 },
49+ { 60 , " IPTC:TimeCreated" , NULL , false , 11 },
50+ { 62 , " IPTC:DigitalCreationDate" , NULL , false , 8 },
51+ { 63 , " IPTC:DigitalCreationTime" , NULL , false , 11 },
52+ { 65 , " IPTC:OriginatingProgram" , " Software" , false , 32 },
53+ { 70 , " IPTC:ProgramVersion" , NULL , false , 10 },
54+ { 80 , " IPTC:Creator" , " Artist" , true , 32 }, // sometimes called "byline"
55+ { 85 , " IPTC:AuthorsPosition" , NULL , true , 32 }, // sometimes "byline title"
56+ { 90 , " IPTC:City" , NULL , false , 32 },
57+ { 92 , " IPTC:Sublocation" , NULL , false , 32 },
58+ { 95 , " IPTC:State" , NULL , false , 32 }, // sometimes "Province/State"
59+ { 100 , " IPTC:CountryCode" , NULL , false , 3 },
60+ { 101 , " IPTC:Country" , NULL , false , 64 },
61+ { 103 , " IPTC:TransmissionReference" , NULL , false , 32 },
62+ { 105 , " IPTC:Headline" , NULL , false , 256 },
63+ { 110 , " IPTC:Provider" , NULL , false , 32 }, // aka Credit
64+ { 115 , " IPTC:Source" , NULL , false , 32 },
65+ { 116 , " IPTC:CopyrightNotice" , " Copyright" , false , 128 },
66+ { 118 , " IPTC:Contact" , NULL , false , 128 },
67+ { 120 , " IPTC:Caption" , " ImageDescription" , false , 2000 },
68+ { 121 , " IPTC:LocalCaption" , NULL , false , 256 },
69+ { 122 , " IPTC:CaptionWriter" , NULL , false , 32 }, // aka Writer/Editor
6970 // Note: 150-154 is audio sampling stuff
70- { 184 , " IPTC:JobID" , NULL , false },
71- { 185 , " IPTC:MasterDocumentID" , NULL , false },
72- { 186 , " IPTC:ShortDocumentID" , NULL , false },
73- { 187 , " IPTC:UniqueDocumentID" , NULL , false },
74- { 188 , " IPTC:OwnerID" , NULL , false },
75- { 221 , " IPTC:Prefs" , NULL , false },
76- { 225 , " IPTC:ClassifyState" , NULL , false },
77- { 228 , " IPTC:SimilarityIndex" , NULL , false },
78- { 230 , " IPTC:DocumentNotes" , NULL , false },
79- { 231 , " IPTC:DocumentHistory" , NULL , false },
80- { -1 , NULL , NULL , false }
71+ { 184 , " IPTC:JobID" , NULL , false , 64 },
72+ { 185 , " IPTC:MasterDocumentID" , NULL , false , 256 },
73+ { 186 , " IPTC:ShortDocumentID" , NULL , false , 64 },
74+ { 187 , " IPTC:UniqueDocumentID" , NULL , false , 128 },
75+ { 188 , " IPTC:OwnerID" , NULL , false , 128 },
76+ { 221 , " IPTC:Prefs" , NULL , false , 64 },
77+ { 225 , " IPTC:ClassifyState" , NULL , false , 64 },
78+ { 228 , " IPTC:SimilarityIndex" , NULL , false , 32 },
79+ { 230 , " IPTC:DocumentNotes" , NULL , false , 1024 },
80+ { 231 , " IPTC:DocumentHistory" , NULL , false , 256 },
81+ { -1 , NULL , NULL , false , 0 }
8182};
8283
8384// N.B. All "Date" fields are 8 digit strings: CCYYMMDD
8485// All "Time" fields are 11 digit strings (what format?)
8586
87+ // IPTC references:
88+ //
89+ // * https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata
90+ // * https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata#iptc-core-schema-1-5-specifications
91+ // This is the one where you can find the length limits
92+ // * ExifTool's documentation about IPTC tags (caveat: not a definitive
93+ // reference, could be outdated or incorrect):
94+ // https://exiftool.org/TagNames/IPTC.html
95+
8696} // anonymous namespace
8797
8898
@@ -144,9 +154,13 @@ decode_iptc_iim(const void* iptc, int length, ImageSpec& spec)
144154 } else {
145155 spec.attribute (iimtag[i].name , s);
146156 }
157+ #if 0
158+ // We are no longer confident about auto-translating IPTC
159+ // data into allegedly equivalent metadata.
147160 if (iimtag[i].anothername
148161 && !spec.extra_attribs.contains(iimtag[i].anothername))
149162 spec.attribute(iimtag[i].anothername, s);
163+ #endif
150164 break ;
151165 }
152166 }
@@ -193,18 +207,28 @@ encode_iptc_iim(const ImageSpec& spec, std::vector<char>& iptc)
193207 Strutil::split (allvals, tokens, " ;" );
194208 for (auto & token : tokens) {
195209 token = Strutil::strip (token);
196- if (token.size ())
210+ if (token.size ()) {
211+ if (iimtag[i].maxlen && iimtag[i].maxlen < token.size ())
212+ token = token.substr (0 , iimtag[i].maxlen );
197213 encode_iptc_iim_one_tag (iimtag[i].tag , token, iptc);
214+ }
198215 }
199216 } else {
200217 // Regular, non-repeating
201- encode_iptc_iim_one_tag (iimtag[i].tag , p->get_string (0 ), iptc);
218+ std::string token = p->get_string (0 );
219+ if (iimtag[i].maxlen && iimtag[i].maxlen < token.size ())
220+ token = token.substr (0 , iimtag[i].maxlen );
221+ encode_iptc_iim_one_tag (iimtag[i].tag , token, iptc);
202222 }
203223 }
224+ #if 0
225+ // We are no longer confident about auto-translating other metadata
226+ // into allegedly equivalent IPTC.
204227 if (iimtag[i].anothername) {
205228 if ((p = spec.find_attribute(iimtag[i].anothername)))
206229 encode_iptc_iim_one_tag(iimtag[i].tag, p->get_string(0), iptc);
207230 }
231+ #endif
208232 }
209233 return iptc.size () != 0 ;
210234}
0 commit comments