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

PHP 圖片浮水印中文亂碼完整解決方案:字體載入、編碼轉換與實戰函式

     編輯:PHP 相關知識

前言

使用 imagettftext() 繪製中文浮水印時,若未正確載入支援中文的 TTF/OTF 字體,或字串編碼與字體預期不符,輸出畫面將出現亂碼 (□□□) 或空白。本文系統說明亂碼成因、解決步驟,並提供一個可直接使用的通用函式 str2pic()。

亂碼三大主因

原因現象解決
未載入中文字體全空白或方塊指定 simhei.ttf、msyh.ttc、NotoSansTC-Regular.otf 等含 CJK 字形的字體檔
字串編碼錯誤亂碼、錯位PHP 檔案存為 UTF-8 無 BOM,若資料來源為 GBK/Big5,先 iconv('gbk','utf-8',$str) 或 mb_convert_encoding
字體路徑錯誤PHP Warning、無輸出使用絕對路徑 __DIR__.'/fonts/xxx.ttf',確認 freetype 支援

最小可行範例

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

$text = "浮水印測試 中文"; // 檔案必須是 UTF-8
$font = __DIR__ . '/fonts/NotoSansTC-Regular.otf'; // 確認檔案存在

$im = imagecreatefromjpeg('photo.jpg');
$black = imagecolorallocate($im, 0, 0, 0);

// 關鍵:直接傳入 UTF-8 字串,不需 iconv
imagettftext($im, 24, 0, 50, 80, $black, $font, $text);

imagepng($im);
imagedestroy($im);

通用浮水印函式 str2pic()

/**
 * 為圖片加上文字浮水印 (支援中文、陰影、自訂儲存)
 *
 * @param string $string      浮水印文字 (UTF-8)
 * @param string $source      來源圖片路徑
 * @param string $destination 輸出路徑 (空則直接輸出瀏覽器)
 * @param string $fontPath    TTF/OTF 字體絕對路徑
 * @param int    $fontSize    字體大小 (pt)
 * @param string $shadowColor 陰影色 #RRGGBB
 * @param string $fontColor   字體色 #RRGGBB
 * @param int    $x           X 座標 (左上角基線)
 * @param int    $y           Y 座標 (左上角基線)
 * @return bool|string        成功回傳輸出路徑或 true,失敗 false
 */
function str2pic(
    $string, $source, $destination='',
    $fontPath, $fontSize=20,
    $shadowColor='#ffffff', $fontColor='#000000',
    $x=10, $y=30
) {
    // 1. 載入來源圖片
    $ext = strtolower(pathinfo($source, PATHINFO_EXTENSION));
    switch ($ext) {
        case 'jpg': case 'jpeg': $im = @imagecreatefromjpeg($source); break;
        case 'gif': $im = @imagecreatefromgif($source); break;
        case 'png': $im = @imagecreatefrompng($source); break;
        default: return false;
    }
    if (!$im) return false;

    // 2. 解析顏色
    $shadow = hex2rgb($shadowColor);
    $fontCol = hex2rgb($fontColor);
    $shadowCol = imagecolorallocatealpha($im, $shadow[0],$shadow[1],$shadow[2], 40); // 半透明
    $fontCol   = imagecolorallocate($im, $fontCol[0],$fontCol[1],$fontCol[2]);

    // 3. 繪製陰影 (偏移 1px) + 主文字
    imagettftext($im, $fontSize, 0, $x+1, $y+1, $shadowCol, $fontPath, $string);
    imagettftext($im, $fontSize, 0, $x,   $y,   $fontCol,   $fontPath, $string);

    // 4. 輸出
    if ($destination) {
        $ext = strtolower(pathinfo($destination, PATHINFO_EXTENSION));
        $ok = ($ext=='png') ? imagepng($im,$destination)
             : (($ext=='gif') ? imagegif($im,$destination)
             : imagejpeg($im,$destination, 90));
        imagedestroy($im);
        return $ok ? $destination : false;
    } else {
        header('Content-Type: image/png');
        imagepng($im);
        imagedestroy($im);
        return true;
    }
}

function hex2rgb($hex) {
    $hex = ltrim($hex, '#');
    if (strlen($hex) === 3) $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
    return [hexdec($hex[0].$hex[1]), hexdec($hex[2].$hex[3]), hexdec($hex[4].$hex[5])];
}

呼叫範例

require_once 'str2pic.php';

$font = __DIR__ . '/fonts/NotoSansTC-Regular.otf';

// 1. 直接輸出瀏覽器
str2pic("© 2024 我的網站", 'photo.jpg', '', $font, 24, '#000000', '#ffffff', 20, 40);

// 2. 存檔
str2pic(
    "機密文件 - 禁止外洩",
    'report.png',
    'report_watermarked.png',
    $font, 18, '#ff0000', '#ffffff', 30, 60
);

進階:九宮格自動定位

function str2picAutoPos($string, $source, $destination, $fontPath, $fontSize=20,
                        $position='right-bottom', $margin=15, $opacity=50) {
    $im = imagecreatefromjpeg($source); // 簡化只示範 JPEG
    $box = imagettfbbox($fontSize, 0, $fontPath, $string);
    $tw = $box[2]-$box[0]; $th = $box[1]-$box[7];
    $iw = imagesx($im); $ih = imagesy($im);

    $positions = [
        'left-top'      => [$margin, $th+$margin],
        'center-top'    => [($iw-$tw)/2, $th+$margin],
        'right-top'     => [$iw-$tw-$margin, $th+$margin],
        'left-center'   => [$margin, ($ih+$th)/2],
        'center'        => [($iw-$tw)/2, ($ih+$th)/2],
        'right-center'  => [$iw-$tw-$margin, ($ih+$th)/2],
        'left-bottom'   => [$margin, $ih-$margin],
        'center-bottom' => [($iw-$tw)/2, $ih-$margin],
        'right-bottom'  => [$iw-$tw-$margin, $ih-$margin],
    ];
    list($x,$y) = $positions[$position];

    $color = imagecolorallocatealpha($im, 255,255,255, $opacity);
    imagettftext($im, $fontSize, 0, $x, $y, $color, $fontPath, $string);

    imagejpeg($im, $destination, 90);
    imagedestroy($im);
}

字體取得建議

  • Google Noto Fonts:Noto Sans TC / SC / JP / KR,完整 CJK 覆蓋、開源免費。
  • 思源黑體:Source Han Sans,七字重、專業排版級。
  • 系統字體:Windows C:/Windows/Fonts/msyh.ttc (微軟正黑體)、simhei.ttf (黑體);Linux /usr/share/fonts/truetype/dejavu/ 需額外安裝中文字體套件。

小結

中文浮水印亂碼的核心在於字體檔案是否包含 CJK 字形與字串編碼是否為 UTF-8。使用 str2pic() 並搭配 Noto Sans TC 等開源字體,即可穩定產出專業級中文浮水印。實務上建議將字體檔隨專案佈署 (放在 fonts/ 目錄),避免依賴伺服器系統字體造成移植問題。

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