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

PHP 圖片處理類別:縮圖、裁切、圓角、旋轉/傾斜整合實作

     編輯:PHP 相關知識

前言

電商商品圖、使用者頭像、海報合成常需縮圖、裁切、圓角、旋轉等組合操作。本文解析一個 resizeimage 類別,將上述功能封裝於單一建構子流程中,支援等比縮放/裁切填滿雙模式、圓角遮罩、任意角度旋轉,適合直接整合至上傳管線或即時轉檔服務。

類別屬性與建構子

class resizeimage {
    var $type;           // 副檔名
    var $width, $height; // 原圖尺寸
    var $resize_width, $resize_height; // 目標尺寸
    var $cut;            // '1'=裁切填滿, '0'=等比含蓋
    var $srcimg;         // 來源路徑
    var $dstimg;         // 輸出路徑
    var $corner;         // 圓角半徑 (0=不圓角)
    var $im;             // GD 資源
    var $angle;          // 旋轉角度

    function resizeimage($img, $corner, $wid, $hei, $c, $corner_radius, $angle) {
        $this->srcimg = $img;
        $this->corner = $corner;           // '1'=啟用圓角
        $this->resize_width  = $wid;
        $this->resize_height = $hei;
        $this->cut = $c;                   // 裁切模式
        $this->corner_radius = $corner_radius;
        $this->angle = $angle;             // 旋轉度數

        // 偵測類型
        $this->type = strtolower(substr(strrchr($img, '.'), 1));
        $this->initi_img();                // 載入資源
        $this->dst_img();                  // 產生輸出路徑
        $this->width  = imagesx($this->im);
        $this->height = imagesy($this->im);
        $this->newimg();                   // 核心處理
        imagedestroy($this->im);
    }
}

核心處理 newimg():裁切 vs 等比

function newimg() {
    $resize_ratio = $this->resize_width / $this->resize_height;
    $ratio = $this->width / $this->height;

    if ($this->cut == '1') {
        // === 裁切填滿 (Cover) ===
        $newimg = imagecreatetruecolor($this->resize_width, $this->resize_height);

        if ($ratio >= $resize_ratio) {
            // 原圖較寬 → 以高為準縮放,左右裁切
            $srcH = $this->height;
            $srcW = $srcH * $resize_ratio;
            $srcX = ($this->width - $srcW) / 2;
            $srcY = 0;
        } else {
            // 原圖較高 → 以寬為準縮放,上下裁切
            $srcW = $this->width;
            $srcH = $srcW / $resize_ratio;
            $srcX = 0;
            $srcY = ($this->height - $srcH) / 2;
        }
        imagecopyresampled($newimg, $this->im, 0,0, $srcX,$srcY, $this->resize_width,$this->resize_height, $srcW,$srcH);

        // 圓角處理
        $tmp = $this->rounded_corner($newimg, $this->resize_width);
        imagepng($tmp, $this->dstimg);
    } else {
        // === 等比含蓋 (Contain) - 原碼未完整,此處補全 ===
        $newimg = imagecreatetruecolor($this->resize_width, $this->resize_height);
        // 白底 (JPEG) 或透明 (PNG)
        $white = imagecolorallocate($newimg, 255,255,255);
        imagefill($newimg, 0,0, $white);

        if ($ratio >= $resize_ratio) {
            // 以寬為準
            $dstW = $this->resize_width;
            $dstH = round($this->height * $dstW / $this->width);
            $dstX = 0; $dstY = ($this->resize_height - $dstH) / 2;
        } else {
            // 以高為準
            $dstH = $this->resize_height;
            $dstW = round($this->width * $dstH / $this->height);
            $dstX = ($this->resize_width - $dstW) / 2; $dstY = 0;
        }
        imagecopyresampled($newimg, $this->im, $dstX,$dstY, 0,0, $dstW,$dstH, $this->width,$this->height);

        // 旋轉
        if ($this->angle) {
            $newimg = imagerotate($newimg, $this->angle, $white);
        }
        // 圓角
        if ($this->corner == '1') $newimg = $this->rounded_corner($newimg, $this->resize_width);

        imagepng($newimg, $this->dstimg);
    }
}

圓角遮罩 rounded_corner() (補全實作)

function rounded_corner($src, $radius) {
    $w = imagesx($src); $h = imagesy($src);
    $mask = imagecreatetruecolor($w, $h);
    $transparent = imagecolorallocatealpha($mask, 0,0,0, 127);
    imagefill($mask, 0,0, $transparent);

    $white = imagecolorallocate($mask, 255,255,255);
    // 四個圓角扇形
    imagefilledellipse($mask, $radius, $radius, $radius*2, $radius*2, $white);           // 左上
    imagefilledellipse($mask, $w-$radius, $radius, $radius*2, $radius*2, $white);       // 右上
    imagefilledellipse($mask, $radius, $h-$radius, $radius*2, $radius*2, $white);       // 左下
    imagefilledellipse($mask, $w-$radius, $h-$radius, $radius*2, $radius*2, $white);    // 右下
    // 中間矩形填補
    imagefilledrectangle($mask, $radius, 0, $w-$radius, $h, $white);
    imagefilledrectangle($mask, 0, $radius, $w, $h-$radius, $white);

    // 套用遮罩
    $dst = imagecreatetruecolor($w, $h);
    imagealphablending($dst, false);
    imagesavealpha($dst, true);
    $trans = imagecolorallocatealpha($dst, 0,0,0, 127);
    imagefill($dst, 0,0, $trans);
    imagecopy($dst, $src, 0,0, 0,0, $w,$h);
    imagecopymerge($dst, $mask, 0,0, 0,0, $w,$h, 100); // 以 mask 為 alpha
    return $dst;
}

輔助方法

function initi_img() {
    switch ($this->type) {
        case 'gif':  $this->im = @imagecreatefromgif($this->srcimg); break;
        case 'jpg':
        case 'jpeg': $this->im = @imagecreatefromjpeg($this->srcimg); break;
        case 'png':  $this->im = @imagecreatefrompng($this->srcimg); break;
        default: die('不支援格式');
    }
}

function dst_img() {
    $path = dirname($this->srcimg);
    $name = basename($this->srcimg, '.'.$this->type);
    $this->dstimg = $path . '/' . $name . '_processed.png'; // 統一輸出 PNG 保留透明度
}

呼叫範例

// 1. 裁切填滿 300x300 + 圓角 20px
new resizeimage(
    'uploads/photo.jpg',  // 來源
    '1',                  // 圓角啟用
    300, 300,             // 目標尺寸
    '1',                  // 裁切模式
    20,                   // 圓角半徑
    0                     // 不旋轉
); // 輸出 uploads/photo_processed.png

// 2. 等比含蓋 400x300 + 旋轉 15° + 無圓角
new resizeimage(
    'uploads/banner.png',
    '0', 400, 300, '0', 0, 15
);

功能對照與擴充建議

功能原類別支援建議擴充
縮放模式裁切/等比新增 stretch (強制拉伸)、fit (等比含蓋含白邊)
圓角四角同半徑支援單獨四角半徑 ['tl'=>20,'tr'=>0,'br'=>20,'bl'=>0]
旋轉任意角度新增 flipH/flipV 鏡像
輸出格式固定 PNG參數化 $format, $quality
濾鏡無整合 imagefilter() (灰階、模糊、銳化)
疊加無新增 overlay($logoPath, $position, $opacity)
記憶體管理手動 destroy實作 __destruct 自動清理

現代化重構:Intervention Image 管線

use Intervention\Image\ImageManagerStatic as Image;

$img = Image::make('uploads/photo.jpg')
    ->resize(300, 300, function($c) { $c->aspectRatio(); }) // 等比
    ->resizeCanvas(300, 300, 'center', false, '#fff')       // 畫布填滿
    ->rounded(20)                                           // 圓角
    ->rotate(15, '#fff')                                    // 旋轉
    ->encode('png', 90)
    ->save('uploads/photo_processed.png');

小結

resizeimage 類別將縮放模式、圓角、旋轉整合在建構子單一流程中,雖程式碼風格較舊 (var、public 屬性、建構子做所有事),但邏輯清晰、功能實用。實務上建議採用 Intervention Image 的鏈式 API,或將每個操作封裝為獨立 Processor 類別,組合成 Pipeline,獲得更好的可測試性、可擴充性與單一職責原則遵循。

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