電商、CMS、圖床等系統常需為一張原圖生成多種尺寸的縮略圖(如列表圖、詳情圖、手機端適配圖等)。硬編碼尺寸不僅維護困難,還難以應對頻繁變更的業務需求。本文介紹一種「INI 配置 + 類別驅動」的批量生成方案,實現尺寸策略與代碼邏輯分離,新增規格只需修改配置文件。
{原文件名}_{類別名}.{後綴},如 photo_translation.jpg、photo_autoheight.jpg。<?php /*
; 縮略圖規格配置,PHP 解析時為註釋,直接訪問不洩露內容
; ; 為 INI 註釋符
; 等比縮放,保持原圖比例(寬高均為 0 表示不縮放,直接複製)
[translation]
width = 0
height = 0
; 強制拉伸至指定尺寸(可能變形)
[stretch]
width = 800
height = 600
; 指定寬度,高度自適應(等比縮放)
[autoheight]
width = 740
height = 0
; 指定高度,寬度自適應(等比縮放)
[autowidth]
width = 0
height = 380
*/ ?>
<?php
/**
* 批量生成縮略圖
* @param string $source_image 源圖片路徑
* @param array $classes 要生成的類別名列表,對應 INI 的 section
* @param string $suffix 輸出文件後綴(默認沿用源格式)
* @param string $ini_file 配置文件路徑
*/
function batch_create_thumbnails($source_image, array $classes, $suffix = '', $ini_file = 'image.ini.php') {
// 1. 校驗源文件
if (!file_exists($source_image)) {
throw new Exception("Source image not found: {$source_image}");
}
// 2. 獲取原圖信息
$size = getimagesize($source_image);
if ($size === false) {
throw new Exception("Invalid image file: {$source_image}");
}
$src_w = $size[0];
$src_h = $size[1];
$ratio = $src_w / $src_h; // 原圖寬高比
// 3. 解析配置
if (!file_exists($ini_file)) {
throw new Exception("INI config not found: {$ini_file}");
}
$config = parse_ini_file($ini_file, true); // true = 解析 section
// 4. 解析源文件名
$path_info = pathinfo($source_image);
$base_name = $path_info['filename'];
$dir = $path_info['dirname'] . '/';
$ext = $suffix ?: $path_info['extension'];
// 5. 載入源圖資源(根據類型)
$create_func = [
IMAGETYPE_JPEG => 'imagecreatefromjpeg',
IMAGETYPE_PNG => 'imagecreatefrompng',
IMAGETYPE_GIF => 'imagecreatefromgif',
IMAGETYPE_WEBP => 'imagecreatefromwebp',
];
$mime_to_func = [
'image/jpeg' => 'imagejpeg',
'image/png' => 'imagepng',
'image/gif' => 'imagegif',
'image/webp' => 'imagewebp',
];
$src_mime = $size['mime'] ?? '';
if (!isset($create_func[$size[2]])) {
throw new Exception("Unsupported image type: {$src_mime}");
}
$src_img = $create_func[$size[2]]($source_image);
// 6. 遍歷類別生成
foreach ($classes as $class) {
if (!isset($config[$class])) {
trigger_error("Class '{$class}' not defined in INI", E_USER_WARNING);
continue;
}
$spec = $config[$class];
$dst_w = (int)($spec['width'] ?? 0);
$dst_h = (int)($spec['height'] ?? 0);
// 計算目標尺寸
if ($dst_w > 0 && $dst_h > 0) {
// 固定寬高
} elseif ($dst_w > 0) {
// 固定寬,高自適應
$dst_h = (int)round($dst_w / $ratio);
} elseif ($dst_h > 0) {
// 固定高,寬自適應
$dst_w = (int)round($dst_h * $ratio);
} else {
// 0,0 保持原尺寸
$dst_w = $src_w;
$dst_h = $src_h;
}
// 創建目標畫布並重採樣
$dst_img = imagecreatetruecolor($dst_w, $dst_h);
// 保持透明度(PNG/GIF/WebP)
if (in_array($size[2], [IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_WEBP])) {
imagealphablending($dst_img, false);
imagesavealpha($dst_img, true);
$transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127);
imagefill($dst_img, 0, 0, $transparent);
}
imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
// 保存
$out_name = "{$base_name}_{$class}.{$ext}";
$out_path = $dir . $out_name;
$save_func = $mime_to_func[$src_mime] ?? 'imagejpeg';
$save_func($dst_img, $out_path, 90); // JPEG 品質 90
imagedestroy($dst_img);
echo "Generated: {$out_path} ({$dst_w}x{$dst_h})" . PHP_EOL;
}
imagedestroy($src_img);
}
// ===== 使用示例 =====
$source = 'product_original.jpg';
$classes = ['translation', 'autoheight', 'autowidth', 'stretch'];
batch_create_thumbnails($source, $classes, 'jpg', 'image.ini.php');
parse_ini_file($file, true) 返回二維數組 ['section_name' => ['key' => 'value', ...], ...],完美映射「類別 → 尺寸策略」。配置文件以 <?php /* ... */ ?> 包裹,直接訪問返回空白,保護配置不被瀏覽器下載。
| 策略 | 配置 | 計算公式 | 適用場景 |
|---|---|---|---|
| 固定寬高 | width>0, height>0 | 直接使用 | 強制規範尺寸,如頭像、Banner |
| 固寬自適應高 | width>0, height=0 | h = w / ratio | 列表圖、卡片圖,寬度固定 |
| 固高自適應寬 | width=0, height>0 | w = h * ratio | 瀑布流、手機端全寬圖 |
| 原圖輸出 | width=0, height=0 | w=src_w, h=src_h | 備份、格式轉換 |
PNG/GIF/WebP 可能包含透明通道,縮放時必須:
imagealphablending($dst_img, false);
imagesavealpha($dst_img, true);
$transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127);
imagefill($dst_img, 0, 0, $transparent);
否則透明區域會變黑或變白。
每生成一張縮略圖即 imagedestroy($dst_img),最後 imagedestroy($src_img),避免批量處理大圖時內存溢出。
imagecopyresampled() 後調用 imagettftext() 或 imagecopy() 疊加水印。output_format = webp,調用 imagewebp($dst_img, $path, 85),體積減少 30%+。「INI 配置驅動 + 批量生成」模式將尺寸策略外部化,業務調整無需改動代碼,極大降低維護成本。核心邏輯僅 50 行左右,涵蓋配置解析、尺寸計算、重採樣、透明度保持、多格式輸出,是一個生產可用、易於擴展的縮略圖生成方案。