[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 //============================================================+ 3 // File name : datamatrix.php 4 // Version : 1.0.001 5 // Begin : 2010-06-07 6 // Last Update : 2011-09-14 7 // Author : Nicola Asuni - Tecnick.com LTD - Manor Coach House, Church Hill, Aldershot, Hants, GU12 4RQ, UK - www.tecnick.com - [email protected] 8 // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) 9 // ------------------------------------------------------------------- 10 // Copyright (C) 2010-2012 Nicola Asuni - Tecnick.com LTD 11 // 12 // This file is part of TCPDF software library. 13 // 14 // TCPDF is free software: you can redistribute it and/or modify it 15 // under the terms of the GNU Lesser General Public License as 16 // published by the Free Software Foundation, either version 3 of the 17 // License, or (at your option) any later version. 18 // 19 // TCPDF is distributed in the hope that it will be useful, but 20 // WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 22 // See the GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with TCPDF. If not, see <http://www.gnu.org/licenses/>. 26 // 27 // See LICENSE.TXT file for more information. 28 // ------------------------------------------------------------------- 29 // 30 // DESCRIPTION : 31 // 32 // Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. 33 // DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. 34 //============================================================+ 35 36 /** 37 * @file 38 * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. 39 * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. 40 * 41 * @package com.tecnick.tcpdf 42 * @author Nicola Asuni 43 * @version 1.0.001 44 */ 45 46 // custom definitions 47 if (!defined('DATAMATRIXDEFS')) { 48 49 /** 50 * Indicate that definitions for this class are set 51 */ 52 define('DATAMATRIXDEFS', true); 53 54 // ----------------------------------------------------- 55 56 } // end of custom definitions 57 58 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# 59 60 61 /** 62 * ASCII encoding: ASCII character 0 to 127 (1 byte per CW) 63 */ 64 define('ENC_ASCII', 0); 65 66 /** 67 * C40 encoding: Upper-case alphanumeric (3/2 bytes per CW) 68 */ 69 define('ENC_C40', 1); 70 71 /** 72 * TEXT encoding: Lower-case alphanumeric (3/2 bytes per CW) 73 */ 74 define('ENC_TXT', 2); 75 76 /** 77 * X12 encoding: ANSI X12 (3/2 byte per CW) 78 */ 79 define('ENC_X12', 3); 80 81 /** 82 * EDIFACT encoding: ASCII character 32 to 94 (4/3 bytes per CW) 83 */ 84 define('ENC_EDF', 4); 85 86 /** 87 * BASE 256 encoding: ASCII character 0 to 255 (1 byte per CW) 88 */ 89 define('ENC_BASE256', 5); 90 91 /** 92 * ASCII extended encoding: ASCII character 128 to 255 (1/2 byte per CW) 93 */ 94 define('ENC_ASCII_EXT', 6); 95 96 /** 97 * ASCII number encoding: ASCII digits (2 bytes per CW) 98 */ 99 define('ENC_ASCII_NUM', 7); 100 101 /** 102 * @class Datamatrix 103 * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. 104 * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. 105 * 106 * @package com.tecnick.tcpdf 107 * @author Nicola Asuni 108 * @version 1.0.001 109 */ 110 class Datamatrix { 111 112 /** 113 * Barcode array to be returned which is readable by TCPDF. 114 * @protected 115 */ 116 protected $barcode_array = array(); 117 118 /** 119 * Store last used encoding for data codewords. 120 * @protected 121 */ 122 protected $last_enc = ENC_ASCII; 123 124 /** 125 * Table of Data Matrix ECC 200 Symbol Attributes:<ul> 126 * <li>total matrix rows (including finder pattern)</li> 127 * <li>total matrix cols (including finder pattern)</li> 128 * <li>total matrix rows (without finder pattern)</li> 129 * <li>total matrix cols (without finder pattern)</li> 130 * <li>region data rows (with finder pattern)</li> 131 * <li>region data col (with finder pattern)</li> 132 * <li>region data rows (without finder pattern)</li> 133 * <li>region data col (without finder pattern)</li> 134 * <li>horizontal regions</li> 135 * <li>vertical regions</li> 136 * <li>regions</li> 137 * <li>data codewords</li> 138 * <li>error codewords</li> 139 * <li>blocks</li> 140 * <li>data codewords per block</li> 141 * <li>error codewords per block</li> 142 * </ul> 143 * @protected 144 */ 145 protected $symbattr = array( 146 // square form --------------------------------------------------------------------------------------- 147 array(0x00a,0x00a,0x008,0x008,0x00a,0x00a,0x008,0x008,0x001,0x001,0x001,0x003,0x005,0x001,0x003,0x005), // 10x10 148 array(0x00c,0x00c,0x00a,0x00a,0x00c,0x00c,0x00a,0x00a,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 12x12 149 array(0x00e,0x00e,0x00c,0x00c,0x00e,0x00e,0x00c,0x00c,0x001,0x001,0x001,0x008,0x00a,0x001,0x008,0x00a), // 14x14 150 array(0x010,0x010,0x00e,0x00e,0x010,0x010,0x00e,0x00e,0x001,0x001,0x001,0x00c,0x00c,0x001,0x00c,0x00c), // 16x16 151 array(0x012,0x012,0x010,0x010,0x012,0x012,0x010,0x010,0x001,0x001,0x001,0x012,0x00e,0x001,0x012,0x00e), // 18x18 152 array(0x014,0x014,0x012,0x012,0x014,0x014,0x012,0x012,0x001,0x001,0x001,0x016,0x012,0x001,0x016,0x012), // 20x20 153 array(0x016,0x016,0x014,0x014,0x016,0x016,0x014,0x014,0x001,0x001,0x001,0x01e,0x014,0x001,0x01e,0x014), // 22x22 154 array(0x018,0x018,0x016,0x016,0x018,0x018,0x016,0x016,0x001,0x001,0x001,0x024,0x018,0x001,0x024,0x018), // 24x24 155 array(0x01a,0x01a,0x018,0x018,0x01a,0x01a,0x018,0x018,0x001,0x001,0x001,0x02c,0x01c,0x001,0x02c,0x01c), // 26x26 156 array(0x020,0x020,0x01c,0x01c,0x010,0x010,0x00e,0x00e,0x002,0x002,0x004,0x03e,0x024,0x001,0x03e,0x024), // 32x32 157 array(0x024,0x024,0x020,0x020,0x012,0x012,0x010,0x010,0x002,0x002,0x004,0x056,0x02a,0x001,0x056,0x02a), // 36x36 158 array(0x028,0x028,0x024,0x024,0x014,0x014,0x012,0x012,0x002,0x002,0x004,0x072,0x030,0x001,0x072,0x030), // 40x40 159 array(0x02c,0x02c,0x028,0x028,0x016,0x016,0x014,0x014,0x002,0x002,0x004,0x090,0x038,0x001,0x090,0x038), // 44x44 160 array(0x030,0x030,0x02c,0x02c,0x018,0x018,0x016,0x016,0x002,0x002,0x004,0x0ae,0x044,0x001,0x0ae,0x044), // 48x48 161 array(0x034,0x034,0x030,0x030,0x01a,0x01a,0x018,0x018,0x002,0x002,0x004,0x0cc,0x054,0x002,0x066,0x02a), // 52x52 162 array(0x040,0x040,0x038,0x038,0x010,0x010,0x00e,0x00e,0x004,0x004,0x010,0x118,0x070,0x002,0x08c,0x038), // 64x64 163 array(0x048,0x048,0x040,0x040,0x012,0x012,0x010,0x010,0x004,0x004,0x010,0x170,0x090,0x004,0x05c,0x024), // 72x72 164 array(0x050,0x050,0x048,0x048,0x014,0x014,0x012,0x012,0x004,0x004,0x010,0x1c8,0x0c0,0x004,0x072,0x030), // 80x80 165 array(0x058,0x058,0x050,0x050,0x016,0x016,0x014,0x014,0x004,0x004,0x010,0x240,0x0e0,0x004,0x090,0x038), // 88x88 166 array(0x060,0x060,0x058,0x058,0x018,0x018,0x016,0x016,0x004,0x004,0x010,0x2b8,0x110,0x004,0x0ae,0x044), // 96x96 167 array(0x068,0x068,0x060,0x060,0x01a,0x01a,0x018,0x018,0x004,0x004,0x010,0x330,0x150,0x006,0x088,0x038), // 104x104 168 array(0x078,0x078,0x06c,0x06c,0x014,0x014,0x012,0x012,0x006,0x006,0x024,0x41a,0x198,0x006,0x0af,0x044), // 120x120 169 array(0x084,0x084,0x078,0x078,0x016,0x016,0x014,0x014,0x006,0x006,0x024,0x518,0x1f0,0x008,0x0a3,0x03e), // 132x132 170 array(0x090,0x090,0x084,0x084,0x018,0x018,0x016,0x016,0x006,0x006,0x024,0x616,0x26c,0x00a,0x09c,0x03e), // 144x144 171 // rectangular form (currently unused) --------------------------------------------------------------------------- 172 array(0x008,0x012,0x006,0x010,0x008,0x012,0x006,0x010,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 8x18 173 array(0x008,0x020,0x006,0x01c,0x008,0x010,0x006,0x00e,0x001,0x002,0x002,0x00a,0x00b,0x001,0x00a,0x00b), // 8x32 174 array(0x00c,0x01a,0x00a,0x018,0x00c,0x01a,0x00a,0x018,0x001,0x001,0x001,0x010,0x00e,0x001,0x010,0x00e), // 12x26 175 array(0x00c,0x024,0x00a,0x020,0x00c,0x012,0x00a,0x010,0x001,0x002,0x002,0x00c,0x012,0x001,0x00c,0x012), // 12x36 176 array(0x010,0x024,0x00e,0x020,0x010,0x012,0x00e,0x010,0x001,0x002,0x002,0x020,0x018,0x001,0x020,0x018), // 16x36 177 array(0x010,0x030,0x00e,0x02c,0x010,0x018,0x00e,0x016,0x001,0x002,0x002,0x031,0x01c,0x001,0x031,0x01c) // 16x48 178 ); 179 180 /** 181 * Map encodation modes whit character sets. 182 * @protected 183 */ 184 protected $chset_id = array(ENC_C40 => 'C40', ENC_TXT => 'TXT', ENC_X12 =>'X12'); 185 186 /** 187 * Basic set of charactes for each encodation mode. 188 * @protected 189 */ 190 protected $chset = array( 191 'C40' => array( // Basic set for C40 ---------------------------------------------------------------------------- 192 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 193 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // 194 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // 195 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27),// 196 'TXT' => array( // Basic set for TEXT --------------------------------------------------------------------------- 197 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 198 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x61=>0x0e,0x62=>0x0f,0x63=>0x10,0x64=>0x11,0x65=>0x12,0x66=>0x13, // 199 0x67=>0x14,0x68=>0x15,0x69=>0x16,0x6a=>0x17,0x6b=>0x18,0x6c=>0x19,0x6d=>0x1a,0x6e=>0x1b,0x6f=>0x1c,0x70=>0x1d, // 200 0x71=>0x1e,0x72=>0x1f,0x73=>0x20,0x74=>0x21,0x75=>0x22,0x76=>0x23,0x77=>0x24,0x78=>0x25,0x79=>0x26,0x7a=>0x27),// 201 'SH1' => array( // Shift 1 set ---------------------------------------------------------------------------------- 202 0x00=>0x00,0x01=>0x01,0x02=>0x02,0x03=>0x03,0x04=>0x04,0x05=>0x05,0x06=>0x06,0x07=>0x07,0x08=>0x08,0x09=>0x09, // 203 0x0a=>0x0a,0x0b=>0x0b,0x0c=>0x0c,0x0d=>0x0d,0x0e=>0x0e,0x0f=>0x0f,0x10=>0x10,0x11=>0x11,0x12=>0x12,0x13=>0x13, // 204 0x14=>0x14,0x15=>0x15,0x16=>0x16,0x17=>0x17,0x18=>0x18,0x19=>0x19,0x1a=>0x1a,0x1b=>0x1b,0x1c=>0x1c,0x1d=>0x1d, // 205 0x1e=>0x1e,0x1f=>0x1f), // 206 'SH2' => array( // Shift 2 set ---------------------------------------------------------------------------------- 207 0x21=>0x00,0x22=>0x01,0x23=>0x02,0x24=>0x03,0x25=>0x04,0x26=>0x05,0x27=>0x06,0x28=>0x07,0x29=>0x08,0x2a=>0x09, // 208 0x2b=>0x0a,0x2c=>0x0b,0x2d=>0x0c,0x2e=>0x0d,0x2f=>0x0e,0x3a=>0x0f,0x3b=>0x10,0x3c=>0x11,0x3d=>0x12,0x3e=>0x13, // 209 0x3f=>0x14,0x40=>0x15,0x5b=>0x16,0x5c=>0x17,0x5d=>0x18,0x5e=>0x19,0x5f=>0x1a,'F1'=>0x1b,'US'=>0x1e), // 210 'S3C' => array( // Shift 3 set for C40 -------------------------------------------------------------------------- 211 0x60=>0x00,0x61=>0x01,0x62=>0x02,0x63=>0x03,0x64=>0x04,0x65=>0x05,0x66=>0x06,0x67=>0x07,0x68=>0x08,0x69=>0x09, // 212 0x6a=>0x0a,0x6b=>0x0b,0x6c=>0x0c,0x6d=>0x0d,0x6e=>0x0e,0x6f=>0x0f,0x70=>0x10,0x71=>0x11,0x72=>0x12,0x73=>0x13, // 213 0x74=>0x14,0x75=>0x15,0x76=>0x16,0x77=>0x17,0x78=>0x18,0x79=>0x19,0x7a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // 214 0x7e=>0x1e,0x7f=>0x1f), 215 'S3T' => array( // Shift 3 set for TEXT ------------------------------------------------------------------------- 216 0x60=>0x00,0x41=>0x01,0x42=>0x02,0x43=>0x03,0x44=>0x04,0x45=>0x05,0x46=>0x06,0x47=>0x07,0x48=>0x08,0x49=>0x09, // 217 0x4a=>0x0a,0x4b=>0x0b,0x4c=>0x0c,0x4d=>0x0d,0x4e=>0x0e,0x4f=>0x0f,0x50=>0x10,0x51=>0x11,0x52=>0x12,0x53=>0x13, // 218 0x54=>0x14,0x55=>0x15,0x56=>0x16,0x57=>0x17,0x58=>0x18,0x59=>0x19,0x5a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // 219 0x7e=>0x1e,0x7f=>0x1f), // 220 'X12' => array( // Set for X12 ---------------------------------------------------------------------------------- 221 0x0d=>0x00,0x2a=>0x01,0x3e=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 222 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // 223 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // 224 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27) // 225 ); 226 227 // ----------------------------------------------------------------------------- 228 229 /** 230 * This is the class constructor. 231 * Creates a datamatrix object 232 * @param $code (string) Code to represent using Datamatrix. 233 * @public 234 */ 235 public function __construct($code) { 236 $barcode_array = array(); 237 if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { 238 return false; 239 } 240 // get data codewords 241 $cw = $this->getHighLevelEncoding($code); 242 // number of data codewords 243 $nd = count($cw); 244 // check size 245 if ($nd > 1558) { 246 return false; 247 } 248 // get minimum required matrix size. 249 foreach ($this->symbattr as $params) { 250 if ($params[11] >= $nd) { 251 break; 252 } 253 } 254 if ($params[11] < $nd) { 255 // too much data 256 return false; 257 } elseif ($params[11] > $nd) { 258 // add padding 259 if ($this->last_enc == ENC_EDF) { 260 // switch to ASCII encoding 261 $cw[] = 124; 262 ++$nd; 263 } elseif (($this->last_enc != ENC_ASCII) AND ($this->last_enc != ENC_BASE256)) { 264 // switch to ASCII encoding 265 $cw[] = 254; 266 ++$nd; 267 } 268 if ($params[11] > $nd) { 269 // add first pad 270 $cw[] = 129; 271 ++$nd; 272 // add remaining pads 273 for ($i = $nd; $i <= $params[11]; ++$i) { 274 $cw[] = $this->get253StateCodeword(129, $i); 275 } 276 } 277 } 278 // add error correction codewords 279 $cw = $this->getErrorCorrection($cw, $params[13], $params[14], $params[15]); 280 // initialize empty arrays 281 $grid = array_fill(0, ($params[2] * $params[3]), 0); 282 // get placement map 283 $places = $this->getPlacemetMap($params[2], $params[3]); 284 // fill the grid with data 285 $grid = array(); 286 $i = 0; 287 // region data row max index 288 $rdri = ($params[4] - 1); 289 // region data column max index 290 $rdci = ($params[5] - 1); 291 // for each vertical region 292 for ($vr = 0; $vr < $params[9]; ++$vr) { 293 // for each row on region 294 for ($r = 0; $r < $params[4]; ++$r) { 295 // get row 296 $row = (($vr * $params[4]) + $r); 297 // for each horizontal region 298 for ($hr = 0; $hr < $params[8]; ++$hr) { 299 // for each column on region 300 for ($c = 0; $c < $params[5]; ++$c) { 301 // get column 302 $col = (($hr * $params[5]) + $c); 303 // braw bits by case 304 if ($r == 0) { 305 // top finder pattern 306 if ($c % 2) { 307 $grid[$row][$col] = 0; 308 } else { 309 $grid[$row][$col] = 1; 310 } 311 } elseif ($r == $rdri) { 312 // bottom finder pattern 313 $grid[$row][$col] = 1; 314 } elseif ($c == 0) { 315 // left finder pattern 316 $grid[$row][$col] = 1; 317 } elseif ($c == $rdci) { 318 // right finder pattern 319 if ($r % 2) { 320 $grid[$row][$col] = 1; 321 } else { 322 $grid[$row][$col] = 0; 323 } 324 } else { // data bit 325 if ($places[$i] < 2) { 326 $grid[$row][$col] = $places[$i]; 327 } else { 328 // codeword ID 329 $cw_id = (floor($places[$i] / 10) - 1); 330 // codeword BIT mask 331 $cw_bit = pow(2, (8 - ($places[$i] % 10))); 332 $grid[$row][$col] = (($cw[$cw_id] & $cw_bit) == 0) ? 0 : 1; 333 } 334 ++$i; 335 } 336 } 337 } 338 } 339 } 340 $this->barcode_array['num_rows'] = $params[0]; 341 $this->barcode_array['num_cols'] = $params[1]; 342 $this->barcode_array['bcode'] = $grid; 343 } 344 345 /** 346 * Returns a barcode array which is readable by TCPDF 347 * @return array barcode array readable by TCPDF; 348 * @public 349 */ 350 public function getBarcodeArray() { 351 return $this->barcode_array; 352 } 353 354 /** 355 * Product of two numbers in a Power-of-Two Galois Field 356 * @param $a (int) first number to multiply. 357 * @param $b (int) second number to multiply. 358 * @param $log (array) Log table. 359 * @param $alog (array) Anti-Log table. 360 * @param $gf (array) Number of Factors of the Reed-Solomon polynomial. 361 * @return int product 362 * @protected 363 */ 364 protected function getGFProduct($a, $b, $log, $alog, $gf) { 365 if (($a == 0) OR ($b == 0)) { 366 return 0; 367 } 368 return $alog[($log[$a] + $log[$b]) % ($gf - 1)]; 369 } 370 371 /** 372 * Add error correction codewords to data codewords array (ANNEX E). 373 * @param $wd (array) Array of datacodewords. 374 * @param $nb (int) Number of blocks. 375 * @param $nd (int) Number of data codewords per block. 376 * @param $nc (int) Number of correction codewords per block. 377 * @param $gf (int) numner of fields on log/antilog table (power of 2). 378 * @param $pp (int) The value of its prime modulus polynomial (301 for ECC200). 379 * @return array data codewords + error codewords 380 * @protected 381 */ 382 protected function getErrorCorrection($wd, $nb, $nd, $nc, $gf=256, $pp=301) { 383 // generate the log ($log) and antilog ($alog) tables 384 $log[0] = 0; 385 $alog[0] = 1; 386 for ($i = 1; $i < $gf; ++$i) { 387 $alog[$i] = ($alog[($i - 1)] * 2); 388 if ($alog[$i] >= $gf) { 389 $alog[$i] ^= $pp; 390 } 391 $log[$alog[$i]] = $i; 392 } 393 ksort($log); 394 // generate the polynomial coefficients (c) 395 $c = array_fill(0, ($nc + 1), 0); 396 $c[0] = 1; 397 for ($i = 1; $i <= $nc; ++$i) { 398 $c[$i] = $c[($i-1)]; 399 for ($j = ($i - 1); $j >= 1; --$j) { 400 $c[$j] = $c[($j - 1)] ^ $this->getGFProduct($c[$j], $alog[$i], $log, $alog, $gf); 401 } 402 $c[0] = $this->getGFProduct($c[0], $alog[$i], $log, $alog, $gf); 403 } 404 ksort($c); 405 // total number of data codewords 406 $num_wd = ($nb * $nd); 407 // total number of error codewords 408 $num_we = ($nb * $nc); 409 // for each block 410 for ($b = 0; $b < $nb; ++$b) { 411 // create interleaved data block 412 $block = array(); 413 for ($n = $b; $n < $num_wd; $n += $nb) { 414 $block[] = $wd[$n]; 415 } 416 // initialize error codewords 417 $we = array_fill(0, ($nc + 1), 0); 418 // calculate error correction codewords for this block 419 for ($i = 0; $i < $nd; ++$i) { 420 $k = ($we[0] ^ $block[$i]); 421 for ($j = 0; $j < $nc; ++$j) { 422 $we[$j] = ($we[($j + 1)] ^ $this->getGFProduct($k, $c[($nc - $j - 1)], $log, $alog, $gf)); 423 } 424 } 425 // add error codewords at the end of data codewords 426 $j = 0; 427 for ($i = $b; $i < $num_we; $i += $nb) { 428 $wd[($num_wd + $i)] = $we[$j]; 429 ++$j; 430 } 431 } 432 // reorder codewords 433 ksort($wd); 434 return $wd; 435 } 436 437 /** 438 * Return the 253-state codeword 439 * @param $cwpad (int) Pad codeword. 440 * @param $cwpos (int) Number of data codewords from the beginning of encoded data. 441 * @return pad codeword 442 * @protected 443 */ 444 protected function get253StateCodeword($cwpad, $cwpos) { 445 $pad = ($cwpad + (((149 * $cwpos) % 253) + 1)); 446 if ($pad > 254) { 447 $pad -= 254; 448 } 449 return $pad; 450 } 451 452 /** 453 * Return the 255-state codeword 454 * @param $cwpad (int) Pad codeword. 455 * @param $cwpos (int) Number of data codewords from the beginning of encoded data. 456 * @return pad codeword 457 * @protected 458 */ 459 protected function get255StateCodeword($cwpad, $cwpos) { 460 $pad = ($cwpad + (((149 * $cwpos) % 255) + 1)); 461 if ($pad > 255) { 462 $pad -= 256; 463 } 464 return $pad; 465 } 466 467 /** 468 * Returns true if the char belongs to the selected mode 469 * @param $chr (int) Character (byte) to check. 470 * @param $mode (int) Current encoding mode. 471 * @return boolean true if the char is of the selected mode. 472 * @protected 473 */ 474 protected function isCharMode($chr, $mode) { 475 $status = false; 476 switch ($mode) { 477 case ENC_ASCII: { // ASCII character 0 to 127 478 $status = (($chr >= 0) AND ($chr <= 127)); 479 break; 480 } 481 case ENC_C40: { // Upper-case alphanumeric 482 $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 65) AND ($chr <= 90))); 483 break; 484 } 485 case ENC_TXT: { // Lower-case alphanumeric 486 $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 97) AND ($chr <= 122))); 487 break; 488 } 489 case ENC_X12: { // ANSI X12 490 $status = (($chr == 13) OR ($chr == 42) OR ($chr == 62)); 491 break; 492 } 493 case ENC_EDF: { // ASCII character 32 to 94 494 $status = (($chr >= 32) AND ($chr <= 94)); 495 break; 496 } 497 case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) 498 $status = (($chr == 232) OR ($chr == 233) OR ($chr == 234) OR ($chr == 241)); 499 break; 500 } 501 case ENC_ASCII_EXT: { // ASCII character 128 to 255 502 $status = (($chr >= 128) AND ($chr <= 255)); 503 break; 504 } 505 case ENC_ASCII_NUM: { // ASCII digits 506 $status = (($chr >= 48) AND ($chr <= 57)); 507 break; 508 } 509 } 510 return $status; 511 } 512 513 /** 514 * The look-ahead test scans the data to be encoded to find the best mode (Annex P - steps from J to S). 515 * @param $data (string) data to encode 516 * @param $pos (int) current position 517 * @param $mode (int) current encoding mode 518 * @return int encoding mode 519 * @protected 520 */ 521 protected function lookAheadTest($data, $pos, $mode) { 522 $data_length = strlen($data); 523 if ($pos >= $data_length) { 524 return $mode; 525 } 526 $charscount = 0; // count processed chars 527 // STEP J 528 if ($mode == ENC_ASCII) { 529 $numch = array(0, 1, 1, 1, 1, 1.25); 530 } else { 531 $numch = array(1, 2, 2, 2, 2, 2.25); 532 $numch[$mode] = 0; 533 } 534 while (true) { 535 // STEP K 536 if (($pos + $charscount) == $data_length) { 537 if ($numch[ENC_ASCII] <= ceil(min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { 538 return ENC_ASCII; 539 } 540 if ($numch[ENC_BASE256] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { 541 return ENC_BASE256; 542 } 543 if ($numch[ENC_EDF] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256]))) { 544 return ENC_EDF; 545 } 546 if ($numch[ENC_TXT] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { 547 return ENC_TXT; 548 } 549 if ($numch[ENC_X12] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256]))) { 550 return ENC_X12; 551 } 552 return ENC_C40; 553 } 554 // get char 555 $chr = ord($data{($pos + $charscount)}); 556 $charscount++; 557 // STEP L 558 if ($this->isCharMode($chr, ENC_ASCII_NUM)) { 559 $numch[ENC_ASCII] += (1 / 2); 560 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 561 $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); 562 $numch[ENC_ASCII] += 2; 563 } else { 564 $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); 565 $numch[ENC_ASCII] += 1; 566 } 567 // STEP M 568 if ($this->isCharMode($chr, ENC_C40)) { 569 $numch[ENC_C40] += (2 / 3); 570 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 571 $numch[ENC_C40] += (8 / 3); 572 } else { 573 $numch[ENC_C40] += (4 / 3); 574 } 575 // STEP N 576 if ($this->isCharMode($chr, ENC_TXT)) { 577 $numch[ENC_TXT] += (2 / 3); 578 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 579 $numch[ENC_TXT] += (8 / 3); 580 } else { 581 $numch[ENC_TXT] += (4 / 3); 582 } 583 // STEP O 584 if ($this->isCharMode($chr, ENC_X12) OR $this->isCharMode($chr, ENC_C40)) { 585 $numch[ENC_X12] += (2 / 3); 586 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 587 $numch[ENC_X12] += (13 / 3); 588 } else { 589 $numch[ENC_X12] += (10 / 3); 590 } 591 // STEP P 592 if ($this->isCharMode($chr, ENC_EDF)) { 593 $numch[ENC_EDF] += (3 / 4); 594 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 595 $numch[ENC_EDF] += (17 / 4); 596 } else { 597 $numch[ENC_EDF] += (13 / 4); 598 } 599 // STEP Q 600 if ($this->isCharMode($chr, ENC_BASE256)) { 601 $numch[ENC_BASE256] += 4; 602 } else { 603 $numch[ENC_BASE256] += 1; 604 } 605 // STEP R 606 if ($charscount >= 4) { 607 if (($numch[ENC_ASCII] + 1) <= min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { 608 return ENC_ASCII; 609 } 610 if ((($numch[ENC_BASE256] + 1) <= $numch[ENC_ASCII]) 611 OR (($numch[ENC_BASE256] + 1) < min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { 612 return ENC_BASE256; 613 } 614 if (($numch[ENC_EDF] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256])) { 615 return ENC_EDF; 616 } 617 if (($numch[ENC_TXT] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { 618 return ENC_TXT; 619 } 620 if (($numch[ENC_X12] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { 621 return ENC_X12; 622 } 623 if (($numch[ENC_C40] + 1) < min($numch[ENC_ASCII], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { 624 if ($numch[ENC_C40] < $numch[ENC_X12]) { 625 return ENC_C40; 626 } 627 if ($numch[ENC_C40] == $numch[ENC_X12]) { 628 $k = ($pos + $charscount + 1); 629 while ($k < $data_length) { 630 $tmpchr = ord($data{$k}); 631 if ($this->isCharMode($tmpchr, ENC_X12)) { 632 return ENC_X12; 633 } elseif (!($this->isCharMode($tmpchr, ENC_X12) OR $this->isCharMode($tmpchr, ENC_C40))) { 634 break; 635 } 636 ++$k; 637 } 638 return ENC_C40; 639 } 640 } 641 } 642 } // end of while 643 } 644 645 /** 646 * Get the switching codeword to a new encoding mode (latch codeword) 647 * @param $mode (int) New encoding mode. 648 * @return (int) Switch codeword. 649 * @protected 650 */ 651 protected function getSwitchEncodingCodeword($mode) { 652 switch ($mode) { 653 case ENC_ASCII: { // ASCII character 0 to 127 654 $cw = 254; 655 break; 656 } 657 case ENC_C40: { // Upper-case alphanumeric 658 $cw = 230; 659 break; 660 } 661 case ENC_TXT: { // Lower-case alphanumeric 662 $cw = 239; 663 break; 664 } 665 case ENC_X12: { // ANSI X12 666 $cw = 238; 667 break; 668 } 669 case ENC_EDF: { // ASCII character 32 to 94 670 $cw = 240; 671 break; 672 } 673 case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) 674 $cw = 231; 675 break; 676 } 677 } 678 return $cw; 679 } 680 681 /** 682 * Choose the minimum matrix size and return the max number of data codewords. 683 * @param $numcw (int) Number of current codewords. 684 * @return number of data codewords in matrix 685 * @protected 686 */ 687 protected function getMaxDataCodewords($numcw) { 688 foreach ($this->symbattr as $key => $matrix) { 689 if ($matrix[11] >= $numcw) { 690 return $matrix[11]; 691 } 692 } 693 return 0; 694 } 695 696 /** 697 * Get high level encoding using the minimum symbol data characters for ECC 200 698 * @param $data (string) data to encode 699 * @return array of codewords 700 * @protected 701 */ 702 protected function getHighLevelEncoding($data) { 703 // STEP A. Start in ASCII encodation. 704 $enc = ENC_ASCII; // current encoding mode 705 $pos = 0; // current position 706 $cw = array(); // array of codewords to be returned 707 $cw_num = 0; // number of data codewords 708 $data_lenght = strlen($data); // number of chars 709 while ($pos < $data_lenght) { 710 switch ($enc) { 711 case ENC_ASCII: { // STEP B. While in ASCII encodation 712 if (($data_lenght > 1) AND ($pos < ($data_lenght - 1)) AND ($this->isCharMode(ord($data{($pos)}), ENC_ASCII_NUM) AND $this->isCharMode(ord($data{($pos + 1)}), ENC_ASCII_NUM))) { 713 // 1. If the next data sequence is at least 2 consecutive digits, encode the next two digits as a double digit in ASCII mode. 714 $cw[] = (intval(substr($data, $pos, 2)) + 130); 715 ++$cw_num; 716 $pos += 2; 717 } else { 718 // 2. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. 719 $newenc = $this->lookAheadTest($data, $pos, $enc); 720 if ($newenc != $enc) { 721 // switch to new encoding 722 $enc = $newenc; 723 $cw[] = $this->getSwitchEncodingCodeword($enc); 724 ++$cw_num; 725 } else { 726 // get new byte 727 $chr = ord($data{($pos)}); 728 ++$pos; 729 if ($this->isCharMode($chr, ENC_ASCII_EXT)) { 730 // 3. If the next data character is extended ASCII (greater than 127) encode it in ASCII mode first using the Upper Shift (value 235) character. 731 $cw[] = 235; 732 $cw[] = ($chr - 127); 733 $cw_num += 2; 734 } else { 735 // 4. Otherwise process the next data character in ASCII encodation. 736 $cw[] = ($chr + 1); 737 ++$cw_num; 738 } 739 } 740 } 741 break; 742 } 743 case ENC_C40 : // Upper-case alphanumeric 744 case ENC_TXT : // Lower-case alphanumeric 745 case ENC_X12 : { // ANSI X12 746 $temp_cw = array(); 747 $p = 0; 748 $epos = $pos; 749 // get charset ID 750 $set_id = $this->chset_id[$enc]; 751 // get basic charset for current encoding 752 $charset = $this->chset[$set_id]; 753 do { 754 // 2. process the next character in C40 encodation. 755 $chr = ord($data{($epos)}); 756 ++$epos; 757 // check for extended character 758 if ($chr & 0x80) { 759 if ($enc == ENC_X12) { 760 return false; 761 } 762 $chr = ($chr & 0x7f); 763 $temp_cw[] = 1; // shift 2 764 $temp_cw[] = 30; // upper shift 765 $p += 2; 766 } 767 if (isset($charset[$chr])) { 768 $temp_cw[] = $charset[$chr]; 769 ++$p; 770 } else { 771 if (isset($this->chset['SH1'][$chr])) { 772 $temp_cw[] = 0; // shift 1 773 $shiftset = $this->chset['SH1']; 774 } elseif (isset($chr, $this->chset['SH2'][$chr])) { 775 $temp_cw[] = 1; // shift 2 776 $shiftset = $this->chset['SH2']; 777 } elseif (($enc == ENC_C40) AND isset($this->chset['S3C'][$chr])) { 778 $temp_cw[] = 2; // shift 3 779 $shiftset = $this->chset['S3C']; 780 } elseif (($enc == ENC_TXT) AND isset($this->chset['S3T'][$chr])) { 781 $temp_cw[] = 2; // shift 3 782 $shiftset = $this->chset['S3T']; 783 } else { 784 return false; 785 } 786 $temp_cw[] = $shiftset[$chr]; 787 $p += 2; 788 } 789 if ($p >= 3) { 790 $c1 = array_shift($temp_cw); 791 $c2 = array_shift($temp_cw); 792 $c3 = array_shift($temp_cw); 793 $p -= 3; 794 $tmp = ((1600 * $c1) + (40 * $c2) + $c3 + 1); 795 $cw[] = ($tmp >> 8); 796 $cw[] = ($tmp % 256); 797 $cw_num += 2; 798 $pos = $epos; 799 // 1. If the C40 encoding is at the point of starting a new double symbol character and if the look-ahead test (starting at step J) indicates another mode, switch to that mode. 800 $newenc = $this->lookAheadTest($data, $pos, $enc); 801 if ($newenc != $enc) { 802 $enc = $newenc; 803 $cw[] = $this->getSwitchEncodingCodeword($enc); 804 ++$cw_num; 805 break; 806 } 807 } 808 } while (($p > 0) AND ($epos < $data_lenght)); 809 // process last data (if any) 810 if ($p > 0) { 811 // get remaining number of data symbols 812 $cwr = ($this->getMaxDataCodewords($cw_num + 2) - $cw_num); 813 if (($cwr == 1) AND ($p == 1)) { 814 // d. If one symbol character remains and one C40 value (data character) remains to be encoded 815 $c1 = array_shift($temp_cw); 816 --$p; 817 $cw[] = ($c1 + 1); 818 ++$cw_num; 819 } elseif (($cwr == 2) AND ($p == 1)) { 820 // c. If two symbol characters remain and only one C40 value (data character) remains to be encoded 821 $c1 = array_shift($temp_cw); 822 --$p; 823 $cw[] = 254; 824 $cw[] = ($c1 + 1); 825 $cw_num += 2; 826 } elseif (($cwr == 2) AND ($p == 2)) { 827 // b. If two symbol characters remain and two C40 values remain to be encoded 828 $c1 = array_shift($temp_cw); 829 $c2 = array_shift($temp_cw); 830 $p -= 2; 831 $tmp = ((1600 * $c1) + (40 * $c2) + 1); 832 $cw[] = ($tmp >> 8); 833 $cw[] = ($tmp % 256); 834 $cw_num += 2; 835 } else { 836 // switch to ASCII encoding 837 $enc = ENC_ASCII; 838 $cw[] = $this->getSwitchEncodingCodeword($enc); 839 ++$cw_num; 840 } 841 } 842 break; 843 } 844 case ENC_EDF: { // F. While in EDIFACT (EDF) encodation 845 // initialize temporary array with 0 lenght 846 $temp_cw = array(); 847 $epos = $pos; 848 $field_lenght = 0; 849 while ($epos < $data_lenght) { 850 // 2. process the next character in EDIFACT encodation. 851 $chr = ord($data{($epos)}); 852 ++$epos; 853 $temp_cw[] = $chr; 854 ++$field_lenght; 855 if (($field_lenght == 4) OR ($epos == $data_lenght)) { 856 if ($field_lenght < 4) { 857 // set unlatch character 858 $temp_cw[] = 0x1f; 859 ++$field_lenght; 860 $enc = ENC_ASCII; 861 // fill empty characters 862 for ($i = $field_lenght; $i < 4; ++$i) { 863 $temp_cw[] = 0; 864 } 865 } 866 // encodes four data characters in three codewords 867 $cw[] = (($temp_cw[0] & 0x3F) << 2) + (($temp_cw[1] & 0x30) >> 4); 868 $cw[] = (($temp_cw[1] & 0x0F) << 4) + (($temp_cw[2] & 0x3C) >> 2); 869 $cw[] = (($temp_cw[2] & 0x03) << 6) + ($temp_cw[3] & 0x3F); 870 $cw_num += 3; 871 $temp_cw = array(); 872 $pos = $epos; 873 $field_lenght = 0; 874 } 875 // 1. If the EDIFACT encoding is at the point of starting a new triple symbol character and if the look-ahead test (starting at step J) indicates another mode, switch to that mode. 876 if ($field_lenght == 0) { 877 // get remaining number of data symbols 878 $cwr = ($this->getMaxDataCodewords($cw_num + 2) - $cw_num); 879 if ($cwr < 3) { 880 // return to ascii without unlatch 881 $enc = ENC_ASCII; 882 break; // exit from EDIFACT mode 883 } else { 884 $newenc = $this->lookAheadTest($data, $pos, $enc); 885 if ($newenc != $enc) { 886 // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. 887 $enc = $newenc; 888 $cw[] = $this->getSwitchEncodingCodeword($enc); 889 ++$cw_num; 890 break; // exit from EDIFACT mode 891 } 892 } 893 } 894 } 895 break; 896 } 897 case ENC_BASE256: { // G. While in Base 256 (B256) encodation 898 // initialize temporary array with 0 lenght 899 $temp_cw = array(); 900 $field_lenght = 0; 901 while (($pos < $data_lenght) AND ($field_lenght <= 1555)) { 902 $newenc = $this->lookAheadTest($data, $pos, $enc); 903 if ($newenc != $enc) { 904 // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. 905 $enc = $newenc; 906 $cw[] = $this->getSwitchEncodingCodeword($enc); 907 ++$cw_num; 908 break; // exit from B256 mode 909 } else { 910 // 2. Otherwise, process the next character in Base 256 encodation. 911 $chr = ord($data{($pos)}); 912 ++$pos; 913 $temp_cw[] = $chr; 914 ++$field_lenght; 915 } 916 } 917 // set field lenght 918 if ($field_lenght <= 249) { 919 $cw[] = $field_lenght; 920 ++$cw_num; 921 } else { 922 $cw[] = (floor($field_lenght / 250) + 249); 923 $cw[] = ($field_lenght % 250); 924 $cw_num += 2; 925 } 926 if (!empty($temp_cw)) { 927 // add B256 field 928 foreach ($temp_cw as $p => $cht) { 929 $cw[] = $this->get255StateCodeword($chr, ($cw_num + $p)); 930 } 931 } 932 break; 933 } 934 } // end of switch enc 935 } // end of while 936 // set last used encoding 937 $this->last_enc = $enc; 938 return $cw; 939 } 940 941 /** 942 * Places "chr+bit" with appropriate wrapping within array[]. 943 * (Annex F - ECC 200 symbol character placement) 944 * @param $marr (array) Array of symbols. 945 * @param $nrow (int) Number of rows. 946 * @param $ncol (int) Number of columns. 947 * @param $row (int) Row number. 948 * @param $col (int) Column number. 949 * @param $chr (int) Char byte. 950 * @param $bit (int) Bit. 951 * @return array 952 * @protected 953 */ 954 protected function placeModule($marr, $nrow, $ncol, $row, $col, $chr, $bit) { 955 if ($row < 0) { 956 $row += $nrow; 957 $col += (4 - (($nrow + 4) % 8)); 958 } 959 if ($col < 0) { 960 $col += $ncol; 961 $row += (4 - (($ncol + 4) % 8)); 962 } 963 $marr[(($row * $ncol) + $col)] = ((10 * $chr) + $bit); 964 return $marr; 965 } 966 967 /** 968 * Places the 8 bits of a utah-shaped symbol character. 969 * (Annex F - ECC 200 symbol character placement) 970 * @param $marr (array) Array of symbols. 971 * @param $nrow (int) Number of rows. 972 * @param $ncol (int) Number of columns. 973 * @param $row (int) Row number. 974 * @param $col (int) Column number. 975 * @param $chr (int) Char byte. 976 * @return array 977 * @protected 978 */ 979 protected function placeUtah($marr, $nrow, $ncol, $row, $col, $chr) { 980 $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-2, $chr, 1); 981 $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-1, $chr, 2); 982 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-2, $chr, 3); 983 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-1, $chr, 4); 984 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col, $chr, 5); 985 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-2, $chr, 6); 986 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-1, $chr, 7); 987 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col, $chr, 8); 988 return $marr; 989 } 990 991 /** 992 * Places the 8 bits of the first special corner case. 993 * (Annex F - ECC 200 symbol character placement) 994 * @param $marr (array) Array of symbols. 995 * @param $nrow (int) Number of rows. 996 * @param $ncol (int) Number of columns. 997 * @param $chr (int) Char byte. 998 * @return array 999 * @protected 1000 */ 1001 protected function placeCornerA($marr, $nrow, $ncol, $chr) { 1002 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); 1003 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 1, $chr, 2); 1004 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 2, $chr, 3); 1005 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); 1006 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); 1007 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); 1008 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); 1009 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); 1010 return $marr; 1011 } 1012 1013 /** 1014 * Places the 8 bits of the second special corner case. 1015 * (Annex F - ECC 200 symbol character placement) 1016 * @param $marr (array) Array of symbols. 1017 * @param $nrow (int) Number of rows. 1018 * @param $ncol (int) Number of columns. 1019 * @param $chr (int) Char byte. 1020 * @return array 1021 * @protected 1022 */ 1023 protected function placeCornerB($marr, $nrow, $ncol, $chr) { 1024 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); 1025 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); 1026 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); 1027 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-4, $chr, 4); 1028 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 5); 1029 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 6); 1030 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 7); 1031 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); 1032 return $marr; 1033 } 1034 1035 /** 1036 * Places the 8 bits of the third special corner case. 1037 * (Annex F - ECC 200 symbol character placement) 1038 * @param $marr (array) Array of symbols. 1039 * @param $nrow (int) Number of rows. 1040 * @param $ncol (int) Number of columns. 1041 * @param $chr (int) Char byte. 1042 * @return array 1043 * @protected 1044 */ 1045 protected function placeCornerC($marr, $nrow, $ncol, $chr) { 1046 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); 1047 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); 1048 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); 1049 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); 1050 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); 1051 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); 1052 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); 1053 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); 1054 return $marr; 1055 } 1056 1057 /** 1058 * Places the 8 bits of the fourth special corner case. 1059 * (Annex F - ECC 200 symbol character placement) 1060 * @param $marr (array) Array of symbols. 1061 * @param $nrow (int) Number of rows. 1062 * @param $ncol (int) Number of columns. 1063 * @param $chr (int) Char byte. 1064 * @return array 1065 * @protected 1066 */ 1067 protected function placeCornerD($marr, $nrow, $ncol, $chr) { 1068 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); 1069 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, $ncol-1, $chr, 2); 1070 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 3); 1071 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); 1072 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); 1073 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-3, $chr, 6); 1074 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-2, $chr, 7); 1075 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); 1076 return $marr; 1077 } 1078 1079 1080 /** 1081 * Build a placement map. 1082 * (Annex F - ECC 200 symbol character placement) 1083 * @param $nrow (int) Number of rows. 1084 * @param $ncol (int) Number of columns. 1085 * @return array 1086 * @protected 1087 */ 1088 protected function getPlacemetMap($nrow, $ncol) { 1089 // initialize array with zeros 1090 $marr = array_fill(0, ($nrow * $ncol), 0); 1091 // set starting values 1092 $chr = 1; 1093 $row = 4; 1094 $col = 0; 1095 do { 1096 // repeatedly first check for one of the special corner cases, then 1097 if (($row == $nrow) AND ($col == 0)) { 1098 $marr = $this->placeCornerA($marr, $nrow, $ncol, $chr); 1099 ++$chr; 1100 } 1101 if (($row == ($nrow - 2)) AND ($col == 0) AND ($ncol % 4)) { 1102 $marr = $this->placeCornerB($marr, $nrow, $ncol, $chr); 1103 ++$chr; 1104 } 1105 if (($row == ($nrow - 2)) AND ($col == 0) AND (($ncol % 8) == 4)) { 1106 $marr = $this->placeCornerC($marr, $nrow, $ncol, $chr); 1107 ++$chr; 1108 } 1109 if (($row == ($nrow + 4)) AND ($col == 2) AND (!($ncol % 8))) { 1110 $marr = $this->placeCornerD($marr, $nrow, $ncol, $chr); 1111 ++$chr; 1112 } 1113 // sweep upward diagonally, inserting successive characters, 1114 do { 1115 if (($row < $nrow) AND ($col >= 0) AND (!$marr[(($row * $ncol) + $col)])) { 1116 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); 1117 ++$chr; 1118 } 1119 $row -= 2; 1120 $col += 2; 1121 } while (($row >= 0) AND ($col < $ncol)); 1122 ++$row; 1123 $col += 3; 1124 // & then sweep downward diagonally, inserting successive characters,... 1125 do { 1126 if (($row >= 0) AND ($col < $ncol) AND (!$marr[(($row * $ncol) + $col)])) { 1127 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); 1128 ++$chr; 1129 } 1130 $row += 2; 1131 $col -= 2; 1132 } while (($row < $nrow) AND ($col >= 0)); 1133 $row += 3; 1134 ++$col; 1135 // ... until the entire array is scanned 1136 } while (($row < $nrow) OR ($col < $ncol)); 1137 // lastly, if the lower righthand corner is untouched, fill in fixed pattern 1138 if (!$marr[(($nrow * $ncol) - 1)]) { 1139 $marr[(($nrow * $ncol) - 1)] = 1; 1140 $marr[(($nrow * $ncol) - $ncol - 2)] = 1; 1141 } 1142 return $marr; 1143 } 1144 1145 } // end DataMatrix class 1146 //============================================================+ 1147 // END OF FILE 1148 //============================================================+
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |