Browse Source

:octocat: QREps: fixes from https://github.com/chillerlan/php-qrcode/discussions/148

smiley 3 years ago
parent
commit
3ed5bbc408
2 changed files with 70 additions and 36 deletions
  1. 26 23
      examples/eps.php
  2. 44 13
      src/Output/QREps.php

+ 26 - 23
examples/eps.php

@@ -14,38 +14,41 @@ use chillerlan\QRCode\Output\QROutputInterface;
 require_once __DIR__.'/../vendor/autoload.php';
 
 $options = new QROptions([
-	'version'      => 7,
-	'outputType'   => QROutputInterface::EPS,
-	'eccLevel'     => EccLevel::L,
-	'scale'        => 5,
-	'addQuietzone' => true,
-#	'cachefile'    => __DIR__.'/test.eps', // save to file
-	'moduleValues' => [
+	'version'          => 7,
+	'outputType'       => QROutputInterface::EPS,
+	'eccLevel'         => EccLevel::L,
+	'scale'            => 5,
+	'addQuietzone'     => true,
+	'drawLightModules' => false,
+	'cachefile'        => __DIR__.'/test.eps', // save to file
+	'moduleValues'     => [
 		// finder
-		QRMatrix::M_FINDER | QRMatrix::IS_DARK     => 0xA71111, // dark (true)
-		QRMatrix::M_FINDER                         => 0xFFBFBF, // light (false)
-		QRMatrix::M_FINDER_DOT | QRMatrix::IS_DARK => 0xA71111, // finder dot, dark (true)
+		QRMatrix::M_FINDER | QRMatrix::IS_DARK     => [0, 63, 255], // dark (true)
+		QRMatrix::M_FINDER                         => [233, 233, 233], // light (false)
+		QRMatrix::M_FINDER_DOT | QRMatrix::IS_DARK => [0, 63, 255], // finder dot, dark (true)
 		// alignment
-		QRMatrix::M_ALIGNMENT | QRMatrix::IS_DARK  => 0xA70364,
-		QRMatrix::M_ALIGNMENT                      => 0xFFC9C9,
+		QRMatrix::M_ALIGNMENT | QRMatrix::IS_DARK  => [255, 0, 255],
+		QRMatrix::M_ALIGNMENT                      => [233, 233, 233],
 		// timing
-		QRMatrix::M_TIMING | QRMatrix::IS_DARK     => 0x98005D,
-		QRMatrix::M_TIMING                         => 0xFFB8E9,
+		QRMatrix::M_TIMING | QRMatrix::IS_DARK     => [255, 0, 0],
+		QRMatrix::M_TIMING                         => [233, 233, 233],
 		// format
-		QRMatrix::M_FORMAT | QRMatrix::IS_DARK     => 0x003804,
-		QRMatrix::M_FORMAT                         => 0x00FB12,
+		QRMatrix::M_FORMAT | QRMatrix::IS_DARK     => [67, 159, 84],
+		QRMatrix::M_FORMAT                         => [233, 233, 233],
 		// version
-		QRMatrix::M_VERSION | QRMatrix::IS_DARK    => 0x650098,
-		QRMatrix::M_VERSION                        => 0xE0B8FF,
+		QRMatrix::M_VERSION | QRMatrix::IS_DARK    => [62, 174, 190],
+		QRMatrix::M_VERSION                        => [233, 233, 233],
 		// data
-		QRMatrix::M_DATA | QRMatrix::IS_DARK       => 0x4A6000,
-		QRMatrix::M_DATA                           => 0xECF9BE,
+		QRMatrix::M_DATA | QRMatrix::IS_DARK       => [0, 0, 0],
+		QRMatrix::M_DATA                           => [233, 233, 233],
 		// darkmodule
-		QRMatrix::M_DARKMODULE | QRMatrix::IS_DARK => 0x080063,
+		QRMatrix::M_DARKMODULE | QRMatrix::IS_DARK => [0, 0, 0],
 		// separator
-		QRMatrix::M_SEPARATOR                      => 0xAFBFBF,
+		QRMatrix::M_SEPARATOR                      => [233, 233, 233],
 		// quietzone
-		QRMatrix::M_QUIETZONE                      => 0xDDDDDD,
+		QRMatrix::M_QUIETZONE                      => [233, 233, 233],
+		// logo (requires a call to QRMatrix::setLogoSpace()), see QRImageWithLogo
+		QRMatrix::M_LOGO                           => [233, 233, 233],
 	],
 ]);
 

+ 44 - 13
src/Output/QREps.php

@@ -10,7 +10,7 @@
 
 namespace chillerlan\QRCode\Output;
 
-use function date, implode, is_int, sprintf;
+use function count, date, implode, is_array, is_numeric, max, min, round, sprintf;
 
 /**
  * Encapsulated Postscript (EPS) output
@@ -18,6 +18,7 @@ use function date, implode, is_int, sprintf;
  * @see https://github.com/t0k4rt/phpqrcode/blob/bb29e6eb77e0a2a85bb0eb62725e0adc11ff5a90/qrvect.php#L52-L137
  * @see https://web.archive.org/web/20170818010030/http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/postscript/pdfs/5002.EPSF_Spec.pdf
  * @see https://web.archive.org/web/20210419003859/https://www.adobe.com/content/dam/acom/en/devnet/actionscript/articles/PLRM.pdf
+ * @see https://github.com/chillerlan/php-qrcode/discussions/148
  */
 class QREps extends QROutputAbstract{
 
@@ -25,18 +26,33 @@ class QREps extends QROutputAbstract{
 	 * @inheritDoc
 	 */
 	protected function moduleValueIsValid($value):bool{
-		return is_int($value) && $value >= 0 && $value <= 0xffffff;
+
+		if(!is_array($value) || count($value) < 3){
+			return false;
+		}
+
+		// check the first 3 values of the array
+		for($i = 0; $i < 3; $i++){
+			if(!is_numeric($value[$i])){
+				return false;
+			}
+		}
+
+		return true;
 	}
 
 	/**
 	 * @inheritDoc
 	 */
 	protected function getModuleValue($value):array{
-		return [
-			round((($value & 0xff0000) >> 16) / 255, 5),
-			round((($value & 0x00ff00) >> 8) / 255, 5),
-			round(($value & 0x0000ff) / 255, 5)
-		];
+		$val = [];
+
+		for($i = 0; $i < 3; $i++){
+			// clamp value and convert from 0-255 to 0-1 RGB range
+			$val[] = round(max(0, min(255, $value[$i])) / 255, 6);
+		}
+
+		return $val;
 	}
 
 	/**
@@ -60,20 +76,17 @@ class QREps extends QROutputAbstract{
 			sprintf('%%%%CreationDate: %1$s', date('c')),
 			'%%DocumentData: Clean7Bit',
 			'%%LanguageLevel: 3',
-			sprintf('%%%%BoundingBox: 0 -%1$s %1$s 0', $this->length),
+			sprintf('%%%%BoundingBox: 0 0 %1$s %1$s', $this->length),
 			'%%EndComments',
 			// function definitions
 			'%%BeginProlog',
 			'/F { rectfill } def',
 			'/S { setrgbcolor } def',
-			'%%EndProlog',
-			// rotate into the proper orientation and scale to fit
-			'-90 rotate',
-			sprintf('%1$s %1$s scale', $this->scale),
+			'%%EndProlog'
 		];
 
 		// create the path elements
-		$paths = $this->collectModules(fn(int $x, int $y):string => sprintf('%s %s 1 1 F', $x, $y));
+		$paths = $this->collectModules(fn(int $x, int $y):string => $this->module($x, $y));
 
 		foreach($paths as $M_TYPE => $path){
 
@@ -97,4 +110,22 @@ class QREps extends QROutputAbstract{
 		return $data;
 	}
 
+	/**
+	 * returns a path segment for a single module
+	 */
+	protected function module(int $x, int $y):string{
+
+		if(!$this->options->drawLightModules && !$this->matrix->check($x, $y)){
+			return '';
+		}
+
+		$outputX = $x * $this->scale;
+		// Actual size - one block = Topmost y pos.
+		$top     = $this->length - $this->scale;
+		// Apparently y-axis is inverted (y0 is at bottom and not top) in EPS so we have to switch the y-axis here
+		$outputY = $top - ($y * $this->scale);
+
+		return sprintf('%d %d %d %d F', $outputX, $outputY, $this->scale, $this->scale);
+	}
+
 }