2011-01-08 2 views
37

Я пытаюсь получить размер изображения (размеры, ширина и высота изображения) сотен удаленных изображений и getimagesize слишком медленный.Супер быстрый getimagesize в php

Я проделал некоторое чтение и выяснил, что самый быстрый способ - использовать file_get_contents для чтения определенного количества байтов из изображений и изучения размера в двоичных данных.

Кто-нибудь пытался это сделать раньше? Как я могу изучить разные форматы? Кто-нибудь видел какую-нибудь библиотеку для этого?

+4

Это, вероятно, медленно, потому что изображения _remote_. Сначала загрузите их, и 'getimagesize()' будет быстро разгоняться. В конце концов, он только считывает определенные бинарные байты из изображений. – kijin

+0

Вот почему я хочу использовать file_get_contents для 1) Не загружать весь файл. 2) читать только определенные байты для получения размера изображения –

+0

на самом деле я cud использовать fopen и fgets читать только эти двоичные байты –

ответ

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

тест ...

640 x 480 (0.20859s)

Загрузка 32кб данных работает для меня.

+0

просто прочитайте эту статью и объясните различные и лучшие методы извлечения файла http://www.php-mysql-tutorial.com/wikis/php-tutorial/reading-a-remote-file-using-php.aspx , Шаг 2. Как различить различный двоичный код, втянутый, чтобы получить размер изображения. –

+12

Я бы не доверял учебнику php, написанному в aspx: P Я обновил свой ответ, у вас должно быть все, что вам нужно. Если это не так, извините, я не совсем понимаю ваш вопрос. Если вы хотите сравнить его с бинарным, вам придется полностью загрузить его в строку. –

+0

@webarto Я думаю, он хочет размеры изображения, которые будут в метаданных изображения, а не метаданных файла. Он должен будет загрузить начальные байты файла, но сколько зависит от формата изображения. – marcog

24

Я создал библиотеку PHP именно для этого сценария, она работает путем загрузки абсолютного минимума удаленного файла, необходимого для определения размера файла. Это разных для каждого изображения и особенно для JPEG зависит от того, сколько встроенных миниатюр в файле.

Он доступен на GitHub здесь: использование https://github.com/tommoor/fastimage

Пример:

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

Это работает для меня медленный Тана getimagesize из PHP: Fast Image: 0.079681873321533s Native размер GetImage: 0.023485898971558s Raeger (webarto пример): 0.16773s – catalinux

+0

Я был бы очень интересно, если это воспроизводимо медленнее, сколько раз вы запускаете тест? Вы можете проверить исходный код - как правило, менее 1 килобайта изображения необходимо загрузить. – Tom

+0

Мне очень нравится этот класс. однако вы используете fopen. так что вам нужно очень долго, чтобы замедлить ответ удаленного запроса с сервером перегрузки. почему бы вам не использовать CURL? И некоторым веб-сайтам нужно подделать заголовок (http_referer) для извлечения размеров изображения. Так что CURL лучше. – TomSawyer

2

Я искал лучший способ справиться с этой ситуацией, так что я использовал несколько различных функций, найденные по всему Интернету.

В целом, когда он работал, самый быстрый, как правило, функции getjpegsize что Джеймс Релайея размещен на странице PHP для getimagesize, побив функцию ranger представленную выше Деян. 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 потерпели неудачу, когда захват 32768 байт на изображение # 3, так что я его увеличить до 65536, и она работала, чтобы успешно захватить размер.

Есть проблемы, хотя, как и ranger и getjpegsize ограничены таким образом, чтобы сделать его не достаточно стабильна для использования. Оба отказались при работе с большим JPG-изображением вокруг 3 МБ, но ranger будет работать после изменения количества байтов, которое он захватывает. Кроме того, эти альтернативы имеют дело только с изображениями JPG, а это означает, что условное значение должно использоваться только для использования в JPG и getimagesize в других форматах изображений.

Кроме того, обратите внимание, что первое изображение было на более старом сервере, на котором установлена ​​старая версия PHP 5.3.2, где 4 других изображения были получены с современного сервера (cPanel на основе облачных вычислений с MultiPHP набрал номер 5.4.45 для совместимость).

Стоит отметить, что на основе сервера облако сделал гораздо лучше с getimagesize, которые выбивают ranger, на самом деле для всех 4 тестов на облачном сервере, ranger был самым медленным. Эти 4 также тянули изображения с того же сервера, что и код, но разные учетные записи.

Это заставляет меня задаться вопросом, улучшилось ли ядро ​​PHP в 5.4 или если факторы версии Apache включены. Кроме того, это может быть связано с недоступностью сервера и загрузки сервера.Давайте не будем забывать, как сети становятся все быстрее и быстрее с каждым годом, поэтому, возможно, проблема скорости становится менее опасной.

Итак, конечный результат и мой ответ заключается в том, что для полной поддержки всех форматов веб-изображений и для достижения сверхбыстрого размера изображения может быть лучше всего сосать его и использовать getimagesize, а затем кешировать размеры изображений (если эти изображения будут проверяться более одного раза) в таблице базы данных. В этом случае только первая проверка потребует больших затрат, но последующие запросы будут минимальными и более быстрыми, чем любая функция, которая читает заголовки изображений.

Как и при любом кешировании, он работает только хорошо, если содержимое не изменяется и есть способ проверить, было ли изменение. Таким образом, возможным решением является проверка только заголовков URL-адреса изображения при проверке кеша, а если они разные, выкиньте кешированную версию и снова возьмите ее с помощью getimagesize.