Forráskód Böngészése

:octocat: circular modules in GD output

codemasher 4 éve
szülő
commit
9b54d1d565
5 módosított fájl, 75 hozzáadás és 38 törlés
  1. 30 18
      examples/image.php
  2. 3 3
      examples/svg.php
  3. 35 12
      src/Output/QRImage.php
  4. 2 2
      src/Output/QRMarkup.php
  5. 5 3
      src/QROptionsTrait.php

+ 30 - 18
examples/image.php

@@ -11,51 +11,63 @@ namespace chillerlan\QRCodeExamples;
 use chillerlan\QRCode\{QRCode, QROptions};
 use chillerlan\QRCode\{QRCode, QROptions};
 use chillerlan\QRCode\Data\QRMatrix;
 use chillerlan\QRCode\Data\QRMatrix;
 use chillerlan\QRCode\Common\EccLevel;
 use chillerlan\QRCode\Common\EccLevel;
+use Throwable;
 
 
 require_once __DIR__.'/../vendor/autoload.php';
 require_once __DIR__.'/../vendor/autoload.php';
 
 
 $data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
 $data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
 
 
 $options = new QROptions([
 $options = new QROptions([
-	'version'      => 5,
-	'outputType'   => QRCode::OUTPUT_IMAGE_PNG,
-	'eccLevel'     => EccLevel::L,
-	'scale'        => 5,
-	'imageBase64'  => false,
-	'moduleValues' => [
+	'version'             => 7,
+	'outputType'          => QRCode::OUTPUT_IMAGE_PNG,
+	'eccLevel'            => EccLevel::L,
+	'scale'               => 10,
+	'imageBase64'         => false,
+	'imageTransparent'    => false,
+	'drawCircularModules' => true,
+	'circleRadius'        => 0.4,
+	'keepAsSquare'        => [QRMatrix::M_FINDER|QRMatrix::IS_DARK, QRMatrix::M_FINDER_DOT, QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK],
+	'moduleValues'        => [
 		// finder
 		// finder
 		QRMatrix::M_FINDER | QRMatrix::IS_DARK     => [0, 63, 255], // dark (true)
 		QRMatrix::M_FINDER | QRMatrix::IS_DARK     => [0, 63, 255], // dark (true)
-		QRMatrix::M_FINDER                         => [255, 255, 255], // light (false), white is the transparency color and is enabled by default
-		QRMatrix::M_FINDER_DOT | QRMatrix::IS_DARK => [241, 28, 163], // finder dot, dark (true)
+		QRMatrix::M_FINDER                         => [233, 233, 233], // light (false), white is the transparency color and is enabled by default
+		QRMatrix::M_FINDER_DOT | QRMatrix::IS_DARK => [0, 63, 255], // finder dot, dark (true)
 		// alignment
 		// alignment
 		QRMatrix::M_ALIGNMENT | QRMatrix::IS_DARK  => [255, 0, 255],
 		QRMatrix::M_ALIGNMENT | QRMatrix::IS_DARK  => [255, 0, 255],
-		QRMatrix::M_ALIGNMENT                      => [255, 255, 255],
+		QRMatrix::M_ALIGNMENT                      => [233, 233, 233],
 		// timing
 		// timing
 		QRMatrix::M_TIMING | QRMatrix::IS_DARK     => [255, 0, 0],
 		QRMatrix::M_TIMING | QRMatrix::IS_DARK     => [255, 0, 0],
-		QRMatrix::M_TIMING                         => [255, 255, 255],
+		QRMatrix::M_TIMING                         => [233, 233, 233],
 		// format
 		// format
-		QRMatrix::M_FORMAT | QRMatrix::IS_DARK     => [67, 99, 84],
-		QRMatrix::M_FORMAT                         => [255, 255, 255],
+		QRMatrix::M_FORMAT | QRMatrix::IS_DARK     => [67, 159, 84],
+		QRMatrix::M_FORMAT                         => [233, 233, 233],
 		// version
 		// version
 		QRMatrix::M_VERSION | QRMatrix::IS_DARK    => [62, 174, 190],
 		QRMatrix::M_VERSION | QRMatrix::IS_DARK    => [62, 174, 190],
-		QRMatrix::M_VERSION                        => [255, 255, 255],
+		QRMatrix::M_VERSION                        => [233, 233, 233],
 		// data
 		// data
 		QRMatrix::M_DATA | QRMatrix::IS_DARK       => [0, 0, 0],
 		QRMatrix::M_DATA | QRMatrix::IS_DARK       => [0, 0, 0],
-		QRMatrix::M_DATA                           => [255, 255, 255],
+		QRMatrix::M_DATA                           => [233, 233, 233],
 		// darkmodule
 		// darkmodule
 		QRMatrix::M_DARKMODULE | QRMatrix::IS_DARK => [0, 0, 0],
 		QRMatrix::M_DARKMODULE | QRMatrix::IS_DARK => [0, 0, 0],
 		// separator
 		// separator
-		QRMatrix::M_SEPARATOR                      => [255, 255, 255],
+		QRMatrix::M_SEPARATOR                      => [233, 233, 233],
 		// quietzone
 		// quietzone
-		QRMatrix::M_QUIETZONE                      => [255, 255, 255],
+		QRMatrix::M_QUIETZONE                      => [233, 233, 233],
 		// logo (requires a call to QRMatrix::setLogoSpace()), see QRImageWithLogo
 		// logo (requires a call to QRMatrix::setLogoSpace()), see QRImageWithLogo
-		QRMatrix::M_LOGO                           => [255, 255, 255],
+		QRMatrix::M_LOGO                           => [233, 233, 233],
 	],
 	],
 ]);
 ]);
 
 
+try{
+	$im = (new QRCode($options))->render($data);
+}
+catch(Throwable $e){
+	exit($e->getMessage());
+}
+
 header('Content-type: image/png');
 header('Content-type: image/png');
 
 
-echo (new QRCode($options))->render($data);
+echo $im;
 
 
 
 
 
 

+ 3 - 3
examples/svg.php

@@ -29,10 +29,10 @@ $options = new QROptions([
 	'markupDark'             => '',
 	'markupDark'             => '',
 	'markupLight'            => '',
 	'markupLight'            => '',
 	// draw the modules as circles isntead of squares
 	// draw the modules as circles isntead of squares
-	'svgDrawCircularModules' => true,
-	'svgCircleRadius'           => 0.3,
+	'drawCircularModules' => true,
+	'circleRadius'           => 0.4,
 	// keep modules of thhese types as square
 	// keep modules of thhese types as square
-	'svgKeepAsSquare'        => [QRMatrix::M_FINDER|QRMatrix::IS_DARK, QRMatrix::M_FINDER_DOT, QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK],
+	'keepAsSquare'        => [QRMatrix::M_FINDER|QRMatrix::IS_DARK, QRMatrix::M_FINDER_DOT, QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK],
 	// connect
 	// connect
 	'svgConnectPaths'        => true,
 	'svgConnectPaths'        => true,
 	// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
 	// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient

+ 35 - 12
src/Output/QRImage.php

@@ -17,9 +17,10 @@ use chillerlan\QRCode\QRCode;
 use chillerlan\Settings\SettingsContainerInterface;
 use chillerlan\Settings\SettingsContainerInterface;
 use Exception;
 use Exception;
 
 
-use function array_values, call_user_func, count, extension_loaded, imagecolorallocate, imagecolortransparent,
-	imagecreatetruecolor, imagedestroy, imagefilledrectangle, imagegif, imagejpeg, imagepng, in_array,
+use function array_values, count, extension_loaded, imagecolorallocate, imagecolortransparent, imagecreatetruecolor,
+	 imagedestroy, imagefilledellipse, imagefilledrectangle, imagegif, imagejpeg, imagepng, imagescale, in_array,
 	is_array, ob_end_clean, ob_get_contents, ob_start, range;
 	is_array, ob_end_clean, ob_get_contents, ob_start, range;
+use const IMG_BICUBIC;
 
 
 /**
 /**
  * Converts the matrix into GD images, raw or base64 output (requires ext-gd)
  * Converts the matrix into GD images, raw or base64 output (requires ext-gd)
@@ -93,6 +94,12 @@ class QRImage extends QROutputAbstract{
 	public function dump(string $file = null){
 	public function dump(string $file = null){
 		$file ??= $this->options->cachefile;
 		$file ??= $this->options->cachefile;
 
 
+		// we're scaling the image up in order to draw crisp round circles, otherwise they appear square-y on small scales
+		if($this->options->drawCircularModules && $this->options->scale <= 20){
+			$this->length  = ($this->length + 2) * 10;
+			$this->scale  *= 10;
+		}
+
 		$this->image = imagecreatetruecolor($this->length, $this->length);
 		$this->image = imagecreatetruecolor($this->length, $this->length);
 
 
 		// avoid: "Indirect modification of overloaded property $imageTransparencyBG has no effect"
 		// avoid: "Indirect modification of overloaded property $imageTransparencyBG has no effect"
@@ -113,6 +120,11 @@ class QRImage extends QROutputAbstract{
 			}
 			}
 		}
 		}
 
 
+		// scale down to the expected size
+		if($this->options->drawCircularModules && $this->options->scale <= 20){
+			$this->image = imagescale($this->image, $this->length/10, $this->length/10, IMG_BICUBIC);
+		}
+
 		if($this->options->returnResource){
 		if($this->options->returnResource){
 			return $this->image;
 			return $this->image;
 		}
 		}
@@ -134,15 +146,26 @@ class QRImage extends QROutputAbstract{
 	 * Creates a single QR pixel with the given settings
 	 * Creates a single QR pixel with the given settings
 	 */
 	 */
 	protected function setPixel(int $x, int $y, int $M_TYPE):void{
 	protected function setPixel(int $x, int $y, int $M_TYPE):void{
-		imagefilledrectangle(
-			$this->image,
-			$x * $this->scale,
-			$y * $this->scale,
-			($x + 1) * $this->scale,
-			($y + 1) * $this->scale,
-			/** @phan-suppress-next-line PhanParamTooFewInternalUnpack */
-			imagecolorallocate($this->image, ...$this->moduleValues[$M_TYPE])
-		);
+		/** @phan-suppress-next-line PhanParamTooFewInternalUnpack */
+		$color = imagecolorallocate($this->image, ...$this->moduleValues[$M_TYPE]);
+
+		$this->options->drawCircularModules && !$this->matrix->checkTypes($x, $y, $this->options->keepAsSquare)
+			? imagefilledellipse(
+				$this->image,
+				($x * $this->scale) + ($this->scale / 2),
+				($y * $this->scale) + ($this->scale / 2),
+				2 * $this->options->circleRadius * $this->scale,
+				2 * $this->options->circleRadius * $this->scale,
+				$color
+			)
+			: imagefilledrectangle(
+				$this->image,
+				$x * $this->scale,
+				$y * $this->scale,
+				($x + 1) * $this->scale,
+				($y + 1) * $this->scale,
+				$color
+			);
 	}
 	}
 
 
 	/**
 	/**
@@ -154,7 +177,7 @@ class QRImage extends QROutputAbstract{
 		ob_start();
 		ob_start();
 
 
 		try{
 		try{
-			call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
+			$this->{$this->outputMode ?? $this->defaultMode}();
 		}
 		}
 		// not going to cover edge cases
 		// not going to cover edge cases
 		// @codeCoverageIgnoreStart
 		// @codeCoverageIgnoreStart

+ 2 - 2
src/Output/QRMarkup.php

@@ -189,8 +189,8 @@ class QRMarkup extends QROutputAbstract{
 			return '';
 			return '';
 		}
 		}
 
 
-		if($this->options->svgDrawCircularModules && !$this->matrix->checkTypes($x, $y, $this->options->svgKeepAsSquare)){
-			$r = $this->options->svgCircleRadius;
+		if($this->options->drawCircularModules && !$this->matrix->checkTypes($x, $y, $this->options->keepAsSquare)){
+			$r = $this->options->circleRadius;
 
 
 			return sprintf(
 			return sprintf(
 				'M%1$s %2$s a%3$s %3$s 0 1 0 %4$s 0 a%3$s,%3$s 0 1 0 -%4$s 0Z',
 				'M%1$s %2$s a%3$s %3$s 0 1 0 %4$s 0 a%3$s,%3$s 0 1 0 -%4$s 0Z',

+ 5 - 3
src/QROptionsTrait.php

@@ -162,18 +162,20 @@ trait QROptionsTrait{
 
 
 	/**
 	/**
 	 * specify whether to draw the modules as filled circles
 	 * specify whether to draw the modules as filled circles
+	 *
+	 * @see https://github.com/chillerlan/php-qrcode/issues/23
 	 */
 	 */
-	protected bool $svgDrawCircularModules = false;
+	protected bool $drawCircularModules = false;
 
 
 	/**
 	/**
 	 * specifies the radius of the modules when $svgDrawCircularModules is set to true
 	 * specifies the radius of the modules when $svgDrawCircularModules is set to true
 	 */
 	 */
-	protected float $svgCircleRadius = 0.45;
+	protected float $circleRadius = 0.45;
 
 
 	/**
 	/**
 	 * specifies which module types to exclude when $svgDrawCircularModules is set to true
 	 * specifies which module types to exclude when $svgDrawCircularModules is set to true
 	 */
 	 */
-	protected array $svgKeepAsSquare = [];
+	protected array $keepAsSquare = [];
 
 
 	/**
 	/**
 	 * string substitute for dark
 	 * string substitute for dark