GIMP.pm 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. #
  8. # References: 1) GIMP source code
  9. # 2) http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup
  10. #------------------------------------------------------------------------------
  11. package Image::ExifTool::GIMP;
  12. use strict;
  13. use vars qw($VERSION);
  14. use Image::ExifTool qw(:DataAccess :Utils);
  15. $VERSION = '1.02';
  16. sub ProcessParasites($$$);
  17. # GIMP XCF properties (ref 2)
  18. %Image::ExifTool::GIMP::Main = (
  19. GROUPS => { 2 => 'Image' },
  20. VARS => { ALPHA_FIRST => 1 },
  21. NOTES => q{
  22. The GNU Image Manipulation Program (GIMP) writes these tags in its native
  23. XCF (eXperimental Computing Facilty) images.
  24. },
  25. header => { SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Header' } },
  26. 17 => {
  27. Name => 'Compression',
  28. Format => 'int8u',
  29. PrintConv => {
  30. 0 => 'None',
  31. 1 => 'RLE Encoding',
  32. 2 => 'Zlib',
  33. 3 => 'Fractal',
  34. },
  35. },
  36. 19 => {
  37. Name => 'Resolution',
  38. SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Resolution' },
  39. },
  40. 21 => {
  41. Name => 'Parasites',
  42. SubDirectory => { TagTable => 'Image::ExifTool::GIMP::Parasite' },
  43. },
  44. );
  45. # information extracted from the XCF file header (ref 2)
  46. %Image::ExifTool::GIMP::Header = (
  47. GROUPS => { 2 => 'Image' },
  48. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  49. 9 => {
  50. Name => 'XCFVersion',
  51. Format => 'string[5]',
  52. PrintConv => {
  53. 'file' => '0',
  54. 'v001' => '1',
  55. 'v002' => '2',
  56. },
  57. },
  58. 14 => { Name => 'ImageWidth', Format => 'int32u' },
  59. 18 => { Name => 'ImageHeight', Format => 'int32u' },
  60. 22 => {
  61. Name => 'ColorMode',
  62. Format => 'int32u',
  63. PrintConv => {
  64. 0 => 'RGB Color',
  65. 1 => 'Grayscale',
  66. 2 => 'Indexed Color',
  67. },
  68. },
  69. );
  70. # XCF resolution data (property type 19) (ref 2)
  71. %Image::ExifTool::GIMP::Resolution = (
  72. GROUPS => { 2 => 'Image' },
  73. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  74. FORMAT => 'float',
  75. 0 => 'XResolution',
  76. 1 => 'YResolution',
  77. );
  78. # XCF "Parasite" data (property type 21) (ref 1/PH)
  79. %Image::ExifTool::GIMP::Parasite = (
  80. GROUPS => { 2 => 'Image' },
  81. PROCESS_PROC => \&ProcessParasites,
  82. 'gimp-comment' => {
  83. Name => 'Comment',
  84. Format => 'string',
  85. },
  86. 'exif-data' => {
  87. Name => 'ExifData',
  88. SubDirectory => {
  89. TagTable => 'Image::ExifTool::Exif::Main',
  90. ProcessProc => \&Image::ExifTool::ProcessTIFF,
  91. Start => 6, # starts after "Exif\0\0" header
  92. },
  93. },
  94. 'jpeg-exif-data' => { # (deprecated, untested)
  95. Name => 'JPEGExifData',
  96. SubDirectory => {
  97. TagTable => 'Image::ExifTool::Exif::Main',
  98. ProcessProc => \&Image::ExifTool::ProcessTIFF,
  99. Start => 6,
  100. },
  101. },
  102. 'iptc-data' => { # (untested)
  103. Name => 'IPTCData',
  104. SubDirectory => { TagTable => 'Image::ExifTool::IPTC::Main' },
  105. },
  106. 'icc-profile' => {
  107. Name => 'ICC_Profile',
  108. SubDirectory => { TagTable => 'Image::ExifTool::ICC_Profile::Main' },
  109. },
  110. 'icc-profile-name' => {
  111. Name => 'ICCProfileName',
  112. Format => 'string',
  113. },
  114. 'gimp-metadata' => {
  115. Name => 'XMP',
  116. SubDirectory => {
  117. TagTable => 'Image::ExifTool::XMP::Main',
  118. Start => 10, # starts after "GIMP_XMP_1" header
  119. },
  120. },
  121. );
  122. #------------------------------------------------------------------------------
  123. # Read information in a GIMP XCF parasite data (ref PH)
  124. # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
  125. # Returns: 1 on success
  126. sub ProcessParasites($$$)
  127. {
  128. my ($et, $dirInfo, $tagTablePtr) = @_;
  129. my $unknown = $et->Options('Unknown') || $et->Options('Verbose');
  130. my $dataPt = $$dirInfo{DataPt};
  131. my $pos = $$dirInfo{DirStart} || 0;
  132. my $end = length $$dataPt;
  133. $et->VerboseDir('Parasites', undef, $end);
  134. for (;;) {
  135. last if $pos + 4 > $end;
  136. my $size = Get32u($dataPt, $pos); # length of tag string
  137. $pos += 4;
  138. last if $pos + $size + 8 > $end;
  139. my $tag = substr($$dataPt, $pos, $size);
  140. $pos += $size;
  141. $tag =~ s/\0.*//s; # trim at null terminator
  142. # my $flags = Get32u($dataPt, $pos); (ignore flags)
  143. $size = Get32u($dataPt, $pos + 4); # length of data
  144. $pos += 8;
  145. last if $pos + $size > $end;
  146. if (not $$tagTablePtr{$tag} and $unknown) {
  147. my $name = $tag;
  148. $name =~ tr/-_A-Za-z0-9//dc;
  149. $name =~ s/^gimp-//;
  150. next unless length $name;
  151. $name = ucfirst $name;
  152. $name =~ s/([a-z])-([a-z])/$1\u$2/g;
  153. $name = "GIMP-$name" unless length($name) > 1;
  154. AddTagToTable($tagTablePtr, $tag, { Name => $name, Unknown => 1 });
  155. }
  156. $et->HandleTag($tagTablePtr, $tag, undef,
  157. DataPt => $dataPt,
  158. Start => $pos,
  159. Size => $size,
  160. );
  161. $pos += $size;
  162. }
  163. return 1;
  164. }
  165. #------------------------------------------------------------------------------
  166. # Read information in a GIMP XCF document
  167. # Inputs: 0) ExifTool ref, 1) dirInfo ref
  168. # Returns: 1 on success, 0 if this wasn't a valid XCF file
  169. sub ProcessXCF($$)
  170. {
  171. my ($et, $dirInfo) = @_;
  172. my $raf = $$dirInfo{RAF};
  173. my $buff;
  174. return 0 unless $raf->Read($buff, 26) == 26;
  175. return 0 unless $buff =~ /^gimp xcf /;
  176. my $tagTablePtr = GetTagTable('Image::ExifTool::GIMP::Main');
  177. my $verbose = $et->Options('Verbose');
  178. $et->SetFileType();
  179. SetByteOrder('MM');
  180. # process the XCF header
  181. $et->HandleTag($tagTablePtr, 'header', $buff);
  182. # loop through image properties
  183. for (;;) {
  184. $raf->Read($buff, 8) == 8 or last;
  185. my $tag = Get32u(\$buff, 0) or last;
  186. my $size = Get32u(\$buff, 4);
  187. $verbose and $et->VPrint(0, "XCF property $tag ($size bytes):\n");
  188. unless ($$tagTablePtr{$tag}) {
  189. $raf->Seek($size, 1);
  190. next;
  191. }
  192. $raf->Read($buff, $size) == $size or last;
  193. $et->HandleTag($tagTablePtr, $tag, undef,
  194. DataPt => \$buff,
  195. DataPos => $raf->Tell() - $size,
  196. Size => $size,
  197. );
  198. }
  199. return 1;
  200. }
  201. 1; # end
  202. __END__
  203. =head1 NAME
  204. Image::ExifTool::GIMP - Read meta information from GIMP XCF images
  205. =head1 SYNOPSIS
  206. This module is used by Image::ExifTool
  207. =head1 DESCRIPTION
  208. This module contains definitions required by Image::ExifTool to read meta
  209. information from GIMP (GNU Image Manipulation Program) XCF (eXperimental
  210. Computing Facility) images. This is the native image format used by the
  211. GIMP software.
  212. =head1 AUTHOR
  213. Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
  214. This library is free software; you can redistribute it and/or modify it
  215. under the same terms as Perl itself.
  216. =head1 REFERENCES
  217. =over 4
  218. =item L<GIMP source code>
  219. =item L<http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup>
  220. =back
  221. =head1 SEE ALSO
  222. L<Image::ExifTool::TagNames/GIMP Tags>,
  223. L<Image::ExifTool(3pm)|Image::ExifTool>
  224. =cut