<?php
function blp_blob($im, $has_alpha = false)
{
$data = '';
// write pixel data
$width = imagesx($im);
$height = imagesy($im);
for ($y = 0; $y < $height; ++$y) {
for ($x = 0; $x < $width; ++$x) {
$index = imagecolorat($im, $x, $y);
$data .= pack('C', $index);
}
}
for ($y = 0; $has_alpha && $y < $height; ++$y) {
for ($x = 0; $x < $width; ++$x) {
$index = imagecolorat($im, $x, $y);
$color = imagecolorsforindex($im, $index);
$alpha = $color['alpha'] * 2;
if ($alpha > 255) {
$alpha = 255;
}
$data .= pack('C', 255 - $alpha);
}
}
return $data;
}
function blp_copypaletteimg($im, $width, $height)
{
$resized = imagecreate($width, $height);
imagepalettecopy($resized, $im);
$transparent_index = imagecolortransparent($im);
if ($transparent_index >= 0) {
// GIF
imagefill($resized, 0, 0, $transparent_index);
imagecolortransparent($resized, $transparent_index);
imagetruecolortopalette($resized, true, 256);
} else {
// PNG
imagealphablending($resized, true);
imagesavealpha($resized, true);
$transparent = imagecolorallocatealpha($resized, 255, 255, 255, 127);
imagefilledrectangle($resized, 0, 0, $width, $height, $transparent);
}
imagecopyresampled(
$resized,
$im,
0,
0,
0,
0,
$width,
$height,
$width,
$height
);
return $resized;
}
function blp_create_paletted($filename, $output)
{
list($width, $height, $type, $attr) = @getimagesize($filename);
if (!isset($type)) {
return false;
}
switch ($type) {
case IMAGETYPE_JPEG:
$im = imagecreatefromjpeg($filename);
break;
case IMAGETYPE_PNG:
$im = imagecreatefrompng($filename);
break;
case IMAGETYPE_BMP:
$im = imagecreatefrombmp($filename);
break;
case IMAGETYPE_GIF:
$im = imagecreatefromgif($filename);
break;
default:
return false;
}
$original = $im;
$im = blp_copypaletteimg($im, $width, $height);
imagecolormatch($original, $im);
imagedestroy($original);
$palette_data = '';
$palette_size = imagecolorstotal($im);
$has_alpha = false;
// write color palette
for ($c = 0; $c < 256; ++$c) {
$col =
$c < $palette_size
? imagecolorsforindex($im, $c)
: ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 0];
$palette_data .= pack('C', intval($col['blue']));
$palette_data .= pack('C', intval($col['green']));
$palette_data .= pack('C', intval($col['red']));
$palette_data .= pack('C', intval($col['alpha']));
if ($col['alpha'] > 0) {
$has_alpha = true;
}
}
// write blp header
$mipmaps = 16;
$f = fopen($output, 'w');
fwrite($f, 'BLP1');
fwrite($f, pack('V', 1)); // compression
fwrite($f, pack('V', $has_alpha ? 8 : 0)); // alphabits
fwrite($f, pack('V', $width)); // width
fwrite($f, pack('V', $height)); // height
fwrite($f, pack('V', 4)); // type
fwrite($f, pack('V', 1)); // hasMipmaps
$mipmap_start = 28 + 4 * (16 * 2) + 1024;
$mipmap_image = [];
$mipmap_size = [];
$mipmap_offset = [];
$mipmap_data = [];
$last_width = $width;
$last_height = $height;
// create mipmaps
for ($i = 0; $i < 16; ++$i) {
if ($last_width < 1 && $last_height < 1) {
$mipmaps = $i;
break;
}
if ($last_width < 1) {
$last_width = 1;
}
if ($last_height < 1) {
$last_height = 1;
}
$resized = blp_copypaletteimg($im, $last_width, $last_height);
imagecopyresampled(
$resized,
$im,
0,
0,
0,
0,
$last_width,
$last_height,
$width,
$height
);
$mipmap_data[$i] = blp_blob($resized, $has_alpha);
$mipmap_size[$i] = $last_width * $last_height * 2;
$mipmap_offset[$i] = strlen($mipmap_data[$i]);
$last_width = $last_width / 2;
$last_height = $last_height / 2;
}
// write mipmap data
$offset = 0;
for ($i = 0; $i < 16; ++$i) {
if ($i >= $mipmaps) {
fwrite($f, pack('V', 0));
continue;
}
if ($i > 0) {
$offset += $mipmap_offset[$i - 1];
}
fwrite($f, pack('V', $mipmap_start + $offset)); // offset
}
for ($i = 0; $i < 16; ++$i) {
if ($i >= $mipmaps) {
fwrite($f, pack('V', 0));
continue;
}
fwrite($f, pack('V', $mipmap_offset[$i])); // size
}
// write to output
fwrite($f, $palette_data);
for ($i = 0; $i < $mipmaps; ++$i) {
fwrite($f, $mipmap_data[$i]);
}
fclose($f);
return true;
}