在 Web 開發中,生成縮略圖、頭像裁剪、響應式圖片適配是高頻需求。本文提供兩個生產就緒的函數:myImageResize 支援多種縮放模式,imagecropper 實現智能居中裁剪至固定尺寸,均兼容 GIF/JPEG/PNG 格式並保持透明度。
myImageResize支援三種模式:最大寬高限制、寬度固定、高度固定,自動計算目標尺寸並保持原始比例。
/**
* 圖片等比縮放
* @param string $source_path 源圖路徑
* @param int $target_width 目標寬度
* @param int $target_height 目標高度
* @param string $fixed_orig 鎖定模式:'width' | 'height' | ''(默認最大限制)
* @return string|false 成功返回新文件路徑,失敗返回 false
*/
function myImageResize($source_path, $target_width = 200, $target_height = 200, $fixed_orig = '') {
if (!file_exists($source_path)) return false;
$source_info = getimagesize($source_path);
if (!$source_info) return false;
$source_width = $source_info[0];
$source_height = $source_info[1];
$source_mime = $source_info['mime'];
$ratio_orig = $source_width / $source_height;
// 根據模式計算目標尺寸
if ($fixed_orig === 'width') {
$target_height = $target_width / $ratio_orig;
} elseif ($fixed_orig === 'height') {
$target_width = $target_height * $ratio_orig;
} else {
// 最大寬高限制模式
if ($target_width / $target_height > $ratio_orig) {
$target_width = $target_height * $ratio_orig;
} else {
$target_height = $target_width / $ratio_orig;
}
}
$target_width = (int)round($target_width);
$target_height = (int)round($target_height);
// 創建源圖資源
switch ($source_mime) {
case 'image/gif': $source_image = imagecreatefromgif($source_path); break;
case 'image/jpeg': $source_image = imagecreatefromjpeg($source_path); break;
case 'image/png': $source_image = imagecreatefrompng($source_path); break;
default: return false;
}
// 保持透明度 (GIF/PNG)
$target_image = imagecreatetruecolor($target_width, $target_height);
if ($source_mime === 'image/gif' || $source_mime === 'image/png') {
imagecolortransparent($target_image, imagecolorallocatealpha($target_image, 0, 0, 0, 127));
imagealphablending($target_image, false);
imagesavealpha($target_image, true);
}
imagecopyresampled($target_image, $source_image, 0, 0, 0, 0,
$target_width, $target_height, $source_width, $source_height);
// 生成輸出文件名
$path_parts = pathinfo($source_path);
$target_path = $path_parts['dirname'] . '/' . $path_parts['filename'] . '_new.' . $path_parts['extension'];
// 輸出 (統一輸出 JPEG 質量 90)
$result = imagejpeg($target_image, $target_path, 90);
imagedestroy($source_image);
imagedestroy($target_image);
return $result ? $target_path : false;
}
// 使用示例
myImageResize('photo.jpg', 800, 600); // 最大 800x600 等比縮放
myImageResize('photo.jpg', 300, 300, 'width'); // 寬度固定 300px
myImageResize('photo.jpg', 200, 200, 'height'); // 高度固定 200px
imagecropper將任意尺寸圖片裁剪並縮放至精確的目標尺寸,自動計算裁剪區域保持內容居中,適用於頭像、縮略圖生成。
/**
* 圖片裁剪並縮放至固定尺寸 (居中裁剪)
* @param string $source_path 源圖路徑
* @param int $target_width 目標寬度
* @param int $target_height 目標高度
* @return string|false 成功返回新文件路徑
*/
function imagecropper($source_path, $target_width, $target_height) {
if (!file_exists($source_path)) return false;
$source_info = getimagesize($source_path);
if (!$source_info) return false;
$source_width = $source_info[0];
$source_height = $source_info[1];
$source_mime = $source_info['mime'];
$source_ratio = $source_height / $source_width;
$target_ratio = $target_height / $target_width;
// 計算裁剪區域 (居中)
if ($source_ratio > $target_ratio) {
// 源圖較高,左右裁剪
$cropped_width = $source_width;
$cropped_height = $source_width * $target_ratio;
$source_x = 0;
$source_y = ($source_height - $cropped_height) / 2;
} elseif ($source_ratio < $target_ratio) {
// 源圖較寬,上下裁剪
$cropped_width = $source_height / $target_ratio;
$cropped_height = $source_height;
$source_x = ($source_width - $cropped_width) / 2;
$source_y = 0;
} else {
// 比例一致,無需裁剪
$cropped_width = $source_width;
$cropped_height = $source_height;
$source_x = 0;
$source_y = 0;
}
// 創建資源
switch ($source_mime) {
case 'image/gif': $source_image = imagecreatefromgif($source_path); break;
case 'image/jpeg': $source_image = imagecreatefromjpeg($source_path); break;
case 'image/png': $source_image = imagecreatefrompng($source_path); break;
default: return false;
}
$target_image = imagecreatetruecolor($target_width, $target_height);
$cropped_image = imagecreatetruecolor($cropped_width, $cropped_height);
// 保持透明度
if ($source_mime === 'image/gif' || $source_mime === 'image/png') {
imagecolortransparent($cropped_image, imagecolorallocatealpha($cropped_image, 0, 0, 0, 127));
imagealphablending($cropped_image, false);
imagesavealpha($cropped_image, true);
imagecolortransparent($target_image, imagecolorallocatealpha($target_image, 0, 0, 0, 127));
imagealphablending($target_image, false);
imagesavealpha($target_image, true);
}
// 1. 裁剪源圖到中間畫布
imagecopy($cropped_image, $source_image, 0, 0, $source_x, $source_y, $cropped_width, $cropped_height);
// 2. 縮放中間畫布到目標尺寸
imagecopyresampled($target_image, $cropped_image, 0, 0, 0, 0,
$target_width, $target_height, $cropped_width, $cropped_height);
// 輸出
$path_parts = pathinfo($source_path);
$target_path = $path_parts['dirname'] . '/' . $path_parts['filename'] . '_small.' . $path_parts['extension'];
$result = imagejpeg($target_image, $target_path, 90);
imagedestroy($source_image);
imagedestroy($cropped_image);
imagedestroy($target_image);
return $result ? $target_path : false;
}
imagecreatefromwebp 和 imagewebp 處理現代格式。ini_set('memory_limit', '256M'),及時 imagedestroy 釋放資源。imagecreatefrom* 返回 false 的情況。這兩個函數結合使用,即可覆蓋從商品圖縮略圖到用戶頭像裁剪的絕大多數業務場景,代碼結構清晰,易於維護擴展。