/**
 * create thumbnail
 * @param  $src string  pic path
 * @param  $w int  thumbnail width
 * @param  $h  int  thumbnail height
 * @return   thmbnail path
 * @demo
 * $src=thumbnail("/upload/1.jpg"); //return /upload/1_thumb.jpg
 *  * **/
function thumbnail($src,$w=100,$h=100)
{
//获取图像路径的信息
$pathinfo=pathinfo($src);
//设定缩略图文件名
$new_img_src="{$pathinfo["dirname"]}/{$pathinfo["filename"]}_thumb.{$pathinfo["extension"]}";
 $pic_info=getimagesize($src);
 
 //判断图片类型。从现有的图像创建一个图像
 //注意:如果用mime来判断图片类型,未必准确。比如你用swfupload来上传的图片,其mime是application/octet-stream
 switch ($pic_info["mime"])
 {
  case "image/gif":
  $img=imagecreatefromgif($src);
  break;
  case "image/pjpeg":
  case "image/jpeg":
  $img=imagecreatefromjpeg($src);
  break;
  case "image/png":
  case "image/x-png":
  $img=imagecreatefrompng($src);
  break;
  default:
  return false;
 }
//获取文件宽度和高度
$width = imagesx($img);
$height = imagesy($img);

// 设定画布宽和高,也就是缩略图的
$target_width = $w;
$target_height = $h;

//画布图宽高比
$target_ratio = $target_width / $target_height;
//原图宽高比
$img_ratio = $width / $height;

/**
 * 这里要将原图缩放到指定的宽度和高度,那么就出现一些问题
 * 比如说,缩略图宽和高的比例是4:3,而原图实际比例是5:3
 * 但是想要缩放之后,保证原图不变形,不裁剪图形,就得需要判断了。
 * 
 * 下面用通俗的例子来说明 后面的代码的作用。
 * 打开photoshop,新建一个400X300的画布
 * 情况1:
 * 原图是1000X600,
 * 那么要将原图缩放到400X300大小
 * (1)按照画布高度进行缩放,缩放的实际尺寸将是500X300,
 * 如果将个缩放后的图片放置到一个只有400X300的画布上面,问题出来了,实际缩放宽度大于画布的宽度,部分不可见 
 * 
 * (2)按照宽度缩放,那么实际缩放尺寸是400X240。这个时候再将其放置于画布上,
 * 正好,全部可见,没有变形,放到画布上全部可见
 * 
 * 因此这样的情况必须按照宽度缩放
 * 
 * 情况2:
 * 假设缩略图比例是4:3,缩放尺寸是400X300,原图大小是600X1000
 *  (1) 按照高度缩放。原图缩放的实际尺寸是180X300,
 *  (2)  按照宽度缩放 原图缩放的实际尺寸是400X666.7 已经超出了画布大小
 * 
 * 这样的情况得按照高度缩放
 * 

 * **/

//根据缩略图比例计算实际缩放的宽度和高度
if ($target_ratio > $img_ratio) {
//按高度缩放,即上面的情况2,$target_ratio=4/3. $img_ratio=3/5
$new_height = $target_height;//$new_height=300
$new_width = $img_ratio * $target_height;//$new_width=(3/5)*300=180
} else {
//按照宽度缩放,即上面的情况1 $target_ratio=4/3. $img_ratio=5/3
$new_height = $target_width / $img_ratio; //$new_height=400/(5/3)=240
$new_width = $target_width;//$new_width=400
} /**
 *  通过上面的部分的代码,得到实际缩放的尺寸,但是没涉及到等比缩放的问题。
 * 下面部分代码就是等比的情况,也就是缩略图比例与原图比例相等,当然这里的原图实际大于缩略图
 * **/
 
if ($new_height > $target_height) {
$new_height = $target_height;
}
if ($new_width > $target_width) {
$new_height = $target_width;
}

//创建画布并填充背景色
$new_img = Imagecreatetruecolor($target_width, $target_height);
$white=imagecolorallocate($new_img,255,255,255);
imagefilledrectangle($new_img, 0, 0, $target_width-1, $target_height-1, $white) ;
//imagecopyresampled — 重采样拷贝部分图像并调整大小,为了防止缩放之后宽度或者高度不足的问题,这里采取居中的做法
imagecopyresampled($new_img, $img, ($target_width-$new_width)/2, ($target_height-$new_height)/2, 0, 0, $new_width, $new_height, $width, $height);

//输出文件,质量100
imagejpeg($new_img,$new_img_src,100);
imagedestroy($new_img);
imagedestroy($img);
return $new_img_src;
}
思考一个问题:当原图的实际尺寸小于缩略图尺寸,代码又怎么写法?

解决方案 »

  1.   

    //注意:如果用mime来判断图片类型,未必准确。比如你用swfupload来上传的图片,其mime是application/octet-stream
    既然已经知道未必准确,为什么还要按 mime 来生成图片呢?
    用 imagecreatefromstring 不是更简捷
      

  2.   

    目标图的尺寸计算,这样不是清楚些?
    设:
    $w 原图宽
    $h 原图高
    $W 画布宽
    $H 画布高
    $tW 目标图宽
    $tH 目标图高if( $W * $h / $w > $H ) {
      $tW = $w * $H / $h;
      $tH = $H;
    }else {
      $tW = $W;
      $tH = $W * $h / $w;
    }