123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- #------------------------------------------------------------------------------
- # File: PhotoMechanic.pm
- #
- # Description: Read/write Camera Bits Photo Mechanic information
- #
- # Revisions: 10/28/2006 - P. Harvey Created
- #------------------------------------------------------------------------------
- package Image::ExifTool::PhotoMechanic;
- use strict;
- use vars qw($VERSION);
- use Image::ExifTool qw(:DataAccess :Utils);
- use Image::ExifTool::Exif;
- use Image::ExifTool::IPTC;
- use Image::ExifTool::XMP;
- $VERSION = '1.04';
- sub ProcessPhotoMechanic($$);
- # color class names
- my %colorClasses = (
- 0 => '0 (None)',
- 1 => '1 (Winner)',
- 2 => '2 (Winner alt)',
- 3 => '3 (Superior)',
- 4 => '4 (Superior alt)',
- 5 => '5 (Typical)',
- 6 => '6 (Typical alt)',
- 7 => '7 (Extras)',
- 8 => '8 (Trash)',
- );
- # main tag table IPTC-format records in PhotoMechanic trailer
- %Image::ExifTool::PhotoMechanic::Main = (
- GROUPS => { 2 => 'Image' },
- PROCESS_PROC => \&Image::ExifTool::IPTC::ProcessIPTC,
- WRITE_PROC => \&Image::ExifTool::IPTC::WriteIPTC,
- NOTES => q{
- The Photo Mechanic trailer contains data in an IPTC-format structure, with
- soft edit information stored under record number 2.
- },
- 2 => {
- Name => 'SoftEdit',
- SubDirectory => {
- TagTable => 'Image::ExifTool::PhotoMechanic::SoftEdit',
- },
- },
- );
- # raw/preview crop coordinate conversions
- my %rawCropConv = (
- ValueConv => '$val / 655.36',
- ValueConvInv => 'int($val * 655.36 + 0.5)',
- PrintConv => 'sprintf("%.3f%%",$val)',
- PrintConvInv => '$val=~tr/ %//d; $val',
- );
- # Record 2 -- PhotoMechanic soft edit information
- %Image::ExifTool::PhotoMechanic::SoftEdit = (
- GROUPS => { 2 => 'Image' },
- WRITE_PROC => \&Image::ExifTool::IPTC::WriteIPTC,
- CHECK_PROC => \&Image::ExifTool::IPTC::CheckIPTC,
- WRITABLE => 1,
- FORMAT => 'int32s',
- 209 => { Name => 'RawCropLeft', %rawCropConv },
- 210 => { Name => 'RawCropTop', %rawCropConv },
- 211 => { Name => 'RawCropRight', %rawCropConv },
- 212 => { Name => 'RawCropBottom', %rawCropConv },
- 213 => 'ConstrainedCropWidth',
- 214 => 'ConstrainedCropHeight',
- 215 => 'FrameNum',
- 216 => {
- Name => 'Rotation',
- PrintConv => {
- 0 => '0',
- 1 => '90',
- 2 => '180',
- 3 => '270',
- },
- },
- 217 => 'CropLeft',
- 218 => 'CropTop',
- 219 => 'CropRight',
- 220 => 'CropBottom',
- 221 => {
- Name => 'Tagged',
- PrintConv => { 0 => 'No', 1 => 'Yes' },
- },
- 222 => {
- Name => 'ColorClass',
- PrintConv => \%colorClasses,
- },
- 223 => 'Rating',
- 236 => { Name => 'PreviewCropLeft', %rawCropConv },
- 237 => { Name => 'PreviewCropTop', %rawCropConv },
- 238 => { Name => 'PreviewCropRight', %rawCropConv },
- 239 => { Name => 'PreviewCropBottom', %rawCropConv },
- );
- # PhotoMechanic XMP properties
- %Image::ExifTool::PhotoMechanic::XMP = (
- GROUPS => { 0 => 'XMP', 1 => 'XMP-photomech', 2 => 'Image' },
- NAMESPACE => { photomechanic => 'http://ns.camerabits.com/photomechanic/1.0/' },
- WRITE_PROC => \&Image::ExifTool::XMP::WriteXMP,
- WRITABLE => 'string',
- NOTES => q{
- Below is a list of the observed PhotoMechanic XMP tags. The actual
- namespace prefix is "photomechanic" but ExifTool shortens this in
- the "XMP-photomech" family 1 group name.
- },
- ColorClass => {
- Writable => 'integer',
- PrintConv => \%colorClasses,
- },
- CountryCode => { Avoid => 1, Groups => { 2 => 'Location' } },
- EditStatus => { },
- PMVersion => { },
- Prefs => {
- Notes => 'format is "Tagged:0, ColorClass:1, Rating:2, FrameNum:3"',
- PrintConv => q{
- $val =~ s[\s*(\d+):\s*(\d+):\s*(\d+):\s*(\S*)]
- [Tagged:$1, ColorClass:$2, Rating:$3, FrameNum:$4];
- return $val;
- },
- PrintConvInv => q{
- $val =~ s[Tagged:\s*(\d+).*ColorClass:\s*(\d+).*Rating:\s*(\d+).*FrameNum:\s*(\S*)]
- [$1:$2:$3:$4]is;
- return $val;
- },
- },
- Tagged => { Writable => 'boolean', PrintConv => { False => 'No', True => 'Yes' } },
- TimeCreated => {
- Avoid => 1,
- Groups => { 2 => 'Time' },
- Shift => 'Time',
- ValueConv => 'Image::ExifTool::Exif::ExifTime($val)',
- ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)',
- },
- );
- #------------------------------------------------------------------------------
- # Read/write PhotoMechanic information in a file
- # Inputs: 0) ExifTool object reference, 1) dirInfo reference
- # Returns: 1 on success, 0 if this file didn't contain PhotoMechanic information
- # - updates DataPos to point to start of PhotoMechanic information
- # - updates DirLen to trailer length
- sub ProcessPhotoMechanic($$)
- {
- my ($et, $dirInfo) = @_;
- my $raf = $$dirInfo{RAF};
- my $offset = $$dirInfo{Offset} || 0;
- my $outfile = $$dirInfo{OutFile};
- my $verbose = $et->Options('Verbose');
- my $out = $et->Options('TextOut');
- my $rtnVal = 0;
- my ($buff, $footer);
- for (;;) {
- # read and validate trailer footer (last 12 bytes)
- last unless $raf->Seek(-12-$offset, 2) and $raf->Read($footer, 12) == 12;
- last unless $footer =~ /cbipcbbl$/;
- my $size = unpack('N', $footer);
- if ($size & 0x80000000 or not $raf->Seek(-$size-12, 1)) {
- $et->Warn('Bad PhotoMechanic trailer');
- last;
- }
- unless ($raf->Read($buff, $size) == $size) {
- $et->Warn('Error reading PhotoMechanic trailer');
- last;
- }
- $rtnVal = 1; # we read the trailer successfully
- # set variables returned in dirInfo hash
- $$dirInfo{DataPos} = $raf->Tell() - $size;
- $$dirInfo{DirLen} = $size + 12;
- my %dirInfo = (
- DataPt => \$buff,
- DataPos => $$dirInfo{DataPos},
- DirStart => 0,
- DirLen => $size,
- Parent => 'PhotoMechanic',
- );
- my $tagTablePtr = GetTagTable('Image::ExifTool::PhotoMechanic::Main');
- if (not $outfile) {
- # extract trailer information
- $et->DumpTrailer($dirInfo) if $verbose or $$et{HTML_DUMP};
- $et->ProcessDirectory(\%dirInfo, $tagTablePtr);
- } elsif ($$et{DEL_GROUP}{PhotoMechanic}) {
- # delete the trailer
- $verbose and print $out " Deleting PhotoMechanic trailer\n";
- ++$$et{CHANGED};
- } else {
- # rewrite the trailer
- my $newPt;
- my $newBuff = $et->WriteDirectory(\%dirInfo, $tagTablePtr);
- if (defined $newBuff) {
- $newPt = \$newBuff; # write out the modified trailer
- my $pad = 0x800 - length($newBuff);
- if ($pad > 0 and not $et->Options('Compact')) {
- # pad out to 2kB like PhotoMechanic does
- $newBuff .= "\0" x $pad;
- }
- # generate new footer
- $footer = pack('N', length($$newPt)) . 'cbipcbbl';
- } else {
- $newPt = \$buff; # just copy existing trailer
- }
- # write out the trailer
- Write($outfile, $$newPt, $footer) or $rtnVal = -1;
- }
- last;
- }
- return $rtnVal;
- }
- 1; # end
- __END__
- =head1 NAME
- Image::ExifTool::PhotoMechanic - Read/write Photo Mechanic information
- =head1 SYNOPSIS
- This module is used by Image::ExifTool
- =head1 DESCRIPTION
- This module contains definitions required by Image::ExifTool to read and
- write information written by the Camera Bits Photo Mechanic software.
- =head1 AUTHOR
- Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
- This library is free software; you can redistribute it and/or modify it
- under the same terms as Perl itself.
- =head1 ACKNOWLEDGEMENTS
- Many thanks to the great support provided by Camera Bits, and in particular
- for the valuable exchanges with Kirk Baker. Based on this experience, I can
- say that the technical support offered by Camera Bits is second to none.
- =head1 SEE ALSO
- L<Image::ExifTool::TagNames/PhotoMechanic Tags>,
- L<Image::ExifTool(3pm)|Image::ExifTool>
- =cut
|