美文网首页
qr code生成二维码并且logo设置为圆角

qr code生成二维码并且logo设置为圆角

作者: fly_侠 | 来源:发表于2020-11-19 15:32 被阅读0次

    本篇介绍的是php如何创建一个带圆角logo的二维码。

    前言
    目前的二维码生成的库有很多,我用的是qr-code,里面有生成带logo的二维码功能,美中不足的是logo不能设置圆角,于是我就自己修改代码实现。


    下载qr-code库,引入项目,qr-code的目录结构如下:


    image.png

    我这里修改的是PngWriter.php文件,这个文件是生成png格式的二维码,logo的添加也在里面。我们找到addLogo这个方法,添加如下代码:

    // 1: 白底
            if ($imgBorderType == '1') {
                $px = 4;
                $logoImage = $this->addBorder($logoImage, $logoWidth, $logoHeight, $logoSourceWidth, $logoSourceHeight, $px);
                $logoSourceWidth = $logoWidth + $px * 2;
                $logoSourceHeight = $logoHeight + $px * 2;
                $logoWidth = $logoWidth + $px * 2;
                $logoHeight = $logoHeight + $px * 2;
            }
            // 2: 圆角
            else if($imgBorderType == '2') {
                $radius = intval(imagesx($sourceImage) * 0.3 * 0.2);
                $logoImage = $this->addBorder($logoImage, $logoWidth, $logoHeight, $logoSourceWidth, $logoSourceHeight);
                $logoSourceWidth = $logoWidth;
                $logoSourceHeight = $logoHeight;
                $logoImage  = $this->addRadius($logoImage, $logoWidth, $logoHeight, $radius);
            }
            // 3: 圆角白底
            else if($imgBorderType == '3') {
                $radius = intval(imagesx($sourceImage) * 0.3 * 0.2);
                $logoImage = $this->addBorder($logoImage, $logoWidth, $logoHeight, $logoSourceWidth, $logoSourceHeight);
                $logoSourceWidth = $logoWidth;
                $logoSourceHeight = $logoHeight;
                $logoImage  = $this->addRadius($logoImage, $logoWidth, $logoHeight, $radius);
                $px = 4;
                $logoImage = $this->addBorder($logoImage, $logoWidth, $logoHeight, $logoSourceWidth, $logoSourceHeight, $px);
                $logoSourceWidth = $logoWidth + $px * 2;
                $logoSourceHeight = $logoHeight + $px * 2;
                $logoWidth = $logoWidth + $px * 2;
                $logoHeight = $logoHeight + $px * 2;
                $logoImage  = $this->addRadius($logoImage, $logoWidth, $logoHeight, $radius + $px);
            }
    

    addBorder是添加白色边框方法:

    function addBorder($img, $imgWidth, $imgHeight, $imgSourceWidth, $imgSourceHeight, $px = 0) {
            $im = imagecreatetruecolor(($imgWidth + $px * 2), ($imgHeight + $px * 2));
            if (!is_resource($im)) {
                throw new GenerateImageException('Unable to generate image: check your GD installation');
            }
            $color = imagecolorallocate($im, 255, 255, 255);
            imagefill($im, 0, 0, $color);
            imageColorTransparent($im, $color);
            imagecopyresampled($im, $img, intval($px), intval($px), 0, 0, $imgWidth, $imgHeight, $imgSourceWidth, $imgSourceHeight);
            imagedestroy($img);
            return $im;
        }
    

    addRadius是设置圆角方法:

    function addRadius($img, $imgWidth, $imgHeight, $radius = 20) {
            $im = imagecreatetruecolor($imgWidth, $imgHeight);
            //这一句一定要有
            imagesavealpha($im, true);
            $bg = imagecolorallocatealpha($im, 255, 255, 255, 127);
            imagefill($im, 0, 0, $bg);
            $widthX = $imgWidth - $radius * 2;
            $heightY = $imgHeight - $radius * 2;
            $limitX = $radius;
            $limitY = $radius;
            if ($widthX > 0) {
                imagecopyresampled($im, $img, intval($radius), intval(0), intval($radius), intval(0), $widthX, $imgHeight, $widthX, $imgHeight);
                if ($heightY > 0) {
                    imagecopyresampled($im, $img, intval(0), intval($radius), intval(0), intval($radius), $radius, $heightY, $radius, $heightY);
                    imagecopyresampled($im, $img, intval($imgWidth - $radius), intval($radius), intval($imgWidth - $radius), intval($radius), $radius, $heightY, $radius, $heightY);
                }
                else {
                    $limitY = $imgHeight / 2;
                }
            }
            else {
                $limitX = $imgWidth / 2;
                if ($heightY > 0) {
                    imagecopyresampled($im, $img, intval(0), intval($radius), intval(0), intval($radius), $imgWidth, $heightY, $imgWidth, $heightY);
                }
                else {
                    $limitY = $imgHeight / 2;
                }
            }
            // 左上
            for ($x = 0; $x < $limitX; $x++) {
                for ($y = 0; $y < $limitY; $y++) {
                    $y_x = $radius; //圆心X坐标
                    $y_y = $radius; //圆心Y坐标
                    $this->setRadius($img, $im, $x, $y, $y_x, $y_y, $radius);
                }
            }
            // 右上
            for ($x = $imgWidth - $limitX; $x < $imgWidth; $x++) {
                for ($y = 0; $y < $limitY; $y++) {
                    $y_x = $imgWidth - $radius; //圆心X坐标
                    $y_y = $radius; //圆心Y坐标
                    $this->setRadius($img, $im, $x, $y, $y_x, $y_y, $radius);
                }
            }
            // 左下
            for ($x = 0; $x < $limitX; $x++) {
                for ($y = $imgHeight - $limitY; $y < $imgHeight; $y++) {
                    $y_x = $radius; //圆心X坐标
                    $y_y = $imgHeight - $radius; //圆心Y坐标
                    $this->setRadius($img, $im, $x, $y, $y_x, $y_y, $radius);
                }
            }
            // 右下
            for ($x = $imgWidth - $limitX; $x < $imgWidth; $x++) {
                for ($y = $imgHeight - $limitY; $y < $imgHeight; $y++) {
                    $y_x = $imgWidth -$radius; //圆心X坐标
                    $y_y = $imgHeight - $radius; //圆心Y坐标
                    $this->setRadius($img, $im, $x, $y, $y_x, $y_y, $radius);
                }
            }
            return $im;
        }
    

    首页先创建一个透明的背景图,然后把logo中的像素点复制到背景图中,四个圆角部分的处理在用setRadius方法处理。

    function setRadius($img, $im, $x, $y, $circleX, $circleY, $radius) {
            $val1 = ($x - $circleX) * ($x - $circleX) + ($y - $circleY) * ($y - $circleY);
            $val2 = $radius * $radius;
            $rgbColor = imagecolorat($img, $x, $y);
            if ($val1 <= $val2) {
                imagesetpixel($im, $x, $y, $rgbColor);
    
            }
            // 除锯齿
            if($val1 > $val2 && $val1 <= ($radius + 0.3) * ($radius + 0.3)) {
                $rgbColor = imagecolorat($img, $x, $y);
                $img_pix_array = imagecolorsforindex($im, $rgbColor);
                imagesetpixel($im, $x, $y, imagecolorallocatealpha($img, $img_pix_array['red'], $img_pix_array['green'], $img_pix_array['blue'], intval((127 - $img_pix_array['alpha']) * 0.3)));
            }
            if($val1 > ($radius + 0.3) * ($radius + 0.3) && $val1 <= ($radius + 0.7) * ($radius + 0.7)) {
                $rgbColor = imagecolorat($img, $x, $y);
                $img_pix_array = imagecolorsforindex($im, $rgbColor);
                imagesetpixel($im, $x, $y, imagecolorallocatealpha($img, $img_pix_array['red'], $img_pix_array['green'], $img_pix_array['blue'], intval((127 - $img_pix_array['alpha']) * 0.6)));
            }
            if($val1 > ($radius + 0.7) * ($radius + 0.7) && $val1 <= ($radius + 0.98) * ($radius + 0.98)) {
                $rgbColor = imagecolorat($img, $x, $y);
                $img_pix_array = imagecolorsforindex($im, $rgbColor);
                imagesetpixel($im, $x, $y, imagecolorallocatealpha($img, $img_pix_array['red'], $img_pix_array['green'], $img_pix_array['blue'], intval((127 - $img_pix_array['alpha']) * 0.8)));
            }
        }
    

    利用圆的公式x2 + y2 <= r2判断需要绘制的像素点。如果只是绘制满足在圆上的像素点,会有很明显的锯齿效果,这里我做了一些处理,当点在圆边上的点我使用透明之后的像素点来绘制。

    相关文章

      网友评论

          本文标题:qr code生成二维码并且logo设置为圆角

          本文链接:https://www.haomeiwen.com/subject/imfliktx.html