使用 imagecreatetruecolor() 創建真彩色畫布後,直接 imagecopyresampled() 貼圖,PNG/GIF 透明區域會變成**黑色**(預設填充色)。根因:真彩色畫布預設不支援 Alpha 通道,需顯式啟用透明度保存並填充全透明色。
<?php
$src = imagecreatefrompng('logo.png');
$dst = imagecreatetruecolor(200, 200); // 預設黑色背景
imagecopyresampled($dst, $src, 0, 0, 0, 0, 200, 200, imagesx($src), imagesy($src));
imagepng($dst, 'logo_thumb.png'); // 輸出:透明區變黑
?>
<?php
$src = imagecreatefrompng('logo.png');
$dst = imagecreatetruecolor(200, 200);
// 1. 關閉 Alpha 混色模式(避免與目標畫布混色)
imagealphablending($dst, false);
// 2. 分配全透明色 (R,G,B, Alpha=127 為完全透明)
$transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
// 3. 填充整個畫布為透明
imagefill($dst, 0, 0, $transparent);
// 4. 關鍵:啟用 Alpha 通道保存(輸出時保留透明度)
imagesavealpha($dst, true);
// 現在可以安全縮放
imagecopyresampled($dst, $src, 0, 0, 0, 0, 200, 200, imagesx($src), imagesy($src));
imagepng($dst, 'logo_thumb.png'); // 輸出:透明完美保留
imagedestroy($src);
imagedestroy($dst);
?>
GIF 只支援**單色透明**(某一調色板索引完全透明),不支援半透明(Alpha 通道)。縮放 GIF 保持透明:
<?php
$src = imagecreatefromgif('icon.gif');
$dst = imagecreatetruecolor(100, 100);
// 獲取源圖透明色索引
$transparentIndex = imagecolortransparent($src);
if ($transparentIndex >= 0) {
// 分配同樣 RGB 色作為目標透明色
$rgb = imagecolorsforindex($src, $transparentIndex);
$newTransparent = imagecolorallocate($dst, $rgb['red'], $rgb['green'], $rgb['blue']);
imagefill($dst, 0, 0, $newTransparent);
imagecolortransparent($dst, $newTransparent); // 設置目標圖透明色索引
}
imagecopyresampled($dst, $src, 0, 0, 0, 0, 100, 100, imagesx($src), imagesy($src));
imagegif($dst, 'icon_thumb.gif');
?>
<?php
/**
* 縮放圖片並保留透明度
* @param string $srcPath 源文件
* @param string $dstPath 目標文件
* @param int $maxW 最大寬
* @param int $maxH 最大高
* @return bool
*/
function smart_resize(string $srcPath, string $dstPath, int $maxW, int $maxH): bool {
$info = getimagesize($srcPath);
if (!$info) return false;
[$srcW, $srcH, $type] = $info;
// 計算目標尺寸(等比)
$ratio = min($maxW / $srcW, $maxH / $srcH);
$dstW = (int)($srcW * $ratio);
$dstH = (int)($srcH * $ratio);
// 創建源圖資源
$createFrom = ['gif'=>'imagecreatefromgif','jpeg'=>'imagecreatefromjpeg','png'=>'imagecreatefrompng','webp'=>'imagecreatefromwebp'];
$func = $createFrom[image_type_to_extension($type, false)] ?? null;
if (!$func) return false;
$src = $func($srcPath);
// 創建目標畫布並設置透明
$dst = imagecreatetruecolor($dstW, $dstH);
imagealphablending($dst, false);
$transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
imagefill($dst, 0, 0, $transparent);
imagesavealpha($dst, true);
// GIF 額外處理單色透明
if ($type === IMAGETYPE_GIF) {
$ti = imagecolortransparent($src);
if ($ti >= 0) {
$rgb = imagecolorsforindex($src, $ti);
$nt = imagecolorallocate($dst, $rgb['red'], $rgb['green'], $rgb['blue']);
imagefill($dst, 0, 0, $nt);
imagecolortransparent($dst, $nt);
}
}
// 縮放
imagecopyresampled($dst, $src, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);
// 輸出
$output = ['gif'=>'imagegif','jpeg'=>'imagejpeg','png'=>'imagepng','webp'=>'imagewebp'];
$outFunc = $output[image_type_to_extension($type, false)];
$result = $outFunc($dst, $dstPath);
imagedestroy($src);
imagedestroy($dst);
return $result;
}
?>