mirror of
https://github.com/msikma/pokesprite.git
synced 2026-03-21 17:54:23 -05:00
212 lines
6.6 KiB
PHP
212 lines
6.6 KiB
PHP
<?php
|
|
|
|
// PokéSprite
|
|
// ----------
|
|
// The use of this source code is governed by the MIT license.
|
|
// See the COPYRIGHT file for more information.
|
|
|
|
namespace PkSpr;
|
|
|
|
/**
|
|
* Generates an image file containing all sprites.
|
|
*/
|
|
class IconSprite
|
|
{
|
|
/** @var mixed The sprite image object. */
|
|
public $sprite;
|
|
/** @var mixed[] Data on the two sections of the sprite image (pkmn, etc). */
|
|
public $sections;
|
|
/** @var mixed[] Copies of primary Pokémon positioning data for use with duplicates. */
|
|
public $std_pkmn;
|
|
/** @var boolean Whether to be verbose in giving feedback. */
|
|
public $verbose;
|
|
/** @var mixed[] Default sprites (base for a duplicate). */
|
|
public $std_sprites = array();
|
|
/** @var int Image padding. */
|
|
public $img_padding;
|
|
|
|
/**
|
|
* Initializes the sprite.
|
|
*
|
|
* @param int $width Width of the sprite.
|
|
* @param int $height Height of the sprite.
|
|
* @param mixed[] $sections Image sprite section data.
|
|
* @param boolean $verbose Verbosity in giving feedback.
|
|
*/
|
|
function __construct($width, $height, $sections, $verbose=false)
|
|
{
|
|
$this->img_padding = Settings::get('pkmn_img_padding');
|
|
$this->sprite = @imagecreatetruecolor($width, $height);
|
|
imagesavealpha($this->sprite, true);
|
|
$trnsp = @imagecolorallocatealpha($this->sprite, 0, 0, 0, 127);
|
|
imagefill($this->sprite, 0, 0, $trnsp);
|
|
|
|
$this->sections = $sections;
|
|
$this->verbose = $verbose;
|
|
}
|
|
|
|
/**
|
|
* Sets standard icons for use with duplicates.
|
|
*
|
|
* @param mixed[] $pkmn Standard icons info.
|
|
*/
|
|
function set_pkmn_std_icons($pkmn)
|
|
{
|
|
$this->std_sprites = $pkmn;
|
|
}
|
|
|
|
/**
|
|
* Adds a single icon to the stack.
|
|
*
|
|
* @param mixed[] $icon Icon (pkmn or etc group).
|
|
*/
|
|
function add($icon)
|
|
{
|
|
$x = $icon['fit']['x'] + $this->img_padding;
|
|
$y = $icon['fit']['y'] + $this->img_padding;
|
|
$w = $icon['w'];
|
|
$h = $icon['h'];
|
|
$file = $icon['file'];
|
|
$slug = $icon['slug'];
|
|
$type = $icon['type'];
|
|
|
|
// Put the other icons underneath the Pokémon icons.
|
|
if ($icon['section'] != 'pkmn') {
|
|
$y += $this->sections['pkmn'];
|
|
}
|
|
// Remove the padding we added to the Pokémon icons earlier.
|
|
// Hackish, I know...
|
|
if ($icon['section'] == 'pkmn') {
|
|
$w -= $this->img_padding;
|
|
$h -= $this->img_padding;
|
|
}
|
|
|
|
$indicator = ($type == 'pkmn' ? $icon['name_display'].' (variation='.$icon['variation'].', subvariation='.$icon['subvariation'].', version='.$icon['version'].')' : $slug);
|
|
|
|
if ($icon['is_duplicate_from']) {
|
|
// If this is a duplicate, we don't need to add it.
|
|
return true;
|
|
}
|
|
|
|
if (!is_file($file)) {
|
|
// If the file does not exist, skip this entry.
|
|
if ($this->verbose) {
|
|
print(I18n::lf('entry_skipped', array($file, $indicator)));
|
|
}
|
|
// Image not added.
|
|
return false;
|
|
}
|
|
else {
|
|
if ($this->verbose) {
|
|
print(I18n::lf('entry_added', array($file, $indicator)));
|
|
}
|
|
}
|
|
|
|
// Open the image data.
|
|
$tmp = @imagecreatefrompng($file);
|
|
|
|
// If we're adding a faux right-facing image, we have to manually
|
|
// flip the image before copying it to the sprite.
|
|
if (@$icon['subvariation'] == 'flipped') {
|
|
$tmp = $this->x_imageflip($tmp, 'v');
|
|
}
|
|
|
|
// Copy the image to the sprite.
|
|
@imagecopy($this->sprite, $tmp, $x, $y, 0, 0, $w, $h);
|
|
@imagedestroy($tmp);
|
|
|
|
// Image added.
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Output the image.
|
|
*
|
|
* If $compress is false, only the lowest compression
|
|
* ratio will be applied, as we'll be using pngcrush later.
|
|
*
|
|
* @param string $location Where to save the (temporary) file.
|
|
* @param boolean $compress Whether to apply significant compression.
|
|
*/
|
|
function output($location, $compress=true)
|
|
{
|
|
imagepng($this->sprite, $location, $compress === true ? 9 : 1);
|
|
}
|
|
|
|
/**
|
|
* Flips an image horizontally, vertically or both.
|
|
*
|
|
* Used to generated flipped images of Pokémon icons from their
|
|
* original icons. Note that, for some inexplicable reason, the position is
|
|
* off by 1px normally. This function accounts for the difference. However,
|
|
* exactly why this happens is unknown. If the PHP version is >= 5.5.0,
|
|
* the native GD imageflip() function is used instead.
|
|
*
|
|
* This was adapted from the code provided on <http://php.net/manual/en/function.imagecopy.php#85992> by xafford.
|
|
*
|
|
* @param mixed $imgsrc Image source.
|
|
* @param string $direction Direction in which to flip (h|v|b).
|
|
*
|
|
*/
|
|
function x_imageflip($imgsrc, $direction='b')
|
|
{
|
|
// If we've got a native function, use that.
|
|
if (function_exists('imageflip')) {
|
|
// This hasn't been verified to be accurate, though...
|
|
imageflip($imgsrc,
|
|
$direction == 'h' ? IMG_FLIP_HORIZONTAL :
|
|
($direction == 'v' ? IMG_FLIP_VERTICAL :
|
|
($direction == 'b' ? IMG_FLIP_BOTH : -1))
|
|
);
|
|
return $imgsrc;
|
|
}
|
|
$width = imagesx($imgsrc);
|
|
$height = imagesy($imgsrc);
|
|
|
|
$src_x = 0;
|
|
$src_y = 0;
|
|
$src_width = $width;
|
|
$src_height = $height;
|
|
|
|
switch ($direction) {
|
|
case 'h':
|
|
$src_y = floor($height - 1);
|
|
$src_height = floor(-$height - 1);
|
|
break;
|
|
|
|
case 'v':
|
|
$src_x = floor($width - 1);
|
|
$src_width = floor(-$width - 1);
|
|
break;
|
|
|
|
case 'b':
|
|
$src_x = $width - 1;
|
|
$src_y = $height - 1;
|
|
$src_width = -$width - 1;
|
|
$src_height = -$height - 1;
|
|
break;
|
|
|
|
default:
|
|
return $imgsrc;
|
|
}
|
|
|
|
$imgdest = imagecreatetruecolor($width, $height);
|
|
imagesavealpha($imgdest, true);
|
|
$trnsp = @imagecolorallocatealpha($imgdest, 0, 0, 0, 127);
|
|
imagefill($imgdest, 0, 0, $trnsp);
|
|
|
|
if (imagecopyresampled($imgdest, $imgsrc, 0, 0, $src_x, $src_y, $width, $height, $src_width, $src_height)) {
|
|
return $imgdest;
|
|
}
|
|
|
|
return $imgsrc;
|
|
}
|
|
|
|
/**
|
|
* Destroys the image object.
|
|
*/
|
|
function destroy()
|
|
{
|
|
imagedestroy($this->sprite);
|
|
}
|
|
} |