From e971678ac514519af3e908e45ac0cc9d6591c03d Mon Sep 17 00:00:00 2001 From: smiley Date: Sat, 9 Jul 2022 18:10:23 +0200 Subject: [PATCH] :octocat: examples cleanup --- examples/MyCustomOutput.php | 58 -------------- examples/QRImageWithLogo.php | 70 ----------------- examples/QRImageWithText.php | 98 ------------------------ examples/QRSvgWithLogo.php | 54 ------------- examples/custom_output.php | 63 ++++++++++++++- examples/eps.php | 19 ++--- examples/fpdf.php | 17 ++-- examples/html.php | 62 +++++++-------- examples/image.php | 13 +--- examples/imageWithLogo.php | 71 ++++++++++++++++- examples/imageWithText.php | 92 +++++++++++++++++++++- examples/imagick.php | 11 +-- examples/qrcode-interactive.php | 8 +- examples/reader.php | 4 +- examples/svg.php | 22 +++--- examples/svgWithLogo.php | 132 ++++++++++++++++++++++---------- examples/text.php | 8 +- 17 files changed, 382 insertions(+), 420 deletions(-) delete mode 100644 examples/MyCustomOutput.php delete mode 100644 examples/QRImageWithLogo.php delete mode 100644 examples/QRImageWithText.php delete mode 100644 examples/QRSvgWithLogo.php diff --git a/examples/MyCustomOutput.php b/examples/MyCustomOutput.php deleted file mode 100644 index 55f01278e..000000000 --- a/examples/MyCustomOutput.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @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; - } - -} diff --git a/examples/QRImageWithLogo.php b/examples/QRImageWithLogo.php deleted file mode 100644 index 788a16417..000000000 --- a/examples/QRImageWithLogo.php +++ /dev/null @@ -1,70 +0,0 @@ - - * @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; - } - -} diff --git a/examples/QRImageWithText.php b/examples/QRImageWithText.php deleted file mode 100644 index 9bf91d276..000000000 --- a/examples/QRImageWithText.php +++ /dev/null @@ -1,98 +0,0 @@ - - * @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); - } - } - -} diff --git a/examples/QRSvgWithLogo.php b/examples/QRSvgWithLogo.php deleted file mode 100644 index a6e366d0c..000000000 --- a/examples/QRSvgWithLogo.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @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 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 element to your liking (css class, style...) - return sprintf( - '%5$s%5$s %4$s%5$s', - ($this->moduleCount - ($this->moduleCount * $this->options->svgLogoScale)) / 2, - $this->options->svgLogoScale, - $this->options->svgLogoCssClass, - file_get_contents($this->options->svgLogo), - $this->options->eol - ); - } - -} diff --git a/examples/custom_output.php b/examples/custom_output.php index 175b5b86e..05b032d47 100644 --- a/examples/custom_output.php +++ b/examples/custom_output.php @@ -4,15 +4,70 @@ * @author Smiley * @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; diff --git a/examples/eps.php b/examples/eps.php index feed60652..84e06db06 100644 --- a/examples/eps.php +++ b/examples/eps.php @@ -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; diff --git a/examples/fpdf.php b/examples/fpdf.php index a693df725..de9606777 100644 --- a/examples/fpdf.php +++ b/examples/fpdf.php @@ -1,6 +1,9 @@ 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; diff --git a/examples/html.php b/examples/html.php index 707f49ce8..a8f8924e3 100644 --- a/examples/html.php +++ b/examples/html.php @@ -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'); -?> - - - - - - QRCode test - - - - 5, 'outputType' => QRCode::OUTPUT_MARKUP_HTML, @@ -80,7 +48,35 @@ header('Content-Type: text/html; charset=utf-8'); ], ]); - echo (new QRCode($options))->render($data); +?> + + + + + + QRCode test + + + +render('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); ?> diff --git a/examples/image.php b/examples/image.php index 1223a8821..66a90a17b 100644 --- a/examples/image.php +++ b/examples/image.php @@ -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; diff --git a/examples/imageWithLogo.php b/examples/imageWithLogo.php index 2f929a9e6..730acfefc 100644 --- a/examples/imageWithLogo.php +++ b/examples/imageWithLogo.php @@ -4,17 +4,77 @@ * @author smiley * @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; diff --git a/examples/imageWithText.php b/examples/imageWithText.php index 0f040f79e..5d8c89ad2 100644 --- a/examples/imageWithText.php +++ b/examples/imageWithText.php @@ -7,15 +7,96 @@ * @author Smiley * @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; diff --git a/examples/imagick.php b/examples/imagick.php index 2cb06ad8d..5376d08bb 100644 --- a/examples/imagick.php +++ b/examples/imagick.php @@ -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; diff --git a/examples/qrcode-interactive.php b/examples/qrcode-interactive.php index 637450e99..4a480c3fe 100644 --- a/examples/qrcode-interactive.php +++ b/examples/qrcode-interactive.php @@ -4,10 +4,10 @@ * @author Smiley * @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 */ diff --git a/examples/reader.php b/examples/reader.php index a6ea549ef..c075e9dab 100644 --- a/examples/reader.php +++ b/examples/reader.php @@ -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; diff --git a/examples/svg.php b/examples/svg.php index a183b7ec8..94748d190 100644 --- a/examples/svg.php +++ b/examples/svg.php @@ -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([ ]]>', ]); -$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; diff --git a/examples/svgWithLogo.php b/examples/svgWithLogo.php index b92c30e35..1900f27e3 100644 --- a/examples/svgWithLogo.php +++ b/examples/svgWithLogo.php @@ -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 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 element to your liking (css class, style...) + return sprintf( + '%5$s%5$s %4$s%5$s', + ($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;} ]]>', -]; +]); -// 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; diff --git a/examples/text.php b/examples/text.php index e85f91b4f..1aef82ab1 100644 --- a/examples/text.php +++ b/examples/text.php @@ -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;