source: gsdl/trunk/perllib/cpan/Image/ExifTool/MIE.pm@ 16842

Last change on this file since 16842 was 16842, checked in by davidb, 16 years ago

ExifTool added to cpan area to support metadata extraction from files such as JPEG. Primarily targetted as Image files (hence the Image folder name decided upon by the ExifTool author) it also can handle video such as flash and audio such as Wav

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