在浏览器中自动裁剪图像

Posted

技术标签:

【中文标题】在浏览器中自动裁剪图像【英文标题】:Cropping an Image In The Browser Automatically 【发布时间】:2011-10-21 04:40:17 【问题描述】:

如何通过上传过程自动裁剪图像?有没有 php 函数可以做到这一点?

我希望我的网页通过裁剪从原始图像的各个维度显示具有相同维度的图像。

或者有什么想法?

【问题讨论】:

【参考方案1】:

如果不知道主题在哪里,自动裁剪会很困难。也许您可以尝试获得一个内部居中的矩形,如图所示:

首先要做的是找到原始图像尺寸和文件类型。您不应该信任图像扩展名,而应使用 getimagesize 。尽管名称 getimagesize 不仅返回大小,还返回文件类型。

//width is at index 0, height at index 1, mime type at ['mime'] key
$original = getimagesize($filename); 

然后你应该构建一个内部 PHP 数据结构来将源图像保存在内存中,这样你就可以使用 imagecreatefromjpegimagecreatefrompngimagecreatefromgif 来操作它,具体取决于图像类型。例如:

$srcImage = imagecreatefromjpeg($filename);

接下来,您应该分配另一个数据结构来保存目标图像。在这种情况下,我们没有图像开始,所以我分配了一个空图像。

$dstImage = imagecreatetruecolor($newWidth, $newHeight);

接下来,您应该将原始图像的一部分复制到目标图像。如果不想调整大小,请使用imagecopy,否则如果要裁剪和调整大小,可以考虑imagecopyresampled

imagecopy(dstImage, $srcImage, 0, 0, $srcX, $srcY, $srcW, $srcH);

其中 $srcX 是源图像中的起始 X 点,$srcY 是起始 Y 点,$srcW 是从起始 X 点开始复制的宽度,$srcH 是要复制的区域的高度。

最后,您可以通过以下方式保存您的图片

imagejpeg($this->dstImage, $filename, 90);

或者您可以将其输出到浏览器

imagejpeg($this->dstImage);

如果您保存图像,您必须考虑将其保存在哪个目录中,如果您有很多图像(数千张或更多),请考虑将它们拆分为多个子目录的方法。

如果您保存原始图像,切勿保存扩展名不在您允许的扩展名列表中的图像,否则这将是一个巨大的安全漏洞,攻击者可以在其中向您发送和执行任何 PHP 代码网站。

基于所描述的概念,我编写了一个小类:

class ImageCrop 

    //Image resources
    private $srcImage, $dstImage;

    //original width and height
    private $width, $height;

    /**
    * Read an image from disk.
    * @return true in case of success, false otherwise.
    */
    public function openImage($filename) 
        if (!file_exists($filename)) 
            return false;
        
        $original = getimagesize($filename);
        switch ($original['mime']) 
        case 'image/jpeg':
            $this->srcImage = imagecreatefromjpeg($filename);
            break;
        case 'image/png':
            $this->srcImage = imagecreatefrompng($filename);
            break;
        case 'image/gif':
            $this->srcImage = imagecreatefromgif($filename);
            break;
        default:
            return false;
        
        $this->width = $original[0];
        $this->height = $original[1];
        return true;
    

    /**
    * Crop an image to the new specified dimension trying to get an 
    * internal rectangle of the original image. No crop is done if the 
    * original dimension is already smaller than $newWidth or $newHeight.
    */
    public function crop($newWidth, $newHeight) 
        $this->dstImage = imagecreatetruecolor($newWidth, $newHeight);
        $srcX = $srcY;
        $srcW = $this->width;
        $srcH = $this->height;
        $extraWidth = $this->width - $newWidth;
        if ($extraWidth > 0) 
            $srcX = $extraWidth / 2;        
        
        $extraHeight = $this->height - $newHeight;
        if ($extraHeight > 0) 
            $srcY = $extraHeight / 2;
        
        imagecopy($this->dstImage, $this->srcImage, 0, 0, 
            $srcX, $srcY, $srcW, $srcH);
    

    /**
     * Save the destination image, the crop function should have been 
     * called already.
     */
    public function save($filename) 
        imagejpeg($this->dstImage, $filename, 90);
    

    /**
    * Output the destination image to the browser.
    */
    public function output() 
        imagejpeg($this->dstImage);
    


将类保存在ImageCrop.php中,示例用法:

require_once 'ImageCrop.php';

$imageCrop = new ImageCrop();
if ($imageCrop->openImage('big.jpg')) 
    $imageCrop->crop(200, 300); //newWidth, newHeight
    $imageCrop->save('small.jpg');

或者,要将输出直接发送到浏览器,请使用$imageCrop->output();

【讨论】:

感谢编辑我的帖子,我很抱歉我的英语不好。 :-) 不,我不想调整它的大小,我只想裁剪它。因此,当用户上传的图片超出我允许的尺寸时,它会被自动裁剪。你能告诉我关于“内部矩形”的想法吗? thx 在高级。 更新了我的帖子,现在我裁剪了一个内部居中的矩形。 好的 Stivlo。这看起来很有趣,让我试一试。稍后我会给你回一些回复。 嗨,这是我的承诺。斯蒂夫洛..干得好!我已经测试了你的课程,它工作正常。多谢。您的回答非常好,因为它伴随着概念和直接实施。我会投票给你的答案。 :-) 我很欣赏你的代码 stivlo 和你们飞利浦 Tel 和 stivlo 之间的化学反应......但我看到这段代码的唯一问题是你必须提供宽度和高度来裁剪真实图像,所以生成的图像可能会失真,而我的您必须提供最大尺寸(宽度或高度),即如果您的图像容器是纵向的,则给出宽度,或者如果它是横向的,则给出高度。就是这样.....【参考方案2】:

请以max_size.php 表示此人

<?php header('Content-type: image/jpeg');
function resampleimage($maxsize, $sourcefile, $imgcomp=0)
$g_imgcomp=100-$imgcomp;
    if(file_exists($sourcefile))
    $g_is=getimagesize($sourcefile);
        if($g_is[0] <= $maxsize && $g_is[1] <= $maxsize)
            $new_width=$g_is[0];
            $new_height=$g_is[1];
         else 
            $w_adjust = ($maxsize / $g_is[0]);
            $h_adjust = ($maxsize / $g_is[1]);
      if($w_adjust <= $h_adjust)
          $new_width=($g_is[0]*$w_adjust);
          $new_height=($g_is[1]*$w_adjust);
       else 
          $new_width=($g_is[0]*$h_adjust);
          $new_height=($g_is[1]*$h_adjust);
      
    
    $image_type = strtolower(strrchr($sourcefile, "."));

    switch($image_type) 
      case '.jpg':
         $img_src = imagecreatefromjpeg($sourcefile);
         break;
      case '.jpeg':
         $img_src = imagecreatefromjpeg($sourcefile);
         break;
      case '.png':
         $img_src = imagecreatefrompng($sourcefile);
         break;
      case '.gif':
         $img_src = imagecreatefromgif($sourcefile);
         break;
      default:
         echo("Error Invalid Image Type");
         die;
         break;
   
  $img_dst=imagecreatetruecolor($new_width,$new_height);
  imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, $new_width, $new_height, $g_is[0], $g_is[1]);
  imagejpeg($img_dst);
  imagedestroy($img_dst);
  return true;
   else 
  return false;
  

resampleimage($_GET['maxsize'], $_GET['source']);
?>

在你有图片的页面中

<img id="img" src="max_size.php?maxsize=152&source=[some image path]" />

【讨论】:

嗯...感谢您的快速响应!我认为上面的脚本只是为高度和宽度创建具有相同尺寸的图像缩略图。然而,这是个好主意。 :-) 您的第一句话是正确的。它正在创建缩略图,但宽度和高度不同..它就像它会创建拇指,但在相同的源比例下,只有最大尺寸将用于横向宽度,而在纵向最大尺寸将用于高度......另外你希望自动创建一些东西......所以可以是这样,否则许多裁剪脚本可用于 jquery 但不是自动...... 大部分可用的裁剪脚本似乎都需要我们手动裁剪图像。我认为在“天空”中还有其他方法可以做到这一点。

以上是关于在浏览器中自动裁剪图像的主要内容,如果未能解决你的问题,请参考以下文章

如何在网站中动态裁剪/缩放图像

GWT 图像裁剪与浏览器中的拖放问题

调整浏览器宽度和封面照片必须保留裁剪图像的中心

如何在 Ruby on Rails 中裁剪图像

如何在浏览器下载之前将图像裁剪为客户端分辨率

图像裁剪父元素的边框半径? (苹果浏览器)