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 | ///////////////////////////////////////////////////////////////// |
---|
7 | // See readme.txt for more details // |
---|
8 | ///////////////////////////////////////////////////////////////// |
---|
9 | // // |
---|
10 | // module.archive.tiff.php // |
---|
11 | // module for analyzing TIFF files // |
---|
12 | // dependencies: NONE // |
---|
13 | // /// |
---|
14 | ///////////////////////////////////////////////////////////////// |
---|
15 | |
---|
16 | |
---|
17 | class getid3_tiff |
---|
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 | ?> |
---|