Subversion Repositories eFlore/Applications.cel

Compare Revisions

Ignore whitespace Rev 631 → Rev 632

/trunk/jrest/services/InventoryImage.php
16,8 → 16,7
* Renvoie les infos sur l'image correspondant à l'id passé en parametre
*/
public function getElement($uid)
{
{d
// uid[0] : utilisateur obligatoire
// uid[1] : identifiant image obligatoire
 
79,8 → 78,8
foreach($valeurs_metadonnees as $champ => $valeur)
{
if(!in_array($champ,$champs_a_ignorer)) {
if($champ == 'ci_meta_date') {
if (!in_array($champ,$champs_a_ignorer)) {
if ($champ == 'ci_meta_date') {
$date_tab = split('/',$valeur) ;
$date = $date_tab[2].'-'.$date_tab[1].'-'.$date_tab[0] ;
111,11 → 110,11
session_start();
$this->controleUtilisateur($pairs['identifiant']);
foreach($_FILES as $file) {
foreach ($_FILES as $file) {
$infos_fichier = $file ;
}
if($this->ajouterImageSurDdEtBdd($pairs, $infos_fichier)) {
if ($this->ajouterImageSurDdEtBdd($pairs, $infos_fichier)) {
// l'upload demande de court-circuiter le fonctionnement normal de JREST
// en quittant directement après l'envoi
126,7 → 125,7
}
/**
* Ajout une image dans la base de données et stocke le fichier en fabriquant les miniatures,
* Ajoute une image dans la base de données et stocke le fichier en fabriquant les miniatures,
* renvoie le nouvel id d'image en cas de succès
*
* @param array $pairs le tableau contenant l'identifiant de l'utilisateur
135,9 → 134,10
*/
public function ajouterImageSurDdEtBdd($pairs, $infos_fichier) {
$nouvel_ordre = $this->obtenirNouvelOrdrePourUtilisateur($pairs['identifiant']);
$identifiant_utilisateur = $pairs['identifiant'];
$nouvel_ordre = $this->obtenirNouvelOrdrePourUtilisateur($identifiant_utilisateur);
if(!$nouvel_ordre) {
if (!$nouvel_ordre) {
$message = 'Erreur lors du calcul du nouvel ordre de l\'image';
trigger_error($message, E_USER_ERROR);
}
158,7 → 158,7
// le md5 du fichier sert à repérer les images en doublons
$informations_image['ci_md5'] = md5_file($infos_fichier['tmp_name']) ;
$informations_image['ci_ce_utilisateur'] = $pairs['identifiant'] ;
$informations_image['ci_ce_utilisateur'] = $identifiant_utilisateur ;
$requete_insertion_infos_image = $this->construireRequeteInsertionImage($informations_image);
$resultat_insertion_infos_image = $this->executerRequeteSimple($requete_insertion_infos_image);
168,7 → 168,7
trigger_error($message, E_USER_ERROR);
}
 
$id_nouvelle_image = $this->obtenirIdImagePourIdentifiantEtOrdre($pairs['identifiant'], $nouvel_ordre);
$id_nouvelle_image = $this->obtenirIdImagePourIdentifiantEtOrdre($identifiant_utilisateur, $nouvel_ordre);
if(!$id_nouvelle_image)
{
177,7 → 177,7
}
$manipulateur_image = new ImageRecreation($this->config);
$fichier_stocke = $manipulateur_image->stockerFichierEtCreerMiniatures($infos_fichier,$id_nouvelle_image) ;
$fichier_stocke = $manipulateur_image->stockerFichierEtCreerMiniatures($infos_fichier,$id_nouvelle_image);
if(!$fichier_stocke) {
$message = 'Erreur lors du stockage du fichier' ;
193,10 → 193,10
$requete_selection_ordre_max ='SELECT MAX(ci_ordre) as max_ordre FROM cel_images WHERE ci_ce_utilisateur = '.$this->proteger($id_utilisateur) ;
$resultat_requete_ordre_max = $this->executerRequete($requete_selection_ordre_max);
if($resultat_requete_ordre_max) {
$nouvel_ordre = $resultat_requete_ordre_max[0]['max_ordre'];
$nouvel_ordre = $nouvel_ordre++;
$nouvel_ordre++;
}
return $nouvel_ordre;
254,6 → 254,7
private function envoyerMessageCreationEffectuee() {
header('HTTP/1.0 200 Created');
echo 'OK';
exit() ;
}
 
/trunk/jrest/lib/ImageRecreation.php
1,24 → 1,84
<?php
Class ImageRecreation extends DBAccessor {
Class ImageRecreation {
private $droits = 0755;
private $formats = array('CRX2S','CXS','CS','S','M','L','XL','X2L','X3L');
private $formats = array('CRX2S','CXS','CS','CRS','XS','S','M','L','XL','X2L','X3L');
const MODE_GD = 'gd';
const MODE_IMAGEMAGICK = 'imagemagick';
private $mode;
private $verbose = true;
 
public function ImageRecreation($config) {
 
$this->config=$config;
$this->mode = self::MODE_GD;
if (extension_loaded('imagick')) {
putenv("MAGICK_TEMPORARY_PATH=/home/aurelien/web/file_tmp");
$this->mode = self::MODE_IMAGEMAGICK;
}
}
public function getRessource() {
public function recreerMiniaturesRecursivement() {
$this->itererRecursivement($this->config['cel_db']['chemin_images']);
}
public function testOptiCrop() {
$image = $this->obtenirImageEtInfosPourChemin('/home/aurelien/web/file_tmp/test.jpg');
return $this->opticrop($image,'CRXS','');
}
public function getElement($param) {
public function regenererMiniaturesIntervalle($params) {
$id_debut = $params[0];
$id_fin = $params[1];
 
if (is_numeric($id_debut) && is_numeric($id_fin)) {
//echo("Début du traitement des images de ".$id_debut." à ".$id_fin."\n");
for ($i = $id_debut; $i <= $id_fin; $i++) {
echo($i."\n");
$tab_param = array($i);
$this->regenererMiniaturesPourId($tab_param);
}
}
}
public function recreerMiniaturesRecursivement() {
$this->itererRecursivement($this->config['cel_db']['chemin_images']);
public function regenererMiniaturesPourId($params) {
 
$id = $params[0];
 
if (!is_numeric($id)) {
return;
}
 
$dossier_fichier = $this->obtenirDossierPourFormat($id, 'O');
 
$nom_fichier = $this->convertirIdBddVersNomFichier($id, 'O');
$chemin_fichier = $dossier_fichier.'/'.$nom_fichier;
 
if(file_exists($chemin_fichier)) {
$infos_image_originale = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
// creation de miniatures pour chacuns des formats définis
foreach($this->formats as $format) {
$this->creerEtStockerMiniatureFichierImageSelonFormat($id, $infos_image_originale, $format);
}
//if($this->verbose) {
//echo("traitement de l'image ".$infos_image_originale."\n");
//}
} else {
//echo 'le fichier '.$chemin_fichier.'n\'existe pas '."\n";
}
}
public function itererRecursivement($dossier) {
28,15 → 88,15
foreach (new DirectoryIterator($dossier) as $fichier_ou_dossier) {
if($fichier_ou_dossier->isDot()) {
if ($fichier_ou_dossier->isDot()) {
continue;
}
if(in_array($fichier_ou_dossier->getBasename(), $dossiers_a_exclure)) {
if (in_array($fichier_ou_dossier->getBasename(), $dossiers_a_exclure)) {
continue;
}
if($fichier_ou_dossier->isDir()) {
if ($fichier_ou_dossier->isDir()) {
$profondeur_dossier_fils = $profondeur + 1;
$this->itererRecursivement($fichier_ou_dossier->getPathname(), $profondeur_dossier_fils);
59,15 → 119,24
public function creerEtStockerMiniatureFichierImageSelonFormat($id ,$infos_image_originale, $format = 'O') {
if($format == 'O') {
if ($format == 'O') {
// format original : rien à faire
$image_redimensionnee = $infos_image_originale['image'];
} else {
if($this->estUnFormatRogne($format)) {
// la minature est une image redimensionnée rognée au centre
$image_redimensionnee = $this->creerMiniatureCarreeRognee($infos_image_originale, $format);
} else if($this->estUnFormatCarre($format)) {
if ($this->estUnFormatRogne($format)) {
if ($this->mode == self::MODE_IMAGEMAGICK) {
// si l'on dispose de la librairie imageMagick
// on applique l'algorithme d'auto détection de sujets
// qui centre la miniature sur le sujet de l'image
$image_redimensionnee = $this->opticrop($infos_image_originale, $format);
} else {
// si l'on ne dispose que de gd
// la minature est une image redimensionnée rognée au centre
$image_redimensionnee = $this->creerMiniatureCarreeRognee($infos_image_originale, $format);
}
} else if ($this->estUnFormatCarre($format)) {
// le format carre et une image redimensionnée en gardant son ratio, insérée dans un carré blanc
$image_redimensionnee = $this->creerMiniatureCarree($infos_image_originale, $format);
} else {
116,7 → 185,7
$image_redimensionnee_avec_rapport = $this->creerMiniature($informations_image, $format);
$taille_redimensionnee_avec_rapport = $this->calculerTailleImage($informations_image, $taille_reference_pour_format['hauteur']);
if($this->estPaysage($informations_image)) {
if ($this->estPaysage($informations_image)) {
$debut_largeur_a_copier = 0 ;
$debut_hauteur_a_copier = ($cote_carre - $taille_redimensionnee_avec_rapport['hauteur'])/2 ;
} else {
140,7 → 209,7
$cote_carre = $taille_reference_pour_format['largeur'];
$cote_carre_non_redimensionne = 0;
if($this->estPaysage($informations_image)) {
if ($this->estPaysage($informations_image)) {
$cote_carre_non_redimensionne = $informations_image['hauteur'];
$debut_largeur_a_copier = ($informations_image['hauteur'] - $informations_image['hauteur'])/2 ;
$debut_hauteur_a_copier = 0;
182,38 → 251,6
return $image_redimensionnee;
}
/*public function extractionSelonDate() {
 
$DB=$this->connectDB($this->config,'cel_db');
$requete_selection_diff = 'SELECT * FROM cel_images WHERE ci_meta_date_ajout >= "2011-02-23"';
$diff_image =& $DB->query($query_ordre);
if (PEAR::isError($diff_imag))
{
$erreur = 'ERROR' ;
die($diff_image->getMessage());
}
while ($row =& $diff_image->fetchrow(DB_FETCHMODE_ASSOC)) {
$id = $row['ci_id_image'];
$dossier = $this->obtenirDossierPourFormat($id,'L');
$nom_fichier = $this->convertirIdBddVersNomFichier($id, 'L');
$chemin_complet = $dossier.'/'.$nom_fichier;
$chemin_stockage_fichier = '/home/telabotap/www/sites/eflore/projets/cel_sauvegarde/'.str_replace(' ','_',$row['ci_nom_original']);
copy($chemin_complet,$chemin_stockage_fichier);
}
}*/
public function stockerFichierEtCreerMiniatures($fichier, $id) {
$chemin_base_fichier = $this->creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, 'O');
221,13 → 258,15
$chemin_fichier = $chemin_base_fichier.'/'.$nom_fichier;
if(rename($fichier['tmp_name'],$chemin_fichier)) {
$deplacement_fichier = $this->stockerImageExterne($fichier['tmp_name'], $chemin_fichier);
if ($deplacement_fichier) {
 
$infos_image_originale = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
$taux_compression = $this->renvoyerTauxCompressionPourPoids($infos_image_originale['poids_octets']);
if($taux_compression < 100) {
$this->recompresserImageSurDisqueEnPreservantMeta($chemin_fichier, $taux_compression);
if ($taux_compression < 100 && $this->mode == self::MODE_IMAGEMAGICK) {
$this->ecrireImageSurDisqueAvecMeta($chemin_fichier, $taux_compression);
}
$infos_image_originale_stockee = $this->obtenirImageEtInfosPourChemin($chemin_fichier);
248,13 → 287,24
}
}
public function stockerImageExterne($chemin_fichier_temp, $chemin_destination) {
if(is_uploaded_file($chemin_fichier_temp)) {
$deplacement = move_uploaded_file($chemin_fichier_temp, $chemin_destination);
} else {
$deplacement = rename($chemin_fichier_temp, $chemin_destination);
}
return $deplacement;
}
public function creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, $format) {
$chemin_sur_serveur_final = $this->obtenirDossierPourFormat($id,$format);
if(!file_exists($chemin_sur_serveur_final))
if (!file_exists($chemin_sur_serveur_final))
{
if(mkdir($chemin_sur_serveur_final,$this->droits, true)) {
if (mkdir($chemin_sur_serveur_final,$this->droits, true)) {
chmod($chemin_sur_serveur_final,$this->droits);
}
else
295,6 → 345,7
list($image_et_infos['largeur'], $image_et_infos['hauteur']) = getimagesize($chemin_fichier);
$image_et_infos['poids_octets'] = filesize($chemin_fichier);
$image_et_infos['image'] = imagecreatefromjpeg($chemin_fichier);
$image_et_infos['chemin'] = $chemin_fichier;
return $image_et_infos;
}
303,7 → 354,7
$dimensions = array('largeur' => 0, 'hauteur' => 0);
if(isset($this->config['cel_db']['format_'.$format])) {
if (isset($this->config['cel_db']['format_'.$format])) {
$format_largeur_hauteur = split('_', $this->config['cel_db']['format_'.$format]);
319,7 → 370,7
$HL_redimension = array();
if($this->estPaysage($informations_images)) {
if ($this->estPaysage($informations_images)) {
$rapport = $informations_images['hauteur']/$informations_images['largeur'] ;
$HL_redimension['largeur'] = round($taille_max) ;
362,7 → 413,7
$ratio_compression = 100 ;
if($poids_octets >= $poids_max_octets) {
if ($poids_octets >= $poids_max_octets) {
$ratio_compression = 75 ;
}
396,7 → 447,7
return $id_image;
}
public function ecrireImageSurDisque($image, $id, $format, $compression = 100) {
public function ecrireImageSurDisque($image_binaire, $id, $format, $compression = 100) {
umask(0);
403,29 → 454,28
$chemin_sur_serveur_final = $this->creerSiNecessaireEtRenvoyerCheminStockageFichierPourIdEtFormat($id, $format);
$nom_fichier = $this->convertirIdBddVersNomFichier($id, $format);
if(file_exists($chemin_sur_serveur_final.'/'.$nom_fichier)) {
if (file_exists($chemin_sur_serveur_final.'/'.$nom_fichier)) {
unlink($chemin_sur_serveur_final.'/'.$nom_fichier);
}
// attention ceci ne preserve pas les metadonnées
imagejpeg($image,$chemin_sur_serveur_final.'/'.$nom_fichier, $compression);
imagejpeg($image_binaire, $chemin_sur_serveur_final.'/'.$nom_fichier, $compression);
chmod($chemin_sur_serveur_final.'/'.$nom_fichier,$this->droits);
}
public function ecrireImageSurDisqueAvecMeta($image_a_stocker, $compression = 100) {
 
$image_a_stocker = new Imagick();
$image_a_stocker->readImageBlob($image_a_stocker);
public function recompresserImageSurDisqueEnPreservantMeta($chemin_fichier, $compression = 100) {
 
/*$blob = file_get_contents($chemin_fichier);
$image_a_compresser = new Imagick();
$image_a_compresser->readImageBlob($blob, $chemin_fichier);
$image_a_compresser->setformat("jpeg");
$image_a_compresser->setImageCompression(imagick::COMPRESSION_JPEG);
$image_a_compresser->setCompressionQuality($compression);
$image_a_compresser->writeImage($chemin_fichier);
$image_a_compresser->destroy();
// l'utilisation d'image magick préserve les métadonnées lors d'une recompression
$image_a_stocker->setformat("jpeg");
$image_a_stocker->setImageCompression(imagick::COMPRESSION_JPEG);
$image_a_stocker->setCompressionQuality($compression);
$image_a_stocker->writeImage($chemin_fichier);
$image_a_stocker->destroy();
chmod($chemin_sur_serveur_final.'/'.$nom_fichier,$this->droits);*/
chmod($chemin_sur_serveur_final.'/'.$nom_fichier,$this->droits);
}
public function renvoyerEtCreerImageCarreeBlancheSelonFormat($cote) {
456,7 → 506,7
$dossier_format = $this->obtenirDossierPourFormat($id, $format);
$nom_fichier = $this->convertirIdBddVersNomFichier($id, $format);
if(file_exists($dossier_format.'/'.$nom_fichier)) {
if (file_exists($dossier_format.'/'.$nom_fichier)) {
$destruction_formats_fichier = unlink($dossier_format.'/'.$nom_fichier);
} else {
$destruction_formats_fichier = true;
465,5 → 515,160
return $destruction_formats_fichier;
}
/*
* edge-maximizing crop
* determines center-of-edginess, then tries different-sized crops around it.
* picks the crop with the highest normalized edginess.
* see documentation on how to tune the algorithm
*
* $informations_image - le tableau d'informations sur l'image tel que renvoyé par la fonction obtenirImageEtInfosPourChemin
* $format - le format (ex. : CS, XS, XL, CRS)
*/
function opticrop($informations_image, $format) {
 
umask(0);
$nom_temp = md5(time());
$out = '/home/aurelien/web/file_tmp/'.$nom_temp;
$dimension_vignettes = $this->obtenirDimensionsPourFormat($format);
$largeur_vignette = $dimension_vignettes['largeur'];
$hauteur_vignette = $dimension_vignettes['hauteur'];
// source dimensions
$largeur_image_originale = $informations_image['largeur'];
$hauteur_image_originale = $informations_image['hauteur'];
$chemin_image = $informations_image['chemin'];
//if ($largeur_vignette > $largeur_image_originale || $hauteur_vignette > $hauteur_image_originale)
// die("Target dimensions must be smaller or equal to source dimensions.");
// parameters for the edge-maximizing crop algorithm
$r = 1; // radius of edge filter
$nk = 9; // scale count: number of crop sizes to try
$gamma = 0.2; // edge normalization parameter -- see documentation
$ar = $largeur_vignette/$hauteur_vignette; // target aspect ratio (AR)
$ar0 = $largeur_image_originale/$hauteur_image_originale; // original aspect ratio (AR)
//echo("$chemin_image: $largeur_image_originale x $hauteur_image_originale => $largeur_vignette x $hauteur_vignette");
$img = new Imagick($chemin_image);
$imgcp = clone $img;
// compute center of edginess
$img->edgeImage($r);
$img->modulateImage(100,0,100); // grayscale
$img->blackThresholdImage("#0f0f0f");
$img->writeImage($out);
// use gd for random pixel access
$im = ImageCreateFromJpeg($out);
$xcenter = 0;
$ycenter = 0;
$sum = 0;
$n = 100000;
for ($k=0; $k<$n; $k++) {
$i = mt_rand(0,$largeur_image_originale-1);
$j = mt_rand(0,$hauteur_image_originale-1);
$val = imagecolorat($im, $i, $j) & 0xFF;
$sum += $val;
$xcenter += ($i+1)*$val;
$ycenter += ($j+1)*$val;
}
$xcenter /= $sum;
$ycenter /= $sum;
// crop source img to target AR
if ($largeur_image_originale/$hauteur_image_originale > $ar) {
// source AR wider than target
// crop width to target AR
$wcrop0 = round($ar*$hauteur_image_originale);
$hcrop0 = $hauteur_image_originale;
}
else {
// crop height to target AR
$wcrop0 = $largeur_image_originale;
$hcrop0 = round($largeur_image_originale/$ar);
}
// crop parameters for all scales and translations
$params = array();
// crop at different scales
$hgap = $hcrop0 - $hauteur_vignette;
$hinc = ($nk == 1) ? 0 : $hgap / ($nk - 1);
$wgap = $wcrop0 - $largeur_vignette;
$winc = ($nk == 1) ? 0 : $wgap / ($nk - 1);
// find window with highest normalized edginess
$n = 10000;
$maxbetanorm = 0;
$maxfile = '';
$maxparam = array('w'=>0, 'h'=>0, 'x'=>0, 'y'=>0);
for ($k = 0; $k < $nk; $k++) {
$hcrop = round($hcrop0 - $k*$hinc);
$wcrop = round($wcrop0 - $k*$winc);
$xcrop = $xcenter - $wcrop / 2;
$ycrop = $ycenter - $hcrop / 2;
//echo("crop: $wcrop, $hcrop, $xcrop, $ycrop");
if ($xcrop < 0) $xcrop = 0;
if ($xcrop+$wcrop > $largeur_image_originale) $xcrop = $largeur_image_originale-$wcrop;
if ($ycrop < 0) $ycrop = 0;
if ($ycrop+$hcrop > $hauteur_image_originale) $ycrop = $hauteur_image_originale-$hcrop;
/*if (self::MODE_DEBUG) {
// debug
$currfile = '/home/aurelien/web/file_tmp/'."image$k.jpg";
$currimg = clone $img;
$c= new ImagickDraw();
$c->setFillColor("red");
$c->circle($xcenter, $ycenter, $xcenter, $ycenter+4);
$currimg->drawImage($c);
$currimg->cropImage($wcrop, $hcrop, $xcrop, $ycrop);
$currimg->writeImage($currfile);
$currimg->destroy();
}*/
$beta = 0;
for ($c=0; $c<$n; $c++) {
$i = mt_rand(0,$wcrop-1);
$j = mt_rand(0,$hcrop-1);
$beta += imagecolorat($im, $xcrop+$i, $ycrop+$j) & 0xFF;
}
$area = $wcrop * $hcrop;
$betanorm = $beta / ($n*pow($area, $gamma-1));
// echo("beta: $beta; betan: $betanorm");
// echo("image$k.jpg:<br/>\n<img src=\"$currfile\"/>");
// best image found, save it
if ($betanorm > $maxbetanorm) {
$maxbetanorm = $betanorm;
$maxparam['w'] = $wcrop;
$maxparam['h'] = $hcrop;
$maxparam['x'] = $xcrop;
$maxparam['y'] = $ycrop;
// $maxfile = $currfile;
}
}
// return image
$imgcp->cropImage($maxparam['w'], $maxparam['h'], $maxparam['x'], $maxparam['y']);
$imgcp->scaleImage($largeur_vignette, $hauteur_vignette);
$imgcp->writeImage($out);
chmod($out, 0777);
$img->destroy();
$imgcp->destroy();
$image_sortie = ImageCreateFromJpeg($out);
unlink($out);
return $image_sortie;
}
}
?>
/trunk/jrest/lib/ExtracteurMetadonnees.php
10,7 → 10,7
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
* @version $Id$
*/
class ExtracteurMetadonnees() {
class ExtracteurMetadonnees {
 
public function extraireMetadonnees($chemin_fichier)
{
30,19 → 30,21
**/
public function extraireExif($chemin_fichier)
{
$exif_tab = $this->initialiserTableauExif() ;
$exif_tab = $this->initialiserTableauExif () ;
$exif = exif_read_data($url,"EXIF,COMPUTED,IFD0,FILE,COMMENT",true,false);
foreach ($exif as $key => $section)
{
foreach ($section as $name => $val)
{
if($name != "MakerNote")
{
$this->decoderValeurExif($name, $val ,&$exif_tab) ;
}
}
$exif = @exif_read_data($chemin_fichier,"EXIF,COMPUTED,IFD0,FILE,COMMENT",true,false);
 
if ($exif) {
foreach ($exif as $key => $section)
{
foreach ($section as $name => $val)
{
if ($name != "MakerNote")
{
$this->decoderValeurExif ($name, $val ,&$exif_tab) ;
}
}
}
}
return $exif_tab ;
62,13 → 64,15
{
// on parse les donnees
$iptc = iptcparse($info["APP13"]);
// et on les analyse
foreach($iptc as $marker => $section)
{
foreach($section as $nom => $val)
if ($iptc) {
// et on les analyse
foreach ($iptc as $marker => $section)
{
// pour remplir le tableau de donnees
decoderValeurIptc($marker, $val ,&$iptc_tab) ;
foreach ($section as $nom => $val)
{
// pour remplir le tableau de donnees
$this->decoderValeurIptc($marker, $val ,&$iptc_tab) ;
}
}
}
}
84,7 → 88,7
**/
private function decoderValeurExif($nom, $val ,$data_tab)
{
switch($nom)
switch ($nom)
{
case "Height" :