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

PHP 圖片處理實戰:等比縮放與智能裁剪完整代碼方案

     編輯:PHP 相關知識

PHP 圖片處理實戰:等比縮放與智能裁剪完整代碼方案

在 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;
}

進階優化建議

  • WebP 支援:添加 imagecreatefromwebp 和 imagewebp 處理現代格式。
  • 內存管理:大圖處理前調整 ini_set('memory_limit', '256M'),及時 imagedestroy 釋放資源。
  • 錯誤處理:檢查 GD 擴展是否加載,捕獲 imagecreatefrom* 返回 false 的情況。
  • 性能提升:高併發場景考慮使用 ImageMagick (Imagick 擴展) 或異步隊列處理。

這兩個函數結合使用,即可覆蓋從商品圖縮略圖到用戶頭像裁剪的絕大多數業務場景,代碼結構清晰,易於維護擴展。

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