Subversion Repositories eFlore/Applications.cel

Rev

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

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