Просмотр исходного кода

:octocat: add logo space creation

codemasher 4 лет назад
Родитель
Сommit
87f7f3aa4a
5 измененных файлов с 128 добавлено и 30 удалено
  1. 0 9
      examples/QRImageWithLogo.php
  2. 11 21
      examples/imageWithLogo.php
  3. 10 0
      src/QRCode.php
  4. 60 0
      src/QROptionsTrait.php
  5. 47 0
      tests/QROptionsTest.php

+ 0 - 9
examples/QRImageWithLogo.php

@@ -16,9 +16,6 @@ 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{
 
 	/**
@@ -38,12 +35,6 @@ class QRImageWithLogo extends QRImage{
 			throw new QRCodeOutputException('invalid logo');
 		}
 
-		$this->matrix->setLogoSpace(
-			$this->options->logoSpaceWidth,
-			$this->options->logoSpaceHeight
-			// not utilizing the position here
-		);
-
 		// there's no need to save the result of dump() into $this->image here
 		parent::dump($file);
 

+ 11 - 21
examples/imageWithLogo.php

@@ -14,27 +14,17 @@ use chillerlan\QRCode\Common\EccLevel;
 require_once __DIR__.'/../vendor/autoload.php';
 
 $data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
-/**
- * @property int $logoSpaceWidth
- * @property int $logoSpaceHeight
- *
- * @noinspection PhpIllegalPsrClassPathInspection
- */
-class LogoOptions extends QROptions{
-	// size in QR modules, multiply with QROptions::$scale for pixel size
-	protected int $logoSpaceWidth;
-	protected int $logoSpaceHeight;
-}
-
-$options = new LogoOptions;
-
-$options->version          = 7;
-$options->eccLevel         = EccLevel::H;
-$options->imageBase64      = false;
-$options->logoSpaceWidth   = 13;
-$options->logoSpaceWidth   = 13;
-$options->scale            = 5;
-$options->imageTransparent = false;
+
+$options = new QROptions([
+	'version'          => 7,
+	'eccLevel'         => EccLevel::H,
+	'imageBase64'      => false,
+	'addLogoSpace'     => true,
+	'logoSpaceWidth'   => 13,
+	'logoSpaceHeight'  => 13,
+	'scale'            => 5,
+	'imageTransparent' => false,
+]);
 
 $qrcode = new QRCode($options);
 $qrcode->addByteSegment($data);

+ 10 - 0
src/QRCode.php

@@ -161,6 +161,16 @@ class QRCode{
 
 		$matrix = $dataInterface->writeMatrix($maskPattern);
 
+		// add matrix modifications after mask pattern evaluation and before handing over to output
+		if($this->options->addLogoSpace){
+			$matrix->setLogoSpace(
+				$this->options->logoSpaceWidth,
+				$this->options->logoSpaceHeight,
+				$this->options->logoSpaceStartX,
+				$this->options->logoSpaceStartY
+			);
+		}
+
 		if($this->options->addQuietzone){
 			$matrix->setQuietZone($this->options->quietzoneSize);
 		}

+ 60 - 0
src/QROptionsTrait.php

@@ -284,6 +284,31 @@ trait QROptionsTrait{
 	 */
 	protected bool $readerIncreaseContrast = false;
 
+	/**
+	 * Toggles logo space creation
+	 */
+	protected bool $addLogoSpace = false;
+
+	/**
+	 * width of the logo space
+	 */
+	protected int $logoSpaceWidth = 0;
+
+	/**
+	 * height of the logo space
+	 */
+	protected int $logoSpaceHeight = 0;
+
+	/**
+	 * optional horizontal start position of the logo space (top left corner)
+	 */
+	protected ?int $logoSpaceStartX = null;
+
+	/**
+	 * optional vertical start position of the logo space (top left corner)
+	 */
+	protected ?int $logoSpaceStartY = null;
+
 	/**
 	 * clamp min/max version number
 	 */
@@ -412,4 +437,39 @@ trait QROptionsTrait{
 			: GDLuminanceSource::class;
 	}
 
+	/**
+	 * clamp the logo space values between 0 and maximum length (177 modules at version 40)
+	 */
+	protected function clampLogoSpaceValue(int $value):int{
+		return (int)max(0, min(177, $value));
+	}
+
+	/**
+	 * clamp/set logo space width
+	 */
+	protected function set_logoSpaceWidth(int $value):void{
+		$this->logoSpaceWidth = $this->clampLogoSpaceValue($value);
+	}
+
+	/**
+	 * clamp/set logo space height
+	 */
+	protected function set_logoSpaceHeight(int $value):void{
+		$this->logoSpaceHeight = $this->clampLogoSpaceValue($value);
+	}
+
+	/**
+	 * clamp/set horizontal logo space start
+	 */
+	protected function set_logoSpaceStartX(?int $value):void{
+		$this->logoSpaceStartX = $value === null ? null : $this->clampLogoSpaceValue($value);
+	}
+
+	/**
+	 * clamp/set vertical logo space start
+	 */
+	protected function set_logoSpaceStartY(?int $value):void{
+		$this->logoSpaceStartY = $value === null ? null : $this->clampLogoSpaceValue($value);
+	}
+
 }

+ 47 - 0
tests/QROptionsTest.php

@@ -139,4 +139,51 @@ class QROptionsTest extends TestCase{
 		$o = new QROptions(['imageTransparencyBG' => ['r', 'g', 'b']]);
 	}
 
+	/**
+	 * @return int[][]
+	 */
+	public function logoSpaceValueProvider():array{
+		return [
+			'negative' => [ -1,   0],
+			'zero'     => [  0,   0],
+			'normal'   => [ 69,  69],
+			'max'      => [177, 177],
+			'exceed'   => [178, 177],
+		];
+	}
+
+	/**
+	 * Tests the clamping (between 0 and 177) of the logo space values
+	 *
+	 * @dataProvider logoSpaceValueProvider
+	 */
+	public function testClampLogoSpaceValue(int $value, int $expected):void{
+		$o = new QROptions;
+
+		foreach(['logoSpaceWidth', 'logoSpaceHeight', 'logoSpaceStartX', 'logoSpaceStartY'] as $prop){
+			$o->{$prop} = $value;
+			$this::assertSame($expected, $o->{$prop});
+		}
+
+	}
+
+	/**
+	 * Tests if the optional logo space start values are nullable
+	 */
+	public function testLogoSpaceStartNullable():void{
+		$o = new QROptions([
+			'logoSpaceStartX' => 42,
+			'logoSpaceStartY' => 69,
+		]);
+
+		$this::assertSame(42, $o->logoSpaceStartX);
+		$this::assertSame(69, $o->logoSpaceStartY);
+
+		$o->logoSpaceStartX = null;
+		$o->logoSpaceStartY = null;
+
+		$this::assertNull($o->logoSpaceStartX);
+		$this::assertNull($o->logoSpaceStartY);
+	}
+
 }