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