1#------------------------------------------------------------------------------
2# File:         acdsee.config
3#
4# Description:  This config file defines ACDSee XMP region tags for writing.
5#               The following tags are created in the XMP-acdsee-rs group
6#
7#                   RegionInfoACDSee : The structured tag for the ACDSee regions
8#                                      (similar to XMP-mwg-rs:RegionInfo)
9#
10#                   The following tags are the width, height, and unit of the
11#                   image at the time of processing  when storing image region
12#                   metadata.  They are similar to the AppliedToDimensions tags
13#                   of the MWG regions.
14#                       ACDSeeRegionAppliedToDimensionsH : Height of the image
15#                       ACDSeeRegionAppliedToDimensionsUnit : Unit of the image
16#                       ACDSeeRegionAppliedToDimensionsW : Width of the image
17#
18#                   Actual region data, stored in an array.  These flattened tags
19#                   are treated as List Type tags.  There are two region types,
20#                   the ALYArea and the DLYArea.  The ALYArea tags tags assigned
21#                   by ACDSee and are usually square in dimensions.  The DLYArea
22#                   tags are both the tags assigned by ACDSee (but possibly
23#                   rectangular instead of square) as well as any  manual
24#                   assigned tags.  They are similar to the area tags of the MWG
25#                   regions.
26#                       ACDSeeRegionDLYAreaH : Height of DLY region
27#                       ACDSeeRegionDLYAreaW : Width of DLY region
28#                       ACDSeeRegionDLYAreaX : X centerpoint of DLY region
29#                       ACDSeeRegionDLYAreaY : Y centerpoint of DLY region
30#                       ACDSeeRegionALYAreaH : Height of ALY region
31#                       ACDSeeRegionALYAreaW : Width of ALY region
32#                       ACDSeeRegionALYAreaX : X centerpoint of ALY region
33#                       ACDSeeRegionALYAreaY : Y centerpoint of ALY region
34#                       ACDSeeRegionName : Name of region
35#                       ACDSeeRegionType : Type of region
36#                       ACDSeeRegionNameAssignType : How the type was assigned.
37#                                                    "Manual" is the only known
38#                                                    entry at this time
39#
40#               Conversion tags.  These tags can be used to convert other region
41#               type tags to ACDSee regions.
42#                   MPRegion2ACDSeeRegion : Converts a Microsoft RegionInfoMP
43#                   IPTCRegion2ACDSeeRegion : Converts an IPTC ImageRegion
44#                   MWGRegion2ACDSeeRegion : Converts a MWG RegionInfo
45#
46# Usage:        To set individual tags
47#               exiftool -config acdsee.config -ACDSEETAG=VALUE FILE ...
48#
49#               To convert Microsoft Regions to ACDSee regions
50#               exiftool -config acdsee.config "-RegionInfoACDSee<MPRegion2ACDSeeRegion" File ...
51#               To convert IPTC regions to ACDSee regions
52#               exiftool -config acdsee.config "-RegionInfoACDSee<IPTCRegion2ACDSeeRegion" File ...
53#               To convert MWG Regions to ACDSee regions
54#               exiftool -config acdsee.config "-RegionInfoACDSee<MWGRegion2ACDSeeRegion" File ...
55#
56# Requires:     ExifTool version 10.28 or later
57#
58# Revisions:    2020/01/28 - Bryan K. Williams (aka StarGeek) Created
59#               2021/04/08 - BKW Added tags to convert from Microsoft, IPTC,
60#                            and MWG regions to ACDSee regions based upon
61#                            convert_regions.config.  Expanded docs.
62#                            Shortened ADCSee tag names and added shortcuts
63#                            from original names to new names, for example
64#                            "RegionInfoACDSeeAppliedToDimensions*" -> "ACDSeeRegionAppliedToDimensions*"
65#                            "RegionInfoACDSeeRegionList* -> "ACDSeeRegion*"
66#------------------------------------------------------------------------------
67use Data::Dumper;
68
69my %sACDSeeDimensions = (
70    STRUCT_NAME => 'ACDSee Dimensions',
71    NAMESPACE   => {'acdsee-stDim' => 'http://ns.acdsee.com/sType/Dimensions#'},
72    'w'         => { Writable => 'real' },
73    'h'         => { Writable => 'real' },
74    'unit'      => { },
75);
76
77my %sACDSeeArea = (
78    STRUCT_NAME => 'ACDSee Area',
79    NAMESPACE => { 'acdsee-stArea' => 'http://ns.acdsee.com/sType/Area#' },
80    'x'     => { Writable => 'real' },
81    'y'     => { Writable => 'real' },
82    w       => { Writable => 'real' },
83    h       => { Writable => 'real' },
84);
85
86my %sACDSeeRegionStruct = (
87    STRUCT_NAME     => 'ACDSee Regions',
88    NAMESPACE => { 'acdsee-rs' => 'http://ns.acdsee.com/regions/' },
89    ALGArea         => { Struct => \%sACDSeeArea },
90    DLYArea         => { Struct => \%sACDSeeArea },
91    Name            => { },
92    NameAssignType  => { },
93    Type            => { },
94);
95
96%Image::ExifTool::UserDefined = (
97    # new XMP namespaces for ACDSee regions
98    'Image::ExifTool::XMP::Main' => {
99        'acdsee-rs' => { # <-- must be the same as the NAMESPACE prefix
100            SubDirectory => {
101                TagTable => 'Image::ExifTool::UserDefined::ACDSeeRegions'
102            },
103        },
104    },
105    'Image::ExifTool::Composite' => {
106    # create an ACDSee RegionInfo structure from a Microsoft RegionInfoMP structure
107        MPRegion2ACDSeeRegion => {
108            Require => {
109                0 => 'RegionInfoMP',
110                1 => 'ImageWidth',
111                2 => 'ImageHeight',
112            },
113            ValueConv => q{
114                my ($rgn, @newRgns);
115                foreach $rgn (@{$val[0]{Regions}}) {
116                    my $name = $$rgn{PersonDisplayName};
117                    next unless $$rgn{Rectangle} or defined $name;
118                    my %newRgn = ( Type => 'Face' );
119                    if (defined $name) {
120                        # don't add ignored faces
121                        next if $name eq 'ffffffffffffffff';
122                        $newRgn{Name} = $name;
123                    }
124                    if ($$rgn{Rectangle}) {
125                        my @rect = split /\s*,\s*/, $$rgn{Rectangle};
126                        $newRgn{DLYArea} = {
127                            X => $rect[0] + $rect[2]/2,
128                            Y => $rect[1] + $rect[3]/2,
129                            W => $rect[2],
130                            H => $rect[3],
131                        } if @rect == 4;
132                    }
133                    push @newRgns, \%newRgn;
134                }
135                return {
136                    AppliedToDimensions => { W => $val[1], H => $val[2], Unit => 'pixel' },
137                    RegionList => \@newRgns,
138                };
139            },
140        },
141        # create an ACDSee RegionInfo structure from an IPTC ImageRegion list
142        IPTCRegion2ACDSeeRegion => {
143            Require => {
144                0 => 'ImageRegion',
145                1 => 'ImageWidth',
146                2 => 'ImageHeight',
147            },
148            ValueConv => q{
149                my ($rgn, @newRgns);
150                my $rgns = ref $val[0] eq 'ARRAY' ? $val[0] : [ $val[0] ];
151                foreach $rgn (@$rgns) {
152                    my %newRgn = ( Type => 'Face' );
153                    if ($$rgn{RegionBoundary} and $$rgn{RegionBoundary}{RbShape} eq 'rectangle') {
154                        my @rect = @{$$rgn{RegionBoundary}}{'RbX','RbY','RbW','RbH'};
155                        if ($$rgn{RegionBoundary}{RbUnit} eq 'pixel') {
156                            $rect[0] /= $val[1],  $rect[2] /= $val[1];
157                            $rect[1] /= $val[2];  $rect[3] /= $val[2];
158                        }
159                        $newRgn{'DLYArea'} = {
160                            X => $rect[0] + $rect[2]/2,
161                            Y => $rect[1] + $rect[3]/2,
162                            W => $rect[2],
163                            H => $rect[3],
164                        };
165                    } else {
166                        next unless defined $$rgn{Name};
167                    }
168                    $newRgn{Name} = $$rgn{Name} if defined $$rgn{Name};
169                    push @newRgns, \%newRgn;
170                }
171                return {
172                    AppliedToDimensions => { 'W' => $val[1], 'H' => $val[2], 'Unit' => 'pixel' },
173                    RegionList => \@newRgns,
174                };
175            },
176        },
177
178        # create an MWG RegionInfo structure from an IPTC ImageRegion list
179        MWGRegion2ACDSeeRegion => {
180            Require => {
181                0 => 'RegionInfo',
182                1 => 'ImageWidth',
183                2 => 'ImageHeight',
184            },
185            ValueConv => q{
186                my ($rgn, @newRgns);
187                my %newRgn;
188                foreach $rgn (@{$val[0]{RegionList}}) {
189                    next unless $$rgn{Area} or defined $$rgn{Name};
190                    my %newRgn;
191                    if ($$rgn{Area}) {
192                        $newRgn{'DLYArea'} = {
193                            'X' => $$rgn{Area}{'X'},
194                            'Y' => $$rgn{Area}{'Y'},
195                            'W' => $$rgn{Area}{'W'},
196                            'H' => $$rgn{Area}{'H'},
197                        };
198                    };
199                    $newRgn{Name} = $$rgn{Name} if defined $$rgn{Name};
200                    $newRgn{'Type'} = $$rgn{'Type'} if defined $$rgn{'Type'};
201                    push @newRgns, \%newRgn;
202                }
203                return {
204                    'AppliedToDimensions' => $val[0]{'AppliedToDimensions'},
205                    RegionList => \@newRgns,
206                }
207            },
208        },
209        ####
210    },
211);
212
213%Image::ExifTool::UserDefined::ACDSeeRegions = (
214    GROUPS => { 0 => 'XMP', 1 => 'XMP-acdsee', 2 => 'Image' },
215    NAMESPACE => { 'acdsee-rs' => 'http://ns.acdsee.com/regions/' },
216    WRITABLE => 'string', # (default to string-type tags)
217    Regions => {
218        Name => 'RegionInfoACDSee',
219        FlatName => 'ACDSee',
220        # the "Struct" entry defines the structure fields
221        Struct => {
222            # optional structure name (used for warning messages only)
223            STRUCT_NAME => 'ACDSee RegionInfo',
224            RegionList => {
225                FlatName => 'Region',
226                Struct => \%sACDSeeRegionStruct,
227                List => 'Bag',
228            },
229            AppliedToDimensions => {
230            FlatName => 'RegionAppliedToDimensions',Struct => \%sACDSeeDimensions },
231        },
232    },
233);
234
235# Shortcuts to old names added so as not to break previously used commands
236%Image::ExifTool::UserDefined::Shortcuts = (
237    RegionInfoACDSeeAppliedToDimensionsH        => 'ACDSeeRegionAppliedToDimensionsH',
238    RegionInfoACDSeeAppliedToDimensionsUnit     => 'ACDSeeRegionAppliedToDimensionsUnit',
239    RegionInfoACDSeeAppliedToDimensionsW        => 'ACDSeeRegionAppliedToDimensionsW',
240    RegionInfoACDSeeRegionListDLYAreaH          => 'ACDSeeRegionDLYAreaH',
241    RegionInfoACDSeeRegionListDLYAreaW          => 'ACDSeeRegionDLYAreaW',
242    RegionInfoACDSeeRegionListDLYAreaX          => 'ACDSeeRegionDLYAreaX',
243    RegionInfoACDSeeRegionListDLYAreaY          => 'ACDSeeRegionDLYAreaY',
244    RegionInfoACDSeeRegionListALGAreaH          => 'ACDSeeRegionALGAreaH',
245    RegionInfoACDSeeRegionListALGAreaW          => 'ACDSeeRegionALGAreaW',
246    RegionInfoACDSeeRegionListALGAreaX          => 'ACDSeeRegionALGAreaX',
247    RegionInfoACDSeeRegionListALGAreaY          => 'ACDSeeRegionALGAreaY',
248    RegionInfoACDSeeRegionListName              => 'ACDSeeRegionName',
249    RegionInfoACDSeeRegionListType              => 'ACDSeeRegionType',
250    RegionInfoACDSeeRegionListNameAssignType    => 'ACDSeeRegionNameAssignType',
251);
252
253# Forced -struct option during debugging
254#%Image::ExifTool::UserDefined::Options = (
255#   Struct => 1,
256#);
257#------------------------------------------------------------------------------
2581;  #end