ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
module.graphic.tiff.php
Go to the documentation of this file.
1 <?php
4 // available at http://getid3.sourceforge.net //
5 // or http://www.getid3.org //
7 // See readme.txt for more details //
9 // //
10 // module.archive.tiff.php //
11 // module for analyzing TIFF files //
12 // dependencies: NONE //
13 // ///
15 
16 
18 {
19 
20  function getid3_tiff(&$fd, &$ThisFileInfo) {
21 
22  fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
23  $TIFFheader = fread($fd, 4);
24 
25  switch (substr($TIFFheader, 0, 2)) {
26  case 'II':
27  $ThisFileInfo['tiff']['byte_order'] = 'Intel';
28  break;
29  case 'MM':
30  $ThisFileInfo['tiff']['byte_order'] = 'Motorola';
31  break;
32  default:
33  $ThisFileInfo['error'][] = 'Invalid TIFF byte order identifier ('.substr($TIFFheader, 0, 2).') at offset '.$ThisFileInfo['avdataoffset'];
34  return false;
35  break;
36  }
37 
38  $ThisFileInfo['fileformat'] = 'tiff';
39  $ThisFileInfo['video']['dataformat'] = 'tiff';
40  $ThisFileInfo['video']['lossless'] = true;
41  $ThisFileInfo['tiff']['ifd'] = array();
42  $CurrentIFD = array();
43 
44  $FieldTypeByteLength = array(1=>1, 2=>1, 3=>2, 4=>4, 5=>8);
45 
46  $nextIFDoffset = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']);
47 
48  while ($nextIFDoffset > 0) {
49 
50  $CurrentIFD['offset'] = $nextIFDoffset;
51 
52  fseek($fd, $ThisFileInfo['avdataoffset'] + $nextIFDoffset, SEEK_SET);
53  $CurrentIFD['fieldcount'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']);
54 
55  for ($i = 0; $i < $CurrentIFD['fieldcount']; $i++) {
56  $CurrentIFD['fields'][$i]['raw']['tag'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']);
57  $CurrentIFD['fields'][$i]['raw']['type'] = $this->TIFFendian2Int(fread($fd, 2), $ThisFileInfo['tiff']['byte_order']);
58  $CurrentIFD['fields'][$i]['raw']['length'] = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']);
59  $CurrentIFD['fields'][$i]['raw']['offset'] = fread($fd, 4);
60 
61  switch ($CurrentIFD['fields'][$i]['raw']['type']) {
62  case 1: // BYTE An 8-bit unsigned integer.
63  if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
64  $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 1), $ThisFileInfo['tiff']['byte_order']);
65  } else {
66  $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
67  }
68  break;
69 
70  case 2: // ASCII 8-bit bytes that store ASCII codes; the last byte must be null.
71  if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
72  $CurrentIFD['fields'][$i]['value'] = substr($CurrentIFD['fields'][$i]['raw']['offset'], 3);
73  } else {
74  $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
75  }
76  break;
77 
78  case 3: // SHORT A 16-bit (2-byte) unsigned integer.
79  if ($CurrentIFD['fields'][$i]['raw']['length'] <= 2) {
80  $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 2), $ThisFileInfo['tiff']['byte_order']);
81  } else {
82  $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
83  }
84  break;
85 
86  case 4: // LONG A 32-bit (4-byte) unsigned integer.
87  if ($CurrentIFD['fields'][$i]['raw']['length'] <= 1) {
88  $CurrentIFD['fields'][$i]['value'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
89  } else {
90  $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $ThisFileInfo['tiff']['byte_order']);
91  }
92  break;
93 
94  case 5: // RATIONAL Two LONG_s: the first represents the numerator of a fraction, the second the denominator.
95  break;
96  }
97  }
98 
99  $ThisFileInfo['tiff']['ifd'][] = $CurrentIFD;
100  $CurrentIFD = array();
101  $nextIFDoffset = $this->TIFFendian2Int(fread($fd, 4), $ThisFileInfo['tiff']['byte_order']);
102 
103  }
104 
105  foreach ($ThisFileInfo['tiff']['ifd'] as $IFDid => $IFDarray) {
106  foreach ($IFDarray['fields'] as $key => $fieldarray) {
107  switch ($fieldarray['raw']['tag']) {
108  case 256: // ImageWidth
109  case 257: // ImageLength
110  case 258: // BitsPerSample
111  case 259: // Compression
112  if (!isset($fieldarray['value'])) {
113  fseek($fd, $fieldarray['offset'], SEEK_SET);
114  $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = fread($fd, $fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]);
115 
116  }
117  break;
118 
119  case 270: // ImageDescription
120  case 271: // Make
121  case 272: // Model
122  case 305: // Software
123  case 306: // DateTime
124  case 315: // Artist
125  case 316: // HostComputer
126  if (isset($fieldarray['value'])) {
127  $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = $fieldarray['value'];
128  } else {
129  fseek($fd, $fieldarray['offset'], SEEK_SET);
130  $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'] = fread($fd, $fieldarray['raw']['length'] * $FieldTypeByteLength[$fieldarray['raw']['type']]);
131 
132  }
133  break;
134  }
135  switch ($fieldarray['raw']['tag']) {
136  case 256: // ImageWidth
137  $ThisFileInfo['video']['resolution_x'] = $fieldarray['value'];
138  break;
139 
140  case 257: // ImageLength
141  $ThisFileInfo['video']['resolution_y'] = $fieldarray['value'];
142  break;
143 
144  case 258: // BitsPerSample
145  if (isset($fieldarray['value'])) {
146  $ThisFileInfo['video']['bits_per_sample'] = $fieldarray['value'];
147  } else {
148  $ThisFileInfo['video']['bits_per_sample'] = 0;
149  for ($i = 0; $i < $fieldarray['raw']['length']; $i++) {
150  $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']);
151  }
152  }
153  break;
154 
155  case 259: // Compression
156  $ThisFileInfo['video']['codec'] = $this->TIFFcompressionMethod($fieldarray['value']);
157  break;
158 
159  case 270: // ImageDescription
160  case 271: // Make
161  case 272: // Model
162  case 305: // Software
163  case 306: // DateTime
164  case 315: // Artist
165  case 316: // HostComputer
166  @$ThisFileInfo['tiff']['comments'][$this->TIFFcommentName($fieldarray['raw']['tag'])][] = $ThisFileInfo['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data'];
167  break;
168 
169  default:
170  break;
171  }
172  }
173  }
174 
175  return true;
176  }
177 
178 
179  function TIFFendian2Int($bytestring, $byteorder) {
180  if ($byteorder == 'Intel') {
181  return getid3_lib::LittleEndian2Int($bytestring);
182  } elseif ($byteorder == 'Motorola') {
183  return getid3_lib::BigEndian2Int($bytestring);
184  }
185  return false;
186  }
187 
188  function TIFFcompressionMethod($id) {
189  static $TIFFcompressionMethod = array();
190  if (empty($TIFFcompressionMethod)) {
191  $TIFFcompressionMethod = array(
192  1 => 'Uncompressed',
193  2 => 'Huffman',
194  3 => 'Fax - CCITT 3',
195  5 => 'LZW',
196  32773 => 'PackBits',
197  );
198  }
199  return (isset($TIFFcompressionMethod[$id]) ? $TIFFcompressionMethod[$id] : 'unknown/invalid ('.$id.')');
200  }
201 
202  function TIFFcommentName($id) {
203  static $TIFFcommentName = array();
204  if (empty($TIFFcommentName)) {
205  $TIFFcommentName = array(
206  270 => 'imagedescription',
207  271 => 'make',
208  272 => 'model',
209  305 => 'software',
210  306 => 'datetime',
211  315 => 'artist',
212  316 => 'hostcomputer',
213  );
214  }
215  return (isset($TIFFcommentName[$id]) ? $TIFFcommentName[$id] : 'unknown/invalid ('.$id.')');
216  }
217 
218 }
219 
220 
221 ?>