File Coverage

blib/lib/Image/ExifTool/XISF.pm
Criterion Covered Total %
statement 45 46 97.8
branch 8 12 66.6
condition 6 9 66.6
subroutine 6 6 100.0
pod 0 2 0.0
total 65 75 86.6


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             # File: XISF.pm
3             #
4             # Description: Read Extensible Image Serialization Format metadata
5             #
6             # Revisions: 2023-10-10 - P. Harvey Created
7             #
8             # References: 1) https://pixinsight.com/doc/docs/XISF-1.0-spec/XISF-1.0-spec.html
9             #------------------------------------------------------------------------------
10              
11             package Image::ExifTool::XISF;
12              
13 1     1   8262 use strict;
  1         2  
  1         48  
14 1     1   6 use vars qw($VERSION);
  1         2  
  1         53  
15 1     1   5 use Image::ExifTool qw(:DataAccess :Utils);
  1         2  
  1         319  
16 1     1   1235 use Image::ExifTool::XMP;
  1         7  
  1         897  
17              
18             $VERSION = '1.00';
19              
20             # XISF tags (ref 1)
21             %Image::ExifTool::XISF::Main = (
22             GROUPS => { 0 => 'XML', 1 => 'XML', 2 => 'Image' },
23             VARS => { LONG_TAGS => 1 },
24             NOTES => q{
25             This table lists some standard Extensible Image Serialization Format (XISF)
26             tags, but ExifTool will extract any other tags found. See
27             L for the specification.
28             },
29             ImageGeometry => { },
30             ImageSampleFormat => { },
31             ImageBounds => { },
32             ImageImageType => { Name => 'ImageType' },
33             ImageColorSpace => { Name => 'ColorSpace' },
34             ImageLocation => { },
35             ImageResolutionHorizontal => 'XResolution',
36             ImageResolutionVertical => 'YResolution',
37             ImageResolutionUnit => 'ResolutionUnit',
38             ImageICCProfile => {
39             Name => 'ICC_Profile',
40             ValueConv => 'Image::ExifTool::XMP::DecodeBase64($val)',
41             Binary => 1,
42             },
43             ImageICCProfileLocation => { Name => 'ICCProfileLocation' },
44             ImagePixelStorage => { },
45             ImageOffset => { Name => 'ImagePixelOffset' },
46             ImageOrientation => { Name => 'Orientation' },
47             ImageId => { Name => 'ImageID' },
48             ImageUuid => { Name => 'UUID' },
49             ImageData => { Binary => 1 },
50             'CreationTime' => {
51             Name => 'CreateDate',
52             Shift => 'Time',
53             Groups => { 2 => 'Time' },
54             ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)',
55             PrintConv => '$self->ConvertDateTime($val)',
56             },
57             CreatorApplication => { },
58             Abstract => { },
59             AccessRights => { },
60             Authors => { Groups => { 2 => 'Author' } },
61             BibliographicReferences => { },
62             BriefDescription => { },
63             CompressionLevel => { },
64             CompressionCodecs => { },
65             Contributors => { Groups => { 2 => 'Author' } },
66             Copyright => { Groups => { 2 => 'Author' } },
67             CreatorModule => { },
68             CreatorOS => { },
69             Description => { },
70             Keywords => { },
71             Languages => { },
72             License => { },
73             OriginalCreationTime => {
74             Name => 'DateTimeOriginal',
75             Description => 'Date/Time Original',
76             Shift => 'Time',
77             Groups => { 2 => 'Time' },
78             ValueConv => 'Image::ExifTool::XMP::ConvertXMPDate($val)',
79             PrintConv => '$self->ConvertDateTime($val)',
80             },
81             RelatedResources => { },
82             Title => { },
83             );
84              
85             #------------------------------------------------------------------------------
86             # Handle properties in XISF metadata structures
87             # Inputs: 0) attribute list ref, 1) attr hash ref,
88             # 2) property name ref, 3) property value ref
89             # Returns: true if value was changed
90             sub HandleXISFAttrs($$$$)
91             {
92 11     11 0 17 my ($attrList, $attrs, $prop, $valPt) = @_;
93 11 100       27 return 0 unless defined $$attrs{id};
94 6         6 my ($changed, $a);
95             # use "id" as the tag name, "value" as the value, and ignore "type"
96 6         9 $$prop = $$attrs{id};
97 6         12 $$prop =~ s/^XISF://; # remove XISF namespace
98 6 100       13 if (defined $$attrs{value}) {
99 1         2 $$valPt = $$attrs{value};
100 1         1 $changed = 1;
101             }
102 6         12 my @attrs = @$attrList;
103 6         9 @$attrList = ( );
104 6         10 foreach $a (@attrs) {
105 13 50 100     33 if ($a eq 'id' or $a eq 'value' or $a eq 'type') {
      66        
106 13         17 delete $$attrs{$a};
107             } else {
108 0         0 push @$attrList, $a;
109             }
110             }
111 6         15 return $changed;
112             }
113              
114             #------------------------------------------------------------------------------
115             # Read information in a XISF document
116             # Inputs: 0) ExifTool ref, 1) dirInfo ref
117             # Returns: 1 on success, 0 if this wasn't a valid XISF file
118             sub ProcessXISF($$)
119             {
120 1     1 0 3 my ($et, $dirInfo) = @_;
121 1         2 my $raf = $$dirInfo{RAF};
122 1         1 my $buff;
123              
124 1 50 33     2 return 0 unless $raf->Read($buff, 16) == 16 and $buff =~ /^XISF0100/;
125 1         6 $et->SetFileType();
126 1         19 SetByteOrder('II');
127 1         6 my $tagTablePtr = GetTagTable('Image::ExifTool::XISF::Main');
128 1         9 my $hdrLen = Get32u(\$buff, 8);
129 1 50       4 $raf->Read($buff, $hdrLen) == $hdrLen or $et->Warn('Error reading XISF header'), return 1;
130 1         3 $et->FoundTag(XML => $buff);
131 1         8 my %dirInfo = (
132             DataPt => \$buff,
133             IgnoreProp => { xisf => 1, Metadata => 1, Property => 1 },
134             XMPParseOpts => { AttrProc => \&HandleXISFAttrs },
135             );
136 1         14 Image::ExifTool::XMP::ProcessXMP($et, \%dirInfo, $tagTablePtr);
137 1         2 my $geo = $$et{VALUE}{ImageGeometry};
138 1 50       2 if ($geo) {
139 1         4 my ($w, $h, $n) = split /:/, $geo;
140 1         3 $et->FoundTag(ImageWidth => $w);
141 1         3 $et->FoundTag(ImageHeight => $h);
142 1         2 $et->FoundTag(NumPlanes => $n);
143             }
144 1         5 return 1;
145             }
146              
147             1; # end
148              
149             __END__