diff --git a/examples/eps.php b/examples/eps.php index 10b7dfe3b..0eab334e0 100644 --- a/examples/eps.php +++ b/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], ], ]); diff --git a/src/Output/QREps.php b/src/Output/QREps.php index 49d7978b7..c7e7ab8fa 100644 --- a/src/Output/QREps.php +++ b/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); + } + }