diff --git a/README.md b/README.md index b97c5e300..085291fd1 100644 --- a/README.md +++ b/README.md @@ -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)) - QR Code reader (via GD and ImageMagick) diff --git a/docs/Usage/Overview.md b/docs/Usage/Overview.md index fbbc6467e..e80a81e67 100644 --- a/docs/Usage/Overview.md +++ b/docs/Usage/Overview.md @@ -23,6 +23,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)) - QR Code reader (via GD and ImageMagick) diff --git a/src/Output/QRNetpbmBitmapAbstract.php b/src/Output/QRNetpbmBitmapAbstract.php new file mode 100644 index 000000000..7ce4ab818 --- /dev/null +++ b/src/Output/QRNetpbmBitmapAbstract.php @@ -0,0 +1,62 @@ +matrix->getBooleanMatrix() as $row) { + $line = ''; + foreach ($row as $isDark) { + $line .= str_repeat( $isDark ? '1' : '0', $this->scale ); + } + $line .= "\n"; + $body .= str_repeat( $line, $this->scale ); + } + return trim($body,"\n"); + } + + public function dump( string|null $file = null ): mixed { + $qrString = $this->getHeader()."\n" + .$this->length.' '.$this->length."\n".$this->getBody(); + + $this->saveToFile( $qrString, $file ); + + if ( $this->options->outputBase64 ) { + $qrString = $this->toBase64DataURI( $qrString ); + } + + return $qrString; + } +} diff --git a/src/Output/QRNetpbmBitmapAscii.php b/src/Output/QRNetpbmBitmapAscii.php new file mode 100644 index 000000000..ad4217735 --- /dev/null +++ b/src/Output/QRNetpbmBitmapAscii.php @@ -0,0 +1,20 @@ +asciiBinToBinary( $row ); + } + return $body; + } + + private function asciiBinToBinary( string $asciiBin ): string { + $binaryString = ''; + foreach(str_split( $asciiBin, 8 ) as $currentChunk) { + $currentChunk = str_pad( $currentChunk, 8, '0' ); + $binaryString .= pack( 'C', bindec( $currentChunk ) ); + } + return $binaryString; + } +} diff --git a/tests/Output/QRNetpbmBitmapAsciiTest.php b/tests/Output/QRNetpbmBitmapAsciiTest.php new file mode 100644 index 000000000..8fedfedc2 --- /dev/null +++ b/tests/Output/QRNetpbmBitmapAsciiTest.php @@ -0,0 +1,58 @@ + + */ + public static function moduleValueProvider():array{ + return [ + 'invalid: wrong type: array' => [[], false], + 'invalid: wrong type: string' => ['abc', false], + 'valid: true' => [true, true], + 'valid: false' => [false, true], + ]; + } + + #[Test] + public function setModuleValues():void{ + $this->options->moduleValues = [ + // data + QRMatrix::M_DATA_DARK => true, + QRMatrix::M_DATA => false, + ]; + + $this->outputInterface = $this->getOutputInterface($this->options, $this->matrix); + $data = $this->outputInterface->dump(); + + $this::assertStringContainsString('1', $data); + $this::assertStringContainsString('0', $data); + } +} diff --git a/tests/Output/QRNetpbmBitmapBinaryTest.php b/tests/Output/QRNetpbmBitmapBinaryTest.php new file mode 100644 index 000000000..8a74cb0a7 --- /dev/null +++ b/tests/Output/QRNetpbmBitmapBinaryTest.php @@ -0,0 +1,57 @@ + + */ + public static function moduleValueProvider():array{ + return [ + 'invalid: wrong type: array' => [[], false], + 'invalid: wrong type: string' => ['abc', false], + 'valid: true' => [true, true], + 'valid: false' => [false, true], + ]; + } + + #[Test] + public function setModuleValues():void{ + $this->options->moduleValues = [ + // data + QRMatrix::M_DATA_DARK => true, + QRMatrix::M_DATA => false, + ]; + + $this->outputInterface = $this->getOutputInterface($this->options, $this->matrix); + $data = $this->outputInterface->dump(); + + $this::assertStringContainsString("\0", $data); + } +}