mirror of
https://github.com/Karaka-Management/Resources.git
synced 2026-01-11 05:18:40 +00:00
fix png image embed
This commit is contained in:
parent
937fa14da3
commit
e29901ab09
|
|
@ -456,12 +456,32 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
$pngalpha = true;
|
$pngalpha = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ct < 4 && strpos($data, 'tRNS') !== false) {
|
$chunkTypes = [];
|
||||||
|
$p = 8;
|
||||||
|
do {
|
||||||
|
$n = $this->fourBytesToInt(substr($data, $p, 4));
|
||||||
|
$p += 4;
|
||||||
|
$type = substr($data, $p, 4);
|
||||||
|
if ($type === 'IEND') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!preg_match('/[a-zA-Z]{4}/', $type)) {
|
||||||
|
return $this->imageError($file, $firsttime, 'Error parsing PNG image data');
|
||||||
|
}
|
||||||
|
$p += 4;
|
||||||
|
$chunkTypes[$type][] = [
|
||||||
|
'bytes' => $n,
|
||||||
|
'data' => substr($data, $p, $n)
|
||||||
|
];
|
||||||
|
$p += $n + 4;
|
||||||
|
} while ($n);
|
||||||
|
|
||||||
|
if ($ct < 4 && \array_key_exists('tRNS', $chunkTypes)) {
|
||||||
$errpng = 'transparency';
|
$errpng = 'transparency';
|
||||||
$pngalpha = true;
|
$pngalpha = true;
|
||||||
} // mPDF 6
|
} // mPDF 6
|
||||||
|
|
||||||
if ($ct === 3 && strpos($data, 'iCCP') !== false) {
|
if ($ct === 3 && \array_key_exists('iCCP', $chunkTypes)) {
|
||||||
$errpng = 'indexed plus ICC';
|
$errpng = 'indexed plus ICC';
|
||||||
} // mPDF 6
|
} // mPDF 6
|
||||||
|
|
||||||
|
|
@ -479,12 +499,11 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
$errpng = 'interlaced file';
|
$errpng = 'interlaced file';
|
||||||
}
|
}
|
||||||
|
|
||||||
$j = strpos($data, 'pHYs');
|
if (array_key_exists('pHYs', $chunkTypes)) {
|
||||||
if ($j) {
|
|
||||||
//Read resolution
|
//Read resolution
|
||||||
$unitSp = ord(substr($data, $j + 12, 1));
|
$unitSp = ord(substr($chunkTypes['pHYs'][0]['data'], 8, 1));
|
||||||
if ($unitSp === 1) {
|
if ($unitSp === 1) {
|
||||||
$ppUx = $this->fourBytesToInt(substr($data, $j + 4, 4)); // horizontal pixels per meter, usually set to zero
|
$ppUx = $this->fourBytesToInt(substr($chunkTypes['pHYs'][0]['data'], 0, 4)); // horizontal pixels per meter, usually set to zero
|
||||||
$ppUx = round($ppUx / 1000 * 25.4);
|
$ppUx = round($ppUx / 1000 * 25.4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -492,9 +511,8 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
// mPDF 6 Gamma correction
|
// mPDF 6 Gamma correction
|
||||||
$gamma = 0;
|
$gamma = 0;
|
||||||
$gAMA = 0;
|
$gAMA = 0;
|
||||||
$j = strpos($data, 'gAMA');
|
if (array_key_exists('gAMA', $chunkTypes) && array_key_exists('sRGB', $chunkTypes)) { // sRGB colorspace - overrides gAMA
|
||||||
if ($j && strpos($data, 'sRGB') === false) { // sRGB colorspace - overrides gAMA
|
$gAMA = $this->fourBytesToInt($chunkTypes['gAMA'][0]['data']); // Gamma value times 100000
|
||||||
$gAMA = $this->fourBytesToInt(substr($data, $j + 4, 4)); // Gamma value times 100000
|
|
||||||
$gAMA /= 100000;
|
$gAMA /= 100000;
|
||||||
|
|
||||||
// http://www.libpng.org/pub/png/spec/1.2/PNG-Encoders.html
|
// http://www.libpng.org/pub/png/spec/1.2/PNG-Encoders.html
|
||||||
|
|
@ -585,10 +603,8 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
// mPDF 6
|
// mPDF 6
|
||||||
if ($colspace === 'Indexed') { // generate Alpha channel values from tRNS
|
if ($colspace === 'Indexed') { // generate Alpha channel values from tRNS
|
||||||
// Read transparency info
|
// Read transparency info
|
||||||
$p = strpos($data, 'tRNS');
|
if (array_key_exists('tRNS', $chunkTypes)) {
|
||||||
if ($p) {
|
$transparency = $chunkTypes['tRNS'][0]['data'];
|
||||||
$n = $this->fourBytesToInt(substr($data, $p - 4, 4));
|
|
||||||
$transparency = substr($data, $p + 4, $n);
|
|
||||||
// ord($transparency[$index]) = the alpha value for that index
|
// ord($transparency[$index]) = the alpha value for that index
|
||||||
// generate alpha channel
|
// generate alpha channel
|
||||||
for ($ypx = 0; $ypx < $h; ++$ypx) {
|
for ($ypx = 0; $ypx < $h; ++$ypx) {
|
||||||
|
|
@ -607,11 +623,9 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
}
|
}
|
||||||
} elseif ($ct === 0 || $ct === 2) { // generate Alpha channel values from tRNS
|
} elseif ($ct === 0 || $ct === 2) { // generate Alpha channel values from tRNS
|
||||||
// Get transparency as array of RGB
|
// Get transparency as array of RGB
|
||||||
$p = strpos($data, 'tRNS');
|
if (\array_key_exists('tRNS', $chunkTypes)) {
|
||||||
if ($p) {
|
|
||||||
$trns = '';
|
$trns = '';
|
||||||
$n = $this->fourBytesToInt(substr($data, $p - 4, 4));
|
$t = $chunkTypes['tRNS'][0]['data'];
|
||||||
$t = substr($data, $p + 4, $n);
|
|
||||||
if ($colspace === 'DeviceGray') { // ct===0
|
if ($colspace === 'DeviceGray') { // ct===0
|
||||||
$trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
|
$trns = [$this->translateValue(substr($t, 0, 2), $bpc)];
|
||||||
} else /* $colspace=='DeviceRGB' */ { // ct==2
|
} else /* $colspace=='DeviceRGB' */ { // ct==2
|
||||||
|
|
@ -716,26 +730,8 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
// No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc)
|
// No alpha/transparency set (but cannot read directly because e.g. bit-depth != 8, interlaced etc)
|
||||||
// ICC profile
|
// ICC profile
|
||||||
$icc = false;
|
$icc = false;
|
||||||
$p = strpos($data, 'iCCP');
|
if (array_key_exists('iCCP', $chunkTypes) && $colspace === "Indexed") { // Cannot have ICC profile and Indexed together
|
||||||
if ($p && $colspace === "Indexed") { // Cannot have ICC profile and Indexed together
|
$icc = $this->getICCP($chunkTypes['iCCP'][0]['data']);
|
||||||
$p += 4;
|
|
||||||
$n = $this->fourBytesToInt(substr($data, ($p - 8), 4));
|
|
||||||
$nullsep = strpos(substr($data, $p, 80), chr(0));
|
|
||||||
$icc = substr($data, ($p + $nullsep + 2), ($n - ($nullsep + 2)));
|
|
||||||
$icc = @gzuncompress($icc); // Ignored if fails
|
|
||||||
if ($icc) {
|
|
||||||
if (substr($icc, 36, 4) !== 'acsp') {
|
|
||||||
$icc = false;
|
|
||||||
} // invalid ICC profile
|
|
||||||
else {
|
|
||||||
$input = substr($icc, 16, 4);
|
|
||||||
$output = substr($icc, 20, 4);
|
|
||||||
// Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
|
|
||||||
if ($input !== 'RGB ' || $output !== 'XYZ ') {
|
|
||||||
$icc = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Convert to RGB colorspace so can use ICC Profile
|
// Convert to RGB colorspace so can use ICC Profile
|
||||||
if ($icc) {
|
if ($icc) {
|
||||||
imagepalettetotruecolor($im);
|
imagepalettetotruecolor($im);
|
||||||
|
|
@ -783,68 +779,25 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
|
|
||||||
$parms = '/DecodeParms <</Predictor 15 /Colors ' . $channels . ' /BitsPerComponent ' . $bpc . ' /Columns ' . $w . '>>';
|
$parms = '/DecodeParms <</Predictor 15 /Colors ' . $channels . ' /BitsPerComponent ' . $bpc . ' /Columns ' . $w . '>>';
|
||||||
//Scan chunks looking for palette, transparency and image data
|
//Scan chunks looking for palette, transparency and image data
|
||||||
$pal = '';
|
$pal = \array_key_exists('PLTE', $chunkTypes) ? $chunkTypes['PLTE'][0]['data'] : '';
|
||||||
$trns = '';
|
$trns = '';
|
||||||
$pngdata = '';
|
if (array_key_exists('tRNS', $chunkTypes)) {
|
||||||
$icc = false;
|
$t = $chunkTypes['tRNS'][0]['data'];
|
||||||
$p = 33;
|
if ($ct === 0) {
|
||||||
|
$trns = [ord(substr($t, 1, 1))];
|
||||||
do {
|
} elseif ($ct === 2) {
|
||||||
$n = $this->fourBytesToInt(substr($data, $p, 4));
|
$trns = [ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))];
|
||||||
$p += 4;
|
|
||||||
$type = substr($data, $p, 4);
|
|
||||||
$p += 4;
|
|
||||||
if ($type === 'PLTE') {
|
|
||||||
//Read palette
|
|
||||||
$pal = substr($data, $p, $n);
|
|
||||||
$p += $n;
|
|
||||||
$p += 4;
|
|
||||||
} elseif ($type === 'tRNS') {
|
|
||||||
//Read transparency info
|
|
||||||
$t = substr($data, $p, $n);
|
|
||||||
$p += $n;
|
|
||||||
if ($ct === 0) {
|
|
||||||
$trns = [ord(substr($t, 1, 1))];
|
|
||||||
} elseif ($ct === 2) {
|
|
||||||
$trns = [ord(substr($t, 1, 1)), ord(substr($t, 3, 1)), ord(substr($t, 5, 1))];
|
|
||||||
} else {
|
|
||||||
$pos = strpos($t, chr(0));
|
|
||||||
if (is_int($pos)) {
|
|
||||||
$trns = [$pos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$p += 4;
|
|
||||||
} elseif ($type === 'IDAT') {
|
|
||||||
$pngdata.=substr($data, $p, $n);
|
|
||||||
$p += $n;
|
|
||||||
$p += 4;
|
|
||||||
} elseif ($type === 'iCCP') {
|
|
||||||
$nullsep = strpos(substr($data, $p, 80), chr(0));
|
|
||||||
$icc = substr($data, $p + $nullsep + 2, $n - ($nullsep + 2));
|
|
||||||
$icc = @gzuncompress($icc); // Ignored if fails
|
|
||||||
if ($icc) {
|
|
||||||
if (substr($icc, 36, 4) !== 'acsp') {
|
|
||||||
$icc = false;
|
|
||||||
} // invalid ICC profile
|
|
||||||
else {
|
|
||||||
$input = substr($icc, 16, 4);
|
|
||||||
$output = substr($icc, 20, 4);
|
|
||||||
// Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
|
|
||||||
if ($input !== 'RGB ' || $output !== 'XYZ ') {
|
|
||||||
$icc = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$p += $n;
|
|
||||||
$p += 4;
|
|
||||||
} elseif ($type === 'IEND') {
|
|
||||||
break;
|
|
||||||
} elseif (preg_match('/[a-zA-Z]{4}/', $type)) {
|
|
||||||
$p += $n + 4;
|
|
||||||
} else {
|
} else {
|
||||||
return $this->imageError($file, $firsttime, 'Error parsing PNG image data');
|
$pos = strpos($t, chr(0));
|
||||||
|
if (is_int($pos)) {
|
||||||
|
$trns = [$pos];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while ($n);
|
}
|
||||||
|
|
||||||
|
$pngdata = implode('', array_column($chunkTypes['IDAT'], 'data'));
|
||||||
|
$icc = array_key_exists('iCCP', $chunkTypes) ? $this->getICCP($chunkTypes['iCCP'][0]['data']) : false;
|
||||||
|
|
||||||
if (!$pngdata) {
|
if (!$pngdata) {
|
||||||
return $this->imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found');
|
return $this->imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found');
|
||||||
}
|
}
|
||||||
|
|
@ -1080,6 +1033,27 @@ class ImageProcessor implements \Psr\Log\LoggerAwareInterface
|
||||||
return $this->imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
|
return $this->imageError($file, $firsttime, 'Error parsing image file - image type not recognised');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getICCP($data)
|
||||||
|
{
|
||||||
|
$nullsep = strpos(substr($data, 0, 79), chr(0));
|
||||||
|
$icc = @gzuncompress(substr($data, ($nullsep + 2))); // Ignored if fails
|
||||||
|
if ($icc) {
|
||||||
|
if (substr($icc, 36, 4) !== 'acsp') {
|
||||||
|
$icc = false;
|
||||||
|
} // invalid ICC profile
|
||||||
|
else {
|
||||||
|
$input = substr($icc, 16, 4);
|
||||||
|
$output = substr($icc, 20, 4);
|
||||||
|
// Ignore Color profiles for conversion to other colorspaces e.g. CMYK/Lab
|
||||||
|
if ($input !== 'RGB ' || $output !== 'XYZ ') {
|
||||||
|
$icc = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $icc;
|
||||||
|
}
|
||||||
|
|
||||||
private function convertImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask, $gamma_correction = false, $pngcolortype = false)
|
private function convertImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask, $gamma_correction = false, $pngcolortype = false)
|
||||||
{
|
{
|
||||||
if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
|
if ($this->mpdf->PDFA || $this->mpdf->PDFX) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user