From efb829c4a6078ecee8895732828f3da524b97f6d Mon Sep 17 00:00:00 2001 From: smiley Date: Thu, 13 Jul 2023 11:44:21 +0200 Subject: [PATCH] :octocat: fully support reflectance reversal --- src/Data/QRMatrix.php | 93 +++++++++++++++++++++++-------- src/Output/QROutputInterface.php | 96 +++++++++++++++++--------------- 2 files changed, 119 insertions(+), 70 deletions(-) diff --git a/src/Data/QRMatrix.php b/src/Data/QRMatrix.php index 5e5aab474..68a0b4f88 100755 --- a/src/Data/QRMatrix.php +++ b/src/Data/QRMatrix.php @@ -21,54 +21,77 @@ use function array_fill, array_map, array_reverse, count, floor, intdiv; */ class QRMatrix{ + /* + * special values + */ + /** @var int */ - public const IS_DARK = 0b100000000000; + public const IS_DARK = 0b100000000000; /** @var int */ - public const M_NULL = 0b000000000000; + public const M_NULL = 0b000000000000; /** @var int */ - public const M_DARKMODULE = 0b100000000001; + public const M_LOGO = 0b001000000000; /** @var int */ - public const M_DATA = 0b000000000010; + public const M_LOGO_DARK = 0b101000000000; /** @var int */ - public const M_DATA_DARK = 0b100000000010; + public const M_TEST = 0b011111111111; /** @var int */ - public const M_FINDER = 0b000000000100; + public const M_TEST_DARK = 0b111111111111; + + /* + * light values + */ + /** @var int */ - public const M_FINDER_DARK = 0b100000000100; + public const M_DATA = 0b000000000010; /** @var int */ - public const M_SEPARATOR = 0b000000001000; + public const M_FINDER = 0b000000000100; /** @var int */ - public const M_SEPARATOR_DARK = 0b100000001000; + public const M_SEPARATOR = 0b000000001000; /** @var int */ - public const M_ALIGNMENT = 0b000000010000; + public const M_ALIGNMENT = 0b000000010000; /** @var int */ - public const M_ALIGNMENT_DARK = 0b100000010000; + public const M_TIMING = 0b000000100000; /** @var int */ - public const M_TIMING = 0b000000100000; + public const M_FORMAT = 0b000001000000; /** @var int */ - public const M_TIMING_DARK = 0b100000100000; + public const M_VERSION = 0b000010000000; /** @var int */ - public const M_FORMAT = 0b000001000000; + public const M_QUIETZONE = 0b000100000000; + + /* + * dark values + */ + /** @var int */ - public const M_FORMAT_DARK = 0b100001000000; + public const M_DARKMODULE = 0b100000000001; /** @var int */ - public const M_VERSION = 0b000010000000; + public const M_DATA_DARK = 0b100000000010; /** @var int */ - public const M_VERSION_DARK = 0b100010000000; + public const M_FINDER_DARK = 0b100000000100; /** @var int */ - public const M_QUIETZONE = 0b000100000000; + public const M_ALIGNMENT_DARK = 0b100000010000; /** @var int */ - public const M_QUIETZONE_DARK = 0b100100000000; + public const M_TIMING_DARK = 0b100000100000; /** @var int */ - public const M_LOGO = 0b001000000000; + public const M_FORMAT_DARK = 0b100001000000; /** @var int */ - public const M_LOGO_DARK = 0b101000000000; + public const M_VERSION_DARK = 0b100010000000; /** @var int */ - public const M_FINDER_DOT = 0b110000000000; + public const M_FINDER_DOT = 0b110000000000; + + /* + * values used for reversed reflectance + */ + /** @var int */ - public const M_TEST = 0b011111111111; + public const M_DARKMODULE_LIGHT = 0b000000000001; /** @var int */ - public const M_TEST_DARK = 0b111111111111; + public const M_FINDER_DOT_LIGHT = 0b010000000000; + /** @var int */ + public const M_SEPARATOR_DARK = 0b100000001000; + /** @var int */ + public const M_QUIETZONE_DARK = 0b100100000000; /** * Map of flag => coord @@ -579,6 +602,28 @@ class QRMatrix{ return $this; } + /** + * Inverts the values of the whole matrix + * + * ISO/IEC 18004:2015 Section 6.2 - Reflectance reversal + */ + public function invert():self{ + + foreach($this->matrix as $y => $row){ + foreach($row as $x => $val){ + + // skip null fields + if($val === $this::M_NULL){ + continue; + } + + $this->set($x, $y, ($val & $this::IS_DARK) !== $this::IS_DARK, $val); + } + } + + return $this; + } + /** * Clears a space of $width * $height in order to add a logo or text. * If no $height is given, the space will be assumed a square of $width. diff --git a/src/Output/QROutputInterface.php b/src/Output/QROutputInterface.php index e4a68a28d..c83d3775c 100644 --- a/src/Output/QROutputInterface.php +++ b/src/Output/QROutputInterface.php @@ -65,30 +65,32 @@ interface QROutputInterface{ */ public const DEFAULT_MODULE_VALUES = [ // light - QRMatrix::M_NULL => false, - QRMatrix::M_DATA => false, - QRMatrix::M_FINDER => false, - QRMatrix::M_SEPARATOR => false, - QRMatrix::M_ALIGNMENT => false, - QRMatrix::M_TIMING => false, - QRMatrix::M_FORMAT => false, - QRMatrix::M_VERSION => false, - QRMatrix::M_QUIETZONE => false, - QRMatrix::M_LOGO => false, - QRMatrix::M_TEST => false, + QRMatrix::M_NULL => false, + QRMatrix::M_DARKMODULE_LIGHT => false, + QRMatrix::M_DATA => false, + QRMatrix::M_FINDER => false, + QRMatrix::M_SEPARATOR => false, + QRMatrix::M_ALIGNMENT => false, + QRMatrix::M_TIMING => false, + QRMatrix::M_FORMAT => false, + QRMatrix::M_VERSION => false, + QRMatrix::M_QUIETZONE => false, + QRMatrix::M_LOGO => false, + QRMatrix::M_FINDER_DOT_LIGHT => false, + QRMatrix::M_TEST => false, // dark - QRMatrix::M_DARKMODULE => true, - QRMatrix::M_DATA_DARK => true, - QRMatrix::M_FINDER_DARK => true, - QRMatrix::M_SEPARATOR_DARK => true, - QRMatrix::M_ALIGNMENT_DARK => true, - QRMatrix::M_TIMING_DARK => true, - QRMatrix::M_FORMAT_DARK => true, - QRMatrix::M_VERSION_DARK => true, - QRMatrix::M_QUIETZONE_DARK => true, - QRMatrix::M_LOGO_DARK => true, - QRMatrix::M_FINDER_DOT => true, - QRMatrix::M_TEST_DARK => true, + QRMatrix::M_DARKMODULE => true, + QRMatrix::M_DATA_DARK => true, + QRMatrix::M_FINDER_DARK => true, + QRMatrix::M_SEPARATOR_DARK => true, + QRMatrix::M_ALIGNMENT_DARK => true, + QRMatrix::M_TIMING_DARK => true, + QRMatrix::M_FORMAT_DARK => true, + QRMatrix::M_VERSION_DARK => true, + QRMatrix::M_QUIETZONE_DARK => true, + QRMatrix::M_LOGO_DARK => true, + QRMatrix::M_FINDER_DOT => true, + QRMatrix::M_TEST_DARK => true, ]; /** @@ -98,30 +100,32 @@ interface QROutputInterface{ */ public const LAYERNAMES = [ // light - QRMatrix::M_NULL => 'null', - QRMatrix::M_DATA => 'data', - QRMatrix::M_FINDER => 'finder', - QRMatrix::M_SEPARATOR => 'separator', - QRMatrix::M_ALIGNMENT => 'alignment', - QRMatrix::M_TIMING => 'timing', - QRMatrix::M_FORMAT => 'format', - QRMatrix::M_VERSION => 'version', - QRMatrix::M_QUIETZONE => 'quietzone', - QRMatrix::M_LOGO => 'logo', - QRMatrix::M_TEST => 'test', + QRMatrix::M_NULL => 'null', + QRMatrix::M_DARKMODULE_LIGHT => 'darkmodule-light', + QRMatrix::M_DATA => 'data', + QRMatrix::M_FINDER => 'finder', + QRMatrix::M_SEPARATOR => 'separator', + QRMatrix::M_ALIGNMENT => 'alignment', + QRMatrix::M_TIMING => 'timing', + QRMatrix::M_FORMAT => 'format', + QRMatrix::M_VERSION => 'version', + QRMatrix::M_QUIETZONE => 'quietzone', + QRMatrix::M_LOGO => 'logo', + QRMatrix::M_FINDER_DOT_LIGHT => 'finder-dot-light', + QRMatrix::M_TEST => 'test', // dark - QRMatrix::M_DARKMODULE => 'darkmodule', - QRMatrix::M_DATA_DARK => 'data-dark', - QRMatrix::M_FINDER_DARK => 'finder-dark', - QRMatrix::M_SEPARATOR_DARK => 'separator-dark', - QRMatrix::M_ALIGNMENT_DARK => 'alignment-dark', - QRMatrix::M_TIMING_DARK => 'timing-dark', - QRMatrix::M_FORMAT_DARK => 'format-dark', - QRMatrix::M_VERSION_DARK => 'version-dark', - QRMatrix::M_QUIETZONE_DARK => 'quietzone-dark', - QRMatrix::M_LOGO_DARK => 'logo-dark', - QRMatrix::M_FINDER_DOT => 'finder-dot', - QRMatrix::M_TEST_DARK => 'test-dark', + QRMatrix::M_DARKMODULE => 'darkmodule', + QRMatrix::M_DATA_DARK => 'data-dark', + QRMatrix::M_FINDER_DARK => 'finder-dark', + QRMatrix::M_SEPARATOR_DARK => 'separator-dark', + QRMatrix::M_ALIGNMENT_DARK => 'alignment-dark', + QRMatrix::M_TIMING_DARK => 'timing-dark', + QRMatrix::M_FORMAT_DARK => 'format-dark', + QRMatrix::M_VERSION_DARK => 'version-dark', + QRMatrix::M_QUIETZONE_DARK => 'quietzone-dark', + QRMatrix::M_LOGO_DARK => 'logo-dark', + QRMatrix::M_FINDER_DOT => 'finder-dot', + QRMatrix::M_TEST_DARK => 'test-dark', ]; /**