Duplicate tags (Nikon:FlashExposureComp) return different values

Started by alyda, June 24, 2010, 03:07:55 PM

Previous topic - Next topic

alyda

Hi Phil,

Quote from: Phil Harvey on June 27, 2010, 06:57:58 PM
Visualizing something is very important to me, and to this end I created the -htmlDump option which is the best visualization tool I know for seeing the structure of the metadata in a JPEG or TIFF image (including TIFF-based raw formats like NEF).  This is very close to the way I visualize things in my mind when thinking of the binary structure.

Thanks Phil. Holy shuzbut you're brainy! If you ever make it over to Maui please look me up. I've ordered a Vulcan mind-meld device and they've promised delivery next week.

I'm going to try a few things incorporating what you've given me but you may not hear back from me right away. My poor brain works best if I step back a bit and switch to 'assimilate and percolate' mode.

If there's anything else I can do to help you please let me know.

---
Alyda



Phil Harvey

Quote from: alyda on June 28, 2010, 01:37:49 AM
If you ever make it over to Maui please look me up.

Maui.  You're one lucky dude.  I spent a month in Maui back in 1994, and it was the vacation of a lifetime.  Here's a picture from that trip of me jumping a wave at Ho'okipa:



- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Phil Harvey

I think I have figured out what I will do.

1) Since the three FlashExposureComp tags have different meanings, they should have different names.  I'm currently leaning towards:

0x0012 => 'FlashExposureComp' (no change)
0x0017 => 'ExternalFlashExposureComp' (since this appears to be the value set on the external flash)
0x000a => 'FlashCompensation' (still not sure about the exact meaning of this one)

2) Regarding the Group A/B/C confusion:  I checked this and the current decoding is definitely correct for the D3 with firmware 2.x.  The confusion is compounded because this information is written differently by different firmware versions of the same model (and possibly even in different flash modes since these are very complicated and I still don't fully understand them).  Without a lot more testing I don't think I'll be able to sort this out, so I will just make a note in the documentation that the Group A tags may apply to the internal flash, etc, for some models.  Maybe sometime down the road I will be able to do better, but I would more help from Nikon owners with other models.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

alyda

Thanks Phil.

Quote from: Phil Harvey on June 28, 2010, 07:18:17 AM
Maui.  You're one lucky dude.  I spent a month in Maui back in 1994, and it was the vacation of a lifetime.  Here's a picture from that trip of me jumping a wave at Ho'okipa:

Nice! I moved here from Calgary seven years ago but I stick to using my camera to catch waves. (How did you get that photo to appear in the post?)

I've got tentative plans to teach a photography class later this year. If I manage to get it off the ground, I'll see if I can get some volunteers for your tests.

---
Alyda

Phil Harvey

Quote from: alyda on June 28, 2010, 11:06:38 AM
Nice! I moved here from Calgary seven years ago but I stick to using my camera to catch waves.

Cool.  A fellow Canuck. :)

Quote(How did you get that photo to appear in the post?)

With the "Insert Image" button () when composing the response.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

alyda

Hi Phil,

I've run more tests and I've got results I can actually understand.

http://www.justagirl.us/exiftests.php
http://www.justagirl.us/exifflash.php

After reading a zillion opinions on built-in flash versus external flash, I've decided to do my flash photography like this:

Will not use the built-in flash on it's own.
Will use SB-800 either in the shoe or remotely.
Will not use command dial for compensation.
When SB-800 in shoe, will set e3 to TTL and set compensation on SB-800.
When SB-800 in remote mode, will set e3 to Commander Mode then choose the mode and compensation on the camera.

Note: Even if [- -] is selected for [Built-in flash]>[Mode], the built-in flash must be raised so that monitor pre-flashes will be emitted. The built-in flash does not fire, but the AF-assist illuminator lights. The AF-assist illuminator lights are so bright I thought the built-in flash was firing, which certainly added to my earlier confusion. Did some research and found this: The Nikon SG-3IR IR Panel for Camera Built-In Flashes attaches to the camera's flash shoe, and covers and prevents the camera's built-in flash (pre-flash) from influencing the exposure (http://photo.net/nikon-camera-forum/00O8yc).

Initially, the 0x000a => 'FlashCompensation' tag was making me crazy and after studying the output (view source) of  -htmlDump files (exiftool -htmlDump *.nef -w html/%f.html), I noticed something that may (or not) be significant. I found no reference to the 0x000a tag in the html files, but it did appear in the txt files (exiftool -a -g1 -H *.nef -w txt/%f.txt). The mdfind command (Terminal) consults the central metadata store and returns a list of files that match the given metadata query. So I ran this:

HereThereBeDragons:~ kaunu$ mdfind 0x000a -onlyin /Volumes/PHOTOS/flashTests/
/Volumes/PHOTOS/flashTests/20100628-07222925_0026400_3092117.nef
/Volumes/PHOTOS/flashTests/20100628-07315000_0026402_3092117.nef
/Volumes/PHOTOS/flashTests/20100628-07380640_0026404_3092117.nef
/Volumes/PHOTOS/flashTests/20100628-07392134_0026405_3092117.nef
/Volumes/PHOTOS/flashTests/20100628-07411467_0026406_3092117.nef
/Volumes/PHOTOS/flashTests/20100628-07422859_0026407_3092117.nef


And noted that there wasn't a match for some of the images. The images listed above are framed in blue on the http://www.justagirl.us/exiftests.php page.

I'm going to start writing up my flash keyword command using some/all of the tags shown on the http://www.justagirl.us/exifflash.php page, and will post the exiftool command(s) when I'm done.

Thanks a bunch for all your help.

---
Alyda

Phil Harvey

Hi Alyda,

The 0x000a version isn't a stand-alone EXIF tag, so you won't see it in the -HtmlDump output.  It is part of the FlashInfo0103 binary data block.  For binary data blocks, the 0x000a is an index into the block and not a tag ID that is stored in the file (this is indicated in the Tag Name documentation with a heading of "Index" instead of "Tag ID" in the first column -- note that these indices are displayed in decimal in the documentation).

I have just released ExifTool 8.24 which renames two of the FlashExposureComp tags as mentioned to make them easier to differentiate.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

alyda

Thanks Phil. The new tags work great!

I've finally finished writing the perl script I hope to use, and have a few questions.

Should I use 'Group' => 'IPTC' when setting keyword values?

How do I apply this date format '%Y%m%d-%H%M%S' to the value returned by $exifTool->GetValue('DateTimeOriginal')?

How do I pad the shutter count number? Will this work? $in = '_' . $exifTool::PrintConv => 'sprintf("%07d", $sc)';

I'm a little confused about how the WriteInfo method works. I thought I'd call it twice since I can't find any perl copy commands that make sense to me (globs, etc.).

Here's the entire script. I haven't run it yet. I had to learn perl as I went along (it's my first), I'm afraid I'll get a million error messages.

#!/usr/bin/perl -w
use Image::ExifTool;

# Reference: http://search.cpan.org/~exiftool/Image-ExifTool-8.15/lib/Image/ExifTool.pod

print "Which Camera?\n1 => Nikon D300,\n2 => Leica D-Lux 4\n";
chomp(my $cam = <STDIN>);
die "No camera chosen; exiting..." if ($cam eq '');

print "Please enter a time zone for this batch of photos:\n10 => UTC-10 Hawaii (HAST)\n7 => UTC-7 Calgary (MST)\n6 => UTC-6 Calgary (MDT)\n4 => UTC-4 New York (EDT)\n";
chomp(my $tz = <STDIN>);
die "No time zone chosen; exiting..." if ($tz eq '');

my $curyr = localtime->year() + 1900;
my $lrimportdir = "/Volumes/PHOTOS/CameraImport";
my $bkupdrv='/Volumes/B-PHOTOS/raw';
# *** these directory names are changed by the pesky cameras at certain intervals; TO DO LIST ***
my @cameradirnames = ("/Volumes/NIKON D300/DCIM/102ND300", "/Volumes/NO NAME/DCIM/101LEICA");
my @fileext = ("nef", "rwl");
my $cameradir = $cameradirnames[$cam - 1];
my $bkupdir = "$bkupdrv/$fileext[$cam - 1]/$curyr";
my $pattern = ".$fileext[$cam - 1]";

my $exifTool = new Image::ExifTool;

# get a list of all image files in the current directory; note case-insensitive pattern match (/i)
opendir(my $dh, $cameradir) or die "Couldn't open $cameradir : $!";
my @camfiles = grep(/$pattern/i, readdir($dh));
closedir($dh);

# process all the image files in our array
foreach $camfile (@camfiles) {
  # Extract meta information from the image
  $exifTool->ExtractInfo($camfile);
  # set GPS date and time stamps
  $exifdto = $exifTool->GetValue('ExifIFD:DateTimeOriginal');
  $exifTool->SetNewValue('GPSDateStamp' => $exifdto);
  $exifTool->SetNewValue('GPSTimeStamp' => $exifdto);
  # camera set to UTC0, so shift the date to reflect proper locale
  $exifTool->SetNewValue('DateTimeOriginal' => $tz, 'Shift' => -1);
  $exifTool->SetNewValue('CreateDate' => $tz, 'Shift' => -1);

  # get flash and exposure compensation tags - Nikon only
  if ($pattern eq '.nef') {
    # get flash compensation tags
    $fm = $exifTool->GetValue('FlashMode');
    if ($fm =~ /Fired/) {
      $fcm = $exifTool->GetValue('FlashCommanderMode');
      if ($fcm eq 'Off') {
        $tagname = 'ExternalFlashExposureComp';
      }
      else {
        $tagname = 'FlashGroupACompensation';
        $flashgrp = 'Group A';
      }
      $flashcomp = 'FEC: ' . $exifTool::Exif::ConvertFraction->GetValue($tagname);
      # *** do I need to use 'Group' => 'IPTC' here? ***
      # add flash compensation keywords without replacing existing keywords in the file
      $exifTool->SetNewValue('Keywords' => $flashcomp, 'AddValue' => 1);
      if (defined($flashgrp)) {
        $exifTool->SetNewValue('Keywords' => $flashgrp, 'AddValue' => 1);
      }
    }
    # get exposure compensation tags
    $sm = $exifTool->GetValue('ShootingMode');
    if ($sm =~ /Exposure Bracketing/) {
      $ebv = 'EBV: ' . $exifTool->GetValue('ExposureBracketValue');
      $ec = $exifTool->GetValue('ExposureCompensation');
      $expcomp = 'EC: ' . $exifTool::Exif::ConvertFraction($ec - ($ebv || 0));
      # add exposure compensation keywords without replacing existing keywords in the file
      $exifTool->SetNewValue('Keywords' => $ebv, 'AddValue' => 1);
      $exifTool->SetNewValue('Keywords' => $ec, 'AddValue' => 1);
    }
  }

  # save state of new values
  $exifTool->SaveNewValues();

  # get tags for new filename
  # want 20100126-08040600_0020213_3092117.nef
  #   or 20100629-10520900_L1010324_3715271.rwl
  # *** how do I apply this date format '%Y%m%d-%H%M%S' to the value returned? ***
  $dto = $exifTool->GetValue('DateTimeOriginal');
  if ($pattern eq '.nef') {
    # the Leica doesn't have these tags
    $ssto = $exifTool->GetValue('ExifIFD:SubSecTimeOriginal');
    $sc = $exifTool->GetValue('ShutterCount');
    # *** is this how I pad the shutter count number? ***
    $in = '_' . $exifTool::PrintConv => 'sprintf("%07d", $sc)';
  }
  else {
    # manually add 'SubSecTimeOriginal' to Leica date
    $ssto = '00';
    # only want basename
    $count = length($camfile) - length($pattern);
    $basename = substr($camfile, 0, $count);
    # using basename instead of shutter count
    $in = '_' . $basename;
  }
  # occasionally grab Karl or Nicole's Nikon when they're in town, so append serial number
  # add it for Leica too, for consistency's sake
  $sn = '_' . $exifTool->GetValue('SerialNumber');

  # *** TO DO: need this date format '%Y%m%d-%H%M%S' ***
  $newname = "$dto$ssto$in$sn$pattern";

  # add information to a source file, writing output to new file
  $exifTool->WriteInfo($camfile, "$lrimportdir/$newname");
  $exifTool->WriteInfo($camfile, "$bkupdir/$newname");
}


Phil Harvey

Hi Alyda,

I will try to answer your questions.

Quote from: alyda on July 02, 2010, 02:19:08 AM
Should I use 'Group' => 'IPTC' when setting keyword values?

Sure, if you only want to set the IPTC version of this tag.  Alternatively you could specify 'IPTC:Keywords' in the call.

Quote
How do I apply this date format '%Y%m%d-%H%M%S' to the value returned by $exifTool->GetValue('DateTimeOriginal')?

Call $exifTool->Options(DateFormat => '%Y%m%d-%H%M%S') before calling GetValue().

Quote
How do I pad the shutter count number? Will this work? $in = '_' . $exifTool::PrintConv => 'sprintf("%07d", $sc)';

Interesting, but it is simpler than you were thinking to do this:

$in = '_' . sprintf("%07d", $sc);

Quote
I'm a little confused about how the WriteInfo method works. I thought I'd call it twice since I can't find any perl copy commands that make sense to me (globs, etc.).

True. There is no file copy function in Perl.  However, it is quite simple to write a routine to do this yourself:


sub Copy($$)
{
  my ($src, $dst) = @_;
  local (*INFILE, *OUTFILE);
  -e $dst and warn("Destination already exists\n"), return 0;
  open INFILE, $src or warn("Error opening src\n"), return 0;
  open OUTFILE, ">$dst" or warn("Error creating dst\n"), return 0;
  binmode INFILE;
  binmode OUTFILE;
  my $buff;
  while (read(INFILE, $buff, 65536)) {
    print OUTFILE $buff or warn("Write error\n"), unlink($dst), return 0;
  }
  close INFILE;
  close OUTFILE or warn("Write error\n"), unlink($dst), return 0;
  return 1;
}


QuoteHere's the entire script. I haven't run it yet. I had to learn perl as I went along (it's my first), I'm afraid I'll get a million error messages.

Well, you will get a few, but it's looking pretty good.  Really pretty impressive for a first Perl script.

Calling a ExifTool function which doesn't require an ExifTool object is done like this: $rtnVal = Image::ExifTool::AFunction($args).

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

alyda

Hi Phil,

The keywords, date format and padding work great, thanks.

I had error messages when I ran the script the first (and second and third :o) time, but they were all easy to fix. After shaking out all the bugs, I still have two problems.

1. I can't write GPSTimeStamp and GPSDateStamp values.
2. The format is right for the date part of the new filename, but it's the original date instead of the 'shifted' date.

I am able to do everything I want with these commands, but by the time I'm done I've overwritten the file several times (and more when I add keywords):
exiftool -overwrite_original '-GPSDateStamp<ExifIFD:DateTimeOriginal' '-GPSTimeStamp<ExifIFD:DateTimeOriginal' .
exiftool -overwrite_original -DateTimeOriginal-=${tz} -CreateDate-=${tz} .
exiftool -d %Y%m%d-%H%M%S '-FileName<${ExifIFD:DateTimeOriginal}${ExifIFD:SubSecTimeOriginal}_${SC}_${SerialNumber}.nef' *.NEF


Result:
<GPS:GPSTimeStamp>16:31:08</GPS:GPSTimeStamp>
<GPS:GPSDateStamp>2010:02:01</GPS:GPSDateStamp>
<IFD0:DateTimeOriginal>2010:02:01 06:31:08</IFD0:DateTimeOriginal>
<ExifIFD:DateTimeOriginal>2010:02:01 06:31:08</ExifIFD:DateTimeOriginal>
<ExifIFD:CreateDate>2010:02:01 06:31:08</ExifIFD:CreateDate>

The Image::ExifTool Module states that GPS meta information is r/w/c, but I haven't had any joy with this:
$exifdto = $exifTool->GetValue('ExifIFD:DateTimeOriginal');
$exifTool->SetNewValue('GPSDateStamp' => $exifdto);
$exifTool->SetNewValue('GPSTimeStamp' => $exifdto);


or this:
$exifTool->SetNewValue('GPS:GPSDateStamp' => $exifdto);
$exifTool->SetNewValue('GPS:GPSTimeStamp' => $exifdto);


Here's the complete script:

#!/usr/bin/perl -w
use Time::localtime;
use Image::ExifTool;
use File::Copy;

# http://search.cpan.org/~exiftool/Image-ExifTool-8.15/lib/Image/ExifTool.pod

print "Which Camera?\n1 => Nikon D300,\n2 => Leica D-Lux 4\n";
chomp(my $cam = <STDIN>);
die 'No camera chosen; exiting...' if ($cam eq '');

print "Please enter a time zone for this batch of photos:\n10 => UTC-10 Hawaii (HAST)\n7 => UTC-7 Calgary (MST)\n6 => UTC-6 Calgary (MDT)\n4 => UTC-4 New York (EDT)\n";
chomp(my $tz = <STDIN>);
die 'No time zone chosen; exiting...' if ($tz eq '');

my $lrimportdir = '/Volumes/PHOTOS/CameraImport';
my $bkupdrv='/Volumes/B-PHOTOS/raw';
# these camera directory names are always the same
my @cameraparentdir = ('/Volumes/NIKON D300/DCIM', '/Volumes/NO NAME/DCIM');

# the camera subdirectory will always have one of these values as 'part' of it's name
my @childdirs = ('ND300', 'LEICA');
my $dirpattern = $childdirs[$cam - 1];

opendir(my $camdh, $cameraparentdir[$cam - 1]) or die "Couldn't open $cameraparentdir[$cam - 1] : $!";
my @camdirs = grep(/$dirpattern/i, readdir($camdh));
closedir($camdh);
foreach $camdir (@camdirs) {
  if (-d "$cameraparentdir[$cam - 1]/$camdir") {
    $cameradir = "$cameraparentdir[$cam - 1]/$camdir";
    last;
  }
}
if (!defined($cameradir)) {
  die "Couldn't open $cameraparentdir[$cam - 1]";
}

my $curyr = localtime->year() + 1900;
my @fileext = ('nef', 'rwl');
my $bkupdir = "$bkupdrv/$fileext[$cam - 1]/$curyr";
my $pattern = ".$fileext[$cam - 1]";

# get a list of all image files in the current directory; note case-insensitive pattern match (/i)
opendir(my $dh, $cameradir) or die "Couldn't open $cameradir : $!";
my @camfiles = grep(/$pattern/i, readdir($dh));
closedir($dh);

# process all the image files in our array
foreach $camfile (@camfiles) {
  $exifTool = new Image::ExifTool;
  # Extract meta information from the image; note full path of image file
  $exifTool->ExtractInfo("$cameradir/$camfile");
  # get date and time
  $exifdto = $exifTool->GetValue('ExifIFD:DateTimeOriginal');
  # set GPS date and time stamps; no GPS tags for Leica
  if ($pattern eq '.nef') {
    $exifTool->SetNewValue('GPSDateStamp' => $exifdto);
    $exifTool->SetNewValue('GPSTimeStamp' => $exifdto);
  }
  # camera set to UTC0, so shift the date to reflect proper locale
  $exifTool->SetNewValue('DateTimeOriginal' => $tz, 'Shift' => -1);
  $exifTool->SetNewValue('CreateDate' => $tz, 'Shift' => -1);

  # get flash and exposure compensation tags - Nikon only
  # Interesting: FlashGroupACompensation returns decimal values; ExternalFlashExposureComp returns fraction values
  if ($pattern eq '.nef') {
    # get flash compensation tags
    $fm = $exifTool->GetValue('FlashMode');
    # if the flash fired...
    if ($fm =~ /^Fired/) {
      # get the mode...
      $fcm = $exifTool->GetValue('FlashCommanderMode');
      # if mode is Off...
      if ($fcm eq 'Off') {
        $tag = 'ExternalFlashExposureComp';
      }
      # if mode is On...
      else {
        $tag = 'FlashGroupACompensation';
        $flashgrp = ': Group A';
      }
      $val = $exifTool->GetValue($tag);
      # want decimal values here, convert fractions
      @isnum = split(/\//, $val);
      if (defined($isnum[1])) {
        # fraction found so convert to decimal
        $num = Image::ExifTool::Exif::ConvertFraction($val);
      }
      else {
        $num = $val;
      }
      # round to one decimal place (i.e., '0.666666666666667' after fraction conversion)
      $tmp = int ($num * 10) / 10;
      $fec = 'FEC: ' . $tmp;
      # add flash compensation keywords without replacing existing keywords in the file
      $tagname = 'Flash Exposure Compensation';
      # $flashgrp is always defined after it's first occurrence in the loop
      if (defined($flashgrp)) {
        $tagname .= $flashgrp;
        # so undefine the bleeping thing
        undef $flashgrp;
      }
      $exifTool->SetNewValue('IPTC:Keywords' => $tagname, 'AddValue' => 1);
      $exifTool->SetNewValue('IPTC:Keywords' => $fec, 'AddValue' => 1);
    }
    # get exposure compensation tags
    $sm = $exifTool->GetValue('ShootingMode');
    if ($sm =~ /Exposure Bracketing/) {
      $tagname = 'Exposure Bracketing';
      $val = $exifTool->GetValue('ExposureBracketValue');
      # want decimal values here, convert fractions
      @isnum = split(/\//, $val);
      if (defined($isnum[1])) {
        # fraction found so convert to decimal
        $num = Image::ExifTool::Exif::ConvertFraction($val);
      }
      else {
        $num = $val;
      }
      # round to one decimal place
      $tmp = int ($num * 10) / 10;
      $ebv = 'EBV: ' . $tmp;
      $val = $exifTool->GetValue('ExposureCompensation');
      # want decimal values here, convert fractions
      @isnum = split(/\//, $val);
      if (defined($isnum[1])) {
        # fraction found so convert to decimal
        $num = Image::ExifTool::Exif::ConvertFraction($val);
      }
      else {
        $num = $val;
      }
      # round to one decimal place
      $tmp = int ($num * 10) / 10;
      $ec = 'EC: ' . $tmp;
      # add exposure compensation keywords without replacing existing keywords in the file
      $exifTool->SetNewValue('IPTC:Keywords' => $tagname, 'AddValue' => 1);
      $exifTool->SetNewValue('IPTC:Keywords' => $ebv, 'AddValue' => 1);
      $exifTool->SetNewValue('IPTC:Keywords' => $ec, 'AddValue' => 1);
    }
  }

  # save state of new values
  $exifTool->SaveNewValues();

  # get tags for new filename
  # want 20100126-08040600_0020213_3092117.nef
  #   or 20100629-10520900_L1010324_3715271.rwl
  $exifTool->Options('DateFormat' => '%Y%m%d-%H%M%S');
  # *** this is not getting the new date (after locale shift) ***
  $dto = $exifTool->GetValue('DateTimeOriginal');
  if ($pattern eq '.nef') {
    # the Leica doesn't have these next three tags...
    $ssto = $exifTool->GetValue('SubSecTimeOriginal');
    $sc = $exifTool->GetValue('ShutterCount');
    # pad the shutter count number
    $in = '_' . sprintf("%07d", $sc);
    # occasionally grab Karl or Nicole's Nikon when they're in town, so append serial number
    $sn = '_' . $exifTool->GetValue('SerialNumber');
  }
  else {
    # so add them manually
    # add 'SubSecTimeOriginal' to Leica date
    $ssto = '00';
    # use file's basename instead of shutter count
    @basename = split (/\./, $camfile);
    $in = '_' . $basename[0];
    # add Leica's serial number too, for consistency's sake
    $sn = '_3715271';
  }

  $newname = $dto . $ssto . $in . $sn . $pattern;

  # add information to source file, writing output to new file; note full path in source file name
  $exifTool->WriteInfo("$cameradir/$camfile", "$lrimportdir/$newname");
  # copy the file to backup directory
  # copy("$lrimportdir/$newname", "$bkupdir/$newname"); 
}

Phil Harvey

Hi Alyda,

Quote from: alyda on July 03, 2010, 04:57:15 PM
The keywords, date format and padding work great, thanks.

Excellent.

Quote
1. I can't write GPSTimeStamp and GPSDateStamp values.

The problem is that you aren't getting the value of DateTimeOriginal properly.  GetValue takes a tag key, not a tag name.

Quote
2. The format is right for the date part of the new filename, but it's the original date instead of the 'shifted' date.

Correct.  To write the shifted date you will need to do the shift yourself.  You can borrow the ExifTool's ShiftTime() function to help with this.  See this thread for an example of how this function is called.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

alyda

Thank you, thank you, thank you. I am experiencing much joy now!

Changed this and got the GPS tags working:
$exifdto = $exifTool->GetValue('DateTimeOriginal');

and this gets the 'shifted' date:
$dto = $exifTool->GetValue('ShiftedDateTime');

New .ExifTool_config file:
%Image::ExifTool::UserDefined = (
  'Image::ExifTool::Composite' => {
    ShiftedDateTime => {
      Require => {
        0 => 'DateTimeOriginal',
      },
      ValueConv => q{
        require 'Image/ExifTool/Shift.pl';
        Image::ExifTool::ShiftTime($val[0], '10:00', -1);
        return $val[0];
      },
      PrintConv => '$self->ConvertDateTime($val)',
    },
  },
); #end


The date is only shifted for Hawaii (HAST) right now, but it's on my ToDo list.

---
Alyda

Phil Harvey

Hi Alyda,

I wasn't suggesting that you do this with a user-defined tag, although it would certainly work.

I was thinking more along the lines of doing this in your script:


$exifdto = $exifTool->GetValue('DateTimeOriginal');
require 'Image/ExifTool/Shift.pl';
Image::ExifTool::ShiftTime($exifdto, '10:00', -1);


If done in your script, it is much easier to set the timezone.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

alyda

Hi Phil,

Thank you Phil. I tried that yesterday morning before settling on doing the shift in the config file. I'm endlessly persistent, but I had a workable solution and felt I had taken up enough of your time, so I didn't mention it.

Before calling shift time I confirmed that $exifdto had this value: 2010:07:04 16:16:38

When I pass the variable ($dto = Image::ExifTool::ShiftTime($exifdto, '10:00', -1);) I get this message:
Use of uninitialized value $dto in concatenation (.) or string at /Users/kaunu/Pictures/bin/workflow.pl line 170.

When I pass the time string ($dto = Image::ExifTool::ShiftTime('2010:07:04 16:16:38', '10:00', -1);) I get this message:
Modification of a read-only value attempted at /Library/Perl/5.10.0/Image/ExifTool/Shift.pl line 439.

I've tried modifying my husband (he too can be stubbornly read-only), but in this case I thought I was just asking.

---
Alyda

Phil Harvey

I see the problem.  You shouldn't be using the return value from ShiftTime().  This function returns an undefined value on success, otherwise an error string is returned.  Just pass in $exifdto as in my example and after the call $exifdto will contain the shifted time.

Confusing I know.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).