source: spip-zone/_core_/branches/spip-3.1/plugins/medias/lib/getid3/module.graphic.png.php @ 113163

Last change on this file since 113163 was 113163, checked in by spip.franck@…, 7 months ago

Mise à jour de la lib getid en version 1.9.16, nous étions en 1.9.12
https://github.com/JamesHeinrich/getID3/blob/master/changelog.txt

File size: 28.8 KB
Line 
1<?php
2
3/////////////////////////////////////////////////////////////////
4/// getID3() by James Heinrich <info@getid3.org>               //
5//  available at https://github.com/JamesHeinrich/getID3       //
6//            or https://www.getid3.org                        //
7//            or http://getid3.sourceforge.net                 //
8//  see readme.txt for more details                            //
9/////////////////////////////////////////////////////////////////
10//                                                             //
11// module.graphic.png.php                                      //
12// module for analyzing PNG Image files                        //
13// dependencies: NONE                                          //
14//                                                            ///
15/////////////////////////////////////////////////////////////////
16
17
18class getid3_png extends getid3_handler
19{
20        /**
21         * If data chunk is larger than this do not read it completely (getID3 only needs the first
22         * few dozen bytes for parsing).
23         *
24         * @var int
25         */
26        public $max_data_bytes = 10000000;
27
28        /**
29         * @return bool
30         */
31        public function Analyze() {
32
33                $info = &$this->getid3->info;
34
35                // shortcut
36                $info['png'] = array();
37                $thisfile_png = &$info['png'];
38
39                $info['fileformat']          = 'png';
40                $info['video']['dataformat'] = 'png';
41                $info['video']['lossless']   = false;
42
43                $this->fseek($info['avdataoffset']);
44                $PNGfiledata = $this->fread($this->getid3->fread_buffer_size());
45                $offset = 0;
46
47                $PNGidentifier = substr($PNGfiledata, $offset, 8); // $89 $50 $4E $47 $0D $0A $1A $0A
48                $offset += 8;
49
50                if ($PNGidentifier != "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") {
51                        $this->error('First 8 bytes of file ('.getid3_lib::PrintHexBytes($PNGidentifier).') did not match expected PNG identifier');
52                        unset($info['fileformat']);
53                        return false;
54                }
55
56                while ((($this->ftell() - (strlen($PNGfiledata) - $offset)) < $info['filesize'])) {
57                        $chunk['data_length'] = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4));
58                        if ($chunk['data_length'] === false) {
59                                $this->error('Failed to read data_length at offset '.$offset);
60                                return false;
61                        }
62                        $offset += 4;
63                        $truncated_data = false;
64                        while (((strlen($PNGfiledata) - $offset) < ($chunk['data_length'] + 4)) && ($this->ftell() < $info['filesize'])) {
65                                if (strlen($PNGfiledata) < $this->max_data_bytes) {
66                                        $PNGfiledata .= $this->fread($this->getid3->fread_buffer_size());
67                                } else {
68                                        $this->warning('At offset '.$offset.' chunk "'.substr($PNGfiledata, $offset, 4).'" exceeded max_data_bytes value of '.$this->max_data_bytes.', data chunk will be truncated at '.(strlen($PNGfiledata) - 8).' bytes');
69                                        break;
70                                }
71                        }
72                        $chunk['type_text']   =                           substr($PNGfiledata, $offset, 4);
73                        $offset += 4;
74                        $chunk['type_raw']    = getid3_lib::BigEndian2Int($chunk['type_text']);
75                        $chunk['data']        =                           substr($PNGfiledata, $offset, $chunk['data_length']);
76                        $offset += $chunk['data_length'];
77                        $chunk['crc']         = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4));
78                        $offset += 4;
79
80                        $chunk['flags']['ancilliary']   = (bool) ($chunk['type_raw'] & 0x20000000);
81                        $chunk['flags']['private']      = (bool) ($chunk['type_raw'] & 0x00200000);
82                        $chunk['flags']['reserved']     = (bool) ($chunk['type_raw'] & 0x00002000);
83                        $chunk['flags']['safe_to_copy'] = (bool) ($chunk['type_raw'] & 0x00000020);
84
85                        // shortcut
86                        $thisfile_png[$chunk['type_text']] = array();
87                        $thisfile_png_chunk_type_text = &$thisfile_png[$chunk['type_text']];
88
89                        switch ($chunk['type_text']) {
90
91                                case 'IHDR': // Image Header
92                                        $thisfile_png_chunk_type_text['header'] = $chunk;
93                                        $thisfile_png_chunk_type_text['width']                     = getid3_lib::BigEndian2Int(substr($chunk['data'],  0, 4));
94                                        $thisfile_png_chunk_type_text['height']                    = getid3_lib::BigEndian2Int(substr($chunk['data'],  4, 4));
95                                        $thisfile_png_chunk_type_text['raw']['bit_depth']          = getid3_lib::BigEndian2Int(substr($chunk['data'],  8, 1));
96                                        $thisfile_png_chunk_type_text['raw']['color_type']         = getid3_lib::BigEndian2Int(substr($chunk['data'],  9, 1));
97                                        $thisfile_png_chunk_type_text['raw']['compression_method'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 10, 1));
98                                        $thisfile_png_chunk_type_text['raw']['filter_method']      = getid3_lib::BigEndian2Int(substr($chunk['data'], 11, 1));
99                                        $thisfile_png_chunk_type_text['raw']['interlace_method']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 1));
100
101                                        $thisfile_png_chunk_type_text['compression_method_text']   = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['raw']['compression_method']);
102                                        $thisfile_png_chunk_type_text['color_type']['palette']     = (bool) ($thisfile_png_chunk_type_text['raw']['color_type'] & 0x01);
103                                        $thisfile_png_chunk_type_text['color_type']['true_color']  = (bool) ($thisfile_png_chunk_type_text['raw']['color_type'] & 0x02);
104                                        $thisfile_png_chunk_type_text['color_type']['alpha']       = (bool) ($thisfile_png_chunk_type_text['raw']['color_type'] & 0x04);
105
106                                        $info['video']['resolution_x']    = $thisfile_png_chunk_type_text['width'];
107                                        $info['video']['resolution_y']    = $thisfile_png_chunk_type_text['height'];
108
109                                        $info['video']['bits_per_sample'] = $this->IHDRcalculateBitsPerSample($thisfile_png_chunk_type_text['raw']['color_type'], $thisfile_png_chunk_type_text['raw']['bit_depth']);
110                                        break;
111
112
113                                case 'PLTE': // Palette
114                                        $thisfile_png_chunk_type_text['header'] = $chunk;
115                                        $paletteoffset = 0;
116                                        for ($i = 0; $i <= 255; $i++) {
117                                                //$thisfile_png_chunk_type_text['red'][$i]   = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1));
118                                                //$thisfile_png_chunk_type_text['green'][$i] = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1));
119                                                //$thisfile_png_chunk_type_text['blue'][$i]  = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1));
120                                                $red   = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1));
121                                                $green = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1));
122                                                $blue  = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1));
123                                                $thisfile_png_chunk_type_text[$i] = (($red << 16) | ($green << 8) | ($blue));
124                                        }
125                                        break;
126
127
128                                case 'tRNS': // Transparency
129                                        $thisfile_png_chunk_type_text['header'] = $chunk;
130                                        switch ($thisfile_png['IHDR']['raw']['color_type']) {
131                                                case 0:
132                                                        $thisfile_png_chunk_type_text['transparent_color_gray']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2));
133                                                        break;
134
135                                                case 2:
136                                                        $thisfile_png_chunk_type_text['transparent_color_red']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2));
137                                                        $thisfile_png_chunk_type_text['transparent_color_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 2));
138                                                        $thisfile_png_chunk_type_text['transparent_color_blue']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 2));
139                                                        break;
140
141                                                case 3:
142                                                        for ($i = 0; $i < strlen($chunk['data']); $i++) {
143                                                                $thisfile_png_chunk_type_text['palette_opacity'][$i] = getid3_lib::BigEndian2Int(substr($chunk['data'], $i, 1));
144                                                        }
145                                                        break;
146
147                                                case 4:
148                                                case 6:
149                                                        $this->error('Invalid color_type in tRNS chunk: '.$thisfile_png['IHDR']['raw']['color_type']);
150                                                        break;
151
152                                                default:
153                                                        $this->warning('Unhandled color_type in tRNS chunk: '.$thisfile_png['IHDR']['raw']['color_type']);
154                                                        break;
155                                        }
156                                        break;
157
158
159                                case 'gAMA': // Image Gamma
160                                        $thisfile_png_chunk_type_text['header'] = $chunk;
161                                        $thisfile_png_chunk_type_text['gamma']  = getid3_lib::BigEndian2Int($chunk['data']) / 100000;
162                                        break;
163
164
165                                case 'cHRM': // Primary Chromaticities
166                                        $thisfile_png_chunk_type_text['header']  = $chunk;
167                                        $thisfile_png_chunk_type_text['white_x'] = getid3_lib::BigEndian2Int(substr($chunk['data'],  0, 4)) / 100000;
168                                        $thisfile_png_chunk_type_text['white_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'],  4, 4)) / 100000;
169                                        $thisfile_png_chunk_type_text['red_y']   = getid3_lib::BigEndian2Int(substr($chunk['data'],  8, 4)) / 100000;
170                                        $thisfile_png_chunk_type_text['red_y']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 4)) / 100000;
171                                        $thisfile_png_chunk_type_text['green_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 16, 4)) / 100000;
172                                        $thisfile_png_chunk_type_text['green_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 20, 4)) / 100000;
173                                        $thisfile_png_chunk_type_text['blue_y']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 24, 4)) / 100000;
174                                        $thisfile_png_chunk_type_text['blue_y']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 28, 4)) / 100000;
175                                        break;
176
177
178                                case 'sRGB': // Standard RGB Color Space
179                                        $thisfile_png_chunk_type_text['header']                 = $chunk;
180                                        $thisfile_png_chunk_type_text['reindering_intent']      = getid3_lib::BigEndian2Int($chunk['data']);
181                                        $thisfile_png_chunk_type_text['reindering_intent_text'] = $this->PNGsRGBintentLookup($thisfile_png_chunk_type_text['reindering_intent']);
182                                        break;
183
184
185                                case 'iCCP': // Embedded ICC Profile
186                                        $thisfile_png_chunk_type_text['header']                  = $chunk;
187                                        list($profilename, $compressiondata)                     = explode("\x00", $chunk['data'], 2);
188                                        $thisfile_png_chunk_type_text['profile_name']            = $profilename;
189                                        $thisfile_png_chunk_type_text['compression_method']      = getid3_lib::BigEndian2Int(substr($compressiondata, 0, 1));
190                                        $thisfile_png_chunk_type_text['compression_profile']     = substr($compressiondata, 1);
191
192                                        $thisfile_png_chunk_type_text['compression_method_text'] = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['compression_method']);
193                                        break;
194
195
196                                case 'tEXt': // Textual Data
197                                        $thisfile_png_chunk_type_text['header']  = $chunk;
198                                        list($keyword, $text) = explode("\x00", $chunk['data'], 2);
199                                        $thisfile_png_chunk_type_text['keyword'] = $keyword;
200                                        $thisfile_png_chunk_type_text['text']    = $text;
201
202                                        $thisfile_png['comments'][$thisfile_png_chunk_type_text['keyword']][] = $thisfile_png_chunk_type_text['text'];
203                                        break;
204
205
206                                case 'zTXt': // Compressed Textual Data
207                                        $thisfile_png_chunk_type_text['header']                  = $chunk;
208                                        list($keyword, $otherdata)                               = explode("\x00", $chunk['data'], 2);
209                                        $thisfile_png_chunk_type_text['keyword']                 = $keyword;
210                                        $thisfile_png_chunk_type_text['compression_method']      = getid3_lib::BigEndian2Int(substr($otherdata, 0, 1));
211                                        $thisfile_png_chunk_type_text['compressed_text']         = substr($otherdata, 1);
212                                        $thisfile_png_chunk_type_text['compression_method_text'] = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['compression_method']);
213                                        switch ($thisfile_png_chunk_type_text['compression_method']) {
214                                                case 0:
215                                                        $thisfile_png_chunk_type_text['text']            = gzuncompress($thisfile_png_chunk_type_text['compressed_text']);
216                                                        break;
217
218                                                default:
219                                                        // unknown compression method
220                                                        break;
221                                        }
222
223                                        if (isset($thisfile_png_chunk_type_text['text'])) {
224                                                $thisfile_png['comments'][$thisfile_png_chunk_type_text['keyword']][] = $thisfile_png_chunk_type_text['text'];
225                                        }
226                                        break;
227
228
229                                case 'iTXt': // International Textual Data
230                                        $thisfile_png_chunk_type_text['header']                  = $chunk;
231                                        list($keyword, $otherdata)                               = explode("\x00", $chunk['data'], 2);
232                                        $thisfile_png_chunk_type_text['keyword']                 = $keyword;
233                                        $thisfile_png_chunk_type_text['compression']             = (bool) getid3_lib::BigEndian2Int(substr($otherdata, 0, 1));
234                                        $thisfile_png_chunk_type_text['compression_method']      = getid3_lib::BigEndian2Int(substr($otherdata, 1, 1));
235                                        $thisfile_png_chunk_type_text['compression_method_text'] = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['compression_method']);
236                                        list($languagetag, $translatedkeyword, $text)                        = explode("\x00", substr($otherdata, 2), 3);
237                                        $thisfile_png_chunk_type_text['language_tag']            = $languagetag;
238                                        $thisfile_png_chunk_type_text['translated_keyword']      = $translatedkeyword;
239
240                                        if ($thisfile_png_chunk_type_text['compression']) {
241
242                                                switch ($thisfile_png_chunk_type_text['compression_method']) {
243                                                        case 0:
244                                                                $thisfile_png_chunk_type_text['text']        = gzuncompress($text);
245                                                                break;
246
247                                                        default:
248                                                                // unknown compression method
249                                                                break;
250                                                }
251
252                                        } else {
253
254                                                $thisfile_png_chunk_type_text['text']                = $text;
255
256                                        }
257
258                                        if (isset($thisfile_png_chunk_type_text['text'])) {
259                                                $thisfile_png['comments'][$thisfile_png_chunk_type_text['keyword']][] = $thisfile_png_chunk_type_text['text'];
260                                        }
261                                        break;
262
263
264                                case 'bKGD': // Background Color
265                                        $thisfile_png_chunk_type_text['header']                   = $chunk;
266                                        switch ($thisfile_png['IHDR']['raw']['color_type']) {
267                                                case 0:
268                                                case 4:
269                                                        $thisfile_png_chunk_type_text['background_gray']  = getid3_lib::BigEndian2Int($chunk['data']);
270                                                        break;
271
272                                                case 2:
273                                                case 6:
274                                                        $thisfile_png_chunk_type_text['background_red']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 0 * $thisfile_png['IHDR']['raw']['bit_depth'], $thisfile_png['IHDR']['raw']['bit_depth']));
275                                                        $thisfile_png_chunk_type_text['background_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1 * $thisfile_png['IHDR']['raw']['bit_depth'], $thisfile_png['IHDR']['raw']['bit_depth']));
276                                                        $thisfile_png_chunk_type_text['background_blue']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 2 * $thisfile_png['IHDR']['raw']['bit_depth'], $thisfile_png['IHDR']['raw']['bit_depth']));
277                                                        break;
278
279                                                case 3:
280                                                        $thisfile_png_chunk_type_text['background_index'] = getid3_lib::BigEndian2Int($chunk['data']);
281                                                        break;
282
283                                                default:
284                                                        break;
285                                        }
286                                        break;
287
288
289                                case 'pHYs': // Physical Pixel Dimensions
290                                        $thisfile_png_chunk_type_text['header']                 = $chunk;
291                                        $thisfile_png_chunk_type_text['pixels_per_unit_x']      = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4));
292                                        $thisfile_png_chunk_type_text['pixels_per_unit_y']      = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4));
293                                        $thisfile_png_chunk_type_text['unit_specifier']         = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 1));
294                                        $thisfile_png_chunk_type_text['unit']                   = $this->PNGpHYsUnitLookup($thisfile_png_chunk_type_text['unit_specifier']);
295                                        break;
296
297
298                                case 'sBIT': // Significant Bits
299                                        $thisfile_png_chunk_type_text['header'] = $chunk;
300                                        switch ($thisfile_png['IHDR']['raw']['color_type']) {
301                                                case 0:
302                                                        $thisfile_png_chunk_type_text['significant_bits_gray']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1));
303                                                        break;
304
305                                                case 2:
306                                                case 3:
307                                                        $thisfile_png_chunk_type_text['significant_bits_red']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1));
308                                                        $thisfile_png_chunk_type_text['significant_bits_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1));
309                                                        $thisfile_png_chunk_type_text['significant_bits_blue']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 1));
310                                                        break;
311
312                                                case 4:
313                                                        $thisfile_png_chunk_type_text['significant_bits_gray']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1));
314                                                        $thisfile_png_chunk_type_text['significant_bits_alpha'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1));
315                                                        break;
316
317                                                case 6:
318                                                        $thisfile_png_chunk_type_text['significant_bits_red']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1));
319                                                        $thisfile_png_chunk_type_text['significant_bits_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1));
320                                                        $thisfile_png_chunk_type_text['significant_bits_blue']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 1));
321                                                        $thisfile_png_chunk_type_text['significant_bits_alpha'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 3, 1));
322                                                        break;
323
324                                                default:
325                                                        break;
326                                        }
327                                        break;
328
329
330                                case 'sPLT': // Suggested Palette
331                                        $thisfile_png_chunk_type_text['header']                           = $chunk;
332                                        list($palettename, $otherdata)                                    = explode("\x00", $chunk['data'], 2);
333                                        $thisfile_png_chunk_type_text['palette_name']                     = $palettename;
334                                        $sPLToffset = 0;
335                                        $thisfile_png_chunk_type_text['sample_depth_bits']                = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, 1));
336                                        $sPLToffset += 1;
337                                        $thisfile_png_chunk_type_text['sample_depth_bytes']               = $thisfile_png_chunk_type_text['sample_depth_bits'] / 8;
338                                        $paletteCounter = 0;
339                                        while ($sPLToffset < strlen($otherdata)) {
340                                                $thisfile_png_chunk_type_text['red'][$paletteCounter]       = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes']));
341                                                $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes'];
342                                                $thisfile_png_chunk_type_text['green'][$paletteCounter]     = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes']));
343                                                $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes'];
344                                                $thisfile_png_chunk_type_text['blue'][$paletteCounter]      = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes']));
345                                                $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes'];
346                                                $thisfile_png_chunk_type_text['alpha'][$paletteCounter]     = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes']));
347                                                $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes'];
348                                                $thisfile_png_chunk_type_text['frequency'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, 2));
349                                                $sPLToffset += 2;
350                                                $paletteCounter++;
351                                        }
352                                        break;
353
354
355                                case 'hIST': // Palette Histogram
356                                        $thisfile_png_chunk_type_text['header'] = $chunk;
357                                        $hISTcounter = 0;
358                                        while ($hISTcounter < strlen($chunk['data'])) {
359                                                $thisfile_png_chunk_type_text[$hISTcounter] = getid3_lib::BigEndian2Int(substr($chunk['data'], $hISTcounter / 2, 2));
360                                                $hISTcounter += 2;
361                                        }
362                                        break;
363
364
365                                case 'tIME': // Image Last-Modification Time
366                                        $thisfile_png_chunk_type_text['header'] = $chunk;
367                                        $thisfile_png_chunk_type_text['year']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2));
368                                        $thisfile_png_chunk_type_text['month']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 1));
369                                        $thisfile_png_chunk_type_text['day']    = getid3_lib::BigEndian2Int(substr($chunk['data'], 3, 1));
370                                        $thisfile_png_chunk_type_text['hour']   = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 1));
371                                        $thisfile_png_chunk_type_text['minute'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 5, 1));
372                                        $thisfile_png_chunk_type_text['second'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 6, 1));
373                                        $thisfile_png_chunk_type_text['unix']   = gmmktime($thisfile_png_chunk_type_text['hour'], $thisfile_png_chunk_type_text['minute'], $thisfile_png_chunk_type_text['second'], $thisfile_png_chunk_type_text['month'], $thisfile_png_chunk_type_text['day'], $thisfile_png_chunk_type_text['year']);
374                                        break;
375
376
377                                case 'oFFs': // Image Offset
378                                        $thisfile_png_chunk_type_text['header']         = $chunk;
379                                        $thisfile_png_chunk_type_text['position_x']     = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4), false, true);
380                                        $thisfile_png_chunk_type_text['position_y']     = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4), false, true);
381                                        $thisfile_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 1));
382                                        $thisfile_png_chunk_type_text['unit']           = $this->PNGoFFsUnitLookup($thisfile_png_chunk_type_text['unit_specifier']);
383                                        break;
384
385
386                                case 'pCAL': // Calibration Of Pixel Values
387                                        $thisfile_png_chunk_type_text['header']             = $chunk;
388                                        list($calibrationname, $otherdata)                              = explode("\x00", $chunk['data'], 2);
389                                        $thisfile_png_chunk_type_text['calibration_name']   = $calibrationname;
390                                        $pCALoffset = 0;
391                                        $thisfile_png_chunk_type_text['original_zero']      = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 4), false, true);
392                                        $pCALoffset += 4;
393                                        $thisfile_png_chunk_type_text['original_max']       = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 4), false, true);
394                                        $pCALoffset += 4;
395                                        $thisfile_png_chunk_type_text['equation_type']      = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 1));
396                                        $pCALoffset += 1;
397                                        $thisfile_png_chunk_type_text['equation_type_text'] = $this->PNGpCALequationTypeLookup($thisfile_png_chunk_type_text['equation_type']);
398                                        $thisfile_png_chunk_type_text['parameter_count']    = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 1));
399                                        $pCALoffset += 1;
400                                        $thisfile_png_chunk_type_text['parameters']         = explode("\x00", substr($chunk['data'], $pCALoffset));
401                                        break;
402
403
404                                case 'sCAL': // Physical Scale Of Image Subject
405                                        $thisfile_png_chunk_type_text['header']         = $chunk;
406                                        $thisfile_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1));
407                                        $thisfile_png_chunk_type_text['unit']           = $this->PNGsCALUnitLookup($thisfile_png_chunk_type_text['unit_specifier']);
408                                        list($pixelwidth, $pixelheight)                             = explode("\x00", substr($chunk['data'], 1));
409                                        $thisfile_png_chunk_type_text['pixel_width']    = $pixelwidth;
410                                        $thisfile_png_chunk_type_text['pixel_height']   = $pixelheight;
411                                        break;
412
413
414                                case 'gIFg': // GIF Graphic Control Extension
415                                        $gIFgCounter = 0;
416                                        if (isset($thisfile_png_chunk_type_text) && is_array($thisfile_png_chunk_type_text)) {
417                                                $gIFgCounter = count($thisfile_png_chunk_type_text);
418                                        }
419                                        $thisfile_png_chunk_type_text[$gIFgCounter]['header']          = $chunk;
420                                        $thisfile_png_chunk_type_text[$gIFgCounter]['disposal_method'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1));
421                                        $thisfile_png_chunk_type_text[$gIFgCounter]['user_input_flag'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1));
422                                        $thisfile_png_chunk_type_text[$gIFgCounter]['delay_time']      = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 2));
423                                        break;
424
425
426                                case 'gIFx': // GIF Application Extension
427                                        $gIFxCounter = 0;
428                                        if (isset($thisfile_png_chunk_type_text) && is_array($thisfile_png_chunk_type_text)) {
429                                                $gIFxCounter = count($thisfile_png_chunk_type_text);
430                                        }
431                                        $thisfile_png_chunk_type_text[$gIFxCounter]['header']                 = $chunk;
432                                        $thisfile_png_chunk_type_text[$gIFxCounter]['application_identifier'] = substr($chunk['data'],  0, 8);
433                                        $thisfile_png_chunk_type_text[$gIFxCounter]['authentication_code']    = substr($chunk['data'],  8, 3);
434                                        $thisfile_png_chunk_type_text[$gIFxCounter]['application_data']       = substr($chunk['data'], 11);
435                                        break;
436
437
438                                case 'IDAT': // Image Data
439                                        $idatinformationfieldindex = 0;
440                                        if (isset($thisfile_png['IDAT']) && is_array($thisfile_png['IDAT'])) {
441                                                $idatinformationfieldindex = count($thisfile_png['IDAT']);
442                                        }
443                                        unset($chunk['data']);
444                                        $thisfile_png_chunk_type_text[$idatinformationfieldindex]['header'] = $chunk;
445                                        break;
446
447                                case 'IEND': // Image Trailer
448                                        $thisfile_png_chunk_type_text['header'] = $chunk;
449                                        break;
450
451                                case 'acTL': // Animation Control chunk
452                                        // https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk
453                                        $thisfile_png['animation']['num_frames'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); // Number of frames
454                                        $thisfile_png['animation']['num_plays']  = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); // Number of times to loop this APNG.  0 indicates infinite looping.
455
456                                        unset($chunk['data']);
457                                        $thisfile_png_chunk_type_text['header'] = $chunk;
458                                        break;
459
460                                case 'fcTL': // Frame Control chunk
461                                        // https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk
462                                        $fcTL = array();
463                                        $fcTL['sequence_number'] = getid3_lib::BigEndian2Int(substr($chunk['data'],  0, 4)); // Sequence number of the animation chunk, starting from 0
464                                        $fcTL['width']           = getid3_lib::BigEndian2Int(substr($chunk['data'],  4, 4)); // Width of the following frame
465                                        $fcTL['height']          = getid3_lib::BigEndian2Int(substr($chunk['data'],  8, 4)); // Height of the following frame
466                                        $fcTL['x_offset']        = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 4)); // X position at which to render the following frame
467                                        $fcTL['y_offset']        = getid3_lib::BigEndian2Int(substr($chunk['data'], 16, 4)); // Y position at which to render the following frame
468                                        $fcTL['delay_num']       = getid3_lib::BigEndian2Int(substr($chunk['data'], 20, 2)); // Frame delay fraction numerator
469                                        $fcTL['delay_den']       = getid3_lib::BigEndian2Int(substr($chunk['data'], 22, 2)); // Frame delay fraction numerator
470                                        $fcTL['dispose_op']      = getid3_lib::BigEndian2Int(substr($chunk['data'], 23, 1)); // Type of frame area disposal to be done after rendering this frame
471                                        $fcTL['blend_op']        = getid3_lib::BigEndian2Int(substr($chunk['data'], 23, 1)); // Type of frame area rendering for this frame
472                                        if ($fcTL['delay_den']) {
473                                                $fcTL['delay'] = $fcTL['delay_num'] / $fcTL['delay_den'];
474                                        }
475                                        $thisfile_png['animation']['fcTL'][$fcTL['sequence_number']] = $fcTL;
476
477                                        unset($chunk['data']);
478                                        $thisfile_png_chunk_type_text['header'] = $chunk;
479                                        break;
480
481                                case 'fdAT': // Frame Data chunk
482                                        // https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk
483                                        // "The `fdAT` chunk has the same purpose as an `IDAT` chunk. It has the same structure as an `IDAT` chunk, except preceded by a sequence number."
484                                        unset($chunk['data']);
485                                        $thisfile_png_chunk_type_text['header'] = $chunk;
486                                        break;
487
488                                default:
489                                        //unset($chunk['data']);
490                                        $thisfile_png_chunk_type_text['header'] = $chunk;
491                                        $this->warning('Unhandled chunk type: '.$chunk['type_text']);
492                                        break;
493                        }
494                }
495                if (!empty($thisfile_png['animation']['num_frames']) && !empty($thisfile_png['animation']['fcTL'])) {
496                        $info['video']['dataformat'] = 'apng';
497                        $info['playtime_seconds'] = 0;
498                        foreach ($thisfile_png['animation']['fcTL'] as $seqno => $fcTL) {
499                                $info['playtime_seconds'] += $fcTL['delay'];
500                        }
501                }
502                return true;
503        }
504
505        /**
506         * @param int $sRGB
507         *
508         * @return string
509         */
510        public function PNGsRGBintentLookup($sRGB) {
511                static $PNGsRGBintentLookup = array(
512                        0 => 'Perceptual',
513                        1 => 'Relative colorimetric',
514                        2 => 'Saturation',
515                        3 => 'Absolute colorimetric'
516                );
517                return (isset($PNGsRGBintentLookup[$sRGB]) ? $PNGsRGBintentLookup[$sRGB] : 'invalid');
518        }
519
520        /**
521         * @param int $compressionmethod
522         *
523         * @return string
524         */
525        public function PNGcompressionMethodLookup($compressionmethod) {
526                static $PNGcompressionMethodLookup = array(
527                        0 => 'deflate/inflate'
528                );
529                return (isset($PNGcompressionMethodLookup[$compressionmethod]) ? $PNGcompressionMethodLookup[$compressionmethod] : 'invalid');
530        }
531
532        /**
533         * @param int $unitid
534         *
535         * @return string
536         */
537        public function PNGpHYsUnitLookup($unitid) {
538                static $PNGpHYsUnitLookup = array(
539                        0 => 'unknown',
540                        1 => 'meter'
541                );
542                return (isset($PNGpHYsUnitLookup[$unitid]) ? $PNGpHYsUnitLookup[$unitid] : 'invalid');
543        }
544
545        /**
546         * @param int $unitid
547         *
548         * @return string
549         */
550        public function PNGoFFsUnitLookup($unitid) {
551                static $PNGoFFsUnitLookup = array(
552                        0 => 'pixel',
553                        1 => 'micrometer'
554                );
555                return (isset($PNGoFFsUnitLookup[$unitid]) ? $PNGoFFsUnitLookup[$unitid] : 'invalid');
556        }
557
558        /**
559         * @param int $equationtype
560         *
561         * @return string
562         */
563        public function PNGpCALequationTypeLookup($equationtype) {
564                static $PNGpCALequationTypeLookup = array(
565                        0 => 'Linear mapping',
566                        1 => 'Base-e exponential mapping',
567                        2 => 'Arbitrary-base exponential mapping',
568                        3 => 'Hyperbolic mapping'
569                );
570                return (isset($PNGpCALequationTypeLookup[$equationtype]) ? $PNGpCALequationTypeLookup[$equationtype] : 'invalid');
571        }
572
573        /**
574         * @param int $unitid
575         *
576         * @return string
577         */
578        public function PNGsCALUnitLookup($unitid) {
579                static $PNGsCALUnitLookup = array(
580                        0 => 'meter',
581                        1 => 'radian'
582                );
583                return (isset($PNGsCALUnitLookup[$unitid]) ? $PNGsCALUnitLookup[$unitid] : 'invalid');
584        }
585
586        /**
587         * @param int $color_type
588         * @param int $bit_depth
589         *
590         * @return int|false
591         */
592        public function IHDRcalculateBitsPerSample($color_type, $bit_depth) {
593                switch ($color_type) {
594                        case 0: // Each pixel is a grayscale sample.
595                                return $bit_depth;
596                                break;
597
598                        case 2: // Each pixel is an R,G,B triple
599                                return 3 * $bit_depth;
600                                break;
601
602                        case 3: // Each pixel is a palette index; a PLTE chunk must appear.
603                                return $bit_depth;
604                                break;
605
606                        case 4: // Each pixel is a grayscale sample, followed by an alpha sample.
607                                return 2 * $bit_depth;
608                                break;
609
610                        case 6: // Each pixel is an R,G,B triple, followed by an alpha sample.
611                                return 4 * $bit_depth;
612                                break;
613                }
614                return false;
615        }
616
617}
Note: See TracBrowser for help on using the repository browser.