Last active
October 29, 2017 06:40
-
-
Save maxpert/eb4d8c588808276c6393 to your computer and use it in GitHub Desktop.
PHP Long shadow icon generator.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# for neater URLS like /{text}/{size}/{bg} | |
RewriteEngine on | |
RewriteRule ^img/([^/]+)/(\d+)/([a-fA-F0-9]{6})$ i/index.php?text=$1&size=$2&bg=$3 [NC,QSA] | |
RewriteRule ^img/([^/]+)/(\d+)$ i/index.php?text=$1&size=$2 [NC,QSA] | |
RewriteRule ^img/([^/]+)$ i/index.php?text=$1 [NC,QSA] | |
RewriteRule ^img/([^/]+)/.+$ i/index.php?text=$1 [NC,QSA] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Copyright 2014 Zohaib Sibte Hassan | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
// --------------------------------- Configuration variables | |
// These are configuration variables that you can modify | |
// Customize them as much as you want | |
// Here are list of parameters you can pass: | |
// - size: Size of image | |
// - font: font name to use | |
// - text: text value to render | |
// - bg: background color | |
// - fg: foreground color | |
// - sh: shadow color | |
// - slope_x: shadow slope along x-axis (1 towards right, -1 towards left) | |
// - slope_y: shadow slope along y-axis (1 towards bottom, -1 towards top) | |
// Cache path | |
// Make it NULL in case you don't want to cache the results | |
$ImageCacheDir = realpath(__DIR__.'/../cached'); | |
// Default image size | |
$DefaultImageSize = 128; | |
// Maximum size of image in pixels | |
// Use a decent value to throttle CPU/memory usage | |
$MaxImageSize = 512; | |
// Directory containing fonts | |
$FontDirectory = __DIR__.'/../fonts'; | |
// List of supported fonts | |
// It's a map of name => font file path that is used to render initials | |
// Font name is passed as ```font``` query parameter | |
$FontsList = array( | |
// Source sans by adobe, available at https://github.com/adobe-fonts/source-sans-pro/releases | |
's' => 'SourceSansVariable-Roman.ttf', | |
// Gidolinya available at http://gidole.github.io/ | |
'g' => 'Gidolinya-Regular.otf', | |
// Opensans | |
'o' => 'OpenSans-Regulare.ttf', | |
// PT Sans Narrow | |
'p' => 'PTN77F.ttf', | |
// Multilingual NotoSans font | |
'n' => array ( | |
'common' => 'NotoSans-Regular.ttf', | |
'latin' => 'NotoSans-Regular.ttf', | |
'arabic' => 'script/NotoNaskhArabic-Regular.ttf', | |
'armenian' => 'script/NotoSans-Armenian-Regular.ttf', | |
'bengali' => 'script/NotoSans-Bengali-Regular.ttf', | |
'han' => 'script/Noto-CJKJP-Regular.otf', | |
'hiragana' => 'script/Noto-CJKJP-Regular.otf', | |
'katakana' => 'script/Noto-CJKJP-Regular.otf', | |
'thai' => 'script/NotoSans-Thai-Regular.ttf', | |
'georgian' => 'script/NotoSans-Georgian-Regular.ttf', | |
'mongolian' => 'script/NotoSans-Mongolian-Regular.ttf', | |
'hebrew' => 'script/NotoSans-Hebrew-Regular.ttf', | |
'tibetan' => 'script/NotoSans-Tibetan-Regular.ttf', | |
), | |
); | |
// Default font name if the parameter is not specified | |
$DefaultFontName = 'n'; | |
// Font scaled size (it's used as ImageSize * FontScaledSize) | |
// Each font might have different value due to ligature | |
$FontScaledSize = 0.35; | |
// Default background color auto or hex value without # e.g. ffaa11 | |
$DefaultBackgroundColor = 'auto'; | |
// Color pallete for auto selecting colors | |
$ColorPalette = array( | |
'1abc9c', '3498db', '9b59b6', | |
'34495e', 'f1c40f', 'e67e22', | |
'e74c3c', '8764B8'); | |
// Default text | |
$DefaultText = 'HI'; | |
// Default shadow slope along x-axis | |
$DefaultSlopeX = 1; | |
// Default shadow slope along y-axis | |
$DefaultSlopeY = 1; | |
// ---------------------- Only modify beyond this if you know what you are doing :) | |
// -------------------------------------------------------------------------------- | |
mb_language('uni'); | |
mb_internal_encoding('UTF-8'); | |
// Supported language ligatures | |
$LanguageFontNamePrefix = array( | |
'Arabic', | |
'Armenian', | |
'Bengali', | |
'Bopomofo', | |
'Braille', | |
'Buhid', | |
'Canadian_Aboriginal', | |
'Cherokee', | |
'Cyrillic', | |
'Devanagari', | |
'Ethiopic', | |
'Georgian', | |
'Greek', | |
'Gujarati', | |
'Gurmukhi', | |
'Han', | |
'Hangul', | |
'Hanunoo', | |
'Hebrew', | |
'Hiragana', | |
'Inherited', | |
'Kannada', | |
'Katakana', | |
'Khmer', | |
'Lao', | |
'Latin', | |
'Limbu', | |
'Malayalam', | |
'Mongolian', | |
'Myanmar', | |
'Ogham', | |
'Oriya', | |
'Runic', | |
'Sinhala', | |
'Syriac', | |
'Tagalog', | |
'Tagbanwa', | |
'Tai_Le', | |
'Tamil', | |
'Telugu', | |
'Thaana', | |
'Thai', | |
'Tibetan', | |
'Yi', | |
'Common' | |
); | |
function req_get($name, $default = null) { | |
return isset($_GET[$name]) ? $_GET[$name] : $default; | |
} | |
function hex2rgb($hex) { | |
if (is_array($hex)){ | |
return $hex; | |
} | |
$hex = str_replace("#", "", $hex); | |
if(strlen($hex) == 3) { | |
$r = hexdec(substr($hex,0,1).substr($hex,0,1)); | |
$g = hexdec(substr($hex,1,1).substr($hex,1,1)); | |
$b = hexdec(substr($hex,2,1).substr($hex,2,1)); | |
} else { | |
$r = hexdec(substr($hex,0,2)); | |
$g = hexdec(substr($hex,2,2)); | |
$b = hexdec(substr($hex,4,2)); | |
} | |
$rgb = array($r, $g, $b); | |
return $rgb; // returns an array with the rgb values | |
} | |
function brighten($color, $steps) { | |
list($r, $g, $b) = $color; | |
$r = max(0,min(255,$r + $steps)); | |
$g = max(0,min(255,$g + $steps)); | |
$b = max(0,min(255,$b + $steps)); | |
return array($r, $g, $b); | |
} | |
function normalize_slope($p) { | |
if($p > 1) { | |
return 1; | |
} | |
if($p < -1) { | |
return -1; | |
} | |
return $p; | |
} | |
function get_str_lang($txt) { | |
global $LanguageFontNamePrefix; | |
foreach ($LanguageFontNamePrefix as $lang) { | |
$exp = '/\p{'.$lang.'}/u'; | |
if (preg_match($exp, $txt)) { | |
return $lang; | |
} | |
} | |
return 'Latin'; | |
} | |
function get_font_file($txt, $name) { | |
global $FontsList, $FontDirectory; | |
if (!isset($FontsList[$name])) { | |
throw new Exception("No font defined for $name"); | |
} | |
$info = $FontsList[$name]; | |
if (is_string($info)) { | |
return $FontDirectory.'/'.$info; | |
} | |
$lang = strtolower(get_str_lang($txt)); | |
if (isset($info[$lang])) { | |
return $FontDirectory.'/'.$info[$lang]; | |
} | |
if (isset($info['common'])) { | |
return $FontDirectory.'/'.$info['common']; | |
} | |
return $FontDirectory.'/'.$info['latin']; | |
} | |
function get_cache_path($ids) { | |
global $ImageCacheDir; | |
if (is_null($ImageCacheDir)) { | |
return null; | |
} | |
return $ImageCacheDir . '/' . hash('sha256', serialize($ids)) . '.png'; | |
} | |
function render_image($string, $image_width, $image_height, $font_size, $font_file, $bg_color, $fg_color, $shadow_color, $x_slope, $y_slope) { | |
$cache_path = get_cache_path(func_get_args()); | |
// If already cached return that | |
if ($cache_path !== NULL && file_exists($cache_path)) { | |
return file_get_contents($cache_path); | |
} | |
// Create image | |
$im = imagecreatetruecolor($image_width, $image_height); | |
imageantialias($im, true); | |
// Create fill brushes | |
$fg_fill = imagecolorallocate($im, $fg_color[0], $fg_color[1], $fg_color[2]); | |
$bg_fill = imagecolorallocate($im, $bg_color[0], $bg_color[1], $bg_color[2]); | |
$sh_fill = imagecolorallocate($im, $shadow_color[0], $shadow_color[1], $shadow_color[2]); | |
// Find the bounding box of text | |
$text_bounding_box = imagettfbbox($font_size, 0, $font_file, $string); | |
$xLeft = $text_bounding_box[0]; // (lower|upper) left corner, X position | |
$xRight = $text_bounding_box[2]; // (lower|upper) right corner, X position | |
$yLower = $text_bounding_box[1]; // lower (left|right) corner, Y position | |
$yUpper = $text_bounding_box[5]; // upper (left|right) corner, Y position | |
$tail_length = max(abs($xLower), abs($xRight), abs($xLeft), abs($yUpper)); | |
$text_size = array( | |
($xRight - $xLeft), | |
($yLower - $yUpper) | |
); | |
if ($xLeft > 2) { | |
$text_size[0] = abs($xRight); | |
} | |
if ($yLower > 2) { | |
$text_size[1] = abs($yUpper); | |
} | |
$text_position = array( | |
($image_width / 2) - ($text_size[0] / 2), | |
($image_height / 2) + ($text_size[1] / 2) | |
); | |
// Fill background | |
imagefill($im, 0, 0, $bg_fill); | |
// Really inefficent version of draw shadow | |
if ($x_slope != 0 && $y_slope != 0) { | |
$max_i = $image_height - $text_position[1] + $tail_length; | |
for($i=1; $i <= $max_i; $i++) { | |
imagettftext($im, | |
$font_size , | |
0 , | |
$text_position[0] + $x_slope * $i, | |
$text_position[1] + $y_slope * $i, | |
$sh_fill, | |
$font_file, | |
$string); | |
} | |
} | |
// Draw text | |
imagettftext($im, $font_size , 0 , $text_position[0] , $text_position[1], $fg_fill , $font_file, $string); | |
// Start buffering if not cached | |
if ($cache_path === NULL) { | |
ob_start(); | |
} | |
imagepng($im, $cache_path, 9); | |
imagedestroy($im); | |
// flush path from buffer if no cache path | |
if ($cache_path === NULL) { | |
$ret = ob_get_contents(); | |
ob_end_clean(); | |
return $ret; | |
} | |
// Save CPU do IO | |
return file_get_contents($cache_path); | |
} | |
// Read request | |
$ImageSize = (int)req_get('size', $DefaultImageSize); | |
if ($ImageSize > $MaxImageSize){ | |
$ImageSize = $MaxImageSize; | |
} | |
// Text | |
$text = mb_strtoupper(req_get('text', $DefaultText)); | |
if (mb_strlen($text) > 2) { | |
$text = mb_substr($text, 0, 2); | |
} | |
// Background color | |
if ($DefaultBackgroundColor == 'auto') { | |
$index = (crc32(req_get('text', $DefaultText)) >> 16) % count($ColorPalette); | |
$DefaultBackgroundColor = $ColorPalette[$index]; | |
} | |
$bg_color = hex2rgb(req_get('bg', $DefaultBackgroundColor)); | |
// Render | |
$imgContent = render_image( | |
$text, | |
$ImageSize, | |
$ImageSize, | |
(int)($ImageSize * $FontScaledSize), | |
get_font_file($text, req_get('font', $DefaultFontName)), | |
$bg_color, | |
hex2rgb(req_get('fg', brighten($bg_color, 150))), | |
hex2rgb(req_get('sh', brighten($bg_color, -100))), | |
normalize_slope((float)req_get('slope_x', $DefaultSlopeX)), | |
normalize_slope((float)req_get('slope_y', $DefaultSlopeY)) | |
); | |
header("Content-type: image/png"); | |
echo $imgContent; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment