2013-05-27 31 views
12

基本的には画像をアップロードして、最大幅や高さなどの特定の制約に縮小して元の画像のアスペクト比を維持したいとします。PHPを使用してアスペクト比を維持する画像の縮尺

私はImagickをサーバーにインストールしていません。そうしなければ簡単になります。

いつものように助けてください。おかげさまで

編集:私はコード全体や何かを必要としません、正しい方向へのプッシュは素晴らしいでしょう。

答えて

10

私が行った別のプロジェクトでは、このようなコードを書いていました。私はそれを下にコピーした、少し微妙にする必要があります!

これらは必要なパラメータです(これは、GDライブラリを必要とん):アップそれは縮小されます

$image_name - Name of the image which is uploaded 
$new_width - Width of the resized photo (maximum) 
$new_height - Height of the resized photo (maximum) 
$uploadDir - Directory of the original image 
$moveToDir - Directory to save the resized image 

または最大の幅や高さのイメージが

function createThumbnail($image_name,$new_width,$new_height,$uploadDir,$moveToDir) 
{ 
    $path = $uploadDir . '/' . $image_name; 

    $mime = getimagesize($path); 

    if($mime['mime']=='image/png') { 
     $src_img = imagecreatefrompng($path); 
    } 
    if($mime['mime']=='image/jpg' || $mime['mime']=='image/jpeg' || $mime['mime']=='image/pjpeg') { 
     $src_img = imagecreatefromjpeg($path); 
    } 

    $old_x   = imageSX($src_img); 
    $old_y   = imageSY($src_img); 

    if($old_x > $old_y) 
    { 
     $thumb_w = $new_width; 
     $thumb_h = $old_y*($new_height/$old_x); 
    } 

    if($old_x < $old_y) 
    { 
     $thumb_w = $old_x*($new_width/$old_y); 
     $thumb_h = $new_height; 
    } 

    if($old_x == $old_y) 
    { 
     $thumb_w = $new_width; 
     $thumb_h = $new_height; 
    } 

    $dst_img  = ImageCreateTrueColor($thumb_w,$thumb_h); 

    imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y); 


    // New save location 
    $new_thumb_loc = $moveToDir . $image_name; 

    if($mime['mime']=='image/png') { 
     $result = imagepng($dst_img,$new_thumb_loc,8); 
    } 
    if($mime['mime']=='image/jpg' || $mime['mime']=='image/jpeg' || $mime['mime']=='image/pjpeg') { 
     $result = imagejpeg($dst_img,$new_thumb_loc,80); 
    } 

    imagedestroy($dst_img); 
    imagedestroy($src_img); 

    return $result; 
} 
+0

ニース - ありがとう、とても役に立ちます。私はImagickをソートしようとホストに話しています...現在、クラスが見つからないという致命的なエラーが発生しています... –

+0

'<?php phpinfo(); ?> 'GDの検索を行いますが、これが有効になっていれば、上記の関数はimagickなしでも動作するはずです:)しかし、エラーが出たら、私に知らせてください。 –

+0

私のために働かなかった。アスペクト比を維持しませんでした。 –

3

フォーミュラが間違っていますアスペクト比を維持するため。 それはあるべきである:元の高さ/元の幅は

function createThumbnail($imageName,$newWidth,$newHeight,$uploadDir,$moveToDir) 
{ 
    $path = $uploadDir . '/' . $imageName; 

    $mime = getimagesize($path); 

    if($mime['mime']=='image/png'){ $src_img = imagecreatefrompng($path); } 
    if($mime['mime']=='image/jpg'){ $src_img = imagecreatefromjpeg($path); } 
    if($mime['mime']=='image/jpeg'){ $src_img = imagecreatefromjpeg($path); } 
    if($mime['mime']=='image/pjpeg'){ $src_img = imagecreatefromjpeg($path); } 

    $old_x = imageSX($src_img); 
    $old_y = imageSY($src_img); 

    if($old_x > $old_y) 
    { 
     $thumb_w = $newWidth; 
     $thumb_h = $old_y/$old_x*$newWidth; 
    } 

    if($old_x < $old_y) 
    { 
     $thumb_w = $old_x/$old_y*$newHeight; 
     $thumb_h = $newHeight; 
    } 

    if($old_x == $old_y) 
    { 
     $thumb_w = $newWidth; 
     $thumb_h = $newHeight; 
    } 

    $dst_img  = ImageCreateTrueColor($thumb_w,$thumb_h); 

    imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y); 


    // New save location 
    $new_thumb_loc = $moveToDir . $imageName; 

    if($mime['mime']=='image/png'){ $result = imagepng($dst_img,$new_thumb_loc,8); } 
    if($mime['mime']=='image/jpg'){ $result = imagejpeg($dst_img,$new_thumb_loc,80); } 
    if($mime['mime']=='image/jpeg'){ $result = imagejpeg($dst_img,$new_thumb_loc,80); } 
    if($mime['mime']=='image/pjpeg'){ $result = imagejpeg($dst_img,$new_thumb_loc,80); } 

    imagedestroy($dst_img); 
    imagedestroy($src_img); 
    return $result; 
} 
+0

ちょうど、それは縦横比を保持しません。300x300の画像を500x200にリサイズする場合、500x200が作成されます。 – vaso123

13

幅=新しい高新をxは実際に受け入れ溶液が正解ありません。理由は簡単です。ソース画像の比率とターゲット画像の比率が異なる場合があります。どのような計算もこの差異を反映する必要があります。

PHP.netのウェブサイト上で与えられた例から関連する行に注意してください:完全な例はここに見つけることができる

$ratio_orig = $width_orig/$height_orig; 

if ($width/$height > $ratio_orig) { 
    $width = $height*$ratio_orig; 
} else { 
    $height = $width/$ratio_orig; 
} 

を: http://php.net/manual/en/function.imagecopyresampled.php

stackoverflowの上(例で)他の回答があります。同じ問題に苦しんでいる同様の質問(別の方法で策定された同じ質問)にも適用されます。

例:

if($old_x < $old_y) 
    { 
     $thumb_w = $old_x*($new_width/$old_y); 
     $thumb_h = $new_height; 
    } 

のは、我々は我々が自動になりたいピクセルがのが受け入れソリューションを取って、いくつかの数学をやってみましょう160×240にアスペクト比を維持リサイズ1630 X 2400のイメージを持っているとしましょう

高さ= 240 幅= 1630 *(160/2400)= 1630 * 0.0666666666666667 = 108.6666666666667 108.6 x 240これは正しい解決策ではありません。

提案された次のソリューションは、以下である:

if($old_x < $old_y) 
    { 
     $thumb_w = $old_x/$old_y*$newHeight; 
     $thumb_h = $newHeight; 
    } 

高さ= 240。 width = 1630/2400 * 240 = 163 これはアスペクト比を維持する方が優れていますが、許容最大幅を超えています。

どちらも失敗します。

我々はPHP.netによって提案された解決策に応じて計算を行う: 幅= 160 高さ= 160 /(/ 2400 1630)= 160/0.6791666666666667 = 235.5828220858896(節)。 160 x 236(丸め)は正解です。

0
<?php 
Class ResizedImage 
{ 
    public $imgfile; 
    public $string  = ''; 
    public $new_width = 0; 
    public $new_height = 0; 
    public $angle  = 0; 
    public $max_font_size = 1000; 
    public $cropped = false;//whether crop the original image if h or w > new h or w 
    public $font = 'fonts/arialbd.ttf'; 

    private $img; 
    private $trans_colour; 
    private $orange; 
    private $white; 
    private $whitetr; 
    private $blacktr; 

    public function PrintAsBase64() 
    { 
     $this->SetImage(); 
     ob_start(); 
     imagepng($this->img); 
     $b64img = ob_get_contents(); 
     ob_clean(); 
     imagedestroy($this->img); 
     $b64img = base64_encode($b64img); 
     echo($b64img); 
    } 
    public function PrintAsImage() 
    { 
     $this->SetImage(); 

     header('Content-type: image/png'); 

     imagepng($this->img); 
     imagedestroy($this->img); 
    } 

    private function SetImage() 
    { 
     if ($this->imgfile == '') {$this->imgfile='NoImageAvailable.jpg';} 
     $this->img   = imagecreatefromstring(file_get_contents($this->imgfile)); 
     $this->trans_colour = imagecolorallocatealpha($this->img, 0, 0, 0, 127); 
     $this->orange  = imagecolorallocate($this->img, 220, 210, 60); 
     $this->white  = imagecolorallocate($this->img, 255,255, 255); 
     $this->whitetr  = imagecolorallocatealpha($this->img, 255,255, 255, 95); 
     $this->blacktr  = imagecolorallocatealpha($this->img, 0, 0, 0, 95); 

     if ((!$this->cropped) && ($this->string !='')) 
     {$this->watermarkimage();} 

     if (($this->new_height > 0) && ($this->new_width > 0)) {$this->ResizeImage();}; 

     if (($this->cropped) && ($this->string !='')) 
     {$this->watermarkimage();} 

     imageAlphaBlending($this->img, true); 
     imageSaveAlpha($this->img, true); 
    } 
    //// 
    private function ResizeImage() 
    { 
     # 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 = $this->new_height/imagesy($this->img);//target_height/im_height; 
     $h_fact = $this->new_width/imagesx($this->img);//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 
     if($this->cropped) 
     { $im_fact = max($v_fact, $h_fact); } 
     else 
     { $im_fact = min($v_fact, $h_fact); } 

     $new_height = round(imagesy($this->img) * $im_fact); 
     $new_width = round(imagesx($this->img) * $im_fact); 

     $img2 = $this->img;  
     $this->img = imagecreatetruecolor($new_width, $new_height);  
     imagecopyresampled($this->img, $img2, 0, 0, 0, 0, $new_width, $new_height, imagesx($img2), imagesy($img2)); 

     $img2 = $this->img;  
     $this->img = imagecreatetruecolor($this->new_width, $this->new_height); 
     imagefill($this->img, 0, 0, $this->trans_colour); 

     $dstx = 0; 
     $dsty = 0; 
     if ($this->cropped) 
     { 
      if (imagesx($this->img) < imagesx($img2)) 
      { $dstx = round((imagesx($this->img)-imagesx($img2))/2); } 

      if (imagesy($this->img) < imagesy($img2)) 
      { $dsty = round((imagesy($this->img)-imagesy($img2))/2); } 
     } 
     else 
     { 
      if (imagesx($this->img) > imagesx($img2)) 
      { $dstx = round((imagesx($this->img)-imagesx($img2))/2); } 

      if (imagesy($this->img) > imagesy($img2)) 
      { $dsty = round((imagesy($this->img)-imagesy($img2))/2); } 
     } 

     imagecopy ($this->img, $img2, $dstx, $dsty, 0, 0, imagesx($img2) , imagesy($img2)); 
     imagedestroy($img2);   
    } 

    //// 

    private function calculateTextBox($text,$fontFile,$fontSize,$fontAngle) 
    { 
     /************ 
     simple function that calculates the *exact* bounding box (single pixel precision). 
     The function returns an associative array with these keys: 
     left, top: coordinates you will pass to imagettftext 
     width, height: dimension of the image you have to create 
     *************/ 
     $rect = imagettfbbox($fontSize,$fontAngle,$fontFile,$text); 
     $minX = min(array($rect[0],$rect[2],$rect[4],$rect[6])); 
     $maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6])); 
     $minY = min(array($rect[1],$rect[3],$rect[5],$rect[7])); 
     $maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7])); 

     return array( 
     "left" => abs($minX) - 1, 
     "top" => abs($minY) - 1, 
     "width" => $maxX - $minX, 
     "height" => $maxY - $minY, 
     "box" => $rect); 
    } 

    private function watermarkimage($font_size=0) 
    { 
     if ($this->string == '') 
     {die('Watermark function call width empty string!');} 

     $box = $this->calculateTextBox($this->string, $this->font, $font_size, $this->angle); 
     while (($box['width'] < imagesx($this->img)) && ($box['height'] < imagesy($this->img)) && ($font_size <= $this->max_font_size)) 
     { 
      $font_size++; 
      $box = $this->calculateTextBox($this->string, $this->font, $font_size, $this->angle); 
     } 

     $font_size--; 
     $box = $this->calculateTextBox($this->string, $this->font, $font_size, $this->angle); 

     $vcenter = round((imagesy($this->img)/2) + ($box['height']/2)); 
     $hcenter = round((imagesx($this->img) - $box['width'])/2); 

     imagettftext($this->img, $font_size, $this->angle, $hcenter, $vcenter, $this->blacktr, $this->font, $this->string);  
     imagettftext($this->img, $font_size, $this->angle, $hcenter+1, $vcenter-2, $this->whitetr, $this->font, $this->string); 
    } 
} 
?> 

また、私は受け入れられた答えを使用していますが、比率を保持しない場合もあります。私はフォーラムでいくつかの良い答えを見つけて一緒に入れて、最終的にイメージをサイズ変更するクラスを作成しました。余分な関数として、透かしテキストを置くことができます。

新しい画像に透明な領域が追加されない場合は、クロップするかどうかを確認することができます。

この例は尋ねられる以上のものですが、私はそれが良い例だと思います。ここで

+0

これは良い機能と思われますが、意図したとおりに動作しますが、いつでも私の目的地の画像が500 400である場合はどうでしょうか: // W400 H300 = stretchW |ストレッチH //最初にW400 H500 =ストレッチW + H次にクロップH // W500 H300 =最初にストレッチW + H次にクロップW // W500 H500 = cropW | cropH –

+0

私はあなたのことをはっきりと理解していませんでしたが、機能は機能しています。あなたは切り抜くかどうかを選ぶことができます。あなたのページで関数を使うときは、デフォルト値を "true"に設定します。もしあなたがいくつかの変更でよりうまく動作するようにすることができれば歓迎です。 私はPHP/Webマスターではなく、ただの愛好家です。 – coban

-1

は、私は、スケールアップ&スケールダウン、サムネイルのような最も一般的な操作が含まれるアスペクト比を維持し、ファイルの種類、変更品質/ファイルサイズなどを変換するために、それに懸命に働いた包括的なアプリケーションは

...です
<?php 
//##// Resize (and convert) image (Scale up & scale down, thumbnail, preserve aspect ratio) //##// 
/////////////////////////////////////////////// 
///////////////// Begin.Setup ///////////////// 
// Source File: 
$src_file = "/your/server/path/to/file.png";// png or jpg files only 

// Resize Dimensions: 
// leave blank for no size change (convert only) 
// if you specify one dimension, the other dimension will be calculated according to the aspect ratio 
// if you specify both dimensions system will take care of it depending on the actual image size 
// $newWidth = 2000; 
// $newHeight = 1500; 

// Destination Path: (optional, if none: download image) 
$dst_path = "/your/server/path/new/"; 

// Destination File Name: (Leave blank for same file name) 
// $dst_name = 'image_name_only_no_extension'; 

// Destination File Type: (Leave blank for same file extension) 
// $dst_type = 'png'; 
$dst_type = 'jpg'; 

// Reduce to 8bit - 256 colors (Very low quality but very small file & transparent PNG. Only for thumbnails!) 
// $palette_8bit = true; 

///////////////// End.Setup ///////////////// 
/////////////////////////////////////////////// 
if (!$dst_name){$dst_name = strtolower(pathinfo($src_file, PATHINFO_FILENAME));} 
if (!$dst_type){$dst_type = strtolower(pathinfo($src_file, PATHINFO_EXTENSION));} 
if ($palette_8bit){$dst_type = 'png';} 
if ($dst_path){$dst_file = $dst_path . $dst_name . '.' . $dst_type;} 

$mime = getimagesize($src_file);// Get image dimensions and type 

// Destination File Parameters: 
if ($dst_type == 'png'){ 
    $dst_content = 'image/png'; 
    $quality = 9;// All same quality! 0 too big file // 0(no comp.)-9 (php default: 6) 
} elseif ($dst_type == 'jpg'){ 
    $dst_content = 'image/jpg'; 
    $quality = 85;// 30 Min. 60 Mid. 85 Cool. 90 Max. (100 Full) // 0-100 (php default: 75) 
} else { 
    exit('Unknown Destination File Type'); 
} 

// Source File Parameters: 
if ($mime['mime']=='image/png'){$src_img = imagecreatefrompng($src_file);} 
elseif ($mime['mime']=='image/jpg'){$src_img = imagecreatefromjpeg($src_file);} 
elseif ($mime['mime']=='image/jpeg'){$src_img = imagecreatefromjpeg($src_file);} 
elseif ($mime['mime']=='image/pjpeg'){$src_img = imagecreatefromjpeg($src_file);} 
else {exit('Unknown Source File Type');} 

// Define Dimensions: 
$old_x = imageSX($src_img); 
$old_y = imageSY($src_img); 

if ($newWidth AND $newHeight){ 
    if($old_x > $old_y){ 
     $new_x = $newWidth; 
     $new_y = $old_y/$old_x * $newWidth; 
    } elseif($old_x < $old_y){ 
     $new_y = $newHeight; 
     $new_x = $old_x/$old_y * $newHeight; 
    } elseif($old_x == $old_y){ 
     $new_x = $newWidth; 
     $new_y = $newHeight; 
    } 
} elseif ($newWidth){ 
    $new_x = $newWidth; 
    $new_y = $old_y/$old_x * $newWidth; 
} elseif ($newHeight){ 
    $new_y = $newHeight; 
    $new_x = $old_x/$old_y * $newHeight; 
} else { 
    $new_x = $old_x; 
    $new_y = $old_y; 
} 

$dst_img = ImageCreateTrueColor($new_x, $new_y); 

if ($palette_8bit){//////// Reduce to 8bit - 256 colors //////// 
    $transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127); 
    imagecolortransparent($dst_img, $transparent); 
    imagefill($dst_img, 0, 0, $transparent); 
    imagecopyresampled($dst_img,$src_img,0,0,0,0,$new_x,$new_y,$old_x,$old_y);// Great quality resize. 
    imagetruecolortopalette($dst_img, false, 255); 
    imagesavealpha($dst_img, true); 
} else { 
    // Check image and set transparent for png or white background for jpg 
    if ($dst_type == 'png'){ 
     imagealphablending($dst_img, false); 
     imagesavealpha($dst_img, true); 
     $transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127); 
     imagefilledrectangle($dst_img, 0, 0, $new_x, $new_y, $transparent); 
    } elseif ($dst_type == 'jpg'){ 
     $white = imagecolorallocate($dst_img, 255, 255, 255); 
     imagefilledrectangle($dst_img, 0, 0, $new_x, $new_y, $white); 
    } 

    imagecopyresampled($dst_img,$src_img,0,0,0,0,$new_x,$new_y,$old_x,$old_y);// Great quality resize. 
} 

// Skip the save to parameter using NULL, then set the quality; imagejpeg($dst_img);=> Default quality 
if ($dst_file){ 
    if ($dst_type == 'png'){ 
     imagepng($dst_img, $dst_file, $quality); 
    } elseif ($dst_type == 'jpg'){ 
     imagejpeg($dst_img, $dst_file, $quality); 
    } 
} else { 
    header('Content-Disposition: Attachment;filename=' . $dst_name . '.' . $dst_type);// comment this line to show image in browser instead of download 
    header('Content-type: ' . $dst_content); 
    if ($dst_type == 'png'){ 
     imagepng($dst_img, NULL, $quality); 
    } elseif ($dst_type == 'jpg'){ 
     imagejpeg($dst_img, NULL, $quality); 
    } 
} 
imagedestroy($src_img); 
imagedestroy($dst_img); 
//##// END : Resize image (Scale Up & Down) (thumbnail, bigger image, preserve aspect ratio) END //##// 
+0

これは非常に高度なスクリプトで、私は一番のものをカバーして完璧にするよう努力しました。私はdownvoteに気づいた、あなたは実際にそれを試してみましたか?それについて何か間違っている場合は教えてください.... – Tarik

0

私はあなたの画像を比例的にサイズ変更できる除数を探していることは知っています。チェックこのdemo

数学

は、私たちの元の画像は、幅xと高さyを持っていると仮定することができます私たちの除数を取得する方法。 x = 300、y = 700

最大高さと最大幅は200です。

まず、画像のどの寸法が他の寸法より大きいかを確認します。 高さ(y)が幅(x)より大きい

次に、高さが私たちの最大高さよりも大きいかどうかを確認します。 私たちの場合、高さは最大高さよりも大きいです。最高の高さよりも少ない場合は、新しい高さを元の高さに設定します。それより大きな高さより

if ($width > $height) { 
    if($width < $max_width) 
     $newwidth = $width; 

    else 

    $newwidth = $max_width; 


    $divisor = $width/$newwidth; 
    $newheight = floor($height/$divisor); 
} 
else { 

    if($height < $max_height) 
     $newheight = $height; 
    else 
     $newheight = $max_height; 

    $divisor = $height/$newheight; 
    $newwidth = floor($width/$divisor); 
} 

は完全な例を参照してくださいworking demoを使用して、それをしようとした場合の幅のために

if y is set to maximum height 200 and max-y=200; 
y=max-y, that is 
if y=max-y 
what about 
x=? 
that is, 
if 700 is resized to 200 
what about 300? 
700=200 
300=? 
new width = (200 (new height) * 300(width))/700 (height) 
so our divisor is 
divisor= new height (300)/height(700) 
new width = divisor * width or width/(1/divisor) 

およびその逆の下に示すように

最後に、私たちは除数を探します。

関連する問題