[php 5.1] photophop (phpdraw 2)

Description

Cette petite application est basée sur le moteur de PHPDRAW http://www.phpcs.com/codes/PHP5-PHPDRAW-PHOTOSHOP-PHP-PRESQUE_44299.aspx

DESCRIPTIF ET INSTALLATION
PhotoPHoP est un applicatif web de dessin et de retouche d'image. Il s'utilise entièrement à la souris, s'appuyant sur
les technologies PHP5.1 et son extension GD2, Javascript et la librairie Prototype, et la technique Ajax.

Pour le faire fonctionner, outre le fait de pouvoir faire tourner PHP5.1 avec GD2 activée, vous devrez peut-être
modifier sa configuration. Celle-ci se trouve dans le fichier 'inc/inc.main.php'. Il faut redéfinir les chemins dans les constantes.
Par défaut, la racine est 'www/phpdraw2/'.

PhotoPHoP a été testé sous Internet Explorer 6 et 7, Firefox 2 et Flock 1.

Les types d'images supportés au 20071207 sont les PNG, JPEG et GIF.

FONCTIONNALITES
Voici la liste des fonctionnalités de PhotoPHoP. Consultez la partie DOCUMENTATION pour apprendre à les utiliser.
- Ouvrir une image
- Créer une nouvelle image
- sauvegarder une image

- faire un "undo"
- effectuer une sélection

- Choisir la couleur courante
- Remplir avec la couleur ou le motif courants
- Choisir le motif courant

- Ecrire un texte horizontal
- Ecrire un texte vertical
- Choisir la taille de la police de caractère du texte

- Tracer une ligne
- Choisir l'épaisseur du trait
- Tracer un rectangle vide
- Tracer un rectangle plein
- Tracer une ellipse vide
- Tracer une ellipse pleine

- Appliquer à l'image un filtre "nuances de gris"
- Appliquer à l'image un filtre "noir et blanc"
- Appliquer à l'image un filtre "colorisation"
- Appliquer à l'image un filtre "sépia"
- Appliquer à l'image un filtre "négatif"
- Appliquer à l'image un filtre "flou gaussien"
- Appliquer à l'image un filtre "flou sélectif"
- Appliquer à l'image un filtre "déplacement"
- Appliquer à l'image un filtre "relief"
- Appliquer à l'image un filtre "surimpression"
- Appliquer à l'image un filtre "lissage"
- Régler l'éclairage de l'image
- Régler le contraste de l'image

- Appliquer une rotation à l'image
- Appliquer à l'image un filtre "ondulations"
- Redimensionner l'image
- Rogner l'image

DOCUMENTATION:

FICHIERS

- Ouvrir une image :
Cliquer sur l'icône "Open image tool" fera apparaître une fenêtre de sélection de fichier. Les fichiers supportés sont
les images de type PNG, JPEG et GIF. Choisissez l'image à ouvrir puis cliquez sur la coche verte pour charger l'image. Elle
s'affichera alors dans PhotoPHoP.

- Créer une nouvelle image :
Cliquer sur l'icône "New image tool" fera apparaître 2 champs de saisie; saisissez-y la largeur puis la hauteur de votre nouvelle
image, en pixel, sans préciser l'unité. Par exemple : saisir 400 et 300 créera une image de 400 pixels de largeur sur 300 pixels
de hauteur. La couleur de fond sera la couleur courante sélectionnée. Voir la partie "Choisir la couleur courante". Cliquez sur
la coche verte pour créer votre nouvelle image. Cliquer à nouveau sur l'icône "New image tool" fera disparaître les champs et
la coche verte.

- Sauvegarder une image :
Cliquer sur l'icône "Save image tool" fera apparaître un champ de saisie et une liste déroulante. Saisissez dans le champ le nom
du fichier sans son extension, puis choisissez son type dans la liste déroulante (PNG, JPEG ou GIF). Cliquez ensuite sur
la coche verte : votre image sera alors sauvegardée dans le répertoire "savedimg/". Cliquer à nouveau sur l'icône
"Save image tool" fera disparaître les champs et la coche verte.

COULEURS
- Choisir la couleur courante :
Cliquer sur l'icône "Color tool" fera apparaître un "colorpicker". Cliquez sur la couleur souhaitée, elle apparaîtra alors dans
le cadre "Current color", à côté de l'icône Color tool". Cliquez à nouveau sur l'icône pour faire disparaître le "colorpicker".
Vous pouvez aussi le laisser ouvert et dessiner en même temps.

- Remplir avec la couleur ou le motif courants :
Cliquer sur l'icône "Fill tool" remplira la page ou la sélection s'il y en a une active, avec la couleur ou le motif
courants.

- Choisir le motif courant :
Cliquer sur l'icône "Tiles tool" fait apparaître une fenêtre avec les motifs présents dans le dossier consacré ("tiles/"
par défaut). Le motif courant est bordé de bleu. Cliquer sur le motif désiré, ou sur "No tile" pour déselectionner un motif (la couleur
courante prendra alors le pas pour les outils de remplissage). Un motif sélectionné prend le pas sur la couleur courante pour les
outils de remplissage.

OUTILS DE DESSIN
NB : Un outil restera sélectionné tant que vous n'en choisissez pas un autre. Pour tracer plusieurs lignes, vous n'avez donc pas à cliquer autant
de fois sur l'icône "Line tool" : un clic suffit pour le sélectionner. Un clic sur un autre outil active ce dernier.
Il existe une exception : le "Line width tool" qui ne désactive pas votre outil courant.

- Tracer une ligne :
Cliquee sur l'icône "Line tool" pour activer cet outil. Il permet de tracer des lignes. Il faut alors cliquer sur l'image : le premier clic marquera la position
de départ de votre ligne. Un second clic marquera son arrivée et affichera la ligne. Sa couleur sera la couleur courante
sélectionnée (voir la partie "Choisir la couleur courante"), et son épaisseur sera l'épaisseur de trait courante (voir la partie
"Choisir l'épaisseur du trait").

- Choisir l'épaisseur du trait :
Cliquer sur l'icône "Line width tool" pour choisir l'épaisseur de votre trait. Une liste déroulante apparaît alors : vous avez
le choix d'une épaisseur allant de 1 à 10 pixels. Cet outil ne change pas l'outil de dessin courant sélectionné.

- Tracer un rectangle vide :
Cliquer sur l'icône "Rectangle tool" pour activer cet outil. Il permet de tracer des rectangles vides. Vous devez ensuite
cliquer sur l'image : le premier clic marque le coin supérieur gauche de vitrre rectangle; un second clic marque le coin
inférieur droit de votre rectangle et l'affiche. La couleur du trait sera la couleur courante
sélectionnée (voir la partie "Choisir la couleur courante"), et son épaisseur sera l'épaisseur de trait courante (voir la partie
"Choisir l'épaisseur du trait").
A noter que la création d'un rectangle est visuellement dynamique.

- Tracer un rectangle plein :
Cliquer sur l'icône "Filled rectangle tool" pour activer cet outil. Son comportement est le même que l'outil "Tracer un rectangle vide"
à ceci prêt que le rectangle sera rempli par la couleur courante.

- Tracer une ellipse vide :
Cliquer sur l'icône "Ellipse tool" pour activer cet outil. Il permet de tracer des elipses vides. Vous devez ensuite
cliquer sur l'image : il faut 2 clics pour tracer votre ellipse, marquant son diamètre. La couleur du trait sera la couleur courante
sélectionnée (voir la partie "Choisir la couleur courante"), et son épaisseur sera l'épaisseur de trait courante (voir la partie
"Choisir l'épaisseur du trait").

- Tracer une ellipse pleine :
Cliquer sur l'icône "Filled ellipse tool" pour activer cet outil. Son comportement est le même que l'outil "Tracer une ellipse vide"
à ceci prêt que l'ellipse sera remplie par la couleur courante.

TEXTE
- Ecrire un texte horizontal :
Cliquer sur l'icône "Horizontal text tool" fera apparaître un champ de saisie. Saisissez-y le texte à afficher puis cliquez sur l'image :
le texte 'affiche alors. Votre clic marque le coin supérieur gauche d'où partira votre texte. La couleur du texte sera la couleur courante
sélectionnée (voir la partie "Choisir la couleur courante"), et la taille de la police sera celle de la taille de police courante
(voir la partie "Choisir la taille de la police de caractère du texte"). Cliquer à nouveau sur l'icône "Text tool" fera
disparaître le champ de saisie. Cet outil reste activé tant que vous n'en choisissez pas un autre, comme les outils de dessin.

- Ecrire un texte vertical :
Cliquer sur l'icône "Vertical text tool" pour activer cet outil identique à l'outil "Ecrire un texte horizontal" sauf que le
texte sera écrit à la verticale.

- Choisir la taille de la police de caractère du texte :
Cliquer sur l'icône "Fontsize tool" fera apparaître une liste de sélection allant de 1 à 5. Il s'agit de la taille de la police
de caractère des textes. Cliquer à nouveau sur l'icône "Fontsize tool" fera disparaître la liste de sélection.

FILTRES
- Appliquer à l'image un filtre "nuances de gris" :
Cliquer sur l'icône "Grayscale tool" transforme votre image en nuances de gris.

- Appliquer à l'image un filtre "noir et blanc" :
Cliquer sur l'icône "Black and white tool" transforme votre image en noir et blanc.

- Appliquer à l'image un filtre "colorisation" :
Cliquer sur l'icône "Colorize tool" applique une colorisation à votre image basée sur la couleur courante sélectionnée avec
l'outil "Choisir la couleur courante".

- Appliquer à l'image un filtre "sépia" :
Cliquer sur l'icône "Sepia tool" applique un filtre sépia à votre image.

- Appliquer à l'image un filtre "négatif" :
Cliquer sur l'icône "Negate tool" inverse les couleurs de votre image.

- Appliquer à l'image un filtre "flou gaussien" :
Cliquer sur l'icône "Gaussian blur tool" applique un flou gaussien à votre image.

- Appliquer à l'image un filtre "flou sélectif" :
Cliquer sur l'icône "Selective blur tool" applique un flou sélectif à votre image.

- Appliquer à l'image un filtre "déplacement" :
Cliquer sur l'icône "Mean removal blur tool" applique un effet de déplacement à votre image lui donnant l'air imprécise.

- Appliquer à l'image un filtre "relief" :
Cliquer sur l'icône "Emboss blur tool" applique un filtre relief à votre image.

- Appliquer à l'image un filtre "surimpression" :
Cliquer sur l'icône "Edge tool" applique un effet de surimpression à votre image.

- Appliquer à l'image un filtre "lissage" :
Cliquer sur l'icône "Smooth tool" applique un filtre de lissage à votre image.

- Régler l'éclairage de l'image :
Cliquer sur l'icône "Brightness tool" pour régler l'éclairage de votre image.

- Régler le contraste de l'image :
Cliquer sur l'icône "Contrast tool" pour régler le contraste de votre image.

DEFORMATIONS
- Appliquer une rotation à l'image
Cliquer sur l'icône "Rotate tool" fera apparaître un champ de saisie. Saisissez-y un angle compris entre -360 et +360 (réels
acceptés), puis cliquez sur la coche verte : votre image sera tournée. La couleur de fond utilisée pour remplir les "blancs" créés
sera la couleur courante sélectionnée (voir la partie "Choisir la couleur courante"). Cliquer à nouveau sur l'icône "Rotate tool"
fera disparaître le champ de saisie et la coche verte. Cet outil ne désactive pas les autres.

- Appliquer à l'image un filtre "ondulation" :
Cliquer sur l'icône "Wavy tool" applique un filtre ondulation à votre image. Attention, selon la taille de l'image,
l'application de ce filtre peut être longue.

- Redimensionner l'image
Cliquer sur l'icône "Resize tool" fera apparaître deux champs de saisie et une case à cocher. Saisissez dans le premier champ la
nouvelle largeur et dans le second la nouvelle hauteur. Si la case à cocher est cochée, les proportions seront respectées.
Cliquez sur la coche verte pour redimensionner l'image. Cliquer à nouveau sur l'icône "Resize tool" fera disparaître les champs
de saisie, la case à cocher et la coche verte. Cet outil ne désactive pas les autres.

- Rogner l'image
Cliquer sur l'icône "Crop tool" pour activer cet outil (il désactive les autres outils). Il permet de rogner votre image : le
rognage se fera en fonction d'une sélection marquée par 2 clics sur l'image (départ et arrivée).
A noter que que la sélection de la zone à rogner est visuellement dynamique.

EDITION
- Faire un "undo" :
Cliquer sur l'icône "Undo tool" annulera la dernière action. Le paramètrage par défaut est de 10 retours en arrière possible.

- Effectuer une sélection :
Cliquer sur l'icône "Selection tool" effectuera une sélection. Toutes les actions entreprises ensuite se fera dans la sélection (filtres,
dessins, rognage, etc...). Un nouveau clic sur cet icône annulera la sélection.

Source / Exemple :


<?php
/**
PHOTOPHOP (PHPDRAW 2)
Copyright (C) 2007  Johan Barbier <johan.barbier@gmail.com>

This program 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 2
of the License, or (at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

  • /
/**
  • Notre INTERFACE EXPRESSION
*
  • /
interface expression { public static function interpret(interpreter $subject, $mParam); } /**
  • Une EXPRESSION CONCRETE pour la création d'une ligne
*
  • /
class line 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 === imageline($subject->IMG, $subject->X, $subject->Y, $iX, $iY, $subject->RCOLOR)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create ellipse'); } } } /**
  • 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'); } } } /**
  • 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($subject->TILE === 'none') { if (false === imagefilledellipse($subject->IMG, $subject->X, $subject->Y, $iWidth, $iHeight, $subject->RCOLOR)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create filled ellipse'); } } else { $rTile = miscImgSetter::set($subject->TILE); if(false === imagesettile($subject->IMG, $rTile)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to set tile'); } if (false === imagefilledellipse($subject->IMG, $subject->X, $subject->Y, $iWidth, $iHeight, IMG_COLOR_TILED)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to fill ellipse with tiles'); } } } } /**
  • 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'); } } } /**
  • 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'); } } } /**
  • Une EXPRESSION CONCRETE pour la création d'une ellipse remplie
*
  • /
class filledrectangle 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($subject->TILE === 'none') { if (false === imagefilledrectangle($subject->IMG, $subject->X, $subject->Y, $iX, $iY, $subject->RCOLOR)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to create filled rectangle'); } } else { $rTile = miscImgSetter::set($subject->TILE); if(false === imagesettile($subject->IMG, $rTile)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to set tile'); } if (false === imagefilledrectangle($subject->IMG, $subject->X, $subject->Y, $iX, $iY, IMG_COLOR_TILED)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to fill rectangle with tiles'); } } } } /**
  • 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'); } } } /**
  • 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 remplir l'image ou une sélection avec la couleur courante
*
  • /
class fill implements expression { public static function interpret(interpreter $subject, $mParam) { if($mParam !== '0') { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid parameter '.$mParam); } if($subject->TILE === 'none') { if (false === imagefill($subject->IMG, 0, 0, $subject->RCOLOR)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to fill image'); } } else { $rTile = miscImgSetter::set($subject->TILE); if(false === imagesettile($subject->IMG, $rTile)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to set tile'); } if (false === imagefill($subject->IMG, 0, 0, IMG_COLOR_TILED)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to fill image with tiles'); } } } } /**
  • 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 appliquer un flou gaussien à l'image
*
  • /
class gaussianblur implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid gaussianblur call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_GAUSSIAN_BLUR)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to apply gaussian blur to the image'); } } } /**
  • Une EXPRESSION CONCRETE pour appliquer un flou sélectif à l'image
*
  • /
class selectiveblur implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid selective call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_SELECTIVE_BLUR)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to apply selective blur to the image'); } } } /**
  • Une EXPRESSION CONCRETE pour appliquer un filtre mettant en évidence les bords de l'image
*
  • /
class edgedetect implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid selective call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_EDGEDETECT)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to apply selective blur to the image'); } } } /**
  • Une EXPRESSION CONCRETE pour appliquer un effet de mouvement à l'image la rendant "imprécise
*
  • /
class meanremoval implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid mean removal call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_MEAN_REMOVAL)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to apply mean removal to the image'); } } } /**
  • Une EXPRESSION CONCRETE pour appliquer un effet de relief à l'image
*
  • /
class emboss implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid emboss call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_EMBOSS)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to apply emboss to the image'); } } } /**
  • Une EXPRESSION CONCRETE pour transformer l'image en nuances de gris
*
  • /
class greyscale implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid greyscale call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_GRAYSCALE)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to gray scale the image'); } } } /**
  • Une EXPRESSION CONCRETE pour transformer l'image en son négatif
*
  • /
class negate implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid negate call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_NEGATE)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to negate the image'); } } } /**
  • Une EXPRESSION CONCRETE pour coloriser l'image
*
  • /
class colorize implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid colorize call '.$mParam); } $aColors = str_split($subject->SCOLOR, 3); if(false === imagefilter($subject->IMG, IMG_FILTER_COLORIZE, $aColors[0], $aColors[1], $aColors[2])) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to colorize the image'); } } } /**
  • Une EXPRESSION CONCRETE pour coloriser l'image en sepia
*
  • /
class sepia implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid sepia call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_GRAYSCALE) || false === imagefilter($subject->IMG, IMG_FILTER_COLORIZE, 90, 60, 40)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to sepia the image'); } } } /**
  • Une EXPRESSION CONCRETE pour lisser l'image
*
  • /
class smooth implements expression { public static function interpret(interpreter $subject, $mParam) { $mparam = (float)$mParam; if($mParam < -1924 || $mParam > 2048) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid smooth call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_SMOOTH, $mParam)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to smoothe the image'); } } } /**
  • Une EXPRESSION CONCRETE pour règler l'éclairage l'image
*
  • /
class brightness implements expression { public static function interpret(interpreter $subject, $mParam) { if(!is_numeric($mParam) || $mParam < -255 || $mParam > 255) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid brightness call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_BRIGHTNESS, $mParam)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to bright the image'); } } } /**
  • Une EXPRESSION CONCRETE pour régler le contraste l'image
*
  • /
class contrast implements expression { public static function interpret(interpreter $subject, $mParam) { if(!is_numeric($mParam) || $mParam < -100 || $mParam > 100) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid contrast call '.$mParam); } if(false === imagefilter($subject->IMG, IMG_FILTER_CONTRAST, -$mParam)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to contrast the image'); } } } /**
  • Une EXPRESSION CONCRETE pour la rotation de l'image
*
  • /
class rotate implements expression { public static function interpret(interpreter $subject, $mParam) { $mParam = (float)$mParam; if($mParam < -360 || $mParam > 360) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid rotate call '.$mParam); } if(false === ($subject->IMG = imagerotate($subject->IMG, $mParam, $subject->RCOLOR))) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to rotate the image'); } } } /**
  • Une EXPRESSION CONCRETE pour le redimensionnement d'une image
*
  • /
class resize implements expression { public static function interpret(interpreter $subject, $mParam) { if(false === strpos($mParam, '-')) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid resize parameter '.$mParam); } $aParam = explode('-', $mParam); $iWidth = (int)$aParam[0]; $iHeight = (int)$aParam[1]; $rDestImg = imagecreatetruecolor($iWidth, $iHeight); if(false === (imagecopyresampled($rDestImg, $subject->IMG, 0, 0, 0, 0, $iWidth, $iHeight, $subject->WIDTH, $subject->HEIGHT))) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to resize the image'); } $subject->IMG = $rDestImg; } } /**
  • Une EXPRESSION CONCRETE pour le rognage d'une image
*
  • /
class crop implements expression { public static function interpret(interpreter $subject, $mParam) { if(false === strpos($mParam, '-')) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid resize parameter '.$mParam); } $aParam = explode('-', $mParam); $iX = (int)$aParam[0]; $iY = (int)$aParam[1]; $iWidth = abs($subject->X - $iX ); $iHeight = abs($subject->Y - $iY ); if($subject->X <= $iX) { $iXSRC = $subject->X; } else { $iXSRC = $iX; } if($subject->Y <= $iY) { $iYSRC = $subject->Y; } else { $iYSRC = $iY; } $rDestImg = imagecreatetruecolor($iWidth, $iHeight); if(false === (imagecopy($rDestImg, $subject->IMG, 0, 0, $iXSRC, $iYSRC, $iWidth, $iHeight))) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to resize the image'); } $subject->IMG = $rDestImg; } } /** *
  • /
class wavy implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid wavy call '.$mParam); } $foreground_color = array(mt_rand(0,100), mt_rand(0,100), mt_rand(0,100)); $background_color = array(mt_rand(200,255), mt_rand(200,255), mt_rand(200,255)); $foreground = imagecolorallocate($subject->IMG, $foreground_color[0], $foreground_color[1], $foreground_color[2]); $background = imagecolorallocate($subject->IMG, $background_color[0], $background_color[1], $background_color[2]); $rand1=mt_rand(400000,1000000)/10000000; $rand2=mt_rand(400000,1000000)/10000000; $rand3=mt_rand(400000,1000000)/10000000; $rand4=mt_rand(400000,1000000)/10000000; // phases $rand5=mt_rand(0,3141592)/500000; $rand6=mt_rand(0,3141592)/500000; $rand7=mt_rand(0,3141592)/500000; $rand8=mt_rand(0,3141592)/500000; // amplitudes $rand9=mt_rand(330,420)/110; $rand10=mt_rand(330,450)/110; $iWidth = imagesx($subject->IMG); $iHeight = imagesy($subject->IMG); for($x=0;$x<$iWidth;$x++){ for($y=0;$y<$iHeight;$y++){ $sx=$x+(sin($x*$rand1+$rand5)+sin($y*$rand3+$rand6))*$rand9-$iWidth/2+($iWidth/2)+1; $sy=$y+(sin($x*$rand2+$rand7)+sin($y*$rand4+$rand8))*$rand10; if($sx<0 || $sy<0 || $sx>=$iWidth-1 || $sy>=$iHeight-1){ $color=255; $color_x=255; $color_y=255; $color_xy=255; }else{ $color=imagecolorat($subject->IMG, $sx, $sy) & 0xFF; $color_x=imagecolorat($subject->IMG, $sx+1, $sy) & 0xFF; $color_y=imagecolorat($subject->IMG, $sx, $sy+1) & 0xFF; $color_xy=imagecolorat($subject->IMG, $sx+1, $sy+1) & 0xFF; } if($color==0 && $color_x==0 && $color_y==0 && $color_xy==0){ $newred=$foreground_color[0]; $newgreen=$foreground_color[1]; $newblue=$foreground_color[2]; }else if($color==255 && $color_x==255 && $color_y==255 && $color_xy==255){ $newred=$background_color[0]; $newgreen=$background_color[1]; $newblue=$background_color[2]; }else{ $frsx=$sx-floor($sx); $frsy=$sy-floor($sy); $frsx1=1-$frsx; $frsy1=1-$frsy; $newcolor=( $color*$frsx1*$frsy1+ $color_x*$frsx*$frsy1+ $color_y*$frsx1*$frsy+ $color_xy*$frsx*$frsy); if($newcolor>255) { $newcolor=255; } $newcolor=$newcolor/255; $newcolor0=1-$newcolor; $newred=$newcolor0*$foreground_color[0]+$newcolor*$background_color[0]; $newgreen=$newcolor0*$foreground_color[1]+$newcolor*$background_color[1]; $newblue=$newcolor0*$foreground_color[2]+$newcolor*$background_color[2]; } if(false === imagesetpixel($subject->IMG, $x, $y, imagecolorallocate($subject->IMG, $newred, $newgreen, $newblue))) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to apply wavy to the image'); } } } } } /**
  • Une EXPRESSION CONCRETE pour transformer l'image en noir et blanc
*
  • /
class blackwhite implements expression { public static function interpret(interpreter $subject, $mParam) { if(!ctype_digit($mParam) || (int)$mParam !== 0) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : invalid black and white call '.$mParam); } if(imageistruecolor($subject->IMG)) { if (false === imagetruecolortopalette($subject->IMG, false, 256)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to get true color to palette'); } } for ($iC = 0; $iC < imagecolorstotal($subject->IMG); $iC++) { $aCol = imagecolorsforindex($subject->IMG, $iC); array_pop($aCol); $iColor = (array_sum($aCol) > 383)?255:0; imagecolorset($subject->IMG, $iC, $iColor, $iColor, $iColor); } } } /**
  • Une EXPRESSION CONCRETE pour l'écriture d'un texte horizontal
*
  • /
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 l'écriture d'un texte vertical
*
  • /
class textV 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 === imagestringup($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(defined('PATH_SAVE') && is_dir(PATH_SAVE)) { $sSavedPath = PATH_SAVE; } else { $sSavedPath = '../saved/'; } if(!is_dir($sSavedPath)) { mkdir($sSavedPath, 0755); } $sType = substr($mParam, strrpos($mParam, '.') + 1); switch($sType) { case 'png': $sFunction = create_function('$rImg, $sFile', 'return imagepng($rImg, $sFile);'); break; case 'jpeg': $sFunction = create_function('$rImg, $sFile', 'return imagejpeg($rImg, $sFile);'); break; case 'gif': $sFunction = create_function('$rImg, $sFile', 'return imagegif($rImg, $sFile);'); break; default: throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to save image to file '.$mParam); break; } if (false === $sFunction($subject->IMG, $sSavedPath.$mParam)) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to save image to file '.$mParam); } } } /**
  • Une EXPRESSION CONCRETE pour annuler la dernière action
*
  • /
class undo implements expression { public static function interpret(interpreter $subject, $mParam) { $storer = new SplImageMemento('../stored'); $rImg = $storer->pop(); if(is_resource($rImg) && get_resource_type($rImg) === 'gd') { $subject->IMG = $rImg; } } } /**
  • A static class used to retrieve misc images (such as tiles images)
*
  • /
class miscImgSetter { public static function set($sFileName) { if(false === ($aProps = getimagesize('../'.$sFileName))) { throw new languageException(__CLASS__.'::'.__FUNCTION__.'() : Failed to retrieve image '.$sFileName); } switch($aProps[2]) { case IMAGETYPE_PNG: $sUserFunc = 'imagecreatefrompng'; break; case IMAGETYPE_JPEG: $sUserFunc = 'imagecreatefromjpeg'; break; case IMAGETYPE_GIF: $sUserFunc = 'imagecreatefromgif'; break; default: throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : '.$sFileName.' is not a valid image type'); } $rMiscImg = $sUserFunc('../'.$sFileName); if(false === $rMiscImg) { throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Failed to retrieve image '.$sFileName); } return $rMiscImg; } } /**
  • 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 $sSelectionPos; private $rStoredImage; private $sTile = 'none'; 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' => true), 'SELECTION' => array('cor' => 'sSelectionPos', 'type' => 'is_string', 'gettable' => true, 'settable' => true), 'TILE' => array('cor' => 'sTile', 'type' => 'is_string', 'gettable' => true, 'settable' => true) ); public function __construct($sFile = null, $aNewImgOptions = null) { if(!is_null($sFile)) { $aProps = getimagesize($sFile); switch($aProps[2]) { case IMAGETYPE_PNG: $sUserFunc = 'imagecreatefrompng'; break; case IMAGETYPE_JPEG: $sUserFunc = 'imagecreatefromjpeg'; break; case IMAGETYPE_GIF: $sUserFunc = 'imagecreatefromgif'; break; default: throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : '.$sFile.' is not a valid image type'); break; } $this->imh = @$sUserFunc($sFile); if(!$this->imh) { throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : '.$sFile.' could not be opened an image'); } } elseif(!is_null($aNewImgOptions)) { if(!isset($aNewImgOptions['HEIGHT']) || !isset($aNewImgOptions['WIDTH']) || !isset($aNewImgOptions['BGCOLOR'])) { throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Options to create a new image are wrong'); } $aColors = str_split($aNewImgOptions['BGCOLOR'], 3); $this->imh = imagecreatetruecolor((int)$aNewImgOptions['WIDTH'], (int)$aNewImgOptions['HEIGHT']); $sBackGround = imagecolorallocate($this->imh, (int)$aColors[0], (int)$aColors[1], (int)$aColors[2]); imagefill($this->imh, 0, 0, $sBackGround); } else { $this->imh = imagecreatetruecolor($this->iWidth, $this->iHeight); $sBackGround = imagecolorallocate($this->imh, 0, 0, 0); imagefill($this->imh, 0, 0, $sBackGround); } $this->iWidth = imagesx($this->imh); $this->iHeight = imagesy($this->imh); } 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); } if($sToken !== 'undo') { $storer = new SplImageMemento('../stored'); $storer->attach($this->imh); } if(!empty($this->sSelectionPos)) { $aSelectionPos = explode('-', $this->sSelectionPos); if(count($aSelectionPos) !== 4) { throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : selection position is invalid : '.$this->sSelectionPos); } $this->rStoredImage = $this->imh; $this->iWidth = abs($aSelectionPos[0] - $aSelectionPos[2]); $this->iHeight = abs($aSelectionPos[1] - $aSelectionPos[3]); $this->iX = $this->iX - min($aSelectionPos[0], $aSelectionPos[2]); $this->iY = $this->iY - min($aSelectionPos[1], $aSelectionPos[3]); $this->imh = imagecreatetruecolor($this->iWidth, $this->iHeight); imagecopyresampled($this->imh, $this->rStoredImage, 0, 0, min($aSelectionPos[0], $aSelectionPos[2]), min($aSelectionPos[1], $aSelectionPos[3]), $this->iWidth, $this->iHeight, $this->iWidth, $this->iHeight); } $this->oExpressionStack->next(); $mParam = $this->oExpressionStack->current(); $interpreter = new ReflectionMethod($sToken, 'interpret'); $interpreter->invoke(null, $this, $mParam); $this->oExpressionStack->next(); if(!is_null($this->rStoredImage)) { imagecopy($this->rStoredImage, $this->imh , min($aSelectionPos[0], $aSelectionPos[2]), min($aSelectionPos[1], $aSelectionPos[3]), 0, 0, $this->iWidth, $this->iHeight); $this->imh = $this->rStoredImage; } } } public function getSavedMove($sFile) { if(!imagepng($this->imh, $sFile)) { throw new functionnalException(__CLASS__.'::'.__FUNCTION__.'() : Failed to save temporary file'); } } 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; } } } ?>

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.