File Coverage

blib/lib/Image/ExifTool/MPF.pm
Criterion Covered Total %
statement 45 52 86.5
branch 11 16 68.7
condition 7 12 58.3
subroutine 6 6 100.0
pod 0 2 0.0
total 69 88 78.4


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             # File: MPF.pm
3             #
4             # Description: Read Multi-Picture Format information
5             #
6             # Revisions: 06/12/2009 - P. Harvey Created
7             #
8             # References: 1) http://www.cipa.jp/std/documents/e/DC-007_E.pdf
9             #------------------------------------------------------------------------------
10              
11             package Image::ExifTool::MPF;
12              
13 4     4   41 use strict;
  4         12  
  4         174  
14 4     4   24 use vars qw($VERSION);
  4         13  
  4         226  
15 4     4   41 use Image::ExifTool qw(:DataAccess :Utils);
  4         18  
  4         953  
16 4     4   39 use Image::ExifTool::Exif;
  4         8  
  4         3572  
17              
18             $VERSION = '1.14';
19              
20             sub ProcessMPImageList($$$);
21              
22             # Tags found in APP2 MPF segment in JPEG images
23             %Image::ExifTool::MPF::Main = (
24             GROUPS => { 0 => 'MPF', 1 => 'MPF0', 2 => 'Image'},
25             NOTES => q{
26             These tags are part of the CIPA Multi-Picture Format specification, and are
27             found in the APP2 "MPF" segment of JPEG images. MPImage data referenced
28             from this segment is stored as a JPEG trailer. The MPF tags are not
29             writable, however the MPF segment may be deleted as a group (with "MPF:All")
30             but then the JPEG trailer should also be deleted (with "Trailer:All"). See
31             L
32             for the official specification.
33             },
34             0xb000 => 'MPFVersion',
35             0xb001 => 'NumberOfImages',
36             0xb002 => {
37             Name => 'MPImageList',
38             SubDirectory => {
39             TagTable => 'Image::ExifTool::MPF::MPImage',
40             ProcessProc => \&ProcessMPImageList,
41             },
42             },
43             0xb003 => {
44             Name => 'ImageUIDList',
45             Binary => 1,
46             },
47             0xb004 => 'TotalFrames',
48             0xb101 => 'MPIndividualNum',
49             0xb201 => {
50             Name => 'PanOrientation',
51             PrintHex => 1,
52             Notes => 'long integer is split into 4 bytes',
53             ValueConv => 'join(" ",unpack("C*",pack("N",$val)))',
54             PrintConv => [
55             '"$val rows"',
56             '"$val columns"',
57             {
58             0 => '[unused]',
59             1 => 'Start at top right',
60             2 => 'Start at top left',
61             3 => 'Start at bottom left',
62             4 => 'Start at bottom right',
63             },
64             {
65             0x01 => 'Left to right',
66             0x02 => 'Right to left',
67             0x03 => 'Top to bottom',
68             0x04 => 'Bottom to top',
69             0x10 => 'Clockwise',
70             0x20 => 'Counter clockwise',
71             0x30 => 'Zigzag (row start)',
72             0x40 => 'Zigzag (column start)',
73             },
74             ],
75             },
76             0xb202 => 'PanOverlapH',
77             0xb203 => 'PanOverlapV',
78             0xb204 => 'BaseViewpointNum',
79             0xb205 => 'ConvergenceAngle',
80             0xb206 => 'BaselineLength',
81             0xb207 => 'VerticalDivergence',
82             0xb208 => 'AxisDistanceX',
83             0xb209 => 'AxisDistanceY',
84             0xb20a => 'AxisDistanceZ',
85             0xb20b => 'YawAngle',
86             0xb20c => 'PitchAngle',
87             0xb20d => 'RollAngle',
88             );
89              
90             # Tags found in MPImage structure
91             %Image::ExifTool::MPF::MPImage = (
92             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
93             #WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
94             #CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
95             #WRITABLE => 1,
96             GROUPS => { 0 => 'MPF', 1 => 'MPImage', 2 => 'Image'},
97             NOTES => q{
98             The first MPF "Large Thumbnail" image is extracted as PreviewImage, and the
99             rest of the embedded MPF images are extracted as MPImage#. The
100             L (-ee) option may be used to extract information from these
101             embedded images.
102             },
103             0.1 => {
104             Name => 'MPImageFlags',
105             Format => 'int32u',
106             Mask => 0xf8000000,
107             PrintConv => { BITMASK => {
108             2 => 'Representative image',
109             3 => 'Dependent child image',
110             4 => 'Dependent parent image',
111             }},
112             },
113             0.2 => {
114             Name => 'MPImageFormat',
115             Format => 'int32u',
116             Mask => 0x07000000,
117             PrintConv => {
118             0 => 'JPEG',
119             },
120             },
121             0.3 => {
122             Name => 'MPImageType',
123             Format => 'int32u',
124             Mask => 0x00ffffff,
125             PrintHex => 1,
126             PrintConv => {
127             0x000000 => 'Undefined',
128             0x010001 => 'Large Thumbnail (VGA equivalent)',
129             0x010002 => 'Large Thumbnail (full HD equivalent)',
130             0x020001 => 'Multi-frame Panorama',
131             0x020002 => 'Multi-frame Disparity',
132             0x020003 => 'Multi-angle',
133             0x030000 => 'Baseline MP Primary Image',
134             },
135             },
136             4 => {
137             Name => 'MPImageLength',
138             Format => 'int32u',
139             },
140             8 => {
141             Name => 'MPImageStart',
142             Format => 'int32u',
143             IsOffset => '$val',
144             },
145             12 => {
146             Name => 'DependentImage1EntryNumber',
147             Format => 'int16u',
148             },
149             14 => {
150             Name => 'DependentImage2EntryNumber',
151             Format => 'int16u',
152             },
153             );
154              
155             # extract MP Images as composite tags
156             %Image::ExifTool::MPF::Composite = (
157             GROUPS => { 2 => 'Preview' },
158             MPImage => {
159             Require => {
160             0 => 'MPImageStart',
161             1 => 'MPImageLength',
162             2 => 'MPImageType',
163             },
164             Notes => q{
165             the first MPF "Large Thumbnail" is extracted as PreviewImage, and the rest
166             of the embedded MPF images are extracted as MPImage#. The L
167             option may be used to extract information from these embedded images.
168             },
169             # extract all MPF images (not just one)
170             RawConv => q{
171             require Image::ExifTool::MPF;
172             @grps = $self->GetGroup($$val{0}); # set groups from input tag
173             Image::ExifTool::MPF::ExtractMPImages($self);
174             },
175             },
176             );
177              
178             # add our composite tags
179             Image::ExifTool::AddCompositeTags('Image::ExifTool::MPF');
180              
181             #------------------------------------------------------------------------------
182             # Extract all MP images
183             # Inputs: 0) ExifTool object ref
184             # Returns: undef
185             sub ExtractMPImages($)
186             {
187 19     19 0 62 my $et = shift;
188 19         88 my $ee = $et->Options('ExtractEmbedded');
189 19         94 my $saveBinary = $et->Options('Binary');
190 19         65 my ($i, $didPreview, $xtra);
191              
192 19   100     163 for ($i=1; $xtra or not defined $xtra; ++$i) {
193             # run through MP images in the same order they were extracted
194 38 100       226 $xtra = defined $$et{VALUE}{"MPImageStart ($i)"} ? " ($i)" : '';
195 38         193 my $off = $et->GetValue("MPImageStart$xtra", 'ValueConv');
196 38         163 my $len = $et->GetValue("MPImageLength$xtra", 'ValueConv');
197 38 100 66     249 if ($off and $len) {
198 19         119 my $type = $et->GetValue("MPImageType$xtra", 'ValueConv');
199 19         92 my $tag = "MPImage$i";
200             # store first "Large Thumbnail" as a PreviewImage
201 19 50 33     183 if (not $didPreview and $type and ($type & 0x0f0000) == 0x010000) {
      33        
202 19         49 $tag = 'PreviewImage';
203 19         66 $didPreview = 1;
204             }
205 19 50       68 $et->Options('Binary', 1) if $ee;
206 19         87 my $val = Image::ExifTool::Exif::ExtractImage($et, $off, $len, $tag);
207 19 50       111 $et->Options('Binary', $saveBinary) if $ee;
208 19 100       85 next unless defined $val;
209 14 50       86 unless ($Image::ExifTool::Extra{$tag}) {
210 0         0 AddTagToTable(\%Image::ExifTool::Extra, $tag, {
211             Name => $tag,
212             Groups => { 0 => 'Composite', 1 => 'Composite', 2 => 'Preview'},
213             });
214             }
215 14         81 my $key = $et->FoundTag($tag, $val, $et->GetGroup("MPImageStart$xtra"));
216             # extract information from MP images if ExtractEmbedded option used
217 14 50       124 if ($ee) {
218 0         0 my $oldBase = $$et{BASE};
219 0         0 $$et{BASE} = $off;
220 0         0 $$et{DOC_NUM} = $i;
221 0         0 $et->ExtractInfo($val, { ReEntry => 1 });
222 0         0 delete $$et{DOC_NUM};
223 0         0 $$et{BASE} = $oldBase;
224             }
225             }
226             }
227 19         216 return undef;
228             }
229              
230             #------------------------------------------------------------------------------
231             # Process MP Entry list
232             # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
233             # Returns: 1 on success
234             sub ProcessMPImageList($$$)
235             {
236 19     19 0 80 my ($et, $dirInfo, $tagTablePtr) = @_;
237 19         74 my $num = int($$dirInfo{DirLen} / 16); # (16 bytes per MP Entry)
238 19         54 $$dirInfo{DirLen} = 16;
239 19         43 my ($i, $success);
240 19         53 my $oldG1 = $$et{SET_GROUP1};
241 19         87 for ($i=0; $i<$num; ++$i) {
242 38         146 $$et{SET_GROUP1} = '+' . ($i + 1);
243 38         180 $success = $et->ProcessBinaryData($dirInfo, $tagTablePtr);
244 38         222 $$dirInfo{DirStart} += 16;
245             }
246 19         91 $$et{SET_GROUP1} = $oldG1;
247 19         68 return $success;
248             }
249              
250             1; # end
251              
252             __END__