Просмотр исходного кода

:shower: moved interleaved data mapping from QRMatrix to ReedSolomonEncoder

smiley 3 лет назад
Родитель
Сommit
fd885fff1c
3 измененных файлов с 69 добавлено и 76 удалено
  1. 64 10
      src/Common/ReedSolomonEncoder.php
  2. 5 4
      src/Data/QRData.php
  3. 0 62
      src/Data/QRMatrix.php

+ 64 - 10
src/Common/ReedSolomonEncoder.php

@@ -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
src/Data/QRData.php

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

+ 0 - 62
src/Data/QRMatrix.php

@@ -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
 	 *