Skip to content

Commit 87f7f3a

Browse files
committed
:octocat: add logo space creation
1 parent 1aee1e9 commit 87f7f3a

File tree

5 files changed

+128
-30
lines changed

5 files changed

+128
-30
lines changed

examples/QRImageWithLogo.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
use function imagecopyresampled, imagecreatefrompng, imagesx, imagesy, is_file, is_readable;
1818

19-
/**
20-
* @property \chillerlan\QRCodeExamples\LogoOptions $options
21-
*/
2219
class QRImageWithLogo extends QRImage{
2320

2421
/**
@@ -38,12 +35,6 @@ public function dump(string $file = null, string $logo = null):string{
3835
throw new QRCodeOutputException('invalid logo');
3936
}
4037

41-
$this->matrix->setLogoSpace(
42-
$this->options->logoSpaceWidth,
43-
$this->options->logoSpaceHeight
44-
// not utilizing the position here
45-
);
46-
4738
// there's no need to save the result of dump() into $this->image here
4839
parent::dump($file);
4940

examples/imageWithLogo.php

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,17 @@
1414
require_once __DIR__.'/../vendor/autoload.php';
1515

1616
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
17-
/**
18-
* @property int $logoSpaceWidth
19-
* @property int $logoSpaceHeight
20-
*
21-
* @noinspection PhpIllegalPsrClassPathInspection
22-
*/
23-
class LogoOptions extends QROptions{
24-
// size in QR modules, multiply with QROptions::$scale for pixel size
25-
protected int $logoSpaceWidth;
26-
protected int $logoSpaceHeight;
27-
}
28-
29-
$options = new LogoOptions;
30-
31-
$options->version = 7;
32-
$options->eccLevel = EccLevel::H;
33-
$options->imageBase64 = false;
34-
$options->logoSpaceWidth = 13;
35-
$options->logoSpaceWidth = 13;
36-
$options->scale = 5;
37-
$options->imageTransparent = false;
17+
18+
$options = new QROptions([
19+
'version' => 7,
20+
'eccLevel' => EccLevel::H,
21+
'imageBase64' => false,
22+
'addLogoSpace' => true,
23+
'logoSpaceWidth' => 13,
24+
'logoSpaceHeight' => 13,
25+
'scale' => 5,
26+
'imageTransparent' => false,
27+
]);
3828

3929
$qrcode = new QRCode($options);
4030
$qrcode->addByteSegment($data);

src/QRCode.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ public function getMatrix():QRMatrix{
161161

162162
$matrix = $dataInterface->writeMatrix($maskPattern);
163163

164+
// add matrix modifications after mask pattern evaluation and before handing over to output
165+
if($this->options->addLogoSpace){
166+
$matrix->setLogoSpace(
167+
$this->options->logoSpaceWidth,
168+
$this->options->logoSpaceHeight,
169+
$this->options->logoSpaceStartX,
170+
$this->options->logoSpaceStartY
171+
);
172+
}
173+
164174
if($this->options->addQuietzone){
165175
$matrix->setQuietZone($this->options->quietzoneSize);
166176
}

src/QROptionsTrait.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,31 @@ trait QROptionsTrait{
284284
*/
285285
protected bool $readerIncreaseContrast = false;
286286

287+
/**
288+
* Toggles logo space creation
289+
*/
290+
protected bool $addLogoSpace = false;
291+
292+
/**
293+
* width of the logo space
294+
*/
295+
protected int $logoSpaceWidth = 0;
296+
297+
/**
298+
* height of the logo space
299+
*/
300+
protected int $logoSpaceHeight = 0;
301+
302+
/**
303+
* optional horizontal start position of the logo space (top left corner)
304+
*/
305+
protected ?int $logoSpaceStartX = null;
306+
307+
/**
308+
* optional vertical start position of the logo space (top left corner)
309+
*/
310+
protected ?int $logoSpaceStartY = null;
311+
287312
/**
288313
* clamp min/max version number
289314
*/
@@ -412,4 +437,39 @@ public function getLuminanceSourceFQCN():string{
412437
: GDLuminanceSource::class;
413438
}
414439

440+
/**
441+
* clamp the logo space values between 0 and maximum length (177 modules at version 40)
442+
*/
443+
protected function clampLogoSpaceValue(int $value):int{
444+
return (int)max(0, min(177, $value));
445+
}
446+
447+
/**
448+
* clamp/set logo space width
449+
*/
450+
protected function set_logoSpaceWidth(int $value):void{
451+
$this->logoSpaceWidth = $this->clampLogoSpaceValue($value);
452+
}
453+
454+
/**
455+
* clamp/set logo space height
456+
*/
457+
protected function set_logoSpaceHeight(int $value):void{
458+
$this->logoSpaceHeight = $this->clampLogoSpaceValue($value);
459+
}
460+
461+
/**
462+
* clamp/set horizontal logo space start
463+
*/
464+
protected function set_logoSpaceStartX(?int $value):void{
465+
$this->logoSpaceStartX = $value === null ? null : $this->clampLogoSpaceValue($value);
466+
}
467+
468+
/**
469+
* clamp/set vertical logo space start
470+
*/
471+
protected function set_logoSpaceStartY(?int $value):void{
472+
$this->logoSpaceStartY = $value === null ? null : $this->clampLogoSpaceValue($value);
473+
}
474+
415475
}

tests/QROptionsTest.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,51 @@ public function testInvalidRGBValueException():void{
139139
$o = new QROptions(['imageTransparencyBG' => ['r', 'g', 'b']]);
140140
}
141141

142+
/**
143+
* @return int[][]
144+
*/
145+
public function logoSpaceValueProvider():array{
146+
return [
147+
'negative' => [ -1, 0],
148+
'zero' => [ 0, 0],
149+
'normal' => [ 69, 69],
150+
'max' => [177, 177],
151+
'exceed' => [178, 177],
152+
];
153+
}
154+
155+
/**
156+
* Tests the clamping (between 0 and 177) of the logo space values
157+
*
158+
* @dataProvider logoSpaceValueProvider
159+
*/
160+
public function testClampLogoSpaceValue(int $value, int $expected):void{
161+
$o = new QROptions;
162+
163+
foreach(['logoSpaceWidth', 'logoSpaceHeight', 'logoSpaceStartX', 'logoSpaceStartY'] as $prop){
164+
$o->{$prop} = $value;
165+
$this::assertSame($expected, $o->{$prop});
166+
}
167+
168+
}
169+
170+
/**
171+
* Tests if the optional logo space start values are nullable
172+
*/
173+
public function testLogoSpaceStartNullable():void{
174+
$o = new QROptions([
175+
'logoSpaceStartX' => 42,
176+
'logoSpaceStartY' => 69,
177+
]);
178+
179+
$this::assertSame(42, $o->logoSpaceStartX);
180+
$this::assertSame(69, $o->logoSpaceStartY);
181+
182+
$o->logoSpaceStartX = null;
183+
$o->logoSpaceStartY = null;
184+
185+
$this::assertNull($o->logoSpaceStartX);
186+
$this::assertNull($o->logoSpaceStartY);
187+
}
188+
142189
}

0 commit comments

Comments
 (0)