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

PHP 圖片處理類實作:水印、等比縮放與固定尺寸裁切

     編輯:PHP 相關知識

PHP 圖片處理類實作:水印、等比縮放與固定尺寸裁切

在 PHP 開發中,圖片處理是常見需求,例如加浮水印、生成縮圖、固定寬高裁切等。本文分享兩個實用的 PHP 圖片處理類,分別展示基本的水印疊加、等比縮放、固定尺寸縮略圖,以及更進階的裁切壓縮、多格式支援與目錄自動建立功能。

類別一:Image_process - 基礎圖片操作

這個類別封裝了常用的圖片處理邏輯,支援 GIF、JPG、PNG 三種格式。主要功能包括:

  • 建構子自動偵測原圖尺寸與格式
  • waterMakeImage():將 Logo 置中疊加為水印
  • fixSizeImage():依指定寬高裁切(若超過原圖則保持原尺寸)
  • scaleImage():依比例縮放
  • tinyImage():核心縮圖邏輯,優先使用 imagecopyresampled 取得較佳品質
  • saveImage():統一輸出為 JPEG 格式
<?php
class Image_process {
    public $source;
    public $source_width;
    public $source_height;
    public $source_type_id;
    public $orign_name;
    public $orign_dirname;
    private $typeList = array(1=>'gif', 2=>'jpg', 3=>'png');

    public function __construct($source) {
        $ginfo = getimagesize($source);
        $this->source_width  = $ginfo[0];
        $this->source_height = $ginfo[1];
        $this->source_type_id = $ginfo[2];
        $this->orign_url = $source;
        $this->orign_name = basename($source);
        $this->orign_dirname = dirname($source);
    }

    private function judgeType($type, $source) {
        switch ($type) {
            case 1: return imagecreatefromgif($source);
            case 2: return imagecreatefromjpeg($source);
            case 3: return imagecreatefrompng($source);
            default: return false;
        }
    }

    public function waterMakeImage($logo) {
        $linfo = getimagesize($logo);
        $logo_w = $linfo[0]; $logo_h = $linfo[1]; $logo_type = $linfo[2];
        $src = $this->judgeType($this->source_type_id, $this->orign_url);
        $logoRes = $this->judgeType($logo_type, $logo);
        if (!$src || !$logoRes) return false;

        $x = ($this->source_width - $logo_w) / 2;
        $y = ($this->source_height - $logo_h) / 2;
        imagecopy($src, $logoRes, $x, $y, 0, 0, $logo_w, $logo_h);

        $newPic = $this->orign_dirname . '/water_' . time() . '.' . $this->typeList[$this->source_type_id];
        if ($this->saveImage($src, $newPic)) {
            imagedestroy($src); imagedestroy($logoRes);
        }
    }

    public function fixSizeImage($width, $height) {
        if ($width > $this->source_width)  $width  = $this->source_width;
        if ($height > $this->source_height) $height = $this->source_height;
        if ($width === false)  $width  = floor($this->source_width / ($this->source_height / $height));
        if ($height === false) $height = floor($this->source_height / ($this->source_width / $width));
        $this->tinyImage($width, $height);
    }

    public function scaleImage($scale) {
        $w = floor($this->source_width * $scale);
        $h = floor($this->source_height * $scale);
        $this->tinyImage($w, $h);
    }

    private function tinyImage($width, $height) {
        $thumb = imagecreatetruecolor($width, $height);
        $src = $this->judgeType($this->source_type_id, $this->orign_url);
        if (function_exists('imagecopyresampled')) {
            imagecopyresampled($thumb, $src, 0,0,0,0, $width,$height, $this->source_width,$this->source_height);
        } else {
            imagecopyresized($thumb, $src, 0,0,0,0, $width,$height, $this->source_width,$this->source_height);
        }
        $newPic = $this->orign_dirname . '/thumb_' . time() . '_' . $width . '_' . $height . '.' . $this->typeList[$this->source_type_id];
        if ($this->saveImage($thumb, $newPic)) {
            imagedestroy($thumb); imagedestroy($src);
        }
    }

    private function saveImage($image, $url) {
        return imagejpeg($image, $url);
    }
}

// 使用範例
$img = new Image_process('D:/AppServ/www/test/getimg/14061907445601.jpg');
// $img->waterMakeImage('D:/AppServ/www/test/getimg/shougongke.png'); // 加水印
// $img->fixSizeImage(200, 150); // 固定尺寸
$img->scaleImage(0.2); // 等比縮放 20%
?>

類別二:Img - 進階圖片處理(裁切壓縮、多格式、目錄自建)

第二個類別 Img 功能更完整,包含:

  • thumb_img():先裁切再等比縮放,避免圖片變形
  • resize_image():單純等比縮放,支援只限寬或只限高
  • water_mark():水印位置、透明度可配置
  • 自動偵測圖片格式(jpg/jpeg/gif/bmp/png)並對應 GD 函式
  • check_dir():儲存路徑不存在時自動建立目錄
  • 錯誤處理統一回傳 array('flag'=>bool, 'msg'=>string)
<?php
class Img {
    private $exts = array('jpg','jpeg','gif','bmp','png');

    public function __construct() {
        if (!function_exists('gd_info')) throw new Exception('GD庫未載入!');
    }

    // 裁切壓縮:保持比例裁切後再縮放至目標尺寸
    public function thumb_img($src_img, $save_img='', $option) {
        if (empty($option['width']) || empty($option['height'])) return array('flag'=>false,'msg'=> '尺寸不可為0');
        $org = $this->is_img($src_img); if (!$org['flag']) return $org;
        if ($save_img) { $chk = $this->check_dir($save_img); if (!$chk['flag']) return $chk; }
        $funcs = $this->get_img_funcs($org['msg']);
        $src = $funcs['create_func']($src_img);
        $sw = imagesx($src); $sh = imagesy($src);
        $dst_scale = $option['height'] / $option['width'];
        $src_scale = $sh / $sw;
        if ($src_scale >= $dst_scale) { // 過高
            $w = $sw; $h = intval($dst_scale * $w);
            $x = 0; $y = ($sh - $h) / 3;
        } else { // 過寬
            $h = $sh; $w = intval($h / $dst_scale);
            $x = ($sw - $w) / 2; $y = 0;
        }
        $crop = imagecreatetruecolor($w, $h);
        imagecopy($crop, $src, 0,0, $x,$y, $sw,$sh);
        $scale = $option['width'] / $w;
        $target = imagecreatetruecolor($option['width'], $option['height']);
        $fw = intval($w * $scale); $fh = intval($h * $scale);
        imagecopyresampled($target, $crop, 0,0,0,0, $fw,$fh, $w,$h);
        imagedestroy($crop);
        if ($save_img) $funcs['save_func']($target, $save_img);
        else { header($funcs['header']); $funcs['save_func']($target); }
        imagedestroy($target);
        return array('flag'=>true,'msg'=>'');
    }

    // 等比縮放(不裁切)
    public function resize_image($src_img, $save_img='', $option) {
        $org = $this->is_img($src_img); if (!$org['flag']) return $org;
        if ($save_img) { $chk = $this->check_dir($save_img); if (!$chk['flag']) return $chk; }
        $funcs = $this->get_img_funcs($org['msg']);
        $src = $funcs['create_func']($src_img);
        $sw = imagesx($src); $sh = imagesy($src);
        $ratio = 1;
        if (($option['width'] && $sw > $option['width']) || ($option['height'] && $sh > $option['height'])) {
            if ($option['width'] && $sw > $option['width'])  $ratio = $option['width'] / $sw;
            if ($option['height'] && $sh > $option['height']) $ratio = min($ratio, $option['height'] / $sh);
            $nw = $sw * $ratio; $nh = $sh * $ratio;
            if (function_exists('imagecopyresampled')) {
                $new = imagecreatetruecolor($nw,$nh);
                imagecopyresampled($new,$src,0,0,0,0,$nw,$nh,$sw,$sh);
            } else {
                $new = imagecreate($nw,$nh);
                imagecopyresized($new,$src,0,0,0,0,$nw,$nh,$sw,$sh);
            }
        } else { $new = $src; }
        if ($save_img) $funcs['save_func']($new,$save_img);
        else { header($funcs['header']); $funcs['save_func']($new); }
        imagedestroy($new);
        return array('flag'=>true,'msg'=>'');
    }

    // 水印:支援位置(x,y)與透明度(alpha)
    public function water_mark($org_img, $mark_img, $save_img='', $option=array()) {
        $org = $this->is_img($org_img); if (!$org['flag']) return $org;
        $mark = $this->is_img($mark_img); if (!$mark['flag']) return $mark;
        if ($save_img) { $chk = $this->check_dir($save_img); if (!$chk['flag']) return $chk; }
        $of = $this->get_img_funcs($org['msg']);
        $mf = $this->get_img_funcs($mark['msg']);
        $oim = $of['create_func']($org_img);
        $mim = $mf['create_func']($mark_img);
        $ow = imagesx($oim); $oh = imagesy($oim);
        $mw = imagesx($mim); $mh = imagesy($mim);
        $x = isset($option['x']) ? $option['x'] : $ow - $mw;
        $y = isset($option['y']) ? $option['y'] : $oh - $mh;
        $x = ($x > $ow || $x < 0) ? $ow-$mw : $x;
        $y = ($y > $oh || $y < 0) ? $oh-$mh : $y;
        $alpha = isset($option['alpha']) ? $option['alpha'] : 50;
        $alpha = ($alpha > 100 || $alpha < 0) ? 50 : $alpha;
        imagecopymerge($oim, $mim, $x, $y, 0, 0, $mw, $mh, $alpha);
        if ($save_img) $of['save_func']($oim,$save_img);
        else { header($of['header']); $of['save_func']($oim); }
        imagedestroy($oim); imagedestroy($mim);
        return array('flag'=>true,'msg'=>'');
    }

    private function is_img($path) {
        if (!file_exists($path)) return array('flag'=>false,'msg'=>"找不到檔案:$path");
        $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
        if (!in_array($ext, $this->exts)) return array('flag'=>false,'msg'=>"不支援的格式:$ext");
        return array('flag'=>true,'msg'=>$ext);
    }

    private function get_img_funcs($ext) {
        switch ($ext) {
            case 'jpg': case 'jpeg': return array('header'=>'Content-Type:image/jpeg','create_func'=>'imagecreatefromjpeg','save_func'=>'imagejpeg');
            case 'gif': return array('header'=>'Content-Type:image/gif','create_func'=>'imagecreatefromgif','save_func'=>'imagegif');
            case 'bmp': return array('header'=>'Content-Type:image/bmp','create_func'=>'imagecreatefrombmp','save_func'=>'imagebmp');
            default: return array('header'=>'Content-Type:image/png','create_func'=>'imagecreatefrompng','save_func'=>'imagepng');
        }
    }

    private function check_dir($path) {
        $dir = dirname($path);
        if (!is_dir($dir) && !mkdir($dir, 0777, true)) return array('flag'=>false,'msg'=>"無法建立目錄:$dir");
        return array('flag'=>true,'msg'=>'');
    }
}
?>

使用建議

  • 簡單專案可直接使用 Image_process,程式碼輕量易懂。
  • 需支援 BMP、自動建目錄、錯誤回傳結構化時,建議採用 Img 類別。
  • 實際部署時請確認伺服器已啟用 GD 擴展,並注意檔案寫入權限。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved