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