49天前2020-04-17 13:09:01 |    抢沙发  53 
最近有一个需求,在php环境下要对url进行二维码生成,且要进行图片合成,网上找了一下phpqrcode二维码生成类库挺好用的,但是它只支持直接存储二维码图片或者直接输出二维码到浏览器,无法实现返回图片资源对象,然后进行再次对二维码的编辑与合成。本文就是通过分析phpqrcode的源代码,然后对原有类库进行修改从而实现返回图片资源,与二维码的再次编辑的教程。

php

今天有点儿时间我就讲的详细点儿吧。

首先phpqrcode类库是开源的,官方地址是:http://phpqrcode.sourceforge.net

其次这个类库最新的一个版本是在2010年维护的,后面作者再也没有对phpqrcode类库进行更新了,但是不要担心,这个类库完全可以运行在php7的环境下。

再说一下phpqrcode类库的运行环境要求,运行环境必须支持GD2;

然后下载下来的phpqrcode压缩包解压后你会得到一大堆文件和文件夹,莫慌,真真有用的就只有一个phpqrcode.php文件,单独复制出来放到项目目录。

OK,咱们先来讲一讲phpqrcode类库的参数和用法:

参数:

$text  表示二维码包含的字符串
$outfile   表示二维码存储的文件名 默认为false 表示不生成文件
$level 表示二维码容错等级,也就是被覆盖的区域还能识别。默认是L 可以识别已损失7%的数据 后面依次是 M-可以识别已损失15%的数据 Q-可以识别已损失25%的数据 H-可以识别已损失30%的数据  
$size 生成图片大小,默认为4
$margin 控制生成二维码的空白区域大小 默认为4
$saveandprint  保存二维码图片并显示出来,$outfile必须传递图片路径
用法:
//引入类库
include 'phpqrcode.php'
//生成二维码
QRcode::png($text, $outfile, $level, $size, $margin, $saveandprint);
上面是原生的参数和用法,下面是我修改后的参数和用法:

修改后的参数:

$text  表示二维码包含的字符串
$outfile   表示二维码存储的文件名 默认为false 表示不生成文件
$level 表示二维码容错等级,也就是被覆盖的区域还能识别。默认是L 可以识别已损失7%的数据 后面依次是 M-可以识别已损失15%的数据 Q-可以识别已损失25%的数据 H-可以识别已损失30%的数据  
$size 生成图片大小,默认为4
$margin 控制生成二维码的空白区域大小 默认为4
$saveandprint  保存二维码图片并显示出来,$outfile必须传递图片路径 值为false或true
$resources 是否直接返回图片resources资源,默认为false
修改后的用法:
//引入类库
include 'phpqrcode.php'
//生成二维码
QRcode::png($text, $outfile, $level, $size, $margin, $saveandprint,true);
通过对比新旧参数和用法你会发现其实就是多了一个参数resources,没错通过新增一个参数来控制返回数据类型应该是最接近原生,最简单的方法了。

OK,下面我们开始对phpqrcode.php类库进行修改以实现我们需要的功能;

首先打开:phpqrcode.php

然后找到QRcode类的png方法。

原文:

public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false)
        {
            $enc = QRencode::factory($level, $size, $margin);
            return $enc->encodePNG($text, $outfile, $saveandprint=false);
        }
这里我就不写具体在多少行了,因为我手里是修改过的,所以实际的行号和原版的存在偏差。

我们需要在$saveandprint=false后面再加一个参数$resources并设置为false,同时我们再return中也要把这个参数传递过去;

修改后的代码:

public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false,$resources = false)
        {
            $enc = QRencode::factory($level, $size, $margin);
            return $enc->encodePNG($text, $outfile, $saveandprint=false,$resources);
        }
当然你也可以直接复制上面这个方法直接替换原来的方法。

OK,我们看到他return的是enc的encodePNG方法我们继续往下找到这个encodePNG方法(他应该是类库中最后的那个方法):

原代码:

public function encodePNG($intext, $outfile = false,$saveandprint=false)
        {
            try {

                ob_start();
                $tab = $this->encode($intext);
                $err = ob_get_contents();
                ob_end_clean();

                if ($err != '')
                    QRtools::log($outfile, $err);

                $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));

                $qr = QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
                if ($resources == true) {
                    return $qr;
                }

            } catch (Exception $e) {

                QRtools::log($outfile, $e->getMessage());

            }
        }
   
OK,我们按照之前同样的操作,在参数$saveandprint=false后面新增一个$resources参数并设置为默认false,不过不设置也没关系,因为这个参数是从上级传过来的,为了和作者的代码风格一致,我以我带上了默认值。

因为encodePNG方法中继续调用了QRimage类中的png方法所以我们在这一行的传递参数中继续添加我们新增的$resources参数(注意这里的png方法和我们第一次找的png方法不一样,他们属于不同的类中)。

修改后的代码:

public function encodePNG($intext, $outfile = false,$saveandprint=false,$resources=false)
        {
            try {

                ob_start();
                $tab = $this->encode($intext);
                $err = ob_get_contents();
                ob_end_clean();

                if ($err != '')
                    QRtools::log($outfile, $err);

                $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));

                $qr = QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint,$resources);
                if ($resources == true) {
                    return $qr;
                }

            } catch (Exception $e) {

                QRtools::log($outfile, $e->getMessage());

            }
        }
同样,你也可以直接复制上面修改后的方法替换原方法。

我们继续顺藤摸瓜,找到QRimage类中的png方法:

原代码:

public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) 
        {
            $image = self::image($frame, $pixelPerPoint, $outerFrame);
            
            if ($filename === false) {
                Header("Content-type: image/png");
                ImagePng($image);
            } else {
                if($saveandprint===TRUE){
                    ImagePng($image, $filename);
                    header("Content-type: image/png");
                    ImagePng($image);
                }else{
                    ImagePng($image, $filename);
                }
            }
            
            ImageDestroy($image);
        }
按照同样的方法,我们先加上新的参数:$resources,然后再对传递过来的$resources参数做一下判断是否需要返回图片资源,然后根据需求去返回不同的值。

修改后的代码:

public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE,$resources = false)
        {
            $image = self::image($frame, $pixelPerPoint, $outerFrame);
            if ($resources == true) {
                return $image;
            }else{
                if ($filename === false) {
                    Header("Content-type: image/png");
                    ImagePng($image);
                } else {
                    if($saveandprint===TRUE){
                        ImagePng($image, $filename);
                        header("Content-type: image/png");
                        ImagePng($image);
                    }else{
                        ImagePng($image, $filename);
                    }
                }

                ImageDestroy($image);
            }
        }
然后保存修改后的类库就大功告成了。

这里没有多深奥的技术,只是做一个笔记,为有需要的同学提供便利,不要重复造车轮。

可能有人会问,这个修改后的phpqrcode类库有啥用呢?

当然有用啦,就拿最常用的一个应用场景来说吧。

比如你要用php生成一个带logo的二维码。

如果无法返回图片资源的话,那么你要实现php生成一个带logo的二维码图片,那么你就只能是先生成一个二维码图片然后保存到本地,然后再读入这张二维码再次进行编辑,这样就太麻烦了。当然还有一种就是使用php缓存技术。但是相对来说,还是原生的支持比较好。

好了今天就到这里了,有时间再来BB。

这里我直接附上修改后的phpqrcode类库吧,省的你改着麻烦。

修改后的phpqrcode.php

发表评论

暂无评论

登录

忘记密码 ?

切换登录

注册

扫一扫二维码分享