From 2766977eee43be0f2ac602e7e42fb12c54b33e35 Mon Sep 17 00:00:00 2001 From: exiftool Date: Tue, 23 Jan 2024 09:14:49 -0500 Subject: Update to 12.74 --- Changes | 27 +- META.json | 2 +- META.yml | 2 +- README | 4 +- exiftool | 89 +- html/ExifTool.html | 13 +- html/ExifTool.pdf | 556 +++++------ html/Shift.pdf | 8 +- html/TagNames/Nikon.html | 4 +- html/TagNames/QuickTime.html | 24 +- html/TagNames/index.html | 4 +- html/exiftool_pod.html | 14 +- html/exiftool_pod.pdf | 1738 +++++++++++++++++---------------- html/faq.html | 9 +- html/filename.html | 15 +- html/history.html | 30 +- html/index.html | 12 +- html/install.html | 22 +- html/models.html | 6 +- html/sample_images.html | 18 +- lib/File/RandomAccess.pm | 36 +- lib/File/RandomAccess.pod | 8 +- lib/Image/ExifTool.pm | 50 +- lib/Image/ExifTool.pod | 13 +- lib/Image/ExifTool/7Z.pm | 6 +- lib/Image/ExifTool/AFCP.pm | 4 +- lib/Image/ExifTool/BZZ.pm | 4 +- lib/Image/ExifTool/BuildTagLookup.pm | 10 +- lib/Image/ExifTool/Canon.pm | 6 +- lib/Image/ExifTool/CanonVRD.pm | 4 +- lib/Image/ExifTool/DICOM.pm | 4 +- lib/Image/ExifTool/DNG.pm | 8 +- lib/Image/ExifTool/Exif.pm | 4 +- lib/Image/ExifTool/FLIR.pm | 4 +- lib/Image/ExifTool/Fixup.pm | 6 +- lib/Image/ExifTool/FlashPix.pm | 6 +- lib/Image/ExifTool/FujiFilm.pm | 11 +- lib/Image/ExifTool/Geotag.pm | 6 +- lib/Image/ExifTool/HtmlDump.pm | 4 +- lib/Image/ExifTool/ID3.pm | 4 +- lib/Image/ExifTool/Import.pm | 10 +- lib/Image/ExifTool/JSON.pm | 4 +- lib/Image/ExifTool/Jpeg2000.pm | 4 +- lib/Image/ExifTool/MIE.pm | 6 +- lib/Image/ExifTool/MinoltaRaw.pm | 4 +- lib/Image/ExifTool/Nikon.pm | 4 +- lib/Image/ExifTool/NikonCustom.pm | 6 +- lib/Image/ExifTool/Ogg.pm | 4 +- lib/Image/ExifTool/PLIST.pm | 6 +- lib/Image/ExifTool/PanasonicRaw.pm | 6 +- lib/Image/ExifTool/PhaseOne.pm | 4 +- lib/Image/ExifTool/Photoshop.pm | 6 +- lib/Image/ExifTool/PostScript.pm | 4 +- lib/Image/ExifTool/QuickTime.pm | 147 +-- lib/Image/ExifTool/QuickTimeStream.pl | 14 +- lib/Image/ExifTool/RSRC.pm | 4 +- lib/Image/ExifTool/Samsung.pm | 8 +- lib/Image/ExifTool/Shift.pl | 2 +- lib/Image/ExifTool/SigmaRaw.pm | 6 +- lib/Image/ExifTool/Sony.pm | 6 +- lib/Image/ExifTool/TagInfoXML.pm | 4 +- lib/Image/ExifTool/TagLookup.pm | 10 +- lib/Image/ExifTool/TagNames.pod | 6 +- lib/Image/ExifTool/WriteCanonRaw.pl | 2 +- lib/Image/ExifTool/WriteExif.pl | 30 +- lib/Image/ExifTool/WritePDF.pl | 2 +- lib/Image/ExifTool/WriteQuickTime.pl | 2 +- lib/Image/ExifTool/WriteXMP.pl | 6 +- lib/Image/ExifTool/Writer.pl | 108 +- lib/Image/ExifTool/ZIP.pm | 12 +- perl-Image-ExifTool.spec | 2 +- pp_build_exe.args | 8 +- t/ExifTool.t | 4 +- t/TestLib.pm | 2 +- t/XMP.t | 10 +- t/XMP_46.out | 1 + windows_exiftool | 76 +- 77 files changed, 1736 insertions(+), 1599 deletions(-) diff --git a/Changes b/Changes index 2b104650..d352c4ca 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,30 @@ RSS feed: https://exiftool.org/rss.xml Note: The most recent production release is Version 12.70. (Other versions are considered development releases, and are not uploaded to MetaCPAN.) +Jan. 23, 2024 - Version 12.74 + + - Added a couple of new Nikon lenses (thanks Chris) + - Added write support for a few new QuickTime Keys tags + - Decode ShutterCount for Canon EOS R5 (thanks John Moyer) + - Improved error messages in the case of file read errors + - Enhanced tag name strings (eg. -if option expressions) to allow values of + multiple matching tags to be concatenated when a group name of "All" is + specified + - Enhanced -p option to add -p- feature which avoids adding trailing newline + - Changed warning from "Shift results in negative time" to "Shift results in + date before 1970" + - Patched calculation of GPSDateTime for the timed metadata in Track3 of + Garmin videos so the API QuickTimeUTC option is no longer required + - Fixed conversion error when writing QuickTime:GoogleTrackDuration + - Fixed misidentification of non-TIFF-format files containing DNGVersion tag + - Fixed bug where Avoid-ed XMP structures could be created when writing + another same-named structure + - Internal Changes: + - Changed form of all new() calls to accommodate backward + incompatibilities in recent versions of Perl + - Changed order of InsertTagValues() arguments + - DateFmt() now returns value of formatted date/time string + Jan. 10, 2024 - Version 12.73 - Added write support for Leica XMP-xmpDSA tags @@ -22,7 +46,8 @@ Jan. 10, 2024 - Version 12.73 decoding - Fixed writing of date/time tags in XMP-xmpMM:Pantry structure - API Changes: - - Added LimitLongValues option + - Added LimitLongValues option to provide control over tags which + previously had a hard-coded length limit Dec. 29, 2023 - Version 12.72 diff --git a/META.json b/META.json index 3449e1b6..2908e6ad 100644 --- a/META.json +++ b/META.json @@ -50,5 +50,5 @@ } }, "release_status" : "stable", - "version" : "12.73" + "version" : "12.74" } diff --git a/META.yml b/META.yml index 327f14ce..06926ecc 100644 --- a/META.yml +++ b/META.yml @@ -31,4 +31,4 @@ recommends: Time::HiRes: 0 requires: perl: 5.004 -version: 12.73 +version: 12.74 diff --git a/README b/README index c8d780f7..05ec4e73 100644 --- a/README +++ b/README @@ -108,8 +108,8 @@ your home directory, then you would type the following commands in a terminal window to extract and run ExifTool: cd ~/Desktop - gzip -dc Image-ExifTool-12.73.tar.gz | tar -xf - - cd Image-ExifTool-12.73 + gzip -dc Image-ExifTool-12.74.tar.gz | tar -xf - + cd Image-ExifTool-12.74 ./exiftool t/images/ExifTool.jpg Note: These commands extract meta information from one of the test images. diff --git a/exiftool b/exiftool index 03b50e5b..3b5404de 100755 --- a/exiftool +++ b/exiftool @@ -11,7 +11,7 @@ use strict; use warnings; require 5.004; -my $version = '12.73'; +my $version = '12.74'; # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool' my $exePath; @@ -70,7 +70,7 @@ sub PreserveTime(); sub AbsPath($); sub MyConvertFileName($$); sub SuggestedExtension($$$); -sub LoadPrintFormat($); +sub LoadPrintFormat($;$); sub FilenameSPrintf($;$@); sub NextUnusedFilename($;$); sub CreateDirectory($); @@ -271,7 +271,7 @@ my %optArgs = ( '-lang' => 0, # (optional arg; cannot begin with "-") '-listitem' => 1, '-o' => 1, '-out' => 1, - '-p' => 1, '-printformat' => 1, + '-p' => 1, '-printformat' => 1, '-p-' => 1, '-printformat-' => 1, '-P' => 0, '-password' => 1, '-require' => 1, @@ -573,7 +573,7 @@ if ($^O eq 'MSWin32' and eval { require File::Glob }) { $doGlob = 1; } -$mt = new Image::ExifTool; # create ExifTool object +$mt = Image::ExifTool->new; # create ExifTool object # don't extract duplicates by default unless set by UserDefined::Options $mt->Options(Duplicates => 0) unless %Image::ExifTool::UserDefined::Options @@ -1133,10 +1133,10 @@ for (;;) { } /^overwrite_original$/i and $overwriteOrig = 1, next; /^overwrite_original_in_place$/i and $overwriteOrig = 2, next; - if (/^p$/ or $a eq 'printformat') { + if (/^p(-?)$/ or /^printformat(-?)$/i) { my $fmt = shift; if ($pass) { - LoadPrintFormat($fmt); + LoadPrintFormat($fmt, $1); # load MWG module now if necessary if (not $useMWG and grep /^mwg:/i, @requestTags) { $useMWG = 1; @@ -1145,7 +1145,7 @@ for (;;) { } } else { # defer to next pass so the filename charset is available - push @nextPass, '-p', $fmt; + push @nextPass, "-$_", $fmt; } next; } @@ -1792,7 +1792,7 @@ if (not $altEnc and $mt->Options('Lang') ne 'en' and eval { require Encode }) { if (@fileOrder) { my @allFiles; ProcessFiles($mt, \@allFiles); - my $sortTool = new Image::ExifTool; + my $sortTool = Image::ExifTool->new; $sortTool->Options(FastScan => $fileOrderFast) if $fileOrderFast; $sortTool->Options(PrintConv => $mt->Options('PrintConv')); $sortTool->Options(Duplicates => 0); @@ -2080,7 +2080,7 @@ sub GetImageInfo($$) @foundTags = ('*', @tags) if @tags; $info = $et->ImageInfo(Infile($pipe,$isWriting), \@foundTags, $opts); foreach $condition (@condition) { - my $cond = $et->InsertTagValues(\@foundTags, $condition, \%info); + my $cond = $et->InsertTagValues($condition, \@foundTags, \%info); { # set package so eval'd functions are in Image::ExifTool namespace package Image::ExifTool; @@ -2281,7 +2281,7 @@ sub GetImageInfo($$) my @lines; my $opt = $type eq 'IF' ? 'Silent' : 'Warn'; # silence "IF" warnings foreach (@$prf) { - my $line = $et->InsertTagValues(\@foundTags, $_, $opt, $grp, $cache); + my $line = $et->InsertTagValues($_, \@foundTags, $opt, $grp, $cache); if ($type eq 'IF') { $skipBody = 1 unless defined $line; } elsif (defined $line) { @@ -2714,7 +2714,7 @@ TAG: foreach $tag (@foundTags) { } elsif ($fixLen == 1) { $padLen -= length Encode::decode_utf8($desc); } else { - my $gcstr = eval { new Unicode::GCString(Encode::decode_utf8($desc)) }; + my $gcstr = eval { Unicode::GCString->new(Encode::decode_utf8($desc)) }; if ($gcstr) { $padLen -= $gcstr->columns; } else { @@ -3640,7 +3640,7 @@ sub Infile($;$) if ($rafStdin) { $rafStdin->Seek(0); # rewind } elsif (open RAF_STDIN, '-') { - $rafStdin = new File::RandomAccess(\*RAF_STDIN); + $rafStdin = File::RandomAccess->new(\*RAF_STDIN); $rafStdin->BinMode(); } return $rafStdin if $rafStdin; @@ -4117,12 +4117,12 @@ sub SuggestedExtension($$$) #------------------------------------------------------------------------------ # Load print format file -# Inputs: 0) file name +# Inputs: 0) file name, 1) flag to avoid adding newline to input argument # - saves lines of file to %printFmt list # - adds tag names to @tags list -sub LoadPrintFormat($) +sub LoadPrintFormat($;$) { - my $arg = shift; + my ($arg, $noNL) = @_; if (not defined $arg) { Error "Must specify file or expression for -p option\n"; } elsif ($arg !~ /\n/ and -f $arg and $mt->Open(\*FMT_FILE, $arg)) { @@ -4131,7 +4131,8 @@ sub LoadPrintFormat($) } close(FMT_FILE); } else { - AddPrintFormat($arg . "\n"); + $arg .= "\n" unless $noNL; + AddPrintFormat($arg); } } @@ -4295,7 +4296,7 @@ sub CreateDirectory($) return 0; } unless ($k32CreateDir) { - $k32CreateDir = new Win32::API('KERNEL32', 'CreateDirectoryW', 'PP', 'I'); + $k32CreateDir = Win32::API->new('KERNEL32', 'CreateDirectoryW', 'PP', 'I'); } $success = $k32CreateDir->Call($d2, 0) if $k32CreateDir; } else { @@ -4752,7 +4753,7 @@ L -lang [LANG] Set current language -listItem INDEX Extract specific item from a list -n (--printConv) No print conversion - -p FMTFILE (-printFormat) Print output in specified format + -p[-] STR (-printFormat) Print output in specified format -php Export tags as a PHP Array -s[NUM] (-short) Short output format (-s for tag names) -S (-veryShort) Very short output format @@ -5561,30 +5562,31 @@ when writing. For example, the following commands all have the same effect: > exiftool -Orientation=6 -n a.jpg > exiftool -Orientation#=6 a.jpg -=item B<-p> I or I (B<-printFormat>) +=item B<-p>[-] I or I (B<-printFormat>) -Print output in the format specified by the given file or string. The +Print output in the format specified by the given string or file. The argument is interpreted as a string unless a file of that name exists, in which case the string is loaded from the contents of the file. Tag names in -the format file or string begin with a C<$> symbol and may contain leading +the format string or file begin with a C<$> symbol and may contain leading group names and/or a trailing C<#> (to disable print conversion). Case is not significant. Braces C<{}> may be used around the tag name to separate it from subsequent text (and must be used if subsequent text begins with an alphanumeric character, hyphen, underline, colon or number sign). Use C<$$> -to represent a C<$> symbol, and C<$/> for a newline. - -Multiple B<-p> options may be used, each contributing a line (or more) of -text to the output. Lines beginning with C<#[HEAD]> and C<#[TAIL]> are -output before the first processed file and after the last processed file -respectively. Lines beginning with C<#[SECT]> and C<#[ENDS]> are output -before and after each section of files. A section is defined as a group of -consecutive files with the same section header (eg. files are grouped by -directory if C<#[SECT]> contains C<$directory>). Lines beginning with -C<#[BODY]> and lines not beginning with C<#> are output for each processed -file. Lines beginning with C<#[IF]> are not output, but all BODY lines are -skipped if any tag on an IF line doesn't exist. Other lines beginning with -C<#> are ignored. (To output a line beginning with C<#>, use C<#[BODY]#>.) -For example, this format file: +to represent a C<$> symbol, and C<$/> for a newline. When the string +argument is used (ie. I), a newline is added to the end of the string +unless B<-p-> is specified. + +Multiple B<-p> options may be used. Lines beginning with C<#[HEAD]> and +C<#[TAIL]> are output before the first processed file and after the last +processed file respectively. Lines beginning with C<#[SECT]> and C<#[ENDS]> +are output before and after each section of files. A section is defined as +a group of consecutive files with the same section header (eg. files are +grouped by directory if C<#[SECT]> contains C<$directory>). Lines beginning +with C<#[BODY]> and lines not beginning with C<#> are output for each +processed file. Lines beginning with C<#[IF]> are not output, but all BODY +lines are skipped if any tag on an IF line doesn't exist. Other lines +beginning with C<#> are ignored. (To output a line beginning with C<#>, use +C<#[BODY]#>.) For example, this format file: # this is a comment line #[HEAD]-- Generated by ExifTool $exifToolVersion -- @@ -5598,16 +5600,21 @@ with this command: produces output like this: - -- Generated by ExifTool 12.73 -- + -- Generated by ExifTool 12.74 -- File: a.jpg - 2003:10:31 15:44:19 (f/5.6, 1/60s, ISO 100) File: b.jpg - 2006:05:23 11:57:38 (f/8.0, 1/13s, ISO 100) -- end -- -The values of List-type tags with multiple items and Shortcut tags -representing multiple tags are joined according the B<-sep> option setting -when interpolated in the string. +The values of List-type tags with multiple items, Shortcut tags representing +multiple tags, and matching tags when the C group is specified are +joined according the B<-sep> option setting when interpolated in the string. +(Note that when C is used as a group name, dupicate tags are included +regardless of the Duplicates option setting.) When C is used as a tag +name, a value of 1 is returned if any tag exists in the specified group, or +0 otherwise (unless the C group is also specified, in which case the +values of all matching tags are joined). When B<-ee> (B<-extractEmbedded>) is combined with B<-p>, embedded documents are effectively processed as separate input files. @@ -6550,7 +6557,9 @@ set to undef if C<=> is used, or an empty string with C<^=>. If I is not specified a list of available options is returned. The option name is not case senstive, but the option values are. See L for option details. This -overrides API options set via the config file. +overrides API options set via the config file. Note that the exiftool app +sets some API options internally, and attempts to change these via the +command line will have no effect. =item B<-common_args> diff --git a/html/ExifTool.html b/html/ExifTool.html index e4a44dbf..1690157d 100644 --- a/html/ExifTool.html +++ b/html/ExifTool.html @@ -558,7 +558,8 @@ effect as a value of 0 for options with numerical values.

format (similar to a DateFormat of "%Y:%m:%d %H:%M:%S"). undef DuplicatesFlag to return values from - tags with duplicate names when extracting information. + tags with duplicate names when extracting information. Forced to 1 + when copying tags with SetNewValuesFromFile. 0 or 11 Escape Escape special characters in extracted values for @@ -746,11 +747,11 @@ effect as a value of 0 for options with numerical values.

'en' LargeFileSupportFlag to indicate that 64-bit file offsets are supported on this system. 0 or 1undef -LimitLongValuesWhen extracting some values - that may be very long, the PrintConv values are length-limited and the value is - truncated with an elipsis ("[...]") if it exceeds a specified length. This - option specifies the length limit for these tags. A setting of 4 or less - disables the limit (because the elipsis string is longer than this). +LimitLongValuesWhen extracting some values for + some specific tags (usually Unknown tags), the PrintConv values are length-limited + and the value is truncated with an ellipsis ("[...]") if it exceeds a specified + length. This option specifies the length limit for these tags. A setting of 4 or + less disables the limit (because the ellipsis string is longer than this). Any integer60 +Jan. 23, 2024 - Version 12.74 +
    +
  • Added a couple of new Nikon lenses (thanks Chris) +
  • Added write support for a few new QuickTime Keys tags +
  • Decode ShutterCount for Canon EOS R5 (thanks John Moyer) +
  • Improved error messages in the case of file read errors +
  • Enhanced tag name strings (eg. -if option expressions) to allow values of + multiple matching tags to be concatenated when a group name of "All" is + specified +
  • Enhanced -p option to add -p- feature which avoids adding trailing newline +
  • Changed warning from "Shift results in negative time" to "Shift results in + date before 1970" +
  • Patched calculation of GPSDateTime for the timed metadata in Track3 of + Garmin videos so the API QuickTimeUTC option is no longer required +
  • Fixed conversion error when writing QuickTime:GoogleTrackDuration +
  • Fixed misidentification of non-TIFF-format files containing DNGVersion tag +
  • Fixed bug where Avoid-ed XMP structures could be created when writing + another same-named structure +
  • Internal Changes: +
      +
    • Changed form of all new() calls to accommodate backward + incompatibilities in recent versions of Perl +
    • Changed order of InsertTagValues() arguments +
    • DateFmt() now returns value of formatted date/time string +
    +
+ Jan. 10, 2024 - Version 12.73
  • Added write support for Leica XMP-xmpDSA tags @@ -33,7 +60,8 @@ considered development releases, and are not uploaded to LimitLongValues option +
  • Added LimitLongValues option to provide control over tags which + previously had a hard-coded length limit
diff --git a/html/index.html b/html/index.html index 68ab933e..c0a48d94 100644 --- a/html/index.html +++ b/html/index.html @@ -94,9 +94,9 @@ the site with a moderate load. An alternate ExifTool homepage is available at
- -Download Version 12.73 (5.1 MB) - -Jan. 10, 2024
+ +Download Version 12.74 (5.1 MB) - +Jan. 23, 2024

ExifTool is a platform-independent Perl library plus a command-line application for @@ -149,8 +149,8 @@ distribution above.)

Windows Executable: - - exiftool-12.73.zip (7.0 MB)
+ + exiftool-12.74.zip (7.0 MB)

The stand-alone Windows executable does not require Perl. Just download and un-zip the archive then double-click on @@ -168,7 +168,7 @@ if you have any problems/comments with this version.)

MacOS Package: - ExifTool-12.73.dmg (3.3 MB)
+ ExifTool-12.74.dmg (3.3 MB)

The MacOS package installs the ExifTool command-line application and libraries in /usr/local/bin. After installing, type "exiftool" in a diff --git a/html/install.html b/html/install.html index 38333eef..312bdf75 100644 --- a/html/install.html +++ b/html/install.html @@ -52,10 +52,10 @@ documentation or some other files of the full distribution.

Stand-Alone Executable

  1. Download the Windows Executable from the ExifTool home page. -
    (The file you download should be named "exiftool-12.73.zip".)
  2. +
    (The file you download should be named "exiftool-12.74.zip".)
  3. Extract "exiftool(-k).exe" from the ".zip" file, and place it on your Desktop. -
    (Double-click on "exiftool-12.73.zip" to open +
    (Double-click on "exiftool-12.74.zip" to open the archive, then drag "exiftool(-k).exe" to your Desktop.)

You can now double-click on "exiftool(-k).exe" to read the @@ -109,7 +109,7 @@ can be downloaded from activeperl.com.)

  1. Download the Image-ExifTool distribution from the ExifTool home page -
    (The file you download should be named "Image-ExifTool-12.73.tar.gz".)
  2. +
    (The file you download should be named "Image-ExifTool-12.74.tar.gz".)
  3. Extract the ExifTool files from the archive.
    (The archive is a gzipped tar file, and can be opened with various Windows utilities, including WinZip.)
  4. @@ -151,7 +151,7 @@ in the MacOS package. Both versions run natively on PPC and Intel Macs.

    MacOS Package

    1. Download the ExifTool MacOS Package from the ExifTool home page. -
      (The file you download should be named "ExifTool-12.73.dmg".)
    2. +
      (The file you download should be named "ExifTool-12.74.dmg".)
    3. Install as a normal MacOS package.
      (Open the disk image, double-click on the install package, and follow the instructions. See the second item in the Notes section below if you are stopped with an "unidentified developer" message.) @@ -167,12 +167,12 @@ See the second item in the Notes section below if you are stopped with an "unide
      1. Download the Image-ExifTool distribution from the ExifTool home page to your Desktop. -
        (The file you download should be named "Image-ExifTool-12.73.tar.gz".)
      2. +
        (The file you download should be named "Image-ExifTool-12.74.tar.gz".)
      3. Launch the Terminal application from the Utilities folder in your Applications folder.
      4. In the Terminal window, type the following:
            cd ~/Desktop
        -    tar -xzf Image-ExifTool-12.73.tar.gz
        -    cd Image-ExifTool-12.73
        +    tar -xzf Image-ExifTool-12.74.tar.gz
        +    cd Image-ExifTool-12.74
             sudo cp -r exiftool lib /usr/local/bin
         
        (Note: The last step above will require you to enter your @@ -188,7 +188,7 @@ your Perl version. If both sets of libraries exist, /usr/local/bin/lib takes precedence for exiftool, but /Library/Perl/#.#.# is the default for any other Perl scripts.
      5. In MacOS 10.8 or later, you may see this message when you try to open the install package: -
        "ExifTool-12.73.pkg" can't be opened because it is from an +
        "ExifTool-12.74.pkg" can't be opened because it is from an unidentified developer.
        The solution is to control-click on the pkg then select "Open" from the pop-up menu instead of just double-clicking. An alternative is to lower the security settings by changing "Allow applications downloaded from" to @@ -215,11 +215,11 @@ have the wrong "lib" folder.
        1. Download the Image-ExifTool distribution from the ExifTool home page -
          (The file you download should be named "Image-ExifTool-12.73.tar.gz".)
        2. +
          (The file you download should be named "Image-ExifTool-12.74.tar.gz".)
        3. Unpack the distribution and make it your current directory by typing:
              cd <your download directory>
          -    gzip -dc Image-ExifTool-12.73.tar.gz | tar -xf -
          -    cd Image-ExifTool-12.73
          +    gzip -dc Image-ExifTool-12.74.tar.gz | tar -xf -
          +    cd Image-ExifTool-12.74
           
          (At this point you may run exiftool by typing "./exiftool <image file name>".)
        4. diff --git a/html/models.html b/html/models.html index 7e3d3204..3ccf4cd4 100644 --- a/html/models.html +++ b/html/models.html @@ -10,7 +10,7 @@

          ExifTool-tested Camera Models

          -

          Images from the following 7463 camera models have been tested with ExifTool.

          +

          Images from the following 7465 camera models have been tested with ExifTool.

          If you own a camera that doesn't appear here, please send me a sample image so I can add it to this list. (The image must be straight out of the camera and not modified by any image editor such as Photoshop. And to make @@ -130,6 +130,7 @@ iPhone 13 Pro iPhone 13 Pro Max
          iPhone 14
          iPhone 14 Pro
          +iPhone 15 Plus
          iPhone SE
          iPhone X
          iPhone XR
          @@ -7313,6 +7314,7 @@ ILCE-7S
          ILCE-7SM2
          ILCE-7SM3
          ILCE-9
          +ILCE-9M3
          ILCE-3000
          ILCE-3500
          ILCE-5000
          @@ -7813,7 +7815,7 @@ Z667T
          Z797C
          Z970


          -Last revised Jan 3, 2024 +Last revised Jan 16, 2024

          <-- Back to ExifTool home page

          diff --git a/html/sample_images.html b/html/sample_images.html index cc93d2ce..9cd1ce23 100644 --- a/html/sample_images.html +++ b/html/sample_images.html @@ -8,7 +8,7 @@

          ExifTool Meta Information Repository

          The following archives contain sample JPEG images with the original meta -information from 7007 different models of digital cameras, DV recorders, +information from 7009 different models of digital cameras, DV recorders, scanners and cell phones from 106 manufacturers. To conserve space and avoid copyright problems, the main image has been replaced, and the large preview image (and any other information found after the JPEG EOI) has been removed. @@ -34,10 +34,10 @@ repository as more suitable samples become available.

          70 kB   Aiptek.tar.gz 2010-08-30 - Apple48 -388 kB  + Apple49 +391 kB   Apple.tar.gz -2023-06-14 +2024-01-16  Asus1 23 kB   Asus.tar.gz @@ -370,10 +370,10 @@ repository as more suitable samples become available.

          82 kB   Skanhex.tar.gz 2011-06-07 - Sony748 + Sony749 8.2 MB   Sony.tar.gz -2023-11-17 +2024-01-16  Sony Ericsson196 3.4 MB   SonyEricsson.tar.gz @@ -446,12 +446,12 @@ repository as more suitable samples become available.

          351 kB   ZTE.tar.gz 2015-07-27 -Total7007 models +Total7009 models 143.6 MB 106 makes -2024-01-03 +2024-01-16
          Created May 15, 2006
          -Last revised Jan 3, 2024 +Last revised Jan 16, 2024

          <-- Back to ExifTool home page

          diff --git a/lib/File/RandomAccess.pm b/lib/File/RandomAccess.pm index 297aa6b5..b4e6da8d 100644 --- a/lib/File/RandomAccess.pm +++ b/lib/File/RandomAccess.pm @@ -17,6 +17,7 @@ # scalar with a multi-character newline # 01/24/2009 - PH Protect against reading too much at once # 10/04/2018 - PH Added NoBuffer option +# 01/20/2024 - PH Set ERROR on file read error # # Notes: Calls the normal file i/o routines unless SeekTest() fails, in # which case the file is buffered in memory to allow random access. @@ -25,6 +26,9 @@ # # May also be used for string i/o (just pass a scalar reference) # +# Sets internal ERROR member from $! if there is an error reading +# the file. +# # Legal: Copyright (c) 2003-2024, Phil Harvey (philharvey66 at gmail.com) # This library is free software; you can redistribute it and/or # modify it under the same terms as Perl itself. @@ -37,7 +41,7 @@ require 5.002; require Exporter; use vars qw($VERSION @ISA @EXPORT_OK); -$VERSION = '1.11'; +$VERSION = '1.12'; @ISA = qw(Exporter); sub Read($$$); @@ -211,6 +215,8 @@ sub Read($$$) if ($num) { ${$self->{BUFF_PT}} .= $buff; $self->{LEN} += $num; + } elsif (not defined $num) { + $self->{ERROR} = $!; } } # number of bytes left in data buffer @@ -229,7 +235,11 @@ sub Read($$$) } else { # read directly from file $_[0] = '' unless defined $_[0]; - $rtnVal = read($self->{FILE_PT}, $_[0], $len) || 0; + $rtnVal = read($self->{FILE_PT}, $_[0], $len); + unless (defined $rtnVal) { + $self->{ERROR} = $!; + $rtnVal = 0; + } } if ($self->{DEBUG}) { my $pos = $self->Tell() - $rtnVal; @@ -258,7 +268,10 @@ sub ReadLine($$) # make sure we have some data after the current position while ($self->{LEN} <= $pos) { $num = read($fp, $buff, $CHUNK_SIZE); - return 0 unless $num; + unless ($num) { + defined $num or $self->{ERROR} = $!; + return 0; + } ${$self->{BUFF_PT}} .= $buff; $self->{LEN} += $num; } @@ -270,7 +283,11 @@ sub ReadLine($$) last; } $pos = $self->{LEN}; # have scanned to end of buffer - $num = read($fp, $buff, $CHUNK_SIZE) or last; + $num = read($fp, $buff, $CHUNK_SIZE); + unless ($num) { + defined $num or $self->{ERROR} = $!; + last; + } ${$self->{BUFF_PT}} .= $buff; $self->{LEN} += $num; } @@ -314,7 +331,12 @@ sub Slurp($) my $fp = $self->{FILE_PT} || return; # read whole file into buffer (in large chunks) my ($buff, $num); - while (($num = read($fp, $buff, $CHUNK_SIZE * $SLURP_CHUNKS)) != 0) { + for (;;) { + $num = read($fp, $buff, $CHUNK_SIZE * $SLURP_CHUNKS); + unless ($num) { + defined $num or $self->{ERROR} = $!; + last; + } ${$self->{BUFF_PT}} .= $buff; $self->{LEN} += $num; } @@ -339,6 +361,10 @@ sub Purge($) $self->{POS} -= $self->{LEN}; ${$self->{BUFF_PT}} = ''; $self->{LEN} = read($self->{FILE_PT}, ${$self->{BUFF_PT}}, $SKIP_SIZE); + if (not defined $self->{LEN}) { + $self->{ERROR} = $!; + last; + } last if $self->{LEN} < $SKIP_SIZE; } } elsif ($purge > 0) { diff --git a/lib/File/RandomAccess.pod b/lib/File/RandomAccess.pod index 5ccd53fe..25930b36 100644 --- a/lib/File/RandomAccess.pod +++ b/lib/File/RandomAccess.pod @@ -16,9 +16,9 @@ File::RandomAccess - Random access reads of sequential file or scalar use File::RandomAccess; - $raf = new File::RandomAccess(\*FILE, $disableSeekTest); + $raf = File::RandomAccess->new(\*FILE, $disableSeekTest); - $raf = new File::RandomAccess(\$data); + $raf = File::RandomAccess->new(\$data); $err = $raf->Seek($pos); $num = $raf->Read($buff, $bytes); @@ -38,10 +38,10 @@ Creates a new RandomAccess object given a file reference or reference to data in memory. # Read from open file or pipe - $raf = new File::RandomAccess(\*FILE); + $raf = File::RandomAccess->new(\*FILE); # Read from data in memory - $raf = new File::RandomAccess(\$data); + $raf = File::RandomAccess->new(\$data); =over 4 diff --git a/lib/Image/ExifTool.pm b/lib/Image/ExifTool.pm index 1e4f591a..08c18a4a 100644 --- a/lib/Image/ExifTool.pm +++ b/lib/Image/ExifTool.pm @@ -29,7 +29,7 @@ use vars qw($VERSION $RELEASE @ISA @EXPORT_OK %EXPORT_TAGS $AUTOLOAD @fileTypes %jpegMarker %specialTags %fileTypeLookup $testLen $exeDir %static_vars); -$VERSION = '12.73'; +$VERSION = '12.74'; $RELEASE = ''; @ISA = qw(Exporter); %EXPORT_TAGS = ( @@ -77,7 +77,7 @@ sub GetDeleteGroups(); sub AddUserDefinedTags($%); sub SetAlternateFile($$$); # non-public routines below -sub InsertTagValues($$$;$$$); +sub InsertTagValues($$;$$$$); sub IsWritable($); sub IsSameFile($$$); sub IsRawType($); @@ -2196,7 +2196,7 @@ sub new # use Image::ExifTool 'ImageInfo'; # my $info = ImageInfo($file, 'DateTimeOriginal', 'ImageSize'); # - or - -# my $et = new Image::ExifTool; +# my $et = Image::ExifTool->new; # my $info = $et->ImageInfo($file, \@tagList, {Sort=>'Group0'} ); sub ImageInfo($;@) { @@ -2206,7 +2206,7 @@ sub ImageInfo($;@) if (ref $_[0] and UNIVERSAL::isa($_[0],'Image::ExifTool')) { $self = shift; } else { - $self = new Image::ExifTool; + $self = Image::ExifTool->new; } my %saveOptions = %{$$self{OPTIONS}}; # save original options @@ -2529,7 +2529,7 @@ sub ExtractInfo($;@) FILE_TYPE => $$self{FILE_TYPE}, }; $saveOrder = GetByteOrder(), - $$self{RAF} = new File::RandomAccess($_[0]); + $$self{RAF} = File::RandomAccess->new($_[0]); $$self{PROCESSED} = { }; delete $$self{EXIF_DATA}; delete $$self{EXIF_POS}; @@ -2636,7 +2636,7 @@ sub ExtractInfo($;@) # open the file if ($self->Open(\*EXIFTOOL_FILE, $filename)) { # create random access file object - $raf = new File::RandomAccess(\*EXIFTOOL_FILE); + $raf = File::RandomAccess->new(\*EXIFTOOL_FILE); # patch to force pipe to be buffered because seek returns success # in Windows cmd shell pipe even though it really failed $$raf{TESTED} = -1 if $filename eq '-' or $filename =~ /\|$/; @@ -2767,12 +2767,16 @@ sub ExtractInfo($;@) $raf->BinMode(); # set binary mode before we start reading my $pos = $raf->Tell(); # get file position so we can rewind # loop through list of file types to test - my ($buff, $seekErr); + my ($buff, $err); my %dirInfo = ( RAF => $raf, Base => $pos, TestBuff => \$buff ); # read start of file for testing - $raf->Read($buff, $testLen) or $buff = ''; - $raf->Seek($pos, 0) or $seekErr = 1; - until ($seekErr) { + if ($raf->Read($buff, $testLen)) { + $raf->Seek($pos, 0) or $err = 'Error seeking in file'; + } else { + $err = $$raf{ERROR}; + $buff = ''; + } + until ($err) { my $unkHeader; $type = shift @fileTypeList; if ($type) { @@ -2795,7 +2799,7 @@ sub ExtractInfo($;@) $type = ($1 eq "\xff\xd8\xff") ? 'JPEG' : 'TIFF'; my $skip = pos($buff) - length($1); $dirInfo{Base} = $pos + $skip; - $raf->Seek($pos + $skip, 0) or $seekErr = 1, last; + $raf->Seek($pos + $skip, 0) or $err = 'Error seeking in file', last; $self->Warn("Processing $type-like data after unknown $skip-byte header"); $unkHeader = 1 unless $$self{DOC_NUM}; } @@ -2841,14 +2845,13 @@ sub ExtractInfo($;@) last; } # seek back to try again from the same position in the file - $raf->Seek($pos, 0) or $seekErr = 1, last; + $raf->Seek($pos, 0) or $err = 'Error seeking in file'; } - if (not defined $type and not $$self{DOC_NUM}) { + if (not $err and not defined $type and not $$self{DOC_NUM}) { # if we were given a single image with a known type there # must be a format error since we couldn't read it, otherwise # it is likely we don't support images of this type my $fileType = GetFileType($realname) || ''; - my $err; if (not length $buff) { $err = 'File is empty'; } else { @@ -2889,10 +2892,9 @@ sub ExtractInfo($;@) } } } - $self->Error($err); } - if ($seekErr) { - $self->Error('Error seeking in file'); + if ($err) { + $self->Error($err); } elsif ($self->Options('ScanForXMP') and (not defined $type or (not $fast and not $$self{FoundXMP}))) { @@ -4114,7 +4116,7 @@ sub Init($) $$self{FileType} = ''; # identified file type if ($self->Options('HtmlDump')) { require Image::ExifTool::HtmlDump; - $$self{HTML_DUMP} = new Image::ExifTool::HtmlDump; + $$self{HTML_DUMP} = Image::ExifTool::HtmlDump->new; } # make sure our TextOut is a file reference $$self{OPTIONS}{TextOut} = \*STDOUT unless ref $$self{OPTIONS}{TextOut}; @@ -4177,7 +4179,7 @@ sub ExtractAltInfo($) # (eg. -file1 '$originalfilename') if ($fileName =~ /\$/) { my @tags = reverse sort keys %{$$self{VALUE}}; - $fileName = $self->InsertTagValues(\@tags, $fileName, 'Warn'); + $fileName = $self->InsertTagValues($fileName, \@tags, 'Warn'); next unless defined $fileName; } $altExifTool->ExtractInfo($fileName); @@ -4504,7 +4506,7 @@ sub GetFileTime($$) $atime = $mtime = $ctime = pack 'LL', 0, 0; unless ($k32GetFileTime) { return () if defined $k32GetFileTime; - $k32GetFileTime = new Win32::API('KERNEL32', 'GetFileTime', 'NPPP', 'I'); + $k32GetFileTime = Win32::API->new('KERNEL32', 'GetFileTime', 'NPPP', 'I'); unless ($k32GetFileTime) { $self->Warn('Error calling Win32::API::GetFileTime'); $k32GetFileTime = 0; @@ -4583,7 +4585,7 @@ sub ParseArguments($;@) my $buff = $@ ? pack('C*',unpack($] < 5.010000 ? 'U0C*' : 'C0C*',$$arg)) : Encode::encode('utf8',$$arg); $arg = \$buff; } - $$self{RAF} = new File::RandomAccess($arg); + $$self{RAF} = File::RandomAccess->new($arg); # set filename to empty string to indicate that # we have a file but we didn't open it $$self{FILENAME} = ''; @@ -6981,7 +6983,7 @@ sub ProcessJPEG($$) } elsif ($$segDataPt =~ /^(II|MM).{4}HEAPJPGM/s) { next if $fast > 1; # skip processing for very fast $dumpType = 'CIFF'; - my %dirInfo = ( RAF => new File::RandomAccess($segDataPt) ); + my %dirInfo = ( RAF => File::RandomAccess->new($segDataPt) ); $$self{SET_GROUP1} = 'CIFF'; push @{$$self{PATH}}, 'CIFF'; require Image::ExifTool::CanonRaw; @@ -7506,6 +7508,8 @@ sub ProcessJPEG($$) } elsif ($$segDataPt =~ /^AROT\0/ and $length > 10) { # iPhone "AROT" segment containing integrated intensity per 16 scan lines # (with number of elements N = ImageHeight / 16 - 1, ref PH/NealKrawetz) + # "Absolute ROTational difference between two frames" + # (see https://www.hackerfactor.com/blog/index.php?/archives/822-Apple-Rot.html) $xtra = 'segment (N=' . unpack('x6N', $$segDataPt) . ')'; } } elsif ($marker == 0xeb) { # APP11 (JPEG-HDR, JUMBF) @@ -8005,7 +8009,7 @@ sub DoProcessTIFF($$;$) } } # update FileType if necessary now that we know more about the file - if ($$self{DNGVersion} and $$self{FileType} !~ /^(DNG|GPR)$/) { + if ($$self{DNGVersion} and $$self{FILE_TYPE} eq 'TIFF' and $$self{FileType} !~ /^(DNG|GPR)$/) { # override whatever FileType we set since we now know it is DNG $self->OverrideFileType($$self{TIFF_TYPE} = 'DNG'); } diff --git a/lib/Image/ExifTool.pod b/lib/Image/ExifTool.pod index b4851038..153e4a46 100644 --- a/lib/Image/ExifTool.pod +++ b/lib/Image/ExifTool.pod @@ -619,7 +619,8 @@ DateFormat of "%Y:%m:%d %H:%M:%S"). =item Duplicates Flag to return values from tags with duplicate names when extracting -information. Default is 1. +information. Default is 1. Forced to 1 when copying tags with +L. =item Escape @@ -824,11 +825,11 @@ Default is undef. =item LimitLongValues -When extracting some values that may be very long, the PrintConv values are -length-limited and the value is truncated with an elipsis ("[...]") if it -exceeds a specified length. This option specifies the length limit for -these tags. A setting of 4 or less disables the limit (because the elipsis -string is longer than this). Default is 60. +When extracting values for some specific tags (usually Unknown tags), the +PrintConv values are length-limited and the value is truncated with an +ellipsis ("[...]") if it exceeds a specified length. This option specifies +the length limit for these tags. A setting of 4 or less disables the limit +(because the ellipsis string is longer than this). Default is 60. =item ListItem diff --git a/lib/Image/ExifTool/7Z.pm b/lib/Image/ExifTool/7Z.pm index 1b8d0bc9..0a048cd5 100644 --- a/lib/Image/ExifTool/7Z.pm +++ b/lib/Image/ExifTool/7Z.pm @@ -15,7 +15,7 @@ use strict; use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.00'; +$VERSION = '1.01'; sub ReadUInt32 { my $buff; @@ -569,7 +569,7 @@ sub ReadFilesInfo { next; } $_[0]->Read($buff, $size); - my $buffer = new File::RandomAccess(\$buff); + my $buffer = File::RandomAccess->new(\$buff); if($prop == 14){ # empty stream my @isempty = ReadBoolean($buffer, $numfiles, 0); my $numemptystreams = 0; @@ -732,7 +732,7 @@ sub Process7Z($$) $folder_data .= Decompress($et, $raf, $decomporessor, $remaining); $remaining = $uncompressed_size - length($folder_data); } - $buffer2 = new File::RandomAccess(\$folder_data); + $buffer2 = File::RandomAccess->new(\$folder_data); } $buffer2->Seek(0, 0); $buffer2->Read($buff, 1); diff --git a/lib/Image/ExifTool/AFCP.pm b/lib/Image/ExifTool/AFCP.pm index 1a8aa24c..d2de0f39 100644 --- a/lib/Image/ExifTool/AFCP.pm +++ b/lib/Image/ExifTool/AFCP.pm @@ -14,7 +14,7 @@ use strict; use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.08'; +$VERSION = '1.09'; sub ProcessAFCP($$); @@ -134,7 +134,7 @@ NoAFCP: for (;;) { $dirBuff = $valBuff = ''; require Image::ExifTool::Fixup; $fixup = $$dirInfo{Fixup}; - $fixup or $fixup = $$dirInfo{Fixup} = new Image::ExifTool::Fixup; + $fixup or $fixup = $$dirInfo{Fixup} = Image::ExifTool::Fixup->new; $vers = substr($buff, 4, 2); # get version number } else { $et->DumpTrailer($dirInfo) if $verbose or $$et{HTML_DUMP}; diff --git a/lib/Image/ExifTool/BZZ.pm b/lib/Image/ExifTool/BZZ.pm index 3bbb59c5..fd06fdc8 100644 --- a/lib/Image/ExifTool/BZZ.pm +++ b/lib/Image/ExifTool/BZZ.pm @@ -19,7 +19,7 @@ use integer; # IMPORTANT!! use integer arithmetic throughout require Exporter; use vars qw($VERSION @ISA @EXPORT_OK); -$VERSION = '1.00'; +$VERSION = '1.01'; @ISA = qw(Exporter); @EXPORT_OK = qw(Decode); @@ -196,7 +196,7 @@ sub Decode($;$) if (ref $_[0] and UNIVERSAL::isa($_[0],'Image::ExifTool::BZZ')) { $self = shift; } else { - $self = new Image::ExifTool::BZZ; + $self = Image::ExifTool::BZZ->new; } my $dataPt = shift; if ($dataPt) { diff --git a/lib/Image/ExifTool/BuildTagLookup.pm b/lib/Image/ExifTool/BuildTagLookup.pm index 4b348d83..f813853a 100644 --- a/lib/Image/ExifTool/BuildTagLookup.pm +++ b/lib/Image/ExifTool/BuildTagLookup.pm @@ -35,7 +35,7 @@ use Image::ExifTool::Sony; use Image::ExifTool::Validate; use Image::ExifTool::MacOS; -$VERSION = '3.52'; +$VERSION = '3.53'; @ISA = qw(Exporter); sub NumbersFirst($$); @@ -797,7 +797,7 @@ sub new } my $tableNum = 0; - my $et = new Image::ExifTool; + my $et = Image::ExifTool->new; my ($tableName, $tag); # create lookup for short table names foreach $tableName (@tableNames) { @@ -1727,12 +1727,12 @@ sub WriteTagLookup($$) } #------------------------------------------------------------------------------ -# Sort numbers first numerically, then strings alphabetically (case insensitive) +# Sort numbers first numerically, then strings alphabetically +# - case-insensitive sorting set by global variable $caseInsensitive # - two global variables are used to change the sort algorithm: # $numbersFirst: -1 = put numbers after other strings # 1 = put numbers before other strings # 2 = put numbers first, but negative numbers last -# $caseInsensitive: flag set for case-insensitive sorting sub NumbersFirst($$) { my ($a, $b) = @_; @@ -2742,7 +2742,7 @@ validation and consistency checks on the tag tables. use Image::ExifTool::BuildTagLookup; - $builder = new Image::ExifTool::BuildTagLookup; + $builder = Image::ExifTool::BuildTagLookup->new; # update Image::ExifTool::TagLookup $ok = $builder->WriteTagLookup('lib/Image/ExifTool/TagLookup.pm'); diff --git a/lib/Image/ExifTool/Canon.pm b/lib/Image/ExifTool/Canon.pm index 9f0d36ed..3dd9709f 100644 --- a/lib/Image/ExifTool/Canon.pm +++ b/lib/Image/ExifTool/Canon.pm @@ -88,7 +88,7 @@ sub ProcessCTMD($$$); sub ProcessExifInfo($$$); sub SwapWords($); -$VERSION = '4.72'; +$VERSION = '4.73'; # Note: Removed 'USM' from 'L' lenses since it is redundant - PH # (or is it? Ref 32 shows 5 non-USM L-type lenses) @@ -1394,7 +1394,7 @@ my %offOn = ( 0 => 'Off', 1 => 'On' ); }, { Name => 'CanonCameraInfoR6', - Condition => '$$self{Model} =~ /\bEOS R6$/', + Condition => '$$self{Model} =~ /\bEOS R[56]$/', SubDirectory => { TagTable => 'Image::ExifTool::Canon::CameraInfoR6' }, }, { @@ -4714,7 +4714,7 @@ my %ciMaxFocal = ( PRIORITY => 0, GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, NOTES => 'CameraInfo tags for the EOS R6.', - 0x0af1 => { #forum15210 + 0x0af1 => { #forum15210/15579 Name => 'ShutterCount', Format => 'int32u', Notes => 'includes electronic + mechanical shutter', diff --git a/lib/Image/ExifTool/CanonVRD.pm b/lib/Image/ExifTool/CanonVRD.pm index 5bee205a..11da665f 100644 --- a/lib/Image/ExifTool/CanonVRD.pm +++ b/lib/Image/ExifTool/CanonVRD.pm @@ -23,7 +23,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Canon; -$VERSION = '1.36'; +$VERSION = '1.37'; sub ProcessCanonVRD($$;$); sub WriteCanonVRD($$;$); @@ -2011,7 +2011,7 @@ sub ProcessCanonVRD($$;$) $verbose and print $out " Creating CanonVRD trailer\n"; $created = 1; } - $raf = new File::RandomAccess($dataPt); + $raf = File::RandomAccess->new($dataPt); } # read and validate the footer $raf->Seek(-0x40-$offset, 2) or return 0; diff --git a/lib/Image/ExifTool/DICOM.pm b/lib/Image/ExifTool/DICOM.pm index 147336a1..3bac7792 100644 --- a/lib/Image/ExifTool/DICOM.pm +++ b/lib/Image/ExifTool/DICOM.pm @@ -20,7 +20,7 @@ use strict; use vars qw($VERSION %uid); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.22'; +$VERSION = '1.23'; # DICOM VR (Value Representation) format conversions my %dicomFormat = ( @@ -3668,7 +3668,7 @@ sub ProcessDICOM($$) } last if length $data < 8; # create new RAF object from inflated data stream - $raf = new File::RandomAccess(\$data); + $raf = File::RandomAccess->new(\$data); # re-read start of stream (now decompressed) $raf->Read($buff, 8) == 8 or last; $group = Get16u(\$buff, 0); diff --git a/lib/Image/ExifTool/DNG.pm b/lib/Image/ExifTool/DNG.pm index e43683d6..4b937ffd 100644 --- a/lib/Image/ExifTool/DNG.pm +++ b/lib/Image/ExifTool/DNG.pm @@ -17,7 +17,7 @@ use Image::ExifTool::Exif; use Image::ExifTool::MakerNotes; use Image::ExifTool::CanonRaw; -$VERSION = '1.24'; +$VERSION = '1.25'; sub ProcessOriginalRaw($$$); sub ProcessAdobeData($$$); @@ -516,7 +516,7 @@ sub ProcessAdobeMRW($$$) my $buff = "\0MRM" . pack('N', $dirLen - 4); # ignore leading byte order and directory count words $buff .= substr($$dataPt, $dirStart + 4, $dirLen - 4); - my $raf = new File::RandomAccess(\$buff); + my $raf = File::RandomAccess->new(\$buff); my %dirInfo = ( RAF => $raf, OutFile => $outfile ); my $rtnVal = Image::ExifTool::MinoltaRaw::ProcessMRW($et, \%dirInfo); if ($outfile and defined $$outfile and length $$outfile) { @@ -548,7 +548,7 @@ sub ProcessAdobeRAF($$$) } $et->VerboseDir($dirInfo); # make fake RAF object for processing (same acronym, different meaning) - my $raf = new File::RandomAccess($dataPt); + my $raf = File::RandomAccess->new($dataPt); my $num = ''; # loop through all records in Adobe RAF data: # 0 - RAF table (not processed) @@ -752,7 +752,7 @@ sub ProcessAdobeMakN($$$) } if ($outfile) { # rewrite the maker notes directory - my $fixup = $subdirInfo{Fixup} = new Image::ExifTool::Fixup; + my $fixup = $subdirInfo{Fixup} = Image::ExifTool::Fixup->new; my $oldChanged = $$et{CHANGED}; my $buff = $et->WriteDirectory(\%subdirInfo, $subTable); # nothing to do if error writing directory or nothing changed diff --git a/lib/Image/ExifTool/Exif.pm b/lib/Image/ExifTool/Exif.pm index 227bac24..0d9b30cc 100644 --- a/lib/Image/ExifTool/Exif.pm +++ b/lib/Image/ExifTool/Exif.pm @@ -57,7 +57,7 @@ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::MakerNotes; -$VERSION = '4.48'; +$VERSION = '4.49'; sub ProcessExif($$$); sub WriteExif($$$); @@ -6465,7 +6465,7 @@ sub ProcessExif($$$) TagInfo => $tagInfo || $tmpInfo, Offset => $base + $valuePtr + $dataPos, Size => $size, - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, }; } } else { diff --git a/lib/Image/ExifTool/FLIR.pm b/lib/Image/ExifTool/FLIR.pm index efdaf1c4..4d020be0 100644 --- a/lib/Image/ExifTool/FLIR.pm +++ b/lib/Image/ExifTool/FLIR.pm @@ -24,7 +24,7 @@ use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; use Image::ExifTool::GPS; -$VERSION = '1.22'; +$VERSION = '1.23'; sub ProcessFLIR($$;$); sub ProcessFLIRText($$$); @@ -1468,7 +1468,7 @@ sub ProcessMeasInfo($$$) sub ProcessFLIR($$;$) { my ($et, $dirInfo, $tagTablePtr) = @_; - my $raf = $$dirInfo{RAF} || new File::RandomAccess($$dirInfo{DataPt}); + my $raf = $$dirInfo{RAF} || File::RandomAccess->new($$dirInfo{DataPt}); my $verbose = $et->Options('Verbose'); my $out = $et->Options('TextOut'); my $base = $raf->Tell(); diff --git a/lib/Image/ExifTool/Fixup.pm b/lib/Image/ExifTool/Fixup.pm index d940e7c5..0ba4fb1a 100644 --- a/lib/Image/ExifTool/Fixup.pm +++ b/lib/Image/ExifTool/Fixup.pm @@ -39,7 +39,7 @@ use Image::ExifTool qw(GetByteOrder SetByteOrder Get32u Get32s Set32u Get16u Get16s Set16u); use vars qw($VERSION); -$VERSION = '1.05'; +$VERSION = '1.06'; sub AddFixup($$;$$); sub ApplyFixup($$); @@ -69,7 +69,7 @@ sub new sub Clone($) { my $self = shift; - my $clone = new Image::ExifTool::Fixup; + my $clone = Image::ExifTool::Fixup->new; $clone->{Start} = $self->{Start}; $clone->{Shift} = $self->{Shift}; my $phash = $self->{Pointers}; @@ -317,7 +317,7 @@ Image::ExifTool::Fixup - Utility to handle pointer fixups use Image::ExifTool::Fixup; - $fixup = new Image::ExifTool::Fixup; + $fixup = Image::ExifTool::Fixup->new; # add a new fixup to a pointer at the specified offset in data $fixup->AddFixup($offset); diff --git a/lib/Image/ExifTool/FlashPix.pm b/lib/Image/ExifTool/FlashPix.pm index 442a1357..a1320b98 100644 --- a/lib/Image/ExifTool/FlashPix.pm +++ b/lib/Image/ExifTool/FlashPix.pm @@ -22,7 +22,7 @@ use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; use Image::ExifTool::ASF; # for GetGUID() -$VERSION = '1.47'; +$VERSION = '1.48'; sub ProcessFPX($$); sub ProcessFPXR($$$); @@ -2206,7 +2206,7 @@ sub ProcessFPX($$) my ($tag, %hier, %objIndex, %loadedDifSect); # handle FPX format in memory from PNG cpIp chunk - $raf or $raf = new File::RandomAccess($$dirInfo{DataPt}); + $raf or $raf = File::RandomAccess->new($$dirInfo{DataPt}); # read header return 0 unless $raf->Read($buff,HDR_SIZE) == HDR_SIZE; @@ -2353,7 +2353,7 @@ sub ProcessFPX($$) $et->Warn('Error loading Mini-FAT stream'); last; } - $miniStream = new File::RandomAccess(\$miniStreamBuff); + $miniStream = File::RandomAccess->new(\$miniStreamBuff); } my $tagInfo; diff --git a/lib/Image/ExifTool/FujiFilm.pm b/lib/Image/ExifTool/FujiFilm.pm index a4628ba4..30d78304 100644 --- a/lib/Image/ExifTool/FujiFilm.pm +++ b/lib/Image/ExifTool/FujiFilm.pm @@ -31,7 +31,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; -$VERSION = '1.91'; +$VERSION = '1.92'; sub ProcessFujiDir($$$); sub ProcessFaceRec($$$); @@ -1187,6 +1187,8 @@ my %faceCategories = ( ValueConv => 'my @v=reverse split(" ",$val);"@v"', # reverse to show width first PrintConv => '$val=~tr/ /x/; $val', }, + # 0x112 - int16u[2] same as 0x111 but with width/height swapped? + # 0x113 - int16u[2] same as 0x111? 0x115 => { Name => 'RawImageAspectRatio', Format => 'int16u', @@ -1236,6 +1238,7 @@ my %faceCategories = ( Count => 36, PrintConv => '$val =~ tr/012 /RGB/d; join " ", $val =~ /....../g', }, + # 0x141 - int16u[2] Bit depth? "14 42" for 14-bit RAF and "16 48" for 16-bit RAF 0x2000 => { #IB Name => 'WB_GRGBLevelsAuto', Format => 'int16u', @@ -1408,6 +1411,8 @@ my %faceCategories = ( 0xf00e => 'WB_GRBLevels', 0xf00f => 'ChromaticAberrationParams', # (rational64s[23]) 0xf010 => 'VignettingParams', #9 (rational64s[31 or 64]) + # 0xf013 - int32u[3] same as 0xf00d + # 0xf014 - int32u[3] - also related to WhiteBalance ); # information found in FFMV atom of MOV videos @@ -1688,7 +1693,7 @@ sub WriteRAF($$) # rewrite the embedded JPEG in memory my %jpegInfo = ( Parent => 'RAF', - RAF => new File::RandomAccess(\$jpeg), + RAF => File::RandomAccess->new(\$jpeg), OutFile => \$outJpeg, ); $$et{FILE_TYPE} = 'JPEG'; @@ -1792,7 +1797,7 @@ sub ProcessRAF($$) # extract information from embedded JPEG my %dirInfo = ( Parent => 'RAF', - RAF => new File::RandomAccess(\$jpeg), + RAF => File::RandomAccess->new(\$jpeg), ); if ($jpos) { $$et{BASE} += $jpos; diff --git a/lib/Image/ExifTool/Geotag.pm b/lib/Image/ExifTool/Geotag.pm index 08b131a4..55bf8a59 100644 --- a/lib/Image/ExifTool/Geotag.pm +++ b/lib/Image/ExifTool/Geotag.pm @@ -29,7 +29,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:Public); use Image::ExifTool::GPS; -$VERSION = '1.73'; +$VERSION = '1.74'; sub JITTER() { return 2 } # maximum time jitter @@ -174,7 +174,7 @@ sub LoadTrackLog($$;$) # $val is track file name if ($et->Open(\*EXIFTOOL_TRKFILE, $val)) { $trackFile = $val; - $raf = new File::RandomAccess(\*EXIFTOOL_TRKFILE); + $raf = File::RandomAccess->new(\*EXIFTOOL_TRKFILE); unless ($raf->Read($_, 256)) { close EXIFTOOL_TRKFILE; return "Empty track file '${val}'"; @@ -202,7 +202,7 @@ sub LoadTrackLog($$;$) } unless ($from) { # set up RAF for reading log file in memory - $raf = new File::RandomAccess(\$val); + $raf = File::RandomAccess->new(\$val); $from = 'data'; } diff --git a/lib/Image/ExifTool/HtmlDump.pm b/lib/Image/ExifTool/HtmlDump.pm index ae2f70db..cbc3cb43 100644 --- a/lib/Image/ExifTool/HtmlDump.pm +++ b/lib/Image/ExifTool/HtmlDump.pm @@ -13,7 +13,7 @@ use vars qw($VERSION); use Image::ExifTool; # only for FinishTiffDump() use Image::ExifTool::HTML qw(EscapeHTML); -$VERSION = '1.39'; +$VERSION = '1.40'; sub DumpTable($$$;$$$$$$); sub Open($$$;@); @@ -894,7 +894,7 @@ Image::ExifTool::HtmlDump - Dump information in hex to HTML page =head1 SYNOPSIS use Image::ExifTool::HtmlDump; - my $dump = new Image::ExifTool::HtmlDump; + my $dump = Image::ExifTool::HtmlDump->new; $dump->Add($start, $size, $comment); $dump->Print($dumpInfo, $raf, $dataPt, $dataPos, $outfile); diff --git a/lib/Image/ExifTool/ID3.pm b/lib/Image/ExifTool/ID3.pm index 840e64d6..24337f8a 100644 --- a/lib/Image/ExifTool/ID3.pm +++ b/lib/Image/ExifTool/ID3.pm @@ -18,7 +18,7 @@ use strict; use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.60'; +$VERSION = '1.61'; sub ProcessID3v2($$$); sub ProcessPrivate($$$); @@ -1408,7 +1408,7 @@ sub ProcessID3($$) $$et{DoneID3} = 1; # allow this to be called with either RAF or DataPt - my $raf = $$dirInfo{RAF} || new File::RandomAccess($$dirInfo{DataPt}); + my $raf = $$dirInfo{RAF} || File::RandomAccess->new($$dirInfo{DataPt}); my ($buff, %id3Header, %id3Trailer, $hBuff, $tBuff, $eBuff, $tagTablePtr); my $rtnVal = 0; my $hdrEnd = 0; diff --git a/lib/Image/ExifTool/Import.pm b/lib/Image/ExifTool/Import.pm index 2b2ba83f..84d73085 100644 --- a/lib/Image/ExifTool/Import.pm +++ b/lib/Image/ExifTool/Import.pm @@ -12,7 +12,7 @@ require Exporter; use vars qw($VERSION @ISA @EXPORT_OK); -$VERSION = '1.10'; +$VERSION = '1.11'; @ISA = qw(Exporter); @EXPORT_OK = qw(ReadCSV ReadJSON); @@ -38,13 +38,13 @@ sub ReadCSV($$;$$) $raf = $file; $file = 'CSV file'; } elsif (ref $file eq 'GLOB') { - $raf = new File::RandomAccess($file); + $raf = File::RandomAccess->new($file); $file = 'CSV file'; } else { open CSVFILE, $file or return "Error opening CSV file '${file}'"; binmode CSVFILE; $openedFile = 1; - $raf = new File::RandomAccess(\*CSVFILE); + $raf = File::RandomAccess->new(\*CSVFILE); } $delim = ',' unless defined $delim; # set input record separator by first newline found in the file @@ -253,13 +253,13 @@ sub ReadJSON($$;$$) $raf = $file; $file = 'JSON file'; } elsif (ref $file eq 'GLOB') { - $raf = new File::RandomAccess($file); + $raf = File::RandomAccess->new($file); $file = 'JSON file'; } else { open JSONFILE, $file or return "Error opening JSON file '${file}'"; binmode JSONFILE; $openedFile = 1; - $raf = new File::RandomAccess(\*JSONFILE); + $raf = File::RandomAccess->new(\*JSONFILE); } my $obj = ReadJSONObject($raf); close JSONFILE if $openedFile; diff --git a/lib/Image/ExifTool/JSON.pm b/lib/Image/ExifTool/JSON.pm index bc6f3dfb..bbaa6f6f 100644 --- a/lib/Image/ExifTool/JSON.pm +++ b/lib/Image/ExifTool/JSON.pm @@ -14,7 +14,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Import; -$VERSION = '1.06'; +$VERSION = '1.07'; sub ProcessJSON($$); sub ProcessTag($$$$%); @@ -120,7 +120,7 @@ sub ProcessJSON($$) my $buff = substr(${$$dirInfo{DataPt}}, $$dirInfo{DirStart}, $$dirInfo{DirLen}); $dataPt = \$buff; } - $raf = new File::RandomAccess($dataPt); + $raf = File::RandomAccess->new($dataPt); # extract as a block if requested my $blockName = $$dirInfo{BlockInfo} ? $$dirInfo{BlockInfo}{Name} : ''; my $blockExtract = $et->Options('BlockExtract'); diff --git a/lib/Image/ExifTool/Jpeg2000.pm b/lib/Image/ExifTool/Jpeg2000.pm index 0a10f9ba..8aef5777 100644 --- a/lib/Image/ExifTool/Jpeg2000.pm +++ b/lib/Image/ExifTool/Jpeg2000.pm @@ -16,7 +16,7 @@ use strict; use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.37'; +$VERSION = '1.38'; sub ProcessJpeg2000Box($$$); sub ProcessJUMD($$$); @@ -1583,7 +1583,7 @@ sub ProcessJXL($$) $$et{IsJXL} = 2; my $buff = "\0\0\0\x0cJXL \x0d\x0a\x87\x0a\0\0\0\x14ftypjxl \0\0\0\0jxl "; # add metadata to empty ISO BMFF container - $$dirInfo{RAF} = new File::RandomAccess(\$buff); + $$dirInfo{RAF} = File::RandomAccess->new(\$buff); } else { $et->SetFileType('JXL Codestream','image/jxl', 'jxl'); if ($$et{ImageDataHash} and $raf->Seek(0,0)) { diff --git a/lib/Image/ExifTool/MIE.pm b/lib/Image/ExifTool/MIE.pm index f693d61b..109e38a6 100644 --- a/lib/Image/ExifTool/MIE.pm +++ b/lib/Image/ExifTool/MIE.pm @@ -14,7 +14,7 @@ use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; use Image::ExifTool::GPS; -$VERSION = '1.52'; +$VERSION = '1.53'; sub ProcessMIE($$); sub ProcessMIEGroup($$$); @@ -1077,7 +1077,7 @@ sub WriteMIEGroup($$$) $newVal = ''; %subdirInfo = ( OutFile => \$newVal, - RAF => new File::RandomAccess(\$oldVal), + RAF => File::RandomAccess(\$oldVal)->new, ); } elsif ($optCompress and not $$dirInfo{IsCompressed}) { # write to memory so we can compress the new MIE group @@ -1585,7 +1585,7 @@ sub ProcessMIEGroup($$$) WasCompressed => $wasCompressed, ); # read from uncompressed data instead if necessary - $subdirInfo{RAF} = new File::RandomAccess(\$value) if $valLen; + $subdirInfo{RAF} = File::RandomAccess(\$value)->new if $valLen; my $oldOrder = GetByteOrder(); SetByteOrder($format & 0x08 ? 'II' : 'MM'); diff --git a/lib/Image/ExifTool/MinoltaRaw.pm b/lib/Image/ExifTool/MinoltaRaw.pm index 1523302a..6f3015d5 100644 --- a/lib/Image/ExifTool/MinoltaRaw.pm +++ b/lib/Image/ExifTool/MinoltaRaw.pm @@ -17,7 +17,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Minolta; -$VERSION = '1.19'; +$VERSION = '1.20'; sub ProcessMRW($$;$); sub WriteMRW($$;$); @@ -400,7 +400,7 @@ sub ProcessMRW($$;$) if ($$dirInfo{DataPt}) { # make a RAF object for MRW information extracted from other file types - $raf = new File::RandomAccess($$dirInfo{DataPt}); + $raf = File::RandomAccess->new($$dirInfo{DataPt}); # MRW information in DNG images may not start at beginning of data block $raf->Seek($$dirInfo{DirStart}, 0) if $$dirInfo{DirStart}; } diff --git a/lib/Image/ExifTool/Nikon.pm b/lib/Image/ExifTool/Nikon.pm index 0b2bbf71..9fbd9863 100644 --- a/lib/Image/ExifTool/Nikon.pm +++ b/lib/Image/ExifTool/Nikon.pm @@ -65,7 +65,7 @@ use Image::ExifTool::Exif; use Image::ExifTool::GPS; use Image::ExifTool::XMP; -$VERSION = '4.29'; +$VERSION = '4.30'; sub LensIDConv($$$); sub ProcessNikonAVI($$$); @@ -677,6 +677,7 @@ sub GetAFPointGrid($$;$); '71 48 64 64 24 24 00 00' => 'Voigtlander APO-Skopar 90mm F2.8 SL IIs', #30 'FD 00 50 50 18 18 DF 00' => 'Voigtlander APO-Lanthar 50mm F2 Aspherical', #35 'FD 00 44 44 18 18 DF 00' => 'Voigtlander APO-Lanthar 35mm F2', #30 + 'FD 00 59 59 18 18 DF 00' => 'Voigtlander Macro APO-Lanthar 65mm F2', #30 # '00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2', '00 48 27 27 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/15 ZF.2', #MykytaKozlov @@ -690,6 +691,7 @@ sub GetAFPointGrid($$;$); '00 54 62 62 0C 0C 00 00' => 'Carl Zeiss Planar T* 1.4/85 ZF.2', '00 54 68 68 18 18 00 00' => 'Carl Zeiss Makro-Planar T* 2/100 ZF.2', '00 54 72 72 18 18 00 00' => 'Carl Zeiss Apo Sonnar T* 2/135 ZF.2', + '02 54 3C 3C 0C 0C 00 00' => 'Zeiss Otus 1.4/28 ZF.2', #30 '00 54 53 53 0C 0C 00 00' => 'Zeiss Otus 1.4/55', #IB '01 54 62 62 0C 0C 00 00' => 'Zeiss Otus 1.4/85', '03 54 68 68 0C 0C 00 00' => 'Zeiss Otus 1.4/100', #IB diff --git a/lib/Image/ExifTool/NikonCustom.pm b/lib/Image/ExifTool/NikonCustom.pm index 7aff0833..8fbc76ae 100644 --- a/lib/Image/ExifTool/NikonCustom.pm +++ b/lib/Image/ExifTool/NikonCustom.pm @@ -9852,7 +9852,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' ); 85 => { Name => 'HighSpeedSync', PrintConv => \%offOn }, # CSe1-b 87 => { # CSe2 Name => 'FlashShutterSpeed', - ValueConv => 'my $t = ($val - 16) % 24; $t ? $val / 24 : 2 + ($val - 16) / 24', #unusual decode perhaps due to need to accomodate 4 new values? + ValueConv => 'my $t = ($val - 16) % 24; $t ? $val / 24 : 2 + ($val - 16) / 24', #unusual decode perhaps due to need to accommodate 4 new values? PrintConv => { 0 => '1 s', 1 => '1/2 s', @@ -10242,7 +10242,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' ); 85 => { Name => 'HighSpeedSync', PrintConv => \%offOn }, # CSe1-b 87 => { # CSe2 Name => 'FlashShutterSpeed', - ValueConv => 'my $t = ($val - 16) % 24; $t ? $val / 24 : 2 + ($val - 16) / 24', #unusual decode perhaps due to need to accomodate 4 new values? + ValueConv => 'my $t = ($val - 16) % 24; $t ? $val / 24 : 2 + ($val - 16) / 24', #unusual decode perhaps due to need to accommodate 4 new values? PrintConv => { 0 => '1 s', 1 => '1/2 s', @@ -10652,7 +10652,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' ); 85 => { Name => 'HighSpeedSync', PrintConv => \%offOn }, # CSe1-b 87 => { # CSe2 Name => 'FlashShutterSpeed', - ValueConv => 'my $t = ($val - 16) % 24; $t ? $val / 24 : 2 + ($val - 16) / 24', #unusual decode perhaps due to need to accomodate 4 new values? + ValueConv => 'my $t = ($val - 16) % 24; $t ? $val / 24 : 2 + ($val - 16) / 24', #unusual decode perhaps due to need to accommodate 4 new values? PrintConv => { 0 => '1 s', 1 => '1/2 s', diff --git a/lib/Image/ExifTool/Ogg.pm b/lib/Image/ExifTool/Ogg.pm index 34ff5273..7b07c593 100644 --- a/lib/Image/ExifTool/Ogg.pm +++ b/lib/Image/ExifTool/Ogg.pm @@ -17,7 +17,7 @@ use strict; use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.02'; +$VERSION = '1.03'; my $MAX_PACKETS = 2; # maximum packets to scan from each stream at start of file @@ -189,7 +189,7 @@ sub ProcessOGG($$) if (defined $numFlac and defined $val{$stream}) { # process FLAC headers as if it was a complete FLAC file require Image::ExifTool::FLAC; - my %dirInfo = ( RAF => new File::RandomAccess(\$val{$stream}) ); + my %dirInfo = ( RAF => File::RandomAccess->new(\$val{$stream}) ); Image::ExifTool::FLAC::ProcessFLAC($et, \%dirInfo); } return $success; diff --git a/lib/Image/ExifTool/PLIST.pm b/lib/Image/ExifTool/PLIST.pm index 6cc81c35..21ba713d 100644 --- a/lib/Image/ExifTool/PLIST.pm +++ b/lib/Image/ExifTool/PLIST.pm @@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::XMP; use Image::ExifTool::GPS; -$VERSION = '1.11'; +$VERSION = '1.12'; sub ExtractObject($$;$); sub Get24u($$); @@ -351,9 +351,9 @@ sub ProcessBinaryPLIST($$;$) my $start = $$dirInfo{DirStart}; if ($start or ($$dirInfo{DirLen} and $$dirInfo{DirLen} != length $$dataPt)) { my $buf2 = substr($$dataPt, $start || 0, $$dirInfo{DirLen}); - $$dirInfo{RAF} = new File::RandomAccess(\$buf2); + $$dirInfo{RAF} = File::RandomAccess->new(\$buf2); } else { - $$dirInfo{RAF} = new File::RandomAccess($dataPt); + $$dirInfo{RAF} = File::RandomAccess->new($dataPt); } my $strt = $$dirInfo{DirStart} || 0; } diff --git a/lib/Image/ExifTool/PanasonicRaw.pm b/lib/Image/ExifTool/PanasonicRaw.pm index d0e2f594..9ca9f124 100644 --- a/lib/Image/ExifTool/PanasonicRaw.pm +++ b/lib/Image/ExifTool/PanasonicRaw.pm @@ -21,7 +21,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; -$VERSION = '1.28'; +$VERSION = '1.29'; sub ProcessJpgFromRaw($$$); sub WriteJpgFromRaw($$$); @@ -839,7 +839,7 @@ sub WriteJpgFromRaw($$$) my $buff = substr($$dataPt, $dirStart, $dirLen); $dataPt = \$buff; } - my $raf = new File::RandomAccess($dataPt); + my $raf = File::RandomAccess->new($dataPt); my $outbuff; my %dirInfo = ( RAF => $raf, @@ -890,7 +890,7 @@ sub ProcessJpgFromRaw($$$) # extract information from embedded JPEG my %dirInfo = ( Parent => 'RAF', - RAF => new File::RandomAccess($dataPt), + RAF => File::RandomAccess->new($dataPt), ); if ($verbose) { my $indent = $$et{INDENT}; diff --git a/lib/Image/ExifTool/PhaseOne.pm b/lib/Image/ExifTool/PhaseOne.pm index 73d78908..7c32dcf9 100644 --- a/lib/Image/ExifTool/PhaseOne.pm +++ b/lib/Image/ExifTool/PhaseOne.pm @@ -15,7 +15,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; -$VERSION = '1.09'; +$VERSION = '1.10'; sub WritePhaseOne($$$); sub ProcessPhaseOne($$$); @@ -473,7 +473,7 @@ sub WritePhaseOne($$$) return undef if $numEntries < 2 or $numEntries > 300 or $ifdEnd > $dirLen; my $hdrBuff = $hdr; my $valBuff = ''; # buffer for value data - my $fixup = new Image::ExifTool::Fixup; + my $fixup = Image::ExifTool::Fixup->new; my $index; for ($index=0; $index<$numEntries; ++$index) { my $entry = $dirStart + $ifdStart + 8 + $entrySize * $index; diff --git a/lib/Image/ExifTool/Photoshop.pm b/lib/Image/ExifTool/Photoshop.pm index 4184a5f9..c6d8c62e 100644 --- a/lib/Image/ExifTool/Photoshop.pm +++ b/lib/Image/ExifTool/Photoshop.pm @@ -28,7 +28,7 @@ use strict; use vars qw($VERSION $AUTOLOAD $iptcDigestInfo %printFlags); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.69'; +$VERSION = '1.70'; sub ProcessPhotoshop($$$); sub WritePhotoshop($$$); @@ -70,7 +70,7 @@ my %thumbnailInfo = ( Protected => 1, RawConv => 'my $img=substr($val,0x1c); $self->ValidateImage(\$img,$tag)', ValueConvInv => q{ - my $et = new Image::ExifTool; + my $et = Image::ExifTool->new; my @tags = qw{ImageWidth ImageHeight FileType}; my $info = $et->ImageInfo(\$val, @tags); my ($w, $h, $type) = @$info{@tags}; @@ -892,7 +892,7 @@ sub ProcessDocumentData($$$) unless ($raf) { my $dataPt = $$dirInfo{DataPt}; my $start = $$dirInfo{DirStart} || 0; - $raf = new File::RandomAccess($dataPt); + $raf = File::RandomAccess->new($dataPt); $raf->Seek($start, 0) if $start; $dirLen = length $$dataPt - $start unless defined $dirLen; $et->VerboseDump($dataPt, Start => $start, Len => $dirLen, Base => $$dirInfo{Base}); diff --git a/lib/Image/ExifTool/PostScript.pm b/lib/Image/ExifTool/PostScript.pm index 80a4b457..3df944ee 100644 --- a/lib/Image/ExifTool/PostScript.pm +++ b/lib/Image/ExifTool/PostScript.pm @@ -16,7 +16,7 @@ use strict; use vars qw($VERSION $AUTOLOAD); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.44'; +$VERSION = '1.45'; sub WritePS($$); sub ProcessPS($$;$); @@ -430,7 +430,7 @@ sub ProcessPS($$;$) # allow read from data unless ($raf) { - $raf = new File::RandomAccess($$dirInfo{DataPt}); + $raf = File::RandomAccess->new($$dirInfo{DataPt}); $et->VerboseDir('PostScript'); } # diff --git a/lib/Image/ExifTool/QuickTime.pm b/lib/Image/ExifTool/QuickTime.pm index e12d7d05..e2cd3692 100644 --- a/lib/Image/ExifTool/QuickTime.pm +++ b/lib/Image/ExifTool/QuickTime.pm @@ -48,7 +48,7 @@ use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; use Image::ExifTool::GPS; -$VERSION = '2.91'; +$VERSION = '2.92'; sub ProcessMOV($$;$); sub ProcessKeys($$$); @@ -268,6 +268,24 @@ my %timeInfo = ( PrintConvInv => '$self->InverseDateTime($val)', # (can't put Groups here because they aren't constant!) ); +# properties for ISO 8601 format date/time tags +my %iso8601Date = ( + Shift => 'Time', + ValueConv => q{ + require Image::ExifTool::XMP; + $val = Image::ExifTool::XMP::ConvertXMPDate($val); + $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary + return $val; + }, + ValueConvInv => q{ + require Image::ExifTool::XMP; + my $tmp = Image::ExifTool::XMP::FormatXMPDate($val); + ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon + return $val; + }, + PrintConv => '$self->ConvertDateTime($val)', + PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) +); # information for duration tags my %durationInfo = ( ValueConv => '$$self{TimeScale} ? $val / $$self{TimeScale} : $val', @@ -1574,22 +1592,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); "\xa9day" => { Name => 'ContentCreateDate', Groups => { 2 => 'Time' }, - Shift => 'Time', - # handle values in the form "2010-02-12T13:27:14-0800" (written by Apple iPhone) - ValueConv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::ConvertXMPDate($val); - $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary - return $val; - }, - ValueConvInv => q{ - require Image::ExifTool::XMP; - my $tmp = Image::ExifTool::XMP::FormatXMPDate($val); - ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon - return $val; - }, - PrintConv => '$self->ConvertDateTime($val)', - PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) + %iso8601Date, }, "\xa9ART" => 'Artist', #PH (iTunes 8.0.2) "\xa9alb" => 'Album', #PH (iTunes 8.0.2) @@ -1873,21 +1876,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); Apple Photos has been reported to show a crazy date/time for some MP4 files containing this tag, but perhaps only if it is missing a time zone }, #forum10690/11125 - Shift => 'Time', - ValueConv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::ConvertXMPDate($val); - $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary - return $val; - }, - ValueConvInv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::FormatXMPDate($val); - $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon - return $val; - }, - PrintConv => '$self->ConvertDateTime($val)', - PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) + %iso8601Date, }, manu => { # (SX280) Name => 'Make', @@ -2310,23 +2299,9 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); symbol in these tag ID's for the Ricoh Theta Z1 and maybe other models }, Groups => { 2 => 'Time' }, - Shift => 'Time', Avoid => 1, # handle values in the form "2010-02-12T13:27:14-0800" - ValueConv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::ConvertXMPDate($val); - $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary - return $val; - }, - ValueConvInv => q{ - require Image::ExifTool::XMP; - my $tmp = Image::ExifTool::XMP::FormatXMPDate($val); - ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon - return $val; - }, - PrintConv => '$self->ConvertDateTime($val)', - PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) + %iso8601Date, }, '@xyz' => { #PH (iPhone 3GS) Name => 'GPSCoordinates', @@ -3339,22 +3314,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); "\xa9day" => { Name => 'ContentCreateDate', Groups => { 2 => 'Time' }, - Shift => 'Time', - # handle values in the form "2010-02-12T13:27:14-0800" - ValueConv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::ConvertXMPDate($val); - $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary - return $val; - }, - ValueConvInv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::FormatXMPDate($val); - $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon - return $val; - }, - PrintConv => '$self->ConvertDateTime($val)', - PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) + %iso8601Date, }, "\xa9des" => 'Description', #4 "\xa9enc" => 'EncodedBy', #10 @@ -6403,12 +6363,10 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); ValueConvInv => '$val * 1000', PrintConv => 'ConvertDuration($val)', PrintConvInv => q{ - $val =~ s/ s$//; - my @a = split /(:| days )/, $val; - my $sign = ($val =~ s/^-//) ? -1 : 1; - $a[0] += shift(@a) * 24 if @a == 4; - $a[0] += shift(@a) * 60 while @a > 1; - return $a[0] * $sign; + my $sign = ($val =~ s/^-//) ? -1 : 1; + my @a = $val =~ /(\d+(?:\.\d+)?)/g; + unshift @a, 0 while @a < 4; + return $sign * (((($a[0] * 24) + $a[1]) * 60 + $a[2]) * 60 + $a[3]); }, }, @@ -6522,21 +6480,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); creationdate=> { Name => 'CreationDate', Groups => { 2 => 'Time' }, - Shift => 'Time', - ValueConv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::ConvertXMPDate($val,1); - $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary - return $val; - }, - ValueConvInv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::FormatXMPDate($val); - $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon - return $val; - }, - PrintConv => '$self->ConvertDateTime($val)', - PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) + %iso8601Date, }, description => { }, director => { }, @@ -6586,21 +6530,7 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); 'location.date' => { Name => 'LocationDate', Groups => { 2 => 'Time' }, - Shift => 'Time', - ValueConv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::ConvertXMPDate($val); - $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary - return $val; - }, - ValueConvInv => q{ - require Image::ExifTool::XMP; - $val = Image::ExifTool::XMP::FormatXMPDate($val); - $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon - return $val; - }, - PrintConv => '$self->ConvertDateTime($val)', - PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist) + %iso8601Date, }, 'location.accuracy.horizontal' => { Name => 'LocationAccuracyHorizontal' }, 'live-photo.auto' => { Name => 'LivePhotoAuto', Writable => 'int8u' }, @@ -6693,6 +6623,16 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); 'detected-face.roll-angle' => { Name => 'DetectedFaceRollAngle', Writable => 0 }, # (fiel)com.apple.quicktime.detected-face.yaw-angle (dtyp=23, float) 'detected-face.yaw-angle' => { Name => 'DetectedFaceYawAngle', Writable => 0 }, + # the following tags generated by ShutterEncoder when "preserve metadata" is selected (forum15610) + major_brand => { Name => 'MajorBrand', Avoid => 1 }, + minor_version => { Name => 'MinorVersion', Avoid => 1 }, + compatible_brands => { Name => 'CompatibleBrands', Avoid => 1 }, + creation_time => { + Name => 'CreationTime', + Groups => { 2 => 'Time' }, + Avoid => 1, + %iso8601Date, + }, # # seen in Apple ProRes RAW file # @@ -6708,13 +6648,6 @@ my %isImageData = ( av01 => 1, avc1 => 1, hvc1 => 1, lhv1 => 1, hvt1 => 1 ); # (mdta)com.apple.proapps.image.{TIFF}.Make (eg. "Atmos") # (mdta)com.apple.proapps.image.{TIFF}.Model (eg. "ShogunInferno") # (mdta)com.apple.proapps.image.{TIFF}.Software (eg. "9.0") -# -# also seen (but don't yet add support for these) -# - # (mdta)major_brand - # (mdta)minor_version - # (mdta)compatible_brands - # (mdta)creation_time ); # iTunes info ('----') atoms @@ -9373,7 +9306,7 @@ sub ProcessMOV($$;$) } # more convenient to package data as a RandomAccess file unless ($raf) { - $raf = new File::RandomAccess($dataPt); + $raf = File::RandomAccess->new($dataPt); $dirEnd = $dataPos + $$dirInfo{DirLen} + ($$dirInfo{DirStart} || 0) if $$dirInfo{DirLen}; } # skip leading bytes if necessary diff --git a/lib/Image/ExifTool/QuickTimeStream.pl b/lib/Image/ExifTool/QuickTimeStream.pl index c284bbd0..aae5f6c7 100644 --- a/lib/Image/ExifTool/QuickTimeStream.pl +++ b/lib/Image/ExifTool/QuickTimeStream.pl @@ -848,11 +848,11 @@ sub FoundSomething($$;$$) #------------------------------------------------------------------------------ # Approximate GPSDateTime value from sample time and CreateDate # Inputs: 0) ExifTool ref, 1) tag table ptr, 2) sample time (s) -# 3) true if CreateDate is at end of video +# 3) true if CreateDate is at end of video, 4) flag if CreateDate is UTC # Notes: Uses ExifTool CreateDateAtEnd as flag to subtract video duration -sub SetGPSDateTime($$$) +sub SetGPSDateTime($$$;$) { - my ($et, $tagTbl, $sampleTime) = @_; + my ($et, $tagTbl, $sampleTime, $isUTC) = @_; my $value = $$et{VALUE}; if (defined $sampleTime and $$value{CreateDate}) { $sampleTime += $$value{CreateDate}; # adjust sample time to seconds since the epoch @@ -863,7 +863,9 @@ sub SetGPSDateTime($$$) } else { $et->WarnOnce('Approximating GPSDateTime as CreateDate + SampleTime', 1); } - unless ($et->Options('QuickTimeUTC')) { + my $utc = $et->Options('QuickTimeUTC'); + $utc = $isUTC unless defined $utc; # (allow QuickTimeUTC=0 to override $isUTC default) + unless ($utc) { my $tzOff = $$et{tzOff}; # use previously calculated offset unless (defined $tzOff) { # adjust to UTC, assuming time is local @@ -1344,7 +1346,7 @@ Sample: for ($i=0; ; ) { $et->HandleTag($tagTbl, GPSLatitude => Get32s(\$buff, 12+$n) * 180/0x80000000); $et->HandleTag($tagTbl, GPSLongitude => Get32s(\$buff, 16+$n) * 180/0x80000000); $et->HandleTag($tagTbl, GPSSpeed => Get16u(\$buff, 8+$n) * $mphToKph); - SetGPSDateTime($et, $tagTbl, $time[$i]); + SetGPSDateTime($et, $tagTbl, $time[$i], 1); next; # all done (don't store/process as text) } unless (defined $val) { @@ -2454,7 +2456,7 @@ sub ProcessLIGO_JSON($$$) $et->VerboseDir('LIGO_JSON', undef, length($$dataPt)); while ($$dataPt =~ /LIGOGPSINFO (\{.*?\})/g) { my $json = $1; - my $raf = new File::RandomAccess(\$json); + my $raf = File::RandomAccess->new(\$json); my %dbase; Image::ExifTool::Import::ReadJSON($raf, \%dbase); my $info = $dbase{'*'} or next; diff --git a/lib/Image/ExifTool/RSRC.pm b/lib/Image/ExifTool/RSRC.pm index 395c556e..40e691ec 100644 --- a/lib/Image/ExifTool/RSRC.pm +++ b/lib/Image/ExifTool/RSRC.pm @@ -14,7 +14,7 @@ use strict; use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.09'; +$VERSION = '1.10'; sub ProcessRSRC($$); @@ -70,7 +70,7 @@ sub ProcessRSRC($$) my ($hdr, $map, $buff, $i, $j); # allow access with data reference - $raf or $raf = new File::RandomAccess($$dirInfo{DataPt}); + $raf or $raf = File::RandomAccess->new($$dirInfo{DataPt}); # attempt to validate the format as thoroughly as practical return 0 unless $raf->Read($hdr, 30) == 30; diff --git a/lib/Image/ExifTool/Samsung.pm b/lib/Image/ExifTool/Samsung.pm index 8d289301..b066b68f 100644 --- a/lib/Image/ExifTool/Samsung.pm +++ b/lib/Image/ExifTool/Samsung.pm @@ -22,7 +22,7 @@ use vars qw($VERSION %samsungLensTypes); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; -$VERSION = '1.55'; +$VERSION = '1.56'; sub WriteSTMN($$$); sub ProcessINFO($$$); @@ -1546,7 +1546,7 @@ sub ProcessSamsung($$$) my ($buff, $buf2, $index, $offsetPos, $audioNOff, $audioSize); unless ($raf) { - $raf = new File::RandomAccess($$dirInfo{DataPt}); + $raf = File::RandomAccess->new($$dirInfo{DataPt}); $et->VerboseDir('SamsungTrailer'); } return 0 unless $raf->Seek(-6-$offset, 2) and $raf->Read($buff, 6) == 6 and @@ -1675,7 +1675,7 @@ SamBlock: # add a fixup so the calling routine can apply further shifts if necessary require Image::ExifTool::Fixup; my $fixup = $$dirInfo{Fixup}; - $fixup or $fixup = $$dirInfo{Fixup} = new Image::ExifTool::Fixup; + $fixup or $fixup = $$dirInfo{Fixup} = Image::ExifTool::Fixup->new; $fixup->AddFixup(length($buff) - $offsetPos); $fixup->AddFixup(length($buff) - $offsetPos + 4); } @@ -1697,7 +1697,7 @@ sub WriteSTMN($$$) { my ($et, $dirInfo, $tagTablePtr) = @_; # create a Fixup for the PreviewImage - $$dirInfo{Fixup} = new Image::ExifTool::Fixup; + $$dirInfo{Fixup} = Image::ExifTool::Fixup->new; my $val = Image::ExifTool::WriteBinaryData($et, $dirInfo, $tagTablePtr); # force PreviewImage into the trailer even if it fits in EXIF segment $$et{PREVIEW_INFO}{IsTrailer} = 1 if $$et{PREVIEW_INFO}; diff --git a/lib/Image/ExifTool/Shift.pl b/lib/Image/ExifTool/Shift.pl index c68e7412..bd743c5f 100644 --- a/lib/Image/ExifTool/Shift.pl +++ b/lib/Image/ExifTool/Shift.pl @@ -403,7 +403,7 @@ sub ShiftTime($;$$$) }; $@ and return CleanWarning($@); $tm += $$shiftOffset{$mode}; # apply the shift - $tm < 0 and return 'Shift results in negative time'; + $tm < 0 and return 'Shift results in date before 1970'; # save fractional seconds in shifted time $frac = $tm - int($tm); if ($frac) { diff --git a/lib/Image/ExifTool/SigmaRaw.pm b/lib/Image/ExifTool/SigmaRaw.pm index d9734783..a0330eec 100644 --- a/lib/Image/ExifTool/SigmaRaw.pm +++ b/lib/Image/ExifTool/SigmaRaw.pm @@ -16,7 +16,7 @@ use vars qw($VERSION); use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Sigma; -$VERSION = '1.31'; +$VERSION = '1.32'; sub ProcessX3FHeader($$$); sub ProcessX3FDirectory($$$); @@ -460,7 +460,7 @@ sub WriteX3F($$) my $newData; my %jpegInfo = ( Parent => 'X3F', - RAF => new File::RandomAccess(\$buff), + RAF => File::RandomAccess->new(\$buff), OutFile => \$newData, ); $$et{FILE_TYPE} = 'JPEG'; @@ -575,7 +575,7 @@ sub ProcessX3FDirectory($$$) if ($$tagInfo{Name} eq 'JpgFromRaw') { my %dirInfo = ( Parent => 'X3F', - RAF => new File::RandomAccess(\$buff), + RAF => File::RandomAccess->new(\$buff), ); $$et{BASE} += $offset; $et->ProcessJPEG(\%dirInfo); diff --git a/lib/Image/ExifTool/Sony.pm b/lib/Image/ExifTool/Sony.pm index 0ba598a7..4172e71a 100644 --- a/lib/Image/ExifTool/Sony.pm +++ b/lib/Image/ExifTool/Sony.pm @@ -34,7 +34,7 @@ use Image::ExifTool qw(:DataAccess :Utils); use Image::ExifTool::Exif; use Image::ExifTool::Minolta; -$VERSION = '3.66'; +$VERSION = '3.67'; sub ProcessSRF($$$); sub ProcessSR2($$$); @@ -859,7 +859,7 @@ my %hidUnk = ( Hidden => 1, Unknown => 1 ); # must construct 0x20-byte header which contains length, width and height ValueConvInv => q{ return 'none' unless $val; - my $e = new Image::ExifTool; + my $e = Image::ExifTool->new; my $info = $e->ImageInfo(\$val,'ImageWidth','ImageHeight'); return undef unless $$info{ImageWidth} and $$info{ImageHeight}; my $size = Set32u($$info{ImageWidth}) . Set32u($$info{ImageHeight}); @@ -11640,7 +11640,7 @@ sub ProcessSR2($$$) ); my $subTable = GetTagTable('Image::ExifTool::Sony::SR2SubIFD'); if ($outfile) { - my $fixup = new Image::ExifTool::Fixup; + my $fixup = Image::ExifTool::Fixup->new; $dirInfo{Fixup} = $fixup; $result = $et->WriteDirectory(\%dirInfo, $subTable); return undef unless $result; diff --git a/lib/Image/ExifTool/TagInfoXML.pm b/lib/Image/ExifTool/TagInfoXML.pm index d3ba2d95..4398c578 100644 --- a/lib/Image/ExifTool/TagInfoXML.pm +++ b/lib/Image/ExifTool/TagInfoXML.pm @@ -15,7 +15,7 @@ use vars qw($VERSION @ISA $makeMissing); use Image::ExifTool qw(:Utils :Vars); use Image::ExifTool::XMP; -$VERSION = '1.35'; +$VERSION = '1.36'; @ISA = qw(Exporter); # set this to a language code to generate Lang module with 'MISSING' entries @@ -74,7 +74,7 @@ sub Write(;$$%) { local ($_, *PTIFILE); my ($file, $group, %opts) = @_; - my $et = new Image::ExifTool; + my $et = Image::ExifTool->new; my ($fp, $tableName, %langInfo, @langs, $defaultLang, @groups); @groups = split ':', $group if $group; diff --git a/lib/Image/ExifTool/TagLookup.pm b/lib/Image/ExifTool/TagLookup.pm index 7a58f855..6db923f3 100644 --- a/lib/Image/ExifTool/TagLookup.pm +++ b/lib/Image/ExifTool/TagLookup.pm @@ -17,7 +17,7 @@ require Exporter; use vars qw($VERSION @ISA @EXPORT_OK); use Image::ExifTool qw(:Utils); -$VERSION = '1.19'; +$VERSION = '1.20'; @ISA = qw(Exporter); @EXPORT_OK = qw(FindTagInfo TagExists); @@ -1870,6 +1870,7 @@ my %tagLookup = ( 'commanderinternalttlcompgroupb' => { 312 => '22.1', 313 => '28.1' }, 'comment' => { 0 => 0x2, 123 => 'Comment', 160 => 'Comment', 336 => 'Comment', 399 => "\xa9cmt", 401 => 'comment', 407 => "\xa9cmt" }, 'compass' => { 417 => 0x4 }, + 'compatiblebrands' => { 401 => 'compatible_brands' }, 'compatibleversion' => { 509 => 'CompatibleVersion', 511 => 'CompatibleVersion' }, 'compilation' => { 399 => 'cpil' }, 'compimageimagespersequence' => { 516 => [\'CompositeImageExposureTimes','CompositeImageExposureTimesNumberOfImagesInSequences'] }, @@ -2022,7 +2023,7 @@ my %tagLookup = ( 'crc32' => { 513 => 'crc32' }, 'createdate' => { 122 => 0x9004, 160 => 'CreateDate', 332 => 'CreationDate', 336 => 'create-date', 398 => 'CreationDate', 404 => 0x1, 536 => 'CreateDate' }, 'creationdate' => { 401 => 'creationdate', 525 => 'CreationDate', 528 => 'creationDate' }, - 'creationtime' => { 336 => 'Creation Time' }, + 'creationtime' => { 336 => 'Creation Time', 401 => 'creation_time' }, 'creativestyle' => { 434 => 0x1a, 435 => 0x18, 445 => 0x41, 448 => 0xb020, 480 => 0x4a }, 'creativestylesetting' => { 436 => 0xf, 453 => 0x7 }, 'creativestylewaschanged' => { 485 => 0x8001 }, @@ -4314,6 +4315,7 @@ my %tagLookup = ( 'mainboardversion' => { 141 => 0x438 }, 'maindialexposurecomp' => { 314 => '0.6' }, 'mainingredient' => { 530 => 'mainIngredient' }, + 'majorbrand' => { 401 => 'major_brand' }, 'majorversion' => { 500 => 'MajorVersion' }, 'make' => { 101 => 0x0, 118 => 0x1, 122 => 0x10f, 159 => 'Make', 336 => 'Make', 352 => 0x10f, 401 => 'make', 407 => ['@mak',"\xa9mak"], 527 => 'make', 534 => 'Make' }, 'makernote' => { 515 => 'MakerNote' }, @@ -4781,7 +4783,7 @@ my %tagLookup = ( 'minoltaquality' => { 184 => 0x5, 185 => 0xd, 186 => 0x3, 189 => [0x102,0x103] }, 'minoltatime' => { 184 => 0x16 }, 'minormodelagedisclosure' => { 333 => 'MinorModelAgeDisclosure' }, - 'minorversion' => { 500 => 'MinorVersion' }, + 'minorversion' => { 401 => 'minor_version', 500 => 'MinorVersion' }, 'minsamplevalue' => { 122 => 0x118 }, 'mirrorlockup' => { 85 => 0xc, 86 => 0xc, 87 => 0x60f, 88 => 0xb, 89 => 0xc, 90 => 0x6, 91 => 0x6, 92 => 0xc, 93 => 0x3 }, 'mobilecountrycode' => { 508 => 'mcc' }, @@ -8509,7 +8511,6 @@ my %tagExists = ( 'companymainphone' => 1, 'companyname' => 1, 'compatibility' => 1, - 'compatiblebrands' => 1, 'compatiblefontname' => 1, 'complete' => 1, 'compobj' => 1, @@ -10361,7 +10362,6 @@ my %tagExists = ( 'mainboard' => 1, 'maininfo' => 1, 'maininfoifd' => 1, - 'majorbrand' => 1, 'makeandmodel' => 1, 'makemodel' => 1, 'makernotepentax5a' => 1, diff --git a/lib/Image/ExifTool/TagNames.pod b/lib/Image/ExifTool/TagNames.pod index fb872f7e..f69196a0 100644 --- a/lib/Image/ExifTool/TagNames.pod +++ b/lib/Image/ExifTool/TagNames.pod @@ -12,7 +12,7 @@ meta information extracted from or written to a file. =head1 TAG TABLES The tables listed below give the names of all tags recognized by ExifTool. -They contain a total of 27469 tags, with 17233 unique tag names. +They contain a total of 27473 tags, with 17233 unique tag names. B, B or B is given in the first column of each table. A B is the computer-readable equivalent of a tag name, and @@ -29481,8 +29481,10 @@ changed via the config file. 'com.android.version' AndroidVersion yes 'com.apple.photos.captureMode' CaptureMode yes 'comment' Comment yes + 'compatible_brands' CompatibleBrands yes/ 'content.identifier' ContentIdentifier yes 'copyright' Copyright yes + 'creation_time' CreationTime yes/ 'creationdate' CreationDate yes 'description' Description yes 'detected-face' FaceInfo QuickTime FaceInfo @@ -29514,7 +29516,9 @@ changed via the config file. 'location.name' LocationName yes 'location.note' LocationNote yes 'location.role' LocationRole yes + 'major_brand' MajorBrand yes/ 'make' Make yes + 'minor_version' MinorVersion yes/ 'model' Model yes 'player.movie.audio.balance' Balance yes 'player.movie.audio.bass' Bass yes diff --git a/lib/Image/ExifTool/WriteCanonRaw.pl b/lib/Image/ExifTool/WriteCanonRaw.pl index 16cb431b..cf17f777 100644 --- a/lib/Image/ExifTool/WriteCanonRaw.pl +++ b/lib/Image/ExifTool/WriteCanonRaw.pl @@ -128,7 +128,7 @@ sub SaveMakerNotes($) delete $$et{MAKER_NOTE_INFO}; my $dirEntries = $makerInfo->{Entries}; my $numEntries = scalar(keys %$dirEntries); - my $fixup = new Image::ExifTool::Fixup; + my $fixup = Image::ExifTool::Fixup->new; return unless $numEntries; # build the MakerNotes directory my $makerNotes = Set16u($numEntries); diff --git a/lib/Image/ExifTool/WriteExif.pl b/lib/Image/ExifTool/WriteExif.pl index 23a7ca68..7c5d5214 100644 --- a/lib/Image/ExifTool/WriteExif.pl +++ b/lib/Image/ExifTool/WriteExif.pl @@ -171,9 +171,9 @@ sub RebuildMakerNotes($$$) my $saveOrder = GetByteOrder(); my $loc = Image::ExifTool::MakerNotes::LocateIFD($et,\%subdirInfo); if (defined $loc) { - my $makerFixup = $subdirInfo{Fixup} = new Image::ExifTool::Fixup; + my $makerFixup = $subdirInfo{Fixup} = Image::ExifTool::Fixup->new; # create new exiftool object to rewrite the directory without changing it - my $newTool = new Image::ExifTool; + my $newTool = Image::ExifTool->new; $newTool->Options( IgnoreMinorErrors => $$et{OPTIONS}{IgnoreMinorErrors}, FixBase => $$et{OPTIONS}{FixBase}, @@ -565,7 +565,7 @@ sub WriteExif($$$) my $firstBase = $base; my $raf = $$dirInfo{RAF}; my $dirName = $$dirInfo{DirName} || 'unknown'; - my $fixup = $$dirInfo{Fixup} || new Image::ExifTool::Fixup; + my $fixup = $$dirInfo{Fixup} || Image::ExifTool::Fixup->new; my $imageDataFlag = $$dirInfo{ImageData} || ''; my $verbose = $et->Options('Verbose'); my $out = $et->Options('TextOut'); @@ -745,7 +745,7 @@ sub WriteExif($$$) my $valBuff = ''; # buffer for value data my @valFixups; # list of fixups for offsets in valBuff # fixup for offsets in dirBuff - my $dirFixup = new Image::ExifTool::Fixup; + my $dirFixup = Image::ExifTool::Fixup->new; my $entryBasedFixup; my $lastTagID = -1; my ($oldInfo, $oldFormat, $oldFormName, $oldCount, $oldSize, $oldValue, $oldImageData); @@ -896,7 +896,7 @@ Entry: for (;;) { TagInfo => $oldInfo || $tmpInfo, Offset => $base + $valuePtr + $dataPos, Size => $oldSize, - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, }, $invalidPreview = 2; # remove SubDirectory to prevent processing (for now) @@ -1348,7 +1348,7 @@ NoOverwrite: next if $isNew > 0; # create empty source directory my %sourceDir = ( Parent => $dirName, - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, ); $sourceDir{DirName} = $$newInfo{Groups}{1} if $$newInfo{SubIFD}; $newValue = $et->WriteDirectory(\%sourceDir, $subTable); @@ -1509,7 +1509,7 @@ NoOverwrite: next if $isNew > 0; } if (defined $loc) { # we need fixup data for this subdirectory - $subdirInfo{Fixup} = new Image::ExifTool::Fixup; + $subdirInfo{Fixup} = Image::ExifTool::Fixup->new; # rewrite maker notes my $changed = $$et{CHANGED}; $subdir = $et->WriteDirectory(\%subdirInfo, $subTable, $writeProc); @@ -1673,7 +1673,7 @@ NoOverwrite: next if $isNew > 0; Name => $$newInfo{Name}, TagInfo => $newInfo, Parent => $dirName, - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, RAF => $raf, Subdir => $subdir, # set ImageData only for 1st level SubIFD's @@ -1782,7 +1782,7 @@ NoOverwrite: next if $isNew > 0; #### eval Base ($start,$base) $subdirBase += eval $$subdir{Base}; } - my $subFixup = new Image::ExifTool::Fixup; + my $subFixup = Image::ExifTool::Fixup->new; my %subdirInfo = ( Base => $subdirBase, DataPt => $valueDataPt, @@ -1995,7 +1995,7 @@ NoOverwrite: next if $isNew > 0; # hold onto the PreviewImage until we can determine if it fits $$et{PREVIEW_INFO} or $$et{PREVIEW_INFO} = { Data => $$newValuePt, - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, }; $$et{PREVIEW_INFO}{ChangeBase} = 1 if $$newInfo{ChangeBase}; if ($$newInfo{IsOffset} and $$newInfo{IsOffset} eq '2') { @@ -2017,7 +2017,7 @@ NoOverwrite: next if $isNew > 0; $valBuff .= $$newValuePt; # add value data to buffer # must save a fixup pointer for every pointer in the directory if ($entryBased) { - $entryBasedFixup or $entryBasedFixup = new Image::ExifTool::Fixup; + $entryBasedFixup or $entryBasedFixup = Image::ExifTool::Fixup->new; $entryBasedFixup->AddFixup(length($dirBuff) + 8, $dataTag); } else { $dirFixup->AddFixup(length($dirBuff) + 8, $dataTag); @@ -2451,7 +2451,7 @@ NoOverwrite: next if $isNew > 0; $newOffset += $blockSize; # data comes after other deferred data # create fixup for SubIFD ImageData if ($imageDataFlag eq 'SubIFD' and not $subIfdDataFixup) { - $subIfdDataFixup = new Image::ExifTool::Fixup; + $subIfdDataFixup = Image::ExifTool::Fixup->new; $imageData[-1][4] = $subIfdDataFixup; } $size += $pad; # account for pad byte if necessary @@ -2522,7 +2522,7 @@ NoOverwrite: next if $isNew > 0; # hold onto the PreviewImage until we can determine if it fits $$et{PREVIEW_INFO} or $$et{PREVIEW_INFO} = { Data => $buff, - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, }; if ($$tagInfo{IsOffset} and $$tagInfo{IsOffset} eq '2') { $$et{PREVIEW_INFO}{NoBaseShift} = 1; @@ -2603,7 +2603,7 @@ NoOverwrite: next if $isNew > 0; $fixup->AddFixup($entry + 8); # create special fixup for SubIFD data if ($imageDataFlag eq 'SubIFD') { - my $subIfdDataFixup = new Image::ExifTool::Fixup; + my $subIfdDataFixup = Image::ExifTool::Fixup->new; $subIfdDataFixup->AddFixup($entry + 8); # save fixup in imageData list $$blockInfo[4] = $subIfdDataFixup; @@ -2668,7 +2668,7 @@ NoOverwrite: next if $isNew > 0; } else { # Doesn't fit, or we still don't know, so save fixup information # and put the preview at the end of the file - $$previewInfo{Fixup} or $$previewInfo{Fixup} = new Image::ExifTool::Fixup; + $$previewInfo{Fixup} or $$previewInfo{Fixup} = Image::ExifTool::Fixup->new; $$previewInfo{Fixup}->AddFixup($fixup); } } elsif (defined $newData and $deleteAll) { diff --git a/lib/Image/ExifTool/WritePDF.pl b/lib/Image/ExifTool/WritePDF.pl index 3bf7d921..b2b222da 100644 --- a/lib/Image/ExifTool/WritePDF.pl +++ b/lib/Image/ExifTool/WritePDF.pl @@ -290,7 +290,7 @@ sub WritePDF($$) $raf->Seek($pos, 0); # create a new ExifTool object and use it to read PDF and XMP information - my $newTool = new Image::ExifTool; + my $newTool = Image::ExifTool->new; $newTool->Options(List => 1); $newTool->Options(Password => $et->Options('Password')); $newTool->Options(NoPDFList => $et->Options('NoPDFList')); diff --git a/lib/Image/ExifTool/WriteQuickTime.pl b/lib/Image/ExifTool/WriteQuickTime.pl index c67ed464..6dcc9fff 100644 --- a/lib/Image/ExifTool/WriteQuickTime.pl +++ b/lib/Image/ExifTool/WriteQuickTime.pl @@ -785,7 +785,7 @@ sub WriteQuickTime($$$) my ($rtnVal, $rtnErr) = $dataPt ? (undef, undef) : (1, 0); if ($dataPt) { - $raf = new File::RandomAccess($dataPt); + $raf = File::RandomAccess->new($dataPt); } else { return 0 unless $raf; } diff --git a/lib/Image/ExifTool/WriteXMP.pl b/lib/Image/ExifTool/WriteXMP.pl index 12fa405e..9cd75ce9 100644 --- a/lib/Image/ExifTool/WriteXMP.pl +++ b/lib/Image/ExifTool/WriteXMP.pl @@ -1083,6 +1083,8 @@ sub WriteXMP($$;$) # delete all structure (or pseudo-structure) elements require 'Image/ExifTool/XMPStruct.pl'; ($deleted, $added, $existed) = DeleteStruct($et, \%capture, \$path, $nvHash, \$changed); + # don't add if it didn't exist and not IsCreating and Avoid + undef $added if not $existed and not $$nvHash{IsCreating} and $$tagInfo{Avoid}; next unless $deleted or $added or $et->IsOverwriting($nvHash); next if $existed and $$nvHash{CreateOnly}; } elsif ($cap) { @@ -1262,8 +1264,8 @@ sub WriteXMP($$;$) # check to see if we want to create this tag # (create non-avoided tags in XMP data files by default) my $isCreating = ($$nvHash{IsCreating} or (($isStruct or - ($preferred and not $$tagInfo{Avoid} and - not defined $$nvHash{Shift})) and not $$nvHash{EditOnly})); + ($preferred and not defined $$nvHash{Shift})) and + not $$tagInfo{Avoid} and not $$nvHash{EditOnly})); # don't add new values unless... # ...tag existed before and was deleted, or we added it to a list diff --git a/lib/Image/ExifTool/Writer.pl b/lib/Image/ExifTool/Writer.pl index fa919ac6..f28547af 100644 --- a/lib/Image/ExifTool/Writer.pl +++ b/lib/Image/ExifTool/Writer.pl @@ -26,6 +26,7 @@ sub RemoveNewValuesForGroup($$); sub GetWriteGroup1($$); sub Sanitize($$); sub ConvInv($$$$$;$$); +sub PushValue($$$;$); my $loadedAllTables; # flag indicating we loaded all tables my $advFmtSelf; # ExifTool object during evaluation of advanced formatting expr @@ -1260,7 +1261,7 @@ sub SetNewValuesFromFile($$;@) } # expand shortcuts @setTags and ExpandShortcuts(\@setTags); - my $srcExifTool = new Image::ExifTool; + my $srcExifTool = Image::ExifTool->new; # set flag to indicate we are being called from inside SetNewValuesFromFile() $$srcExifTool{TAGS_FROM_FILE} = 1; # synchronize and increment the file sequence number @@ -1582,7 +1583,7 @@ SET: foreach $set (@setList) { my $opts = $$set[3]; # handle expressions if ($$opts{EXPR}) { - my $val = $srcExifTool->InsertTagValues(\@tags, $$set[1], 'Error'); + my $val = $srcExifTool->InsertTagValues($$set[1], \@tags, 'Error'); my $err = $$srcExifTool{VALUE}{Error}; if ($err) { # pass on any error as a warning unless it is suppressed @@ -2432,7 +2433,7 @@ sub WriteInfo($$;$$) # until ($$self{VALUE}{Error}) { # create random access file object (disable seek test in case of straight copy) - $raf or $raf = new File::RandomAccess($inRef, 1); + $raf or $raf = File::RandomAccess->new($inRef, 1); $raf->BinMode(); if ($numNew == $numPseudo) { $rtnVal = 1; @@ -2703,7 +2704,7 @@ sub GetAllTags(;$) my (%allTags, @groups); @groups = split ':', $group if $group; - my $et = new Image::ExifTool; + my $et = Image::ExifTool->new; LoadAllTables(); # first load all our tables my @tableNames = keys %allTables; @@ -2748,7 +2749,7 @@ sub GetWritableTags(;$) my (%writableTags, @groups); @groups = split ':', $group if $group; - my $et = new Image::ExifTool; + my $et = Image::ExifTool->new; LoadAllTables(); my @tableNames = keys %allTables; @@ -3124,11 +3125,37 @@ Conv: for (;;) { return($val, $err); } +#------------------------------------------------------------------------------ +# Dereference value and push onto list +# Inputs: 0) ExifTool ref, 1) value, 2) list ref, 3) flag to push MissingTagValue for undef value +sub PushValue($$$;$) +{ + local $_; + my ($self, $val, $list, $missing) = @_; + if (ref $val eq 'ARRAY' and ref $$val[0] ne 'HASH') { + $self->PushValue($_, $list, $missing) foreach @$val; + } elsif (ref $val eq 'SCALAR') { + if ($$self{OPTIONS}{Binary} or $$val =~ /^Binary data/) { + push @$list, $$val; + } else { + push @$list, 'Binary data ' . length($$val) . ' bytes'; + } + } elsif (ref $val eq 'HASH' or ref $val eq 'ARRAY') { + require 'Image/ExifTool/XMPStruct.pl'; + push @$list, Image::ExifTool::XMP::SerializeStruct($self, $val); + } elsif (not defined $val) { + my $mval = $$self{OPTIONS}{MissingTagValue}; + push @$list, $mval if $missing and defined $mval; + } else { + push @$list, $val; + } +} + #------------------------------------------------------------------------------ # Convert tag names to values or variables in a string # (eg. '${EXIF:ISO}x $$' --> '100x $' without hash ref, or "$info{'EXIF:ISO'}x $" with) -# Inputs: 0) ExifTool object ref, 1) reference to list of found tags -# 2) string with embedded tag names, 3) Options: +# Inputs: 0) ExifTool object ref, 1) string with embedded tag names, +# 2) reference to list of found tags or undef to use FOUND_TAGS, 3) Options: # undef - set missing tags to '' # 'Error' - issue minor error on missing tag (and return undef) # 'Warn' - issue minor warning on missing tag (and return undef) @@ -3145,20 +3172,22 @@ Conv: for (;;) { # - advanced feature allows Perl expressions inside braces (eg. '${model;tr/ //d}') # - an error/warning in an advanced expression ("${TAG;EXPR}") generates an error # if option set to 'Error', or a warning otherwise -sub InsertTagValues($$$;$$$) +sub InsertTagValues($$;$$$$) { local $_; - my ($self, $foundTags, $line, $opt, $docGrp, $cache) = @_; + my ($self, $line, $foundTags, $opt, $docGrp, $cache) = @_; my $rtnStr = ''; my ($docNum, $tag); + if ($docGrp) { $docNum = $docGrp =~ /(\d+)$/ ? $1 : 0; } else { undef $cache; # no cache if no document groups } + $foundTags or $foundTags = $$self{FOUND_TAGS} || []; while ($line =~ s/(.*?)\$(\{\s*)?([-\w]*\w|\$|\/)//s) { my ($pre, $bra, $var) = ($1, $2, $3); - my (@tags, $val, $tg, @val, $type, $expr, $didExpr, $level, $asList); + my (@tags, $tg, $val, @val, $type, $expr, $didExpr, $level, $asList); # "$$" represents a "$" symbol, and "$/" is a newline if ($var eq '$' or $var eq '/') { $line =~ s/^\s*\}// if $bra; @@ -3261,15 +3290,24 @@ sub InsertTagValues($$$;$$$) } elsif (defined $$et{OPTIONS}{UserParam}{$lcTag}) { $val = $$et{OPTIONS}{UserParam}{$lcTag}; } elsif ($tag =~ /(.*):(.+)/) { - my $group; + my ($group, @matches); ($group, $tag) = ($1, $2); - if (lc $tag eq 'all') { - # see if any tag from the specified group exists - my $match = $et->GroupMatches($group, $fileTags); - $val = $match ? 1 : 0; + # join values of all matching tags if "All" group is used + # (and remove "All" from group prefix) + if ($group =~ s/(^|:)(all|\*)(:|$)/$1 and $3/ei) { + if (lc $tag eq 'all') { + @matches = $group ? $et->GroupMatches($group, $fileTags) : @$fileTags; + } else { + @matches = grep /^$tag(\s|$)/i, @$fileTags; + @matches = $et->GroupMatches($group, \@matches) if $group; + } + $self->PushValue(scalar $et->GetValue($_, $type), \@val) foreach @matches; + } elsif (lc $tag eq 'all') { + # return "1" if any tag from the specified group exists + $val = $et->GroupMatches($group, $fileTags) ? 1 : 0; } else { # find the specified tag - my @matches = grep /^$tag(\s|$)/i, @$fileTags; + @matches = grep /^$tag(\s|$)/i, @$fileTags; @matches = $et->GroupMatches($group, \@matches); foreach $tg (@matches) { if (defined $val and $tg =~ / \((\d+)\)$/) { @@ -3298,31 +3336,15 @@ sub InsertTagValues($$$;$$$) } } $self->Options(ListJoin => $oldListJoin) if $asList; - if (ref $val eq 'ARRAY') { - push @val, @$val; - undef $val; - last unless @tags; - } elsif (ref $val eq 'SCALAR') { - if ($$self{OPTIONS}{Binary} or $$val =~ /^Binary data/) { - $val = $$val; - } else { - $val = 'Binary data ' . length($$val) . ' bytes'; - } - } elsif (ref $val eq 'HASH') { - require 'Image/ExifTool/XMPStruct.pl'; - $val = Image::ExifTool::XMP::SerializeStruct($self, $val); - } elsif (not defined $val) { - $val = $$self{OPTIONS}{MissingTagValue} if $asList; - } - last unless @tags; - push @val, $val if defined $val; + $self->PushValue($val, \@val, $asList); undef $val; + last unless @tags; } if (@val) { - push @val, $val if defined $val; + $self->PushValue($val, \@val) if defined $val; $val = join $$self{OPTIONS}{ListSep}, @val; - } else { - push @val, $val if defined $val; # (so the eval has access to @val if required) + } elsif (defined $val) { + $self->PushValue($val, \@val); # (so the eval has access to @val if required) } # evaluate advanced formatting expression if given (eg. "${TAG;EXPR}") if (defined $expr and defined $val) { @@ -3395,6 +3417,7 @@ sub InsertTagValues($$$;$$$) #------------------------------------------------------------------------------ # Reformat date/time value in $_ based on specified format string # Inputs: 0) date/time format string +# Returns: Reformatted date/time string sub DateFmt($) { my $et = bless { OPTIONS => { DateFormat => shift, StrictDate => 1 } }; @@ -3406,6 +3429,7 @@ sub DateFmt($) $_ = $et->ConvertDateTime($_); defined $_ or warn "Error converting date/time\n"; $$advFmtSelf{GLOBAL_TIME_OFFSET} = $$et{GLOBAL_TIME_OFFSET} if $shift; + return $_; } #------------------------------------------------------------------------------ @@ -3515,7 +3539,7 @@ sub CreateDirectory($$) } unless ($k32CreateDir) { return -1 if defined $k32CreateDir; - $k32CreateDir = new Win32::API('KERNEL32', 'CreateDirectoryW', 'PP', 'I'); + $k32CreateDir = Win32::API->new('KERNEL32', 'CreateDirectoryW', 'PP', 'I'); unless ($k32CreateDir) { $self->Warn('Error calling Win32::API::CreateDirectoryW'); $k32CreateDir = 0; @@ -6233,7 +6257,7 @@ sub WriteJPEG($$) last unless $$editDirs{CIFF}; my $newData = ''; my %dirInfo = ( - RAF => new File::RandomAccess($segDataPt), + RAF => File::RandomAccess->new($segDataPt), OutFile => \$newData, ); require Image::ExifTool::CanonRaw; @@ -6952,7 +6976,7 @@ sub SetFileTime($$;$$$$) } unless ($k32SetFileTime) { return 0 if defined $k32SetFileTime; - $k32SetFileTime = new Win32::API('KERNEL32', 'SetFileTime', 'NPPP', 'I'); + $k32SetFileTime = Win32::API->new('KERNEL32', 'SetFileTime', 'NPPP', 'I'); unless ($k32SetFileTime) { $self->Warn('Error calling Win32::API::SetFileTime'); $k32SetFileTime = 0; @@ -7196,7 +7220,7 @@ sub WriteBinaryData($$$) $$self{HiddenData} = { Offset => $offset, Size => $size, - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, Base => $$dirInfo{Base}, }; next; @@ -7205,7 +7229,7 @@ sub WriteBinaryData($$$) next unless $$tagInfo{DataTag} eq 'PreviewImage' and $$self{FILE_TYPE} eq 'JPEG'; my $previewInfo = $$self{PREVIEW_INFO}; $previewInfo or $previewInfo = $$self{PREVIEW_INFO} = { - Fixup => new Image::ExifTool::Fixup, + Fixup => Image::ExifTool::Fixup->new, }; # set flag indicating we are using short pointers $$previewInfo{IsShort} = 1 unless $format eq 'int32u'; diff --git a/lib/Image/ExifTool/ZIP.pm b/lib/Image/ExifTool/ZIP.pm index 5ee9d54f..48e44a6c 100644 --- a/lib/Image/ExifTool/ZIP.pm +++ b/lib/Image/ExifTool/ZIP.pm @@ -20,7 +20,7 @@ use strict; use vars qw($VERSION $warnString); use Image::ExifTool qw(:DataAccess :Utils); -$VERSION = '1.30'; +$VERSION = '1.31'; sub WarnProc($) { $warnString = $_[0]; } @@ -367,7 +367,7 @@ sub ProcessRAR($$) # read the header and create new RAF object for reading it my $header; $raf->Read($header, $headSize) == $headSize or last; - my $rafHdr = new File::RandomAccess(\$header); + my $rafHdr = File::RandomAccess->new(\$header); my $headType = ReadULEB($rafHdr); # get header type if ($headType == 4) { # encryption block @@ -550,14 +550,14 @@ sub ProcessZIP($$) } elsif (eval { require IO::String }) { # read the whole file into memory (what else can I do?) $raf->Slurp(); - $fh = new IO::String ${$raf->{BUFF_PT}}; + $fh = IO::String->new(${$raf->{BUFF_PT}}); } else { my $type = $raf->{FILE_PT} ? 'pipe or socket' : 'scalar reference'; $et->Warn("Install IO::String to decode compressed ZIP information from a $type"); last; } $et->VPrint(1, " --- using Archive::Zip ---\n"); - $zip = new Archive::Zip; + $zip = Archive::Zip->new; # catch all warnings! (Archive::Zip is bad for this) local $SIG{'__WARN__'} = \&WarnProc; my $status = $zip->readFromFileHandle($fh); @@ -568,8 +568,8 @@ sub ProcessZIP($$) # a failed test with Perl 5.6.2 GNU/Linux 2.6.32-5-686 i686-linux-64int-ld $raf->Seek(0,0); $raf->Slurp(); - $fh = new IO::String ${$raf->{BUFF_PT}}; - $zip = new Archive::Zip; + $fh = IO::String->new(${$raf->{BUFF_PT}}); + $zip = Archive::Zip->new; $status = $zip->readFromFileHandle($fh); } if ($status) { diff --git a/perl-Image-ExifTool.spec b/perl-Image-ExifTool.spec index 496db53c..736b8825 100644 --- a/perl-Image-ExifTool.spec +++ b/perl-Image-ExifTool.spec @@ -1,6 +1,6 @@ Summary: perl module for image data extraction Name: perl-Image-ExifTool -Version: 12.73 +Version: 12.74 Release: 1 License: Artistic/GPL Group: Development/Libraries/Perl diff --git a/pp_build_exe.args b/pp_build_exe.args index de2bc17a..74aafdfd 100644 --- a/pp_build_exe.args +++ b/pp_build_exe.args @@ -21,10 +21,10 @@ # 10) Copy zip archive to web servers. # 11) Update zip file version in link and text of html/index.html. #------------------------------------------------------------------------------ --T exiftool-12.73 -#--info=FileVersion=12.7.3.0 -#--info=ProductVersion=12.7.3.0 -##"--info=Build Date=2024:01:10 13:53:16-05:00" +-T exiftool-12.74 +#--info=FileVersion=12.7.4.0 +#--info=ProductVersion=12.7.4.0 +##"--info=Build Date=2024:01:23 08:16:18-05:00" ##"--info=Bundled Perl Version=ActivePerl 5.24.0" ##"--info=LegalCopyright=Copyright (c) 2003-2024, Phil Harvey" ##"--info=ProductName=ExifTool" diff --git a/t/ExifTool.t b/t/ExifTool.t index 9e936eaa..a0828592 100644 --- a/t/ExifTool.t +++ b/t/ExifTool.t @@ -232,7 +232,7 @@ my $testnum = 1; my $exifTool = Image::ExifTool->new; my @foundTags; $exifTool->ImageInfo('t/images/ExifTool.jpg', \@foundTags); - my $str = $exifTool->InsertTagValues(\@foundTags, '${ifd0:model;tr/i/_/} - $1ciff:3main:model'); + my $str = $exifTool->InsertTagValues('${ifd0:model;tr/i/_/} - $1ciff:3main:model', \@foundTags); my $testfile = "t/ExifTool_$testnum"; open(TESTFILE,">$testfile.failed"); my $oldSep = $/; @@ -370,7 +370,7 @@ my $testnum = 1; my @foundTags; $exifTool->SetAlternateFile(File010 => 't/images/Nikon.jpg'); $exifTool->ImageInfo('t/images/Canon.jpg', \@foundTags); - my $val = $exifTool->InsertTagValues(\@foundTags, '$file010:make - $make'); + my $val = $exifTool->InsertTagValues('$file010:make - $make', \@foundTags); my $testfile = "t/${testname}_$testnum.failed"; my $goodfile = "t/${testname}_$testnum.out"; open OUT, ">$testfile"; diff --git a/t/TestLib.pm b/t/TestLib.pm index 6caac917..9a56a5c9 100644 --- a/t/TestLib.pm +++ b/t/TestLib.pm @@ -378,7 +378,7 @@ sub writeCheck($$$;$$$$) $srcfile or $srcfile = "t/images/$testname.jpg"; my ($ext) = ($srcfile =~ /\.(.+?)$/); my $testfile = "t/${testname}_${testnum}_failed.$ext"; - my $exifTool = new Image::ExifTool; + my $exifTool = Image::ExifTool->new; my @tags; if (ref $onlyWritten eq 'ARRAY') { @tags = @$onlyWritten; diff --git a/t/XMP.t b/t/XMP.t index 7167c18d..b7665617 100644 --- a/t/XMP.t +++ b/t/XMP.t @@ -571,18 +571,20 @@ my $testnum = 1; print "ok $testnum\n"; } -# test 46: Test the advanced-formatting '@' feature on an XMP:Subject list +# test 46: Test the advanced-formatting '@' feature and "All" in the source group { ++$testnum; my $exifTool = Image::ExifTool->new; $exifTool->Options(ListSplit => ', '); - my $cpy = 'subject<${subject@;/^Test/ ? $_=undef : s/Tool$//}'; - $exifTool->SetNewValuesFromFile('t/images/XMP.jpg', $cpy); + my $subj = 'subject<${subject@;/^Test/ ? $_=undef : s/Tool$//}'; + my $keyw = 'creator<${Adobe:all:all@;s/n/N/;$_=undef if /Y/}'; + # (exclude Adobe tag because the Adobe segment would be extracted as a block when copying) + $exifTool->SetNewValuesFromFile('t/images/XMP.jpg', $subj, '-adobe', $keyw); $testfile = "t/${testname}_${testnum}_failed.xmp"; unlink $testfile; writeInfo($exifTool, undef, $testfile); $exifTool->Options(ListSep => ' // '); - my $info = $exifTool->ImageInfo($testfile, 'Subject'); + my $info = $exifTool->ImageInfo($testfile, 'Subject', 'Creator'); if (check($exifTool, $info, $testname, $testnum)) { unlink $testfile; } else { diff --git a/t/XMP_46.out b/t/XMP_46.out index fb5ffed0..48f4119f 100644 --- a/t/XMP_46.out +++ b/t/XMP_46.out @@ -1 +1,2 @@ +[XMP, XMP-dc, Author] creator - Creator: 100 // (None) // (None) [XMP, XMP-dc, Image] subject - Subject: Exif // XMP diff --git a/windows_exiftool b/windows_exiftool index e58eeb3d..4297e959 100755 --- a/windows_exiftool +++ b/windows_exiftool @@ -11,7 +11,7 @@ use strict; use warnings; require 5.004; -my $version = '12.73'; +my $version = '12.74'; # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool' my $exePath; @@ -61,7 +61,7 @@ sub PreserveTime(); sub AbsPath($); sub MyConvertFileName($$); sub SuggestedExtension($$$); -sub LoadPrintFormat($); +sub LoadPrintFormat($;$); sub FilenameSPrintf($;$@); sub NextUnusedFilename($;$); sub CreateDirectory($); @@ -263,7 +263,7 @@ my %optArgs = ( '-lang' => 0, # (optional arg; cannot begin with "-") '-listitem' => 1, '-o' => 1, '-out' => 1, - '-p' => 1, '-printformat' => 1, + '-p' => 1, '-printformat' => 1, '-p-' => 1, '-printformat-' => 1, '-P' => 0, '-password' => 1, '-require' => 1, @@ -586,7 +586,7 @@ if ($^O eq 'MSWin32' and eval { require File::Glob }) { $doGlob = 1; } -$mt = new Image::ExifTool; # create ExifTool object +$mt = Image::ExifTool->new; # create ExifTool object # don't extract duplicates by default unless set by UserDefined::Options $mt->Options(Duplicates => 0) unless %Image::ExifTool::UserDefined::Options @@ -1146,10 +1146,10 @@ for (;;) { } /^overwrite_original$/i and $overwriteOrig = 1, next; /^overwrite_original_in_place$/i and $overwriteOrig = 2, next; - if (/^p$/ or $a eq 'printformat') { + if (/^p(-?)$/ or /^printformat(-?)$/i) { my $fmt = shift; if ($pass) { - LoadPrintFormat($fmt); + LoadPrintFormat($fmt, $1); # load MWG module now if necessary if (not $useMWG and grep /^mwg:/i, @requestTags) { $useMWG = 1; @@ -1158,7 +1158,7 @@ for (;;) { } } else { # defer to next pass so the filename charset is available - push @nextPass, '-p', $fmt; + push @nextPass, "-$_", $fmt; } next; } @@ -1789,7 +1789,7 @@ if (not $altEnc and $mt->Options('Lang') ne 'en' and eval { require Encode }) { if (@fileOrder) { my @allFiles; ProcessFiles($mt, \@allFiles); - my $sortTool = new Image::ExifTool; + my $sortTool = Image::ExifTool->new; $sortTool->Options(FastScan => $fileOrderFast) if $fileOrderFast; $sortTool->Options(PrintConv => $mt->Options('PrintConv')); $sortTool->Options(Duplicates => 0); @@ -2077,7 +2077,7 @@ sub GetImageInfo($$) @foundTags = ('*', @tags) if @tags; $info = $et->ImageInfo(Infile($pipe,$isWriting), \@foundTags, $opts); foreach $condition (@condition) { - my $cond = $et->InsertTagValues(\@foundTags, $condition, \%info); + my $cond = $et->InsertTagValues($condition, \@foundTags, \%info); { # set package so eval'd functions are in Image::ExifTool namespace package Image::ExifTool; @@ -2278,7 +2278,7 @@ sub GetImageInfo($$) my @lines; my $opt = $type eq 'IF' ? 'Silent' : 'Warn'; # silence "IF" warnings foreach (@$prf) { - my $line = $et->InsertTagValues(\@foundTags, $_, $opt, $grp, $cache); + my $line = $et->InsertTagValues($_, \@foundTags, $opt, $grp, $cache); if ($type eq 'IF') { $skipBody = 1 unless defined $line; } elsif (defined $line) { @@ -2711,7 +2711,7 @@ TAG: foreach $tag (@foundTags) { } elsif ($fixLen == 1) { $padLen -= length Encode::decode_utf8($desc); } else { - my $gcstr = eval { new Unicode::GCString(Encode::decode_utf8($desc)) }; + my $gcstr = eval { Unicode::GCString->new(Encode::decode_utf8($desc)) }; if ($gcstr) { $padLen -= $gcstr->columns; } else { @@ -3637,7 +3637,7 @@ sub Infile($;$) if ($rafStdin) { $rafStdin->Seek(0); # rewind } elsif (open RAF_STDIN, '-') { - $rafStdin = new File::RandomAccess(\*RAF_STDIN); + $rafStdin = File::RandomAccess->new(\*RAF_STDIN); $rafStdin->BinMode(); } return $rafStdin if $rafStdin; @@ -4114,12 +4114,12 @@ sub SuggestedExtension($$$) #------------------------------------------------------------------------------ # Load print format file -# Inputs: 0) file name +# Inputs: 0) file name, 1) flag to avoid adding newline to input argument # - saves lines of file to %printFmt list # - adds tag names to @tags list -sub LoadPrintFormat($) +sub LoadPrintFormat($;$) { - my $arg = shift; + my ($arg, $noNL) = @_; if (not defined $arg) { Error "Must specify file or expression for -p option\n"; } elsif ($arg !~ /\n/ and -f $arg and $mt->Open(\*FMT_FILE, $arg)) { @@ -4128,7 +4128,8 @@ sub LoadPrintFormat($) } close(FMT_FILE); } else { - AddPrintFormat($arg . "\n"); + $arg .= "\n" unless $noNL; + AddPrintFormat($arg); } } @@ -4292,7 +4293,7 @@ sub CreateDirectory($) return 0; } unless ($k32CreateDir) { - $k32CreateDir = new Win32::API('KERNEL32', 'CreateDirectoryW', 'PP', 'I'); + $k32CreateDir = Win32::API->new('KERNEL32', 'CreateDirectoryW', 'PP', 'I'); } $success = $k32CreateDir->Call($d2, 0) if $k32CreateDir; } else { @@ -4759,7 +4760,7 @@ OPTIONS -lang [LANG] Set current language -listItem INDEX Extract specific item from a list -n (--printConv) No print conversion - -p FMTFILE (-printFormat) Print output in specified format + -p[-] STR (-printFormat) Print output in specified format -php Export tags as a PHP Array -s[NUM] (-short) Short output format (-s for tag names) -S (-veryShort) Very short output format @@ -5582,23 +5583,24 @@ OPTIONS > exiftool -Orientation=6 -n a.jpg > exiftool -Orientation#=6 a.jpg - -p *FMTFILE* or *STR* (-printFormat) - Print output in the format specified by the given file or string. + -p[-] *STR* or *FMTFILE* (-printFormat) + Print output in the format specified by the given string or file. The argument is interpreted as a string unless a file of that name exists, in which case the string is loaded from the contents of the - file. Tag names in the format file or string begin with a "$" + file. Tag names in the format string or file begin with a "$" symbol and may contain leading group names and/or a trailing "#" (to disable print conversion). Case is not significant. Braces "{}" may be used around the tag name to separate it from subsequent text (and must be used if subsequent text begins with an alphanumeric character, hyphen, underline, colon or number sign). Use $$ to - represent a "$" symbol, and $/ for a newline. - - Multiple -p options may be used, each contributing a line (or more) - of text to the output. Lines beginning with "#[HEAD]" and "#[TAIL]" - are output before the first processed file and after the last - processed file respectively. Lines beginning with "#[SECT]" and - "#[ENDS]" are output before and after each section of files. A + represent a "$" symbol, and $/ for a newline. When the string + argument is used (ie. *STR*), a newline is added to the end of the + string unless -p- is specified. + + Multiple -p options may be used. Lines beginning with "#[HEAD]" and + "#[TAIL]" are output before the first processed file and after the + last processed file respectively. Lines beginning with "#[SECT]" + and "#[ENDS]" are output before and after each section of files. A section is defined as a group of consecutive files with the same section header (eg. files are grouped by directory if "#[SECT]" contains $directory). Lines beginning with "#[BODY]" and lines not @@ -5620,16 +5622,22 @@ OPTIONS produces output like this: - -- Generated by ExifTool 12.73 -- + -- Generated by ExifTool 12.74 -- File: a.jpg - 2003:10:31 15:44:19 (f/5.6, 1/60s, ISO 100) File: b.jpg - 2006:05:23 11:57:38 (f/8.0, 1/13s, ISO 100) -- end -- - The values of List-type tags with multiple items and Shortcut tags - representing multiple tags are joined according the -sep option - setting when interpolated in the string. + The values of List-type tags with multiple items, Shortcut tags + representing multiple tags, and matching tags when the "All" group + is specified are joined according the -sep option setting when + interpolated in the string. (Note that when "All" is used as a + group name, dupicate tags are included regardless of the Duplicates + option setting.) When "All" is used as a tag name, a value of 1 is + returned if any tag exists in the specified group, or 0 otherwise + (unless the "All" group is also specified, in which case the values + of all matching tags are joined). When -ee (-extractEmbedded) is combined with -p, embedded documents are effectively processed as separate input files. @@ -6556,7 +6564,9 @@ OPTIONS with "^=". If *OPT* is not specified a list of available options is returned. The option name is not case senstive, but the option values are. See Image::ExifTool Options for option details. This - overrides API options set via the config file. + overrides API options set via the config file. Note that the + exiftool app sets some API options internally, and attempts to + change these via the command line will have no effect. -common_args Specifies that all arguments following this option are common to -- cgit v1.2.3