2011-09-13 61 views
1

我使用jQuery的imgAreaSelect插件來裁剪圖像並保存縮略圖以便在例如比例發生變化的情況下使用。令人遺憾的是,結果與我所期望的並不相符,而我無法做到。圖像被整體調整大小而不是被裁剪。PHP GD作物和比例尺圖像

這裏的測試例子:

<?php 

/*** 
* 
* $_GET returned values 
* 
* x1 = 0 
* x2 = 400 
* y1 = 66 
* y2 = 258 
* w = 400 
* h = 192 
* folder = widethumb 
* filename = IMG_4591.jpg 
* scale = 48 
* 
* Original image properties 
* 
* width = 600px 
* height = 900px 
* 
***/ 

define('DOCROOT', realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR); 

extract($_GET); 

$fn = $filename; 
$filename = DOCROOT.$filename; 

list($width, $height) = getimagesize($filename); 

$src = imagecreatefromjpeg($filename); 
$dst = imagecreatetruecolor($w, $h); 
imagecopyresampled($dst, $src, 0, 0, (int) $x1, (int) $y1, (int) $w, (int) $h, $width, $height); 

header('Content-Type: image/jpeg'); 
imagejpeg($dst); 

什麼我mising這裏?

乾杯!

回答

5

從PHP文檔:

bool imagecopyresampled (resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h) 

imagecopyresampled()拷貝一個圖像到另一個圖像的矩形部分,平滑地內插像素值,因此,特別地,減少圖像的尺寸仍然保留了大量的的清晰度。換句話說,imagecopyresampled()將從src_image的寬度src_w和高度src_h的位置(src_x,src_y)取一個矩形區域,並將其放置在寬度爲dst_w的dst_image和位置爲(dst_x的高度爲dst_h的矩形區域中,dst_y)。

因此,要獲得您正在尋找的結果,您需要避免縮放。用於該用途:

imagecopy($dst, $src, 0, 0, $x1, $y1, $w, $h); 

// this can also be done but is less efficient (over 10 times slower) 
imagecopyresampled($dst, $src, 0, 0, (int) $x1, (int) $y1, $w, $h, $w, $h); 

在這裏,我們正在從源頭採取相同大小的矩形,因爲我們將它放入目標圖像。
我剛剛測試過它,它工作得很好。

更新: 我剛剛在我的測試服務器上再次嘗試,它工作正常。我使用下面的代碼:

$filename = "test.jpg"; 

extract($_GET); 

$src = imagecreatefromjpeg($filename); 
$dst = imagecreatetruecolor($w, $h); 
imagecopy($dst, $src, 0, 0, $x1, $y1, $w, $h); 

// this is over 10 times slower, as we are only cropping we should use imagecopy 
//imagecopyresampled($dst, $src, 0, 0, $x1, $y1, $w, $h, $w, $h); 

header('Content-Type: image/jpeg'); 
imagejpeg($dst); 

我打電話這樣說:

http://localserver/test/gd_crop.php?x1=906&y1=267&w=501&h=355

性能更新
,因爲我們沒有調整,我們可以簡單地使用imagecopy。下面給出了我測量的3個功能的性能。

imagecopyresampled 69ms 
imagecopyresized  5.5ms 
imagecopy    4.5ms 

所以重新採樣和其他兩個函數之間存在10個速度差的順序。

我終於想出了下面一行到位imagecopyresampled功能的,試試吧,我也更新了上面的代碼清單:

imagecopy($dst, $src, 0, 0, $x1, $y1, $w, $h); 
+0

沒有工作,顯示的圖像似乎指向'0,0',而不是'0,66'。 – yoda

+0

你可以發佈你的更新代碼。由於它對我來說非常合適,請參閱更新我的答案。 – danishgoel

+0

解決了這個問題,在'imagecopyresampled'上使用'$ width'和'$ height',我會堅持下去,在需要按比例顯示時在'img'標籤上定義'width'和'height'。不是最好的解決方案,但它也可以。我忘記的另一件事是我用小規模('2/3'或原來的)'jQuery'顯示圖像,因此給我一個奇怪的結果。謝謝,你的答案幫助:) – yoda

0

爲什麼不看看使用imagemagik;它非常適合圖像處理,裁剪只是使用cropImage($ width,$ height,$ x,$ y)的簡單例子。

+0

因爲我的客戶端的主機不具備安裝該組件,客戶拒絕改變主機和託管公司......還是不要說出來:) – yoda

+1

而事實上,PHP具有內置的圖像處理功能。 – Bojangles

1

使用WideImage庫,而不是。

這是我自己的裁剪功能:

function createThumbnail($file, $cropX, $cropY, $cropWidth, $cropHeight, $desiredWidth, $desiredHeight, $shrink = false) 
{ 
    if(file_exists(MPS_ROOT_PATH . "$file") && $cropWidth && $cropHeight) 
    { 
     $source_path = MPS_ROOT_PATH . $file; 

     list($source_width, $source_height, $source_type) = getimagesize($source_path); 
     switch ($source_type) 
     { 
      case IMAGETYPE_GIF: 
       $source_gdim = imagecreatefromgif($source_path); 
       break; 

      case IMAGETYPE_JPEG: 
       $source_gdim = imagecreatefromjpeg($source_path); 
       break; 

      case IMAGETYPE_PNG: 
       $source_gdim = imagecreatefrompng($source_path); 
       break; 

      default: 
       return false; 
     } 

     if(!$desiredWidth) 
     { 
      // Desired width not set, computing new width based on original 
      // image's aspect ratio... 
      $desiredWidth = $cropWidth * ($desiredHeight/$cropHeight); 
     } 

     if(!$desiredHeight) 
     { 
      // Desired height not set, computing new height based on original 
      // image's aspect ratio 
      $desiredHeight = $cropHeight * ($desiredWidth/$cropWidth); 
     } 

     if(!$desiredWidth || !$desiredHeight) 
     { 
      // Desired height or width not set. 
      // Halting image processing and returning file 
      return $file; 
     } 

     $source_aspect_ratio = $cropWidth/$cropHeight; 
     $desired_aspect_ratio = $desiredWidth/$desiredHeight; 

     if($shrink) 
     { 
      // Shrink to fit flag set. Inverting computations to make image fit 
      // within the desired dimensions... 
      if($source_aspect_ratio > $desired_aspect_ratio) 
      { 
       // Source image is wider than desired aspect ratio, 
       // setting thumbnail width to the desired width and the height 
       // will be computed based on the original image's aspect ratio 
       $temp_width = $desiredWidth; 
       $temp_height = (int) ($desiredWidth/$source_aspect_ratio); 
      } 
      else 
      { 
       // Source image is taller than desired aspect ratio, 
       // setting thumbnail height to the desired height and the width 
       // will be computed based on the original image's aspect ratio 
       $temp_height = $desiredHeight; 
       $temp_width = (int) ($desiredHeight * $source_aspect_ratio); 
      } 
     } 
     // shrink to fit not set 
     else 
     { 
      if($source_aspect_ratio > $desired_aspect_ratio) 
      { 
       // Source image is wider than desired aspect ratio, 
       // setting thumbnail height to the desired height to fill the 
       // desired aspect ratio and the width will be computed based on 
       // the original image's aspect ratio 
       $temp_height = $desiredHeight; 
       $temp_width = (int) ($desiredHeight * $source_aspect_ratio); 
      } 
      else 
      { 
       // Source image is taller than desired aspect ratio, 
       // setting thumbnail width to the desired width to fill the 
       // desired aspect ratio and the width will be computed based on 
       // the original image's aspect ratio"); 
       $temp_width = $desiredWidth; 
       $temp_height = (int) ($desiredWidth/$source_aspect_ratio); 
      } 
     } 

     $temp_gdim = imagecreatetruecolor($temp_width, $temp_height); 

     // Copying a $cropWidth x $cropHeight image from the source 
     // file at ($cropX, $cropY) and resampling it to fit the temporary 
     // $temp_width x $temp_height thumbnail at (0, 0) 
     imagecopyresampled(
      $temp_gdim, 
      $source_gdim, 
      0, 0, 
      $cropX, $cropY, 
      $temp_width, $temp_height, 
      $cropWidth, $cropHeight 
     ); 

     $x0 = ($desiredWidth - $temp_width)/2; 
     $y0 = ($desiredHeight - $temp_height)/2; 
     // Positioning the temporary $temp_width x $temp_height thumbnail in 
     // the center of the final $desiredWidth x $desiredHeight thumbnail... 
     // Creating final thumbnail canvas at $desiredWidth x $desiredHeight 
     $desired_gdim = imagecreatetruecolor($desiredWidth, $desiredHeight); 

     $white = imagecolorallocate($desired_gdim, 255, 255, 255); 
     imagefill($desired_gdim, 0, 0, $white); 
     // Filling final thumbnail canvas with white 

     // Copying a $temp_width x $temp_height image from the temporary 
     // thumbnail at (0, 0) and placing it in the final 
     // thumbnail at ($x0, $y0) 
     imagecopy(
      $desired_gdim, 
      $temp_gdim, 
      $x0, $y0, 
      0, 0, 
      $temp_width, $temp_height 
     ); 

     $pathInfo = pathinfo($file); 
     $thumbFile = "images/thumbs/thumb_" . basename($pathInfo["filename"]) . ".jpg"; 

     if(imagejpeg($desired_gdim, MPS_ROOT_PATH . $thumbFile, 80)) 
     { 
      return $thumbFile; 
     } 
     else 
     { 
      return 1; 
     } 
    } 
    else 
    { 
     echo "Image File Does not exist or Invalid crop parameters!"; 
     return false; 
    } 
} 
+1

沒有必要 - PHP可以做到這一點內部。請在發佈您的答案之前做一點研究。 – Bojangles

+0

@JamWaffles:我知道我在說什麼。我知道PHP可以自己做到這一點,我一直在使用GD2來裁剪和調整圖像大小,但使用庫會減輕開發人員的負擔,因此開發人員可以專注於腳本的更大部分。 –

+1

確實如此,但如果開發人員只需要整個庫中的一個函數,爲什麼還要增加額外的膨脹?如果他們需要重新使用它或稍後擴展它,PHP有類是有原因的:-) – Bojangles

0

這裏,你可以通過在目標層面,將規模和作物從中心,保持縱橫比,並且將擴展功能。用響應式設計的圖片元素很容易實現。如果您更改目標尺寸,只需刪除輸出的文件,這將在不存在的情況下重新創建圖像。

<?php 
    function scaleCrop($src, $dest, $destW, $destH, $anchor){ 
     if(!file_exists($dest) && is_file($src) && is_readable($src)){ 
      $srcSize = getimagesize($src); 
      $srcW = $srcSize[0]; 
      $srcH = $srcSize[1]; 
      $srcRatio = $srcW/$srcH; 
      $destRatio = $destW/$destH; 
      $img = (imagecreatefromjpeg($src)); 
      $imgNew = imagecreatetruecolor($destW, $destH); 

      if ($srcRatio < $destRatio){ 
       $scale = $srcW/$destW; 
      } 
      elseif($srcRatio >= $destRatio){ 
       $scale = $srcH/$destH; 
      } 
      $srcX = ($srcW - ($destW * $scale))/2; 
      if($anchor = 'middle'){ 
       $srcY = ($srcH - ($destH * $scale))/2; 
      } 
      elseif($anchor = 'top'){ 
       $srcY = 0; 
      } 
      elseif($anchor = 'bottom'){ 
       $srcY = $srcH - ($destH * $scale); 
      } 
      if($srcX < 0){$srcX = 0;}; 
      if($srcY < 0){$srcY = 0;}; 
      imagecopyresampled($imgNew, $img, 0, 0, $srcX, $srcY, $destW, $destH, $destW * $scale, $destH * $scale); 
      imagejpeg($imgNew, $dest, 70); 
      imagedestroy($img); 
      imagedestroy($imgNew); 
     } 
     return $dest; 
    } 
    ?> 

<img src="<?php echo scaleCrop('srcfolder/srcfile.jpg', 'destfolder/destfile.jpg', 320, 240, 'top'); ?>">