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

PHP GD庫實現圖片馬賽克與文字描邊效果完整指南

     編輯:PHP 綜合知識

前言

在 PHP 開發中,圖片處理是常見需求。GD 庫作為 PHP 內建的圖形處理擴展,提供了強大的像素級操作能力。本文將詳細介紹如何使用 PHP GD 庫實現兩項實用功能:圖片區域馬賽克處理與文字描邊(外發光)效果,並提供可直接部署的完整代碼示例。

一、圖片馬賽克功能實現

核心原理

馬賽克本質上是將指定矩形區域內的像素進行區域取樣並填充。通過設定 deep 參數控制採樣塊大小,數值越大馬賽克效果越明顯,圖像細節保留越少。

函數定義與參數說明

void imagemask(resource $image, int $x1, int $y1, int $x2, int $y2, int $deep)
  • $image:imagecreatefromjpeg() 等函數返回的圖片資源
  • $x1, $y1:矩形區域左上角座標(原點為圖片左上角 0,0)
  • $x2, $y2:矩形區域右下角座標
  • $deep:馬賽克塊大小(像素),建議 5-15 之間

完整實現代碼

<?php
/**
 * GD 圖片馬賽克處理
 * @param resource $im 圖片資源(引用傳遞)
 * @param int $x1 起始 X 座標
 * @param int $y1 起始 Y 座標
 * @param int $x2 結束 X 座標
 * @param int $y2 結束 Y 座標
 * @param int $deep 馬賽克塊大小
 */
function imagemask(&$im, $x1, $y1, $x2, $y2, $deep) {
    for ($x = $x1; $x < $x2; $x += $deep) {
        for ($y = $y1; $y < $y2; $y += $deep) {
            // 取區域中心點顏色作為填充色
            $color = imagecolorat($im, $x + round($deep / 2), $y + round($deep / 2));
            // 繪製實心矩形塊
            imagefilledrectangle($im, $x, $y, $x + $deep, $y + $deep, $color);
        }
    }
}

// 使用示例
header("Content-Type: image/png");
$im = imagecreatefromjpeg("test.jpg");
// 對座標 (57,22) 到 (103,40) 區域應用 8px 馬賽克
imagemask($im, 57, 22, 103, 40, 8);
imagepng($im);
imagedestroy($im);
?>

效果展示

馬賽克效果示例圖

二、文字描邊(外發光)效果實現

功能特點

  • 支援 TrueType 字體(.ttf/.ttc)與 GD 內建字體雙模式
  • 可自定義文字顏色、描邊顏色、字體大小、位置
  • 支援 UTF-8 多語言文字(含中文)
  • 實現原理:建立臨時畫布繪製黑色文字輪廓,再通過像素鄰域檢測在原圖繪製描邊

函數定義與參數說明

void imagetextouter(
    resource $image,
    int $size,
    int $x,
    int $y,
    string $color,
    string $fontfile,
    string $text,
    string $outercolor
)
  • $color / $outercolor:十六進制顏色格式 #RRGGBB(如 #FF0000 紅色)
  • $fontfile:字體檔案路徑;留空則使用 GD 內建字體
  • $x, $y:TTF 模式下為文字基線左下角;內建字體模式下為右上角

完整實現代碼

<?php
/**
 * GD 文字描邊繪製
 */
function imagetextouter(&$im, $size, $x, $y, $color, $fontfile, $text, $outer) {
    // 輔助函數:十六進制顏色轉 GD 色彩資源
    if (!function_exists('imagecolorallocatehex')) {
        function imagecolorallocatehex($im, $s) {
            if ($s[0] == "#") $s = substr($s, 1);
            $bg_dec = hexdec($s);
            return imagecolorallocate($im,
                ($bg_dec & 0xff0000) >> 16,
                ($bg_dec & 0x00ff00) >> 8,
                ($bg_dec & 0x0000ff)
            );
        }
    }

    $ttf = false;
    if (is_file($fontfile)) {
        $ttf = true;
        // 計算文字邊界框
        $area = imagettfbbox($size, 0, $fontfile, $text);
        $width  = $area[2] - $area[0] + 2;
        $height = $area[1] - $area[5] + 2;
    } else {
        // 內建字體估算尺寸
        $width  = strlen($text) * 10;
        $height = 16;
    }

    // 建立臨時單色畫布
    $im_tmp = imagecreate($width, $height);
    $white = imagecolorallocate($im_tmp, 255, 255, 255);
    $black = imagecolorallocate($im_tmp, 0, 0, 0);
    $color = imagecolorallocatehex($im, $color);
    $outer = imagecolorallocatehex($im, $outer);

    if ($ttf) {
        // TTF 模式:先在臨時畫布繪製黑色文字
        imagettftext($im_tmp, $size, 0, 0, $height - 2, $black, $fontfile, $text);
        // 在目標圖片繪製主文字
        imagettftext($im, $size, 0, $x, $y, $color, $fontfile, $text);
        $y = $y - $height + 2; // 調整描邊起始 Y 座標
    } else {
        // 內建字體模式
        imagestring($im_tmp, $size, 0, 0, $text, $black);
        imagestring($im, $size, $x, $y, $text, $color);
    }

    // 掃描臨時畫布,檢測文字像素鄰域並在原圖繪製描邊
    for ($i = 0; $i < $width; $i++) {
        for ($j = 0; $j < $height; $j++) {
            $c = imagecolorat($im_tmp, $i, $j);
            if ($c !== $white) {
                // 四向鄰域檢測(上下左右)
                imagecolorat($im_tmp, $i, $j - 1) != $white || imagesetpixel($im, $x + $i, $y + $j - 1, $outer);
                imagecolorat($im_tmp, $i, $j + 1) != $white || imagesetpixel($im, $x + $i, $y + $j + 1, $outer);
                imagecolorat($im_tmp, $i - 1, $j) != $white || imagesetpixel($im, $x + $i - 1, $y + $j, $outer);
                imagecolorat($im_tmp, $i + 1, $j) != $white || imagesetpixel($im, $x + $i + 1, $y + $j, $outer);
                
                /* 
                 * 取消註釋可啟用八向鄰域(含對角線),效果類似 Fireworks 發光
                 * imagecolorat($im_tmp, $i - 1, $j - 1) != $white || imagesetpixel($im, $x + $i - 1, $y + $j - 1, $outer);
                 * imagecolorat($im_tmp, $i + 1, $j - 1) != $white || imagesetpixel($im, $x + $i + 1, $y + $j - 1, $outer);
                 * imagecolorat($im_tmp, $i - 1, $j + 1) != $white || imagesetpixel($im, $x + $i - 1, $y + $j + 1, $outer);
                 * imagecolorat($im_tmp, $i + 1, $j + 1) != $white || imagesetpixel($im, $x + $i + 1, $y + $j + 1, $outer);
                 */
            }
        }
    }
    imagedestroy($im_tmp);
}

// 使用示例
header("Content-Type: image/png");
$im = imagecreatefromjpeg("bluesky.jpg");
// TTF 字體模式:黑字白描邊
imagetextouter($im, 9, 10, 20, '#000000', "simsun.ttc", '新年快樂', '#ffffff');
// 內建字體模式:黃字藍描邊
imagetextouter($im, 2, 10, 30, '#ffff00', "", 'hello, world!', '#103993');
imagepng($im);
imagedestroy($im);
?>

三、進階應用建議

效能優化

  • 馬賽克處理大圖時,建議先縮放再處理,或使用 imagecopyresampled() 降低解析度
  • 文字描邊的雙重繪製可封裝為類,避免重複建立臨時畫布

常見問題排查

  1. 中文顯示亂碼:確保 PHP 檔案以 UTF-8 無 BOM 編碼保存,字體檔案支援對應字符集
  2. 座標偏移:TTF 模式基線為左下角,內建字體為右上角,混用時需換算
  3. 顏色不準:imagecolorallocatehex() 僅支援 6 位十六進制,不支援縮寫 3 位格式

總結

本文提供的兩個函數 imagemask() 與 imagetextouter() 實現了 PHP GD 庫層面的馬賽克遮罩與文字描邊效果,代碼結構清晰、參數靈活,可直接整合至項目中。配合 GD 庫的其他函數(如 imagefilter()、imagecopymerge()),還能構建出水印生成、圖片編輯器等更豐富的應用場景。

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