- Timestamp:
- 2021-02-26T19:39:51+13:00 (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone2/perllib/cpan/Image/ExifTool/BuildTagLookup.pm
r24107 r34921 32 32 use Image::ExifTool::Canon; 33 33 use Image::ExifTool::Nikon; 34 35 $VERSION = '2.28'; 34 use Image::ExifTool::Sony; 35 use Image::ExifTool::Validate; 36 use Image::ExifTool::MacOS; 37 38 $VERSION = '3.42'; 36 39 @ISA = qw(Exporter); 37 40 38 sub NumbersFirst; 39 40 my $numbersFirst = 1; # set to -1 to sort numbers last 41 sub NumbersFirst($$); 42 sub SortedTagTablekeys($); 43 44 my $createDate = 'Feb 15, 2005'; 45 46 # global variables to control sorting order of table entries 47 my $numbersFirst = 1; # set to -1 to sort numbers last, or 2 to put negative numbers last 48 my $caseInsensitive; # flag to ignore case when sorting tag names 41 49 42 50 # list of all tables in plug-in modules … … 51 59 }; 52 60 53 my $homePage = 'http://owl.phy.queensu.ca/~phil/exiftool'; 61 my $homePage = 'https://exiftool.org'; 62 63 # tweak the ordering of tables in the documentation 64 my %tweakOrder = ( 65 # this => comes after this 66 # ------- ----------------- 67 JPEG => '-', # JPEG comes first 68 IPTC => 'Exif', # put IPTC after EXIF, 69 GPS => 'XMP', # etc... 70 Composite => 'Extra', 71 GeoTiff => 'GPS', 72 CanonVRD=> 'CanonCustom', 73 DJI => 'Casio', 74 FLIR => 'DJI', 75 FujiFilm => 'FLIR', 76 Kodak => 'JVC', 77 Leaf => 'Kodak', 78 Minolta => 'Leaf', 79 Motorola => 'Minolta', 80 Nikon => 'Motorola', 81 NikonCustom => 'Nikon', 82 NikonCapture => 'NikonCustom', 83 Nintendo => 'NikonCapture', 84 Pentax => 'Panasonic', 85 SonyIDC => 'Sony', 86 Unknown => 'SonyIDC', 87 DNG => 'Unknown', 88 PrintIM => 'ICC_Profile', 89 Vorbis => 'Ogg', 90 ID3 => 'PostScript', 91 MinoltaRaw => 'KyoceraRaw', 92 KyoceraRaw => 'CanonRaw', 93 SigmaRaw => 'PanasonicRaw', 94 Lytro => 'SigmaRaw', 95 PhotoMechanic => 'FotoStation', 96 Microsoft => 'PhotoMechanic', 97 'Microsoft::MP'=> 'Microsoft::MP1', 98 GIMP => 'Microsoft', 99 'Nikon::CameraSettingsD300' => 'Nikon::ShotInfoD300b', 100 'Pentax::LensData' => 'Pentax::LensInfo2', 101 'Sony::SRF2' => 'Sony::SRF', 102 DarwinCore => 'AFCP', 103 'MWG::Regions' => 'MWG::Composite', 104 'MWG::Keywords' => 'MWG::Regions', 105 'MWG::Collections' => 'MWG::Keywords', 106 'GoPro::fdsc' => 'GoPro::KBAT', 107 ); 54 108 55 109 # list of all recognized Format strings 56 110 # (not a complete list, but this is all we use so far) 57 # (also, formats like "var_X[ Y]" are allowed for any valid X)111 # (also, formats like "var_X[num]" are allowed for any valid X) 58 112 my %formatOK = ( 59 113 %Image::ExifTool::Exif::formatNumber, 60 114 0 => 1, 61 115 1 => 1, 116 2 => 1, # (writable for docs only) 62 117 real => 1, 63 118 integer => 1, … … 74 129 digits => 1, 75 130 int16uRev => 1, 131 int32uRev => 1, 76 132 rational32u => 1, 77 133 rational32s => 1, 134 pstring => 1, 78 135 var_string => 1, 79 136 var_int16u => 1, 80 137 var_pstr32 => 1, 138 var_ustr32 => 1, 139 var_ue7 => 1, # (BPG) 81 140 # Matroska 82 141 signed => 1, … … 84 143 utf8 => 1, 85 144 ); 86 87 my $caseInsensitive; # flag to ignore case when sorting tag names88 145 89 146 # Descriptions for the TagNames documentation … … 107 164 ExifTool => q{ 108 165 The tables listed below give the names of all tags recognized by ExifTool. 166 They contain a total of $$self{COUNT}{'total tags'} tags, with $$self{COUNT}{'unique tag names'} unique tag names. 109 167 }, 110 168 ExifTool2 => q{ 111 B<Tag ID>, B<Index > or B<Sequence> is given in the first column of each169 B<Tag ID>, B<Index#> or B<Sequence> is given in the first column of each 112 170 table. A B<Tag ID> is the computer-readable equivalent of a tag name, and 113 is the identifier that is actually stored in the file. An B<Index> refers 114 to the location of a value when found at a fixed position within a data 115 block, and B<Sequence> gives the order of values for a serial data stream. 171 is the identifier that is actually stored in the file. B<Index#> refers to 172 the offset of a value when found at a fixed position within a data block 173 (B<#> is the multiplier for calculating a byte offset: B<1>, B<2>, B<4> or 174 B<8>). These offsets may have a decimal part which is used only to 175 differentiate tags with values stored at the same position. (Note that 176 writable tags within binary data blocks are not individually deletable, 177 and the usual alternative is to set them to a value of zero.) B<Sequence> 178 gives the order of values for a serial data stream. 116 179 117 180 A B<Tag Name> is the handle by which the information is accessed in … … 121 184 question mark (C<?>) after a tag name indicates that the information is 122 185 either not understood, not verified, or not very useful -- these tags are 123 not extracted by ExifTool unless the Unknown(-u) option is enabled. Be186 not extracted by ExifTool unless the L<Unknown|../ExifTool.html#Unknown> (-u) option is enabled. Be 124 187 aware that some tag names are different than the descriptions printed out by 125 188 default when extracting information with exiftool. To see the tag names … … 127 190 128 191 The B<Writable> column indicates whether the tag is writable by ExifTool. 129 Anything but a n C<N> in this column means the tag is writable. A C<Y>192 Anything but a C<no> in this column means the tag is writable. A C<yes> 130 193 indicates writable information that is either unformatted or written using 131 the existing format. Other expressions give details about the information132 format, and vary depending on the general type of information. The format 133 name may be followed by a number in square brackets to indicate the number 134 of values written, or the number of characters in a fixed-length string 135 (including a null terminator which is added if required).194 the existing format. Other expressions give details about the format of the 195 stored value, and vary depending on the general type of information. The 196 format name may be followed by a number in square brackets to indicate the 197 number of values written, or the number of characters in a fixed-length 198 string (including a null terminator which is added if required). 136 199 137 200 A plus sign (C<+>) after an entry in the B<Writable> column indicates a 138 "list" tag which supports multiple values and allows individual values to be 139 added and deleted. A slash (C</>) indicates an "avoided" tag that is not 140 created when writing if another same-named tag may be created instead. To 141 write these tags, the group should be specified. A tilde (C<~>) indicates a 142 tag this is writable only when the print conversion is disabled (by setting 143 PrintConv to 0, using the -n option, or suffixing the tag name with a C<#> 144 character). An exclamation point (C<!>) indicates a tag that is considered 145 unsafe to write under normal circumstances. These "unsafe" tags are not set 146 when calling SetNewValuesFromFile() or copied with the exiftool 147 -tagsFromFile option unless specified explicitly, and care should be taken 148 when editing them manually since they may affect the way an image is149 rendered. An asterisk (C<*>) indicates a "protected"tag which is not201 I<List> tag which supports multiple values and allows individual values to 202 be added and deleted. A slash (C</>) indicates a tag that ExifTool will 203 I<Avoid> when writing. These will be edited but not created if another 204 same-named tag may be created instead. To create these tags, the group 205 should be specified. A tilde (C<~>) indicates a tag this is writable only 206 when the print conversion is disabled (by setting L<PrintConv|../ExifTool.html#PrintConv> to 0, using the 207 -n option, or suffixing the tag name with a C<#> character). An exclamation 208 point (C<!>) indicates a tag that is considered I<Unsafe> to write under 209 normal circumstances. These tags are not written unless specified 210 explicitly (ie. not when wildcards or "all" are used), and care should be 211 taken when editing them manually since they may affect the way an image is 212 rendered. An asterisk (C<*>) indicates a I<Protected> tag which is not 150 213 writable directly, but is written automatically by ExifTool (often when a 151 corresponding Composite or Extra tag is written). A colon (C<:>) indicates 152 a mandatory tag which may be added automatically when writing. 214 corresponding L<Composite|Image::ExifTool::TagNames/Composite Tags> or 215 L<Extra|Image::ExifTool::TagNames/Extra Tags> tag is written). A colon 216 (C<:>) indicates a I<Mandatory> tag which may be added automatically when 217 writing. Normally MakerNotes tags may not be deleted individually, but a 218 caret (C<^>) indicates a I<Deletable> MakerNotes tag. 153 219 154 220 The HTML version of these tables also lists possible B<Values> for 155 221 discrete-valued tags, as well as B<Notes> for some tags. The B<Values> are 156 listed as the computer-readable and human-readable values on the left and157 right hand side of an equals sign (C<=>) respectively. The human-readable222 listed with the computer-readable values on the left of the equals sign 223 (C<=>), and the human-readable values on the right. The human-readable 158 224 values are used by default when reading and writing, but the 159 225 computer-readable values may be accessed by disabling the value conversion 160 with the -n option on the command line, by setting the ValueConvoption to 0161 in the API, or or on a per-tag basis by a ppending a number symbol (C<#>) to162 the tagname.226 with the -n option on the command line, by setting the L<PrintConv|../ExifTool.html#PrintConv> option to 0 227 in the API, or or on a per-tag basis by adding a hash (C<#>) after the tag 228 name. 163 229 164 230 B<Note>: If you are familiar with common meta-information tag names, you may … … 168 234 documentation or run C<exiftool -s> on a file containing the information in 169 235 question. 236 237 I<(This documentation is the result of years of research, testing and 238 reverse engineering, and is the most complete metadata tag list available 239 anywhere on the internet. It is provided not only for ExifTool users, but 240 more importantly as a public service to help augment the collective 241 knowledge, and is often used as a primary source of information in the 242 development of other metadata software. Please help keep this documentation 243 as accurate and complete as possible, and feed any new discoveries back to 244 ExifTool. A big thanks to everyone who has helped with this so far!)> 170 245 }, 171 246 EXIF => q{ 172 247 EXIF stands for "Exchangeable Image File Format". This type of information 173 248 is formatted according to the TIFF specification, and may be found in JPG, 174 TIFF, PNG, PGF, MIFF, HDP, PSP and XCF images, as well as many TIFF-based175 RAW images, and even some AVI and MOV videos.249 TIFF, PNG, JP2, PGF, MIFF, HDP, PSP and XCF images, as well as many 250 TIFF-based RAW images, and even some AVI and MOV videos. 176 251 177 252 The EXIF meta information is organized into different Image File Directories … … 180 255 B<Group> listed below is used unless another group is specified. 181 256 257 Mandatory tags (indicated by a colon after the B<Writable> type) may be 258 added automatically with default values when creating a new IFD, and the IFD 259 is removed automatically when deleting tags if only default-valued mandatory 260 tags remain. 261 182 262 The table below lists all EXIF tags. Also listed are TIFF, DNG, HDP and 183 263 other tags which are not part of the EXIF specification, but may co-exist 184 with EXIF tags in some images. Tags which are part of the EXIF 2.3 264 with EXIF tags in some images. Tags which are part of the EXIF 2.32 185 265 specification have an underlined B<Tag Name> in the HTML version of this 186 266 documentation. See 187 L<http ://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf> for the188 official EXIF 2.3specification.267 L<https://web.archive.org/web/20190624045241if_/http://www.cipa.jp:80/std/documents/e/DC-008-Translation-2019-E.pdf> 268 for the official EXIF 2.32 specification. 189 269 }, 190 270 GPS => q{ … … 201 281 indicated string lengths include a null terminator which is added 202 282 automatically by ExifTool. Remember that the descriptive values are used 203 when writing ( ie. 'Above Sea Level', not '0') unless the print conversion is204 disabled (with '-n' on the command line or the PrintConvoption in the API,283 when writing (eg. 'Above Sea Level', not '0') unless the print conversion is 284 disabled (with '-n' on the command line or the L<PrintConv|../ExifTool.html#PrintConv> option in the API, 205 285 or by suffixing the tag name with a C<#> character). 206 286 207 287 When adding GPS information to an image, it is important to set all of the 208 288 following tags: GPSLatitude, GPSLatitudeRef, GPSLongitude, GPSLongitudeRef, 209 GPSAltitude and GPSAltitudeRef. ExifTool will write the required 210 GPSVersionID tag automatically if new a GPS IFD is added to an image. 289 and GPSAltitude and GPSAltitudeRef if the altitude is known. ExifTool will 290 write the required GPSVersionID tag automatically if new a GPS IFD is added 291 to an image. 211 292 }, 212 293 XMP => q{ … … 214 295 format which is being pushed by Adobe. Information in this format can be 215 296 embedded in many different image file types including JPG, JP2, TIFF, GIF, 216 EPS, PDF, PSD, IND, PNG, DJVU, SVG, PGF, MIFF, XCF, CRW, DNG and a variety 217 of proprietary TIFF-based RAW images, as well as MOV, AVI, ASF, WMV, FLV, 218 SWF and MP4 videos, and WMA and audio formats supporting ID3v2 information. 297 EPS, PDF, PSD, IND, INX, PNG, DJVU, SVG, PGF, MIFF, XCF, CRW, DNG and a 298 variety of proprietary TIFF-based RAW images, as well as MOV, AVI, ASF, WMV, 299 FLV, SWF and MP4 videos, and WMA and audio formats supporting ID3v2 300 information. 219 301 220 302 The XMP B<Tag ID>'s aren't listed because in most cases they are identical … … 229 311 point number but stored as two C<integer> strings separated by a '/' 230 312 character, C<date> is a date/time string entered in the format "YYYY:mm:dd 231 HH:MM:SS[.ss][+/-HH:MM]", C<boolean> is either "True" or "False", 232 C<lang-alt> indicates that the tag supports alternate languages (see below), 233 and C<struct> is an XMP structure. When reading, structures are extracted 234 only if the Struct (-struct) option is used. Otherwise the corresponding 235 "flattened" tags, indicated by an underline (C<_>) after the B<Writable> 236 type, are extracted. When copying information, the Struct option is in 237 effect by default. When writing, the Struct option has no effect, and both 238 structured and flattened tags may be written. See 239 L<http://owl.phy.queensu.ca/~phil/exiftool/struct.html> for more details. 313 HH:MM:SS[.ss][+/-HH:MM]", C<boolean> is either "True" or "False" (but "true" 314 and "false" may be written as a ValueConv value for compatibility with 315 non-conforming applications), C<struct> indicates a structured tag, and 316 C<lang-alt> is a tag that supports alternate languages. 317 318 When reading, C<struct> tags are extracted only if the L<Struct|../ExifTool.html#Struct> (-struct) 319 option is used. Otherwise the corresponding I<Flattened> tags, indicated by 320 an underline (C<_>) after the B<Writable> type, are extracted. When 321 copying, by default both structured and flattened tags are available, but 322 the flattened tags are considered "unsafe" so they aren't copied unless 323 specified explicitly. The L<Struct|../ExifTool.html#Struct> option may be disabled by setting Struct 324 to 0 via the API or with --struct on the command line to copy only flattened 325 tags, or enabled by setting Struct to 1 via the API or with -struct on the 326 command line to copy only as structures. When writing, the L<Struct|../ExifTool.html#Struct> option 327 has no effect, and both structured and flattened tags may be written. See 328 L<https://exiftool.org/struct.html> for more details. 240 329 241 330 Individual languages for C<lang-alt> tags are accessed by suffixing the tag 242 name with a '-', followed by an RFC 3066 language code ( ie. "XMP:Title-fr",331 name with a '-', followed by an RFC 3066 language code (eg. "XMP:Title-fr", 243 332 or "Rights-en-US"). (See L<http://www.ietf.org/rfc/rfc3066.txt> for the RFC 244 333 3066 specification.) A C<lang-alt> tag with no language code accesses the 245 334 "x-default" language, but causes other languages for this tag to be deleted 246 335 when writing. The "x-default" language code may be specified when writing 247 to preserve other existing languages ( ie. "XMP-dc:Description-x-default").336 to preserve other existing languages (eg. "XMP-dc:Description-x-default"). 248 337 When reading, "x-default" is not specified. 249 338 250 339 The XMP tags are organized according to schema B<Namespace> in the following 251 tables. Note that a few of the longer namespace prefixes given below have 252 been shortened for convenience (since the family 1 group names are derived 253 from these by adding a leading "XMP-"). In cases where a tag name exists in 254 more than one namespace, less common namespaces are avoided when writing. 255 However, any namespace may be written by specifying a family 1 group name 256 for the tag, ie) XMP-exif:Contrast or XMP-crs:Contrast. When deciding on 257 which tags to add to an image, using standard schemas such as 258 L<dc|/XMP dc Tags>, L<xmp|/XMP xmp Tags> or L<iptc|/XMP iptcCore Tags> is 340 tables. The ExifTool family 1 group names are derived from the namespace 341 prefixes by adding a leading "XMP-" (eg. "XMP-dc"). A few of the longer 342 prefixes have been shortened (as mentioned in the documentation below) to 343 avoid excessively long ExifTool group names. The tags of any namespace may 344 be deleted as a group by specifying the family 1 group name (eg. 345 "-XMP-dc:all=" on the command line). This includes namespaces which are not 346 pre-defined by ExifTool. 347 348 In cases where a tag name exists in more than one namespace, less common 349 namespaces are avoided when writing. However, a specific namespace may be 350 written by providing a family 1 group name for the tag (eg. XMP-crs:Contrast 351 or XMP-exif:Contrast). When deciding on which tags to add to an image, 352 using standard schemas such as L<dc|/XMP dc Tags>, L<xmp|/XMP xmp Tags>, 353 L<iptcCore|/XMP iptcCore Tags> and L<iptcExt|/XMP iptcExt Tags> is 259 354 recommended if possible. 260 355 … … 262 357 names are very similar to tag names, except they are used to identify fields 263 358 inside structures instead of stand-alone tags. See 264 L<the Field Name section of the Structured Information documentation|http ://owl.phy.queensu.ca/~phil/exiftool/struct.html#Fields> for more359 L<the Field Name section of the Structured Information documentation|https://exiftool.org/struct.html#Fields> for more 265 360 details. 266 361 267 362 ExifTool will extract XMP information even if it is not listed in these 268 tables. For example, the C<pdfx> namespace doesn't have a predefined set of 269 tag names because it is used to store application-defined PDF information, 270 but this information is extracted by ExifTool. 271 272 See L<http://www.adobe.com/devnet/xmp/> for the official XMP specification. 363 tables, but other tags are not writable unless added as user-defined tags in 364 the L<ExifTool config file|../config.html>. For example, the C<pdfx> namespace doesn't have a 365 predefined set of tag names because it is used to store application-defined 366 PDF information, so although this information will be extracted, it is only 367 writable if the corresponding user-defined tags have been created. 368 369 The tables below list tags from the official XMP specification (with an 370 underlined B<Namespace> in the HTML version of this documentation), as well 371 as extensions from various other sources. See 372 L<http://www.adobe.com/devnet/xmp/> for the official XMP specification. 273 373 }, 274 374 IPTC => q{ … … 276 376 Council (IPTC) and the Newspaper Association of America (NAA) Information 277 377 Interchange Model (IIM). This is an older meta information format, slowly 278 being phased out in favor of XMP . (In fact, the newer IPTCCore279 specification actually uses XMP format!) IPTC information may be embedded 280 in JPG, TIFF, PNG, MIFF, PS, PDF,PSD, XCF and DNG images.378 being phased out in favor of XMP -- the newer IPTCCore specification uses 379 XMP format. IPTC information may be found in JPG, TIFF, PNG, MIFF, PS, PDF, 380 PSD, XCF and DNG images. 281 381 282 382 IPTC information is separated into different records, each of which has its 283 383 own set of tags. See 284 384 L<http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf> for the 285 official specification.385 official IPTC IIM specification. 286 386 287 387 This specification dictates a length for ASCII (C<string> or C<digits>) and … … 289 389 the B<Writable> format name. For tags where a range of lengths is allowed, 290 390 the minimum and maximum lengths are separated by a comma within the 291 brackets. IPTC strings are not null terminated. When writing, ExifTool 292 issues a minor warning and truncates the value if it is longer than allowed 293 by the IPTC specification. Minor errors may be ignored with the 294 IgnoreMinorErrors (-m) option, allowing longer values to be written, but 295 beware that values like this may cause problems for some other IPTC readers. 391 brackets. When writing, ExifTool issues a minor warning and truncates the 392 value if it is longer than allowed by the IPTC specification. Minor errors 393 may be ignored with the L<IgnoreMinorErrors|../ExifTool.html#IgnoreMinorErrors> (-m) option, allowing longer 394 values to be written, but beware that values like this may cause problems 395 for some other IPTC readers. ExifTool will happily read IPTC values of any 396 length. 296 397 297 398 Separate IPTC date and time tags may be written with a combined date/time … … 306 407 offset at the specified date/time is used, which may be different due to 307 408 changes in daylight savings time). 409 410 Note that it is not uncommon for IPTC to be found in non-standard locations 411 in JPEG and TIFF-based images. When reading, the family 1 group name has a 412 number added for non-standard IPTC ("IPTC2", "IPTC3", etc), but when writing 413 only "IPTC" may be specified as the group. To keep the IPTC consistent, 414 ExifTool updates tags in all existing IPTC locations, but will create a new 415 IPTC group only in the standard location. 416 }, 417 QuickTime => q{ 418 The QuickTime format is used for many different types of audio, video and 419 image files (most notably, MOV/MP4 videos and HEIC/CR3 images). ExifTool 420 extracts standard meta information and a variety of audio, video and image 421 parameters, as well as proprietary information written by many camera 422 models. Tags with a question mark after their name are not extracted unless 423 the L<Unknown|../ExifTool.html#Unknown> option is set. 424 425 When writing, ExifTool creates both QuickTime and XMP tags by default, but 426 the group may be specified to write one or the other separately. If no 427 location is specified, newly created QuickTime tags are added in the 428 L<ItemList|Image::ExifTool::TagNames/QuickTime ItemList Tags> location if 429 possible, otherwise in 430 L<UserData|Image::ExifTool::TagNames/QuickTime UserData Tags>, and 431 finally in L<Keys|Image::ExifTool::TagNames/QuickTime Keys Tags>, 432 but this order may be changed by setting the PREFERRED level of the 433 appropriate table in the config file (see 434 L<example.config|../config.html#PREF> in the full distribution for an 435 example). Note that some tags with the same name but different ID's may 436 exist in the same location, but the family 7 group names may be used to 437 differentiate these. ExifTool currently writes only top-level metadata in 438 QuickTime-based files; it extracts other track-specific and timed metadata, 439 but can not yet edit tags in these locations (with the exception of 440 track-level date/time tags). 441 442 Alternate language tags may be accessed for 443 L<ItemList|Image::ExifTool::TagNames/QuickTime ItemList Tags> and 444 L<Keys|Image::ExifTool::TagNames/QuickTime Keys Tags> tags by adding 445 a 3-character ISO 639-2 language code and an optional ISO 3166-1 alpha 2 446 country code to the tag name (eg. "ItemList:Artist-deu" or 447 "ItemList::Artist-deu-DE"). Most 448 L<UserData|Image::ExifTool::TagNames/QuickTime UserData Tags> tags support a 449 language code, but without a country code. If no language code is specified 450 when writing, the default language is written and alternate languages for 451 the tag are deleted. Use the "und" language code to write the default 452 language without deleting alternate languages. Note that "eng" is treated 453 as a default language when reading, but not when writing. 454 455 According to the specification, integer-format QuickTime date/time tags 456 should be stored as UTC. Unfortunately, digital cameras often store local 457 time values instead (presumably because they don't know the time zone). For 458 this reason, by default ExifTool does not assume a time zone for these 459 values. However, if the L<QuickTimeUTC|../ExifTool.html#QuickTimeUTC> API option is set, then ExifTool will 460 assume these values are properly stored as UTC, and will convert them to 461 local time when extracting. 462 463 When writing string-based date/time tags, the system time zone is added if 464 the PrintConv option is enabled and no time zone is specified. This is 465 because Apple software may display crazy values if the time zone is missing 466 for some tags. 467 468 See 469 L<https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/> 470 for the official specification. 308 471 }, 309 472 Photoshop => q{ … … 314 477 Many Photoshop tags are marked as Unknown (indicated by a question mark 315 478 after the tag name) because the information they provide is not very useful 316 under normal circumstances I<[and because Adobe denied my application for 317 their file format documentation -- apparently open source software is too 318 big a concept for them]>. These unknown tags are not extracted unless the 319 Unknown (-u) option is used. 479 under normal circumstances. These unknown tags are not extracted unless the 480 L<Unknown|../ExifTool.html#Unknown> (-u) option is used. See 481 L<http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/> for the 482 official specification 483 484 Photoshop path tags (Tag ID's 0x7d0 to 0xbb5) are not defined by default, 485 but a config file included in the full ExifTool distribution 486 (config_files/photoshop_paths.config) contains the tag definitions to allow 487 access to this information. 320 488 }, 321 489 PrintIM => q{ 322 490 The format of the PrintIM information is known, however no PrintIM tags have 323 been decoded. Use the Unknown(-u) option to extract PrintIM information.491 been decoded. Use the L<Unknown|../ExifTool.html#Unknown> (-u) option to extract PrintIM information. 324 492 }, 325 493 GeoTiff => q{ 326 494 ExifTool extracts the following tags from GeoTIFF images. See 327 495 L<http://www.remotesensing.org/geotiff/spec/geotiffhome.html> for the 328 complete GeoTIFF specification. 496 complete GeoTIFF specification. Also included in the table below are 497 ChartTIFF tags (see L<http://www.charttiff.com/whitepapers.shtml>). GeoTIFF 498 tags are not writable individually, but they may be copied en mass via the 499 block tags GeoTiffDirectory, GeoTiffDoubleParams and GeoTiffAsciiParams. 329 500 }, 330 501 JFIF => q{ 331 502 The following information is extracted from the JPEG JFIF header. See 332 L<http://www.jpeg.org/public/jfif.pdf> for the JFIF 1.02 specification. 503 L<https://www.w3.org/Graphics/JPEG/jfif3.pdf> for the JFIF 1.02 504 specification. 333 505 }, 334 506 Kodak => q{ … … 350 522 Olympus => q{ 351 523 Tags 0x0000 through 0x0103 are used by some older Olympus cameras, and are 352 the same as Konica/Minolta tags. The Olympus tags are also used for Epson 353 and Agfa cameras. 524 the same as Konica/Minolta tags. These tags are also used for some models 525 from other brands such as Acer, BenQ, Epson, Hitachi, HP, Maginon, Minolta, 526 Pentax, Ricoh, Samsung, Sanyo, SeaLife, Sony, Supra and Vivitar. 354 527 }, 355 528 Panasonic => q{ … … 358 531 Pentax => q{ 359 532 These tags are used in Pentax/Asahi cameras. 360 },361 Sigma => q{362 These tags are used in Sigma/Foveon cameras.363 },364 Sony => q{365 The maker notes in images from most recent Sony camera models contain a366 wealth of information, but for some models very little has been decoded.367 Use the ExifTool Unknown (-u) or Verbose (-v) options to see information368 about the unknown tags. Also see the Minolta tags which are used by some369 Sony models.370 533 }, 371 534 CanonRaw => q{ … … 374 537 length of the information is preserved (and the new information is truncated 375 538 or padded as required) unless B<Writable> is C<resize>. Currently, only 376 JpgFromRaw and ThumbnailImage are allowed to change size. 539 JpgFromRaw and ThumbnailImage are allowed to change size. See 540 L<https://exiftool.org/canon_raw.html> for a description of the Canon CRW 541 format. 377 542 378 543 CRW images also support the addition of a CanonVRD trailer, which in turn … … 380 545 ExifTool is used to write XMP to a CRW image. 381 546 }, 547 NikonCustom => q{ 548 Unfortunately, the NikonCustom settings are stored in a binary data block 549 which changes from model to model. This means that significant effort must 550 be spent in decoding these for each model, usually requiring hundreds of 551 test images from a dedicated Nikon owner. For this reason, the NikonCustom 552 settings have not been decoded for all models. The tables below list the 553 custom settings for the currently supported models. 554 }, 382 555 Unknown => q{ 383 The following tags are decoded in unsupported maker notes. Use the Unknown556 The following tags are decoded in unsupported maker notes. Use the L<Unknown|../ExifTool.html#Unknown> 384 557 (-u) option to display other unknown tags. 385 558 }, … … 393 566 ExifTool supports reading and writing PDF documents up to version 1.7 394 567 extension level 3, including support for RC4, AES-128 and AES-256 395 encryption. A Passwordoption is provided to allow processing of568 encryption. A L<Password|../ExifTool.html#Password> option is provided to allow processing of 396 569 password-protected PDF files. 397 570 398 When writing PDF files, ExifTool uses an incremental update. This has the 399 advantages of being fast and reversible. The original PDF can be easily 400 recovered by deleting the C<PDF-update> pseudo-group (with 401 C<-PDF-update:all=> on the command line). But there are two main 571 ExifTool may be used to write native PDF and XMP metadata to PDF files. It 572 uses an incremental update technique that has the advantages of being both 573 fast and reversible. If ExifTool was used to modify a PDF file, the 574 original may be recovered by deleting the C<PDF-update> pseudo-group (with 575 C<-PDF-update:all=> on the command line). However, there are two main 402 576 disadvantages to this technique: 403 577 … … 407 581 2) All metadata edits are reversible. While this would normally be 408 582 considered an advantage, it is a potential security problem because old 409 information is never actually deleted from the file. 583 information is never actually deleted from the file. (However, after 584 running ExifTool the old information may be removed permanently using the 585 "qpdf" utility with this command: "qpdf --linearize in.pdf out.pdf".) 410 586 }, 411 587 DNG => q{ … … 425 601 }, 426 602 Extra => q{ 427 The extra tags represent extra information extracted or generated by 428 ExifTool that is not directly associated with another tag group. The three 429 writable "pseudo" tags (FileName, Directory and FileModifyDate) may be 430 written without the need to rewrite the file since their values are not 431 contained within the file data. These "pseudo" tags belong to the family 1 432 "System" group. 603 The extra tags provide extra features or extra information extracted or 604 generated by ExifTool that is not directly associated with another tag 605 group. The B<Group> column lists the family 1 group name when reading. 606 Tags with a "-" in this column are write-only. 607 608 Tags in the family 1 "System" group are referred to as "pseudo" tags because 609 they don't represent real metadata in the file. Instead, this information 610 is stored in the directory structure of the filesystem. The B<Writable> 611 System "pseudo" tags in this table may be written without modifying the file 612 itself. The TestName tag is used for dry-run testing before writing 613 FileName. 433 614 }, 434 615 Composite => q{ 435 616 The values of the composite tags are B<Derived From> the values of other 436 617 tags. These are convenience tags which are calculated after all other 437 information is extracted. 618 information is extracted. Only a few of these tags are writable directly, 619 the others are changed by writing the corresponding B<Derived From> tags. 620 User-defined Composite tags, also useful for custom-formatting of tag 621 values, may created via the L<ExifTool configuration file|../config.html>. 438 622 }, 439 623 Shortcuts => q{ … … 447 631 for more details. 448 632 }, 633 MWG => q{ 634 The Metadata Working Group (MWG) recommends techniques to allow certain 635 overlapping EXIF, IPTC and XMP tags to be reconciled when reading, and 636 synchronized when writing. The MWG Composite tags below are designed to aid 637 in the implementation of these recommendations. As well, the MWG defines 638 new XMP tags which are listed in the subsequent tables below. See 639 L<https://web.archive.org/web/20181006115950/http://www.metadataworkinggroup.org/specs/> 640 for the official MWG specification. 641 }, 642 MacOS => q{ 643 On MacOS systems, the there are additional MDItem and XAttr Finder tags that 644 may be extracted. These tags are not extracted by default -- they must be 645 specifically requested or enabled via an API option. (Except when reading 646 MacOS "._" files directly, see below.) 647 648 The tables below list some of the tags that may be extracted, but ExifTool 649 will extract all available information even for tags not listed. 650 651 Tags in these tables are referred to as "pseudo" tags because their 652 information is not stored in the file itself. As such, B<Writable> tags in 653 these tables may be changed without having to rewrite the file. 654 }, 449 655 PodTrailer => q{ 450 656 ~head1 NOTES … … 455 661 ~head1 AUTHOR 456 662 457 Copyright 2003-20 11, Phil Harvey (phil at owl.phy.queensu.ca)663 Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) 458 664 459 665 This library is free software; you can redistribute it and/or modify it … … 470 676 # notes for Shortcuts tags 471 677 my %shortcutNotes = ( 678 AllDates => q{ 679 contrary to the shortcut name, this represents only the common EXIF 680 date/time tags. To access all date/time tags, use Time:All instead 681 }, 472 682 MakerNotes => q{ 473 683 useful when copying tags between files to either copy the maker notes as a 474 684 block or prevent it from being copied 475 685 }, 686 ColorSpaceTags => q{ 687 standard tags which carry color space information. Useful for preserving 688 color space when deleting all other metadata 689 }, 476 690 CommonIFD0 => q{ 477 691 common metadata tags found in IFD0 of TIFF-format images. Used to simpify 478 deletion of all metadata from these images. See FAQ number 7 for details 692 deletion of all metadata from these images. See 693 L<FAQ number 7|../faq.html#Q7> for details 479 694 }, 480 695 Unsafe => q{ 481 "unsafe" tags in JPEG images which are normally not copied. Defined here 482 as a shortcut to use when rebuilding JPEG EXIF from scratch 696 I<Unsafe> tags in JPEG images which are normally not copied. Defined here 697 as a shortcut to use when rebuilding JPEG EXIF from scratch. See 698 L<FAQ number 20|../faq.html#Q20> for more information 699 }, 700 LargeTags => q{ 701 large binary data tags which may be excluded to reduce memory usage if 702 memory limitations are a problem 703 }, 704 'ls-l' => q{ 705 mimics columns shown by Unix "ls -l" command. Includes some tags which are 706 extracted only if the API L<SystemTags|../ExifTool.html#SystemTags> option 707 is enabled 483 708 }, 484 709 ); 485 710 486 711 487 488 # EXIF table tag ID's which are part of the EXIF 2.3 specification489 # (used only to add underlines in HTML version of EXIF Tag Table)490 my %exifSpec = (491 0x100 => 1, 0x212 => 1, 0x9204 => 1, 0xa217 => 1,492 0x101 => 1, 0x213 => 1, 0x9205 => 1, 0xa300 => 1,493 0x102 => 1, 0x214 => 1, 0x9206 => 1, 0xa301 => 1,494 0x103 => 1, 0x8298 => 1, 0x9207 => 1, 0xa302 => 1,495 0x106 => 1, 0x829a => 1, 0x9208 => 1, 0xa401 => 1,496 0x10e => 1, 0x829d => 1, 0x9209 => 1, 0xa402 => 1,497 0x10f => 1, 0x8769 => 1, 0x920a => 1, 0xa403 => 1,498 0x110 => 1, 0x8822 => 1, 0x9214 => 1, 0xa404 => 1,499 0x111 => 1, 0x8824 => 1, 0x927c => 1, 0xa405 => 1,500 0x112 => 1, 0x8825 => 1, 0x9286 => 1, 0xa406 => 1,501 0x115 => 1, 0x8827 => 1, 0x9290 => 1, 0xa407 => 1,502 0x116 => 1, 0x8828 => 1, 0x9291 => 1, 0xa408 => 1,503 0x117 => 1, 0x8830 => 1, 0x9292 => 1, 0xa409 => 1,504 0x11a => 1, 0x8831 => 1, 0xa000 => 1, 0xa40a => 1,505 0x11b => 1, 0x8832 => 1, 0xa001 => 1, 0xa40b => 1,506 0x11c => 1, 0x8833 => 1, 0xa002 => 1, 0xa40c => 1,507 0x128 => 1, 0x8834 => 1, 0xa003 => 1, 0xa420 => 1,508 0x12d => 1, 0x8835 => 1, 0xa004 => 1, 0xa430 => 1,509 0x131 => 1, 0x9000 => 1, 0xa005 => 1, 0xa431 => 1,510 0x132 => 1, 0x9003 => 1, 0xa20b => 1, 0xa432 => 1,511 0x13b => 1, 0x9004 => 1, 0xa20c => 1, 0xa433 => 1,512 0x13e => 1, 0x9101 => 1, 0xa20e => 1, 0xa434 => 1,513 0x13f => 1, 0x9102 => 1, 0xa20f => 1, 0xa435 => 1,514 0x201 => 1, 0x9201 => 1, 0xa210 => 1,515 0x202 => 1, 0x9202 => 1, 0xa214 => 1,516 0x211 => 1, 0x9203 => 1, 0xa215 => 1,517 );518 712 # same thing for RIFF INFO tags found in the EXIF spec 519 713 my %riffSpec = ( … … 523 717 ICMT => 1, IDPI => 1, IMED => 1, ISFT => 1, 524 718 ICOP => 1, IENG => 1, INAM => 1, ISHP => 1, 719 ); 720 # same thing for XMP namespaces 721 my %xmpSpec = ( 722 aux => 1, 'x' => 1, 723 crs => 1, xmp => 1, 724 dc => 1, xmpBJ => 1, 725 exif => 1, xmpDM => 1, 726 pdf => 1, xmpMM => 1, 727 pdfx => 1, xmpNote => 1, 728 photoshop => 1, xmpRights => 1, 729 tiff => 1, xmpTPg => 1, 525 730 ); 526 731 … … 534 739 my $class = ref($that) || $that || 'Image::ExifTool::BuildTagLookup'; 535 740 my $self = bless {}, $class; 536 my (%subdirs, %isShortcut , %allStructs);741 my (%subdirs, %isShortcut); 537 742 my %count = ( 538 743 'unique tag names' => 0, … … 543 748 # 544 749 my (%tagNameInfo, %id, %longID, %longName, %shortName, %tableNum, 545 %tagLookup, %tagExists, %tableWritable, %sepTable, %structs, 546 %compositeModules, %isPlugin, %flattened, %structLookup); 750 %tagLookup, %tagExists, %noLookup, %tableWritable, %sepTable, %case, 751 %structs, %compositeModules, %isPlugin, %flattened, %structLookup, 752 @writePseudo); 547 753 $self->{TAG_NAME_INFO} = \%tagNameInfo; 548 754 $self->{ID_LOOKUP} = \%id; … … 560 766 $self->{COMPOSITE_MODULES} = \%compositeModules; 561 767 $self->{COUNT} = \%count; 768 $self->{WRITE_PSEUDO} = \@writePseudo; 562 769 563 770 Image::ExifTool::LoadAllTables(); … … 566 773 push @tableNames, 'Image::ExifTool::Shortcuts::Main'; 567 774 # add plug-in modules last 568 $Image::ExifTool::documentOnly = 1; # (don't really load them)569 775 foreach (@pluginTables) { 570 776 push @tableNames, $_; … … 573 779 574 780 my $tableNum = 0; 575 my $e xifTool= new Image::ExifTool;781 my $et = new Image::ExifTool; 576 782 my ($tableName, $tag); 577 783 # create lookup for short table names … … 583 789 $short =~ s/^(.+)Tags$/\u$1/ unless $short eq 'Nikon AVITags'; 584 790 $short =~ s/^Exif\b/EXIF/; 791 # change underlines to dashes in XMP-mwg group names 792 # (we used underlines just because Perl variables can't contain dashes) 793 $short =~ s/^XMP mwg_/XMP mwg-/; 585 794 $shortName{$tableName} = $short; # remember short name 586 795 $tableNum{$tableName} = $tableNum++; … … 622 831 $longName{$tableName} = 0; 623 832 # save all tag names 624 my ($tagID, $binaryTable, $noID, $ isIPTC, $isXMP);833 my ($tagID, $binaryTable, $noID, $hexID, $isIPTC, $isXMP); 625 834 $isIPTC = 1 if $writeProc and $writeProc eq \&Image::ExifTool::IPTC::WriteIPTC; 626 835 # generate flattened tag names for structure fields if this is an XMP table 627 836 if ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP') { 837 Image::ExifTool::XMP::AddFlattenedTags($table); 628 838 $isXMP = 1; 629 foreach $tagID (TagTableKeys($table)) {630 my $tagInfo = $$table{$tagID};631 next unless ref $tagInfo eq 'HASH' and $$tagInfo{Struct};632 Image::ExifTool::XMP::AddFlattenedTags($table, $tagID);633 }634 839 } 635 840 $noID = 1 if $isXMP or $short =~ /^(Shortcuts|ASF.*)$/ or $$vars{NO_ID}; 841 $hexID = $$vars{HEX_ID}; 636 842 my $processBinaryData = ($$table{PROCESS_PROC} and ( 637 843 $$table{PROCESS_PROC} eq \&Image::ExifTool::ProcessBinaryData or 638 $$table{PROCESS_PROC} eq \&Image::ExifTool::Nikon::ProcessNikonEncrypted)); 844 $$table{PROCESS_PROC} eq \&Image::ExifTool::Nikon::ProcessNikonEncrypted or 845 $$table{PROCESS_PROC} eq \&Image::ExifTool::Sony::ProcessEnciphered)); 639 846 if ($$vars{ID_LABEL} or $processBinaryData) { 847 my $s = $$table{FORMAT} ? Image::ExifTool::FormatSize($$table{FORMAT}) || 1 : 1; 640 848 $binaryTable = 1; 641 $id{$tableName} = $$vars{ID_LABEL} || 'Index';849 $id{$tableName} = $$vars{ID_LABEL} || "Index$s"; 642 850 } elsif ($isIPTC and $$table{PROCESS_PROC}) { #only the main IPTC table has a PROCESS_PROC 643 851 $id{$tableName} = 'Record'; … … 646 854 } 647 855 $caseInsensitive = $isXMP; 856 $numbersFirst = 2; 648 857 $numbersFirst = -1 if $$table{VARS} and $$table{VARS}{ALPHA_FIRST}; 649 my @keys = sort NumbersFirstTagTableKeys($table);858 my @keys = SortedTagTableKeys($table); 650 859 $numbersFirst = 1; 651 860 my $defFormat = $table->{FORMAT}; … … 654 863 655 864 TagID: foreach $tagID (@keys) { 656 my ($tagInfo, @tagNames, $subdir, $format,@values);865 my ($tagInfo, @tagNames, $subdir, @values); 657 866 my (@infoArray, @require, @writeGroup, @writable); 658 867 if ($shortcut) { … … 672 881 @infoArray = GetTagInfoList($table,$tagID); 673 882 } 674 $format = $defFormat;675 883 foreach $tagInfo (@infoArray) { 676 884 my $name = $$tagInfo{Name}; 677 # validate Name 678 warn "Warning: Invalid tag name $short '$name'\n" if $name !~ /^[-\w]+$/; 885 if ($$tagInfo{WritePseudo}) { 886 push @writePseudo, $name; 887 warn "Writable pseudo tag $name is not protected!\n" unless $$tagInfo{Protected}; 888 } 889 unless ($$tagInfo{SubDirectory} or $$tagInfo{Struct}) { 890 my $lc = lc $name; 891 warn "Different case for $tableName $name $case{$lc}\n" if $case{$lc} and $case{$lc} ne $name; 892 $case{$lc} = $name; 893 } 894 my $format = $$tagInfo{Format}; 895 # check TagID's to make sure they don't start with 'ID-' 896 my @grps = $et->GetGroup($tagInfo); 897 foreach (@grps) { 898 warn "Group name starts with 'ID-' for $short $name\n" if /^ID-/i; 899 } 900 # validate Name (must not start with a digit or else XML output will not be valid; 901 # must not start with a dash or exiftool command line may get confused) 902 if ($name !~ /^[_A-Za-z][-\w]+$/ and 903 # single-character subdirectory names are allowed 904 (not $$tagInfo{SubDirectory} or $name !~ /^[_A-Za-z]$/)) 905 { 906 warn "Warning: Invalid tag name $short '${name}'\n"; 907 } 908 # validate list type 909 if ($$tagInfo{List} and $$tagInfo{List} !~ /^(1|Alt|Bag|Seq|array|string)$/) { 910 warn "Warning: Unknown List type ($$tagInfo{List}) for $name in $tableName\n"; 911 } 679 912 # accumulate information for consistency check of BinaryData tables 680 913 if ($processBinaryData and $$table{WRITABLE}) { 914 # can't currently write tag if Condition accesses $valPt 915 if ($$tagInfo{Condition} and not $$tagInfo{SubDirectory} and 916 $$tagInfo{Condition} =~ /\$valPt/ and 917 ($$tagInfo{Writable} or not defined $$tagInfo{Writable})) 918 { 919 warn "Warning: Tag not writable due to Condition - $short $name\n"; 920 } 681 921 $isOffset{$tagID} = $name if $$tagInfo{IsOffset}; 682 922 $hasSubdir{$tagID} = $name if $$tagInfo{SubDirectory}; 683 923 # require DATAMEMBER for writable var-format tags, Hook and DataMember tags 684 if ($ $tagInfo{Format} and $$tagInfo{Format}=~ /^var_/) {924 if ($format and $format =~ /^var_/) { 685 925 $datamember{$tagID} = $name; 686 926 unless (defined $$tagInfo{Writable} and not $$tagInfo{Writable}) { 687 927 warn "Warning: Var-format tag is writable - $short $name\n" 928 } 929 # also need DATAMEMBER for tags used in length of var-sized value 930 while ($format =~ /\$val\{(.*?)\}/g) { 931 my $id = $1; 932 $id = hex($id) if $id =~ /^0x/; # convert from hex if necessary 933 $datamember{$id} = $$table{$id}{Name} if ref $$table{$id} eq 'HASH'; 934 unless ($datamember{$id}) { 935 warn "Warning: Unknown ID ($id) used in Format - $short $name\n"; 936 } 688 937 } 689 938 } elsif ($$tagInfo{Hook} or ($$tagInfo{RawConv} and … … 692 941 $datamember{$tagID} = $name; 693 942 } 943 if ($format and $format =~ /\$val\{/ and 944 ($$tagInfo{Writable} or not defined $$tagInfo{Writable})) 945 { 946 warn "Warning: \$var{} used in Format of writable tag - $short $name\n" 947 } 694 948 } 695 949 if ($$tagInfo{Hidden}) { 696 warn "Warning: Hidden tag in list - $short $name\n" if @infoArray > 1; 697 next TagID; 950 if ($tagInfo == $infoArray[0]) { 951 next TagID; # hide all tags with this ID if first tag in list is hidden 952 } else { 953 next; # only hide this tag 954 } 698 955 } 699 956 my $writable; … … 702 959 # validate Writable 703 960 unless ($formatOK{$writable} or ($writable =~ /(.*)\[/ and $formatOK{$1})) { 704 warn "Warning: Unknown Writable ($writable) for$short $name\n",961 warn "Warning: Unknown Writable ($writable) - $short $name\n", 705 962 } 706 963 } elsif (not $$tagInfo{SubDirectory}) { 707 964 $writable = $$table{WRITABLE}; 708 965 } 966 # in general, we can't write unless we have a WRITE_PROC 967 if ($writable and not ($$table{WRITE_PROC} or $tableName =~ /Shortcuts/ or $writable eq '2')) { 968 undef $writable; 969 } 709 970 # validate some characteristics of obvious date/time tags 971 my @g = $et->GetGroup($tagInfo); 972 if ($$tagInfo{List} and $g[2] eq 'Time' and $writable and not $$tagInfo{Protected} and 973 not $$tagInfo{PrintConvInv}) 974 { 975 # (this is a problem because shifting Time:All would create a new list entry) 976 warn "Writable List-type Time tag $g[1]:$name has no PrintConvInv and is not Protected!\n"; 977 } 710 978 if ($$tagInfo{PrintConv} and $$tagInfo{PrintConv} eq '$self->ConvertDateTime($val)') { 711 my @g = $exifTool->GetGroup($tagInfo);712 979 warn "$short $name should be in 'Time' group!\n" unless $g[2] eq 'Time'; 713 if ($writable and not $$tagInfo{Shift} and $g[0] ne 'Composite' and 714 $short ne 'PostScript') 980 if ($writable and not defined $$tagInfo{Shift} and $short ne 'PostScript') { 981 warn "$short $name is not shiftable!\n"; 982 } 983 if ($writable and (not $$tagInfo{PrintConvInv} or 984 $$tagInfo{PrintConvInv} !~ /InverseDateTime/)) 715 985 { 716 warn "$short $name is not shiftable!\n";986 warn "$short $name missing InverseDateTime PrintConvInv\n"; 717 987 } 718 988 } elsif ($name =~ /DateTime(?!Stamp)/ and (not $$tagInfo{Groups}{2} or 719 989 $$tagInfo{Groups}{2} ne 'Time') and $short ne 'DICOM') { 720 990 warn "$short $name should be in 'Time' group!\n"; 991 } 992 if ($name eq 'DateTimeOriginal' and (not $$tagInfo{Description} or 993 $$tagInfo{Description} ne 'Date/Time Original')) 994 { 995 warn "Need Description for $short DateTimeOriginal\n"; 721 996 } 722 997 # validate Description (can't contain special characters) … … 728 1003 warn "$name description contains special characters!\n"; 729 1004 } 730 # validate SubIFD flag 731 my $subdir = $$tagInfo{SubDirectory}; 1005 # generate structure lookup 732 1006 my $struct = $$tagInfo{Struct}; 733 1007 my $strTable; … … 749 1023 $strTable = $structLookup{$struct}; 750 1024 unless ($strTable) { 751 warn "Missing XMP $struct structure!\n"; 1025 $struct = "XMP $struct" unless $struct =~ / /; 1026 warn "Missing $struct structure!\n"; 752 1027 undef $struct; 753 1028 } 754 1029 } 755 my $isSub = ($subdir and $$subdir{Start} and $$subdir{Start} eq '$val'); 1030 # validate SubIFD flag 1031 my $subdir = $$tagInfo{SubDirectory}; 1032 my $isSub = ($subdir and $$subdir{Start} and $$subdir{Start} =~ /\$val\b/); 756 1033 if ($$tagInfo{SubIFD}) { 757 1034 warn "Warning: Wrong SubDirectory Start for SubIFD tag - $short $name\n" unless $isSub; … … 762 1039 my $note = $$tagInfo{Notes}; 763 1040 # remove leading/trailing blank lines 764 $note =~ s/ (^\s+|\s+$)//g;1041 $note =~ s/^\s+//; $note =~ s/\s+$//; 765 1042 # remove leading/trailing spaces on each line 766 1043 $note =~ s/(^[ \t]+|[ \t]+$)//mg; 767 1044 push @values, "($note)"; 768 } elsif ($isXMP and lc $tagID ne lc $name) { 769 # add note about different XMP Tag ID 770 if ($$tagInfo{RootTagInfo}) { 771 push @values, "($tagID)"; 1045 } 1046 if ($isXMP and (lc $tagID ne lc $name or $$tagInfo{NotFlat})) { 1047 my $note; 1048 if ($$tagInfo{NotFlat}) { 1049 $note = 'NOT a flattened tag!'; 772 1050 } else { 773 push @values,"(called $tagID by the spec)"; 1051 # add note about different XMP Tag ID 1052 $note = $$tagInfo{RootTagInfo} ? $tagID : "called $tagID by the spec"; 1053 } 1054 if ($$tagInfo{Notes}) { 1055 $values[-1] =~ s/^\(/($note; /; 1056 } else { 1057 push @values, "($note)"; 774 1058 } 775 1059 } 776 1060 my $writeGroup; 777 $writeGroup = $$tagInfo{WriteGroup}; 1061 if ($short eq 'Extra') { 1062 $writeGroup = $$tagInfo{WriteOnly} ? '-' : $g[1]; 1063 } else { 1064 $writeGroup = $$tagInfo{WriteGroup}; 1065 } 778 1066 unless ($writeGroup) { 779 1067 $writeGroup = $$table{WRITE_GROUP} if $writable; 780 1068 $writeGroup = '-' unless $writeGroup; 781 1069 } 782 if (defined $$tagInfo{Format}) { 783 $format = $$tagInfo{Format}; 1070 if (defined $format) { 784 1071 # validate Format 785 1072 unless ($formatOK{$format} or $short eq 'PICT' or … … 788 1075 warn "Warning: Unknown Format ($format) for $short $name\n"; 789 1076 } 1077 } else { 1078 $format = $defFormat; 790 1079 } 791 1080 if ($subdir) { … … 810 1099 if ($$tagInfo{Mask}) { 811 1100 my $val = $$tagInfo{Mask}; 812 push @values, sprintf('[Mask 0x%.2x]',$val); 813 $$tagInfo{PrintHex} = 1 unless defined $$tagInfo{PrintHex}; 1101 my $bsh = $$tagInfo{BitShift}; 1102 if ($bsh) { 1103 push @values, sprintf('[val >> %d & 0x%x]',$bsh,$val>>$bsh); 1104 } else { 1105 push @values, sprintf('[val & 0x%x]',$val); 1106 } 814 1107 # verify that all values are within the mask 815 1108 if (ref $printConv eq 'HASH') { 816 # convert mask if necessary 817 if ($$tagInfo{ValueConv}) { 818 my $v = eval $$tagInfo{ValueConv}; 819 $val = $v if defined $v; 820 } 1109 $val >>= $$tagInfo{BitShift}; 821 1110 foreach (keys %$printConv) { 822 1111 next if $_ !~ /^\d+$/ or ($_ & $val) == $_; … … 827 1116 } 828 1117 if (ref($printConv) =~ /^(HASH|ARRAY)$/) { 829 my (@printConvList, @indexList, $index );1118 my (@printConvList, @indexList, $index, $valueConvHash); 830 1119 if (ref $printConv eq 'ARRAY') { 831 1120 for ($index=0; $index<@$printConv; ++$index) { 832 next if ref $$printConv[$index] ne 'HASH'; 833 next unless %{$$printConv[$index]}; 834 push @printConvList, $$printConv[$index]; 835 push @indexList, $index; 1121 if (ref $$printConv[$index] eq 'HASH') { 1122 next unless %{$$printConv[$index]}; 1123 push @printConvList, $$printConv[$index]; 1124 push @indexList, $index; 1125 } elsif ($$printConv[$index] and $$printConv[$index] eq 'REPEAT' and $index) { 1126 push @printConvList, $$printConv[$index-1]; 1127 push @indexList, 'N'; 1128 } else { 1129 next; 1130 } 836 1131 # collapse values with identical PrintConv's 837 1132 if (@printConvList >= 2 and $printConvList[-1] eq $printConvList[-2]) { … … 847 1142 $printConv = shift @printConvList; 848 1143 $index = shift @indexList; 1144 } else { 1145 $valueConvHash = $$tagInfo{ValueConv} if ref $$tagInfo{ValueConv} eq 'HASH'; 849 1146 } 850 1147 while (defined $printConv) { … … 858 1155 my ($i, @i, $rngStart); 859 1156 for ($i=0; $i<@$idx; ++$i) { 860 if ($i < @$idx - 1 and $$idx[$i+1] == $$idx[$i] + 1) {861 $rngStart = $ iunless defined $rngStart;1157 if ($i < @$idx - 1 and ($$idx[$i+1] eq 'N' or $$idx[$i+1] == $$idx[$i] + 1)) { 1158 $rngStart = $$idx[$i] unless defined $rngStart; 862 1159 next; 863 1160 } 864 push @i, defined($rngStart) ? "$rngStart-$i" : $i;1161 push @i, (defined($rngStart) ? "$rngStart-" : '') . $$idx[$i]; 865 1162 } 866 1163 ($idx = join ', ', @i) =~ s/(.*),/$1 and/; … … 890 1187 } else { 891 1188 $caseInsensitive = 0; 892 my @pk = sort NumbersFirst keys %$printConv; 1189 my @pk; 1190 if ($$tagInfo{PrintSort}) { 1191 @pk = sort { NumbersFirst($$printConv{$a},$$printConv{$b}) } keys %$printConv; 1192 } else { 1193 @pk = sort { NumbersFirst($a,$b) } keys %$printConv; 1194 } 893 1195 my $n = scalar @values; 894 my ($bits, $ cols, $i);1196 my ($bits, $i, $v); 895 1197 foreach (@pk) { 896 next if $_ eq '' ;1198 next if $_ eq '' and $$printConv{$_} eq ''; 897 1199 $_ eq 'BITMASK' and $bits = $$printConv{$_}, next; 898 1200 $_ eq 'OTHER' and next; 899 1201 my $index; 900 if (($$tagInfo{PrintHex} or $$printConv{BITMASK}) and /^\d+$/) { 901 $index = sprintf('0x%x',$_); 1202 if (($$tagInfo{PrintHex} or $$printConv{BITMASK}) and /^-?\d+$/) { 1203 my $dig = $$tagInfo{PrintHex} || 1; 1204 if ($_ >= 0) { 1205 $index = sprintf('0x%.*x', $dig, $_); 1206 } elsif ($format and $format =~ /int(16|32)/) { 1207 # mask off unused bits of signed integer hex value 1208 my $mask = { 16 => 0xffff, 32 => 0xffffffff }->{$1}; 1209 $index = sprintf('0x%.*x', $dig, $_ & $mask); 1210 } else { 1211 $index = $_; 1212 } 902 1213 } elsif (/^[+-]?(?=\d|\.\d)\d*(\.\d*)?$/ and not $$tagInfo{PrintString}) { 903 1214 $index = $_; … … 908 1219 $index = qq{"$index"}; 909 1220 } else { 910 $index = qq{'$ index'};1221 $index = qq{'${index}'}; 911 1222 } 912 1223 } 913 1224 push @values, "$index = " . $$printConv{$_}; 1225 if ($valueConvHash) { 1226 foreach $v (keys %$valueConvHash) { 1227 next unless $$valueConvHash{$v} eq $_; 1228 $values[-1] = "$v => " . $values[-1]; 1229 last; 1230 } 1231 } 914 1232 # validate all PrintConv values 915 1233 if ($$printConv{$_} =~ /[\0-\x1f\x7f-\xff]/) { … … 918 1236 } 919 1237 if ($bits) { 920 my @pk = sort NumbersFirstkeys %$bits;1238 my @pk = sort { NumbersFirst($a,$b) } keys %$bits; 921 1239 foreach (@pk) { 922 1240 push @values, "Bit $_ = " . $$bits{$_}; … … 924 1242 } 925 1243 # organize values into columns if specified 926 if (defined($cols = $$tagInfo{PrintConvColumns})) { 1244 my $cols = $$tagInfo{PrintConvColumns}; 1245 if (not $cols and scalar(@values) - $n >= 6) { 1246 # do columns if more than 6 short entries 1247 my $maxLen = 0; 1248 for ($i=$n; $i<@values; ++$i) { 1249 next unless $maxLen < length $values[$i]; 1250 $maxLen = length $values[$i]; 1251 } 1252 my $num = scalar(@values) - $n; 1253 $cols = int(50 / ($maxLen + 2)); # (50 chars max width) 1254 # have 3 rows minimum 1255 --$cols while $cols and $num / $cols < 3; 1256 } 1257 if ($cols) { 927 1258 my @new = splice @values, $n; 928 1259 my $v = '[!HTML]<table class=cols><tr>'; 929 1260 my $rows = int((scalar(@new) + $cols - 1) / $cols); 930 for ($n=0; $n<@new; $n+=$rows) {1261 for ($n=0; ;) { 931 1262 $v .= "\n <td>"; 932 1263 for ($i=0; $i<$rows and $n+$i<@new; ++$i) { … … 934 1265 $v .= EscapeHTML($new[$n+$i]); 935 1266 } 936 $v .= '</td><td> </td>'; 1267 $v .= '</td>'; 1268 last if ($n += $rows) >= @new; 1269 $v .= '<td> </td>'; # add spaces between columns 937 1270 } 938 1271 push @values, $v . "</tr></table>\n"; … … 950 1283 warn $@; 951 1284 } else { 952 my @pk = sort NumbersFirstkeys %$bits;1285 my @pk = sort { NumbersFirst($a,$b) } keys %$bits; 953 1286 foreach (@pk) { 954 1287 push @values, "Bit $_ = " . $$bits{$_}; … … 957 1290 } 958 1291 if ($subdir and not $$tagInfo{SeparateTable}) { 959 # subdirectories are only writable if specified explicitly 960 my $tw = $$tagInfo{Writable}; 961 $writable = '-' . ($tw ? $writable : ''); 962 $writable .= '!' if $tw and ($$tagInfo{Protected} || 0) & 0x01; 1292 if ($writable) { 1293 # subdirectories are only writable if specified explicitly 1294 my $tw = $$tagInfo{Writable}; 1295 $writable = 'yes' if $tw and $writable eq '1' or $writable eq '2'; 1296 $writable = '-' . ($tw ? $writable : ''); 1297 $writable .= '!' if $tw and ($$tagInfo{Protected} || 0) & 0x01; 1298 $writable .= '+' if $$tagInfo{List}; 1299 if (defined $$tagInfo{Permanent}) { 1300 $writable .= '^' unless $$tagInfo{Permanent}; 1301 } elsif (defined $$table{PERMANENT}) { 1302 $writable .= '^' unless $$table{PERMANENT}; 1303 } 1304 } else { 1305 $writable = '-'; 1306 } 963 1307 } else { 964 1308 # not writable if we can't do the inverse conversions … … 978 1322 } 979 1323 if (not $writable) { 980 $writable = ' N';1324 $writable = 'no'; 981 1325 } else { 982 $writable eq '1' and $writable = $format ? $format : 'Y';1326 $writable = $format ? $format : 'yes' if $writable eq '1' or $writable eq '2'; 983 1327 my $count = $$tagInfo{Count} || 1; 984 1328 # adjust count to Writable size if different than Format … … 1008 1352 $writable .= '+' if $$tagInfo{List}; 1009 1353 $writable .= ':' if $$tagInfo{Mandatory}; 1354 if (defined $$tagInfo{Permanent}) { 1355 $writable .= '^' unless $$tagInfo{Permanent}; 1356 } elsif (defined $$table{PERMANENT}) { 1357 $writable .= '^' unless $$table{PERMANENT}; 1358 } 1010 1359 # separate tables link like subdirectories (flagged with leading '-') 1011 1360 $writable = "-$writable" if $subdir; … … 1028 1377 } 1029 1378 # 1030 # add this tag to the tag lookup unless PROCESS_PROC is 0or shortcut or plug-in tag1379 # add this tag to the tag lookup unless NO_LOOKUP is set or shortcut or plug-in tag 1031 1380 # 1032 1381 next if $shortcut or $isPlugin; 1033 next if defined $$table{PROCESS_PROC} and not $$table{PROCESS_PROC}; 1034 # count our tags 1382 # count tags 1035 1383 if ($$tagInfo{SubDirectory}) { 1384 next if $$vars{NO_LOOKUP}; 1036 1385 $subdirs{$lcName} or $subdirs{$lcName} = 0; 1037 1386 ++$subdirs{$lcName}; 1038 1387 } else { 1039 1388 ++$count{'total tags'}; 1040 unless ($tagExists{$lcName} and (not $subdirs{$lcName} or $subdirs{$lcName} == $tagExists{$lcName})) { 1041 ++$count{'unique tag names'}; 1042 } 1389 unless ($tagExists{$lcName} and 1390 (not $subdirs{$lcName} or $subdirs{$lcName} == $tagExists{$lcName})) 1391 { 1392 ++$count{'unique tag names'} unless $noLookup{$lcName}; 1393 } 1394 # don't add to tag lookup if specified 1395 $$vars{NO_LOOKUP} and $noLookup{$lcName} = 1, next; 1043 1396 } 1044 1397 $tagExists{$lcName} or $tagExists{$lcName} = 0; … … 1071 1424 $tableWritable{$tableName} = 1; 1072 1425 $tagLookup{$lcName}->{$tableNum} = $tagIDs; 1073 if ($short eq 'Composite' and $$tagInfo{Module}) { 1074 $compositeModules{$lcName} = $$tagInfo{Module}; 1075 } 1426 # keep track of extra modules needed for Composite tags 1427 $compositeModules{$lcName} = $$tagInfo{Module} if $$tagInfo{Module}; 1076 1428 } 1077 1429 # … … 1079 1431 # 1080 1432 my $tagIDstr; 1081 if ($tagID =~ /^\d+(\.\d+)?$/) { 1082 if ($1 or $binaryTable or $isIPTC or ($short =~ /^CanonCustom/ and $tagID < 256)) { 1083 if ($tagID < 0x10000) { 1084 $tagIDstr = $tagID; 1085 } else { 1086 $tagIDstr = sprintf('0x%.8x',$tagID); 1087 } 1433 if ($tagID =~ /^(-)?\d+(\.\d+)?$/) { 1434 if ($1) { 1435 $tagIDstr = $tagID; 1436 } elsif (defined $hexID) { 1437 $tagIDstr = $hexID ? sprintf('0x%.4x',$tagID) : $tagID; 1438 } elsif (not $2 and not $binaryTable and not $isIPTC and 1439 not ($short =~ /^CanonCustom/ and $tagID < 256)) 1440 { 1441 $tagIDstr = sprintf('0x%.4x',$tagID); 1442 } elsif ($tagID < 0x10000) { 1443 $tagIDstr = $tagID; 1088 1444 } else { 1089 $tagIDstr = sprintf('0x%. 4x',$tagID);1445 $tagIDstr = sprintf('0x%.8x',$tagID); 1090 1446 } 1091 1447 } elsif ($short eq 'DICOM') { 1092 1448 ($tagIDstr = $tagID) =~ s/_/,/; 1449 } elsif ($tagID =~ /^0x([0-9a-f]+)\.(\d+)$/) { # DR4 tags like '0x20500.0' 1450 $tagIDstr = $tagID; 1093 1451 } else { 1094 1452 # convert non-printable characters to hex escape sequences … … 1098 1456 $tagIDstr = qq{"$tagID"}; 1099 1457 } else { 1100 $tagIDstr = "'$ tagID'";1458 $tagIDstr = "'${tagID}'"; 1101 1459 } 1102 1460 } … … 1122 1480 foreach $tagID (@{$$table{$var}}) { 1123 1481 $$hash{$tagID} and delete($$hash{$tagID}), next; 1124 warn "Warning: Extra $var for $short tag $tagID\n"; 1482 warn sprintf("Warning: Extra %s for %s tag %d (0x%.4x)\n", 1483 $var, $short, $tagID, $tagID); 1125 1484 } 1126 1485 } 1127 1486 foreach $tagID (sort keys %$hash) { 1128 warn "Warning: Missing $var for $short $$hash{$tagID}\n"; 1487 warn sprintf("Warning: Missing %s for %s %s, tag %d (0x%.4x)\n", 1488 $var, $short, $$hash{$tagID}, $tagID, $tagID); 1129 1489 } 1130 1490 } … … 1135 1495 foreach $strName (keys %structs) { 1136 1496 my $struct = $structLookup{$strName}; 1137 my $info = $tagNameInfo{"XMP $strName Struct"} = [ ]; 1497 my $fullName = ($strName =~ / / ? '' : 'XMP ') . "$strName Struct"; 1498 my $info = $tagNameInfo{$fullName} = [ ]; 1138 1499 my $tag; 1139 1500 foreach $tag (sort keys %$struct) { 1140 1501 my $tagInfo = $$struct{$tag}; 1141 next unless ref $tagInfo eq 'HASH'; 1502 next unless ref $tagInfo eq 'HASH' and $tag ne 'NAMESPACE' and $tag ne 'GROUPS'; 1503 warn "WARNING: $strName Struct containes $tag\n" if $Image::ExifTool::specialTags{$tag}; 1142 1504 my $writable = $$tagInfo{Writable}; 1143 1505 my @vals; … … 1154 1516 } 1155 1517 $writable .= '+' if $$tagInfo{List}; 1518 push @vals, "($$tagInfo{Notes})" if $$tagInfo{Notes}; 1519 # handle PrintConv lookups in Structure elements 1520 my $printConv = $$tagInfo{PrintConv}; 1521 if (ref $printConv eq 'HASH') { 1522 foreach (sort keys %$printConv) { 1523 next if /^(OTHER|BITMASK)$/; 1524 push @vals, "$_ = $$printConv{$_}"; 1525 } 1526 } 1156 1527 push @$info, [ 1157 1528 $tag, … … 1169 1540 # Rewrite this file to build the lookup tables 1170 1541 # Inputs: 0) BuildTagLookup object reference 1171 # 1) output tag lookup module name ( ie. 'lib/Image/ExifTool/TagLookup.pm')1542 # 1) output tag lookup module name (eg. 'lib/Image/ExifTool/TagLookup.pm') 1172 1543 # Returns: true on success 1173 1544 sub WriteTagLookup($$) … … 1210 1581 foreach $tableName (@tableNames) { 1211 1582 if ($$tableWritable{$tableName}) { 1212 print OUTFILE "\t'$ tableName',\n";1583 print OUTFILE "\t'${tableName}',\n"; 1213 1584 $wrNum{$count} = $num++; 1214 1585 } … … 1223 1594 next unless $$tagLookup{$tag}; 1224 1595 my $n = scalar keys %{$$tagLookup{$tag}}; 1225 warn "Warning: $n writable '$ tag' tags!\n" if $n > 1;1596 warn "Warning: $n writable '${tag}' tags!\n" if $n > 1; 1226 1597 } 1227 1598 print OUTFILE ");\n\n# lookup for all writable tags\nmy \%tagLookup = (\n"; 1228 1599 foreach $tag (sort keys %$tagLookup) { 1229 print OUTFILE "\t'$ tag' => { ";1600 print OUTFILE "\t'${tag}' => { "; 1230 1601 my @tableNums = sort { $a <=> $b } keys %{$$tagLookup{$tag}}; 1231 1602 my (@entries, $tableNum); … … 1249 1620 # reference to root structure ID must come first in lookup 1250 1621 # (so we can generate the flattened tags just before we need them) 1251 unshift @tagIDs, "\\'$ rootID'" if $rootID;1622 unshift @tagIDs, "\\'${rootID}'" if $rootID; 1252 1623 $entry = '[' . join(',', @tagIDs) . ']'; 1253 1624 } elsif ($tagID =~ /^\d+$/) { 1254 1625 $entry = sprintf('0x%x',$tagID); 1255 1626 } else { 1256 $entry = "'$tagID'"; 1627 my $quot = "'"; 1628 # escape non-printable characters in tag ID if necessary 1629 $quot = '"' if $tagID =~ s/[\x00-\x1f,\x7f-\xff]/sprintf('\\x%.2x',ord($&))/ge; 1630 $entry = "$quot${tagID}$quot"; 1257 1631 } 1258 1632 my $wrNum = $wrNum{$tableNum}; … … 1269 1643 foreach $tag (sort keys %$tagExists) { 1270 1644 next if $$tagLookup{$tag}; 1271 print OUTFILE "\t'$ tag' => 1,\n";1645 print OUTFILE "\t'${tag}' => 1,\n"; 1272 1646 } 1273 1647 # … … 1278 1652 print OUTFILE "my \%compositeModules = (\n"; 1279 1653 foreach (sort keys %$compositeModules) { 1280 print OUTFILE "\t'$ _' => '$$compositeModules{$_}',\n";1654 print OUTFILE "\t'${_}' => '$$compositeModules{$_}',\n"; 1281 1655 } 1282 1656 print OUTFILE ");\n\n"; … … 1325 1699 1326 1700 #------------------------------------------------------------------------------ 1327 # sort numbers first numerically, then strings alphabetically (case insensitive) 1328 sub NumbersFirst 1701 # Sort numbers first numerically, then strings alphabetically (case insensitive) 1702 # - two global variables are used to change the sort algorithm: 1703 # $numbersFirst: -1 = put numbers after other strings 1704 # 1 = put numbers before other strings 1705 # 2 = put numbers first, but negative numbers last 1706 # $caseInsensitive: flag set for case-insensitive sorting 1707 sub NumbersFirst($$) 1329 1708 { 1709 my ($a, $b) = @_; 1330 1710 my $rtnVal; 1331 my $bNum = ($b =~ /^-?[0-9]+(\.\d*)?$/); 1332 if ($a =~ /^-?[0-9]+(\.\d*)?$/) { 1333 $rtnVal = ($bNum ? $a <=> $b : -$numbersFirst); 1334 } elsif ($bNum) { 1711 my ($bNum, $bDec); 1712 ($bNum, $bDec) = ($1, $3) if $b =~ /^(-?[0-9]+)(\.(\d*))?$/; 1713 if ($a =~ /^(-?[0-9]+)(\.(\d*))?$/) { 1714 if (defined $bNum) { 1715 $bNum += 1e9 if $numbersFirst == 2 and $bNum < 0; 1716 my $aInt = $1; 1717 $aInt += 1e9 if $numbersFirst == 2 and $aInt < 0; 1718 # compare integer part as a number 1719 $rtnVal = $aInt <=> $bNum; 1720 unless ($rtnVal) { 1721 my $aDec = $3 || 0; 1722 $bDec or $bDec = 0; 1723 # compare decimal part as an integer too 1724 # (so that "1.10" comes after "1.9") 1725 $rtnVal = $aDec <=> $bDec; 1726 } 1727 } else { 1728 $rtnVal = -$numbersFirst; 1729 } 1730 } elsif (defined $bNum) { 1335 1731 $rtnVal = $numbersFirst; 1336 1732 } else { 1337 1733 my ($a2, $b2) = ($a, $b); 1338 1734 # expand numbers to 3 digits (with restrictions to avoid messing up ascii-hex tags) 1339 $a2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $a2 =~ /^(APP )?[.0-9 ]*$/ and length($a2)<16;1340 $b2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $b2 =~ /^(APP )?[.0-9 ]*$/ and length($b2)<16;1735 $a2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $a2 =~ /^(APP|DMC-\w+ )?[.0-9 ]*$/ and length($a2)<16; 1736 $b2 =~ s/(\d+)/sprintf("%.3d",$1)/eg if $b2 =~ /^(APP|DMC-\w+ )?[.0-9 ]*$/ and length($b2)<16; 1341 1737 $caseInsensitive and $rtnVal = (lc($a2) cmp lc($b2)); 1342 1738 $rtnVal or $rtnVal = ($a2 cmp $b2); … … 1346 1742 1347 1743 #------------------------------------------------------------------------------ 1348 # Convert poddocumentation to pod1744 # Convert our pod-like documentation to pod 1349 1745 # (funny, I know, but the pod headings must be hidden to prevent confusing 1350 1746 # the pod parser) … … 1357 1753 $doc =~ s/\n~/\n=/g; 1358 1754 $doc =~ s/L<[^>]+?\|(http[^>]+)>/L<$1>/g; # POD doesn't support text for http links 1755 $doc =~ s/L<([^>]+?)\|[^>]+\.html(#\w+)?>/$1/g; # remove relative HTML links 1359 1756 return $doc; 1360 1757 } 1361 1758 1362 1759 #------------------------------------------------------------------------------ 1363 # Convert poddocumentation to html1760 # Convert our pod-like documentation to html 1364 1761 # Inputs: 0) string 1365 1762 sub Doc2Html($) … … 1370 1767 $doc =~ s/C<(.*?)>/<code>$1<\/code>/sg; 1371 1768 $doc =~ s/I<(.*?)>/<i>$1<\/i>/sg; 1372 $doc =~ s{L<([^&]+?)\|\Q$homePage\E/TagNames/(.*?)>}{<a href="$2">$1<\/a>}sg;1769 # L<some text|https://exiftool.org/struct.html#Fields> --> <a href="../struct.html#Fields">some text</a> 1373 1770 $doc =~ s{L<([^&]+?)\|\Q$homePage\E/(.*?)>}{<a href="../$2">$1<\/a>}sg; 1374 $doc =~ s{L<\Q$homePage\E/TagNames/(.*?)>}{<a href="$1">$1<\/a>}sg;1771 # L<https://exiftool.org/struct.html> --> <a href="https://exiftool.org/struct.html">https://exiftool.org/struct.html</a> 1375 1772 $doc =~ s{L<\Q$homePage\E/(.*?)>}{<a href="../$1">$1<\/a>}sg; 1773 # L<XMP DICOM Tags|Image::ExifTool::TagNames/XMP DICOM Tags> --> <a href="XMP.html#DICOM">XMP DICOM Tags</a> 1774 # (specify "Image::ExifTool::TagNames" to link to another html file) 1775 $doc =~ s{L<([^&]+?)\|Image::ExifTool::TagNames/(\w+) ([^/&|]+) Tags>}{<a href="$2.html#$3">$1</a>}sg; 1776 # L<DICOM Tags|Image::ExifTool::TagNames/DICOM Tags> --> <a href="DICOM.html">DICOM Tags</a> 1777 $doc =~ s{L<([^&]+?)\|Image::ExifTool::TagNames/(\w+) Tags>}{<a href="$2.html">$1</a>}sg; 1778 # L<dc|/XMP dc Tags> --> <a href="#dc">dc</a> 1779 # (a relative POD link turns into a relative HTML link) 1376 1780 $doc =~ s{L<([^&]+?)\|/\w+ ([^/&|]+) Tags>}{<a href="#$2">$1</a>}sg; 1781 # L<sample config file|../config.html> --> <a href="../config.html">sample config file</a> 1377 1782 $doc =~ s/L<([^&]+?)\|(.+?)>/<a href="$2">$1<\/a>/sg; 1378 $doc =~ s/L<(.*?)>/<a href="$1">$1<\/a>/sg; 1783 # L<http://some.web.site/> --> <a href="http://some.web.site">http://some.web.site</a> 1784 $doc =~ s/L<(http.*?)>/<a href="$1">$1<\/a>/sg; 1379 1785 return $doc; 1380 1786 } 1381 1787 1382 1788 #------------------------------------------------------------------------------ 1789 # Tweak order of tables 1790 # Inputs: 0) table list ref, 1) reference to tweak hash 1791 sub TweakOrder($$) 1792 { 1793 local $_; 1794 my ($sortedTables, $tweakOrder) = @_; 1795 my @tweak = sort keys %$tweakOrder; 1796 my (%addedMain, @sorted); 1797 # flag files which have a "Main" table 1798 foreach (@$sortedTables) { 1799 $addedMain{$1} = 0 if /^Image::ExifTool::(\w+)::(\w+)/ and $2 eq 'Main'; 1800 } 1801 # make sure that the main table always comes first in each file 1802 foreach (@$sortedTables) { 1803 if (/^Image::ExifTool::(\w+)::(\w+)/) { 1804 if ($addedMain{$1}) { 1805 next if $2 eq 'Main'; # don't add again 1806 } elsif (defined $addedMain{$1}) { 1807 push @sorted, "Image::ExifTool::${1}::Main" if $2 ne 'Main'; 1808 $addedMain{$1} = 1; 1809 } 1810 } 1811 push @sorted, $_; 1812 } 1813 @$sortedTables = @sorted; 1814 # apply manual tweaks 1815 while (@tweak) { 1816 my $table = shift @tweak; 1817 my $first = $$tweakOrder{$table}; 1818 if ($$tweakOrder{$first}) { 1819 push @tweak, $table; # must defer this till later 1820 next; 1821 } 1822 delete $$tweakOrder{$table}; # because the table won't move again 1823 my @moving = grep /^Image::ExifTool::$table\b/, @$sortedTables; 1824 my @notMoving = grep !/^Image::ExifTool::$table\b/, @$sortedTables; 1825 my @after; 1826 while (@notMoving) { 1827 last if $notMoving[-1] =~ /^Image::ExifTool::$first\b/; 1828 unshift @after, pop @notMoving; 1829 } 1830 @$sortedTables = (@notMoving, @moving, @after); 1831 } 1832 } 1833 1834 #------------------------------------------------------------------------------ 1835 # Get a list of sorted tag ID's from a table 1836 # Inputs: 0) tag table ref 1837 # Returns: list of sorted keys 1838 sub SortedTagTableKeys($) 1839 { 1840 my $table = shift; 1841 my $vars = $$table{VARS} || { }; 1842 my @keys = TagTableKeys($table); 1843 if ($$vars{NO_ID}) { 1844 # sort by tag name if ID not shown 1845 my ($key, %name); 1846 foreach $key (@keys) { 1847 my ($tagInfo) = GetTagInfoList($table, $key); 1848 $name{$key} = $$tagInfo{Name}; 1849 } 1850 return sort { $name{$a} cmp $name{$b} or $a cmp $b } @keys; 1851 } else { 1852 my $sortProc = $$vars{SORT_PROC} || \&NumbersFirst; 1853 return sort { &$sortProc($a,$b) } @keys; 1854 } 1855 } 1856 1857 #------------------------------------------------------------------------------ 1383 1858 # Get the order that we want to print the tables in the documentation 1859 # Inputs: 0-N) Extra tables to add at end 1384 1860 # Returns: tables in the order we want 1385 sub GetTableOrder( )1861 sub GetTableOrder(@) 1386 1862 { 1387 1863 my %gotTable; … … 1406 1882 $caseInsensitive = ($$table{GROUPS} and $$table{GROUPS}{0} eq 'XMP'); 1407 1883 $numbersFirst = -1 if $$table{VARS} and $$table{VARS}{ALPHA_FIRST}; 1408 my @keys = sort NumbersFirstTagTableKeys($table);1884 my @keys = SortedTagTableKeys($table); 1409 1885 $numbersFirst = 1; 1410 1886 foreach (@keys) { … … 1450 1926 } 1451 1927 } 1928 # add the extra tables 1929 push @sortedTables, @_; 1452 1930 # tweak the table order 1453 my %tweakOrder = ( 1454 JPEG => '-', # JPEG comes first 1455 IPTC => 'Exif', # put IPTC after EXIF, 1456 GPS => 'XMP', # etc... 1457 GeoTiff => 'GPS', 1458 CanonVRD=> 'CanonCustom', 1459 Kodak => 'JVC', 1460 'Kodak::IFD' => 'Kodak::Unknown', 1461 'Kodak::TextualInfo' => 'Kodak::IFD', 1462 'Kodak::Processing' => 'Kodak::TextualInfo', 1463 Leaf => 'Kodak', 1464 Minolta => 'Leaf', 1465 SonyIDC => 'Sony', 1466 Unknown => 'SonyIDC', 1467 DNG => 'Unknown', 1468 PrintIM => 'ICC_Profile', 1469 ID3 => 'PostScript', 1470 MinoltaRaw => 'KyoceraRaw', 1471 KyoceraRaw => 'CanonRaw', 1472 SigmaRaw => 'PanasonicRaw', 1473 Olympus => 'NikonCapture', 1474 PhotoMechanic => 'FotoStation', 1475 Microsoft => 'PhotoMechanic', 1476 'Microsoft::MP'=> 'Microsoft::MP1', 1477 GIMP => 'Microsoft', 1478 'Nikon::CameraSettingsD300' => 'Nikon::ShotInfoD300b', 1479 'Pentax::LensData' => 'Pentax::LensInfo2', 1480 'Sony::SRF2' => 'Sony::SRF', 1481 'Samsung::INFO' => 'Samsung::Type2', # (necessary because Samsung doesn't have a main table) 1482 'Samsung::MP4' => 'Samsung::INFO', # (necessary because Samsung doesn't have a main table) 1483 ); 1484 my @tweak = sort keys %tweakOrder; 1485 while (@tweak) { 1486 my $table = shift @tweak; 1487 my $first = $tweakOrder{$table}; 1488 if ($tweakOrder{$first}) { 1489 push @tweak, $table; # must defer this till later 1490 next; 1491 } 1492 delete $tweakOrder{$table}; # because the table won't move again 1493 my @moving = grep /^Image::ExifTool::$table\b/, @sortedTables; 1494 my @notMoving = grep !/^Image::ExifTool::$table\b/, @sortedTables; 1495 my @after; 1496 while (@notMoving) { 1497 last if $notMoving[-1] =~ /^Image::ExifTool::$first\b/; 1498 unshift @after, pop @notMoving; 1499 } 1500 @sortedTables = (@notMoving, @moving, @after); 1501 } 1502 return @sortedTables 1931 TweakOrder(\@sortedTables, \%tweakOrder); 1932 1933 return @sortedTables; 1503 1934 } 1504 1935 … … 1519 1950 $htmlFile = "$htmldir/TagNames/$class.html"; 1520 1951 $head = $category; 1521 if ($head =~ /^ XMP.+ Struct$/) {1952 if ($head =~ /^\S+ .+ Struct$/) { 1522 1953 pop @names; 1523 1954 } else { … … 1535 1966 } else { 1536 1967 open(HTMLFILE, ">${htmlFile}_tmp") or return 0; 1537 print HTMLFILE "$docType<html>\n<head>\n<title>$title</title>\n"; 1968 print HTMLFILE "$docType<html>\n"; 1969 print HTMLFILE "<!-- (this file generated automatically by Image::ExifTool::BuildTagLookup) -->\n"; 1970 print HTMLFILE "<head>\n<title>$title</title>\n"; 1538 1971 print HTMLFILE "<link rel=stylesheet type='text/css' href='style.css' title='Style'>\n"; 1539 1972 print HTMLFILE "</head>\n<body>\n"; … … 1545 1978 } 1546 1979 } 1547 $head = "<a name='$ url'>$head</a>" if $url;1980 $head = "<a name='${url}'>$head</a>" if $url; 1548 1981 print HTMLFILE "<h2$top>$head</h2>\n" or return 0; 1549 1982 print HTMLFILE '<p>',Doc2Html($docs{$category}),"</p>\n" if $docs{$category}; … … 1580 2013 print HTMLFILE "<hr>\n"; 1581 2014 print HTMLFILE "(This document generated automatically by Image::ExifTool::BuildTagLookup)\n"; 2015 print HTMLFILE "<br><i>Created $createDate</i>\n" if $htmlFile eq 'html/TagNames/index.html'; 1582 2016 print HTMLFILE "<br><i>Last revised $fileDate</i>\n"; 1583 2017 print HTMLFILE "<p class=lf><a href="; … … 1628 2062 1629 2063 #------------------------------------------------------------------------------ 2064 # Get bitmask for POD documentation 2065 # Inputs: mask string from HTML docs 2066 # Returns: mask string for POD, or '' 2067 sub PodMask($) 2068 { 2069 my $mask = shift; 2070 return '' unless $mask =~ /^\[val( >> (\d+))? \& (0x[\da-f]+)\]/; 2071 return sprintf(' & 0x%.2x', hex($3) << ($2 || 0)); 2072 } 2073 2074 #------------------------------------------------------------------------------ 1630 2075 # Write the TagName HTML and POD documentation 1631 2076 # Inputs: 0) BuildTagLookup object reference 1632 # 1) output pod file ( ie. 'lib/Image/ExifTool/TagNames.pod')1633 # 2) output html directory ( ie. 'html')2077 # 1) output pod file (eg. 'lib/Image/ExifTool/TagNames.pod') 2078 # 2) output html directory (eg. 'html') 1634 2079 # Returns: true on success 1635 2080 # Notes: My apologies for the patchwork code, but this is only used to generate the docs. … … 1650 2095 # open the file and write the header 1651 2096 open(PODFILE, ">$podFile") or return 0; 2097 $docs{ExifTool} = eval qq{"$docs{ExifTool}"}; 1652 2098 print PODFILE Doc2Pod($docs{PodHeader}, $docs{ExifTool}, $docs{ExifTool2}); 1653 mkdir "$htmldir/TagNames" ;2099 mkdir "$htmldir/TagNames", 0777; 1654 2100 OpenHtmlFile($htmldir) or return 0; 1655 2101 print HTMLFILE "<blockquote>\n"; … … 1658 2104 print HTMLFILE "<th colspan=$columns><span class=l>Tag Table Index</span></th></tr>\n"; 1659 2105 print HTMLFILE "<tr class=b><td width='$percent%'>\n"; 1660 # write the index 1661 my @tableNames = GetTableOrder(); 1662 # add shortcuts last 1663 push @tableNames, 'Image::ExifTool::Shortcuts::Main'; 1664 push @tableNames, @pluginTables; 2106 2107 # get the full table list, adding shortcuts and plug-in tables to the end 2108 my @tableNames = GetTableOrder('Image::ExifTool::Shortcuts::Main', @pluginTables); 2109 1665 2110 # get list of headings and add any missing ones 1666 2111 my $heading = 'xxx'; … … 1698 2143 $short = $tableName unless $short; 1699 2144 $url = "$short.html"; 1700 print HTMLFILE "<a href='$ url'>$short</a>";2145 print HTMLFILE "<a href='${url}'>$short</a>"; 1701 2146 ++$count; 1702 2147 } 1703 2148 print HTMLFILE "\n</td></tr></table></td></tr></table></blockquote>\n"; 1704 2149 print HTMLFILE '<p>',Doc2Html($docs{ExifTool2}),"</p>\n"; 2150 1705 2151 # write all the tag tables 1706 2152 while (@tableNames or @sepTables or @structs) { … … 1713 2159 if ($notes) { 1714 2160 # remove unnecessary whitespace 1715 $notes =~ s/ (^\s+|\s+$)//g;2161 $notes =~ s/^\s+//; $notes =~ s/\s+$//; 1716 2162 $notes =~ s/(^[ \t]+|[ \t]+$)//mg; 1717 2163 } 1718 2164 my $head = $tableName; 1719 $head =~ s/ .* //;2165 $head =~ s/^.* //s; 1720 2166 close HTMLFILE; 1721 2167 if (OpenHtmlFile($htmldir, $tableName, 1)) { … … 1727 2173 my $wid = 0; 1728 2174 my @keys; 1729 foreach (sort NumbersFirstkeys %$printConv) {2175 foreach (sort { NumbersFirst($a,$b) } keys %$printConv) { 1730 2176 next if /^(Notes|PrintHex|PrintString|OTHER)$/; 1731 2177 $align = '' if $align and /[^\d]/; … … 1733 2179 $wid = $w if $wid < $w; 1734 2180 push @keys, $_; 2181 if ($$printConv{$_} =~ /[\0-\x1f\x7f-\xff]/) { 2182 warn "Warning: Special characters in $tableName PrintConv ($$printConv{$_})\n"; 2183 } 1735 2184 } 1736 2185 $wid = length($tableName)+7 if $wid < length($tableName)+7; 1737 2186 # print in multiple columns if there is room 1738 my $cols = int( 80 / ($wid + 4));2187 my $cols = int(110 / ($wid + 4)); 1739 2188 $cols = 1 if $cols < 1 or $cols > @keys or @keys < 4; 1740 2189 my $rows = int((scalar(@keys) + $cols - 1) / $cols); … … 1754 2203 $prt = '= ' . EscapeHTML($$printConv{$key}); 1755 2204 if ($$printConv{PrintHex}) { 2205 $index =~ s/(\.\d+)$//; # remove decimal 1756 2206 $index = sprintf('0x%x',$index); 2207 $index .= $1 if $1; # add back decimal 1757 2208 } elsif ($$printConv{PrintString} or 1758 2209 $index !~ /^[+-]?(?=\d|\.\d)\d*(\.\d*)?$/) … … 1786 2237 $isStruct = $$structLookup{$tableName}; 1787 2238 $isStruct or warn("Missing structure $tableName\n"), next; 1788 $short = $tableName = "XMP $tableName Struct"; 2239 $tableName = "XMP $tableName" unless $tableName =~ / /; 2240 $short = $tableName = "$tableName Struct"; 1789 2241 my $maxLen = 0; 1790 2242 $maxLen < length and $maxLen = length foreach keys %$isStruct; … … 1800 2252 } 1801 2253 } 1802 my $isExif = $tableName eq 'Image::ExifTool::Exif::Main' ? 1 : undef; 1803 my $isRiff = $tableName eq 'Image::ExifTool::RIFF::Info' ? 1 : undef; 2254 my $isExif = ($tableName eq 'Image::ExifTool::Exif::Main'); 2255 my $isRiff = ($tableName eq 'Image::ExifTool::RIFF::Info'); 2256 my $isXmpMain = ($tableName eq 'Image::ExifTool::XMP::Main'); 1804 2257 my $info = $$tagNameInfo{$tableName}; 1805 2258 my $id = $$idLabel{$tableName}; … … 1807 2260 # widths of the different columns in the POD documentation 1808 2261 my ($wID,$wTag,$wReq,$wGrp) = (8,36,24,10); 1809 my ($composite, $derived, $notes, $ prefix);2262 my ($composite, $derived, $notes, $longTags, $wasLong, $prefix); 1810 2263 if ($short eq 'Shortcuts') { 1811 2264 $derived = '<th>Refers To</th>'; … … 1817 2270 my $table = GetTagTable($tableName); 1818 2271 $notes = $$table{NOTES}; 2272 if ($$table{NAMESPACE}) { 2273 my $ns = $Image::ExifTool::XMP::stdXlatNS{$$table{NAMESPACE}} || $$table{NAMESPACE}; 2274 my $msg = "These tags belong to the ExifTool XMP-$ns family 1 group."; 2275 if ($notes) { 2276 $notes =~ s/\s+$//; 2277 $notes .= "\n\n" . $msg; 2278 } else { 2279 $notes = $msg; 2280 } 2281 } 2282 $longTags = $$table{VARS}{LONG_TAGS} if $$table{VARS}; 1819 2283 if ($$table{GROUPS}{0} eq 'Composite') { 1820 2284 $composite = 1; … … 1828 2292 if ($notes) { 1829 2293 # remove unnecessary whitespace 1830 $notes =~ s/ (^\s+|\s+$)//g;2294 $notes =~ s/^\s+//; $notes =~ s/\s+$//; 1831 2295 $notes =~ s/(^[ \t]+|[ \t]+$)//mg; 1832 2296 if ($notes =~ /leading '(.*?_)' which/) { … … 1850 2314 my $longTag = $self->{LONG_NAME}->{$tableName}; 1851 2315 if ($wTag < $longTag) { 1852 warn "Notice: Long tags in $tableName table\n";1853 2316 if ($wID - $longTag + $wTag >= 6) { # don't let ID column get too narrow 1854 2317 $wID -= $longTag - $wTag; 1855 2318 $wTag = $longTag; 1856 2319 } 2320 $wasLong = 1 if $wID <= $self->{LONG_ID}->{$tableName}; 1857 2321 } 1858 2322 } elsif ($composite) { … … 1863 2327 $hid = ''; 1864 2328 } 1865 if ($short eq 'EXIF' ) {2329 if ($short eq 'EXIF' or $short eq 'Extra') { 1866 2330 $derived = '<th>Group</th>'; 1867 2331 $showGrp = 1; 2332 $wGrp += 8 if $short eq 'Extra'; # tweak Group column width for "Extra" tags 1868 2333 $wTag -= $wGrp + 1; 1869 2334 } … … 1887 2352 $line .= ' Writable'; 1888 2353 print PODFILE $line; 1889 $line =~ s/^(\s*\w.{6}\w) /$1\t/; # change space to tab after long ID label ( ie. "Sequence")2354 $line =~ s/^(\s*\w.{6}\w) /$1\t/; # change space to tab after long ID label (eg. "Sequence") 1890 2355 $line =~ s/\S/-/g; 1891 2356 $line =~ s/- -/---/g; … … 1910 2375 if (not $id) { 1911 2376 $idStr = ' '; 1912 } elsif ($tagIDstr =~ /^ \d+(\.\d+)?$/) {2377 } elsif ($tagIDstr =~ /^-?\d+(\.\d+)?$/) { 1913 2378 $w = $wID - 3; 1914 2379 $idStr = sprintf " %${w}g ", $tagIDstr; 2380 my $tooLong = length($idStr) - 6 - $w; 2381 if ($tooLong) { 2382 $tooLong = 3 if $tooLong > 3; 2383 $idStr = substr($idStr, 0, -$tooLong); 2384 } 1915 2385 $align = " class=r"; 1916 2386 } else { … … 1926 2396 # put tag name on next line if ID is too long 1927 2397 $idStr = " $tagIDstr\n " . (' ' x $w); 1928 warn "Notice: Split $$tagNames[0] line\n"; 2398 if ($longTags) { 2399 --$longTags; 2400 } else { 2401 warn "Notice: Split $$tagNames[0] line\n"; 2402 } 1929 2403 } 1930 2404 } … … 1938 2412 my $wrStr = shift @vals; 1939 2413 my $subdir; 1940 my @masks = grep /^\[ Mask0x[\da-f]+\]/, @$values;2414 my @masks = grep /^\[val( >> \d+)? \& 0x[\da-f]+\]/, @$values; 1941 2415 my $tag = shift @tags; 1942 2416 # if this is a subdirectory or structure, print subdir name (from values) instead of writable … … 1945 2419 if (@masks) { 1946 2420 # combine any mask into the format string 1947 $wrStr .= " & $1" if $masks[0] =~ /(0x[\da-f]+)/;2421 $wrStr .= PodMask($masks[0]); 1948 2422 shift @masks; 1949 @vals = grep !/^\[ Mask0x[\da-f]+\]/, @$values;2423 @vals = grep !/^\[val( >> \d+)? \& 0x[\da-f]+\]/, @$values; 1950 2424 } else { 1951 2425 @vals = @$values; … … 1958 2432 $vals[$i] = $$writable[$i] unless defined $vals[$i]; 1959 2433 if (@masks) { 1960 $vals[$i] .= " & $1" if $masks[0] =~ /(0x[\da-f]+)/;2434 $vals[$i] .= PodMask($masks[0]); 1961 2435 shift @masks; 1962 2436 } … … 1964 2438 if ($$sepTable{$vals[0]}) { 1965 2439 $wrStr =~ s/^[-=]//; 1966 $wrStr = ' N' unless $wrStr;2440 $wrStr = 'no' unless $wrStr; 1967 2441 } elsif ($$structs{$vals[0]}) { 1968 2442 my $flags = $wrStr =~ /([+_]+)$/ ? $1 : ''; … … 1972 2446 } 1973 2447 shift @vals; 1974 } elsif ($wrStr and $wrStr ne ' N' and @masks) {2448 } elsif ($wrStr and $wrStr ne 'no' and @masks) { 1975 2449 # fill in missing entries if masks are different 1976 2450 my $mask = shift @masks; … … 1981 2455 } 1982 2456 # add Mask to Writable column in POD doc 1983 $wrStr .= " & $1" if $mask =~ /(0x[\da-f]+)/; 1984 } 1985 printf PODFILE "%s%-${wTag2}s", $idStr, $tag; 1986 warn "Warning: Pushed $tag\n" if $id and length($tag) > $wTag2; 1987 printf PODFILE " %-${wGrp}s", shift(@wGrp) || '-' if $showGrp; 2457 $wrStr .= PodMask($mask); 2458 } 2459 my $pod = sprintf "%s%-${wTag2}s", $idStr, $tag; 2460 my $tGrp = $wGrp; 2461 if ($id and length($tag) > $wTag2) { 2462 my $madeRoom; 2463 if ($showGrp) { 2464 my $wGrp0 = length($wGrp[0] || '-'); 2465 if (not $composite and $wGrp > $wGrp0) { 2466 $tGrp = $wGrp - (length($tag) - $wTag2); 2467 if ($tGrp < length $wGrp0) { 2468 $tGrp = length $wGrp0; 2469 } else { 2470 $madeRoom = 1; 2471 } 2472 } 2473 } 2474 warn "Warning: Pushed $tag\n" unless $madeRoom; 2475 } 2476 $pod .= sprintf " %-${tGrp}s", shift(@wGrp) || '-' if $showGrp; 1988 2477 if ($composite) { 1989 2478 @reqs = @$require; 1990 2479 $w = $wReq; # Keep writable column in line 1991 2480 length($tag) > $wTag2 and $w -= length($tag) - $wTag2; 1992 printf PODFILE " %-${w}s", shift(@reqs) || ''; 1993 } 1994 printf PODFILE " $wrStr\n"; 2481 $pod .= sprintf " %-${w}s", shift(@reqs) || ''; 2482 } 2483 $pod .= " $wrStr"; 2484 # limit line length to 82 characters (even if it means messing up column alignment) 2485 if (length $pod > 82 and $pod !~ /\n/) { 2486 my $remove = length($pod) - 82; 2487 $pod =~ s/(\w)\s{$remove}/$1/; 2488 } 2489 print PODFILE $pod, "\n"; 1995 2490 my $numTags = scalar @$tagNames; 1996 2491 my $n = 0; … … 2019 2514 $line .= " $val"; 2020 2515 if (@masks) { 2021 $line .= " & $1" if $masks[0] =~ /(0x[\da-f]+)/;2516 $line .= PodMask($masks[0]); 2022 2517 shift @masks; 2023 2518 } … … 2031 2526 push @htmlTags, EscapeHTML($_); 2032 2527 } 2033 if (($isExif and $exifSpec{hex $tagIDstr}) or 2034 ($isRiff and $tagIDstr=~/(\w+)/ and $riffSpec{$1})) 2528 if (($isExif and $Image::ExifTool::Validate::exifSpec{hex $tagIDstr}) or 2529 ($isRiff and $tagIDstr=~/(\w+)/ and $riffSpec{$1}) or 2530 ($isXmpMain and $tagIDstr=~/([-\w]+)/ and $xmpSpec{$1})) 2035 2531 { 2036 2532 # underline "unknown" makernote tags only … … 2045 2541 } 2046 2542 # add tooltip for hex conversion of Tag ID 2047 if ($tagIDstr =~ /^ 0x[0-9a-f]+$/i) {2048 $tip = sprintf(" title='$tagIDstr = %u '",hex $tagIDstr);2543 if ($tagIDstr =~ /^(0x[0-9a-f]+)(\.\d+)?$/i) { 2544 $tip = sprintf(" title='$tagIDstr = %u%s'", hex($1), $2||''); 2049 2545 } elsif ($tagIDstr =~ /^(\d+)(\.\d*)?$/) { 2050 2546 $tip = sprintf(" title='%u = 0x%x'", $1, $1); … … 2059 2555 '_' => 'Flattened', 2060 2556 '+' => 'List', 2061 '/' => 'Avoid ed',2557 '/' => 'Avoid', 2062 2558 '~' => 'Writable only with -n', 2063 2559 '!' => 'Unsafe', 2064 2560 '*' => 'Protected', 2065 2561 ':' => 'Mandatory', 2562 '^' => 'Deletable', 2066 2563 ); 2067 2564 my ($wstr, %hasAttr, @hasAttr); 2068 2565 foreach $wstr (@$writable) { 2069 next unless $wstr =~ m{([+/~!*:_ ]+)$};2566 next unless $wstr =~ m{([+/~!*:_^]+)$}; 2070 2567 my @a = split //, $1; 2071 2568 foreach (@a) { … … 2098 2595 foreach (@$values) { 2099 2596 if (/^\(/) { 2597 $_ = Doc2Html($_); 2100 2598 # set the note font 2101 2599 $smallNote = 1 if $numTags < 2; … … 2104 2602 } 2105 2603 # make text in square brackets small 2106 /^\[/ and push(@values, "<span class=s>$_</span>"), next; 2604 if (/^\[/) { 2605 if (s/^\[!HTML\]//) { 2606 push @values, $_; 2607 } else { 2608 $_ = Doc2Html($_); 2609 push @values, "<span class=s>$_</span>"; 2610 } 2611 next; 2612 } 2107 2613 /=/ and push(@values, $_), next; 2108 2614 my @names = split; … … 2112 2618 $suffix = ' Values'; 2113 2619 } 2114 # currently all structures are in XMP documentation 2115 if ($$structs{$_} and $short =~ /^XMP/) { 2116 unshift @names, 'XMP'; 2620 # handle structures specially 2621 if ($$structs{$_}) { 2622 # assume XMP module for this struct unless otherwise specified 2623 unshift @names, 'XMP' unless / /; 2117 2624 push @structs, $_; # list this later 2625 # hack to put Area Struct in with XMP tags, 2626 # even though it is only used by the MWG module 2627 push @structs, 'Area' if $_ eq 'Dimensions'; 2118 2628 $suffix = ' Struct'; 2119 2629 } 2120 2630 $url = (shift @names) . '.html'; 2121 2631 @names and $url .= '#' . join '_', @names; 2122 push @values, "--> <a href='$ url'>$_$suffix</a>";2632 push @values, "--> <a href='${url}'>$_$suffix</a>"; 2123 2633 } 2124 2634 # put small note last … … 2151 2661 print HTMLFILE "</td></tr>\n"; 2152 2662 } 2663 warn "$longTags unaccounted-for long tags in $tableName\n" if $longTags; 2664 if ($wasLong and not defined $longTags) { 2665 warn "Notice: Long tags in $tableName table\n"; 2666 } 2153 2667 unless ($infoCount) { 2154 print fPODFILE " [no tags known]\n";2668 print PODFILE " [no tags known]\n"; 2155 2669 my $cols = 3; 2156 2670 ++$cols if $hid; … … 2182 2696 Image::ExifTool::TagNames.pod, as well as HTML tag name documentation. It 2183 2697 is used before each new ExifTool release to update the lookup tables and 2184 documentation, but it is not used otherwise. 2698 documentation, but it is not used otherwise. It also performs some 2699 validation and consistency checks on the tag tables. 2185 2700 2186 2701 =head1 SYNOPSIS … … 2190 2705 $builder = new Image::ExifTool::BuildTagLookup; 2191 2706 2707 # update Image::ExifTool::TagLookup 2192 2708 $ok = $builder->WriteTagLookup('lib/Image/ExifTool/TagLookup.pm'); 2193 2709 2710 # update the tag name documentation 2194 2711 $ok = $builder->WriteTagNames('lib/Image/ExifTool/TagNames.pod','html'); 2712 2713 # print some statistics 2714 my $count = $$builder{COUNT}; 2715 foreach (sort keys %$count) { 2716 printf "%5d %s\n", $$count{$_}, $_; 2717 } 2195 2718 2196 2719 =head1 MEMBER VARIABLES … … 2210 2733 WriteTagNames(). 2211 2734 2735 =item WRITE_PSEUDO 2736 2737 Returned list of writable pseudo tags. 2738 2212 2739 =back 2213 2740 2214 2741 =head1 AUTHOR 2215 2742 2216 Copyright 2003-20 11, Phil Harvey (phil at owl.phy.queensu.ca)2743 Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) 2217 2744 2218 2745 This library is free software; you can redistribute it and/or modify it
Note:
See TracChangeset
for help on using the changeset viewer.