Redimensionner image

Eléphant du PHP | 61 Messages

06 janv. 2021, 11:00

Hello tout le monde,

J'ai une version stable de mon projet où je présente tous les lieux incroyables de la Terre :D
Encore merci à tous !!

Le chargement de la page est un peu long.
Pour cause je suppose les images qui font entre 2Mo et +20Mo.

J'ai trouvé ce script pour réduire la taille des images (sur code-boxx.com).

Code : Tout sélectionner

<?php $img = imagecreatefromjpeg("image.jpg"); imagejpeg($img, "compressed.jpg", 30); echo "OK";
Mais j'ai l'impression que c'est pour modifier une image.
Or moi je voudrais automatiquement que toutes les images de ma boucle while soient modifiées:

Code : Tout sélectionner

<?php $reponse = $bdd->query('SELECT l.comte_nom, l.lieu_nom, l.pays_nom, p.flag_nom, l.lieu_url FROM lieux l LEFT JOIN pays p ON l.pays_nom = p.pays_nom LIMIT 1,650'); ?> <?php while ($donnees = $reponse->fetch()) { ?> <div class="vignette"> <img src="<?php echo $donnees['lieu_url']; ?>" alt="Lieu" class="imglieu"/> <div class="overlay"></div> <div class="lieu"><?php echo $donnees['lieu_nom']; ?></div> <div class="pays"><?php echo $donnees['pays_nom']; ?>, <?php echo $donnees['comte_nom']; ?></div> <img src="<?php echo $donnees['flag_nom']; ?>" alt="drapeau" class="flag"/> </div> <?php } ?> </body> </html>
Grand merci de votre aide !

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

06 janv. 2021, 11:36

Hello !

La fonction imagejpeg permet effectivement de créer une nouvelle image jpeg à partir d'une ressource passée en paramètre. Elle permet également de gérer la qualité de celle-ci, ce qui peut légèrement affecter son poids, mais pas ses dimensions (cela doit être fait en amont). Pour cela tu peux utiliser "imagecopyresized()" avec au besoin un petit calcul pour conserver les proportions de l'image :)

Pour autant, créer une image à partir d'une autre est un processus couteux en ressources et s'il doit être fait à chaque fois que quelqu'un charge la page, fois autant d'image que tu veux y afficher, c'est pas forcément beaucoup plus judicieux. Il est dans ce cas préférable de générer une vignette de ton image une fois pour toute et de proposer celle-ci (qui ne nécessitera donc plus de temps de traitement et sera suffisamment légère pour charger rapidement la liste).

J'avais réalisé une galerie ainsi qui pour chaque "image" vérifiait s'il y avait une miniature présente sur le serveur (avec un nom ou dans un dossier dédié). Si la miniature existait, elle était retournée sans autre traitement. Si par contre le fichier miniature n'était pas trouvé, j'utilisais imagecopyresized pour le créer et ainsi le retourner les fois suivantes.

Ce n'est pour autant pas non plus le top du top puisqu'on regarde systématiquement si le fichier est présent et le mieux serait d'ajouter la miniature en même temps que tu ajoutes l'image du lieu (ou de la générer à ce moment là). Tu es ainsi sûr d'avoir ta miniature à proposer sur les listes, et l'image original à dispo pour le détail du lieu :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 61 Messages

06 janv. 2021, 15:31

Salut Ryle !!!
Content de te relire :D

Merci de tes bons conseils.

Mais donc concrètement je suis pas sûr de ce que je dois faire :oops:

Le format de ma vignette existe (en CSS). Le problème c'est que ca prend juste une partie de l'image (et des fois même pas une bonne partie). Il faudrait que je puisse au moins dire que l'image fasse la largeur ou longueur désirée de la vignette (d'ou ta solution de cropping si je comprends bien).

Dans la boucle php construite je vais chercher l'url de l'image qui est dans mon dossier "img_lieux".
Est-ce que tu me dis que je dois traiter manuellement chaque image (avec un logiciel genre Sketch ou photoshop) pour cadrer l'image comme je le veux (et plus avec la fonction "Object-fit: cover;" et la remplacer dans mon fichier ?

J'ai actuellement 630 lieux et potentiellement le double et à long terme surement +3.000.
J'imagine mal faire tout ça à la main.
Mais j'attends tes instructions :-)

Merci de ton aide !

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

06 janv. 2021, 16:43

En fait la question à te poser c'est de savoir comment se passe l'ajout d'un nouveau lieu (et de l'image associé). Si tu intervient directement en base pour l'ajouter et via un logiciel FTP pour ajouter l'image, c'est plus complexe que si tu as un espace d'administration depuis lequel tu vas créer le lieu et charger l'image.

Dans le premier cas, bien qu'elle ne soit pas optimum, vérifier la présence d'une miniature et à défaut en générer une, peut convenir. Si en revanche tu un back office, c'est au moment de l'upload de la photo qu'il te suffit de créer la miniature à la volée.

Dans un cas comme dans l'autre, la procédure de création de la miniature reste la même. Il faut lire l'image d'origine, la réduire et l'enregistrer
// Chemins à adapter à ton contexte / rendre dynamique au besoin
$dirOrigine = "images/"; 
$dirVignettes = "vignettes/";
$fichier = "image.jpg";

// Dimensions de la vignette en pixels
$thumbWidth = 250;
$thumbHeight = 120;

// Lecture de l'image en supposant que ton image de base soit toujours un JPG
// Nota : si tu veux pouvoir utiliser des PNG ou autre, il faut tester le type de l'image et utiliser la fonction adaptée
$img = imageCreateFromJpeg($dirOrigine . $fichier); 

// Détermine les dimensions de l'image d'origine
$imgWidth = imagesx($img);
$imgHeight = imagesy($img);

// Crée la future vignette avec TrueColor si GD2 est disponible, sinon tu peux utiliser ImageCreate()
$imgThumb = imageCreateTrueColor($thumbWidth, $thumbHeight);

// Redimensionne l'image d'origine, 
imageCopyResized($imgThumb, $img, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imgWidth, $imgHeight);

// Sauvegarde de l'image dans le dossier vignettes
imageJpeg($imgThumb, $dirVignettes . $fichier);

// Libération de la mémoire
imageDestroy($imgThumb);
L'idée étant de le faire après avoir uploadé un fichier, ou dans ton code actuel, vérifier dans ta boucle avec file_exists si la vignette est déjà présente sur le serveur dans le dossier vignettes (elle aura le même nom que ton image grand format).
Si elle n'existe pas, tu la génères et tu n'as alors plus qu'à l'afficher à la place de ton image actuelle (en changeant simplement le nom du dossier dans lequel tu vas la chercher)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 1967 Messages

07 janv. 2021, 09:37

Par contre si tu veux recadrer certaines images, tu n'a pas d'autre moyen que de le faire manuellement. difficile d'avoir un programme qui décide quelle partie d'une image est interessante.
Spols
pour les fan de rubik's cube ou pour les curieux ==> le portail francophone du rubik's cube

Eléphant du PHP | 61 Messages

07 janv. 2021, 13:10

Salut @Ryle !

Merci pour toutes ces informations ! :D

J'ai fait ceci mais il y a une erreur:

Code : Tout sélectionner

$dirOrigine = "img_lieux/"; $dirVignettes = "uploads/"; $fichier = "<?php echo $donnees['lieu_url']; ?>";
Je dois pas quand même faire ca pour chaque image ?
J'ai mis le fichier = url de l'image ou se trouve le fichier mais ca n'a pas l'air de fonctionner ?

@Spols, merci ! Je vais faire ca dans le cas ou je juge que l'image ne donne pas un bon rendu :wink:

PS: qu'est-ce que je dois utiliser pour créer un backend pour faire l'upload des photos et voir meme avoir une administration générale pour la suite du projet ?

Mammouth du PHP | 1967 Messages

07 janv. 2021, 23:54

Code : Tout sélectionner

$dirOrigine = "img_lieux/"; $dirVignettes = "uploads/"; $fichier = "<?php echo $donnees['lieu_url']; ?>";
Tu es dèjà dans des balises php, pas besoin d'en rouvrir ni même de faire un echo
Spols
pour les fan de rubik's cube ou pour les curieux ==> le portail francophone du rubik's cube

Eléphant du PHP | 61 Messages

08 janv. 2021, 12:36

Ohhh yeah super Spols, merci !!!! :D
Alors ca fonctionne mais...
Forcément le mais... :lol:

1. Je ne vois d'images dans mon fichier "vignettes" (ou uploads chez moi).
a. Est-ce que je dois les créer ?
b. Ou ca dit simplement que si une vignette existe dans ce fichier (uploads) alors il va la chercher là bas ?
--> Mais ca insinue que je dois les créer manuellement avec une plus petite résolution et les cadrer éventuellement. On est d'accord ?

2. Pas sur que ca change quelque chose à l'efficacité (normal je suppose si ca ne fonctionne pas :p)

Merci à vous !!!! :wink:

Eléphant du PHP | 61 Messages

11 janv. 2021, 10:59

Hello,
J'ai essayé de créer une image dans /uploads mais il ne la prend pas en considération. *
Vous savez me guider pour essayer de résoudre ce point ? *
Comment on peut vérifier que la page charge plus vite ?
Ici, clairement je crois pas que c'est le cas.
Quand on remonte (re scroll vers le haut) les images rechargent encore alors qu'elles avaient deja été affichées.

Voici le code:

Code : Tout sélectionner

<?php } $dirOrigine = "img_lieux/"; $diruploads = "uploads/"; $fichier = $donnees['lieu_url']; // Dimensions de la vignette en pixels $thumbWidth = 270; $thumbHeight = 302; // Lecture de l'image en supposant que ton image de base soit toujours un JPG // Nota : si tu veux pouvoir utiliser des PNG ou autre, il faut tester le type de l'image et utiliser la fonction adaptée $img = imageCreateFromJpeg($dirOrigine . $fichier); // Détermine les dimensions de l'image d'origine $imgWidth = imagesx($img); $imgHeight = imagesy($img); // Crée la future vignette avec TrueColor si GD2 est disponible, sinon tu peux utiliser ImageCreate() $imgThumb = imageCreateTrueColor($thumbWidth, $thumbHeight); // Redimensionne l'image d'origine, imageCopyResized($imgThumb, $img, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $imgWidth, $imgHeight); // Sauvegarde de l'image dans le dossier uploads imageJpeg($imgThumb, $diruploads . $fichier); // Libération de la mémoire imageDestroy($imgThumb); ?>