- Timestamp:
- Jul 7, 2009, 10:27:37 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/charlies_content/getid3/getid3/module.graphic.png.php
r3318 r3544 1 1 <?php 2 // +----------------------------------------------------------------------+ 3 // | PHP version 5 | 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 2002-2006 James Heinrich, Allan Hansen | 6 // +----------------------------------------------------------------------+ 7 // | This source file is subject to version 2 of the GPL license, | 8 // | that is bundled with this package in the file license.txt and is | 9 // | available through the world-wide-web at the following url: | 10 // | http://www.gnu.org/copyleft/gpl.html | 11 // +----------------------------------------------------------------------+ 12 // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org | 13 // +----------------------------------------------------------------------+ 14 // | Authors: James Heinrich <infoØgetid3*org> | 15 // | Allan Hansen <ahØartemis*dk> | 16 // +----------------------------------------------------------------------+ 17 // | module.graphic.png.php | 18 // | Module for analyzing PNG graphic files. | 19 // | dependencies: zlib support in PHP (optional) | 20 // +----------------------------------------------------------------------+ 21 // 22 // $Id$ 23 24 25 26 class getid3_png extends getid3_handler 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.graphic.png.php // 11 // module for analyzing PNG Image files // 12 // dependencies: NONE // 13 // /// 14 ///////////////////////////////////////////////////////////////// 15 16 17 class getid3_png 27 18 { 28 19 29 public function Analyze() { 30 31 $getid3 = $this->getid3; 32 33 $getid3->info['png'] = array (); 34 $info_png = &$getid3->info['png']; 35 36 $getid3->info['fileformat'] = 'png'; 37 $getid3->info['video']['dataformat'] = 'png'; 38 $getid3->info['video']['lossless'] = false; 39 40 fseek($getid3->fp, $getid3->info['avdataoffset'], SEEK_SET); 41 $png_filedata = fread($getid3->fp, getid3::FREAD_BUFFER_SIZE); 42 43 // Magic bytes "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A" 44 45 $offset = 8; 46 47 while (((ftell($getid3->fp) - (strlen($png_filedata) - $offset)) < $getid3->info['filesize'])) { 48 49 $chunk['data_length'] = getid3_lib::BigEndian2Int(substr($png_filedata, $offset, 4)); 50 $offset += 4; 51 while (((strlen($png_filedata) - $offset) < ($chunk['data_length'] + 4)) && (ftell($getid3->fp) < $getid3->info['filesize'])) { 52 $png_filedata .= fread($getid3->fp, getid3::FREAD_BUFFER_SIZE); 53 } 54 55 $chunk['type_text'] = substr($png_filedata, $offset, 4); 56 $chunk['type_raw'] = getid3_lib::BigEndian2Int($chunk['type_text']); 57 $offset += 4; 58 59 $chunk['data'] = substr($png_filedata, $offset, $chunk['data_length']); 60 $offset += $chunk['data_length']; 61 62 $chunk['crc'] = getid3_lib::BigEndian2Int(substr($png_filedata, $offset, 4)); 63 $offset += 4; 64 65 $chunk['flags']['ancilliary'] = (bool)($chunk['type_raw'] & 0x20000000); 66 $chunk['flags']['private'] = (bool)($chunk['type_raw'] & 0x00200000); 67 $chunk['flags']['reserved'] = (bool)($chunk['type_raw'] & 0x00002000); 68 $chunk['flags']['safe_to_copy'] = (bool)($chunk['type_raw'] & 0x00000020); 69 70 // shortcut 71 $info_png[$chunk['type_text']] = array (); 72 $info_png_chunk_type_text = &$info_png[$chunk['type_text']]; 73 74 switch ($chunk['type_text']) { 75 76 case 'IHDR': // Image Header 77 $info_png_chunk_type_text['header'] = $chunk; 78 $info_png_chunk_type_text['width'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); 79 $info_png_chunk_type_text['height'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); 80 81 getid3_lib::ReadSequence('BigEndian2Int', $info_png_chunk_type_text['raw'], $chunk['data'], 8, 82 array ( 83 'bit_depth' => 1, 84 'color_type' => 1, 85 'compression_method' => 1, 86 'filter_method' => 1, 87 'interlace_method' => 1 88 ) 89 ); 90 91 $info_png_chunk_type_text['compression_method_text'] = getid3_png::PNGcompressionMethodLookup($info_png_chunk_type_text['raw']['compression_method']); 92 $info_png_chunk_type_text['color_type']['palette'] = (bool)($info_png_chunk_type_text['raw']['color_type'] & 0x01); 93 $info_png_chunk_type_text['color_type']['true_color'] = (bool)($info_png_chunk_type_text['raw']['color_type'] & 0x02); 94 $info_png_chunk_type_text['color_type']['alpha'] = (bool)($info_png_chunk_type_text['raw']['color_type'] & 0x04); 95 96 $getid3->info['video']['resolution_x'] = $info_png_chunk_type_text['width']; 97 $getid3->info['video']['resolution_y'] = $info_png_chunk_type_text['height']; 98 99 $getid3->info['video']['bits_per_sample'] = getid3_png::IHDRcalculateBitsPerSample($info_png_chunk_type_text['raw']['color_type'], $info_png_chunk_type_text['raw']['bit_depth']); 100 break; 101 102 103 case 'PLTE': // Palette 104 $info_png_chunk_type_text['header'] = $chunk; 105 $palette_offset = 0; 106 for ($i = 0; $i <= 255; $i++) { 107 $red = @getid3_lib::BigEndian2Int($chunk['data']{$palette_offset++}); 108 $green = @getid3_lib::BigEndian2Int($chunk['data']{$palette_offset++}); 109 $blue = @getid3_lib::BigEndian2Int($chunk['data']{$palette_offset++}); 110 $info_png_chunk_type_text[$i] = (($red << 16) | ($green << 8) | ($blue)); 111 } 112 break; 113 114 115 case 'tRNS': // Transparency 116 $info_png_chunk_type_text['header'] = $chunk; 117 switch ($info_png['IHDR']['raw']['color_type']) { 118 case 0: 119 $info_png_chunk_type_text['transparent_color_gray'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2)); 120 break; 121 122 case 2: 123 $info_png_chunk_type_text['transparent_color_red'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2)); 124 $info_png_chunk_type_text['transparent_color_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 2)); 125 $info_png_chunk_type_text['transparent_color_blue'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 2)); 126 break; 127 128 case 3: 129 for ($i = 0; $i < strlen($chunk['data']); $i++) { 130 $info_png_chunk_type_text['palette_opacity'][$i] = getid3_lib::BigEndian2Int($chunk['data'][$i]); 131 } 132 break; 133 134 case 4: 135 case 6: 136 throw new getid3_exception('Invalid color_type in tRNS chunk: '.$info_png['IHDR']['raw']['color_type']); 137 138 default: 139 $getid3->warning('Unhandled color_type in tRNS chunk: '.$info_png['IHDR']['raw']['color_type']); 140 break; 141 } 142 break; 143 144 145 case 'gAMA': // Image Gamma 146 $info_png_chunk_type_text['header'] = $chunk; 147 $info_png_chunk_type_text['gamma'] = getid3_lib::BigEndian2Int($chunk['data']) / 100000; 148 break; 149 150 151 case 'cHRM': // Primary Chromaticities 152 $info_png_chunk_type_text['header'] = $chunk; 153 $info_png_chunk_type_text['white_x'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)) / 100000; 154 $info_png_chunk_type_text['white_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)) / 100000; 155 $info_png_chunk_type_text['red_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 4)) / 100000; 156 $info_png_chunk_type_text['red_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 4)) / 100000; 157 $info_png_chunk_type_text['green_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 16, 4)) / 100000; 158 $info_png_chunk_type_text['green_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 20, 4)) / 100000; 159 $info_png_chunk_type_text['blue_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 24, 4)) / 100000; 160 $info_png_chunk_type_text['blue_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 28, 4)) / 100000; 161 break; 162 163 164 case 'sRGB': // Standard RGB Color Space 165 $info_png_chunk_type_text['header'] = $chunk; 166 $info_png_chunk_type_text['reindering_intent'] = getid3_lib::BigEndian2Int($chunk['data']); 167 $info_png_chunk_type_text['reindering_intent_text'] = getid3_png::PNGsRGBintentLookup($info_png_chunk_type_text['reindering_intent']); 168 break; 169 170 171 case 'iCCP': // Embedded ICC Profile 172 $info_png_chunk_type_text['header'] = $chunk; 173 list($profilename, $compressiondata) = explode("\x00", $chunk['data'], 2); 174 $info_png_chunk_type_text['profile_name'] = $profilename; 175 $info_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int($compressiondata[0]); 176 $info_png_chunk_type_text['compression_profile'] = substr($compressiondata, 1); 177 $info_png_chunk_type_text['compression_method_text'] = getid3_png::PNGcompressionMethodLookup($info_png_chunk_type_text['compression_method']); 178 break; 179 180 181 case 'tEXt': // Textual Data 182 $info_png_chunk_type_text['header'] = $chunk; 183 list($keyword, $text) = explode("\x00", $chunk['data'], 2); 184 $info_png_chunk_type_text['keyword'] = $keyword; 185 $info_png_chunk_type_text['text'] = $text; 186 187 $info_png['comments'][$info_png_chunk_type_text['keyword']][] = $info_png_chunk_type_text['text']; 188 break; 189 190 191 case 'zTXt': // Compressed Textual Data 192 $info_png_chunk_type_text['header'] = $chunk; 193 list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2); 194 $info_png_chunk_type_text['keyword'] = $keyword; 195 $info_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($otherdata, 0, 1)); 196 $info_png_chunk_type_text['compressed_text'] = substr($otherdata, 1); 197 $info_png_chunk_type_text['compression_method_text'] = getid3_png::PNGcompressionMethodLookup($info_png_chunk_type_text['compression_method']); 198 199 if ($info_png_chunk_type_text['compression_method'] != 0) { 200 // unknown compression method 201 break; 202 } 203 204 if (function_exists('gzuncompress')) { 205 $info_png_chunk_type_text['text'] = gzuncompress($info_png_chunk_type_text['compressed_text']); 206 } 207 else { 208 if (!@$this->zlib_warning) { 209 $getid3->warning('PHP does not have --with-zlib support - cannot gzuncompress()'); 210 } 211 $this->zlib_warning = true; 212 } 213 214 215 if (isset($info_png_chunk_type_text['text'])) { 216 $info_png['comments'][$info_png_chunk_type_text['keyword']][] = $info_png_chunk_type_text['text']; 217 } 218 break; 219 220 221 case 'iTXt': // International Textual Data 222 $info_png_chunk_type_text['header'] = $chunk; 223 list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2); 224 $info_png_chunk_type_text['keyword'] = $keyword; 225 $info_png_chunk_type_text['compression'] = (bool)getid3_lib::BigEndian2Int(substr($otherdata, 0, 1)); 226 $info_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int($otherdata[1]); 227 $info_png_chunk_type_text['compression_method_text'] = getid3_png::PNGcompressionMethodLookup($info_png_chunk_type_text['compression_method']); 228 list($languagetag, $translatedkeyword, $text) = explode("\x00", substr($otherdata, 2), 3); 229 $info_png_chunk_type_text['language_tag'] = $languagetag; 230 $info_png_chunk_type_text['translated_keyword'] = $translatedkeyword; 231 232 if ($info_png_chunk_type_text['compression']) { 233 234 switch ($info_png_chunk_type_text['compression_method']) { 235 case 0: 236 if (function_exists('gzuncompress')) { 237 $info_png_chunk_type_text['text'] = gzuncompress($text); 238 } 239 else { 240 if (!@$this->zlib_warning) { 241 $getid3->warning('PHP does not have --with-zlib support - cannot gzuncompress()'); 242 } 243 $this->zlib_warning = true; 244 } 245 break; 246 247 default: 248 // unknown compression method 249 break; 250 } 251 252 } else { 253 254 $info_png_chunk_type_text['text'] = $text; 255 256 } 257 258 if (isset($info_png_chunk_type_text['text'])) { 259 $info_png['comments'][$info_png_chunk_type_text['keyword']][] = $info_png_chunk_type_text['text']; 260 } 261 break; 262 263 264 case 'bKGD': // Background Color 265 $info_png_chunk_type_text['header'] = $chunk; 266 switch ($info_png['IHDR']['raw']['color_type']) { 267 case 0: 268 case 4: 269 $info_png_chunk_type_text['background_gray'] = getid3_lib::BigEndian2Int($chunk['data']); 270 break; 271 272 case 2: 273 case 6: 274 $info_png_chunk_type_text['background_red'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0 * $info_png['IHDR']['raw']['bit_depth'], $info_png['IHDR']['raw']['bit_depth'])); 275 $info_png_chunk_type_text['background_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1 * $info_png['IHDR']['raw']['bit_depth'], $info_png['IHDR']['raw']['bit_depth'])); 276 $info_png_chunk_type_text['background_blue'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2 * $info_png['IHDR']['raw']['bit_depth'], $info_png['IHDR']['raw']['bit_depth'])); 277 break; 278 279 case 3: 280 $info_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 $info_png_chunk_type_text['header'] = $chunk; 291 $info_png_chunk_type_text['pixels_per_unit_x'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); 292 $info_png_chunk_type_text['pixels_per_unit_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); 293 $info_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 1)); 294 $info_png_chunk_type_text['unit'] = getid3_png::PNGpHYsUnitLookup($info_png_chunk_type_text['unit_specifier']); 295 break; 296 297 298 case 'sBIT': // Significant Bits 299 $info_png_chunk_type_text['header'] = $chunk; 300 switch ($info_png['IHDR']['raw']['color_type']) { 301 case 0: 302 $info_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 $info_png_chunk_type_text['significant_bits_red'] = getid3_lib::BigEndian2Int($chunk['data'][0]); 308 $info_png_chunk_type_text['significant_bits_green'] = getid3_lib::BigEndian2Int($chunk['data'][1]); 309 $info_png_chunk_type_text['significant_bits_blue'] = getid3_lib::BigEndian2Int($chunk['data'][2]); 310 break; 311 312 case 4: 313 $info_png_chunk_type_text['significant_bits_gray'] = getid3_lib::BigEndian2Int($chunk['data'][0]); 314 $info_png_chunk_type_text['significant_bits_alpha'] = getid3_lib::BigEndian2Int($chunk['data'][1]); 315 break; 316 317 case 6: 318 $info_png_chunk_type_text['significant_bits_red'] = getid3_lib::BigEndian2Int($chunk['data'][0]); 319 $info_png_chunk_type_text['significant_bits_green'] = getid3_lib::BigEndian2Int($chunk['data'][1]); 320 $info_png_chunk_type_text['significant_bits_blue'] = getid3_lib::BigEndian2Int($chunk['data'][2]); 321 $info_png_chunk_type_text['significant_bits_alpha'] = getid3_lib::BigEndian2Int($chunk['data'][3]); 322 break; 323 324 default: 325 break; 326 } 327 break; 328 329 330 case 'sPLT': // Suggested Palette 331 $info_png_chunk_type_text['header'] = $chunk; 332 333 list($palettename, $otherdata) = explode("\x00", $chunk['data'], 2); 334 $info_png_chunk_type_text['palette_name'] = $palettename; 335 336 $info_png_chunk_type_text['sample_depth_bits'] = getid3_lib::BigEndian2Int($otherdata[0]); 337 $info_png_chunk_type_text['sample_depth_bytes'] = $info_png_chunk_type_text['sample_depth_bits'] / 8; 338 339 $s_plt_offset = 1; 340 $paletteCounter = 0; 341 while ($s_plt_offset < strlen($otherdata)) { 342 343 $info_png_chunk_type_text['red'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $s_plt_offset, $info_png_chunk_type_text['sample_depth_bytes'])); 344 $s_plt_offset += $info_png_chunk_type_text['sample_depth_bytes']; 345 346 $info_png_chunk_type_text['green'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $s_plt_offset, $info_png_chunk_type_text['sample_depth_bytes'])); 347 $s_plt_offset += $info_png_chunk_type_text['sample_depth_bytes']; 348 349 $info_png_chunk_type_text['blue'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $s_plt_offset, $info_png_chunk_type_text['sample_depth_bytes'])); 350 $s_plt_offset += $info_png_chunk_type_text['sample_depth_bytes']; 351 352 $info_png_chunk_type_text['alpha'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $s_plt_offset, $info_png_chunk_type_text['sample_depth_bytes'])); 353 $s_plt_offset += $info_png_chunk_type_text['sample_depth_bytes']; 354 355 $info_png_chunk_type_text['frequency'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $s_plt_offset, 2)); 356 $s_plt_offset += 2; 357 358 $paletteCounter++; 359 } 360 break; 361 362 363 case 'hIST': // Palette Histogram 364 $info_png_chunk_type_text['header'] = $chunk; 365 $h_ist_counter = 0; 366 while ($h_ist_counter < strlen($chunk['data'])) { 367 $info_png_chunk_type_text[$h_ist_counter] = getid3_lib::BigEndian2Int(substr($chunk['data'], $h_ist_counter / 2, 2)); 368 $h_ist_counter += 2; 369 } 370 break; 371 372 373 case 'tIME': // Image Last-Modification Time 374 $info_png_chunk_type_text['header'] = $chunk; 375 $info_png_chunk_type_text['year'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2)); 376 $info_png_chunk_type_text['month'] = getid3_lib::BigEndian2Int($chunk['data']{2}); 377 $info_png_chunk_type_text['day'] = getid3_lib::BigEndian2Int($chunk['data']{3}); 378 $info_png_chunk_type_text['hour'] = getid3_lib::BigEndian2Int($chunk['data']{4}); 379 $info_png_chunk_type_text['minute'] = getid3_lib::BigEndian2Int($chunk['data']{5}); 380 $info_png_chunk_type_text['second'] = getid3_lib::BigEndian2Int($chunk['data']{6}); 381 $info_png_chunk_type_text['unix'] = gmmktime($info_png_chunk_type_text['hour'], $info_png_chunk_type_text['minute'], $info_png_chunk_type_text['second'], $info_png_chunk_type_text['month'], $info_png_chunk_type_text['day'], $info_png_chunk_type_text['year']); 382 break; 383 384 385 case 'oFFs': // Image Offset 386 $info_png_chunk_type_text['header'] = $chunk; 387 $info_png_chunk_type_text['position_x'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4), false, true); 388 $info_png_chunk_type_text['position_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4), false, true); 389 $info_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int($chunk['data'][8]); 390 $info_png_chunk_type_text['unit'] = getid3_png::PNGoFFsUnitLookup($info_png_chunk_type_text['unit_specifier']); 391 break; 392 393 394 case 'pCAL': // Calibration Of Pixel Values 395 $info_png_chunk_type_text['header'] = $chunk; 396 list($calibrationname, $otherdata) = explode("\x00", $chunk['data'], 2); 397 $info_png_chunk_type_text['calibration_name'] = $calibrationname; 398 $info_png_chunk_type_text['original_zero'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4), false, true); 399 $info_png_chunk_type_text['original_max'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4), false, true); 400 $info_png_chunk_type_text['equation_type'] = getid3_lib::BigEndian2Int($chunk['data'][8]); 401 $info_png_chunk_type_text['equation_type_text'] = getid3_png::PNGpCALequationTypeLookup($info_png_chunk_type_text['equation_type']); 402 $info_png_chunk_type_text['parameter_count'] = getid3_lib::BigEndian2Int($chunk['data'][9]); 403 $info_png_chunk_type_text['parameters'] = explode("\x00", substr($chunk['data'], 10)); 404 break; 405 406 407 case 'sCAL': // Physical Scale Of Image Subject 408 $info_png_chunk_type_text['header'] = $chunk; 409 $info_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1)); 410 $info_png_chunk_type_text['unit'] = getid3_png::PNGsCALUnitLookup($info_png_chunk_type_text['unit_specifier']); 411 list($info_png_chunk_type_text['pixel_width'], $info_png_chunk_type_text['pixel_height']) = explode("\x00", substr($chunk['data'], 1)); 412 break; 413 414 415 case 'gIFg': // GIF Graphic Control Extension 416 $gIFg_counter = 0; 417 if (isset($info_png_chunk_type_text) && is_array($info_png_chunk_type_text)) { 418 $gIFg_counter = count($info_png_chunk_type_text); 419 } 420 $info_png_chunk_type_text[$gIFg_counter]['header'] = $chunk; 421 $info_png_chunk_type_text[$gIFg_counter]['disposal_method'] = getid3_lib::BigEndian2Int($chunk['data'][0]); 422 $info_png_chunk_type_text[$gIFg_counter]['user_input_flag'] = getid3_lib::BigEndian2Int($chunk['data'][1]); 423 $info_png_chunk_type_text[$gIFg_counter]['delay_time'] = getid3_lib::BigEndian2Int($chunk['data'][2]); 424 break; 425 426 427 case 'gIFx': // GIF Application Extension 428 $gIFx_counter = 0; 429 if (isset($info_png_chunk_type_text) && is_array($info_png_chunk_type_text)) { 430 $gIFx_counter = count($info_png_chunk_type_text); 431 } 432 $info_png_chunk_type_text[$gIFx_counter]['header'] = $chunk; 433 $info_png_chunk_type_text[$gIFx_counter]['application_identifier'] = substr($chunk['data'], 0, 8); 434 $info_png_chunk_type_text[$gIFx_counter]['authentication_code'] = substr($chunk['data'], 8, 3); 435 $info_png_chunk_type_text[$gIFx_counter]['application_data'] = substr($chunk['data'], 11); 436 break; 437 438 439 case 'IDAT': // Image Data 440 $idat_information_field_index = 0; 441 if (isset($info_png['IDAT']) && is_array($info_png['IDAT'])) { 442 $idat_information_field_index = count($info_png['IDAT']); 443 } 444 unset($chunk['data']); 445 $info_png_chunk_type_text[$idat_information_field_index]['header'] = $chunk; 446 break; 447 448 449 case 'IEND': // Image Trailer 450 $info_png_chunk_type_text['header'] = $chunk; 451 break; 452 453 454 default: 455 $info_png_chunk_type_text['header'] = $chunk; 456 $getid3->warning('Unhandled chunk type: '.$chunk['type_text']); 457 break; 458 } 459 } 460 461 return true; 462 } 463 464 465 466 public static function PNGsRGBintentLookup($sRGB) { 467 468 static $lookup = array ( 469 0 => 'Perceptual', 470 1 => 'Relative colorimetric', 471 2 => 'Saturation', 472 3 => 'Absolute colorimetric' 473 ); 474 return (isset($lookup[$sRGB]) ? $lookup[$sRGB] : 'invalid'); 475 } 476 477 478 479 public static function PNGcompressionMethodLookup($compression_method) { 480 481 return ($compression_method == 0 ? 'deflate/inflate' : 'invalid'); 482 } 483 484 485 486 public static function PNGpHYsUnitLookup($unit_id) { 487 488 static $lookup = array ( 489 0 => 'unknown', 490 1 => 'meter' 491 ); 492 return (isset($lookup[$unit_id]) ? $lookup[$unit_id] : 'invalid'); 493 } 494 495 496 497 public static function PNGoFFsUnitLookup($unit_id) { 498 499 static $lookup = array ( 500 0 => 'pixel', 501 1 => 'micrometer' 502 ); 503 return (isset($lookup[$unit_id]) ? $lookup[$unit_id] : 'invalid'); 504 } 505 506 507 508 public static function PNGpCALequationTypeLookup($equation_type) { 509 510 static $lookup = array ( 511 0 => 'Linear mapping', 512 1 => 'Base-e exponential mapping', 513 2 => 'Arbitrary-base exponential mapping', 514 3 => 'Hyperbolic mapping' 515 ); 516 return (isset($lookup[$equation_type]) ? $lookup[$equation_type] : 'invalid'); 517 } 518 519 520 521 public static function PNGsCALUnitLookup($unit_id) { 522 523 static $lookup = array ( 524 0 => 'meter', 525 1 => 'radian' 526 ); 527 return (isset($lookup[$unit_id]) ? $lookup[$unit_id] : 'invalid'); 528 } 529 530 531 532 public static function IHDRcalculateBitsPerSample($color_type, $bit_depth) { 533 534 switch ($color_type) { 535 case 0: // Each pixel is a grayscale sample. 536 return $bit_depth; 537 538 case 2: // Each pixel is an R,G,B triple 539 return 3 * $bit_depth; 540 541 case 3: // Each pixel is a palette index; a PLTE chunk must appear. 542 return $bit_depth; 543 544 case 4: // Each pixel is a grayscale sample, followed by an alpha sample. 545 return 2 * $bit_depth; 546 547 case 6: // Each pixel is an R,G,B triple, followed by an alpha sample. 548 return 4 * $bit_depth; 549 } 550 return false; 551 } 20 function getid3_png(&$fd, &$ThisFileInfo) { 21 22 // shortcut 23 $ThisFileInfo['png'] = array(); 24 $thisfile_png = &$ThisFileInfo['png']; 25 26 $ThisFileInfo['fileformat'] = 'png'; 27 $ThisFileInfo['video']['dataformat'] = 'png'; 28 $ThisFileInfo['video']['lossless'] = false; 29 30 fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET); 31 $PNGfiledata = fread($fd, GETID3_FREAD_BUFFER_SIZE); 32 $offset = 0; 33 34 $PNGidentifier = substr($PNGfiledata, $offset, 8); // $89 $50 $4E $47 $0D $0A $1A $0A 35 $offset += 8; 36 37 if ($PNGidentifier != "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") { 38 $ThisFileInfo['error'][] = 'First 8 bytes of file ('.getid3_lib::PrintHexBytes($PNGidentifier).') did not match expected PNG identifier'; 39 unset($ThisFileInfo['fileformat']); 40 return false; 41 } 42 43 while (((ftell($fd) - (strlen($PNGfiledata) - $offset)) < $ThisFileInfo['filesize'])) { 44 $chunk['data_length'] = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4)); 45 $offset += 4; 46 while (((strlen($PNGfiledata) - $offset) < ($chunk['data_length'] + 4)) && (ftell($fd) < $ThisFileInfo['filesize'])) { 47 $PNGfiledata .= fread($fd, GETID3_FREAD_BUFFER_SIZE); 48 } 49 $chunk['type_text'] = substr($PNGfiledata, $offset, 4); 50 $offset += 4; 51 $chunk['type_raw'] = getid3_lib::BigEndian2Int($chunk['type_text']); 52 $chunk['data'] = substr($PNGfiledata, $offset, $chunk['data_length']); 53 $offset += $chunk['data_length']; 54 $chunk['crc'] = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4)); 55 $offset += 4; 56 57 $chunk['flags']['ancilliary'] = (bool) ($chunk['type_raw'] & 0x20000000); 58 $chunk['flags']['private'] = (bool) ($chunk['type_raw'] & 0x00200000); 59 $chunk['flags']['reserved'] = (bool) ($chunk['type_raw'] & 0x00002000); 60 $chunk['flags']['safe_to_copy'] = (bool) ($chunk['type_raw'] & 0x00000020); 61 62 // shortcut 63 $thisfile_png[$chunk['type_text']] = array(); 64 $thisfile_png_chunk_type_text = &$thisfile_png[$chunk['type_text']]; 65 66 switch ($chunk['type_text']) { 67 68 case 'IHDR': // Image Header 69 $thisfile_png_chunk_type_text['header'] = $chunk; 70 $thisfile_png_chunk_type_text['width'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); 71 $thisfile_png_chunk_type_text['height'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); 72 $thisfile_png_chunk_type_text['raw']['bit_depth'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 1)); 73 $thisfile_png_chunk_type_text['raw']['color_type'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 9, 1)); 74 $thisfile_png_chunk_type_text['raw']['compression_method'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 10, 1)); 75 $thisfile_png_chunk_type_text['raw']['filter_method'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 11, 1)); 76 $thisfile_png_chunk_type_text['raw']['interlace_method'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 1)); 77 78 $thisfile_png_chunk_type_text['compression_method_text'] = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['raw']['compression_method']); 79 $thisfile_png_chunk_type_text['color_type']['palette'] = (bool) ($thisfile_png_chunk_type_text['raw']['color_type'] & 0x01); 80 $thisfile_png_chunk_type_text['color_type']['true_color'] = (bool) ($thisfile_png_chunk_type_text['raw']['color_type'] & 0x02); 81 $thisfile_png_chunk_type_text['color_type']['alpha'] = (bool) ($thisfile_png_chunk_type_text['raw']['color_type'] & 0x04); 82 83 $ThisFileInfo['video']['resolution_x'] = $thisfile_png_chunk_type_text['width']; 84 $ThisFileInfo['video']['resolution_y'] = $thisfile_png_chunk_type_text['height']; 85 86 $ThisFileInfo['video']['bits_per_sample'] = $this->IHDRcalculateBitsPerSample($thisfile_png_chunk_type_text['raw']['color_type'], $thisfile_png_chunk_type_text['raw']['bit_depth']); 87 break; 88 89 90 case 'PLTE': // Palette 91 $thisfile_png_chunk_type_text['header'] = $chunk; 92 $paletteoffset = 0; 93 for ($i = 0; $i <= 255; $i++) { 94 //$thisfile_png_chunk_type_text['red'][$i] = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1)); 95 //$thisfile_png_chunk_type_text['green'][$i] = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1)); 96 //$thisfile_png_chunk_type_text['blue'][$i] = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1)); 97 $red = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1)); 98 $green = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1)); 99 $blue = getid3_lib::BigEndian2Int(substr($chunk['data'], $paletteoffset++, 1)); 100 $thisfile_png_chunk_type_text[$i] = (($red << 16) | ($green << 8) | ($blue)); 101 } 102 break; 103 104 105 case 'tRNS': // Transparency 106 $thisfile_png_chunk_type_text['header'] = $chunk; 107 switch ($thisfile_png['IHDR']['raw']['color_type']) { 108 case 0: 109 $thisfile_png_chunk_type_text['transparent_color_gray'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2)); 110 break; 111 112 case 2: 113 $thisfile_png_chunk_type_text['transparent_color_red'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2)); 114 $thisfile_png_chunk_type_text['transparent_color_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 2)); 115 $thisfile_png_chunk_type_text['transparent_color_blue'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 2)); 116 break; 117 118 case 3: 119 for ($i = 0; $i < strlen($chunk['data']); $i++) { 120 $thisfile_png_chunk_type_text['palette_opacity'][$i] = getid3_lib::BigEndian2Int(substr($chunk['data'], $i, 1)); 121 } 122 break; 123 124 case 4: 125 case 6: 126 $ThisFileInfo['error'][] = 'Invalid color_type in tRNS chunk: '.$thisfile_png['IHDR']['raw']['color_type']; 127 128 default: 129 $ThisFileInfo['warning'][] = 'Unhandled color_type in tRNS chunk: '.$thisfile_png['IHDR']['raw']['color_type']; 130 break; 131 } 132 break; 133 134 135 case 'gAMA': // Image Gamma 136 $thisfile_png_chunk_type_text['header'] = $chunk; 137 $thisfile_png_chunk_type_text['gamma'] = getid3_lib::BigEndian2Int($chunk['data']) / 100000; 138 break; 139 140 141 case 'cHRM': // Primary Chromaticities 142 $thisfile_png_chunk_type_text['header'] = $chunk; 143 $thisfile_png_chunk_type_text['white_x'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)) / 100000; 144 $thisfile_png_chunk_type_text['white_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)) / 100000; 145 $thisfile_png_chunk_type_text['red_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 4)) / 100000; 146 $thisfile_png_chunk_type_text['red_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 4)) / 100000; 147 $thisfile_png_chunk_type_text['green_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 16, 4)) / 100000; 148 $thisfile_png_chunk_type_text['green_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 20, 4)) / 100000; 149 $thisfile_png_chunk_type_text['blue_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 24, 4)) / 100000; 150 $thisfile_png_chunk_type_text['blue_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 28, 4)) / 100000; 151 break; 152 153 154 case 'sRGB': // Standard RGB Color Space 155 $thisfile_png_chunk_type_text['header'] = $chunk; 156 $thisfile_png_chunk_type_text['reindering_intent'] = getid3_lib::BigEndian2Int($chunk['data']); 157 $thisfile_png_chunk_type_text['reindering_intent_text'] = $this->PNGsRGBintentLookup($thisfile_png_chunk_type_text['reindering_intent']); 158 break; 159 160 161 case 'iCCP': // Embedded ICC Profile 162 $thisfile_png_chunk_type_text['header'] = $chunk; 163 list($profilename, $compressiondata) = explode("\x00", $chunk['data'], 2); 164 $thisfile_png_chunk_type_text['profile_name'] = $profilename; 165 $thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($compressiondata, 0, 1)); 166 $thisfile_png_chunk_type_text['compression_profile'] = substr($compressiondata, 1); 167 168 $thisfile_png_chunk_type_text['compression_method_text'] = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['compression_method']); 169 break; 170 171 172 case 'tEXt': // Textual Data 173 $thisfile_png_chunk_type_text['header'] = $chunk; 174 list($keyword, $text) = explode("\x00", $chunk['data'], 2); 175 $thisfile_png_chunk_type_text['keyword'] = $keyword; 176 $thisfile_png_chunk_type_text['text'] = $text; 177 178 $thisfile_png['comments'][$thisfile_png_chunk_type_text['keyword']][] = $thisfile_png_chunk_type_text['text']; 179 break; 180 181 182 case 'zTXt': // Compressed Textual Data 183 $thisfile_png_chunk_type_text['header'] = $chunk; 184 list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2); 185 $thisfile_png_chunk_type_text['keyword'] = $keyword; 186 $thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($otherdata, 0, 1)); 187 $thisfile_png_chunk_type_text['compressed_text'] = substr($otherdata, 1); 188 $thisfile_png_chunk_type_text['compression_method_text'] = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['compression_method']); 189 switch ($thisfile_png_chunk_type_text['compression_method']) { 190 case 0: 191 $thisfile_png_chunk_type_text['text'] = gzuncompress($thisfile_png_chunk_type_text['compressed_text']); 192 break; 193 194 default: 195 // unknown compression method 196 break; 197 } 198 199 if (isset($thisfile_png_chunk_type_text['text'])) { 200 $thisfile_png['comments'][$thisfile_png_chunk_type_text['keyword']][] = $thisfile_png_chunk_type_text['text']; 201 } 202 break; 203 204 205 case 'iTXt': // International Textual Data 206 $thisfile_png_chunk_type_text['header'] = $chunk; 207 list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2); 208 $thisfile_png_chunk_type_text['keyword'] = $keyword; 209 $thisfile_png_chunk_type_text['compression'] = (bool) getid3_lib::BigEndian2Int(substr($otherdata, 0, 1)); 210 $thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($otherdata, 1, 1)); 211 $thisfile_png_chunk_type_text['compression_method_text'] = $this->PNGcompressionMethodLookup($thisfile_png_chunk_type_text['compression_method']); 212 list($languagetag, $translatedkeyword, $text) = explode("\x00", substr($otherdata, 2), 3); 213 $thisfile_png_chunk_type_text['language_tag'] = $languagetag; 214 $thisfile_png_chunk_type_text['translated_keyword'] = $translatedkeyword; 215 216 if ($thisfile_png_chunk_type_text['compression']) { 217 218 switch ($thisfile_png_chunk_type_text['compression_method']) { 219 case 0: 220 $thisfile_png_chunk_type_text['text'] = gzuncompress($text); 221 break; 222 223 default: 224 // unknown compression method 225 break; 226 } 227 228 } else { 229 230 $thisfile_png_chunk_type_text['text'] = $text; 231 232 } 233 234 if (isset($thisfile_png_chunk_type_text['text'])) { 235 $thisfile_png['comments'][$thisfile_png_chunk_type_text['keyword']][] = $thisfile_png_chunk_type_text['text']; 236 } 237 break; 238 239 240 case 'bKGD': // Background Color 241 $thisfile_png_chunk_type_text['header'] = $chunk; 242 switch ($thisfile_png['IHDR']['raw']['color_type']) { 243 case 0: 244 case 4: 245 $thisfile_png_chunk_type_text['background_gray'] = getid3_lib::BigEndian2Int($chunk['data']); 246 break; 247 248 case 2: 249 case 6: 250 $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'])); 251 $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'])); 252 $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'])); 253 break; 254 255 case 3: 256 $thisfile_png_chunk_type_text['background_index'] = getid3_lib::BigEndian2Int($chunk['data']); 257 break; 258 259 default: 260 break; 261 } 262 break; 263 264 265 case 'pHYs': // Physical Pixel Dimensions 266 $thisfile_png_chunk_type_text['header'] = $chunk; 267 $thisfile_png_chunk_type_text['pixels_per_unit_x'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); 268 $thisfile_png_chunk_type_text['pixels_per_unit_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); 269 $thisfile_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 1)); 270 $thisfile_png_chunk_type_text['unit'] = $this->PNGpHYsUnitLookup($thisfile_png_chunk_type_text['unit_specifier']); 271 break; 272 273 274 case 'sBIT': // Significant Bits 275 $thisfile_png_chunk_type_text['header'] = $chunk; 276 switch ($thisfile_png['IHDR']['raw']['color_type']) { 277 case 0: 278 $thisfile_png_chunk_type_text['significant_bits_gray'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1)); 279 break; 280 281 case 2: 282 case 3: 283 $thisfile_png_chunk_type_text['significant_bits_red'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1)); 284 $thisfile_png_chunk_type_text['significant_bits_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1)); 285 $thisfile_png_chunk_type_text['significant_bits_blue'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 1)); 286 break; 287 288 case 4: 289 $thisfile_png_chunk_type_text['significant_bits_gray'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1)); 290 $thisfile_png_chunk_type_text['significant_bits_alpha'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1)); 291 break; 292 293 case 6: 294 $thisfile_png_chunk_type_text['significant_bits_red'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1)); 295 $thisfile_png_chunk_type_text['significant_bits_green'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1)); 296 $thisfile_png_chunk_type_text['significant_bits_blue'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 1)); 297 $thisfile_png_chunk_type_text['significant_bits_alpha'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 3, 1)); 298 break; 299 300 default: 301 break; 302 } 303 break; 304 305 306 case 'sPLT': // Suggested Palette 307 $thisfile_png_chunk_type_text['header'] = $chunk; 308 list($palettename, $otherdata) = explode("\x00", $chunk['data'], 2); 309 $thisfile_png_chunk_type_text['palette_name'] = $palettename; 310 $sPLToffset = 0; 311 $thisfile_png_chunk_type_text['sample_depth_bits'] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, 1)); 312 $sPLToffset += 1; 313 $thisfile_png_chunk_type_text['sample_depth_bytes'] = $thisfile_png_chunk_type_text['sample_depth_bits'] / 8; 314 $paletteCounter = 0; 315 while ($sPLToffset < strlen($otherdata)) { 316 $thisfile_png_chunk_type_text['red'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes'])); 317 $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes']; 318 $thisfile_png_chunk_type_text['green'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes'])); 319 $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes']; 320 $thisfile_png_chunk_type_text['blue'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes'])); 321 $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes']; 322 $thisfile_png_chunk_type_text['alpha'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, $thisfile_png_chunk_type_text['sample_depth_bytes'])); 323 $sPLToffset += $thisfile_png_chunk_type_text['sample_depth_bytes']; 324 $thisfile_png_chunk_type_text['frequency'][$paletteCounter] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, 2)); 325 $sPLToffset += 2; 326 $paletteCounter++; 327 } 328 break; 329 330 331 case 'hIST': // Palette Histogram 332 $thisfile_png_chunk_type_text['header'] = $chunk; 333 $hISTcounter = 0; 334 while ($hISTcounter < strlen($chunk['data'])) { 335 $thisfile_png_chunk_type_text[$hISTcounter] = getid3_lib::BigEndian2Int(substr($chunk['data'], $hISTcounter / 2, 2)); 336 $hISTcounter += 2; 337 } 338 break; 339 340 341 case 'tIME': // Image Last-Modification Time 342 $thisfile_png_chunk_type_text['header'] = $chunk; 343 $thisfile_png_chunk_type_text['year'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 2)); 344 $thisfile_png_chunk_type_text['month'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 1)); 345 $thisfile_png_chunk_type_text['day'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 3, 1)); 346 $thisfile_png_chunk_type_text['hour'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 1)); 347 $thisfile_png_chunk_type_text['minute'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 5, 1)); 348 $thisfile_png_chunk_type_text['second'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 6, 1)); 349 $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']); 350 break; 351 352 353 case 'oFFs': // Image Offset 354 $thisfile_png_chunk_type_text['header'] = $chunk; 355 $thisfile_png_chunk_type_text['position_x'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4), false, true); 356 $thisfile_png_chunk_type_text['position_y'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4), false, true); 357 $thisfile_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 1)); 358 $thisfile_png_chunk_type_text['unit'] = $this->PNGoFFsUnitLookup($thisfile_png_chunk_type_text['unit_specifier']); 359 break; 360 361 362 case 'pCAL': // Calibration Of Pixel Values 363 $thisfile_png_chunk_type_text['header'] = $chunk; 364 list($calibrationname, $otherdata) = explode("\x00", $chunk['data'], 2); 365 $thisfile_png_chunk_type_text['calibration_name'] = $calibrationname; 366 $pCALoffset = 0; 367 $thisfile_png_chunk_type_text['original_zero'] = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 4), false, true); 368 $pCALoffset += 4; 369 $thisfile_png_chunk_type_text['original_max'] = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 4), false, true); 370 $pCALoffset += 4; 371 $thisfile_png_chunk_type_text['equation_type'] = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 1)); 372 $pCALoffset += 1; 373 $thisfile_png_chunk_type_text['equation_type_text'] = $this->PNGpCALequationTypeLookup($thisfile_png_chunk_type_text['equation_type']); 374 $thisfile_png_chunk_type_text['parameter_count'] = getid3_lib::BigEndian2Int(substr($chunk['data'], $pCALoffset, 1)); 375 $pCALoffset += 1; 376 $thisfile_png_chunk_type_text['parameters'] = explode("\x00", substr($chunk['data'], $pCALoffset)); 377 break; 378 379 380 case 'sCAL': // Physical Scale Of Image Subject 381 $thisfile_png_chunk_type_text['header'] = $chunk; 382 $thisfile_png_chunk_type_text['unit_specifier'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1)); 383 $thisfile_png_chunk_type_text['unit'] = $this->PNGsCALUnitLookup($thisfile_png_chunk_type_text['unit_specifier']); 384 list($pixelwidth, $pixelheight) = explode("\x00", substr($chunk['data'], 1)); 385 $thisfile_png_chunk_type_text['pixel_width'] = $pixelwidth; 386 $thisfile_png_chunk_type_text['pixel_height'] = $pixelheight; 387 break; 388 389 390 case 'gIFg': // GIF Graphic Control Extension 391 $gIFgCounter = 0; 392 if (isset($thisfile_png_chunk_type_text) && is_array($thisfile_png_chunk_type_text)) { 393 $gIFgCounter = count($thisfile_png_chunk_type_text); 394 } 395 $thisfile_png_chunk_type_text[$gIFgCounter]['header'] = $chunk; 396 $thisfile_png_chunk_type_text[$gIFgCounter]['disposal_method'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 1)); 397 $thisfile_png_chunk_type_text[$gIFgCounter]['user_input_flag'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 1, 1)); 398 $thisfile_png_chunk_type_text[$gIFgCounter]['delay_time'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 2, 2)); 399 break; 400 401 402 case 'gIFx': // GIF Application Extension 403 $gIFxCounter = 0; 404 if (isset($thisfile_png_chunk_type_text) && is_array($thisfile_png_chunk_type_text)) { 405 $gIFxCounter = count($thisfile_png_chunk_type_text); 406 } 407 $thisfile_png_chunk_type_text[$gIFxCounter]['header'] = $chunk; 408 $thisfile_png_chunk_type_text[$gIFxCounter]['application_identifier'] = substr($chunk['data'], 0, 8); 409 $thisfile_png_chunk_type_text[$gIFxCounter]['authentication_code'] = substr($chunk['data'], 8, 3); 410 $thisfile_png_chunk_type_text[$gIFxCounter]['application_data'] = substr($chunk['data'], 11); 411 break; 412 413 414 case 'IDAT': // Image Data 415 $idatinformationfieldindex = 0; 416 if (isset($thisfile_png['IDAT']) && is_array($thisfile_png['IDAT'])) { 417 $idatinformationfieldindex = count($thisfile_png['IDAT']); 418 } 419 unset($chunk['data']); 420 $thisfile_png_chunk_type_text[$idatinformationfieldindex]['header'] = $chunk; 421 break; 422 423 424 case 'IEND': // Image Trailer 425 $thisfile_png_chunk_type_text['header'] = $chunk; 426 break; 427 428 429 default: 430 //unset($chunk['data']); 431 $thisfile_png_chunk_type_text['header'] = $chunk; 432 $ThisFileInfo['warning'][] = 'Unhandled chunk type: '.$chunk['type_text']; 433 break; 434 } 435 } 436 437 return true; 438 } 439 440 function PNGsRGBintentLookup($sRGB) { 441 static $PNGsRGBintentLookup = array( 442 0 => 'Perceptual', 443 1 => 'Relative colorimetric', 444 2 => 'Saturation', 445 3 => 'Absolute colorimetric' 446 ); 447 return (isset($PNGsRGBintentLookup[$sRGB]) ? $PNGsRGBintentLookup[$sRGB] : 'invalid'); 448 } 449 450 function PNGcompressionMethodLookup($compressionmethod) { 451 static $PNGcompressionMethodLookup = array( 452 0 => 'deflate/inflate' 453 ); 454 return (isset($PNGcompressionMethodLookup[$compressionmethod]) ? $PNGcompressionMethodLookup[$compressionmethod] : 'invalid'); 455 } 456 457 function PNGpHYsUnitLookup($unitid) { 458 static $PNGpHYsUnitLookup = array( 459 0 => 'unknown', 460 1 => 'meter' 461 ); 462 return (isset($PNGpHYsUnitLookup[$unitid]) ? $PNGpHYsUnitLookup[$unitid] : 'invalid'); 463 } 464 465 function PNGoFFsUnitLookup($unitid) { 466 static $PNGoFFsUnitLookup = array( 467 0 => 'pixel', 468 1 => 'micrometer' 469 ); 470 return (isset($PNGoFFsUnitLookup[$unitid]) ? $PNGoFFsUnitLookup[$unitid] : 'invalid'); 471 } 472 473 function PNGpCALequationTypeLookup($equationtype) { 474 static $PNGpCALequationTypeLookup = array( 475 0 => 'Linear mapping', 476 1 => 'Base-e exponential mapping', 477 2 => 'Arbitrary-base exponential mapping', 478 3 => 'Hyperbolic mapping' 479 ); 480 return (isset($PNGpCALequationTypeLookup[$equationtype]) ? $PNGpCALequationTypeLookup[$equationtype] : 'invalid'); 481 } 482 483 function PNGsCALUnitLookup($unitid) { 484 static $PNGsCALUnitLookup = array( 485 0 => 'meter', 486 1 => 'radian' 487 ); 488 return (isset($PNGsCALUnitLookup[$unitid]) ? $PNGsCALUnitLookup[$unitid] : 'invalid'); 489 } 490 491 function IHDRcalculateBitsPerSample($color_type, $bit_depth) { 492 switch ($color_type) { 493 case 0: // Each pixel is a grayscale sample. 494 return $bit_depth; 495 break; 496 497 case 2: // Each pixel is an R,G,B triple 498 return 3 * $bit_depth; 499 break; 500 501 case 3: // Each pixel is a palette index; a PLTE chunk must appear. 502 return $bit_depth; 503 break; 504 505 case 4: // Each pixel is a grayscale sample, followed by an alpha sample. 506 return 2 * $bit_depth; 507 break; 508 509 case 6: // Each pixel is an R,G,B triple, followed by an alpha sample. 510 return 4 * $bit_depth; 511 break; 512 } 513 return false; 514 } 552 515 553 516 }
Note: See TracChangeset
for help on using the changeset viewer.