Subversion Repositories eFlore/Applications.cel

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
591 aurelien 1
<?php
632 aurelien 2
Class ImageRecreation {
591 aurelien 3
 
605 aurelien 4
	private $droits = 0755;
632 aurelien 5
	private $formats = array('CRX2S','CXS','CS','CRS','XS','S','M','L','XL','X2L','X3L');
6
	const MODE_GD = 'gd';
7
	const MODE_IMAGEMAGICK = 'imagemagick';
8
	private $mode;
9
 
10
	private $verbose = true;
591 aurelien 11
 
12
	public function ImageRecreation($config) {
13
 
14
		$this->config=$config;
632 aurelien 15
		$this->mode = self::MODE_GD;
16
 
17
		if (extension_loaded('imagick')) {
18
			putenv("MAGICK_TEMPORARY_PATH=/home/aurelien/web/file_tmp");
19
			$this->mode = self::MODE_IMAGEMAGICK;
20
		}
591 aurelien 21
	}
22
 
632 aurelien 23
	public function recreerMiniaturesRecursivement() {
24
		$this->itererRecursivement($this->config['cel_db']['chemin_images']);
25
	}
26
 
27
	public function testOptiCrop() {
605 aurelien 28
 
632 aurelien 29
		$image = $this->obtenirImageEtInfosPourChemin('/home/aurelien/web/file_tmp/test.jpg');
30
		return $this->opticrop($image,'CRXS','');
31
 
591 aurelien 32
	}
33
 
632 aurelien 34
	public function regenererMiniaturesIntervalle($params) {
591 aurelien 35
 
632 aurelien 36
		$id_debut = $params[0];
37
		$id_fin = $params[1];
38
 
39
		if (is_numeric($id_debut) && is_numeric($id_fin)) {
40
 
41
 
42
			//echo("Début du traitement des images de ".$id_debut." à ".$id_fin."\n");
43
 
44
			for ($i = $id_debut; $i <= $id_fin; $i++) {
45
 
46
				echo($i."\n");
47
 
48
			    $tab_param = array($i);
49
			    $this->regenererMiniaturesPourId($tab_param);
50
			}
51
		}
591 aurelien 52
	}
53
 
632 aurelien 54
	public function regenererMiniaturesPourId($params) {
55
 
56
		$id = $params[0];
57
 
58
		if (!is_numeric($id)) {
59
		      return;
60
		}
61
 
62
		$dossier_fichier = $this->obtenirDossierPourFormat($id, 'O');
63
 
64
		$nom_fichier = $this->convertirIdBddVersNomFichier($id, 'O');
65
 
66
		$chemin_fichier = $dossier_fichier.'/'.$nom_fichier;
67
 
68
		if(file_exists($chemin_fichier)) {
69
			$infos_image_originale = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
70
 
71
			// creation de miniatures pour chacuns des formats définis
72
			foreach($this->formats as $format) {
73
				$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale, $format);
74
			}
75
 
76
	      	//if($this->verbose) {
77
	      		//echo("traitement de l'image ".$infos_image_originale."\n");
78
	      	//}
79
		} else {
80
			//echo 'le fichier '.$chemin_fichier.'n\'existe pas '."\n";
81
		}
621 aurelien 82
	}
591 aurelien 83
 
605 aurelien 84
	public function itererRecursivement($dossier) {
591 aurelien 85
 
86
		// on ne parse que le dossier des images originales
87
		$dossiers_a_exclure = $this->getFormats();
88
 
89
		foreach (new DirectoryIterator($dossier) as $fichier_ou_dossier) {
90
 
632 aurelien 91
			if ($fichier_ou_dossier->isDot()) {
591 aurelien 92
				continue;
93
			}
94
 
632 aurelien 95
			if (in_array($fichier_ou_dossier->getBasename(), $dossiers_a_exclure)) {
591 aurelien 96
				continue;
97
			}
98
 
632 aurelien 99
		    if ($fichier_ou_dossier->isDir()) {
591 aurelien 100
 
101
		    	$profondeur_dossier_fils = $profondeur + 1;
102
	    		$this->itererRecursivement($fichier_ou_dossier->getPathname(), $profondeur_dossier_fils);
103
 
104
		    } else {
105
 
106
		    	$nom_fichier = $fichier_ou_dossier->getFilename();
107
 
108
				$infos_image_originale = $this->obtenirImageEtInfosPourChemin($fichier_ou_dossier->getPathname());
605 aurelien 109
		    	$id = $this->convertirBaseNomFichierVersIdBdd($nom_fichier, $this->formats);
591 aurelien 110
 
111
		    	// creation de miniatures pour chacuns des formats définis
605 aurelien 112
				foreach($this->formats as $format) {
591 aurelien 113
 
114
					$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale, $format);
115
				}
116
		    }
117
		}
118
	}
119
 
120
	public function creerEtStockerMiniatureFichierImageSelonFormat($id ,$infos_image_originale, $format = 'O') {
121
 
632 aurelien 122
		if ($format == 'O') {
591 aurelien 123
			// format original : rien à faire
124
			$image_redimensionnee = $infos_image_originale['image'];
125
 
126
		} else {
632 aurelien 127
			 if ($this->estUnFormatRogne($format)) {
128
 
129
			 	if ($this->mode == self::MODE_IMAGEMAGICK) {
130
			 		// si l'on dispose de la librairie imageMagick
131
			 		// on applique l'algorithme d'auto détection de sujets
132
			 		// qui centre la miniature sur le sujet de l'image
133
			 		$image_redimensionnee = $this->opticrop($infos_image_originale, $format);
134
			 	} else {
135
			 		// si l'on ne dispose que de gd
136
					// la minature est une image redimensionnée rognée au centre
137
					$image_redimensionnee = $this->creerMiniatureCarreeRognee($infos_image_originale, $format);
138
			 	}
139
			} else if ($this->estUnFormatCarre($format)) {
591 aurelien 140
				// le format carre et une image redimensionnée en gardant son ratio, insérée dans un carré blanc
141
				$image_redimensionnee = $this->creerMiniatureCarree($infos_image_originale, $format);
142
			} else {
143
				$image_redimensionnee = $this->creerMiniature($infos_image_originale, $format);
144
			}
145
		}
146
 
147
		$taux_compression = $this->renvoyerTauxCompressionPourPoids($infos_image_originale['poids_octets']);
148
		$this->ecrireImageSurDisque($image_redimensionnee, $id, $format, $taux_compression);
149
 
150
		return true;
151
	}
152
 
153
	public function creerImageRedimensionnee($infos_image_originale, $hauteur_redimension, $largeur_redimension) {
154
 
155
		$image_redimensionnee = imagecreatetruecolor($largeur_redimension, $hauteur_redimension);
156
 
157
		imagecopyresampled($image_redimensionnee,
158
						$infos_image_originale['image'],
159
						0, 0,
160
						0, 0,
161
						$largeur_redimension,
162
						$hauteur_redimension,
163
						$infos_image_originale['largeur'],
164
						$infos_image_originale['hauteur']
165
		);
166
 
167
		return $image_redimensionnee;
168
	}
169
 
170
	public function creerMiniature($informations_images, $format) {
171
 
172
		$taille_reference_pour_format = $this->obtenirDimensionsPourFormat($format);
173
 
174
		$taille_image_redimensionnee = $this->calculerTailleImage($informations_images, $taille_reference_pour_format['hauteur']);
175
		$image_redimensionnee = $this->creerImageRedimensionnee($informations_images, $taille_image_redimensionnee['hauteur'], $taille_image_redimensionnee['largeur']);
176
 
177
		return $image_redimensionnee;
178
	}
179
 
180
	public function creerMiniatureCarree($informations_image, $format) {
181
 
182
		$taille_reference_pour_format = $this->obtenirDimensionsPourFormat($format);
183
		$cote_carre = $taille_reference_pour_format['largeur'];
184
 
185
		$image_redimensionnee_avec_rapport = $this->creerMiniature($informations_image, $format);
186
		$taille_redimensionnee_avec_rapport = $this->calculerTailleImage($informations_image, $taille_reference_pour_format['hauteur']);
187
 
632 aurelien 188
		if ($this->estPaysage($informations_image)) {
591 aurelien 189
				$debut_largeur_a_copier = 0 ;
190
				$debut_hauteur_a_copier = ($cote_carre - $taille_redimensionnee_avec_rapport['hauteur'])/2 ;
191
		} else {
192
				$debut_largeur_a_copier = ($cote_carre - $taille_redimensionnee_avec_rapport['largeur'])/2 ;
193
				$debut_hauteur_a_copier = 0 ;
194
		}
195
 
196
		$image_carre_blanc_cible = $this->renvoyerEtCreerImageCarreeBlancheSelonFormat($cote_carre);
197
 
198
		imagecopy($image_carre_blanc_cible, $image_redimensionnee_avec_rapport,
199
				$debut_largeur_a_copier ,$debut_hauteur_a_copier, 0, 0,
200
				$taille_redimensionnee_avec_rapport['largeur'], $taille_redimensionnee_avec_rapport['hauteur']
201
		);
202
 
203
		return $image_carre_blanc_cible;
204
	}
205
 
206
	public function creerMiniatureCarreeRognee($informations_image, $format) {
207
 
208
		$taille_reference_pour_format = $this->obtenirDimensionsPourFormat($format);
209
		$cote_carre = $taille_reference_pour_format['largeur'];
210
		$cote_carre_non_redimensionne = 0;
211
 
632 aurelien 212
		if ($this->estPaysage($informations_image)) {
591 aurelien 213
				$cote_carre_non_redimensionne = $informations_image['hauteur'];
214
				$debut_largeur_a_copier = ($informations_image['hauteur'] - $informations_image['hauteur'])/2 ;
215
				$debut_hauteur_a_copier = 0;
216
				$nb_pixels_largeur_a_copier = $informations_image['hauteur'];
217
				$nb_pixels_hauteur_a_copier = $informations_image['hauteur'];
218
		} else {
219
				$cote_carre_non_redimensionne = $informations_image['largeur'];
220
				$debut_largeur_a_copier = 0 ;
221
				$debut_hauteur_a_copier = ($informations_image['largeur'] - $informations_image['largeur'])/2;
222
				$nb_pixels_largeur_a_copier = $informations_image['largeur'];
223
				$nb_pixels_hauteur_a_copier = $informations_image['largeur'];
224
		}
225
 
226
		$image_carre_temporaire = imagecreatetruecolor($cote_carre_non_redimensionne, $cote_carre_non_redimensionne);
227
 
228
		imagecopyresampled($image_carre_temporaire,
229
						$informations_image['image'],
230
						0, 0,
231
						$debut_largeur_a_copier,
232
						$debut_hauteur_a_copier,
233
						$cote_carre_non_redimensionne,
234
						$cote_carre_non_redimensionne,
235
						$nb_pixels_largeur_a_copier,
236
						$nb_pixels_hauteur_a_copier
237
		);
238
 
239
		$image_redimensionnee = imagecreatetruecolor($cote_carre, $cote_carre);
240
 
241
		imagecopyresampled($image_redimensionnee,
242
						$image_carre_temporaire,
243
						0, 0,
244
						0, 0,
245
						$cote_carre,
246
						$cote_carre,
247
						$cote_carre_non_redimensionne,
248
						$cote_carre_non_redimensionne
249
		);
250
 
251
		return $image_redimensionnee;
252
	}
253
 
621 aurelien 254
	public function stockerFichierEtCreerMiniatures($fichier, $id) {
255
 
591 aurelien 256
		$chemin_base_fichier = $this->creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, 'O');
257
		$nom_fichier = $this->convertirIdBddVersNomFichier($id, 'O');
258
 
259
		$chemin_fichier = $chemin_base_fichier.'/'.$nom_fichier;
260
 
632 aurelien 261
		$deplacement_fichier = $this->stockerImageExterne($fichier['tmp_name'], $chemin_fichier);
262
 
263
		if ($deplacement_fichier) {
591 aurelien 264
 
265
			$infos_image_originale = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
266
			$taux_compression = $this->renvoyerTauxCompressionPourPoids($infos_image_originale['poids_octets']);
267
 
632 aurelien 268
			if ($taux_compression < 100 && $this->mode == self::MODE_IMAGEMAGICK) {
269
				$this->ecrireImageSurDisqueAvecMeta($chemin_fichier, $taux_compression);
591 aurelien 270
			}
271
 
272
			$infos_image_originale_stockee = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
273
 
274
			$formats = $this->getFormats();
275
 
276
			// creation de miniatures pour chacuns des formats définis
277
			foreach($formats as $format) {
278
				$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale_stockee, $format);
279
			}
280
 
281
	  		return true ;
282
 
283
		} else {
284
			$erreur =  'ERROR : probleme durant le déplacement du fichier temporaire \n' ;
285
			$this->logger('CEL_bugs',$erreur);
286
  			return false ;
287
		}
288
	}
289
 
632 aurelien 290
	public function stockerImageExterne($chemin_fichier_temp, $chemin_destination) {
291
 
292
		if(is_uploaded_file($chemin_fichier_temp)) {
293
			$deplacement = move_uploaded_file($chemin_fichier_temp, $chemin_destination);
294
		} else {
295
			$deplacement = rename($chemin_fichier_temp, $chemin_destination);
296
		}
297
 
298
		return $deplacement;
299
	}
300
 
591 aurelien 301
	public function creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, $format) {
302
 
303
		$chemin_sur_serveur_final = $this->obtenirDossierPourFormat($id,$format);
304
 
632 aurelien 305
		if (!file_exists($chemin_sur_serveur_final))
591 aurelien 306
		{
632 aurelien 307
			if (mkdir($chemin_sur_serveur_final,$this->droits, true)) {
591 aurelien 308
				chmod($chemin_sur_serveur_final,$this->droits);
309
			}
310
			else
311
			{
312
				$erreur =  'ERROR : probleme durant l\'écriture du dossier '.$format.' \n' ;
313
				echo $erreur;
314
				$this->logger('CEL_bugs',$erreur);
315
				return false;
316
			}
317
		}
318
 
319
		return $chemin_sur_serveur_final;
320
	}
321
 
322
	public function obtenirDossierPourFormat($id, $format) {
323
 
324
		$chemin_base = $this->config['cel_db']['chemin_images'];
325
 
326
		$chemin_sur_serveur = $chemin_base ;
327
 
328
		$id = sprintf('%09s', $id) ;
329
		$id = wordwrap($id, 3 , '_', true) ;
330
 
331
		$niveauDossier = split("_", $id) ;
332
 
333
		$dossierNiveau1 = $niveauDossier[0] ;
334
		$dossierNiveau2 = $niveauDossier[1] ;
335
 
336
		$chemin_sur_serveur_final = $chemin_sur_serveur.'/'.$dossierNiveau1.'/'.$dossierNiveau2.'/'.$format;
337
 
338
		return $chemin_sur_serveur_final;
339
	}
340
 
341
	public function obtenirImageEtInfosPourChemin($chemin_fichier) {
342
 
343
		$image_et_infos = array();
344
 
345
		list($image_et_infos['largeur'], $image_et_infos['hauteur']) = getimagesize($chemin_fichier);
346
		$image_et_infos['poids_octets'] = filesize($chemin_fichier);
347
		$image_et_infos['image'] = imagecreatefromjpeg($chemin_fichier);
632 aurelien 348
		$image_et_infos['chemin'] = $chemin_fichier;
591 aurelien 349
 
350
		return $image_et_infos;
351
	}
352
 
353
	public function obtenirDimensionsPourFormat($format) {
354
 
355
		$dimensions = array('largeur' => 0, 'hauteur' => 0);
356
 
632 aurelien 357
		if (isset($this->config['cel_db']['format_'.$format])) {
591 aurelien 358
 
359
			$format_largeur_hauteur = split('_', $this->config['cel_db']['format_'.$format]);
360
 
361
			$dimensions['largeur'] = $format_largeur_hauteur[0];
362
			$dimensions['hauteur'] = $format_largeur_hauteur[1];
363
		}
364
 
365
		return $dimensions;
366
 
367
	}
368
 
369
	public function calculerTailleImage($informations_images, $taille_max) {
370
 
371
	        $HL_redimension = array();
372
 
632 aurelien 373
	        if ($this->estPaysage($informations_images)) {
591 aurelien 374
 
375
		        $rapport = $informations_images['hauteur']/$informations_images['largeur'] ;
376
		        $HL_redimension['largeur'] = round($taille_max) ;
377
		        $HL_redimension['hauteur'] = round($taille_max*$rapport) ;
378
 
379
	        } else {
380
	        	$rapport = $informations_images['largeur']/$informations_images['hauteur'] ;
381
		        $HL_redimension['hauteur'] = round($taille_max) ;
382
		        $HL_redimension['largeur'] = round($taille_max*$rapport) ;
383
	        }
384
 
385
	        return $HL_redimension;
386
	}
387
 
388
	public function getFormats() {
389
		return $this->formats;
390
	}
391
 
392
	public function estUnFormatCarre($format) {
393
 
394
		return (strpos($format,'C') === 0);
395
	}
396
 
397
	public function estUnFormatRogne($format) {
398
 
399
		return (strpos($format,'R') === 1);
400
	}
401
 
402
	public function estPaysage($informations_images) {
403
		return $informations_images['largeur'] > $informations_images['hauteur'];
404
	}
405
 
406
	public function estPortait($informations_images) {
407
		return $informations_images['largeur'] < $informations_images['hauteur'];
408
	}
409
 
410
	public function renvoyerTauxCompressionPourPoids($poids_octets) {
411
 
412
		$poids_max_octets = $this->config['cel_db']['taille_max'];
413
 
414
		$ratio_compression = 100 ;
415
 
632 aurelien 416
	    if ($poids_octets >= $poids_max_octets) {
591 aurelien 417
	      $ratio_compression = 75 ;
418
	    }
419
 
420
	    return $ratio_compression;
421
	}
422
 
423
	public function convertirIdBddVersNomFichier($id, $format, $extension = 'jpg') {
424
 
425
			// creation du format original
426
		$id_avec_zeros = sprintf('%09s', $id) ;
427
		$id_avec_zeros_underscores = wordwrap($id_avec_zeros, 3 , '_', true) ;
428
 
429
		$nom_fichier = $id_avec_zeros_underscores.'_'.$format.'.'.$extension;
430
 
431
		return $nom_fichier;
432
	}
433
 
434
	public function convertirBaseNomFichierVersIdBdd($nom_fichier, $formats) {
435
 
436
		$nom_fichier_sans_extension = trim($nom_fichier, '.jpg');
437
 
438
		foreach($formats as $format) {
439
			$nom_fichier_sans_extension = trim($nom_fichier_sans_extension, '_'.$format);
440
		}
441
 
442
		$id_image = str_replace('_', '', $nom_fichier_sans_extension);
443
 
444
		// suppression des 0 devant
445
		$id_image += 0;
446
 
447
		return $id_image;
448
	}
449
 
632 aurelien 450
	public function ecrireImageSurDisque($image_binaire, $id, $format, $compression = 100) {
591 aurelien 451
 
452
		umask(0);
453
 
454
		$chemin_sur_serveur_final = $this->creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, $format);
455
		$nom_fichier = $this->convertirIdBddVersNomFichier($id, $format);
456
 
632 aurelien 457
		if (file_exists($chemin_sur_serveur_final.'/'.$nom_fichier)) {
591 aurelien 458
			unlink($chemin_sur_serveur_final.'/'.$nom_fichier);
459
		}
460
 
461
		// attention ceci ne preserve pas les metadonnées
632 aurelien 462
		imagejpeg($image_binaire, $chemin_sur_serveur_final.'/'.$nom_fichier, $compression);
591 aurelien 463
		chmod($chemin_sur_serveur_final.'/'.$nom_fichier,$this->droits);
464
	}
632 aurelien 465
 
466
	public function ecrireImageSurDisqueAvecMeta($image_a_stocker, $compression = 100) {
467
 
468
		$image_a_stocker = new Imagick();
469
		$image_a_stocker->readImageBlob($image_a_stocker);
591 aurelien 470
 
632 aurelien 471
		// l'utilisation d'image magick préserve les métadonnées lors d'une recompression
472
		$image_a_stocker->setformat("jpeg");
473
		$image_a_stocker->setImageCompression(imagick::COMPRESSION_JPEG);
474
		$image_a_stocker->setCompressionQuality($compression);
475
		$image_a_stocker->writeImage($chemin_fichier);
476
		$image_a_stocker->destroy();
591 aurelien 477
 
632 aurelien 478
		chmod($chemin_sur_serveur_final.'/'.$nom_fichier,$this->droits);
591 aurelien 479
	}
480
 
481
	public function renvoyerEtCreerImageCarreeBlancheSelonFormat($cote) {
482
 
483
		$image_blanche = imagecreatetruecolor($cote, $cote);
484
		$blanc = imagecolorallocate($image_blanche, 255, 255, 255);
485
		imagefilledrectangle($image_blanche, 0, 0, $cote, $cote, $blanc);
486
 
487
		return $image_blanche;
488
	}
489
 
490
	public function detruireImageEnMemoire($image) {
491
		imagedestroy($image);
492
	}
493
 
494
	public function detruireImageSurDisque($id) {
621 aurelien 495
 
591 aurelien 496
		$formats = $this->getFormats();
497
 
498
		// on detruit aussi l'image originale
499
		$formats[] = 'O';
500
 
621 aurelien 501
		$destruction_formats_fichier = false;
502
 
591 aurelien 503
		// destructions de chacuns des formats définis
504
		foreach($formats as $format) {
621 aurelien 505
 
591 aurelien 506
			$dossier_format = $this->obtenirDossierPourFormat($id, $format);
507
			$nom_fichier = $this->convertirIdBddVersNomFichier($id, $format);
621 aurelien 508
 
632 aurelien 509
			if (file_exists($dossier_format.'/'.$nom_fichier)) {
621 aurelien 510
				$destruction_formats_fichier = unlink($dossier_format.'/'.$nom_fichier);
511
			} else {
512
				$destruction_formats_fichier = true;
513
			}
591 aurelien 514
		}
621 aurelien 515
 
516
		return $destruction_formats_fichier;
591 aurelien 517
	}
632 aurelien 518
 
519
	/*
520
	 * edge-maximizing crop
521
	 * determines center-of-edginess, then tries different-sized crops around it.
522
	 * picks the crop with the highest normalized edginess.
523
	 * see documentation on how to tune the algorithm
524
	 *
525
	 * $informations_image - le tableau d'informations sur l'image tel que renvoyé par la fonction obtenirImageEtInfosPourChemin
526
	 * $format - le format (ex. : CS, XS, XL, CRS)
527
	*/
528
	function opticrop($informations_image, $format) {
529
 
530
		umask(0);
531
 
532
		$nom_temp = md5(time());
533
		$out = '/home/aurelien/web/file_tmp/'.$nom_temp;
534
 
535
		$dimension_vignettes = $this->obtenirDimensionsPourFormat($format);
536
 
537
		$largeur_vignette = $dimension_vignettes['largeur'];
538
		$hauteur_vignette = $dimension_vignettes['hauteur'];
539
 
540
	    // source dimensions
541
	    $largeur_image_originale = $informations_image['largeur'];
542
	    $hauteur_image_originale = $informations_image['hauteur'];
543
 
544
	    $chemin_image = $informations_image['chemin'];
545
 
546
	    //if ($largeur_vignette > $largeur_image_originale || $hauteur_vignette > $hauteur_image_originale)
547
	    //    die("Target dimensions must be smaller or equal to source dimensions.");
548
 
549
	    // parameters for the edge-maximizing crop algorithm
550
	    $r = 1;         // radius of edge filter
551
	    $nk = 9;        // scale count: number of crop sizes to try
552
	    $gamma = 0.2;   // edge normalization parameter -- see documentation
553
	    $ar = $largeur_vignette/$hauteur_vignette;    // target aspect ratio (AR)
554
	    $ar0 = $largeur_image_originale/$hauteur_image_originale;    // original aspect ratio (AR)
555
 
556
	    //echo("$chemin_image: $largeur_image_originale x $hauteur_image_originale => $largeur_vignette x $hauteur_vignette");
557
	    $img = new Imagick($chemin_image);
558
	    $imgcp = clone $img;
559
 
560
	    // compute center of edginess
561
	    $img->edgeImage($r);
562
	    $img->modulateImage(100,0,100); // grayscale
563
	    $img->blackThresholdImage("#0f0f0f");
564
	    $img->writeImage($out);
565
	    // use gd for random pixel access
566
	    $im = ImageCreateFromJpeg($out);
567
	    $xcenter = 0;
568
	    $ycenter = 0;
569
	    $sum = 0;
570
	    $n = 100000;
571
	    for ($k=0; $k<$n; $k++) {
572
	        $i = mt_rand(0,$largeur_image_originale-1);
573
	        $j = mt_rand(0,$hauteur_image_originale-1);
574
	        $val = imagecolorat($im, $i, $j) & 0xFF;
575
	        $sum += $val;
576
	        $xcenter += ($i+1)*$val;
577
	        $ycenter += ($j+1)*$val;
578
	    }
579
	    $xcenter /= $sum;
580
	    $ycenter /= $sum;
581
 
582
	    // crop source img to target AR
583
	    if ($largeur_image_originale/$hauteur_image_originale > $ar) {
584
	        // source AR wider than target
585
	        // crop width to target AR
586
	        $wcrop0 = round($ar*$hauteur_image_originale);
587
	        $hcrop0 = $hauteur_image_originale;
588
	    }
589
	    else {
590
	        // crop height to target AR
591
	        $wcrop0 = $largeur_image_originale;
592
	        $hcrop0 = round($largeur_image_originale/$ar);
593
	    }
594
 
595
	    // crop parameters for all scales and translations
596
	    $params = array();
597
 
598
	    // crop at different scales
599
	    $hgap = $hcrop0 - $hauteur_vignette;
600
	    $hinc = ($nk == 1) ? 0 : $hgap / ($nk - 1);
601
	    $wgap = $wcrop0 - $largeur_vignette;
602
	    $winc = ($nk == 1) ? 0 : $wgap / ($nk - 1);
603
 
604
	    // find window with highest normalized edginess
605
	    $n = 10000;
606
	    $maxbetanorm = 0;
607
	    $maxfile = '';
608
	    $maxparam = array('w'=>0, 'h'=>0, 'x'=>0, 'y'=>0);
609
 
610
	    for ($k = 0; $k < $nk; $k++) {
611
	        $hcrop = round($hcrop0 - $k*$hinc);
612
	        $wcrop = round($wcrop0 - $k*$winc);
613
	        $xcrop = $xcenter - $wcrop / 2;
614
	        $ycrop = $ycenter - $hcrop / 2;
615
	        //echo("crop: $wcrop, $hcrop, $xcrop, $ycrop");
616
 
617
	        if ($xcrop < 0) $xcrop = 0;
618
	        if ($xcrop+$wcrop > $largeur_image_originale) $xcrop = $largeur_image_originale-$wcrop;
619
	        if ($ycrop < 0) $ycrop = 0;
620
	        if ($ycrop+$hcrop > $hauteur_image_originale) $ycrop = $hauteur_image_originale-$hcrop;
621
 
622
	        /*if (self::MODE_DEBUG) {
623
	        	// debug
624
	        	$currfile = '/home/aurelien/web/file_tmp/'."image$k.jpg";
625
 
626
	            $currimg = clone $img;
627
	            $c= new ImagickDraw();
628
	            $c->setFillColor("red");
629
	            $c->circle($xcenter, $ycenter, $xcenter, $ycenter+4);
630
	            $currimg->drawImage($c);
631
	            $currimg->cropImage($wcrop, $hcrop, $xcrop, $ycrop);
632
	            $currimg->writeImage($currfile);
633
	            $currimg->destroy();
634
	        }*/
635
 
636
	        $beta = 0;
637
	        for ($c=0; $c<$n; $c++) {
638
	            $i = mt_rand(0,$wcrop-1);
639
	            $j = mt_rand(0,$hcrop-1);
640
	            $beta += imagecolorat($im, $xcrop+$i, $ycrop+$j) & 0xFF;
641
	        }
642
	        $area = $wcrop * $hcrop;
643
	        $betanorm = $beta / ($n*pow($area, $gamma-1));
644
	        // echo("beta: $beta; betan: $betanorm");
645
	        // echo("image$k.jpg:<br/>\n<img src=\"$currfile\"/>");
646
	        // best image found, save it
647
 
648
	        if ($betanorm > $maxbetanorm) {
649
 
650
	            $maxbetanorm = $betanorm;
651
	            $maxparam['w'] = $wcrop;
652
	            $maxparam['h'] = $hcrop;
653
	            $maxparam['x'] = $xcrop;
654
	            $maxparam['y'] = $ycrop;
655
	            // $maxfile = $currfile;
656
	        }
657
	    }
658
 
659
        // return image
660
        $imgcp->cropImage($maxparam['w'], $maxparam['h'], $maxparam['x'], $maxparam['y']);
661
        $imgcp->scaleImage($largeur_vignette, $hauteur_vignette);
662
        $imgcp->writeImage($out);
663
	    chmod($out, 0777);
664
	    $img->destroy();
665
	    $imgcp->destroy();
666
 
667
	    $image_sortie = ImageCreateFromJpeg($out);
668
	    unlink($out);
669
 
670
	    return $image_sortie;
671
	}
672
 
591 aurelien 673
}
674
?>