Php 调整图像大小并将其裁剪成白色背景的正方形-使用GD

Php 调整图像大小并将其裁剪成白色背景的正方形-使用GD,php,caching,thumbnails,gdlib,Php,Caching,Thumbnails,Gdlib,我有一个脚本,可以缓存来自外部提要的图像,并在站点上查看图像时将其存储在服务器上的目录中 目前,它工作得很好——将原始图像存储在我的服务器上,还创建了两个额外的缩略图,它们的宽度重新调整为300px和150px 我想对此稍作更改,以便发生以下情况: 完整/原始映像存储在服务器上(正常情况下) 将创建一个正方形300x300px和150x150px.jpg缩略图 但是,是否有可能在调整图像宽度/高度后,添加额外的画布宽度/高度,使其完全成正方形?我想这里的一个问题是首先确定图像是“肖像”还是“风景

我有一个脚本,可以缓存来自外部提要的图像,并在站点上查看图像时将其存储在服务器上的目录中

目前,它工作得很好——将原始图像存储在我的服务器上,还创建了两个额外的缩略图,它们的宽度重新调整为300px和150px

我想对此稍作更改,以便发生以下情况:

  • 完整/原始映像存储在服务器上(正常情况下)
  • 将创建一个正方形300x300px和150x150px.jpg缩略图
  • 但是,是否有可能在调整图像宽度/高度后,添加额外的画布宽度/高度,使其完全成正方形?我想这里的一个问题是首先确定图像是“肖像”还是“风景”

    此外,目前我得到了一个透明的PNG图像黑色背景。有没有办法克服这个问题,用白色来填充背景

    非常感谢您的帮助!!:)

    下面是进行大小调整的代码(imageCache.php):

    <?php
      function cacheFetch($url,$size,$age)
      {
    // directory in which to store cached files, must be writable by PHP
    $cacheDir = "cache/";
    // cache filename constructed from MD5 hash of URL
    $filename = $cacheDir.md5($url);
    // append size to filename if not 0
    if ($size) $filename .= "_".$size;
    // default to fetch the file
    $fetch = true;
    // but if the file exists, don't fetch if it is recent enough
    if (file_exists($filename))
    {
      $fetch = (filemtime($filename) < (time()-$age));
    }
    // fetch the file if required
    if ($fetch)
    {
      if (substr($url,0,4)=="http")
      {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
        $data = curl_exec($ch);
        curl_close($ch);
        if (strlen($data))
        {
          $fp = fopen($filename,"w");
          fwrite($fp,$data);
          fclose($fp);
          $error = false;
        }
        else
        {
          $error = true;
        }
      }
      else
      {
        copy($url,$filename);
        $error = false;
      }
    }
    // return the filename only if wget did not fail
    if (!$error)
    {
      if ($size)
      {
        $src = file_get_contents($filename);
        $oldImage = imagecreatefromstring($src);
        $oldX = imagesx($oldImage);
        $oldY = imagesy($oldImage);
        if ($oldX && $oldY)
        {
          $newX = $size;
          $xFactor = ($newX / $oldX);
          $newY = intval($oldY * $xFactor);
          $newImage = imagecreatetruecolor($newX,$newY);
          imagecopyresized($newImage, $oldImage, 0,0,0,0, $newX, $newY, $oldX, $oldY);
          imagejpeg($newImage,$filename);
        }
      }
      return $filename;
    }
    else
    {
      // as an error occured, delete the empty file so it is retried next time
      unlink($filename);
      // return false
      return false;
    }
    }
    require("includes/common.php");
    
    $id = $_GET["id"];
    
    $size = $_GET["size"];
    
    $sql = "SELECT image_url FROM `".$config_databaseTablePrefix."products` WHERE id='".database_safe($id)."'";
    if (database_querySelect($sql,$rows))
    {
    $src = $rows[0]["image_url"];
    
    $src = cacheFetch($src,$size,604800);
    
    $img = file_get_contents($src);
    
    header("Content-Type: image");
    
    print $img;
      }
    ?>
    

    编辑:重新工作的代码:

    if ($size)
    {
        $src = file_get_contents($filename);
        $oldImage = imagecreatefromstring($src);
        $oldX = imagesx($oldImage);
        $oldY = imagesy($oldImage);
        if ($oldX && $oldY)
        {
          $color = imagecolorallocate($newImage, 255,255,255);  //The three parameters are R,G,B
      imagefilledrectangle ($newImage, 0, 0, $newX,  $newY,$color);
          $size = max($newX,$newY);
          $newImage = imagecreatetruecolor($newX,$newY);
          imagecopyresized($newImage, $oldImage, ($size-$newX)/2,($size-$newY)/2,0,0, $newX, $newY, $oldX, $oldY);  //Just the coordinates was changed
          imagejpeg($newImage,$filename);
    

    很抱歉,我不会将我的建议添加到您的代码中,因为它太复杂了。所以,只是一些提示

    1.如何使调整大小的图像成为正方形? 显然,我们必须创建原始图像尺寸较大的正方形。这里我假设图像已经调整了大小

    $resized = /*We hae resized image downloaded from the site [note1]*/;
    $size = max(imagesx($resized), imagesy($resized)); //Make the square so the thumbnail fits in it
    $thumbNail = imagecreate($size, $size);  //Square.
    imagecopy($thumbNail, 
              ($size-imagesx($resized))/2,   //Put the image in the middle of the square
              ($size-imagesy($resized))/2, 
              0,
              0,
              imagesx($resized),
              imagesy($resized)  
    );
    
    [note1]另外,您可以计算尺寸,在正方形上生成$size和copyrize图像。这将更快,但为其制作伪代码更为复杂

    2.如何更改新图像的背景 这并不是什么真正的谜团——你只不过是对整个图像进行了概括:

    $color = imagecolorallocate($thumbNail, 255,255,255);
    imagefilledrectangle ($thumbNail, 0, 0, imagesx($thumbNail),  imagesy($thumbNail),$color);
    
    您甚至可以使用透明背景:

    $color = imagecolorallocatealpha($thumbNail, 255,255,255,127);
    imagealphablending($thumbNail, false);  //[note2]
    imagefilledrectangle ($thumbNail, 0, 0, imagesx($thumbNail),  imagesy($thumbNail),$color);
    imagealphablending($thumbNail, true);  //If you use it
    
    [note2]关闭混合,因为
    透明
    +
    黑色
    =
    黑色

    3.与答案相关的代码 首先是调整大小、复制。在原始代码中,我们在
    $newX
    $newY
    中计算了新的高度和宽度。我将在新的图像尺寸中使用SE

    $size = max($newX,$newY);
    $newImage = imagecreatetruecolor($size, $size);
    imagecopyresized($newImage, $oldImage, ($size-$newX)/2,($size-$newY)/2,0,0, $newX, $newY, $oldX, $oldY);  //Just the coordinates was changed
    
    然后他问了他的背景。显然,你应该先设置背景,然后复制图像。但是,我将这些步骤分开,这样您就可以看到函数的作用

     $newImage = imagecreatetruecolor($newX,$newY);
     $color = imagecolorallocate($newImage, 255,255,255);  //The three parameters are R,G,B
     imagefilledrectangle ($newImage, 0, 0, $newX,  $newY,$color);
    

    哇-非常感谢你抽出时间来帮助我。我可能应该提到我是一个真正的新手。考虑到这一点,我是否可以在任何地方学习如何将这些代码与我的原始脚本放在一起?例如,我是否需要用“imagecopy”代码替换当前的“imagecopyresized”?再次感谢:)正如我在注1中提到的,一步调整大小和复制到square要方便得多。我将使用变量为您的代码添加更具体的示例。好的,我将重新编写的代码放在上面,向您展示我是如何将其组合在一起的,但它似乎不起作用。我把它拼错了吗?我把它贴在“问题”空间,因为这里有太多的字符…对不起。我不想刻薄,但我有强烈的怀疑,你没有考虑甚至没有阅读代码。您正在实际定义图像之前更改图像。
     $newImage = imagecreatetruecolor($newX,$newY);
     $color = imagecolorallocate($newImage, 255,255,255);  //The three parameters are R,G,B
     imagefilledrectangle ($newImage, 0, 0, $newX,  $newY,$color);