1#------------------------------------------------------------------------------ 2# File: Microsoft.pm 3# 4# Description: Definitions for custom Microsoft tags 5# 6# Revisions: 2010/10/01 - P. Harvey Created 7# 2011/10/05 - PH Added ProcessXtra() 8# 2021/02/23 - PH Added abiltity to write Xtra tags 9# 10# References: 1) http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm 11#------------------------------------------------------------------------------ 12 13package Image::ExifTool::Microsoft; 14 15use strict; 16use vars qw($VERSION); 17use Image::ExifTool qw(:DataAccess :Utils); 18use Image::ExifTool::XMP; 19 20$VERSION = '1.23'; 21 22sub ProcessXtra($$$); 23sub WriteXtra($$$); 24sub CheckXtra($$$); 25 26# tags written by Microsoft HDView (ref 1) 27%Image::ExifTool::Microsoft::Stitch = ( 28 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, 29 WRITE_PROC => \&Image::ExifTool::WriteBinaryData, 30 CHECK_PROC => \&Image::ExifTool::CheckBinaryData, 31 WRITABLE => 1, 32 FORMAT => 'float', 33 FIRST_ENTRY => 0, 34 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, 35 NOTES => q{ 36 Information found in the Microsoft custom EXIF tag 0x4748, as written by 37 Windows Live Photo Gallery. 38 }, 39 0 => { 40 Name => 'PanoramicStitchVersion', 41 Format => 'int32u', 42 }, 43 1 => { 44 Name => 'PanoramicStitchCameraMotion', 45 Format => 'int32u', 46 PrintConv => { 47 2 => 'Rigid Scale', 48 3 => 'Affine', 49 4 => '3D Rotation', 50 5 => 'Homography', 51 }, 52 }, 53 2 => { 54 Name => 'PanoramicStitchMapType', 55 Format => 'int32u', 56 PrintConv => { 57 0 => 'Perspective', 58 1 => 'Horizontal Cylindrical', 59 2 => 'Horizontal Spherical', 60 257 => 'Vertical Cylindrical', 61 258 => 'Vertical Spherical', 62 }, 63 }, 64 3 => 'PanoramicStitchTheta0', 65 4 => 'PanoramicStitchTheta1', 66 5 => 'PanoramicStitchPhi0', 67 6 => 'PanoramicStitchPhi1', 68); 69 70# Microsoft Photo schema properties (MicrosoftPhoto) (ref PH) 71%Image::ExifTool::Microsoft::XMP = ( 72 %Image::ExifTool::XMP::xmpTableDefaults, 73 GROUPS => { 0 => 'XMP', 1 => 'XMP-microsoft', 2 => 'Image' }, 74 NAMESPACE => 'MicrosoftPhoto', 75 TABLE_DESC => 'XMP Microsoft', 76 VARS => { NO_ID => 1 }, 77 NOTES => q{ 78 Microsoft Photo 1.0 schema XMP tags. This is likely not a complete list, 79 but represents tags which have been observed in sample images. The actual 80 namespace prefix is "MicrosoftPhoto", but ExifTool shortens this in the 81 family 1 group name. 82 }, 83 CameraSerialNumber => { }, 84 DateAcquired => { Groups => { 2 => 'Time' }, %Image::ExifTool::XMP::dateTimeInfo }, 85 FlashManufacturer => { }, 86 FlashModel => { }, 87 LastKeywordIPTC => { List => 'Bag' }, 88 LastKeywordXMP => { List => 'Bag' }, 89 LensManufacturer => { }, 90 LensModel => { Avoid => 1 }, 91 Rating => { 92 Name => 'RatingPercent', 93 Notes => q{ 94 XMP-xmp:Rating values of 1,2,3,4 and 5 stars correspond to RatingPercent 95 values of 1,25,50,75 and 99 respectively 96 }, 97 }, 98 CreatorAppId => { Name => 'CreatorAppID' }, 99 CreatorOpenWithUIOptions => { }, 100 ItemSubType => { }, 101); 102 103# Microsoft Photo 1.1 schema properties (MP1 - written as 'prefix0' by MSPhoto) (ref PH) 104%Image::ExifTool::Microsoft::MP1 = ( 105 %Image::ExifTool::XMP::xmpTableDefaults, 106 GROUPS => { 0 => 'XMP', 1 => 'XMP-MP1', 2 => 'Image' }, 107 NAMESPACE => 'MP1', 108 TABLE_DESC => 'XMP Microsoft Photo', 109 VARS => { NO_ID => 1 }, 110 NOTES => q{ 111 Microsoft Photo 1.1 schema XMP tags which have been observed. 112 }, 113 PanoramicStitchCameraMotion => { 114 PrintConv => { 115 'RigidScale' => 'Rigid Scale', 116 'Affine' => 'Affine', 117 '3DRotation' => '3D Rotation', 118 'Homography' => 'Homography', 119 }, 120 }, 121 PanoramicStitchMapType => { 122 PrintConv => { 123 'Perspective' => 'Perspective', 124 'Horizontal-Cylindrical' => 'Horizontal Cylindrical', 125 'Horizontal-Spherical' => 'Horizontal Spherical', 126 'Vertical-Cylindrical' => 'Vertical Cylindrical', 127 'Vertical-Spherical' => 'Vertical Spherical', 128 }, 129 }, 130 PanoramicStitchPhi0 => { Writable => 'real' }, 131 PanoramicStitchPhi1 => { Writable => 'real' }, 132 PanoramicStitchTheta0 => { Writable => 'real' }, 133 PanoramicStitchTheta1 => { Writable => 'real' }, 134 WhiteBalance0 => { Writable => 'real' }, 135 WhiteBalance1 => { Writable => 'real' }, 136 WhiteBalance2 => { Writable => 'real' }, 137 Brightness => { Avoid => 1 }, 138 Contrast => { Avoid => 1 }, 139 CameraModelID => { Avoid => 1 }, 140 ExposureCompensation => { Avoid => 1 }, 141 PipelineVersion => { }, 142 StreamType => { }, 143); 144 145# Microsoft Photo 1.2 schema properties (MP) (ref PH) 146# (also ref http://msdn.microsoft.com/en-us/library/windows/desktop/ee719905(v=vs.85).aspx) 147my %sRegions = ( 148 STRUCT_NAME => 'Microsoft Regions', 149 NAMESPACE => 'MPReg', 150 NOTES => q{ 151 Note that PersonLiveIdCID element is called PersonLiveCID according to the 152 Microsoft specification, but in practice their software actually writes 153 PersonLiveIdCID, so ExifTool uses this too. 154 }, 155 Rectangle => { }, 156 PersonDisplayName => { }, 157 PersonEmailDigest => { }, 158 PersonLiveIdCID => { }, # (see https://exiftool.org/forum/index.php?topic=4274.msg20368#msg20368) 159 PersonSourceID => { }, 160); 161%Image::ExifTool::Microsoft::MP = ( 162 %Image::ExifTool::XMP::xmpTableDefaults, 163 GROUPS => { 0 => 'XMP', 1 => 'XMP-MP', 2 => 'Image' }, 164 NAMESPACE => 'MP', 165 TABLE_DESC => 'XMP Microsoft Photo', 166 VARS => { NO_ID => 1 }, 167 NOTES => q{ 168 Microsoft Photo 1.2 schema XMP tags which have been observed. 169 }, 170 RegionInfo => { 171 Name => 'RegionInfoMP', 172 Struct => { 173 STRUCT_NAME => 'Microsoft RegionInfo', 174 NAMESPACE => 'MPRI', 175 Regions => { Struct => \%sRegions, List => 'Bag' }, 176 DateRegionsValid => { 177 Writable => 'date', 178 Shift => 'Time', 179 Groups => { 2 => 'Time'}, 180 PrintConv => '$self->ConvertDateTime($val)', 181 PrintConvInv => '$self->InverseDateTime($val,undef,1)', 182 }, 183 }, 184 }, 185 # remove "MP" from tag name (was added only to avoid conflict with XMP-mwg-rs:RegionInfo) 186 RegionInfoRegions => { Flat => 1, Name => 'RegionInfoRegions' }, 187 RegionInfoDateRegionsValid => { Flat => 1, Name => 'RegionInfoDateRegionsValid' }, 188 # shorten flattened Regions tag names to make them easier to use 189 RegionInfoRegionsRectangle => { Flat => 1, Name => 'RegionRectangle' }, 190 RegionInfoRegionsPersonDisplayName => { Flat => 1, Name => 'RegionPersonDisplayName' }, 191 RegionInfoRegionsPersonEmailDigest => { Flat => 1, Name => 'RegionPersonEmailDigest' }, 192 RegionInfoRegionsPersonLiveIdCID => { Flat => 1, Name => 'RegionPersonLiveIdCID' }, 193 RegionInfoRegionsPersonSourceID => { Flat => 1, Name => 'RegionPersonSourceID' }, 194); 195 196# Xtra tags written in MP4 files written by Microsoft Windows Media Player 197# (ref http://msdn.microsoft.com/en-us/library/windows/desktop/dd562330(v=VS.85).aspx) 198# Note: These tags are closely related to tags in Image::ExifTool::ASF::ExtendedDescr 199# and Image::ExifTool::WTV::Metadata 200%Image::ExifTool::Microsoft::Xtra = ( 201 PROCESS_PROC => \&ProcessXtra, 202 WRITE_PROC => \&WriteXtra, 203 CHECK_PROC => \&CheckXtra, 204 WRITE_GROUP => 'Microsoft', 205 AVOID => 1, 206 GROUPS => { 0 => 'QuickTime', 2 => 'Video' }, 207 VARS => { NO_ID => 1 }, 208 NOTES => q{ 209 Tags found in the Microsoft "Xtra" atom of QuickTime videos. Tag ID's are 210 not shown because some are unruly GUID's. Currently most of these tags are 211 not writable because the Microsoft documentation is poor and samples were 212 not available, but more tags may be made writable in the future if samples 213 are provided. Note that writable tags in this table are are flagged to 214 "Avoid", which means that other more common tags will be written instead if 215 possible unless the Microsoft group is specified explicitly. 216 }, 217 Abstract => { }, 218 AcquisitionTime => { Groups => { 2 => 'Time' } }, 219 AcquisitionTimeDay => { Groups => { 2 => 'Time' } }, 220 AcquisitionTimeMonth => { Groups => { 2 => 'Time' } }, 221 AcquisitionTimeYear => { Groups => { 2 => 'Time' } }, 222 AcquisitionTimeYearMonth => { Groups => { 2 => 'Time' } }, 223 AcquisitionTimeYearMonthDay => { Groups => { 2 => 'Time' } }, 224 AlbumArtistSortOrder => { }, 225 AlbumID => { }, 226 AlbumIDAlbumArtist => { }, 227 AlbumTitleSortOrder => { }, 228 AlternateSourceURL => { }, 229 AudioBitrate => { }, 230 AudioFormat => { }, 231 Author => { Groups => { 2 => 'Author' } }, 232 AuthorSortOrder => { }, 233 AverageLevel => { }, 234 Bitrate => { }, 235 BuyNow => { }, 236 BuyTickets => { }, 237 CallLetters => { }, 238 CameraManufacturer => { }, 239 CameraModel => { }, 240 CDTrackEnabled => { }, 241 Channels => { }, 242 chapterNum => { }, 243 Comment => { }, 244 ContentDistributorDuration => { }, 245 Copyright => { Groups => { 2 => 'Author' } }, 246 Count => { }, 247 CurrentBitrate => { }, 248 Description => { }, 249 DisplayArtist => { }, 250 DLNAServerUDN => { }, 251 DLNASourceURI => { }, 252 DRMKeyID => { }, 253 DRMIndividualizedVersion => { }, 254 DTCPIPHost => { }, 255 DTCPIPPort => { }, 256 Duration => { }, 257 DVDID => { }, 258 Event => { }, 259 FileSize => { }, 260 FileType => { }, 261 FourCC => { }, 262 FormatTag => { }, 263 FrameRate => { }, 264 Frequency => { }, 265 IsNetworkFeed => { }, 266 Is_Protected => 'IsProtected', 267 IsVBR => { }, 268 LeadPerformer => { }, 269 LibraryID => { }, 270 LibraryName => { }, 271 Location => { }, 272 MediaContentTypes => { }, 273 MediaType => { }, 274 ModifiedBy => { }, 275 MoreInfo => { }, 276 PartOfSet => { }, 277 PeakValue => { }, 278 PixelAspectRatioX => { }, 279 PixelAspectRatioY => { }, 280 PlaylistIndex => { }, 281 Provider => { }, 282 ProviderLogoURL => { }, 283 ProviderURL => { }, 284 RadioBand => { }, 285 RadioFormat => { }, 286 RatingOrg => { }, 287 RecordingTime => { Groups => { 2 => 'Time' } }, 288 RecordingTimeDay => { Groups => { 2 => 'Time' } }, 289 RecordingTimeMonth => { Groups => { 2 => 'Time' } }, 290 RecordingTimeYear => { Groups => { 2 => 'Time' } }, 291 RecordingTimeYearMonth => { Groups => { 2 => 'Time' } }, 292 RecordingTimeYearMonthDay => { Groups => { 2 => 'Time' } }, 293 ReleaseDate => { Groups => { 2 => 'Time' } }, 294 ReleaseDateDay => { Groups => { 2 => 'Time' } }, 295 ReleaseDateMonth => { Groups => { 2 => 'Time' } }, 296 ReleaseDateYear => { Groups => { 2 => 'Time' } }, 297 ReleaseDateYearMonth => { Groups => { 2 => 'Time' } }, 298 ReleaseDateYearMonthDay => { Groups => { 2 => 'Time' } }, 299 RequestState => { }, 300 ShadowFilePath => { }, 301 SourceURL => { }, 302 Subject => { }, 303 SyncState => { }, 304 Sync01 => { }, 305 Sync02 => { }, 306 Sync03 => { }, 307 Sync04 => { }, 308 Sync05 => { }, 309 Sync06 => { }, 310 Sync07 => { }, 311 Sync08 => { }, 312 Sync09 => { }, 313 Sync10 => { }, 314 Sync11 => { }, 315 Sync12 => { }, 316 Sync13 => { }, 317 Sync14 => { }, 318 Sync15 => { }, 319 Sync16 => { }, 320 SyncOnly => { }, 321 Temporary => { }, 322 Title => { }, 323 titleNum => { }, 324 TitleSortOrder => { }, 325 TotalDuration => { }, 326 TrackingID => { }, 327 UserCustom1 => { }, 328 UserCustom2 => { }, 329 UserEffectiveRating => { }, 330 UserLastPlayedTime => { }, 331 UserPlayCount => { }, 332 UserPlaycountAfternoon => { }, 333 UserPlaycountEvening => { }, 334 UserPlaycountMorning => { }, 335 UserPlaycountNight => { }, 336 UserPlaycountWeekday => { }, 337 UserPlaycountWeekend => { }, 338 UserRating => { }, 339 UserServiceRating => { }, 340 VideoBitrate => { }, 341 VideoFormat => { }, 342 'WM/AlbumArtist' => { Name => 'AlbumArtist', Writable => 'Unicode' }, # (NC) 343 'WM/AlbumCoverURL' => { Name => 'AlbumCoverURL', Writable => 'Unicode' }, # (NC) 344 'WM/AlbumTitle' => { Name => 'AlbumTitle', Writable => 'Unicode' }, # (NC) 345 'WM/BeatsPerMinute' => 'BeatsPerMinute', 346 'WM/Category' => { Name => 'Category', Writable => 'Unicode', List => 1 }, 347 'WM/Composer' => { Name => 'Composer', Writable => 'Unicode' }, # (NC) 348 'WM/Conductor' => { Name => 'Conductor', Writable => 'Unicode', List => 1 }, 349 'WM/ContentDistributor' => { Name => 'ContentDistributor', Writable => 'Unicode' }, 350 'WM/ContentDistributorType' => 'ContentDistributorType', 351 'WM/ContentGroupDescription'=> 'ContentGroupDescription', 352 'WM/Director' => { Name => 'Director', Writable => 'Unicode', List => 1 }, 353 'WM/EncodingTime' => { 354 Name => 'EncodingTime', 355 Groups => { 2 => 'Time' }, 356 Shift => 'Time', 357 Writable => 'date', 358 PrintConv => '$self->ConvertDateTime($val)', 359 PrintConvInv => '$self->InverseDateTime($val)', 360 }, 361 'WM/Genre' => 'Genre', 362 'WM/GenreID' => 'GenreID', 363 'WM/InitialKey' => { Name => 'InitialKey', Writable => 'Unicode' }, 364 'WM/Language' => 'Language', 365 'WM/Lyrics' => 'Lyrics', 366 'WM/MCDI' => 'MCDI', 367 'WM/MediaClassPrimaryID' => { 368 Name => 'MediaClassPrimaryID', 369 Writable => 'GUID', 370 PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx 371 'D1607DBC-E323-4BE2-86A1-48A42A28441E' => 'Music', 372 'DB9830BD-3AB3-4FAB-8A37-1A995F7FF74B' => 'Video', 373 '01CD0F29-DA4E-4157-897B-6275D50C4F11' => 'Audio (not music)', 374 'FCF24A76-9A57-4036-990D-E35DD8B244E1' => 'Other (not audio or video)', 375 }, 376 }, 377 'WM/MediaClassSecondaryID' => { 378 Name => 'MediaClassSecondaryID', 379 Writable => 'GUID', 380 PrintConv => { #http://msdn.microsoft.com/en-us/library/windows/desktop/dd757960(v=vs.85).aspx 381 'E0236BEB-C281-4EDE-A36D-7AF76A3D45B5' => 'Audio Book', 382 '3A172A13-2BD9-4831-835B-114F6A95943F' => 'Spoken Word', 383 '6677DB9B-E5A0-4063-A1AD-ACEB52840CF1' => 'Audio News', 384 '1B824A67-3F80-4E3E-9CDE-F7361B0F5F1B' => 'Talk Show', 385 '1FE2E091-4E1E-40CE-B22D-348C732E0B10' => 'Video News', 386 'D6DE1D88-C77C-4593-BFBC-9C61E8C373E3' => 'Web-based Video', 387 '00033368-5009-4AC3-A820-5D2D09A4E7C1' => 'Sound Clip from Game', 388 'F24FF731-96FC-4D0F-A2F5-5A3483682B1A' => 'Song from Game', 389 'E3E689E2-BA8C-4330-96DF-A0EEEFFA6876' => 'Music Video', 390 'B76628F4-300D-443D-9CB5-01C285109DAF' => 'Home Movie', 391 'A9B87FC9-BD47-4BF0-AC4F-655B89F7D868' => 'Feature Film', 392 'BA7F258A-62F7-47A9-B21F-4651C42A000E' => 'TV Show', 393 '44051B5B-B103-4B5C-92AB-93060A9463F0' => 'Corporate Video', 394 '0B710218-8C0C-475E-AF73-4C41C0C8F8CE' => 'Home Video from Pictures', 395 '00000000-0000-0000-0000-000000000000' => 'Unknown Content', #PH 396 }, 397 }, 398 'WM/MediaOriginalBroadcastDateTime' => { 399 Name => 'MediaOriginalBroadcastDateTime', 400 Groups => { 2 => 'Time' }, 401 PrintConv => '$self->ConvertDateTime($val)', 402 }, 403 'WM/MediaOriginalChannel' => 'MediaOriginalChannel', 404 'WM/MediaStationName' => 'MediaStationName', 405 'WM/Mood' => { Name => 'Mood', Writable => 'Unicode' }, 406 'WM/OriginalAlbumTitle' => { Name => 'OriginalAlbumTitle', Writable => 'Unicode' }, # (NC) 407 'WM/OriginalArtist' => { Name => 'OriginalArtist', Writable => 'Unicode' }, # (NC) 408 'WM/OriginalLyricist' => { Name => 'OriginalLyricist', Writable => 'Unicode' }, # (NC) 409 'WM/ParentalRating' => { Name => 'ParentalRating', Writable => 'Unicode' }, 410 'WM/PartOfSet' => 'PartOfSet', 411 'WM/Period' => { Name => 'Period', Writable => 'Unicode' }, 412 'WM/Producer' => { Name => 'Producer', Writable => 'Unicode', List => 1 }, 413 'WM/ProtectionType' => 'ProtectionType', 414 'WM/Provider' => { Name => 'Provider', Writable => 'Unicode' }, # (NC) 415 'WM/ProviderRating' => 'ProviderRating', 416 'WM/ProviderStyle' => 'ProviderStyle', 417 'WM/Publisher' => { Name => 'Publisher', Writable => 'Unicode' }, # (multiple entries separated by semicolon) 418 'WM/SharedUserRating' => { Name => 'SharedUserRating', Writable => 'int64u' }, 419 'WM/SubscriptionContentID' => 'SubscriptionContentID', 420 'WM/SubTitle' => { Name => 'Subtitle', Writable => 'Unicode' }, 421 'WM/SubTitleDescription' => 'SubtitleDescription', 422 'WM/TrackNumber' => 'TrackNumber', 423 'WM/UniqueFileIdentifier' => 'UniqueFileIdentifier', 424 'WM/VideoFrameRate' => 'VideoFrameRate', 425 'WM/VideoHeight' => 'VideoHeight', 426 'WM/VideoWidth' => 'VideoWidth', 427 'WM/WMCollectionGroupID' => 'WMCollectionGroupID', 428 'WM/WMCollectionID' => 'WMCollectionID', 429 'WM/WMContentID' => 'WMContentID', 430 'WM/WMShadowFileSourceDRMType' => 'WMShadowFileSourceDRMType', 431 'WM/WMShadowFileSourceFileType' => 'WMShadowFileSourceFileType', 432 'WM/Writer' => { Name => 'Writer', Groups => { 2 => 'Author' }, Writable => 'Unicode' }, # (NC) 433 'WM/Year' => { Name => 'Year', Groups => { 2 => 'Time' } }, 434 'WM/PromotionURL' => { Name => 'PromotionURL',Writable => 'Unicode' }, 435 'WM/AuthorURL' => { Name => 'AuthorURL', Groups => { 2 => 'Author' }, Writable => 'Unicode' }, 436 'WM/EncodedBy', => { Name => 'EncodedBy', Writable => 'Unicode' }, 437 438 # I can't find documentation for the following tags in videos, 439 # but the tag ID's correspond to Microsoft property GUID+ID's 440 # References: 441 # http://msdn.microsoft.com/en-us/library/cc251929%28v=prot.10%29.aspx 442 # http://multi-rename-script.googlecode.com/svn-history/r4/trunk/plugins/ShellDetails/ShellDetails.ini 443 # I have observed only 1 so far: 444 '{2CBAA8F5-D81F-47CA-B17A-F8D822300131} 100' => { 445 Name => 'DateAcquired', # (seems to be when videos are downloaded from the camera) 446 Groups => { 2 => 'Time' }, 447 Shift => 'Time', 448 Writable => 'vt_filetime', 449 PrintConv => '$self->ConvertDateTime($val)', 450 PrintConvInv => '$self->InverseDateTime($val,undef)', 451 }, 452 # the following have not yet been observed... 453 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 10' => 'Name', 454 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 12' => 'Size', 455 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 4' => 'Type', 456 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 14' => { 457 Name => 'DateModified', 458 Groups => { 2 => 'Time' }, 459 PrintConv => '$self->ConvertDateTime($val)', 460 }, 461 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 15' => { 462 Name => 'DateCreated', 463 Groups => { 2 => 'Time' }, 464 PrintConv => '$self->ConvertDateTime($val)', 465 }, 466 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 16' => { 467 Name => 'DateAccessed', 468 Groups => { 2 => 'Time' }, 469 PrintConv => '$self->ConvertDateTime($val)', 470 }, 471 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 13' => 'Attributes', 472 '{D8C3986F-813B-449C-845D-87B95D674ADE} 2' => 'Status', 473 '{9B174B34-40FF-11D2-A27E-00C04FC30871} 4' => 'Owner', 474 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 4' => { 475 Name => 'Author', 476 Groups => { 2 => 'Author' }, 477 }, 478 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 2' => 'Title', 479 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 3' => 'Subject', 480 '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 2' => 'Category', 481 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 14' => 'Pages', 482 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 6' => 'Comments', 483 '{64440492-4C8B-11D1-8B70-080036B11A03} 11' => { 484 Name => 'Copyright', 485 Groups => { 2 => 'Author' }, 486 }, 487 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 2' => 'Artist', 488 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 4' => 'AlbumTitle', 489 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 5' => { 490 Name => 'Year', 491 Groups => { 2 => 'Time' }, 492 }, 493 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 7' => 'TrackNumber', 494 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 11' => 'Genre', 495 '{64440490-4C8B-11D1-8B70-080036B11A03} 3' => 'Duration', 496 '{64440490-4C8B-11D1-8B70-080036B11A03} 4' => 'Bitrate', 497 '{AEAC19E4-89AE-4508-B9B7-BB867ABEE2ED} 2' => 'Protected', 498 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 272' => 'CameraModel', 499 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 36867' => { 500 Name => 'DatePictureTaken', 501 Groups => { 2 => 'Time' }, 502 PrintConv => '$self->ConvertDateTime($val)', 503 }, 504 '{6444048F-4C8B-11D1-8B70-080036B11A03} 13' => 'Dimensions', 505 '{6444048F-4C8B-11D1-8B70-080036B11A03} 3' => 'Untitled0', 506 '{6444048F-4C8B-11D1-8B70-080036B11A03} 4' => 'Untitled1', 507 '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 2' => 'EpisodeName', 508 '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 3' => 'ProgramDescription', 509 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 12' => 'Untitled2', 510 '{64440490-4C8B-11D1-8B70-080036B11A03} 6' => 'AudioSampleSize', 511 '{64440490-4C8B-11D1-8B70-080036B11A03} 5' => 'AudioSampleRate', 512 '{64440490-4C8B-11D1-8B70-080036B11A03} 7' => 'Channels', 513 '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 15' => 'Company', 514 '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 3' => 'Description', 515 '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 4' => 'FileVersion', 516 '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 7' => 'ProductName', 517 '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 8' => 'ProductVersion', 518 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 5' => 'Keywords', 519 '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 11' => 'Type', 520 '{6D24888F-4718-4BDA-AFED-EA0FB4386CD8} 100' => 'OfflineStatus', 521 '{A94688B6-7D9F-4570-A648-E3DFC0AB2B3F} 100' => 'OfflineAvailability', 522 '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 9' => 'PerceivedType', 523 '{1E3EE840-BC2B-476C-8237-2ACD1A839B22} 3' => 'Kinds', 524 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 36' => 'Conductors', 525 '{64440492-4C8B-11D1-8B70-080036B11A03} 9' => 'Rating', 526 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 271' => 'CameraMaker', 527 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 18' => 'ProgramName', 528 '{293CA35A-09AA-4DD2-B180-1FE245728A52} 100' => 'Duration', 529 '{BFEE9149-E3E2-49A7-A862-C05988145CEC} 100' => 'IsOnline', 530 '{315B9C8D-80A9-4EF9-AE16-8E746DA51D70} 100' => 'IsRecurring', 531 '{F6272D18-CECC-40B1-B26A-3911717AA7BD} 100' => 'Location', 532 '{D55BAE5A-3892-417A-A649-C6AC5AAAEAB3} 100' => 'OptionalAttendeeAddresses', 533 '{09429607-582D-437F-84C3-DE93A2B24C3C} 100' => 'OptionalAttendees', 534 '{744C8242-4DF5-456C-AB9E-014EFB9021E3} 100' => 'OrganizerAddress', 535 '{AAA660F9-9865-458E-B484-01BC7FE3973E} 100' => 'OrganizerName', 536 '{72FC5BA4-24F9-4011-9F3F-ADD27AFAD818} 100' => 'ReminderTime', 537 '{0BA7D6C3-568D-4159-AB91-781A91FB71E5} 100' => 'RequiredAttendeeAddresses', 538 '{B33AF30B-F552-4584-936C-CB93E5CDA29F} 100' => 'RequiredAttendees', 539 '{00F58A38-C54B-4C40-8696-97235980EAE1} 100' => 'Resources', 540 '{5BF396D4-5EB2-466F-BDE9-2FB3F2361D6E} 100' => 'Free-busyStatus', 541 '{9B174B35-40FF-11D2-A27E-00C04FC30871} 3' => 'TotalSize', 542 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 9' => 'AccountName', 543 '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 5' => 'Computer', 544 '{9AD5BADB-CEA7-4470-A03D-B84E51B9949E} 100' => 'Anniversary', 545 '{CD102C9C-5540-4A88-A6F6-64E4981C8CD1} 100' => 'AssistantsName', 546 '{9A93244D-A7AD-4FF8-9B99-45EE4CC09AF6} 100' => 'AssistantsPhone', 547 '{176DC63C-2688-4E89-8143-A347800F25E9} 47' => 'Birthday', 548 '{730FB6DD-CF7C-426B-A03F-BD166CC9EE24} 100' => 'BusinessAddress', 549 '{402B5934-EC5A-48C3-93E6-85E86A2D934E} 100' => 'BusinessCity', 550 '{B0B87314-FCF6-4FEB-8DFF-A50DA6AF561C} 100' => 'BusinessCountry-Region', 551 '{BC4E71CE-17F9-48D5-BEE9-021DF0EA5409} 100' => 'BusinessPOBox', 552 '{E1D4A09E-D758-4CD1-B6EC-34A8B5A73F80} 100' => 'BusinessPostalCode', 553 '{446F787F-10C4-41CB-A6C4-4D0343551597} 100' => 'BusinessStateOrProvince', 554 '{DDD1460F-C0BF-4553-8CE4-10433C908FB0} 100' => 'BusinessStreet', 555 '{91EFF6F3-2E27-42CA-933E-7C999FBE310B} 100' => 'BusinessFax', 556 '{56310920-2491-4919-99CE-EADB06FAFDB2} 100' => 'BusinessHomePage', 557 '{6A15E5A0-0A1E-4CD7-BB8C-D2F1B0C929BC} 100' => 'BusinessPhone', 558 '{BF53D1C3-49E0-4F7F-8567-5A821D8AC542} 100' => 'CallbackNumber', 559 '{8FDC6DEA-B929-412B-BA90-397A257465FE} 100' => 'CarPhone', 560 '{D4729704-8EF1-43EF-9024-2BD381187FD5} 100' => 'Children', 561 '{8589E481-6040-473D-B171-7FA89C2708ED} 100' => 'CompanyMainPhone', 562 '{FC9F7306-FF8F-4D49-9FB6-3FFE5C0951EC} 100' => 'Department', 563 '{F8FA7FA3-D12B-4785-8A4E-691A94F7A3E7} 100' => 'E-mailAddress', 564 '{38965063-EDC8-4268-8491-B7723172CF29} 100' => 'E-mail2', 565 '{644D37B4-E1B3-4BAD-B099-7E7C04966ACA} 100' => 'E-mail3', 566 '{84D8F337-981D-44B3-9615-C7596DBA17E3} 100' => 'E-mailList', 567 '{CC6F4F24-6083-4BD4-8754-674D0DE87AB8} 100' => 'E-mailDisplayName', 568 '{F1A24AA7-9CA7-40F6-89EC-97DEF9FFE8DB} 100' => 'FileAs', 569 '{14977844-6B49-4AAD-A714-A4513BF60460} 100' => 'FirstName', 570 '{635E9051-50A5-4BA2-B9DB-4ED056C77296} 100' => 'FullName', 571 '{3C8CEE58-D4F0-4CF9-B756-4E5D24447BCD} 100' => 'Gender', 572 '{176DC63C-2688-4E89-8143-A347800F25E9} 70' => 'GivenName', 573 '{5DC2253F-5E11-4ADF-9CFE-910DD01E3E70} 100' => 'Hobbies', 574 '{98F98354-617A-46B8-8560-5B1B64BF1F89} 100' => 'HomeAddress', 575 '{176DC63C-2688-4E89-8143-A347800F25E9} 65' => 'HomeCity', 576 '{08A65AA1-F4C9-43DD-9DDF-A33D8E7EAD85} 100' => 'HomeCountry-Region', 577 '{7B9F6399-0A3F-4B12-89BD-4ADC51C918AF} 100' => 'HomePOBox', 578 '{8AFCC170-8A46-4B53-9EEE-90BAE7151E62} 100' => 'HomePostalCode', 579 '{C89A23D0-7D6D-4EB8-87D4-776A82D493E5} 100' => 'HomeStateOrProvince', 580 '{0ADEF160-DB3F-4308-9A21-06237B16FA2A} 100' => 'HomeStreet', 581 '{660E04D6-81AB-4977-A09F-82313113AB26} 100' => 'HomeFax', 582 '{176DC63C-2688-4E89-8143-A347800F25E9} 20' => 'HomePhone', 583 '{D68DBD8A-3374-4B81-9972-3EC30682DB3D} 100' => 'IMAddresses', 584 '{F3D8F40D-50CB-44A2-9718-40CB9119495D} 100' => 'Initials', 585 '{176DC63C-2688-4E89-8143-A347800F25E9} 6' => 'JobTitle', 586 '{97B0AD89-DF49-49CC-834E-660974FD755B} 100' => 'Label', 587 '{8F367200-C270-457C-B1D4-E07C5BCD90C7} 100' => 'LastName', 588 '{C0AC206A-827E-4650-95AE-77E2BB74FCC9} 100' => 'MailingAddress', 589 '{176DC63C-2688-4E89-8143-A347800F25E9} 71' => 'MiddleName', 590 '{176DC63C-2688-4E89-8143-A347800F25E9} 35' => 'CellPhone', 591 '{176DC63C-2688-4E89-8143-A347800F25E9} 74' => 'Nickname', 592 '{176DC63C-2688-4E89-8143-A347800F25E9} 7' => 'OfficeLocation', 593 '{508161FA-313B-43D5-83A1-C1ACCF68622C} 100' => 'OtherAddress', 594 '{6E682923-7F7B-4F0C-A337-CFCA296687BF} 100' => 'OtherCity', 595 '{8F167568-0AAE-4322-8ED9-6055B7B0E398} 100' => 'OtherCountry-Region', 596 '{8B26EA41-058F-43F6-AECC-4035681CE977} 100' => 'OtherPOBox', 597 '{95C656C1-2ABF-4148-9ED3-9EC602E3B7CD} 100' => 'OtherPostalCode', 598 '{71B377D6-E570-425F-A170-809FAE73E54E} 100' => 'OtherStateOrProvince', 599 '{FF962609-B7D6-4999-862D-95180D529AEA} 100' => 'OtherStreet', 600 '{D6304E01-F8F5-4F45-8B15-D024A6296789} 100' => 'Pager', 601 '{176DC63C-2688-4E89-8143-A347800F25E9} 69' => 'PersonalTitle', 602 '{C8EA94F0-A9E3-4969-A94B-9C62A95324E0} 100' => 'City', 603 '{E53D799D-0F3F-466E-B2FF-74634A3CB7A4} 100' => 'Country-Region', 604 '{DE5EF3C7-46E1-484E-9999-62C5308394C1} 100' => 'POBox', 605 '{18BBD425-ECFD-46EF-B612-7B4A6034EDA0} 100' => 'PostalCode', 606 '{F1176DFE-7138-4640-8B4C-AE375DC70A6D} 100' => 'StateOrProvince', 607 '{63C25B20-96BE-488F-8788-C09C407AD812} 100' => 'Street', 608 '{176DC63C-2688-4E89-8143-A347800F25E9} 48' => 'PrimaryE-mail', 609 '{176DC63C-2688-4E89-8143-A347800F25E9} 25' => 'PrimaryPhone', 610 '{7268AF55-1CE4-4F6E-A41F-B6E4EF10E4A9} 100' => 'Profession', 611 '{9D2408B6-3167-422B-82B0-F583B7A7CFE3} 100' => 'Spouse', 612 '{176DC63C-2688-4E89-8143-A347800F25E9} 73' => 'Suffix', 613 '{AAF16BAC-2B55-45E6-9F6D-415EB94910DF} 100' => 'TTY-TTDPhone', 614 '{C554493C-C1F7-40C1-A76C-EF8C0614003E} 100' => 'Telex', 615 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 18' => 'Webpage', 616 '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 27' => 'Status', 617 '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 26' => 'ContentType', 618 '{43F8D7B7-A444-4F87-9383-52271C9B915C} 100' => { 619 Name => 'DateArchived', 620 Groups => { 2 => 'Time' }, 621 PrintConv => '$self->ConvertDateTime($val)', 622 }, 623 '{72FAB781-ACDA-43E5-B155-B2434F85E678} 100' => { 624 Name => 'DateCompleted', 625 Groups => { 2 => 'Time' }, 626 PrintConv => '$self->ConvertDateTime($val)', 627 }, 628 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 18258' => { 629 Name => 'DateImported', 630 Groups => { 2 => 'Time' }, 631 PrintConv => '$self->ConvertDateTime($val)', 632 }, 633 '{276D7BB0-5B34-4FB0-AA4B-158ED12A1809} 100' => 'ClientID', 634 '{F334115E-DA1B-4509-9B3D-119504DC7ABB} 100' => 'Contributors', 635 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 11' => 'LastPrinted', 636 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 13' => { 637 Name => 'DateLastSaved', 638 Groups => { 2 => 'Time' }, 639 PrintConv => '$self->ConvertDateTime($val)', 640 }, 641 '{1E005EE6-BF27-428B-B01C-79676ACD2870} 100' => 'Division', 642 '{E08805C8-E395-40DF-80D2-54F0D6C43154} 100' => 'DocumentID', 643 '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 7' => 'Slides', 644 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 10' => 'TotalEditingTime', 645 '{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 15' => 'WordCount', 646 '{3F8472B5-E0AF-4DB2-8071-C53FE76AE7CE} 100' => 'DueDate', 647 '{C75FAA05-96FD-49E7-9CB4-9F601082D553} 100' => 'EndDate', 648 '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 12' => 'FileCount', 649 '{41CF5AE0-F75A-4806-BD87-59C7D9248EB9} 100' => 'WindowsFileName', 650 '{67DF94DE-0CA7-4D6F-B792-053A3E4F03CF} 100' => 'FlagColor', 651 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 12' => 'FlagStatus', 652 '{9B174B35-40FF-11D2-A27E-00C04FC30871} 2' => 'SpaceFree', 653 '{6444048F-4C8B-11D1-8B70-080036B11A03} 7' => 'BitDepth', 654 '{6444048F-4C8B-11D1-8B70-080036B11A03} 5' => 'HorizontalResolution', 655 '{6444048F-4C8B-11D1-8B70-080036B11A03} 6' => 'VerticalResolution', 656 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 11' => 'Importance', 657 '{F23F425C-71A1-4FA8-922F-678EA4A60408} 100' => 'IsAttachment', 658 '{5CDA5FC8-33EE-4FF3-9094-AE7BD8868C4D} 100' => 'IsDeleted', 659 '{5DA84765-E3FF-4278-86B0-A27967FBDD03} 100' => 'HasFlag', 660 '{A6F360D2-55F9-48DE-B909-620E090A647C} 100' => 'IsCompleted', 661 '{346C8BD1-2E6A-4C45-89A4-61B78E8E700F} 100' => 'Incomplete', 662 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 10' => 'ReadStatus', 663 '{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902} 100' => 'Shared', 664 '{D0A04F0A-462A-48A4-BB2F-3706E88DBD7D} 100' => { 665 Name => 'Creator', 666 Groups => { 2 => 'Author' }, 667 }, 668 '{F7DB74B4-4287-4103-AFBA-F1B13DCD75CF} 100' => { 669 Name => 'Date', 670 Groups => { 2 => 'Time' }, 671 PrintConv => '$self->ConvertDateTime($val)', 672 }, 673 '{B725F130-47EF-101A-A5F1-02608C9EEBAC} 2' => 'FolderName', 674 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 6' => 'FolderPath', 675 '{DABD30ED-0043-4789-A7F8-D013A4736622} 100' => 'Folder', 676 '{D4D0AA16-9948-41A4-AA85-D97FF9646993} 100' => 'Participants', 677 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 7' => 'Path', 678 '{DEA7C82C-1D89-4A66-9427-A4E3DEBABCB1} 100' => 'ContactNames', 679 '{95BEB1FC-326D-4644-B396-CD3ED90E6DDF} 100' => 'EntryType', 680 '{D5CDD502-2E9C-101B-9397-08002B2CF9AE} 28' => 'Language', 681 '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 23' => { 682 Name => 'DateVisited', 683 Groups => { 2 => 'Time' }, 684 PrintConv => '$self->ConvertDateTime($val)', 685 }, 686 '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 21' => 'Description', 687 '{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25} 3' => 'LinkStatus', 688 '{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25} 2' => 'LinkTarget', 689 '{5CBF2787-48CF-4208-B90E-EE5E5D420294} 2' => 'URL', 690 '{2E4B640D-5019-46D8-8881-55414CC5CAA0} 100' => 'MediaCreated', 691 '{DE41CC29-6971-4290-B472-F59F2E2F31E2} 100' => { 692 Name => 'DateReleased', 693 Groups => { 2 => 'Time' }, 694 PrintConv => '$self->ConvertDateTime($val)', 695 }, 696 '{64440492-4C8B-11D1-8B70-080036B11A03} 36' => 'EncodedBy', 697 '{64440492-4C8B-11D1-8B70-080036B11A03} 22' => 'Producers', 698 '{64440492-4C8B-11D1-8B70-080036B11A03} 30' => 'Publisher', 699 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 38' => 'Subtitle', 700 '{64440492-4C8B-11D1-8B70-080036B11A03} 34' => 'UserWebURL', 701 '{64440492-4C8B-11D1-8B70-080036B11A03} 23' => 'Writers', 702 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 21' => 'Attachments', 703 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 2' => 'BccAddresses', 704 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 3' => 'BccNames', 705 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 4' => 'CcAddresses', 706 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 5' => 'CcNames', 707 '{DC8F80BD-AF1E-4289-85B6-3DFC1B493992} 100' => 'ConversationID', 708 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 20' => { 709 Name => 'DateReceived', 710 Groups => { 2 => 'Time' }, 711 PrintConv => '$self->ConvertDateTime($val)', 712 }, 713 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 19' => { 714 Name => 'DateSent', 715 Groups => { 2 => 'Time' }, 716 PrintConv => '$self->ConvertDateTime($val)', 717 }, 718 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 13' => 'FromAddresses', 719 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 14' => 'FromNames', 720 '{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4} 8' => 'HasAttachments', 721 '{0BE1C8E7-1981-4676-AE14-FDD78F05A6E7} 100' => 'SenderAddress', 722 '{0DA41CFA-D224-4A18-AE2F-596158DB4B3A} 100' => 'SenderName', 723 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 15' => 'Store', 724 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 16' => 'ToAddresses', 725 '{BCCC8A3C-8CEF-42E5-9B1C-C69079398BC7} 100' => 'ToDoTitle', 726 '{E3E0584C-B788-4A5A-BB20-7F5A44C9ACDD} 17' => 'ToNames', 727 '{FDF84370-031A-4ADD-9E91-0D775F1C6605} 100' => 'Mileage', 728 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 13' => 'AlbumArtist', 729 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 35' => 'Beats-per-minute', 730 '{64440492-4C8B-11D1-8B70-080036B11A03} 19' => 'Composers', 731 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 34' => 'InitialKey', 732 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 39' => 'Mood', 733 '{56A3372E-CE9C-11D2-9F0E-006097C686F6} 37' => 'PartOfSet', 734 '{64440492-4C8B-11D1-8B70-080036B11A03} 31' => 'Period', 735 '{4776CAFA-BCE4-4CB1-A23E-265E76D8EB11} 100' => 'Color', 736 '{64440492-4C8B-11D1-8B70-080036B11A03} 21' => 'ParentalRating', 737 '{10984E0A-F9F2-4321-B7EF-BAF195AF4319} 100' => 'ParentalRatingReason', 738 '{9B174B35-40FF-11D2-A27E-00C04FC30871} 5' => 'SpaceUsed', 739 '{D35F743A-EB2E-47F2-A286-844132CB1427} 100' => 'ExifVersion', 740 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 18248' => 'Event', 741 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37380' => 'ExposureBias', 742 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 34850' => 'ExposureProgram', 743 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 33434' => 'ExposureTime', 744 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 33437' => 'F-stop', 745 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37385' => 'FlashMode', 746 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37386' => 'FocalLength', 747 '{A0E74609-B84D-4F49-B860-462BD9971F98} 100' => 'FocalLength35mm', 748 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 34855' => 'ISOSpeed', 749 '{E6DDCAF7-29C5-4F0A-9A68-D19412EC7090} 100' => 'LensMaker', 750 '{E1277516-2B5F-4869-89B1-2E585BD38B7A} 100' => 'LensModel', 751 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37384' => 'LightSource', 752 '{08F6D7C2-E3F2-44FC-AF1E-5AA5C81A2D3E} 100' => 'MaxAperture', 753 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37383' => 'MeteringMode', 754 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 274' => 'Orientation', 755 '{6D217F6D-3F6A-4825-B470-5F03CA2FBE9B} 100' => 'ProgramMode', 756 '{49237325-A95A-4F67-B211-816B2D45D2E0} 100' => 'Saturation', 757 '{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 37382' => 'SubjectDistance', 758 '{EE3D3D8A-5381-4CFA-B13B-AAF66B5F4EC9} 100' => 'WhiteBalance', 759 '{9C1FCF74-2D97-41BA-B4AE-CB2E3661A6E4} 5' => 'Priority', 760 '{39A7F922-477C-48DE-8BC8-B28441E342E3} 100' => 'Project', 761 '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 7' => 'ChannelNumber', 762 '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 12' => 'ClosedCaptioning', 763 '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 13' => 'Rerun', 764 '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 14' => 'SAP', 765 '{4684FE97-8765-4842-9C13-F006447B178C} 100' => 'BroadcastDate', 766 '{A5477F61-7A82-4ECA-9DDE-98B69B2479B3} 100' => 'RecordingTime', 767 '{6D748DE2-8D38-4CC3-AC60-F009B057C557} 5' => 'StationCallSign', 768 '{1B5439E7-EBA1-4AF8-BDD7-7AF1D4549493} 100' => 'StationName', 769 '{560C36C0-503A-11CF-BAA1-00004C752A9A} 2' => 'AutoSummary', 770 '{560C36C0-503A-11CF-BAA1-00004C752A9A} 3' => 'Summary', 771 '{49691C90-7E17-101A-A91C-08002B2ECDA9} 3' => 'SearchRanking', 772 '{F8D3F6AC-4874-42CB-BE59-AB454B30716A} 100' => 'Sensitivity', 773 '{EF884C5B-2BFE-41BB-AAE5-76EEDF4F9902} 200' => 'SharedWith', 774 '{668CDFA5-7A1B-4323-AE4B-E527393A1D81} 100' => 'Source', 775 '{48FD6EC8-8A12-4CDF-A03E-4EC5A511EDDE} 100' => 'StartDate', 776 '{D37D52C6-261C-4303-82B3-08B926AC6F12} 100' => 'BillingInformation', 777 '{084D8A0A-E6D5-40DE-BF1F-C8820E7C877C} 100' => 'Complete', 778 '{08C7CC5F-60F2-4494-AD75-55E3E0B5ADD0} 100' => 'TaskOwner', 779 '{28636AA6-953D-11D2-B5D6-00C04FD918D0} 14' => 'TotalFileSize', 780 '{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 9' => 'LegalTrademarks', 781 '{64440491-4C8B-11D1-8B70-080036B11A03} 10' => 'VideoCompression', 782 '{64440492-4C8B-11D1-8B70-080036B11A03} 20' => 'Directors', 783 '{64440491-4C8B-11D1-8B70-080036B11A03} 8' => 'DataRate', 784 '{64440491-4C8B-11D1-8B70-080036B11A03} 4' => 'FrameHeight', 785 '{64440491-4C8B-11D1-8B70-080036B11A03} 6' => 'FrameRate', 786 '{64440491-4C8B-11D1-8B70-080036B11A03} 3' => 'FrameWidth', 787 '{64440491-4C8B-11D1-8B70-080036B11A03} 43' => 'TotalBitrate', 788); 789 790#------------------------------------------------------------------------------ 791# check new value for Xtra tag 792# Inputs: 0) ExifTool object ref, 1) tagInfo hash ref, 2) raw value ref 793# Returns: error string, or undef on success 794sub CheckXtra($$$) 795{ 796 my ($et, $tagInfo, $valPt) = @_; 797 my $format = $$tagInfo{Writable}; 798 return 'Unknown format' unless $format; 799 if ($format =~ /^int/) { 800 return 'Not an integer' unless Image::ExifTool::IsInt($$valPt); 801 } elsif ($format ne 'Unicode') { 802 my @vals = ($$valPt); 803 return 'Invalid format' unless WriteXtraValue($et, $tagInfo, \@vals); 804 } 805 return undef; 806} 807 808#------------------------------------------------------------------------------ 809# Decode value(s) in Microsoft Xtra tag 810# Inputs: 0) ExifTool object ref, 1) value data 811# Returns: Scalar context: decoded value, List context: 0) decoded value, 1) format string 812sub ReadXtraValue($$) 813{ 814 my ($et, $data) = @_; 815 my ($format, $i, @vals); 816 817 return undef if length($data) < 10; 818 819 # (version flags according to the reference, but looks more like a count - PH) 820 my $count = Get32u(\$data, 0); 821 # point to start of first value (after 4-byte count, 4-byte length and 2-byte type) 822 my $valPos = 10; 823 for ($i=0; ;) { 824 # (stored value includes size of $valLen and $valType, so subtract 6) 825 my $valLen = Get32u(\$data, $valPos - 6) - 6; 826 last if $valPos + $valLen > length($data); 827 my $valType = Get16u(\$data, $valPos - 2); 828 my $val = substr($data, $valPos, $valLen); 829 # Note: all dumb Microsoft values are little-endian inside a big-endian-format file 830 SetByteOrder('II'); 831 if ($valType == 8) { 832 $format = 'Unicode'; 833 $val = $et->Decode($val, 'UCS2'); 834 } elsif ($valType == 19 and $valLen == 8) { 835 $format = 'int64u'; 836 $val = Get64u(\$val, 0); 837 } elsif ($valType == 21 and $valLen == 8) { 838 $format = 'date'; 839 $val = Get64u(\$val, 0); 840 # convert time from 100 ns intervals since Jan 1, 1601 841 $val = $val * 1e-7 - 11644473600 if $val; 842 # (the Nikon S100 uses UTC timezone, same as ASF - PH) 843 $val = Image::ExifTool::ConvertUnixTime($val, 1); 844 } elsif ($valType == 72 and $valLen == 16) { 845 $format = 'GUID'; 846 $val = uc unpack('H*',pack('NnnNN',unpack('VvvNN',$val))); 847 $val =~ s/(.{8})(.{4})(.{4})(.{4})/$1-$2-$3-$4-/; 848 } elsif ($valType == 65 and $valLen > 4) { #PH (empirical) 849 $format = 'variant'; 850 require Image::ExifTool::FlashPix; 851 my $vPos = 0; # (necessary because ReadFPXValue updates this) 852 # read entry as a VT_VARIANT (use FlashPix module for this) 853 $val = Image::ExifTool::FlashPix::ReadFPXValue($et, \$val, $vPos, 854 Image::ExifTool::FlashPix::VT_VARIANT(), $valLen, 1); 855 } else { 856 $format = "Unknown($valType)"; 857 } 858 SetByteOrder('MM'); # back to native QuickTime byte ordering 859 push @vals, $val; 860 last if ++$i >= $count; 861 $valPos += $valLen + 6; # step to next value 862 last if $valPos > length($data); 863 } 864 return wantarray ? (\@vals, $format) : \@vals; 865} 866 867#------------------------------------------------------------------------------ 868# Write a Microsoft Xtra value 869# Inputs: 0) ExifTool object ref, 1) tagInfo ref, 2) reference to list of values 870# Returns: new value binary data (or empty string) 871sub WriteXtraValue($$$) 872{ 873 my ($et, $tagInfo, $vals) = @_; 874 my $format = $$tagInfo{Writable}; 875 my $buff = ''; 876 my $count = 0; 877 my $val; 878 foreach $val (@$vals) { 879 SetByteOrder('II'); 880 my ($type, $dat); 881 if ($format eq 'Unicode') { 882 $dat = $et->Encode($val,'UCS2','II') . "\0\0"; # (must be null terminated) 883 $type = 8; 884 } elsif ($format eq 'int64u') { 885 if (Image::ExifTool::IsInt($val)) { 886 $dat = Set64u($val); 887 $type = 19; 888 } 889 } elsif ($format eq 'date') { 890 $dat = Image::ExifTool::GetUnixTime($val, 1); # (convert to UTC, NC) 891 if ($dat) { 892 # 100ns intervals since Jan 1, 1601 893 $dat = Set64u(($dat + 11644473600) * 1e7); 894 $type = 21; 895 } 896 } elsif ($format eq 'vt_filetime') { # 'date' value inside a VT_VARIANT 897 $dat = Image::ExifTool::GetUnixTime($val); # (leave as local time, NC) 898 if ($dat) { 899 # 100ns intervals since Jan 1, 1601 900 $dat = Set32u(64) . Set64u(($dat + 11644473600) * 1e7); 901 $type = 65; 902 } 903 } elsif ($format eq 'GUID') { 904 ($dat = $val) =~ tr/-//d; 905 if (length($dat) == 32) { 906 $dat = pack('VvvNN',unpack('NnnNN',pack('H*', $dat))); 907 $type = 72; 908 } 909 } else { 910 $et->WarnOnce("Error converting value for Microsoft:$$tagInfo{Name}"); 911 } 912 SetByteOrder('MM'); 913 if (defined $type) { 914 ++$count; 915 $buff .= Set32u(length($dat)+6) . Set16u($type) . $dat; 916 } 917 } 918 return $count ? Set32u($count) . $buff : ''; 919} 920 921#------------------------------------------------------------------------------ 922# Add new values to list 923# Inputs: 0) ExifTool ref, 1) new value list ref, 2) nvHash ref 924# Returns: true if something was added 925sub AddNewValues($$$) 926{ 927 my ($et, $vals, $nvHash) = @_; 928 my @newVals = $et->GetNewValue($nvHash) or return undef; 929 if ($$et{OPTIONS}{Verbose} > 1) { 930 $et->VPrint(1, " + Microsoft:$$nvHash{TagInfo}{Name} = $_\n") foreach @newVals; 931 } 932 push @$vals, @newVals; 933 return 1; 934} 935 936#------------------------------------------------------------------------------ 937# Write tags to a Microsoft Xtra MP4 atom 938# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref 939# Returns: Microsoft Xtra data block (may be empty if no Xtra data) or undef on error 940sub WriteXtra($$$) 941{ 942 my ($et, $dirInfo, $tagTablePtr) = @_; 943 $et or return 1; # allow dummy access 944 945 my $delGroup = ($$et{DEL_GROUP} and $$et{DEL_GROUP}{Microsoft}); 946 my $newTags = $et->GetNewTagInfoHash($tagTablePtr); 947 948 return undef unless $delGroup or %$newTags; # don't rewrite if nothing to do 949 950 my $dataPt = $$dirInfo{DataPt}; 951 my $dataLen = length $$dataPt; 952 my $newData = ''; 953 my $pos = 0; 954 my ($err, %done, $changed, $tag); 955 956 if ($delGroup) { 957 $changed = 1 if $dataLen; 958 my $empty = ''; 959 $dataPt = $empty; 960 $dataLen = 0; 961 } 962 for (;;) { 963 last if $pos + 4 > $dataLen; 964 my $size = Get32u($dataPt, $pos); # (includes $size word) 965 ($size < 8 or $pos + $size > $dataLen) and $err=1, last; 966 my $tagLen = Get32u($dataPt, $pos + 4); 967 $tagLen + 18 > $size and $err=1, last; 968 $tag = substr($$dataPt, $pos + 8, $tagLen); 969 my @newVals; 970 while ($$newTags{$tag}) { 971 my $nvHash = $et->GetNewValueHash($$newTags{$tag}); 972 $$nvHash{CreateOnly} and delete($$newTags{$tag}), last; # don't edit this tag 973 my $valPos = $pos + 8 + $tagLen; 974 my $valLen = $size - 8 - $tagLen; 975 my $val = ReadXtraValue($et, substr($$dataPt, $valPos, $valLen)); 976 foreach $val (@$val) { 977 my $overwrite = $et->IsOverwriting($nvHash, $val); 978 $overwrite or push(@newVals, $val), next; 979 $et->VPrint(1, " - Microsoft:$$newTags{$tag}{Name} = $val\n"); 980 next if $done{$tag}; 981 $done{$tag} = 1; 982 AddNewValues($et, \@newVals, $nvHash); 983 } 984 # add to the end of the list if this was a List-type tag and we didn't delete anything 985 if (not $done{$tag} and $$newTags{$tag}{List}) { 986 AddNewValues($et, \@newVals, $nvHash) or last; 987 $done{$tag} = 1; 988 } 989 last; # (it was a cheap goto) 990 } 991 if ($done{$tag}) { 992 $changed = 1; 993 # write changed values 994 my $buff = WriteXtraValue($et, $$newTags{$tag}, \@newVals); 995 if (length $buff) { 996 $newData .= Set32u(8+length($tag)+length($buff)) . Set32u(length($tag)) . $tag . $buff; 997 } 998 } else { 999 # nothing changed; just copy over 1000 $newData .= substr($$dataPt, $pos, $size); 1001 } 1002 $pos += $size; # step to next entry 1003 } 1004 if ($err) { 1005 $et->Warn('Microsoft Xtra format error'); 1006 return undef; 1007 } 1008 # add any new tags 1009 foreach $tag (sort keys %$newTags) { 1010 next if $done{$tag}; 1011 my $nvHash = $et->GetNewValueHash($$newTags{$tag}); 1012 next unless $$nvHash{IsCreating} and not $$nvHash{EditOnly}; 1013 my @newVals; 1014 AddNewValues($et, \@newVals, $nvHash) or next; 1015 my $buff = WriteXtraValue($et, $$newTags{$tag}, \@newVals); 1016 if (length $buff) { 1017 $newData .= Set32u(8+length($tag)+length($buff)) . Set32u(length($tag)) . $tag . $buff; 1018 $changed = 1; 1019 } 1020 } 1021 if ($changed) { 1022 ++$$et{CHANGED}; 1023 } else { 1024 undef $newData; 1025 } 1026 return $newData; 1027} 1028 1029#------------------------------------------------------------------------------ 1030# Extract information from Xtra MP4 atom 1031# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref 1032# Returns: 1 on success 1033# Reference: http://code.google.com/p/mp4v2/ [since removed from trunk] 1034sub ProcessXtra($$$) 1035{ 1036 my ($et, $dirInfo, $tagTablePtr) = @_; 1037 my $dataPt = $$dirInfo{DataPt}; 1038 my $dataPos = $$dirInfo{Base} || 0; 1039 my $dataLen = $$dirInfo{DataLen}; 1040 my $pos = 0; 1041 $et->VerboseDir('Xtra', 0, $dataLen); 1042 for (;;) { 1043 last if $pos + 4 > $dataLen; 1044 my $size = Get32u($dataPt, $pos); # (includes $size word) 1045 last if $size < 8 or $pos + $size > $dataLen; 1046 my $tagLen = Get32u($dataPt, $pos + 4); 1047 last if $tagLen + 18 > $size; 1048 my $valLen = $size - 8 - $tagLen; 1049 if ($tagLen > 0 and $valLen > 0) { 1050 my $tag = substr($$dataPt, $pos + 8, $tagLen); 1051 my $valPos = $pos + 8 + $tagLen; 1052 my ($val, $format) = ReadXtraValue($et, substr($$dataPt, $valPos, $valLen)); 1053 last unless defined $val; 1054 $val = $$val[0] if @$val == 1; 1055 my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); 1056 unless ($tagInfo) { 1057 # generate tag information for unrecognized tags 1058 my $name = $tag; 1059 $name =~ s{^WM/}{}; 1060 # $name =~ tr/-_A-Za-z0-9//dc; 1061 if ($name =~ /^[-\w]+$/) { 1062 $tagInfo = { Name => ucfirst($name) }; 1063 AddTagToTable($tagTablePtr, $tag, $tagInfo); 1064 $et->VPrint(0, $$et{INDENT}, "[adding Microsoft:$tag]\n"); 1065 } 1066 } 1067 my $count = ref $val ? scalar @$val : 1; 1068 $et->HandleTag($tagTablePtr, $tag, $val, 1069 TagInfo => $tagInfo, 1070 DataPt => $dataPt, 1071 DataPos => $dataPos, 1072 Start => $valPos, 1073 Size => $valLen, 1074 Format => $format, 1075 Extra => " count=$count", 1076 ); 1077 } 1078 $pos += $size; # step to next entry 1079 } 1080 return 1; 1081} 1082 10831; # end 1084 1085__END__ 1086 1087=head1 NAME 1088 1089Image::ExifTool::Microsoft - Definitions for custom Microsoft tags 1090 1091=head1 SYNOPSIS 1092 1093This module is used by Image::ExifTool 1094 1095=head1 DESCRIPTION 1096 1097This module contains definitions required by Image::ExifTool to interpret 1098Microsoft-specific EXIF and XMP tags, and routines to read/write Microsoft 1099Xtra tags in videos. 1100 1101=head1 AUTHOR 1102 1103Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) 1104 1105This library is free software; you can redistribute it and/or modify it 1106under the same terms as Perl itself. 1107 1108=head1 REFERENCES 1109 1110=over 4 1111 1112=item L<http://research.microsoft.com/en-us/um/redmond/groups/ivm/hdview/hdmetadataspec.htm> 1113 1114=back 1115 1116=head1 SEE ALSO 1117 1118L<Image::ExifTool::TagNames/Microsoft Tags>, 1119L<Image::ExifTool(3pm)|Image::ExifTool> 1120 1121=cut 1122 1123