Skip to content

Added a new hint BINARY_MODE to allow working with binary QRCodes. #158

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions lib/Qrcode/Decoder/DecodedBitStreamParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,24 +309,27 @@ private static function decodeByteSegment(
$readBytes[$i] = $bits->readBits(8); //(byte)
}
$text = implode(array_map('chr', $readBytes));
$encoding = '';
if ($currentCharacterSetECI == null) {
// The spec isn't clear on this mode; see
// section 6.4.5: t does not say which encoding to assuming
// upon decoding. I have seen ISO-8859-1 used as well as
// Shift_JIS -- without anything like an ECI designator to
// give a hint.
if ($hints !== null && array_key_exists('BINARY_MODE', $hints) && $hints['BINARY_MODE']) {
$result .= $text;
} else {
$encoding = '';
if ($currentCharacterSetECI == null) {
// The spec isn't clear on this mode; see
// section 6.4.5: t does not say which encoding to assuming
// upon decoding. I have seen ISO-8859-1 used as well as
// Shift_JIS -- without anything like an ECI designator to
// give a hint.

try {
$encoding = mb_detect_encoding($text, $hints);
} catch (ValueError $e) {
$encoding = mb_detect_encoding($text, mb_detect_order(), false);
}
} else {
$encoding = $currentCharacterSetECI->name();
}
$result .= mb_convert_encoding($text, $encoding); //(new String(readBytes, encoding));
// $result .= $text; //(new String(readBytes, encoding));
try {
$encoding = mb_detect_encoding($text, $hints);
} catch (ValueError $e) {
$encoding = mb_detect_encoding($text, mb_detect_order(), false);
}
} else {
$encoding = $currentCharacterSetECI->name();
}
$result .= mb_convert_encoding($text, $encoding); //(new String(readBytes, encoding));
}

$byteSegments = array_merge($byteSegments, $readBytes);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Qrcode/Decoder/Decoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public function decodeBits(\Zxing\Common\BitMatrix $bits, $hints = null): string
}
}

private function decodeParser(\Zxing\Qrcode\Decoder\BitMatrixParser $parser, array $hints = null): DecoderResult
private function decodeParser(\Zxing\Qrcode\Decoder\BitMatrixParser $parser, ?array $hints = null): DecoderResult
{
$version = $parser->readVersion();
$ecLevel = $parser->readFormatInformation()->getErrorCorrectionLevel();
Expand Down
2 changes: 1 addition & 1 deletion lib/Qrcode/Detector/Detector.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function __construct(private BitMatrix $image)
* @throws NotFoundException if QR Code cannot be found
* @throws FormatException if a QR Code cannot be decoded
*/
final public function detect(array $hints = null): DetectorResult
final public function detect(?array $hints = null): DetectorResult
{/*Map<DecodeHintType,?>*/

$resultPointCallback = ($hints !== null && array_key_exists('NEED_RESULT_POINT_CALLBACK', $hints)) ?
Expand Down
30 changes: 30 additions & 0 deletions tests/QrReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,36 @@ public function testText3()
$this->assertSame("https://www.gosuslugi.ru/covid-cert/verify/9770000014233333?lang=ru&ck=733a9d218d312fe134f1c2cc06e1a800", $qrcode->text());
}

/**
* The following test is meant to check if it works with QRCodes containing raw binary data.
* The test qrcode image was generated with `qrencode -8 -r 'binary-test.bin' -o 'test-binary-test.png'`.
*
* @return void
*/
public function testBinary() {
$image = __DIR__ . "/qrcodes/binary-test.png";
$expected = hex2bin(
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'.
'202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f'.
'404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f'.
'606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f'.
'808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f'.
'a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf'.
'c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf'.
'e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'
);

$qrcode = new QrReader($image);
$qrcode->decode([
'BINARY_MODE' => true
]);
$this->assertSame(null, $qrcode->getError());
$result = $qrcode->getResult();
$this->assertInstanceOf(Result::class, $result);
$text = $result->getText();
$this->assertEquals($expected, $text);
}

// TODO: fix this test
// public function testText4()
// {
Expand Down
Binary file added tests/qrcodes/binary-test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.