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

PHP 圖片裁切與縮放實戰:imagecopyresampled 參數詳解與完整範例

     編輯:PHP 綜合知識

前言

在 PHP 開發中,圖片裁切、縮圖、區域截取 是常見需求。核心函式 imagecopyresampled() 功能強大但參數眾多,初學者容易混淆「來源座標」與「目標座標」。本文將逐一拆解參數含義,並提供三種典型應用場景的完整代碼:固定區域裁切、裁切後放大、裁切後縮小。

函式簽名與參數對照表

bool imagecopyresampled(
    GdImage $dst_image,   // 目標圖片資源(輸出畫布)
    GdImage $src_image,   // 來源圖片資源
    int $dst_x,           // 目標畫布起始 X 座標
    int $dst_y,           // 目標畫布起始 Y 座標
    int $src_x,           // 來源圖片起始 X 座標(裁切區域左上角)
    int $src_y,           // 來源圖片起始 Y 座標
    int $dst_w,           // 目標畫布寬度(輸出寬度)
    int $dst_h,           // 目標畫布高度(輸出高度)
    int $src_w,           // 來源裁切區域寬度
    int $src_h            // 來源裁切區域高度
): bool

關鍵概念圖解

來源圖片 (Source)                    目標畫布 (Destination)
+-------------------------+          +-------------------------+
|                         |          |                         |
|   (src_x, src_y) ●------|--------->| ● (dst_x, dst_y)        |
|        |       |        |          |        |                |
|        | src_w |        |          |        | dst_w           |
|        |       |        |          |        |                |
|        ●-------|--------|          |        ●----------------|
|                src_h                 |                dst_h   |
+-------------------------+          +-------------------------+

流程:從來源 (src_x, src_y) 切出 src_w × src_h 區域
      → 縮放/拉伸至 dst_w × dst_h
      → 繪製到目標畫布 (dst_x, dst_y) 位置

場景一:固定區域裁切輸出(不縮放)

需求:從原圖 (7, 174) 起裁切 120×42 區域,直接輸出同尺寸圖片。

<?php
header('Content-Type: image/jpeg');

$filename = 'book_rabbit_rule.jpg';
$srcImg   = imagecreatefromjpeg($filename);

// 輸出尺寸 = 裁切尺寸
$dstW = 120;
$dstH = 42;

$dstImg = imagecreatetruecolor($dstW, $dstH); // 真彩色畫布,避免調色盤失真

// 參數對照:dst(0,0) src(7,174) 輸出120x42 來源區域120x42
imagecopyresampled($dstImg, $srcImg,
    0, 0,       // 目標起點
    7, 174,     // 來源起點(裁切左上角)
    $dstW, $dstH, // 目標寬高
    120, 42     // 來源區域寬高
);

imagejpeg($dstImg, null, 90); // 輸出瀏覽器,品質 90
imagedestroy($dstImg);
imagedestroy($srcImg);

場景二:裁切後放大至指定尺寸

需求:同樣從 (100, 30) 裁切區域,但輸出放大為 500×500。

$dstW = 500;
$dstH = 500;
$dstImg = imagecreatetruecolor($dstW, $dstH);

imagecopyresampled($dstImg, $srcImg,
    0, 0,       // 目標從 (0,0) 開始畫
    100, 30,    // 來源裁切起點
    $dstW, $dstH, // 目標大尺寸(放大)
    120, 42     // 來源區域大小(同場景一)
);

場景三:裁切後縮小生成縮圖

需求:裁切同一區域,輸出為 10×10 縮圖。

$dstW = 10;
$dstH = 10;
$dstImg = imagecreatetruecolor($dstW, $dstH);

imagecopyresampled($dstImg, $srcImg,
    0, 0,
    100, 30,
    $dstW, $dstH, // 目標小尺寸(縮小)
    120, 42
);

進階:等比例縮放生成縮圖(完整函式)

實務上常需「依最大寬高限制等比縮放」,以下為可直接復用的函式:

/**
 * 等比例縮放圖片並輸出或儲存
 * @param string $srcPath 來源圖路徑
 * @param int $maxW 最大寬度
 * @param int $maxH 最大高度
 * @param string|null $savePath 儲存路徑,null 直接輸出瀏覽器
 * @param int $quality JPEG 品質 0-100
 */
function smartResize(string $srcPath, int $maxW, int $maxH, ?string $savePath = null, int $quality = 90): bool
{
    [$srcW, $srcH, $type] = getimagesize($srcPath);
    if (!$srcW) return false;

    // 計算縮放比例
    $ratio = min($maxW / $srcW, $maxH / $srcH);
    if ($ratio >= 1) { // 原圖已小於限制,直接複製或輸出
        if ($savePath) return copy($srcPath, $savePath);
        header('Content-Type: ' . image_type_to_mime_type($type));
        readfile($srcPath);
        return true;
    }

    $dstW = (int)round($srcW * $ratio);
    $dstH = (int)round($srcH * $ratio);

    $srcImg = match ($type) {
        IMAGETYPE_JPEG => imagecreatefromjpeg($srcPath),
        IMAGETYPE_PNG  => imagecreatefrompng($srcPath),
        IMAGETYPE_GIF  => imagecreatefromgif($srcPath),
        IMAGETYPE_WEBP => imagecreatefromwebp($srcPath),
        default => throw new Exception('Unsupported image type'),
    };

    $dstImg = imagecreatetruecolor($dstW, $dstH);

    // 保持 PNG/GIF/WEBP 透明度
    if ($type !== IMAGETYPE_JPEG) {
        imagealphablending($dstImg, false);
        imagesavealpha($dstImg, true);
        $transparent = imagecolorallocatealpha($dstImg, 255, 255, 255, 127);
        imagefill($dstImg, 0, 0, $transparent);
    }

    imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);

    $result = match ($type) {
        IMAGETYPE_JPEG => imagejpeg($dstImg, $savePath, $quality),
        IMAGETYPE_PNG  => imagepng($dstImg, $savePath, 9),
        IMAGETYPE_GIF  => imagegif($dstImg, $savePath),
        IMAGETYPE_WEBP => imagewebp($dstImg, $savePath, $quality),
    };

    imagedestroy($srcImg);
    imagedestroy($dstImg);
    return $result;
}

// 使用範例
smartResize('upload/photo.jpg', 800, 600, 'thumb/photo_800x600.jpg');

常見坑點與避雷指南

問題原因解決
輸出圖片模糊/鋸齒用 imagecopyresized 而非 resampled務必用 imagecopyresampled 重採樣
PNG 透明變黑底未開啟 alpha blending見進階範例:imagesavealpha + imagealphablending
記憶體耗盡大圖直接載入分塊處理或增加 memory_limit;考慮用 Imagick
座標越界src_x + src_w > 圖寬裁切前驗證座標範圍
輸出檔案為 0 bytes未檢查 imagejpeg 回傳值檢查回傳值、確認目錄可寫入

結語

掌握 imagecopyresampled() 的「來源區域 → 目標區域」映射關係,即可靈活實現裁切、縮放、縮圖等所有圖片幾何變換。建議將常用邏輯封裝為工具類或 Helper 函式,專案中統一呼叫,減少重複代碼與錯誤。

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