| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- <?php
- /**
- * Class MaskPatternTester
- *
- * @filesource MaskPatternTester.php
- * @created 22.11.2017
- * @package chillerlan\QRCode\Data
- * @author Smiley <smiley@chillerlan.net>
- * @copyright 2017 Smiley
- * @license MIT
- */
- namespace chillerlan\QRCode\Data;
- /**
- * The sole purpose of this class is to receive a QRMatrix object and run the pattern tests on it.
- *
- * @link http://www.thonky.com/qr-code-tutorial/data-masking
- */
- class MaskPatternTester{
- /**
- * @var \chillerlan\QRCode\Data\QRMatrix
- */
- protected $matrix;
- /**
- * @var int
- */
- protected $moduleCount;
- /**
- * Receives the matrix an sets the module count
- *
- * @see \chillerlan\QRCode\QROptions::$maskPattern
- * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
- * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
- *
- * @param \chillerlan\QRCode\Data\QRMatrix $matrix
- *
- * @return \chillerlan\QRCode\Data\MaskPatternTester
- */
- public function setMatrix(QRMatrix $matrix){
- $this->matrix = $matrix;
- $this->moduleCount = $this->matrix->size();
- return $this;
- }
- /**
- * Returns the penalty for the given mask pattern
- *
- * @see \chillerlan\QRCode\QROptions::$maskPattern
- * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
- * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
- *
- * @return int
- */
- public function testPattern(){
- $penalty = 0;
- for($level = 1; $level <= 4; $level++){
- $penalty += call_user_func([$this, 'testLevel'.$level]);
- }
- return (int)$penalty;
- }
- /**
- * Checks for each group of five or more same-colored modules in a row (or column)
- *
- * @return float
- */
- protected function testLevel1(){
- $penalty = 0;
- foreach($this->matrix->matrix() as $y => $row){
- foreach($row as $x => $val){
- $count = 0;
- for($ry = -1; $ry <= 1; $ry++){
- if($y + $ry < 0 || $this->moduleCount <= $y + $ry){
- continue;
- }
- for($rx = -1; $rx <= 1; $rx++){
- if(($ry === 0 && $rx === 0) || ($x + $rx < 0 || $this->moduleCount <= $x + $rx)){
- continue;
- }
- if($this->matrix->check($x + $rx, $y + $ry) === ($val >> 8 > 0)){
- $count++;
- }
- }
- }
- if($count > 5){
- $penalty += (3 + $count - 5);
- }
- }
- }
- return $penalty;
- }
- /**
- * Checks for each 2x2 area of same-colored modules in the matrix
- *
- * @return float
- */
- protected function testLevel2(){
- $penalty = 0;
- foreach($this->matrix->matrix() as $y => $row){
- if($y > $this->moduleCount - 2){
- break;
- }
- foreach($row as $x => $val){
- if($x > $this->moduleCount - 2){
- break;
- }
- $count = 0;
- if($val >> 8 > 0){
- $count++;
- }
- if($this->matrix->check($y, $x + 1)){
- $count++;
- }
- if($this->matrix->check($y + 1, $x)){
- $count++;
- }
- if($this->matrix->check($y + 1, $x + 1)){
- $count++;
- }
- if($count === 0 || $count === 4){
- $penalty += 3;
- }
- }
- }
- return $penalty;
- }
- /**
- * Checks if there are patterns that look similar to the finder patterns
- *
- * @return float
- */
- protected function testLevel3(){
- $penalty = 0;
- foreach($this->matrix->matrix() as $y => $row){
- foreach($row as $x => $val){
- if($x <= $this->moduleCount - 7){
- if(
- $this->matrix->check($x , $y)
- && !$this->matrix->check($x + 1, $y)
- && $this->matrix->check($x + 2, $y)
- && $this->matrix->check($x + 3, $y)
- && $this->matrix->check($x + 4, $y)
- && !$this->matrix->check($x + 5, $y)
- && $this->matrix->check($x + 6, $y)
- ){
- $penalty += 40;
- }
- }
- if($y <= $this->moduleCount - 7){
- if(
- $this->matrix->check($x, $y)
- && !$this->matrix->check($x, $y + 1)
- && $this->matrix->check($x, $y + 2)
- && $this->matrix->check($x, $y + 3)
- && $this->matrix->check($x, $y + 4)
- && !$this->matrix->check($x, $y + 5)
- && $this->matrix->check($x, $y + 6)
- ){
- $penalty += 40;
- }
- }
- }
- }
- return $penalty;
- }
- /**
- * Checks if more than half of the modules are dark or light, with a larger penalty for a larger difference
- *
- * @return float
- */
- protected function testLevel4() {
- $count = 0;
- foreach($this->matrix->matrix() as $y => $row){
- foreach($row as $x => $val){
- if($val >> 8 > 0){
- $count++;
- }
- }
- }
- return (abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
- }
- }
|