【问题标题】:Super fast getimagesize in phpphp中的超快速getimagesize
【发布时间】:2011-06-05 21:01:21
【问题描述】:

我正在尝试获取数百个远程图像的图像大小(图像尺寸、宽度和高度),getimagesize 太慢了。

我做了一些阅读,发现最快的方法是使用file_get_contents 从图像中读取一定数量的字节并检查二进制数据中的大小。

以前有人尝试过吗?我将如何检查不同的格式?有人看过这方面的图书馆吗?

【问题讨论】:

  • 这可能很慢,因为图像是远程。首先下载它们,getimagesize() 将会非常快。毕竟,它只从图像中读取某些二进制字节。
  • 这就是为什么我想使用 file_get_contents 来 1) 不下载整个文件。 2)只读取某些字节来获取图像大小
  • 实际上我 cud 使用 fopen 和 fgets 来读取那些二进制字节
  • 远程站点不提供Content-Length 标头吗?
  • 如果 getimagesize() 下载的文件比需要的多得多,我会感到惊讶。

标签: php image http getimagesize


【解决方案1】:

我一直在寻找一种更好的方法来处理这种情况,所以我使用了一些在互联网上找到的不同功能。

总的来说,当它起作用时,最快的往往是 James Relyea 在 PHP 页面上为 getimagesize 发布的 getjpegsize 函数,击败了上面 Dejan 提供的 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 在 Image #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 个人也在代码运行时从同一服务器提取图像,但帐户不同。

这让我想知道 PHP 核心是否在 5.4 中得到了改进,或者 Apache 版本是否有所改进。此外,这可能取决于服务器和服务器负载的可用性。我们不要忘记网络每年都在变得越来越快,因此速度问题可能正在变得不那么令人担忧。

所以,最终结果和我的回答是,为了完全支持所有 Web 图像格式,并且仍要实现超快的图像大小,最好将其吸收并使用 getimagesize,然后缓存图像大小(如果将多次检查这些图像)在数据库表中。在这种情况下,只有第一次检查会产生更大的成本,但随后的请求将比读取图像标题的任何函数最小且更快。

与任何缓存一样,它只有在内容没有发生变化并且有办法检查是否发生变化时才能正常工作。因此,一种可能的解决方案是在检查缓存时仅检查图像 URL 的标头,如果不同,则转储缓存版本并使用 getimagesize 再次获取它。

【讨论】:

    【解决方案2】:

    我已经为这个场景创建了一个 PHP 库,它通过下载确定文件大小所需的远程文件的绝对最小值来工作。这每个图像都不同,尤其是对于 JPEG,取决于文件中有多少嵌入的缩略图。

    它可以在 GitHub 上找到:https://github.com/tommoor/fastimage

    示例用法:

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

    【讨论】:

    • 这对我来说比 PHP 的 getimagesize 慢:Fast Image:0.079681873321533s Native getimage size: 0.023485898971558s Raeger (webarto example): 0.16773s
    • 我会非常感兴趣,如果它是可重现的慢,你运行了多少次测试?您可以查看源代码 - 通常需要下载 1kb 以下的图像。
    • 我真的很喜欢这门课。但是您使用的是 fopen。因此,您需要很长时间才能通过超载服务器来减慢响应远程请求的速度。你为什么不改用 CURL 呢?有些网站需要伪造标题(http_referer)来检索图像尺寸。所以 CURL 更好。
    • 如果我想要以字节为单位的文件大小怎么办?
    • @codecowboy 对本地或 HTTP HEAD 请求使用 filesize(),对远程使用 content-length 标头
    【解决方案3】:
    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 的数据对我有用。

    【讨论】:

    • 阅读这篇文章,它解释了检索文件php-mysql-tutorial.com/wikis/php-tutorial/… 的不同和最佳方法。步骤 2. 如何区分拉入的不同二进制代码以获得图像大小
    • 我不相信用 aspx 编写的 php 教程:P 我更新了我的答案,你应该有你需要的一切。如果不是这样,那么对不起,我不完全理解你的问题。如果你想比较它是二进制的,你必须把它完全加载到一个字符串中。
    • @webarto 我认为他想要图像尺寸,这将在图像元数据而不是文件元数据中。他必须下载文件的初始字节,但具体多少取决于图像格式。
    • 顺便说一句,我应该指定,我正在寻找图像尺寸。让我编辑
    • 使用 range 参数时,我在处理较大的 PNG 时遇到了问题。我的情况最好的方法是增强 API,不仅可以获取图像 URL,还可以获取大小或方向。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 2013-07-10
    相关资源
    最近更新 更多