|
|
@@ -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;
|
|
|
+ }
|
|
|
+
|
|
|
}
|