<?php
header ( "Content-type: image/png; charset=UTF-8" );
if ( ! defined ( 'BUTTONS_TEMP_DIR' ) ) {
define ( 'BUTTONS_TEMP_DIR', realpath ( dirname(__FILE__) ) . '/../various/temp/' );
}
if ( ! defined ( 'BASEPATH' ) ) {
define ( 'BASEPATH', realpath ( dirname(__FILE__) ) . '/../system/' );
}
$text = ( isset ( $_GET [ 'text' ] ) && ! empty ( $_GET [ 'text' ] ) ) ? base64_decode ( $_GET [ 'text' ] ) : "drSoft Buttons Test";
$fontSize = ( isset ( $_GET [ 'size' ] ) && ! empty ( $_GET [ 'size' ] ) ) ? $_GET [ 'size' ] : 11;
$font_type = ( isset ( $_GET [ 'font' ] ) && ! empty ( $_GET [ 'font' ] ) ) ? $_GET [ 'font' ] : 'AlteHaasGroteskBold';
$angle = ( isset ( $_GET [ 'angle' ] ) && ! empty ( $_GET [ 'angle' ] ) ) ? $_GET [ 'angle' ] : 125;
$offset = ( isset ( $_GET [ 'offset' ] ) && ! empty ( $_GET [ 'offset' ] ) ) ? $_GET [ 'offset' ] : 0.6;
$transparency = ( isset ( $_GET [ 'transparency' ] ) && ! empty ( $_GET [ 'transparency' ] ) ) ? $_GET [ 'transparency' ] : 0.6;
$softness = ( isset ( $_GET [ 'softness' ] ) && ! empty ( $_GET [ 'softness' ] ) ) ? $_GET [ 'softness' ] : 3;
$color = ( isset ( $_GET [ 'color' ] ) && ! empty ( $_GET [ 'color' ] ) ) ? $_GET [ 'color' ] : 'FFFFFF';
$shadow_color = ( isset ( $_GET [ 'shadow_color' ] ) && ! empty ( $_GET [ 'shadow_color' ] ) ) ? $_GET [ 'shadow_color' ] : '000000';
$filename = md5 ( $text . $fontSize . $font_type . $angle . $offset . $transparency . $softness . $color . $shadow_color ) . '.png';
if ( file_exists ( BUTTONS_TEMP_DIR . $filename ) ) {
echo @read_file ( BUTTONS_TEMP_DIR . $filename );
exit;
}
@ob_start ();
$font = BASEPATH . "fonts/$font_type.ttf";
if ( ! file_exists ( $font ) ) {
die ( "Unable to load font at $font" );
}
$textColor = Color::createFromHex ( $color );
$shadowColor = Color::createFromHex ( $shadow_color );
$textImage = ImageGenerator::createTextImage ( $text, $font, $fontSize, $textColor );
$textImage->addShadow ( $angle, $offset, $transparency, $softness, $shadowColor );
imagePNG ( $textImage->imageData );
$output = @ob_get_contents();
@ob_end_clean ();
@touch ( BUTTONS_TEMP_DIR . $filename );
@write_file ( BUTTONS_TEMP_DIR . $filename, $output );
echo $output;
die ();
//http://marcoslot.net/files/text.phps
function read_file ( $file )
{
if ( ! file_exists ( $file ) )
{
return FALSE;
}
if ( function_exists ( 'file_get_contents' ) )
{
return file_get_contents ( $file );
}
if ( ! $fp = @fopen ( $file, FOPEN_READ ) )
{
return FALSE;
}
flock($fp, LOCK_SH);
$data = '';
if (filesize($file) > 0)
{
$data =& fread($fp, filesize($file));
}
flock($fp, LOCK_UN);
fclose($fp);
return $data;
}
function write_file($path, $data, $mode = 'w' )
{
if ( ! $fp = @fopen($path, $mode))
{
return FALSE;
}
flock($fp, LOCK_EX);
fwrite($fp, $data);
flock($fp, LOCK_UN);
fclose($fp);
return TRUE;
}
function imageClone ( $source )
{
$width = imagesx ( $source );
$height = imagesy ( $source );
$newImage = imageCreateTrueColor ( $width, $height );
imagePaletteCopy ( $newImage, $source );
imageAlphaBlending ( $newImage, false );
imageSaveAlpha ( $newImage, true );
imageCopy ( $newImage, $source, 0, 0, 0, 0, $width, $height );
return $newImage;
}
class ImageObject {
public $imageData;
public function __construct ( $image )
{
$this->imageData = $image;
}
public function __destruct ()
{
@imageDestroy ( $this->imageData );
}
public function getWidth ()
{
return imagesx ( $this->imageData );
}
public function getHeight ()
{
return imagesy ( $this->imageData );
}
public function getColor ( $x, $y )
{
$colorIndex = imageColorAt ( $this->imageData, $x, $y );
$colorRGB = imageColorsForIndex ( $this->imageData, $colorIndex );
return new Color ( $colorRGB [ 'red' ], $colorRGB [ 'green' ], $colorRGB [ 'blue' ], $colorRGB [ 'alpha' ] );
}
public function merge ( $mergeImage, $startX = 0, $startY = 0 )
{
imageAlphaBlending ( $this->imageData, true );
imageCopy ( $this->imageData, $mergeImage->imageData, $startX, $startY, 0, 0, $mergeImage->getWidth (), $mergeImage->getHeight () );
}
public function blurGaussian ( $spread )
{
self::imageGaussian ( $this->imageData, $spread, $this->getWidth (), $this->getHeight () );
}
public static function imageGaussian ( &$image, $spread, $width, $height )
{
$use_low_memory_method = false;
// Check for silly spreads
if ( $spread == 0 ) {
return;
}
if ( $spread > 10 ) {
$spread = 10;
}
if ( strlen ( $memory_limit = trim ( ini_get ( 'memory_limit' ) ) ) > 0 )
{
$last = strtolower ( $memory_limit { strlen ( $memory_limit ) - 1 } );
switch ( $last )
{
// The 'G' modifier is available since PHP 5.1.0
case 'g' :
$memory_limit *= 1024;
case 'm' :
$memory_limit *= 1024;
case 'k' :
$memory_limit *= 1024;
}
if ( $memory_limit <= 8 * 1024 * 1024 )
{
$use_low_memory_method = true;
}
}
else {
$use_low_memory_method = false;
}
// Perform gaussian blur convlution. First, prepare the convolution
// kernel and precalculated multiplication array. Algorithm
// adapted from the simply exceptional code by Mario Klingemann
// <http://incubator.quasimondo.com>. Kernel is essentially an
// approximation of a gaussian distribution by utilizing squares.
$kernelsize = $spread * 2 - 1;
$kernel = array_fill ( 0, $kernelsize, 0 );
$mult = array_fill ( 0, $kernelsize, array_fill ( 0, 256, 0 ) );
for ( $i = 1; $i < $spread; $i ++ )
{
$smi = $spread - $i;
$kernel [ $smi - 1 ] = $kernel [ $spread + $i - 1 ] = $smi * $smi;
for ( $j = 0; $j < 256; $j ++ )
{
$mult [ $smi - 1 ] [ $j ] = $mult [ $spread + $i - 1 ] [ $j ] = $kernel [ $smi - 1 ] * $j;
}
}
$kernel [ $spread - 1 ] = $spread * $spread;
for ( $j = 0; $j < 256; $j ++ )
{
$mult [ $spread - 1 ] [ $j ] = $kernel [ $spread - 1 ] * $j;
}
if ( ! $use_low_memory_method )
{
$i = 0;
for ( $x = 0; $x < $width; $x ++ )
{
for ( $y = 0; $y < $height; $y ++ )
{
$rgb = imagecolorat ( $image, $x, $y );
$imagearray [ $i ++ ] = $rgb;
}
}
}
// Everything's set. Let's run the first pass. Our first pass will be a
// vertical pass.
for ( $x = 0; $x < $width; $x ++ )
{
for ( $y = 0; $y < $height; $y ++ )
{
$sum = 0;
$cr = $cg = $cb = 0;
for ( $j = 0; $j < $kernelsize; $j ++ )
{
$kernely = $y + ( $j - ( $spread - 1 ) );
if ( ( $kernely >= 0 ) && ( $kernely < $height ) )
{
if ( ! $use_low_memory_method )
{
$ci = ( $x * $height ) + $kernely;
$rgb = $imagearray [ $ci ];
}
else
{
$rgb = imagecolorat ( $image, $x, $kernely );
}
$cr += $mult [ $j ] [ ( $rgb >> 16 ) & 0xFF ];
$cg += $mult [ $j ] [ ( $rgb >> 8 ) & 0xFF ];
$cb += $mult [ $j ] [ $rgb & 0xFF ];
$sum += $kernel [ $j ];
}
}
$ci = ( $x * $height ) + $y;
$shadowarray [ $ci ] = ( ( intval ( round ( $cr / $sum ) ) & 0xff ) << 16 ) | ( ( intval ( round ( $cg / $sum ) ) & 0xff ) << 8 ) | ( intval ( round ( $cb / $sum ) ) & 0xff );
}
}
// Free up some memory
if ( isset ( $imagearray ) )
{
unset ( $imagearray );
}
// Now let's make with the horizontal passing. That sentence
// contruct never gets old: "make with the". Oh the humor.
for ( $x = 0; $x < $width; $x ++ )
{
for ( $y = 0; $y < $height; $y ++ )
{
$sum = 0;
$cr = $cg = $cb = 0;
for ( $j = 0; $j < $kernelsize; $j ++ )
{
$kernelx = $x + ( $j - ( $spread - 1 ) );
if ( ( $kernelx >= 0 ) && ( $kernelx < $width ) )
{
$ci = ( $kernelx * $height ) + $y;
$cr += $mult [ $j ] [ ( $shadowarray [ $ci ] >> 16 ) & 0xFF ];
$cg += $mult [ $j ] [ ( $shadowarray [ $ci ] >> 8 ) & 0xFF ];
$cb += $mult [ $j ] [ $shadowarray [ $ci ] & 0xFF ];
$sum += $kernel [ $j ];
}
}
$r = intval ( round ( $cr / $sum ) );
$g = intval ( round ( $cg / $sum ) );
$b = intval ( round ( $cb / $sum ) );
if ( $r < 0 ) {
$r = 0;
}
else if ( $r > 255 ) {
$r = 255;
}
if ( $g < 0 ) {
$g = 0;
}
else if ( $g > 255 ) {
$g = 255;
}
if ( $b < 0 ) {
$b = 0;
}
else if ( $b > 255 ) {
$b = 255;
}
$color = ( $r << 16 ) | ( $g << 8 ) | $b;
if ( ! isset ( $colors [ $color ] ) )
{
$colors [ $color ] = imagecolorallocate ( $image, $r, $g, $b );
}
imagesetpixel ( $image, $x, $y, $colors [ $color ] );
}
}
}
public function addShadow ( $angle, $offset, $transparency, $softness, $shadowColor )
{
$semiSoft = 0.5 * $softness;
$xOffset = round ( cos ( deg2rad ( $angle ) ) * $offset );
$yOffset = round ( sin ( deg2rad ( $angle ) ) * $offset );
$newWidth = $this->getWidth () + abs ( $xOffset ) + $softness;
$newHeight = $this->getHeight () + abs ( $yOffset ) + $softness;
$shadowX = $xOffset < 0 ? 0 : $xOffset;
$shadowY = $yOffset < 0 ? 0 : $yOffset;
$newX = $xOffset < 0 ? $semiSoft + abs ( $xOffset ) : ( $xOffset < $semiSoft ? $semiSoft - $xOffset : 0 );
$newY = $yOffset < 0 ? $semiSoft + abs ( $yOffset ) : ( $yOffset < $semiSoft ? $semiSoft - $yOffset : 0 );
$newImage = ImageGenerator::createTransparentImage ( $newWidth, $newHeight );
$shadowImage = ImageGenerator::createShadowImage ( $this, $transparency, $softness, $shadowColor );
$newImage->merge ( $shadowImage, $shadowX, $shadowY );
$newImage->merge ( $this, $newX, $newY );
$this->imageData = imageClone ( $newImage->imageData );
}
}
class ImageGenerator {
public static function createTransparentImage ( $width, $height )
{
$image = new ImageObject ( imageCreateTrueColor ( $width, $height ) );
imageAlphaBlending ( $image->imageData, false );
imageSaveAlpha ( $image->imageData, true );
$transparency = imageColorAllocateAlpha ( $image->imageData, 0, 0, 0, 127 );
imageFill ( $image->imageData, 0, 0, $transparency );
return $image;
}
public static function createBlankShadowImage ( $image, $transparency, $softness )
{
$shadowImage = new ImageObject ( imageCreateTrueColor ( $image->getWidth () + $softness, $image->getHeight () + $softness ) );
$black = imageColorAllocate ( $image->imageData, 0, 0, 0 );
imageFill ( $shadowImage->imageData, 0, 0, $black );
for ( $x = 0; $x < $image->getWidth (); $x ++ )
{
for ( $y = 0; $y < $image->getHeight (); $y ++ )
{
$colorIndex = imageColorAt ( $image->imageData, $x, $y );
$colorRGB = imageColorsForIndex ( $image->imageData, $colorIndex );
$alphaValue = ( int ) round ( ( 127 - $colorRGB [ 'alpha' ] ) * 2 * $transparency );
$shadowColor = imageColorAllocate ( $shadowImage->imageData, $alphaValue, $alphaValue, $alphaValue );
imageSetPixel ( $shadowImage->imageData, $x + $softness / 2, $y + $softness / 2, $shadowColor );
}
}
$shadowImage->blurGaussian ( $softness );
return $shadowImage;
}
public static function createShadowImage ( $image, $transparency, $softness, $shadowColor )
{
$shadowImage = self::createBlankShadowImage ( $image, $transparency, $softness );
imageAlphaBlending ( $shadowImage->imageData, false );
imageSaveAlpha ( $shadowImage->imageData, true );
for ( $x = 0; $x < $shadowImage->getWidth (); $x ++ )
{
for ( $y = 0; $y < $shadowImage->getHeight (); $y ++ )
{
$color = $shadowImage->getColor ( $x, $y );
$shadowColor = imageColorAllocateAlpha ( $shadowImage->imageData, $color->r, $color->g, $color->b, 127 - ( $color->r / 2 ) );
imageSetPixel ( $shadowImage->imageData, $x, $y, $shadowColor );
}
}
return $shadowImage;
}
public static function createTextImage ( $text, $font, $fontSize, $color )
{
$size = imageTTFBBox ( $fontSize, 0, $font, $text );
$width = abs ( $size [ 2 ] ) + abs ( $size [ 0 ] );
$height = abs ( $size [ 7 ] ) + abs ( $size [ 1 ] );
$image = self::createTransparentImage ( $width, $height );
$textColor = imageColorAllocateAlpha ( $image->imageData, $color->r, $color->g, $color->b, 0 );
imageTTFText ( $image->imageData, $fontSize, 0, 0, abs ( $size [ 5 ] ), $textColor, $font, $text );
return $image;
}
}
class Color {
public function __construct ( $red, $green, $blue, $alpha = 0 )
{
$this->r = $red;
$this->g = $green;
$this->b = $blue;
$this->a = $alpha;
}
public static function createFromHex ( $hexColor )
{
$red = hexdec ( self::charAt ( $hexColor, 0 ) . self::charAt ( $hexColor, 1 ) );
$green = hexdec ( self::charAt ( $hexColor, 2 ) . self::charAt ( $hexColor, 3 ) );
$blue = hexdec ( self::charAt ( $hexColor, 4 ) . self::charAt ( $hexColor, 5 ) );
return new Color ( $red, $green, $blue );
}
public static function charAt ( $str, $pos )
{
return ( substr ( $str, $pos, 1 ) ) ? substr ( $str, $pos, 1 ) : - 1;
}
}