GD库PNG透明底图片添加文字及图片水印

在之前的文章中我们介绍了,如何使用 GD库 更换小程序码中的logo;
这里我们来具体介绍一下,如何使用 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;
    }

    /**
     * [text_writer 画布写入字体]
     * @param  [type] $text       [字体]
     * @param  [type] $color      [颜色]
     * @param  [type] $text_size  [大小]
     * @param  [type] $text_fonts [样式]
     * @return [type]             [description]
     */
    public function text_writer($text, $color, $text_size, $text_fonts, $text_x, $text_y)
    {
        // 获取文字信息(基点位置及宽高)
        $text_info = self::text_image($text_size, $angle=0, $text_fonts, $text);

        // 设置字体颜色(十六进制颜色码转换RGB颜色值与透明度)
        $color = self::color_16($color);
        $color = imagecolorallocatealpha(self::$canvas, $color[0], $color[1], $color[2], $color[3]);

        // 计算文字文字在画布中的位置(以基点为准,文字在图像中的位置)
        $text_x = $text_x ?? (imagesx(self::$canvas) - $text_info['w'])/2 + $text_info['x'];
        if ($text_x < 0) {
            $text_x = imagesx(self::$canvas) - $text_info['w'] + $text_x;
        }
        $text_y = $text_y ?? (imagesy(self::$canvas) - $text_info['h'])/2 + $text_info['y'];

        // 图片添加字体
        imagettftext(self::$canvas, $text_size, 0, $text_x, $text_y, $color, $text_fonts, $text);
    }

    /**
     * [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();

冯奎博客
请先登录后发表评论
  • latest comments
  • 总共0条评论