🚿 moved interleaved data mapping from QRMatrix to ReedSolomonEncoder

This commit is contained in:
smiley
2022-05-14 00:30:12 +02:00
parent 27e82de500
commit fd885fff1c
3 changed files with 69 additions and 76 deletions
+64 -10
View File
@@ -10,8 +10,7 @@
namespace chillerlan\QRCode\Common;
use SplFixedArray;
use chillerlan\QRCode\Data\QRMatrix;
use function array_fill, array_merge, count, max;
/**
@@ -21,16 +20,15 @@ use function array_fill, array_merge, count, max;
*/
final class ReedSolomonEncoder{
private SplFixedArray $interleavedData;
private int $interleavedDataIndex;
private array $interleavedData;
private int $interleavedDataIndex;
/**
* ECC interleaving
*
* @return \SplFixedArray<int>
*/
public function interleaveEcBytes(BitBuffer $bitBuffer, Version $version, EccLevel $eccLevel):SplFixedArray{
[$numEccCodewords, [[$l1, $b1], [$l2, $b2]]] = $version->getRSBlocks($eccLevel);
public function interleaveEcBytes(BitBuffer $bitBuffer, QRMatrix $matrix):QRMatrix{
$version = $matrix->version();
[$numEccCodewords, [[$l1, $b1], [$l2, $b2]]] = $version->getRSBlocks($matrix->eccLevel());
$rsBlocks = array_fill(0, $l1, [$numEccCodewords + $b1, $b1]);
@@ -61,14 +59,14 @@ final class ReedSolomonEncoder{
$dataByteOffset += $dataByteCount;
}
$this->interleavedData = new SplFixedArray($version->getTotalCodewords());
$this->interleavedData = array_fill(0, $version->getTotalCodewords(), 0);
$this->interleavedDataIndex = 0;
$numRsBlocks = $l1 + $l2;
$this->interleave($dataBytes, $maxDataBytes, $numRsBlocks);
$this->interleave($ecBytes, $maxEcBytes, $numRsBlocks);
return $this->interleavedData;
return $this->mapData($matrix);
}
/**
@@ -112,4 +110,60 @@ final class ReedSolomonEncoder{
}
}
/**
* Maps the interleaved binary $data on the matrix
*/
private function mapData(QRMatrix $matrix):QRMatrix{
$byteCount = count($this->interleavedData);
$size = $matrix->size();
$y = $size - 1;
$inc = -1;
$byteIndex = 0;
$bitIndex = 7;
for($i = $y; $i > 0; $i -= 2){
if($i === 6){
$i--;
}
while(true){
for($c = 0; $c < 2; $c++){
$x = $i - $c;
if($matrix->get($x, $y) !== QRMatrix::M_NULL){
continue;
}
$v = false;
if($byteIndex < $byteCount){
$v = (($this->interleavedData[$byteIndex] >> $bitIndex) & 1) === 1;
}
$matrix->set($x, $y, $v, QRMatrix::M_DATA);
$bitIndex--;
if($bitIndex === -1){
$byteIndex++;
$bitIndex = 7;
}
}
$y += $inc;
if($y < 0 || $size <= $y){
$y -= $inc;
$inc = -$inc;
break;
}
}
}
return $matrix;
}
}
+5 -4
View File
@@ -94,12 +94,13 @@ final class QRData{
* returns a fresh matrix object with the data written and masked with the given $maskPattern
*/
public function writeMatrix(MaskPattern $maskPattern):QRMatrix{
$data = (new ReedSolomonEncoder)->interleaveEcBytes($this->bitBuffer, $this->version, $this->eccLevel);
return (new QRMatrix($this->version, $this->eccLevel))
$matrix = (new QRMatrix($this->version, $this->eccLevel))
->initFunctionalPatterns()
->initFormatInfo($maskPattern)
->mapData($data)
;
return (new ReedSolomonEncoder)
->interleaveEcBytes($this->bitBuffer, $matrix)
->mask($maskPattern)
;
}
-62
View File
@@ -532,68 +532,6 @@ final class QRMatrix{
return $this;
}
/**
* Maps the binary $data array from QRData::maskECC() on the matrix,
* masking the data using $maskPattern (ISO/IEC 18004:2000 Section 8.8)
*
* @see \chillerlan\QRCode\Data\QRData::maskECC()
*
* @param \SplFixedArray<int> $data
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function mapData(SplFixedArray $data):self{
$byteCount = $data->count();
$y = $this->moduleCount - 1;
$inc = -1;
$byteIndex = 0;
$bitIndex = 7;
for($i = $y; $i > 0; $i -= 2){
if($i === 6){
$i--;
}
while(true){
for($c = 0; $c < 2; $c++){
$x = $i - $c;
if($this->matrix[$y][$x] !== $this::M_NULL){
continue;
}
$v = false;
if($byteIndex < $byteCount){
$v = (($data[$byteIndex] >> $bitIndex) & 1) === 1;
}
$this->matrix[$y][$x] = $this::M_DATA | ($v ? $this::IS_DARK : 0);
$bitIndex--;
if($bitIndex === -1){
$byteIndex++;
$bitIndex = 7;
}
}
$y += $inc;
if($y < 0 || $this->moduleCount <= $y){
$y -= $inc;
$inc = -$inc;
break;
}
}
}
return $this;
}
/**
* Applies the mask pattern
*