<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#------------------------------------------------------------------------------
# File:         MPF.pm
#
# Description:  Read Multi-Picture Format information
#
# Revisions:    06/12/2009 - P. Harvey Created
#
# References:   1) http://www.cipa.jp/std/documents/e/DC-007_E.pdf
#------------------------------------------------------------------------------

package Image::ExifTool::MPF;

use strict;
use vars qw($VERSION);
use Image::ExifTool qw(:DataAccess :Utils);
use Image::ExifTool::Exif;

$VERSION = '1.09';

sub ProcessMPImageList($$$);

# Tags found in MPF APP2 segment in JPEG images
%Image::ExifTool::MPF::Main = (
    GROUPS =&gt; { 0 =&gt; 'MPF', 1 =&gt; 'MPF0', 2 =&gt; 'Image'},
    NOTES =&gt; q{
        These tags are part of the CIPA Multi-Picture Format specification, and are
        found in the APP2 "MPF" segment of JPEG images.  MPImage data referenced
        from this segment is stored as a JPEG trailer.  The MPF tags are not
        writable, however the MPG segment may be deleted as a group (with "MPF:All")
        but then the JPEG trailer should also be deleted (with "Trailer:All").  See
        L&lt;http://www.cipa.jp/std/documents/e/DC-007_E.pdf&gt; for the official
        specification.
    },
    0xb000 =&gt; 'MPFVersion',
    0xb001 =&gt; 'NumberOfImages',
    0xb002 =&gt; {
        Name =&gt; 'MPImageList',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::MPF::MPImage',
            ProcessProc =&gt; \&amp;ProcessMPImageList,
        },
    },
    0xb003 =&gt; {
        Name =&gt; 'ImageUIDList',
        Binary =&gt; 1,
    },
    0xb004 =&gt; 'TotalFrames',
    0xb101 =&gt; 'MPIndividualNum',
    0xb201 =&gt; {
        Name =&gt; 'PanOrientation',
        PrintHex =&gt; 1,
        Notes =&gt; 'long integer is split into 4 bytes',
        ValueConv =&gt; 'join(" ",unpack("C*",pack("N",$val)))',
        PrintConv =&gt; [
            '"$val rows"',
            '"$val columns"',
            {
                0 =&gt; '[unused]',
                1 =&gt; 'Start at top right',
                2 =&gt; 'Start at top left',
                3 =&gt; 'Start at bottom left',
                4 =&gt; 'Start at bottom right',
            },
            {
                0x01 =&gt; 'Left to right',
                0x02 =&gt; 'Right to left',
                0x03 =&gt; 'Top to bottom',
                0x04 =&gt; 'Bottom to top',
                0x10 =&gt; 'Clockwise',
                0x20 =&gt; 'Counter clockwise',
                0x30 =&gt; 'Zigzag (row start)',
                0x40 =&gt; 'Zigzag (column start)',
            },
        ],
    },          
    0xb202 =&gt; 'PanOverlapH',
    0xb203 =&gt; 'PanOverlapV',
    0xb204 =&gt; 'BaseViewpointNum',
    0xb205 =&gt; 'ConvergenceAngle',
    0xb206 =&gt; 'BaselineLength',
    0xb207 =&gt; 'VerticalDivergence',
    0xb208 =&gt; 'AxisDistanceX',
    0xb209 =&gt; 'AxisDistanceY',
    0xb20a =&gt; 'AxisDistanceZ',
    0xb20b =&gt; 'YawAngle',
    0xb20c =&gt; 'PitchAngle',
    0xb20d =&gt; 'RollAngle',
);

# Tags found in MPImage structure
%Image::ExifTool::MPF::MPImage = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    #WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    #CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    #WRITABLE =&gt; 1,
    GROUPS =&gt; { 0 =&gt; 'MPF', 1 =&gt; 'MPImage', 2 =&gt; 'Image'},
    NOTES =&gt; q{
        The first MPF "Large Thumbnail" image is extracted as PreviewImage, and the
        rest of the embedded MPF images are extracted as MPImage#.  The
        ExtractEmbedded (-ee) option may be used to extract information from these
        embedded images.
    },
    0.1 =&gt; {
        Name =&gt; 'MPImageFlags',
        Format =&gt; 'int32u',
        Mask =&gt; 0xf8000000,
        PrintConv =&gt; { BITMASK =&gt; {
            29 =&gt; 'Representative image',
            30 =&gt; 'Dependent child image',
            31 =&gt; 'Dependent parent image',
        }},
    },
    0.2 =&gt; {
        Name =&gt; 'MPImageFormat',
        Format =&gt; 'int32u',
        Mask =&gt; 0x07000000,
        PrintConv =&gt; {
            0 =&gt; 'JPEG',
        },
    },
    0.3 =&gt; {
        Name =&gt; 'MPImageType',
        Format =&gt; 'int32u',
        Mask =&gt; 0x00ffffff,
        PrintHex =&gt; 1,
        PrintConv =&gt; {
            0x000000 =&gt; 'Undefined',
            0x010001 =&gt; 'Large Thumbnail (VGA equivalent)',
            0x010002 =&gt; 'Large Thumbnail (full HD equivalent)',
            0x020001 =&gt; 'Multi-frame Panorama',
            0x020002 =&gt; 'Multi-frame Disparity',
            0x020003 =&gt; 'Multi-angle',
            0x030000 =&gt; 'Baseline MP Primary Image',
        },
    },
    4 =&gt; {
        Name =&gt; 'MPImageLength',
        Format =&gt; 'int32u',
    },
    8 =&gt; {
        Name =&gt; 'MPImageStart',
        Format =&gt; 'int32u',
        IsOffset =&gt; '$val',
    },
    12 =&gt; {
        Name =&gt; 'DependentImage1EntryNumber',
        Format =&gt; 'int16u',
    },
    14 =&gt; {
        Name =&gt; 'DependentImage2EntryNumber',
        Format =&gt; 'int16u',
    },
);

# extract MP Images as composite tags
%Image::ExifTool::MPF::Composite = (
    GROUPS =&gt; { 2 =&gt; 'Image' },
    MPImage =&gt; {
        Require =&gt; {
            0 =&gt; 'MPImageStart',
            1 =&gt; 'MPImageLength',
            2 =&gt; 'MPImageType',
        },
        Notes =&gt; q{
            the first MPF "Large Thumbnail" is extracted as PreviewImage, and the rest
            of the embedded MPF images are extracted as MPImage#.  The ExtractEmbedded
            option may be used to extract information from these embedded images.
        },
        # extract all MPF images (not just one)
        RawConv =&gt; q{
            require Image::ExifTool::MPF;
            Image::ExifTool::MPF::ExtractMPImages($self);
        },
    },
);

# add our composite tags
Image::ExifTool::AddCompositeTags('Image::ExifTool::MPF');

#------------------------------------------------------------------------------
# Extract all MP images
# Inputs: 0) ExifTool object ref
# Returns: undef
sub ExtractMPImages($)
{
    my $et = shift;
    my $ee = $et-&gt;Options('ExtractEmbedded');
    my $saveBinary = $et-&gt;Options('Binary');
    my ($i, $didPreview, $xtra);

    for ($i=1; $xtra or not defined $xtra; ++$i) {
        # run through MP images in the same order they were extracted
        $xtra = defined $$et{VALUE}{"MPImageStart ($i)"} ? " ($i)" : '';
        my $off = $et-&gt;GetValue("MPImageStart$xtra");
        my $len = $et-&gt;GetValue("MPImageLength$xtra");
        if ($off and $len) {
            my $type = $et-&gt;GetValue("MPImageType$xtra", 'ValueConv');
            my $tag = "MPImage$i";
            # store first "Large Thumbnail" as a PreviewImage
            if (not $didPreview and $type and ($type &amp; 0x0f0000) == 0x010000) {
                $tag = 'PreviewImage';
                $didPreview = 1;
            }
            $et-&gt;Options('Binary', 1) if $ee;
            my $val = Image::ExifTool::Exif::ExtractImage($et, $off, $len, $tag);
            $et-&gt;Options('Binary', $saveBinary) if $ee;
            next unless defined $val;
            unless ($Image::ExifTool::Extra{$tag}) {
                AddTagToTable(\%Image::ExifTool::Extra, $tag, {
                    Name =&gt; $tag,
                    Groups =&gt; { 0 =&gt; 'Composite', 1 =&gt; 'Composite', 2 =&gt; 'Image'},
                });
            }
            my $key = $et-&gt;FoundTag($tag, $val);
            # set groups for PreviewImage
            if ($tag eq 'PreviewImage') {
                $et-&gt;SetGroup($key, 'Composite', 0);
                $et-&gt;SetGroup($key, 'Composite');
            }
            # extract information from MP images if ExtractEmbedded option used
            if ($ee) {
                my $oldBase = $$et{BASE};
                $$et{BASE} = $off;
                $$et{DOC_NUM} = $i;
                $et-&gt;ExtractInfo($val, { ReEntry =&gt; 1 });
                delete $$et{DOC_NUM};
                $$et{BASE} = $oldBase;
            }
        }
    }
    return undef;
}

#------------------------------------------------------------------------------
# Process MP Entry list
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
# Returns: 1 on success
sub ProcessMPImageList($$$)
{
    my ($et, $dirInfo, $tagTablePtr) = @_;
    my $num = int($$dirInfo{DirLen} / 16); # (16 bytes per MP Entry)
    $$dirInfo{DirLen} = 16;
    my ($i, $success);
    my $oldG1 = $$et{SET_GROUP1};
    for ($i=0; $i&lt;$num; ++$i) {
        $$et{SET_GROUP1} = '+' . ($i + 1);
        $success = $et-&gt;ProcessBinaryData($dirInfo, $tagTablePtr);
        $$dirInfo{DirStart} += 16;
    }
    $$et{SET_GROUP1} = $oldG1;
    return $success;
}

1;  # end

__END__

=head1 NAME

Image::ExifTool::MPF - Read Multi-Picture Format information

=head1 SYNOPSIS

This module is used by Image::ExifTool

=head1 DESCRIPTION

This module contains tag definitions and routines to read Multi-Picture
Format (MPF) information from JPEG images.

=head1 AUTHOR

Copyright 2003-2015, Phil Harvey (phil at owl.phy.queensu.ca)

This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 REFERENCES

=over 4

=item L&lt;http://www.cipa.jp/std/documents/e/DC-007_E.pdf&gt;

=back

=head1 SEE ALSO

L&lt;Image::ExifTool::TagNames/MPF Tags&gt;,
L&lt;Image::ExifTool(3pm)|Image::ExifTool&gt;

=cut

</pre></body></html>