php根据背景图片深浅加水印

来源:互联网 发布:网络运营需要什么技术 编辑:程序博客网 时间:2024/06/05 19:07

最近做到一个项目要实现这样一个功能, 根据上传图片的主色调, 在图片上加水印或文字.

比如上传的图片颜色较深,文字的颜色用浅色标识,如果图片颜色较浅, 则文字颜色用深色标识.

解决方法是:

先确定要加文字的图片区域,遍历每一个像素点, 取得该区域像素点的平均亮度, 根据平均亮度决定文字的颜色. 如果该图片区域的颜色不复杂,只是一个纯色块,就不需要遍历了,只需要获取色块中某个像素点的亮度就可以了.

不建议遍历整张图, 而只是遍历需要加水印的图片文字的区域, 否则会有性能问题.

/** * 获取图片某个像素的颜色及亮度 * @author  church <church_qi@aliyun.com> * @date 2017-4-5 */class ImgColor{    /**     * RGB格式     */    const RGB = 1;    /**     * 6位十六进制格式     */    const HEX_6_BIT = 2;    /**     * 8位十六进制格式     */    const HEX_8_BIT = 3;    /**     * 打开图片     * @param  string $img_path 图片路径     * @return resource                */    public static function openImg($img_path)    {        if(!is_file($img_path)) {            throw new Exception("不存在的图片");        }        $info = getimagesize($img_path);        if(false === $info || (IMAGETYPE_GIF === $info[2] && empty($info['bits']))){            throw new Exception("非法的图片");        }        $img_info = array(            'width'  => $info[0],            'height' => $info[1],            'type'   => image_type_to_extension($info[2], false),            'mime'   => $info['mime'],        );        $fun = "imagecreatefrom{$img_info['type']}";        $img = $fun($img_path);        return $img;    }    /**     * 获取某个像素的颜色     * @param  string $img_path  图片路径     * @param  integer $x        横坐标     * @param  integer $y        纵坐标     * @param  integer $format   格式     * @return mixed     */    public static function getColor($img_path = '', $x, $y, $format = self::HEX_8_BIT)    {        static $img;        $getRgb = function($img) use ($x, $y) {            $rgb = imagecolorat($img, $x, $y);            $r = ($rgb >> 16) & 0xFF;            $g = ($rgb >> 8) & 0xFF;            $b = $rgb & 0xFF;            return [$r, $g, $b];        };        if (!(isset($img) && is_resource($img))) {            $img = self::openImg($img_path);        }        return self::rgbToFormat($getRgb($img), $format);    }    /**     * 获取某个像素的亮度 (范围为0~255, 越小越深)     * 算法参考: https://www.w3.org/TR/AERT#color-contrast     *      * @param  string $img_path  图片路径     * @param  integer $x        横坐标     * @param  integer $y        纵坐标     * @return double                */    public static function getBrightnessOfPixel($img_path = '', $x, $y)    {        list($r, $g, $b) = self::getColor($img_path, $x, $y, self::RGB);        $g = $r * 0.299 + $g * 0.587 + $b * 0.114;        return $g;    }    /**     * 把rgb格式转换成其它格式     * @param  array  $rgb          * @param  integer $format 格式     * @return string              */    public static function rgbToFormat($rgb, $format)    {        list($r, $g, $b) = $rgb;        $result = '#';        switch ($format) {            case self::RGB:                return $rgb;                break;            case self::HEX_6_BIT:                $result .= str_pad(dechex($r), 2, '0', STR_PAD_LEFT);                $result .= str_pad(dechex($g), 2, '0', STR_PAD_LEFT);                $result .= str_pad(dechex($b), 2, '0', STR_PAD_LEFT);                return $result;                break;            case self::HEX_8_BIT:                $result .= 'ff';                $result .= str_pad(dechex($r), 2, '0', STR_PAD_LEFT);                $result .= str_pad(dechex($g), 2, '0', STR_PAD_LEFT);                $result .= str_pad(dechex($b), 2, '0', STR_PAD_LEFT);                return $result;                break;        }    }}

亮度的范围为0~255, 越小越深, 越大越浅; 判断时可以取中位, 大于125就算浅,小于就算深.

require './ImgColor.php';$img_path = './test.png';$brightness = 0;for ($i = 0; $i < 100; $i++) {    for ($j = 0; $j < 100; $j++) {        $brightness += ImgColor::getBrightnessOfPixel($img_path, $i, $j);    }}$brightness /= 10000;$font_color = '';$brightness = $brightness > 125 ? '较浅' : '较深';//若背景色较浅, 水印文字颜色设置为黑色, 反之则设置为白色$font_color = $brightness == '较浅' ? '#00000000' : '#ffffffff';
0 0