| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- <?php
- /**
- * php-gd realization of QR code with rounded modules
- *
- * @see https://github.com/chillerlan/php-qrcode/pull/215
- * @see https://github.com/chillerlan/php-qrcode/issues/127
- *
- * @created 17.09.2023
- * @author livingroot
- * @copyright 2023 livingroot
- * @license MIT
- *
- * @noinspection PhpComposerExtensionStubsInspection
- */
- declare(strict_types=1);
- use chillerlan\QRCode\{QRCode, QROptions};
- use chillerlan\QRCode\Common\EccLevel;
- use chillerlan\QRCode\Data\QRMatrix;
- use chillerlan\QRCode\Output\QRGdImagePNG;
- use chillerlan\Settings\SettingsContainerInterface;
- require_once __DIR__.'/../vendor/autoload.php';
- // --------------------
- // Class definition
- // --------------------
- class QRGdRounded extends QRGdImagePNG{
- public function __construct(SettingsContainerInterface|QROptions $options, QRMatrix $matrix){
- // enable the internal scaling for better rounding results at scale < 20
- $options->drawCircularModules = true;
- parent::__construct($options, $matrix);
- }
- protected function module(int $x, int $y, int $M_TYPE):void{
- /**
- * The bit order (starting from 0):
- *
- * 0 1 2
- * 7 # 3
- * 6 5 4
- */
- $neighbours = $this->matrix->checkNeighbours($x, $y);
- $x1 = ($x * $this->scale);
- $y1 = ($y * $this->scale);
- $x2 = (($x + 1) * $this->scale);
- $y2 = (($y + 1) * $this->scale);
- $rectsize = (int)($this->scale / 2);
- $light = $this->getModuleValue($M_TYPE);
- $dark = $this->getModuleValue($M_TYPE | QRMatrix::IS_DARK);
- // ------------------
- // Outer rounding
- // ------------------
- if(($neighbours & (1 << 7))){ // neighbour left
- // top left
- imagefilledrectangle($this->image, $x1, $y1, ($x1 + $rectsize), ($y1 + $rectsize), $light);
- // bottom left
- imagefilledrectangle($this->image, $x1, ($y2 - $rectsize), ($x1 + $rectsize), $y2, $light);
- }
- if(($neighbours & (1 << 3))){ // neighbour right
- // top right
- imagefilledrectangle($this->image, ($x2 - $rectsize), $y1, $x2, ($y1 + $rectsize), $light);
- // bottom right
- imagefilledrectangle($this->image, ($x2 - $rectsize), ($y2 - $rectsize), $x2, $y2, $light);
- }
- if(($neighbours & (1 << 1))){ // neighbour top
- // top left
- imagefilledrectangle($this->image, $x1, $y1, ($x1 + $rectsize), ($y1 + $rectsize), $light);
- // top right
- imagefilledrectangle($this->image, ($x2 - $rectsize), $y1, $x2, ($y1 + $rectsize), $light);
- }
- if(($neighbours & (1 << 5))){ // neighbour bottom
- // bottom left
- imagefilledrectangle($this->image, $x1, ($y2 - $rectsize), ($x1 + $rectsize), $y2, $light);
- // bottom right
- imagefilledrectangle($this->image, ($x2 - $rectsize), ($y2 - $rectsize), $x2, $y2, $light);
- }
- // ---------------------
- // inner rounding
- // ---------------------
- if(!$this->matrix->check($x, $y)){
- if(($neighbours & 1) && ($neighbours & (1 << 7)) && ($neighbours & (1 << 1))){
- // top left
- imagefilledrectangle($this->image, $x1, $y1, ($x1 + $rectsize), ($y1 + $rectsize), $dark);
- }
- if(($neighbours & (1 << 1)) && ($neighbours & (1 << 2)) && ($neighbours & (1 << 3))){
- // top right
- imagefilledrectangle($this->image, ($x2 - $rectsize), $y1, $x2, ($y1 + $rectsize), $dark);
- }
- if(($neighbours & (1 << 7)) && ($neighbours & (1 << 6)) && ($neighbours & (1 << 5))){
- // bottom left
- imagefilledrectangle($this->image, $x1, ($y2 - $rectsize), ($x1 + $rectsize), $y2, $dark);
- }
- if(($neighbours & (1 << 3)) && ($neighbours & (1 << 4)) && ($neighbours & (1 << 5))){
- // bottom right
- imagefilledrectangle($this->image, ($x2 - $rectsize), ($y2 - $rectsize), $x2, $y2, $dark);
- }
- }
- imagefilledellipse(
- $this->image,
- (int)($x * $this->scale + $this->scale / 2),
- (int)($y * $this->scale + $this->scale / 2),
- ($this->scale - 1),
- ($this->scale - 1),
- $light,
- );
- }
- }
- // --------------------
- // Example
- // --------------------
- $options = new QROptions([
- 'version' => 7,
- 'eccLevel' => EccLevel::H,
- 'outputInterface' => QRGdRounded::class,
- 'outputBase64' => false,
- 'scale' => 30,
- 'addLogoSpace' => true,
- 'logoSpaceWidth' => 13,
- 'logoSpaceHeight' => 13,
- ]);
- $img = (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
- header('Content-type: image/png');
- echo $img;
|