module.graphic.tiff.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <?php
  2. /////////////////////////////////////////////////////////////////
  3. /// getID3() by James Heinrich <info@getid3.org> //
  4. // available at http://getid3.sourceforge.net //
  5. // or http://www.getid3.org //
  6. /////////////////////////////////////////////////////////////////
  7. // See readme.txt for more details //
  8. /////////////////////////////////////////////////////////////////
  9. // //
  10. // module.archive.tiff.php //
  11. // module for analyzing TIFF files //
  12. // dependencies: NONE //
  13. // ///
  14. /////////////////////////////////////////////////////////////////
  15. class getid3_tiff
  16. {
  17. function getid3_tiff(&$fd, &$ThisFileInfo) {
  18. fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
  19. $TIFFheader = fread($fd, 4);
  20. switch (substr($TIFFheader, 0, 2)) {
  21. case 'II':
  22. $ThisFileInfo['tiff']['byte_order'] = 'Intel';
  23. break;
  24. case 'MM':
  25. $ThisFileInfo['tiff']['byte_order'] = 'Motorola';
  26. break;
  27. default:
  28. $ThisFileInfo['error'][] = 'Invalid TIFF byte order identifier ('.substr($TIFFheader, 0, 2).') at offset '.$ThisFileInfo['avdataoffset'];
  29. return false;
  30. break;
  31. }
  32. $ThisFileInfo['fileformat'] = 'tiff';
  33. $ThisFileInfo['video']['dataformat'] = 'tiff';
  34. $ThisFileInfo['video']['lossless'] = true;
  35. $ThisFileInfo['tiff']['ifd'] = array();
  36. $CurrentIFD = array();
  37. $FieldTypeByteLength = array(1=>1, 2=>1, 3=>2, 4=>4, 5=>8);
  38. $nextIFDoffset = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']);
  39. while ($nextIFDoffset > 0) {
  40. $CurrentIFD['offset'] = $nextIFDoffset;
  41. fseek($fd, $ThisFileInfo['avdataoffset'] + $nextIFDoffset, SEEK_SET);
  42. $CurrentIFD['fieldcount'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']);
  43. for ($i = 0; $i < $CurrentIFD['fieldcount']; $i++) {
  44. $CurrentIFD['fields'][$i]['raw']['tag'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']);
  45. $CurrentIFD['fields'][$i]['raw']['type'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']);
  46. $CurrentIFD['fields'][$i]['raw']['length'] = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']);
  47. $CurrentIFD['fields'][$i]['raw']['offset'] = fread($fd, 4);
  48. switch ($CurrentIFD['fields'][$i]['raw']['type']) {
  49. case 1: // BYTE An 8-bit unsigned integer.
  50. if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
  51. $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 1), $ThisFileInfo['tiff']['byte_order']);
  52. } else {
  53. $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
  54. }
  55. break;
  56. case 2: // ASCII 8-bit bytes that store ASCII codes; the last byte must be null.
  57. if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
  58. $CurrentIFD['fields'][$i]['value'] = substr($CurrentIFD['fields'][$i]['raw']['offset'], 3);
  59. } else {
  60. $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
  61. }
  62. break;
  63. case 3: // SHORT A 16-bit (2-byte) unsigned integer.
  64. if ($CurrentIFD['fields'][$i]['raw']['length'] <= 2) {
  65. $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 2), $ThisFileInfo['tiff']['byte_order']);
  66. } else {
  67. $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
  68. }
  69. break;
  70. case 4: // LONG A 32-bit (4-byte) unsigned integer.
  71. if ($CurrentIFD['fields'][$i]['raw']['length'] <= 1) {
  72. $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
  73. } else {
  74. $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
  75. }
  76. break;
  77. case 5: // RATIONAL Two LONG_s: the first represents the numerator of a fraction, the second the denominator.
  78. break;
  79. }
  80. }
  81. $ThisFileInfo['tiff']['ifd'][] = $CurrentIFD;
  82. $CurrentIFD = array();
  83. $nextIFDoffset = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']);
  84. }
  85. foreach ($ThisFileInfo['tiff']['ifd'] as $IFDid => $IFDarray) {
  86. foreach ($IFDarray['fields'] as $key => $fieldarray) {
  87. switch ($fieldarray['raw']['tag']) {
  88. case 256: // ImageWidth
  89. case 257: // ImageLength
  90. case 258: // BitsPerSample
  91. case 259: // Compression
  92. if (!isset($fieldarray['value'])) {
  93. fseek($fd, $fieldarray['offset'], SEEK_SET);
  94. $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = fread($fd, $fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]);
  95. }
  96. break;
  97. case 270: // ImageDescription
  98. case 271: // Make
  99. case 272: // Model
  100. case 305: // Software
  101. case 306: // DateTime
  102. case 315: // Artist
  103. case 316: // HostComputer
  104. if (isset($fieldarray['value'])) {
  105. $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $fieldarray['value'];
  106. } else {
  107. fseek($fd, $fieldarray['offset'], SEEK_SET);
  108. $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = fread($fd, $fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]);
  109. }
  110. break;
  111. }
  112. switch ($fieldarray['raw']['tag']) {
  113. case 256: // ImageWidth
  114. $ThisFileInfo['video']['resolution_x'] = $fieldarray['value'];
  115. break;
  116. case 257: // ImageLength
  117. $ThisFileInfo['video']['resolution_y'] = $fieldarray['value'];
  118. break;
  119. case 258: // BitsPerSample
  120. if (isset($fieldarray['value'])) {
  121. $ThisFileInfo['video']['bits_per_sample'] = $fieldarray['value'];
  122. } else {
  123. $ThisFileInfo['video']['bits_per_sample'] = 0;
  124. for ($i = 0; $i < $fieldarray['raw']['length']; $i++) {
  125. $ThisFileInfo['video']['bits_per_sample'] += $this->TIFFendian2Int(substr($ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'], $i * $FieldTypeByteLength[$fieldarray['raw']['type']], $FieldTypeByteLength[$fieldarray['raw']['type']]), $ThisFileInfo['tiff']['byte_order']);
  126. }
  127. }
  128. break;
  129. case 259: // Compression
  130. $ThisFileInfo['video']['codec'] = $this->TIFFcompressionMethod($fieldarray['value']);
  131. break;
  132. case 270: // ImageDescription
  133. case 271: // Make
  134. case 272: // Model
  135. case 305: // Software
  136. case 306: // DateTime
  137. case 315: // Artist
  138. case 316: // HostComputer
  139. @$ThisFileInfo['tiff']['comments'][$this->TIFFcommentName($fieldarray['raw']['tag'])][] = $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'];
  140. break;
  141. default:
  142. break;
  143. }
  144. }
  145. }
  146. return true;
  147. }
  148. function TIFFendian2Int($bytestring, $byteorder) {
  149. if ($byteorder == 'Intel') {
  150. return getid3_lib::LittleEndian2Int($bytestring);
  151. } elseif ($byteorder == 'Motorola') {
  152. return getid3_lib::BigEndian2Int($bytestring);
  153. }
  154. return false;
  155. }
  156. function TIFFcompressionMethod($id) {
  157. static $TIFFcompressionMethod = array();
  158. if (empty($TIFFcompressionMethod)) {
  159. $TIFFcompressionMethod = array(
  160. 1 => 'Uncompressed',
  161. 2 => 'Huffman',
  162. 3 => 'Fax - CCITT 3',
  163. 5 => 'LZW',
  164. 32773 => 'PackBits',
  165. );
  166. }
  167. return (isset($TIFFcompressionMethod[$id]) ? $TIFFcompressionMethod[$id] : 'unknown/invalid ('.$id.')');
  168. }
  169. function TIFFcommentName($id) {
  170. static $TIFFcommentName = array();
  171. if (empty($TIFFcommentName)) {
  172. $TIFFcommentName = array(
  173. 270 => 'imagedescription',
  174. 271 => 'make',
  175. 272 => 'model',
  176. 305 => 'software',
  177. 306 => 'datetime',
  178. 315 => 'artist',
  179. 316 => 'hostcomputer',
  180. );
  181. }
  182. return (isset($TIFFcommentName[$id]) ? $TIFFcommentName[$id] : 'unknown/invalid ('.$id.')');
  183. }
  184. }
  185. ?>