From 4968063fb3baeedb658293f89f9673fbf2499a3e Mon Sep 17 00:00:00 2001 From: codemasher Date: Wed, 18 Nov 2020 21:49:20 +0100 Subject: [PATCH] :octocat: logo image example (#52) --- examples/QRImageWithLogo.php | 81 +++++++++++++++++++++++++++++++++++ examples/imageWithLogo.php | 44 +++++++++++++++++++ examples/octocat.png | Bin 0 -> 2468 bytes 3 files changed, 125 insertions(+) create mode 100644 examples/QRImageWithLogo.php create mode 100644 examples/imageWithLogo.php create mode 100644 examples/octocat.png diff --git a/examples/QRImageWithLogo.php b/examples/QRImageWithLogo.php new file mode 100644 index 000000000..f9d94ae34 --- /dev/null +++ b/examples/QRImageWithLogo.php @@ -0,0 +1,81 @@ + + * @copyright 2020 smiley + * @license MIT + * + * @noinspection PhpComposerExtensionStubsInspection + */ + +namespace chillerlan\QRCodeExamples; + +use chillerlan\QRCode\Output\{QRCodeOutputException, QRImage}; + +use function imagecopyresampled, imagecreatefrompng, imagesx, imagesy, is_file, is_readable; + +/** + * @property \chillerlan\QRCodeExamples\LogoOptions $options + */ +class QRImageWithLogo extends QRImage{ + + /** + * @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'); + } + + $this->matrix->setLogoSpace( + $this->options->logoWidth, + $this->options->logoHeight + // not utilizing the position here + ); + + // 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 + $lw = ($this->options->logoWidth - 2) * $this->options->scale; + $lh = ($this->options->logoHeight - 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 = 'data:image/'.$this->options->outputType.';base64,'.base64_encode($imageData); + } + + return $imageData; + } + +} diff --git a/examples/imageWithLogo.php b/examples/imageWithLogo.php new file mode 100644 index 000000000..90e41e069 --- /dev/null +++ b/examples/imageWithLogo.php @@ -0,0 +1,44 @@ + + * @copyright 2020 smiley + * @license MIT + */ + +namespace chillerlan\QRCodeExamples; + +use chillerlan\QRCode\{QRCode, QROptions}; + +require_once __DIR__.'/../vendor/autoload.php'; + +$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s'; +/** + * @property int $logoWidth + * @property int $logoHeight + * + * @noinspection PhpIllegalPsrClassPathInspection + */ +class LogoOptions extends QROptions{ + protected int $logoWidth; + protected int $logoHeight; +} + +$options = new LogoOptions; + +$options->version = 7; +$options->eccLevel = QRCode::ECC_H; +$options->imageBase64 = false; +$options->logoWidth = 13; +$options->logoHeight = 13; +$options->scale = 5; +$options->imageTransparent = false; + +header('Content-type: image/png'); + +$qrOutputInterface = new QRImageWithLogo($options, (new QRCode($options))->getMatrix($data)); + +// dump the output, with an additional logo +echo $qrOutputInterface->dump(null, __DIR__.'/octocat.png'); diff --git a/examples/octocat.png b/examples/octocat.png new file mode 100644 index 0000000000000000000000000000000000000000..f9050b935792512349e6f1ba0e6e55d99ecbf508 GIT binary patch literal 2468 zcmdT_`8U)H8~>UyLoN;~FS1vbQdF{J8?J4NA)_*3EJd=#Ysq#qBaJ2d9!+*iOqN76 z(^xZO--od$2`LQ5i0|#b_pf+A=RBX~x96PabIucIjWQG9li&jYKmciOZ1Ygs5xr>DERy2_uF=WzDH z?*pQu$A67A2j97g#bUvYVfOAWxI||&X=%zQq$DMKdU`Ze6t`L1At50a78Yt3)UFz6 zLZMLb*EGl)1KE=xIDatIC?g}&*VotE+q>0TGCMo#=H})X6fiL{5$0xh-_CN4Quehz zAM0~(lvF`-vTbQ;;q=!Vo0$#_3`mKIZftB!PftfjM|*pFYiMe8baV_24S_!fIfD)0 zOq;K-?-9NudwYB10Y25?2~4K)K0N77Rnt?f zE1Yh}DvRH`ICrvj1Dmv1-U8)%QtNaV2D$%{knUKIrHY0|4MMNMl3W5NzqV zo86ST7|%~?E1`q<&UOw*uYY(ebJZ~|NOS7@W#sQnpDbYS_9KDp0cDm`BYpX)e{f9Fux9 zIBaHbgExwuw+dM73(IHL3{U;s7JF|gqtiLoF}NcIZQBUEcIl~CQ0y5axVBmuAZ{-A zAgTBPwfENu1Zj~_BHMQ|d!`7x1yBX$!(Zy8KA4gXmMyx3R4y zI5*C@cmz?}SVBEd-r68f(l4QqmpfUJ#~W+S%_&QRiZYcUj&;wwfTN+ZMi=}`nzhbL z7fP1)zQ(zz8R^NPv9KAGk*V;^T^}k#O58HIZxGIJV+N~4HH<*YqGgNuVn|1Fwgtmu zkS3PO%D0l8ROr*A!^7$1vke{((O2)#H*yfuqaM=*@4_hKWZxe73ONNt+%=_>|9|D zwpH@HH9r)ZtCRK#&k2I)Jv?!id=>bQs3+Gu5#X4NBW)2h^7_a;+`?oezT!HhMfcvD z><8mG&fOmsaf0FB-K)ibM?9q#hhM=L6KnPUP>D_{$bf-HSm<9(unyyeb zX#kQ;fX=PIrv7-0Xy=O7BH9+OeG@Vhr+$WUb1T`Zx~Qf{Cgu3%b&AMuNgMbYM2f1+ z!+|WN7BOin8eVH!U_3&#`);i*AZZTGV`OE1$wYX|XMHd#nQV8etCcSJ%Iu~lB zc5Aogv-&v;o;1t0C;N^S8w^NxnO zsS1<;NeAgBTIUI-iuy_43v|f9#yU|y$PCwz8e6-$S=;_a*wvpsh%SHXr?)?(u35XW zt{ECi;2jf*SI)jX85o>dSJe?Roo&v3V25WL z{Bh$!e*(toq=fQw(->1;4oh3IiSuTR(t^@#mKnUd!bkIES!ty zOiRQ~%m+a=f3uVn_ShKd;K@FhP?G@9yCs~obQSr?BL0?ezFa&v{q^5JSA_umycY#oGsD2MCI;jqMAX6hlh@>GIb7qHfpaMoXj zlbzvw+ApCJ{x4S0FtKXLb7>hIodmf&Qty1^yhGGI8>o9ks+Gg(IA#EZEn%LHKQYjK z8-ChZgt9}|(q2RA1_|dR@~A*BQ$EFu6y(pH3)Co3g*}bgmSe+|VvwRsl$lU>q0222 z`4z&d?l%N`sCtcZP7B}o43AcwD;#Ve9c)Fyu2|&%s0g4&e)1F1XV%ak|Nc1u(gbBp IGIEak8#