Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP iOS PNG normalizer. This PHP class can be used to convert an iOS compressed PNG (CgBI format files) back to the standard format. Requires PHP 5.4 or greater. Credit goes to Axel E. Brzostowski for the original Python version of this script: http://www.axelbrz.com.ar/?mod=iphone-png-images-normalizer
<?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;
while ($chunkPos < strlen($oldPNG)) {
// 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);
}
// Reading image chunk
if ($chunkType == 'IDAT') {
try {
// Uncompressing the image chunk
$bufSize = $width * $height * 4 + $height;
$chunkData = zlib_decode($chunkData, $bufSize);
} catch (Exception $exc) {
return $oldPNG; // already optimized
}
// 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;
}
if ($chunkType != 'CgBI') {
$newPNG .= pack("N", $chunkLength);
$newPNG .= $chunkType;
if ($chunkLength > 0)
$newPNG .= $chunkData;
$newPNG .= pack("N", $chunkCRC);
}
// Reading header chunk
if ($chunkType == 'IEND') {
break;
}
}
return $newPNG;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.