Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ It also features a QR Code reader based on a [PHP port](https://github.com/khana
- String types: JSON, plain text, etc.
- Encapsulated Postscript (EPS)
- PDF via [FPDF](https://github.com/setasign/fpdf)
- Portable Bitmap ([PBM](https://en.wikipedia.org/wiki/Netpbm))
Comment thread
wgevaert marked this conversation as resolved.
- QR Code reader (via GD and ImageMagick)


Expand Down
50 changes: 50 additions & 0 deletions src/Output/QRPbm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* Class QRPbm
*
* @created 11.12.2025
* @author wgevaert
* @copyright 2025 wgevaert
* @license MIT
*/
declare(strict_types=1);

namespace chillerlan\QRCode\Output;

use chillerlan\QRCode\Output\QROutputAbstract;

class QRPbm extends QROutputAbstract {

private const LIGHT_DARK = [ '0', '1' ];
Comment thread
wgevaert marked this conversation as resolved.
Outdated

protected function prepareModuleValue( mixed $value ): mixed {
return $value;
Comment thread
wgevaert marked this conversation as resolved.
Outdated
}

protected function getDefaultModuleValue( bool $isDark ): mixed {
return $isDark ? self::LIGHT_DARK[1] : self::LIGHT_DARK[0];
Comment thread
wgevaert marked this conversation as resolved.
Outdated
}

public static function moduleValueIsValid( mixed $value): bool {
return is_string( $value ) && in_array( $value, self::LIGHT_DARK, true );
Comment thread
wgevaert marked this conversation as resolved.
Outdated
}

public function dump( string|null $file = null ): mixed {
$size = $this->matrix->getSize();
Comment thread
wgevaert marked this conversation as resolved.
Outdated
$qrString = "P1\n"
.$size.' '.$size."\n";
Comment thread
wgevaert marked this conversation as resolved.
Outdated
foreach($this->matrix->getBooleanMatrix() as $row) {
foreach ($row as $isDark) {
$qrString .= $this->getDefaultModuleValue( $isDark );
Comment thread
wgevaert marked this conversation as resolved.
Outdated
}
$qrString .= "\n";
}
if ( is_string($file) ) {
$writeResult = file_put_contents($file,$qrString);
if ( $writeResult === false ) {
throw new QRCodeOutputException('Cannot write data to cache file: '.$file);
}
}
Comment thread
wgevaert marked this conversation as resolved.
Outdated
return $qrString;
}
}
60 changes: 60 additions & 0 deletions tests/Output/QRPbmTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/**
* Class QRPbmTest
*
* @created 11.12.2025
* @author wgevaert
* @copyright 2025 wgevaert
* @license MIT
*/
declare(strict_types=1);

namespace chillerlan\QRCodeTest\Output;

use chillerlan\QRCode\QROptions;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Output\{QROutputInterface, QRPbm};
use chillerlan\Settings\SettingsContainerInterface;
use PHPUnit\Framework\Attributes\Test;

/**
* Tests the QRPbm output class
*/
final class QRPbmTest extends QROutputTestAbstract{

protected function getOutputInterface(
SettingsContainerInterface|QROptions $options,
QRMatrix $matrix,
):QROutputInterface{
return new QRPbm($options, $matrix);
}

/**
* @phpstan-return array<string, array{0: mixed, 1: bool}>
*/
public static function moduleValueProvider():array{
return [
'invalid: wrong type' => [[], false],
'invalid: Not 0 or 1' => ['abc', false],
'invalid: empty string' => ['', false],
'invalid: space string' => [' ', false],
'valid: zero' => ['0', true],
];
}

#[Test]
public function setModuleValues():void{

$this->options->moduleValues = [
// data
QRMatrix::M_DATA_DARK => '1',
QRMatrix::M_DATA => '0',
];

$this->outputInterface = $this->getOutputInterface($this->options, $this->matrix);
$data = $this->outputInterface->dump();

$this->assertStringContainsString('1', $data);
$this->assertStringContainsString('0', $data);
Comment thread
wgevaert marked this conversation as resolved.
Outdated
}
}