:octocat: examples cleanup

This commit is contained in:
smiley
2022-07-09 18:10:23 +02:00
parent 9d309e2ff8
commit e971678ac5
17 changed files with 382 additions and 420 deletions
-58
View File
@@ -1,58 +0,0 @@
<?php
/**
* Class MyCustomOutput
*
* @created 24.12.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\Output\QROutputAbstract;
class MyCustomOutput extends QROutputAbstract{
/**
* @inheritDoc
*/
protected function moduleValueIsValid($value):bool{
// TODO: Implement moduleValueIsValid() method. (abstract)
return false;
}
/**
* @inheritDoc
*/
protected function getModuleValue($value){
// TODO: Implement getModuleValue() method. (abstract)
return null;
}
/**
* @inheritDoc
*/
protected function getDefaultModuleValue(bool $isDark){
// TODO: Implement getDefaultModuleValue() method. (abstract)
return null;
}
/**
* @inheritDoc
*/
public function dump(string $file = null):string{
$output = '';
for($y = 0; $y < $this->moduleCount; $y++){
for($x = 0; $x < $this->moduleCount; $x++){
$output .= (int)$this->matrix->check($x, $y);
}
$output .= $this->options->eol;
}
return $output;
}
}
-70
View File
@@ -1,70 +0,0 @@
<?php
/**
* Class QRImageWithLogo
*
* @created 18.11.2020
* @author smiley <smiley@chillerlan.net>
* @copyright 2020 smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\Output\{QRGdImage, QRCodeOutputException};
use function imagecopyresampled, imagecreatefrompng, imagesx, imagesy, is_file, is_readable;
class QRImageWithLogo extends QRGdImage{
/**
* @param string|null $file
* @param string|null $logo
*
* @return string
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
public function dump(string $file = null, string $logo = null):string{
// set returnResource to true to skip further processing for now
$this->options->returnResource = true;
// of course you could accept other formats too (such as resource or Imagick)
// i'm not checking for the file type either for simplicity reasons (assuming PNG)
if(!is_file($logo) || !is_readable($logo)){
throw new QRCodeOutputException('invalid logo');
}
// there's no need to save the result of dump() into $this->image here
parent::dump($file);
$im = imagecreatefrompng($logo);
// get logo image size
$w = imagesx($im);
$h = imagesy($im);
// set new logo size, leave a border of 1 module (no proportional resize/centering)
$lw = ($this->options->logoSpaceWidth - 2) * $this->options->scale;
$lh = ($this->options->logoSpaceHeight - 2) * $this->options->scale;
// get the qrcode size
$ql = $this->matrix->size() * $this->options->scale;
// scale the logo and copy it over. done!
imagecopyresampled($this->image, $im, ($ql - $lw) / 2, ($ql - $lh) / 2, 0, 0, $lw, $lh, $w, $h);
$imageData = $this->dumpImage();
if($file !== null){
$this->saveToFile($imageData, $file);
}
if($this->options->imageBase64){
$imageData = $this->base64encode($imageData, 'image/'.$this->options->outputType);
}
return $imageData;
}
}
-98
View File
@@ -1,98 +0,0 @@
<?php
/**
* Class QRImageWithText
*
* example for additional text
*
* @link https://github.com/chillerlan/php-qrcode/issues/35
*
* @created 22.06.2019
* @author smiley <smiley@chillerlan.net>
* @copyright 2019 smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\Output\QRGdImage;
use chillerlan\QRCode\QRCode;
use function imagechar, imagecolorallocate, imagecolortransparent, imagecopymerge, imagecreatetruecolor,
imagedestroy, imagefilledrectangle, imagefontwidth, round, str_split, strlen;
class QRImageWithText extends QRGdImage{
/**
* @param string|null $file
* @param string|null $text
*
* @return string
*/
public function dump(string $file = null, string $text = null):string{
// set returnResource to true to skip further processing for now
$this->options->returnResource = true;
// there's no need to save the result of dump() into $this->image here
parent::dump($file);
// render text output if a string is given
if($text !== null){
$this->addText($text);
}
$imageData = $this->dumpImage();
if($file !== null){
$this->saveToFile($imageData, $file);
}
if($this->options->imageBase64){
$imageData = $this->base64encode($imageData, 'image/'.$this->options->outputType);
}
return $imageData;
}
/**
* @param string $text
*/
protected function addText(string $text):void{
// save the qrcode image
$qrcode = $this->image;
// options things
$textSize = 3; // see imagefontheight() and imagefontwidth()
$textBG = [200, 200, 200];
$textColor = [50, 50, 50];
$bgWidth = $this->length;
$bgHeight = $bgWidth + 20; // 20px extra space
// create a new image with additional space
$this->image = imagecreatetruecolor($bgWidth, $bgHeight);
$background = imagecolorallocate($this->image, ...$textBG);
// allow transparency
if($this->options->imageTransparent && $this->options->outputType !== QRCode::OUTPUT_IMAGE_JPG){
imagecolortransparent($this->image, $background);
}
// fill the background
imagefilledrectangle($this->image, 0, 0, $bgWidth, $bgHeight, $background);
// copy over the qrcode
imagecopymerge($this->image, $qrcode, 0, 0, 0, 0, $this->length, $this->length, 100);
imagedestroy($qrcode);
$fontColor = imagecolorallocate($this->image, ...$textColor);
$w = imagefontwidth($textSize);
$x = round(($bgWidth - strlen($text) * $w) / 2);
// loop through the string and draw the letters
foreach(str_split($text) as $i => $chr){
imagechar($this->image, $textSize, (int)($i * $w + $x), $this->length, $chr, $fontColor);
}
}
}
-54
View File
@@ -1,54 +0,0 @@
<?php
/**
* Class QRSvgWithLogo
*
* @created 05.03.2022
* @author smiley <smiley@chillerlan.net>
* @copyright 2022 smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\Output\QRMarkupSVG;
use function ceil, file_get_contents, sprintf;
/**
* Create SVG QR Codes with embedded logos (that are also SVG)
*/
class QRSvgWithLogo extends QRMarkupSVG{
/**
* @inheritDoc
*/
protected function paths():string{
$size = (int)ceil($this->moduleCount * $this->options->svgLogoScale);
// we're calling QRMatrix::setLogoSpace() manually, so QROptions::$addLogoSpace has no effect here
$this->matrix->setLogoSpace($size, $size);
$svg = parent::paths();
$svg .= $this->getLogo();
return $svg;
}
/**
* returns a <g> element that contains the SVG logo and positions it properly within the QR Code
*
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform
*/
protected function getLogo():string{
// @todo: customize the <g> element to your liking (css class, style...)
return sprintf(
'%5$s<g transform="translate(%1$s %1$s) scale(%2$s)" class="%3$s">%5$s %4$s%5$s</g>',
($this->moduleCount - ($this->moduleCount * $this->options->svgLogoScale)) / 2,
$this->options->svgLogoScale,
$this->options->svgLogoCssClass,
file_get_contents($this->options->svgLogo),
$this->options->eol
);
}
}
+60 -3
View File
@@ -4,15 +4,70 @@
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*
* @noinspection PhpIllegalPsrClassPathInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Common\EccLevel;
use chillerlan\QRCode\Output\QROutputAbstract;
require_once __DIR__.'/../vendor/autoload.php';
/*
* Class definition
*/
class MyCustomOutput extends QROutputAbstract{
/**
* @inheritDoc
*/
protected function moduleValueIsValid($value):bool{
// TODO: Implement moduleValueIsValid() method. (abstract)
return false;
}
/**
* @inheritDoc
*/
protected function getModuleValue($value){
// TODO: Implement getModuleValue() method. (abstract)
return null;
}
/**
* @inheritDoc
*/
protected function getDefaultModuleValue(bool $isDark){
// TODO: Implement getDefaultModuleValue() method. (abstract)
return null;
}
/**
* @inheritDoc
*/
public function dump(string $file = null):string{
$output = '';
for($y = 0; $y < $this->moduleCount; $y++){
for($x = 0; $x < $this->moduleCount; $x++){
$output .= (int)$this->matrix->check($x, $y);
}
$output .= $this->options->eol;
}
return $output;
}
}
/*
* Runtime
*/
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
// invoke the QROutputInterface manually
@@ -29,7 +84,7 @@ $qrOutputInterface = new MyCustomOutput($options, $qrcode->getMatrix());
var_dump($qrOutputInterface->dump());
// or just
// or just via the options
$options = new QROptions([
'version' => 5,
'eccLevel' => EccLevel::L,
@@ -38,3 +93,5 @@ $options = new QROptions([
]);
var_dump((new QRCode($options))->render($data));
exit;
+10 -9
View File
@@ -6,23 +6,19 @@
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Common\EccLevel;
use chillerlan\QRCode\Data\QRMatrix;
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_EPS,
'eccLevel' => EccLevel::L,
'scale' => 5,
'addQuietzone' => true,
'cachefile' => __DIR__.'/test.eps',
# 'cachefile' => __DIR__.'/test.eps', // save to file
'moduleValues' => [
// finder
QRMatrix::M_FINDER | QRMatrix::IS_DARK => 0xA71111, // dark (true)
@@ -52,11 +48,16 @@ $options = new QROptions([
],
]);
// if viewed in the browser, we should push it as file download as EPS isn't usually supported
header('Content-type: application/postscript');
header('Content-Disposition: filename="qrcode.eps"');
echo (new QRCode($options))->render($data);
if(php_sapi_name() !== 'cli'){
// if viewed in the browser, we should push it as file download as EPS isn't usually supported
header('Content-type: application/postscript');
header('Content-Disposition: filename="qrcode.eps"');
}
echo (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
exit;
+11 -6
View File
@@ -1,6 +1,9 @@
<?php
namespace chillerlan\QRCodeExamples;
/**
* @created 03.06.2020
* @author Maximilian Kresse
* @license MIT
*/
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Data\QRMatrix;
@@ -8,8 +11,6 @@ use chillerlan\QRCode\Common\EccLevel;
require_once __DIR__ . '/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_FPDF,
@@ -44,6 +45,10 @@ $options = new QROptions([
],
]);
\header('Content-type: application/pdf');
if(php_sapi_name() !== 'cli'){
header('Content-type: application/pdf');
}
echo (new QRCode($options))->render($data);
echo (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
exit;
+29 -33
View File
@@ -6,8 +6,6 @@
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Common\EccLevel;
@@ -16,36 +14,6 @@ require_once '../vendor/autoload.php';
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>QRCode test</title>
<style>
div.qrcode{
margin: 5em;
}
/* rows */
div.qrcode > div {
height: 10px;
}
/* modules */
div.qrcode > div > span {
display: inline-block;
width: 10px;
height: 10px;
}
</style>
</head>
<body>
<?php
$data = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
$options = new QROptions([
'version' => 5,
'outputType' => QRCode::OUTPUT_MARKUP_HTML,
@@ -80,7 +48,35 @@ header('Content-Type: text/html; charset=utf-8');
],
]);
echo (new QRCode($options))->render($data);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>QRCode test</title>
<style>
div.qrcode{
margin: 5em;
}
/* rows */
div.qrcode > div {
height: 10px;
}
/* modules */
div.qrcode > div > span {
display: inline-block;
width: 10px;
height: 10px;
}
</style>
</head>
<body>
<?php
echo (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
?>
</body>
+3 -10
View File
@@ -6,17 +6,12 @@
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Common\EccLevel;
use Throwable;
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_IMAGE_PNG,
@@ -58,8 +53,9 @@ $options = new QROptions([
],
]);
try{
$im = (new QRCode($options))->render($data);
$im = (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
}
catch(Throwable $e){
exit($e->getMessage());
@@ -69,7 +65,4 @@ header('Content-type: image/png');
echo $im;
exit;
+67 -4
View File
@@ -4,17 +4,77 @@
* @author smiley <smiley@chillerlan.net>
* @copyright 2020 smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection, PhpIllegalPsrClassPathInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Common\EccLevel;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Output\{QRGdImage, QRCodeOutputException};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://github.com';
/*
* Class definition
*/
class QRImageWithLogo extends QRGdImage{
/**
* @param string|null $file
* @param string|null $logo
*
* @return string
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
public function dump(string $file = null, string $logo = null):string{
// set returnResource to true to skip further processing for now
$this->options->returnResource = true;
// of course you could accept other formats too (such as resource or Imagick)
// i'm not checking for the file type either for simplicity reasons (assuming PNG)
if(!is_file($logo) || !is_readable($logo)){
throw new QRCodeOutputException('invalid logo');
}
// there's no need to save the result of dump() into $this->image here
parent::dump($file);
$im = imagecreatefrompng($logo);
// get logo image size
$w = imagesx($im);
$h = imagesy($im);
// set new logo size, leave a border of 1 module (no proportional resize/centering)
$lw = ($this->options->logoSpaceWidth - 2) * $this->options->scale;
$lh = ($this->options->logoSpaceHeight - 2) * $this->options->scale;
// get the qrcode size
$ql = $this->matrix->size() * $this->options->scale;
// scale the logo and copy it over. done!
imagecopyresampled($this->image, $im, ($ql - $lw) / 2, ($ql - $lh) / 2, 0, 0, $lw, $lh, $w, $h);
$imageData = $this->dumpImage();
if($file !== null){
$this->saveToFile($imageData, $file);
}
if($this->options->imageBase64){
$imageData = $this->base64encode($imageData, 'image/'.$this->options->outputType);
}
return $imageData;
}
}
/*
* Runtime
*/
$options = new QROptions([
'version' => 5,
@@ -31,11 +91,14 @@ $options = new QROptions([
]);
$qrcode = new QRCode($options);
$qrcode->addByteSegment($data);
$qrcode->addByteSegment('https://github.com');
header('Content-type: image/png');
$qrOutputInterface = new QRImageWithLogo($options, $qrcode->getMatrix());
// dump the output, with an additional logo
// the logo could also be supplied via the options, see the svgWithLogo example
echo $qrOutputInterface->dump(null, __DIR__.'/octocat.png');
exit;
+88 -4
View File
@@ -7,15 +7,96 @@
* @author Smiley <smiley@chillerlan.net>
* @copyright 2019 Smiley
* @license MIT
*
* @noinspection PhpIllegalPsrClassPathInspection, PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Output\QRGdImage;
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
/*
* Class definition
*/
class QRImageWithText extends QRGdImage{
/**
* @inheritDoc
*/
public function dump(string $file = null, string $text = null):string{
// set returnResource to true to skip further processing for now
$this->options->returnResource = true;
// there's no need to save the result of dump() into $this->image here
parent::dump($file);
// render text output if a string is given
if($text !== null){
$this->addText($text);
}
$imageData = $this->dumpImage();
if($file !== null){
$this->saveToFile($imageData, $file);
}
if($this->options->imageBase64){
$imageData = $this->base64encode($imageData, 'image/'.$this->options->outputType);
}
return $imageData;
}
/**
* @inheritDoc
*/
protected function addText(string $text):void{
// save the qrcode image
$qrcode = $this->image;
// options things
$textSize = 3; // see imagefontheight() and imagefontwidth()
$textBG = [200, 200, 200];
$textColor = [50, 50, 50];
$bgWidth = $this->length;
$bgHeight = $bgWidth + 20; // 20px extra space
// create a new image with additional space
$this->image = imagecreatetruecolor($bgWidth, $bgHeight);
$background = imagecolorallocate($this->image, ...$textBG);
// allow transparency
if($this->options->imageTransparent && $this->options->outputType !== QRCode::OUTPUT_IMAGE_JPG){
imagecolortransparent($this->image, $background);
}
// fill the background
imagefilledrectangle($this->image, 0, 0, $bgWidth, $bgHeight, $background);
// copy over the qrcode
imagecopymerge($this->image, $qrcode, 0, 0, 0, 0, $this->length, $this->length, 100);
imagedestroy($qrcode);
$fontColor = imagecolorallocate($this->image, ...$textColor);
$w = imagefontwidth($textSize);
$x = round(($bgWidth - strlen($text) * $w) / 2);
// loop through the string and draw the letters
foreach(str_split($text) as $i => $chr){
imagechar($this->image, $textSize, (int)($i * $w + $x), $this->length, $chr, $fontColor);
}
}
}
/*
* Runtime
*/
$options = new QROptions([
'version' => 7,
@@ -25,11 +106,14 @@ $options = new QROptions([
]);
$qrcode = new QRCode($options);
$qrcode->addByteSegment($data);
$qrcode->addByteSegment('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
header('Content-type: image/png');
$qrOutputInterface = new QRImageWithText($options, $qrcode->getMatrix());
// dump the output, with additional text
// the text could also be supplied via the options, see the svgWithLogo example
echo $qrOutputInterface->dump(null, 'example text');
exit;
+2 -9
View File
@@ -6,16 +6,12 @@
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Common\EccLevel;
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_IMAGICK,
@@ -56,9 +52,6 @@ $options = new QROptions([
header('Content-type: image/png');
echo (new QRCode($options))->render($data);
echo (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
exit;
+5 -3
View File
@@ -4,10 +4,10 @@
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodePublic;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
@@ -86,11 +86,13 @@ try{
send_response(['qrcode' => $qrcode]);
}
// Pokémon exception handler
catch(\Exception $e){
catch(Throwable $e){
header('HTTP/1.1 500 Internal Server Error');
send_response(['error' => $e->getMessage()]);
}
exit;
/**
* @param array $response
*/
+2 -2
View File
@@ -8,8 +8,6 @@
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
@@ -23,3 +21,5 @@ $options->readerIncreaseContrast = true;
$result = (new QRCode($options))->readFromFile(__DIR__.'/../.github/images/example_image.png');
var_dump($result);
exit;
+10 -12
View File
@@ -9,18 +9,12 @@
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Common\EccLevel;
use function gzencode, header;
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
$gzip = true;
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_MARKUP_SVG,
@@ -59,14 +53,18 @@ $options = new QROptions([
]]></style>',
]);
$qrcode = (new QRCode($options))->render($data);
$qrcode = (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
header('Content-type: image/svg+xml');
if(php_sapi_name() !== 'cli'){
header('Content-type: image/svg+xml');
if($gzip){
header('Vary: Accept-Encoding');
header('Content-Encoding: gzip');
$qrcode = gzencode($qrcode, 9);
if(extension_loaded('zlib')){
header('Vary: Accept-Encoding');
header('Content-Encoding: gzip');
$qrcode = gzencode($qrcode, 9);
}
}
echo $qrcode;
exit;
+92 -40
View File
@@ -8,19 +8,94 @@
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QRCodeException, QROptions};
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Common\EccLevel;
use function file_exists, gzencode, header, is_readable, max, min;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Output\QRMarkupSVG;
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
$gzip = true;
/*
* Class definition
*/
$options_arr = [
/**
* Create SVG QR Codes with embedded logos (that are also SVG)
*/
class QRSvgWithLogo extends QRMarkupSVG{
/**
* @inheritDoc
*/
protected function paths():string{
$size = (int)ceil($this->moduleCount * $this->options->svgLogoScale);
// we're calling QRMatrix::setLogoSpace() manually, so QROptions::$addLogoSpace has no effect here
$this->matrix->setLogoSpace($size, $size);
$svg = parent::paths();
$svg .= $this->getLogo();
return $svg;
}
/**
* returns a <g> element that contains the SVG logo and positions it properly within the QR Code
*
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g
* @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform
*/
protected function getLogo():string{
// @todo: customize the <g> element to your liking (css class, style...)
return sprintf(
'%5$s<g transform="translate(%1$s %1$s) scale(%2$s)" class="%3$s">%5$s %4$s%5$s</g>',
($this->moduleCount - ($this->moduleCount * $this->options->svgLogoScale)) / 2,
$this->options->svgLogoScale,
$this->options->svgLogoCssClass,
file_get_contents($this->options->svgLogo),
$this->options->eol
);
}
}
/**
* augment the QROptions class
*/
class SVGWithLogoOptions extends QROptions{
// path to svg logo
protected string $svgLogo;
// logo scale in % of QR Code size, clamped to 10%-30%
protected float $svgLogoScale = 0.20;
// css class for the logo (defined in $svgDefs)
protected string $svgLogoCssClass = '';
// check logo
protected function set_svgLogo(string $svgLogo):void{
if(!file_exists($svgLogo) || !is_readable($svgLogo)){
throw new QRCodeException('invalid svg logo');
}
// @todo: validate svg
$this->svgLogo = $svgLogo;
}
// clamp logo scale
protected function set_svgLogoScale(float $svgLogoScale):void{
$this->svgLogoScale = max(0.05, min(0.3, $svgLogoScale));
}
}
/*
* Runtime
*/
$options = new SVGWithLogoOptions([
// SVG logo options (see extended class below)
'svgLogo' => __DIR__.'/github.svg', // logo from: https://github.com/simple-icons/simple-icons
'svgLogoScale' => 0.25,
@@ -60,44 +135,21 @@ $options_arr = [
.dark{fill: url(#gradient);}
.light{fill: #eaeaea;}
]]></style>',
];
]);
// augment the QROptions class
$options = new class ($options_arr) extends QROptions{
// path to svg logo
protected string $svgLogo;
// logo scale in % of QR Code size, clamped to 10%-30%
protected float $svgLogoScale = 0.20;
// css class for the logo (defined in $svgDefs)
protected string $svgLogoCssClass = '';
$qrcode = (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
// check logo
protected function set_svgLogo(string $svgLogo):void{
if(!file_exists($svgLogo) || !is_readable($svgLogo)){
throw new QRCodeException('invalid svg logo');
}
if(php_sapi_name() !== 'cli'){
header('Content-type: image/svg+xml');
// @todo: validate svg
$this->svgLogo = $svgLogo;
if(extension_loaded('zlib')){
header('Vary: Accept-Encoding');
header('Content-Encoding: gzip');
$qrcode = gzencode($qrcode, 9);
}
// clamp logo scale
protected function set_svgLogoScale(float $svgLogoScale):void{
$this->svgLogoScale = max(0.05, min(0.3, $svgLogoScale));
}
};
$qrcode = (new QRCode($options))->render($data);
header('Content-type: image/svg+xml');
if($gzip){
header('Vary: Accept-Encoding');
header('Content-Encoding: gzip');
$qrcode = gzencode($qrcode, 9);
}
echo $qrcode;
exit;
+3 -5
View File
@@ -8,8 +8,6 @@
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Common\EccLevel;
@@ -17,8 +15,6 @@ use PHPUnit\Util\Color;
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_STRING_TEXT,
@@ -60,4 +56,6 @@ $options = new QROptions([
],
]);
echo (new QRCode($options))->render($data);
echo (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
exit;