| // | Allan Hansen | // +----------------------------------------------------------------------+ // | module.graphic.tiff.php | // | Module for analyzing TIFF graphic files. | // | dependencies: NONE | // +----------------------------------------------------------------------+ // // $Id: module.graphic.tiff.php 3318 2009-05-20 21:54:10Z vdigital $ class getid3_tiff extends getid3_handler { public function Analyze() { $getid3 = $this->getid3; fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET); $tiff_header = fread($getid3->fp, 4); $getid3->info['tiff']['byte_order'] = substr($tiff_header, 0, 2) == 'II' ? 'Intel' : 'Motorola'; $endian2int = substr($tiff_header, 0, 2) == 'II' ? 'LittleEndian2Int' : 'BigEndian2Int'; $getid3->info['fileformat'] = 'tiff'; $getid3->info['video']['dataformat'] = 'tiff'; $getid3->info['video']['lossless'] = true; $getid3->info['tiff']['ifd'] = array (); $current_ifd = array (); $field_type_byte_length = array (1=>1, 2=>1, 3=>2, 4=>4, 5=>8); $next_ifd_offset = getid3_lib::$endian2int(fread($getid3->fp, 4)); while ($next_ifd_offset > 0) { $current_ifd['offset'] = $next_ifd_offset; fseek($getid3->fp, $getid3->info['avdataoffset'] + $next_ifd_offset, SEEK_SET); $current_ifd['fieldcount'] = getid3_lib::$endian2int(fread($getid3->fp, 2)); for ($i = 0; $i < $current_ifd['fieldcount']; $i++) { // shortcut $current_ifd['fields'][$i] = array (); $current_ifd_fields_i = &$current_ifd['fields'][$i]; $current_ifd_fields_i['raw']['tag'] = getid3_lib::$endian2int(fread($getid3->fp, 2)); $current_ifd_fields_i['raw']['type'] = getid3_lib::$endian2int(fread($getid3->fp, 2)); $current_ifd_fields_i['raw']['length'] = getid3_lib::$endian2int(fread($getid3->fp, 4)); $current_ifd_fields_i['raw']['offset'] = fread($getid3->fp, 4); switch ($current_ifd_fields_i['raw']['type']) { case 1: // BYTE An 8-bit unsigned integer. if ($current_ifd_fields_i['raw']['length'] <= 4) { $current_ifd_fields_i['value'] = getid3_lib::$endian2int(substr($current_ifd_fields_i['raw']['offset'], 0, 1)); } else { $current_ifd_fields_i['offset'] = getid3_lib::$endian2int($current_ifd_fields_i['raw']['offset']); } break; case 2: // ASCII 8-bit bytes that store ASCII codes; the last byte must be null. if ($current_ifd_fields_i['raw']['length'] <= 4) { $current_ifd_fields_i['value'] = substr($current_ifd_fields_i['raw']['offset'], 3); } else { $current_ifd_fields_i['offset'] = getid3_lib::$endian2int($current_ifd_fields_i['raw']['offset']); } break; case 3: // SHORT A 16-bit (2-byte) unsigned integer. if ($current_ifd_fields_i['raw']['length'] <= 2) { $current_ifd_fields_i['value'] = getid3_lib::$endian2int(substr($current_ifd_fields_i['raw']['offset'], 0, 2)); } else { $current_ifd_fields_i['offset'] = getid3_lib::$endian2int($current_ifd_fields_i['raw']['offset']); } break; case 4: // LONG A 32-bit (4-byte) unsigned integer. if ($current_ifd_fields_i['raw']['length'] <= 1) { $current_ifd_fields_i['value'] = getid3_lib::$endian2int($current_ifd_fields_i['raw']['offset']); } else { $current_ifd_fields_i['offset'] = getid3_lib::$endian2int($current_ifd_fields_i['raw']['offset']); } break; case 5: // RATIONAL Two LONG_s: the first represents the numerator of a fraction, the second the denominator. break; } } $getid3->info['tiff']['ifd'][] = $current_ifd; $current_ifd = array (); $next_ifd_offset = getid3_lib::$endian2int(fread($getid3->fp, 4)); } foreach ($getid3->info['tiff']['ifd'] as $ifd_id => $ifd_array) { foreach ($ifd_array['fields'] as $key => $field_array) { switch ($field_array['raw']['tag']) { case 256: // ImageWidth case 257: // ImageLength case 258: // BitsPerSample case 259: // Compression if (!isset($field_array['value'])) { fseek($getid3->fp, $field_array['offset'], SEEK_SET); $getid3->info['tiff']['ifd'][$ifd_id]['fields'][$key]['raw']['data'] = fread($getid3->fp, $field_array['raw']['length'] * $field_type_byte_length[$field_array['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($field_array['value'])) { $getid3->info['tiff']['ifd'][$ifd_id]['fields'][$key]['raw']['data'] = $field_array['value']; } else { fseek($getid3->fp, $field_array['offset'], SEEK_SET); $getid3->info['tiff']['ifd'][$ifd_id]['fields'][$key]['raw']['data'] = fread($getid3->fp, $field_array['raw']['length'] * $field_type_byte_length[$field_array['raw']['type']]); } break; } switch ($field_array['raw']['tag']) { case 256: // ImageWidth $getid3->info['video']['resolution_x'] = $field_array['value']; break; case 257: // ImageLength $getid3->info['video']['resolution_y'] = $field_array['value']; break; case 258: // BitsPerSample if (isset($field_array['value'])) { $getid3->info['video']['bits_per_sample'] = $field_array['value']; } else { $getid3->info['video']['bits_per_sample'] = 0; for ($i = 0; $i < $field_array['raw']['length']; $i++) { $getid3->info['video']['bits_per_sample'] += getid3_lib::$endian2int(substr($getid3->info['tiff']['ifd'][$ifd_id]['fields'][$key]['raw']['data'], $i * $field_type_byte_length[$field_array['raw']['type']], $field_type_byte_length[$field_array['raw']['type']])); } } break; case 259: // Compression $getid3->info['video']['codec'] = getid3_tiff::TIFFcompressionMethod($field_array['value']); break; case 270: // ImageDescription case 271: // Make case 272: // Model case 305: // Software case 306: // DateTime case 315: // Artist case 316: // HostComputer @$getid3->info['tiff']['comments'][getid3_tiff::TIFFcommentName($field_array['raw']['tag'])][] = $getid3->info['tiff']['ifd'][$ifd_id]['fields'][$key]['raw']['data']; break; default: break; } } } return true; } public static function TIFFcompressionMethod($id) { static $lookup = array ( 1 => 'Uncompressed', 2 => 'Huffman', 3 => 'Fax - CCITT 3', 5 => 'LZW', 32773 => 'PackBits', ); return (isset($lookup[$id]) ? $lookup[$id] : 'unknown/invalid ('.$id.')'); } public static function TIFFcommentName($id) { static $lookup = array ( 270 => 'imagedescription', 271 => 'make', 272 => 'model', 305 => 'software', 306 => 'datetime', 315 => 'artist', 316 => 'hostcomputer', ); return (isset($lookup[$id]) ? $lookup[$id] : 'unknown/invalid ('.$id.')'); } } ?>