ITC.pm 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #------------------------------------------------------------------------------
  2. # File: ITC.pm
  3. #
  4. # Description: Read iTunes Cover Flow meta information
  5. #
  6. # Revisions: 01/12/2008 - P. Harvey Created
  7. #
  8. # References: 1) http://www.waldoland.com/dev/Articles/ITCFileFormat.aspx
  9. # 2) http://www.falsecognate.org/2007/01/deciphering_the_itunes_itc_fil/
  10. #------------------------------------------------------------------------------
  11. package Image::ExifTool::ITC;
  12. use strict;
  13. use vars qw($VERSION);
  14. use Image::ExifTool qw(:DataAccess :Utils);
  15. $VERSION = '1.02';
  16. sub ProcessITC($$);
  17. # tags used in ITC files
  18. %Image::ExifTool::ITC::Main = (
  19. NOTES => 'This information is found in iTunes Cover Flow data files.',
  20. itch => { SubDirectory => { TagTable => 'Image::ExifTool::ITC::Header' } },
  21. item => { SubDirectory => { TagTable => 'Image::ExifTool::ITC::Item' } },
  22. data => {
  23. Name => 'ImageData',
  24. Notes => 'embedded JPEG or PNG image, depending on ImageType',
  25. },
  26. );
  27. # ITC header information
  28. %Image::ExifTool::ITC::Header = (
  29. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  30. GROUPS => { 2 => 'Image' },
  31. 0x10 => {
  32. Name => 'DataType',
  33. Format => 'undef[4]',
  34. PrintConv => { artw => 'Artwork' },
  35. },
  36. );
  37. # ITC item information
  38. %Image::ExifTool::ITC::Item = (
  39. PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
  40. GROUPS => { 2 => 'Image' },
  41. FORMAT => 'int32u',
  42. FIRST_ENTRY => 0,
  43. 0 => {
  44. Name => 'LibraryID',
  45. Format => 'undef[8]',
  46. ValueConv => 'uc unpack "H*", $val',
  47. },
  48. 2 => {
  49. Name => 'TrackID',
  50. Format => 'undef[8]',
  51. ValueConv => 'uc unpack "H*", $val',
  52. },
  53. 4 => {
  54. Name => 'DataLocation',
  55. Format => 'undef[4]',
  56. PrintConv => {
  57. down => 'Downloaded Separately',
  58. locl => 'Local Music File',
  59. },
  60. },
  61. 5 => {
  62. Name => 'ImageType',
  63. Format => 'undef[4]',
  64. ValueConv => { # (not PrintConv because the unconverted JPEG value is nasty)
  65. 'PNGf' => 'PNG',
  66. "\0\0\0\x0d" => 'JPEG',
  67. },
  68. },
  69. 7 => 'ImageWidth',
  70. 8 => 'ImageHeight',
  71. );
  72. #------------------------------------------------------------------------------
  73. # Process an iTunes Cover Flow (ITC) file
  74. # Inputs: 0) ExifTool object reference, 1) Directory information reference
  75. # Returns: 1 on success, 0 if this wasn't a valid ITC file
  76. sub ProcessITC($$)
  77. {
  78. my ($et, $dirInfo) = @_;
  79. my $raf = $$dirInfo{RAF};
  80. my $rtnVal = 0;
  81. my ($buff, $err, $pos, $tagTablePtr, %dirInfo);
  82. # loop through all blocks in this image
  83. for (;;) {
  84. # read the block header
  85. my $n = $raf->Read($buff, 8);
  86. unless ($n == 8) {
  87. # no error if we reached the EOF normally
  88. undef $err unless $n;
  89. last;
  90. }
  91. my ($size, $tag) = unpack('Na4', $buff);
  92. if ($rtnVal) {
  93. last unless $size >= 8 and $size < 0x80000000;
  94. } else {
  95. # check to be sure this is a valid ITC image
  96. # (first block must be 'itch')
  97. last unless $tag eq 'itch';
  98. last unless $size >= 0x1c and $size < 0x10000;
  99. $et->SetFileType();
  100. SetByteOrder('MM');
  101. $rtnVal = 1; # this is an ITC file
  102. $err = 1; # format error unless we read to EOF
  103. }
  104. if ($tag eq 'itch') {
  105. $pos = $raf->Tell();
  106. $size -= 8; # size of remaining data in block
  107. $raf->Read($buff,$size) == $size or last;
  108. # extract header information
  109. %dirInfo = (
  110. DirName => 'ITC Header',
  111. DataPt => \$buff,
  112. DataPos => $pos,
  113. );
  114. my $tagTablePtr = GetTagTable('Image::ExifTool::ITC::Header');
  115. $et->ProcessDirectory(\%dirInfo, $tagTablePtr);
  116. } elsif ($tag eq 'item') {
  117. # don't want to read the entire item data (includes image)
  118. $size > 12 or last;
  119. $raf->Read($buff, 4) == 4 or last;
  120. my $len = unpack('N', $buff);
  121. $len >= 0xd0 and $len <= $size or last;
  122. $size -= $len; # size of data after item header
  123. $len -= 12; # length of remaining item header
  124. # read in 4-byte blocks until we find the null terminator
  125. # (this is just a guess about how to parse this variable-length part)
  126. while ($len >= 4) {
  127. $raf->Read($buff, 4) == 4 or last;
  128. $len -= 4;
  129. last if $buff eq "\0\0\0\0";
  130. }
  131. last if $len < 4;
  132. $pos = $raf->Tell();
  133. $raf->Read($buff, $len) == $len or last;
  134. unless ($len >= 0xb4 and substr($buff, 0xb0, 4) eq 'data') {
  135. $et->Warn('Parsing error. Please submit this ITC file for testing');
  136. last;
  137. }
  138. %dirInfo = (
  139. DirName => 'ITC Item',
  140. DataPt => \$buff,
  141. DataPos => $pos,
  142. );
  143. $tagTablePtr = GetTagTable('Image::ExifTool::ITC::Item');
  144. $et->ProcessDirectory(\%dirInfo, $tagTablePtr);
  145. # extract embedded image
  146. $pos += $len;
  147. if ($size > 0) {
  148. $tagTablePtr = GetTagTable('Image::ExifTool::ITC::Main');
  149. my $tagInfo = $et->GetTagInfo($tagTablePtr, 'data');
  150. my $image = $et->ExtractBinary($pos, $size, $$tagInfo{Name});
  151. $et->FoundTag($tagInfo, \$image);
  152. # skip the rest of the block if necessary
  153. $raf->Seek($pos+$size, 0) or last
  154. } elsif ($size < 0) {
  155. last;
  156. }
  157. } else {
  158. $et->VPrint(0, "Unknown $tag block ($size bytes)\n");
  159. $raf->Seek($size-8, 1) or last;
  160. }
  161. }
  162. $err and $et->Warn('ITC file format error');
  163. return $rtnVal;
  164. }
  165. 1; # end
  166. __END__
  167. =head1 NAME
  168. Image::ExifTool::ITC - Read iTunes Cover Flow meta information
  169. =head1 SYNOPSIS
  170. This module is used by Image::ExifTool
  171. =head1 DESCRIPTION
  172. This module contains the routines required by Image::ExifTool to read meta
  173. information (including artwork images) from iTunes Cover Flow files.
  174. =head1 AUTHOR
  175. Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
  176. This library is free software; you can redistribute it and/or modify it
  177. under the same terms as Perl itself.
  178. =head1 REFERENCES
  179. =over 4
  180. =item L<http://www.waldoland.com/dev/Articles/ITCFileFormat.aspx>
  181. =item L<http://www.falsecognate.org/2007/01/deciphering_the_itunes_itc_fil/>
  182. =back
  183. =head1 SEE ALSO
  184. L<Image::ExifTool::TagNames/ITC Tags>,
  185. L<Image::ExifTool(3pm)|Image::ExifTool>
  186. =cut