Skip to content

Instantly share code, notes, and snippets.

@Prometee
Forked from juban/iOSPNGNormalizer.php
Last active July 28, 2020 10:16
Show Gist options
  • Save Prometee/de1829bece0601f485ab to your computer and use it in GitHub Desktop.
Save Prometee/de1829bece0601f485ab to your computer and use it in GitHub Desktop.
Update script to fit the newest version of the initial python script
<?php
class iOSPNGNormalizer
{
public static function fix($filename, $destfilename = null)
{
try {
$handle = fopen($filename, "rb");
$oldPNG = fread($handle, filesize($filename));
fclose($handle);
$newPng = self::getNormalizedPNG($oldPNG);
if (is_null($destfilename))
$destfilename = $filename;
file_put_contents($destfilename, $newPng);
} catch (Exception $exc) {
return $exc->getMessage();
}
return true;
}
public static function getNormalizedPNG($oldPNG)
{
// Check if the orginal png needs to be processed
$im = @imagecreatefromstring($oldPNG);
if($im !== false)
return $oldPNG;
$pngheader = "\x89PNG\r\n\x1a\n";
if (substr($oldPNG, 0, 8) != $pngheader)
return;
$newPNG = substr($oldPNG, 0, 8);
$chunkPos = 8;
$idatAcc = "";
$breakLoop = false;
while ($chunkPos < strlen($oldPNG)) {
$skip = false;
// Reading chunk
$chunkLength = unpack("N", substr($oldPNG, $chunkPos, $chunkPos + 4));
$chunkLength = array_shift($chunkLength);
$chunkType = substr($oldPNG, $chunkPos + 4, 4);
$chunkData = substr($oldPNG, $chunkPos + 8, $chunkLength);
$chunkCRC = unpack("N", substr($oldPNG, $chunkPos + $chunkLength + 8, 4));
$chunkCRC = array_shift($chunkCRC);
$chunkPos += $chunkLength + 12;
// Reading header chunk
if ($chunkType == 'IHDR') {
$width = unpack("N", substr($chunkData, 0, 4));
$width = array_shift($width);
$height = unpack("N", substr($chunkData, 4, 8));
$height = array_shift($height);
}
// Parsing the image chunk
if ($chunkType == "IDAT") {
// Store the chunk data for later decompression
$idatAcc .= $chunkData;
$skip = true;
}
// Removing CgBI chunk
if ($chunkType == "CgBI") {
$skip = true;
}
// Add all accumulated IDATA chunks
if ($chunkType == 'IEND') {
try {
// Uncompressing the image chunk
$bufSize = $width * $height * 4 + $height;
$chunkData = zlib_decode($idatAcc, $bufSize);
} catch (Exception $exc) {
return $oldPNG; // already optimized
}
$chunkType = "IDAT";
// Swapping red & blue bytes for each pixel
$newdata = "";
for ($y = 0; $y < $height; $y++) {
$i = strlen($newdata);
$newdata .= $chunkData[$i];
for ($x = 0; $x < $width; $x++) {
$i = strlen($newdata);
$newdata .= $chunkData[$i + 2];
$newdata .= $chunkData[$i + 1];
$newdata .= $chunkData[$i + 0];
$newdata .= $chunkData[$i + 3];
}
}
// Compressing the image chunk
$chunkData = $newdata;
$chunkData = zlib_encode($chunkData, ZLIB_ENCODING_DEFLATE);
$chunkLength = strlen($chunkData);
$chunkCRC = crc32($chunkType . $chunkData);
$chunkCRC = ($chunkCRC + 0x100000000) % 0x100000000;
$breakLoop = true;
}
if (!$skip) {
$newPNG .= pack("N", $chunkLength);
$newPNG .= $chunkType;
if ($chunkLength > 0) {
$newPNG .= $chunkData;
$newPNG .= pack("N", $chunkCRC);
}
}
if ($breakLoop) break;
}
return $newPNG;
}
}
@arvindkumar-gr
Copy link

@Prometee Transparent portion of the png turns into black. any solution?

Also, $chunkCRC = ($chunkCRC + 0x100000000) % 0x100000000; getting divisible by zero warning.

I'm into iOS and working on a small tool using PHP(beginner). Help me to resolve these issue.

@afzafri
Copy link

afzafri commented Jul 28, 2020

Thank you so much for this fork. I used the original one but not working. Yours is working great! Thank you

@Prometee
Copy link
Author

Thanks ! I almost forget that I write this 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment