New: Add feature to resize or crop images (for product's photo).

This commit is contained in:
Laurent Destailleur 2010-02-21 11:50:21 +00:00
parent 5af5d306eb
commit b4c9331461
6 changed files with 99 additions and 66 deletions

View File

@ -3,10 +3,11 @@ English Dolibarr ChangeLog
***** ChangeLog for 2.9 compared to 2.8 ***** ***** ChangeLog for 2.9 compared to 2.8 *****
For users: For users:
New: Add "payment due before" field in invoice exports - New: Add "payment due before" field in invoice exports
- New: Add feature to resize or crop image files (for products photos)
For developers: For developers:
- More comments in code
***** ChangeLog for 2.8 compared to 2.7 ***** ***** ChangeLog for 2.8 compared to 2.7 *****

View File

@ -1,8 +1,6 @@
<?php <?php
/* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org> /* Copyright (C) 2010 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2004-2009 Laurent Destailleur <eldy@users.sourceforge.net> * Copyright (C) 2009 Meos
* Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
* Copyright (C) 2005-2009 Regis Houssin <regis@dolibarr.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -26,19 +24,17 @@ require_once(DOL_DOCUMENT_ROOT."/product.class.php");
$langs->load("products"); $langs->load("products");
// Security check $modulepart=$_REQUEST['modulepart']?$_REQUEST['modulepart']:'produit|service';
if (isset($_GET["id"])) if (isset($_GET["id"]))
{ {
$id = isset($_GET["id"])?$_GET["id"]:''; $id = isset($_GET["id"])?$_GET["id"]:'';
} }
$result=restrictedArea($user,'produit|service',$id,'product','','',$fieldid);
$original_file = isset($_REQUEST["file"])?urldecode($_REQUEST["file"]):''; $original_file = isset($_REQUEST["file"])?urldecode($_REQUEST["file"]):'';
$langs->load("products"); // Security check
if ($modulepart=='produit|service') $result=restrictedArea($user,'produit|service',$id,'product','','',$fieldid);
if (!$user->rights->produit->lire) accessforbidden(); else accessforbidden('Bad value for modulepart');
if ($modulepart=='produit|service' && (! $user->rights->produit->lire && ! $user->rights->service->lire)) accessforbidden();
@ -48,8 +44,8 @@ if (!$user->rights->produit->lire) accessforbidden();
if ($_POST["action"] == 'confirm_resize' && (isset($_POST["file"]) != "") && (isset($_POST["sizex"]) != "") && (isset($_POST["sizey"]) != "")) if ($_POST["action"] == 'confirm_resize' && (isset($_POST["file"]) != "") && (isset($_POST["sizex"]) != "") && (isset($_POST["sizey"]) != ""))
{ {
$fullpath=$conf->produit->dir_output."/".$_POST["file"]; $fullpath=$conf->produit->dir_output."/".$original_file;
$result=dol_imageResize($fullpath,$_POST['sizex'],$_POST['sizey']); $result=dol_imageResizeOrCrop($fullpath,0,$_POST['sizex'],$_POST['sizey']);
if ($result == $fullpath) if ($result == $fullpath)
{ {
@ -65,16 +61,22 @@ if ($_POST["action"] == 'confirm_resize' && (isset($_POST["file"]) != "") && (is
} }
// Crop d'une image // Crop d'une image
if ($_POST["action"] == 'confirm_crop' && $_POST["file"]) if ($_POST["action"] == 'confirm_crop')
{ {
// TODO Add function to crop image in images.lib.php $fullpath=$conf->produit->dir_output."/".$original_file;
/* $thumb = new Imagick($conf->produit->dir_output."/".urldecode($_POST["file"])); $result=dol_imageResizeOrCrop($fullpath,1,$_POST['w'],$_POST['h'],$_POST['x'],$_POST['y']);
$thumb->cropImage($_POST['w'], $_POST['h'], $_POST['x'], $_POST['y']);
$thumb->writeImage($conf->produit->dir_output."/".urldecode($_POST["file"])); if ($result == $fullpath)
$thumb->destroy(); {
*/ header("Location: ".DOL_URL_ROOT."/product/photos.php?id=".$_POST["product"].'&action=addthumb&file='.urldecode($_POST["file"]));
header("Location: ".DOL_URL_ROOT."/product/photos.php?id=".$_POST["product"].'&action=addthumb&file='.urldecode($_POST["file"])); exit;
exit; }
else
{
$mesg=$result;
$_GET['file']=$_POST["file"];
$_GET['id']=$_POST["id"];
}
} }
@ -92,17 +94,18 @@ if ($mesg) print '<div class="error">'.$mesg.'</div>';
$infoarray=dol_getImageSize($conf->produit->dir_output."/".urldecode($_GET["file"])); $infoarray=dol_getImageSize($conf->produit->dir_output."/".urldecode($_GET["file"]));
$height=$infoarray['height']; $height=$infoarray['height'];
$width=$infoarray['width']; $width=$infoarray['width'];
print $langs->trans("Size").': </p> print $langs->trans("CurrentInformationOnImage").':';
<ul> print '<ul>
<li>'.$langs->trans("Width").': '.$width.' px</li> <li>'.$langs->trans("Width").': '.$width.' px</li>
<li>'.$langs->trans("Height").': '.$height.' px</li> <li>'.$langs->trans("Height").': '.$height.' px</li>
</ul>'; </ul>';
print '<br>'; print '<br>';
print_fiche_titre($langs->trans("Resize"),'','');
print '<form name="redim_file" action="'.$_SERVER["PHP_SELF"].'?id='.$_GET['id'].'" method="POST">'; print '<form name="redim_file" action="'.$_SERVER["PHP_SELF"].'?id='.$_GET['id'].'" method="POST">';
print '<fieldset id="redim_file">';
print '<legend>'.$langs->trans("Resize").'</legend>';
print $langs->trans("ResizeDesc").'<br>'; print $langs->trans("ResizeDesc").'<br>';
print $langs->trans("NewLength").': <input class="flat" name="sizex" size="10" type="text" > px <br /> '; print $langs->trans("NewLength").': <input class="flat" name="sizex" size="10" type="text" > px <br /> ';
print $langs->trans("NewHeight").': <input class="flat" name="sizey" size="10" type="text" > px &nbsp; <br />'; print $langs->trans("NewHeight").': <input class="flat" name="sizey" size="10" type="text" > px &nbsp; <br />';
@ -111,16 +114,17 @@ print '<input type="hidden" name="action" value="confirm_resize" />';
print '<input type="hidden" name="product" value="'.$_GET['id'].'" />'; print '<input type="hidden" name="product" value="'.$_GET['id'].'" />';
print '<input type="hidden" name="id" value="'.$_GET['id'].'" />'; print '<input type="hidden" name="id" value="'.$_GET['id'].'" />';
print '<br><input class="button" name="sendit" value="'.dol_escape_htmltag($langs->trans("Resize")).'" type="submit" />'; print '<br><input class="button" name="sendit" value="'.dol_escape_htmltag($langs->trans("Resize")).'" type="submit" />';
print '</fieldset>';
print '<br></form>'; print '<br></form>';
print '<br>';
/* /*
* Recadrage d'une image * Recadrage d'une image
*/ */
print '<br>'; print '<br>';
print_fiche_titre($langs->trans("Recenter"),'','');
print '<fieldset id="redim_file">';
print '<legend>'.$langs->trans("Recenter").'</legend>';
print $langs->trans("DefineNewAreaToPick").'...<br>'; print $langs->trans("DefineNewAreaToPick").'...<br>';
print '<br>'; print '<br>';
print '<img style="border: 1px solid #888888;" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.$original_file.'" alt="Taille origine" id="cropbox" />'; print '<img style="border: 1px solid #888888;" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.$original_file.'" alt="Taille origine" id="cropbox" />';
@ -145,6 +149,7 @@ print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$_GET['id'].'" method="post"
<input type="hidden" name="id" value="'.$_GET['id'].'" /> <input type="hidden" name="id" value="'.$_GET['id'].'" />
<br><input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Recenter")).'" /> <br><input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Recenter")).'" />
</form>'; </form>';
print '</fieldset>';
llxFooter('$Date$ - $Revision$'); llxFooter('$Date$ - $Revision$');
?> ?>

View File

@ -120,6 +120,7 @@ NewLength=New width
NewHeight=New height NewHeight=New height
NewSizeAfterCropping=New size after cropping NewSizeAfterCropping=New size after cropping
DefineNewAreaToPick=Define new area on image to pick (left click on image then drag until you reach the opposite corner) DefineNewAreaToPick=Define new area on image to pick (left click on image then drag until you reach the opposite corner)
CurrentInformationOnImage=Informations on current image
##### Bookmark ##### ##### Bookmark #####
Bookmark=Bookmark Bookmark=Bookmark

View File

@ -120,6 +120,7 @@ NewLength=Nouvelle largeur
NewHeight=Nouvelle hauteur NewHeight=Nouvelle hauteur
NewSizeAfterCropping=Nouvelles dimensions après recadrage NewSizeAfterCropping=Nouvelles dimensions après recadrage
DefineNewAreaToPick=Définissez la zone d'image à conserver (clic gauche sur l'image puis drag vers les coin opposé) DefineNewAreaToPick=Définissez la zone d'image à conserver (clic gauche sur l'image puis drag vers les coin opposé)
CurrentInformationOnImage=Informations courante sur l'image
##### Bookmark ##### ##### Bookmark #####
Bookmark=Marque page Bookmark=Marque page

View File

@ -26,7 +26,7 @@
/** /**
* \brief Return size of image file on disk * \brief Return size of image file on disk (Supported extensions are gif, jpg, png and bmp)
* \param $file Full path name of file * \param $file Full path name of file
* \return Array array('width'=>width, 'height'=>height) * \return Array array('width'=>width, 'height'=>height)
*/ */
@ -50,21 +50,23 @@ function dol_getImageSize($file)
/** /**
* \brief Resize an image file * \brief Resize or crop an image file (Supported extensions are gif, jpg, png and bmp)
* \brief Supported extensions are jpg and png * \param file Path of file to resize/crop
* \param file Chemin du fichier image a redimensionner * \param mode 0=Resize, 1=Crop
* \param newWidth Largeur maximum que dois faire la miniature (-1=unchanged) * \param newWidth Largeur maximum que dois faire l'image destination (0=keep ratio)
* \param newHeight Hauteur maximum que dois faire l'image (-1=unchanged) * \param newHeight Hauteur maximum que dois faire l'image destination (0=keep ratio)
* \param src_x Position of croping image in source image (not use if mode=0)
* \param src_y Position of croping image in source image (not use if mode=0)
* \return int File name if OK, error message if KO * \return int File name if OK, error message if KO
* \remarks With file=myfile.jpg -> myfile_small.jpg * \remarks With file=myfile.jpg -> myfile_small.jpg
*/ */
function dol_imageResize($file, $newWidth, $newHeight) function dol_imageResizeOrCrop($file, $mode, $newWidth, $newHeight, $src_x=0, $src_y=0)
{ {
require_once(DOL_DOCUMENT_ROOT."/lib/functions2.lib.php"); require_once(DOL_DOCUMENT_ROOT."/lib/functions2.lib.php");
global $conf,$langs; global $conf,$langs;
dol_syslog("dol_imageResize file=".$file." newWidth=".$newWidth." newHeight=".$newHeight); dol_syslog("dol_imageResizeOrCrop file=".$file." mode=".$mode." newWidth=".$newWidth." newHeight=".$newHeight." src_x=".$src_x." src_y=".$src_y);
// Clean parameters // Clean parameters
$file=trim($file); $file=trim($file);
@ -82,14 +84,19 @@ function dol_imageResize($file, $newWidth, $newHeight)
} }
elseif(image_format_supported($file) < 0) elseif(image_format_supported($file) < 0)
{ {
return 'This file '.$file.' does not seem to be an image format file name.'; return 'This filename '.$file.' does not seem to be an image filename.';
} }
elseif(!is_numeric($newWidth) && !is_numeric($newHeight)){ elseif(!is_numeric($newWidth) && !is_numeric($newHeight))
{
return 'Wrong value for parameter newWidth or newHeight'; return 'Wrong value for parameter newWidth or newHeight';
} }
elseif ($newWidth <= 0 && $newHeight <= 0) elseif ($mode == 0 && $newWidth <= 0 && $newHeight <= 0)
{ {
return 'At least newHeight or newWidth must be defined'; return 'At least newHeight or newWidth must be defined for resizing';
}
elseif ($mode == 1 && ($newWidth <= 0 || $newHeight <= 0))
{
return 'Both newHeight or newWidth must be defined for croping';
} }
$fichier = realpath($file); // Chemin canonique absolu de l'image $fichier = realpath($file); // Chemin canonique absolu de l'image
@ -99,13 +106,16 @@ function dol_imageResize($file, $newWidth, $newHeight)
$imgWidth = $infoImg[0]; // Largeur de l'image $imgWidth = $infoImg[0]; // Largeur de l'image
$imgHeight = $infoImg[1]; // Hauteur de l'image $imgHeight = $infoImg[1]; // Hauteur de l'image
if ($newWidth <= 0) if ($mode == 0) // If resize, we check parameters
{ {
$newWidth=intval(($newHeight / $imgHeight) * $imgWidth); // Keep ratio if ($newWidth <= 0)
} {
if ($newHeight <= 0) $newWidth=intval(($newHeight / $imgHeight) * $imgWidth); // Keep ratio
{ }
$newHeight=intval(($newWidth / $imgWidth) * $imgHeight); // Keep ratio if ($newHeight <= 0)
{
$newHeight=intval(($newWidth / $imgWidth) * $imgHeight); // Keep ratio
}
} }
$imgfonction=''; $imgfonction='';
@ -138,23 +148,23 @@ function dol_imageResize($file, $newWidth, $newHeight)
{ {
case 1: // Gif case 1: // Gif
$img = imagecreatefromgif($fichier); $img = imagecreatefromgif($fichier);
$extImg = '.gif'; // Extension de l'image $extImg = '.gif'; // File name extension of image
$newquality='NU'; $newquality='NU'; // Quality is not used for this format
break; break;
case 2: // Jpg case 2: // Jpg
$img = imagecreatefromjpeg($fichier); $img = imagecreatefromjpeg($fichier);
$extImg = '.jpg'; // Extension de l'image $extImg = '.jpg';
$newquality=100; $newquality=100; // % quality maximum
break; break;
case 3: // Png case 3: // Png
$img = imagecreatefrompng($fichier); $img = imagecreatefrompng($fichier);
$extImg = '.png'; $extImg = '.png';
$newquality=10; $newquality=0; // No compression (0-9)
break; break;
case 4: // Bmp case 4: // Bmp
$img = imagecreatefromwbmp($fichier); $img = imagecreatefromwbmp($fichier);
$extImg = '.bmp'; $extImg = '.bmp';
$newquality='NU'; $newquality='NU'; // Quality is not used for this format
break; break;
} }
@ -201,9 +211,9 @@ function dol_imageResize($file, $newWidth, $newHeight)
} }
if (function_exists("imagefill")) imagefill($imgThumb, 0, 0, $trans_colour); if (function_exists("imagefill")) imagefill($imgThumb, 0, 0, $trans_colour);
dol_syslog("dol_imageResize: convert image from ($imgWidth x $imgHeight) to ($newWidth x $newHeight) as $extImg, newquality=$newquality"); dol_syslog("dol_imageResizeOrCrop: convert image from ($imgWidth x $imgHeight) at position ($src_x x $src_y) to ($newWidth x $newHeight) as $extImg, newquality=$newquality");
//imagecopyresized($imgThumb, $img, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imgWidth, $imgHeight); // Insere l'image de base redimensionnee //imagecopyresized($imgThumb, $img, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imgWidth, $imgHeight); // Insere l'image de base redimensionnee
imagecopyresampled($imgThumb, $img, 0, 0, 0, 0, $newWidth, $newHeight, $imgWidth, $imgHeight); // Insere l'image de base redimensionnee imagecopyresampled($imgThumb, $img, 0, 0, $src_x, $src_y, $newWidth, $newHeight, ($mode==0?$imgWidth:$newWidth), ($mode==0?$imgHeight:$newHeight)); // Insere l'image de base redimensionnee
$imgThumbName = $file; $imgThumbName = $file;
@ -234,13 +244,14 @@ function dol_imageResize($file, $newWidth, $newHeight)
// Free memory // Free memory
imagedestroy($imgThumb); imagedestroy($imgThumb);
clearstatcache(); // File was replaced by a modified on, so we clear file caches.
return $imgThumbName; return $imgThumbName;
} }
/** /**
* \brief Create a thumbnail from an image file (une small et un mini) * \brief Create 2 thumbnails from an image file: one small and one mini (Supported extensions are gif, jpg, png and bmp)
* \brief Les extensions prises en compte sont jpg et png
* \param file Chemin du fichier image a redimensionner * \param file Chemin du fichier image a redimensionner
* \param maxWidth Largeur maximum que dois faire la miniature (-1=unchanged, 160 par defaut) * \param maxWidth Largeur maximum que dois faire la miniature (-1=unchanged, 160 par defaut)
* \param maxHeight Hauteur maximum que dois faire l'image (-1=unchanged, 120 par defaut) * \param maxHeight Hauteur maximum que dois faire l'image (-1=unchanged, 120 par defaut)

View File

@ -130,7 +130,7 @@ class Product extends CommonObject
$this->stock_reel = 0; $this->stock_reel = 0;
$this->seuil_stock_alerte = 0; $this->seuil_stock_alerte = 0;
$this->canvas = ''; $this->canvas = '';
if ($this->id > 0) $this->fetch($this->id); if ($this->id > 0) $this->fetch($this->id);
} }
@ -2397,7 +2397,7 @@ class Product extends CommonObject
/** /**
* \brief Affiche toutes les photos du produit (nbmax maximum) * \brief Affiche toutes les photos du produit (nbmax maximum)
* \param sdir Repertoire a scanner * \param sdir Directory to scan
* \param size 0=taille origine, 1 taille vignette * \param size 0=taille origine, 1 taille vignette
* \param nbmax Nombre maximum de photos (0=pas de max) * \param nbmax Nombre maximum de photos (0=pas de max)
* \param nbbyrow Nombre vignettes par ligne (si mode vignette) * \param nbbyrow Nombre vignettes par ligne (si mode vignette)
@ -2408,6 +2408,7 @@ class Product extends CommonObject
global $conf,$user,$langs; global $conf,$user,$langs;
include_once(DOL_DOCUMENT_ROOT ."/lib/files.lib.php"); include_once(DOL_DOCUMENT_ROOT ."/lib/files.lib.php");
include_once(DOL_DOCUMENT_ROOT ."/lib/images.lib.php");
$pdir = get_exdir($this->id,2) . $this->id ."/photos/"; $pdir = get_exdir($this->id,2) . $this->id ."/photos/";
$dir = $sdir . '/'. $pdir; $dir = $sdir . '/'. $pdir;
@ -2424,7 +2425,7 @@ class Product extends CommonObject
{ {
$photo=''; $photo='';
if (! utf8_check($file)) $file=utf8_encode($file); // To be sure date is stored in UTF8 in memory if (! utf8_check($file)) $file=utf8_encode($file); // To be sure file is stored in UTF8 in memory
if (dol_is_file($dir.$file)) if (dol_is_file($dir.$file))
{ {
@ -2440,20 +2441,28 @@ class Product extends CommonObject
if (! dol_is_file($dirthumb.$photo_vignette)) $photo_vignette=''; if (! dol_is_file($dirthumb.$photo_vignette)) $photo_vignette='';
} }
// Get filesize of original file
$imgarray=dol_getImageSize($dir.$photo);
if ($nbbyrow && $nbphoto == 1) print '<table width="100%" valign="top" align="center" border="0" cellpadding="2" cellspacing="2">'; if ($nbbyrow && $nbphoto == 1) print '<table width="100%" valign="top" align="center" border="0" cellpadding="2" cellspacing="2">';
if ($nbbyrow && ($nbphoto % $nbbyrow == 1)) print '<tr align=center valign=middle border=1>'; if ($nbbyrow && ($nbphoto % $nbbyrow == 1)) print '<tr align=center valign=middle border=1>';
if ($nbbyrow) print '<td width="'.ceil(100/$nbbyrow).'%" class="photo">'; if ($nbbyrow) print '<td width="'.ceil(100/$nbbyrow).'%" class="photo">';
print '<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo).'" alt="Taille origine" target="_blank">'; print "\n";
print '<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo).'" target="_blank">';
// Si fichier vignette disponible, on l'utilise, sinon on utilise photo origine // Show image (width height=120)
if ($photo_vignette) { // Si fichier vignette disponible et image source trop grande, on utilise la vignette, sinon on utilise photo origine
print '<img class="photo" border="0" height="120" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdirthumb.$photo_vignette).'">'; $alt=$langs->transnoentitiesnoconv('File').': '.$pdir.$photo;
$alt.=' - '.$langs->transnoentitiesnoconv('Size').': '.$imgarray['width'].'x'.$imgarray['height'];
if ($photo_vignette && $imgarray['height'] > 120) {
print '<!-- Show thumb -->';
print '<img class="photo" border="0" height="120" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdirthumb.$photo_vignette).'" title="'.dol_escape_htmltag($alt).'">';
} }
else { else {
print '<img class="photo" border="0" height="120" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo).'">'; print '<!-- Show original file -->';
print '<img class="photo" border="0" height="120" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=product&file='.urlencode($pdir.$photo).'" title="'.dol_escape_htmltag($alt).'">';
} }
print '</a>'; print '</a>';
@ -2477,6 +2486,7 @@ class Product extends CommonObject
print img_delete().'</a>'; print img_delete().'</a>';
} }
} }
print "\n";
if ($nbbyrow) print '</td>'; if ($nbbyrow) print '</td>';
if ($nbbyrow && ($nbphoto % $nbbyrow == 0)) print '</tr>'; if ($nbbyrow && ($nbphoto % $nbbyrow == 0)) print '</tr>';
@ -2491,7 +2501,11 @@ class Product extends CommonObject
{ {
if ($user->rights->produit->creer || $user->rights->service->creer) if ($user->rights->produit->creer || $user->rights->service->creer)
{ {
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$_GET["id"].'&amp;action=delete&amp;file='.urlencode($pdir.$viewfilename).'">'; // Link to resize
print '<a href="'.DOL_URL_ROOT.'/core/photos_resize.php?id='.$_GET["id"].'&amp;file='.urlencode($pdir.$viewfilename).'" title="'.dol_escape_htmltag($langs->trans("Resize")).'">'.img_picto($langs->trans("Resize"),DOL_URL_ROOT.'/theme/common/transform-crop-and-resize','',1).'</a> &nbsp; ';
// Link to delete
print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$_GET["id"].'&amp;action=delete&amp;file='.urlencode($pdir.$viewfilename).'">';
print img_delete().'</a>'; print img_delete().'</a>';
} }
} }