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

PHP 等比例縮放圖片完整實現:GD 庫生成縮略圖、保持比例、質量控制

     編輯:PHP 綜合知識

圖片等比縮放是上傳/展示系統的基礎功能。本文提供一個生產級 imgResize() 函數,支援「指定最大寬高、自動計算比例、JPEG/PNG/GIF 格式保留、輸出質量可控、輸出到文件或瀏覽器」,附完整錯誤處理與記憶體優化。

核心函數 imgResize()

/**
 * 等比例縮放圖片
 * @param string $srcPath 源圖絕對路徑
 * @param int $maxWidth 最大寬度
 * @param int $maxHeight 最大高度
 * @param string|null $destPath 目標路徑,null 直接輸出瀏覽器
 * @param int $quality JPEG質量 0-100
 * @return bool|string 成功返回目標路徑或 true(直接輸出),失敗 false
 */
function imgResize($srcPath, $maxWidth, $maxHeight, $destPath = null, $quality = 85) {
    // 1. 檢查源文件
    if (!file_exists($srcPath) || !is_readable($srcPath)) {
        trigger_error("源文件不存在或不可讀: $srcPath", E_USER_WARNING);
        return false;
    }
    
    // 2. 獲取圖片信息
    $info = @getimagesize($srcPath);
    if (!$info) {
        trigger_error("無法識別圖片格式: $srcPath", E_USER_WARNING);
        return false;
    }
    [$srcWidth, $srcHeight, $type] = $info;
    $mime = $info['mime'];
    
    // 3. 計算目標尺寸(等比縮放)
    $ratio = min($maxWidth / $srcWidth, $maxHeight / $srcHeight);
    if ($ratio >= 1) { // 無需縮放
        $dstWidth = $srcWidth;
        $dstHeight = $srcHeight;
    } else {
        $dstWidth = (int)round($srcWidth * $ratio);
        $dstHeight = (int)round($srcHeight * $ratio);
    }
    
    // 4. 創建源圖資源
    $createFunc = "imagecreatefrom" . image_type_to_extension($type, false);
    if (!function_exists($createFunc)) {
        trigger_error("不支援的圖片類型: $mime", E_USER_WARNING);
        return false;
    }
    $srcImg = $createFunc($srcPath);
    if (!$srcImg) return false;
    
    // 5. 創建目標畫布(真彩色)
    $dstImg = imagecreatetruecolor($dstWidth, $dstHeight);
    
    // 6. 處理透明度(PNG/GIF)
    if ($type === IMAGETYPE_PNG || $type === IMAGETYPE_GIF) {
        imagealphablending($dstImg, false);
        imagesavealpha($dstImg, true);
        $transparent = imagecolorallocatealpha($dstImg, 255, 255, 255, 127);
        imagefill($dstImg, 0, 0, $transparent);
    }
    
    // 7. 重採樣縮放(高質量)
    if (!imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $dstWidth, $dstHeight, $srcWidth, $srcHeight)) {
        imagedestroy($srcImg); imagedestroy($dstImg);
        return false;
    }
    
    // 8. 輸出
    $outputFunc = "image" . ($type === IMAGETYPE_JPEG ? 'jpeg' : ($type === IMAGETYPE_PNG ? 'png' : 'gif'));
    $result = true;
    
    if ($destPath) {
        // 確保目標目錄存在
        $dir = dirname($destPath);
        if (!is_dir($dir) && !mkdir($dir, 0755, true)) {
            $result = false;
        } else {
            $result = $outputFunc($dstImg, $destPath, $quality);
        }
    } else {
        // 直接輸出瀏覽器
        header("Content-Type: $mime");
        $result = $outputFunc($dstImg, null, $quality);
    }
    
    // 9. 清理資源
    imagedestroy($srcImg);
    imagedestroy($dstImg);
    
    return $result ? ($destPath ?? true) : false;
}

使用示例

// 1. 生成縮略圖保存到文件
imgResize('/data/uploads/photo.jpg', 640, 480, '/data/thumbs/photo_thumb.jpg', 80);

// 2. 直接輸出到瀏覽器(用於 )
// thumb.php
$file = $_GET['file'] ?? '';
$allowed = ['/data/uploads/', '/data/thumbs/'];
if ($file && str_starts_with($file, $allowed)) {
    imgResize($file, 300, 200); // 直接輸出
} else {
    http_response_code(404);
}

// 3. 批量處理上傳圖片
foreach ($_FILES['photos']['tmp_name'] as $i => $tmp) {
    if ($tmp) {
        $ext = pathinfo($_FILES['photos']['name'][$i], PATHINFO_EXTENSION);
        $name = uniqid('img_') . ".$ext";
        $dest = "/data/uploads/$name";
        move_uploaded_file($tmp, $dest);
        imgResize($dest, 1200, 1200, $dest, 85); // 原圖壓縮覆蓋
        imgResize($dest, 300, 300, "/data/thumbs/$name", 80); // 生成縮略圖
    }
}

關鍵技術點解析

技術點實現細節作用
等比計算min(maxW/srcW, maxH/srcH)保證長邊不超限,短邊自適應,不變形
imagecreatetruecolor真彩色畫布(24位)避免調色板模式導致色彩失真
imagecopyresampled雙線性插值重採樣比 imagecopyresized 質量高得多
透明度保留imagealphablending + imagesavealphaPNG/GIF 透明背景不變黑
質量參數僅 JPEG 有效 (0-100)平衡體積與清晰度,80-85 通常最佳
記憶體管理及時 imagedestroy防止大量圖片處理時內存洩漏

常見問題與解決

  • 允許超大圖片:設置 ini_set('memory_limit', '256M'),或分塊處理(需 ImageMagick)
  • 保留 EXIF 方向:GD 無法自動旋轉,需讀取 EXIF Orientation 標籤手動旋轉,建議用 Intervention/Image 庫
  • 輸出 WebP:PHP 7.0+ 支援 imagewebp(),現代瀏覽器體積減 30%+
  • 高併發處理:異步隊列(Redis/RabbitMQ)+ Worker 進程處理,Web 進程即時返回

GD vs ImageMagick 選型建議

場景推薦理由
常規縮略圖、質量要求一般GDPHP 內建、無額外依賴、部署簡單
大圖、高質量、保留 EXIF、WebP、色彩管理ImageMagick (imagick 擴展)功能強、性能好、支援格式多、多線程
極高併發、雲原生對象存儲圖片處理(OSS/CDN)卸載應用服務器、無狀態、無限擴展

掌握這個 imgResize(),即可覆蓋 95% 的圖片縮放需求。建議封裝為 ImageService,統一異常處理、日誌記錄、格式轉換、存儲適配,構建可維護的圖片處理核心模組。

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