source: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/OpenEXR.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: 10.1 KB
Line 
1#------------------------------------------------------------------------------
2# File: OpenEXR.pm
3#
4# Description: Read OpenEXR meta information
5#
6# Revisions: 2011/12/10 - P. Harvey Created
7#
8# References: 1) http://www.openexr.com/
9#------------------------------------------------------------------------------
10
11package Image::ExifTool::OpenEXR;
12
13use strict;
14use vars qw($VERSION);
15use Image::ExifTool qw(:DataAccess :Utils);
16use Image::ExifTool::GPS;
17
18$VERSION = '1.02';
19
20# supported EXR value format types (other types are extracted as undef binary data)
21my %formatType = (
22 box2f => 'float[4]',
23 box2i => 'int32s[4]',
24 chlist => 1,
25 chromaticities => 'float[8]',
26 compression => 'int8u',
27 double => 'double',
28 envmap => 'int8u',
29 float => 'float',
30 'int' => 'int32s',
31 keycode => 'int32s[7]',
32 lineOrder => 'int8u',
33 m33f => 'float[9]',
34 m44f => 'float[16]',
35 rational => 'rational64s',
36 string => 'string', # incorrect in specification! (no leading int)
37 stringvector => 1,
38 tiledesc => 1,
39 timecode => 'int32u[2]',
40 v2f => 'float[2]',
41 v2i => 'int32s[2]',
42 v3f => 'float[3]',
43 v3i => 'int32s[3]',
44);
45
46# OpenEXR tags
47%Image::ExifTool::OpenEXR::Main = (
48 GROUPS => { 2 => 'Image' },
49 NOTES => q{
50 Information extracted from EXR images. See L<http://www.openexr.com/> for
51 the official specification.
52 },
53 _ver => { Name => 'EXRVersion' },
54 _lay => {
55 Name => 'Layout',
56 PrintHex => 1,
57 PrintConv => { 0 => 'Scan Lines', 0x200 => 'Tiles' },
58 },
59 adoptedNeutral => { },
60 altitude => {
61 Name => 'GPSAltitude',
62 Groups => { 2 => 'Location' },
63 PrintConv => q{
64 $val = int($val * 10) / 10;
65 return(($val =~ s/^-// ? "$val m Below" : "$val m Above") . " Sea Level");
66 },
67 },
68 aperture => { PrintConv => 'sprintf("%.1f",$val)' },
69 channels => { },
70 chromaticities => { },
71 capDate => {
72 Name => 'DateTimeOriginal',
73 Description => 'Date/Time Original',
74 Groups => { 2 => 'Time' },
75 PrintConv => '$self->ConvertDateTime($val)',
76 },
77 comments => { },
78 compression => {
79 PrintConvColumns => 2,
80 PrintConv => {
81 0 => 'None',
82 1 => 'RLE',
83 2 => 'ZIPS',
84 3 => 'ZIP',
85 4 => 'PIZ',
86 5 => 'PXR24',
87 6 => 'B44',
88 7 => 'B44A',
89 },
90 },
91 dataWindow => { },
92 displayWindow => { },
93 envmap => {
94 Name => 'EnvironmentMap',
95 PrintConv => {
96 0 => 'Latitude/Longitude',
97 1 => 'Cube',
98 },
99 },
100 expTime => {
101 Name => 'ExposureTime',
102 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
103 },
104 focus => {
105 Name => 'FocusDistance',
106 PrintConv => '"$val m"',
107 },
108 framesPerSecond => { },
109 keyCode => { },
110 isoSpeed => { Name => 'ISO' },
111 latitude => {
112 Name => 'GPSLatitude',
113 Groups => { 2 => 'Location' },
114 PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
115 },
116 lineOrder => {
117 PrintConv => {
118 0 => 'Increasing Y',
119 1 => 'Decreasing Y',
120 2 => 'Random Y',
121 },
122 },
123 longitude => {
124 Name => 'GPSLongitude',
125 Groups => { 2 => 'Location' },
126 PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
127 },
128 lookModTransform => { },
129 multiView => { },
130 owner => { Groups => { 2 => 'Author' } },
131 pixelAspectRatio => { },
132 preview => { },
133 renderingTransform => { },
134 screenWindowCenter => { },
135 screenWindowWidth => { },
136 tiles => { },
137 timeCode => { },
138 utcOffset => {
139 Name => 'TimeZone',
140 Groups => { 2 => 'Time' },
141 PrintConv => 'TimeZoneString($val / 60)',
142 },
143 whiteLuminance => { },
144 worldToCamera => { },
145 worldToNDC => { },
146 wrapmodes => { Name => 'WrapModes' },
147 xDensity => { Name => 'XResolution' },
148 # also observed:
149 # ilut
150);
151
152#------------------------------------------------------------------------------
153# Extract information from an OpenEXR file
154# Inputs: 0) ExifTool object reference, 1) DirInfo reference
155# Returns: 1 on success, 0 if this wasn't a valid OpenEXR file
156sub ProcessEXR($$)
157{
158 my ($et, $dirInfo) = @_;
159 my $raf = $$dirInfo{RAF};
160 my $verbose = $et->Options('Verbose');
161 my $binary = $et->Options('Binary') || $verbose;
162 my ($buff, $dim);
163
164 # verify this is a valid RIFF file
165 return 0 unless $raf->Read($buff, 8) == 8;
166 return 0 unless $buff =~ /^\x76\x2f\x31\x01/s;
167 $et->SetFileType();
168 SetByteOrder('II');
169 my $tagTablePtr = GetTagTable('Image::ExifTool::OpenEXR::Main');
170
171 # extract information from header
172 my $ver = unpack('x4V', $buff);
173 $et->HandleTag($tagTablePtr, '_ver', $ver & 0xff);
174 $et->HandleTag($tagTablePtr, '_lay', $ver & 0x200);
175
176 # extract attributes
177 for (;;) {
178 $raf->Read($buff, 68) or last;
179 last if $buff =~ /^\0/;
180 unless ($buff =~ /^([^\0]{1,31})\0([^\0]{1,31})\0(.{4})/sg) {
181 $et->Warn('EXR format error');
182 last;
183 }
184 my ($tag, $type, $size) = ($1, $2, unpack('V', $3));
185 unless ($raf->Seek(pos($buff) - length($buff), 1)) {
186 $et->Warn('Seek error');
187 last;
188 }
189 my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
190 unless ($tagInfo) {
191 my $name = ucfirst $tag;
192 $name =~ tr/-_a-zA-Z0-9//dc;
193 if (length $name <= 1) {
194 if (length $name) {
195 $name = "Tag$name";
196 } else {
197 $name = 'Invalid';
198 }
199 }
200 $tagInfo = { Name => $name };
201 AddTagToTable($tagTablePtr, $tag, $tagInfo);
202 $et->VPrint(0, $$et{INDENT}, "[adding $tag]\n");
203 }
204 my ($val, $success);
205 my $format = $formatType{$type};
206 if ($format or $binary) {
207 $raf->Read($buff, $size) == $size and $success = 1;
208 if (not $format) {
209 $val = \$buff; # treat as undef binary data
210 } elsif ($format ne '1') {
211 # handle formats which map nicely into ExifTool format codes
212 if ($format =~ /^(\w+)\[?(\d*)/) {
213 my ($fmt, $cnt) = ($1, $2);
214 $cnt = $fmt eq 'string' ? $size : 1 unless $cnt;
215 $val = ReadValue(\$buff, 0, $fmt, $cnt, $size);
216 }
217 # handle other format types
218 } elsif ($type eq 'tiledesc') {
219 if ($size >= 9) {
220 my $x = Get32u(\$buff, 0);
221 my $y = Get32u(\$buff, 4);
222 my $mode = Get8u(\$buff, 8);
223 my $lvl = { 0 => 'One Level', 1 => 'MIMAP Levels', 2 => 'RIPMAP Levels' }->{$mode & 0x0f};
224 $lvl or $lvl = 'Unknown Levels (' . ($mode & 0xf) . ')';
225 my $rnd = { 0 => 'Round Down', 1 => 'Round Up' }->{$mode >> 4};
226 $rnd or $rnd = 'Unknown Rounding (' . ($mode >> 4) . ')';
227 $val = "${x}x$y; $lvl; $rnd";
228 }
229 } elsif ($type eq 'chlist') {
230 $val = [ ];
231 while ($buff =~ /\G([^\0]{1,31})\0(.{16})/sg) {
232 my ($str, $dat) = ($1, $2);
233 my ($pix,$lin,$x,$y) = unpack('VCx3VV', $dat);
234 $pix = { 0 => 'int8u', 1 => 'half', 2 => 'float' }->{$pix} || "unknown($pix)";
235 push @$val, "$str $pix" . ($lin ? ' linear' : '') . " $x $y";
236 }
237 } elsif ($type eq 'stringvector') {
238 $val = [ ];
239 my $pos = 0;
240 while ($pos + 4 <= length($buff)) {
241 my $len = Get32u(\$buff, $pos);
242 last if $pos + 4 + $len > length($buff);
243 push @$val, substr($buff, $pos + 4, $len);
244 $pos += 4 + $len;
245 }
246 } else {
247 $val = \$buff; # (shouldn't happen)
248 }
249 } else {
250 # avoid loading binary data
251 $val = \ "Binary data $size bytes";
252 $success = $raf->Seek($size, 1);
253 }
254 unless ($success) {
255 $et->Warn('Truncated or corrupted EXR file');
256 last;
257 }
258 $val = '<bad>' unless defined $val;
259
260 # take image dimensions from dataWindow (with displayWindow as backup)
261 if (($tag eq 'dataWindow' or (not $dim and $tag eq 'displayWindow')) and
262 $val =~ /^(-?\d+) (-?\d+) (-?\d+) (-?\d+)$/)
263 {
264 $dim = [$3 - $1 + 1, $4 - $2 + 1];
265 }
266 if ($verbose) {
267 my $dataPt = ref $val ? $val : \$val,
268 $et->VerboseInfo($tag, $tagInfo,
269 Table => $tagTablePtr,
270 Value => $val,
271 Size => $size,
272 Format => $type,
273 DataPt => \$buff,
274 Addr => $raf->Tell() - $size,
275 );
276 }
277 $et->FoundTag($tagInfo, $val);
278 }
279 if ($dim) {
280 $et->FoundTag('ImageWidth', $$dim[0]);
281 $et->FoundTag('ImageHeight', $$dim[1]);
282 }
283 return 1;
284}
285
2861; # end
287
288__END__
289
290=head1 NAME
291
292Image::ExifTool::OpenEXR - Read OpenEXR meta information
293
294=head1 SYNOPSIS
295
296This module is used by Image::ExifTool
297
298=head1 DESCRIPTION
299
300This module contains definitions required by Image::ExifTool to extract meta
301information from OpenEXR images.
302
303=head1 AUTHOR
304
305Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
306
307This library is free software; you can redistribute it and/or modify it
308under the same terms as Perl itself.
309
310=head1 REFERENCES
311
312=over 4
313
314=item L<http://www.openexr.com/documentation.html>
315
316=back
317
318=head1 SEE ALSO
319
320L<Image::ExifTool::TagNames/OpenEXR Tags>,
321L<Image::ExifTool(3pm)|Image::ExifTool>
322
323=cut
324
Note: See TracBrowser for help on using the repository browser.