*/ namespace ImageHeberg; use Imagick; use ImagickException; /** * Bibliothèque d'outils pour la gestion des images */ abstract class HelperImage { /** * Type de l'image * @param string $path chemin sur le filesystem * @return false|int */ public static function getType(string $path): bool|int { return exif_imagetype($path); } /** * MIME type de l'image * @param string $path chemin sur le filesystem * @return string */ public static function getMimeType(string $path): string { return image_type_to_mime_type(self::getType($path)); } /** * Chargement ressource PHP image * @param string $path * @return Imagick * @throws ImagickException */ public static function getImage(string $path): Imagick { $monImage = new Imagick(); $monImage->readImage($path); // Pour les images animeés (GIF), générer une image pour chaque frame la composant if (self::getType($path) === IMAGETYPE_GIF) { $monImage = $monImage->coalesceImages(); } return $monImage; } /** * Enregistrement d'une ressource PHP image * @param Imagick $uneImage Image à enregistrer * @param int $imageType type PHP de l'image * @param string $path chemin du fichier * @return bool Succès ? * @throws ImagickException */ public static function setImage(Imagick $uneImage, int $imageType, string $path): bool { $monRetour = false; // Image animée (GIF) if ($imageType === IMAGETYPE_GIF) { $uneImage->setInterlaceScheme(Imagick::INTERLACE_GIF); // Pour la génération du GIF, on ne veut que les différences entre les images $uneImage = $uneImage->deconstructImages(); // Suppression des commentaires & co $uneImage->stripImage(); // Enregistrement de l'ensemble des images $monRetour = $uneImage->writeImages($path, true); } else { // Image non animée if ($imageType === IMAGETYPE_JPEG) { $uneImage->setInterlaceScheme(Imagick::INTERLACE_JPEG); // Pas de destruction de l'image $uneImage->setImageCompression(Imagick::COMPRESSION_JPEG); $uneImage->setImageCompressionQuality(100); } elseif ($imageType === IMAGETYPE_PNG) { $uneImage->setInterlaceScheme(Imagick::INTERLACE_PNG); $uneImage->setImageCompression(Imagick::COMPRESSION_LZW); $uneImage->setImageCompressionQuality(9); } elseif ($imageType === IMAGETYPE_WEBP) { $uneImage->setImageFormat('webp'); $uneImage->setImageCompression(Imagick::COMPRESSION_LZW); $uneImage->setImageCompressionQuality(100); } // Suppression des commentaires & co $uneImage->stripImage(); $monRetour = $uneImage->writeImage($path); } return $monRetour; } /** * Fourni l'extension officielle d'une ressource * @param string $path chemin sur le filesystem * @return string */ public static function getExtension(string $path): string { $ext = strtolower(image_type_to_extension(self::getType($path), false)); if ($ext === 'jpeg') { // Préférence pour .jpg [filename.ext] $ext = 'jpg'; } return $ext; } /** * Est-il possible de modifier l'image (mémoire suffisante ?) * @param string $path * @return bool Possible ? * @see http://www.dotsamazing.com/en/labs/phpmemorylimit */ public static function isModifiableEnMemoire(string $path): bool { $monRetour = false; // Nombre de canaux d'information de l'image $nbCanaux = 4; /** * Information sur les canaux ? */ $imageinfo = getimagesize($path); // Si information sur les canaux de l'image... if (isset($imageinfo['channels']) && is_int($imageinfo['channels'])) { $nbCanaux = $imageinfo['channels']; } /** * Mémoire requise : * (hauteur x largeur x profondeur) * => x 2 [imageSource + imageDest] * => x 1.8 [fudge factor] */ $memReq = $imageinfo[1] * $imageinfo[0] * $nbCanaux; $memReq *= 2; $memReq *= _FUDGE_FACTOR_; // Est-ce possible ? if ($memReq < HelperSysteme::getMemoireAllouee()) { $monRetour = true; } return $monRetour; } /** * Dimension maximale acceptable en mémoire pour les images *
Suppose que l'image est carrée (donc indicatif !) *
Suppose 4 canaux dans l'image * @return int * @see isModifiableEnMemoire */ public static function getMaxDimension(): int { $memDispo = HelperSysteme::getMemoireAllouee(); /** * Mémoire requise : * (hauteur x largeur x profondeur) * => x 2 [imageSource + imageDest] * => x 1.8 [fudge factor] */ $dimMax = round(sqrt($memDispo / 4 / 2 / _FUDGE_FACTOR_)); return (int)$dimMax; } /** * Est-ce une image WEBP animée ? * @param string $path fichier à tester * @return bool */ public static function isAnimatedWebp(string $path): bool { $monRetour = false; // "Note that animated WebP files cannot be read." // https://www.php.net/manual/en/function.imagecreatefromwebp.php if (self::getType($path) === IMAGETYPE_WEBP) { // "An animation is controlled by 'ANIM' and 'ANMF' Chunks." // https://developers.google.com/speed/webp/docs/riff_container?hl=en $headerFile = file_get_contents($path, false, null, 0, 100); if (stripos($headerFile, 'ANIM') !== false || stripos($headerFile, 'ANMF') !== false) { $monRetour = true; } } return $monRetour; } }