qr code生成二維碼并且logo設(shè)置為圓角

本篇介紹的是php如何創(chuàng)建一個(gè)帶圓角logo的二維碼。

前言
目前的二維碼生成的庫有很多,我用的是qr-code,里面有生成帶logo的二維碼功能,美中不足的是logo不能設(shè)置圓角,于是我就自己修改代碼實(shí)現(xiàn)。


下載qr-code庫,引入項(xiàng)目,qr-code的目錄結(jié)構(gòu)如下:


image.png

我這里修改的是PngWriter.php文件,這個(gè)文件是生成png格式的二維碼,logo的添加也在里面。我們找到addLogo這個(gè)方法,添加如下代碼:

// 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是設(shè)置圓角方法:

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坐標(biāo)
                $y_y = $radius; //圓心Y坐標(biāo)
                $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坐標(biāo)
                $y_y = $radius; //圓心Y坐標(biāo)
                $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坐標(biāo)
                $y_y = $imgHeight - $radius; //圓心Y坐標(biāo)
                $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坐標(biāo)
                $y_y = $imgHeight - $radius; //圓心Y坐標(biāo)
                $this->setRadius($img, $im, $x, $y, $y_x, $y_y, $radius);
            }
        }
        return $im;
    }

首頁先創(chuàng)建一個(gè)透明的背景圖,然后把logo中的像素點(diǎn)復(fù)制到背景圖中,四個(gè)圓角部分的處理在用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判斷需要繪制的像素點(diǎn)。如果只是繪制滿足在圓上的像素點(diǎn),會(huì)有很明顯的鋸齒效果,這里我做了一些處理,當(dāng)點(diǎn)在圓邊上的點(diǎn)我使用透明之后的像素點(diǎn)來繪制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容