source-class-Com.Tecnick.Barcode.Type.Square.QrCode.Mask

It appears that you are using AdBlocking software. The cost of running this website is covered by advertisements. If you like it please feel free to a small amount of money to secure the future of this website.
Overview

Classes

Exceptions

  1: <?php
  2: /**
  3:  * Mask.php
  4:  *
  5:  * @since       2015-02-21
  6:  * @category    Library
  7:  * @package     Barcode
  8:  * @author      Nicola Asuni <info@tecnick.com>
  9:  * @copyright   2010-2016 Nicola Asuni - Tecnick.com LTD
 10:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 11:  * @link        https://github.com/tecnickcom/tc-lib-barcode
 12:  *
 13:  * This file is part of tc-lib-barcode software library.
 14:  */
 15: 
 16: namespace Com\Tecnick\Barcode\Type\Square\QrCode;
 17: 
 18: use \Com\Tecnick\Barcode\Exception as BarcodeException;
 19: use \Com\Tecnick\Barcode\Type\Square\QrCode\Data;
 20: use \Com\Tecnick\Barcode\Type\Square\QrCode\Spec;
 21: 
 22: /**
 23:  * Com\Tecnick\Barcode\Type\Square\QrCode\Mask
 24:  *
 25:  * @since       2015-02-21
 26:  * @category    Library
 27:  * @package     Barcode
 28:  * @author      Nicola Asuni <info@tecnick.com>
 29:  * @copyright   2010-2016 Nicola Asuni - Tecnick.com LTD
 30:  * @license     http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
 31:  * @link        https://github.com/tecnickcom/tc-lib-barcode
 32:  */
 33: abstract class Mask extends \Com\Tecnick\Barcode\Type\Square\QrCode\MaskNum
 34: {
 35:     /**
 36:      * If false, checks all masks available,
 37:      * otherwise the value indicates the number of masks to be checked, mask id are random
 38:      *
 39:      * @var int
 40:      */
 41:     protected $qr_find_from_random = false;
 42: 
 43:     /**
 44:      * If true, estimates best mask (spec. default, but extremally slow;
 45:      * set to false to significant performance boost but (propably) worst quality code
 46:      *
 47:      * @var bool
 48:      */
 49:     protected $qr_find_best_mask = true;
 50: 
 51:     /**
 52:      * Default mask used when $this->qr_find_best_mask === false
 53:      *
 54:      * @var int
 55:      */
 56:     protected $qr_default_mask = 2;
 57: 
 58:     /**
 59:      * Run length
 60:      *
 61:      * @var array
 62:      */
 63:     protected $runLength = array();
 64: 
 65:     /**
 66:      * QR code version.
 67:      * The Size of QRcode is defined as version. Version is an integer value from 1 to 40.
 68:      * Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases.
 69:      * So version 40 is 177*177 matrix.
 70:      *
 71:      * @var int
 72:      */
 73:     public $version = 0;
 74: 
 75:     /**
 76:      * Error correction level
 77:      *
 78:      * @var int
 79:      */
 80:     protected $level = 0;
 81: 
 82:     /**
 83:      * Spec class object
 84:      *
 85:      * @var \Com\Tecnick\Barcode\Type\Square\QrCode\Spec
 86:      */
 87:     protected $spc;
 88: 
 89:     /**
 90:      * Initialize
 91:      *
 92:      * @param int  $version       Code version
 93:      * @param int  $level         Error Correction Level
 94:      * @param bool $random_mask   If false, checks all masks available,
 95:      *                            otherwise the value indicates the number of masks to be checked, mask id are random
 96:      * @param bool $best_mask     If true, estimates best mask (slow)
 97:      * @param int  $default_mask  Default mask used when $fbm is false
 98:      */
 99:     public function __construct($version, $level, $random_mask = false, $best_mask = true, $default_mask = 2)
100:     {
101:         $this->version = $version;
102:         $this->level = $level;
103:         $this->qr_find_from_random = (bool)$random_mask;
104:         $this->qr_find_best_mask = (bool)$best_mask;
105:         $this->qr_default_mask = intval($default_mask);
106:         $this->spc = new Spec;
107:     }
108: 
109:     /**
110:      * Get the best mask
111:      *
112:      * @param int   $width Width
113:      * @param array $frame Frame
114:      * @param int   $level Error Correction lLevel
115:      *
116:      * @return array best mask
117:      */
118:     protected function mask($width, $frame, $level)
119:     {
120:         $minDemerit = PHP_INT_MAX;
121:         $bestMaskNum = 0;
122:         $bestMask = array();
123:         $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7);
124:         if ($this->qr_find_from_random !== false) {
125:             $howManuOut = (8 - ($this->qr_find_from_random % 9));
126:             for ($idx = 0; $idx <  $howManuOut; ++$idx) {
127:                 $remPos = rand(0, (count($checked_masks) - 1));
128:                 unset($checked_masks[$remPos]);
129:                 $checked_masks = array_values($checked_masks);
130:             }
131:         }
132:         $bestMask = $frame;
133:         foreach ($checked_masks as $idx) {
134:             $mask = array_fill(0, $width, str_repeat("\0", $width));
135:             $demerit = 0;
136:             $blacks = 0;
137:             $blacks  = $this->makeMaskNo($idx, $width, $frame, $mask);
138:             $blacks += $this->writeFormatInformation($width, $mask, $idx, $level);
139:             $blacks  = (int)(100 * $blacks / ($width * $width));
140:             $demerit = (int)((int)(abs($blacks - 50) / 5) * Data::N4);
141:             $demerit += $this->evaluateSymbol($width, $mask);
142:             if ($demerit < $minDemerit) {
143:                 $minDemerit = $demerit;
144:                 $bestMask = $mask;
145:                 $bestMaskNum = $idx;
146:             }
147:         }
148:         return $bestMask;
149:     }
150: 
151:     /**
152:      * Make a mask
153:      *
154:      * @param int   $width  Mask width
155:      * @param array $frame  Frame
156:      * @param int   $maskNo Mask number
157:      * @param int   $level  Error Correction level
158:      *
159:      * @return array mask
160:      */
161:     protected function makeMask($width, $frame, $maskNo, $level)
162:     {
163:         $this->makeMaskNo($maskNo, $width, $frame, $mask);
164:         $this->writeFormatInformation($width, $mask, $maskNo, $level);
165:         return $mask;
166:     }
167: 
168:     /**
169:      * Write Format Information on the frame and returns the number of black bits
170:      *
171:      * @param int   $width  Mask width
172:      * @param array $frame  Frame
173:      * @param int   $maskNo Mask number
174:      * @param int   $level  Error Correction level
175:      *
176:      * @return int blacks
177:      */
178:     protected function writeFormatInformation($width, &$frame, $maskNo, $level)
179:     {
180:         $blacks = 0;
181:         $spec = new Spec;
182:         $format =  $spec->getFormatInfo($maskNo, $level);
183:         for ($idx = 0; $idx < 8; ++$idx) {
184:             if ($format & 1) {
185:                 $blacks += 2;
186:                 $val = 0x85;
187:             } else {
188:                 $val = 0x84;
189:             }
190:             $frame[8][($width - 1 - $idx)] = chr($val);
191:             if ($idx < 6) {
192:                 $frame[$idx][8] = chr($val);
193:             } else {
194:                 $frame[($idx + 1)][8] = chr($val);
195:             }
196:             $format = $format >> 1;
197:         }
198:         for ($idx = 0; $idx < 7; ++$idx) {
199:             if ($format & 1) {
200:                 $blacks += 2;
201:                 $val = 0x85;
202:             } else {
203:                 $val = 0x84;
204:             }
205:             $frame[($width - 7 + $idx)][8] = chr($val);
206:             if ($idx == 0) {
207:                 $frame[8][7] = chr($val);
208:             } else {
209:                 $frame[8][(6 - $idx)] = chr($val);
210:             }
211:             $format = $format >> 1;
212:         }
213:         return $blacks;
214:     }
215: 
216:     /**
217:      * Evaluate Symbol
218:      *
219:      * @param int   $width Width
220:      * @param array $frame Frame
221:      *
222:      * @return int demerit
223:      */
224:     protected function evaluateSymbol($width, $frame)
225:     {
226:         for ($ypos = 0; $ypos < $width; ++$ypos) {
227:             $frameY = $frame[$ypos];
228:             if ($ypos > 0) {
229:                 $frameYM = $frame[($ypos - 1)];
230:             } else {
231:                 $frameYM = $frameY;
232:             }
233:             $demerit = $this->evaluateSymbolB($ypos, $width, $frameY, $frameYM);
234:         }
235:         for ($xpos = 0; $xpos < $width; ++$xpos) {
236:             $head = 0;
237:             $this->runLength[0] = 1;
238:             for ($ypos = 0; $ypos < $width; ++$ypos) {
239:                 if (($ypos == 0) && (ord($frame[$ypos][$xpos]) & 1)) {
240:                     $this->runLength[0] = -1;
241:                     $head = 1;
242:                     $this->runLength[$head] = 1;
243:                 } elseif ($ypos > 0) {
244:                     if ((ord($frame[$ypos][$xpos]) ^ ord($frame[($ypos - 1)][$xpos])) & 1) {
245:                         $head++;
246:                         $this->runLength[$head] = 1;
247:                     } else {
248:                         $this->runLength[$head]++;
249:                     }
250:                 }
251:             }
252:             $demerit += $this->calcN1N3($head + 1);
253:         }
254:         return $demerit;
255:     }
256: 
257:     /**
258:      * Evaluate Symbol
259:      *
260:      * @param int   $ypos   Y position
261:      * @param int   $width  Width
262:      * @param array $frameY
263:      * @param array $frameYM
264:      *
265:      * @return int demerit
266:      */
267:     protected function evaluateSymbolB($ypos, $width, $frameY, $frameYM)
268:     {
269:         $head = 0;
270:         $demerit = 0;
271:         $this->runLength[0] = 1;
272:         for ($xpos = 0; $xpos < $width; ++$xpos) {
273:             if (($xpos > 0) && ($ypos > 0)) {
274:                 $b22 = ord($frameY[$xpos])
275:                     & ord($frameY[($xpos - 1)])
276:                     & ord($frameYM[$xpos])
277:                     & ord($frameYM[($xpos - 1)]);
278:                 $w22 = ord($frameY[$xpos])
279:                     | ord($frameY[($xpos - 1)])
280:                     | ord($frameYM[$xpos])
281:                     | ord($frameYM[($xpos - 1)]);
282:                 if (($b22 | ($w22 ^ 1)) & 1) {
283:                     $demerit += Data::N2;
284:                 }
285:             }
286:             if (($xpos == 0) && (ord($frameY[$xpos]) & 1)) {
287:                 $this->runLength[0] = -1;
288:                 $head = 1;
289:                 $this->runLength[$head] = 1;
290:             } elseif ($xpos > 0) {
291:                 if ((ord($frameY[$xpos]) ^ ord($frameY[($xpos - 1)])) & 1) {
292:                     $head++;
293:                     $this->runLength[$head] = 1;
294:                 } else {
295:                     ++$this->runLength[$head];
296:                 }
297:             }
298:         }
299:         return ($demerit + $this->calcN1N3($head + 1));
300:     }
301: 
302:     /**
303:      * Calc N1 N3
304:      *
305:      * @param int $length
306:      *
307:      * @return int demerit
308:      */
309:     protected function calcN1N3($length)
310:     {
311:         $demerit = 0;
312:         for ($idx = 0; $idx < $length; ++$idx) {
313:             if ($this->runLength[$idx] >= 5) {
314:                 $demerit += (Data::N1 + ($this->runLength[$idx] - 5));
315:             }
316:             if (($idx & 1) && ($idx >= 3) && ($idx < ($length - 2)) && ($this->runLength[$idx] % 3 == 0)) {
317:                 $demerit += $this->calcN1N3delta($length, $idx);
318:             }
319:         }
320:         return $demerit;
321:     }
322: 
323:     /**
324:      * Calc N1 N3 delta
325:      *
326:      * @param int $length
327:      * @param int $idx
328:      *
329:      * @return int demerit delta
330:      */
331:     protected function calcN1N3delta($length, $idx)
332:     {
333:         $fact = (int)($this->runLength[$idx] / 3);
334:         if (($this->runLength[($idx - 2)] == $fact)
335:             && ($this->runLength[($idx - 1)] == $fact)
336:             && ($this->runLength[($idx + 1)] == $fact)
337:             && ($this->runLength[($idx + 2)] == $fact)) {
338:             if (($this->runLength[($idx - 3)] < 0) || ($this->runLength[($idx - 3)] >= (4 * $fact))) {
339:                 return Data::N3;
340:             } elseif ((($idx + 3) >= $length) || ($this->runLength[($idx + 3)] >= (4 * $fact))) {
341:                 return Data::N3;
342:             }
343:         }
344:         return 0;
345:     }
346: }
347: 
 

© 2004-2017 – Nicola Asuni - Tecnick.com - All rights reserved.
about - disclaimer - privacy