|
|
|
|
|
|
| |
PHPDRAW, the wannabe Photoshop ;-)
This application allows you to draw an image using commands just like we used to with good old LOGO :-). Its use is easy : a command followed by a space and its parameter(s). Here are all the commands :
right, left, down, up followed by an integer in pixel : draws a line.
pixel followed by an integer in pixel : sets pixels thickness.
color followed by an integer 9 characters long (rrrgggbbb) : sets the color of your next commands.
x, y followed by an integer in pixel : moves to the X, Y position (command is not x, y...command is either x followed by its position, or y followed by its position)
ellipse followed by 2 integers in pixel separated by the character - : draws an ellipse using current X and Y position for the start.
filledellipse followed by 2 integers in pixel separated by the character - : same as above, but for a filled ellipse.
filledarc followed by 4 integers in pixel separated by the character - : same as above, bu for a filled arc.
rectangle followed by 2 integers in pixel separated by the character - : draws a rectangle.
polygon followed by N integers in pixel separated by the character _ : draws a polygon. Beware : N must be even.
fontsize followed by an integer between 1 and 5 : sets the font size.
text followed by a string delimited by the character " : draws the text (example : text "Hello World")
file followed by a string: saves your masterpiece to a file named after the given string :-)
Some examples :
right 40
draws a line going to the right and of 40 pixels long
x 10
moves to position x = 10
color 255000000
sets color to red
rectangle 40-40
draws a rectangle which upper left starts at X-Y current position and bottom right ends at 40-40
polygon 40-40-100-120-10-20
draws a triangle (3 summits, because we have 3 pairs of integers)
And of course, you can use a chain of commands, each of them will be interpreted one after the other :
color 000000255 right 40 pixel 2 up 60 fontsize 4 text "Hello World" file myMasterPiece.png
| <?php
/**
* Notre INTERFACE EXPRESSION
*
*/
interface expression {
public static function interpret(interpreter $subject, $mParam);
}
/**
* Une EXPRESSION CONCRETE pour les mouvements vers la droite
*
*/
class right implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid distance '.$mParam);
}
$mParam = (int)$mParam;
if (false === imageline($subject->IMG, $subject->X, $subject->Y, $subject->X+$mParam, $subject->Y, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create line');
}
$subject->X += $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour les mouvements vers la gauche
*
*/
class left implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid distance '.$mParam);
}
$mParam = (int)$mParam;
if (false === imageline($subject->IMG, $subject->X, $subject->Y, $subject->X-$mParam, $subject->Y, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create line');
}
$subject->X -= $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour les mouvements vers le haut
*
*/
class up implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid distance '.$mParam);
}
$mParam = (int)$mParam;
if (false === imageline($subject->IMG, $subject->X, $subject->Y, $subject->X, $subject->Y-$mParam, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create line');
}
$subject->Y -= $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour les mouvements vers le bas
*
*/
class down implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid distance '.$mParam);
}
$mParam = (int)$mParam;
if (false === imageline($subject->IMG, $subject->X, $subject->Y, $subject->X, $subject->Y+$mParam, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create line');
}
$subject->Y += $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour la création d'une ellipse
*
*/
class ellipse implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(false === strpos($mParam, '-')) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid parameter '.$mParam);
}
$aParam = explode('-', $mParam);
$iWidth = (int)$aParam[0];
$iHeight = (int)$aParam[1];
if (false === imageellipse($subject->IMG, $subject->X, $subject->Y, $iWidth, $iHeight, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create ellipse');
}
$subject->Y += $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour la création d'une ellipse remplie
*
*/
class filledellipse implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(false === strpos($mParam, '-')) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid parameter '.$mParam);
}
$aParam = explode('-', $mParam);
$iWidth = (int)$aParam[0];
$iHeight = (int)$aParam[1];
if (false === imagefilledellipse($subject->IMG, $subject->X, $subject->Y, $iWidth, $iHeight, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create filled ellipse');
}
$subject->Y += $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour la création d'un arc remplis
*
*/
class filledarc implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(false === strpos($mParam, '-')) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid parameter '.$mParam);
}
$aParam = explode('-', $mParam);
$iWidth = (int)$aParam[0];
$iHeight = (int)$aParam[1];
$iStart = (int)$aParam[2];
$iEnd = (int)$aParam[3];
if (false === imagefilledarc($subject->IMG, $subject->X, $subject->Y, $iWidth, $iHeight, $iStart, $iEnd, $subject->RCOLOR, IMG_ARC_PIE)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create filled arc');
}
$subject->Y += $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour la création d'un rectangle
*
*/
class rectangle implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(false === strpos($mParam, '-')) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid parameter '.$mParam);
}
$aParam = explode('-', $mParam);
$iX = (int)$aParam[0];
$iY = (int)$aParam[1];
if (false === imagerectangle($subject->IMG, $subject->X, $subject->Y, $iX, $iY, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create rectangle');
}
$subject->Y += $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour la création d'un polygone
*
*/
class polygon implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(false === strpos($mParam, '-')) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid parameter '.$mParam);
}
$aParam = array_map ('intval', explode('-', $mParam));
$iCount = count($aParam);
if(0 !== $iCount%2) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : total points must be even : '.$iCount);
}
$iCount /= 2;
if (false === imagepolygon($subject->IMG, $aParam, $iCount, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create polygon');
}
$subject->Y += $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour la couleur du trait
*
*/
class color implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam) || 9 !== strlen($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid color '.$mParam);
}
$iRed = (int)substr($mParam, 0, 3);
$iGreen = (int)substr($mParam, 3, 3);
$iBlue = (int)substr($mParam, 6, 3);
$subject->RCOLOR = imagecolorallocate($subject->IMG, $iRed, $iGreen, $iBlue);
$subject->SCOLOR = $mParam;
if(false === $subject->RCOLOR) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to allocate color '.$mParam);
}
}
}
/**
* Une EXPRESSION CONCRETE pour la position X
*
*/
class x implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid position '.$mParam);
}
$mParam = (int)$mParam;
$subject->X = $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour la position Y
*
*/
class y implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid position '.$mParam);
}
$mParam = (int)$mParam;
$subject->Y = $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour l'épaisseur du trait
*
*/
class pixel implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid position '.$mParam);
}
$mParam = (int)$mParam;
if (false === imagesetthickness($subject->IMG, $mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to set thickness '.$mParam);
}
$subject->SPIXEL = $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour initialiser la taille de la police de caractère (1-5)
*
*/
class fontsize implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_numeric($mParam) || $mParam < 1 || $mParam > 5) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid font size '.$mParam);
}
$mParam = (int)$mParam;
$subject->FONTSIZE = $mParam;
}
}
/**
* Une EXPRESSION CONCRETE pour l'écriture d'un texte
*
*/
class text implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(0 !== strpos($mParam, '"') || (strlen($mParam) - 1) !== strrpos($mParam, '"')) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid text value '.$mParam);
}
$mParam = trim($mParam, '"');
if (false === imagestring($subject->IMG, $subject->FONTSIZE, $subject->X, $subject->Y, $mParam, $subject->RCOLOR)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to write text '.$mParam);
}
}
}
/**
* Une EXPRESSION CONCRETE pour la sauvegarde de l'image sous un nom particulier
*
*/
class file implements expression {
public static function interpret(interpreter $subject, $mParam) {
if(!is_string($mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid filename '.$mParam);
}
if (false === imagepng($subject->IMG, $mParam)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to ssave image to file '.$mParam);
}
}
}
/**
* Notre INTERPRETER
*
*/
class interpreter {
private $iX = 200;
private $iY = 200;
private $sColor;
private $iWidth = 500;
private $iHeight = 500;
private $iThickNess = 1;
private $iFontSize = 1;
private $aDefaultDim = array(500,500);
private $oExpressionStack;
private $imh;
private $colorh;
private $aCor = array(
'X' => array('cor' => 'iX', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'Y' => array('cor' => 'iY', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'COLOR' => array('cor' => 'sColor', 'type' => 'is_string', 'gettable' => true, 'settable' => true),
'SCOLOR' => array('cor' => 'sColor', 'type' => 'is_string', 'gettable' => true, 'settable' => true),
'RCOLOR' => array('cor' => 'colorh', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'WIDTH' => array('cor' => 'iWidth', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'HEIGHT' => array('cor' => 'iHeight', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'PIXEL' => array('cor' => 'iThickNess', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'FONTSIZE' => array('cor' => 'iFontSize', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'SPIXEL' => array('cor' => 'iThickNess', 'type' => 'is_int', 'gettable' => true, 'settable' => true),
'IMG' => array('cor' => 'imh', 'type' => 'is_resource', 'gettable' => true, 'settable' => false)
);
public function __construct($sFile = null) {
if(!is_null($sFile)) {
$this->imh = @imagecreatefrompng($sFile);
if(!$this->imh) {
throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : '.$sFile.' has not been found');
}
} else {
$this->imh = imagecreatetruecolor($this->iWidth, $this->iHeight);
imagecolorallocate($this->imh, 0, 0, 0);
}
}
public function interpret ($sChaine) {
if(!is_string($sChaine)) {
throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Parameter must be a string');
}
$this->oExpressionStack = new ArrayIterator(preg_split('`("[^"]+")|[\s]+`', $sChaine, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE));
$this->evaluate();
}
private function evaluate() {
while($this->oExpressionStack->valid()) {
$sToken = $this->oExpressionStack->current();
if(!class_exists($sToken)) {
throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid expression '.$sToken);
}
$this->oExpressionStack->next();
$mParam = $this->oExpressionStack->current();
$interpreter = new ReflectionMethod($sToken, 'interpret');
$interpreter->invoke(null, $this, $mParam);
$this->oExpressionStack->next();
}
}
public function getMove() {
if(true === headers_sent()) {
throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Unable to display image, headers already sent');
}
header('Content-type: image/png');
imagepng($this->imh);
}
public function getSavedMove($sFile) {
imagepng($this->imh, $sFile);
}
public function __get($sProp) {
if(!array_key_exists($sProp, $this->aCor) || !isset($this->aCor[$sProp]['gettable']) || false === $this->aCor[$sProp]['gettable']) {
throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Property '.$sProp.' is not gettable');
}
$sThisProp = $this->aCor[$sProp]['cor'];
return $this->$sThisProp;
}
public function __set($sProp, $mVal) {
if(!array_key_exists($sProp, $this->aCor) || !isset($this->aCor[$sProp]['settable']) || false === $this->aCor[$sProp]['settable'] || !isset($this->aCor[$sProp]['type'])) {
throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Property '.$sProp.' is not settable');
}
$sFunc = $this->aCor[$sProp]['type'];
if(!$sFunc($mVal)) {
throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Value '.$mVal.' is not a valid value for '.$sProp.'; waited : '.substr($sFunc, 3));
}
if($sProp === 'COLOR') {
color::interpret($this, $mVal);
$this->sColor = $mVal;
} elseif($sProp === 'PIXEL') {
pixel::interpret($this, $mVal);
$this->iThickNess = (int)$mVal;
} elseif($sProp === 'FONTSIZE') {
fontsize::interpret($this, $mVal);
$this->iFontSize = (int)$mVal;
} else {
$sThisProp = $this->aCor[$sProp]['cor'];
$this->$sThisProp = $mVal;
}
}
}
?> | | |
|
| |