Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > Images > Imagick
Imagick Forum d'entraide pour l'extension Imagick permettant de manipuler des images en PHP (port de l'API ImageMagick).
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 16/10/2006, 17h54   #1
Invité régulier
 
Inscription : octobre 2006
Messages : 14
Détails du profil
Informations personnelles :
Localisation : France, Hérault (Languedoc Roussillon)

Informations forums :
Inscription : octobre 2006
Messages : 14
Points : 7
Points : 7
Par défaut [ImageMagick] Problème de création de vignette d'image à la volée

Bonjour,

Voici les données de mon problème:

Je fais une application de gestion de fichiers sur un serveur, avec comme possibilité:
- upload de fichiers (forcément ...)
- création d'une vignette à la volée quand il s'agit d'une image

J'ai une fonction qui doit normalement s'occuper de créer des vignettes lors du chargement.

la voici:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function createThumb($source,$cible,$NW,$NH,$ext){
setMemoryForImage( $source );
 
// Cacul des nouvelles dimensions
list($width_orig, $height_orig) = getimagesize($source);
 
	if ($NW && ($width_orig < $height_orig)) {
	$NW = ($NH / $height_orig) * $width_orig;
	} else {
	$NH = ($NW / $width_orig) * $height_orig;
	}
 
$NW=floor($NW);
$NH=floor($NH);
 
// Redimensionnement
$create_cible = imageCreateTrueColor($NW, $NH);
 
	if($ext=="jpg" || $ext=="jpeg"){
	$image = imageCreateFromJpeg($source);
 
	imageCopyResampled($create_cible, $image, 0, 0, 0, 0, $NW, $NH, $width_orig, $height_orig);
		if(imageJpeg($create_cible,$cible)){
		$report=true;
		}
		else{
		$report=false;
		}
	}
return $report;
}
la fonction setMemoryForImage me permet (normalement) d'allouer les ressources nécessaires pour la manipulation de l'image. c'est une fonction récupérée sur php.net:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function setMemoryForImage( $filename ){
$imageInfo = getimagesize($filename);
$MB = 1048576;  // number of bytes in 1M
$K64 = 65536;    // number of bytes in 64K
$TWEAKFACTOR = 1.5;  // Or whatever works for you
$memoryNeeded = round( ( $imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + $K64) * $TWEAKFACTOR);
//ini_get('memory_limit') only works if compiled with "--enable-memory-limit" also
//Default memory limit is 8MB so well stick with that. 
//To find out what yours is, view your php.ini file.
$memoryLimitMB = 32;
$memoryLimit = $memoryLimitMB * $MB;
   if (function_exists('memory_get_usage') && (memory_get_usage() + $memoryNeeded > $memoryLimit)){
	$newLimit = $memoryLimitMB + ceil( ( memory_get_usage() + $memoryNeeded - $memoryLimit ) / $MB);
	ini_set( 'memory_limit', $newLimit . 'M' );
   return true;
   }
	else{
   return false;
   }
}
l'upload du fichier repose sur un formulaire avec un champ parcourir et un bouton ok.
le formulaire pointe vers un fichier qui copie le fichier sur le serveur et, en fonction de l'extension, tente de créer la vignette.

mon problème: la création des vignettes de certains fichiers images ne passent pas, et d'autres passent sans souci. Aucun problème au niveau de l'upload dans tous les cas.

Quelques indications:
- Serveur dédié
- la version de PHP: 4.3.11
- la version de la GD: bundled (2.0.28 compatible) => support de GIF, JPG, PNG
- 32 Mo en memory_limit
- 10 Mo en upload maximal
- les fichiers qui ne passent pas ne sont pas forcément plus lourd que ceux qui passent. Une vignette a été créée pour une image de 1.56 Mo et aussi pour une image de 1.69 Mo, et ça plante pour une image de 1.27 Mo
- les images qui ne passent pas sont bien en RVB
- En mode de debug, j'affiche un message basique qui indique que la vignette a été créée puis exit. Quand le script ne fonctionne pas, Internet Explorer m'affiche "Impossible d'afficher la page" (erreur 404 quoi !), et Firefox lui fait comme si aucun lien n'est cliqué, c-a-d rien.

Je sèche et je ne comprends pas ce qui se passe.

Toute proposition, voire solution, est bienvenue.

Merci d'avoir lu jusqu'ici
falatop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/10/2006, 18h36   #2
Membre expérimenté
 
Avatar de jc_cornic
 
Inscription : octobre 2006
Messages : 624
Détails du profil
Informations personnelles :
Âge : 36

Informations forums :
Inscription : octobre 2006
Messages : 624
Points : 588
Points : 588
Envoyer un message via MSN à jc_cornic
Tu peux préciser les spécifications de tes fichiers images qui marchent et de ceux qui ne marchent pas...

Par exemple, les extensions, si les tailles sont des puissances de 2 ou non...
bref, un peu plus de détail sur les fichiers...

++
JC
jc_cornic est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/10/2006, 19h31   #3
Invité régulier
 
Inscription : octobre 2006
Messages : 14
Détails du profil
Informations personnelles :
Localisation : France, Hérault (Languedoc Roussillon)

Informations forums :
Inscription : octobre 2006
Messages : 14
Points : 7
Points : 7
Citation:
Envoyé par jc_cornic
Tu peux préciser les spécifications de tes fichiers images qui marchent et de ceux qui ne marchent pas...

Par exemple, les extensions, si les tailles sont des puissances de 2 ou non...
bref, un peu plus de détail sur les fichiers...

++
JC
Toutes les extensions sont en .jpg (minuscules)

Exemple d'un fichier pour lequel la vignette a été créée:
RH188S-5.jpg -> 1332759 octets (1.27 Mo)
largeur originale=3888 pixels
hauteur originale=1600 pixels

Exemple d'un fichier pour lequel la vignette a été créée:
LCD-TV_47LB2RF.jpg -> 1772368 octets (1,69 Mo)
largeur originale=674 pixels
hauteur originale=590 pixels

Exemple d'un fichier pour lequel la vignette échoue:
RH188S.jpg -> 867320 octets (846,99 Ko)
largeur originale=3888 pixels
hauteur originale=2238 pixels

Exemple d'un fichier pour lequel la vignette échoue:
LC2RR-Silver.jpg -> 1403205 octets (1,34 Mo)
largeur originale=3425 pixels
hauteur originale=3368 pixels

A noter que les fichiers sont renommés avant d'être copiés sur le disque:
- pas de caractères accentués
- espaces remplacés par des tirets

et la copie est tentée à partir du fichier renommé.

les fichiers sont tous en 300 dpi... et je suis en train de me demander si la taille ( largeur et hauteur ) n'est pas en cause...

++
falatop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/10/2006, 13h22   #4
Invité régulier
 
Inscription : octobre 2006
Messages : 14
Détails du profil
Informations personnelles :
Localisation : France, Hérault (Languedoc Roussillon)

Informations forums :
Inscription : octobre 2006
Messages : 14
Points : 7
Points : 7
J'ai enfin un message d'erreur:
Allowed memory size of 39845888 bytes exhausted (tried to allocate 15552 bytes).
Donc c'est un problème d'allocation de mémoire.

Autre question du coup:
la taille de la mémoire mentionnée (39845888 = 38Mo) correspond à la taille de memory_limit modifiée par la fonction setMemoryForImage($source), qui ne semble pas suffisante.

Vu que je suis sur un serveur dédié et que d'autres domaines fonctionnent dessus, est-ce correct de penser que les 32 Mo de memory_limit configurés initialement dans le php.ini sont répartis sur l'ensemble des scripts du serveur.

Car si je ne modifie pas la memory_limit, la fonction memory_get_usage() me renvoie environ 390 Ko de disponibilité pour le script, ce qui est insuffisant je pense.

Bref, je comprends le message d'erreur, mais je ne saisi pas bien les mécanismes de répartition de la mémoire sur le serveur.

Merci d'avance à ceux qui s'intéressent à mon problème
falatop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/10/2006, 12h18   #5
Invité régulier
 
Inscription : octobre 2006
Messages : 14
Détails du profil
Informations personnelles :
Localisation : France, Hérault (Languedoc Roussillon)

Informations forums :
Inscription : octobre 2006
Messages : 14
Points : 7
Points : 7
Par défaut Problème résolu

Bonjour,

Je modifie la valeur du memory_limit avant l'execution du script avec la fonction ini_set() de PHP, et ça marche
falatop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/10/2006, 15h13   #6
Nouveau Membre du Club
 
Inscription : novembre 2003
Messages : 70
Détails du profil
Informations forums :
Inscription : novembre 2003
Messages : 70
Points : 29
Points : 29
Salut, j'ai le même style de problème.
D'après ce que j'ai lu à droite à gauche sur le web, il s'emblerai effectivement que le problème vienne de memory_limite trops bas.
Il semble aussi que pour réduire une image avec GD il soit nécessaire à celui-ci de charger la totalité de l'image et de la convertir en BMP. Ce qui importe alors pour définir la mémoire utilisé est la dimension de l'image.
ex: une image jpeg de 1.5Mo de 2500*3500px une fois converti en BMP pèse:2500*3500*4=35Mo!!!!!!
et j'ai constater qu'un script(voir ci-dessous) tout simple qui ne fait que réduire la taille de cette image et afficher celle-ci à l'ecran en dimension réduite (1/10 de la taille originale) consomme entre 50 et 60Mo de memoire!!!!
Alors comment fixer la mémoire limite????

Autre problème remarqué:
J'utilise easyPHP en local pour débuguer avant l'envoi sur le serveur.
En local mon script fonctionne correctement bienque que memory_limite=8Mo dans la config de PHP en local et que la ligne ini_set("memory_limit","60M"); soit commenté.
Alors que sur le serveur de mon hébergeur memory_limite=12Mo ça ne fonctionne que ci ini_set("memory_limit","60M"); est décommenté.
Je ne comprend alors pas pourquoi ça marche chez moi (8Mo seulement!!!!)

code utilisé:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
//redimmentionnement d'une image jpg déjà sur le serveur---------------------------
ini_set("memory_limit","60M");
 
header('Content-type: image/jpeg');
//coefficient de réduction---
$ratio = .1;
// Calcul des nouvelles dimensions
list($largeur, $hauteur) = getimagesize("image.jpg"); //list est un moyen plus pratique pour ne récupérer que ce qu'on veut
$n_largeur = $largeur * $ratio;
$n_hauteur = $hauteur * $ratio;
 
//création de l'image de destination
$destination = imagecreatetruecolor($n_largeur, $n_hauteur);
 
//on ouvre l'image source
$source = imagecreatefromjpeg("image.jpg");
 
// Redimensionnement
imagecopyresized($destination, $source, 0, 0, 0, 0, $n_largeur, $n_hauteur, $largeur, $hauteur);
//affichage de l'image
imagejpeg($destination);
//libération des ressources----------
imagedestroy($destination);
imagedestroy($source);
?>
Cyrilh7 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h31.


 
 
 
 
Partenaires

Hébergement Web