二維碼中心嵌入 Logo/頭像是常見需求。本文採用「Google Chart API 生成高容錯二維碼」+ 「GD 庫縮放 Logo 並疊加」的兩步走方案,代碼簡潔、無需安裝擴展、生成效果專業。
<?php
// qrcode.php
class QRCode {
public function __construct(
public int $width = 300,
public int $height = 300,
public string $content = '',
public string $level = 'H' // 容錯等級 L/M/Q/H,H 最高(30%),適合嵌 Logo
) {}
public function generate(): string|false {
$params = [
'cht' => 'qr',
'chs' => "{$this->width}x{$this->height}",
'chl' => $this->content,
'chld' => "{$this->level}|0", // 邊距 0
'choe' => 'UTF-8'
];
$url = 'https://chart.googleapis.com/chart?' . http_build_query($params);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false, // 簡化演示,生產請配置 CA
CURLOPT_TIMEOUT => 10,
]);
$imgData = curl_exec($ch);
curl_close($ch);
return $imgData ?: false;
}
}
// 使用
header('Content-Type: image/png');
$qr = new QRCode(300, 300, 'https://example.com/hello-world');
echo $qr->generate();
<?php
// merge_logo.php
function mergeLogoToQR(string $qrImageData, string $logoPath, string $outputPath, float $logoRatio = 0.2): bool {
// 1. 從二進制數據創建二維碼圖片資源
$qr = imagecreatefromstring($qrImageData);
if (!$qr) return false;
// 2. 載入 Logo 並縮放
$logoInfo = getimagesize($logoPath);
if (!$logoInfo) return false;
$logoMime = $logoInfo['mime'];
$createFunc = 'imagecreatefrom' . ($logoMime === 'image/jpeg' ? 'jpeg' : substr($logoMime, 6));
$logo = $createFunc($logoPath);
if (!$logo) return false;
$qrW = imagesx($qr);
$qrH = imagesy($qr);
$logoW = imagesx($logo);
$logoH = imagesy($logo);
// 目標 Logo 尺寸 = 二維碼邊長 * 比例(建議 0.15-0.25)
$targetSize = min($qrW, $qrH) * $logoRatio;
$scale = min($targetSize / $logoW, $targetSize / $logoH);
$newW = (int)($logoW * $scale);
$newH = (int)($logoH * $scale);
// 創建縮放後的真彩色圖片(保持透明度)
$logoResized = imagecreatetruecolor($newW, $newH);
imagealphablending($logoResized, false);
imagesavealpha($logoResized, true);
$transparent = imagecolorallocatealpha($logoResized, 0, 0, 0, 127);
imagefill($logoResized, 0, 0, $transparent);
imagecopyresampled($logoResized, $logo, 0, 0, 0, 0, $newW, $newH, $logoW, $logoH);
// 3. 計算居中座標
$dstX = ($qrW - $newW) / 2;
$dstY = ($qrH - $newH) / 2;
// 4. 疊加:開啟混色模式,將 Logo 複製到二維碼上
imagealphablending($qr, true);
imagecopy($qr, $logoResized, $dstX, $dstY, 0, 0, $newW, $newH);
// 5. 可選:在 Logo 周圍畫白邊框,提高識別率
$white = imagecolorallocate($qr, 255, 255, 255);
imagerectangle($qr, $dstX - 2, $dstY - 2, $dstX + $newW + 2, $dstY + $newH + 2, $white);
// 6. 輸出保存
$result = imagepng($qr, $outputPath);
// 7. 釋放資源
imagedestroy($qr);
imagedestroy($logo);
imagedestroy($logoResized);
return $result;
}
// 完整調用鏈
$qrData = (new QRCode(400, 400, 'https://shop.example.com/item/12345', 'H'))->generate();
if ($qrData) {
mergeLogoToQR($qrData, __DIR__ . '/logo.png', __DIR__ . '/qrcode_with_logo.png');
echo '<img src="qrcode_with_logo.png" alt="帶 Logo 二維碼">';
}
imagealphablending + imagesavealpha 確保 Logo 透明背景正確疊加。md5(content . logo_mtime),避免重複請求 Google API。若項目對外網依賴敏感、或需批量生成、自定義樣式,建議直接集成 endroid/qrcode;原型驗證、低頻調用時,Google API + GD 方案零依賴、最輕量。