#------------------------------------------------------------------------------
# File:         acdsee.config
#
# Description:  This config file defines ACDSee XMP region tags for writing.
#               The following tags are created in the XMP-acdsee-rs group
#
#                   RegionInfoACDSee : The structured tag for the ACDSee regions
#                                      (similar to XMP-mwg-rs:RegionInfo)
#
#                   The following tags are the width, height, and unit of the
#                   image at the time of processing  when storing image region
#                   metadata.  They are similar to the AppliedToDimensions tags
#                   of the MWG regions.
#                       ACDSeeRegionAppliedToDimensionsH : Height of the image
#                       ACDSeeRegionAppliedToDimensionsUnit : Unit of the image
#                       ACDSeeRegionAppliedToDimensionsW : Width of the image
#
#                   Actual region data, stored in an array.  These flattened tags
#                   are treated as List Type tags.  There are two region types,
#                   the ALYArea and the DLYArea.  The ALYArea tags tags assigned
#                   by ACDSee and are usually square in dimensions.  The DLYArea
#                   tags are both the tags assigned by ACDSee (but possibly
#                   rectangular instead of square) as well as any  manual
#                   assigned tags.  They are similar to the area tags of the MWG
#                   regions.
#                       ACDSeeRegionDLYAreaH : Height of DLY region
#                       ACDSeeRegionDLYAreaW : Width of DLY region
#                       ACDSeeRegionDLYAreaX : X centerpoint of DLY region
#                       ACDSeeRegionDLYAreaY : Y centerpoint of DLY region
#                       ACDSeeRegionALYAreaH : Height of ALY region
#                       ACDSeeRegionALYAreaW : Width of ALY region
#                       ACDSeeRegionALYAreaX : X centerpoint of ALY region
#                       ACDSeeRegionALYAreaY : Y centerpoint of ALY region
#                       ACDSeeRegionName : Name of region
#                       ACDSeeRegionType : Type of region
#                       ACDSeeRegionNameAssignType : How the type was assigned.
#                                                    "Manual" is the only known
#                                                    entry at this time
#
#               Conversion tags.  These tags can be used to convert other region
#               type tags to ACDSee regions.
#                   MPRegion2ACDSeeRegion : Converts a Microsoft RegionInfoMP
#                   IPTCRegion2ACDSeeRegion : Converts an IPTC ImageRegion
#                   MWGRegion2ACDSeeRegion : Converts a MWG RegionInfo
#
# Usage:        To set individual tags
#               exiftool -config acdsee.config -ACDSEETAG=VALUE FILE ...
#
#               To convert Microsoft Regions to ACDSee regions
#               exiftool -config acdsee.config "-RegionInfoACDSee<MPRegion2ACDSeeRegion" File ...
#               To convert IPTC regions to ACDSee regions
#               exiftool -config acdsee.config "-RegionInfoACDSee<IPTCRegion2ACDSeeRegion" File ...
#               To convert MWG Regions to ACDSee regions
#               exiftool -config acdsee.config "-RegionInfoACDSee<MWGRegion2ACDSeeRegion" File ...
#
# Requires:     ExifTool version 10.28 or later
#
# Revisions:    2020/01/28 - Bryan K. Williams (aka StarGeek) Created
#               2021/04/08 - BKW Added tags to convert from Microsoft, IPTC,
#                            and MWG regions to ACDSee regions based upon
#                            convert_regions.config.  Expanded docs.
#                            Shortened ADCSee tag names and added shortcuts
#                            from original names to new names, for example
#                            "RegionInfoACDSeeAppliedToDimensions*" -> "ACDSeeRegionAppliedToDimensions*"
#                            "RegionInfoACDSeeRegionList* -> "ACDSeeRegion*"
#------------------------------------------------------------------------------
use Data::Dumper;

my %sACDSeeDimensions = (
    STRUCT_NAME => 'ACDSee Dimensions',
    NAMESPACE   => {'acdsee-stDim' => 'http://ns.acdsee.com/sType/Dimensions#'},
    'w'         => { Writable => 'real' },
    'h'         => { Writable => 'real' },
    'unit'      => { },
);

my %sACDSeeArea = (
    STRUCT_NAME => 'ACDSee Area',
    NAMESPACE => { 'acdsee-stArea' => 'http://ns.acdsee.com/sType/Area#' },
    'x'     => { Writable => 'real' },
    'y'     => { Writable => 'real' },
    w       => { Writable => 'real' },
    h       => { Writable => 'real' },
);

my %sACDSeeRegionStruct = (
    STRUCT_NAME     => 'ACDSee Regions',
    NAMESPACE => { 'acdsee-rs' => 'http://ns.acdsee.com/regions/' },
    ALGArea         => { Struct => \%sACDSeeArea },
    DLYArea         => { Struct => \%sACDSeeArea },
    Name            => { },
    NameAssignType  => { },
    Type            => { },
);

%Image::ExifTool::UserDefined = (
    # new XMP namespaces for ACDSee regions
    'Image::ExifTool::XMP::Main' => {
        'acdsee-rs' => { # <-- must be the same as the NAMESPACE prefix
            SubDirectory => { 
                TagTable => 'Image::ExifTool::UserDefined::ACDSeeRegions' 
            },
        },
    },
    'Image::ExifTool::Composite' => {
    # create an ACDSee RegionInfo structure from a Microsoft RegionInfoMP structure
        MPRegion2ACDSeeRegion => {
            Require => {
                0 => 'RegionInfoMP',
                1 => 'ImageWidth',
                2 => 'ImageHeight',
            },
            ValueConv => q{
                my ($rgn, @newRgns);
                foreach $rgn (@{$val[0]{Regions}}) {
                    my $name = $$rgn{PersonDisplayName};
                    next unless $$rgn{Rectangle} or defined $name;
                    my %newRgn = ( Type => 'Face' );
                    if (defined $name) {
                        # don't add ignored faces
                        next if $name eq 'ffffffffffffffff';
                        $newRgn{Name} = $name;
                    }
                    if ($$rgn{Rectangle}) {
                        my @rect = split /\s*,\s*/, $$rgn{Rectangle};
                        $newRgn{DLYArea} = {
                            X => $rect[0] + $rect[2]/2,
                            Y => $rect[1] + $rect[3]/2,
                            W => $rect[2],
                            H => $rect[3],
                        } if @rect == 4;
                    }
                    push @newRgns, \%newRgn;
                }
                return {
                    AppliedToDimensions => { W => $val[1], H => $val[2], Unit => 'pixel' },
                    RegionList => \@newRgns,
                };
            },
        },
        # create an ACDSee RegionInfo structure from an IPTC ImageRegion list
        IPTCRegion2ACDSeeRegion => {
            Require => {
                0 => 'ImageRegion',
                1 => 'ImageWidth',
                2 => 'ImageHeight',
            },
            ValueConv => q{
                my ($rgn, @newRgns);
                my $rgns = ref $val[0] eq 'ARRAY' ? $val[0] : [ $val[0] ]; 
                foreach $rgn (@$rgns) {
                    my %newRgn = ( Type => 'Face' );
                    if ($$rgn{RegionBoundary} and $$rgn{RegionBoundary}{RbShape} eq 'rectangle') {
                        my @rect = @{$$rgn{RegionBoundary}}{'RbX','RbY','RbW','RbH'};
                        if ($$rgn{RegionBoundary}{RbUnit} eq 'pixel') {
                            $rect[0] /= $val[1],  $rect[2] /= $val[1];
                            $rect[1] /= $val[2];  $rect[3] /= $val[2];
                        }
                        $newRgn{'DLYArea'} = {
                            X => $rect[0] + $rect[2]/2,
                            Y => $rect[1] + $rect[3]/2,
                            W => $rect[2],
                            H => $rect[3],
                        };
                    } else {
                        next unless defined $$rgn{Name};
                    }
                    $newRgn{Name} = $$rgn{Name} if defined $$rgn{Name};
                    push @newRgns, \%newRgn;
                }
                return {
                    AppliedToDimensions => { 'W' => $val[1], 'H' => $val[2], 'Unit' => 'pixel' },
                    RegionList => \@newRgns,
                };
            },
        },

        # create an MWG RegionInfo structure from an IPTC ImageRegion list
        MWGRegion2ACDSeeRegion => {
            Require => {
                0 => 'RegionInfo',
                1 => 'ImageWidth',
                2 => 'ImageHeight',
            },
            ValueConv => q{
                my ($rgn, @newRgns);
                my %newRgn;
                foreach $rgn (@{$val[0]{RegionList}}) {
                    next unless $$rgn{Area} or defined $$rgn{Name};
                    my %newRgn;
                    if ($$rgn{Area}) {
                        $newRgn{'DLYArea'} = {
                            'X' => $$rgn{Area}{'X'},
                            'Y' => $$rgn{Area}{'Y'},
                            'W' => $$rgn{Area}{'W'},
                            'H' => $$rgn{Area}{'H'},
                        };
                    };
                    $newRgn{Name} = $$rgn{Name} if defined $$rgn{Name};
                    $newRgn{'Type'} = $$rgn{'Type'} if defined $$rgn{'Type'};
                    push @newRgns, \%newRgn;
                }
                return {
                    'AppliedToDimensions' => $val[0]{'AppliedToDimensions'},
                    RegionList => \@newRgns,
                }
            },
        },
        ####
    },
);

%Image::ExifTool::UserDefined::ACDSeeRegions = (
    GROUPS => { 0 => 'XMP', 1 => 'XMP-acdsee', 2 => 'Image' },
    NAMESPACE => { 'acdsee-rs' => 'http://ns.acdsee.com/regions/' },
    WRITABLE => 'string', # (default to string-type tags)
    Regions => {
        Name => 'RegionInfoACDSee',
        FlatName => 'ACDSee',
        # the "Struct" entry defines the structure fields
        Struct => {
            # optional structure name (used for warning messages only)
            STRUCT_NAME => 'ACDSee RegionInfo',        
            RegionList => {
                FlatName => 'Region',
                Struct => \%sACDSeeRegionStruct,
                List => 'Bag',
            },
            AppliedToDimensions => { 
            FlatName => 'RegionAppliedToDimensions',Struct => \%sACDSeeDimensions },
        },
    },
);

# Shortcuts to old names added so as not to break previously used commands
%Image::ExifTool::UserDefined::Shortcuts = (
    RegionInfoACDSeeAppliedToDimensionsH        => 'ACDSeeRegionAppliedToDimensionsH',
    RegionInfoACDSeeAppliedToDimensionsUnit     => 'ACDSeeRegionAppliedToDimensionsUnit',
    RegionInfoACDSeeAppliedToDimensionsW        => 'ACDSeeRegionAppliedToDimensionsW',
    RegionInfoACDSeeRegionListDLYAreaH          => 'ACDSeeRegionDLYAreaH',
    RegionInfoACDSeeRegionListDLYAreaW          => 'ACDSeeRegionDLYAreaW',
    RegionInfoACDSeeRegionListDLYAreaX          => 'ACDSeeRegionDLYAreaX',  
    RegionInfoACDSeeRegionListDLYAreaY          => 'ACDSeeRegionDLYAreaY',
    RegionInfoACDSeeRegionListALGAreaH          => 'ACDSeeRegionALGAreaH',
    RegionInfoACDSeeRegionListALGAreaW          => 'ACDSeeRegionALGAreaW',
    RegionInfoACDSeeRegionListALGAreaX          => 'ACDSeeRegionALGAreaX',
    RegionInfoACDSeeRegionListALGAreaY          => 'ACDSeeRegionALGAreaY',
    RegionInfoACDSeeRegionListName              => 'ACDSeeRegionName',
    RegionInfoACDSeeRegionListType              => 'ACDSeeRegionType',
    RegionInfoACDSeeRegionListNameAssignType    => 'ACDSeeRegionNameAssignType',
);

# Forced -struct option during debugging
#%Image::ExifTool::UserDefined::Options = (
#   Struct => 1,
#);
#------------------------------------------------------------------------------
1;  #end