web-dev-qa-db-fra.com

Getimagesize ultra rapide en php

J'essaie d'obtenir la taille de l'image (dimensions de l'image, largeur et hauteur) de centaines d'images distantes et getimagesize est beaucoup trop lent.

J'ai fait quelques lectures et j'ai découvert que le moyen le plus rapide serait d'utiliser file_get_contents pour lire une certaine quantité d'octets à partir des images et examiner la taille des données binaires.

Quelqu'un a déjà essayé cela? Comment examiner différents formats? Quelqu'un a vu une bibliothèque pour ça?

40
Sir Lojik
function ranger($url){
    $headers = array(
    "Range: bytes=0-32768"
    );

    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $data = curl_exec($curl);
    curl_close($curl);
    return $data;
}

$start = microtime(true);

$url = "http://news.softpedia.com/images/news2/Debian-Turns-15-2.jpeg";

$raw = ranger($url);
$im = imagecreatefromstring($raw);

$width = imagesx($im);
$height = imagesy($im);

$stop = round(microtime(true) - $start, 5);

echo $width." x ".$height." ({$stop}s)";

tester...

640 x 480 (0,20859 s)

Le chargement de 32 Ko de données a fonctionné pour moi.

91
Dejan Marjanovic

J'ai créé une bibliothèque PHP pour exactement ce scénario, cela fonctionne en téléchargeant le minimum absolu du fichier distant nécessaire pour déterminer la taille du fichier. Ceci est différent pour chaque image et en particulier pour JPEG dépend du nombre de miniatures intégrées dans le fichier.

Il est disponible sur GitHub ici: https://github.com/tommoor/fastimage

Exemple d'utilisation:

$image = new FastImage($uri);
list($width, $height) = $image->getSize();
echo "dimensions: " . $width . "x" . $height;
26
Tom

Je cherchais une meilleure façon de gérer cette situation, j'ai donc utilisé quelques fonctions différentes trouvées sur Internet.

Dans l'ensemble, quand cela fonctionnait, la plus rapide était généralement la fonction getjpegsize que James Relyea avait publiée sur la page PHP pour getimagesize, battant la ranger fonction fournie par Dejan ci-dessus. http://php.net/manual/en/function.getimagesize.php#8879

Image #1 (787KB JPG on external older server)
getimagesize: 0.47042 to 0.47627 - 1700x2340 [SLOWEST]
getjpegsize: 0.11988 to 0.14854 - 1700x2340 [FASTEST]
ranger: 0.1917 to 0.22869 - 1700x2340

Image #2 (3MB PNG)
getimagesize: 0.01436 to 0.01451 - 1508x1780 [FASTEST]
getjpegsize: - failed
ranger: - failed

Image #3 (2.7MB JPG)
getimagesize: 0.00855 to 0.04806 - 3264x2448 [FASTEST]
getjpegsize: - failed
ranger: 0.06222 to 0.06297 - 3264x2448 * [SLOWEST]

Image #4 (1MB JPG)
getimagesize: 0.00245 to 0.00261 - 2031x1434
getjpegsize: 0.00135 to 0.00142 - 2031x1434 [FASTEST]
ranger: 0.0168 to 0.01702 - 2031x1434 [SLOWEST]

Image #5 (316KB JPG)
getimagesize: 0.00152 to 0.00162 - 1280x720
getjpegsize: 0.00092 to 0.00106 - 1280x720 [FASTEST]
ranger: 0.00651 to 0.00674 - 1280x720 [SLOWEST]
  • ranger a échoué lors de la capture de 32 768 octets sur l'image n ° 3, donc je l'ai augmenté à 65 536 et cela a fonctionné pour saisir la taille avec succès.

Il y a cependant des problèmes, car ranger et getjpegsize sont limités de manière à ne pas être suffisamment stable pour être utilisé. Les deux ont échoué lors du traitement d'une grande image JPG autour de 3 Mo, mais ranger fonctionnera après avoir modifié la quantité d'octets récupérés. De plus, ces alternatives ne concernent que les images JPG, ce qui signifie qu'un conditionnel devrait être utilisé pour les utiliser uniquement sur les JPG et getimagesize sur les autres formats d'image.

Notez également que la première image était sur un serveur plus ancien exécutant une ancienne version de PHP 5.3.2, alors que les 4 autres images provenaient d'un serveur moderne (cPanel basé sur le cloud avec MultiPHP rappelé) à 5.4.45 pour la compatibilité).

Il convient de noter que le serveur basé sur le cloud a fait bien mieux avec getimagesize qui a battu ranger, en fait pour les 4 tests sur le serveur cloud, ranger a été le plus lent. Ces 4 tiraient également les images du même serveur que le code était en cours d'exécution, mais à travers des comptes différents.

Cela me fait me demander si le noyau PHP amélioré en 5.4 ou si la version Apache prend en compte. De plus, cela pourrait être dû à la disponibilité du serveur et de la charge du serveur. N'oublions pas comment les réseaux obtiennent de plus en plus vite chaque année, alors peut-être que le problème de vitesse devient moins préoccupant.

Donc, le résultat final et ma réponse est que pour une prise en charge complète de tous les formats d'image Web, et pour toujours atteindre une taille d'image ultra rapide, il pourrait être préférable de le sucer et d'utiliser getimagesize, puis de mettre en cache les tailles d'image (si ces images seront vérifiées plusieurs fois) dans une table de base de données. Dans ce scénario, seule la première vérification entraînera un coût plus élevé, mais les demandes ultérieures seraient minimes et plus rapides que n'importe quelle fonction qui lit les en-têtes d'image.

Comme pour toute mise en cache, cela ne fonctionne bien que si le contenu ne change pas et il existe un moyen de vérifier s'il y a eu un changement. Ainsi, une solution possible consiste à vérifier uniquement les en-têtes d'une URL d'image lors de la vérification du cache et, si elle est différente, à vider la version mise en cache et à la récupérer à nouveau avec getimagesize.

5
Exit