WaterMark de masse en PHP

Tous les benchmarks, vos résultats, vos tests.
Vos programmes, vos conseils logiciel
Votre matos, vos problèmes
Avatar de l’utilisateur
Davidazerty
l'élu
Réactions :
Messages : 2443
Inscription : octobre 12, 2002, 3:30 pm

WaterMark de masse en PHP

Message par Davidazerty »

Christophe m'a demandé si c'etait possible de faire du watermark en php pour éviter d'avoir à acheter Batch it! v4.

J'ai regardé un peu sur le net et j'ai trouvé un ptit algo permettant de watermark une image (avec positionnement) en PHP !
J'y ai apportée des modifications pour redimensionner les images trop grandes, convertir les images au format souhaité (JPEG, PNG ou GIF)
J'ai mi tout ca dans un fonction récursive qui parcours un dossier donner (et ses sous dossiers). La fonction redimensionne, watermark et renomme toutes les images. (note: il y a des parametres configurable)

Christophe m'a passé les variables qui doivent etre placé en parametre pour l'integration au site, et il devrait voir avec Aurelien pour ajouter tout ca ce week end.



NB : source comming soon
Avatar de l’utilisateur
Christophe
L’humanité parlementaire
Réactions :
Messages : 8435
Inscription : septembre 27, 2002, 7:25 am

Re: WaterMark de masse en PHP

Message par Christophe »

oui oui, ça viens ...
Avatar de l’utilisateur
Aurelienazerty
Webmaster / Président
Réactions :
Messages : 25088
Inscription : septembre 27, 2002, 9:41 pm

Les sources

Message par Aurelienazerty »

Voilà la source php:

Code : Tout sélectionner

<?php	
	
/*
Entrée :

    $source : Chemin vers le répertoire contenant les photos non traités (sans / a la fin ex: "/html/image/in")
    $destination : Chemin vers le répertoire où seront les photos traitées (sans / a la fin ex: "/html/image/out")
    $prefixe : préfixe des photos
    $watermark: Chemin vers le watermark répertoire des watermarks (sans / a la fin ex: "/html/image/watermark")
    $max_largeur: Largeur maximale
    $max_hauteur: Longueur maximale
    $num_img : numero de la premiere image

           /!\ le chemin est le chemin local sur le FTP
Sortie :
    le numero de la derniere image
Description :
    Le script scanne le répertoire $source contenant les photos à traiter    (Ainsi que les sous répertoires)
    Le script crée le répertoire $destination s'il n'existe pas
    Pour chaque photo :
        - Redimentionnement de la photo en gardant les ratios
        - Ajout du watermark $watermark selon la configuration
        - Convertit au format d'image choisie
        - Copie de la photo dans $destination avec le nom suivant :
            $prefixe_$numero.[extension]
        Où $numero est unique et au nombre de chiffre configurer
        Où [extension] est l'extension du format choisie

Exemple:
	watermark_dossier("./in","./out","test","./watermark.png","800","600","0");
*/

	
function watermark_dossier($source,$destination,$prefixe,$watermark,$max_largeur,$max_hauteur,$num_img) {
  //safe_mode(false);
  set_time_limit(2400);
  ini_set("safe_mode", false);
  ini_set("max_execution_time", 2400);
  ini_set("Timeout", 2400);
  
  	// Création du répertoire $destination s'il n'existe pas
	!is_dir($destination) ? mkdir($destination, 0777):"";
	chmod($destination, 0777);
	
	$nbchiffre=4; // nombre de chiffre pour le nommage
	$img_format='jpg'; // format de sortie : jpg, png, gif
	$quality='80'; // qualite encodage jpeg
	$v_position='bottom'; //position vertical
	$h_position='right'; //position horizontal
	$wm_size='0' ; //redimensionnement 0: sans / .5: 50% / 1: 100% / larger: max
	$edgePadding=15;
  	
  	
	$dh  = opendir($source);
	while (false !== ($image = readdir($dh))) {
		if($image!="."&&$image!=".."&&strtolower($image)!="thumbs.db") {
			if (is_dir($source."/".$image)) {
				$num_img=watermark_dossier($source."/".$image,$destination,$prefixe,$watermark,$max_largeur,$max_hauteur,$num_img);
			}
			else {
				echo " ";
				watermark($source, $image, $destination, $prefixe, $watermark, $max_largeur, $max_hauteur, $img_format, $quality, $v_position, $h_position, $wm_size, $edgePadding, $num_img, $nbchiffre);
				$num_img++;
			}
		}
	}
	return $num_img;
}
	
function watermark($source, $image, $destination, $prefixe, $watermark, $max_largeur, $max_hauteur, $img_format, $quality, $v_position, $h_position, $wm_size, $edgePadding, $num_img, $nbchiffre) {
		
	$size=getimagesize($source."/".$image);
	if($size[2]==1 || $size[2]==2 || $size[2]==3){
		// it was a GIF or JPEG or PNG image, so we're OK so far
	    
	  $original=$source."/".$image;
	  $image_sansExtension=substr($image,0,strlen($image)-4);
	  $numero=$num_img;
	  while(strlen($numero)<$nbchiffre)
	  	$numero='0'.$numero;
	  $target_name=$prefixe.'-'.$numero.".".$img_format;
	  		//preg_replace('`[^a-z0-9-_.]`i','',$image_sansExtension);
	  $target=$destination."/".$target_name;
	  $wmTarget=$watermark.'.tmp';
	  //$wmTarget=$watermark;
	
	  $origInfo = getimagesize($original); 
	  $origWidth = $origInfo[0]; 
	  $origHeight = $origInfo[1]; 
	  
	  // Création de la ressource image a partir du fichier;
	  
	  if($size[2]==3)
	      $resultImage = imagecreatefrompng($original);
	  elseif($size[2]==2)
	      $resultImage = imagecreatefromjpeg($original);
	  else
	  	$resultImage = imagecreatefromgif($original);
	  imagealphablending($resultImage, TRUE);
	  
	  // Redimensionnement de l'image si plus grande que $max_largeur / $max_hauteur
	  
	  $largeur=$origWidth;
	  $hauteur=$origHeight;
	      
		//on regarde si l'image depasse en longueur
		$depasse_hauteur=$hauteur-$max_largeur;
		//on regarde si l'image depasse en largeur
		$depasse_large=$largeur-$max_largeur;
				
		if($depasse_hauteur>0 || $depasse_large>0)	{
			if($depasse_hauteur>$depasse_large) {
				$largeur=($max_hauteur/$hauteur)*$largeur;
				$hauteur=$max_hauteur;
			}	else {
				$hauteur=($max_largeur/$largeur)*$hauteur;
				$largeur=$max_largeur;	
			}
	  }
	 	$resultImageResize = imagecreatetruecolor($largeur, $hauteur);
	  imagecopyresampled ($resultImageResize, $resultImage, 0, 0, 0, 0, $largeur, $hauteur, $origWidth, $origHeight);
	  
	  $origWidth=$largeur;
	  $origHeight=$hauteur;
	  
	  
	  // Création du watermark 
	
	  $waterMarkInfo = getimagesize($watermark);
	  $waterMarkWidth = $waterMarkInfo[0];
	  $waterMarkHeight = $waterMarkInfo[1];
	
	  // watermark sizing info
	  if($wm_size=='larger') {
	    $placementX=0;
	    $placementY=0;
	    $h_position='center';
	    $v_position='center';
	  	$waterMarkDestWidth=$waterMarkWidth;
	  	$waterMarkDestHeight=$waterMarkHeight;
	      
	    // both of the watermark dimensions need to be 5% more than the original image...
	    // adjust width first.
	    if($waterMarkWidth > $origWidth*1.05 && $waterMarkHeight > $origHeight*1.05){
	    	// both are already larger than the original by at least 5%...
	    	// we need to make the watermark *smaller* for this one.
	    	
	    	// where is the largest difference?
	    	$wdiff=$waterMarkDestWidth - $origWidth;
	    	$hdiff=$waterMarkDestHeight - $origHeight;
	    	if($wdiff > $hdiff) {
	    		// the width has the largest difference - get percentage
	    		$sizer=($wdiff/$waterMarkDestWidth)-0.05;
	    	} else {
	    		$sizer=($hdiff/$waterMarkDestHeight)-0.05;
	    	}
	    	$waterMarkDestWidth-=$waterMarkDestWidth * $sizer;
	    	$waterMarkDestHeight-=$waterMarkDestHeight * $sizer;
	    } else {
	    	// the watermark will need to be enlarged for this one
	    	
	    	// where is the largest difference?
	    	$wdiff=$origWidth - $waterMarkDestWidth;
	    	$hdiff=$origHeight - $waterMarkDestHeight;
	    	if($wdiff > $hdiff) {
	    		// the width has the largest difference - get percentage
	    		$sizer=($wdiff/$waterMarkDestWidth)+0.05;
	    	} else {
	    		$sizer=($hdiff/$waterMarkDestHeight)+0.05;
	    	}
	    	$waterMarkDestWidth+=$waterMarkDestWidth * $sizer;
	    	$waterMarkDestHeight+=$waterMarkDestHeight * $sizer;
	    }
	  }
	  
	  if($wm_size=='0'){ // On garde la taille du watermark par defaut
	  	$waterMarkDestWidth=$waterMarkWidth;
	  	$waterMarkDestHeight=$waterMarkHeight;
		}
	  else{
	    $waterMarkDestWidth=round($origWidth * floatval($wm_size));
	    $waterMarkDestHeight=round($origHeight * floatval($wm_size));
	    if($wm_size==1){
	        $waterMarkDestWidth-=2*$edgePadding;
	        $waterMarkDestHeight-=2*$edgePadding;
	    }
	  }
	      
	  //if ($wm_size!='0') {
	    // OK, we have what size we want the watermark to be, time to scale the watermark image
	    resize_png_image($watermark,$waterMarkDestWidth,$waterMarkDestHeight,$wmTarget);
	  //}
	  
	  // get the size info for this watermark.
	  $wmInfo=getimagesize($wmTarget);
	  $waterMarkDestWidth=$wmInfo[0];
	  $waterMarkDestHeight=$wmInfo[1];
	
	  $differenceX = $origWidth - $waterMarkDestWidth;
	  $differenceY = $origHeight - $waterMarkDestHeight;
	
	  // where to place the watermark?
	  switch($h_position){
	      // find the X coord for placement
	      case 'left':
	          $placementX = $edgePadding;
	          break;
	      case 'center':
	          $placementX =  round($differenceX / 2);
	          break;
	      case 'right':
	          $placementX = $origWidth - $waterMarkDestWidth - $edgePadding;
	          break;
	  }
	
	  switch($v_position){
	      // find the Y coord for placement
	      case 'top':
	          $placementY = $edgePadding;
	          break;
	      case 'center':
	          $placementY =  round($differenceY / 2);
	          break;
	      case 'bottom':
	          $placementY = $origHeight - $waterMarkDestHeight - $edgePadding;
	          break;
	  }
	
	  $finalWaterMarkImage = imagecreatefrompng($wmTarget);
	  $finalWaterMarkWidth = imagesx($finalWaterMarkImage);
	  $finalWaterMarkHeight = imagesy($finalWaterMarkImage);
	
	
	  imagecopy($resultImageResize,
	            $finalWaterMarkImage,
	            $placementX,
	            $placementY,
	            0,
	            0,
	            $finalWaterMarkWidth,
	            $finalWaterMarkHeight
	  );
	      
	  // Enregistrement de l'image au format souhaité
	  
	  if($img_format=='jpg'){
	      imagejpeg($resultImageResize,$target,$quality); 
	  }
	  elseif($img_format=='png'){
	      imagealphablending($resultImageResize,FALSE);
	      imagesavealpha($resultImageResize,TRUE);
	      imagepng($resultImageResize,$target);
	  }
	  elseif($img_format=='gif'){
	      imagegif($resultImageResize,$target);
	  }
	
	  imagedestroy($resultImage);
	  imagedestroy($resultImageResize);
	  imagedestroy($finalWaterMarkImage);
	  
		unlink($wmTarget);
		//Virer l'image source
		unlink($original);
		echo "Fait pour ".$original."<br>";
	}
	return true;
}


function resize_png_image($img,$newWidth,$newHeight,$target){
	$srcImage=imagecreatefrompng($img);
	if($srcImage==''){
	    return FALSE;
	}
	$srcWidth=imagesx($srcImage);
	$srcHeight=imagesy($srcImage);
	$percentage=(double)$newWidth/$srcWidth;
	$destHeight=round($srcHeight*$percentage)+1;
	$destWidth=round($srcWidth*$percentage)+1;
	if($destHeight > $newHeight) {
	    // if the width produces a height bigger than we want, calculate based on height
	    $percentage=(double)$newHeight/$srcHeight;
	    $destHeight=round($srcHeight*$percentage)+1;
	    $destWidth=round($srcWidth*$percentage)+1;
	}
	$destImage=imagecreatetruecolor($destWidth-1,$destHeight-1);
	if(!imagealphablending($destImage,FALSE)) {
	    return FALSE;
	}
	if(!imagesavealpha($destImage,TRUE)) {
	    return FALSE;
	}
	if(!imagecopyresampled($destImage,$srcImage,0,0,0,0,$destWidth,$destHeight,$srcWidth,$srcHeight)){
	    return FALSE;
	}
	if(!imagepng($destImage,$target)) {
	    return FALSE;
	}
	imagedestroy($destImage);
	imagedestroy($srcImage);
	return TRUE;
}
?>
Il reste quand même un petit problème de type timeout.
En effet, le traitement d'une photo met presqu'une seconde. En début de code, j'ai ajouté de quoi lutter contre ça, mais la configuration actuelle de notre hébergeur empèche tout changement.
Une solution serait de pouvoir faire ça en plusieur passes:
  1. On contruit le tableau des images à traiter en scannant les répertoires ainsi que les sous répertoires
  2. La page se recharge
  3. Pour toute les lignes du tableau:
    • Convertir N photos
    • Recharger la page