GD 庫 PNG 透明底圖片新增文字及圖片水印

fengkui發表於2019-07-24

如何使用 GD庫 中的相關函式,
生成 PNG 透明底影象,
並且在影象上新增文字及影象水印。

首先我們要生成一張透明底的畫布:

// 建立 PNG透明底 畫布
$canvas = imagecreatetruecolor('720', '480');
// 為一幅影象分配顏色和透明度
$background = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
// 區域填充背景顏色
imagefill($canvas, 0, 0, $background);
// 將某個顏色定義為透明色
imagecolortransparent($canvas, $background);

畫布生成了,下面就是對文字和LOGO影象進行處理了,
這裡我們使用 imagecreatefromstring 從字串中的影象流新建一LOGO影象;
然後使用 imagecopyresampled 將LOGO影象合併到畫布上:

$logo = @file_get_contents($logo_url); // 將 logo 讀取到字串中
$logo_img = imagecreatefromstring($logo); // 從字串中的影象流新建一影象
// 將logo合併到畫布上
imagecopyresampled($canvas, $logo_img, 30, 115, 0, 0, 250, 250, imagesx($logo_img), imagesy($logo_img));

下面對文字的相關資訊進行獲取,字型基點的位置,以及字型的寬高,
使用 imagettftext 將字型新增到畫布上,

(重要:這裡影象在畫布中的位置不是以字型的左下角為準,而是以字型的基點位置為準

計算字型的相關資訊:


/**
 * [text_image 獲取字型相關屬性]
 * @param  [type] $size     [畫素單位的字型大小]
 * @param  [type] $angle    [text 將被度量的角度大小]
 * @param  [type] $fontfile [TrueType 字型檔案的檔名]
 * @param  [type] $text     [要度量的字串]
 * @return [type]           [description]
 */
public static function text_image($size,  $angle=0, $fontfile, $text)
{
    //獲取文字資訊
    $info = imagettfbbox($size,  $angle=0, $fontfile, $text);
    $minx = min($info[0], $info[2], $info[4], $info[6]);
    $maxx = max($info[0], $info[2], $info[4], $info[6]);
    $miny = min($info[1], $info[3], $info[5], $info[7]);
    $maxy = max($info[1], $info[3], $info[5], $info[7]);
    // var_dump($minx.'     '.$maxx.'     '.$miny.'     '.$maxy);
    /* 計算文字初始座標和尺寸 */
    $x = $minx;
    $y = abs($miny);
    $w = $maxx - $minx;
    $h = $maxy - $miny;
    $re = array(
        'x' => $x, // 基點 X 位置
        'y' => $y, // 基點 Y 位置
        'w' => $w, // 字型寬度
        'h' => $h, // 字型高度
    );
    return $re;
}

將字型新增到畫布上:

// 設定字型顏色(十六進位制顏色碼轉換RGB顏色值與透明度)
$color = self::color_16($text_color);
$color = imagecolorallocatealpha($canvas, $color[0], $color[1], $color[2], $color[3]);

// 計算文字文字在畫布中的位置(以基點為準,文字在影象中的位置)
$text_x = 30 + 250 + 30;
$text_y = $text_info['y'] + (480-$text_info['h'])/2;
// 圖片新增字型
imagettftext($canvas, $text_size, 0, $text_x, $text_y, $color, $text_fonts, $text);

生成的字型效果:
馮奎部落格

如何輸出真正透明底的影象:

// (很重要)不合並顏色,直接用 PNG 影象顏色替換,包括透明色;
imagealphablending($canvas, false);
// (很重要)設定標記以在儲存 PNG 影象時儲存完整的 alpha 通道資訊;
imagesavealpha($canvas, true);

完整程式碼:

<?php
/**
 * @Author: [FENG] <1161634940@qq.com>
 * @Date:   2019-07-16T22:26:38+08:00
 * @Last Modified by:   [FENG] <1161634940@qq.com>
 * @Last Modified time: 2019-07-16T23:03:51+08:00
 */

Class Image
{
    protected static $canvas = '';

    public static function canvas_image()
    {
        // 建立 PNG透明底 畫布
        self::$canvas = imagecreatetruecolor('720', '480');
        // 為一幅影象分配顏色和透明度
        $background = imagecolorallocatealpha(self::$canvas, 0, 0, 0, 127);
        // 區域填充背景顏色
        imagefill(self::$canvas, 0, 0, $background);
        // 將某個顏色定義為透明色
        imagecolortransparent(self::$canvas, $background);

        $text = '馮奎部落格';
        $text_fonts = './jianti.ttf';
        $text_color = '#000000';
        $text_size = 60;
        $logo_url = './logo.png'; // logo 路徑

        // 獲取文字資訊(基點位置及寬高)
        $text_info = self::text_image($text_size, $angle=0, $text_fonts, $text);

        $logo = @file_get_contents($logo_url); // 將 logo 讀取到字串中
        $logo_img = imagecreatefromstring($logo); // 從字串中的影象流新建一影象

        // 將logo合併到畫布上
        imagecopyresampled(self::$canvas, $logo_img, 30, 115, 0, 0, 250, 250, imagesx($logo_img), imagesy($logo_img));

        // 設定字型顏色(十六進位制顏色碼轉換RGB顏色值與透明度)
        $color = self::color_16($text_color);
        $color = imagecolorallocatealpha(self::$canvas, $color[0], $color[1], $color[2], $color[3]);

        // 計算文字文字在畫布中的位置(以基點為準,文字在影象中的位置)
        $text_x = 30 + 250 + 30;
        $text_y = $text_info['y'] + (480-$text_info['h'])/2;
        // 圖片新增字型
        imagettftext(self::$canvas, $text_size, 0, $text_x, $text_y, $color, $text_fonts, $text);

        //輸出到瀏覽器上面並且告訴瀏覽器這個一個影象
        header('content-type:image/png'); // 設定header頭
        imagealphablending(self::$canvas, false); // (很重要)不合並顏色,直接用 PNG 影象顏色替換,包括透明色;
        imagesavealpha(self::$canvas, true);  // (很重要)設定標記以在儲存 PNG 影象時儲存完整的 alpha 通道資訊;
        imagepng(self::$canvas); // 儲存圖片為png
        imagedestroy(self::$canvas); // 清除畫布資源
    }

    /**
     * [text_image 獲取字型相關屬性]
     * @param  [type] $size     [畫素單位的字型大小]
     * @param  [type] $angle    [text 將被度量的角度大小]
     * @param  [type] $fontfile [TrueType 字型檔案的檔名]
     * @param  [type] $text     [要度量的字串]
     * @return [type]           [description]
     */
    public static function text_image($size,  $angle=0, $fontfile, $text)
    {
        //獲取文字資訊
        $info = imagettfbbox($size,  $angle=0, $fontfile, $text);
        $minx = min($info[0], $info[2], $info[4], $info[6]);
        $maxx = max($info[0], $info[2], $info[4], $info[6]);
        $miny = min($info[1], $info[3], $info[5], $info[7]);
        $maxy = max($info[1], $info[3], $info[5], $info[7]);
        // var_dump($minx.'     '.$maxx.'     '.$miny.'     '.$maxy);
        /* 計算文字初始座標和尺寸 */
        $x = $minx;
        $y = abs($miny);
        $w = $maxx - $minx;
        $h = $maxy - $miny;
        $re = array(
            'x' => $x, // 基點 X 位置
            'y' => $y, // 基點 Y 位置
            'w' => $w, // 字型寬度
            'h' => $h, // 字型高度
        );
        return $re;
    }

    /**
     * [color_16 十六進位制顏色碼轉換RGB顏色值與透明度]
     * @param  string $color [十六進位制顏色碼]
     * @return [type]        [description]
     */
    public static function color_16($color='#FFFFFF')
    {
        if (is_string($color) && 0 === strpos($color, '#')) {
            $color = str_split(substr($color, 1), 2);
            $color = array_map('hexdec', $color);
            if (empty($color[3]) || $color[3] > 127) {
                $color[3] = 0;
            }
            return $color;
        } else {
            return false;
        }
    }

}

Image::canvas_image();

相關文章