web-dev-qa-db-ja.com

PHPの超高速getimagesize

何百ものリモートイメージのイメージサイズ(イメージの寸法、幅、高さ)を取得しようとしていますが、 getimagesize が遅すぎます。

私はいくつかの読書をしましたが、最も速い方法は file_get_contents 画像から一定量のバイトを読み取り、バイナリデータ内のサイズを調べます。

誰もこれを前に試みましたか?さまざまな形式をどのように調べますか?誰もこれのライブラリを見ましたか?

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

テスト...

640 x 480(0.20859s)

32kbのデータの読み込みがうまくいきました。

91

私はPHPこのシナリオのためのライブラリを作成しました。ファイルサイズを決定するために必要なリモートファイルの絶対最小値をダウンロードすることで動作します。これはすべての画像および特にJPEGの場合、ファイルに埋め込まれたサムネイルの数に依存します。

GitHubで入手できます: https://github.com/tommoor/fastimage

使用例:

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

この状況に対処するためのより良い方法を探していたので、インターネットで見つかったいくつかの異なる機能を使用しました。

全体として、動作したとき、最も高速なのは、James Relyeaがgetjpegsize関数を破って、PHP getimagesizeのページに投稿した)ranger関数である傾向がありました。上記のDejan提供 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は、イメージ#3で32768バイトを取得するときに失敗したため、65536に増やして、サイズを正常に取得するようにしました。

ただし、rangergetjpegsizeの両方が、使用するのに十分なほど安定しないように制限されているため、問題があります。 3MB前後の大きなJPGイメージを処理する場合は両方とも失敗しましたが、rangerは取得するバイト数を変更した後に機能します。また、これらの代替はJPG画像のみを処理します。つまり、それらをJPGおよび他の画像形式でgetimagesizeでのみ使用するには、条件を使用する必要があります。

また、最初のイメージは、古いバージョンのPHP 5.3.2を実行している古いサーバー上にあり、他の4つのイメージは最新のサーバー(MultiPHPを使用したクラウドベースのcPanel互換性のために5.4.45に)。

クラウドベースのサーバーがgetimagesizeではるかに優れていたことは注目に値する。ranger。実際、クラウドサーバーでの4つのテストすべてで、rangerが最も遅い。これら4人は、異なるアカウントであるにもかかわらず、コードが実行されているのと同じサーバーからイメージをプルしていました。

これにより、5.4でPHPコアが改善されたのか、Apacheバージョンが考慮に入れられたのか疑問に思います。また、サーバーとサーバーの負荷からの可用性が低下する可能性があります。毎年ますます速くなっているので、おそらく速度の問題はそれほど懸念されなくなっています。

したがって、最終結果と私の答えは、すべてのウェブ画像フォーマットを完全にサポートし、それでも超高速画像サイズを実現するには、それを吸い込んでgetimagesizeを使用し、画像サイズをキャッシュすることです(これらの画像が複数回チェックされる場合)データベーステーブルで。そのシナリオでは、最初のチェックのみに大きなコストがかかりますが、その後のリクエストは、画像ヘッダーを読み取る関数よりも最小限で高速です。

キャッシュと同様に、コンテンツが変更されない場合にのみ機能し、変更があったかどうかを確認する方法があります。したがって、可能な解決策は、キャッシュをチェックするときに画像URLのヘッダーのみをチェックし、異なる場合は、キャッシュされたバージョンをダンプし、getimagesizeで再度取得することです。

5
Exit