<?php
/**
* ----------------------------------------------
* MyImage class - (c) 2010 - marco zabel
* marco106 @ gmail . com
* vers. 1.0 21-dec-2010
* It uses the imagick class. For info check:
* http://php.net/manual/en/book.imagick.php
*
* Scope: create and output (to screen or file) an image with superimposed text
* and or other images. See example example.php
*
* You may use and distribute as you want but please leave
* copyright above.
*
* ----------------------------------------------
*/
class MyImage {
var $root_dir="images/"; // source dir for images. Nay be override using ABS=1
var $fonts_dir="fonts/"; // dir where to find fonts
var $image; // deafualt image name
var $dim=array(); // image dimensions. Computed when images are loaded
var $mkr=array(); // stores text to be put on images
//------------------------------------------------------------------------------------------
// $im background image or principal. May be omitted and created later with NewImage
// $root Directory where most images are taken from.
// $abs Set different from '0' if $im is an absolute address
//
// examples:
// 1) $image=new MyImage("http://www.piedmontshills.com/t/images/pergam.jpg","images/",1);
// 2) $image=new MyImage("pergam.jpg","images/");
//
// 3) $image=new MyImage("","/images");
// $image->NewImage("pergam.jpg","image");
//
// are equivalent.
//------------------------------------------------------------------------------------------
function MyImage($im="",$root="images/",$abs=0) {
$this->root_dir = $root; // default images root is "images/"
if (!($im=="")) {
if ($abs<>0) {
$this->image= new Imagick($im);
} else {
$this->image= new Imagick($this->root_dir.$im);
}
$this->imgDim("image");
}
// ------------------------------------ on creation we prepare some arrays to hold texts
$this->mkr['text']=array(); // Text
$this->mkr['color']=array(); // font color
$this->mkr['font']=array(); // font. MUST be in fonts directory.
$this->mkr['fontsize']=array(); // fonts sizeE
$this->mkr['angle']=array(); // text angle. Clockwise is positive
$this->mkr['center']=array(); // if true the text is placed centered to center of image
$this->mkr['x']=array(); // displacemets from center of from top left corner
$this->mkr['y']=array();
}
// -------------- Set Fonts di
function SetFontsDir($dir,$abs=0) {
if ($abs<>0) {
$this->fonts_dir=$dir; // absolute may also be relative to page dir
} else {
$this->fonts_dir=$this->root_dir.$dir; // relative to Root_dir
}
}
// -------------- Get image size and store
function imgDim($name) {
$idfy=$this->$name->identifyImage(); // store sizes in array
$this->dim['x'][$name]=intval($idfy['geometry']['width']/2);
$this->dim['y'][$name]=intval($idfy['geometry']['height']/2);
}
// -------------- Output to screen
function toScreen($out="image") {
header('Content-type: image/jpg'); // you may choose png instead of jpg to preserve trasparency
$this->$out->setImageFormat('jpg'); // only ONE output to screen can be shown
echo $this->$out;
}
// -------------- Output to file
function toFile($file_name,$abs=0,$out="image") {
$this->$out->flattenImages(); // flatten image before output
$this->$out->setImageFormat('jpg'); // can be also jpg ...
if ($abs<>0) { // and you may output all the images you want
$this->$out->writeImage($file_name.".jpg");
} else {
$this->$out->writeImage($this->root_dir.$file_name.".jpg");
}
}
// -------------- Create a support image. It is any image that can be placed on the background
function NewImage($name,$im,$abs=0) {
if ($abs<>0) {
$this->$name=new Imagick($im);
} else {
$this->$name=new Imagick($this->root_dir.$im);
}
$this->imgDim($name);
}
// -------------- Add image to background. A previously craeted image is palced on the background
// x,y are the coordinate referred to top-left corner of background.
// Default mode if DEFAULT but mau be changed (see imagick manual)
function AddToImage($add,$x,$y,$src="image",$mode=Imagick::COMPOSITE_DEFAULT) {
$this->$src->compositeImage($this->$add,Imagick::COMPOSITE_DEFAULT,$x,$y);
}
// -------------- Add a colored bord to an image. The measures of the image are NOT changed
// in array unless you call to change it: $image->imgDim($image_name)
function AddBord($colorin,$sizeh,$sizev,$name="image") {
if ($name=="") { $name="image"; }
$color=new ImagickPixel();
$color->setColor($colorin); // border color
$this->$name->borderImage($color,$sizeh,$sizev); // border width (dx,sx - alto,basso)
}
// ------------------------------- Store texts to add to image
// text is stored for later addition to background
// If $name is omitted the default background image is used
// If the TEXT doesn't fit in one line the font size is reduced to occupy the 90% of the available space
// In case there is a even smaller place to use you can reduce the space available
// with $reduce=0.5 to allow only the 50% of the 90% of the space
// Warning; if Center=false reduction will give unwanted results
function AddText($text,$color,$font,$fontsize,$angle,$center,$x,$y,$name="image",$reduce=1) {
$txs=$this->gsz($text,$font,$fontsize);
if ($txs > ($this->dim['x'][$name]*2*$reduce)) { // check if text fit
$perc=1.90*$reduce*($this->dim['x'][$name])/$txs;
$fontsize=intval($fontsize*$perc); // reduce fontsize
}
array_push($this->mkr['text'],$text);
array_push($this->mkr['color'],$color);
array_push($this->mkr['font'],$font);
array_push($this->mkr['fontsize'],$fontsize);
array_push($this->mkr['angle'],$angle);
array_push($this->mkr['center'],$center);
array_push($this->mkr['x'],$x);
array_push($this->mkr['y'],$y);
}
// ------------------------------- reset texts stored
// Since text can be added to any image when we finish with one we need to reset the array store
function ResetStoredText() {
$this->mkr['text']=array();
$this->mkr['color']=array();
$this->mkr['font']=array();
$this->mkr['fontsize']=array();
$this->mkr['angle']=array();
$this->mkr['center']=array();
$this->mkr['x']=array();
$this->mkr['y']=array();
}
// --------------------------------- Get text size
// Compute size of a given text with a font and a fontsize
function gsz($text,$font,$size) {
$draw = new ImagickDraw();
$draw->setFont($this->fonts_dir.$font);
$draw->setFontSize( $size );
$im = new Imagick();
$mx=$im->queryFontMetrics( $draw, $text ) ;
return $mx['textWidth'];
}
// --------------------------------- Add stored text to image
//
// Put the stored text on the indicated image.
function do_image($name="image") {
$n=count($this->mkr['text']);
for ($i=0;$i<$n;$i++) {
$draw = new ImagickDraw();
$draw->setFillColor($this->mkr['color'][$i]);
$draw->setFont($this->fonts_dir.$this->mkr['font'][$i]);
$draw->setFontSize($this->mkr['fontsize'][$i]);
if ($this->mkr['center'][$i]===true) {
$draw->setGravity (Imagick::GRAVITY_CENTER);
} else {
$draw->setGravity (Imagick::GRAVITY_NORTHWEST);
}
$this->$name->annotateImage($draw,$this->mkr['x'][$i], $this->mkr['y'][$i], $this->mkr['angle'][$i], $this->mkr['text'][$i]);
}
//----------------------------------
// attention! delete following line if you don't want the array sotre be
// emptied after the text ahs been put on the image.
// This should be done if you want to add same text over different images
//----------------------------------
$this->ResetStoredText();
}
// -------------------------------- Store splittable text
// Same as AddText but:
// Words separated by SPACE will be considered one after the other
// Initial of any word will be diplayed with font1 and the rest of the world with font2
// The used is space is computed as in AddText.
// The Text is placed centered on x,y related to center of page.
function AddSplitText($text,$font1,$size1,$color1,$font2,$size2,$color2,$x,$y,$name="image",$reduce=1) {
$y+=$this->dim['y'][$name]; // y= inizial verticalposition of name
$v=split(" ",$text); // split text into words
$txs=$this->gsz($text,$font1,$size1); // size of text
if ($txs > ($this->dim['x'][$name]*2*$reduce)) { // if text doesn'fit reduce font size
$perc=1.90*$reduce*($this->dim['x'][$name])/$txs;
$size1=intval($size1*$perc);
$size2=intval($size2*$perc);
}
// prepare info on each word: c=first letter, cs= its size, r=remaing part or word, cr its size
$str=array();
$totsz=0;
for ($i=0;$i<count($v);$i++) {
$str['c'][$i]=substr($v[$i],0,1);
$str['cs'][$i]=$this->gsz(substr($v[$i],0,1),$font1,$size1);
$str['r'][$i]=substr($v[$i],1,99);
$str['rs'][$i]=$this->gsz(substr($v[$i],1,99),$font2,$size2);
$totsz+=$str['cs'][$i]+$str['rs'][$i]; // size of all words
}
$str['blank']=$this->gsz(" ",$font2,$size2);
$str['totsz']=(count($v)-1)*$str['blank']+$totsz; // we add blanks
$x=$this->dim['x'][$name]-intval($str['totsz']/2); // x= where the text will start
for ($i=0;$i<count($v);$i++) { // add each peace to array store
$this->AddText($str['c'][$i],$color1,$font1,$size1,0,false,$x,$y,$name);
$x+=$str['cs'][$i];
$this->AddText($str['r'][$i],$color2,$font2,$size2,0,false,$x,$y,$name);
$x+=$str['rs'][$i];
$x+=$str['blank'];
}
}
}
?>