Retour sur le Forum PHP 2024
Découvrez un résumé concis des conférences qui nous ont le plus marqué lors du Forum PHP 2024 !
L’optimisation d’images est un enjeu très important dans la conception d’une application web et nécessite une attention particulière. Durant le développement d’un jeu en ligne impliquant une gestion importante d’images, nous avons été amenés à les optimiser pour différents devices (desktop et mobile). La suite de cet article sera dédiée à expliquer notre démarche en créant une version simplifiée que vous retrouverez ici.
Notre projet est un jeu dont le but est de placer des objets (par drag and drop en Javascript) dans une pièce. Les données à manipuler essentiellement sont :
.
L'objectif à atteindre :
Cette section sera subdivisée en deux grandes parties :
Dans cette partie, on parlera brièvement de la mise en place de la bibliothèque Imagine, et de nos classes (room et furniture).
Nous utilisons la librairie Imagine parce qu'elle permet notamment :
$ composer require imagine/imagine
Définissons nos pièces.
<?php
namespace AppBundle\Entity;
class Room
{
...
/** @var string */
private $imageUrl;
/** @var float */
private $scale;
...
}
Voici un preview de nos objets :
<?php
namespace AppBundle\Entity;
class Furniture
{
...
/** @var string */
private $imageUrl;
/** @var float */
private $height;
/** @var Room[] */
private $rooms;
...
}
Optimiser, dans notre cas, cela implique de :
A quoi servent les tailles de destination ? Elles permettent de définir les tailles idéales que doivent avoir nos images. Dans notre projet, nous avons défini deux tailles basées sur la taille maximale de chaque pièce sur mobile, et sur desktop.
Nous reflétons nos tailles dans le fichier de configuration config.yml.
parameters: format_size: ld: size: 600 quality: 90 hd: size: 1200 quality: 75
Pour optimiser, il faut déterminer une méthode qui permettrait de réduire la taille des images (pièces et objets) sans pour autant en perdre la qualité.
Pour toutes nos images, nous utiliserons les méthodes open
, resize
et save
d'Imagine pour les traitements.
Les pièces
Elles sont censées recouvrir la quasi totalité de l'écran donc nous leur appliquons les tailles maximales LD et HD tout en gardant les proportions des images.
Ex : Pour une image WIDTHxHEIGHT: 3000x1687
de 14Mo ca donnera en :
600x336
, soit à peu près 592 ko1200x672
, soit environ 2 Mo<?php
...
/**
* Execute resize.
*
* @param Room $object
* @param string $fullInputfile
* @param string $relativeOutputFilePath
* @param string $fullOutputFilePath
* @param int $size
* @param int $quality
*
* @return string
*/
protected function execute(
$object,
$fullInputfile,
$relativeOutputFilePath,
$fullOutputFilePath,
$size,
$quality
): string {
//On récupère la taille de l'image d'origine
list($width, $height) = getimagesize($fullInputfile);
//On calcule le ratio pour toujours garder la même proportion
$ratio = $height / $width;
$newWidth = $size;
//Ne pas agrandir l'image si elle est déjà assez petite
if ($width < $newWidth) {
$newWidth = $width;
}
//Calcul de la nouvelle taille de l'image
$newHeight = ceil($newWidth * $ratio);
$this->createFileDirectory($fullOutputFilePath);
//Enregistrons tout ça
$box = new Box($newWidth, $newHeight);
$this->imagine->open($fullInputfile)
->resize($box)
->save($fullOutputFilePath, ['jpeg_quality' => $quality]);
return $relativeOutputFilePath;
}
...
Les objets
Pour les objets, la méthode de calcul est un peu différente. On ne peut pas leur appliquer une taille par défaut comme pour les pièces. En effet ils n'ont pas tous la même taille (On ne peut pas redimensionner une table et un écran de la même manière)!
.
Nous avons décidé de calculer la taille maximale des images de nos objets lorsqu'elles sont au maximum zoomées dans les pièces.
Pour ce faire il fallait se baser sur trois éléments :
LONG_PIECE_EN_PX = LARG_PIECE_EN_PX * 0.75
.HAUTEUR_REEL_OBJET_EN_METRE = HAUTEUR_REEL_OBJET_EN_CM * 0.01
.Par une petite règle de trois, nous obtenons :
LONG_PIECE_EN_PX -> HAUTEUR_PIECE_EN_METRE
LONG_OBJET_EN_PX(?) -> HAUTEUR_REEL_OBJET_EN_METRE
LONG_OBJET_EN_PX = (HAUTEUR_REEL_OBJET_EN_METRE * LONG_PIECE_EN_PX) / HAUTEUR_PIECE_EN_METRE
Le code correspondant est :
<?php
...
/**
* Execute resize
*
* @param Furniture $object
* @param $fullInputfile
* @param $relativeOutputFilePath
* @param $fullOutputFilePath
* @param $size
* @param $quality
*
* @return string
*/
public function execute(
$object,
$fullInputfile,
$relativeOutputFilePath,
$fullOutputFilePath,
$size,
$quality
): string {
list($width, $height) = getimagesize($fullInputfile);
$ratio = $width / $height;
$newHeight = ($object->getHeight() * 0.01) * ($size * 0.75) / 2.30;
if ($newHeight > $height) {
$newHeight = $height;
}
$newWidth = floor($newHeight * $ratio);
$this->createFileDirectory($fullOutputFilePath);
$box = new Box($newWidth, $newHeight);
$this->imagine->open($fullInputfile)
->resize($box)
->save($fullOutputFilePath, [
'png_compression_level' => floor($quality * 9 / 100)
]);
return $relativeOutputFilePath;
}
...
Pour résoudre notre problème, nous avons :
Auteur(s)
Shalom KPOTOGBEY
Lifelong learner, je suis passionné par les technologies web et mobile, je pratique essentiellement du PHP (SYMFONY) et MOBILE(android)
Vous souhaitez en savoir plus sur le sujet ?
Organisons un échange !
Notre équipe d'experts répond à toutes vos questions.
Nous contacterDécouvrez nos autres contenus dans le même thème
Découvrez un résumé concis des conférences qui nous ont le plus marqué lors du Forum PHP 2024 !
Le composant Symfony ExpressionLanguage : qu'est-ce que c'est ? Quand et comment l'utiliser ? Comment créer des expressions lors de cas plus complexes ?
Découvrez comment réaliser du typage générique en PHP : introduction et définition du concept, conseils et explications pas-à-pas de cas pratique.