Probleme de consommation memoire avec imagecreatefromjpeg()

5 réponses
Avatar
yodaz
Bonjour,

Je teste mon script de génération de miniatures, et je rencontre de gros
problèmes de consommation mémoire.
Mon hébergeur est Free, et la limite de consommation mémoire est fixée à 32M
chez cet hébergeur.
A chaque fois que j'essaie de générer une miniature avec le code ci-dessous,
j'ai systématiquement une erreur de type "Fatal error: Allowed memory size
of 33554432 bytes exhausted".

L'erreur se produit au niveau de l'appel à la fonction
imagecreatefromjpeg().

Mes images ont une taille variable entre 2 et 3,5Mo. Vu que la limite est
fixée à 32Mo, je ne comprends pas pourquoi j'ai l'erreur. Est ce que mon
script comporte une erreur ? Est ce que mon appel a imagecreatefromjpeg()
est correct ?

J'ai également essayé de convertir l'image jpeg en wbmp en utilisant
jpeg2wbmp() en redimensionnant à la volée, mais l'erreur se produit quand
même (cette fois au niveau de l'appel à jpeg2wbmp()).

Existe t-il une solution de contournement pour mon problème (plus de 32M de
mémoire utilisé pour une image de 2M me parait quand même beaucoup) ?

Merci d'avance pour vos réponses.

///////////////////////////////////////////////////////////////////////////
    function thumbnailize($img)
    {
        $thumb="";
        if (file_exists($img))
        {
            $imgInfo = getimagesize($img);
            $imgWidth=$imgInfo[0];
            $imgHeight=$imgInfo[1];
            $imgType=$imgInfo['mime'];

             // $imgInfo[2] -> image type 2 = JPG,JPEG
            if ($imgInfo[2] == 2)
            {
                // check image format is jpeg
                $imgSrc=imagecreatefromjpeg($img);

                // source image must be larger than destination image
                if ( ($imgWidth > THUMB_WIDTH) || ($imgHeight >
THUMB_HEIGHT) )
                {
                        // if width larger than height
                        if ($imgHeight <= $imgWidth)
                        {
                            $ratio = THUMB_WIDTH / $imgWidth;
                        }
                        else
                        {
                            $ratio = THUMB_HEIGHT / $imgHeight;
                        }
                }
                else
                {
                    $ratio = 1;  // same as original
                }

                $thumb = imagecreatetruecolor(round($imgWidth * $ratio),
round($imgHeight*$ratio));
                imagecopyresampled($thumb
$imgSrc,0,0,0,0,round($imgWidth*$ratio),round($imgHeight*$ratio),$imgWidth
$imgHeight);
                imagedestroy($imgSrc);

                // Send image file to browser
                imageinterlace($thumb);
                header('Content-Type: ' . $imgType);
                imagejpeg($thumb, NULL, THUMB_QUALITY);
                imagedestroy($imgLow);
                imagedestroy($thumb);
            }
        }
    }
///////////////////////////////////////////////////////////////////////////

5 réponses

Avatar
Dominique Ottello
yodaz écrivait :

Existe t-il une solution de contournement pour mon problème (plus de 32M de
mémoire utilisé pour une image de 2M me parait quand même beaucoup) ?



Générer les miniatures en local où on pourra modifier dans php.ini les
allocations mémoire, puis transférer les miniatures sur le site par FTP.

Où alors prendre un hébergement (payant) avec des allocations mémoire
plus importantes que sur un hébergement mutualisé.
--
Ce n'est pas parce que l'erreur se propage qu'elle devient vérité. Gandhi
Technologie aéronautique : http://aviatechno.free.fr (http://ottello.net)
Concorde dans la presse de 1965 à 2003 : http://le.pointu.free.fr
Avatar
Denis Beauregard
Le 10 Nov 2008 09:59:48 GMT, yodaz écrivait
dans fr.comp.lang.php:

Mes images ont une taille variable entre 2 et 3,5Mo. Vu que la limite est
fixée à 32Mo, je ne comprends pas pourquoi j'ai l'erreur. Est ce que mon
script comporte une erreur ? Est ce que mon appel a imagecreatefromjpeg()
est correct ?



La taille permise pour l'image est beaucoup plus petite que celle
de la mémoire.

J'ai fait l'essai sur un PC qui avait 512 Mo de mémoire et il
fallait que je limite la grosseur de mes images. Cela fait un bout
de temps que j'ai travaillé sur ce code, mais en regardant mes
fichiers, la limite semblait être 1000 x 700 ou 1200 x 800, ce qui
donne autour de 700000 à 1000000 de pixels, bien plus petit que vos
2 Mo en jpg.


Denis
Avatar
TJ
On 2008-11-10, yodaz wrote:
Bonjour,



Bonjour,

Mes images ont une taille variable entre 2 et 3,5Mo. Vu que la limite est
fixée à 32Mo, je ne comprends pas pourquoi j'ai l'erreur. Est ce que mon
script comporte une erreur ? Est ce que mon appel a imagecreatefromjpeg()
est correct ?



Bien que tes images aient un poids faible, leur taille décompressée
sera toujours bien plus importante. Enregistrées en JPEG elle sont
compressées, mais pas manipulables directement pour du traitement
d'image.

Lorsque GD lit ton image il alloue de la mémoire pour stocker toutes
les informations contenues dans celle-ci et à minima par exemple pour
une image de 4096*4096 pixels avec trois canaux par pixel cela
occupera :

4096*4096*3*8 = 402653184 bits (soit environ 48 Mo)

alors que cette même image, en JPEG peut très bien avoir un poids de
seulement quelques Ko (tout dépend de la compression et de l'image).
Note que je parle de taille mémoire minimale, GD peut très bien en
allouer encore pour d'autres données. Je ne connais pas le
fonctionnement interne de GD mais je pense que ce que je te dis est
valable pour beaucoup de bibliothèques de traitement d'image. Il peut
aussi y avoir des fuites.

Une solution (mais je ne sais pas si c'est possible avec GD) surtout
pour faire des vignettes, est de charger l'image dans une résolution
inférieure (par exemple le double de tes vignettes). C'est possible avec
ImageMagick par exemple.
Avatar
yodaz
Bonjour et merci à tous pour vos réponses très instructives.

Je pense que je vais m'orienter vers un vrai hébergeur, car les pages perso
de Free sont une vrai catastrophe autant en terme de restrictions que de
performance : même en réduisant mes images avec la commande convert
d'ImageMagick avant de les uploader, j'ai toujours des problèmes de
vignettes qui n'apparaissent pas, ou qui disparaissent après un refresh.

Je précise que tout fonctionne parfaitement en local.

Côté hébergeur, je suis interessé par l'offre de Gandi
(http://www.gandi.net/hebergement/), qu'en pensez-vous ? Est ce suffisant
pour mes besoins ? (la question est un peu off-topic, désolé)

Merci d'avance et bonne journée.
Avatar
Pascal PONCET
yodaz a écrit :
Je précise que tout fonctionne parfaitement en local.



Bonjour,

En local, ça serait l'occasion de tester l'usage mémoire à plusieurs
endroits du script, en utilisant les fonctions "memory_get_usage()" et
"memory_get_peak_usage( TRUE )".

Car, même en trouvant un hébergeur "sympa", la quantité de mémoire
allouée à un script conditionnera fortement les accès au serveur, en
nombre et en débit.

Cordialement,
Pascal