getSize(); echo "Expected Data: '{$data}'\n"; echo "Matrix Size: {$size}x{$size}\n\n"; // Get mask pattern $formatBits = ''; $cols = [0, 1, 2, 3, 4, 5, 7, 8, 20, 19, 18, 17, 16, 15, 14]; foreach ($cols as $col) { $formatBits .= $matrix->getModuleAt(8, $col)->isDark() ? '1' : '0'; } $formatTable = [ 0 => '101010000010010', 1 => '101000100100101', 2 => '101111001111100', 3 => '101101101001011', 4 => '100010111111001', 5 => '100000011001110', 6 => '100111110010111', 7 => '100101010100000', ]; $maskPattern = null; foreach ($formatTable as $mask => $bits) { if ($formatBits === $bits) { $maskPattern = $mask; break; } } echo "Detected Mask Pattern: {$maskPattern}\n\n"; // Function to check if position is occupied by function pattern function isOccupied(int $row, int $col, int $size): bool { // Finder patterns + separators if ( ($row <= 8 && $col <= 8) || ($row <= 7 && $col >= $size - 8) || ($row >= $size - 8 && $col <= 7) ) { return true; } // Timing patterns if ($row === 6 || $col === 6) { return true; } // Dark module if ($row === 13 && $col === 8) { return true; } // Format information if ($row === 8 || $col === 8) { return true; } return false; } // Apply mask to get original data function applyMask(int $row, int $col, int $maskPattern): bool { return match ($maskPattern) { 0 => ($row + $col) % 2 === 0, 1 => $row % 2 === 0, 2 => $col % 3 === 0, 3 => ($row + $col) % 3 === 0, 4 => ((int)($row / 2) + (int)($col / 3)) % 2 === 0, 5 => (($row * $col) % 2) + (($row * $col) % 3) === 0, 6 => ((($row * $col) % 2) + (($row * $col) % 3)) % 2 === 0, 7 => ((($row + $col) % 2) + (($row * $col) % 3)) % 2 === 0, default => false }; } // Extract data bits in zig-zag pattern echo "=== Extracting Data Bits ===\n"; $dataBits = ''; $bitCount = 0; for ($col = $size - 1; $col >= 1; $col -= 2) { // Skip timing column if ($col === 6) { $col--; } $upward = ((int)(($size - 1 - $col) / 2) % 2) === 0; for ($i = 0; $i < $size; $i++) { $row = $upward ? ($size - 1 - $i) : $i; for ($c = 0; $c < 2; $c++) { $currentCol = $col - $c; if (isOccupied($row, $currentCol, $size)) { continue; } $module = $matrix->getModuleAt($row, $currentCol); $bit = $module->isDark() ? 1 : 0; // Unmask the bit if (applyMask($row, $currentCol, $maskPattern)) { $bit = $bit === 1 ? 0 : 1; } $dataBits .= $bit; $bitCount++; if ($bitCount <= 32) { echo sprintf("Bit %2d at (%2d,%2d): %d\n", $bitCount, $row, $currentCol, $bit); } } } } echo "\nTotal data bits extracted: " . strlen($dataBits) . "\n\n"; // Parse data echo "=== Parsing Data ===\n"; // Mode indicator (4 bits) $modeIndicator = substr($dataBits, 0, 4); echo "Mode Indicator: {$modeIndicator} (" . bindec($modeIndicator) . ")\n"; $modeNames = [ 1 => 'Numeric', 2 => 'Alphanumeric', 4 => 'Byte', 8 => 'Kanji' ]; $mode = bindec($modeIndicator); echo "Mode: " . ($modeNames[$mode] ?? 'Unknown') . "\n\n"; // Character count (8 bits for byte mode, version 1) $charCountBits = substr($dataBits, 4, 8); $charCount = bindec($charCountBits); echo "Character Count Indicator: {$charCountBits}\n"; echo "Character Count: {$charCount}\n\n"; // Data bytes echo "Data Bytes:\n"; $offset = 12; $decodedData = ''; for ($i = 0; $i < $charCount; $i++) { $byteBits = substr($dataBits, $offset + ($i * 8), 8); $byte = bindec($byteBits); $char = chr($byte); $decodedData .= $char; echo sprintf("Byte %2d: %s = %3d = '%s'\n", $i + 1, $byteBits, $byte, $char); } echo "\n=== Result ===\n"; echo "Expected: '{$data}'\n"; echo "Decoded: '{$decodedData}'\n"; echo ($decodedData === $data ? "✅ MATCH!" : "❌ MISMATCH!") . "\n";