qrspec.php (26612B)
1 <?php 2 /* 3 * PHP QR Code encoder 4 * 5 * QR Code specifications 6 * 7 * Based on libqrencode C library distributed under LGPL 2.1 8 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 9 * 10 * PHP QR Code is distributed under LGPL 3 11 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 12 * 13 * The following data / specifications are taken from 14 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) 15 * or 16 * "Automatic identification and data capture techniques -- 17 * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) 18 * 19 * This library is free software; you can redistribute it and/or 20 * modify it under the terms of the GNU Lesser General Public 21 * License as published by the Free Software Foundation; either 22 * version 3 of the License, or any later version. 23 * 24 * This library is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 * Lesser General Public License for more details. 28 * 29 * You should have received a copy of the GNU Lesser General Public 30 * License along with this library; if not, write to the Free Software 31 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 32 */ 33 34 define('QRSPEC_VERSION_MAX', 40); 35 define('QRSPEC_WIDTH_MAX', 177); 36 37 define('QRCAP_WIDTH', 0); 38 define('QRCAP_WORDS', 1); 39 define('QRCAP_REMINDER', 2); 40 define('QRCAP_EC', 3); 41 42 class QRspec { 43 44 public static $capacity = array( 45 array( 0, 0, 0, array( 0, 0, 0, 0)), 46 array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 47 array( 25, 44, 7, array( 10, 16, 22, 28)), 48 array( 29, 70, 7, array( 15, 26, 36, 44)), 49 array( 33, 100, 7, array( 20, 36, 52, 64)), 50 array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 51 array( 41, 172, 7, array( 36, 64, 96, 112)), 52 array( 45, 196, 0, array( 40, 72, 108, 130)), 53 array( 49, 242, 0, array( 48, 88, 132, 156)), 54 array( 53, 292, 0, array( 60, 110, 160, 192)), 55 array( 57, 346, 0, array( 72, 130, 192, 224)), //10 56 array( 61, 404, 0, array( 80, 150, 224, 264)), 57 array( 65, 466, 0, array( 96, 176, 260, 308)), 58 array( 69, 532, 0, array( 104, 198, 288, 352)), 59 array( 73, 581, 3, array( 120, 216, 320, 384)), 60 array( 77, 655, 3, array( 132, 240, 360, 432)), //15 61 array( 81, 733, 3, array( 144, 280, 408, 480)), 62 array( 85, 815, 3, array( 168, 308, 448, 532)), 63 array( 89, 901, 3, array( 180, 338, 504, 588)), 64 array( 93, 991, 3, array( 196, 364, 546, 650)), 65 array( 97, 1085, 3, array( 224, 416, 600, 700)), //20 66 array(101, 1156, 4, array( 224, 442, 644, 750)), 67 array(105, 1258, 4, array( 252, 476, 690, 816)), 68 array(109, 1364, 4, array( 270, 504, 750, 900)), 69 array(113, 1474, 4, array( 300, 560, 810, 960)), 70 array(117, 1588, 4, array( 312, 588, 870, 1050)), //25 71 array(121, 1706, 4, array( 336, 644, 952, 1110)), 72 array(125, 1828, 4, array( 360, 700, 1020, 1200)), 73 array(129, 1921, 3, array( 390, 728, 1050, 1260)), 74 array(133, 2051, 3, array( 420, 784, 1140, 1350)), 75 array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30 76 array(141, 2323, 3, array( 480, 868, 1290, 1530)), 77 array(145, 2465, 3, array( 510, 924, 1350, 1620)), 78 array(149, 2611, 3, array( 540, 980, 1440, 1710)), 79 array(153, 2761, 3, array( 570, 1036, 1530, 1800)), 80 array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 81 array(161, 3034, 0, array( 600, 1120, 1680, 1980)), 82 array(165, 3196, 0, array( 630, 1204, 1770, 2100)), 83 array(169, 3362, 0, array( 660, 1260, 1860, 2220)), 84 array(173, 3532, 0, array( 720, 1316, 1950, 2310)), 85 array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 86 ); 87 88 //---------------------------------------------------------------------- 89 public static function getDataLength($version, $level) 90 { 91 return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; 92 } 93 94 //---------------------------------------------------------------------- 95 public static function getECCLength($version, $level) 96 { 97 return self::$capacity[$version][QRCAP_EC][$level]; 98 } 99 100 //---------------------------------------------------------------------- 101 public static function getWidth($version) 102 { 103 return self::$capacity[$version][QRCAP_WIDTH]; 104 } 105 106 //---------------------------------------------------------------------- 107 public static function getRemainder($version) 108 { 109 return self::$capacity[$version][QRCAP_REMINDER]; 110 } 111 112 //---------------------------------------------------------------------- 113 public static function getMinimumVersion($size, $level) 114 { 115 116 for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) { 117 $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level]; 118 if($words >= $size) 119 return $i; 120 } 121 122 return -1; 123 } 124 125 //###################################################################### 126 127 public static $lengthTableBits = array( 128 array(10, 12, 14), 129 array( 9, 11, 13), 130 array( 8, 16, 16), 131 array( 8, 10, 12) 132 ); 133 134 //---------------------------------------------------------------------- 135 public static function lengthIndicator($mode, $version) 136 { 137 if ($mode == QR_MODE_STRUCTURE) 138 return 0; 139 140 if ($version <= 9) { 141 $l = 0; 142 } else if ($version <= 26) { 143 $l = 1; 144 } else { 145 $l = 2; 146 } 147 148 return self::$lengthTableBits[$mode][$l]; 149 } 150 151 //---------------------------------------------------------------------- 152 public static function maximumWords($mode, $version) 153 { 154 if($mode == QR_MODE_STRUCTURE) 155 return 3; 156 157 if($version <= 9) { 158 $l = 0; 159 } else if($version <= 26) { 160 $l = 1; 161 } else { 162 $l = 2; 163 } 164 165 $bits = self::$lengthTableBits[$mode][$l]; 166 $words = (1 << $bits) - 1; 167 168 if($mode == QR_MODE_KANJI) { 169 $words *= 2; // the number of bytes is required 170 } 171 172 return $words; 173 } 174 175 // Error correction code ----------------------------------------------- 176 // Table of the error correction code (Reed-Solomon block) 177 // See Table 12-16 (pp.30-36), JIS X0510:2004. 178 179 public static $eccTable = array( 180 array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), 181 array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 182 array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), 183 array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), 184 array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), 185 array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 186 array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), 187 array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), 188 array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), 189 array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), 190 array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10 191 array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), 192 array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), 193 array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), 194 array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), 195 array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15 196 array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), 197 array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), 198 array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), 199 array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), 200 array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20 201 array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), 202 array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), 203 array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), 204 array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), 205 array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25 206 array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), 207 array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), 208 array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), 209 array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), 210 array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 211 array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), 212 array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), 213 array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), 214 array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), 215 array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35 216 array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), 217 array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), 218 array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), 219 array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), 220 array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40 221 ); 222 223 //---------------------------------------------------------------------- 224 // CACHEABLE!!! 225 226 public static function getEccSpec($version, $level, array &$spec) 227 { 228 if (count($spec) < 5) { 229 $spec = array(0,0,0,0,0); 230 } 231 232 $b1 = self::$eccTable[$version][$level][0]; 233 $b2 = self::$eccTable[$version][$level][1]; 234 $data = self::getDataLength($version, $level); 235 $ecc = self::getECCLength($version, $level); 236 237 if($b2 == 0) { 238 $spec[0] = $b1; 239 $spec[1] = (int)($data / $b1); 240 $spec[2] = (int)($ecc / $b1); 241 $spec[3] = 0; 242 $spec[4] = 0; 243 } else { 244 $spec[0] = $b1; 245 $spec[1] = (int)($data / ($b1 + $b2)); 246 $spec[2] = (int)($ecc / ($b1 + $b2)); 247 $spec[3] = $b2; 248 $spec[4] = $spec[1] + 1; 249 } 250 } 251 252 // Alignment pattern --------------------------------------------------- 253 254 // Positions of alignment patterns. 255 // This array includes only the second and the third position of the 256 // alignment patterns. Rest of them can be calculated from the distance 257 // between them. 258 259 // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. 260 261 public static $alignmentPattern = array( 262 array( 0, 0), 263 array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 264 array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 265 array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 266 array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 267 array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 268 array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 269 array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 270 array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 271 ); 272 273 274 /** -------------------------------------------------------------------- 275 * Put an alignment marker. 276 * @param frame 277 * @param width 278 * @param ox,oy center coordinate of the pattern 279 */ 280 public static function putAlignmentMarker(array &$frame, $ox, $oy) 281 { 282 $finder = array( 283 "\xa1\xa1\xa1\xa1\xa1", 284 "\xa1\xa0\xa0\xa0\xa1", 285 "\xa1\xa0\xa1\xa0\xa1", 286 "\xa1\xa0\xa0\xa0\xa1", 287 "\xa1\xa1\xa1\xa1\xa1" 288 ); 289 290 $yStart = $oy-2; 291 $xStart = $ox-2; 292 293 for($y=0; $y<5; $y++) { 294 QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); 295 } 296 } 297 298 //---------------------------------------------------------------------- 299 public static function putAlignmentPattern($version, &$frame, $width) 300 { 301 if($version < 2) 302 return; 303 304 $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0]; 305 if($d < 0) { 306 $w = 2; 307 } else { 308 $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2); 309 } 310 311 if($w * $w - 3 == 1) { 312 $x = self::$alignmentPattern[$version][0]; 313 $y = self::$alignmentPattern[$version][0]; 314 self::putAlignmentMarker($frame, $x, $y); 315 return; 316 } 317 318 $cx = self::$alignmentPattern[$version][0]; 319 for($x=1; $x<$w - 1; $x++) { 320 self::putAlignmentMarker($frame, 6, $cx); 321 self::putAlignmentMarker($frame, $cx, 6); 322 $cx += $d; 323 } 324 325 $cy = self::$alignmentPattern[$version][0]; 326 for($y=0; $y<$w-1; $y++) { 327 $cx = self::$alignmentPattern[$version][0]; 328 for($x=0; $x<$w-1; $x++) { 329 self::putAlignmentMarker($frame, $cx, $cy); 330 $cx += $d; 331 } 332 $cy += $d; 333 } 334 } 335 336 // Version information pattern ----------------------------------------- 337 338 // Version information pattern (BCH coded). 339 // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. 340 341 // size: [QRSPEC_VERSION_MAX - 6] 342 343 public static $versionPattern = array( 344 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 345 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, 346 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, 347 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, 348 0x27541, 0x28c69 349 ); 350 351 //---------------------------------------------------------------------- 352 public static function getVersionPattern($version) 353 { 354 if($version < 7 || $version > QRSPEC_VERSION_MAX) 355 return 0; 356 357 return self::$versionPattern[$version -7]; 358 } 359 360 // Format information -------------------------------------------------- 361 // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) 362 363 public static $formatInfo = array( 364 array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), 365 array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), 366 array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), 367 array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) 368 ); 369 370 public static function getFormatInfo($mask, $level) 371 { 372 if($mask < 0 || $mask > 7) 373 return 0; 374 375 if($level < 0 || $level > 3) 376 return 0; 377 378 return self::$formatInfo[$level][$mask]; 379 } 380 381 // Frame --------------------------------------------------------------- 382 // Cache of initial frames. 383 384 public static $frames = array(); 385 386 /** -------------------------------------------------------------------- 387 * Put a finder pattern. 388 * @param frame 389 * @param width 390 * @param ox,oy upper-left coordinate of the pattern 391 */ 392 public static function putFinderPattern(&$frame, $ox, $oy) 393 { 394 $finder = array( 395 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", 396 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", 397 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", 398 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", 399 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", 400 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", 401 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" 402 ); 403 404 for($y=0; $y<7; $y++) { 405 QRstr::set($frame, $ox, $oy+$y, $finder[$y]); 406 } 407 } 408 409 //---------------------------------------------------------------------- 410 public static function createFrame($version) 411 { 412 $width = self::$capacity[$version][QRCAP_WIDTH]; 413 $frameLine = str_repeat ("\0", $width); 414 $frame = array_fill(0, $width, $frameLine); 415 416 // Finder pattern 417 self::putFinderPattern($frame, 0, 0); 418 self::putFinderPattern($frame, $width - 7, 0); 419 self::putFinderPattern($frame, 0, $width - 7); 420 421 // Separator 422 $yOffset = $width - 7; 423 424 for($y=0; $y<7; $y++) { 425 $frame[$y][7] = "\xc0"; 426 $frame[$y][$width - 8] = "\xc0"; 427 $frame[$yOffset][7] = "\xc0"; 428 $yOffset++; 429 } 430 431 $setPattern = str_repeat("\xc0", 8); 432 433 QRstr::set($frame, 0, 7, $setPattern); 434 QRstr::set($frame, $width-8, 7, $setPattern); 435 QRstr::set($frame, 0, $width - 8, $setPattern); 436 437 // Format info 438 $setPattern = str_repeat("\x84", 9); 439 QRstr::set($frame, 0, 8, $setPattern); 440 QRstr::set($frame, $width - 8, 8, $setPattern, 8); 441 442 $yOffset = $width - 8; 443 444 for($y=0; $y<8; $y++,$yOffset++) { 445 $frame[$y][8] = "\x84"; 446 $frame[$yOffset][8] = "\x84"; 447 } 448 449 // Timing pattern 450 451 for($i=1; $i<$width-15; $i++) { 452 $frame[6][7+$i] = chr(0x90 | ($i & 1)); 453 $frame[7+$i][6] = chr(0x90 | ($i & 1)); 454 } 455 456 // Alignment pattern 457 self::putAlignmentPattern($version, $frame, $width); 458 459 // Version information 460 if($version >= 7) { 461 $vinf = self::getVersionPattern($version); 462 463 $v = $vinf; 464 465 for($x=0; $x<6; $x++) { 466 for($y=0; $y<3; $y++) { 467 $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); 468 $v = $v >> 1; 469 } 470 } 471 472 $v = $vinf; 473 for($y=0; $y<6; $y++) { 474 for($x=0; $x<3; $x++) { 475 $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); 476 $v = $v >> 1; 477 } 478 } 479 } 480 481 // and a little bit... 482 $frame[$width - 8][8] = "\x81"; 483 484 return $frame; 485 } 486 487 //---------------------------------------------------------------------- 488 public static function debug($frame, $binary_mode = false) 489 { 490 if ($binary_mode) { 491 492 foreach ($frame as &$frameLine) { 493 $frameLine = join('<span class="m"> </span>', explode('0', $frameLine)); 494 $frameLine = join('██', explode('1', $frameLine)); 495 } 496 497 ?> 498 <style> 499 .m { background-color: white; } 500 </style> 501 <?php 502 echo '<pre><tt><br/ ><br/ ><br/ > '; 503 echo join("<br/ > ", $frame); 504 echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >'; 505 506 } else { 507 508 foreach ($frame as &$frameLine) { 509 $frameLine = join('<span class="m"> </span>', explode("\xc0", $frameLine)); 510 $frameLine = join('<span class="m">▒</span>', explode("\xc1", $frameLine)); 511 $frameLine = join('<span class="p"> </span>', explode("\xa0", $frameLine)); 512 $frameLine = join('<span class="p">▒</span>', explode("\xa1", $frameLine)); 513 $frameLine = join('<span class="s">◇</span>', explode("\x84", $frameLine)); //format 0 514 $frameLine = join('<span class="s">◆</span>', explode("\x85", $frameLine)); //format 1 515 $frameLine = join('<span class="x">☢</span>', explode("\x81", $frameLine)); //special bit 516 $frameLine = join('<span class="c"> </span>', explode("\x90", $frameLine)); //clock 0 517 $frameLine = join('<span class="c">◷</span>', explode("\x91", $frameLine)); //clock 1 518 $frameLine = join('<span class="f"> </span>', explode("\x88", $frameLine)); //version 519 $frameLine = join('<span class="f">▒</span>', explode("\x89", $frameLine)); //version 520 $frameLine = join('♦', explode("\x01", $frameLine)); 521 $frameLine = join('⋅', explode("\0", $frameLine)); 522 } 523 524 ?> 525 <style> 526 .p { background-color: yellow; } 527 .m { background-color: #00FF00; } 528 .s { background-color: #FF0000; } 529 .c { background-color: aqua; } 530 .x { background-color: pink; } 531 .f { background-color: gold; } 532 </style> 533 <?php 534 echo "<pre><tt>"; 535 echo join("<br/ >", $frame); 536 echo "</tt></pre>"; 537 538 } 539 } 540 541 //---------------------------------------------------------------------- 542 public static function serial($frame) 543 { 544 return gzcompress(join("\n", $frame), 9); 545 } 546 547 //---------------------------------------------------------------------- 548 public static function unserial($code) 549 { 550 return explode("\n", gzuncompress($code)); 551 } 552 553 //---------------------------------------------------------------------- 554 public static function newFrame($version) 555 { 556 if($version < 1 || $version > QRSPEC_VERSION_MAX) 557 return null; 558 559 if(!isset(self::$frames[$version])) { 560 561 $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat'; 562 563 if (QR_CACHEABLE) { 564 if (file_exists($fileName)) { 565 self::$frames[$version] = self::unserial(file_get_contents($fileName)); 566 } else { 567 self::$frames[$version] = self::createFrame($version); 568 file_put_contents($fileName, self::serial(self::$frames[$version])); 569 } 570 } else { 571 self::$frames[$version] = self::createFrame($version); 572 } 573 } 574 575 if(is_null(self::$frames[$version])) 576 return null; 577 578 return self::$frames[$version]; 579 } 580 581 //---------------------------------------------------------------------- 582 public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } 583 public static function rsBlockNum1($spec) { return $spec[0]; } 584 public static function rsDataCodes1($spec) { return $spec[1]; } 585 public static function rsEccCodes1($spec) { return $spec[2]; } 586 public static function rsBlockNum2($spec) { return $spec[3]; } 587 public static function rsDataCodes2($spec) { return $spec[4]; } 588 public static function rsEccCodes2($spec) { return $spec[2]; } 589 public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } 590 public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } 591 592 }