source: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/GIMP.pm@ 34921

Last change on this file since 34921 was 34921, checked in by anupama, 3 years ago

Committing the improvements to EmbeddedMetaPlugin's processing of Keywords vs other metadata fields. Keywords were literally stored as arrays of words rather than phrases in PDFs (at least in Diego's sample PDF), whereas other meta fields like Subjects and Creators stored them as arrays of phrases. To get both to work, Kathy updated EXIF to a newer version, to retrieve the actual EXIF values stored in the PDF. And Kathy and Dr Bainbridge came up with a new option that I added called apply_join_before_split_to_metafields that's a regex which can list the metadata fields to apply the join_before_split to and whcih previously always got applied to all metadata fields. Now it's applied to any *Keywords metafields by default, as that's the metafield we have experience of that behaves differently to the others, as it stores by word instead of phrases. Tested on Diego's sample PDF. Diego has double-checked it to works on his sample PDF too, setting the split char to ; and turning on the join_before_split and leaving apply_join_before_split_to_metafields at its default of .*Keywords. File changes are strings.properties for the tooltip, the plugin introducing the option and working with it and Kathy's EXIF updates affecting cpan/File and cpan/Image.

  • Property svn:executable set to *
File size: 8.3 KB
Line 
1#------------------------------------------------------------------------------
2# File: GIMP.pm
3#
4# Description: Read meta information from GIMP XCF images
5#
6# Revisions: 2010/10/05 - P. Harvey Created
7# 2018/08/21 - PH Updated to current XCF specification (v013)
8#
9# References: 1) GIMP source code
10# 2) https://gitlab.gnome.org/GNOME/gimp/blob/master/devel-docs/xcf.txt
11#------------------------------------------------------------------------------
12
13package Image::ExifTool::GIMP;
14
15use strict;
16use vars qw($VERSION);
17use Image::ExifTool qw(:DataAccess :Utils);
18
19$VERSION = '1.03';
20
21sub ProcessParasites($$$);
22
23# GIMP XCF properties (ref 2)
24%Image::ExifTool::GIMP::Main = (
25 GROUPS => { 2 => 'Image' },
26 VARS => { ALPHA_FIRST => 1 },
27 NOTES => q{
28 The GNU Image Manipulation Program (GIMP) writes these tags in its native
29 XCF (eXperimental Computing Facilty) images.
30 },
31 header => { SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Header' } },
32 # recognized properties
33 # 1 - ColorMap
34 # 17 - SamplePoints? (doc says 17 is also "PROP_SAMPLE_POINTS"??)
35 17 => {
36 Name => 'Compression',
37 Format => 'int8u',
38 PrintConv => {
39 0 => 'None',
40 1 => 'RLE Encoding',
41 2 => 'Zlib',
42 3 => 'Fractal',
43 },
44 },
45 # 18 - Guides
46 19 => {
47 Name => 'Resolution',
48 SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Resolution' },
49 },
50 20 => {
51 Name => 'Tattoo',
52 Format => 'int32u',
53 },
54 21 => {
55 Name => 'Parasites',
56 SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Parasite' },
57 },
58 22 => {
59 Name => 'Units',
60 Format => 'int32u',
61 PrintConv => {
62 1 => 'Inches',
63 2 => 'mm',
64 3 => 'Points',
65 4 => 'Picas',
66 },
67 },
68 # 23 Paths
69 # 24 UserUnit
70 # 25 Vectors
71);
72
73# information extracted from the XCF file header (ref 2)
74%Image::ExifTool::GIMP::Header = (
75 GROUPS => { 2 => 'Image' },
76 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
77 9 => {
78 Name => 'XCFVersion',
79 Format => 'string[5]',
80 DataMember => 'XCFVersion',
81 RawConv => '$$self{XCFVersion} = $val',
82 PrintConv => {
83 'file' => '0',
84 'v001' => '1',
85 'v002' => '2',
86 OTHER => sub { my $val = shift; $val =~ s/^v0*//; return $val },
87 },
88 },
89 14 => { Name => 'ImageWidth', Format => 'int32u' },
90 18 => { Name => 'ImageHeight', Format => 'int32u' },
91 22 => {
92 Name => 'ColorMode',
93 Format => 'int32u',
94 PrintConv => {
95 0 => 'RGB Color',
96 1 => 'Grayscale',
97 2 => 'Indexed Color',
98 },
99 },
100 # 26 - [XCF 4 or later] Precision
101);
102
103# XCF resolution data (property type 19) (ref 2)
104%Image::ExifTool::GIMP::Resolution = (
105 GROUPS => { 2 => 'Image' },
106 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
107 FORMAT => 'float',
108 0 => 'XResolution',
109 1 => 'YResolution',
110);
111
112# XCF "Parasite" data (property type 21) (ref 1/PH)
113%Image::ExifTool::GIMP::Parasite = (
114 GROUPS => { 2 => 'Image' },
115 PROCESS_PROC => \&ProcessParasites,
116 'gimp-comment' => {
117 Name => 'Comment',
118 Format => 'string',
119 },
120 'exif-data' => {
121 Name => 'ExifData',
122 SubDirectory => {
123 TagTable => 'Image::ExifTool::Exif::Main',
124 ProcessProc => \&Image::ExifTool::ProcessTIFF,
125 Start => 6, # starts after "Exif\0\0" header
126 },
127 },
128 'jpeg-exif-data' => { # (deprecated, untested)
129 Name => 'JPEGExifData',
130 SubDirectory => {
131 TagTable => 'Image::ExifTool::Exif::Main',
132 ProcessProc => \&Image::ExifTool::ProcessTIFF,
133 Start => 6,
134 },
135 },
136 'iptc-data' => { # (untested)
137 Name => 'IPTCData',
138 SubDirectory => { TagTable => 'Image::ExifTool::IPTC::Main' },
139 },
140 'icc-profile' => {
141 Name => 'ICC_Profile',
142 SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
143 },
144 'icc-profile-name' => {
145 Name => 'ICCProfileName',
146 Format => 'string',
147 },
148 'gimp-metadata' => {
149 Name => 'XMP',
150 SubDirectory => {
151 TagTable => 'Image::ExifTool::XMP::Main',
152 Start => 10, # starts after "GIMP_XMP_1" header
153 },
154 },
155 'gimp-image-metadata' => {
156 Name => 'XML',
157 SubDirectory => { TagTable => 'Image::ExifTool::XMP::XML' },
158 },
159 # Seen, but not yet decoded:
160 # gimp-image-grid
161 # jpeg-settings
162);
163
164#------------------------------------------------------------------------------
165# Read information in a GIMP XCF parasite data (ref PH)
166# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
167# Returns: 1 on success
168sub ProcessParasites($$$)
169{
170 my ($et, $dirInfo, $tagTablePtr) = @_;
171 my $unknown = $et->Options('Unknown') || $et->Options('Verbose');
172 my $dataPt = $$dirInfo{DataPt};
173 my $pos = $$dirInfo{DirStart} || 0;
174 my $end = length $$dataPt;
175 $et->VerboseDir('Parasites', undef, $end);
176 for (;;) {
177 last if $pos + 4 > $end;
178 my $size = Get32u($dataPt, $pos); # length of tag string
179 $pos += 4;
180 last if $pos + $size + 8 > $end;
181 my $tag = substr($$dataPt, $pos, $size);
182 $pos += $size;
183 $tag =~ s/\0.*//s; # trim at null terminator
184 # my $flags = Get32u($dataPt, $pos); (ignore flags)
185 $size = Get32u($dataPt, $pos + 4); # length of data
186 $pos += 8;
187 last if $pos + $size > $end;
188 if (not $$tagTablePtr{$tag} and $unknown) {
189 my $name = $tag;
190 $name =~ tr/-_A-Za-z0-9//dc;
191 $name =~ s/^gimp-//;
192 next unless length $name;
193 $name = ucfirst $name;
194 $name =~ s/([a-z])-([a-z])/$1\u$2/g;
195 $name = "GIMP-$name" unless length($name) > 1;
196 AddTagToTable($tagTablePtr, $tag, { Name => $name, Unknown => 1 });
197 }
198 $et->HandleTag($tagTablePtr, $tag, undef,
199 DataPt => $dataPt,
200 Start => $pos,
201 Size => $size,
202 );
203 $pos += $size;
204 }
205 return 1;
206}
207
208#------------------------------------------------------------------------------
209# Read information in a GIMP XCF document
210# Inputs: 0) ExifTool ref, 1) dirInfo ref
211# Returns: 1 on success, 0 if this wasn't a valid XCF file
212sub ProcessXCF($$)
213{
214 my ($et, $dirInfo) = @_;
215 my $raf = $$dirInfo{RAF};
216 my $buff;
217
218 return 0 unless $raf->Read($buff, 26) == 26;
219 return 0 unless $buff =~ /^gimp xcf /;
220
221 my $tagTablePtr = GetTagTable('Image::ExifTool::GIMP::Main');
222 my $verbose = $et->Options('Verbose');
223 $et->SetFileType();
224 SetByteOrder('MM');
225
226 # process the XCF header
227 $et->HandleTag($tagTablePtr, 'header', $buff);
228
229 # skip over precision for XCV version 4 or later
230 $raf->Seek(4, 1) if $$et{XCFVersion} =~ /^v0*(\d+)/ and $1 >= 4;
231
232 # loop through image properties
233 for (;;) {
234 $raf->Read($buff, 8) == 8 or last;
235 my $tag = Get32u(\$buff, 0) or last;
236 my $size = Get32u(\$buff, 4);
237 $verbose and $et->VPrint(0, "XCF property $tag ($size bytes):\n");
238 unless ($$tagTablePtr{$tag}) {
239 $raf->Seek($size, 1);
240 next;
241 }
242 $raf->Read($buff, $size) == $size or last;
243 $et->HandleTag($tagTablePtr, $tag, undef,
244 DataPt => \$buff,
245 DataPos => $raf->Tell() - $size,
246 Size => $size,
247 );
248 }
249 return 1;
250}
251
2521; # end
253
254__END__
255
256=head1 NAME
257
258Image::ExifTool::GIMP - Read meta information from GIMP XCF images
259
260=head1 SYNOPSIS
261
262This module is used by Image::ExifTool
263
264=head1 DESCRIPTION
265
266This module contains definitions required by Image::ExifTool to read meta
267information from GIMP (GNU Image Manipulation Program) XCF (eXperimental
268Computing Facility) images. This is the native image format used by the
269GIMP software.
270
271=head1 AUTHOR
272
273Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
274
275This library is free software; you can redistribute it and/or modify it
276under the same terms as Perl itself.
277
278=head1 REFERENCES
279
280=over 4
281
282=item L<GIMP source code>
283
284=item L<http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup>
285
286=back
287
288=head1 SEE ALSO
289
290L<Image::ExifTool::TagNames/GIMP Tags>,
291L<Image::ExifTool(3pm)|Image::ExifTool>
292
293=cut
294
Note: See TracBrowser for help on using the repository browser.