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

PHP 圖片處理封裝類:水印、縮圖、裁切、輸出儲存一站式方案

     編輯:PHP 相關知識

GD 庫物件導向封裝,四步驟統一流程:開啟→操作→輸出→銷毀

將重複的 GD 圖片操作封裝為 `Image` 類別,提供文字水印、圖片水印、縮略圖生成、區域裁切、直接輸出/儲存等功能,自動管理資源生命週期,避免記憶體洩漏。

完整類別程式碼

<?php
class Image {
    private $resource;
    private $info;
    public $type;  // 副檔名:jpg, png, gif...

    public function __construct(string $src) {
        $this->info = @getimagesize($src);
        if (!$this->info) throw new InvalidArgumentException("Invalid image: $src");
        
        $this->type = image_type_to_extension($this->info[2], false); // jpg, png, gif...
        $func = "imagecreatefrom{$this->type}";
        if (!function_exists($func)) throw new RuntimeException("Unsupported image type: {$this->type}");
        
        $this->resource = $func($src);
        if (!$this->resource) throw new RuntimeException("Failed to create image resource from: $src");
    }

    /** 文字水印 */
    public function textWatermark(string $fontFile, string $text, int $size, array $color, array $position, int $angle = 0): self {
        $color = imagecolorallocatealpha($this->resource, $color[0], $color[1], $color[2], $color[3] ?? 0);
        imagettftext($this->resource, $size, $angle, $position[0], $position[1], $color, $fontFile, $text);
        return $this;
    }

    /** 圖片水印 */
    public function imageWatermark(string $watermarkPath, array $dstPos, int $opacity = 50): self {
        $wmInfo = @getimagesize($watermarkPath);
        if (!$wmInfo) throw new InvalidArgumentException("Invalid watermark: $watermarkPath");
        
        $wmType = image_type_to_extension($wmInfo[2], false);
        $createFunc = "imagecreatefrom{$wmType}";
        $watermark = $createFunc($watermarkPath);
        
        imagecopymerge($this->resource, $watermark, $dstPos[0], $dstPos[1], 0, 0, $wmInfo[0], $wmInfo[1], $opacity);
        imagedestroy($watermark);
        return $this;
    }

    /** 縮略圖(等比縮放) */
    public function thumbnail(int $maxWidth, int $maxHeight): self {
        $srcW = $this->info[0];
        $srcH = $this->info[1];
        
        $ratio = min($maxWidth / $srcW, $maxHeight / $srcH);
        $newW = (int)($srcW * $ratio);
        $newH = (int)($srcH * $ratio);
        
        $thumb = imagecreatetruecolor($newW, $newH);
        // 保持透明度(PNG/GIF)
        if ($this->type === 'png' || $this->type === 'gif') {
            imagealphablending($thumb, false);
            imagesavealpha($thumb, true);
            $transparent = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
            imagefill($thumb, 0, 0, $transparent);
        }
        
        imagecopyresampled($thumb, $this->resource, 0, 0, 0, 0, $newW, $newH, $srcW, $srcH);
        imagedestroy($this->resource);
        $this->resource = $thumb;
        $this->info[0] = $newW;
        $this->info[1] = $newH;
        return $this;
    }

    /** 裁切(固定尺寸,從指定座標) */
    public function crop(int $width, int $height, int $srcX = 0, int $srcY = 0): self {
        $crop = imagecreatetruecolor($width, $height);
        if ($this->type === 'png' || $this->type === 'gif') {
            imagealphablending($crop, false);
            imagesavealpha($crop, true);
        }
        imagecopyresampled($crop, $this->resource, 0, 0, $srcX, $srcY, $width, $height, $width, $height);
        imagedestroy($this->resource);
        $this->resource = $crop;
        $this->info[0] = $width;
        $this->info[1] = $height;
        return $this;
    }

    /** 直接輸出到瀏覽器 */
    public function output(): void {
        header("Content-Type: {$this->info['mime']}");
        $func = "image{$this->type}";
        $func($this->resource);
    }

    /** 儲存到檔案 */
    public function save(string $destPath): bool {
        $func = "image{$this->type}";
        return $func($this->resource, $destPath);
    }

    /** 取得資源(進階操作) */
    public function getResource() { return $this->resource; }

    /** 取得資訊 */
    public function getInfo() { return $this->info; }

    public function __destruct() {
        if ($this->resource) imagedestroy($this->resource);
    }
}
?>

使用範例

<?php
require 'Image.php';

try {
    // 1. 基本縮圖 + 文字水印
    $img = new Image('photo.jpg');
    $img->thumbnail(800, 600)
        ->textWatermark('font.ttf', '© MySite 2024', 20, [255,255,255,50], [20, 20])
        ->save('thumb_watermarked.jpg');

    // 2. 圖片水印(Logo)
    $img2 = new Image('banner.png');
    $img2->imageWatermark('logo.png', [10, 10], 70)
         ->output(); // 直接輸出瀏覽器

    // 3. 裁切正方形頭像
    $avatar = new Image('upload.jpg');
    $avatar->crop(200, 200, 50, 30) // 從 (50,30) 裁切 200x200
           ->save('avatar_200.jpg');

    // 4. 鏈式操作:縮圖 → 水印 → 裁切 → 儲存
    new Image('source.jpg')
        ->thumbnail(1200, 800)
        ->textWatermark('font.ttf', 'Watermark', 30, [0,0,0,30], [30, 30])
        ->crop(400, 300, 100, 50)
        ->save('final.jpg');

} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}
?>

進階擴充建議

功能實作方向
智能裁切偵測人臉/主體區域(OpenCV/模型)自動計算裁切座標
多格式輸出WebP、AVIF 支援(需 GD 編譯支援或用 Imagick)
圖片壓縮品質`imagejpeg($res, $path, 85)` 品質參數控制
EXIF 保留/移除隱私保護:上傳頭像自動剝離 EXIF
Imagick 適配器大圖/多幀/複雜濾鏡用 Imagick,介面統一

資源管理重點

  • 建構子建立資源,解構子 `__destruct` 保證銷毀
  • 每次操作回傳 `$this` 支援鏈式呼叫
  • 縮圖/裁切會建立新資源,舊資源立即銷毀
  • 透明度處理:`imagealphablending(false)` + `imagesavealpha(true)`
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved