代码之家  ›  专栏  ›  技术社区  ›  fire

从外部链接选择缩略图

  •  3
  • fire  · 技术社区  · 15 年前

    我正在尝试构建一个脚本,从外部链接中检索缩略图列表,就像Facebook在共享链接时所做的那样,并且可以选择与该文章相关联的缩略图。

    我的脚本当前的工作方式如下:

    • file_get_contents 在URL上
    • preg_match_all 匹配任何 <img src="" 内容中
    • 计算出每个图像的完整URL并将其存储在数组中
    • 如果有10个图像,则循环使用 getimagesize 查找宽度和高度
    • 如果有10幅图像,则循环使用 fread imagecreatefromstring 找出宽度和高度(速度)
    • 一旦计算出所有的宽度和高度,它就会循环并只将图像添加到具有最小宽度和高度的新数组中(因此只显示较大的图像,较小的图像就不太可能描述URL)。
    • 每个图像都有自己的新尺寸计算出来(按比例缩小)并返回…

    <img src="'.$image[0].'" width="'.$image[1].'" height="'.$image[2].'"><br><br>

    目前这很好,但我可能会遇到一些问题:

    1. 速度!如果URL在页面上有许多图像,则需要花费相当长的时间来处理。
    2. 记忆!使用 地理计量 弗雷德 和; 图像创建自字符串 将整个图像存储在内存中,页面上的任何大图像都会占用服务器的内存并杀死我的脚本(和服务器)

    我发现的一个解决方案是,不需要下载整个图像就可以从图像的头端检索图像的宽度和高度,尽管我只找到了一些代码来为JPG(它需要支持GIF&PNG)执行此操作。

    有人能提出任何建议来帮助我解决上面提到的任何问题吗,或者你可以提出另一种方法来解决这个问题,我愿意接受这些想法…谢谢!

    **编辑:代码如下:

    // Example images array
    $images = array('http://blah.com/1.jpg', 'http://blah.com/2.jpg');
    
    // Find the image sizes
    $image_sizes = $this->image_sizes($images);
    
    // Find the images that meet the minimum size
    for ($i = 0; $i < count($image_sizes); $i++) {
        if ($image_sizes[$i][0] >= $min || $image_sizes[$i][1] >= $min) {                
            // Scale down the original image size
            $dimensions = $this->resize_dimensions($scale_width, $scale_height, $image_sizes[$i][0], $image_sizes[$i][1]);
            $img[] = array($images[$i], $dimensions['width'], $dimensions['height']);
        }
    }
    
    // Output the images
    foreach ($img as $image) echo '<img src="'.$image[0].'" width="'.$image[1].'" height="'.$image[2].'"><br><br>';
    
    /**
     * Retrieves the image sizes
     * Uses the getimagesize() function or the filesystem for speed increases
     */
    public function image_sizes($images) {
        $out = array();
        if (count($images) < 10) {
            foreach ($images as $image) {
                list($width, $height) = @getimagesize($image);
                if (is_numeric($width) && is_numeric($height)) {
                    $out[] = array($width, $height);
                }
                else {
                    $out[] = array(0, 0);
                }
            }
        }
        else {
            foreach ($images as $image) {
                $handle = @fopen($image, "rb");
                $contents = "";
                if ($handle) {
                    while(true) {
                        $data = fread($handle, 8192);
                        if (strlen($data) == 0) break;
                        $contents .= $data;
                    }
                    fclose($handle);
                    $im = @imagecreatefromstring($contents);
                    if ($im) {
                        $out[] = array(imagesx($im), imagesy($im));
                    }
                    else {
                        $out[] = array(0, 0);
                    }
                    @imagedestroy($im);
                }
                else {
                    $out[] = array(0, 0);
                }
            }
        }
        return $out;
    }
    
    /**
     * Calculates restricted dimensions with a maximum of $goal_width by $goal_height 
     */
    public function resize_dimensions($goal_width, $goal_height, $width, $height) {
        $return = array('width' => $width, 'height' => $height);
    
        // If the ratio > goal ratio and the width > goal width resize down to goal width
        if ($width/$height > $goal_width/$goal_height && $width > $goal_width) {
            $return['width'] = floor($goal_width);
            $return['height'] = floor($goal_width/$width * $height);
        }
    
        // Otherwise, if the height > goal, resize down to goal height
        else if ($height > $goal_height) {
            $return['width'] = floor($goal_height/$height * $width);
            $return['height'] = floor($goal_height);
        }   
        return $return;
    }
    
    2 回复  |  直到 12 年前
        1
  •  1
  •   poiuyttr    15 年前

    GetImageSize只读取头,但ImageCreateFromString读取整个图像。由gd、imagemagick或graphicsmagic读取的图像存储为位图,因此它消耗宽度 高度 (3或4)字节,您对此无能为力。 对于您的问题,最好的解决方案是发出curl multi请求(请参见 http://ru.php.net/manual/en/function.curl-multi-select.php ,然后一个接一个进程使用gd或任何其他库接收图像。为了降低内存消耗,您可以将图像文件存储在磁盘上,而不是内存中。

        2
  •  0
  •   nortron    15 年前

    对于您当前的方法(令人印象深刻),唯一想到的是检查HTML中现有的宽度和高度属性,如果它们存在,则跳过文件读取过程。