<?php
//
// CF ImageText 1.0
// -------------------------------
//
// Author: codefuture.co.uk
// Version: 1.0v
// Date: 07 June 2011 @ 21:48:33
//
// download the latest version from - http://codefuture.co.uk/projects/ImageText/
//
// Copyright (c) 2011 codefuture.co.uk
// This file is part of the CF ImageText 1.0.
//
// CF ImageText 1.0 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// CF ImageText 1.0 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with CF ImageText 1.0. If not, see http://www.gnu.org/licenses/.
//
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
if(isset($_GET['text'])){
$authKey = isset($_GET['a']) ? $_GET['a']:'';
$text = isset($_GET['text']) ? $_GET['text']:'';
$fontSize = isset($_GET['size']) ? (intval($_GET['size'])<5?null:intval($_GET['size'])):null;
$fontName = isset($_GET['font']) ? $_GET['font']:null;
$fontColor = isset($_GET['color']) ? $_GET['color']:null;
$timg = new imageText();
$timg->imageSettings($text,$fontSize,$fontName,$fontColor);
$timg->authSign($authKey);
$timg->makeImage();
}
class imageText {
var $set = array();
var $imgSet = array();
var $imgKey;
function __construct() {
// Settings
$this->set['Path'] = realpath(dirname(__FILE__)); // set's the server path to the script folder
$this->set['url'] = 'http://www.YourSite.com/cfImageText'; // url to the script folder
$this->set['cacheDir'] = '/cache/'; // directory for caching generated images should be writable
$this->set['imgQuality'] = 0; // image save Quality 0-9 (0 is best, not 9)
$this->set['fontDir'] = $this->set['Path'].'/fonts/'; // full path to font folder
$this->set['fontName'] = ''; // preferred TTF font (it needs to be in the fonts folder)
$this->set['fontSize'] = 30; // preferred font size
$this->set['fontColor'] = 666; // preferred font color
$this->set['userKey'] = 'YourUserKey'; // your user key it's best to make this a random string
}
/*
* imageSettings
*
* text -> text on image (str)
* $fontSize -> font settings (arr)
* $fontName -> dir\imageName.png (str)
* $fontColor -> image save quality (int)
*/
public function imageSettings($text,$fontSize=null,$fontName=null,$fontColor=null){
$this->imgSet['txt'] = $text;
$this->imgSet['fontSize'] = is_numeric($fontSize) ? (int)$fontSize:$fontSize;
$this->imgSet['fontColor'] = $fontColor;
$this->imgSet['fontName'] = $fontName;
}
/*
* basic sign checking: computing md5 sum of concatenation of secret key and parameters
*
* auth_sign -> user key (str)
* var -> key var (arr) (order -> userKey, text, fontSize, fontColor, fontName)
*/
public function authSign($authKey){
$this->imgKey = md5($this->set['userKey'].implode("",$this->imgSet));
if ($this->imgKey != $authKey){
// auth error, provided sign is invalid
die('Auth failed');//.$authKey.' != '.$this->imgKey);
}
}
/*
* Make the image
*
* return -> the type of info to send back (str)
*/
public function makeImage($return = 'print'){
$this->imgSet['fontSize'] = !is_null($this->imgSet['fontSize']) && is_numeric($this->imgSet['fontSize']) ? (int)$this->imgSet['fontSize']:$this->set['fontSize'];
$this->imgSet['fontColor'] = !is_null($this->imgSet['fontColor']) ? $this->imgSet['fontColor'] : $this->set['fontColor'];
$this->imgSet['fontName'] = !is_null($this->imgSet['fontName']) ? $this->imgSet['fontName'] : $this->set['fontName'];
// set image key for html out
if($return != 'print'){
$this->imgKey = md5($this->set['userKey'].implode("",$this->imgSet));
}
// if cached file exists output it and quit or return the cache file address
$cacheImg = $this->loadCache($return);
if(is_resource($cacheImg)) return $cacheImg;
if($return == 'html' && is_array($cacheImg))return $cacheImg[0];
$fontAddress = $this->set['fontDir'].$this->imgSet['fontName'].'.ttf';
$txtArray = explode("|",$this->imgSet['txt']);
$longStr = 0;
$offy = 3;
$offx = 3;
foreach ($txtArray as $line){
$lines[]=$line;
$longStr = strlen($line)>strlen($longStr)?$line:$longStr;
}
$n = count($lines);
$bbox = $this->imagettfbbox_t($this->imgSet['fontSize'], 0, $fontAddress, $longStr);
$tww = abs($bbox[2] - $bbox[0]) * 1.01; //Calculates the width of the text box by subtracting the Upper Right "X" position with the Lower Left "X" position.
$thh = abs($bbox[7] - $bbox[1]); //Calculates the height of the text box by adding the absolute value of the Upper Left "Y" position with the Lower Left "Y" position.
$th = -$bbox[7]-1;
$sp = ($n>1)?$th+((($thh*$n)-($n*$th))/($n)):0;
$width = $tww+($offx*2);
$height = $thh*$n+($offy*2);
$image = $this->transparentImage($width,$height);// creating image
$fontColor = $this->html2rgb($this->imgSet['fontColor']);
$tclr = imagecolorallocate($image, $fontColor[0], $fontColor[1], $fontColor[2]);
$ynew = $this->Vert($height,$thh*$n,$th);
foreach($lines as $tx){
$bbox = $this->imagettfbbox_t ($this->imgSet['fontSize'], 0, $fontAddress, $tx);
$tw = $bbox[2]-$bbox[0];
$xnew = $this->Horiz($width,$tww,$tw);
imagettftext($image, $this->imgSet['fontSize'], 0, $xnew, $ynew, $tclr, $fontAddress, $tx);// rendering text
$ynew += $sp;
}
// save cache file
imagepng($image, $cacheImg,$this->set['imgQuality']); // outputing PNG image to file cache
// return image as resource
if($return == 'resource'){
return $image;
}
// output html image tag
elseif($return == 'html'){
return '<img src="'.$this->set['url'].$this->set['cacheDir'].$this->imgKey.'.png" alt="'.implode(" ",$lines).'" title="'.implode(" ",$lines).'" />';
}
// print image png
else{
$this->browserCache(time());
header("Content-type: image/png");
imagepng($image);
}
// destroy image
imagedestroy($image);
}
/*
* checking for cached file:
*
* return -> the type of info to send back (str)
*/
private function loadCache($return){
$cacheFile = $this->set['Path'].$this->set['cacheDir'].$this->imgKey.'.png';
//if cached file exists
if (!file_exists($cacheFile))return $cacheFile;
//if cached file exists output it and quit
if($return == 'resource') return $this->openImage($cacheFile);
if($return == 'html') return array('<img src="'.$this->set['url'].$this->set['cacheDir'].$this->imgKey.'.png'.'" alt="'.urlencode(str_replace("|"," ",$this->imgSet['txt'])).'" title="'.urlencode(str_replace("|"," ",$this->imgSet['txt'])).'" />');
if(array_key_exists("HTTP_IF_MODIFIED_SINCE",$_SERVER)){
$if_modified_since=strtotime(preg_replace('/;.*$/','',$_SERVER["HTTP_IF_MODIFIED_SINCE"]));
if($if_modified_since >= filemtime($cacheFile)){
header("HTTP/1.0 304 Not Modified");
exit();
}
}
$this->browserCache(filemtime($cacheFile));
$filePieces = pathinfo($cacheFile);
header("Content-type: image/".($filePieces['extension']=='jpg'?'jpeg':$filePieces['extension']));
readfile($cacheFile);
exit();
}
/*
* Set's the browsers Cache
*
* time -> the time when the file was last modified
*/
private function browserCache($time){
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT', true, 200);
header('Expires: '.gmdate('D, d M Y H:i:s', $time + 86400*365).' GMT', true, 200);
header("Pragma: public");
header("Cache-Control: maxage=".(86400*14));
}
/*
* openImage
*
* $src -> address of the image
* return image resource
*/
private function openImage($src){
switch( exif_imagetype($src)){
case IMAGETYPE_PNG:
$img = @imagecreatefrompng($src);
break;
case IMAGETYPE_GIF:
$img = @imagecreatefromgif($src);
break;
case IMAGETYPE_JPEG:
$img = @imagecreatefromjpeg($src);
break;
default:
die('can\'t open image');
break;
}
return $img;
}
/*
* Sets the horizontal position of the first character of a line of text.
*
* $width -> width of the image
* $twidth -> width of the longest line of this group of lines of text
* $lwidth -> width of this line of text.
*/
private function Horiz($width,$twidth,$lwidth){
$xnew=0;
$just='left';
$horz='center';
if($just=="right")$xnew=$twidth-$lwidth-2;
if($just=="center")$xnew=($twidth-$lwidth)/2;
if($just=="left")$xnew=1;
if($horz=="right")$xnew=$xnew+($width-$twidth);
if($horz=="center")$xnew=$xnew+($width-$twidth)/2;
return $xnew;
}
/*
* Sets the vertical position of the first character of a line of text.
*
* $height -> height of the image
* $theight -> height of this group of lines of text
* $lheight -> height of one line of text.
*/
private function Vert($height,$theight,$lheight){
$vert = 'center';
if($vert=="center")$ynew=($height/2)-($theight/2)+$lheight;
if($vert=="top")$ynew=$lheight;
if($vert=="bottom")$ynew=$height-$theight+$lheight;
return $ynew;
}
/*
* html2rgb recognizes HTML or CSS colors in format #(hex_red)(hex_green)(hex_blue),
* where hex_red, hex_green and hex_blue are 1 or 2-digit hex-representations of red,
* green or blue color components.
*
* color -> hex color (str)
*/
private function html2rgb($color) {
if (strlen($color) == 6) {
list($strRed, $strGreen, $strBlue) = array( $color[0].$color[1],
$color[2].$color[3],
$color[4].$color[5]);
} elseif (strlen($color) == 3) {
list($strRed, $strGreen, $strBlue) = array( $color[0].$color[0],
$color[1].$color[1],
$color[2].$color[2]);
} elseif (strlen($color) == 2) {
list($strRed, $strGreen, $strBlue) = array( $color[0].$color[1],
$color[0].$color[1],
$color[0].$color[1]);
} elseif (strlen($color) == 1) {
list($strRed, $strGreen, $strBlue) = array( $color[0].$color[0],
$color[0].$color[0],
$color[0].$color[0]);
}
$strRed = hexdec($strRed);
$strGreen = hexdec($strGreen);
$strBlue = hexdec($strBlue);
return array($strRed, $strGreen, $strBlue);
}
/*
* imagettfbbox_t a better function to find the coordinates of the text bounding box so I used it.
* made by uquay K Calloway http://ruquay.com/sandbox/imagettf/ made
*/
private function imagettfbbox_t($size, $angle, $fontfile, $text){
// compute size with a zero angle
$coords = imagettfbbox($size, 0, $fontfile, $text);
// convert angle to radians
$a = deg2rad($angle);
// compute some usefull values
$ca = cos($a);
$sa = sin($a);
$ret = array();
// perform transformations
for($i = 0; $i < 7; $i += 2){
$ret[$i] = round($coords[$i] * $ca + $coords[$i+1] * $sa);
$ret[$i+1] = round($coords[$i+1] * $ca - $coords[$i] * $sa);
}
return $ret;
}
/*
* Checking for gd, Freetype support and
* that your cache dir is really writable to PHP scripts
*
* dir -> cache dir (str)
*/
private function checking($dir){
if (!function_exists('gd_info')) die('No <a href="http://www.php.net/manual/en/ref.image.php">gd</a> support in PHP.');
$gd = gd_info();
if ($gd["FreeType Support"] == false) die('No FreeType support in gd</a>');
$tf = $dir.md5(rand()).".test";
$f = @fopen($tf, "w");
if ($f == false)
die("Fatal error! {$cache_dir} is not writable. Set 'chmod 777 {$cache_dir}'
or something like this");
fclose($f);
unlink($tf);
}
private function transparentImage($width,$height){
$im = imagecreatetruecolor($width, $height);
imagealphablending($im, false);
$color = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $color);
imagesavealpha($im, true);
imagealphablending($im, true);
return $im;
}
}