120 lines
3.8 KiB
PHP
120 lines
3.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Domain\QrCode\Pattern;
|
|
|
|
/**
|
|
* Implementiert das Version Information Pattern für QR-Codes ab Version 7
|
|
*/
|
|
class VersionInfoPattern implements PatternInterface
|
|
{
|
|
/**
|
|
* Lookup-Tabelle für die Version-Information (BCH-kodiert)
|
|
* Diese 18-Bit-Werte enthalten die Versionsinformation mit Fehlerkorrektur
|
|
*/
|
|
private const VERSION_INFO = [
|
|
7 => 0b000111110010010100,
|
|
8 => 0b001000010110111100,
|
|
9 => 0b001001101010011001,
|
|
10 => 0b001010010011010011,
|
|
11 => 0b001011101111110110,
|
|
12 => 0b001100011101100010,
|
|
13 => 0b001101100001000111,
|
|
14 => 0b001110011000001101,
|
|
15 => 0b001111100100101000,
|
|
16 => 0b010000101101111000,
|
|
17 => 0b010001010001011101,
|
|
18 => 0b010010101000010111,
|
|
19 => 0b010011010100110010,
|
|
20 => 0b010100100110100110,
|
|
21 => 0b010101011010000011,
|
|
22 => 0b010110100011001001,
|
|
23 => 0b010111011111101100,
|
|
24 => 0b011000111011000100,
|
|
25 => 0b011001000111100001,
|
|
26 => 0b011010111110101011,
|
|
27 => 0b011011000010001110,
|
|
28 => 0b011100110000011010,
|
|
29 => 0b011101001100111111,
|
|
30 => 0b011110110101110101,
|
|
31 => 0b011111001001010000,
|
|
32 => 0b100000100111010101,
|
|
33 => 0b100001011011110000,
|
|
34 => 0b100010100010111010,
|
|
35 => 0b100011011110011111,
|
|
36 => 0b100100101100001011,
|
|
37 => 0b100101010000101110,
|
|
38 => 0b100110101001100100,
|
|
39 => 0b100111010101000001,
|
|
40 => 0b101000110001101001,
|
|
];
|
|
|
|
private int $version;
|
|
|
|
public function __construct(int $version)
|
|
{
|
|
$this->version = $version;
|
|
}
|
|
|
|
public function apply(array &$matrix, int $size): void
|
|
{
|
|
// Version Information Pattern nur für QR-Codes ab Version 7
|
|
if ($this->version < 7) {
|
|
return;
|
|
}
|
|
|
|
$versionInfo = self::VERSION_INFO[$this->version] ?? 0;
|
|
|
|
// Versionsinformation an zwei Positionen einfügen
|
|
$this->placeVersionInfo($matrix, $versionInfo); // Platziere oben rechts
|
|
$this->placeVersionInfoTransposed($matrix, $versionInfo); // Platziere unten links
|
|
}
|
|
|
|
/**
|
|
* Platziert die Versionsinformation unterhalb des Finder Patterns oben rechts
|
|
*/
|
|
private function placeVersionInfo(array &$matrix, int $versionInfo): void
|
|
{
|
|
// Position: unterhalb des rechten oberen Finder Patterns
|
|
// 3 Zeilen x 6 Spalten = 18 Bits
|
|
$row = 0;
|
|
$col = $this->version * 4 + 6; // Rechts oben, die exakte Position hängt von der Version ab
|
|
|
|
// 18 Bits des Versionsinformationsblocks setzen
|
|
for ($i = 0; $i < 18; $i++) {
|
|
// Bit von rechts nach links extrahieren (LSB zuerst)
|
|
$bit = ($versionInfo >> $i) & 1;
|
|
|
|
// Berechne Position: 6 Bits pro Zeile, 3 Zeilen
|
|
$r = $row + ($i / 3);
|
|
$c = $col - ($i % 3);
|
|
|
|
$matrix[(int)$r][(int)$c] = $bit === 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Platziert die Versionsinformation rechts vom Finder Pattern unten links
|
|
*/
|
|
private function placeVersionInfoTransposed(array &$matrix, int $versionInfo): void
|
|
{
|
|
// Position: rechts vom linken unteren Finder Pattern
|
|
// 6 Zeilen x 3 Spalten = 18 Bits
|
|
$row = $this->version * 4 + 6; // Unten links, die exakte Position hängt von der Version ab
|
|
$col = 0;
|
|
|
|
// 18 Bits des Versionsinformationsblocks setzen
|
|
for ($i = 0; $i < 18; $i++) {
|
|
// Bit von rechts nach links extrahieren (LSB zuerst)
|
|
$bit = ($versionInfo >> $i) & 1;
|
|
|
|
// Berechne Position: 3 Bits pro Zeile, 6 Zeilen (transponiert)
|
|
$r = $row - ($i % 3);
|
|
$c = $col + ($i / 3);
|
|
|
|
$matrix[(int)$r][(int)$c] = $bit === 1;
|
|
}
|
|
}
|
|
}
|