/** * @param resource|string $data * @param string $path * @param string $relpath * @param callable $write_callback * @param string $content_type */ private static function _output($data, $path, $relpath, $write_callback, $content_type) { if (isset($data)) { CoreUtils::createUploadFolder($path); $write_callback($path, $data); } CoreUtils::fixPath("{$relpath}?t=" . filemtime($path)); header("Content-Type: image/{$content_type}"); readfile($path); exit; }
/** * Render appearance PNG image * * @param array $Appearance * * @throws \Exception */ static function renderAppearancePNG($Appearance) { global $CGPath; $OutputPath = FSPATH . "cg_render/{$Appearance['id']}-palette.png"; $FileRelPath = "{$CGPath}/v/{$Appearance['id']}.png"; if (file_exists($OutputPath)) { Image::outputPNG(null, $OutputPath, $FileRelPath); } $OutWidth = 0; $OutHeight = 0; $SpriteWidth = $SpriteHeight = 0; $SpriteRightMargin = 10; $ColorCircleSize = 17; $ColorCircleRMargin = 5; $ColorNameFontSize = 12; $FontFile = APPATH . 'font/Celestia Medium Redux.ttf'; //$PixelatedFontFile = APPATH.'font/Volter (Goldfish).ttf'; $PixelatedFontFile = $FontFile; if (!file_exists($FontFile)) { throw new \Exception('Font file missing'); } $Name = $Appearance['label']; $NameVerticalMargin = 5; $NameFontSize = 22; $TextMargin = 10; $ColorsOutputted = 0; $SplitTreshold = 12; $ColumnRightMargin = 20; // Detect if sprite exists and adjust image size & define starting positions $SpritePath = SPRITE_PATH . "{$Appearance['id']}.png"; $SpriteExists = file_exists($SpritePath); if ($SpriteExists) { $SpriteSize = getimagesize($SpritePath); $Sprite = Image::preserveAlpha(imagecreatefrompng($SpritePath)); $SpriteHeight = $SpriteSize[HEIGHT]; $SpriteWidth = $SpriteSize[WIDTH]; $SpriteRealWidth = $SpriteWidth + $SpriteRightMargin; $OutWidth = $SpriteRealWidth; $OutHeight = $SpriteHeight; } else { $SpriteRealWidth = 0; } $origin = array('x' => $SpriteExists ? $SpriteRealWidth : $TextMargin, 'y' => 0); // Get color groups & calculate the space they take up $ColorGroups = ColorGroups::get($Appearance['id']); $CGCount = count($ColorGroups); $CGFontSize = round($NameFontSize / 1.25); $CGVerticalMargin = $NameVerticalMargin; $GroupLabelBox = Image::saneGetTTFBox($CGFontSize, $FontFile, 'ABCDEFGIJKLMOPQRSTUVWQYZabcdefghijklmnopqrstuvwxyz'); $ColorNameBox = Image::saneGetTTFBox($ColorNameFontSize, $PixelatedFontFile, 'AGIJKFagijkf'); $CGsHeight = $CGCount * ($GroupLabelBox['height'] + $CGVerticalMargin * 2 + $ColorCircleSize); // Get export time & size $ExportTS = "Generated at: " . Time::format(time(), Time::FORMAT_FULL); $ExportFontSize = round($CGFontSize / 1.5); $ExportBox = Image::saneGetTTFBox($ExportFontSize, $FontFile, $ExportTS); // Check how long & tall appearance name is, and set image width $NameBox = Image::saneGetTTFBox($NameFontSize, $FontFile, $Name); $OutWidth = $origin['x'] + max($NameBox['width'], $ExportBox['width']) + $TextMargin; // Set image height $OutHeight = max($origin['y'] + ($NameVerticalMargin * 4 + $NameBox['height'] + $ExportBox['height'] + $CGsHeight), $OutHeight); // Create base image $BaseImage = Image::createTransparent($OutWidth, $OutHeight); $BLACK = imagecolorallocate($BaseImage, 0, 0, 0); // If sprite exists, output it on base image if ($SpriteExists) { Image::copyExact($BaseImage, $Sprite, 0, 0, $SpriteWidth, $SpriteHeight); } // Output appearance name $origin['y'] += $NameVerticalMargin * 2; Image::writeOn($BaseImage, $Name, $origin['x'], $NameFontSize, $BLACK, $origin, $FontFile); $origin['y'] += $NameVerticalMargin; // Output generation time Image::writeOn($BaseImage, $ExportTS, $origin['x'], $ExportFontSize, $BLACK, $origin, $FontFile); $origin['y'] += $NameVerticalMargin; if (!empty($ColorGroups)) { $LargestX = 0; $LargestLabel = ''; $AllColors = ColorGroups::getColorsForEach($ColorGroups); foreach ($ColorGroups as $cg) { $CGLabelBox = Image::saneGetTTFBox($CGFontSize, $FontFile, $cg['label']); Image::calcRedraw($OutWidth, $OutHeight, $CGLabelBox['width'] + $TextMargin, $GroupLabelBox['height'] + $NameVerticalMargin + $CGVerticalMargin, $BaseImage, $origin); Image::writeOn($BaseImage, $cg['label'], $origin['x'], $CGFontSize, $BLACK, $origin, $FontFile, $GroupLabelBox); $origin['y'] += $GroupLabelBox['height'] + $CGVerticalMargin; if ($CGLabelBox['width'] > $LargestX) { $LargestX = $CGLabelBox['width']; $LargestLabel = $cg['label']; } if (!empty($AllColors[$cg['groupid']])) { foreach ($AllColors[$cg['groupid']] as $c) { $ColorNameLeftOffset = $ColorCircleSize + $ColorCircleRMargin; $CNBox = Image::saneGetTTFBox($ColorNameFontSize, $PixelatedFontFile, $c['label']); $WidthIncrease = $ColorNameLeftOffset + $CNBox['width'] + $TextMargin; $HeightIncrease = max($ColorCircleSize, $CNBox['height']) + $CGVerticalMargin; Image::calcRedraw($OutWidth, $OutHeight, $WidthIncrease, $HeightIncrease, $BaseImage, $origin); Image::drawCircle($BaseImage, $origin['x'], $origin['y'], $ColorCircleSize, $c['hex'], $BLACK); $yOffset = 2; Image::writeOn($BaseImage, $c['label'], $origin['x'] + $ColorNameLeftOffset, $ColorNameFontSize, $BLACK, $origin, $PixelatedFontFile, $ColorNameBox, $yOffset); $origin['y'] += $HeightIncrease; $ColorsOutputted++; $TotalWidth = $ColorNameLeftOffset + $CNBox['width']; if ($TotalWidth > $LargestX) { $LargestX = $TotalWidth; $LargestLabel = $c['label']; } } } if ($ColorsOutputted > $SplitTreshold) { Image::calcRedraw($OutWidth, $OutHeight, 0, $NameVerticalMargin, $BaseImage, $origin); $origin['y'] = $NameVerticalMargin * 4 + Image::saneGetTTFBox($NameFontSize, $FontFile, $Name)['height'] + Image::saneGetTTFBox($ExportFontSize, $FontFile, $ExportTS)['height']; $origin['x'] += $LargestX + $ColumnRightMargin; $ColorsOutputted = 0; $LargestX = 0; } else { $origin['y'] += $NameVerticalMargin; } } } $FinalBase = Image::createWhiteBG($OutWidth, $OutHeight); Image::drawSquare($FinalBase, 0, 0, array($OutWidth, $OutHeight), null, $BLACK); Image::copyExact($FinalBase, $BaseImage, 0, 0, $OutWidth, $OutHeight); if (!CoreUtils::createUploadFolder($OutputPath)) { Response::fail('Failed to create render directory'); } Image::outputPNG($FinalBase, $OutputPath, $FileRelPath); }