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   29 use strict;
  4         9  
  4         204  
14 4     4   23 use vars qw($VERSION);
  4         9  
  4         231  
15 4     4   19 use Image::ExifTool qw(:DataAccess :Utils);
  4         9  
  4         1055  
16 4     4   26 use Image::ExifTool::Exif;
  4         7  
  4         3669  
17              
18             $VERSION = '1.16';
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             0x010003 => 'Large Thumbnail (4K equivalent)',
131             0x010004 => 'Large Thumbnail (8K equivalent)',
132             0x010005 => 'Large Thumbnail (16K equivalent)',
133             0x020001 => 'Multi-frame Panorama',
134             0x020002 => 'Multi-frame Disparity',
135             0x020003 => 'Multi-angle',
136             0x030000 => 'Baseline MP Primary Image',
137             0x040000 => 'Original Preservation Image', # (Exif 3.0)
138             0x050000 => 'Gain Map Image',
139             },
140             },
141             4 => {
142             Name => 'MPImageLength',
143             Format => 'int32u',
144             },
145             8 => {
146             Name => 'MPImageStart',
147             Format => 'int32u',
148             IsOffset => '$val',
149             },
150             12 => {
151             Name => 'DependentImage1EntryNumber',
152             Format => 'int16u',
153             },
154             14 => {
155             Name => 'DependentImage2EntryNumber',
156             Format => 'int16u',
157             },
158             );
159              
160             # extract MP Images as composite tags
161             %Image::ExifTool::MPF::Composite = (
162             GROUPS => { 2 => 'Preview' },
163             MPImage => {
164             Require => {
165             0 => 'MPImageStart',
166             1 => 'MPImageLength',
167             2 => 'MPImageType',
168             },
169             Notes => q{
170             the first MPF "Large Thumbnail" is extracted as PreviewImage, and the rest
171             of the embedded MPF images are extracted as MPImage#. The L
172             option may be used to extract information from these embedded images.
173             },
174             # extract all MPF images (not just one)
175             RawConv => q{
176             require Image::ExifTool::MPF;
177             @grps = $self->GetGroup($$val{0}); # set groups from input tag
178             Image::ExifTool::MPF::ExtractMPImages($self);
179             },
180             },
181             );
182              
183             # add our composite tags
184             Image::ExifTool::AddCompositeTags('Image::ExifTool::MPF');
185              
186             #------------------------------------------------------------------------------
187             # Extract all MP images
188             # Inputs: 0) ExifTool object ref
189             # Returns: undef
190             sub ExtractMPImages($)
191             {
192 19     19 0 61 my $et = shift;
193 19         96 my $ee = $et->Options('ExtractEmbedded');
194 19         64 my $saveBinary = $et->Options('Binary');
195 19         50 my ($i, $didPreview, $xtra);
196              
197 19   100     161 for ($i=1; $xtra or not defined $xtra; ++$i) {
198             # run through MP images in the same order they were extracted
199 38 100       209 $xtra = defined $$et{VALUE}{"MPImageStart ($i)"} ? " ($i)" : '';
200 38         220 my $off = $et->GetValue("MPImageStart$xtra", 'ValueConv');
201 38         160 my $len = $et->GetValue("MPImageLength$xtra", 'ValueConv');
202 38 100 66     217 if ($off and $len) {
203 19         83 my $type = $et->GetValue("MPImageType$xtra", 'ValueConv');
204 19         64 my $tag = "MPImage$i";
205             # store first "Large Thumbnail" as a PreviewImage
206 19 50 33     199 if (not $didPreview and $type and ($type & 0x0f0000) == 0x010000) {
      33        
207 19         42 $tag = 'PreviewImage';
208 19         40 $didPreview = 1;
209             }
210 19 50       52 $et->Options('Binary', 1) if $ee;
211 19         123 my $val = Image::ExifTool::Exif::ExtractImage($et, $off, $len, $tag);
212 19 50       58 $et->Options('Binary', $saveBinary) if $ee;
213 19 100       75 next unless defined $val;
214 14 50       75 unless ($Image::ExifTool::Extra{$tag}) {
215 0         0 AddTagToTable(\%Image::ExifTool::Extra, $tag, {
216             Name => $tag,
217             Groups => { 0 => 'Composite', 1 => 'Composite', 2 => 'Preview'},
218             });
219             }
220 14         90 my $key = $et->FoundTag($tag, $val, $et->GetGroup("MPImageStart$xtra"));
221             # extract information from MP images if ExtractEmbedded option used
222 14 50       124 if ($ee) {
223 0         0 my $oldBase = $$et{BASE};
224 0         0 $$et{BASE} = $off;
225 0         0 $$et{DOC_NUM} = $i;
226 0         0 $et->ExtractInfo($val, { ReEntry => 1 });
227 0         0 delete $$et{DOC_NUM};
228 0         0 $$et{BASE} = $oldBase;
229             }
230             }
231             }
232 19         248 return undef;
233             }
234              
235             #------------------------------------------------------------------------------
236             # Process MP Entry list
237             # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
238             # Returns: 1 on success
239             sub ProcessMPImageList($$$)
240             {
241 19     19 0 58 my ($et, $dirInfo, $tagTablePtr) = @_;
242 19         103 my $num = int($$dirInfo{DirLen} / 16); # (16 bytes per MP Entry)
243 19         64 $$dirInfo{DirLen} = 16;
244 19         62 my ($i, $success);
245 19         51 my $oldG1 = $$et{SET_GROUP1};
246 19         80 for ($i=0; $i<$num; ++$i) {
247 38         142 $$et{SET_GROUP1} = '+' . ($i + 1);
248 38         193 $success = $et->ProcessBinaryData($dirInfo, $tagTablePtr);
249 38         179 $$dirInfo{DirStart} += 16;
250             }
251 19         55 $$et{SET_GROUP1} = $oldG1;
252 19         63 return $success;
253             }
254              
255             1; # end
256              
257             __END__