Skin Minecraft Viewer 2D на PHP
Скрипт для просмотра 2D скинов в Minecraft.
Код:
class SkinViewer2D
{
/* Допустимые пропорции образа */
const SKIN_BASE = 64;
const SKIN_PROP = 2; // 64 / 32
/*
* Массив допустимых пропорций плаща (для плаща в MC нет четкой привязки к размеру)
* Некоторые плащи используют соотношение 22x17, тогда как обычно используется
* соотношение 64x32 с незаполненным пространством
*/
private static $cloakProps = array(
0 => array('base' => 64, 'ratio' => 2),
1 => array('base' => 22, 'ratio' => 1.29),
);
/**
* Создает изображение головы; вид спереди
* @param string $way_skin полный путь до файла изображения скина
* @param int $size размер возвращаемого изображения в пикселях
* @return resource Возвращает идентификатор GD image при успешном результате и <b>false</b> при ошибке
*/
public static function createHead($way_skin, $size = 151)
{
if (!$info = self::isValidSkin($way_skin))
return false;
$im = @imagecreatefrompng($way_skin);
if (!$im)
return false;
$av = imagecreatetruecolor($size, $size);
$mp = $info['scale'];
imagecopyresized($av, $im, 0, 0, 8 * $mp, 8 * $mp, $size, $size, 8 * $mp, 8 * $mp);
imagecopyresized($av, $im, 0, 0, 40 * $mp, 8 * $mp, $size, $size, 8 * $mp, 8 * $mp);
imagedestroy($im);
return $av;
}
/**
* Создать видовое изображение из скина; фронтальный \ задний вид
* @param string $way_skin полный путь до файла изображения скина
* @param string $way_cloak полный путь до файла изображения плаща ( при необходимости )
* @param string $side вид спереди - front \ вид сзади - back \ по умолчанию оба вида на одном изображении последовательно
* @param int $size высота возвращаемого изображения в пикселях (ширина пропорцианальна задаваемой высоте и завист так же от параметра $side)
* @return resource Возвращает идентификатор GD image при успешном результате и <b>false</b> при ошибке
*/
public static function createPreview($way_skin, $way_cloak = false, $side = false, $size = 224)
{
if (!$info = self::isValidSkin($way_skin))
return false;
$skin = @imagecreatefrompng($way_skin);
if (!$skin)
return false;
$mp = $info['scale'];
$size_x = (($side) ? 16 : 32);
$preview = imagecreatetruecolor($size_x * $mp, 32 * $mp);
$mp_x_h = ($side) ? 0 : imagesx($preview) / 2;
$transparent = imagecolorallocatealpha($preview, 255, 255, 255, 127);
imagefill($preview, 0, 0, $transparent);
if (!$side or $side === 'front') {
imagecopy($preview, $skin, 4 * $mp, 0 * $mp, 8 * $mp, 8 * $mp, 8 * $mp, 8 * $mp);
imagecopy($preview, $skin, 0 * $mp, 8 * $mp, 44 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
self::imageflip($preview, $skin, 12 * $mp, 8 * $mp, 44 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
imagecopy($preview, $skin, 4 * $mp, 8 * $mp, 20 * $mp, 20 * $mp, 8 * $mp, 12 * $mp);
imagecopy($preview, $skin, 4 * $mp, 20 * $mp, 4 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
self::imageflip($preview, $skin, 8 * $mp, 20 * $mp, 4 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
imagecopy($preview, $skin, 4 * $mp, 0 * $mp, 40 * $mp, 8 * $mp, 8 * $mp, 8 * $mp);
}
if (!$side or $side === 'back') {
imagecopy($preview, $skin, $mp_x_h + 4 * $mp, 8 * $mp, 32 * $mp, 20 * $mp, 8 * $mp, 12 * $mp);
imagecopy($preview, $skin, $mp_x_h + 4 * $mp, 0 * $mp, 24 * $mp, 8 * $mp, 8 * $mp, 8 * $mp);
self::imageflip($preview, $skin, $mp_x_h + 0 * $mp, 8 * $mp, 52 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
imagecopy($preview, $skin, $mp_x_h + 12 * $mp, 8 * $mp, 52 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
self::imageflip($preview, $skin, $mp_x_h + 4 * $mp, 20 * $mp, 12 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
imagecopy($preview, $skin, $mp_x_h + 8 * $mp, 20 * $mp, 12 * $mp, 20 * $mp, 4 * $mp, 12 * $mp);
imagecopy($preview, $skin, $mp_x_h + 4 * $mp, 0 * $mp, 56 * $mp, 8 * $mp, 8 * $mp, 8 * $mp);
}
if ($way_cloak and !$info = self::isValidCloak($way_cloak)) {
$way_cloak = null;
} else {
$mp_cloak = $info['scale'];
}
$cloak = @imagecreatefrompng($way_cloak);
if (!$cloak)
$way_cloak = null;
if ($way_cloak) {
if ($mp_cloak > $mp) { // cloak bigger
$mp_x_h = ($side) ? 0 : ($size_x * $mp_cloak) / 2;
$mp_result = $mp_cloak;
} else {
$mp_x_h = ($side) ? 0 : ($size_x * $mp) / 2;
$mp_result = $mp;
}
$preview_cloak = imagecreatetruecolor($size_x * $mp_result, 32 * $mp_result);
$transparent = imagecolorallocatealpha($preview_cloak, 255, 255, 255, 127);
imagefill($preview_cloak, 0, 0, $transparent);
// ex. copy front side of cloak to new image
if (!$side or $side === 'front')
imagecopyresized(
$preview_cloak, // result image
$cloak, // source image
round(3 * $mp_result), // start x point of result
round(8 * $mp_result), // start y point of result
round(12 * $mp_cloak), // start x point of source img
round(1 * $mp_cloak), // start y point of source img
round(10 * $mp_result), // result <- width ->
round(16 * $mp_result), // result /|\ height \|/
round(10 * $mp_cloak), // width of cloak img (from start x \ y)
round(16 * $mp_cloak) // height of cloak img (from start x \ y)
);
imagecopyresized($preview_cloak, $preview, 0, 0, 0, 0, imagesx($preview_cloak), imagesy($preview_cloak), imagesx($preview), imagesy($preview));
if (!$side or $side === 'back')
imagecopyresized(
$preview_cloak,
$cloak,
$mp_x_h + 3 * $mp_result,
round(8 * $mp_result),
round(1 * $mp_cloak),
round(1 * $mp_cloak),
round(10 * $mp_result),
round(16 * $mp_result),
round(10 * $mp_cloak),
round(16 * $mp_cloak)
);
$preview = $preview_cloak;
}
$size_x = ($side) ? $size / 2 : $size;
$fullsize = imagecreatetruecolor($size_x, $size);
imagesavealpha($fullsize, true);
$transparent = imagecolorallocatealpha($fullsize, 255, 255, 255, 127);
imagefill($fullsize, 0, 0, $transparent);
imagecopyresized($fullsize, $preview, 0, 0, 0, 0, imagesx($fullsize), imagesy($fullsize), imagesx($preview), imagesy($preview));
imagedestroy($preview);
imagedestroy($skin);
if ($way_cloak)
imagedestroy($cloak);
return $fullsize;
}
/**
* Сохранить изображение в формате png; отрисованое по правилам createPreview
* @param string $way_save путь до сохраняемого файла
* @param string $way_skin полный путь до файла изображения скина
* @param string $way_cloak полный путь до файла изображения плаща ( при необходимости )
* @param string $side вид спереди - front \ вид сзади - back \ по умолчанию обе стороны
* @param int $size высота возвращаемого изображения в пикселях (ширина пропорцианальна задаваемой высоте и завист так же от параметра $side)
* @return resource Возвращает идентификатор GD image при успешном результате и <b>false</b> при ошибке
*/
public static function savePreview($way_save, $way_skin, $way_cloak = false, $side = false, $size = 224)
{
if (file_exists($way_save))
unlink($way_save);
$new_skin = self::createPreview($way_skin, $way_cloak, $side, $size);
if (!$new_skin)
return false;
imagepng($new_skin, $way_save);
return $new_skin;
}
/**
* Сохранить изображение в формате png; отрисованое по правилам createHead
* @param int $size размер возвращаемого изображения в пикселях для одной стороны
* @param string $way_save путь до сохраняемого файла
* @param string $way_skin полный путь до файла изображения скина
* @return resource Возвращает идентификатор GD image при успешном результате и <b>false</b> при ошибке
*/
public static function saveHead($way_save, $way_skin, $size = 151)
{
if (file_exists($way_save))
unlink($way_save);
$new_head = self::createHead($way_skin, $size);
if (!$new_head)
return false;
imagepng($new_head, $way_save);
return $new_head;
}
/**
* Проверить, является ли файл изображением, с соответствующими для скина пропорциями
* @param string $way_skin полный путь до файла изображения скина
* @return array Если файл не проходит проверку возвращает <b>false</b>, иначе возвращает массив пропорций изображения
*/
public static function isValidSkin($way_skin)
{
if (!file_exists($way_skin))
return false;
if (!$imageSize = self::getImageSize($way_skin))
return false;
if (round(self::SKIN_PROP, 2) != self::getRatio($imageSize))
return false;
return array(
'ratio' => self::getRatio($imageSize),
'scale' => self::getScale($imageSize, self::SKIN_BASE),
);
}
/**
* Проверить, является ли файл изображением, с соответствующими для плащя пропорциями
* @param string $way_cloak полный путь до файла изображения плаща
* @return array Если файл не проходит проверку возвращает <b>false</b>, иначе возвращает массив пропорций изображения
*/
public static function isValidCloak($way_cloak)
{
if (!file_exists($way_cloak))
return false;
if (!$imageSize = self::getImageSize($way_cloak))
return false;
for ($i = 0; $i < sizeof(self::$cloakProps); $i++) {
if (round(self::$cloakProps[$i]['ratio'], 2) != self::getRatio($imageSize))
continue;
return array(
'ratio' => self::$cloakProps[$i]['ratio'],
'scale' => self::getScale($imageSize, self::$cloakProps[$i]['base']),
);
}
return false;
}
private static function getScale($inputImg, $size)
{
if (!is_array($inputImg) and !$inputImg = self::getImageSize($inputImg))
return false;
return $inputImg[0] / $size;
}
private static function getRatio($inputImg)
{
if (!is_array($inputImg) and !$inputImg = self::getImageSize($inputImg))
return false;
return round($inputImg[0] / $inputImg[1], 2);
}
private static function getImageSize($file)
{
$imageSize = @getimagesize($file);
if (empty($imageSize))
return false;
return $imageSize;
}
private static function imageflip(&$result, &$img, $rx = 0, $ry = 0, $x = 0, $y = 0, $size_x = null, $size_y = null)
{
if ($size_x < 1)
$size_x = imagesx($img);
if ($size_y < 1)
$size_y = imagesy($img);
imagecopyresampled($result, $img, $rx, $ry, ($x + $size_x - 1), $y, $size_x, $size_y, 0 - $size_x, $size_y);
}
}
Создание просмотра скина:
$img = skinViewer2D::createPreview($skin, $cloak, $side); // где $skin путь к скину, $cloak путь к плащу, и $side вид спереди - front \ вид сзади - back.
Создание головы скина:
$img = skinViewer2D::createHead($skin, 64); // где $skin путь к скину.
Скачать:
9.02.2016, 09:02 -
Категория: Статьи » Программирование » PHP