source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/MIE.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

File size: 101.5 KB
Line 
1#------------------------------------------------------------------------------
2# File: MIE.pm
3#
4# Description: Read/write MIE meta information
5#
6# Revisions: 11/18/2005 - P. Harvey Created
7#------------------------------------------------------------------------------
8
9package Image::ExifTool::MIE;
10
11use strict;
12use vars qw($VERSION %tableDefaults);
13use Image::ExifTool qw(:DataAccess :Utils);
14use Image::ExifTool::Exif;
15use Image::ExifTool::GPS;
16
17$VERSION = '1.34';
18
19sub ProcessMIE($$);
20sub ProcessMIEGroup($$$);
21sub WriteMIEGroup($$$);
22sub CheckMIE($$$);
23sub GetLangInfo($$);
24
25# local variables
26my $hasZlib; # 1=Zlib available, 0=no Zlib
27my %mieCode; # reverse lookup for MIE format names
28my $doneMieMap; # flag indicating we added user-defined groups to %mieMap
29
30# MIE format codes
31my %mieFormat = (
32 0x00 => 'undef',
33 0x10 => 'MIE',
34 0x18 => 'MIE',
35 0x20 => 'string', # ASCII (ISO 8859-1)
36 0x28 => 'utf8',
37 0x29 => 'utf16',
38 0x2a => 'utf32',
39 0x30 => 'string_list',
40 0x38 => 'utf8_list',
41 0x39 => 'utf16_list',
42 0x3a => 'utf32_list',
43 0x40 => 'int8u',
44 0x41 => 'int16u',
45 0x42 => 'int32u',
46 0x43 => 'int64u',
47 0x48 => 'int8s',
48 0x49 => 'int16s',
49 0x4a => 'int32s',
50 0x4b => 'int64s',
51 0x52 => 'rational32u',
52 0x53 => 'rational64u',
53 0x5a => 'rational32s',
54 0x5b => 'rational64s',
55 0x61 => 'fixed16u',
56 0x62 => 'fixed32u',
57 0x69 => 'fixed16s',
58 0x6a => 'fixed32s',
59 0x72 => 'float',
60 0x73 => 'double',
61 0x80 => 'free',
62);
63
64# map of MIE directory locations
65my %mieMap = (
66 'MIE-Meta' => 'MIE',
67 'MIE-Audio' => 'MIE-Meta',
68 'MIE-Camera' => 'MIE-Meta',
69 'MIE-Doc' => 'MIE-Meta',
70 'MIE-Geo' => 'MIE-Meta',
71 'MIE-Image' => 'MIE-Meta',
72 'MIE-MakerNotes' => 'MIE-Meta',
73 'MIE-Preview' => 'MIE-Meta',
74 'MIE-Thumbnail' => 'MIE-Meta',
75 'MIE-Video' => 'MIE-Meta',
76 'MIE-Flash' => 'MIE-Camera',
77 'MIE-Lens' => 'MIE-Camera',
78 'MIE-Orient' => 'MIE-Camera',
79 'MIE-Extender' => 'MIE-Lens',
80 'MIE-GPS' => 'MIE-Geo',
81 'MIE-UTM' => 'MIE-Geo',
82 'MIE-Canon' => 'MIE-MakerNotes',
83 EXIF => 'MIE-Meta',
84 XMP => 'MIE-Meta',
85 IPTC => 'MIE-Meta',
86 ICC_Profile => 'MIE-Meta',
87 ID3 => 'MIE-Meta',
88 CanonVRD => 'MIE-Canon',
89 IFD0 => 'EXIF',
90 IFD1 => 'IFD0',
91 ExifIFD => 'IFD0',
92 GPS => 'IFD0',
93 SubIFD => 'IFD0',
94 GlobParamIFD => 'IFD0',
95 PrintIM => 'IFD0',
96 InteropIFD => 'ExifIFD',
97 MakerNotes => 'ExifIFD',
98);
99
100# convenience variables for common tagInfo entries
101my %binaryConv = (
102 Writable => 'undef',
103 Binary => 1,
104);
105my %dateInfo = (
106 Shift => 'Time',
107 PrintConv => '$self->ConvertDateTime($val)',
108 PrintConvInv => '$self->InverseDateTime($val)',
109);
110my %noYes = ( 0 => 'No', 1 => 'Yes' );
111my %offOn = ( 0 => 'Off', 1 => 'On' );
112
113# default entries for MIE tag tables
114%tableDefaults = (
115 PROCESS_PROC => \&ProcessMIE,
116 WRITE_PROC => \&ProcessMIE,
117 CHECK_PROC => \&CheckMIE,
118 LANG_INFO => \&GetLangInfo,
119 WRITABLE => 'string',
120 PREFERRED => 1,
121);
122
123# MIE info
124%Image::ExifTool::MIE::Main = (
125 %tableDefaults,
126 GROUPS => { 1 => 'MIE-Main' },
127 WRITE_GROUP => 'MIE-Main',
128 NOTES => q{
129 MIE is a flexible format which may be used as a stand-alone meta information
130 format, for encapsulation of other files and information, or as a trailer
131 appended to other file formats. The tables below represent currently
132 defined MIE tags, however ExifTool will also extract any other information
133 present in a MIE file.
134
135 When writing MIE information, some special features are supported:
136
137 1) String values may be written as ASCII (ISO 8859-1) or UTF-8. ExifTool
138 automatically detects the presence of wide characters and treats the string
139 appropriately. Internally, UTF-8 text may be converted to UTF-16 or UTF-32
140 and stored in this format in the file if it is more compact.
141
142 2) All MIE string-value tags support localized text. Localized values are
143 written by adding a language/country code to the tag name in the form
144 C<TAG-xx_YY>, where C<TAG> is the tag name, C<xx> is a 2-character lower
145 case ISO 639-1 language code, and C<YY> is a 2-character upper case ISO
146 3166-1 alpha 2 country code (ie. C<Title-en_US>). But as usual, the user
147 interface is case-insensitive, and ExifTool will write the correct case to
148 the file.
149
150 3) Some numerical MIE tags allow units of measurement to be specified. For
151 these tags, units may be added in brackets immediately following the value
152 (ie. C<55(mi/h)>). If no units are specified, the default units are
153 written.
154 },
155 '0Type' => {
156 Name => 'SubfileType',
157 Notes => q{
158 the capitalized common extension for this type of file. If the extension
159 has a dot-3 abbreviation, then the longer version is used here. For
160 instance, JPEG and TIFF are used, not JPG and TIF
161 },
162 },
163 '0Vers' => {
164 Name => 'MIEVersion',
165 Notes => 'version 1.1 is assumed if not specified',
166 },
167 '1Directory' => {
168 Name => 'SubfileDirectory',
169 Notes => 'original directory for the file',
170 },
171 '1Name' => {
172 Name => 'SubfileName',
173 Notes => 'the file name, including extension if it exists',
174 },
175 '2MIME' => { Name => 'SubfileMIMEType' },
176 Meta => {
177 SubDirectory => {
178 TagTable => 'Image::ExifTool::MIE::Meta',
179 DirName => 'MIE-Meta',
180 },
181 },
182 data => {
183 Name => 'SubfileData',
184 Notes => 'the subfile data',
185 %binaryConv,
186 },
187 rsrc => {
188 Name => 'SubfileResource',
189 Notes => 'subfile resource fork if it exists',
190 %binaryConv,
191 },
192 zmd5 => {
193 Name => 'MD5Digest',
194 Notes => q{
195 16-byte MD5 digest written in binary form or as a 32-character hex-encoded
196 ASCII string. Value is an MD5 digest of the entire 0MIE group as it would be
197 with the digest value itself set to all null bytes
198 },
199 },
200 zmie => {
201 Name => 'TrailerSignature',
202 Writable => 'undef',
203 Notes => q{
204 used as the last element in the main "0MIE" group to identify a MIE trailer
205 when appended to another type of file. ExifTool will create this tag if set
206 to any value, but always with an empty data block
207 },
208 ValueConvInv => '""', # data block must be empty
209 },
210);
211
212# MIE meta information group
213%Image::ExifTool::MIE::Meta = (
214 %tableDefaults,
215 GROUPS => { 1 => 'MIE-Meta', 2 => 'Image' },
216 WRITE_GROUP => 'MIE-Meta',
217 Audio => {
218 SubDirectory => {
219 TagTable => 'Image::ExifTool::MIE::Audio',
220 DirName => 'MIE-Audio',
221 },
222 },
223 Camera => {
224 SubDirectory => {
225 TagTable => 'Image::ExifTool::MIE::Camera',
226 DirName => 'MIE-Camera',
227 },
228 },
229 Document => {
230 SubDirectory => {
231 TagTable => 'Image::ExifTool::MIE::Doc',
232 DirName => 'MIE-Doc',
233 },
234 },
235 EXIF => {
236 SubDirectory => {
237 TagTable => 'Image::ExifTool::Exif::Main',
238 ProcessProc => \&Image::ExifTool::ProcessTIFF,
239 WriteProc => \&Image::ExifTool::WriteTIFF,
240 },
241 },
242 Geo => {
243 SubDirectory => {
244 TagTable => 'Image::ExifTool::MIE::Geo',
245 DirName => 'MIE-Geo',
246 },
247 },
248 ICCProfile => {
249 Name => 'ICC_Profile',
250 SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
251 },
252 ID3 => { SubDirectory => { TagTable => 'Image::ExifTool::ID3::Main' } },
253 IPTC => { SubDirectory => { TagTable => 'Image::ExifTool::IPTC::Main' } },
254 Image => {
255 SubDirectory => {
256 TagTable => 'Image::ExifTool::MIE::Image',
257 DirName => 'MIE-Image',
258 },
259 },
260 MakerNotes => {
261 SubDirectory => {
262 TagTable => 'Image::ExifTool::MIE::MakerNotes',
263 DirName => 'MIE-MakerNotes',
264 },
265 },
266 Preview => {
267 SubDirectory => {
268 TagTable => 'Image::ExifTool::MIE::Preview',
269 DirName => 'MIE-Preview',
270 },
271 },
272 Thumbnail => {
273 SubDirectory => {
274 TagTable => 'Image::ExifTool::MIE::Thumbnail',
275 DirName => 'MIE-Thumbnail',
276 },
277 },
278 Video => {
279 SubDirectory => {
280 TagTable => 'Image::ExifTool::MIE::Video',
281 DirName => 'MIE-Video',
282 },
283 },
284 XMP => { SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' } },
285);
286
287# MIE document information
288%Image::ExifTool::MIE::Doc = (
289 %tableDefaults,
290 GROUPS => { 1 => 'MIE-Doc', 2 => 'Document' },
291 WRITE_GROUP => 'MIE-Doc',
292 NOTES => 'Information describing the main document, image or file.',
293 Author => { Groups => { 2 => 'Author' } },
294 Comment => { },
295 Contributors=> { Groups => { 2 => 'Author' }, List => 1 },
296 Copyright => { Groups => { 2 => 'Author' } },
297 CreateDate => { Groups => { 2 => 'Time' }, %dateInfo },
298 EMail => { Groups => { 2 => 'Author' } },
299 Keywords => { List => 1 },
300 ModifyDate => { Groups => { 2 => 'Time' }, %dateInfo },
301 OriginalDate=> {
302 Name => 'DateTimeOriginal',
303 Description => 'Date/Time Original',
304 Groups => { 2 => 'Time' },
305 %dateInfo,
306 },
307 Phone => { Name => 'PhoneNumber', Groups => { 2 => 'Author' } },
308 References => { List => 1 },
309 Software => { },
310 Title => { },
311 URL => { },
312);
313
314# MIE geographic information
315%Image::ExifTool::MIE::Geo = (
316 %tableDefaults,
317 GROUPS => { 1 => 'MIE-Geo', 2 => 'Location' },
318 WRITE_GROUP => 'MIE-Geo',
319 NOTES => 'Information related to geographic location.',
320 Address => { },
321 City => { },
322 Country => { },
323 GPS => {
324 SubDirectory => {
325 TagTable => 'Image::ExifTool::MIE::GPS',
326 DirName => 'MIE-GPS',
327 },
328 },
329 PostalCode => { },
330 State => { Notes => 'state or province' },
331 UTM => {
332 SubDirectory => {
333 TagTable => 'Image::ExifTool::MIE::UTM',
334 DirName => 'MIE-UTM',
335 },
336 },
337);
338
339# MIE GPS information
340%Image::ExifTool::MIE::GPS = (
341 %tableDefaults,
342 GROUPS => { 1 => 'MIE-GPS', 2 => 'Location' },
343 WRITE_GROUP => 'MIE-GPS',
344 Altitude => {
345 Name => 'GPSAltitude',
346 Writable => 'rational64s',
347 Units => [ qw(m ft) ],
348 Notes => q{'m' above sea level unless 'ft' specified},
349 },
350 Bearing => {
351 Name => 'GPSDestBearing',
352 Writable => 'rational64s',
353 Units => [ qw(deg deg{mag}) ],
354 Notes => q{'deg' CW from true north unless 'deg{mag}' specified},
355 },
356 Datum => { Name => 'GPSMapDatum', Notes => 'WGS-84 assumed if not specified' },
357 Differential => {
358 Name => 'GPSDifferential',
359 Writable => 'int8u',
360 PrintConv => {
361 0 => 'No Correction',
362 1 => 'Differential Corrected',
363 },
364 },
365 Distance => {
366 Name => 'GPSDestDistance',
367 Writable => 'rational64s',
368 Units => [ qw(km mi nmi) ],
369 Notes => q{'km' unless 'mi' or 'nmi' specified},
370 },
371 Heading => {
372 Name => 'GPSTrack',
373 Writable => 'rational64s',
374 Units => [ qw(deg deg{mag}) ],
375 Notes => q{'deg' CW from true north unless 'deg{mag}' specified},
376 },
377 Latitude => {
378 Name => 'GPSLatitude',
379 Writable => 'rational64s',
380 Count => -1,
381 Notes => q{
382 1 to 3 numbers: degrees, minutes then seconds. South latitudes are stored
383 as all negative numbers, but may be entered as positive numbers with a
384 trailing 'S' for convenience. For example, these are all equivalent: "-40
385 -30", "-40.5", "40 30 0.00 S"
386 },
387 ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)',
388 ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 0)',
389 PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
390 PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)',
391 },
392 Longitude => {
393 Name => 'GPSLongitude',
394 Writable => 'rational64s',
395 Count => -1,
396 Notes => q{
397 1 to 3 numbers: degrees, minutes then seconds. West longitudes are
398 negative, but may be entered as positive numbers with a trailing 'W'
399 },
400 ValueConv => 'Image::ExifTool::GPS::ToDegrees($val, 1)',
401 ValueConvInv => 'Image::ExifTool::GPS::ToDMS($self, $val, 0)',
402 PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
403 PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1)',
404 },
405 MeasureMode => {
406 Name => 'GPSMeasureMode',
407 Writable => 'int8u',
408 PrintConv => { 2 => '2-D', 3 => '3-D' },
409 },
410 Satellites => 'GPSSatellites',
411 Speed => {
412 Name => 'GPSSpeed',
413 Writable => 'rational64s',
414 Units => [ qw(km/h mi/h m/s kn) ],
415 Notes => q{'km/h' unless 'mi/h', 'm/s' or 'kn' specified},
416 },
417 DateTime => { Name => 'GPSDateTime', Groups => { 2 => 'Time' }, %dateInfo },
418);
419
420# MIE UTM information
421%Image::ExifTool::MIE::UTM = (
422 %tableDefaults,
423 GROUPS => { 1 => 'MIE-UTM', 2 => 'Location' },
424 WRITE_GROUP => 'MIE-UTM',
425 Datum => { Name => 'UTMMapDatum', Notes => 'WGS-84 assumed if not specified' },
426 Easting => { Name => 'UTMEasting' },
427 Northing => { Name => 'UTMNorthing' },
428 Zone => { Name => 'UTMZone', Writable => 'int8s' },
429);
430
431# MIE image information
432%Image::ExifTool::MIE::Image = (
433 %tableDefaults,
434 GROUPS => { 1 => 'MIE-Image', 2 => 'Image' },
435 WRITE_GROUP => 'MIE-Image',
436 '0Type' => { Name => 'FullSizeImageType', Notes => 'JPEG if not specified' },
437 '1Name' => { Name => 'FullSizeImageName' },
438 BitDepth => { Name => 'BitDepth', Writable => 'int16u' },
439 ColorSpace => { Notes => 'standard ColorSpace values are "sRGB" and "Adobe RGB"' },
440 Components => {
441 Name => 'ComponentsConfiguration',
442 Notes => 'string composed of R, G, B, Y, Cb and Cr',
443 },
444 Compression => { Name => 'CompressionRatio', Writable => 'rational32u' },
445 ImageSize => {
446 Writable => 'int16u',
447 Count => -1,
448 Notes => '2 or 3 values, for number of XY or XYZ pixels',
449 PrintConv => '$val=~tr/ /x/;$val',
450 PrintConvInv => '$val=~tr/x/ /;$val',
451 },
452 Resolution => {
453 Writable => 'rational64u',
454 Units => [ qw(/in /cm /deg /arcmin /arcsec), '' ],
455 Count => -1,
456 Notes => q{
457 1 to 3 values. A single value for equal resolution in all directions, or
458 separate X, Y and Z values if necessary. Units are '/in' unless '/cm',
459 '/deg', '/arcmin', '/arcsec' or '' specified
460 },
461 PrintConv => '$val=~tr/ /x/;$val',
462 PrintConvInv => '$val=~tr/x/ /;$val',
463 },
464 data => {
465 Name => 'FullSizeImage',
466 %binaryConv,
467 RawConv => '$self->ValidateImage(\$val,$tag)',
468 },
469);
470
471# MIE preview image
472%Image::ExifTool::MIE::Preview = (
473 %tableDefaults,
474 GROUPS => { 1 => 'MIE-Preview', 2 => 'Image' },
475 WRITE_GROUP => 'MIE-Preview',
476 '0Type' => { Name => 'PreviewImageType', Notes => 'JPEG if not specified' },
477 '1Name' => { Name => 'PreviewImageName' },
478 ImageSize => {
479 Name => 'PreviewImageSize',
480 Writable => 'int16u',
481 Count => -1,
482 Notes => '2 or 3 values, for number of XY or XYZ pixels',
483 PrintConv => '$val=~tr/ /x/;$val',
484 PrintConvInv => '$val=~tr/x/ /;$val',
485 },
486 data => {
487 Name => 'PreviewImage',
488 %binaryConv,
489 RawConv => '$self->ValidateImage(\$val,$tag)',
490 },
491);
492
493# MIE thumbnail image
494%Image::ExifTool::MIE::Thumbnail = (
495 %tableDefaults,
496 GROUPS => { 1 => 'MIE-Thumbnail', 2 => 'Image' },
497 WRITE_GROUP => 'MIE-Thumbnail',
498 '0Type' => { Name => 'ThumbnailImageType', Notes => 'JPEG if not specified' },
499 '1Name' => { Name => 'ThumbnailImageName' },
500 ImageSize => {
501 Name => 'ThumbnailImageSize',
502 Writable => 'int16u',
503 Count => -1,
504 Notes => '2 or 3 values, for number of XY or XYZ pixels',
505 PrintConv => '$val=~tr/ /x/;$val',
506 PrintConvInv => '$val=~tr/x/ /;$val',
507 },
508 data => {
509 Name => 'ThumbnailImage',
510 %binaryConv,
511 RawConv => '$self->ValidateImage(\$val,$tag)',
512 },
513);
514
515# MIE audio information
516%Image::ExifTool::MIE::Audio = (
517 %tableDefaults,
518 GROUPS => { 1 => 'MIE-Audio', 2 => 'Audio' },
519 WRITE_GROUP => 'MIE-Audio',
520 NOTES => q{
521 For the Audio group (and any other group containing a 'data' element), tags
522 refer to the contained data if present, otherwise they refer to the main
523 SubfileData. The C<0Type> and C<1Name> elements should exist only if C<data>
524 is present.
525 },
526 '0Type' => { Name => 'RelatedAudioFileType', Notes => 'MP3 if not specified' },
527 '1Name' => { Name => 'RelatedAudioFileName' },
528 SampleBits => { Writable => 'int16u' },
529 Channels => { Writable => 'int8u' },
530 Compression => { Name => 'AudioCompression' },
531 Duration => { Writable => 'rational64u', PrintConv => 'ConvertDuration($val)' },
532 SampleRate => { Writable => 'int32u' },
533 data => { Name => 'RelatedAudioFile', %binaryConv },
534);
535
536# MIE video information
537%Image::ExifTool::MIE::Video = (
538 %tableDefaults,
539 GROUPS => { 1 => 'MIE-Video', 2 => 'Video' },
540 WRITE_GROUP => 'MIE-Video',
541 '0Type' => { Name => 'RelatedVideoFileType', Notes => 'MOV if not specified' },
542 '1Name' => { Name => 'RelatedVideoFileName' },
543 Codec => { },
544 Duration => { Writable => 'rational64u', PrintConv => 'ConvertDuration($val)' },
545 data => { Name => 'RelatedVideoFile', %binaryConv },
546);
547
548# MIE camera information
549%Image::ExifTool::MIE::Camera = (
550 %tableDefaults,
551 GROUPS => { 1 => 'MIE-Camera', 2 => 'Camera' },
552 WRITE_GROUP => 'MIE-Camera',
553 Brightness => { Writable => 'int8s' },
554 ColorTemperature=> { Writable => 'int32u' },
555 ColorBalance => {
556 Writable => 'rational64u',
557 Count => 3,
558 Notes => 'RGB scaling factors',
559 },
560 Contrast => { Writable => 'int8s' },
561 DigitalZoom => { Writable => 'rational64u' },
562 ExposureComp => { Name => 'ExposureCompensation', Writable => 'rational64s' },
563 ExposureMode => { },
564 ExposureTime => {
565 Writable => 'rational64u',
566 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
567 PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
568 },
569 Flash => {
570 SubDirectory => {
571 TagTable => 'Image::ExifTool::MIE::Flash',
572 DirName => 'MIE-Flash',
573 },
574 },
575 FirmwareVersion => { },
576 FocusMode => { },
577 ISO => { Writable => 'int16u' },
578 ISOSetting => {
579 Writable => 'int16u',
580 Notes => '0 = Auto, otherwise manual ISO speed setting',
581 },
582 ImageNumber => { Writable => 'int32u' },
583 ImageQuality => { Notes => 'Economy, Normal, Fine, Super Fine or Raw' },
584 ImageStabilization => { Writable => 'int8u', %offOn },
585 Lens => {
586 SubDirectory => {
587 TagTable => 'Image::ExifTool::MIE::Lens',
588 DirName => 'MIE-Lens',
589 },
590 },
591 Make => { },
592 MeasuredEV => { Writable => 'rational64s' },
593 Model => { },
594 OwnerName => { },
595 Orientation => {
596 SubDirectory => {
597 TagTable => 'Image::ExifTool::MIE::Orient',
598 DirName => 'MIE-Orient',
599 },
600 },
601 Saturation => { Writable => 'int8s' },
602 SensorSize => {
603 Writable => 'rational64u',
604 Count => 2,
605 Notes => 'width and height of active sensor area in mm',
606 },
607 SerialNumber => { },
608 Sharpness => { Writable => 'int8s' },
609 ShootingMode => { },
610);
611
612# Camera orientation information
613%Image::ExifTool::MIE::Orient = (
614 %tableDefaults,
615 GROUPS => { 1 => 'MIE-Orient', 2 => 'Camera' },
616 WRITE_GROUP => 'MIE-Orient',
617 NOTES => 'These tags describe the camera orientation.',
618 Azimuth => {
619 Writable => 'rational64s',
620 Units => [ qw(deg deg{mag}) ],
621 Notes => q{'deg' CW from true north unless 'deg{mag}' specified},
622 },
623 Declination => { Writable => 'rational64s' },
624 Elevation => { Writable => 'rational64s' },
625 RightAscension => { Writable => 'rational64s' },
626 Rotation => {
627 Writable => 'rational64s',
628 Notes => 'CW rotation angle of camera about lens axis',
629 },
630);
631
632# MIE camera lens information
633%Image::ExifTool::MIE::Lens = (
634 %tableDefaults,
635 GROUPS => { 1 => 'MIE-Lens', 2 => 'Camera' },
636 WRITE_GROUP => 'MIE-Lens',
637 NOTES => q{
638 All recorded lens parameters (focal length, aperture, etc) include the
639 effects of the extender if present.
640 },
641 Extender => {
642 SubDirectory => {
643 TagTable => 'Image::ExifTool::MIE::Extender',
644 DirName => 'MIE-Extender',
645 },
646 },
647 FNumber => { Writable => 'rational64u' },
648 FocalLength => { Writable => 'rational64u', Notes => 'all focal lengths in mm' },
649 FocusDistance => {
650 Writable => 'rational64u',
651 Units => [ qw(m ft) ],
652 Notes => q{'m' unless 'ft' specified},
653 },
654 Make => { Name => 'LensMake' },
655 MaxAperture => { Writable => 'rational64u' },
656 MaxApertureAtMaxFocal => { Writable => 'rational64u' },
657 MaxFocalLength => { Writable => 'rational64u' },
658 MinAperture => { Writable => 'rational64u' },
659 MinFocalLength => { Writable => 'rational64u' },
660 Model => { Name => 'LensModel' },
661 OpticalZoom => { Writable => 'rational64u' },
662 SerialNumber => { Name => 'LensSerialNumber' },
663);
664
665# MIE lens extender information
666%Image::ExifTool::MIE::Extender = (
667 %tableDefaults,
668 GROUPS => { 1 => 'MIE-Extender', 2 => 'Camera' },
669 WRITE_GROUP => 'MIE-Extender',
670 Magnification => { Name => 'ExtenderMagnification', Writable => 'rational64s' },
671 Make => { Name => 'ExtenderMake' },
672 Model => { Name => 'ExtenderModel' },
673 SerialNumber => { Name => 'ExtenderSerialNumber' },
674);
675
676# MIE camera flash information
677%Image::ExifTool::MIE::Flash = (
678 %tableDefaults,
679 GROUPS => { 1 => 'MIE-Flash', 2 => 'Camera' },
680 WRITE_GROUP => 'MIE-Flash',
681 ExposureComp => { Name => 'FlashExposureComp', Writable => 'rational64s' },
682 Fired => { Name => 'FlashFired', Writable => 'int8u', PrintConv => \%noYes },
683 GuideNumber => { Name => 'FlashGuideNumber' },
684 Make => { Name => 'FlashMake' },
685 Mode => { Name => 'FlashMode' },
686 Model => { Name => 'FlashModel' },
687 SerialNumber => { Name => 'FlashSerialNumber' },
688 Type => { Name => 'FlashType', Notes => '"Internal" or "External"' },
689);
690
691# MIE maker notes information
692%Image::ExifTool::MIE::MakerNotes = (
693 %tableDefaults,
694 GROUPS => { 1 => 'MIE-MakerNotes' },
695 WRITE_GROUP => 'MIE-MakerNotes',
696 NOTES => q{
697 MIE maker notes are contained within separate groups for each manufacturer
698 to avoid name conflicts.
699 },
700 Canon => {
701 SubDirectory => {
702 TagTable => 'Image::ExifTool::MIE::Canon',
703 DirName => 'MIE-Canon',
704 },
705 },
706 Casio => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
707 FujiFilm => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
708 Kodak => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
709 KonicaMinolta=>{ SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
710 Nikon => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
711 Olympus => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
712 Panasonic => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
713 Pentax => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
714 Ricoh => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
715 Sigma => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
716 Sony => { SubDirectory => { TagTable => 'Image::ExifTool::MIE::Unknown' } },
717);
718
719# MIE Canon-specific information
720%Image::ExifTool::MIE::Canon = (
721 %tableDefaults,
722 GROUPS => { 1 => 'MIE-Canon' },
723 WRITE_GROUP => 'MIE-Canon',
724 VRD => {
725 Name => 'CanonVRD',
726 SubDirectory => { TagTable => 'Image::ExifTool::CanonVRD::Main' },
727 },
728);
729
730%Image::ExifTool::MIE::Unknown = (
731 PROCESS_PROC => \&ProcessMIE,
732 GROUPS => { 1 => 'MIE-Unknown' },
733);
734
735#------------------------------------------------------------------------------
736# Add user-defined MIE groups to %mieMap
737# Inputs: none; Returns: nothing, but sets $doneMieMap flag
738sub UpdateMieMap()
739{
740 $doneMieMap = 1; # set flag so we only do this once
741 return unless %Image::ExifTool::UserDefined;
742 my ($tableName, @tables, %doneTable, $tagID);
743 # get list of top-level MIE tables with user-defined tags
744 foreach $tableName (keys %Image::ExifTool::UserDefined) {
745 next unless $tableName =~ /^Image::ExifTool::MIE::/;
746 my $userTable = $Image::ExifTool::UserDefined{$tableName};
747 my $tagTablePtr = GetTagTable($tableName) or next;
748 # copy the WRITE_GROUP from the actual table
749 $$userTable{WRITE_GROUP} = $$tagTablePtr{WRITE_GROUP};
750 # add to list of tables to process
751 $doneTable{$tableName} = 1;
752 push @tables, [$tableName, $userTable];
753 }
754 # recursively add all user-defined groups to MIE map
755 while (@tables) {
756 my ($tableName, $tagTablePtr) = @{shift @tables};
757 my $parent = $$tagTablePtr{WRITE_GROUP};
758 $parent or warn("No WRITE_GROUP for $tableName\n"), next;
759 $mieMap{$parent} or warn("$parent is not in MIE map\n"), next;
760 foreach $tagID (TagTableKeys($tagTablePtr)) {
761 my $tagInfo = $$tagTablePtr{$tagID};
762 next unless ref $tagInfo eq 'HASH' and $$tagInfo{SubDirectory};
763 my $subTableName = $tagInfo->{SubDirectory}->{TagTable};
764 my $subTablePtr = GetTagTable($subTableName) or next;
765 # only care about MIE tables
766 next unless $$subTablePtr{PROCESS_PROC} and
767 $$subTablePtr{PROCESS_PROC} eq \&ProcessMIE;
768 my $group = $$subTablePtr{WRITE_GROUP};
769 $group or warn("No WRITE_GROUP for $subTableName\n"), next;
770 if ($mieMap{$group} and $mieMap{$group} ne $parent) {
771 warn("$group already has different parent ($mieMap{$group})\n"), next;
772 }
773 $mieMap{$group} = $parent; # add to map
774 # process tables within this one too
775 $doneTable{$subTableName} and next;
776 $doneTable{$subTableName} = 1;
777 push @tables, [$subTableName, $subTablePtr];
778 }
779 }
780}
781
782#------------------------------------------------------------------------------
783# Get localized version of tagInfo hash
784# Inputs: 0) tagInfo hash ref, 1) locale code (ie. "en_CA")
785# Returns: new tagInfo hash ref, or undef if invalid
786sub GetLangInfo($$)
787{
788 my ($tagInfo, $langCode) = @_;
789 # check for properly formatted language code
790 return undef unless $langCode =~ /^[a-z]{2}([-_])[A-Z]{2}$/;
791 # use '_' as a separator, but recognize '_' or '-'
792 $langCode =~ tr/-/_/ if $1 eq '-';
793 # can only set locale on string types
794 return undef if $$tagInfo{Writable} and $$tagInfo{Writable} ne 'string';
795 return Image::ExifTool::GetLangInfo($tagInfo, $langCode);
796}
797
798#------------------------------------------------------------------------------
799# return true if we have Zlib::Compress
800# Inputs: 0) ExifTool object ref, 1) verb for what you want to do with the info
801# Returns: 1 if Zlib available, 0 otherwise
802sub HasZlib($$)
803{
804 unless (defined $hasZlib) {
805 $hasZlib = eval 'require Compress::Zlib';
806 unless ($hasZlib) {
807 $hasZlib = 0;
808 $_[0]->Warn("Install Compress::Zlib to $_[1] compressed information");
809 }
810 }
811 return $hasZlib;
812}
813
814#------------------------------------------------------------------------------
815# Get format code for MIE group element with current byte order
816# Inputs: 0) [optional] true to convert result to chr()
817# Returns: format code
818sub MIEGroupFormat(;$)
819{
820 my $chr = shift;
821 my $format = GetByteOrder() eq 'MM' ? 0x10 : 0x18;
822 return $chr ? chr($format) : $format;
823}
824
825#------------------------------------------------------------------------------
826# ReadValue() with added support for UTF formats (utf8, utf16 and utf32)
827# Inputs: 0) data reference, 1) value offset, 2) format string,
828# 3) number of values (or undef to use all data)
829# 4) valid data length relative to offset
830# Returns: converted value, or undefined if data isn't there
831# or list of values in list context
832# Notes: all string formats are converted to UTF8
833sub ReadMIEValue($$$$$)
834{
835 my ($dataPt, $offset, $format, $count, $size) = @_;
836 my $val;
837 if ($format =~ /^(utf(8|16|32)|string)/) {
838 if ($1 eq 'utf8' or $1 eq 'string') {
839 # read the 8-bit string
840 $val = substr($$dataPt, $offset, $size);
841 # (as of ExifTool 7.62, leave string values unconverted)
842 } else {
843 # convert to UTF8
844 my $fmt;
845 if (GetByteOrder() eq 'MM') {
846 $fmt = ($1 eq 'utf16') ? 'n' : 'N';
847 } else {
848 $fmt = ($1 eq 'utf16') ? 'v' : 'V';
849 }
850 my @unpk = unpack("x$offset$fmt$size",$$dataPt);
851 if ($] >= 5.006001) {
852 $val = pack('C0U*', @unpk);
853 } else {
854 $val = Image::ExifTool::PackUTF8(@unpk);
855 }
856 }
857 # truncate at null unless this is a list
858 # (strings shouldn't have a null, but just in case)
859 $val =~ s/\0.*//s unless $format =~ /_list$/;
860 } else {
861 $format = 'undef' if $format eq 'free'; # read 'free' as 'undef'
862 return ReadValue($dataPt, $offset, $format, $count, $size);
863 }
864 return $val;
865}
866
867#------------------------------------------------------------------------------
868# validate raw values for writing
869# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref
870# Returns: error string or undef (and possibly changes value) on success
871sub CheckMIE($$$)
872{
873 my ($exifTool, $tagInfo, $valPtr) = @_;
874 my $format = $$tagInfo{Writable} || $tagInfo->{Table}->{WRITABLE};
875 my $err;
876
877 return 'No writable format' if not $format or $format eq '1';
878 # handle units if supported by this tag
879 my $ulist = $$tagInfo{Units};
880 if ($ulist and $$valPtr =~ /(.*)\((.*)\)$/) {
881 my ($val, $units) = ($1, $2);
882 ($units) = grep /^$units$/i, @$ulist;
883 defined $units or return 'Allowed units: (' . join('|', @$ulist) . ')';
884 $err = Image::ExifTool::CheckValue(\$val, $format, $$tagInfo{Count});
885 # add units back onto value
886 $$valPtr = "$val($units)" unless $err;
887 } elsif ($format !~ /^(utf|string|undef)/ and $$valPtr =~ /\)$/) {
888 return 'Units not supported';
889 } else {
890 if ($format eq 'string' and $exifTool->{OPTIONS}->{Charset} ne 'UTF8' and
891 $$valPtr =~ /[\x80-\xff]/)
892 {
893 # convert from Charset to UTF-8
894 $$valPtr = $exifTool->Encode($$valPtr,'UTF8');
895 }
896 $err = Image::ExifTool::CheckValue($valPtr, $format, $$tagInfo{Count});
897 }
898 return $err;
899}
900
901#------------------------------------------------------------------------------
902# Rewrite a MIE directory
903# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ptr
904# Returns: undef on success, otherwise error message (empty message if nothing to write)
905sub WriteMIEGroup($$$)
906{
907 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
908 my $outfile = $$dirInfo{OutFile};
909 my $dirName = $$dirInfo{DirName};
910 my $toWrite = $$dirInfo{ToWrite} || '';
911 my $raf = $$dirInfo{RAF};
912 my $verbose = $exifTool->Options('Verbose');
913 my $optCompress = $exifTool->Options('Compress');
914 my $out = $exifTool->Options('TextOut');
915 my ($msg, $err, $ok, $sync, $delGroup);
916 my $tag = '';
917 my $deletedTag = '';
918
919 # count each MIE directory found and make name for this specific instance
920 my ($grp1, %isWriting);
921 my $cnt = $exifTool->{MIE_COUNT};
922 my $grp = $tagTablePtr->{GROUPS}->{1};
923 my $n = $$cnt{'MIE-Main'} || 0;
924 if ($grp eq 'MIE-Main') {
925 $$cnt{$grp} = ++$n;
926 ($grp1 = $grp) =~ s/MIE-/MIE$n-/;
927 } else {
928 ($grp1 = $grp) =~ s/MIE-/MIE$n-/;
929 my $m = $$cnt{$grp1} = ($$cnt{$grp1} || 0) + 1;
930 $isWriting{"$grp$m"} = 1; # ie. 'MIE-Doc2'
931 $isWriting{$grp1} = 1; # ie. 'MIE1-Doc'
932 $grp1 .= $m;
933 }
934 # build lookup for all valid group names for this MIE group
935 $isWriting{$grp} = 1; # ie. 'MIE-Doc'
936 $isWriting{$grp1} = 1; # ie. 'MIE1-Doc2'
937 $isWriting{"MIE$n"} = 1; # ie. 'MIE1'
938
939 # determine if we are deleting this group
940 if (%{$exifTool->{DEL_GROUP}}) {
941 $delGroup = 1 if $exifTool->{DEL_GROUP}->{MIE} or
942 $exifTool->{DEL_GROUP}->{$grp} or
943 $exifTool->{DEL_GROUP}->{$grp1} or
944 $exifTool->{DEL_GROUP}->{"MIE$n"};
945 }
946
947 # prepare lookups and lists for writing
948 my $newTags = $exifTool->GetNewTagInfoHash($tagTablePtr);
949 my ($addDirs, $editDirs) = $exifTool->GetAddDirHash($tagTablePtr, $dirName);
950 my @editTags = sort keys %$newTags, keys %$editDirs;
951 $verbose and print $out $raf ? 'Writing' : 'Creating', " $grp1:\n";
952
953 # loop through elements in MIE group
954 MieElement: for (;;) {
955 my ($format, $tagLen, $valLen, $units, $oldHdr, $buff);
956 my $lastTag = $tag;
957 if ($raf) {
958 # read first 4 bytes of element header
959 my $n = $raf->Read($oldHdr, 4);
960 if ($n != 4) {
961 last if $n or defined $sync;
962 undef $raf; # all done reading
963 $ok = 1;
964 }
965 }
966 if ($raf) {
967 ($sync, $format, $tagLen, $valLen) = unpack('aC3', $oldHdr);
968 $sync eq '~' or $msg = 'Invalid sync byte', last;
969
970 # read tag name
971 if ($tagLen) {
972 $raf->Read($tag, $tagLen) == $tagLen or last;
973 $oldHdr .= $tag; # add tag to element header
974 $exifTool->Warn("MIE tag '$tag' out of sequence") if $tag lt $lastTag;
975 # separate units from tag name if they exist
976 $units = $1 if $tag =~ s/\((.*)\)$//;
977 } else {
978 $tag = '';
979 }
980
981 # get multi-byte value length if necessary
982 if ($valLen > 252) {
983 # calculate number of bytes in extended DataLength
984 my $n = 1 << (256 - $valLen);
985 $raf->Read($buff, $n) == $n or last;
986 $oldHdr .= $buff; # add to old header
987 my $fmt = 'int' . ($n * 8) . 'u';
988 $valLen = ReadValue(\$buff, 0, $fmt, 1, $n);
989 if ($valLen > 0x7fffffff) {
990 $msg = "Can't write $tag (DataLength > 2GB not yet supported)";
991 last;
992 }
993 }
994 # don't rewrite free bytes or information in deleted groups
995 if ($format eq 0x80 or ($delGroup and $tagLen and ($format & 0xf0) != 0x10)) {
996 $raf->Seek($valLen, 1) or $msg = 'Seek error', last;
997 if ($verbose > 1) {
998 my $free = ($format eq 0x80) ? ' free' : '';
999 print $out " - $grp1:$tag ($valLen$free bytes)\n";
1000 }
1001 ++$exifTool->{CHANGED} if $delGroup;
1002 next;
1003 }
1004 } else {
1005 # no more elements to read
1006 $tagLen = $valLen = 0;
1007 $tag = '';
1008 }
1009#
1010# write necessary new tags and process directories
1011#
1012 while (@editTags) {
1013 last if $tagLen and $editTags[0] gt $tag;
1014 # we are writing the new tag now
1015 my ($newVal, $writable, $oldVal, $newFormat, $compress);
1016 my $newTag = shift @editTags;
1017 my $newInfo = $$editDirs{$newTag};
1018 if ($newInfo) {
1019 # create the new subdirectory or rewrite existing non-MIE directory
1020 my $subTablePtr = GetTagTable($newInfo->{SubDirectory}->{TagTable});
1021 unless ($subTablePtr) {
1022 $exifTool->Warn("No tag table for $newTag $$newInfo{Name}");
1023 next;
1024 }
1025 my %subdirInfo;
1026 my $isMieGroup = ($$subTablePtr{WRITE_PROC} and
1027 $$subTablePtr{WRITE_PROC} eq \&ProcessMIE);
1028
1029 if ($newTag eq $tag) {
1030 # make sure that either both or neither old and new tags are MIE groups
1031 if ($isMieGroup xor ($format & 0xf3) == 0x10) {
1032 $exifTool->Warn("Tag '$tag' not expected type");
1033 next; # don't write our new tag
1034 }
1035 # uncompress existing directory into $oldVal since we are editing it
1036 if ($format & 0x04) {
1037 last unless HasZlib($exifTool, 'edit');
1038 $raf->Read($oldVal, $valLen) == $valLen or last MieElement;
1039 my $stat;
1040 my $inflate = Compress::Zlib::inflateInit();
1041 $inflate and ($oldVal, $stat) = $inflate->inflate($oldVal);
1042 unless ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) {
1043 $msg = "Error inflating $tag";
1044 last MieElement;
1045 }
1046 $compress = 1;
1047 $valLen = length $oldVal; # uncompressed value length
1048 }
1049 } else {
1050 # don't create this directory unless necessary
1051 next unless $$addDirs{$newTag};
1052 }
1053
1054 if ($isMieGroup) {
1055 my $hdr;
1056 if ($newTag eq $tag) {
1057 # rewrite existing directory later unless it was compressed
1058 last unless $compress;
1059 # rewrite directory to '$newVal'
1060 $newVal = '';
1061 %subdirInfo = (
1062 OutFile => \$newVal,
1063 RAF => new File::RandomAccess(\$oldVal),
1064 );
1065 } elsif ($optCompress and not $$dirInfo{IsCompressed}) {
1066 # write to memory so we can compress the new MIE group
1067 $compress = 1;
1068 %subdirInfo = (
1069 OutFile => \$newVal,
1070 );
1071 } else {
1072 $hdr = '~' . MIEGroupFormat(1) . chr(length($newTag)) .
1073 "\0" . $newTag;
1074 %subdirInfo = (
1075 OutFile => $outfile,
1076 ToWrite => $toWrite . $hdr,
1077 );
1078 }
1079 $subdirInfo{DirName} = $newInfo->{SubDirectory}->{DirName} || $newTag;
1080 $subdirInfo{Parent} = $dirName;
1081 # don't compress elements of an already compressed group
1082 $subdirInfo{IsCompressed} = 1;
1083 $msg = WriteMIEGroup($exifTool, \%subdirInfo, $subTablePtr);
1084 last MieElement if $msg;
1085 # message is defined but empty if nothing was written
1086 if (defined $msg) {
1087 undef $msg; # not a problem if nothing was written
1088 next;
1089 } elsif (not $compress) {
1090 # group was written already
1091 $toWrite = '';
1092 next;
1093 }
1094 $writable = 'undef';
1095 $newFormat = MIEGroupFormat();
1096 } else {
1097 if ($newTag eq $tag) {
1098 unless ($compress) {
1099 # read and edit existing directory
1100 $raf->Read($oldVal, $valLen) == $valLen or last MieElement;
1101 }
1102 %subdirInfo = (
1103 DataPt => \$oldVal,
1104 DataLen => $valLen,
1105 DirName => $$newInfo{Name},
1106 DataPos => $raf->Tell() - $valLen,
1107 DirStart=> 0,
1108 DirLen => $valLen,
1109 );
1110 # write Compact subdirectories if we will compress the data
1111 if (($compress or $optCompress or $$dirInfo{IsCompressed}) and
1112 eval 'require Compress::Zlib')
1113 {
1114 $subdirInfo{Compact} = 1;
1115 }
1116 }
1117 $subdirInfo{Parent} = $dirName;
1118 my $writeProc = $newInfo->{SubDirectory}->{WriteProc};
1119 # reset processed lookup to avoid errors in case of multiple EXIF blocks
1120 $exifTool->{PROCESSED} = { };
1121 $newVal = $exifTool->WriteDirectory(\%subdirInfo, $subTablePtr, $writeProc);
1122 if (defined $newVal) {
1123 if ($newVal eq '') {
1124 next MieElement if $newTag eq $tag; # deleting the directory
1125 next; # not creating the new directory
1126 }
1127 } else {
1128 next unless defined $oldVal;
1129 $newVal = $oldVal; # just copy over the old directory
1130 }
1131 $writable = 'undef';
1132 $newFormat = 0x00; # all other directories are 'undef' format
1133 }
1134 } else {
1135
1136 # get the new tag information
1137 $newInfo = $$newTags{$newTag};
1138 my $nvHash = $exifTool->GetNewValueHash($newInfo);
1139 my @newVals;
1140
1141 # write information only to specified group
1142 my $writeGroup = $$nvHash{WriteGroup};
1143 last unless $isWriting{$writeGroup};
1144
1145 # if tag existed, must decide if we want to overwrite the value
1146 if ($newTag eq $tag) {
1147 my $isOverwriting;
1148 my $isList = $$newInfo{List};
1149 if ($isList) {
1150 $isOverwriting = -1; # force processing list elements individually
1151 } else {
1152 $isOverwriting = Image::ExifTool::IsOverwriting($nvHash);
1153 last unless $isOverwriting;
1154 }
1155 my ($val, $cmpVal);
1156 if ($isOverwriting < 0 or $verbose > 1) {
1157 # check to be sure we can uncompress the value if necessary
1158 HasZlib($exifTool, 'edit') or last if $format & 0x04;
1159 # read the old value
1160 $raf->Read($oldVal, $valLen) == $valLen or last MieElement;
1161 # uncompress if necessary
1162 if ($format & 0x04) {
1163 my $stat;
1164 my $inflate = Compress::Zlib::inflateInit();
1165 # must save original compressed value in case we decide
1166 # not to overwrite it later
1167 $cmpVal = $oldVal;
1168 $inflate and ($oldVal, $stat) = $inflate->inflate($oldVal);
1169 unless ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) {
1170 $msg = "Error inflating $tag";
1171 last MieElement;
1172 }
1173 $valLen = length $oldVal; # update value length
1174 }
1175 # convert according to specified format
1176 my $formatStr = $mieFormat{$format & 0xfb} || 'undef';
1177 $val = ReadMIEValue(\$oldVal, 0, $formatStr, undef, $valLen);
1178 if ($isOverwriting < 0 and defined $val) {
1179 # handle list values individually
1180 if ($isList) {
1181 my (@vals, $v);
1182 if ($formatStr =~ /_list$/) {
1183 @vals = split "\0", $val;
1184 } else {
1185 @vals = $val;
1186 }
1187 # keep any list items that we aren't overwriting
1188 foreach $v (@vals) {
1189 next if Image::ExifTool::IsOverwriting($nvHash, $v);
1190 push @newVals, $v;
1191 }
1192 } else {
1193 # test to see if we really want to overwrite the value
1194 $isOverwriting = Image::ExifTool::IsOverwriting($nvHash, $val);
1195 }
1196 }
1197 }
1198 if ($isOverwriting) {
1199 # skip the old value if we didn't read it already
1200 unless (defined $oldVal) {
1201 $raf->Seek($valLen, 1) or $msg = 'Seek error';
1202 }
1203 if ($verbose > 1) {
1204 $val .= "($units)" if defined $units;
1205 $exifTool->VerboseValue("- $grp1:$$newInfo{Name}", $val);
1206 }
1207 $deletedTag = $tag; # remember that we deleted this tag
1208 ++$exifTool->{CHANGED}; # we deleted the old value
1209 } else {
1210 if (defined $oldVal) {
1211 # write original compressed value
1212 $oldVal = $cmpVal if defined $cmpVal;
1213 } else {
1214 $raf->Read($oldVal, $valLen) == $valLen or last MieElement;
1215 }
1216 # write the old value now
1217 Write($outfile, $toWrite, $oldHdr, $oldVal) or $err = 1;
1218 $toWrite = '';
1219 }
1220 unless (@newVals) {
1221 # unshift the new tag info to write it later
1222 unshift @editTags, $newTag;
1223 next MieElement; # get next element from file
1224 }
1225 } else {
1226 # write new value if creating, or if List and list existed, or
1227 # if tag was previously deleted
1228 next unless Image::ExifTool::IsCreating($nvHash) or
1229 ($newTag eq $lastTag and ($$newInfo{List} or $deletedTag eq $lastTag));
1230 }
1231 # get the new value to write (undef to delete)
1232 push @newVals, Image::ExifTool::GetNewValues($nvHash);
1233 next unless @newVals;
1234 $writable = $$newInfo{Writable} || $$tagTablePtr{WRITABLE};
1235 if ($writable eq 'string') {
1236 # join multiple values into a single string
1237 $newVal = join "\0", @newVals;
1238 # write string as UTF-8,16 or 32 if value contains valid UTF-8 codes
1239 require Image::ExifTool::XMP;
1240 my $isUTF8 = Image::ExifTool::XMP::IsUTF8(\$newVal);
1241 if ($isUTF8 > 0) {
1242 $writable = 'utf8';
1243 # write UTF-16 or UTF-32 if it is more compact
1244 my $to = $isUTF8 > 1 ? 'UCS4' : 'UCS2';
1245 my $tmp = Image::ExifTool::Decode(undef,$newVal,'UTF8',undef,$to);
1246 if (length $tmp < length $newVal) {
1247 $newVal = $tmp;
1248 $writable = ($isUTF8 > 1) ? 'utf32' : 'utf16';
1249 }
1250 }
1251 # write as a list if we have multiple values
1252 $writable .= '_list' if @newVals > 1;
1253 } else {
1254 # should only be one element in the list
1255 $newVal = shift @newVals;
1256 }
1257 $newFormat = $mieCode{$writable};
1258 unless (defined $newFormat) {
1259 $msg = "Bad format '$writable' for $$newInfo{Name}";
1260 next MieElement;
1261 }
1262 }
1263
1264 # write the new or edited element
1265 while (defined $newFormat) {
1266 my $valPt = \$newVal;
1267 # remove units from value and add to tag name if supported by this tag
1268 if ($$newInfo{Units}) {
1269 my $val2;
1270 if ($$valPt =~ /(.*)\((.*)\)$/) {
1271 $val2 = $1;
1272 $newTag .= "($2)";
1273 } else {
1274 $val2 = $$valPt;
1275 # add default units
1276 my $ustr = '(' . $newInfo->{Units}->[0] . ')';
1277 $newTag .= $ustr;
1278 $$valPt .= $ustr;
1279 }
1280 $valPt = \$val2;
1281 }
1282 # convert value if necessary
1283 if ($writable !~ /^(utf|string|undef)/) {
1284 my $val3 = WriteValue($$valPt, $writable, $$newInfo{Count});
1285 defined $val3 or $exifTool->Warn("Error writing $newTag"), last;
1286 $valPt = \$val3;
1287 }
1288 my $len = length $$valPt;
1289 # compress value before writing if required
1290 if (($compress or $optCompress) and not $$dirInfo{IsCompressed} and
1291 HasZlib($exifTool, 'write'))
1292 {
1293 my $deflate = Compress::Zlib::deflateInit();
1294 my $val4;
1295 if ($deflate) {
1296 $val4 = $deflate->deflate($$valPt);
1297 $val4 .= $deflate->flush() if defined $val4;
1298 }
1299 if (defined $val4) {
1300 my $len4 = length $val4;
1301 my $saved = $len - $len4;
1302 # only use compressed data if it is smaller
1303 if ($saved > 0) {
1304 $verbose and print $out " [$newTag compression saved $saved bytes]\n";
1305 $newFormat |= 0x04; # set compressed bit
1306 $len = $len4; # set length
1307 $valPt = \$val4; # set value pointer
1308 } elsif ($verbose) {
1309 print $out " [$newTag compression saved $saved bytes -- written uncompressed]\n";
1310 }
1311 } else {
1312 $exifTool->Warn("Error deflating $newTag (written uncompressed)");
1313 }
1314 }
1315 # calculate the DataLength code
1316 my $extLen;
1317 if ($len < 253) {
1318 $extLen = '';
1319 } elsif ($len < 65536) {
1320 $extLen = Set16u($len);
1321 $len = 255;
1322 } elsif ($len <= 0x7fffffff) {
1323 $extLen = Set32u($len);
1324 $len = 254;
1325 } else {
1326 $exifTool->Warn("Can't write $newTag (DataLength > 2GB not yet suppported)");
1327 last; # don't write this tag
1328 }
1329 # write this element (with leading MIE group element if not done already)
1330 my $hdr = $toWrite . '~' . chr($newFormat) . chr(length $newTag);
1331 Write($outfile, $hdr, chr($len), $newTag, $extLen, $$valPt) or $err = 1;
1332 $toWrite = '';
1333 # we changed a tag unless just editing a subdirectory
1334 unless ($$editDirs{$newTag}) {
1335 $exifTool->VerboseValue("+ $grp1:$$newInfo{Name}", $newVal);
1336 ++$exifTool->{CHANGED};
1337 }
1338 last; # didn't want to loop anyway
1339 }
1340 next MieElement if defined $oldVal;
1341 }
1342#
1343# rewrite existing element or descend into uncompressed MIE group
1344#
1345 # all done this MIE group if we reached the terminator element
1346 unless ($tagLen) {
1347 # skip over existing terminator data (if any)
1348 last if $valLen and not $raf->Seek($valLen, 1);
1349 $ok = 1;
1350 # write group terminator if necessary
1351 unless ($toWrite) {
1352 # write end-of-group terminator element
1353 my $term = "~\0\0\0";
1354 unless ($$dirInfo{Parent}) {
1355 # write extended terminator for file-level group
1356 my $len = ref $outfile eq 'SCALAR' ? length($$outfile) : tell $outfile;
1357 $len += 10; # include length of terminator itself
1358 if ($len and $len <= 0x7fffffff) {
1359 $term = "~\0\0\x06" . Set32u($len) . MIEGroupFormat(1) . "\x04";
1360 }
1361 }
1362 Write($outfile, $term) or $err = 1;
1363 }
1364 last;
1365 }
1366
1367 # descend into existing uncompressed MIE group
1368 if ($format == 0x10 or $format == 0x18) {
1369 my ($subTablePtr, $dirName);
1370 my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
1371 if ($tagInfo and $$tagInfo{SubDirectory}) {
1372 $dirName = $tagInfo->{SubDirectory}->{DirName};
1373 my $subTable = $tagInfo->{SubDirectory}->{TagTable};
1374 $subTablePtr = $subTable ? GetTagTable($subTable) : $tagTablePtr;
1375 } else {
1376 $subTablePtr = GetTagTable('Image::ExifTool::MIE::Unknown');
1377 }
1378 my $hdr = '~' . chr($format) . chr(length $tag) . "\0" . $tag;
1379 my %subdirInfo = (
1380 DirName => $dirName || $tag,
1381 RAF => $raf,
1382 ToWrite => $toWrite . $hdr,
1383 OutFile => $outfile,
1384 Parent => $dirName,
1385 IsCompressed => $$dirInfo{IsCompressed},
1386 );
1387 my $oldOrder = GetByteOrder();
1388 SetByteOrder($format & 0x08 ? 'II' : 'MM');
1389 $msg = WriteMIEGroup($exifTool, \%subdirInfo, $subTablePtr);
1390 SetByteOrder($oldOrder);
1391 last if $msg;
1392 if (defined $msg) {
1393 undef $msg; # no problem if nothing written
1394 } else {
1395 $toWrite = '';
1396 }
1397 next;
1398 }
1399 # just copy existing element
1400 my $oldVal;
1401 $raf->Read($oldVal, $valLen) == $valLen or last;
1402 if ($toWrite) {
1403 Write($outfile, $toWrite) or $err = 1;
1404 $toWrite = '';
1405 }
1406 Write($outfile, $oldHdr, $oldVal) or $err = 1;
1407 }
1408 # return error message
1409 if ($err) {
1410 $msg = 'Error writing file';
1411 } elsif (not $ok and not $msg) {
1412 $msg = 'Unexpected end of file';
1413 } elsif (not $msg and $toWrite) {
1414 $msg = ''; # flag for nothing written
1415 $verbose and print $out "Deleted $grp1 (empty)\n";
1416 }
1417 return $msg;
1418}
1419
1420#------------------------------------------------------------------------------
1421# Process MIE directory
1422# Inputs: 0) ExifTool object reference, 1) DirInfo reference, 2) tag table ref
1423# Returns: undef on success, or error message if there was a problem
1424# Notes: file pointer is positioned at the MIE end on entry
1425sub ProcessMIEGroup($$$)
1426{
1427 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1428 my $raf = $$dirInfo{RAF};
1429 my $verbose = $exifTool->Options('Verbose');
1430 my $out = $exifTool->Options('TextOut');
1431 my $notUTF8 = ($exifTool->{OPTIONS}->{Charset} ne 'UTF8');
1432 my ($msg, $buff, $ok, $oldIndent, $mime);
1433 my $lastTag = '';
1434
1435 # get group 1 names: $grp doesn't have numbers (ie. 'MIE-Doc'),
1436 # and $grp1 does (ie. 'MIE1-Doc1')
1437 my $cnt = $exifTool->{MIE_COUNT};
1438 my $grp1 = $tagTablePtr->{GROUPS}->{1};
1439 my $n = $$cnt{'MIE-Main'} || 0;
1440 if ($grp1 eq 'MIE-Main') {
1441 $$cnt{$grp1} = ++$n;
1442 $grp1 =~ s/MIE-/MIE$n-/ if $n > 1;
1443 } else {
1444 $grp1 =~ s/MIE-/MIE$n-/ if $n > 1;
1445 $$cnt{$grp1} = ($$cnt{$grp1} || 0) + 1;
1446 $grp1 .= $$cnt{$grp1} if $$cnt{$grp1} > 1;
1447 }
1448 # set group1 name for all tags extracted from this group
1449 $exifTool->{SET_GROUP1} = $grp1;
1450
1451 if ($verbose) {
1452 $oldIndent = $exifTool->{INDENT};
1453 $exifTool->{INDENT} .= '| ';
1454 $exifTool->VerboseDir($grp1);
1455 }
1456 my $wasCompressed = $$dirInfo{WasCompressed};
1457
1458 # process all MIE elements
1459 for (;;) {
1460 $raf->Read($buff, 4) == 4 or last;
1461 my ($sync, $format, $tagLen, $valLen) = unpack('aC3', $buff);
1462 $sync eq '~' or $msg = 'Invalid sync byte', last;
1463
1464 # read tag name
1465 my ($tag, $units);
1466 if ($tagLen) {
1467 $raf->Read($tag, $tagLen) == $tagLen or last;
1468 $exifTool->Warn("MIE tag '$tag' out of sequence") if $tag lt $lastTag;
1469 $lastTag = $tag;
1470 # separate units from tag name if they exist
1471 $units = $1 if $tag =~ s/\((.*)\)$//;
1472 } else {
1473 $tag = '';
1474 }
1475
1476 # get multi-byte value length if necessary
1477 if ($valLen > 252) {
1478 my $n = 1 << (256 - $valLen);
1479 $raf->Read($buff, $n) == $n or last;
1480 my $fmt = 'int' . ($n * 8) . 'u';
1481 $valLen = ReadValue(\$buff, 0, $fmt, 1, $n);
1482 if ($valLen > 0x7fffffff) {
1483 $msg = "Can't read $tag (DataLength > 2GB not yet supported)";
1484 last;
1485 }
1486 }
1487
1488 # all done if we reached the group terminator
1489 unless ($tagLen) {
1490 # skip over terminator data block
1491 $ok = 1 unless $valLen and not $raf->Seek($valLen, 1);
1492 last;
1493 }
1494
1495 # get tag information hash unless this is free space
1496 my ($tagInfo, $value);
1497 while ($format != 0x80) {
1498 $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
1499 last if $tagInfo;
1500 # extract tags with locale code
1501 if ($tag =~ /\W/) {
1502 if ($tag =~ /^(\w+)-([a-z]{2}_[A-Z]{2})$/) {
1503 my ($baseTag, $langCode) = ($1, $2);
1504 $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $baseTag);
1505 $tagInfo = GetLangInfo($tagInfo, $langCode) if $tagInfo;
1506 last if $tagInfo;
1507 } else {
1508 $exifTool->Warn('Invalid MIE tag name');
1509 last;
1510 }
1511 }
1512 # extract unknown tags if specified
1513 $tagInfo = {
1514 Name => $tag,
1515 Writable => 0,
1516 PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val',
1517 };
1518 Image::ExifTool::AddTagToTable($tagTablePtr, $tag, $tagInfo);
1519 last;
1520 }
1521
1522 # read value and uncompress if necessary
1523 my $formatStr = $mieFormat{$format & 0xfb} || 'undef';
1524 if ($tagInfo or ($formatStr eq 'MIE' and $format & 0x04)) {
1525 $raf->Read($value, $valLen) == $valLen or last;
1526 if ($format & 0x04) {
1527 if ($verbose) {
1528 print $out "$$exifTool{INDENT}\[Tag '$tag' $valLen bytes compressed]\n";
1529 }
1530 next unless HasZlib($exifTool, 'decode');
1531 my $stat;
1532 my $inflate = Compress::Zlib::inflateInit();
1533 $inflate and ($value, $stat) = $inflate->inflate($value);
1534 unless ($inflate and $stat == Compress::Zlib::Z_STREAM_END()) {
1535 $exifTool->Warn("Error inflating $tag");
1536 next;
1537 }
1538 $valLen = length $value;
1539 $wasCompressed = 1;
1540 }
1541 }
1542
1543 # process this tag
1544 if ($formatStr eq 'MIE') {
1545 # process MIE directory
1546 my ($subTablePtr, $dirName);
1547 if ($tagInfo and $$tagInfo{SubDirectory}) {
1548 $dirName = $tagInfo->{SubDirectory}->{DirName};
1549 my $subTable = $tagInfo->{SubDirectory}->{TagTable};
1550 $subTablePtr = $subTable ? GetTagTable($subTable) : $tagTablePtr;
1551 } else {
1552 $subTablePtr = GetTagTable('Image::ExifTool::MIE::Unknown');
1553 }
1554 if ($verbose) {
1555 my $order = ', byte order ' . GetByteOrder();
1556 $exifTool->VerboseInfo($tag, $tagInfo, Size => $valLen, Extra => $order);
1557 }
1558 my %subdirInfo = (
1559 DirName => $dirName || $tag,
1560 RAF => $raf,
1561 Parent => $$dirInfo{DirName},
1562 WasCompressed => $wasCompressed,
1563 );
1564 # read from uncompressed data instead if necessary
1565 $subdirInfo{RAF} = new File::RandomAccess(\$value) if $format & 0x04;
1566
1567 my $oldOrder = GetByteOrder();
1568 SetByteOrder($format & 0x08 ? 'II' : 'MM');
1569 $msg = ProcessMIEGroup($exifTool, \%subdirInfo, $subTablePtr);
1570 SetByteOrder($oldOrder);
1571 $exifTool->{SET_GROUP1} = $grp1; # restore this group1 name
1572 last if $msg;
1573 } else {
1574 # process MIE data format types
1575 if ($tagInfo) {
1576 # extract tag value
1577 my $val = ReadMIEValue(\$value, 0, $formatStr, undef, $valLen);
1578 unless (defined $val) {
1579 $exifTool->Warn("Error reading $tag value");
1580 $val = '<err>';
1581 }
1582 # save type or mime type
1583 $mime = $val if $tag eq '0Type' or $tag eq '2MIME';
1584 if ($verbose) {
1585 my $count;
1586 my $s = Image::ExifTool::FormatSize($formatStr);
1587 if ($s and $formatStr !~ /^(utf|string|undef)/) {
1588 $count = $valLen / $s;
1589 }
1590 $exifTool->VerboseInfo($lastTag, $tagInfo,
1591 DataPt => \$value,
1592 DataPos => $raf->Tell() - $valLen,
1593 Size => $valLen,
1594 Format => $formatStr,
1595 Value => $val,
1596 Count => $count,
1597 );
1598 }
1599 if ($$tagInfo{SubDirectory}) {
1600 my $subTablePtr = GetTagTable($tagInfo->{SubDirectory}->{TagTable});
1601 my %subdirInfo = (
1602 DirName => $$tagInfo{Name},
1603 DataPt => \$value,
1604 DataLen => $valLen,
1605 DirStart=> 0,
1606 DirLen => $valLen,
1607 Parent => $$dirInfo{DirName},
1608 WasCompressed => $wasCompressed,
1609 );
1610 # set DataPos and Base for uncompressed information only
1611 unless ($wasCompressed) {
1612 $subdirInfo{DataPos} = $raf->Tell() - $valLen;
1613 $subdirInfo{Base} = $raf->Tell() - $valLen;
1614 }
1615 # reset PROCESSED lookup for each MIE directory
1616 # (there is no possibility of double-processing a MIE directory)
1617 $exifTool->{PROCESSED} = { };
1618 my $processProc = $tagInfo->{SubDirectory}->{ProcessProc};
1619 delete $exifTool->{SET_GROUP1};
1620 delete $exifTool->{NO_LIST};
1621 $exifTool->ProcessDirectory(\%subdirInfo, $subTablePtr, $processProc);
1622 $exifTool->{SET_GROUP1} = $grp1;
1623 $exifTool->{NO_LIST} = 1;
1624 } else {
1625 # convert to specified character set if necessary
1626 if ($notUTF8 and $formatStr =~ /^(utf|string)/) {
1627 $val = $exifTool->Decode($val, 'UTF8');
1628 }
1629 if ($formatStr =~ /_list$/) {
1630 # split list value into separate strings
1631 my @vals = split "\0", $val;
1632 $val = \@vals;
1633 }
1634 if (defined $units) {
1635 $val = "@$val" if ref $val; # convert string list to number list
1636 # add units to value if specified
1637 $val .= "($units)" if defined $units;
1638 }
1639 $exifTool->FoundTag($tagInfo, $val);
1640 }
1641 } else {
1642 # skip over unknown information or free bytes
1643 $raf->Seek($valLen, 1) or $msg = 'Seek error', last;
1644 $verbose and $exifTool->VerboseInfo($tag, undef, Size => $valLen);
1645 }
1646 }
1647 }
1648 # modify MIME type if necessary
1649 $mime and not $$dirInfo{Parent} and $exifTool->ModifyMimeType($mime);
1650
1651 $ok or $msg or $msg = 'Unexpected end of file';
1652 $verbose and $exifTool->{INDENT} = $oldIndent;
1653 return $msg;
1654}
1655
1656#------------------------------------------------------------------------------
1657# Read/write a MIE file
1658# Inputs: 0) ExifTool object reference, 1) DirInfo reference
1659# Returns: 1 on success, 0 if this wasn't a valid MIE file, or -1 on write error
1660# - process as a trailer if "Trailer" flag set in dirInfo
1661sub ProcessMIE($$)
1662{
1663 my ($exifTool, $dirInfo) = @_;
1664 return 1 unless defined $exifTool;
1665 my $raf = $$dirInfo{RAF};
1666 my $outfile = $$dirInfo{OutFile};
1667 my ($buff, $err, $msg, $pos, $end, $isCreating);
1668 my $numDocs = 0;
1669#
1670# process as a trailer (from end of file) if specified
1671#
1672 if ($$dirInfo{Trailer}) {
1673 my $offset = $$dirInfo{Offset} || 0; # offset from end of file
1674 $raf->Seek(-10 - $offset, 2) or return 0;
1675 for (;;) {
1676 # read and validate last 10 bytes
1677 $raf->Read($buff, 10) == 10 or last;
1678 last unless $buff =~ /~\0\0\x06.{4}(\x10|\x18)(\x04)$/s or
1679 $buff =~ /(\x10|\x18)(\x08)$/s;
1680 SetByteOrder($1 eq "\x10" ? 'MM' : 'II');
1681 my $len = ($2 eq "\x04") ? Get32u(\$buff, 4) : Get64u(\$buff, 0);
1682 my $curPos = $raf->Tell() or last;
1683 last if $len < 12 or $len > $curPos;
1684 # validate element header if 8-byte offset was used
1685 if ($2 eq "\x08") {
1686 last if $len < 14;
1687 $raf->Seek($curPos - 14, 0) and $raf->Read($buff, 4) or last;
1688 last unless $buff eq "~\0\0\x0a";
1689 }
1690 # looks like a good group, so remember start position
1691 $pos = $curPos - $len;
1692 $end = $curPos unless $end;
1693 # seek to 10 bytes from end of previous group
1694 $raf->Seek($pos - 10, 0) or last;
1695 }
1696 # seek to start of first MIE group
1697 return 0 unless defined $pos and $raf->Seek($pos, 0);
1698 # update DataPos and DirLen for ProcessTrailers()
1699 $$dirInfo{DataPos} = $pos;
1700 $$dirInfo{DirLen} = $end - $pos;
1701 if ($outfile and $exifTool->{DEL_GROUP}->{MIE}) {
1702 # delete the trailer
1703 $exifTool->VPrint(0," Deleting MIE trailer\n");
1704 ++$exifTool->{CHANGED};
1705 return 1;
1706 } elsif ($exifTool->Options('Verbose') or $exifTool->{HTML_DUMP}) {
1707 $exifTool->DumpTrailer($dirInfo);
1708 }
1709 }
1710#
1711# loop through all documents in MIE file
1712#
1713 for (;;) {
1714 # look for "0MIE" group element
1715 my $num = $raf->Read($buff, 8);
1716 if ($num == 8) {
1717 # verify file identifier
1718 if ($buff =~ /^~(\x10|\x18)\x04(.)0MIE/) {
1719 SetByteOrder($1 eq "\x10" ? 'MM' : 'II');
1720 my $len = ord($2);
1721 # skip extended DataLength if it exists
1722 if ($len > 252 and not $raf->Seek(1 << (256 - $len), 1)) {
1723 $msg = 'Seek error';
1724 last;
1725 }
1726 } else {
1727 return 0 unless $numDocs; # not a MIE file
1728 if ($buff =~ /^~/) {
1729 $msg = 'Non-standard file-level MIE element';
1730 } else {
1731 $msg = 'Invalid MIE file-level data';
1732 }
1733 }
1734 } elsif ($numDocs) {
1735 last unless $num; # OK, all done with file
1736 $msg = 'Truncated MIE element header';
1737 } else {
1738 return 0 if $num or not $outfile;
1739 # we have the ability to create a MIE file from scratch
1740 $buff = ''; # start from nothing
1741 # set byte order according to preferences
1742 $exifTool->SetPreferredByteOrder();
1743 $isCreating = 1;
1744 }
1745 if ($msg) {
1746 last if $$dirInfo{Trailer}; # allow other trailers after MIE
1747 if ($outfile) {
1748 $exifTool->Error($msg);
1749 } else {
1750 $exifTool->Warn($msg);
1751 }
1752 last;
1753 }
1754 # this is a new MIE document -- increment document count
1755 unless ($numDocs) {
1756 # this is a valid MIE file (unless a trailer on another file)
1757 $exifTool->SetFileType();
1758 $exifTool->{NO_LIST} = 1; # handle lists ourself
1759 $exifTool->{MIE_COUNT} = { };
1760 undef $hasZlib;
1761 }
1762 ++$numDocs;
1763
1764 # process the MIE groups recursively, beginning with the main MIE group
1765 my $tagTablePtr = GetTagTable('Image::ExifTool::MIE::Main');
1766
1767 my %subdirInfo = (
1768 DirName => 'MIE',
1769 RAF => $raf,
1770 OutFile => $outfile,
1771 # don't define Parent so WriteMIEGroup() writes extended terminator
1772 );
1773 if ($outfile) {
1774 # generate lookup for MIE format codes if not done already
1775 unless (%mieCode) {
1776 foreach (keys %mieFormat) {
1777 $mieCode{$mieFormat{$_}} = $_;
1778 }
1779 }
1780 # update %mieMap with user-defined MIE groups
1781 UpdateMieMap() unless $doneMieMap;
1782 # initialize write directories, with MIE tags taking priority
1783 # (note that this may re-initialize directories when writing trailer
1784 # to another type of image, but this is OK because we are done writing
1785 # the other format by the time we start writing the trailer)
1786 $exifTool->InitWriteDirs(\%mieMap, 'MIE');
1787 $subdirInfo{ToWrite} = '~' . MIEGroupFormat(1) . "\x04\xfe0MIE\0\0\0\0";
1788 $msg = WriteMIEGroup($exifTool, \%subdirInfo, $tagTablePtr);
1789 if ($msg) {
1790 $exifTool->Error($msg);
1791 $err = 1;
1792 last;
1793 } elsif (defined $msg and $isCreating) {
1794 last;
1795 }
1796 } else {
1797 $msg = ProcessMIEGroup($exifTool, \%subdirInfo, $tagTablePtr);
1798 if ($msg) {
1799 $exifTool->Warn($msg);
1800 last;
1801 }
1802 }
1803 }
1804 delete $exifTool->{NO_LIST};
1805 delete $exifTool->{MIE_COUNT};
1806 delete $exifTool->{SET_GROUP1};
1807 return $err ? -1 : 1;
1808}
1809
18101; # end
1811
1812__END__
1813
1814=head1 NAME
1815
1816Image::ExifTool::MIE - Read/write MIE meta information
1817
1818=head1 SYNOPSIS
1819
1820This module is used by Image::ExifTool
1821
1822=head1 DESCRIPTION
1823
1824This module contains routines required by Image::ExifTool to read and write
1825information in MIE files.
1826
1827=head1 WHAT IS MIE?
1828
1829MIE stands for "Meta Information Encapsulation". The MIE format is an
1830extensible, dedicated meta information format which supports storage of
1831binary as well as textual meta information. MIE can be used to encapsulate
1832meta information from many sources and bundle it together with any type of
1833file.
1834
1835=head2 Features
1836
1837Below is very subjective score card comparing the features of a number of
1838common file and meta information formats, and comparing them to MIE. The
1839following features are rated for each format with a score of 0 to 10:
1840
1841 1) Extensible (can incorporate user-defined information).
1842 2) Meaningful tag ID's (hint to meaning of unknown information).
1843 3) Sequential read/write ability (streamable).
1844 4) Hierarchical information structure.
1845 5) Easy to implement reader/writer/editor.
1846 6) Order of information well defined.
1847 7) Large data lengths supported: >64kB (+5) and >4GB (+5).
1848 8) Localized text strings.
1849 9) Multiple documents in a single file.
1850 10) Compact format doesn't squander disk space or bandwidth.
1851 11) Compressed meta information supported.
1852 12) Relocatable data elements (ie. no fixed offsets).
1853 13) Binary meta information (+7) with variable byte order (+3).
1854 14) Mandatory tags not required (an unecessary complication).
1855 15) Append information to end of file without editing.
1856
1857 Feature number Total
1858 Format 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Score
1859 ------ --------------------------------------------- -----
1860 MIE 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 150
1861 PDF 10 10 0 10 0 0 10 0 10 10 10 0 7 10 10 97
1862 PNG 10 10 10 0 8 0 5 10 0 10 10 10 0 10 0 93
1863 XMP 10 10 10 10 2 0 10 10 10 0 0 10 0 10 0 92
1864 AIFF 0 5 10 10 10 0 5 0 0 10 0 10 7 10 0 77
1865 RIFF 0 5 10 10 10 0 5 0 0 10 0 10 7 10 0 77
1866 JPEG 10 0 10 0 10 0 0 0 0 10 0 10 7 10 0 67
1867 EPS 10 10 10 0 0 0 10 0 10 0 0 5 0 10 0 65
1868 CIFF 0 0 0 10 10 0 5 0 0 10 0 10 10 10 0 65
1869 TIFF 0 0 0 10 5 10 5 0 10 10 0 0 10 0 0 60
1870 EXIF 0 0 0 10 5 10 0 0 0 10 0 0 10 0 0 45
1871 IPTC 0 0 10 0 8 0 0 0 0 10 0 10 7 0 0 45
1872
1873By design, MIE ranks highest by a significant margin. Other formats with
1874reasonable scores are PDF, PNG and XMP, but each has significant weak
1875points. What may be surprising is that TIFF, EXIF and IPTC rank so low.
1876
1877As well as scoring high in all these features, the MIE format has the unique
1878ability to encapsulate any other type of file, and provides a non-invasive
1879method of adding meta information to a file. The meta information is
1880logically separated from the original file data, which is extremely
1881important because meta information is routinely lost when files are edited.
1882
1883Also, the MIE format supports multiple files by simple concatenation,
1884enabling all kinds of wonderful features such as linear databases, edit
1885histories or non-intrusive file updates. This ability can also be leveraged
1886to allow MIE-format trailers to be added to some other file types.
1887
1888=head1 MIE 1.1 FORMAT SPECIFICATION (2007-01-21)
1889
1890=head2 File Structure
1891
1892A MIE file consists of a series of MIE elements. A MIE element may contain
1893either data or a group of MIE elements, providing a hierarchical format for
1894storing data. Each MIE element is identified by a human-readable tag name,
1895and may store data from zero to 2^64-1 bytes in length.
1896
1897=head2 File Signature
1898
1899The first element in the MIE file must be an uncompressed MIE group element
1900with a tag name of "0MIE". This restriction allows the first 8 bytes of a
1901MIE file to be used to identify a MIE format file. The following table
1902lists the two possible initial byte sequences for a MIE-format file (the
1903first for big-endian, and the second for little-endian byte ordering):
1904
1905 Byte Number: 0 1 2 3 4 5 6 7
1906
1907 C Characters: ~ \x10 \x04 ? 0 M I E
1908 or ~ \x18 \x04 ? 0 M I E
1909
1910 Hexadecimal: 7e 10 04 ? 30 4d 49 45
1911 or 7e 18 04 ? 30 4d 49 45
1912
1913 Decimal: 126 16 4 ? 48 77 73 69
1914 or 126 24 4 ? 48 77 73 69
1915
1916Note that byte 1 may have one of the two possible values (0x10 or 0x18), and
1917byte 3 may have any value (0x00 to 0xff).
1918
1919=head2 Element Structure
1920
1921 1 byte SyncByte = 0x7e (decimal 126, character '~')
1922 1 byte FormatCode (see below)
1923 1 byte TagLength (T)
1924 1 byte DataLength (gives D if DataLength < 253)
1925 T bytes TagName (T given by TagLength)
1926 2 bytes DataLength2 [exists only if DataLength == 255 (0xff)]
1927 4 bytes DataLength4 [exists only if DataLength == 254 (0xfe)]
1928 8 bytes DataLength8 [exists only if DataLength == 253 (0xfd)]
1929 D bytes DataBlock (D given by DataLength)
1930
1931The minimum element length is 4 bytes (for a group terminator). The maximum
1932DataBlock size is 2^64-1 bytes. TagLength and DataLength are unsigned
1933integers, and the byte ordering for multi-byte DataLength fields is
1934specified by the containing MIE group element. The SyncByte is byte
1935aligned, so no padding is added to align on an N-byte boundary.
1936
1937=head3 FormatCode
1938
1939The format code is a bitmask that defines the format of the data:
1940
1941 7654 3210
1942 ++++ ---- FormatType
1943 ---- +--- TypeModifier
1944 ---- -+-- Compressed
1945 ---- --++ FormatSize
1946
1947=over 4
1948
1949=item FormatType (bitmask 0xf0):
1950
1951 0x00 - other (or unknown) data
1952 0x10 - MIE group
1953 0x20 - text string
1954 0x30 - list of null-separated text strings
1955 0x40 - integer
1956 0x50 - rational
1957 0x60 - fixed point
1958 0x70 - floating point
1959 0x80 - free space
1960
1961=item TypeModifier (bitmask 0x08):
1962
1963Modifies the meaning of certain FormatTypes (0x00-0x60):
1964
1965 0x08 - other data sensitive to MIE group byte order
1966 0x18 - MIE group with little-endian byte ordering
1967 0x28 - UTF encoded text string
1968 0x38 - UTF encoded text string list
1969 0x48 - signed integer
1970 0x58 - signed rational (denominator is always unsigned)
1971 0x68 - signed fixed-point
1972
1973=item Compressed (bitmask 0x04):
1974
1975If this bit is set, the data block is compressed using Zlib deflate. An
1976entire MIE group may be compressed, with the exception of file-level groups.
1977
1978=item FormatSize (bitmask 0x03):
1979
1980Gives the byte size of each data element:
1981
1982 0x00 - 8 bits (1 byte)
1983 0x01 - 16 bits (2 bytes)
1984 0x02 - 32 bits (4 bytes)
1985 0x03 - 64 bits (8 bytes)
1986
1987The number of bytes in a single value for this format is given by
19882**FormatSize (or 1 << FormatSize). The number of values is the data length
1989divided by this number of bytes. It is an error if the data length is not
1990an even multiple of the format size in bytes.
1991
1992=back
1993
1994The following is a list of all currently defined MIE FormatCode values for
1995uncompressed data (add 0x04 to each value for compressed data):
1996
1997 0x00 - other data (insensitive to MIE group byte order) (1)
1998 0x01 - other 16-bit data (may be byte swapped)
1999 0x02 - other 32-bit data (may be byte swapped)
2000 0x03 - other 64-bit data (may be byte swapped)
2001 0x08 - other data (sensitive to MIE group byte order) (1)
2002 0x10 - MIE group with big-endian values (1)
2003 0x18 - MIE group with little-endian values (1)
2004 0x20 - ASCII (ISO 8859-1) string (2,3)
2005 0x28 - UTF-8 string (2,3,4)
2006 0x29 - UTF-16 string (2,3,4)
2007 0x2a - UTF-32 string (2,3,4)
2008 0x30 - ASCII (ISO 8859-1) string list (3,5)
2009 0x38 - UTF-8 string list (3,4,5)
2010 0x39 - UTF-16 string list (3,4,5)
2011 0x3a - UTF-32 string list (3,4,5)
2012 0x40 - unsigned 8-bit integer
2013 0x41 - unsigned 16-bit integer
2014 0x42 - unsigned 32-bit integer
2015 0x43 - unsigned 64-bit integer (6)
2016 0x48 - signed 8-bit integer
2017 0x49 - signed 16-bit integer
2018 0x4a - signed 32-bit integer
2019 0x4b - signed 64-bit integer (6)
2020 0x52 - unsigned 32-bit rational (16-bit numerator then denominator) (7)
2021 0x53 - unsigned 64-bit rational (32-bit numerator then denominator) (7)
2022 0x5a - signed 32-bit rational (denominator is unsigned) (7)
2023 0x5b - signed 64-bit rational (denominator is unsigned) (7)
2024 0x61 - unsigned 16-bit fixed-point (high 8 bits is integer part) (8)
2025 0x62 - unsigned 32-bit fixed-point (high 16 bits is integer part) (8)
2026 0x69 - signed 16-bit fixed-point (high 8 bits is signed integer) (8)
2027 0x6a - signed 32-bit fixed-point (high 16 bits is signed integer) (8)
2028 0x72 - 32-bit IEEE float (not recommended for portability reasons)
2029 0x73 - 64-bit IEEE double (not recommended for portability reasons) (6)
2030 0x80 - free space (value data does not contain useful information)
2031
2032Notes:
2033
2034=over 4
2035
2036=item 1.
2037
2038The byte ordering specified by the MIE group TypeModifier applies to the MIE
2039group element as well as all elements within the group. Data for all
2040FormatCodes except 0x08 (other data, sensitive to byte order) may be
2041transferred between MIE groups with different byte order by byte swapping
2042the uncompressed data according to the specified data format. The following
2043list illustrates the byte-swapping pattern, based on FormatSize, for all
2044format types except rational (FormatType 0x50).
2045
2046 FormatSize Change in Byte Sequence
2047 -------------- -----------------------------------
2048 0x00 (8 bits) 0 1 2 3 4 5 6 7 --> 0 1 2 3 4 5 6 7 (no change)
2049 0x01 (16 bits) 0 1 2 3 4 5 6 7 --> 1 0 3 2 5 4 7 6
2050 0x02 (32 bits) 0 1 2 3 4 5 6 7 --> 3 2 1 0 7 6 5 4
2051 0x03 (64 bits) 0 1 2 3 4 5 6 7 --> 7 6 5 4 3 2 1 0
2052
2053Rational values consist of two integers, so they are swapped as the next
2054lower FormatSize. For example, a 32-bit rational (FormatSize 0x02, and
2055FormatCode 0x52 or 0x5a) is swapped as two 16-bit values (ie. as if it had
2056FormatSize 0x01).
2057
2058=item 2.
2059
2060The TagName of a string element may have an 6-character suffix to indicate a
2061specific locale. (ie. "Title-en_US", or "Keywords-de_DE").
2062
2063=item 3.
2064
2065Text strings are not normally null terminated, however they may be padded
2066with one or more null characters to the end of the data block to allow
2067strings to be edited within fixed-length data blocks. Newlines in the text
2068are indicated by a single LF (0x0a) character.
2069
2070=item 4.
2071
2072UTF strings must not begin with a byte order mark (BOM) since the byte order
2073and byte size are specified by the MIE format. If a BOM is found, it should
2074be treated as a zero-width non-breaking space.
2075
2076=item 5.
2077
2078A list of text strings separated by null characters. These lists must not
2079be null padded or null terminated, since this would be interpreted as
2080additional zero-length strings. For ASCII and UTF-8 strings, the null
2081character is a single zero (0x00) byte. For UTF-16 or UTF-32 strings, the
2082null character is 2 or 4 zero bytes respectively.
2083
2084=item 6.
2085
208664-bit integers and doubles are subject to the specified byte ordering for
2087both 32-bit words and bytes within these words. For instance, the high
2088order byte is always the first byte if big-endian, and the eighth byte if
2089little-endian. This means that some swapping is always necessary for these
2090values on systems where the byte order differs from the word order (ie. some
2091ARM systems), regardless of the endian-ness of the stored values.
2092
2093=item 7.
2094
2095Rational values are treated as two separate integers. The numerator always
2096comes first regardless of the byte ordering. In a signed rational value,
2097only the numerator is signed. The denominator of all rational values is
2098unsigned (ie. a signed 64-bit rational of 0x80000000/0x80000000 evaluates to
2099-1, not +1).
2100
2101=item 8.
2102
210332-bit fixed point values are converted to floating point by treating them
2104as an integer and dividing by an appropriate value. ie)
2105
2106 16-bit fixed value = 16-bit integer value / 256.0
2107 32-bit fixed value = 32-bit integer value / 65536.0
2108
2109=back
2110
2111=head3 TagLength
2112
2113Gives the length of the TagName string. Any value between 0 and 255 is
2114valid, but the TagLength of 0 is valid only for the MIE group terminator.
2115
2116=head3 DataLength
2117
2118DataLength is an unsigned byte that gives the number of bytes in the data
2119block. A value between 0 and 252 gives the data length directly, and
2120numbers from 253 to 255 are reserved for extended DataLength codes. Codes
2121of 255, 254 and 253 indicate that the element contains an additional 2, 4 or
21228 byte unsigned integer representing the data length.
2123
2124 0-252 - length of data block
2125 255 (0xff) - use DataLength2
2126 254 (0xfe) - use DataLength4
2127 253 (0xfd) - use DataLength8
2128
2129A DataLength of zero is valid for any element except a compressed MIE group.
2130A zero DataLength for an uncompressed MIE group indicates that the group
2131length is unknown. For other elements, a zero length indicates there is no
2132associated data. A terminator element must have a DataLength of 0, 6 or 10,
2133and may not use an extended DataLength.
2134
2135=head3 TagName
2136
2137The TagName string is 0 to 255 bytes long, and is composed of the ASCII
2138characters A-Z, a-z, 0-9 and underline ('_'). Also, a dash ('-') is used to
2139separate the language/country code in the TagName of a localized text
2140string, and a units string (possibly containing other ASCII characters) may
2141be appear in brackets at the end of the TagName. The TagName string is NOT
2142null terminated. A MIE element with a tag string of zero length is reserved
2143for the group terminator.
2144
2145MIE elements are sorted alphabetically by TagName within each group.
2146Multiple elements with the same TagName are allowed, even within the same
2147group.
2148
2149TagNames should be meaningful. Case is significant. Words should be
2150lowercase with an uppercase first character, and acronyms should be all
2151upper case. The underline ("_") is provided to allow separation of two
2152acronyms or two numbers, but it shouldn't be used unless necessary. No
2153separation is necessary between an acronym and a word (ie. "ISOSetting").
2154
2155All TagNames should start with an uppercase letter. An exception to this
2156rule allows tags to begin with a digit (0-9) if they must come before other
2157tags in the sort order, or a lowercase letter (a-z) if they must come after.
2158For instance, the '0Type' element begins with a digit so it comes before,
2159and the 'data' element begins with a lowercase letter so that it comes after
2160meta information tags in the main "0MIE" group.
2161
2162Tag names for localized text strings have an 6-character suffix with the
2163following format: The first character is a dash ('-'), followed by a
21642-character lower case ISO 639-1 language code, then an underline ('_'), and
2165ending with a 2-character upper case ISO 3166-1 alpha 2 country code. (ie.
2166"-en_US", "-en_GB", "-de_DE" or "-fr_FR". Note that "GB", and not "UK" is
2167the code for Great Britain, although "UK" should be recognized for
2168compatibility reasons.) The suffix is included when sorting the tags
2169alphabetically, so the default locale (with no tag-name suffix) always comes
2170first. If the country is unknown or not applicable, a country code of "XX"
2171should be used.
2172
2173Tags with numerical values may allow units of measurement to be specified.
2174The units string is stored in brackets at the end of the tag name, and is
2175composed of zero or more ASCII characters in the range 0x21 to 0x7d,
2176excluding the bracket characters 0x28 and 0x29. (ie. "Resolution(/cm)" or
2177"SpecificHeat(J/kg.K)".) See L<Image::ExifTool::MIEUnits> for details. Unit
2178strings are not localized, and may not be used in combination with localized
2179text strings.
2180
2181Sets of tags which would require a common prefix should be added in a
2182separate MIE group instead of adding the prefix to all tag names. For
2183example, instead of these TagName's:
2184
2185 ExternalFlashType
2186 ExternalFlashSerialNumber
2187 ExternalFlashFired
2188
2189one would instead designate a separate "ExternalFlash" MIE group to contain
2190the following elements:
2191
2192 Type
2193 SerialNumber
2194 Fired
2195
2196=head3 DataLength2/4/8
2197
2198These extended DataLength fields exist only if DataLength is 255, 254 or
2199253, and are respectively 2, 4 or 8 byte unsigned integers giving the data
2200block length. One of these values must be used if the data block is larger
2201than 252 bytes, but they may be used if desired for smaller blocks too
2202(although this may add a few unnecessary bytes to the MIE element).
2203
2204=head3 DataBlock
2205
2206The data value for the MIE element. The format of the data is given by the
2207FormatCode. For MIE group elements, the data includes all contained
2208elements and the group terminator.
2209
2210=head2 MIE groups
2211
2212All MIE data elements must be contained within a group. A group begins with
2213a MIE group element, and ends with a group terminator. Groups may be nested
2214in a hierarchy to arbitrary depth.
2215
2216A MIE group element is identified by a format code of 0x10 (big endian byte
2217ordering) or 0x18 (little endian). The group terminator is distinguished by
2218a zero TagLength (it is the only element allowed to have a zero TagLength),
2219and has a FormatCode of 0x00.
2220
2221The MIE group element is permitted to have a zero DataLength only if the
2222data is uncompressed. This special value indicates that the group length is
2223unknown (otherwise the minimum value for DataLength is 4, corresponding the
2224the minimum group size which includes a terminator of at least 4 bytes). If
2225DataLength is zero, all elements in the group must be parsed until the group
2226terminator is found. If non-zero, DataLength includes the length of all
2227elements contained within the group, including the group terminator. Use of
2228a non-zero DataLength is encouraged because it allows readers quickly skip
2229over entire MIE groups. For compressed groups DataLength must be non-zero,
2230and is the length of the compressed group data (which includes the
2231compressed group terminator).
2232
2233=head3 Group Terminator
2234
2235The group terminator has a FormatCode and TagLength of zero. The terminator
2236DataLength must be 0, 6 or 10 bytes, and extended DataLength codes may not
2237be used. With a zero DataLength, the byte sequence for a terminator is "7e
223800 00 00" (hex). With a DataLength of 6 or 10 bytes, the terminator data
2239block contains information about the length and byte ordering of the
2240preceding group. This additional information is recommended for file-level
2241groups, and is used in multi-document MIE files and MIE trailers to allow
2242the file to be scanned backwards from the end. (This may also allow some
2243documents to be recovered if part of the file is corrupted.) The structure
2244of this optional terminator data block is as follows:
2245
2246 4 or 8 bytes GroupLength (unsigned integer)
2247 1 byte ByteOrder (0x10 or 0x18, same as MIE group)
2248 1 byte GroupLengthSize (0x04 or 0x08)
2249
2250The ByteOrder and GroupLengthSize values give the byte ordering and size of
2251the GroupLength integer. The GroupLength value is the total length of the
2252entire MIE group ending with this terminator, including the opening MIE
2253group element and the terminator itself.
2254
2255=head3 File-level MIE groups
2256
2257File-level MIE groups may NOT be compressed.
2258
2259All elements in a MIE file are contained within a special group with a
2260TagName of "0MIE". The purpose of the "OMIE" group is to provide a unique
2261signature at the start of the file, and to encapsulate information allowing
2262files to be easily combined. The "0MIE" group must be terminated like any
2263other group, but it is recommended that the terminator of a file-level group
2264include the optional data block (defined above) to provide information about
2265the group length and byte order.
2266
2267It is valid to have more than one "0MIE" group at the file level, allowing
2268multiple documents in a single MIE file. Furthermore, the MIE structure
2269enables multi-document files to be generated by simply concatenating two or
2270more MIE files.
2271
2272=head2 Scanning Backwards through a MIE File
2273
2274The steps below give an algorithm to quickly locate the last document in a
2275MIE file:
2276
2277=over 4
2278
2279=item 1.
2280
2281Read the last 10 bytes of the file. (Note that a valid MIE file may be as
2282short as 12 bytes long, but a file this length contains only an an empty MIE
2283group.)
2284
2285=item 2.
2286
2287If the last byte of the file is zero, then it is not possible to scan
2288backward through the file, so the file must be scanned from the beginning.
2289Otherwise, proceed to the next step.
2290
2291=item 3.
2292
2293If the last byte is 4 or 8, the terminator contains information about the
2294byte ordering and length of the group. Otherwise, stop here because this
2295isn't a valid MIE file.
2296
2297=item 4.
2298
2299The next-to-last byte must be either 0x10 indicating big-endian byte
2300ordering or 0x18 for little-endian ordering, otherwise this isn't a valid
2301MIE file.
2302
2303=item 5.
2304
2305The value of the preceding 4 or 8 bytes gives the length of the complete
2306file-level MIE group (GroupLength). This length includes both the leading
2307MIE group element and the terminator element itself. The value is an
2308unsigned integer with a byte length given in step 3), and a byte order from
2309step 4). From the current file position (at the end of the data read in
2310step 1), seek backward by this number of bytes to find the start of the MIE
2311group element for this document.
2312
2313=back
2314
2315This algorithm may be repeated again beginning at this point in the file to
2316locate the next-to-last document, etc.
2317
2318The table below lists all 5 valid patterns for the last 14 bytes of a
2319file-level MIE group, with all numbers in hex. The comments indicate the
2320length and byte ordering of GroupLength (xx) if available:
2321
2322 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 7e 00 00 00 - (no GroupLength)
2323 ?? ?? ?? ?? 7e 00 00 06 xx xx xx xx 10 04 - 4 bytes, big endian
2324 ?? ?? ?? ?? 7e 00 00 06 xx xx xx xx 18 04 - 4 bytes, little endian
2325 7e 00 00 0a xx xx xx xx xx xx xx xx 10 08 - 8 bytes, big endian
2326 7e 00 00 0a xx xx xx xx xx xx xx xx 18 08 - 8 bytes, little endian
2327
2328=head2 Trailer Signature
2329
2330The MIE format may be used for trailer information appended to other types
2331of files. When this is done, a signature must appear at the end of the main
2332MIE group to uniquely identify the MIE format trailer. To achieve this, a
2333"zmie" trailer signature is written as the last element in the main "0MIE"
2334group. This element has a FormatCode of 0, a TagLength of 4, a DataLength
2335of 0, and a TagName of "zmie". With this signature, the hex byte sequence
2336"7e 00 04 00 7a 6d 69 65" appears immediately before the final group
2337terminator, and the last 22 bytes of the trailer correspond to one of the
2338following 4 patterns (where the trailer length is given by "xx", as above):
2339
2340 ?? ?? ?? ?? 7e 00 04 00 7a 6d 69 65 7e 00 00 06 xx xx xx xx 10 04
2341 ?? ?? ?? ?? 7e 00 04 00 7a 6d 69 65 7e 00 00 06 xx xx xx xx 18 04
2342 7e 00 04 00 7a 6d 69 65 7e 00 00 0a xx xx xx xx xx xx xx xx 10 08
2343 7e 00 04 00 7a 6d 69 65 7e 00 00 0a xx xx xx xx xx xx xx xx 18 08
2344
2345Note that the zero-DataLength terminator may not be used here because the
2346trailer length must be known for seeking backwards from the end of the file.
2347
2348Multiple trailers may be appended to the same file using this technique.
2349
2350=head2 MIE Data Values
2351
2352MIE data values for a given tag are usually not restricted to a specific
2353FormatCode. Any value may be represented in any appropriate format,
2354including numbers represented in string (ASCII or UTF) form.
2355
2356It is preferred that closely related values with the same format are written
2357to a single tag instead of using multiple tags. This improves localization
2358of like values and decreases MIE element overhead. For instance, instead of
2359separate ImageWidth and ImageHeight tags, a single ImageSize tag is defined.
2360
2361Tags which may take on a discrete set of values should have meaningful
2362values if possible. This improves the extensibility of the format and
2363allows a more reasonable interpretation of unrecognized values.
2364
2365=head3 Numerical Representation
2366
2367Integer and floating point numbers may be represented in binary or string
2368form. In string form, integers are a series of digits with an optional
2369leading sign (ie. "[+|-]DDDDDD"), and multiple values are separated by a
2370single space character (ie. "23 128 -32"). Floating point numbers are
2371similar but may also contain a decimal point and/or a signed exponent with a
2372leading 'e' character (ie. "[+|-]DD[.DDDDDD][e(+|-)EEE]"). The string "inf"
2373is used to represent infinity. One advantage of numerical strings is that
2374they can have an arbitrarily high precision because the possible number of
2375significant digits is virtually unlimited.
2376
2377Note that numerical values may have associated units of measurement which
2378are specified in the L</TagName> string.
2379
2380=head3 Date/Time Format
2381
2382All MIE dates are strings in the form "YYYY:mm:dd HH:MM:SS.ss+HH:MM". The
2383fractional seconds (".ss") are optional, and if included may contain any
2384number of significant digits (unlike all other fields which are a fixed
2385number of digits and must be padded with leading zeros if necessary). The
2386timezone ("+HH:MM" or "-HH:MM") is recommended but not required. If not
2387given, the local system timezone is assumed.
2388
2389=head2 MIME Type
2390
2391The basic MIME type for a MIE file is "application/x-mie", however the
2392specific MIME type depends on the type of subfile, and is obtained by adding
2393"x-mie-" to the MIME type of the subfile. For example, with a subfile of
2394type "image/jpeg", the MIE file MIME type is "image/x-mie-jpeg". But note
2395that the "x-" is not duplicated if the subfile MIME type already starts with
2396"x-". So a subfile with MIME type "image/x-raw" is contained within a MIE
2397file of type "image/x-mie-raw", not "image/x-mie-x-raw". In the case of
2398multiple documents in a MIE file, the MIME type is taken from the first
2399document. Regardless of the subfile type, all MIE-format files should have
2400a filename extension of ".MIE".
2401
2402=head2 Levels of Support
2403
2404Basic MIE reader/writer applications may choose not to provide support for
2405some advanced features of the MIE format. Features which may not be
2406supported by all software are:
2407
2408=over 4
2409
2410=item Compression
2411
2412Software not supporting compression must ignore compressed elements and
2413groups, but should be able to process the remaining information.
2414
2415=item Large data lengths
2416
2417Some software may limit the maximum size of a MIE group or element.
2418Historically, a limit of 2GB may be imposed by some systems. However,
24198-byte data lengths should be supported by all applications provided the
2420value doesn't exceed the system limit. (ie. For systems with a 2GB limit,
24218-byte data lengths should be supported if the upper 17 bits are all zero.)
2422If a data length above the system limit is encountered, it may be necessary
2423for the application to stop processing if it can not seek to the next
2424element in the file.
2425
2426=back
2427
2428=head1 EXAMPLES
2429
2430This section gives examples for working with MIE information using ExifTool.
2431
2432=head2 Encapsulating Information with Data in a MIE File
2433
2434The following command encapsulates any file recognized by ExifTool inside a
2435MIE file, and initializes MIE tags from information within the file:
2436
2437 exiftool -o new.mie -tagsfromfile FILE '-mie:all<all' \
2438 '-subfilename<filename' '-subfiletype<filetype' \
2439 '-subfilemimetype<mimetype' '-subfiledata<=FILE'
2440
2441where C<FILE> is the name of the file.
2442
2443For unrecognized files, this command may be used:
2444
2445 exiftool -o new.mie -subfilename=FILE -subfiletype=TYPE \
2446 -subfilemimetype=MIME '-subfiledata<=FILE'
2447
2448where C<TYPE> and C<MIME> represent the source file type and MIME type
2449respectively.
2450
2451=head2 Adding a MIE Trailer to a File
2452
2453The MIE format may also be used to store information in a trailer appended
2454to another type of file. Beware that trailers may not be compatible with
2455all file formats, but JPEG and TIFF are two formats where additional trailer
2456information doesn't create any problems for normal parsing of the file.
2457Also note that this technique has the disadvantage that trailer information
2458is commonly lost if the file is subsequently edited by other software.
2459
2460Creating a MIE trailer with ExifTool is a two-step process since ExifTool
2461can't currently be used to add a MIE trailer directly. The example below
2462illustrates the steps for adding a MIE trailer with a small preview image
2463(C<small.jpg>) to a destination JPEG image (C<dst.jpg>).
2464
2465Step 1) Create a MIE file with a TrailerSignature containing the desired
2466information:
2467
2468 exiftool -o new.mie -trailersignature=1 -tagsfromfile small.jpg \
2469 '-previewimagetype<filetype' '-previewimagesize<imagesize' \
2470 '-previewimagename<filename' '-previewimage<=small.jpg'
2471
2472Step 2) Append the MIE information to another file. In Unix, this can be
2473done with the 'cat' command:
2474
2475 cat new.mie >> dst.jpg
2476
2477Once added, ExifTool may be used to edit or delete a MIE trailer in a JPEG
2478or TIFF image.
2479
2480=head2 Multiple MIE Documents in a Single File
2481
2482The MIE specification allows multiple MIE documents (or trailers) to exist
2483in a single file. A file like this may be created by simply concatenating
2484MIE documents. ExifTool may be used to access information in a specific
2485document by adding a copy number to the MIE group name. For example:
2486
2487 # write the Author tag in the second MIE document
2488 exiftool -mie2:author=phil test.mie
2489
2490 # delete the first MIE document from a file
2491 exiftool -mie1:all= test.mie
2492
2493=head2 Units of Measurement
2494
2495Some MIE tags allow values to be specified in different units of
2496measurement. In the MIE file format these units are combined with the tag
2497name, but when using ExifTool they are specified in brackets after the
2498value:
2499
2500 exiftool -mie:gpsaltitude='7500(ft)' test.mie
2501
2502If no units are provided, the default units are written.
2503
2504=head2 Localized Text
2505
2506Localized text values are accessed by adding a language/country code to the
2507tag name. For example:
2508
2509 exiftool -comment-en_us='this is a comment' test.mie
2510
2511=head1 REVISIONS
2512
2513 2010-04-05 - Fixed ÒFormat SizeÓ Note 7 to give the correct number of bits
2514 in the example rational value
2515 2007-01-21 - Specified LF character (0x0a) for text newline sequence
2516 2007-01-19 - Specified ISO 8859-1 character set for extended ASCII codes
2517 2007-01-01 - Improved wording of Step 5 for scanning backwards in MIE file
2518 2006-12-30 - Added EXAMPLES section and note about UTF BOM
2519 2006-12-20 - MIE 1.1: Changed meaning of TypeModifier bit (0x08) for
2520 unknown data (FormatType 0x00), and documented byte swapping
2521 2006-12-14 - MIE 1.0: Added Data Values and Numerical Representations
2522 sections, and added ability to specify units in tag names
2523 2006-11-09 - Added Levels of Support section
2524 2006-11-03 - Added Trailer Signature
2525 2005-11-18 - Original specification created
2526
2527=head1 AUTHOR
2528
2529Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
2530
2531This library is free software; you can redistribute it and/or modify it
2532under the same terms as Perl itself. The MIE format itself is also
2533copyright Phil Harvey, and is covered by the same free-use license.
2534
2535=head1 REFERENCES
2536
2537=over 4
2538
2539=item L<http://owl.phy.queensu.ca/~phil/exiftool/MIE1.1-20070121.pdf>
2540
2541=back
2542
2543=head1 SEE ALSO
2544
2545L<Image::ExifTool::TagNames/MIE Tags>, L<Image::ExifTool::MIEUnits>,
2546L<Image::ExifTool(3pm)|Image::ExifTool>
2547
2548=cut
2549
Note: See TracBrowser for help on using the repository browser.