rlm@3: <?php
rlm@3: // +----------------------------------------------------------------------+
rlm@3: // | PHP version 5                                                        |
rlm@3: // +----------------------------------------------------------------------+
rlm@3: // | Copyright (c) 2002-2006 James Heinrich, Allan Hansen                 |
rlm@3: // +----------------------------------------------------------------------+
rlm@3: // | This source file is subject to version 2 of the GPL license,         |
rlm@3: // | that is bundled with this package in the file license.txt and is     |
rlm@3: // | available through the world-wide-web at the following url:           |
rlm@3: // | http://www.gnu.org/copyleft/gpl.html                                 |
rlm@3: // +----------------------------------------------------------------------+
rlm@3: // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org    |
rlm@3: // +----------------------------------------------------------------------+
rlm@3: // | Authors: James Heinrich <infoØgetid3*org>                            |
rlm@3: // |          Allan Hansen <ahØartemis*dk>                                |
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: ?>