LMLPHP后院

图像处理技术之图片添加水印技术

maybe yes 发表于 2014-11-25 11:37

关于如何给添加图片水印,网上流传的代码片段有很多,但是基本都是相同的代码,被各大网站转载的到处都是。网上流传的使用PHP给添加图片水印的代码,一般情况下还能使用,发现不了有什么问题,处理图片量一大,就会发现很多图片添加水印会有问题。给某些图片添加文字水印会出现颜色失效的问题,有时候会出现文字中空问题,有些图片会有锯齿,锯齿可能跟字体有关,同时也跟代码处理方式有关。

本文讲解如何使用PHP为图片添加水印技术,都是作者自己的亲身经验总结,欢迎交流。

添加水印出现文字颜色失效,可能跟PHP自身的函数imagettftext()有关,这个函数直接使用时可能会出现文字颜色失效,一律变成了黑色。该如何解决这个问题呢,于是我想到了创建透明图片,将文字写入到透明图片中,然后合并到背景图,但是这种方式导致了另一个问题出现:文字出现锯齿。为了解决图片水印锯齿问题,最后通过复制背景图片中需要添加水印的区域到创建的透明背景中作为临时图片,然后添加文字水印到这个临时图片上,然后再将这个临时图片贴合到背景图片中,最后完美解决了问题。在贴合的过程中需要注意计算正确的位置,位置计算错误就导致图片变样了。通过这样的方式添加图片水印,还没有出现过任何问题。

下面附上PHP写的为图片添加图片水印或文字水印函数。

<?php 
function imageWaterMark($groundImage, $waterPos = 0, $waterImage = "", 
    $waterText = "", $fontSize = 12, $textColor = "#CCCCCC", 
    $fontfile = '', $xOffset = 0, $yOffset = 0 ){
    $isWaterImage = FALSE;
    // 读取水印文件
    if (!empty($waterImage) && file_exists($waterImage)) {
        $isWaterImage = TRUE;
        $water_info = @getimagesize($waterImage);
        $water_w = $water_info[0];// 取得水印图片的宽
        $water_h = $water_info[1];// 取得水印图片的高
        // 取得水印图片的格式
        switch($water_info[2]){ 
            case 1:$water_im = @imagecreatefromgif($waterImage);break;
            case 2:$water_im = @imagecreatefromjpeg($waterImage);break;
            case 3:$water_im = @imagecreatefrompng($waterImage);break;
            default:return 1;// 水印图片格式目前不支持
        }
    }
    // 读取背景图片
    if (!empty($groundImage) && file_exists($groundImage)) {
        $ground_info = @getimagesize($groundImage);
        $ground_w = $ground_info[0];// 取得背景图片的宽
        $ground_h = $ground_info[1];// 取得背景图片的高
        // 取得背景图片的格式
        $bgimgtype = $ground_info[2];
        switch($bgimgtype) {
            case 1:$ground_im = @imagecreatefromgif($groundImage);break;
            case 2:$ground_im = @imagecreatefromjpeg($groundImage);break;
            case 3:$ground_im = @imagecreatefrompng($groundImage);break;
            default:return 1;// 水印图片格式目前不支持
        }
    } else return 2;// 要水印的背景图片不存在

    if($isWaterImage) {
        // 图片水印
        $w = $water_w;
        $h = $water_h;
    } else {
        // 文字水印
        if (!file_exists($fontfile)) return 4;// 字体文件不存在
        // 取得使用TrueType字体的文本的范围
        $temp = @imagettfbbox($fontSize,0,$fontfile,$waterText);
        $w = $temp[2] - $temp[6] +20;
        $h = $temp[3] - $temp[7] +20;
        unset($temp);
    }
    // 需要加水印的图片的长度或宽度比水印图片或文字区域还小,无法生成水印
    if (($ground_w < $w) || ($ground_h < $h)) return 3;
    // 水印位置
    switch($waterPos){
        case 1:// 1为顶端居左
            $posX = 0;
            $posY = 0;
            break;
        case 2:// 2为顶端居中
            $posX = ($ground_w - $w) / 2;
            $posY = 0;
            break;
        case 3:// 3为顶端居右
            $posX = $ground_w - $w;
            $posY = 0;
            break;
        case 4:// 4为中部居左
            $posX = 0;
            $posY = ($ground_h - $h) / 2;
            break;
        case 5:// 5为中部居中
            $posX = ($ground_w - $w) / 2;
            $posY = ($ground_h - $h) / 2;
            break;
        case 6:// 6为中部居右
            $posX = $ground_w - $w;
            $posY = ($ground_h - $h) / 2;
            break;
        case 7:// 7为底端居左
            $posX = 0;
            $posY = $ground_h - $h;
            break;
        case 8://8为底端居中
            $posX = ($ground_w - $w) / 2;
            $posY = $ground_h - $h;
            break;
        case 9://9为底端居右
            $posX = $ground_w - $w;
            $posY = $ground_h - $h;
            break;
        case 0:
        default:// 随机
            $posX = rand(0,($ground_w - $w));
            $posY = rand(0,($ground_h - $h));
            break;     
    }
    // 设定图像的混色模式
    @imagealphablending($ground_im,true);
    // 图片水印
    if ($isWaterImage) {
        // 拷贝水印到目标文件 
        @imagecopy($ground_im,$water_im,$posX + $xOffset,
            $posY + $yOffset,0,0,$water_w,$water_h);
    } else {
        // 修复某些图片水印文字颜色失效的问题,通过生成透明图片来解决这个问题
        $text_water_im = imagecreatetruecolor($w, $h);
        $white_alpha = imagecolorallocatealpha($text_water_im, 
            255, 255, 255, 127);
        imagecolortransparent($text_water_im, $white_alpha);
        imagefilledrectangle($text_water_im, 0, 0, $w, $h, $white_alpha);
        // 将背景图片中需要添加水印的区域复制出来添加到透明背景,防止产生锯齿
        imagecopyresampled($text_water_im, $ground_im, 0, 0, 
            $posX+$xOffset, $posY+$yOffset, $w, $h, $w, $h);
        
        // 文字水印
        if (!empty($textColor) && (strlen($textColor) == 7)) {
            $R = hexdec(substr($textColor,1,2));
            $G = hexdec(substr($textColor,3,2));
            $B = hexdec(substr($textColor,5));
        } else {
            // 水印文字颜色格式不正确
            return 5;
        }

        // 文字透明度设置为20 (0->127 逐渐透明)
        @imagettftext( $text_water_im, $fontSize, 0, 10, $h-10,
            @imagecolorallocatealpha($text_water_im,$R,$G,$B, 20), 
            $fontfile, $waterText );
        imagealphablending($text_water_im);
        imagecopymerge( $ground_im, $text_water_im, $posX+$xOffset, 
            $posY+$yOffset, 0, 0, $w, $h, 100 );
    }
    // 生成水印后的图片
    @unlink($groundImage);
    // 取得背景图片的格式
    switch($bgimgtype){
        case 1:@imagegif($ground_im,$groundImage);break;
        case 2:@imagejpeg($ground_im,$groundImage, 100);break;
        case 3:@imagepng($ground_im,$groundImage);break;
        default:return 6;// 水印背景图片格式目前不支持
    }
    // 释放内存
    if (isset($water_info)) unset($water_info);
    if (isset($water_im)) @imagedestroy($water_im);
    unset($ground_info);
    @imagedestroy($ground_im);
    // 水印成功
    return 0;
}
相关文章
2020-09-23 21:45:01 1600868701 0.051915