Hi Phil,
I'm adding an additional bit of functionality to an older perl script, and it's working as desired. I'm fairly good at copying and tweaking bits and pieces I find in the Image::ExifTool Perl Library Module and this forum, but I really haven't a clue what some of it means.
Here's the new piece (copied, in part, from https://exiftool.org/forum/index.php/topic,19.msg33.html#msg33 (https://exiftool.org/forum/index.php/topic,19.msg33.html#msg33)):
my $out = $jpg_dir . $dto . $ssto . $sc . '.jpg';
# extract the PreviewImage tag explicitly
my $previewInfo = $exifTool->ImageInfo($file, 'PreviewImage');
my $val = $$previewInfo{PreviewImage};
if ($val) {
open OUT, ">$out";
print OUT $$val and close OUT;
# copy all EXIF information, preserving the original IFD
# (without '>*.*' tags would be copied to the preferred EXIF IFD)
my $info = $exifTool->SetNewValuesFromFile($file, 'EXIF:*>*:*');
$exifTool->WriteInfo($out);
}
I understand that references are commonly used when you are returning a large object or data structure (for example an array or hash) from a subroutine, and that I can also use references to subroutines and scalars. When I want to actually use the values in these variables, I need to dereference the pointer. (http://perlmeme.org/howtos/using_perl/dereferencing.html (http://perlmeme.org/howtos/using_perl/dereferencing.html))
In your reply to Janc you state, "Notice that I dereference $val because I know both JpgFromRaw and PreviewImage will return a scalar reference, but to be safe you should probably test for this."
Question 1: What do you mean by, "but to be safe you should probably test for this."
Question 2: Open, print and close feel so clumsy and old-fashioned compared to the object-oriented method of the rest of the code. Is there a 'prettier' way to write this part?
Here's the entire script:
use strict;
use Image::ExifTool;
require 'Image/ExifTool/Shift.pl';
# camera set to UTC0; will shift [-]10 for Hawaii
my $tz = 10;
my $numArgs = $#ARGV;
my $raw_dir = $ARGV[$numArgs - 1] . '/';
my $jpg_dir = $ARGV[$numArgs] . '/';
my $exifTool = new Image::ExifTool;
$exifTool->Options('DateFormat' => '%Y%m%d-%H%M%S');
foreach my $i (0..($numArgs - 2)) {
$exifTool = new Image::ExifTool;
# extract meta information from the image
my $file = $ARGV[$i];
$exifTool->ExtractInfo($file);
# get date and time
my $exifdto = $exifTool->GetValue('DateTimeOriginal');
# set GPS date and time stamps
$exifTool->SetNewValue('GPSDateStamp' => $exifdto);
$exifTool->SetNewValue('GPSTimeStamp' => $exifdto);
# camera set to UTC0, so shift the dates to reflect proper locale
# for convenience, a shortcut tag called AllDates has been defined to represent these three tags: DateTimeOriginal, CreateDate and ModifyDate
# http://www.exiftool.org/index.html#shift
$exifTool->SetNewValue('AllDates' => $tz, 'Shift' => -1);
# get values for use in new filename
# set desired date format
$exifTool->Options('DateFormat' => '%Y%m%d-%H%M%S');
# to *use* a shifted date/time value the shift must be applied to the unformatted (ValueConv) value
# then you must do the DateFormat conversion yourself
my $dto = $exifTool->GetValue('DateTimeOriginal', 'ValueConv');
Image::ExifTool::ShiftTime($dto, $tz, -1);
$dto = $exifTool->ConvertDateTime($dto);
# Nikon records multiple frames per second; get 'SubSecTimeOriginal' to avoid filename collision
my $ssto = $exifTool->GetValue('SubSecTimeOriginal');
# get shutter count
my $sc = $exifTool->GetValue('ShutterCount');
# pad the shutter count number
$sc = '_' . sprintf('%07d', $sc);
# concatenate all the pieces of the new filename
# i.e., 20100126-08040600_0020213.nef
my $nn = $dto . $ssto . $sc . '.nef';
# add information to source file, writing output to new file
# https://exiftool.org/ExifTool.html#WriteInfo
# note use of full path in filenames
$exifTool->WriteInfo($file, $raw_dir . $nn);
my $out = $jpg_dir . $dto . $ssto . $sc . '.jpg';
# extract the PreviewImage tag explicitly
my $previewInfo = $exifTool->ImageInfo($file, 'PreviewImage');
my $val = $$previewInfo{PreviewImage};
if ($val) {
open OUT, ">$out";
print OUT $$val and close OUT;
# copy all EXIF information, preserving the original IFD
# (without '>*.*' tags would be copied to the preferred EXIF IFD)
my $info = $exifTool->SetNewValuesFromFile($file, 'EXIF:*>*:*');
# overwrite file
$exifTool->WriteInfo($out);
}
}
Quote from: alyda on September 15, 2014, 03:39:36 PM
In your reply to Janc you state, "Notice that I dereference $val because I know both JpgFromRaw and PreviewImage will return a scalar reference, but to be safe you should probably test for this."
Question 1: What do you mean by, "but to be safe you should probably test for this."
$val = $$val if ref $val eq 'SCALAR';
QuoteQuestion 2: Open, print and close feel so clumsy and old-fashioned compared to the object-oriented method of the rest of the code. Is there a 'prettier' way to write this part?
You could maybe make it more object oriented with some other Perl library, but the open/print/close is the way I would do it (although I would do a
binmode(OUT); after opening the file so the code would work on Windows platforms.
- Phil
Thank you Phil!