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']) { // 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 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); } }