PageRenderTime 68ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/tcpdf/barcodes.php

http://github.com/masom/Chowly
PHP | 1965 lines | 1591 code | 37 blank | 337 comment | 195 complexity | 9f0f79a92e025acfd5aef0c09b0ea736 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. //============================================================+
  3. // File name : barcodes.php
  4. // Version : 1.0.012
  5. // Begin : 2008-06-09
  6. // Last Update : 2010-12-16
  7. // Author : Nicola Asuni - Tecnick.com S.r.l - Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
  8. // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
  9. // -------------------------------------------------------------------
  10. // Copyright (C) 2008-2010 Nicola Asuni - Tecnick.com S.r.l.
  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 : PHP class to creates array representations for
  31. // common 1D barcodes to be used with TCPDF.
  32. //
  33. //============================================================+
  34. /**
  35. * @file
  36. * PHP class to creates array representations for common 1D barcodes to be used with TCPDF.
  37. * @package com.tecnick.tcpdf
  38. * @author Nicola Asuni
  39. * @version 1.0.012
  40. */
  41. /**
  42. * @class TCPDFBarcode
  43. * PHP class to creates array representations for common 1D barcodes to be used with TCPDF (http://www.tcpdf.org).<br>
  44. * @package com.tecnick.tcpdf
  45. * @version 1.0.012
  46. * @author Nicola Asuni
  47. */
  48. class TCPDFBarcode {
  49. /**
  50. * Array representation of barcode.
  51. * @protected
  52. */
  53. protected $barcode_array;
  54. /**
  55. * This is the class constructor.
  56. * Return an array representations for common 1D barcodes:<ul>
  57. * <li>$arrcode['code'] code to be printed on text label</li>
  58. * <li>$arrcode['maxh'] max bar height</li>
  59. * <li>$arrcode['maxw'] max bar width</li>
  60. * <li>$arrcode['bcode'][$k] single bar or space in $k position</li>
  61. * <li>$arrcode['bcode'][$k]['t'] bar type: true = bar, false = space.</li>
  62. * <li>$arrcode['bcode'][$k]['w'] bar width in units.</li>
  63. * <li>$arrcode['bcode'][$k]['h'] bar height in units.</li>
  64. * <li>$arrcode['bcode'][$k]['p'] bar top position (0 = top, 1 = middle)</li></ul>
  65. * @param $code (string) code to print
  66. * @param $type (string) type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul>
  67. */
  68. public function __construct($code, $type) {
  69. $this->setBarcode($code, $type);
  70. }
  71. /**
  72. * Return an array representations of barcode.
  73. * @return array
  74. */
  75. public function getBarcodeArray() {
  76. return $this->barcode_array;
  77. }
  78. /**
  79. * Set the barcode.
  80. * @param $code (string) code to print
  81. * @param $type (string) type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul>
  82. * @return array
  83. */
  84. public function setBarcode($code, $type) {
  85. switch (strtoupper($type)) {
  86. case 'C39': { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
  87. $arrcode = $this->barcode_code39($code, false, false);
  88. break;
  89. }
  90. case 'C39+': { // CODE 39 with checksum
  91. $arrcode = $this->barcode_code39($code, false, true);
  92. break;
  93. }
  94. case 'C39E': { // CODE 39 EXTENDED
  95. $arrcode = $this->barcode_code39($code, true, false);
  96. break;
  97. }
  98. case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM
  99. $arrcode = $this->barcode_code39($code, true, true);
  100. break;
  101. }
  102. case 'C93': { // CODE 93 - USS-93
  103. $arrcode = $this->barcode_code93($code);
  104. break;
  105. }
  106. case 'S25': { // Standard 2 of 5
  107. $arrcode = $this->barcode_s25($code, false);
  108. break;
  109. }
  110. case 'S25+': { // Standard 2 of 5 + CHECKSUM
  111. $arrcode = $this->barcode_s25($code, true);
  112. break;
  113. }
  114. case 'I25': { // Interleaved 2 of 5
  115. $arrcode = $this->barcode_i25($code, false);
  116. break;
  117. }
  118. case 'I25+': { // Interleaved 2 of 5 + CHECKSUM
  119. $arrcode = $this->barcode_i25($code, true);
  120. break;
  121. }
  122. case 'C128A': { // CODE 128 A
  123. $arrcode = $this->barcode_c128($code, 'A');
  124. break;
  125. }
  126. case 'C128B': { // CODE 128 B
  127. $arrcode = $this->barcode_c128($code, 'B');
  128. break;
  129. }
  130. case 'C128C': { // CODE 128 C
  131. $arrcode = $this->barcode_c128($code, 'C');
  132. break;
  133. }
  134. case 'EAN2': { // 2-Digits UPC-Based Extention
  135. $arrcode = $this->barcode_eanext($code, 2);
  136. break;
  137. }
  138. case 'EAN5': { // 5-Digits UPC-Based Extention
  139. $arrcode = $this->barcode_eanext($code, 5);
  140. break;
  141. }
  142. case 'EAN8': { // EAN 8
  143. $arrcode = $this->barcode_eanupc($code, 8);
  144. break;
  145. }
  146. case 'EAN13': { // EAN 13
  147. $arrcode = $this->barcode_eanupc($code, 13);
  148. break;
  149. }
  150. case 'UPCA': { // UPC-A
  151. $arrcode = $this->barcode_eanupc($code, 12);
  152. break;
  153. }
  154. case 'UPCE': { // UPC-E
  155. $arrcode = $this->barcode_eanupc($code, 6);
  156. break;
  157. }
  158. case 'MSI': { // MSI (Variation of Plessey code)
  159. $arrcode = $this->barcode_msi($code, false);
  160. break;
  161. }
  162. case 'MSI+': { // MSI + CHECKSUM (modulo 11)
  163. $arrcode = $this->barcode_msi($code, true);
  164. break;
  165. }
  166. case 'POSTNET': { // POSTNET
  167. $arrcode = $this->barcode_postnet($code, false);
  168. break;
  169. }
  170. case 'PLANET': { // PLANET
  171. $arrcode = $this->barcode_postnet($code, true);
  172. break;
  173. }
  174. case 'RMS4CC': { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
  175. $arrcode = $this->barcode_rms4cc($code, false);
  176. break;
  177. }
  178. case 'KIX': { // KIX (Klant index - Customer index)
  179. $arrcode = $this->barcode_rms4cc($code, true);
  180. break;
  181. }
  182. case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
  183. $arrcode = $this->barcode_imb($code);
  184. break;
  185. }
  186. case 'CODABAR': { // CODABAR
  187. $arrcode = $this->barcode_codabar($code);
  188. break;
  189. }
  190. case 'CODE11': { // CODE 11
  191. $arrcode = $this->barcode_code11($code);
  192. break;
  193. }
  194. case 'PHARMA': { // PHARMACODE
  195. $arrcode = $this->barcode_pharmacode($code);
  196. break;
  197. }
  198. case 'PHARMA2T': { // PHARMACODE TWO-TRACKS
  199. $arrcode = $this->barcode_pharmacode2t($code);
  200. break;
  201. }
  202. default: {
  203. $this->barcode_array = false;
  204. $arrcode = false;
  205. break;
  206. }
  207. }
  208. $this->barcode_array = $arrcode;
  209. }
  210. /**
  211. * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
  212. * General-purpose code in very wide use world-wide
  213. * @param $code (string) code to represent.
  214. * @param $extended (boolean) if true uses the extended mode.
  215. * @param $checksum (boolean) if true add a checksum to the code.
  216. * @return array barcode representation.
  217. * @protected
  218. */
  219. protected function barcode_code39($code, $extended=false, $checksum=false) {
  220. $chr['0'] = '111221211';
  221. $chr['1'] = '211211112';
  222. $chr['2'] = '112211112';
  223. $chr['3'] = '212211111';
  224. $chr['4'] = '111221112';
  225. $chr['5'] = '211221111';
  226. $chr['6'] = '112221111';
  227. $chr['7'] = '111211212';
  228. $chr['8'] = '211211211';
  229. $chr['9'] = '112211211';
  230. $chr['A'] = '211112112';
  231. $chr['B'] = '112112112';
  232. $chr['C'] = '212112111';
  233. $chr['D'] = '111122112';
  234. $chr['E'] = '211122111';
  235. $chr['F'] = '112122111';
  236. $chr['G'] = '111112212';
  237. $chr['H'] = '211112211';
  238. $chr['I'] = '112112211';
  239. $chr['J'] = '111122211';
  240. $chr['K'] = '211111122';
  241. $chr['L'] = '112111122';
  242. $chr['M'] = '212111121';
  243. $chr['N'] = '111121122';
  244. $chr['O'] = '211121121';
  245. $chr['P'] = '112121121';
  246. $chr['Q'] = '111111222';
  247. $chr['R'] = '211111221';
  248. $chr['S'] = '112111221';
  249. $chr['T'] = '111121221';
  250. $chr['U'] = '221111112';
  251. $chr['V'] = '122111112';
  252. $chr['W'] = '222111111';
  253. $chr['X'] = '121121112';
  254. $chr['Y'] = '221121111';
  255. $chr['Z'] = '122121111';
  256. $chr['-'] = '121111212';
  257. $chr['.'] = '221111211';
  258. $chr[' '] = '122111211';
  259. $chr['$'] = '121212111';
  260. $chr['/'] = '121211121';
  261. $chr['+'] = '121112121';
  262. $chr['%'] = '111212121';
  263. $chr['*'] = '121121211';
  264. $code = strtoupper($code);
  265. if ($extended) {
  266. // extended mode
  267. $code = $this->encode_code39_ext($code);
  268. }
  269. if ($code === false) {
  270. return false;
  271. }
  272. if ($checksum) {
  273. // checksum
  274. $code .= $this->checksum_code39($code);
  275. }
  276. // add start and stop codes
  277. $code = '*'.$code.'*';
  278. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  279. $k = 0;
  280. $clen = strlen($code);
  281. for ($i = 0; $i < $clen; ++$i) {
  282. $char = $code{$i};
  283. if(!isset($chr[$char])) {
  284. // invalid character
  285. return false;
  286. }
  287. for ($j = 0; $j < 9; ++$j) {
  288. if (($j % 2) == 0) {
  289. $t = true; // bar
  290. } else {
  291. $t = false; // space
  292. }
  293. $w = $chr[$char]{$j};
  294. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  295. $bararray['maxw'] += $w;
  296. ++$k;
  297. }
  298. $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
  299. $bararray['maxw'] += 1;
  300. ++$k;
  301. }
  302. return $bararray;
  303. }
  304. /**
  305. * Encode a string to be used for CODE 39 Extended mode.
  306. * @param $code (string) code to represent.
  307. * @return encoded string.
  308. * @protected
  309. */
  310. protected function encode_code39_ext($code) {
  311. $encode = array(
  312. chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
  313. chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
  314. chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
  315. chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
  316. chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
  317. chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
  318. chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
  319. chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
  320. chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
  321. chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
  322. chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
  323. chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
  324. chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
  325. chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
  326. chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
  327. chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
  328. chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
  329. chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
  330. chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
  331. chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
  332. chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
  333. chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
  334. chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
  335. chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
  336. chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
  337. chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
  338. chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
  339. chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
  340. chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
  341. chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
  342. chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
  343. chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
  344. $code_ext = '';
  345. $clen = strlen($code);
  346. for ($i = 0 ; $i < $clen; ++$i) {
  347. if (ord($code{$i}) > 127) {
  348. return false;
  349. }
  350. $code_ext .= $encode[$code{$i}];
  351. }
  352. return $code_ext;
  353. }
  354. /**
  355. * Calculate CODE 39 checksum (modulo 43).
  356. * @param $code (string) code to represent.
  357. * @return char checksum.
  358. * @protected
  359. */
  360. protected function checksum_code39($code) {
  361. $chars = array(
  362. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  363. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  364. 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  365. 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
  366. $sum = 0;
  367. $clen = strlen($code);
  368. for ($i = 0 ; $i < $clen; ++$i) {
  369. $k = array_keys($chars, $code{$i});
  370. $sum += $k[0];
  371. }
  372. $j = ($sum % 43);
  373. return $chars[$j];
  374. }
  375. /**
  376. * CODE 93 - USS-93
  377. * Compact code similar to Code 39
  378. * @param $code (string) code to represent.
  379. * @return array barcode representation.
  380. * @protected
  381. */
  382. protected function barcode_code93($code) {
  383. $chr['0'] = '131112';
  384. $chr['1'] = '111213';
  385. $chr['2'] = '111312';
  386. $chr['3'] = '111411';
  387. $chr['4'] = '121113';
  388. $chr['5'] = '121212';
  389. $chr['6'] = '121311';
  390. $chr['7'] = '111114';
  391. $chr['8'] = '131211';
  392. $chr['9'] = '141111';
  393. $chr['A'] = '211113';
  394. $chr['B'] = '211212';
  395. $chr['C'] = '211311';
  396. $chr['D'] = '221112';
  397. $chr['E'] = '221211';
  398. $chr['F'] = '231111';
  399. $chr['G'] = '112113';
  400. $chr['H'] = '112212';
  401. $chr['I'] = '112311';
  402. $chr['J'] = '122112';
  403. $chr['K'] = '132111';
  404. $chr['L'] = '111123';
  405. $chr['M'] = '111222';
  406. $chr['N'] = '111321';
  407. $chr['O'] = '121122';
  408. $chr['P'] = '131121';
  409. $chr['Q'] = '212112';
  410. $chr['R'] = '212211';
  411. $chr['S'] = '211122';
  412. $chr['T'] = '211221';
  413. $chr['U'] = '221121';
  414. $chr['V'] = '222111';
  415. $chr['W'] = '112122';
  416. $chr['X'] = '112221';
  417. $chr['Y'] = '122121';
  418. $chr['Z'] = '123111';
  419. $chr['-'] = '121131';
  420. $chr['.'] = '311112';
  421. $chr[' '] = '311211';
  422. $chr['$'] = '321111';
  423. $chr['/'] = '112131';
  424. $chr['+'] = '113121';
  425. $chr['%'] = '211131';
  426. $chr[128] = '121221'; // ($)
  427. $chr[129] = '311121'; // (/)
  428. $chr[130] = '122211'; // (+)
  429. $chr[131] = '312111'; // (%)
  430. $chr['*'] = '111141';
  431. $code = strtoupper($code);
  432. $encode = array(
  433. chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C',
  434. chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G',
  435. chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K',
  436. chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O',
  437. chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S',
  438. chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W',
  439. chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A',
  440. chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E',
  441. chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C',
  442. chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G',
  443. chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K',
  444. chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O',
  445. chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
  446. chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
  447. chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F',
  448. chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J',
  449. chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
  450. chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
  451. chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
  452. chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
  453. chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
  454. chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
  455. chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K',
  456. chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O',
  457. chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C',
  458. chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G',
  459. chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K',
  460. chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O',
  461. chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S',
  462. chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W',
  463. chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P',
  464. chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T');
  465. $code_ext = '';
  466. $clen = strlen($code);
  467. for ($i = 0 ; $i < $clen; ++$i) {
  468. if (ord($code{$i}) > 127) {
  469. return false;
  470. }
  471. $code_ext .= $encode[$code{$i}];
  472. }
  473. // checksum
  474. $code .= $this->checksum_code93($code);
  475. // add start and stop codes
  476. $code = '*'.$code.'*';
  477. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  478. $k = 0;
  479. $clen = strlen($code);
  480. for ($i = 0; $i < $clen; ++$i) {
  481. $char = $code{$i};
  482. if(!isset($chr[$char])) {
  483. // invalid character
  484. return false;
  485. }
  486. for ($j = 0; $j < 6; ++$j) {
  487. if (($j % 2) == 0) {
  488. $t = true; // bar
  489. } else {
  490. $t = false; // space
  491. }
  492. $w = $chr[$char]{$j};
  493. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  494. $bararray['maxw'] += $w;
  495. ++$k;
  496. }
  497. }
  498. $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
  499. $bararray['maxw'] += 1;
  500. ++$k;
  501. return $bararray;
  502. }
  503. /**
  504. * Calculate CODE 93 checksum (modulo 47).
  505. * @param $code (string) code to represent.
  506. * @return string checksum code.
  507. * @protected
  508. */
  509. protected function checksum_code93($code) {
  510. $chars = array(
  511. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  512. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  513. 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  514. 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
  515. // translate special characters
  516. $code = strtr($code, chr(128).chr(129).chr(130).chr(131), '$/+%');
  517. $len = strlen($code);
  518. // calculate check digit C
  519. $p = 1;
  520. $check = 0;
  521. for ($i = ($len - 1); $i >= 0; --$i) {
  522. $k = array_keys($chars, $code{$i});
  523. $check += ($k[0] * $p);
  524. ++$p;
  525. if ($p > 20) {
  526. $p = 1;
  527. }
  528. }
  529. $check %= 47;
  530. $c = $chars[$check];
  531. $code .= $c;
  532. // calculate check digit K
  533. $p = 1;
  534. $check = 0;
  535. for ($i = $len; $i >= 0; --$i) {
  536. $k = array_keys($chars, $code{$i});
  537. $check += ($k[0] * $p);
  538. ++$p;
  539. if ($p > 15) {
  540. $p = 1;
  541. }
  542. }
  543. $check %= 47;
  544. $k = $chars[$check];
  545. return $c.$k;
  546. }
  547. /**
  548. * Checksum for standard 2 of 5 barcodes.
  549. * @param $code (string) code to process.
  550. * @return int checksum.
  551. * @protected
  552. */
  553. protected function checksum_s25($code) {
  554. $len = strlen($code);
  555. $sum = 0;
  556. for ($i = 0; $i < $len; $i+=2) {
  557. $sum += $code{$i};
  558. }
  559. $sum *= 3;
  560. for ($i = 1; $i < $len; $i+=2) {
  561. $sum += ($code{$i});
  562. }
  563. $r = $sum % 10;
  564. if($r > 0) {
  565. $r = (10 - $r);
  566. }
  567. return $r;
  568. }
  569. /**
  570. * MSI.
  571. * Variation of Plessey code, with similar applications
  572. * Contains digits (0 to 9) and encodes the data only in the width of bars.
  573. * @param $code (string) code to represent.
  574. * @param $checksum (boolean) if true add a checksum to the code (modulo 11)
  575. * @return array barcode representation.
  576. * @protected
  577. */
  578. protected function barcode_msi($code, $checksum=false) {
  579. $chr['0'] = '100100100100';
  580. $chr['1'] = '100100100110';
  581. $chr['2'] = '100100110100';
  582. $chr['3'] = '100100110110';
  583. $chr['4'] = '100110100100';
  584. $chr['5'] = '100110100110';
  585. $chr['6'] = '100110110100';
  586. $chr['7'] = '100110110110';
  587. $chr['8'] = '110100100100';
  588. $chr['9'] = '110100100110';
  589. $chr['A'] = '110100110100';
  590. $chr['B'] = '110100110110';
  591. $chr['C'] = '110110100100';
  592. $chr['D'] = '110110100110';
  593. $chr['E'] = '110110110100';
  594. $chr['F'] = '110110110110';
  595. if ($checksum) {
  596. // add checksum
  597. $clen = strlen($code);
  598. $p = 2;
  599. $check = 0;
  600. for ($i = ($clen - 1); $i >= 0; --$i) {
  601. $check += (hexdec($code{$i}) * $p);
  602. ++$p;
  603. if ($p > 7) {
  604. $p = 2;
  605. }
  606. }
  607. $check %= 11;
  608. if ($check > 0) {
  609. $check = 11 - $check;
  610. }
  611. $code .= $check;
  612. }
  613. $seq = '110'; // left guard
  614. $clen = strlen($code);
  615. for ($i = 0; $i < $clen; ++$i) {
  616. $digit = $code{$i};
  617. if (!isset($chr[$digit])) {
  618. // invalid character
  619. return false;
  620. }
  621. $seq .= $chr[$digit];
  622. }
  623. $seq .= '1001'; // right guard
  624. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  625. return $this->binseq_to_array($seq, $bararray);
  626. }
  627. /**
  628. * Standard 2 of 5 barcodes.
  629. * Used in airline ticket marking, photofinishing
  630. * Contains digits (0 to 9) and encodes the data only in the width of bars.
  631. * @param $code (string) code to represent.
  632. * @param $checksum (boolean) if true add a checksum to the code
  633. * @return array barcode representation.
  634. * @protected
  635. */
  636. protected function barcode_s25($code, $checksum=false) {
  637. $chr['0'] = '10101110111010';
  638. $chr['1'] = '11101010101110';
  639. $chr['2'] = '10111010101110';
  640. $chr['3'] = '11101110101010';
  641. $chr['4'] = '10101110101110';
  642. $chr['5'] = '11101011101010';
  643. $chr['6'] = '10111011101010';
  644. $chr['7'] = '10101011101110';
  645. $chr['8'] = '10101110111010';
  646. $chr['9'] = '10111010111010';
  647. if ($checksum) {
  648. // add checksum
  649. $code .= $this->checksum_s25($code);
  650. }
  651. if((strlen($code) % 2) != 0) {
  652. // add leading zero if code-length is odd
  653. $code = '0'.$code;
  654. }
  655. $seq = '11011010';
  656. $clen = strlen($code);
  657. for ($i = 0; $i < $clen; ++$i) {
  658. $digit = $code{$i};
  659. if (!isset($chr[$digit])) {
  660. // invalid character
  661. return false;
  662. }
  663. $seq .= $chr[$digit];
  664. }
  665. $seq .= '1101011';
  666. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  667. return $this->binseq_to_array($seq, $bararray);
  668. }
  669. /**
  670. * Convert binary barcode sequence to TCPDF barcode array.
  671. * @param $seq (string) barcode as binary sequence.
  672. * @param $bararray (array) barcode array.
  673. * òparam array $bararray TCPDF barcode array to fill up
  674. * @return array barcode representation.
  675. * @protected
  676. */
  677. protected function binseq_to_array($seq, $bararray) {
  678. $len = strlen($seq);
  679. $w = 0;
  680. $k = 0;
  681. for ($i = 0; $i < $len; ++$i) {
  682. $w += 1;
  683. if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
  684. if ($seq{$i} == '1') {
  685. $t = true; // bar
  686. } else {
  687. $t = false; // space
  688. }
  689. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  690. $bararray['maxw'] += $w;
  691. ++$k;
  692. $w = 0;
  693. }
  694. }
  695. return $bararray;
  696. }
  697. /**
  698. * Interleaved 2 of 5 barcodes.
  699. * Compact numeric code, widely used in industry, air cargo
  700. * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
  701. * @param $code (string) code to represent.
  702. * @param $checksum (boolean) if true add a checksum to the code
  703. * @return array barcode representation.
  704. * @protected
  705. */
  706. protected function barcode_i25($code, $checksum=false) {
  707. $chr['0'] = '11221';
  708. $chr['1'] = '21112';
  709. $chr['2'] = '12112';
  710. $chr['3'] = '22111';
  711. $chr['4'] = '11212';
  712. $chr['5'] = '21211';
  713. $chr['6'] = '12211';
  714. $chr['7'] = '11122';
  715. $chr['8'] = '21121';
  716. $chr['9'] = '12121';
  717. $chr['A'] = '11';
  718. $chr['Z'] = '21';
  719. if ($checksum) {
  720. // add checksum
  721. $code .= $this->checksum_s25($code);
  722. }
  723. if((strlen($code) % 2) != 0) {
  724. // add leading zero if code-length is odd
  725. $code = '0'.$code;
  726. }
  727. // add start and stop codes
  728. $code = 'AA'.strtolower($code).'ZA';
  729. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  730. $k = 0;
  731. $clen = strlen($code);
  732. for ($i = 0; $i < $clen; $i = ($i + 2)) {
  733. $char_bar = $code{$i};
  734. $char_space = $code{$i+1};
  735. if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
  736. // invalid character
  737. return false;
  738. }
  739. // create a bar-space sequence
  740. $seq = '';
  741. $chrlen = strlen($chr[$char_bar]);
  742. for ($s = 0; $s < $chrlen; $s++){
  743. $seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
  744. }
  745. $seqlen = strlen($seq);
  746. for ($j = 0; $j < $seqlen; ++$j) {
  747. if (($j % 2) == 0) {
  748. $t = true; // bar
  749. } else {
  750. $t = false; // space
  751. }
  752. $w = $seq{$j};
  753. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  754. $bararray['maxw'] += $w;
  755. ++$k;
  756. }
  757. }
  758. return $bararray;
  759. }
  760. /**
  761. * C128 barcodes.
  762. * Very capable code, excellent density, high reliability; in very wide use world-wide
  763. * @param $code (string) code to represent.
  764. * @param $type (string) barcode type: A, B or C
  765. * @return array barcode representation.
  766. * @protected
  767. */
  768. protected function barcode_c128($code, $type='B') {
  769. $chr = array(
  770. '212222', /* 00 */
  771. '222122', /* 01 */
  772. '222221', /* 02 */
  773. '121223', /* 03 */
  774. '121322', /* 04 */
  775. '131222', /* 05 */
  776. '122213', /* 06 */
  777. '122312', /* 07 */
  778. '132212', /* 08 */
  779. '221213', /* 09 */
  780. '221312', /* 10 */
  781. '231212', /* 11 */
  782. '112232', /* 12 */
  783. '122132', /* 13 */
  784. '122231', /* 14 */
  785. '113222', /* 15 */
  786. '123122', /* 16 */
  787. '123221', /* 17 */
  788. '223211', /* 18 */
  789. '221132', /* 19 */
  790. '221231', /* 20 */
  791. '213212', /* 21 */
  792. '223112', /* 22 */
  793. '312131', /* 23 */
  794. '311222', /* 24 */
  795. '321122', /* 25 */
  796. '321221', /* 26 */
  797. '312212', /* 27 */
  798. '322112', /* 28 */
  799. '322211', /* 29 */
  800. '212123', /* 30 */
  801. '212321', /* 31 */
  802. '232121', /* 32 */
  803. '111323', /* 33 */
  804. '131123', /* 34 */
  805. '131321', /* 35 */
  806. '112313', /* 36 */
  807. '132113', /* 37 */
  808. '132311', /* 38 */
  809. '211313', /* 39 */
  810. '231113', /* 40 */
  811. '231311', /* 41 */
  812. '112133', /* 42 */
  813. '112331', /* 43 */
  814. '132131', /* 44 */
  815. '113123', /* 45 */
  816. '113321', /* 46 */
  817. '133121', /* 47 */
  818. '313121', /* 48 */
  819. '211331', /* 49 */
  820. '231131', /* 50 */
  821. '213113', /* 51 */
  822. '213311', /* 52 */
  823. '213131', /* 53 */
  824. '311123', /* 54 */
  825. '311321', /* 55 */
  826. '331121', /* 56 */
  827. '312113', /* 57 */
  828. '312311', /* 58 */
  829. '332111', /* 59 */
  830. '314111', /* 60 */
  831. '221411', /* 61 */
  832. '431111', /* 62 */
  833. '111224', /* 63 */
  834. '111422', /* 64 */
  835. '121124', /* 65 */
  836. '121421', /* 66 */
  837. '141122', /* 67 */
  838. '141221', /* 68 */
  839. '112214', /* 69 */
  840. '112412', /* 70 */
  841. '122114', /* 71 */
  842. '122411', /* 72 */
  843. '142112', /* 73 */
  844. '142211', /* 74 */
  845. '241211', /* 75 */
  846. '221114', /* 76 */
  847. '413111', /* 77 */
  848. '241112', /* 78 */
  849. '134111', /* 79 */
  850. '111242', /* 80 */
  851. '121142', /* 81 */
  852. '121241', /* 82 */
  853. '114212', /* 83 */
  854. '124112', /* 84 */
  855. '124211', /* 85 */
  856. '411212', /* 86 */
  857. '421112', /* 87 */
  858. '421211', /* 88 */
  859. '212141', /* 89 */
  860. '214121', /* 90 */
  861. '412121', /* 91 */
  862. '111143', /* 92 */
  863. '111341', /* 93 */
  864. '131141', /* 94 */
  865. '114113', /* 95 */
  866. '114311', /* 96 */
  867. '411113', /* 97 */
  868. '411311', /* 98 */
  869. '113141', /* 99 */
  870. '114131', /* 100 */
  871. '311141', /* 101 */
  872. '411131', /* 102 */
  873. '211412', /* 103 START A */
  874. '211214', /* 104 START B */
  875. '211232', /* 105 START C */
  876. '233111', /* STOP */
  877. '200000' /* END */
  878. );
  879. $keys = '';
  880. switch(strtoupper($type)) {
  881. case 'A': {
  882. $startid = 103;
  883. $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
  884. for ($i = 0; $i < 32; ++$i) {
  885. $keys .= chr($i);
  886. }
  887. break;
  888. }
  889. case 'B': {
  890. $startid = 104;
  891. $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
  892. break;
  893. }
  894. case 'C': {
  895. $startid = 105;
  896. $keys = '';
  897. if ((strlen($code) % 2) != 0) {
  898. // The length of barcode value must be even ($code). You must pad the number with zeros
  899. return false;
  900. }
  901. for ($i = 0; $i <= 99; ++$i) {
  902. $keys .= chr($i);
  903. }
  904. $new_code = '';
  905. $hclen = (strlen($code) / 2);
  906. for ($i = 0; $i < $hclen; ++$i) {
  907. $new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)}));
  908. }
  909. $code = $new_code;
  910. break;
  911. }
  912. default: {
  913. return false;
  914. }
  915. }
  916. // calculate check character
  917. $sum = $startid;
  918. $clen = strlen($code);
  919. for ($i = 0; $i < $clen; ++$i) {
  920. $sum += (strpos($keys, $code{$i}) * ($i+1));
  921. }
  922. $check = ($sum % 103);
  923. // add start, check and stop codes
  924. $code = chr($startid).$code.chr($check).chr(106).chr(107);
  925. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  926. $k = 0;
  927. $len = strlen($code);
  928. for ($i = 0; $i < $len; ++$i) {
  929. $ck = strpos($keys, $code{$i});
  930. if (($i == 0) OR ($i > ($len-4))) {
  931. $char_num = ord($code{$i});
  932. $seq = $chr[$char_num];
  933. } elseif(($ck >= 0) AND isset($chr[$ck])) {
  934. $seq = $chr[$ck];
  935. } else {
  936. // invalid character
  937. return false;
  938. }
  939. for ($j = 0; $j < 6; ++$j) {
  940. if (($j % 2) == 0) {
  941. $t = true; // bar
  942. } else {
  943. $t = false; // space
  944. }
  945. $w = $seq{$j};
  946. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  947. $bararray['maxw'] += $w;
  948. ++$k;
  949. }
  950. }
  951. return $bararray;
  952. }
  953. /**
  954. * EAN13 and UPC-A barcodes.
  955. * EAN13: European Article Numbering international retail product code
  956. * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
  957. * UPC-E: Short version of UPC symbol
  958. * @param $code (string) code to represent.
  959. * @param $len (string) barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A
  960. * @return array barcode representation.
  961. * @protected
  962. */
  963. protected function barcode_eanupc($code, $len=13) {
  964. $upce = false;
  965. if ($len == 6) {
  966. $len = 12; // UPC-A
  967. $upce = true; // UPC-E mode
  968. }
  969. $data_len = $len - 1;
  970. //Padding
  971. $code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
  972. $code_len = strlen($code);
  973. // calculate check digit
  974. $sum_a = 0;
  975. for ($i = 1; $i < $data_len; $i+=2) {
  976. $sum_a += $code{$i};
  977. }
  978. if ($len > 12) {
  979. $sum_a *= 3;
  980. }
  981. $sum_b = 0;
  982. for ($i = 0; $i < $data_len; $i+=2) {
  983. $sum_b += ($code{$i});
  984. }
  985. if ($len < 13) {
  986. $sum_b *= 3;
  987. }
  988. $r = ($sum_a + $sum_b) % 10;
  989. if($r > 0) {
  990. $r = (10 - $r);
  991. }
  992. if ($code_len == $data_len) {
  993. // add check digit
  994. $code .= $r;
  995. } elseif ($r !== intval($code{$data_len})) {
  996. // wrong checkdigit
  997. return false;
  998. }
  999. if ($len == 12) {
  1000. // UPC-A
  1001. $code = '0'.$code;
  1002. ++$len;
  1003. }
  1004. if ($upce) {
  1005. // convert UPC-A to UPC-E
  1006. $tmp = substr($code, 4, 3);
  1007. if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
  1008. // manufacturer code ends in 000, 100, or 200
  1009. $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1);
  1010. } else {
  1011. $tmp = substr($code, 5, 2);
  1012. if ($tmp == '00') {
  1013. // manufacturer code ends in 00
  1014. $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3';
  1015. } else {
  1016. $tmp = substr($code, 6, 1);
  1017. if ($tmp == '0') {
  1018. // manufacturer code ends in 0
  1019. $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4';
  1020. } else {
  1021. // manufacturer code does not end in zero
  1022. $upce_code = substr($code, 2, 5).substr($code, 11, 1);
  1023. }
  1024. }
  1025. }
  1026. }
  1027. //Convert digits to bars
  1028. $codes = array(
  1029. 'A'=>array( // left odd parity
  1030. '0'=>'0001101',
  1031. '1'=>'0011001',
  1032. '2'=>'0010011',
  1033. '3'=>'0111101',
  1034. '4'=>'0100011',
  1035. '5'=>'0110001',
  1036. '6'=>'0101111',
  1037. '7'=>'0111011',
  1038. '8'=>'0110111',
  1039. '9'=>'0001011'),
  1040. 'B'=>array( // left even parity
  1041. '0'=>'0100111',
  1042. '1'=>'0110011',
  1043. '2'=>'0011011',
  1044. '3'=>'0100001',
  1045. '4'=>'0011101',
  1046. '5'=>'0111001',
  1047. '6'=>'0000101',
  1048. '7'=>'0010001',
  1049. '8'=>'0001001',
  1050. '9'=>'0010111'),
  1051. 'C'=>array( // right
  1052. '0'=>'1110010',
  1053. '1'=>'1100110',
  1054. '2'=>'1101100',
  1055. '3'=>'1000010',
  1056. '4'=>'1011100',
  1057. '5'=>'1001110',
  1058. '6'=>'1010000',
  1059. '7'=>'1000100',
  1060. '8'=>'1001000',
  1061. '9'=>'1110100')
  1062. );
  1063. $parities = array(
  1064. '0'=>array('A','A','A','A','A','A'),
  1065. '1'=>array('A','A','B','A','B','B'),
  1066. '2'=>array('A','A','B','B','A','B'),
  1067. '3'=>array('A','A','B','B','B','A'),
  1068. '4'=>array('A','B','A','A','B','B'),
  1069. '5'=>array('A','B','B','A','A','B'),
  1070. '6'=>array('A','B','B','B','A','A'),
  1071. '7'=>array('A','B','A','B','A','B'),
  1072. '8'=>array('A','B','A','B','B','A'),
  1073. '9'=>array('A','B','B','A','B','A')
  1074. );
  1075. $upce_parities = array();
  1076. $upce_parities[0] = array(
  1077. '0'=>array('B','B','B','A','A','A'),
  1078. '1'=>array('B','B','A','B','A','A'),
  1079. '2'=>array('B','B','A','A','B','A'),
  1080. '3'=>array('B','B','A','A','A','B'),
  1081. '4'=>array('B','A','B','B','A','A'),
  1082. '5'=>array('B','A','A','B','B','A'),
  1083. '6'=>array('B','A','A','A','B','B'),
  1084. '7'=>array('B','A','B','A','B','A'),
  1085. '8'=>array('B','A','B','A','A','B'),
  1086. '9'=>array('B','A','A','B','A','B')
  1087. );
  1088. $upce_parities[1] = array(
  1089. '0'=>array('A','A','A','B','B','B'),
  1090. '1'=>array('A','A','B','A','B','B'),
  1091. '2'=>array('A','A','B','B','A','B'),
  1092. '3'=>array('A','A','B','B','B','A'),
  1093. '4'=>array('A','B','A','A','B','B'),
  1094. '5'=>array('A','B','B','A','A','B'),
  1095. '6'=>array('A','B','B','B','A','A'),
  1096. '7'=>array('A','B','A','B','A','B'),
  1097. '8'=>array('A','B','A','B','B','A'),
  1098. '9'=>array('A','B','B','A','B','A')
  1099. );
  1100. $k = 0;
  1101. $seq = '101'; // left guard bar
  1102. if ($upce) {
  1103. $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1104. $p = $upce_parities[$code{1}][$r];
  1105. for ($i = 0; $i < 6; ++$i) {
  1106. $seq .= $codes[$p[$i]][$upce_code{$i}];
  1107. }
  1108. $seq .= '010101'; // right guard bar
  1109. } else {
  1110. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1111. $half_len = ceil($len / 2);
  1112. if ($len == 8) {
  1113. for ($i = 0; $i < $half_len; ++$i) {
  1114. $seq .= $codes['A'][$code{$i}];
  1115. }
  1116. } else {
  1117. $p = $parities[$code{0}];
  1118. for ($i = 1; $i < $half_len; ++$i) {
  1119. $seq .= $codes[$p[$i-1]][$code{$i}];
  1120. }
  1121. }
  1122. $seq .= '01010'; // center guard bar
  1123. for ($i = $half_len; $i < $len; ++$i) {
  1124. $seq .= $codes['C'][$code{$i}];
  1125. }
  1126. $seq .= '101'; // right guard bar
  1127. }
  1128. $clen = strlen($seq);
  1129. $w = 0;
  1130. for ($i = 0; $i < $clen; ++$i) {
  1131. $w += 1;
  1132. if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
  1133. if ($seq{$i} == '1') {
  1134. $t = true; // bar
  1135. } else {
  1136. $t = false; // space
  1137. }
  1138. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  1139. $bararray['maxw'] += $w;
  1140. ++$k;
  1141. $w = 0;
  1142. }
  1143. }
  1144. return $bararray;
  1145. }
  1146. /**
  1147. * UPC-Based Extentions
  1148. * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers
  1149. * 5-Digit Ext.: Used to mark suggested retail price of books
  1150. * @param $code (string) code to represent.
  1151. * @param $len (string) barcode type: 2 = 2-Digit, 5 = 5-Digit
  1152. * @return array barcode representation.
  1153. * @protected
  1154. */
  1155. protected function barcode_eanext($code, $len=5) {
  1156. //Padding
  1157. $code = str_pad($code, $len, '0', STR_PAD_LEFT);
  1158. // calculate check digit
  1159. if ($len == 2) {
  1160. $r = $code % 4;
  1161. } elseif ($len == 5) {
  1162. $r = (3 * ($code{0} + $code{2} + $code{4})) + (9 * ($code{1} + $code{3}));
  1163. $r %= 10;
  1164. } else {
  1165. return false;
  1166. }
  1167. //Convert digits to bars
  1168. $codes = array(
  1169. 'A'=>array( // left odd parity
  1170. '0'=>'0001101',
  1171. '1'=>'0011001',
  1172. '2'=>'0010011',
  1173. '3'=>'0111101',
  1174. '4'=>'0100011',
  1175. '5'=>'0110001',
  1176. '6'=>'0101111',
  1177. '7'=>'0111011',
  1178. '8'=>'0110111',
  1179. '9'=>'0001011'),
  1180. 'B'=>array( // left even parity
  1181. '0'=>'0100111',
  1182. '1'=>'0110011',
  1183. '2'=>'0011011',
  1184. '3'=>'0100001',
  1185. '4'=>'0011101',
  1186. '5'=>'0111001',
  1187. '6'=>'0000101',
  1188. '7'=>'0010001',
  1189. '8'=>'0001001',
  1190. '9'=>'0010111')
  1191. );
  1192. $parities = array();
  1193. $parities[2] = array(
  1194. '0'=>array('A','A'),
  1195. '1'=>array('A','B'),
  1196. '2'=>array('B','A'),
  1197. '3'=>array('B','B')
  1198. );
  1199. $parities[5] = array(
  1200. '0'=>array('B','B','A','A','A'),
  1201. '1'=>array('B','A','B','A','A'),
  1202. '2'=>array('B','A','A','B','A'),
  1203. '3'=>array('B','A','A','A','B'),
  1204. '4'=>array('A','B','B','A','A'),
  1205. '5'=>array('A','A','B','B','A'),
  1206. '6'=>array('A','A','A','B','B'),
  1207. '7'=>array('A','B','A','B','A'),
  1208. '8'=>array('A','B','A','A','B'),
  1209. '9'=>array('A','A','B','A','B')
  1210. );
  1211. $p = $parities[$len][$r];
  1212. $seq = '1011'; // left guard bar
  1213. $seq .= $codes[$p[0]][$code{0}];
  1214. for ($i = 1; $i < $len; ++$i) {
  1215. $seq .= '01'; // separator
  1216. $seq .= $codes[$p[$i]][$code{$i}];
  1217. }
  1218. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1219. return $this->binseq_to_array($seq, $bararray);
  1220. }
  1221. /**
  1222. * POSTNET and PLANET barcodes.
  1223. * Used by U.S. Postal Service for automated mail sorting
  1224. * @param $code (string) zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD.
  1225. * @param $planet (boolean) if true print the PLANET barcode, otherwise print POSTNET
  1226. * @return array barcode representation.
  1227. * @protected
  1228. */
  1229. protected function barcode_postnet($code, $planet=false) {
  1230. // bar lenght
  1231. if ($planet) {
  1232. $barlen = Array(
  1233. 0 => Array(1,1,2,2,2),
  1234. 1 => Array(2,2,2,1,1),
  1235. 2 => Array(2,2,1,2,1),
  1236. 3 => Array(2,2,1,1,2),
  1237. 4 => Array(2,1,2,2,1),
  1238. 5 => Array(2,1,2,1,2),
  1239. 6 => Array(2,1,1,2,2),
  1240. 7 => Array(1,2,2,2,1),
  1241. 8 => Array(1,2,2,1,2),
  1242. 9 => Array(1,2,1,2,2)
  1243. );
  1244. } else {
  1245. $barlen = Array(
  1246. 0 => Array(2,2,1,1,1),
  1247. 1 => Array(1,1,1,2,2),
  1248. 2 => Array(1,1,2,1,2),
  1249. 3 => Array(1,1,2,2,1),
  1250. 4 => Array(1,2,1,1,2),
  1251. 5 => Array(1,2,1,2,1),
  1252. 6 => Array(1,2,2,1,1),
  1253. 7 => Array(2,1,1,1,2),
  1254. 8 => Array(2,1,1,2,1),
  1255. 9 => Array(2,1,2,1,1)
  1256. );
  1257. }
  1258. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
  1259. $k = 0;
  1260. $code = str_replace('-', '', $code);
  1261. $code = str_replace(' ', '', $code);
  1262. $len = strlen($code);
  1263. // calculate checksum
  1264. $sum = 0;
  1265. for ($i = 0; $i < $len; ++$i) {
  1266. $sum += intval($code{$i});
  1267. }
  1268. $chkd = ($sum % 10);
  1269. if($chkd > 0) {
  1270. $chkd = (10 - $chkd);
  1271. }
  1272. $code .= $chkd;
  1273. $len = strlen($code);
  1274. // start bar
  1275. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
  1276. $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
  1277. $bararray['maxw'] += 2;
  1278. for ($i = 0; $i < $len; ++$i) {
  1279. for ($j = 0; $j < 5; ++$j) {
  1280. $h = $barlen[$code{$i}][$j];
  1281. $p = floor(1 / $h);
  1282. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
  1283. $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
  1284. $bararray['maxw'] += 2;
  1285. }
  1286. }
  1287. // end bar
  1288. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
  1289. $bararray['maxw'] += 1;
  1290. return $bararray;
  1291. }
  1292. /**
  1293. * RMS4CC - CBC - KIX
  1294. * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index)
  1295. * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service.
  1296. * @param $code (string) code to print
  1297. * @param $kix (boolean) if true prints the KIX variation (doesn't use the start and end symbols, and the checksum) - in this case the house number must be sufficed with an X and placed at the end of the code.
  1298. * @return array barcode representation.
  1299. * @protected
  1300. */
  1301. protected function barcode_rms4cc($code, $kix=false) {
  1302. $notkix = !$kix;
  1303. // bar mode
  1304. // 1 = pos 1, length 2
  1305. // 2 = pos 1, length 3
  1306. // 3 = pos 2, length 1
  1307. // 4 = pos 2, length 2
  1308. $barmode = array(
  1309. '0' => array(3,3,2,2),
  1310. '1' => array(3,4,1,2),
  1311. '2' => array(3,4,2,1),
  1312. '3' => array(4,3,1,2),
  1313. '4' => array(4,3,2,1),
  1314. '5' => array(4,4,1,1),
  1315. '6' => array(3,1,4,2),
  1316. '7' => array(3,2,3,2),
  1317. '8' => array(3,2,4,1),
  1318. '9' => array(4,1,3,2),
  1319. 'A' => array(4,1,4,1),
  1320. 'B' => array(4,2,3,1),
  1321. 'C' => array(3,1,2,4),
  1322. 'D' => array(3,2,1,4),
  1323. 'E' => array(3,2,2,3),
  1324. 'F' => array(4,1,1,4),
  1325. 'G' => array(4,1,2,3),
  1326. 'H' => array(4,2,1,3),
  1327. 'I' => array(1,3,4,2),
  1328. 'J' => array(1,4,3,2),
  1329. 'K' => array(1,4,4,1),
  1330. 'L' => array(2,3,3,2),
  1331. 'M' => array(2,3,4,1),
  1332. 'N' => array(2,4,3,1),
  1333. 'O' => array(1,3,2,4),
  1334. 'P' => array(1,4,1,4),
  1335. 'Q' => array(1,4,2,3),
  1336. 'R' => array(2,3,1,4),
  1337. 'S' => array(2,3,2,3),
  1338. 'T' => array(2,4,1,3),
  1339. 'U' => array(1,1,4,4),
  1340. 'V' => array(1,2,3,4),
  1341. 'W' => array(1,2,4,3),
  1342. 'X' => array(2,1,3,4),
  1343. 'Y' => array(2,1,4,3),
  1344. 'Z' => array(2,2,3,3)
  1345. );
  1346. $code = strtoupper($code);
  1347. $len = strlen($code);
  1348. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
  1349. if ($notkix) {
  1350. // table for checksum calculation (row,col)
  1351. $checktable = array(
  1352. '0' => array(1,1),
  1353. '1' => array(1,2),
  1354. '2' => array(1,3),
  1355. '3' => array(1,4),
  1356. '4' => array(1,5),
  1357. '5' => array(1,0),
  1358. '6' => array(2,1),
  1359. '7' => array(2,2),
  1360. '8' => array(2,3),
  1361. '9' => array(2,4),
  1362. 'A' => array(2,5),
  1363. 'B' => array(2,0),
  1364. 'C' => array(3,1),
  1365. 'D' => array(3,2),
  1366. 'E' => array(3,3),
  1367. 'F' => array(3,4),
  1368. 'G' => array(3,5),
  1369. 'H' => array(3,0),
  1370. 'I' => array(4,1),
  1371. 'J' => array(4,2),
  1372. 'K' => array(4,3),
  1373. 'L' => array(4,4),
  1374. 'M' => array(4,5),
  1375. 'N' => array(4,0),
  1376. 'O' => array(5,1),
  1377. 'P' => array(5,2),
  1378. 'Q' => array(5,3),
  1379. 'R' => array(5,4),
  1380. 'S' => array(5,5),
  1381. 'T' => array(5,0),
  1382. 'U' => array(0,1),
  1383. 'V' => array(0,2),
  1384. 'W' => array(0,3),
  1385. 'X' => array(0,4),
  1386. 'Y' => array(0,5),
  1387. 'Z' => array(0,0)
  1388. );
  1389. $row = 0;
  1390. $col = 0;
  1391. for ($i = 0; $i < $len; ++$i) {
  1392. $row += $checktable[$code{$i}][0];
  1393. $col += $checktable[$code{$i}][1];
  1394. }
  1395. $row %= 6;
  1396. $col %= 6;
  1397. $chk = array_keys($checktable, array($row,$col));
  1398. $code .= $chk[0];
  1399. ++$len;
  1400. }
  1401. $k = 0;
  1402. if ($notkix) {
  1403. // start bar
  1404. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
  1405. $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
  1406. $bararray['maxw'] += 2;
  1407. }
  1408. for ($i = 0; $i < $len; ++$i) {
  1409. for ($j = 0; $j < 4; ++$j) {
  1410. switch ($barmode[$code{$i}][$j]) {
  1411. case 1: {
  1412. $p = 0;
  1413. $h = 2;
  1414. break;
  1415. }
  1416. case 2: {
  1417. $p = 0;
  1418. $h = 3;
  1419. break;
  1420. }
  1421. case 3: {
  1422. $p = 1;
  1423. $h = 1;
  1424. break;
  1425. }
  1426. case 4: {
  1427. $p = 1;
  1428. $h = 2;
  1429. break;
  1430. }
  1431. }
  1432. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
  1433. $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
  1434. $bararray['maxw'] += 2;
  1435. }
  1436. }
  1437. if ($notkix) {
  1438. // stop bar
  1439. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
  1440. $bararray['maxw'] += 1;
  1441. }
  1442. return $bararray;
  1443. }
  1444. /**
  1445. * CODABAR barcodes.
  1446. * Older code often used in library systems, sometimes in blood banks
  1447. * @param $code (string) code to represent.
  1448. * @return array barcode representation.
  1449. * @protected
  1450. */
  1451. protected function barcode_codabar($code) {
  1452. $chr = array(
  1453. '0' => '11111221',
  1454. '1' => '11112211',
  1455. '2' => '11121121',
  1456. '3' => '22111111',
  1457. '4' => '11211211',
  1458. '5' => '21111211',
  1459. '6' => '12111121',
  1460. '7' => '12112111',
  1461. '8' => '12211111',
  1462. '9' => '21121111',
  1463. '-' => '11122111',
  1464. '$' => '11221111',
  1465. ':' => '21112121',
  1466. '/' => '21211121',
  1467. '.' => '21212111',
  1468. '+' => '11222221',
  1469. 'A' => '11221211',
  1470. 'B' => '12121121',
  1471. 'C' => '11121221',
  1472. 'D' => '11122211'
  1473. );
  1474. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1475. $k = 0;
  1476. $w = 0;
  1477. $seq = '';
  1478. $code = 'A'.strtoupper($code).'A';
  1479. $len = strlen($code);
  1480. for ($i = 0; $i < $len; ++$i) {
  1481. if (!isset($chr[$code{$i}])) {
  1482. return false;
  1483. }
  1484. $seq = $chr[$code{$i}];
  1485. for ($j = 0; $j < 8; ++$j) {
  1486. if (($j % 2) == 0) {
  1487. $t = true; // bar
  1488. } else {
  1489. $t = false; // space
  1490. }
  1491. $w = $seq{$j};
  1492. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  1493. $bararray['maxw'] += $w;
  1494. ++$k;
  1495. }
  1496. }
  1497. return $bararray;
  1498. }
  1499. /**
  1500. * CODE11 barcodes.
  1501. * Used primarily for labeling telecommunications equipment
  1502. * @param $code (string) code to represent.
  1503. * @return array barcode representation.
  1504. * @protected
  1505. */
  1506. protected function barcode_code11($code) {
  1507. $chr = array(
  1508. '0' => '111121',
  1509. '1' => '211121',
  1510. '2' => '121121',
  1511. '3' => '221111',
  1512. '4' => '112121',
  1513. '5' => '212111',
  1514. '6' => '122111',
  1515. '7' => '111221',
  1516. '8' => '211211',
  1517. '9' => '211111',
  1518. '-' => '112111',
  1519. 'S' => '112211'
  1520. );
  1521. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1522. $k = 0;
  1523. $w = 0;
  1524. $seq = '';
  1525. $len = strlen($code);
  1526. // calculate check digit C
  1527. $p = 1;
  1528. $check = 0;
  1529. for ($i = ($len - 1); $i >= 0; --$i) {
  1530. $digit = $code{$i};
  1531. if ($digit == '-') {
  1532. $dval = 10;
  1533. } else {
  1534. $dval = intval($digit);
  1535. }
  1536. $check += ($dval * $p);
  1537. ++$p;
  1538. if ($p > 10) {
  1539. $p = 1;
  1540. }
  1541. }
  1542. $check %= 11;
  1543. if ($check == 10) {
  1544. $check = '-';
  1545. }
  1546. $code .= $check;
  1547. if ($len > 10) {
  1548. // calculate check digit K
  1549. $p = 1;
  1550. $check = 0;
  1551. for ($i = $len; $i >= 0; --$i) {
  1552. $digit = $code{$i};
  1553. if ($digit == '-') {
  1554. $dval = 10;
  1555. } else {
  1556. $dval = intval($digit);
  1557. }
  1558. $check += ($dval * $p);
  1559. ++$p;
  1560. if ($p > 9) {
  1561. $p = 1;
  1562. }
  1563. }
  1564. $check %= 11;
  1565. $code .= $check;
  1566. ++$len;
  1567. }
  1568. $code = 'S'.$code.'S';
  1569. $len += 3;
  1570. for ($i = 0; $i < $len; ++$i) {
  1571. if (!isset($chr[$code{$i}])) {
  1572. return false;
  1573. }
  1574. $seq = $chr[$code{$i}];
  1575. for ($j = 0; $j < 6; ++$j) {
  1576. if (($j % 2) == 0) {
  1577. $t = true; // bar
  1578. } else {
  1579. $t = false; // space
  1580. }
  1581. $w = $seq{$j};
  1582. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  1583. $bararray['maxw'] += $w;
  1584. ++$k;
  1585. }
  1586. }
  1587. return $bararray;
  1588. }
  1589. /**
  1590. * Pharmacode
  1591. * Contains digits (0 to 9)
  1592. * @param $code (string) code to represent.
  1593. * @return array barcode representation.
  1594. * @protected
  1595. */
  1596. protected function barcode_pharmacode($code) {
  1597. $seq = '';
  1598. $code = intval($code);
  1599. while ($code > 0) {
  1600. if (($code % 2) == 0) {
  1601. $seq .= '11100';
  1602. $code -= 2;
  1603. } else {
  1604. $seq .= '100';
  1605. $code -= 1;
  1606. }
  1607. $code /= 2;
  1608. }
  1609. $seq = substr($seq, 0, -2);
  1610. $seq = strrev($seq);
  1611. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1612. return $this->binseq_to_array($seq, $bararray);
  1613. }
  1614. /**
  1615. * Pharmacode two-track
  1616. * Contains digits (0 to 9)
  1617. * @param $code (string) code to represent.
  1618. * @return array barcode representation.
  1619. * @protected
  1620. */
  1621. protected function barcode_pharmacode2t($code) {
  1622. $seq = '';
  1623. $code = intval($code);
  1624. do {
  1625. switch ($code % 3) {
  1626. case 0: {
  1627. $seq .= '3';
  1628. $code = ($code - 3) / 3;
  1629. break;
  1630. }
  1631. case 1: {
  1632. $seq .= '1';
  1633. $code = ($code - 1) / 3;
  1634. break;
  1635. }
  1636. case 2: {
  1637. $seq .= '2';
  1638. $code = ($code - 2) / 3;
  1639. break;
  1640. }
  1641. }
  1642. } while($code != 0);
  1643. $seq = strrev($seq);
  1644. $k = 0;
  1645. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
  1646. $len = strlen($seq);
  1647. for ($i = 0; $i < $len; ++$i) {
  1648. switch ($seq{$i}) {
  1649. case '1': {
  1650. $p = 1;
  1651. $h = 1;
  1652. break;
  1653. }
  1654. case '2': {
  1655. $p = 0;
  1656. $h = 1;
  1657. break;
  1658. }
  1659. case '3': {
  1660. $p = 0;
  1661. $h = 2;
  1662. break;
  1663. }
  1664. }
  1665. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
  1666. $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
  1667. $bararray['maxw'] += 2;
  1668. }
  1669. unset($bararray['bcode'][($k - 1)]);
  1670. --$bararray['maxw'];
  1671. return $bararray;
  1672. }
  1673. /**
  1674. * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
  1675. * (requires PHP bcmath extension)
  1676. * Intelligent Mail barcode is a 65-bar code for use on mail in…

Large files files are truncated, but you can click here to view the full file