2011-01-08 12 views
37

Estoy tratando de obtener el tamaño de la imagen (dimensiones de la imagen, ancho y alto) de cientos de imágenes remotas y getimagesize es demasiado lento.Super rápido getimagesize en php

He leído un poco y descubrí que la manera más rápida sería usar file_get_contents para leer una cierta cantidad de bytes de las imágenes y examinar el tamaño dentro de los datos binarios.

¿Alguien intentó esto antes? ¿Cómo examinaría diferentes formatos? ¿Alguien ha visto alguna biblioteca para esto?

+4

Probablemente sea lento porque las imágenes son _remote_. Descárguelos primero y 'getimagesize()' será increíblemente rápido. Después de todo, solo lee ciertos bytes binarios de las imágenes. – kijin

+0

por eso quiero usar file_get_contents para 1) No descargar todo el archivo. 2) leer solo ciertos bytes para obtener el tamaño de imagen –

+0

, de hecho puedo usar fopen y fgets para leer solo esos bytes binarios –

Respuesta

86
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)"; 

prueba ...

640 x 480 (0.20859s)

Cargando 32kb de datos trabajó para mí.

+0

acabo de leer este artículo y explica los diferentes y mejores métodos para recuperar el archivo http://www.php-mysql-tutorial.com/wikis/php-tutorial/reading-a-remote-file-using-php.aspx . Paso 2. Cómo diferenciar los diferentes códigos binarios ingresados ​​para obtener el tamaño de la imagen –

+12

No confío en el tutorial php escrito en aspx: P Actualicé mi respuesta, debe tener todo lo que necesita. Si no es así, lo siento, no entiendo completamente tu pregunta. Si quieres compararlo binario, deberías cargarlo completamente en una cadena. –

+0

@webarto Creo que quiere las dimensiones de la imagen, que estarán en los metadatos de la imagen y no en los metadatos del archivo. Tendrá que descargar los bytes iniciales del archivo, pero cuántos dependen del formato de la imagen. – marcog

24

He creado una biblioteca de PHP para exactamente este escenario, funciona descargando el mínimo absoluto del archivo remoto necesario para determinar el tamaño del archivo. Esto es diferente para cada imagen y particularmente para JPEG depende de cuántas miniaturas incrustadas hay en el archivo.

Está disponible en GitHub aquí: el uso https://github.com/tommoor/fastimage

Ejemplo:

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

Esto funciona para mí más lenta getimagesize thant desde PHP: Fast Image: 0.079681873321533s tamaño getimage Nativo: 0.023485898971558s Raeger (webarto ejemplo): 0.16773s – catalinux

+0

Estaría muy interesado si es reproducible más lento, ¿cuántas veces ejecutas la prueba? Puede verificar el código fuente: normalmente se necesita descargar menos de 1kb de la imagen. – Tom

+0

me gusta mucho esta clase. sin embargo, estás usando fopen. por lo que tarda mucho tiempo en ralentizar la solicitud remota de respuesta con el servidor de sobrecarga. ¿Por qué no usas CURL en su lugar? Y algunos sitios web necesitan falsificar el encabezado (http_referer) para recuperar las dimensiones de la imagen. Entonces CURL es mejor. – TomSawyer

2

que estaba buscando una mejor manera de manejar esta situación, por lo que utiliza un par de funciones diferentes que se encuentran alrededor de la Internet.

En general, cuando funcionaba, el más rápido tendido a ser la función getjpegsize que James Relyea publicada en la página PHP para getimagesize, superando a la función ranger proporcionada por Dejan anteriormente. http://php.net/manual/en/function.getimagesize.php#88793

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 fallaron cuando se agarra 32768 bytes en la imagen # 3, por lo que aumentar la cantidad hasta 65536 y funcionó para agarrar el tamaño éxito.

hay problemas, sin embargo, ya que ambos ranger y getjpegsize se limitan de manera que lo hacen no lo suficientemente estable como para su uso. Ambos fallaron cuando se trataba de una imagen JPG grande de alrededor de 3 MB, pero ranger funcionará después de cambiar la cantidad de bytes que capta. Además, estas alternativas solo se ocupan de las imágenes JPG, lo que significa que se debe usar un condicional solo para usarlas en JPG y getimagesize en los otros formatos de imagen.

Además, tenga en cuenta que la primera imagen estaba en un servidor anterior ejecutando una versión anterior de PHP 5.3.2, mientras que las otras 4 imágenes provenían de un servidor moderno (cPanel basado en la nube con MultiPHP marcado de nuevo en 5.4.45 para compatibilidad).

Vale la pena señalar que el servidor basado en la nube hizo mucho mejor con lo que superó a getimagesizeranger, de hecho, para las 4 pruebas en el servidor de la nube, ranger fue el más lento. Esos 4 también estaban sacando las imágenes del mismo servidor que el código se estaba ejecutando, aunque diferentes cuentas.

Esto me hace preguntarme si el núcleo de PHP mejoró en 5.4 o si la versión de Apache tiene en cuenta. Además, podría deberse a la disponibilidad del servidor y la carga del servidor.No olvidemos que las redes cada vez son más y más rápidas cada año, por lo que quizás el problema de la velocidad sea cada vez menos preocupante.

Por lo tanto, el resultado final y mi respuesta es que para soporte completo para todos los formatos de imagen web, y aún así lograr un tamaño de imagen superrápido, sería mejor aspirar y usar getimagesize y luego almacenar en caché los tamaños de imagen (si estas imágenes serán revisadas más de una vez) en una tabla de base de datos. En ese escenario, solo el primer cheque tendrá un costo mayor, pero las solicitudes posteriores serán mínimas y más rápidas que cualquier función que lea los encabezados de las imágenes.

Al igual que con cualquier almacenamiento en caché, solo funciona bien si el contenido no cambia y hay una forma de comprobar si ha habido algún cambio. Por lo tanto, una posible solución es verificar solo los encabezados de una URL de imagen al verificar la memoria caché, y si es diferente, volcar la versión en caché y volver a capturarla con getimagesize.