Sei sulla pagina 1di 32

Photo Tools

Perl scripts for digital photography

Jon Allen
http://perl.jonallen.info - jj@jonallen.info
Organisation
•  Digital photography can create lots of files
–  Camera filenames are usually meaningless

•  Manual file renaming


–  Very time consuming
–  Doesn't scale well (100s of folders, most called "cats")
•  Use management software
–  Many products import files into their own library format
–  Difficult to use other tools or to change systems

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Ideal solution
•  Standard directory structure, based on date

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Image::ExifTool
•  Cameras store image metadata as "EXIF tags"
–  Timestamp, focal length, shutter speed, aperture, etc.

•  Image::ExifTool provides an API and command-line


utility to access and modify this data
use Image::ExifTool;
my $exif = Image::ExifTool->new();
my $tags = $exif->ImageInfo($filename);

say "Shutter speed was $tags->{ShutterSpeed}";

•  See http://search.cpan.org/dist/Image-ExifTool
Photo Tools – Perl scripts for digital photography perl.jonallen.info
Getting the timestamp
•  We need the timestamp as a Time::Piece object
–  Time::Piece is a core module from Perl 5.10.0
–  See http://search.cpan.org/dist/Time-Piece
sub exif_timestamp {
my $filename = shift;
my $format = '%Y:%m:%d:%H:%M:%S';
my $exif = Image::ExifTool->new();
my $tags = $exif->ImageInfo($filename,
{DateFormat=>$format});

return Time::Piece->strptime($tags->{DateTimeOriginal},
$format);
}

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Change time zone
•  Who remembers to update the clock on their
camera when going abroad?

•  Using Time::Piece objects this is an easy fix


–  Time::Seconds exports various useful constants
use Time::Piece;
use Time::Seconds;

my $time = exif_timestamp($filename);
my $offset = -8; # 8 hours behind UK

$time += $offset * ONE_HOUR;

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Creating the new filenames
•  Use a template – gives flexibility
–  Time::Piece uses POSIX format specification
–  Oracle date formats are more "human-friendly"
–  http://search.cpan.org/dist/Convert-
NLS_DATE_FORMAT

use Convert::NLS_DATE_FORMAT qw/oracle2posix/;

my $template = 'YYYY/MM/DD/YYYY-MM-DD_HH24-MI-SS';
my $target = $time->strftime(oracle2posix($template));

# Target filename is in the format:


# 2008/05/13/2008-05-13_17-23-00

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Finishing up
•  What next…
–  Prepend destination directory to target filename
–  Check full path already exists (and if not, create it)
–  Does the file already exist? If so, add a sequence number
(some cameras can take multiple images per second)
–  Copy the file!
copy_rename(
source => $filename,
destination => $destination_dir,
template => $template,
offset => $offset,
);

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Finding the source files
use File::Find; # Perl core module

my %find_options;
$find_options{no_chdir} = 1;
$find_options{wanted} = sub {
if (/\.(jpg|jpe|jpeg|tif|tiff)$/i) {
copy_rename(
source => $File::Find::name,
destination => $destination_dir,
template => $template,
offset => $offset,
);
}
};

find(\%find_options, $source_directory);

Photo Tools – Perl scripts for digital photography perl.jonallen.info


More uses for EXIF tags
•  Keywords can be embedded in images
•  Spotlight (OS X), Beagle (Linux), and Windows
search engines can read EXIF keywords
my $keywords = ['Dubai', 'Sunset'];
my $exif = Image::ExifTool->new();

$exif->SetNewValuesFromFile($filename);

$exif->SetNewValue('Keywords',$keywords);
$exif->SetNewValue('XPKeywords',join ', ',@$keywords);

$exif->WriteInfo($filename);

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Searching by keyword

Photo Tools – Perl scripts for digital photography perl.jonallen.info


copyphotos.pl
•  http://perl.jonallen.info/projects/copyphotos
$ ./copyphotos.pl --offset=-1 --template
"YYYY/MM_Mon/DD_Day/HH24-MI-SS"
--keyword "Dubai" -–keyword "Sunset"
source/ photos/

Copying source/a.jpg to photos/2004/01_Jan/25_Sunday


/17-29-05.jpg ... OK
Copying source/b.JPG to photos/2006/11_Nov/18_Saturday
/16-55-13.JPG ... OK
Copying source/c.JPG to photos/2006/11_Nov/18_Saturday
/16-58-06.JPG ... OK
Copying source/d.JPG to photos/2006/01_Jan/28_Saturday
/12-03-47.JPG ... OK

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Future enhancements
•  Automatic keyword generation

•  Camera knows when a picture was taken…


•  A GPS tracker knows where you were…
•  Your calendar (or phone) knows what you were
doing…

•  Correlate these together into a list of keywords

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Camera aspect ratios
•  Cameras typically use one of two aspect ratios

•  3:2 (1:1.5)
–  Based on 35mm film format
–  Canon, Nikon, Pentax, Sony DSLRs

•  4:3 (1:1.33)
–  Olympus, Panasonic, Leica DSLRs
–  Most compact digital cameras

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Printing – the aspect ratio problem
•  There are many "standard" paper sizes in use:
–  6x4 (1:1.5)
–  7x5 (1:1.4)
–  10x8 (1:1.25)
–  A4 (1:1.41)

•  If the paper aspect ratio does not match your


camera, then part of the image will be cropped
–  Note that "full-bleed" printing will slightly crop all sides of
an image, even if the aspect ratios match

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Headless chickens
•  A standard 7x5 print does not match either of the
camera formats particularly well

3:2 format:
7% lost (½")

4:3 format:
7x5 5% lost (¼")

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Removing the need to crop
•  Cropping can be avoided by adding a border
–  Makes the image aspect ratio equal to the paper

7x5 paper
4:3 image
No cropping!

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Find the original sizes
•  How big is the image?
use Image::Size;
my ($width,$height) = imgsize($filename);

•  How big is the paper?


use Paper::Specs;

my $paper_size = 'A4';
Paper::Specs->units('in');

my $page = Paper::Specs->find(code=>$paper_size)
or die("Invalid paper size\n");
my $width = $page->sheet_width;
my $height = $page->sheet_height;

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Compare the aspect ratios
•  Compare based on the longest sides
use List::Util qw/max min/;

my $paper_longside = max($paper_width,$paper_height);
my $paper_shortside = min($paper_width,$paper_height);
my $paper_aspect = $paper_longside / $paper_shortside;

my $image_longside = max($image_width,$image_height);
my $image_shortside = min($image_width,$image_height);
my $image_aspect = $image_longside / $image_shortside;

•  With a 4:3 image and 7x5 paper…


–  $paper_aspect = 1.4, $image_aspect = 1.33

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Which way to adjust?
•  If $paper_aspect >
$image_aspect, we need to
add borders to the long side
of the image

•  If $image_aspect >
$paper_aspect, we need to
add borders to the short
side of the image

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Work out the new sizes
•  Equal border on each side to centre the image
my $target_longside = $image_longside;
my $target_shortside = $image_shortside;
my ($border_longside,$border_shortside) = (0,0);

if ($paper_aspect > $image_aspect) {


$target_longside = $image_shortside * $paper_aspect;
$border_longside = ($target_longside –
$image_longside) / 2;
} else {
$target_shortside = $image_longside / $paper_aspect;
$border_shortside = ($target_shortside -
$image_shortside) / 2;
}

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Image::Magick
•  Open source image manipulation library
–  Supports over 100 image formats
–  Very high quality resizing algorithms
–  Command-line tools and APIs for Perl, C, PHP, .NET, etc
–  See http://www.imagemagick.org

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Image::Magick
•  Open source image manipulation library
–  Supports over 100 image formats
–  Very high quality resizing algorithms
–  Command-line tools and APIs for Perl, C, PHP, .NET, etc
–  See http://www.imagemagick.org
•  However…
–  Can be difficult to build
–  Even harder to package!
–  Remember Elaine's Law:
•  "Just make it easy to install, stupid!"

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Image::Magick
•  Open source image manipulation library
–  Supports over 100 image formats
–  Very high quality resizing algorithms
–  Command-line tools and APIs for Perl, C, PHP, .NET, etc
–  See http://www.imagemagick.org
•  However…
–  Can be difficult to build
–  Even harder to package!
–  Remember Elaine's Law:
•  "Just make it easy to install, stupid!"

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Imager
•  Self-contained Perl module
–  http://search.cpan.org/dist/Imager
–  Installs from CPAN shell
–  Requires file format libraries (libjpeg, libtiff etc)
–  Works with PAR!
•  Include libraries with pp -l ./libjpeg.62.dylib

•  Disadvantages
–  Fewer facilities than Image::Magick
–  Strips image metadata (EXIF)

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Adding a border with Imager
use Imager;

my $source = Imager->new->read(file=>$source_filename);

my $dest = Imager->new(
xsize => $source->getwidth() + 2 * $border_width,
ysize => $source->getheight() + 2 * $border_height,
bits => $source->bits,
channels => $source->getchannels
);

$dest->box(filled=>1, color=>'white');
$dest->paste(img=>$source,
top=>$border_height, left=>$border_width);

$dest->write(file=>$target_filename,jpegquality=>100);

Photo Tools – Perl scripts for digital photography perl.jonallen.info


What happened to the colours?
•  Unfortunately, Imager strips metadata
–  This includes EXIF tags and the ICC colour profile

•  Image::ExifTool can copy the EXIF tags and ICC


profile back from the original file
use Image::ExifTool;

my $exif = Image::ExifTool->new();

$exif->SetNewValuesFromFile($source_filename);
$exif->WriteInfo($target_filename);

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Image aspect ratio changed
•  We now have an image with the correct aspect
ratio, padded with borders on two sides

•  For a full-bleed print, we need a border around all


four sides of the image

Photo Tools – Perl scripts for digital photography perl.jonallen.info


The problem with borders
•  Applying an even border to a rectangular image will
affect its aspect ratio
–  A 7x5 image (1.4 aspect) with an even ½" border would
become an 8x6 image (1.33 aspect)

•  To keep the correct aspect ratio, we need to add a


½" border to the short side and a (½ * 1.4)" border
to the long side
–  How do we work this out in pixels?

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Calculating the border sizes
•  7x5 paper with ½" border
•  Short side of image will be 500px
(5"-½"-½") = 4"
•  Image resolution = 500px / 700px
4" = 125dpi
•  Short side border = ½" *
125dpi = 62.5px 625px
•  Long side border = 62.5 * 1.4
= 87.5px
875px
Photo Tools – Perl scripts for digital photography perl.jonallen.info
photofit.pl
•  http://perl.jonallen.info/projects/photofit

$ ./photofit.pl --paper-size=7x5 --border=0.5in sunset.jpg

Photo Tools – Perl scripts for digital photography perl.jonallen.info


Fin!

Thank you for listening!

Any questions?
http://perl.jonallen.info/talks

Photo Tools – Perl scripts for digital photography perl.jonallen.info

Potrebbero piacerti anche