| 591 | aurelien | 1 | <?php
 | 
        
           | 2462 | jpm | 2 | // declare(encoding='UTF-8');
 | 
        
           |  |  | 3 | /**
 | 
        
           |  |  | 4 |  * Classe de manipulation des fichiers images JPEG.
 | 
        
           |  |  | 5 |  *
 | 
        
           |  |  | 6 |  * @internal   Mininum PHP version : 5.2
 | 
        
           |  |  | 7 |  * @category   CEL
 | 
        
           |  |  | 8 |  * @package    Services
 | 
        
           |  |  | 9 |  * @subpackage Bibliothèques
 | 
        
           |  |  | 10 |  * @version    0.1
 | 
        
           |  |  | 11 |  * @author     Mathias CHOUET <mathias@tela-botanica.org>
 | 
        
           |  |  | 12 |  * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
 | 
        
           |  |  | 13 |  * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
 | 
        
           |  |  | 14 |  * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
 | 
        
           |  |  | 15 |  * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
 | 
        
           |  |  | 16 |  * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
 | 
        
           |  |  | 17 |  */
 | 
        
           | 632 | aurelien | 18 | Class ImageRecreation {
 | 
        
           | 1154 | jpm | 19 |   | 
        
           | 1883 | mathias | 20 | 	private $droits = 0755;
 | 
        
           | 1874 | aurelien | 21 | 	private $formats = array('CRX2S','CRXS','CXS','CS','CRS','XS','S','M','L','XL','X2L','X3L');
 | 
        
           | 632 | aurelien | 22 | 	const MODE_GD = 'gd';
 | 
        
           |  |  | 23 | 	const MODE_IMAGEMAGICK = 'imagemagick';
 | 
        
           |  |  | 24 | 	private $mode;
 | 
        
           | 1154 | jpm | 25 |   | 
        
           | 632 | aurelien | 26 | 	private $verbose = true;
 | 
        
           | 591 | aurelien | 27 |   | 
        
           | 672 | jpm | 28 | 	public function __construct($config) {
 | 
        
           |  |  | 29 | 		$this->config = $config;
 | 
        
           | 1154 | jpm | 30 |   | 
        
           | 632 | aurelien | 31 | 		if (extension_loaded('imagick')) {
 | 
        
           |  |  | 32 | 			$this->mode = self::MODE_IMAGEMAGICK;
 | 
        
           | 1154 | jpm | 33 | 		} else {
 | 
        
           |  |  | 34 | 			$this->mode = self::MODE_GD;
 | 
        
           | 632 | aurelien | 35 | 		}
 | 
        
           | 591 | aurelien | 36 | 	}
 | 
        
           | 1154 | jpm | 37 |   | 
        
           | 632 | aurelien | 38 | 	public function recreerMiniaturesRecursivement() {
 | 
        
           | 970 | aurelien | 39 | 		$this->itererRecursivement($this->config['cel']['chemin_images']);
 | 
        
           | 632 | aurelien | 40 | 	}
 | 
        
           | 1154 | jpm | 41 |   | 
        
           | 632 | aurelien | 42 | 	public function regenererMiniaturesIntervalle($params) {
 | 
        
           |  |  | 43 | 		$id_debut = $params[0];
 | 
        
           |  |  | 44 | 		$id_fin = $params[1];
 | 
        
           |  |  | 45 |   | 
        
           |  |  | 46 | 		if (is_numeric($id_debut) && is_numeric($id_fin)) {
 | 
        
           | 668 | aurelien | 47 | 			for ($i = $id_debut; $i <= $id_fin; $i++) {;
 | 
        
           | 632 | aurelien | 48 | 			    $tab_param = array($i);
 | 
        
           |  |  | 49 | 			    $this->regenererMiniaturesPourId($tab_param);
 | 
        
           |  |  | 50 | 			}
 | 
        
           |  |  | 51 | 		}
 | 
        
           | 591 | aurelien | 52 | 	}
 | 
        
           | 1154 | jpm | 53 |   | 
        
           | 632 | aurelien | 54 | 	public function regenererMiniaturesPourId($params) {
 | 
        
           |  |  | 55 | 		$id = $params[0];
 | 
        
           |  |  | 56 |   | 
        
           |  |  | 57 | 		if (!is_numeric($id)) {
 | 
        
           | 2462 | jpm | 58 | 			return;
 | 
        
           | 632 | aurelien | 59 | 		}
 | 
        
           |  |  | 60 |   | 
        
           |  |  | 61 | 		$dossier_fichier = $this->obtenirDossierPourFormat($id, 'O');
 | 
        
           |  |  | 62 | 		$nom_fichier = $this->convertirIdBddVersNomFichier($id, 'O');
 | 
        
           | 1154 | jpm | 63 |   | 
        
           | 632 | aurelien | 64 | 		$chemin_fichier = $dossier_fichier.'/'.$nom_fichier;
 | 
        
           |  |  | 65 |   | 
        
           | 1154 | jpm | 66 | 		if (file_exists($chemin_fichier)) {
 | 
        
           | 632 | aurelien | 67 | 			$infos_image_originale = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
 | 
        
           | 1154 | jpm | 68 |   | 
        
           | 632 | aurelien | 69 | 			// creation de miniatures pour chacuns des formats définis
 | 
        
           | 1154 | jpm | 70 | 			foreach ($this->formats as $format) {
 | 
        
           | 632 | aurelien | 71 | 				$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale, $format);
 | 
        
           | 668 | aurelien | 72 | 			};
 | 
        
           | 632 | aurelien | 73 | 		}
 | 
        
           | 621 | aurelien | 74 | 	}
 | 
        
           | 1154 | jpm | 75 |   | 
        
           | 605 | aurelien | 76 | 	public function itererRecursivement($dossier) {
 | 
        
           | 591 | aurelien | 77 | 		// on ne parse que le dossier des images originales
 | 
        
           |  |  | 78 | 		$dossiers_a_exclure = $this->getFormats();
 | 
        
           | 1154 | jpm | 79 |   | 
        
           | 591 | aurelien | 80 | 		foreach (new DirectoryIterator($dossier) as $fichier_ou_dossier) {
 | 
        
           | 632 | aurelien | 81 | 			if ($fichier_ou_dossier->isDot()) {
 | 
        
           | 591 | aurelien | 82 | 				continue;
 | 
        
           |  |  | 83 | 			}
 | 
        
           | 1154 | jpm | 84 |   | 
        
           | 632 | aurelien | 85 | 			if (in_array($fichier_ou_dossier->getBasename(), $dossiers_a_exclure)) {
 | 
        
           | 591 | aurelien | 86 | 				continue;
 | 
        
           |  |  | 87 | 			}
 | 
        
           | 1154 | jpm | 88 |   | 
        
           | 2462 | jpm | 89 | 			if ($fichier_ou_dossier->isDir()) {
 | 
        
           |  |  | 90 | 				$this->itererRecursivement($fichier_ou_dossier->getPathname());
 | 
        
           |  |  | 91 | 			} else {
 | 
        
           |  |  | 92 | 				$nom_fichier = $fichier_ou_dossier->getFilename();
 | 
        
           | 1154 | jpm | 93 |   | 
        
           | 591 | aurelien | 94 | 				$infos_image_originale = $this->obtenirImageEtInfosPourChemin($fichier_ou_dossier->getPathname());
 | 
        
           | 2462 | jpm | 95 | 				$id = $this->convertirBaseNomFichierVersIdBdd($nom_fichier, $this->formats);
 | 
        
           | 1154 | jpm | 96 |   | 
        
           | 2462 | jpm | 97 | 				// creation de miniatures pour chacuns des formats définis
 | 
        
           | 1154 | jpm | 98 | 				foreach ($this->formats as $format) {
 | 
        
           | 591 | aurelien | 99 | 					$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale, $format);
 | 
        
           |  |  | 100 | 				}
 | 
        
           | 2462 | jpm | 101 | 			}
 | 
        
           | 591 | aurelien | 102 | 		}
 | 
        
           |  |  | 103 | 	}
 | 
        
           | 2462 | jpm | 104 |   | 
        
           | 2083 | aurelien | 105 | 	public function creerOuRenvoyerImage($id, $format) {
 | 
        
           |  |  | 106 | 		$dossier = $this->obtenirDossierPourFormat($id, $format);
 | 
        
           |  |  | 107 | 		$nom_fichier = $this->convertirIdBddVersNomFichier($id, $format);
 | 
        
           | 2462 | jpm | 108 | 		$chemin_image = $dossier.'/'.$nom_fichier;
 | 
        
           | 1154 | jpm | 109 |   | 
        
           | 2083 | aurelien | 110 | 		$image = false;
 | 
        
           | 2462 | jpm | 111 | 		if (!file_exists($chemin_image)) {
 | 
        
           | 2133 | aurelien | 112 | 			$chemin_image_originale = $this->obtenirCheminImageOriginale($id);
 | 
        
           |  |  | 113 | 			$infos_image_originale = $this->obtenirImageEtInfosPourChemin($chemin_image_originale);
 | 
        
           | 2083 | aurelien | 114 | 			if($infos_image_originale) {
 | 
        
           | 2133 | aurelien | 115 | 				// le verrou est là dans le (rare) cas où l'image est déjà en train
 | 
        
           | 2462 | jpm | 116 | 				// d'être générée par le script de création des miniatures ou bien
 | 
        
           | 2133 | aurelien | 117 | 				// un autre instance de cette classe appelée par le web service
 | 
        
           |  |  | 118 | 				$fp = fopen($chemin_image_originale, "r");
 | 
        
           | 2462 | jpm | 119 | 				// si le fichier est verrouillé, flock attendra qu'il se libère
 | 
        
           | 2133 | aurelien | 120 | 				$verrou = flock($fp, LOCK_EX);
 | 
        
           |  |  | 121 | 				if(!file_exists($chemin_image)) {
 | 
        
           |  |  | 122 | 					// si le fichier a été locké alors l'image était en train d'être générée
 | 
        
           |  |  | 123 | 					// et donc il n'est pas nécéssaire de la créer (d'où le 2eme test sur file exists)
 | 
        
           |  |  | 124 | 					$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale, $format);
 | 
        
           |  |  | 125 | 				}
 | 
        
           |  |  | 126 | 				$verrou = flock($fp, LOCK_UN);
 | 
        
           |  |  | 127 | 				fclose($fp);
 | 
        
           | 2083 | aurelien | 128 | 				$image = file_get_contents($chemin_image);
 | 
        
           |  |  | 129 | 			}
 | 
        
           |  |  | 130 | 		} else {
 | 
        
           |  |  | 131 | 			$image = file_get_contents($chemin_image);
 | 
        
           |  |  | 132 | 		}
 | 
        
           |  |  | 133 | 		return $image;
 | 
        
           |  |  | 134 | 	}
 | 
        
           |  |  | 135 |   | 
        
           | 668 | aurelien | 136 | 	public function creerMiniatureImageSelonFormat($infos_image_originale, $format = 'O') {
 | 
        
           | 2238 | mathias | 137 | 		$image_redimensionnee = false;
 | 
        
           | 1154 | jpm | 138 | 		if ($format == 'O') {
 | 
        
           | 591 | aurelien | 139 | 			// format original : rien à faire
 | 
        
           |  |  | 140 | 			$image_redimensionnee = $infos_image_originale['image'];
 | 
        
           |  |  | 141 | 		} else {
 | 
        
           | 632 | aurelien | 142 | 			 if ($this->estUnFormatRogne($format)) {
 | 
        
           |  |  | 143 | 			 	if ($this->mode == self::MODE_IMAGEMAGICK) {
 | 
        
           |  |  | 144 | 			 		// si l'on dispose de la librairie imageMagick
 | 
        
           |  |  | 145 | 			 		// on applique l'algorithme d'auto détection de sujets
 | 
        
           |  |  | 146 | 			 		// qui centre la miniature sur le sujet de l'image
 | 
        
           |  |  | 147 | 			 		$image_redimensionnee = $this->opticrop($infos_image_originale, $format);
 | 
        
           | 2238 | mathias | 148 | 			 	}
 | 
        
           |  |  | 149 | 			 	if ($image_redimensionnee === false) {
 | 
        
           |  |  | 150 | 			 		// si l'on ne dispose que de gd ou bien que Imagick a échoué
 | 
        
           | 632 | aurelien | 151 | 					// la minature est une image redimensionnée rognée au centre
 | 
        
           | 1154 | jpm | 152 | 					$image_redimensionnee = $this->creerMiniatureCarreeRognee($infos_image_originale, $format);
 | 
        
           |  |  | 153 | 			 	}
 | 
        
           | 632 | aurelien | 154 | 			} else if ($this->estUnFormatCarre($format)) {
 | 
        
           | 591 | aurelien | 155 | 				// le format carre et une image redimensionnée en gardant son ratio, insérée dans un carré blanc
 | 
        
           | 1154 | jpm | 156 | 				$image_redimensionnee = $this->creerMiniatureCarree($infos_image_originale, $format);
 | 
        
           | 591 | aurelien | 157 | 			} else {
 | 
        
           | 1154 | jpm | 158 | 				$image_redimensionnee = $this->creerMiniature($infos_image_originale, $format);
 | 
        
           | 591 | aurelien | 159 | 			}
 | 
        
           |  |  | 160 | 		}
 | 
        
           | 668 | aurelien | 161 | 		return $image_redimensionnee;
 | 
        
           |  |  | 162 | 	}
 | 
        
           | 2370 | mathias | 163 |   | 
        
           |  |  | 164 | 	/**
 | 
        
           |  |  | 165 | 	 * Déplace une image temporaire uploadée vers le répertoire de stockage d'images,
 | 
        
           |  |  | 166 | 	 * en enregistrant les métadonnées et tout le tintouin.
 | 
        
           |  |  | 167 | 	 * Si $conserverFichiersTemporaires vaut true, l'image est copiée et non déplacée.
 | 
        
           | 2462 | jpm | 168 | 	 *
 | 
        
           | 2370 | mathias | 169 | 	 * @param unknown $fichier
 | 
        
           |  |  | 170 | 	 * @param unknown $id
 | 
        
           |  |  | 171 | 	 * @param unknown $conserverFichiersTemporaires
 | 
        
           |  |  | 172 | 	 * @return Ambigous <multitype:, boolean>|boolean
 | 
        
           |  |  | 173 | 	 */
 | 
        
           |  |  | 174 | 	public function stockerFichierOriginal($fichier, $id, $conserverFichiersTemporaires=false) {
 | 
        
           | 2083 | aurelien | 175 | 		$chemin_fichier_origine = is_array($fichier) ? $fichier['tmp_name'] : $fichier;
 | 
        
           | 2462 | jpm | 176 |   | 
        
           | 2083 | aurelien | 177 | 		$chemin_base_fichier = $this->creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, 'O');
 | 
        
           |  |  | 178 | 		$nom_fichier = $this->convertirIdBddVersNomFichier($id, 'O');
 | 
        
           | 2462 | jpm | 179 |   | 
        
           | 2083 | aurelien | 180 | 		$chemin_fichier = $chemin_base_fichier.'/'.$nom_fichier;
 | 
        
           | 2462 | jpm | 181 |   | 
        
           | 2370 | mathias | 182 | 		$deplacement_fichier = $this->stockerImageExterne($chemin_fichier_origine, $chemin_fichier, $conserverFichiersTemporaires);
 | 
        
           | 2462 | jpm | 183 |   | 
        
           | 2083 | aurelien | 184 | 		if ($deplacement_fichier) {
 | 
        
           |  |  | 185 | 			$infos_image_originale = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
 | 
        
           |  |  | 186 | 			$taux_compression = $this->renvoyerTauxCompressionPourPoids($infos_image_originale['poids_octets']);
 | 
        
           | 2462 | jpm | 187 |   | 
        
           | 2083 | aurelien | 188 | 			if ($taux_compression < 100 && $this->mode == self::MODE_IMAGEMAGICK) {
 | 
        
           |  |  | 189 | 				$this->ecrireImageSurDisqueAvecMeta($chemin_fichier, $taux_compression);
 | 
        
           |  |  | 190 | 			}
 | 
        
           | 1154 | jpm | 191 |   | 
        
           | 2083 | aurelien | 192 | 			return $infos_image_originale;
 | 
        
           | 2462 | jpm | 193 |   | 
        
           | 2083 | aurelien | 194 | 		} else {
 | 
        
           |  |  | 195 | 			$erreur =  'ERROR : probleme durant le déplacement du fichier temporaire \n' ;
 | 
        
           |  |  | 196 | 			$this->logger('CEL_bugs',$erreur);
 | 
        
           |  |  | 197 | 			return false ;
 | 
        
           |  |  | 198 | 		}
 | 
        
           |  |  | 199 | 	}
 | 
        
           | 2462 | jpm | 200 |   | 
        
           | 2083 | aurelien | 201 | 	public function stockerFichierEtCreerMiniatures($fichier, $id) {
 | 
        
           |  |  | 202 | 		$infos_image_originale_stockee = $this->stockerFichierOriginal($fichier, $id);
 | 
        
           | 2462 | jpm | 203 | 		if ($infos_image_originale_stockee) {
 | 
        
           | 2083 | aurelien | 204 | 			$formats = $this->getFormats();
 | 
        
           | 2462 | jpm | 205 |   | 
        
           | 2083 | aurelien | 206 | 			// creation de miniatures pour chacuns des formats définis
 | 
        
           |  |  | 207 | 			foreach($formats as $format) {
 | 
        
           |  |  | 208 | 				$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale_stockee, $format);
 | 
        
           |  |  | 209 | 			}
 | 
        
           |  |  | 210 | 		} else {
 | 
        
           |  |  | 211 | 			$erreur =  'ERROR : impossible d\'obtenir les informations sur l\'image originale \n' ;
 | 
        
           |  |  | 212 | 			$this->logger('CEL_bugs',$erreur);
 | 
        
           |  |  | 213 | 			return false ;
 | 
        
           |  |  | 214 | 		}
 | 
        
           |  |  | 215 | 		return true ;
 | 
        
           |  |  | 216 | 	}
 | 
        
           |  |  | 217 |   | 
        
           | 668 | aurelien | 218 | 	public function creerEtStockerMiniatureFichierImageSelonFormat($id ,$infos_image_originale, $format = 'O') {
 | 
        
           |  |  | 219 | 		$image_redimensionnee = $this->creerMiniatureImageSelonFormat($infos_image_originale, $format);
 | 
        
           | 591 | aurelien | 220 | 		$taux_compression = $this->renvoyerTauxCompressionPourPoids($infos_image_originale['poids_octets']);
 | 
        
           |  |  | 221 | 		$this->ecrireImageSurDisque($image_redimensionnee, $id, $format, $taux_compression);
 | 
        
           |  |  | 222 | 		return true;
 | 
        
           |  |  | 223 | 	}
 | 
        
           | 1154 | jpm | 224 |   | 
        
           | 591 | aurelien | 225 | 	public function creerImageRedimensionnee($infos_image_originale, $hauteur_redimension, $largeur_redimension) {
 | 
        
           |  |  | 226 | 		$image_redimensionnee = imagecreatetruecolor($largeur_redimension, $hauteur_redimension);
 | 
        
           | 1154 | jpm | 227 |   | 
        
           |  |  | 228 | 		imagecopyresampled($image_redimensionnee,
 | 
        
           |  |  | 229 | 			$infos_image_originale['image'],
 | 
        
           |  |  | 230 | 			0, 0,
 | 
        
           |  |  | 231 | 			0, 0,
 | 
        
           |  |  | 232 | 			$largeur_redimension,
 | 
        
           |  |  | 233 | 			$hauteur_redimension,
 | 
        
           |  |  | 234 | 			$infos_image_originale['largeur'],
 | 
        
           | 672 | jpm | 235 | 			$infos_image_originale['hauteur']
 | 
        
           | 591 | aurelien | 236 | 		);
 | 
        
           |  |  | 237 | 		return $image_redimensionnee;
 | 
        
           |  |  | 238 | 	}
 | 
        
           | 1154 | jpm | 239 |   | 
        
           | 591 | aurelien | 240 | 	public function creerMiniature($informations_images, $format) {
 | 
        
           |  |  | 241 | 		$taille_reference_pour_format = $this->obtenirDimensionsPourFormat($format);
 | 
        
           | 1154 | jpm | 242 |   | 
        
           | 591 | aurelien | 243 | 		$taille_image_redimensionnee = $this->calculerTailleImage($informations_images, $taille_reference_pour_format['hauteur']);
 | 
        
           |  |  | 244 | 		$image_redimensionnee = $this->creerImageRedimensionnee($informations_images, $taille_image_redimensionnee['hauteur'], $taille_image_redimensionnee['largeur']);
 | 
        
           | 1154 | jpm | 245 |   | 
        
           | 591 | aurelien | 246 | 		return $image_redimensionnee;
 | 
        
           |  |  | 247 | 	}
 | 
        
           | 1154 | jpm | 248 |   | 
        
           | 591 | aurelien | 249 | 	public function creerMiniatureCarree($informations_image, $format) {
 | 
        
           |  |  | 250 | 		$taille_reference_pour_format = $this->obtenirDimensionsPourFormat($format);
 | 
        
           |  |  | 251 | 		$cote_carre = $taille_reference_pour_format['largeur'];
 | 
        
           | 1154 | jpm | 252 |   | 
        
           | 591 | aurelien | 253 | 		$image_redimensionnee_avec_rapport = $this->creerMiniature($informations_image, $format);
 | 
        
           |  |  | 254 | 		$taille_redimensionnee_avec_rapport = $this->calculerTailleImage($informations_image, $taille_reference_pour_format['hauteur']);
 | 
        
           | 1154 | jpm | 255 |   | 
        
           |  |  | 256 | 		if ($this->estPaysage($informations_image)) {
 | 
        
           | 672 | jpm | 257 | 			$debut_largeur_a_copier = 0 ;
 | 
        
           | 1154 | jpm | 258 | 			$debut_hauteur_a_copier = ($cote_carre - $taille_redimensionnee_avec_rapport['hauteur'])/2 ;
 | 
        
           | 591 | aurelien | 259 | 		} else {
 | 
        
           | 672 | jpm | 260 | 			$debut_largeur_a_copier = ($cote_carre - $taille_redimensionnee_avec_rapport['largeur'])/2 ;
 | 
        
           | 1154 | jpm | 261 | 			$debut_hauteur_a_copier = 0 ;
 | 
        
           | 591 | aurelien | 262 | 		}
 | 
        
           | 1154 | jpm | 263 |   | 
        
           | 591 | aurelien | 264 | 		$image_carre_blanc_cible = $this->renvoyerEtCreerImageCarreeBlancheSelonFormat($cote_carre);
 | 
        
           | 1154 | jpm | 265 |   | 
        
           | 591 | aurelien | 266 | 		imagecopy($image_carre_blanc_cible, $image_redimensionnee_avec_rapport,
 | 
        
           | 672 | jpm | 267 | 			$debut_largeur_a_copier ,$debut_hauteur_a_copier, 0, 0,
 | 
        
           |  |  | 268 | 			$taille_redimensionnee_avec_rapport['largeur'], $taille_redimensionnee_avec_rapport['hauteur']
 | 
        
           | 591 | aurelien | 269 | 		);
 | 
        
           |  |  | 270 |   | 
        
           |  |  | 271 | 		return $image_carre_blanc_cible;
 | 
        
           |  |  | 272 | 	}
 | 
        
           | 1154 | jpm | 273 |   | 
        
           | 591 | aurelien | 274 | 	public function creerMiniatureCarreeRognee($informations_image, $format) {
 | 
        
           |  |  | 275 | 		$taille_reference_pour_format = $this->obtenirDimensionsPourFormat($format);
 | 
        
           |  |  | 276 | 		$cote_carre = $taille_reference_pour_format['largeur'];
 | 
        
           |  |  | 277 | 		$cote_carre_non_redimensionne = 0;
 | 
        
           | 1154 | jpm | 278 |   | 
        
           |  |  | 279 | 		if ($this->estPaysage($informations_image)) {
 | 
        
           |  |  | 280 | 			$cote_carre_non_redimensionne = $informations_image['hauteur'];
 | 
        
           | 2238 | mathias | 281 | 			$debut_largeur_a_copier = ($informations_image['largeur'] / 2) - ($informations_image['hauteur'] / 2);
 | 
        
           | 672 | jpm | 282 | 			$debut_hauteur_a_copier = 0;
 | 
        
           | 1154 | jpm | 283 |   | 
        
           | 672 | jpm | 284 | 			if($debut_largeur_a_copier <= 0) {
 | 
        
           |  |  | 285 | 				$debut_largeur_a_copier = 0;
 | 
        
           |  |  | 286 | 			}
 | 
        
           | 1154 | jpm | 287 |   | 
        
           | 672 | jpm | 288 | 			$nb_pixels_largeur_a_copier = $cote_carre_non_redimensionne;
 | 
        
           |  |  | 289 | 			$nb_pixels_hauteur_a_copier = $cote_carre_non_redimensionne;
 | 
        
           |  |  | 290 | 		} else {
 | 
        
           |  |  | 291 | 			$cote_carre_non_redimensionne = $informations_image['largeur'];
 | 
        
           |  |  | 292 | 			$debut_largeur_a_copier = 0 ;
 | 
        
           | 2238 | mathias | 293 | 			$debut_hauteur_a_copier = ($informations_image['hauteur'] / 2) - ($informations_image['largeur'] / 2);
 | 
        
           | 1154 | jpm | 294 |   | 
        
           | 672 | jpm | 295 | 			if($debut_hauteur_a_copier <= 0) {
 | 
        
           | 591 | aurelien | 296 | 				$debut_hauteur_a_copier = 0;
 | 
        
           | 672 | jpm | 297 | 			}
 | 
        
           | 1154 | jpm | 298 |   | 
        
           | 672 | jpm | 299 | 			$nb_pixels_largeur_a_copier = $cote_carre_non_redimensionne;
 | 
        
           |  |  | 300 | 			$nb_pixels_hauteur_a_copier = $cote_carre_non_redimensionne;
 | 
        
           | 591 | aurelien | 301 | 		}
 | 
        
           | 1154 | jpm | 302 |   | 
        
           | 591 | aurelien | 303 | 		$image_carre_temporaire = imagecreatetruecolor($cote_carre_non_redimensionne, $cote_carre_non_redimensionne);
 | 
        
           | 1154 | jpm | 304 |   | 
        
           |  |  | 305 | 		imagecopyresampled($image_carre_temporaire,
 | 
        
           |  |  | 306 | 			$informations_image['image'],
 | 
        
           |  |  | 307 | 			0, 0,
 | 
        
           | 672 | jpm | 308 | 			$debut_largeur_a_copier,
 | 
        
           | 1154 | jpm | 309 | 			$debut_hauteur_a_copier,
 | 
        
           |  |  | 310 | 			$cote_carre_non_redimensionne,
 | 
        
           |  |  | 311 | 			$cote_carre_non_redimensionne,
 | 
        
           |  |  | 312 | 			$nb_pixels_largeur_a_copier,
 | 
        
           | 672 | jpm | 313 | 			$nb_pixels_hauteur_a_copier
 | 
        
           | 591 | aurelien | 314 | 		);
 | 
        
           | 1154 | jpm | 315 |   | 
        
           | 591 | aurelien | 316 | 		$image_redimensionnee = imagecreatetruecolor($cote_carre, $cote_carre);
 | 
        
           | 1154 | jpm | 317 |   | 
        
           |  |  | 318 | 		imagecopyresampled($image_redimensionnee,
 | 
        
           |  |  | 319 | 			$image_carre_temporaire,
 | 
        
           |  |  | 320 | 			0, 0,
 | 
        
           |  |  | 321 | 			0, 0,
 | 
        
           |  |  | 322 | 			$cote_carre,
 | 
        
           |  |  | 323 | 			$cote_carre,
 | 
        
           |  |  | 324 | 			$cote_carre_non_redimensionne,
 | 
        
           | 672 | jpm | 325 | 			$cote_carre_non_redimensionne
 | 
        
           | 591 | aurelien | 326 | 		);
 | 
        
           |  |  | 327 |   | 
        
           |  |  | 328 | 		return $image_redimensionnee;
 | 
        
           |  |  | 329 | 	}
 | 
        
           | 1154 | jpm | 330 |   | 
        
           | 2370 | mathias | 331 | 	/**
 | 
        
           |  |  | 332 | 	 * Déplace un fichier temporaire vers une destination donnée. Si
 | 
        
           |  |  | 333 | 	 * $conserverFichiersTemporaires vaut true, le fichier est copié et non déplacé.
 | 
        
           | 2462 | jpm | 334 | 	 *
 | 
        
           | 2370 | mathias | 335 | 	 * @param unknown $chemin_fichier_temp
 | 
        
           |  |  | 336 | 	 * @param unknown $chemin_destination
 | 
        
           |  |  | 337 | 	 * @param string $conserverFichiersTemporaires
 | 
        
           |  |  | 338 | 	 * @return boolean
 | 
        
           |  |  | 339 | 	 */
 | 
        
           |  |  | 340 | 	public function stockerImageExterne($chemin_fichier_temp, $chemin_destination, $conserverFichiersTemporaires=false) {
 | 
        
           |  |  | 341 | 		if ($conserverFichiersTemporaires === true) {
 | 
        
           |  |  | 342 | 			// copie du fichier
 | 
        
           |  |  | 343 | 			$deplacement = copy($chemin_fichier_temp, $chemin_destination);
 | 
        
           | 632 | aurelien | 344 | 		} else {
 | 
        
           | 2370 | mathias | 345 | 			if (is_uploaded_file($chemin_fichier_temp)) {
 | 
        
           |  |  | 346 | 				$deplacement = move_uploaded_file($chemin_fichier_temp, $chemin_destination);
 | 
        
           |  |  | 347 | 			} else {
 | 
        
           |  |  | 348 | 				$deplacement = rename($chemin_fichier_temp, $chemin_destination);
 | 
        
           |  |  | 349 | 			}
 | 
        
           | 632 | aurelien | 350 | 		}
 | 
        
           | 1154 | jpm | 351 |   | 
        
           | 632 | aurelien | 352 | 		return $deplacement;
 | 
        
           |  |  | 353 | 	}
 | 
        
           | 1154 | jpm | 354 |   | 
        
           | 591 | aurelien | 355 | 	public function creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, $format) {
 | 
        
           | 672 | jpm | 356 | 		$chemin_sur_serveur_final = $this->obtenirDossierPourFormat($id, $format);
 | 
        
           | 1154 | jpm | 357 |   | 
        
           | 672 | jpm | 358 | 		if (!file_exists($chemin_sur_serveur_final)) {
 | 
        
           | 668 | aurelien | 359 | 			umask(0);
 | 
        
           | 672 | jpm | 360 | 			if (!mkdir($chemin_sur_serveur_final, $this->droits, true)) {
 | 
        
           | 591 | aurelien | 361 | 				$erreur =  'ERROR : probleme durant l\'écriture du dossier '.$format.' \n' ;
 | 
        
           | 672 | jpm | 362 | 				$this->logger('CEL_bugs', $erreur);
 | 
        
           | 591 | aurelien | 363 | 				return false;
 | 
        
           |  |  | 364 | 			}
 | 
        
           |  |  | 365 | 		}
 | 
        
           | 1154 | jpm | 366 |   | 
        
           | 591 | aurelien | 367 | 		return $chemin_sur_serveur_final;
 | 
        
           |  |  | 368 | 	}
 | 
        
           | 1154 | jpm | 369 |   | 
        
           | 591 | aurelien | 370 | 	public function obtenirDossierPourFormat($id, $format) {
 | 
        
           | 970 | aurelien | 371 | 		$chemin_base = $this->config['cel']['chemin_images'];
 | 
        
           | 1154 | jpm | 372 |   | 
        
           | 672 | jpm | 373 | 		$chemin_sur_serveur = $chemin_base;
 | 
        
           | 1154 | jpm | 374 |   | 
        
           | 672 | jpm | 375 | 		$id = sprintf('%09s', $id);
 | 
        
           |  |  | 376 | 		$id = wordwrap($id, 3 , '_', true);
 | 
        
           | 1154 | jpm | 377 |   | 
        
           | 672 | jpm | 378 | 		list($dossierNiveau1, $dossierNiveau2) = explode('_', $id);
 | 
        
           | 1154 | jpm | 379 |   | 
        
           | 591 | aurelien | 380 | 		$chemin_sur_serveur_final = $chemin_sur_serveur.'/'.$dossierNiveau1.'/'.$dossierNiveau2.'/'.$format;
 | 
        
           | 1154 | jpm | 381 |   | 
        
           | 591 | aurelien | 382 | 		return $chemin_sur_serveur_final;
 | 
        
           |  |  | 383 | 	}
 | 
        
           | 1154 | jpm | 384 |   | 
        
           | 668 | aurelien | 385 | 	public function obtenirCheminImageOriginale($id_image) {
 | 
        
           |  |  | 386 | 		$nom = $this->convertirIdBddVersNomFichier($id_image, 'O');
 | 
        
           |  |  | 387 | 		$dossier = $this->obtenirDossierPourFormat($id_image,'O');
 | 
        
           | 1154 | jpm | 388 |   | 
        
           | 668 | aurelien | 389 | 		return $dossier.'/'.$nom;
 | 
        
           |  |  | 390 | 	}
 | 
        
           | 1154 | jpm | 391 |   | 
        
           | 668 | aurelien | 392 | 	public function obtenirImageEtInfosPourId($id_image) {
 | 
        
           |  |  | 393 | 		$chemin_image_o = $this->obtenirCheminImageOriginale($id_image);
 | 
        
           |  |  | 394 | 		return $this->obtenirImageEtInfosPourChemin($chemin_image_o);
 | 
        
           |  |  | 395 | 	}
 | 
        
           | 1154 | jpm | 396 |   | 
        
           | 591 | aurelien | 397 | 	public function obtenirImageEtInfosPourChemin($chemin_fichier) {
 | 
        
           | 668 | aurelien | 398 | 		$image_et_infos = false;
 | 
        
           | 1154 | jpm | 399 |   | 
        
           |  |  | 400 | 		if (file_exists($chemin_fichier)) {
 | 
        
           | 668 | aurelien | 401 | 			$image_et_infos = array();
 | 
        
           | 1154 | jpm | 402 | 			list($image_et_infos['largeur'], $image_et_infos['hauteur']) = getimagesize($chemin_fichier);
 | 
        
           | 668 | aurelien | 403 | 			$image_et_infos['poids_octets'] = filesize($chemin_fichier);
 | 
        
           |  |  | 404 | 			$image_et_infos['image'] = imagecreatefromjpeg($chemin_fichier);
 | 
        
           |  |  | 405 | 			$image_et_infos['chemin'] = $chemin_fichier;
 | 
        
           |  |  | 406 | 		}
 | 
        
           | 1154 | jpm | 407 |   | 
        
           | 591 | aurelien | 408 | 		return $image_et_infos;
 | 
        
           |  |  | 409 | 	}
 | 
        
           | 1154 | jpm | 410 |   | 
        
           | 591 | aurelien | 411 | 	public function obtenirDimensionsPourFormat($format) {
 | 
        
           | 672 | jpm | 412 | 		$dimensions = array('largeur' => 0, 'hauteur' => 0);
 | 
        
           | 1154 | jpm | 413 |   | 
        
           | 970 | aurelien | 414 | 		if (isset($this->config['cel']['format_'.$format])) {
 | 
        
           |  |  | 415 | 			list($dimensions['largeur'], $dimensions['hauteur']) = explode('_', $this->config['cel']['format_'.$format]);
 | 
        
           | 591 | aurelien | 416 | 		}
 | 
        
           | 1154 | jpm | 417 |   | 
        
           | 591 | aurelien | 418 | 		return $dimensions;
 | 
        
           |  |  | 419 | 	}
 | 
        
           | 1154 | jpm | 420 |   | 
        
           | 591 | aurelien | 421 | 	public function calculerTailleImage($informations_images, $taille_max) {
 | 
        
           | 2462 | jpm | 422 | 		$HL_redimension = array();
 | 
        
           | 1154 | jpm | 423 |   | 
        
           | 2462 | jpm | 424 | 		if ($this->estPaysage($informations_images)) {
 | 
        
           |  |  | 425 | 			$rapport = $informations_images['hauteur']/$informations_images['largeur'] ;
 | 
        
           |  |  | 426 | 			$HL_redimension['largeur'] = round($taille_max) ;
 | 
        
           |  |  | 427 | 			$HL_redimension['hauteur'] = round($taille_max*$rapport) ;
 | 
        
           | 1154 | jpm | 428 |   | 
        
           | 2462 | jpm | 429 | 		} else {
 | 
        
           |  |  | 430 | 			$rapport = $informations_images['largeur']/$informations_images['hauteur'] ;
 | 
        
           |  |  | 431 | 			$HL_redimension['hauteur'] = round($taille_max) ;
 | 
        
           |  |  | 432 | 			$HL_redimension['largeur'] = round($taille_max*$rapport) ;
 | 
        
           |  |  | 433 | 		}
 | 
        
           | 1154 | jpm | 434 |   | 
        
           | 2462 | jpm | 435 | 		return $HL_redimension;
 | 
        
           | 591 | aurelien | 436 | 	}
 | 
        
           | 1154 | jpm | 437 |   | 
        
           | 591 | aurelien | 438 | 	public function getFormats() {
 | 
        
           |  |  | 439 | 		return $this->formats;
 | 
        
           |  |  | 440 | 	}
 | 
        
           | 1154 | jpm | 441 |   | 
        
           | 591 | aurelien | 442 | 	public function estUnFormatCarre($format) {
 | 
        
           | 1154 | jpm | 443 | 		return (strpos($format,'C') === 0);
 | 
        
           | 591 | aurelien | 444 | 	}
 | 
        
           | 1154 | jpm | 445 |   | 
        
           | 591 | aurelien | 446 | 	public function estUnFormatRogne($format) {
 | 
        
           | 1154 | jpm | 447 | 		return (strpos($format,'R') === 1);
 | 
        
           | 591 | aurelien | 448 | 	}
 | 
        
           | 1154 | jpm | 449 |   | 
        
           | 591 | aurelien | 450 | 	public function estPaysage($informations_images) {
 | 
        
           |  |  | 451 | 		return $informations_images['largeur'] > $informations_images['hauteur'];
 | 
        
           |  |  | 452 | 	}
 | 
        
           | 1154 | jpm | 453 |   | 
        
           | 591 | aurelien | 454 | 	public function estPortait($informations_images) {
 | 
        
           |  |  | 455 | 		return $informations_images['largeur'] < $informations_images['hauteur'];
 | 
        
           |  |  | 456 | 	}
 | 
        
           | 1154 | jpm | 457 |   | 
        
           | 591 | aurelien | 458 | 	public function renvoyerTauxCompressionPourPoids($poids_octets) {
 | 
        
           | 970 | aurelien | 459 | 		$poids_max_octets = $this->config['cel']['taille_max'];
 | 
        
           | 1154 | jpm | 460 |   | 
        
           | 591 | aurelien | 461 | 		$ratio_compression = 100 ;
 | 
        
           | 1154 | jpm | 462 |   | 
        
           | 2462 | jpm | 463 | 		if ($poids_octets >= $poids_max_octets) {
 | 
        
           |  |  | 464 | 			$ratio_compression = 75 ;
 | 
        
           |  |  | 465 | 		}
 | 
        
           | 1154 | jpm | 466 |   | 
        
           | 2462 | jpm | 467 | 		return $ratio_compression;
 | 
        
           | 591 | aurelien | 468 | 	}
 | 
        
           | 1154 | jpm | 469 |   | 
        
           | 591 | aurelien | 470 | 	public function convertirIdBddVersNomFichier($id, $format, $extension = 'jpg') {
 | 
        
           | 672 | jpm | 471 | 		// creation du format original
 | 
        
           | 591 | aurelien | 472 | 		$id_avec_zeros = sprintf('%09s', $id) ;
 | 
        
           |  |  | 473 | 		$id_avec_zeros_underscores = wordwrap($id_avec_zeros, 3 , '_', true) ;
 | 
        
           | 1154 | jpm | 474 |   | 
        
           | 591 | aurelien | 475 | 		$nom_fichier = $id_avec_zeros_underscores.'_'.$format.'.'.$extension;
 | 
        
           | 1154 | jpm | 476 |   | 
        
           | 591 | aurelien | 477 | 		return $nom_fichier;
 | 
        
           |  |  | 478 | 	}
 | 
        
           | 1154 | jpm | 479 |   | 
        
           | 591 | aurelien | 480 | 	public function convertirBaseNomFichierVersIdBdd($nom_fichier, $formats) {
 | 
        
           |  |  | 481 | 		$nom_fichier_sans_extension = trim($nom_fichier, '.jpg');
 | 
        
           | 1154 | jpm | 482 |   | 
        
           | 2462 | jpm | 483 | 		foreach ($formats as $format) {
 | 
        
           | 591 | aurelien | 484 | 			$nom_fichier_sans_extension = trim($nom_fichier_sans_extension, '_'.$format);
 | 
        
           |  |  | 485 | 		}
 | 
        
           |  |  | 486 | 		$id_image = str_replace('_', '', $nom_fichier_sans_extension);
 | 
        
           | 1154 | jpm | 487 |   | 
        
           | 591 | aurelien | 488 | 		// suppression des 0 devant
 | 
        
           |  |  | 489 | 		$id_image += 0;
 | 
        
           | 1154 | jpm | 490 |   | 
        
           | 591 | aurelien | 491 | 		return $id_image;
 | 
        
           |  |  | 492 | 	}
 | 
        
           | 1154 | jpm | 493 |   | 
        
           | 632 | aurelien | 494 | 	public function ecrireImageSurDisque($image_binaire, $id, $format, $compression = 100) {
 | 
        
           | 591 | aurelien | 495 | 		umask(0);
 | 
        
           | 1154 | jpm | 496 |   | 
        
           | 591 | aurelien | 497 | 		$chemin_sur_serveur_final = $this->creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, $format);
 | 
        
           |  |  | 498 | 		$nom_fichier = $this->convertirIdBddVersNomFichier($id, $format);
 | 
        
           | 1154 | jpm | 499 |   | 
        
           | 632 | aurelien | 500 | 		if (file_exists($chemin_sur_serveur_final.'/'.$nom_fichier)) {
 | 
        
           | 591 | aurelien | 501 | 			unlink($chemin_sur_serveur_final.'/'.$nom_fichier);
 | 
        
           |  |  | 502 | 		}
 | 
        
           | 1154 | jpm | 503 |   | 
        
           | 668 | aurelien | 504 | 		// attention, ceci ne preserve pas les metadonnées
 | 
        
           | 632 | aurelien | 505 | 		imagejpeg($image_binaire, $chemin_sur_serveur_final.'/'.$nom_fichier, $compression);
 | 
        
           | 591 | aurelien | 506 | 		chmod($chemin_sur_serveur_final.'/'.$nom_fichier,$this->droits);
 | 
        
           |  |  | 507 | 	}
 | 
        
           | 1154 | jpm | 508 |   | 
        
           |  |  | 509 | 	public function ecrireImageSurDisqueAvecMeta($chemin_image_a_stocker, $compression = 100) {
 | 
        
           |  |  | 510 | 		$img = new Imagick($chemin_image_a_stocker);
 | 
        
           |  |  | 511 |   | 
        
           | 632 | aurelien | 512 | 		// l'utilisation d'image magick préserve les métadonnées lors d'une recompression
 | 
        
           | 2462 | jpm | 513 | 		$img->setformat('jpeg');
 | 
        
           | 1154 | jpm | 514 | 		$img->setImageCompression(imagick::COMPRESSION_JPEG);
 | 
        
           |  |  | 515 | 		$img->setCompressionQuality($compression);
 | 
        
           |  |  | 516 | 		$img->writeImage($chemin_image_a_stocker);
 | 
        
           |  |  | 517 | 		$img->destroy();
 | 
        
           |  |  | 518 |   | 
        
           |  |  | 519 | 		chmod($chemin_image_a_stocker, $this->droits);
 | 
        
           | 591 | aurelien | 520 | 	}
 | 
        
           | 1154 | jpm | 521 |   | 
        
           | 591 | aurelien | 522 | 	public function renvoyerEtCreerImageCarreeBlancheSelonFormat($cote) {
 | 
        
           | 1154 | jpm | 523 | 		$image_blanche = imagecreatetruecolor($cote, $cote);
 | 
        
           | 591 | aurelien | 524 | 		$blanc = imagecolorallocate($image_blanche, 255, 255, 255);
 | 
        
           |  |  | 525 | 		imagefilledrectangle($image_blanche, 0, 0, $cote, $cote, $blanc);
 | 
        
           |  |  | 526 | 		return $image_blanche;
 | 
        
           |  |  | 527 | 	}
 | 
        
           | 1154 | jpm | 528 |   | 
        
           |  |  | 529 | 	public function detruireImageEnMemoire($image) {
 | 
        
           | 591 | aurelien | 530 | 		imagedestroy($image);
 | 
        
           |  |  | 531 | 	}
 | 
        
           | 1154 | jpm | 532 |   | 
        
           | 2370 | mathias | 533 | 	/**
 | 
        
           |  |  | 534 | 	 * Supprime une image du disque, ainsi que tous les formats générés
 | 
        
           | 2462 | jpm | 535 | 	 *
 | 
        
           | 2370 | mathias | 536 | 	 * @param Integer $id
 | 
        
           |  |  | 537 | 	 * @return boolean true si tous les formats y compris l'original ont été détruits, false s'il en reste au moins un
 | 
        
           |  |  | 538 | 	 */
 | 
        
           | 591 | aurelien | 539 | 	public function detruireImageSurDisque($id) {
 | 
        
           |  |  | 540 | 		$formats = $this->getFormats();
 | 
        
           |  |  | 541 | 		// on detruit aussi l'image originale
 | 
        
           |  |  | 542 | 		$formats[] = 'O';
 | 
        
           | 1154 | jpm | 543 |   | 
        
           | 2370 | mathias | 544 | 		$destruction_formats_fichier = true;
 | 
        
           |  |  | 545 | 		// destructions de chacun des formats définis
 | 
        
           | 591 | aurelien | 546 | 		foreach($formats as $format) {
 | 
        
           |  |  | 547 | 			$dossier_format = $this->obtenirDossierPourFormat($id, $format);
 | 
        
           |  |  | 548 | 			$nom_fichier = $this->convertirIdBddVersNomFichier($id, $format);
 | 
        
           | 1154 | jpm | 549 |   | 
        
           | 632 | aurelien | 550 | 			if (file_exists($dossier_format.'/'.$nom_fichier)) {
 | 
        
           | 2370 | mathias | 551 | 				$detruit = unlink($dossier_format.'/'.$nom_fichier);
 | 
        
           |  |  | 552 | 				$destruction_formats_fichier = ($destruction_formats_fichier && $detruit);
 | 
        
           | 621 | aurelien | 553 | 			}
 | 
        
           | 591 | aurelien | 554 | 		}
 | 
        
           | 1154 | jpm | 555 |   | 
        
           | 621 | aurelien | 556 | 		return $destruction_formats_fichier;
 | 
        
           | 591 | aurelien | 557 | 	}
 | 
        
           | 1154 | jpm | 558 |   | 
        
           | 1755 | raphael | 559 | 	// recopie de Cel->logger() (pas d'extends pour ça)
 | 
        
           |  |  | 560 | 	public function logger($index,$chaine) {
 | 
        
           | 2462 | jpm | 561 | 		if (!class_exists('Log')) {
 | 
        
           | 1755 | raphael | 562 | 			Log::getInstance();
 | 
        
           |  |  | 563 | 		}
 | 
        
           |  |  | 564 |   | 
        
           |  |  | 565 | 		Log::setCheminLog($this->config['log']['cheminlog']);
 | 
        
           |  |  | 566 | 		Log::setTimeZone($this->config['log']['timezone']);
 | 
        
           |  |  | 567 | 		Log::setTailleMax($this->config['log']['taillemax']);
 | 
        
           |  |  | 568 |   | 
        
           |  |  | 569 | 		Log::ajouterEntree($index,$chaine);
 | 
        
           |  |  | 570 | 	}
 | 
        
           |  |  | 571 |   | 
        
           | 1154 | jpm | 572 | 	/*
 | 
        
           | 632 | aurelien | 573 | 	 * edge-maximizing crop
 | 
        
           | 1154 | jpm | 574 | 	 * determines center-of-edginess, then tries different-sized crops around it.
 | 
        
           | 632 | aurelien | 575 | 	 * picks the crop with the highest normalized edginess.
 | 
        
           |  |  | 576 | 	 * see documentation on how to tune the algorithm
 | 
        
           |  |  | 577 | 	 *
 | 
        
           |  |  | 578 | 	 * $informations_image - le tableau d'informations sur l'image tel que renvoyé par la fonction obtenirImageEtInfosPourChemin
 | 
        
           |  |  | 579 | 	 * $format - le format (ex. : CS, XS, XL, CRS)
 | 
        
           |  |  | 580 | 	*/
 | 
        
           | 672 | jpm | 581 | 	public function opticrop($informations_image, $format) {
 | 
        
           | 632 | aurelien | 582 | 		umask(0);
 | 
        
           | 2238 | mathias | 583 | 		$erreur_ecriture = false;
 | 
        
           | 1154 | jpm | 584 |   | 
        
           | 632 | aurelien | 585 | 		$nom_temp = md5(time());
 | 
        
           | 1154 | jpm | 586 | 		$chemin_temp =
 | 
        
           |  |  | 587 |   | 
        
           | 970 | aurelien | 588 | 		$out = $this->config['cel']['chemin_stockage_temp'].'/'.$nom_temp;
 | 
        
           | 1154 | jpm | 589 |   | 
        
           | 632 | aurelien | 590 | 		$dimension_vignettes = $this->obtenirDimensionsPourFormat($format);
 | 
        
           | 1154 | jpm | 591 |   | 
        
           | 632 | aurelien | 592 | 		$largeur_vignette = $dimension_vignettes['largeur'];
 | 
        
           |  |  | 593 | 		$hauteur_vignette = $dimension_vignettes['hauteur'];
 | 
        
           | 1154 | jpm | 594 |   | 
        
           | 2462 | jpm | 595 | 		// source dimensions
 | 
        
           |  |  | 596 | 		$largeur_image_originale = $informations_image['largeur'];
 | 
        
           |  |  | 597 | 		$hauteur_image_originale = $informations_image['hauteur'];
 | 
        
           | 1154 | jpm | 598 |   | 
        
           | 2462 | jpm | 599 | 		$chemin_image = $informations_image['chemin'];
 | 
        
           | 1154 | jpm | 600 |   | 
        
           | 2462 | jpm | 601 | 		// parameters for the edge-maximizing crop algorithm
 | 
        
           |  |  | 602 | 		$r = 1;         // radius of edge filter
 | 
        
           |  |  | 603 | 		$nk = 9;        // scale count: number of crop sizes to try
 | 
        
           |  |  | 604 | 		$gamma = 0.2;   // edge normalization parameter -- see documentation
 | 
        
           |  |  | 605 | 		$ar = $largeur_vignette/$hauteur_vignette;    // target aspect ratio (AR)
 | 
        
           |  |  | 606 | 		$ar0 = $largeur_image_originale/$hauteur_image_originale;    // original aspect ratio (AR)
 | 
        
           | 1154 | jpm | 607 |   | 
        
           | 2462 | jpm | 608 | 		//echo("$chemin_image: $largeur_image_originale x $hauteur_image_originale => $largeur_vignette x $hauteur_vignette");
 | 
        
           |  |  | 609 | 		$img = new Imagick($chemin_image);
 | 
        
           |  |  | 610 | 		$imgcp = clone $img;
 | 
        
           | 1154 | jpm | 611 |   | 
        
           | 2462 | jpm | 612 | 		// compute center of edginess
 | 
        
           |  |  | 613 | 		$img->edgeImage($r);
 | 
        
           |  |  | 614 | 		$img->modulateImage(100,0,100); // grayscale
 | 
        
           |  |  | 615 | 		$img->blackThresholdImage("#0f0f0f");
 | 
        
           |  |  | 616 | 		$retour_ecriture_img = $img->writeImage($out);
 | 
        
           | 1154 | jpm | 617 |   | 
        
           | 2462 | jpm | 618 | 		if ($retour_ecriture_img !== true) {
 | 
        
           |  |  | 619 | 			error_log("Erreur d'écriture Imagick : [" . $chemin_image . "] vers [" . $out . "]");
 | 
        
           |  |  | 620 | 			$erreur_ecriture = true;
 | 
        
           |  |  | 621 | 		}
 | 
        
           |  |  | 622 | 		// use gd for random pixel access
 | 
        
           |  |  | 623 | 		$im = ImageCreateFromJpeg($out);
 | 
        
           | 2238 | mathias | 624 |   | 
        
           | 2462 | jpm | 625 | 		if ($im === false) {
 | 
        
           |  |  | 626 | 			error_log("GD ne peut pas lire l'image créée par Imagick : [" . $chemin_image . "] vers [" . $out . "]");
 | 
        
           |  |  | 627 | 			$erreur_ecriture = true;
 | 
        
           |  |  | 628 | 		}
 | 
        
           | 2238 | mathias | 629 |   | 
        
           | 2462 | jpm | 630 | 		if (! $erreur_ecriture) {
 | 
        
           |  |  | 631 | 			$xcenter = 0;
 | 
        
           |  |  | 632 | 			$ycenter = 0;
 | 
        
           |  |  | 633 | 			$sum = 0;
 | 
        
           |  |  | 634 | 			$n = 100000;
 | 
        
           |  |  | 635 | 			for ($k=0; $k<$n; $k++) {
 | 
        
           |  |  | 636 | 				$i = mt_rand(0,$largeur_image_originale-1);
 | 
        
           |  |  | 637 | 				$j = mt_rand(0,$hauteur_image_originale-1);
 | 
        
           |  |  | 638 | 				$val = imagecolorat($im, $i, $j) & 0xFF;
 | 
        
           |  |  | 639 | 				$sum += $val;
 | 
        
           |  |  | 640 | 				$xcenter += ($i+1)*$val;
 | 
        
           |  |  | 641 | 				$ycenter += ($j+1)*$val;
 | 
        
           |  |  | 642 | 			}
 | 
        
           |  |  | 643 | 			$xcenter /= $sum;
 | 
        
           |  |  | 644 | 			$ycenter /= $sum;
 | 
        
           | 1154 | jpm | 645 |   | 
        
           | 2462 | jpm | 646 | 			// crop source img to target AR
 | 
        
           |  |  | 647 | 			if ($largeur_image_originale/$hauteur_image_originale > $ar) {
 | 
        
           |  |  | 648 | 				// source AR wider than target
 | 
        
           |  |  | 649 | 				// crop width to target AR
 | 
        
           |  |  | 650 | 				$wcrop0 = round($ar*$hauteur_image_originale);
 | 
        
           |  |  | 651 | 				$hcrop0 = $hauteur_image_originale;
 | 
        
           |  |  | 652 | 			} else {
 | 
        
           |  |  | 653 | 				// crop height to target AR
 | 
        
           |  |  | 654 | 				$wcrop0 = $largeur_image_originale;
 | 
        
           |  |  | 655 | 				$hcrop0 = round($largeur_image_originale/$ar);
 | 
        
           |  |  | 656 | 			}
 | 
        
           | 1154 | jpm | 657 |   | 
        
           | 2462 | jpm | 658 | 			// crop parameters for all scales and translations
 | 
        
           |  |  | 659 | 			$params = array();
 | 
        
           | 1154 | jpm | 660 |   | 
        
           | 2462 | jpm | 661 | 			// crop at different scales
 | 
        
           |  |  | 662 | 			$hgap = $hcrop0 - $hauteur_vignette;
 | 
        
           |  |  | 663 | 			$hinc = ($nk == 1) ? 0 : $hgap / ($nk - 1);
 | 
        
           |  |  | 664 | 			$wgap = $wcrop0 - $largeur_vignette;
 | 
        
           |  |  | 665 | 			$winc = ($nk == 1) ? 0 : $wgap / ($nk - 1);
 | 
        
           |  |  | 666 |   | 
        
           |  |  | 667 | 			// find window with highest normalized edginess
 | 
        
           |  |  | 668 | 			$n = 10000;
 | 
        
           |  |  | 669 | 			$maxbetanorm = 0;
 | 
        
           |  |  | 670 | 			$maxfile = '';
 | 
        
           |  |  | 671 | 			$maxparam = array('w'=>0, 'h'=>0, 'x'=>0, 'y'=>0);
 | 
        
           |  |  | 672 |   | 
        
           |  |  | 673 | 			for ($k = 0; $k < $nk; $k++) {
 | 
        
           |  |  | 674 | 				$hcrop = round($hcrop0 - $k*$hinc);
 | 
        
           |  |  | 675 | 				$wcrop = round($wcrop0 - $k*$winc);
 | 
        
           |  |  | 676 | 				$xcrop = $xcenter - $wcrop / 2;
 | 
        
           |  |  | 677 | 				$ycrop = $ycenter - $hcrop / 2;
 | 
        
           |  |  | 678 | 				//echo("crop: $wcrop, $hcrop, $xcrop, $ycrop");
 | 
        
           |  |  | 679 |   | 
        
           |  |  | 680 | 				if ($xcrop < 0) $xcrop = 0;
 | 
        
           |  |  | 681 | 				if ($xcrop+$wcrop > $largeur_image_originale) $xcrop = $largeur_image_originale-$wcrop;
 | 
        
           |  |  | 682 | 				if ($ycrop < 0) $ycrop = 0;
 | 
        
           |  |  | 683 | 				if ($ycrop+$hcrop > $hauteur_image_originale) $ycrop = $hauteur_image_originale-$hcrop;
 | 
        
           |  |  | 684 |   | 
        
           |  |  | 685 | 				$beta = 0;
 | 
        
           |  |  | 686 | 				for ($c=0; $c<$n; $c++) {
 | 
        
           |  |  | 687 | 					$i = mt_rand(0,$wcrop-1);
 | 
        
           |  |  | 688 | 					$j = mt_rand(0,$hcrop-1);
 | 
        
           |  |  | 689 | 					$beta += imagecolorat($im, $xcrop+$i, $ycrop+$j) & 0xFF;
 | 
        
           |  |  | 690 | 				}
 | 
        
           |  |  | 691 | 				$area = $wcrop * $hcrop;
 | 
        
           |  |  | 692 | 				$betanorm = $beta / ($n*pow($area, $gamma-1));
 | 
        
           |  |  | 693 | 				// echo("beta: $beta; betan: $betanorm");
 | 
        
           |  |  | 694 | 				// echo("image$k.jpg:<br/>\n<img src=\"$currfile\"/>");
 | 
        
           |  |  | 695 | 				// best image found, save it
 | 
        
           |  |  | 696 |   | 
        
           |  |  | 697 | 				if ($betanorm > $maxbetanorm) {
 | 
        
           |  |  | 698 |   | 
        
           |  |  | 699 | 					$maxbetanorm = $betanorm;
 | 
        
           |  |  | 700 | 					$maxparam['w'] = $wcrop;
 | 
        
           |  |  | 701 | 					$maxparam['h'] = $hcrop;
 | 
        
           |  |  | 702 | 					$maxparam['x'] = $xcrop;
 | 
        
           |  |  | 703 | 					$maxparam['y'] = $ycrop;
 | 
        
           |  |  | 704 | 					// $maxfile = $currfile;
 | 
        
           |  |  | 705 | 				}
 | 
        
           |  |  | 706 | 			}
 | 
        
           |  |  | 707 |   | 
        
           |  |  | 708 | 			// écrasement de l'image par la version "croppée"
 | 
        
           |  |  | 709 | 			$imgcp->cropImage($maxparam['w'], $maxparam['h'], $maxparam['x'], $maxparam['y']);
 | 
        
           |  |  | 710 | 			$imgcp->scaleImage($largeur_vignette, $hauteur_vignette);
 | 
        
           |  |  | 711 | 			$imgcp->writeImage($out);
 | 
        
           |  |  | 712 |   | 
        
           |  |  | 713 | 			// return image
 | 
        
           |  |  | 714 | 			chmod($out, 0777);
 | 
        
           |  |  | 715 | 			$img->destroy();
 | 
        
           |  |  | 716 | 			$imgcp->destroy();
 | 
        
           |  |  | 717 | 			$image_sortie = ImageCreateFromJpeg($out);
 | 
        
           |  |  | 718 | 		} else {
 | 
        
           |  |  | 719 | 			// image n'a pas pu être croppée - on retourne l'originale
 | 
        
           |  |  | 720 | 			//$image_sortie = ImageCreateFromJpeg($chemin_image);
 | 
        
           |  |  | 721 | 			$image_sortie = false;
 | 
        
           |  |  | 722 | 		}
 | 
        
           |  |  | 723 |   | 
        
           |  |  | 724 | 		// destruction fichier temporaire dans tous les cas
 | 
        
           |  |  | 725 | 		unlink($out);
 | 
        
           |  |  | 726 |   | 
        
           |  |  | 727 | 		return $image_sortie;
 | 
        
           | 632 | aurelien | 728 | 	}
 | 
        
           | 2462 | jpm | 729 | }
 |