首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 批量生成多規格縮略圖:INI 配置驅動的靈活方案

     編輯:PHP 相關知識

前言

電商、CMS、圖床等系統常需為一張原圖生成多種尺寸的縮略圖(如列表圖、詳情圖、手機端適配圖等)。硬編碼尺寸不僅維護困難,還難以應對頻繁變更的業務需求。本文介紹一種「INI 配置 + 類別驅動」的批量生成方案,實現尺寸策略與代碼邏輯分離,新增規格只需修改配置文件。

架構設計

  • 配置文件 (image.ini.php):定義各類別的目標寬高,支持「固定寬高」「固定寬自適應高」「固定高自適應寬」「原圖輸出」四種模式。
  • 核心腳本:解析配置,遍歷類別,按策略計算目標尺寸,調用 GD 庫生成縮略圖並按命名規則保存。
  • 命名規則:{原文件名}_{類別名}.{後綴},如 photo_translation.jpg、photo_autoheight.jpg。

配置文件示例 (image.ini.php)

<?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');

關鍵技術點解析

1. parse_ini_file() 解析多 Section 配置

parse_ini_file($file, true) 返回二維數組 ['section_name' => ['key' => 'value', ...], ...],完美映射「類別 → 尺寸策略」。配置文件以 <?php /* ... */ ?> 包裹,直接訪問返回空白,保護配置不被瀏覽器下載。

2. 四種縮放策略的統一計算邏輯

策略配置計算公式適用場景
固定寬高width>0, height>0直接使用強制規範尺寸,如頭像、Banner
固寬自適應高width>0, height=0h = w / ratio列表圖、卡片圖,寬度固定
固高自適應寬width=0, height>0w = h * ratio瀑布流、手機端全寬圖
原圖輸出width=0, height=0w=src_w, h=src_h備份、格式轉換

3. 透明度保持處理

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);

否則透明區域會變黑或變白。

4. 內存管理

每生成一張縮略圖即 imagedestroy($dst_img),最後 imagedestroy($src_img),避免批量處理大圖時內存溢出。

擴展建議

  • 添加水印:在 imagecopyresampled() 後調用 imagettftext() 或 imagecopy() 疊加水印。
  • 支持 WebP 輸出:配置中添加 output_format = webp,調用 imagewebp($dst_img, $path, 85),體積減少 30%+。
  • 異步隊列:大文件/高併發場景下,將生成任務推入 Redis/RabbitMQ,Worker 進程消費處理。
  • CDN 回源預熱:生成完成後自動推送至 CDN 或刷新緩存。

總結

「INI 配置驅動 + 批量生成」模式將尺寸策略外部化,業務調整無需改動代碼,極大降低維護成本。核心邏輯僅 50 行左右,涵蓋配置解析、尺寸計算、重採樣、透明度保持、多格式輸出,是一個生產可用、易於擴展的縮略圖生成方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved