File Coverage

blib/lib/Image/ExifTool/Apple.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             # File: Apple.pm
3             #
4             # Description: Apple EXIF maker notes tags
5             #
6             # Revisions: 2013-09-13 - P. Harvey Created
7             #
8             # References: 1) http://www.photoinvestigator.co/blog/the-mystery-of-maker-apple-metadata/
9             #------------------------------------------------------------------------------
10              
11             package Image::ExifTool::Apple;
12              
13 3     3   4390 use strict;
  3         8  
  3         127  
14 3     3   20 use vars qw($VERSION);
  3         10  
  3         131  
15 3     3   1297 use Image::ExifTool::Exif;
  3         12  
  3         207  
16 3     3   1483 use Image::ExifTool::PLIST;
  3         9  
  3         719  
17              
18             $VERSION = '1.07';
19              
20             # Apple iPhone metadata (ref PH)
21             %Image::ExifTool::Apple::Main = (
22             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
23             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
24             WRITABLE => 1,
25             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
26             NOTES => 'Tags extracted from the maker notes of iPhone images.',
27             # 0x0001 - int32s: seen 0,1,2,3,4,9
28             # 0x0002 - binary plist with a single data object of size 512 bytes (iPhone5s)
29             0x0003 => {
30             Name => 'RunTime', # (includes time plugged in, but not when suspended, ref 1)
31             SubDirectory => { TagTable => 'Image::ExifTool::Apple::RunTime' },
32             },
33             # 0x0004 - int32s: normally 1, but 0 for low-light images
34             # 0x0005 - int32s: seen values 113-247, and 100 for blank images
35             # 0x0006 - int32s: seen values 27-258, and 20 for blank images
36             # 0x0007 - int32s: seen 1
37             0x0008 => { #1
38             Name => 'AccelerationVector',
39             Groups => { 2 => 'Camera' },
40             Writable => 'rational64s',
41             Count => 3,
42             # Note: the directions are contrary to the Apple documentation (which have the
43             # signs of all axes reversed -- apparently the Apple geeks aren't very good
44             # with basic physics, and don't understand the concept of acceleration. See
45             # http://nscookbook.com/2013/03/ios-programming-recipe-19-using-core-motion-to-access-gyro-and-accelerometer/
46             # for one of the few correct descriptions of this). Note that this leads to
47             # a left-handed coordinate system for acceleration.
48             Notes => q{
49             XYZ coordinates of the acceleration vector in units of g. As viewed from
50             the front of the phone, positive X is toward the left side, positive Y is
51             toward the bottom, and positive Z points into the face of the phone
52             },
53             },
54             # 0x0009 - int32s: seen 19,275,531,4371
55             0x000a => {
56             Name => 'HDRImageType',
57             Writable => 'int32s',
58             PrintConv => {
59             # 2 => ? (iPad mini 2)
60             3 => 'HDR Image',
61             4 => 'Original Image',
62             },
63             },
64             0x000b => {
65             Name => 'BurstUUID',
66             Writable => 'string',
67             Notes => 'unique ID for all images in a burst',
68             },
69             0x000c => { # ref forum13710 (Neal Krawetz)
70             Name => 'FocusDistanceRange',
71             Writable => 'rational64s',
72             Count => 2,
73             PrintConv => q{
74             my @a = split ' ', $val;
75             sprintf('%.2f - %.2f m', $a[0] <= $a[1] ? @a : reverse @a);
76             },
77             PrintConvInv => '$val =~ s/ - //; $val =~ s/ ?m$//; $val',
78             },
79             # 0x000d - int32s: 0,1,6,20,24,32,40
80             # 0x000e - int32s: 0,1,4,12 (Orientation? 0=landscape? 4=portrait? ref 1)
81             # 0x000f - int32s: 2,3
82             # 0x0010 - int32s: 1
83             0x0011 => { # (if defined, there is a live photo associated with the video, #forum13565)
84             Name => 'MediaGroupUUID', #NealKrawetz private communication
85             # (changed in 12.19 from Name => 'ContentIdentifier', #forum8750)
86             Writable => 'string',
87             },
88             # 0x0014 - int32s: 1,2,3,4,5 (iPhone 6s, iOS 6.1)
89             0x0015 => {
90             Name => 'ImageUniqueID',
91             Writable => 'string',
92             },
93             # 0x0016 - string[29]: "AXZ6pMTOh2L+acSh4Kg630XCScoO\0"
94             0x0017 => { #forum13565 (only valid if MediaGroupUUID exists)
95             Name => 'LivePhotoVideoIndex',
96             Notes => 'divide by RunTimeScale to get time in seconds',
97             },
98             # 0x0017 - int32s: 0,8192
99             # 0x0019 - int32s: 0,2,128
100             # 0x001a - string[6]: "q825s\0"
101             # 0x001f - int32s: 0
102             );
103              
104             # PLIST-format CMTime structure (ref PH)
105             # (CMTime ref https://developer.apple.com/library/ios/documentation/CoreMedia/Reference/CMTime/Reference/reference.html)
106             %Image::ExifTool::Apple::RunTime = (
107             PROCESS_PROC => \&Image::ExifTool::PLIST::ProcessBinaryPLIST,
108             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
109             NOTES => q{
110             This PLIST-format information contains the elements of a CMTime structure
111             representing the amount of time the phone has been running since the last
112             boot, not including standby time.
113             },
114             timescale => { Name => 'RunTimeScale' }, # (seen 1000000000 --> ns)
115             epoch => { Name => 'RunTimeEpoch' }, # (seen 0)
116             value => { Name => 'RunTimeValue' }, # (should divide by RunTimeScale to get seconds)
117             flags => {
118             Name => 'RunTimeFlags',
119             PrintConv => { BITMASK => {
120             0 => 'Valid',
121             1 => 'Has been rounded',
122             2 => 'Positive infinity',
123             3 => 'Negative infinity',
124             4 => 'Indefinite',
125             }},
126             },
127             );
128              
129             # Apple composite tags
130             %Image::ExifTool::Apple::Composite = (
131             GROUPS => { 2 => 'Camera' },
132             RunTimeSincePowerUp => {
133             Require => {
134             0 => 'Apple:RunTimeValue',
135             1 => 'Apple:RunTimeScale',
136             },
137             ValueConv => '$val[1] ? $val[0] / $val[1] : undef',
138             PrintConv => 'ConvertDuration($val)',
139             },
140             );
141              
142             # add our composite tags
143             Image::ExifTool::AddCompositeTags('Image::ExifTool::Apple');
144              
145              
146             1; # end
147              
148             __END__