PHP利用endroid/qr-code生成个性二维码

橙子与柠檬 / 2024-09-21 / 原文

需先安装拓展库

composer require endroid/qr-code


use Endroid\QrCode\Color\Color;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Label\Label;
use Endroid\QrCode\Logo\Logo;
use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin;
use Endroid\QrCode\Writer\PngWriter;

/**
     * @notes: myGenerateQrCode
     * @param $code_detail
     * @return array
     */
    public function myGenerateQrCode($code_detail)
    {
        /*$code_detail = [
            'qr_code_text'             => 'qr code text',
            'qr_code_margin'           => 10,
            'logo_path'                => '/static/assets/images/logo.jpg',
            'label_text'               => 'Label Text',
            'label_text_color'         => [0, 0, 0]
        ];*/
        if (!isset($code_detail['label_text_color'])) {
            $code_detail['label_text_color'] = [0, 0, 0];
        }
        try {
            $writer = new PngWriter();
            // Create QR code
            $qrCode = QrCode::create(strval($code_detail['qr_code_text']))
                ->setEncoding(new Encoding('UTF-8'))
                ->setErrorCorrectionLevel(new ErrorCorrectionLevelHigh())
                ->setSize(640)
                ->setMargin(20)
                ->setRoundBlockSizeMode(new RoundBlockSizeModeMargin())
                ->setForegroundColor(new Color(0, 0, 0))
                ->setBackgroundColor(new Color(255, 255, 255));
            // Create generic logo
            if (isset($code_detail['logo_path'])) {
                $logo = Logo::create('.' . $code_detail['logo_path'])->setResizeToWidth(128);
            } else {
                $logo = null;
            }
            // Create generic label
            if (isset($code_detail['label_text'])) {
                $label = Label::create(strval($code_detail['label_text']))
                    ->setTextColor(new Color($code_detail['label_text_color'][0], $code_detail['label_text_color'][1], $code_detail['label_text_color'][2]));
            } else {
                $label = null;
            }
            $result      = $writer->write($qrCode, $logo, $label);
            $folder_path = '/storage/qr_code/';
            $file_name   = get_now_date('YmdHis') . bin2hex(random_bytes(8));
            $file_path   = $folder_path . $file_name . '.png';
            // 如果需要修改定位标
            // $this->myGenerateQrCodeLocator($file_path);
            // 如果需要渐变色
            // $this->myGenerateQrCodeGradient($file_path);
            $result->saveToFile('.' . $file_path);
            return [
                'code'      => 200,
                'media_url' => $folder_path . $file_name . '.png',
                'media_uri' => get_file_url($file_path)
            ];
        } catch (\Exception $e) {
            return [
                'code' => 500,
                'msg'  => $e->getMessage()
            ];
        }
    }

    /**
     * @notes: 二维码菱形定位标
     * @param $file_path
     * @return void
     */
    public function myGenerateQrCodeLocator($file_path)
    {
        // 加载二维码图像
        $qrImage = imagecreatefrompng('.' . $file_path);
        $width   = imagesx($qrImage);
        $height  = imagesy($qrImage);
        // 自定义定位标志的颜色
        $circleBorderColor = imagecolorallocate($qrImage, 255, 255, 255); // 圆圈边框颜色(黑色)
        $circleFillColor   = imagecolorallocate($qrImage, 0, 0, 0);       // 圆圈填充颜色(白色)
        $diamondColor      = imagecolorallocate($qrImage, 0, 0, 0);       // 菱形颜色(黑色)
        $squareColor       = imagecolorallocate($qrImage, 255, 255, 255); // 正方形颜色(红色)
        // 绘制自定义定位标志
        function drawMarker($image, $x, $y, $circleBorderColor, $circleFillColor, $diamondColor, $squareColor)
        {
            imageantialias($image, true);
            // 绘制正方形
            imagefilledrectangle($image, $x - 90, $y - 90, $x + 90, $y + 90, $squareColor);
            // 绘制圆圈填充
            imagefilledellipse($image, $x, $y, 160, 160, $circleFillColor);   // 增加直径
            // 绘制圆圈边框
            imagefilledellipse($image, $x, $y, 100, 100, $circleBorderColor); // 增加直径
            // 绘制菱形
            $diamondPoints = [
                $x, $y - 30, // 上
                $x + 30, $y, // 右
                $x, $y + 30, // 下
                $x - 30, $y  // 左
            ];
            imagefilledpolygon($image, $diamondPoints, 4, $diamondColor);
        }

        // 定位标志的位置
        $markerPositions = [
            [105, 105],           // 左上角
            [105, $height - 135], // 左下角
            [$width - 105, 105]   // 右上角
        ];
        // 绘制定位标志
        foreach ($markerPositions as $position) {
            drawMarker($qrImage, $position[0], $position[1], $circleBorderColor, $circleFillColor, $diamondColor, $squareColor);
        }
        // 保存最终带自定义定位标志的二维码
        imagepng($qrImage, '.' . $file_path, 9);
        // 清理内存
        imagedestroy($qrImage);
    }

    /**
     * @notes: 二维码渐变颜色
     * @param $file_path
     * @return void
     */
    public function myGenerateQrCodeGradient($file_path)
    {
        // 加载二维码图像
        $qrImage = imagecreatefrompng('.' . $file_path);
        $width   = imagesx($qrImage);
        $height  = imagesy($qrImage);
        // 创建空白图像
        $gradientImage = imagecreatetruecolor($width, $height);
        // 创建渐变色
        for ($y = 0; $y < $height; $y++) {
            $r     = (int)(255 * ($y / $height));  // 红色渐变
            $g     = 0;
            $b     = (int)(255 * (1 - $y / $height));  // 蓝色渐变
            $color = imagecolorallocate($gradientImage, $r, $g, $b);
            imageline($gradientImage, 0, $y, $width, $y, $color);
        }
        // 合成渐变背景和二维码
        for ($x = 0; $x < $width; $x++) {
            for ($y = 0; $y < $height; $y++) {
                $pixelColor = imagecolorat($qrImage, $x, $y);
                $rgba       = imagecolorsforindex($qrImage, $pixelColor);
                // 如果是黑色,则替换为渐变色
                if ($rgba['red'] == 0 && $rgba['green'] == 0 && $rgba['blue'] == 0) {
                    $colorAtGradient = imagecolorat($gradientImage, $x, $y);
                    imagesetpixel($qrImage, $x, $y, $colorAtGradient);
                }
            }
        }
        // 保存最终带渐变色的二维码
        imagepng($qrImage, '.' . $file_path);
        // 清理内存
        imagedestroy($qrImage);
        imagedestroy($gradientImage);
    }