source: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/Lytro.pm@ 34921

Last change on this file since 34921 was 34921, checked in by anupama, 3 years ago

Committing the improvements to EmbeddedMetaPlugin's processing of Keywords vs other metadata fields. Keywords were literally stored as arrays of words rather than phrases in PDFs (at least in Diego's sample PDF), whereas other meta fields like Subjects and Creators stored them as arrays of phrases. To get both to work, Kathy updated EXIF to a newer version, to retrieve the actual EXIF values stored in the PDF. And Kathy and Dr Bainbridge came up with a new option that I added called apply_join_before_split_to_metafields that's a regex which can list the metadata fields to apply the join_before_split to and whcih previously always got applied to all metadata fields. Now it's applied to any *Keywords metafields by default, as that's the metafield we have experience of that behaves differently to the others, as it stores by word instead of phrases. Tested on Diego's sample PDF. Diego has double-checked it to works on his sample PDF too, setting the split char to ; and turning on the join_before_split and leaving apply_join_before_split_to_metafields at its default of .*Keywords. File changes are strings.properties for the tooltip, the plugin introducing the option and working with it and Kathy's EXIF updates affecting cpan/File and cpan/Image.

File size: 7.6 KB
Line 
1#------------------------------------------------------------------------------
2# File: Lytro.pm
3#
4# Description: Read Lytro LFP files
5#
6# Revisions: 2014-07-17 - P. Harvey Created
7#
8# References: 1) http://optics.miloush.net/lytro/TheFileFormat.aspx
9#------------------------------------------------------------------------------
10
11package Image::ExifTool::Lytro;
12
13use strict;
14use vars qw($VERSION);
15use Image::ExifTool qw(:DataAccess :Utils);
16use Image::ExifTool::Import;
17
18$VERSION = '1.03';
19
20sub ExtractTags($$$);
21
22# Lytro LFP tags (ref PH)
23%Image::ExifTool::Lytro::Main = (
24 GROUPS => { 2 => 'Camera' },
25 VARS => { NO_ID => 1 },
26 NOTES => q{
27 Tag definitions for Lytro Light Field Picture (LFP) files. ExifTool
28 extracts the full JSON metadata blocks, as well as breaking them down into
29 individual tags. All available tags are extracted from the JSON metadata,
30 even if they don't appear in the table below.
31 },
32 JSONMetadata => {
33 Notes => 'the full JSON-format metadata blocks',
34 Binary => 1,
35 List => 1,
36 },
37 EmbeddedImage => {
38 Notes => 'JPEG image embedded in LFP files written by Lytro Desktop',
39 Groups => { 2 => 'Preview' },
40 Binary => 1,
41 },
42 Type => { Name => 'CameraType' },
43 CameraMake => { Name => 'Make' },
44 CameraModel => { Name => 'Model', Description => 'Camera Model Name' },
45 CameraSerialNumber => { Name => 'SerialNumber'},
46 CameraFirmware => { Name => 'FirmwareVersion'},
47 DevicesAccelerometerSampleArrayTime => { Name => 'AccelerometerTime'},
48 DevicesAccelerometerSampleArrayX => { Name => 'AccelerometerX'},
49 DevicesAccelerometerSampleArrayY => { Name => 'AccelerometerY'},
50 DevicesAccelerometerSampleArrayZ => { Name => 'AccelerometerZ'},
51 DevicesClockZuluTime => {
52 Name => 'DateTimeOriginal',
53 Description => 'Date/Time Original',
54 Groups => { 2 => 'Time' },
55 ValueConv => 'require Image::ExifTool::XMP; Image::ExifTool::XMP::ConvertXMPDate($val)',
56 PrintConv => '$self->ConvertDateTime($val)',
57 },
58 DevicesLensFNumber => {
59 Name => 'FNumber',
60 PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
61 },
62 DevicesLensFocalLength => {
63 Name => 'FocalLength',
64 ValueConv => '$val * 1000', # convert from metres to mm
65 PrintConv => 'sprintf("%.1f mm",$val)',
66 },
67 DevicesLensTemperature => {
68 Name => 'LensTemperature',
69 PrintConv => 'sprintf("%.1f C",$val)',
70 },
71 DevicesSocTemperature => {
72 Name => 'SocTemperature',
73 PrintConv => 'sprintf("%.1f C",$val)',
74 },
75 DevicesShutterFrameExposureDuration => {
76 Name => 'FrameExposureTime',
77 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
78 },
79 DevicesShutterPixelExposureDuration => {
80 Name => 'ExposureTime',
81 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
82 },
83 DevicesSensorPixelPitch => {
84 Name => 'FocalPlaneXResolution',
85 Notes => 'Y resolution is the same as X resolution',
86 ValueConv => '25.4 / $val / 1000', # convert from metres to pixels/inch
87 },
88 DevicesSensorSensorSerial => { Name => 'SensorSerialNumber'},
89 DevicesSensorIso => { Name => 'ISO' },
90 ImageLimitExposureBias => { Groups => { 2 => 'Image' }, PrintConv => 'sprintf("%+.1f", $val)' },
91 ImageModulationExposureBias => { Groups => { 2 => 'Image' }, PrintConv => 'sprintf("%+.1f", $val)' },
92 ImageOrientation => {
93 Name => 'Orientation',
94 Groups => { 2 => 'Image' },
95 PrintConv => {
96 1 => 'Horizontal (normal)',
97 },
98 },
99);
100
101#------------------------------------------------------------------------------
102# Extract tags from a parsed JSON hash
103# Inputs: 0) ExifTool ref, 1) tag hash ref, 2) base tag name
104sub ExtractTags($$$)
105{
106 my ($et, $meta, $parent) = @_;
107 ref $meta eq 'HASH' or $et->Warn('Invalid LFP metadata'), return;
108 my ($key, $val, $name, $tagTablePtr);
109 foreach $key (sort keys %$meta) {
110 my $tag = $parent . ucfirst($key);
111 foreach $val (ref $$meta{$key} eq 'ARRAY' ? @{$$meta{$key}} : $$meta{$key}) {
112 ref $val eq 'HASH' and ExtractTags($et, $val, $tag), next;
113 $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::Lytro::Main');
114 unless ($$tagTablePtr{$tag}) {
115 ($name = $tag) =~ s/[^-_a-zA-Z0-9](.?)/\U$1/g;
116 $name =~ s/ParametersVendorContentComLytroTags//;
117 my %tagInfo;
118 $tagInfo{Groups} = { 2 => 'Image' } unless $name =~ s/^Devices//;
119 $tagInfo{List} = 1 if ref $$meta{$key} eq 'ARRAY';
120 $tagInfo{Name} = $name;
121 my $str = $tag eq $name ? '' : " as $name";
122 $et->VPrint(0, " [adding $tag$str]\n");
123 AddTagToTable($tagTablePtr, $tag, \%tagInfo);
124 }
125 $et->HandleTag($tagTablePtr, $tag, $val);
126 }
127 }
128}
129
130#------------------------------------------------------------------------------
131# Process segments from a Lytro LFP image
132# Inputs: 0) ExifTool object reference, 1) dirInfo reference
133# Returns: 1 on success, 0 if this wasn't a valid Lytro image
134sub ProcessLFP($$)
135{
136 my ($et, $dirInfo) = @_;
137 my $raf = $$dirInfo{RAF};
138 my $verbose = $et->Options('Verbose');
139 my ($buff, $id);
140
141 # validate the Lytro file header
142 return 0 unless $raf->Read($buff, 16) == 16 and $buff =~ /^\x89LFP\x0d\x0a\x1a\x0a/;
143 $et->SetFileType(); # set the FileType tag
144 SetByteOrder('MM');
145 my $tagTablePtr = GetTagTable('Image::ExifTool::Lytro::Main');
146 while ($raf->Read($buff, 16) == 16) {
147 $buff =~ /^\x89LF/ or $et->Warn('LFP format error'), last;
148 my $size = Get32u(\$buff, 12);
149 $size & 0x80000000 and $et->Warn('Invalid LFP segment size'), last;
150 $raf->Read($id, 80) == 80 or $et->Warn('Truncated LFP segment'), last; # ignore the sha1
151 if ($verbose) {
152 $id =~ s/\0.*//s;
153 $et->VPrint(0, substr($buff,1,3), " segment ($size bytes, $id)\n");
154 }
155 if ($size > 20000000) {
156 $raf->Seek($size, 1) or $et->Warn('Seek error in LFP file'), last;
157 } else {
158 $raf->Read($buff,$size) == $size or $et->Warn('Truncated LFP data'), last;
159 $et->VerboseDump(\$buff, Addr=>$raf->Tell()-$size);
160 if ($buff =~ /^\{\s+"/) { # JSON metadata?
161 pos($buff) = 0;
162 $et->HandleTag($tagTablePtr, 'JSONMetadata', $buff);
163 my $meta = Image::ExifTool::Import::ReadJSONObject(undef, \$buff);
164 ExtractTags($et, $meta, '');
165 } elsif ($buff =~ /^\xff\xd8\xff/) { # embedded JPEG image?
166 $et->HandleTag($tagTablePtr, 'EmbeddedImage', $buff);
167 }
168 }
169 # skip padding if necessary
170 my $pad = 16 - ($size % 16);
171 $raf->Seek($pad, 1) if $pad != 16;
172 }
173 return 1;
174}
175
1761; # end
177
178__END__
179
180=head1 NAME
181
182Image::ExifTool::Lytro - Read Lytro LFP files
183
184=head1 SYNOPSIS
185
186This module is used by Image::ExifTool
187
188=head1 DESCRIPTION
189
190This module contains routines required by Image::ExifTool to read metadata
191from Lytro Light Field Picture (LFP) files.
192
193=head1 AUTHOR
194
195Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
196
197This library is free software; you can redistribute it and/or modify it
198under the same terms as Perl itself.
199
200=head1 REFERENCES
201
202=over 4
203
204=item L<http://optics.miloush.net/lytro/TheFileFormat.aspx>
205
206=back
207
208=head1 SEE ALSO
209
210L<Image::ExifTool::TagNames/Lytro Tags>,
211L<Image::ExifTool(3pm)|Image::ExifTool>
212
213=cut
214
Note: See TracBrowser for help on using the repository browser.