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

PHP等比例縮放圖片生成縮略圖完整代碼實現

     編輯:PHP 相關知識

PHP GD 庫實現高質量等比例縮略圖生成

本文封裝一個健壯的 createSmallImg() 函數,支持 JPEG/PNG/GIF 格式、指定最大寬/高單邊限制、保持原圖比例、輸出質量控制、錯誤處理,可直接用於項目中。

核心函數功能特性

  • 單邊限制:僅傳 `$maxWidth` 或 `$maxHeight` 其一,另一邊自動計算。
  • 格式自適應:根據副檔名自動調用對應 `imagecreatefrom*` / `image*` 函數。
  • 真彩色支持:JPG/PNG 使用 `imagecreatetruecolor` 避免調色板失真。
  • 高質量重採樣:使用 `imagecopyresampled` 而非 `resized`,縮放平滑無鋸齒。
  • 命名規範:原文件名 + 後綴 (默認 `_s`) + 原副檔名,如 `photo_s.jpg`。

完整可用代碼

<?php
/**
 * 創建等比例縮略圖
 * @param string $dir 圖片目錄絕對路徑 (結尾帶 /)
 * @param string $sourceImg 源文件名 (如 photo.jpg)
 * @param string $suffix 縮略圖文件名後綴 (默認 _s)
 * @param int $maxWidth 最大寬度 (像素),與 maxHeight 二擇一
 * @param int $maxHeight 最大高度 (像素),與 maxWidth 二擇一
 * @return string|false 成功返回縮略圖相對路徑,失敗返回 false
 */
function createSmallImg($dir, $sourceImg, $suffix = '_s', $maxWidth = 0, $maxHeight = 0) {
    // 1. 參數校驗
    if (($maxWidth <= 0 && $maxHeight <= 0) || ($maxWidth > 0 && $maxHeight > 0)) {
        trigger_error('必須且只能指定 maxWidth 或 maxHeight 其中一項', E_USER_WARNING);
        return false;
    }
    $sourcePath = $dir . $sourceImg;
    if (!is_file($sourcePath) || !is_readable($sourcePath)) {
        trigger_error("源文件不存在或不可讀: $sourcePath", E_USER_WARNING);
        return false;
    }

    // 2. 解析文件信息
    $info = pathinfo($sourceImg);
    $filename = $info['filename']; // PHP 5.2+ 無 filename 鍵,兼容寫法見下
    if (!isset($filename)) {
        $filename = substr($sourceImg, 0, strrpos($sourceImg, '.'));
    }
    $ext = strtolower($info['extension'] ?? '');
    $allowed = ['jpg', 'jpeg', 'png', 'gif'];
    if (!in_array($ext, $allowed)) {
        trigger_error("不支持的圖片格式: $ext", E_USER_WARNING);
        return false;
    }
    // 統一 jpeg 副檔名
    $extOut = ($ext === 'jpeg') ? 'jpg' : $ext;

    // 3. 創建源圖資源
    $createFunc = "imagecreatefrom$extOut";
    if ($extOut === 'jpg') $createFunc = 'imagecreatefromjpeg';
    if (!function_exists($createFunc)) {
        trigger_error("GD 庫未編譯 $extOut 支持", E_USER_WARNING);
        return false;
    }
    $srcImg = @$createFunc($sourcePath);
    if (!$srcImg) {
        trigger_error("源圖資源創建失敗 (可能文件損壞): $sourcePath", E_USER_WARNING);
        return false;
    }

    $srcW = imagesx($srcImg);
    $srcH = imagesy($srcImg);

    // 4. 計算目標尺寸
    if ($maxHeight > 0 && $srcH >= $maxHeight) {
        $dstH = $maxHeight;
        $dstW = (int)round($srcW * $dstH / $srcH);
    } elseif ($maxWidth > 0 && $srcW >= $maxWidth) {
        $dstW = $maxWidth;
        $dstH = (int)round($srcH * $dstW / $srcW);
    } else {
        // 原圖已小於限制,無需縮放,直接複製或返回原路徑
        imagedestroy($srcImg);
        return $sourceImg; // 或按需複製文件
    }

    // 5. 創建目標真彩色畫布
    $dstImg = imagecreatetruecolor($dstW, $dstH);

    // PNG/GIF 透明度保持
    if ($extOut === 'png' || $extOut === 'gif') {
        imagealphablending($dstImg, false);
        imagesavealpha($dstImg, true);
        $transparent = imagecolorallocatealpha($dstImg, 255, 255, 255, 127);
        imagefilledrectangle($dstImg, 0, 0, $dstW, $dstH, $transparent);
    }

    // 6. 高質量重採樣縮放
    if (!imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH)) {
        imagedestroy($srcImg);
        imagedestroy($dstImg);
        trigger_error('圖片重採樣失敗', E_USER_WARNING);
        return false;
    }

    // 7. 輸出保存
    $destName = $filename . $suffix . '.' . $extOut;
    $destPath = $dir . $destName;
    $saveFunc = "image$extOut";
    if ($extOut === 'jpg') $saveFunc = 'imagejpeg';
    
    $result = false;
    if ($extOut === 'jpg') {
        $result = @$saveFunc($dstImg, $destPath, 90); // 質量 90%
    } else {
        $result = @$saveFunc($dstImg, $destPath);
    }

    // 8. 清理資源
    imagedestroy($srcImg);
    imagedestroy($dstImg);

    if (!$result) {
        trigger_error("縮略圖保存失敗: $destPath", E_USER_WARNING);
        return false;
    }
    return $destName; // 返回文件名,便於構建 URL
}

// --- 使用示例 ---
// 目錄結構: /var/www/html/uploads/photo.jpg
$uploadDir = '/var/www/html/uploads/';
// 生成寬度不超過 300px 的縮略圖
$thumb = createSmallImg($uploadDir, 'photo.jpg', '_thumb', 300, 0);
if ($thumb) {
    echo "成功: ";
} else {
    echo "失敗,查看 error_log";
}
?>

進階擴展建議

  1. 裁剪模式 (Crop):添加 `$mode = 'fit' | 'crop' | 'stretch'` 參數,`crop` 模式下先縮放填滿短邊,再居中裁剪長邊多餘部分 (適合正方形頭像)。
  2. WebP 支持:檢測 `function_exists('imagecreatefromwebp')`,添加 `webp` 到允許列表,輸出 `imagewebp($dstImg, $path, 85)`。
  3. Intervention/Image 庫:現代項目建議使用 Composer 包 `intervention/image`,支持鏈式調用、水印、濾鏡、緩存,底層自動選擇 GD/Imagick。
  4. 異步處理:上傳後推送消息隊列,Worker 進程處理縮略圖,避免阻塞 HTTP 響應。

常見錯誤排查

現象原因解決
生成的圖片是黑色/空白未處理 PNG/GIF 透明通道添加 `imagealphablending(false); imagesavealpha(true);` 及透明色填充
報錯 Call to undefined function imagecreatefromjpeg()PHP 編譯時未加 `--with-jpeg-dir`重新編譯 PHP 或安裝 `php-gd` 擴展包 (yum/dnf/apt)
內存耗盡 Fatal error超大圖片 (如 5000x5000) 解碼佔用巨大內存預先檢查 `getimagesize()` 尺寸,拒絕超限圖片;或用 Imagick 流式處理
輸出文件 0 字節目錄不可寫、磁盤滿、GD 輸出失敗檢查 `is_writable($dir)`、磁盤空間、error_log
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved