2011-07-06 97 views
39

我有定義的固定寬度和高度來調整圖像的大小。但是,我有這個問題,因爲圖像可以有任何種類的大小比例(它可以是垂直水平)。在這種情況下,固定的寬度和高度會導致問題。我想以更智能的方式計算寬度和高度計算調整大小的圖像大小比例

例如可以說我已經定義了寬度1024px和高度768px。我想調整垂直圖像(高度1100px和寬度200px)。所以在我的情況下,它將調整到固定的大小(1024x768),所以寬度將從100px增加到768px,這將是非常醜陋的。同樣,如果圖片的高度小於768px,則會將高度增加至768px

因此,我想根據原始圖像大小比例計算新的圖像大小。可以說,如果上面的示例圖像應調整到最大高度768px,但寬度又如何呢?它已經小於我的「最大寬度」,這是200px,所以寬度應該保持不變嗎?還是應該進一步減少?

同樣,如果圖像有的高度200px,寬度1100px。所以寬度應該是減少到1024px,但高度呢?

第三個問題是,假設高度和寬度都大於最大高度和最大寬度,比如說寬度:1100px,高度:4000px。現在由於寬度和高度都大於最大寬度和最大高度,但圖像是垂直的,因此會使其水平。那麼如何在這種情況下檢查是否應根據最大高度或根據最大寬度調整圖像?

我感謝任何幫助。

+0

的可能重複[圖片縮小問題(PHP/GD)](http://stackoverflow.com/questions/1830829/image-resizing-question-php-gd) – hakre

+3

已經寫了一個擴展類,檢查它:https://github.com/qaribhaider/php-image-resize –

回答

63

這是我個人抓取的圖像大小調整代碼的代碼。首先,數據,您需要:

list($originalWidth, $originalHeight) = getimagesize($imageFile); 
$ratio = $originalWidth/$originalHeight; 

然後,該算法適合圖像到目標大小,它最好的,保持原有的寬高比,不拉伸圖像大於原:

$targetWidth = $targetHeight = min($size, max($originalWidth, $originalHeight)); 

if ($ratio < 1) { 
    $targetWidth = $targetHeight * $ratio; 
} else { 
    $targetHeight = $targetWidth/$ratio; 
} 

$srcWidth = $originalWidth; 
$srcHeight = $originalHeight; 
$srcX = $srcY = 0; 

這裁剪圖像完全填充目標大小,而不是將其拉伸:

$targetWidth = $targetHeight = min($originalWidth, $originalHeight, $size); 

if ($ratio < 1) { 
    $srcX = 0; 
    $srcY = ($originalHeight/2) - ($originalWidth/2); 
    $srcWidth = $srcHeight = $originalWidth; 
} else { 
    $srcY = 0; 
    $srcX = ($originalWidth/2) - ($originalHeight/2); 
    $srcWidth = $srcHeight = $originalHeight; 
} 

而且這樣做的實際大小調整:

$targetImage = imagecreatetruecolor($targetWidth, $targetHeight); 
imagecopyresampled($targetImage, $originalImage, 0, 0, $srcX, $srcY, $targetWidth, $targetHeight, $srcWidth, $srcHeight); 

在這種情況下,$size只是寬度和高度(平方目標尺寸)的一個數字。我相信你可以修改它來使用非平方目標。它也應該給你一個啓發你可以使用的其他調整大小算法。

+0

如果有非方形目標,例如。 $ expectedWidth = 200; $ expectedHeight = 150;'那麼下面哪一個是正確的方式, '$ targetWidth = $ targetHeight = min(max($ expectedWidth,$ expectedHeight),max($ originalWidth,$ originalHeight)); ' OR '$ targetWidth = $ targetHeight = min($ expectedWidth,$ expectedHeight,max($ originalWidth,$ originalHeight));' – Roopendra

+0

@deceze請確認這裏可能有什麼值$的尺寸 –

+0

@Heemanshu正如書面,它是*目標圖像大小*。 '$ size = 200'表示結果將是(最大)200 x 200像素的圖像。 – deceze

0

你需要的是'維持'寬高比。 原來你有一個尺寸(wxh)500x1000的圖像,這個寬度/高度比是0.5。假設您將高度更改爲1000768,則結果寬度將爲0.5 * 768 = 384

又如,1800 x 1200和你高度爲200,那麼你寬度爲300因爲300/2001.51800/12001.5

祝你好運。

0

你應該調整它的大小取決於哪些屬性距離最大值更遠。然後,計算比率。

if(($w - $w_max) > ($h - $h_max)) { 
    $w_new = $w_max; 
    $h_new = (int) ($h * ($w_max/$w)); 
} 
else { 
    $h_new = $h_max; 
    $w_new = (int) ($w * ($h_max/$h)); 
} 
+0

這隻適用於如果你的目標大小是方形($ w_max = $ h_max),否則你可以得到結果的地方根據輸入圖像和目標大小的相對大小,新圖像的寬度或高度均大於目標大小。 –

+0

例如:如果輸入= 400x300,目標= 300x220,那麼您的代碼將導致300x225的圖像大於目標圖像。 –

10

你想要的是保持原始圖像的縱橫比。這是圖像的寬度和高度之間的比率。因此,您要計算必須在垂直和水平方向調整圖像大小的因子,然後保持兩者中較高的一個。在僞代碼:

target_height = 768 
target_width = 1024 
# v_fact and h_fact are the factor by which the original vertical/horizontal 
# image sizes should be multiplied to get the image to your target size. 
v_fact = target_height/im_height 
h_fact = target_width/im_width 
# you want to resize the image by the same factor in both vertical 
# and horizontal direction, so you need to pick the correct factor from 
# v_fact/h_fact so that the largest (relative to target) of the new height/width 
# equals the target height/width and the smallest is lower than the target. 
# this is the lowest of the two factors 
im_fact = min(v_fact, h_fact) 
new_height = im_height * im_fact 
new_width = im_width * im_fact 
image.resize(new_width, new_height) 
+2

這很棒,這裏是一個較短的PHP版本: list($ width,$ height,$ type,$ attr)= getimagesize($ path ); $ ratio = min($ maxHeight/$ height,$ maxWidth/$ width); $ newHeight = ceil($ height * $ ratio); $ newWidth = ceil($ width * $ ratio); – Kus

1

檢查下面的PHP代碼:

$new_width = 1024; 
$new_height = 768; 
$this_image = "images/my_image"; 

list($width, $height, $type, $attr) = getimagesize("$this_image"); 

if ($width > $height) { 
    $image_height = floor(($height/$width)*$new_width); 
    $image_width = $new_width; 
} else { 
    $image_width = floor(($width/$height)*$new_height); 
    $image_height = $new_height; 
} 
echo "<img src='$this_image' height='$image_height' width='$image_width'>"; 
44
$ratio = $originalWidth/$originalHeight 
如果你想改變高度

$targetWidth = $targetHeight * $ratio 
如果要更改寬度

$targetHeight = $targetWidth/$ratio 
+0

你可以在這裏查看一個工作的演示http:// whats-online。info/science-and-tutorials/77/resize-image-proportionally-on-upload-and-save-in-PHP/ –

0

我遇到了這個問題,沒有找到合適的答案,所以我自己着手回答問題。

我從一些基本的邏輯開始,在諮詢了一位數學能力稍好的朋友之後,這就是我們想到的。

function calculate_dimensions($width,$height,$max){ 
    if($width != $height){ 
     if($width > $height){ 
      $t_height = $max; 
      $t_width = min(($width * $t_height)/$height); 
     } 
     if($height > $width){ 
      $t_width = $max; 
      $t_height = min(($t_width * $height)/$width) 
     } 
    }else{ 
     if($width > $max){ 
      $t_width = $t_height = $max; 
     } 
    } 
    $res = ['height'=>$t_height,'width'=>$t_width] 
    return $res; 
} 

這段代碼是可重複使用的,所以請自己敲出來。只是通過它允許的最大最小尺寸,並且它會計算最大側的尺寸,所以您將返回一個正確縮放的尺寸,然後可以居中裁剪,從而生成正確縮小和裁剪的圖像正方形圖像。這對於個人資料圖片和縮略圖很有用。

貸給我的朋友,Justin Gillett他的輝煌的交叉倍增建議。

6

這是工作。

function calculateDimensions($width,$height,$maxwidth,$maxheight) 
{ 

     if($width != $height) 
     { 
      if($width > $height) 
      { 
       $t_width = $maxwidth; 
       $t_height = (($t_width * $height)/$width); 
       //fix height 
       if($t_height > $maxheight) 
       { 
        $t_height = $maxheight; 
        $t_width = (($width * $t_height)/$height); 
       } 
      } 
      else 
      { 
       $t_height = $maxheight; 
       $t_width = (($width * $t_height)/$height); 
       //fix width 
       if($t_width > $maxwidth) 
       { 
        $t_width = $maxwidth; 
        $t_height = (($t_width * $height)/$width); 
       } 
      } 
     } 
     else 
      $t_width = $t_height = min($maxheight,$maxwidth); 

     return array('height'=>(int)$t_height,'width'=>(int)$t_width); 
    } 
0

本示例將縮小圖像以適合創建不超過指定限制(1200 x 675)的圖像的定義像素完美寬高比(16:9)。

設置你的圖像比和任何上限:

const RATIO_W      = 16; 
const RATIO_H      = 9; 
const RATIO_MULIPLIER_UPPER_LIMIT = 75; 

通過因子計算新的圖像的寬度和高度

list($imageWidth, $imageHeight) = getimagesize($path_to_image);  

if(($imageWidth/$imageHeight) === (self::RATIO_W/self::RATIO_H)){ 
    return; 

// Find closest ratio multiple to image size 
if($imageWidth > $imageHeight){ 
    // landscape 
    $ratioMultiple = round($imageHeight/self::RATIO_H, 0, PHP_ROUND_HALF_DOWN); 
}else{ 
    // portrait 
    $ratioMultiple = round($imageWidth/self::RATIO_W, 0, PHP_ROUND_HALF_DOWN); 
}  

$newWidth = $ratioMultiple * self::RATIO_W; 
$newHeight = $ratioMultiple * self::RATIO_H;  

if($newWidth > self::RATIO_W * self::RATIO_MULIPLIER_UPPER_LIMIT|| $newHeight > self::RATIO_H * self::RATIO_MULIPLIER_UPPER_LIMIT){ 
    // File is larger than upper limit 
    $ratioMultiple = self::RATIO_MULIPLIER_UPPER_LIMIT; 
}  

$this->tweakMultiplier($ratioMultiple, $imageWidth, $imageHeight);  

$newWidth = $ratioMultiple * self::RATIO_W; 
$newHeight = $ratioMultiple * self::RATIO_H;  

調整尺寸圖像

$originalImage = imagecreatefromjpeg($tempImagePath); 
$newImage  = imagecreatetruecolor($newWidth, $newHeight); 
imagefilledrectangle($newImage, 0, 0, $newWidth, $newHeight, imagecolorallocate($newImage, 255, 255, 255)); 
imagecopyresampled($newImage, $originalImage, 0, 0, 0, 0, $newWidth, $newHeight, $imageWidth, $imageHeight); 
imagejpeg($newImage, $tempImagePath, 100); 

循環直到兩個尺寸小於原始圖像尺寸

protected function tweakMultiplier(&$ratioMultiple, $fitInsideWidth, $fitInsideHeight){ 
    $newWidth = $ratioMultiple * self::RATIO_W; 
    $newHeight = $ratioMultiple * self::RATIO_H;  

    if($newWidth > $fitInsideWidth || $newHeight > $fitInsideHeight){ 
     echo " Tweak "; 
     $ratioMultiple--; 
     $this->tweakMultiplier($ratioMultiple, $fitInsideWidth, $fitInsideHeight); 
    }else{ 
     return; 
    }  
} 
0

如果最大高度或寬度給出,使用@(jilles德維特)邏輯

考慮:這些應該已經被定義!

$mh = given height limit; //optional 
$mw = given width limit; //optional 

$height = $nh =[your original height]; 
$width = $nw =[your original width]; 

守則

if($mh || $mw){ 
if(is_numeric($mh)){$h_fact = $mh/$nh;} 
if(is_numeric($mw)){$v_fact = $mw/$nw;} 

if(is_numeric($v_fact) && is_numeric($h_fact) ){$im_fact = min($v_fact, $h_fact);}else{$im_fact=is_numeric($v_fact)?$v_fact:$h_fact;} 
$nw = $nw * $im_fact; 
$nh = $nh * $im_fact; 
} 

重採樣

$dst_img = imagecreatetruecolor($nw,$nh); 
imagecopyresampled ($dst_img, $image, 0, 0, 0, 0, $nw, $nh, $width , $height); 
0
class Image_Aspect_Ratio_Resize { 
var $image_to_resize; 
var $new_width; 
var $new_height; 
var $ratio; 
var $new_image_name; 
var $save_folder; 

function resize() { 
    if (!file_exists($this->image_to_resize)) { 
     exit("File " . $this->image_to_resize . " does not exist."); 
    } 

    $info = GetImageSize($this->image_to_resize); 

    if (empty($info)) { 
     exit("The file " . $this->image_to_resize . " doesn't seem to be an image."); 
    } 

    $width = $info[0]; 
    $height = $info[1]; 
    $mime = $info['mime']; 

    /* Keep Aspect Ratio? */ 

    if ($this->ratio) { 
     $thumb = ($this->new_width < $width && $this->new_height < $height) ? true : false; // Thumbnail 
     $bigger_image = ($this->new_width > $width || $this->new_height > $height) ? true : false; // Bigger Image 

     if ($thumb) { 
      if ($this->new_width >= $this->new_height) { 
       $x = ($width/$this->new_width); 

       $this->new_height = ($height/$x); 
      } else if ($this->new_height >= $this->new_width) { 
       $x = ($height/$this->new_height); 

       $this->new_width = ($width/$x); 
      } 
     } else if ($bigger_image) { 
      if ($this->new_width >= $width) { 
       $x = ($this->new_width/$width); 

       $this->new_height = ($height * $x); 
      } else if ($this->new_height >= $height) { 
       $x = ($this->new_height/$height); 

       $this->new_width = ($width * $x); 
      } 
     } 
    } 


    $type = substr(strrchr($mime, '/'), 1); 

    switch ($type) { 
     case 'jpeg': 
      $image_create_func = 'ImageCreateFromJPEG'; 
      $image_save_func = 'ImageJPEG'; 
      $new_image_ext = 'jpg'; 
      break; 

     case 'png': 
      $image_create_func = 'ImageCreateFromPNG'; 
      $image_save_func = 'ImagePNG'; 
      $new_image_ext = 'png'; 
      break; 

     case 'bmp': 
      $image_create_func = 'ImageCreateFromBMP'; 
      $image_save_func = 'ImageBMP'; 
      $new_image_ext = 'bmp'; 
      break; 

     case 'gif': 
      $image_create_func = 'ImageCreateFromGIF'; 
      $image_save_func = 'ImageGIF'; 
      $new_image_ext = 'gif'; 
      break; 

     case 'vnd.wap.wbmp': 
      $image_create_func = 'ImageCreateFromWBMP'; 
      $image_save_func = 'ImageWBMP'; 
      $new_image_ext = 'bmp'; 
      break; 

     case 'xbm': 
      $image_create_func = 'ImageCreateFromXBM'; 
      $image_save_func = 'ImageXBM'; 
      $new_image_ext = 'xbm'; 
      break; 

     default: 
      $image_create_func = 'ImageCreateFromJPEG'; 
      $image_save_func = 'ImageJPEG'; 
      $new_image_ext = 'jpg'; 
    } 

    // New Image 
    $image_c = ImageCreateTrueColor($this->new_width, $this->new_height); 

    $new_image = $image_create_func($this->image_to_resize); 

    ImageCopyResampled($image_c, $new_image, 0, 0, 0, 0, $this->new_width, $this->new_height, $width, $height); 

    if ($this->save_folder) { 
     if ($this->new_image_name) { 
      $new_name = $this->new_image_name . '.' . $new_image_ext; 
     } else { 
      $new_name = $this->new_thumb_name(basename($this->image_to_resize)) . '_resized.' . $new_image_ext; 
     } 

     $save_path = $this->save_folder . $new_name; 
    } else { 
     /* Show the image without saving it to a folder */ 
     header("Content-Type: " . $mime); 

     $image_save_func($image_c); 

     $save_path = ''; 
    } 

    $process = $image_save_func($image_c, $save_path); 

    return array('result' => $process, 'new_file_path' => $save_path); 
}} 

/*函數調用*/

$resize_image = new Image_Aspect_Ratio_Resize; 
$new_width = (int) $_POST['new_width']; 
$new_height = (int) $_POST['new_height']; 
$resize_image->new_width = $new_width; 
$resize_image->new_height = $new_height; 
$resize_image->image_to_resize = $image; // Full Path to the file 
$resize_image->ratio = true; // Keep aspect ratio 
// Name of the new image (optional) - If it's not set a new will be added automatically 
$resize_image->new_image_name = 'water_lilies_thumbnail'; 
/* Path where the new image should be saved. If it's not set the script will output the image without saving it */ 
$resize_image->save_folder = 'thumbs/'; 
$process = $resize_image->resize(); // Output image 
+0

你能否加一些解釋? –

0

如何:

double ratio = imageWidth/imageHeight; 
int newHeight = Math.min(displayHeight, displayWidth/ratio); 
int newWidth = Math.min(displayWidth, displayHeight * ratio);