diff options
Diffstat (limited to 'getid3/module.graphic.tiff.php')
-rw-r--r-- | getid3/module.graphic.tiff.php | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/getid3/module.graphic.tiff.php b/getid3/module.graphic.tiff.php new file mode 100644 index 0000000..ae57cd6 --- /dev/null +++ b/getid3/module.graphic.tiff.php @@ -0,0 +1,221 @@ +<?php +///////////////////////////////////////////////////////////////// +/// getID3() by James Heinrich <info@getid3.org> // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.archive.tiff.php // +// module for analyzing TIFF files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// + + +class getid3_tiff +{ + + function getid3_tiff(&$fd, &$ThisFileInfo) { + + fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); + $TIFFheader = fread($fd, 4); + + switch (substr($TIFFheader, 0, 2)) { + case 'II': + $ThisFileInfo['tiff']['byte_order'] = 'Intel'; + break; + case 'MM': + $ThisFileInfo['tiff']['byte_order'] = 'Motorola'; + break; + default: + $ThisFileInfo['error'][] = 'Invalid TIFF byte order identifier ('.substr($TIFFheader, 0, 2).') at offset '.$ThisFileInfo['avdataoffset']; + return false; + break; + } + + $ThisFileInfo['fileformat'] = 'tiff'; + $ThisFileInfo['video']['dataformat'] = 'tiff'; + $ThisFileInfo['video']['lossless'] = true; + $ThisFileInfo['tiff']['ifd'] = array(); + $CurrentIFD = array(); + + $FieldTypeByteLength = array(1=>1, 2=>1, 3=>2, 4=>4, 5=>8); + + $nextIFDoffset = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']); + + while ($nextIFDoffset > 0) { + + $CurrentIFD['offset'] = $nextIFDoffset; + + fseek($fd, $ThisFileInfo['avdataoffset'] + $nextIFDoffset, SEEK_SET); + $CurrentIFD['fieldcount'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']); + + for ($i = 0; $i < $CurrentIFD['fieldcount']; $i++) { + $CurrentIFD['fields'][$i]['raw']['tag'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']); + $CurrentIFD['fields'][$i]['raw']['type'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']); + $CurrentIFD['fields'][$i]['raw']['length'] = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']); + $CurrentIFD['fields'][$i]['raw']['offset'] = fread($fd, 4); + + switch ($CurrentIFD['fields'][$i]['raw']['type']) { + case 1: // BYTE An 8-bit unsigned integer. + if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) { + $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 1), $ThisFileInfo['tiff']['byte_order']); + } else { + $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']); + } + break; + + case 2: // ASCII 8-bit bytes that store ASCII codes; the last byte must be null. + if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) { + $CurrentIFD['fields'][$i]['value'] = substr($CurrentIFD['fields'][$i]['raw']['offset'], 3); + } else { + $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']); + } + break; + + case 3: // SHORT A 16-bit (2-byte) unsigned integer. + if ($CurrentIFD['fields'][$i]['raw']['length'] <= 2) { + $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 2), $ThisFileInfo['tiff']['byte_order']); + } else { + $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']); + } + break; + + case 4: // LONG A 32-bit (4-byte) unsigned integer. + if ($CurrentIFD['fields'][$i]['raw']['length'] <= 1) { + $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']); + } else { + $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']); + } + break; + + case 5: // RATIONAL Two LONG_s: the first represents the numerator of a fraction, the second the denominator. + break; + } + } + + $ThisFileInfo['tiff']['ifd'][] = $CurrentIFD; + $CurrentIFD = array(); + $nextIFDoffset = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']); + + } + + foreach ($ThisFileInfo['tiff']['ifd'] as $IFDid => $IFDarray) { + foreach ($IFDarray['fields'] as $key => $fieldarray) { + switch ($fieldarray['raw']['tag']) { + case 256: // ImageWidth + case 257: // ImageLength + case 258: // BitsPerSample + case 259: // Compression + if (!isset($fieldarray['value'])) { + fseek($fd, $fieldarray['offset'], SEEK_SET); + $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = fread($fd, $fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]); + + } + break; + + case 270: // ImageDescription + case 271: // Make + case 272: // Model + case 305: // Software + case 306: // DateTime + case 315: // Artist + case 316: // HostComputer + if (isset($fieldarray['value'])) { + $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $fieldarray['value']; + } else { + fseek($fd, $fieldarray['offset'], SEEK_SET); + $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = fread($fd, $fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]); + + } + break; + } + switch ($fieldarray['raw']['tag']) { + case 256: // ImageWidth + $ThisFileInfo['video']['resolution_x'] = $fieldarray['value']; + break; + + case 257: // ImageLength + $ThisFileInfo['video']['resolution_y'] = $fieldarray['value']; + break; + + case 258: // BitsPerSample + if (isset($fieldarray['value'])) { + $ThisFileInfo['video']['bits_per_sample'] = $fieldarray['value']; + } else { + $ThisFileInfo['video']['bits_per_sample'] = 0; + for ($i = 0; $i < $fieldarray['raw']['length']; $i++) { + $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']); + } + } + break; + + case 259: // Compression + $ThisFileInfo['video']['codec'] = $this->TIFFcompressionMethod($fieldarray['value']); + break; + + case 270: // ImageDescription + case 271: // Make + case 272: // Model + case 305: // Software + case 306: // DateTime + case 315: // Artist + case 316: // HostComputer + @$ThisFileInfo['tiff']['comments'][$this->TIFFcommentName($fieldarray['raw']['tag'])][] = $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data']; + break; + + default: + break; + } + } + } + + return true; + } + + + function TIFFendian2Int($bytestring, $byteorder) { + if ($byteorder == 'Intel') { + return getid3_lib::LittleEndian2Int($bytestring); + } elseif ($byteorder == 'Motorola') { + return getid3_lib::BigEndian2Int($bytestring); + } + return false; + } + + function TIFFcompressionMethod($id) { + static $TIFFcompressionMethod = array(); + if (empty($TIFFcompressionMethod)) { + $TIFFcompressionMethod = array( + 1 => 'Uncompressed', + 2 => 'Huffman', + 3 => 'Fax - CCITT 3', + 5 => 'LZW', + 32773 => 'PackBits', + ); + } + return (isset($TIFFcompressionMethod[$id]) ? $TIFFcompressionMethod[$id] : 'unknown/invalid ('.$id.')'); + } + + function TIFFcommentName($id) { + static $TIFFcommentName = array(); + if (empty($TIFFcommentName)) { + $TIFFcommentName = array( + 270 => 'imagedescription', + 271 => 'make', + 272 => 'model', + 305 => 'software', + 306 => 'datetime', + 315 => 'artist', + 316 => 'hostcomputer', + ); + } + return (isset($TIFFcommentName[$id]) ? $TIFFcommentName[$id] : 'unknown/invalid ('.$id.')'); + } + +} + + +?>
\ No newline at end of file |