File indexing completed on 2024-12-22 05:33:13
0001 <?php 0002 ///////////////////////////////////////////////////////////////// 0003 /// getID3() by James Heinrich <info@getid3.org> // 0004 // available at http://getid3.sourceforge.net // 0005 // or http://www.getid3.org // 0006 // also https://github.com/JamesHeinrich/getID3 // 0007 ///////////////////////////////////////////////////////////////// 0008 // See readme.txt for more details // 0009 ///////////////////////////////////////////////////////////////// 0010 // // 0011 // module.archive.tiff.php // 0012 // module for analyzing TIFF files // 0013 // dependencies: NONE // 0014 // /// 0015 ///////////////////////////////////////////////////////////////// 0016 0017 0018 class getid3_tiff extends getid3_handler 0019 { 0020 0021 public function Analyze() { 0022 $info = &$this->getid3->info; 0023 0024 $this->fseek($info['avdataoffset']); 0025 $TIFFheader = $this->fread(4); 0026 0027 switch (substr($TIFFheader, 0, 2)) { 0028 case 'II': 0029 $info['tiff']['byte_order'] = 'Intel'; 0030 break; 0031 case 'MM': 0032 $info['tiff']['byte_order'] = 'Motorola'; 0033 break; 0034 default: 0035 $info['error'][] = 'Invalid TIFF byte order identifier ('.substr($TIFFheader, 0, 2).') at offset '.$info['avdataoffset']; 0036 return false; 0037 break; 0038 } 0039 0040 $info['fileformat'] = 'tiff'; 0041 $info['video']['dataformat'] = 'tiff'; 0042 $info['video']['lossless'] = true; 0043 $info['tiff']['ifd'] = array(); 0044 $CurrentIFD = array(); 0045 0046 $FieldTypeByteLength = array(1=>1, 2=>1, 3=>2, 4=>4, 5=>8); 0047 0048 $nextIFDoffset = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']); 0049 0050 while ($nextIFDoffset > 0) { 0051 0052 $CurrentIFD['offset'] = $nextIFDoffset; 0053 0054 $this->fseek($info['avdataoffset'] + $nextIFDoffset); 0055 $CurrentIFD['fieldcount'] = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']); 0056 0057 for ($i = 0; $i < $CurrentIFD['fieldcount']; $i++) { 0058 $CurrentIFD['fields'][$i]['raw']['tag'] = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']); 0059 $CurrentIFD['fields'][$i]['raw']['type'] = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']); 0060 $CurrentIFD['fields'][$i]['raw']['length'] = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']); 0061 $CurrentIFD['fields'][$i]['raw']['offset'] = $this->fread(4); 0062 0063 switch ($CurrentIFD['fields'][$i]['raw']['type']) { 0064 case 1: // BYTE An 8-bit unsigned integer. 0065 if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) { 0066 $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 1), $info['tiff']['byte_order']); 0067 } else { 0068 $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']); 0069 } 0070 break; 0071 0072 case 2: // ASCII 8-bit bytes that store ASCII codes; the last byte must be null. 0073 if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) { 0074 $CurrentIFD['fields'][$i]['value'] = substr($CurrentIFD['fields'][$i]['raw']['offset'], 3); 0075 } else { 0076 $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']); 0077 } 0078 break; 0079 0080 case 3: // SHORT A 16-bit (2-byte) unsigned integer. 0081 if ($CurrentIFD['fields'][$i]['raw']['length'] <= 2) { 0082 $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 2), $info['tiff']['byte_order']); 0083 } else { 0084 $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']); 0085 } 0086 break; 0087 0088 case 4: // LONG A 32-bit (4-byte) unsigned integer. 0089 if ($CurrentIFD['fields'][$i]['raw']['length'] <= 1) { 0090 $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']); 0091 } else { 0092 $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']); 0093 } 0094 break; 0095 0096 case 5: // RATIONAL Two LONG_s: the first represents the numerator of a fraction, the second the denominator. 0097 break; 0098 } 0099 } 0100 0101 $info['tiff']['ifd'][] = $CurrentIFD; 0102 $CurrentIFD = array(); 0103 $nextIFDoffset = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']); 0104 0105 } 0106 0107 foreach ($info['tiff']['ifd'] as $IFDid => $IFDarray) { 0108 foreach ($IFDarray['fields'] as $key => $fieldarray) { 0109 switch ($fieldarray['raw']['tag']) { 0110 case 256: // ImageWidth 0111 case 257: // ImageLength 0112 case 258: // BitsPerSample 0113 case 259: // Compression 0114 if (!isset($fieldarray['value'])) { 0115 $this->fseek($fieldarray['offset']); 0116 $info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $this->fread($fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]); 0117 0118 } 0119 break; 0120 0121 case 270: // ImageDescription 0122 case 271: // Make 0123 case 272: // Model 0124 case 305: // Software 0125 case 306: // DateTime 0126 case 315: // Artist 0127 case 316: // HostComputer 0128 if (isset($fieldarray['value'])) { 0129 $info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $fieldarray['value']; 0130 } else { 0131 $this->fseek($fieldarray['offset']); 0132 $info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $this->fread($fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]); 0133 0134 } 0135 break; 0136 } 0137 switch ($fieldarray['raw']['tag']) { 0138 case 256: // ImageWidth 0139 $info['video']['resolution_x'] = $fieldarray['value']; 0140 break; 0141 0142 case 257: // ImageLength 0143 $info['video']['resolution_y'] = $fieldarray['value']; 0144 break; 0145 0146 case 258: // BitsPerSample 0147 if (isset($fieldarray['value'])) { 0148 $info['video']['bits_per_sample'] = $fieldarray['value']; 0149 } else { 0150 $info['video']['bits_per_sample'] = 0; 0151 for ($i = 0; $i < $fieldarray['raw']['length']; $i++) { 0152 $info['video']['bits_per_sample'] += $this->TIFFendian2Int(substr($info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'], $i * $FieldTypeByteLength[$fieldarray['raw']['type']], $FieldTypeByteLength[$fieldarray['raw']['type']]), $info['tiff']['byte_order']); 0153 } 0154 } 0155 break; 0156 0157 case 259: // Compression 0158 $info['video']['codec'] = $this->TIFFcompressionMethod($fieldarray['value']); 0159 break; 0160 0161 case 270: // ImageDescription 0162 case 271: // Make 0163 case 272: // Model 0164 case 305: // Software 0165 case 306: // DateTime 0166 case 315: // Artist 0167 case 316: // HostComputer 0168 $TIFFcommentName = $this->TIFFcommentName($fieldarray['raw']['tag']); 0169 if (isset($info['tiff']['comments'][$TIFFcommentName])) { 0170 $info['tiff']['comments'][$TIFFcommentName][] = $info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data']; 0171 } else { 0172 $info['tiff']['comments'][$TIFFcommentName] = array($info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data']); 0173 } 0174 break; 0175 0176 default: 0177 break; 0178 } 0179 } 0180 } 0181 0182 return true; 0183 } 0184 0185 0186 public function TIFFendian2Int($bytestring, $byteorder) { 0187 if ($byteorder == 'Intel') { 0188 return getid3_lib::LittleEndian2Int($bytestring); 0189 } elseif ($byteorder == 'Motorola') { 0190 return getid3_lib::BigEndian2Int($bytestring); 0191 } 0192 return false; 0193 } 0194 0195 public function TIFFcompressionMethod($id) { 0196 static $TIFFcompressionMethod = array(); 0197 if (empty($TIFFcompressionMethod)) { 0198 $TIFFcompressionMethod = array( 0199 1 => 'Uncompressed', 0200 2 => 'Huffman', 0201 3 => 'Fax - CCITT 3', 0202 5 => 'LZW', 0203 32773 => 'PackBits', 0204 ); 0205 } 0206 return (isset($TIFFcompressionMethod[$id]) ? $TIFFcompressionMethod[$id] : 'unknown/invalid ('.$id.')'); 0207 } 0208 0209 public function TIFFcommentName($id) { 0210 static $TIFFcommentName = array(); 0211 if (empty($TIFFcommentName)) { 0212 $TIFFcommentName = array( 0213 270 => 'imagedescription', 0214 271 => 'make', 0215 272 => 'model', 0216 305 => 'software', 0217 306 => 'datetime', 0218 315 => 'artist', 0219 316 => 'hostcomputer', 0220 ); 0221 } 0222 return (isset($TIFFcommentName[$id]) ? $TIFFcommentName[$id] : 'unknown/invalid ('.$id.')'); 0223 } 0224 0225 }