Duplicate tags (Nikon:FlashExposureComp) return different values

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

Previous topic - Next topic

alyda

Hi Phil,

I had some help from you a while back (2010-02-03) on writing exposure compensation values into keywords if I was shooting in Exposure Bracketing mode.

Command line:
exiftool -sep ", " '-keywords+<EBV: ${Nikon:ExposureBracketValue}, EC: ${EC}' -overwrite_original - +if '$Nikon:ShootingMode =~ "Exposure Bracketing"' *.nef

My .ExifTool_config file looks like this:
%Image::ExifTool::UserDefined = (
'Image::ExifTool::Composite' => {
    FN => {
      Require => 'Nikon:FileNumber',
      PrintConv => 'sprintf("%07d",$val)',
    },
    SC => {
      Require => 'Nikon:ShutterCount',
      PrintConv => 'sprintf("%07d",$val)',
    },
    EC => {
      Require => {
        0 => 'ExposureBracketValue',
        1 => 'EXIF:ExposureCompensation',
      },
      ValueConv => '$val[1] - $val[0]',
      PrintConv => 'Image::ExifTool::Exif::ConvertFraction($val)',
    },
    FEC => {
      Require => 'Nikon:FlashExposureComp',
      PrintConv => 'Image::ExifTool::Exif::ConvertFraction($val)',
    },
  },
); #end


I'm making the switch to a perl script because I can't think of a way to use two '-if' conditions--one for exposure compensation, the other for flash compensation (-if 'not $ExifIFD:Flash =~ "No Flash"')--without making two passes.

It looks like I can get where I want to go if I take advantage of the GetValue, SetNewValue and WriteInfo methods of the Image::ExifTool module: 'SetNewValue - Set the new value for a tag. The routine may be called multiple times to set the values of many tags before using "WriteInfo" to write the new values to an image.'

The problem is that I'm seeing duplicate tags for 'Nikon:FlashExposureComp' and they return different values.

Code:
#!/usr/bin/perl
use Image::ExifTool;
my $exifTool = new Image::ExifTool;
my $filename = '20100619-14320274_0025637_3092117.nef';
my $tag1 = 'ExifIFD:Flash'; #! line 86; looking for 'On, Return detected'
my $tag2 = 'Nikon:FlashMode'; #! line 153; looking for 'Fired, TTL Mode'
my $tag3 = 'Nikon:FlashExposureComp'; #! line 118: -1, line 120: 0, line 187: -1; returning duplicate tags with different values
my $flash = $exifTool->ImageInfo($filename, $tag1, $tag2, $tag3);
foreach (keys %$flash) {
  print "$_ => $$flash{$_}\n";
}


Returns:
FlashExposureComp (1) => -5/3
FlashExposureComp (2) => -5/3
FlashExposureComp => 0
FlashMode => Fired, TTL Mode
Flash => On, Return detected


I've been unable to attach the RAW file to this post so I've zipped it and made it available for download at http://www.justagirl.us/downloads/20100619-14320274_0025637_3092117.zip. File size: 20.4MB.

Please note: My server is scheduled for upgrade and will not be available between 9:00pm ET Thursday, June 24, 2010, and 3:00am ET Friday, June 25, 2010.


Phil Harvey

Thanks for the sample.  (It was over the 10MB limit of this forum -- that's why it couldn't be uploaded here.)


exiftool 20100619-14320274_0025637_3092117.nef -flashexposurecomp -flashmode -H
0x0012 Flash Exposure Compensation     : -5/3
0x0017 Flash Exposure Compensation     : 0
0x000a Flash Exposure Compensation     : -5/3
0x0087 Flash Mode                      : Fired, TTL Mode


It is the version with tag ID 0x0017 which is the problem.  This tag is a relatively recent addition and it could be that we don't yet fully understand its meaning.  Perhaps this tag is related to the external flash only, in which case it should be renamed to ExternalFlashExposureComp.  Do you have an external flash that you could test this with?  If so, we should be able to sort this out.

- 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

I do have an external flash, thanks for asking.

Updated perl (filename):
#!/usr/bin/perl
use Image::ExifTool;
my $exifTool = new Image::ExifTool;
my $filename = '20100625-04330525_0026017_3092117.nef';
my $tag1 = 'ExifIFD:Flash';
my $tag2 = 'Nikon:FlashMode';
my $tag3 = 'Nikon:FlashExposureComp';
my $flash = $exifTool->ImageInfo($filename, $tag1, $tag2, $tag3);
foreach (keys %$flash) {
  print "$_ => $$flash{$_}\n";
}


Returns:
FlashExposureComp (1) => -4/3
FlashExposureComp (2) => 0
FlashExposureComp => 0
FlashMode => Fired, External
Flash => On, Return detected


RAW file: http://www.justagirl.us/downloads/20100625-04330525_0026017_3092117.zip



Phil Harvey

Great, thanks!:


exiftool 20100625-04330525_0026017_3092117.nef  -flashexposurecomp -flashmode -H
0x0012 Flash Exposure Compensation     : -4/3
0x0017 Flash Exposure Compensation     : 0
0x000a Flash Exposure Compensation     : 0
0x0087 Flash Mode                      : Fired, External


So only 0x0012 is valid for the ExternalFlash.  Then it must be that 0x0017 has some other meaning for the D300.  In light of this, maybe the tags should be renamed as follows:

0x0012 => 'FlashExposureComp' (no change)
0x0017 => 'FlashExposureComp2' (until we figure out what this means)
0x000a => 'InternalFlashExposureComp' (not sure about this one)

Note that 0x0012 still has the odd behaviour that it is set even if the flash didn't fire (in which case it should be ignored).

If you want to run some more tests, be my guest.  It would be interesting to know how these tags are set if you fire both flashes together (is this possible?  And if so, it it possible to set the compensation differently for each flash -- probably not I would imagine), or if you use the external flash as a remote by triggering it using the internal flash as a commander.

Also, you don't need to upload the whole NEF.  Just the EXIF information will do.  An EXIF file can be produced with this command line:

exiftool SRC.nef -o DST.exif

- 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

Wow! You ask really interesting questions. I'm a geek (note to self: must get housekeeper), so I ran a few more tests.

I've attached the EXIF information for the all the photos below (exif.zip), along with a couple of other files you may like to refer to.

SB-800 External Flash in Remote Mode, Built-In Flash in Commander Mode

20100625-06552859_0026042_3092117.nef
Camera's flash compensation (command dial; see attached commandDials.jpg): -4/3
SB-800 flash compensation: -2

FlashExposureComp (1) => -4/3
FlashExposureComp (2) => -2
FlashExposureComp => -2
FlashMode => Fired, External
Flash => On, Return detected


20100625-06560568_0026043_3092117.nef
Camera's flash compensation (command dial): 0
SB-800 flash compensation: -2

FlashExposureComp (1) => 0
FlashExposureComp (2) => -2
FlashExposureComp => -2
FlashMode => Fired, External
Flash => On, Return detected


20100625-06564594_0026044_3092117.nef
Camera's flash compensation (command dial): 0
SB-800 flash compensation: 0

FlashExposureComp (1) => 0
FlashExposureComp (2) => 0
FlashExposureComp => 0
FlashMode => Fired, External
Flash => On, Return detected


20100625-06571293_0026045_3092117.nef
Camera's flash compensation (command dial): 0
SB-800 flash compensation: 0

FlashExposureComp (1) => 0
FlashExposureComp (2) => 0
FlashExposureComp => 0
FlashMode => Fired, External
Flash => On, Return detected


20100625-08441707_0026062_3092117.nef
Camera's flash compensation (command dial): 0
SB-800 flash compensation: 0

FlashExposureComp (1) => -1
FlashExposureComp (2) => -1
FlashExposureComp => 0
FlashMode => Fired, TTL Mode
Flash => On, Return not detected


20100625-08444889_0026063_3092117.nef
Camera's flash compensation (command dial): 0
SB-800 flash compensation: 0

FlashExposureComp (1) => -4/3
FlashExposureComp (2) => -4/3
FlashExposureComp => 0
FlashMode => Fired, TTL Mode
Flash => On, Return not detected


From Nikon D300 manual: Use the built-in flash as a master flash controlling one or more remote optional SB-800, SB-600, or SB-R200 flash units in up to two groups (A and B) using advanced wireless lighting (e3 menu item on camera). See attached manualNikonD300_FlashControlForBuilt-inFlash.pdf

20100625-09015843_0026069_3092117.nef
Camera's flash compensation (command dial): -2/3
SB-800 flash compensation: 0
e3 Flash cntrl - Built-in flash compensation: -4/3
e3 Flash cntrl - Group A (SB-800?) compensation: -1/3

FlashExposureComp (1) => -2
FlashExposureComp (2) => -2
FlashExposureComp => 0
FlashMode => Fired, TTL Mode
Flash => On, Return not detected


20100625-09022351_0026070_3092117.nef
Camera's flash compensation (command dial): -1
SB-800 flash compensation: 0
e3 Flash cntrl - Built-in flash compensation: -4/3
e3 Flash cntrl - Group A (SB-800?) compensation: -1/3

FlashExposureComp (1) => -7/3
FlashExposureComp (2) => -7/3
FlashExposureComp => 0
FlashMode => Fired, TTL Mode
Flash => On, Return not detected


20100625-09025925_0026071_3092117.nef
Camera's flash compensation (command dial): -1
SB-800 flash compensation: 0
e3 Flash cntrl - Built-in flash compensation: 0
e3 Flash cntrl - Group A (SB-800?) compensation: -1/3


FlashExposureComp (1) => -1
FlashExposureComp (2) => -1
FlashExposureComp => 0
FlashMode => Fired, TTL Mode
Flash => On, Return not detected


SB-800 External Flash in Hot Shoe

20100625-07403416_0026055_3092117.nef
Camera's flash compensation (command dial): 0
SB-800 flash compensation: 0

FlashExposureComp (1) => 0
FlashExposureComp (2) => 0
FlashExposureComp => 0
FlashMode => Fired, External
Flash => On, Return detected


20100625-07405452_0026056_3092117.nef
Camera's flash compensation (command dial): -1/3
SB-800 flash compensation: 0

FlashExposureComp (1) => -1/3
FlashExposureComp (2) => 0
FlashExposureComp => 0
FlashMode => Fired, External
Flash => On, Return detected


20100625-07411100_0026057_3092117.nef
Camera's flash compensation (command dial): -1/3
SB-800 flash compensation: -1

FlashExposureComp (1) => -1/3
FlashExposureComp (2) => -1
FlashExposureComp => -1
FlashMode => Fired, External
Flash => On, Return detected


20100625-07413350_0026058_3092117.nef
Camera's flash compensation (command dial): 0
SB-800 flash compensation: -1

FlashExposureComp (1) => 0
FlashExposureComp (2) => -1
FlashExposureComp => -1
FlashMode => Fired, External
Flash => On, Return detected


No Flash

20100625-07535149_0026059_3092117.nef
Camera's flash compensation (command dial): 0
FlashExposureComp (1) => 0
FlashExposureComp (2) => 0
FlashExposureComp => 0
FlashMode => Did Not Fire
Flash => No Flash


20100625-07540806_0026060_3092117.nef
Camera's flash compensation (command dial): -5/3
FlashExposureComp (1) => -5/3
FlashExposureComp (2) => 0
FlashExposureComp => 0
FlashMode => Did Not Fire
Flash => No Flash


Phil Harvey

Excellent!  Thanks for running these tests.

This is starting to make a bit of sense.  The camera controls either the internal or external flash depending on the mode.  Here is what I think is going on:

FlashExposureComp (1) = 0x0012: The flash compensation set in the camera.  Controls either the internal or external flash depending on the mode.

FlashExposureComp (2) = 0x000a: The flash compensation actually applied?

FlashExposureComp = 0x0017: The compensation set on the external flash.

The things I don't understand are:

1) 20100625-08441707_0026062_3092117.nef and 20100625-08444889_0026063_3092117.nef:  It seems you must have set the compensation in the e3 custom setting here, but you didn't mention this.

2) For all of the images taken with the SB-800 on the hot shoe, tag 0x000a reflects the SB-800 setting and not the camera setting.  In this mode, which setting is actually applied?

- 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'm sorry about the confusion.

Quote from: Phil Harvey on June 26, 2010, 07:30:18 AM
The things I don't understand are:

1) 20100625-08441707_0026062_3092117.nef and 20100625-08444889_0026063_3092117.nef:  It seems you must have set the compensation in the e3 custom setting here, but you didn't mention this.

I've checked my notes and don't see anything for the e3 custom setting. I may have forgotten to jot it down or values weren't set. I have no idea which.

Quote from: Phil Harvey on June 26, 2010, 07:30:18 AM
2) For all of the images taken with the SB-800 on the hot shoe, tag 0x000a reflects the SB-800 setting and not the camera setting.  In this mode, which setting is actually applied?

I'm sorry, I don't understand the question.

I played with the settings some more this morning and have become even more confused. You refer to Tag ID (0x0012, 0x000a, etc.). I don't see them when I do testing:

exiftool *.nef -o %f.exif
exiftool -a -u -g1 *.exif


Is there another command I can use? I'd like to spend more time on it and, hopefully, become enlightened.

---
Alyda



Phil Harvey

Hi Alyda,

Quote
I'm sorry, I don't understand the question.

With the SB-800 on the hot shoe, does the flash output change when a) the command dial setting is changed, or b) when the compensation is adjusted in the SB-800, or both?

The tag ID's are shown with the -H option.

This is very interesting.  I think my idea of calling 0x0017 ExternalFlashExposureComp was good since this is the value you actually set on the SB-800.  But I'm still wondering about how to clear up the confusion between the other two tags.

- 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

Confirmed:

"e3: Flash Cntrl for Built-in Flash" settings completely ignored when SB-800 is in hot shoe (makes sense given the name).

With the SB-800 in the hot shoe the actual flash output is a combination of the command dial and SB-800 compensation settings.

So, if the SB-800 is in the hot shoe, "FlashExposureComp (2) = 0x000a" should be the flash compensation actually applied.

I still need to run more tests with the SB-800 in remote mode.

Phil Harvey

Hi Alyda,

Thanks for your effort in helping to figure this out.

Quote from: alyda on June 26, 2010, 08:18:03 PM
"e3: Flash Cntrl for Built-in Flash" settings completely ignored when SB-800 is in hot shoe (makes sense given the name).

It's always nice when something makes sense. :)

Quote
With the SB-800 in the hot shoe the actual flash output is a combination of the command dial and SB-800 compensation settings.

So, if the SB-800 is in the hot shoe, "FlashExposureComp (2) = 0x000a" should be the flash compensation actually applied.

I still don't understand this.  For example, 20100625-07405452_0026056_3092117.nef has a command-dial setting of -1/3 and an SB-800 setting of 0, but 0x000a is 0 for this image.  It is the hot shoe tests that I am having the most trouble with because 0x000a seems to follow the SB-800 setting, which isn't what I would have expected.

- 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,

With SB-800 in remote mode, the camera must be set to commander mode in e3 menu. Exposure compensation adjustments can be made in one of four places in this mode: one at the command dial and three in the e3 menu--Built-in, Group A and Group B Group B is irrelevant here and I don't have another flash for testing). In remote mode, the SB-800 can be set to Group A, B or C. It's been set to Group A for all of the images I've taken so far. In this set, I verified visually on the camera's monitor that each of the compensation settings affect the brightness of the image.

SB-800 set to Group A
20100626-16231614_0026337_3092117.nef
command dial set to 0, e3 Built-in set to 0, Group A set to 0, Group B set to 0
20100626-16234363_0026338_3092117.nef
command dial set to -1, e3 Built-in set to 0, Group A set to 0, Group B set to 0
20100626-16244094_0026339_3092117.nef
command dial set to -1, e3 Built-in set to -1, Group A set to 0, Group B set to 0
20100626-16250186_0026340_3092117.nef
command dial set to -1, e3 Built-in set to -1, Group A set to -1, Group B set to 0

SB-800 set to Group B
20100626-17233668_0026345_3092117.nef
command dial set to -1, e3 Built-in set to -1, Group A set to -1, Group B set to -1

SB-800 set to Group C - SB-800 did not fire but the Built-in flash did
20100626-17234860_0026346_3092117.nef
command dial set to -1, e3 Built-in set to -1, Group A set to -1, Group B set to -1

There's a very brief discussion of flash modes and compensation in each of the three PDF attachments to this post. Maybe you'll get more out of it than I did.

I think part of the answer may lie in one or more of these tags:

0x0009 Flash Type
0x0011 Flash Group A Control Mode
0x0012 Flash Group B Control Mode
0x0012 Flash Group C Control Mode
0x0013 Flash Group A Exposure Comp
0x0014 Flash Group B Exposure Comp
0x0015 Flash Group C Exposure Comp

Perhaps Group A should be named Built-in, and then groups B and C become A and B? I feel a bit silly making this suggestion since I know so little about how your fabulous tool works. I hope you're not offended.

Quote from: Phil Harvey on June 26, 2010, 08:57:38 PM
I still don't understand this.  For example, 20100625-07405452_0026056_3092117.nef has a command-dial setting of -1/3 and an SB-800 setting of 0, but 0x000a is 0 for this image.  It is the hot shoe tests that I am having the most trouble with because 0x000a seems to follow the SB-800 setting, which isn't what I would have expected.

I'm not sure if I agree with this based on new findings above.

---
Alyda


Phil Harvey

Hi Alyda,

Quote from: alyda on June 27, 2010, 12:04:10 AM
With SB-800 in remote mode, the camera must be set to commander mode in e3 menu. Exposure compensation adjustments can be made in one of four places in this mode:

Actually I think 5 places:  You forgot about the compensation on the SB-800, which was 0 for all of these tests.

Quote
There's a very brief discussion of flash modes and compensation in each of the three PDF attachments to this post. Maybe you'll get more out of it than I did.

I have downloaded the full D300 and SB-800 manuals myself and read through them too.  Like you, I find that they don't answer all of my questions.

Quote
Perhaps Group A should be named Built-in, and then groups B and C become A and B?

I will to look into this, thanks for pointing out this problem.  It seems that other models may have different meanings for the same tags.  If so, we may just have to live with this because it would get messy for me to change the names of all of these tags depending on the camera model.

Quote
I hope you're not offended.

Absolutely not!  You don't have to worry about offending me.  I don't claim to have all of the answers, and with your help I have learned a lot that I didn't know before.

Quote
Quote from: Phil Harvey on June 26, 2010, 08:57:38 PM
It is the hot shoe tests that I am having the most trouble with because 0x000a seems to follow the SB-800 setting, which isn't what I would have expected.

I'm not sure if I agree with this based on new findings above.

The difference is that in the above tests your FlashType was "Built-in,TTL&Comdr.".  In any type of "Built-in" flash 0x000a follows the command dial.  However, for all of your previous hot-shoe tests the FlashType was "Optional,TTL", and in this mode 0x000a seems to follow the SB-800 setting (also for your previous tests in commander mode with the built-in flash off).

So for me this part is starting to make a bit more sense.

- 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,

Quote from: Phil Harvey on June 27, 2010, 07:16:32 AM
Actually I think 5 places:  You forgot about the compensation on the SB-800, which was 0 for all of these tests.

I'd be delighted to be wrong about this but I think it's four (4) places. In remote mode, the SB-800 is completely slaved to the camera. The only selectable options in this mode are channel and group. Flash compensation values on the SB-800 can be set while it's in the hot shoe. So...while in TTL/TTL-BL mode (in the hot shoe) I set the compensation to -1. Then I took it off the hot shoe, switched to remote mode and shot an image with these settings:

SB-800 set to Group A
20100627-04292994_0026362_3092117.nef
command dial set to -1, e3 Built-in set to -1, Group A set to -1, Group B set to -1

I'm not seeing anything different in the output.

Quote from: Phil Harvey on June 27, 2010, 07:16:32 AM
Quote
Perhaps Group A should be named Built-in, and then groups B and C become A and B?

I will to look into this, thanks for pointing out this problem.  It seems that other models may have different meanings for the same tags.  If so, we may just have to live with this because it would get messy for me to change the names of all of these tags depending on the camera model.

No problem. So...if we focus for a moment on my desire to write flash output level compensation values as keywords to the RAW file...can you suggest a workaround?

Here's some [maybe] helpful background: I took an online HDR photography class early this year and some us found comparing exposure compensation metadata in Lightroom to be painfully slow. With your help in February, I wrote an article on adding keywords to the RAW files before import into Lightroom and shared it with my classmates (http://www.justagirl.us/keywords.php).

Here's the command I currently use for that:
exiftool -sep ", " '-keywords+<EBV: ${Nikon:ExposureBracketValue}, EC: ${EC}' -overwrite_original -if '$Nikon:ShootingMode =~ "Exposure Bracketing"' *.NEF

I'll need to specify one or more conditions to be evaluated before processing each file. My thought is to use some magic combination of flash mode, type and compensation, and then do some math with the values of the compensation tags, but it makes my head hurt when I start to write it down. Maybe a beer would help; it's 5:00 somewhere, right? I'm going to print this post, and the tag/value output from a couple of photos, and start making some notes.

I've been told I have a very logical mind and strong abstract conceptualization skills. I'm not really sure how to phrase this question, but is there something you could share about how your software accesses the manufacturer-specific metadata from the image file, and how you interpret the context of the information found? How do you see an image file in your mind?

---
Alyda

Phil Harvey

Hi Alyda,

Quote from: alyda on June 27, 2010, 03:09:15 PM
I'd be delighted to be wrong about this but I think it's four (4) places.

I understand.  Thanks for explaining.

Quote
No problem. So...if we focus for a moment on my desire to write flash output level compensation values as keywords to the RAW file...can you suggest a workaround?

Here's the command I currently use for that:
exiftool -sep ", " '-keywords+<EBV: ${Nikon:ExposureBracketValue}, EC: ${EC}' -overwrite_original -if '$Nikon:ShootingMode =~ "Exposure Bracketing"' *.NEF

I'll need to specify one or more conditions to be evaluated before processing each file. My thought is to use some magic combination of flash mode, type and compensation, and then do some math with the values of the compensation tags, but it makes my head hurt when I start to write it down.

If you can define exactly what you want to do, this can be done in a user-defined Composite tag.  Of course it can also be done by writing a Perl script and calling the ExifTool functions as you are doing.  If you can write down the algorithm you want to use I can help with this.  Sorry to get distracted by the FlashExposureComp problem.  Until I get this fixed you can select the specific FlashExposureComp tag you want by specifying a copy number.  For instance, the 0x0012 value is Copy1:FlashExposureComp.

Quote
I've been told I have a very logical mind and strong abstract conceptualization skills. I'm not really sure how to phrase this question, but is there something you could share about how your software accesses the manufacturer-specific metadata from the image file, and how you interpret the context of the information found? How do you see an image file in your mind?

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.

- 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 was thinking about something like this when I mentioned the user-defined tags:


%Image::ExifTool::UserDefined = (
'Image::ExifTool::Composite' => {
    MyKeywords => {
      Require => {
        0 => 'Nikon:FileNumber',
      },
      Desire => {
        1 => 'Nikon:ShutterCount',
        2 => 'ExposureBracketValue',
        3 => 'EXIF:ExposureCompensation',
        4 => 'FlashMode',
        5 => 'Copy1:FlashExposureComp',
      },
      ValueConv => q{
        my @a;
        push @a, "FN: $val[0]";
        push @a, 'EC: ' . Image::ExifTool::Exif::ConvertFraction($val[3] - ($val[2] || 0)) if defined $val[3];
        push @a, 'FEC: ' . Image::ExifTool::Exif::ConvertFraction($val[5]) if defined $val[5] and $val[4] and $val[4] =~ /Fired/;
        return \@a;
      },
    },
  },
);
1; #end


And this command:

exiftool "-keywords+<mykeywords" FILE

- 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,

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 ($).

alyda

Well, you've got me slapping my forehead on that one. I forgot that Perl variables are passed by reference by default. Introduces a new old problem however. The $exifTool->Options('DateFormat' => '%Y%m%d-%H%M%S'); statement no longer formats the date for my filename.

Phil Harvey

I'm sorry.  I wasn't thinking about your entire script.  You use the shifted date/time value in your file name?  This adds complexity because the shift must be applied to the unformatted (ValueConv) value, then you must do the DateFormat conversion yourself:


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

$exifTool->Options('DateFormat' => '%Y%m%d-%H%M%S');
$exifdto = $exifTool->ConvertDateTime($exifdto);


You're being very patient here.  This is fairly involved because we're taking advantage of some private ExifTool functions to ease the programming load for you.

- 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

Yes! It even works when I substitute my $tz variable for '10:00.'

Quote from: Phil Harvey on July 05, 2010, 03:30:13 PM
You're being very patient here.

You're the patient one. Thank you so very much for all your help. If you do make it down to Maui, the drinks are on me. I promise I won't attempt a mind-meld unless you're very drunk.

---
Alyda

Phil Harvey

Quote from: alyda on July 05, 2010, 03:48:52 PM
Thank you so very much for all your help.

You're welcome.

Quote
If you do make it down to Maui, the drinks are on me. I promise I won't attempt a mind-meld unless you're very drunk.

LOL. With free drinks, there is little chance that I would remain sober... :P

- 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 ($).