/** * Extract info from a PNG file without using the GD library. * @param $file (string) image file to parse * @return array structure containing the image data * @public static */ public static function _parsepng($file) { $f = @fopen($file, 'rb'); if ($f === false) { // Can't open image file return false; } //Check signature if (fread($f, 8) != chr(137) . 'PNG' . chr(13) . chr(10) . chr(26) . chr(10)) { // Not a PNG file return false; } //Read header chunk fread($f, 4); if (fread($f, 4) != 'IHDR') { //Incorrect PNG file return false; } $w = TCPDF_STATIC::_freadint($f); $h = TCPDF_STATIC::_freadint($f); $bpc = ord(fread($f, 1)); $ct = ord(fread($f, 1)); if ($ct == 0) { $colspace = 'DeviceGray'; } elseif ($ct == 2) { $colspace = 'DeviceRGB'; } elseif ($ct == 3) { $colspace = 'Indexed'; } else { // alpha channel fclose($f); return 'pngalpha'; } if (ord(fread($f, 1)) != 0) { // Unknown compression method fclose($f); return false; } if (ord(fread($f, 1)) != 0) { // Unknown filter method fclose($f); return false; } if (ord(fread($f, 1)) != 0) { // Interlacing not supported fclose($f); return false; } fread($f, 4); $channels = $ct == 2 ? 3 : 1; $parms = '/DecodeParms << /Predictor 15 /Colors ' . $channels . ' /BitsPerComponent ' . $bpc . ' /Columns ' . $w . ' >>'; //Scan chunks looking for palette, transparency and image data $pal = ''; $trns = ''; $data = ''; $icc = false; do { $n = TCPDF_STATIC::_freadint($f); $type = fread($f, 4); if ($type == 'PLTE') { // read palette $pal = TCPDF_STATIC::rfread($f, $n); fread($f, 4); } elseif ($type == 'tRNS') { // read transparency info $t = TCPDF_STATIC::rfread($f, $n); if ($ct == 0) { // DeviceGray $trns = array(ord($t[1])); } elseif ($ct == 2) { // DeviceRGB $trns = array(ord($t[1]), ord($t[3]), ord($t[5])); } else { // Indexed if ($n > 0) { $trns = array(); for ($i = 0; $i < $n; ++$i) { $trns[] = ord($t[$i]); } } } fread($f, 4); } elseif ($type == 'IDAT') { // read image data block $data .= TCPDF_STATIC::rfread($f, $n); fread($f, 4); } elseif ($type == 'iCCP') { // skip profile name $len = 0; while (ord(fread($f, 1)) != 0 and $len < 80) { ++$len; } // get compression method if (ord(fread($f, 1)) != 0) { // Unknown filter method fclose($f); return false; } // read ICC Color Profile $icc = TCPDF_STATIC::rfread($f, $n - $len - 2); // decompress profile $icc = gzuncompress($icc); fread($f, 4); } elseif ($type == 'IEND') { break; } else { TCPDF_STATIC::rfread($f, $n + 4); } } while ($n); if ($colspace == 'Indexed' and empty($pal)) { // Missing palette fclose($f); return false; } fclose($f); return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data); }