. // // See LICENSE.TXT file for more information. // ---------------------------------------------------------------------------- // // Description : PHP class to creates array representations for // common 1D barcodes to be used with TCPDF. // // Author: Nicola Asuni // // (c) Copyright: // Nicola Asuni // Tecnick.com S.r.l. // Via della Pace, 11 // 09044 Quartucciu (CA) // ITALY // www.tecnick.com // info@tecnick.com //============================================================+ class PDFBarcode { protected $barcode_array; protected $gapwidth; protected $print_ratio; protected $daft; public function __construct() { } public function getBarcodeArray($code, $type, $pr='') { $this->setBarcode($code, $type, $pr); return $this->barcode_array; } public function getChecksum($code, $type) { $this->setBarcode($code, $type); if (!$this->barcode_array) { return ''; } else { return $this->barcode_array['checkdigit']; } } public function setBarcode($code, $type, $pr='') { $this->print_ratio = 1; switch (strtoupper($type)) { case 'ISBN': case 'ISSN': case 'EAN13': { // EAN 13 $arrcode = $this->barcode_eanupc($code, 13); $arrcode['lightmL'] = 11; // LEFT light margin = x X-dim (http://www.gs1uk.org) $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org) $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org) $arrcode['nom-H'] = 25.93; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org) break; } case 'UPCA': { // UPC-A $arrcode = $this->barcode_eanupc($code, 12); $arrcode['lightmL'] = 9; // LEFT light margin = x X-dim (http://www.gs1uk.org) $arrcode['lightmR'] = 9; // RIGHT light margin = x X-dim (http://www.gs1uk.org) $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org) $arrcode['nom-H'] = 25.91; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org) break; } case 'UPCE': { // UPC-E $arrcode = $this->barcode_eanupc($code, 6); $arrcode['lightmL'] = 9; // LEFT light margin = x X-dim (http://www.gs1uk.org) $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org) $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org) $arrcode['nom-H'] = 25.93; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org) break; } case 'EAN8': { // EAN 8 $arrcode = $this->barcode_eanupc($code, 8); $arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (http://www.gs1uk.org) $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org) $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org) $arrcode['nom-H'] = 21.64; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org) break; } case 'EAN2': { // 2-Digits UPC-Based Extention $arrcode = $this->barcode_eanext($code, 2); $arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (estimated) $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (estimated) $arrcode['sepM'] = 9; // SEPARATION margin = x X-dim (http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm) $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org) $arrcode['nom-H'] = 20; // Nominal bar height in mm incl. numerals (estimated) not used when combined break; } case 'EAN5': { // 5-Digits UPC-Based Extention $arrcode = $this->barcode_eanext($code, 5); $arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (estimated) $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (estimated) $arrcode['sepM'] = 9; // SEPARATION margin = x X-dim (http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm) $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org) $arrcode['nom-H'] = 20; // Nominal bar height in mm incl. numerals (estimated) not used when combined break; } case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.) $bpi = 22; // Bars per inch // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim; $this->daft = array('D'=>2, 'A'=>2, 'F'=>3, 'T'=>1); // Descender; Ascender; Full; Tracker bar heights $arrcode = $this->barcode_imb($code); $arrcode['nom-X'] = $xdim ; $arrcode['nom-H'] = 3.68; // Nominal value for Height of Full bar in mm (spec.) // USPS-B-3200 Revision C = 4.623 // USPS-B-3200 Revision E = 3.68 $arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (spec.) $arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (spec.) $arrcode['quietTB'] = 0.711; // TOP/BOTTOM Quiet margin = mm (spec.) break; } case 'RM4SCC': { // RM4SCC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.) $bpi = 22; // Bars per inch // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim; $this->daft = array('D'=>5, 'A'=>5, 'F'=>8, 'T'=>2); // Descender; Ascender; Full; Tracker bar heights $arrcode = $this->barcode_rm4scc($code, false); $arrcode['nom-X'] = $xdim ; $arrcode['nom-H'] = 5.0; // Nominal value for Height of Full bar in mm (spec.) $arrcode['quietL'] = 2; // LEFT Quiet margin = mm (spec.) $arrcode['quietR'] = 2; // RIGHT Quiet margin = mm (spec.) $arrcode['quietTB'] = 2; // TOP/BOTTOM Quiet margin = mm (spec?) break; } case 'KIX': { // KIX (Klant index - Customer index) $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.) $bpi = 22; // Bars per inch // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim; $this->daft = array('D'=>5, 'A'=>5, 'F'=>8, 'T'=>2); // Descender; Ascender; Full; Tracker bar heights $arrcode = $this->barcode_rm4scc($code, true); $arrcode['nom-X'] = $xdim ; $arrcode['nom-H'] = 5.0; // Nominal value for Height of Full bar in mm (? spec.) $arrcode['quietL'] = 2; // LEFT Quiet margin = mm (spec.) $arrcode['quietR'] = 2; // RIGHT Quiet margin = mm (spec.) $arrcode['quietTB'] = 2; // TOP/BOTTOM Quiet margin = mm (spec.) break; } case 'POSTNET': { // POSTNET $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.) $bpi = 22; // Bars per inch // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim; $arrcode = $this->barcode_postnet($code, false); $arrcode['nom-X'] = $xdim ; $arrcode['nom-H'] = 3.175; // Nominal value for Height of Full bar in mm (spec.) $arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (?spec.) $arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (?spec.) $arrcode['quietTB'] = 1.016; // TOP/BOTTOM Quiet margin = mm (?spec.) break; } case 'PLANET': { // PLANET $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.) $bpi = 22; // Bars per inch // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim; $arrcode = $this->barcode_postnet($code, true); $arrcode['nom-X'] = $xdim ; $arrcode['nom-H'] = 3.175; // Nominal value for Height of Full bar in mm (spec.) $arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (?spec.) $arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (?spec.) $arrcode['quietTB'] = 1.016; // TOP/BOTTOM Quiet margin = mm (?spec.) break; } case 'C93': { // CODE 93 - USS-93 $arrcode = $this->barcode_code93($code); if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'CODE11': { // CODE 11 if ($pr > 0) { $this->print_ratio = $pr; } else { $this->print_ratio = 3; } // spec: Pr= 1:2.24 - 1:3.5 $arrcode = $this->barcode_code11($code); if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'MSI': // MSI (Variation of Plessey code) case 'MSI+': { // MSI + CHECKSUM (modulo 11) if (strtoupper($type)=='MSI') { $arrcode = $this->barcode_msi($code, false); } if (strtoupper($type)=='MSI+') { $arrcode = $this->barcode_msi($code, true); } if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 12; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 12; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'CODABAR': { // CODABAR if ($pr > 0) { $this->print_ratio = $pr; } else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50) if (strtoupper($type)=='CODABAR') { $arrcode = $this->barcode_codabar($code); } if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'C128A': // CODE 128 A case 'C128B': // CODE 128 B case 'C128C': // CODE 128 C case 'EAN128A': // EAN 128 A case 'EAN128B': // EAN 128 B case 'EAN128C': { // EAN 128 C if (strtoupper($type)=='C128A') { $arrcode = $this->barcode_c128($code, 'A'); } if (strtoupper($type)=='C128B') { $arrcode = $this->barcode_c128($code, 'B'); } if (strtoupper($type)=='C128C') { $arrcode = $this->barcode_c128($code, 'C'); } if (strtoupper($type)=='EAN128A') { $arrcode = $this->barcode_c128($code, 'A', true); } if (strtoupper($type)=='EAN128B') { $arrcode = $this->barcode_c128($code, 'B', true); } if (strtoupper($type)=='EAN128C') { $arrcode = $this->barcode_c128($code, 'C', true); } if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'C39': // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. case 'C39+': // CODE 39 with checksum case 'C39E': // CODE 39 EXTENDED case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM if ($pr > 0) { $this->print_ratio = $pr; } else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50) $code = str_replace(chr(194).chr(160), ' ', $code); // mPDF 5.3.95 (for utf-8 encoded) $code = str_replace(chr(160), ' ', $code); // mPDF 5.3.95 (for win-1252) if (strtoupper($type)=='C39') { $arrcode = $this->barcode_code39($code, false, false); } if (strtoupper($type)=='C39+') { $arrcode = $this->barcode_code39($code, false, true); } if (strtoupper($type)=='C39E') { $arrcode = $this->barcode_code39($code, true, false); } if (strtoupper($type)=='C39E+') { $arrcode = $this->barcode_code39($code, true, true); } if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'S25': // Standard 2 of 5 case 'S25+': { // Standard 2 of 5 + CHECKSUM if ($pr > 0) { $this->print_ratio = $pr; } else { $this->print_ratio = 3; } // spec: Pr=1:3/1:4.5 if (strtoupper($type)=='S25') { $arrcode = $this->barcode_s25($code, false); } if (strtoupper($type)=='S25+') { $arrcode = $this->barcode_s25($code, true); } if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'I25': // Interleaved 2 of 5 case 'I25+': { // Interleaved 2 of 5 + CHECKSUM if ($pr > 0) { $this->print_ratio = $pr; } else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50) if (strtoupper($type)=='I25') { $arrcode = $this->barcode_i25($code, false); } if (strtoupper($type)=='I25+') { $arrcode = $this->barcode_i25($code, true); } if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) break; } case 'I25B': // Interleaved 2 of 5 + Bearer bars case 'I25B+': { // Interleaved 2 of 5 + CHECKSUM + Bearer bars if ($pr > 0) { $this->print_ratio = $pr; } else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50) if (strtoupper($type)=='I25B') { $arrcode = $this->barcode_i25($code, false); } if (strtoupper($type)=='I25B+') { $arrcode = $this->barcode_i25($code, true); } if ($arrcode == false) { break; } $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) $arrcode['lightTB'] = 2; // TOP/BOTTOM light margin = x X-dim (non-spec.) - used for bearer bars break; } default: { $this->barcode_array = false; } } $this->barcode_array = $arrcode; } /** * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. */ protected function barcode_code39($code, $extended=false, $checksum=false) { $chr['0'] = '111221211'; $chr['1'] = '211211112'; $chr['2'] = '112211112'; $chr['3'] = '212211111'; $chr['4'] = '111221112'; $chr['5'] = '211221111'; $chr['6'] = '112221111'; $chr['7'] = '111211212'; $chr['8'] = '211211211'; $chr['9'] = '112211211'; $chr['A'] = '211112112'; $chr['B'] = '112112112'; $chr['C'] = '212112111'; $chr['D'] = '111122112'; $chr['E'] = '211122111'; $chr['F'] = '112122111'; $chr['G'] = '111112212'; $chr['H'] = '211112211'; $chr['I'] = '112112211'; $chr['J'] = '111122211'; $chr['K'] = '211111122'; $chr['L'] = '112111122'; $chr['M'] = '212111121'; $chr['N'] = '111121122'; $chr['O'] = '211121121'; $chr['P'] = '112121121'; $chr['Q'] = '111111222'; $chr['R'] = '211111221'; $chr['S'] = '112111221'; $chr['T'] = '111121221'; $chr['U'] = '221111112'; $chr['V'] = '122111112'; $chr['W'] = '222111111'; $chr['X'] = '121121112'; $chr['Y'] = '221121111'; $chr['Z'] = '122121111'; $chr['-'] = '121111212'; $chr['.'] = '221111211'; $chr[' '] = '122111211'; $chr['$'] = '121212111'; $chr['/'] = '121211121'; $chr['+'] = '121112121'; $chr['%'] = '111212121'; $chr['*'] = '121121211'; $code = strtoupper($code); if ($extended) { // extended mode $code = $this->encode_code39_ext($code); } if ($code === false) { return false; } if ($checksum) { // checksum $checkdigit = $this->checksum_code39($code); $code .= $checkdigit ; } // add start and stop codes $code = '*'.$code.'*'; $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $k = 0; $clen = strlen($code); for ($i = 0; $i < $clen; ++$i) { $char = $code[$i]; if(!isset($chr[$char])) { // invalid character return false; } for ($j = 0; $j < 9; ++$j) { if (($j % 2) == 0) { $t = true; // bar } else { $t = false; // space } $x = $chr[$char][$j]; if ($x == 2) { $w = $this->print_ratio; } else { $w = 1; } $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; } $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0); $bararray['maxw'] += 1; ++$k; } $bararray['checkdigit'] = $checkdigit; return $bararray; } /** * Encode a string to be used for CODE 39 Extended mode. */ protected function encode_code39_ext($code) { $encode = array( chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C', chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G', chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K', chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O', chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S', chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W', chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A', chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E', chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C', chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G', chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K', chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O', chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3', chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7', chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F', chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J', chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C', chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G', chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K', chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O', chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S', chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W', chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K', chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O', chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C', chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G', chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K', chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O', chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S', chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W', chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P', chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T'); $code_ext = ''; $clen = strlen($code); for ($i = 0 ; $i < $clen; ++$i) { if (ord($code[$i]) > 127) { return false; } $code_ext .= $encode[$code[$i]]; } return $code_ext; } /** * Calculate CODE 39 checksum (modulo 43). */ protected function checksum_code39($code) { $chars = array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%'); $sum = 0; $clen = strlen($code); for ($i = 0 ; $i < $clen; ++$i) { $k = array_keys($chars, $code[$i]); $sum += $k[0]; } $j = ($sum % 43); return $chars[$j]; } /** * CODE 93 - USS-93 * Compact code similar to Code 39 */ protected function barcode_code93($code) { $chr['0'] = '131112'; $chr['1'] = '111213'; $chr['2'] = '111312'; $chr['3'] = '111411'; $chr['4'] = '121113'; $chr['5'] = '121212'; $chr['6'] = '121311'; $chr['7'] = '111114'; $chr['8'] = '131211'; $chr['9'] = '141111'; $chr['A'] = '211113'; $chr['B'] = '211212'; $chr['C'] = '211311'; $chr['D'] = '221112'; $chr['E'] = '221211'; $chr['F'] = '231111'; $chr['G'] = '112113'; $chr['H'] = '112212'; $chr['I'] = '112311'; $chr['J'] = '122112'; $chr['K'] = '132111'; $chr['L'] = '111123'; $chr['M'] = '111222'; $chr['N'] = '111321'; $chr['O'] = '121122'; $chr['P'] = '131121'; $chr['Q'] = '212112'; $chr['R'] = '212211'; $chr['S'] = '211122'; $chr['T'] = '211221'; $chr['U'] = '221121'; $chr['V'] = '222111'; $chr['W'] = '112122'; $chr['X'] = '112221'; $chr['Y'] = '122121'; $chr['Z'] = '123111'; $chr['-'] = '121131'; $chr['.'] = '311112'; $chr[' '] = '311211'; $chr['$'] = '321111'; $chr['/'] = '112131'; $chr['+'] = '113121'; $chr['%'] = '211131'; $chr[128] = '121221'; // ($) $chr[129] = '311121'; // (/) $chr[130] = '122211'; // (+) $chr[131] = '312111'; // (%) $chr['*'] = '111141'; $code = strtoupper($code); $encode = array( chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C', chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G', chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K', chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O', chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S', chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W', chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A', chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E', chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C', chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G', chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K', chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O', chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3', chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7', chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F', chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J', chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C', chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G', chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K', chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O', chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S', chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W', chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K', chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O', chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C', chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G', chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K', chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O', chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S', chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W', chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P', chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T'); $code_ext = ''; $clen = strlen($code); for ($i = 0 ; $i < $clen; ++$i) { if (ord($code[$i]) > 127) { return false; } $code_ext .= $encode[$code[$i]]; } // checksum $checkdigit = $this->checksum_code93($code); $code .= $checkdigit ; // add start and stop codes $code = '*'.$code.'*'; $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $k = 0; $clen = strlen($code); for ($i = 0; $i < $clen; ++$i) { $char = $code[$i]; if(!isset($chr[$char])) { // invalid character return false; } for ($j = 0; $j < 6; ++$j) { if (($j % 2) == 0) { $t = true; // bar } else { $t = false; // space } $w = $chr[$char][$j]; $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; } } $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0); $bararray['maxw'] += 1; ++$k; $bararray['checkdigit'] = $checkdigit; return $bararray; } /** * Calculate CODE 93 checksum (modulo 47). */ protected function checksum_code93($code) { $chars = array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%'); // translate special characters $code = strtr($code, chr(128).chr(129).chr(130).chr(131), '$/+%'); $len = strlen($code); // calculate check digit C $p = 1; $check = 0; for ($i = ($len - 1); $i >= 0; --$i) { $k = array_keys($chars, $code[$i]); $check += ($k[0] * $p); ++$p; if ($p > 20) { $p = 1; } } $check %= 47; $c = $chars[$check]; $code .= $c; // calculate check digit K $p = 1; $check = 0; for ($i = $len; $i >= 0; --$i) { $k = array_keys($chars, $code[$i]); $check += ($k[0] * $p); ++$p; if ($p > 15) { $p = 1; } } $check %= 47; $k = $chars[$check]; return $c.$k; } /** * Checksum for standard 2 of 5 barcodes. */ protected function checksum_s25($code) { $len = strlen($code); $sum = 0; for ($i = 0; $i < $len; $i+=2) { $sum += $code[$i]; } $sum *= 3; for ($i = 1; $i < $len; $i+=2) { $sum += ($code[$i]); } $r = $sum % 10; if($r > 0) { $r = (10 - $r); } return $r; } /** * MSI. * Variation of Plessey code, with similar applications * Contains digits (0 to 9) and encodes the data only in the width of bars. */ protected function barcode_msi($code, $checksum=false) { $chr['0'] = '100100100100'; $chr['1'] = '100100100110'; $chr['2'] = '100100110100'; $chr['3'] = '100100110110'; $chr['4'] = '100110100100'; $chr['5'] = '100110100110'; $chr['6'] = '100110110100'; $chr['7'] = '100110110110'; $chr['8'] = '110100100100'; $chr['9'] = '110100100110'; $chr['A'] = '110100110100'; $chr['B'] = '110100110110'; $chr['C'] = '110110100100'; $chr['D'] = '110110100110'; $chr['E'] = '110110110100'; $chr['F'] = '110110110110'; if ($checksum) { // add checksum $clen = strlen($code); $p = 2; $check = 0; for ($i = ($clen - 1); $i >= 0; --$i) { $check += (hexdec($code[$i]) * $p); ++$p; if ($p > 7) { $p = 2; } } $check %= 11; if ($check > 0) { $check = 11 - $check; } $code .= $check; $checkdigit = $check; } $seq = '110'; // left guard $clen = strlen($code); for ($i = 0; $i < $clen; ++$i) { $digit = $code[$i]; if (!isset($chr[$digit])) { // invalid character return false; } $seq .= $chr[$digit]; } $seq .= '1001'; // right guard $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $bararray['checkdigit'] = $checkdigit; return $this->binseq_to_array($seq, $bararray); } /** * Standard 2 of 5 barcodes. * Used in airline ticket marking, photofinishing * Contains digits (0 to 9) and encodes the data only in the width of bars. */ protected function barcode_s25($code, $checksum=false) { $chr['0'] = '10101110111010'; $chr['1'] = '11101010101110'; $chr['2'] = '10111010101110'; $chr['3'] = '11101110101010'; $chr['4'] = '10101110101110'; $chr['5'] = '11101011101010'; $chr['6'] = '10111011101010'; $chr['7'] = '10101011101110'; $chr['8'] = '10101110111010'; $chr['9'] = '10111010111010'; if ($checksum) { // add checksum $checkdigit = $this->checksum_s25($code); $code .= $checkdigit ; } if((strlen($code) % 2) != 0) { // add leading zero if code-length is odd $code = '0'.$code; } $seq = '11011010'; $clen = strlen($code); for ($i = 0; $i < $clen; ++$i) { $digit = $code[$i]; if (!isset($chr[$digit])) { // invalid character return false; } $seq .= $chr[$digit]; } $seq .= '1101011'; $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $bararray['checkdigit'] = $checkdigit; return $this->binseq_to_array($seq, $bararray); } /** * Convert binary barcode sequence to barcode array */ protected function binseq_to_array($seq, $bararray) { $len = strlen($seq); $w = 0; $k = 0; for ($i = 0; $i < $len; ++$i) { $w += 1; if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq[$i] != $seq[($i+1)]))) { if ($seq[$i] == '1') { $t = true; // bar } else { $t = false; // space } $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; $w = 0; } } return $bararray; } /** * Interleaved 2 of 5 barcodes. * Compact numeric code, widely used in industry, air cargo * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces. */ protected function barcode_i25($code, $checksum=false) { $chr['0'] = '11221'; $chr['1'] = '21112'; $chr['2'] = '12112'; $chr['3'] = '22111'; $chr['4'] = '11212'; $chr['5'] = '21211'; $chr['6'] = '12211'; $chr['7'] = '11122'; $chr['8'] = '21121'; $chr['9'] = '12121'; $chr['A'] = '11'; $chr['Z'] = '21'; if ($checksum) { // add checksum $checkdigit = $this->checksum_s25($code); $code .= $checkdigit ; } if((strlen($code) % 2) != 0) { // add leading zero if code-length is odd $code = '0'.$code; } // add start and stop codes $code = 'AA'.strtolower($code).'ZA'; $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $k = 0; $clen = strlen($code); for ($i = 0; $i < $clen; $i = ($i + 2)) { $char_bar = $code[$i]; $char_space = $code[$i+1]; if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) { // invalid character return false; } // create a bar-space sequence $seq = ''; $chrlen = strlen($chr[$char_bar]); for ($s = 0; $s < $chrlen; $s++){ $seq .= $chr[$char_bar][$s] . $chr[$char_space][$s]; } $seqlen = strlen($seq); for ($j = 0; $j < $seqlen; ++$j) { if (($j % 2) == 0) { $t = true; // bar } else { $t = false; // space } $x = $seq[$j]; if ($x == 2) { $w = $this->print_ratio; } else { $w = 1; } $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; } } $bararray['checkdigit'] = $checkdigit; return $bararray; } /** * C128 barcodes. * Very capable code, excellent density, high reliability; in very wide use world-wide */ protected function barcode_c128($code, $type='B', $ean=false) { $chr = array( '212222', /* 00 */ '222122', /* 01 */ '222221', /* 02 */ '121223', /* 03 */ '121322', /* 04 */ '131222', /* 05 */ '122213', /* 06 */ '122312', /* 07 */ '132212', /* 08 */ '221213', /* 09 */ '221312', /* 10 */ '231212', /* 11 */ '112232', /* 12 */ '122132', /* 13 */ '122231', /* 14 */ '113222', /* 15 */ '123122', /* 16 */ '123221', /* 17 */ '223211', /* 18 */ '221132', /* 19 */ '221231', /* 20 */ '213212', /* 21 */ '223112', /* 22 */ '312131', /* 23 */ '311222', /* 24 */ '321122', /* 25 */ '321221', /* 26 */ '312212', /* 27 */ '322112', /* 28 */ '322211', /* 29 */ '212123', /* 30 */ '212321', /* 31 */ '232121', /* 32 */ '111323', /* 33 */ '131123', /* 34 */ '131321', /* 35 */ '112313', /* 36 */ '132113', /* 37 */ '132311', /* 38 */ '211313', /* 39 */ '231113', /* 40 */ '231311', /* 41 */ '112133', /* 42 */ '112331', /* 43 */ '132131', /* 44 */ '113123', /* 45 */ '113321', /* 46 */ '133121', /* 47 */ '313121', /* 48 */ '211331', /* 49 */ '231131', /* 50 */ '213113', /* 51 */ '213311', /* 52 */ '213131', /* 53 */ '311123', /* 54 */ '311321', /* 55 */ '331121', /* 56 */ '312113', /* 57 */ '312311', /* 58 */ '332111', /* 59 */ '314111', /* 60 */ '221411', /* 61 */ '431111', /* 62 */ '111224', /* 63 */ '111422', /* 64 */ '121124', /* 65 */ '121421', /* 66 */ '141122', /* 67 */ '141221', /* 68 */ '112214', /* 69 */ '112412', /* 70 */ '122114', /* 71 */ '122411', /* 72 */ '142112', /* 73 */ '142211', /* 74 */ '241211', /* 75 */ '221114', /* 76 */ '413111', /* 77 */ '241112', /* 78 */ '134111', /* 79 */ '111242', /* 80 */ '121142', /* 81 */ '121241', /* 82 */ '114212', /* 83 */ '124112', /* 84 */ '124211', /* 85 */ '411212', /* 86 */ '421112', /* 87 */ '421211', /* 88 */ '212141', /* 89 */ '214121', /* 90 */ '412121', /* 91 */ '111143', /* 92 */ '111341', /* 93 */ '131141', /* 94 */ '114113', /* 95 */ '114311', /* 96 */ '411113', /* 97 */ '411311', /* 98 */ '113141', /* 99 */ '114131', /* 100 */ '311141', /* 101 */ '411131', /* 102 */ '211412', /* 103 START A */ '211214', /* 104 START B */ '211232', /* 105 START C */ '233111', /* STOP */ '200000' /* END */ ); $keys = ''; switch(strtoupper($type)) { case 'A': { $startid = 103; $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'; for ($i = 0; $i < 32; ++$i) { $keys .= chr($i); } break; } case 'B': { $startid = 104; $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127); break; } case 'C': { $startid = 105; $keys = ''; if ((strlen($code) % 2) != 0) { // The length of barcode value must be even ($code). You must pad the number with zeros return false; } for ($i = 0; $i <= 99; ++$i) { $keys .= chr($i); } $new_code = ''; $hclen = (strlen($code) / 2); for ($i = 0; $i < $hclen; ++$i) { $new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)})); } $code = $new_code; break; } default: { return false; } } // calculate check character $sum = $startid; if ($ean) { $code = chr(102) . $code; } // Add FNC 1 - which identifies it as EAN-128 $clen = strlen($code); for ($i = 0; $i < $clen; ++$i) { if ($ean && $i==0) { $sum += 102; } else { $sum += (strpos($keys, $code[$i]) * ($i+1)); } } $check = ($sum % 103); $checkdigit = $check ; // add start, check and stop codes $code = chr($startid).$code.chr($check).chr(106).chr(107); $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $k = 0; $len = strlen($code); for ($i = 0; $i < $len; ++$i) { $ck = strpos($keys, $code[$i]); if (($i == 0) || ($ean && $i==1) | ($i > ($len-4))) { $char_num = ord($code[$i]); $seq = $chr[$char_num]; } elseif(($ck >= 0) AND isset($chr[$ck])) { $seq = $chr[$ck]; } else { // invalid character return false; } for ($j = 0; $j < 6; ++$j) { if (($j % 2) == 0) { $t = true; // bar } else { $t = false; // space } $w = $seq[$j]; $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; } } $bararray['checkdigit'] = $checkdigit; return $bararray; } /** * EAN13 and UPC-A barcodes. * EAN13: European Article Numbering international retail product code * UPC-A: Universal product code seen on almost all retail products in the USA and Canada * UPC-E: Short version of UPC symbol */ protected function barcode_eanupc($code, $len=13) { $upce = false; $checkdigit = false; if ($len == 6) { $len = 12; // UPC-A $upce = true; // UPC-E mode } $data_len = $len - 1; //Padding $code = str_pad($code, $data_len, '0', STR_PAD_LEFT); $code_len = strlen($code); // calculate check digit $sum_a = 0; for ($i = 1; $i < $data_len; $i+=2) { $sum_a += $code[$i]; } if ($len > 12) { $sum_a *= 3; } $sum_b = 0; for ($i = 0; $i < $data_len; $i+=2) { $sum_b += ($code[$i]); } if ($len < 13) { $sum_b *= 3; } $r = ($sum_a + $sum_b) % 10; if($r > 0) { $r = (10 - $r); } if ($code_len == $data_len) { // add check digit $code .= $r; $checkdigit = $r; } elseif ($r !== intval($code[$data_len])) { // wrong checkdigit return false; } if ($len == 12) { // UPC-A $code = '0'.$code; ++$len; } if ($upce) { // convert UPC-A to UPC-E $tmp = substr($code, 4, 3); $prod_code = intval(substr($code,7,5)); // product code $invalid_upce = false; if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) { // manufacturer code ends in 000, 100, or 200 $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1); if ($prod_code > 999) { $invalid_upce = true; } } else { $tmp = substr($code, 5, 2); if ($tmp == '00') { // manufacturer code ends in 00 $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3'; if ($prod_code > 99) { $invalid_upce = true; } } else { $tmp = substr($code, 6, 1); if ($tmp == '0') { // manufacturer code ends in 0 $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4'; if ($prod_code > 9) { $invalid_upce = true; } } else { // manufacturer code does not end in zero $upce_code = substr($code, 2, 5).substr($code, 11, 1); if ($prod_code > 9) { $invalid_upce = true; } } } } if ($invalid_upce) { die("Error - UPC-A cannot produce a valid UPC-E barcode"); } // Error generating a UPCE code } //Convert digits to bars $codes = array( 'A'=>array( // left odd parity '0'=>'0001101', '1'=>'0011001', '2'=>'0010011', '3'=>'0111101', '4'=>'0100011', '5'=>'0110001', '6'=>'0101111', '7'=>'0111011', '8'=>'0110111', '9'=>'0001011'), 'B'=>array( // left even parity '0'=>'0100111', '1'=>'0110011', '2'=>'0011011', '3'=>'0100001', '4'=>'0011101', '5'=>'0111001', '6'=>'0000101', '7'=>'0010001', '8'=>'0001001', '9'=>'0010111'), 'C'=>array( // right '0'=>'1110010', '1'=>'1100110', '2'=>'1101100', '3'=>'1000010', '4'=>'1011100', '5'=>'1001110', '6'=>'1010000', '7'=>'1000100', '8'=>'1001000', '9'=>'1110100') ); $parities = array( '0'=>array('A','A','A','A','A','A'), '1'=>array('A','A','B','A','B','B'), '2'=>array('A','A','B','B','A','B'), '3'=>array('A','A','B','B','B','A'), '4'=>array('A','B','A','A','B','B'), '5'=>array('A','B','B','A','A','B'), '6'=>array('A','B','B','B','A','A'), '7'=>array('A','B','A','B','A','B'), '8'=>array('A','B','A','B','B','A'), '9'=>array('A','B','B','A','B','A') ); $upce_parities = array(); $upce_parities[0] = array( '0'=>array('B','B','B','A','A','A'), '1'=>array('B','B','A','B','A','A'), '2'=>array('B','B','A','A','B','A'), '3'=>array('B','B','A','A','A','B'), '4'=>array('B','A','B','B','A','A'), '5'=>array('B','A','A','B','B','A'), '6'=>array('B','A','A','A','B','B'), '7'=>array('B','A','B','A','B','A'), '8'=>array('B','A','B','A','A','B'), '9'=>array('B','A','A','B','A','B') ); $upce_parities[1] = array( '0'=>array('A','A','A','B','B','B'), '1'=>array('A','A','B','A','B','B'), '2'=>array('A','A','B','B','A','B'), '3'=>array('A','A','B','B','B','A'), '4'=>array('A','B','A','A','B','B'), '5'=>array('A','B','B','A','A','B'), '6'=>array('A','B','B','B','A','A'), '7'=>array('A','B','A','B','A','B'), '8'=>array('A','B','A','B','B','A'), '9'=>array('A','B','B','A','B','A') ); $k = 0; $seq = '101'; // left guard bar if ($upce) { $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $p = $upce_parities[$code{1}][$r]; for ($i = 0; $i < 6; ++$i) { $seq .= $codes[$p[$i]][$upce_code[$i]]; } $seq .= '010101'; // right guard bar } else { $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $half_len = ceil($len / 2); if ($len == 8) { for ($i = 0; $i < $half_len; ++$i) { $seq .= $codes['A'][$code[$i]]; } } else { $p = $parities[$code{0}]; for ($i = 1; $i < $half_len; ++$i) { $seq .= $codes[$p[$i-1]][$code[$i]]; } } $seq .= '01010'; // center guard bar for ($i = $half_len; $i < $len; ++$i) { $seq .= $codes['C'][$code[$i]]; } $seq .= '101'; // right guard bar } $clen = strlen($seq); $w = 0; for ($i = 0; $i < $clen; ++$i) { $w += 1; if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq[$i] != $seq[($i+1)]))) { if ($seq[$i] == '1') { $t = true; // bar } else { $t = false; // space } $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; $w = 0; } } $bararray['checkdigit'] = $checkdigit; return $bararray; } /** * UPC-Based Extentions * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers * 5-Digit Ext.: Used to mark suggested retail price of books */ protected function barcode_eanext($code, $len=5) { //Padding $code = str_pad($code, $len, '0', STR_PAD_LEFT); // calculate check digit if ($len == 2) { $r = $code % 4; } elseif ($len == 5) { $r = (3 * ($code{0} + $code{2} + $code{4})) + (9 * ($code{1} + $code{3})); $r %= 10; } else { return false; } //Convert digits to bars $codes = array( 'A'=>array( // left odd parity '0'=>'0001101', '1'=>'0011001', '2'=>'0010011', '3'=>'0111101', '4'=>'0100011', '5'=>'0110001', '6'=>'0101111', '7'=>'0111011', '8'=>'0110111', '9'=>'0001011'), 'B'=>array( // left even parity '0'=>'0100111', '1'=>'0110011', '2'=>'0011011', '3'=>'0100001', '4'=>'0011101', '5'=>'0111001', '6'=>'0000101', '7'=>'0010001', '8'=>'0001001', '9'=>'0010111') ); $parities = array(); $parities[2] = array( '0'=>array('A','A'), '1'=>array('A','B'), '2'=>array('B','A'), '3'=>array('B','B') ); $parities[5] = array( '0'=>array('B','B','A','A','A'), '1'=>array('B','A','B','A','A'), '2'=>array('B','A','A','B','A'), '3'=>array('B','A','A','A','B'), '4'=>array('A','B','B','A','A'), '5'=>array('A','A','B','B','A'), '6'=>array('A','A','A','B','B'), '7'=>array('A','B','A','B','A'), '8'=>array('A','B','A','A','B'), '9'=>array('A','A','B','A','B') ); $p = $parities[$len][$r]; $seq = '1011'; // left guard bar $seq .= $codes[$p[0]][$code{0}]; for ($i = 1; $i < $len; ++$i) { $seq .= '01'; // separator $seq .= $codes[$p[$i]][$code[$i]]; } $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); return $this->binseq_to_array($seq, $bararray); } /** * POSTNET and PLANET barcodes. * Used by U.S. Postal Service for automated mail sorting */ protected function barcode_postnet($code, $planet=false) { // bar lenght if ($planet) { $barlen = Array( 0 => Array(1,1,2,2,2), 1 => Array(2,2,2,1,1), 2 => Array(2,2,1,2,1), 3 => Array(2,2,1,1,2), 4 => Array(2,1,2,2,1), 5 => Array(2,1,2,1,2), 6 => Array(2,1,1,2,2), 7 => Array(1,2,2,2,1), 8 => Array(1,2,2,1,2), 9 => Array(1,2,1,2,2) ); } else { $barlen = Array( 0 => Array(2,2,1,1,1), 1 => Array(1,1,1,2,2), 2 => Array(1,1,2,1,2), 3 => Array(1,1,2,2,1), 4 => Array(1,2,1,1,2), 5 => Array(1,2,1,2,1), 6 => Array(1,2,2,1,1), 7 => Array(2,1,1,1,2), 8 => Array(2,1,1,2,1), 9 => Array(2,1,2,1,1) ); } $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 5, 'bcode' => array()); $k = 0; $code = str_replace('-', '', $code); $code = str_replace(' ', '', $code); $len = strlen($code); // calculate checksum $sum = 0; for ($i = 0; $i < $len; ++$i) { $sum += intval($code[$i]); } $chkd = ($sum % 10); if($chkd > 0) { $chkd = (10 - $chkd); } $code .= $chkd; $checkdigit = $chkd; $len = strlen($code); // start bar $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 5, 'p' => 0); $bararray['bcode'][$k++] = array('t' => 0, 'w' => $this->gapwidth , 'h' => 5, 'p' => 0); $bararray['maxw'] += (1 + $this->gapwidth ); for ($i = 0; $i < $len; ++$i) { for ($j = 0; $j < 5; ++$j) { $bh = $barlen[$code[$i]][$j]; if ($bh == 2) { $h = 5; $p = 0; } else { $h = 2; $p = 3; } $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); $bararray['bcode'][$k++] = array('t' => 0, 'w' => $this->gapwidth , 'h' => 2, 'p' => 0); $bararray['maxw'] += (1 + $this->gapwidth ); } } // end bar $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 5, 'p' => 0); $bararray['maxw'] += 1; $bararray['checkdigit'] = $checkdigit; return $bararray; } /** * RM4SCC - CBC - KIX * RM4SCC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index) * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service. */ protected function barcode_rm4scc($code, $kix=false) { $notkix = !$kix; // bar mode // 1 = pos 1, length 2 // 2 = pos 1, length 3 // 3 = pos 2, length 1 // 4 = pos 2, length 2 $barmode = array( '0' => array(3,3,2,2), '1' => array(3,4,1,2), '2' => array(3,4,2,1), '3' => array(4,3,1,2), '4' => array(4,3,2,1), '5' => array(4,4,1,1), '6' => array(3,1,4,2), '7' => array(3,2,3,2), '8' => array(3,2,4,1), '9' => array(4,1,3,2), 'A' => array(4,1,4,1), 'B' => array(4,2,3,1), 'C' => array(3,1,2,4), 'D' => array(3,2,1,4), 'E' => array(3,2,2,3), 'F' => array(4,1,1,4), 'G' => array(4,1,2,3), 'H' => array(4,2,1,3), 'I' => array(1,3,4,2), 'J' => array(1,4,3,2), 'K' => array(1,4,4,1), 'L' => array(2,3,3,2), 'M' => array(2,3,4,1), 'N' => array(2,4,3,1), 'O' => array(1,3,2,4), 'P' => array(1,4,1,4), 'Q' => array(1,4,2,3), 'R' => array(2,3,1,4), 'S' => array(2,3,2,3), 'T' => array(2,4,1,3), 'U' => array(1,1,4,4), 'V' => array(1,2,3,4), 'W' => array(1,2,4,3), 'X' => array(2,1,3,4), 'Y' => array(2,1,4,3), 'Z' => array(2,2,3,3) ); $code = strtoupper($code); $len = strlen($code); $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => $this->daft['F'], 'bcode' => array()); if ($notkix) { // table for checksum calculation (row,col) $checktable = array( '0' => array(1,1), '1' => array(1,2), '2' => array(1,3), '3' => array(1,4), '4' => array(1,5), '5' => array(1,0), '6' => array(2,1), '7' => array(2,2), '8' => array(2,3), '9' => array(2,4), 'A' => array(2,5), 'B' => array(2,0), 'C' => array(3,1), 'D' => array(3,2), 'E' => array(3,3), 'F' => array(3,4), 'G' => array(3,5), 'H' => array(3,0), 'I' => array(4,1), 'J' => array(4,2), 'K' => array(4,3), 'L' => array(4,4), 'M' => array(4,5), 'N' => array(4,0), 'O' => array(5,1), 'P' => array(5,2), 'Q' => array(5,3), 'R' => array(5,4), 'S' => array(5,5), 'T' => array(5,0), 'U' => array(0,1), 'V' => array(0,2), 'W' => array(0,3), 'X' => array(0,4), 'Y' => array(0,5), 'Z' => array(0,0) ); $row = 0; $col = 0; for ($i = 0; $i < $len; ++$i) { $row += $checktable[$code[$i]][0]; $col += $checktable[$code[$i]][1]; } $row %= 6; $col %= 6; $chk = array_keys($checktable, array($row,$col)); $code .= $chk[0]; $bararray['checkdigit'] = $chk[0]; ++$len; } $k = 0; if ($notkix) { // start bar $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $this->daft['A'] , 'p' => 0); $bararray['bcode'][$k++] = array('t' => 0, 'w' => $this->gapwidth , 'h' => $this->daft['A'] , 'p' => 0); $bararray['maxw'] += (1 + $this->gapwidth) ; } for ($i = 0; $i < $len; ++$i) { for ($j = 0; $j < 4; ++$j) { switch ($barmode[$code[$i]][$j]) { case 1: { // ascender (A) $p = 0; $h = $this->daft['A']; break; } case 2: { // full bar (F) $p = 0; $h = $this->daft['F']; break; } case 3: { // tracker (T) $p = ($this->daft['F'] - $this->daft['T'])/2; $h = $this->daft['T']; break; } case 4: { // descender (D) $p = $this->daft['F'] - $this->daft['D']; $h = $this->daft['D']; break; } } $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p); $bararray['bcode'][$k++] = array('t' => 0, 'w' => $this->gapwidth, 'h' => 2, 'p' => 0); $bararray['maxw'] += (1 + $this->gapwidth) ; } } if ($notkix) { // stop bar $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $this->daft['F'], 'p' => 0); $bararray['maxw'] += 1; } return $bararray; } /** * CODABAR barcodes. * Older code often used in library systems, sometimes in blood banks */ protected function barcode_codabar($code) { $chr = array( '0' => '11111221', '1' => '11112211', '2' => '11121121', '3' => '22111111', '4' => '11211211', '5' => '21111211', '6' => '12111121', '7' => '12112111', '8' => '12211111', '9' => '21121111', '-' => '11122111', '$' => '11221111', ':' => '21112121', '/' => '21211121', '.' => '21212111', '+' => '11222221', 'A' => '11221211', 'B' => '12121121', 'C' => '11121221', 'D' => '11122211' ); $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $k = 0; $w = 0; $seq = ''; $code = strtoupper($code); $len = strlen($code); for ($i = 0; $i < $len; ++$i) { if (!isset($chr[$code[$i]])) { return false; } $seq = $chr[$code[$i]]; for ($j = 0; $j < 8; ++$j) { if (($j % 2) == 0) { $t = true; // bar } else { $t = false; // space } $x = $seq[$j]; if ($x == 2) { $w = $this->print_ratio; } else { $w = 1; } $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; } } return $bararray; } /** * CODE11 barcodes. * Used primarily for labeling telecommunications equipment */ protected function barcode_code11($code) { $chr = array( '0' => '111121', '1' => '211121', '2' => '121121', '3' => '221111', '4' => '112121', '5' => '212111', '6' => '122111', '7' => '111221', '8' => '211211', '9' => '211111', '-' => '112111', 'S' => '112211' ); $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array()); $k = 0; $w = 0; $seq = ''; $len = strlen($code); // calculate check digit C $p = 1; $check = 0; for ($i = ($len - 1); $i >= 0; --$i) { $digit = $code[$i]; if ($digit == '-') { $dval = 10; } else { $dval = intval($digit); } $check += ($dval * $p); ++$p; if ($p > 10) { $p = 1; } } $check %= 11; if ($check == 10) { $check = '-'; } $code .= $check; $checkdigit = $check; if ($len > 10) { // calculate check digit K $p = 1; $check = 0; for ($i = $len; $i >= 0; --$i) { $digit = $code[$i]; if ($digit == '-') { $dval = 10; } else { $dval = intval($digit); } $check += ($dval * $p); ++$p; if ($p > 9) { $p = 1; } } $check %= 11; $code .= $check; $checkdigit .= $check; ++$len; } $code = 'S'.$code.'S'; $len += 3; for ($i = 0; $i < $len; ++$i) { if (!isset($chr[$code[$i]])) { return false; } $seq = $chr[$code[$i]]; for ($j = 0; $j < 6; ++$j) { if (($j % 2) == 0) { $t = true; // bar } else { $t = false; // space } $x = $seq[$j]; if ($x == 2) { $w = $this->print_ratio; } else { $w = 1; } $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0); $bararray['maxw'] += $w; ++$k; } } $bararray['checkdigit'] = $checkdigit; return $bararray; } /** * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200 * (requires PHP bcmath extension) * Intelligent Mail barcode is a 65-bar code for use on mail in the United States. * The fields are described as follows: