PageRenderTime 67ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/mpdf/classes/barcode.php

https://bitbucket.org/jojoluzifer/kkucardweb
PHP | 1965 lines | 1701 code | 44 blank | 220 comment | 264 complexity | d2d827faf3ff06d51b19e6c0a9d2a481 MD5 | raw file
Possible License(s): LGPL-2.1

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

  1. <?php
  2. // Adapted for mPDF from TCPDF barcode. Original Details left below.
  3. //============================================================+
  4. // File name : barcodes.php
  5. // Begin : 2008-06-09
  6. // Last Update : 2009-04-15
  7. // Version : 1.0.008
  8. // License : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
  9. // ----------------------------------------------------------------------------
  10. // Copyright (C) 2008-2009 Nicola Asuni - Tecnick.com S.r.l.
  11. //
  12. // This program is free software: you can redistribute it and/or modify
  13. // it under the terms of the GNU Lesser General Public License as published by
  14. // the Free Software Foundation, either version 2.1 of the License, or
  15. // (at your option) any later version.
  16. //
  17. // This program is distributed in the hope that it will be useful,
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. // GNU Lesser General Public License for more details.
  21. //
  22. // You should have received a copy of the GNU Lesser General Public License
  23. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. //
  25. // See LICENSE.TXT file for more information.
  26. // ----------------------------------------------------------------------------
  27. //
  28. // Description : PHP class to creates array representations for
  29. // common 1D barcodes to be used with TCPDF.
  30. //
  31. // Author: Nicola Asuni
  32. //
  33. // (c) Copyright:
  34. // Nicola Asuni
  35. // Tecnick.com S.r.l.
  36. // Via della Pace, 11
  37. // 09044 Quartucciu (CA)
  38. // ITALY
  39. // www.tecnick.com
  40. // info@tecnick.com
  41. //============================================================+
  42. class PDFBarcode {
  43. protected $barcode_array;
  44. protected $gapwidth;
  45. protected $print_ratio;
  46. protected $daft;
  47. public function __construct() {
  48. }
  49. public function getBarcodeArray($code, $type, $pr='') {
  50. $this->setBarcode($code, $type, $pr);
  51. return $this->barcode_array;
  52. }
  53. public function getChecksum($code, $type) {
  54. $this->setBarcode($code, $type);
  55. if (!$this->barcode_array) { return ''; }
  56. else { return $this->barcode_array['checkdigit']; }
  57. }
  58. public function setBarcode($code, $type, $pr='') {
  59. $this->print_ratio = 1;
  60. switch (strtoupper($type)) {
  61. case 'ISBN':
  62. case 'ISSN':
  63. case 'EAN13': { // EAN 13
  64. $arrcode = $this->barcode_eanupc($code, 13);
  65. $arrcode['lightmL'] = 11; // LEFT light margin = x X-dim (http://www.gs1uk.org)
  66. $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
  67. $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
  68. $arrcode['nom-H'] = 25.93; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
  69. break;
  70. }
  71. case 'UPCA': { // UPC-A
  72. $arrcode = $this->barcode_eanupc($code, 12);
  73. $arrcode['lightmL'] = 9; // LEFT light margin = x X-dim (http://www.gs1uk.org)
  74. $arrcode['lightmR'] = 9; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
  75. $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
  76. $arrcode['nom-H'] = 25.91; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
  77. break;
  78. }
  79. case 'UPCE': { // UPC-E
  80. $arrcode = $this->barcode_eanupc($code, 6);
  81. $arrcode['lightmL'] = 9; // LEFT light margin = x X-dim (http://www.gs1uk.org)
  82. $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
  83. $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
  84. $arrcode['nom-H'] = 25.93; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
  85. break;
  86. }
  87. case 'EAN8': { // EAN 8
  88. $arrcode = $this->barcode_eanupc($code, 8);
  89. $arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (http://www.gs1uk.org)
  90. $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
  91. $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
  92. $arrcode['nom-H'] = 21.64; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
  93. break;
  94. }
  95. case 'EAN2': { // 2-Digits UPC-Based Extention
  96. $arrcode = $this->barcode_eanext($code, 2);
  97. $arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (estimated)
  98. $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (estimated)
  99. $arrcode['sepM'] = 9; // SEPARATION margin = x X-dim (http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm)
  100. $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
  101. $arrcode['nom-H'] = 20; // Nominal bar height in mm incl. numerals (estimated) not used when combined
  102. break;
  103. }
  104. case 'EAN5': { // 5-Digits UPC-Based Extention
  105. $arrcode = $this->barcode_eanext($code, 5);
  106. $arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (estimated)
  107. $arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (estimated)
  108. $arrcode['sepM'] = 9; // SEPARATION margin = x X-dim (http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm)
  109. $arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
  110. $arrcode['nom-H'] = 20; // Nominal bar height in mm incl. numerals (estimated) not used when combined
  111. break;
  112. }
  113. case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
  114. $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
  115. $bpi = 22; // Bars per inch
  116. // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
  117. $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
  118. $this->daft = array('D'=>2, 'A'=>2, 'F'=>3, 'T'=>1); // Descender; Ascender; Full; Tracker bar heights
  119. $arrcode = $this->barcode_imb($code);
  120. $arrcode['nom-X'] = $xdim ;
  121. $arrcode['nom-H'] = 3.68; // Nominal value for Height of Full bar in mm (spec.)
  122. // USPS-B-3200 Revision C = 4.623
  123. // USPS-B-3200 Revision E = 3.68
  124. $arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (spec.)
  125. $arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (spec.)
  126. $arrcode['quietTB'] = 0.711; // TOP/BOTTOM Quiet margin = mm (spec.)
  127. break;
  128. }
  129. case 'RM4SCC': { // RM4SCC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
  130. $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
  131. $bpi = 22; // Bars per inch
  132. // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
  133. $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
  134. $this->daft = array('D'=>5, 'A'=>5, 'F'=>8, 'T'=>2); // Descender; Ascender; Full; Tracker bar heights
  135. $arrcode = $this->barcode_rm4scc($code, false);
  136. $arrcode['nom-X'] = $xdim ;
  137. $arrcode['nom-H'] = 5.0; // Nominal value for Height of Full bar in mm (spec.)
  138. $arrcode['quietL'] = 2; // LEFT Quiet margin = mm (spec.)
  139. $arrcode['quietR'] = 2; // RIGHT Quiet margin = mm (spec.)
  140. $arrcode['quietTB'] = 2; // TOP/BOTTOM Quiet margin = mm (spec?)
  141. break;
  142. }
  143. case 'KIX': { // KIX (Klant index - Customer index)
  144. $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
  145. $bpi = 22; // Bars per inch
  146. // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
  147. $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
  148. $this->daft = array('D'=>5, 'A'=>5, 'F'=>8, 'T'=>2); // Descender; Ascender; Full; Tracker bar heights
  149. $arrcode = $this->barcode_rm4scc($code, true);
  150. $arrcode['nom-X'] = $xdim ;
  151. $arrcode['nom-H'] = 5.0; // Nominal value for Height of Full bar in mm (? spec.)
  152. $arrcode['quietL'] = 2; // LEFT Quiet margin = mm (spec.)
  153. $arrcode['quietR'] = 2; // RIGHT Quiet margin = mm (spec.)
  154. $arrcode['quietTB'] = 2; // TOP/BOTTOM Quiet margin = mm (spec.)
  155. break;
  156. }
  157. case 'POSTNET': { // POSTNET
  158. $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
  159. $bpi = 22; // Bars per inch
  160. // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
  161. $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
  162. $arrcode = $this->barcode_postnet($code, false);
  163. $arrcode['nom-X'] = $xdim ;
  164. $arrcode['nom-H'] = 3.175; // Nominal value for Height of Full bar in mm (spec.)
  165. $arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (?spec.)
  166. $arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (?spec.)
  167. $arrcode['quietTB'] = 1.016; // TOP/BOTTOM Quiet margin = mm (?spec.)
  168. break;
  169. }
  170. case 'PLANET': { // PLANET
  171. $xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
  172. $bpi = 22; // Bars per inch
  173. // Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
  174. $this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
  175. $arrcode = $this->barcode_postnet($code, true);
  176. $arrcode['nom-X'] = $xdim ;
  177. $arrcode['nom-H'] = 3.175; // Nominal value for Height of Full bar in mm (spec.)
  178. $arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (?spec.)
  179. $arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (?spec.)
  180. $arrcode['quietTB'] = 1.016; // TOP/BOTTOM Quiet margin = mm (?spec.)
  181. break;
  182. }
  183. case 'C93': { // CODE 93 - USS-93
  184. $arrcode = $this->barcode_code93($code);
  185. if ($arrcode == false) { break; }
  186. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  187. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  188. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  189. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  190. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  191. break;
  192. }
  193. case 'CODE11': { // CODE 11
  194. if ($pr > 0) { $this->print_ratio = $pr; }
  195. else { $this->print_ratio = 3; } // spec: Pr= 1:2.24 - 1:3.5
  196. $arrcode = $this->barcode_code11($code);
  197. if ($arrcode == false) { break; }
  198. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  199. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  200. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  201. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  202. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  203. break;
  204. }
  205. case 'MSI': // MSI (Variation of Plessey code)
  206. case 'MSI+': { // MSI + CHECKSUM (modulo 11)
  207. if (strtoupper($type)=='MSI') { $arrcode = $this->barcode_msi($code, false); }
  208. if (strtoupper($type)=='MSI+') { $arrcode = $this->barcode_msi($code, true); }
  209. if ($arrcode == false) { break; }
  210. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  211. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  212. $arrcode['lightmL'] = 12; // LEFT light margin = x X-dim (spec.)
  213. $arrcode['lightmR'] = 12; // RIGHT light margin = x X-dim (spec.)
  214. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  215. break;
  216. }
  217. case 'CODABAR': { // CODABAR
  218. if ($pr > 0) { $this->print_ratio = $pr; }
  219. else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
  220. if (strtoupper($type)=='CODABAR') { $arrcode = $this->barcode_codabar($code); }
  221. if ($arrcode == false) { break; }
  222. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  223. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  224. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  225. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  226. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  227. break;
  228. }
  229. case 'C128A': // CODE 128 A
  230. case 'C128B': // CODE 128 B
  231. case 'C128C': // CODE 128 C
  232. case 'EAN128A': // EAN 128 A
  233. case 'EAN128B': // EAN 128 B
  234. case 'EAN128C': { // EAN 128 C
  235. if (strtoupper($type)=='C128A') { $arrcode = $this->barcode_c128($code, 'A'); }
  236. if (strtoupper($type)=='C128B') { $arrcode = $this->barcode_c128($code, 'B'); }
  237. if (strtoupper($type)=='C128C') { $arrcode = $this->barcode_c128($code, 'C'); }
  238. if (strtoupper($type)=='EAN128A') { $arrcode = $this->barcode_c128($code, 'A', true); }
  239. if (strtoupper($type)=='EAN128B') { $arrcode = $this->barcode_c128($code, 'B', true); }
  240. if (strtoupper($type)=='EAN128C') { $arrcode = $this->barcode_c128($code, 'C', true); }
  241. if ($arrcode == false) { break; }
  242. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  243. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  244. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  245. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  246. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  247. break;
  248. }
  249. case 'C39': // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
  250. case 'C39+': // CODE 39 with checksum
  251. case 'C39E': // CODE 39 EXTENDED
  252. case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM
  253. if ($pr > 0) { $this->print_ratio = $pr; }
  254. else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
  255. $code = str_replace(chr(194).chr(160), ' ', $code); // mPDF 5.3.95 (for utf-8 encoded)
  256. $code = str_replace(chr(160), ' ', $code); // mPDF 5.3.95 (for win-1252)
  257. if (strtoupper($type)=='C39') { $arrcode = $this->barcode_code39($code, false, false); }
  258. if (strtoupper($type)=='C39+') { $arrcode = $this->barcode_code39($code, false, true); }
  259. if (strtoupper($type)=='C39E') { $arrcode = $this->barcode_code39($code, true, false); }
  260. if (strtoupper($type)=='C39E+') { $arrcode = $this->barcode_code39($code, true, true); }
  261. if ($arrcode == false) { break; }
  262. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  263. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  264. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  265. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  266. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  267. break;
  268. }
  269. case 'S25': // Standard 2 of 5
  270. case 'S25+': { // Standard 2 of 5 + CHECKSUM
  271. if ($pr > 0) { $this->print_ratio = $pr; }
  272. else { $this->print_ratio = 3; } // spec: Pr=1:3/1:4.5
  273. if (strtoupper($type)=='S25') { $arrcode = $this->barcode_s25($code, false); }
  274. if (strtoupper($type)=='S25+') { $arrcode = $this->barcode_s25($code, true); }
  275. if ($arrcode == false) { break; }
  276. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  277. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  278. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  279. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  280. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  281. break;
  282. }
  283. case 'I25': // Interleaved 2 of 5
  284. case 'I25+': { // Interleaved 2 of 5 + CHECKSUM
  285. if ($pr > 0) { $this->print_ratio = $pr; }
  286. else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
  287. if (strtoupper($type)=='I25') { $arrcode = $this->barcode_i25($code, false); }
  288. if (strtoupper($type)=='I25+') { $arrcode = $this->barcode_i25($code, true); }
  289. if ($arrcode == false) { break; }
  290. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  291. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  292. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  293. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  294. $arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
  295. break;
  296. }
  297. case 'I25B': // Interleaved 2 of 5 + Bearer bars
  298. case 'I25B+': { // Interleaved 2 of 5 + CHECKSUM + Bearer bars
  299. if ($pr > 0) { $this->print_ratio = $pr; }
  300. else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
  301. if (strtoupper($type)=='I25B') { $arrcode = $this->barcode_i25($code, false); }
  302. if (strtoupper($type)=='I25B+') { $arrcode = $this->barcode_i25($code, true); }
  303. if ($arrcode == false) { break; }
  304. $arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
  305. $arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
  306. $arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
  307. $arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
  308. $arrcode['lightTB'] = 2; // TOP/BOTTOM light margin = x X-dim (non-spec.) - used for bearer bars
  309. break;
  310. }
  311. default: {
  312. $this->barcode_array = false;
  313. }
  314. }
  315. $this->barcode_array = $arrcode;
  316. }
  317. /**
  318. * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
  319. */
  320. protected function barcode_code39($code, $extended=false, $checksum=false) {
  321. $chr['0'] = '111221211';
  322. $chr['1'] = '211211112';
  323. $chr['2'] = '112211112';
  324. $chr['3'] = '212211111';
  325. $chr['4'] = '111221112';
  326. $chr['5'] = '211221111';
  327. $chr['6'] = '112221111';
  328. $chr['7'] = '111211212';
  329. $chr['8'] = '211211211';
  330. $chr['9'] = '112211211';
  331. $chr['A'] = '211112112';
  332. $chr['B'] = '112112112';
  333. $chr['C'] = '212112111';
  334. $chr['D'] = '111122112';
  335. $chr['E'] = '211122111';
  336. $chr['F'] = '112122111';
  337. $chr['G'] = '111112212';
  338. $chr['H'] = '211112211';
  339. $chr['I'] = '112112211';
  340. $chr['J'] = '111122211';
  341. $chr['K'] = '211111122';
  342. $chr['L'] = '112111122';
  343. $chr['M'] = '212111121';
  344. $chr['N'] = '111121122';
  345. $chr['O'] = '211121121';
  346. $chr['P'] = '112121121';
  347. $chr['Q'] = '111111222';
  348. $chr['R'] = '211111221';
  349. $chr['S'] = '112111221';
  350. $chr['T'] = '111121221';
  351. $chr['U'] = '221111112';
  352. $chr['V'] = '122111112';
  353. $chr['W'] = '222111111';
  354. $chr['X'] = '121121112';
  355. $chr['Y'] = '221121111';
  356. $chr['Z'] = '122121111';
  357. $chr['-'] = '121111212';
  358. $chr['.'] = '221111211';
  359. $chr[' '] = '122111211';
  360. $chr['$'] = '121212111';
  361. $chr['/'] = '121211121';
  362. $chr['+'] = '121112121';
  363. $chr['%'] = '111212121';
  364. $chr['*'] = '121121211';
  365. $code = strtoupper($code);
  366. if ($extended) {
  367. // extended mode
  368. $code = $this->encode_code39_ext($code);
  369. }
  370. if ($code === false) {
  371. return false;
  372. }
  373. if ($checksum) {
  374. // checksum
  375. $checkdigit = $this->checksum_code39($code);
  376. $code .= $checkdigit ;
  377. }
  378. // add start and stop codes
  379. $code = '*'.$code.'*';
  380. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  381. $k = 0;
  382. $clen = strlen($code);
  383. for ($i = 0; $i < $clen; ++$i) {
  384. $char = $code[$i];
  385. if(!isset($chr[$char])) {
  386. // invalid character
  387. return false;
  388. }
  389. for ($j = 0; $j < 9; ++$j) {
  390. if (($j % 2) == 0) {
  391. $t = true; // bar
  392. } else {
  393. $t = false; // space
  394. }
  395. $x = $chr[$char][$j];
  396. if ($x == 2) { $w = $this->print_ratio; }
  397. else { $w = 1; }
  398. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  399. $bararray['maxw'] += $w;
  400. ++$k;
  401. }
  402. $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
  403. $bararray['maxw'] += 1;
  404. ++$k;
  405. }
  406. $bararray['checkdigit'] = $checkdigit;
  407. return $bararray;
  408. }
  409. /**
  410. * Encode a string to be used for CODE 39 Extended mode.
  411. */
  412. protected function encode_code39_ext($code) {
  413. $encode = array(
  414. chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
  415. chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
  416. chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
  417. chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
  418. chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
  419. chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
  420. chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
  421. chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
  422. chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
  423. chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
  424. chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
  425. chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
  426. chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
  427. chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
  428. chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
  429. chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
  430. chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
  431. chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
  432. chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
  433. chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
  434. chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
  435. chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
  436. chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
  437. chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
  438. chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
  439. chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
  440. chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
  441. chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
  442. chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
  443. chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
  444. chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
  445. chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
  446. $code_ext = '';
  447. $clen = strlen($code);
  448. for ($i = 0 ; $i < $clen; ++$i) {
  449. if (ord($code[$i]) > 127) {
  450. return false;
  451. }
  452. $code_ext .= $encode[$code[$i]];
  453. }
  454. return $code_ext;
  455. }
  456. /**
  457. * Calculate CODE 39 checksum (modulo 43).
  458. */
  459. protected function checksum_code39($code) {
  460. $chars = array(
  461. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  462. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  463. 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  464. 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
  465. $sum = 0;
  466. $clen = strlen($code);
  467. for ($i = 0 ; $i < $clen; ++$i) {
  468. $k = array_keys($chars, $code[$i]);
  469. $sum += $k[0];
  470. }
  471. $j = ($sum % 43);
  472. return $chars[$j];
  473. }
  474. /**
  475. * CODE 93 - USS-93
  476. * Compact code similar to Code 39
  477. */
  478. protected function barcode_code93($code) {
  479. $chr['0'] = '131112';
  480. $chr['1'] = '111213';
  481. $chr['2'] = '111312';
  482. $chr['3'] = '111411';
  483. $chr['4'] = '121113';
  484. $chr['5'] = '121212';
  485. $chr['6'] = '121311';
  486. $chr['7'] = '111114';
  487. $chr['8'] = '131211';
  488. $chr['9'] = '141111';
  489. $chr['A'] = '211113';
  490. $chr['B'] = '211212';
  491. $chr['C'] = '211311';
  492. $chr['D'] = '221112';
  493. $chr['E'] = '221211';
  494. $chr['F'] = '231111';
  495. $chr['G'] = '112113';
  496. $chr['H'] = '112212';
  497. $chr['I'] = '112311';
  498. $chr['J'] = '122112';
  499. $chr['K'] = '132111';
  500. $chr['L'] = '111123';
  501. $chr['M'] = '111222';
  502. $chr['N'] = '111321';
  503. $chr['O'] = '121122';
  504. $chr['P'] = '131121';
  505. $chr['Q'] = '212112';
  506. $chr['R'] = '212211';
  507. $chr['S'] = '211122';
  508. $chr['T'] = '211221';
  509. $chr['U'] = '221121';
  510. $chr['V'] = '222111';
  511. $chr['W'] = '112122';
  512. $chr['X'] = '112221';
  513. $chr['Y'] = '122121';
  514. $chr['Z'] = '123111';
  515. $chr['-'] = '121131';
  516. $chr['.'] = '311112';
  517. $chr[' '] = '311211';
  518. $chr['$'] = '321111';
  519. $chr['/'] = '112131';
  520. $chr['+'] = '113121';
  521. $chr['%'] = '211131';
  522. $chr[128] = '121221'; // ($)
  523. $chr[129] = '311121'; // (/)
  524. $chr[130] = '122211'; // (+)
  525. $chr[131] = '312111'; // (%)
  526. $chr['*'] = '111141';
  527. $code = strtoupper($code);
  528. $encode = array(
  529. chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C',
  530. chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G',
  531. chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K',
  532. chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O',
  533. chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S',
  534. chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W',
  535. chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A',
  536. chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E',
  537. chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C',
  538. chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G',
  539. chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K',
  540. chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O',
  541. chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
  542. chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
  543. chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F',
  544. chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J',
  545. chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
  546. chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
  547. chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
  548. chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
  549. chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
  550. chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
  551. chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K',
  552. chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O',
  553. chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C',
  554. chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G',
  555. chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K',
  556. chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O',
  557. chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S',
  558. chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W',
  559. chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P',
  560. chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T');
  561. $code_ext = '';
  562. $clen = strlen($code);
  563. for ($i = 0 ; $i < $clen; ++$i) {
  564. if (ord($code[$i]) > 127) {
  565. return false;
  566. }
  567. $code_ext .= $encode[$code[$i]];
  568. }
  569. // checksum
  570. $checkdigit = $this->checksum_code93($code);
  571. $code .= $checkdigit ;
  572. // add start and stop codes
  573. $code = '*'.$code.'*';
  574. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  575. $k = 0;
  576. $clen = strlen($code);
  577. for ($i = 0; $i < $clen; ++$i) {
  578. $char = $code[$i];
  579. if(!isset($chr[$char])) {
  580. // invalid character
  581. return false;
  582. }
  583. for ($j = 0; $j < 6; ++$j) {
  584. if (($j % 2) == 0) {
  585. $t = true; // bar
  586. } else {
  587. $t = false; // space
  588. }
  589. $w = $chr[$char][$j];
  590. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  591. $bararray['maxw'] += $w;
  592. ++$k;
  593. }
  594. }
  595. $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
  596. $bararray['maxw'] += 1;
  597. ++$k;
  598. $bararray['checkdigit'] = $checkdigit;
  599. return $bararray;
  600. }
  601. /**
  602. * Calculate CODE 93 checksum (modulo 47).
  603. */
  604. protected function checksum_code93($code) {
  605. $chars = array(
  606. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  607. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  608. 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  609. 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
  610. // translate special characters
  611. $code = strtr($code, chr(128).chr(129).chr(130).chr(131), '$/+%');
  612. $len = strlen($code);
  613. // calculate check digit C
  614. $p = 1;
  615. $check = 0;
  616. for ($i = ($len - 1); $i >= 0; --$i) {
  617. $k = array_keys($chars, $code[$i]);
  618. $check += ($k[0] * $p);
  619. ++$p;
  620. if ($p > 20) {
  621. $p = 1;
  622. }
  623. }
  624. $check %= 47;
  625. $c = $chars[$check];
  626. $code .= $c;
  627. // calculate check digit K
  628. $p = 1;
  629. $check = 0;
  630. for ($i = $len; $i >= 0; --$i) {
  631. $k = array_keys($chars, $code[$i]);
  632. $check += ($k[0] * $p);
  633. ++$p;
  634. if ($p > 15) {
  635. $p = 1;
  636. }
  637. }
  638. $check %= 47;
  639. $k = $chars[$check];
  640. return $c.$k;
  641. }
  642. /**
  643. * Checksum for standard 2 of 5 barcodes.
  644. */
  645. protected function checksum_s25($code) {
  646. $len = strlen($code);
  647. $sum = 0;
  648. for ($i = 0; $i < $len; $i+=2) {
  649. $sum += $code[$i];
  650. }
  651. $sum *= 3;
  652. for ($i = 1; $i < $len; $i+=2) {
  653. $sum += ($code[$i]);
  654. }
  655. $r = $sum % 10;
  656. if($r > 0) {
  657. $r = (10 - $r);
  658. }
  659. return $r;
  660. }
  661. /**
  662. * MSI.
  663. * Variation of Plessey code, with similar applications
  664. * Contains digits (0 to 9) and encodes the data only in the width of bars.
  665. */
  666. protected function barcode_msi($code, $checksum=false) {
  667. $chr['0'] = '100100100100';
  668. $chr['1'] = '100100100110';
  669. $chr['2'] = '100100110100';
  670. $chr['3'] = '100100110110';
  671. $chr['4'] = '100110100100';
  672. $chr['5'] = '100110100110';
  673. $chr['6'] = '100110110100';
  674. $chr['7'] = '100110110110';
  675. $chr['8'] = '110100100100';
  676. $chr['9'] = '110100100110';
  677. $chr['A'] = '110100110100';
  678. $chr['B'] = '110100110110';
  679. $chr['C'] = '110110100100';
  680. $chr['D'] = '110110100110';
  681. $chr['E'] = '110110110100';
  682. $chr['F'] = '110110110110';
  683. if ($checksum) {
  684. // add checksum
  685. $clen = strlen($code);
  686. $p = 2;
  687. $check = 0;
  688. for ($i = ($clen - 1); $i >= 0; --$i) {
  689. $check += (hexdec($code[$i]) * $p);
  690. ++$p;
  691. if ($p > 7) {
  692. $p = 2;
  693. }
  694. }
  695. $check %= 11;
  696. if ($check > 0) {
  697. $check = 11 - $check;
  698. }
  699. $code .= $check;
  700. $checkdigit = $check;
  701. }
  702. $seq = '110'; // left guard
  703. $clen = strlen($code);
  704. for ($i = 0; $i < $clen; ++$i) {
  705. $digit = $code[$i];
  706. if (!isset($chr[$digit])) {
  707. // invalid character
  708. return false;
  709. }
  710. $seq .= $chr[$digit];
  711. }
  712. $seq .= '1001'; // right guard
  713. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  714. $bararray['checkdigit'] = $checkdigit;
  715. return $this->binseq_to_array($seq, $bararray);
  716. }
  717. /**
  718. * Standard 2 of 5 barcodes.
  719. * Used in airline ticket marking, photofinishing
  720. * Contains digits (0 to 9) and encodes the data only in the width of bars.
  721. */
  722. protected function barcode_s25($code, $checksum=false) {
  723. $chr['0'] = '10101110111010';
  724. $chr['1'] = '11101010101110';
  725. $chr['2'] = '10111010101110';
  726. $chr['3'] = '11101110101010';
  727. $chr['4'] = '10101110101110';
  728. $chr['5'] = '11101011101010';
  729. $chr['6'] = '10111011101010';
  730. $chr['7'] = '10101011101110';
  731. $chr['8'] = '10101110111010';
  732. $chr['9'] = '10111010111010';
  733. if ($checksum) {
  734. // add checksum
  735. $checkdigit = $this->checksum_s25($code);
  736. $code .= $checkdigit ;
  737. }
  738. if((strlen($code) % 2) != 0) {
  739. // add leading zero if code-length is odd
  740. $code = '0'.$code;
  741. }
  742. $seq = '11011010';
  743. $clen = strlen($code);
  744. for ($i = 0; $i < $clen; ++$i) {
  745. $digit = $code[$i];
  746. if (!isset($chr[$digit])) {
  747. // invalid character
  748. return false;
  749. }
  750. $seq .= $chr[$digit];
  751. }
  752. $seq .= '1101011';
  753. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  754. $bararray['checkdigit'] = $checkdigit;
  755. return $this->binseq_to_array($seq, $bararray);
  756. }
  757. /**
  758. * Convert binary barcode sequence to barcode array
  759. */
  760. protected function binseq_to_array($seq, $bararray) {
  761. $len = strlen($seq);
  762. $w = 0;
  763. $k = 0;
  764. for ($i = 0; $i < $len; ++$i) {
  765. $w += 1;
  766. if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq[$i] != $seq[($i+1)]))) {
  767. if ($seq[$i] == '1') {
  768. $t = true; // bar
  769. } else {
  770. $t = false; // space
  771. }
  772. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  773. $bararray['maxw'] += $w;
  774. ++$k;
  775. $w = 0;
  776. }
  777. }
  778. return $bararray;
  779. }
  780. /**
  781. * Interleaved 2 of 5 barcodes.
  782. * Compact numeric code, widely used in industry, air cargo
  783. * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
  784. */
  785. protected function barcode_i25($code, $checksum=false) {
  786. $chr['0'] = '11221';
  787. $chr['1'] = '21112';
  788. $chr['2'] = '12112';
  789. $chr['3'] = '22111';
  790. $chr['4'] = '11212';
  791. $chr['5'] = '21211';
  792. $chr['6'] = '12211';
  793. $chr['7'] = '11122';
  794. $chr['8'] = '21121';
  795. $chr['9'] = '12121';
  796. $chr['A'] = '11';
  797. $chr['Z'] = '21';
  798. if ($checksum) {
  799. // add checksum
  800. $checkdigit = $this->checksum_s25($code);
  801. $code .= $checkdigit ;
  802. }
  803. if((strlen($code) % 2) != 0) {
  804. // add leading zero if code-length is odd
  805. $code = '0'.$code;
  806. }
  807. // add start and stop codes
  808. $code = 'AA'.strtolower($code).'ZA';
  809. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  810. $k = 0;
  811. $clen = strlen($code);
  812. for ($i = 0; $i < $clen; $i = ($i + 2)) {
  813. $char_bar = $code[$i];
  814. $char_space = $code[$i+1];
  815. if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
  816. // invalid character
  817. return false;
  818. }
  819. // create a bar-space sequence
  820. $seq = '';
  821. $chrlen = strlen($chr[$char_bar]);
  822. for ($s = 0; $s < $chrlen; $s++){
  823. $seq .= $chr[$char_bar][$s] . $chr[$char_space][$s];
  824. }
  825. $seqlen = strlen($seq);
  826. for ($j = 0; $j < $seqlen; ++$j) {
  827. if (($j % 2) == 0) {
  828. $t = true; // bar
  829. } else {
  830. $t = false; // space
  831. }
  832. $x = $seq[$j];
  833. if ($x == 2) { $w = $this->print_ratio; }
  834. else { $w = 1; }
  835. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  836. $bararray['maxw'] += $w;
  837. ++$k;
  838. }
  839. }
  840. $bararray['checkdigit'] = $checkdigit;
  841. return $bararray;
  842. }
  843. /**
  844. * C128 barcodes.
  845. * Very capable code, excellent density, high reliability; in very wide use world-wide
  846. */
  847. protected function barcode_c128($code, $type='B', $ean=false) {
  848. $chr = array(
  849. '212222', /* 00 */
  850. '222122', /* 01 */
  851. '222221', /* 02 */
  852. '121223', /* 03 */
  853. '121322', /* 04 */
  854. '131222', /* 05 */
  855. '122213', /* 06 */
  856. '122312', /* 07 */
  857. '132212', /* 08 */
  858. '221213', /* 09 */
  859. '221312', /* 10 */
  860. '231212', /* 11 */
  861. '112232', /* 12 */
  862. '122132', /* 13 */
  863. '122231', /* 14 */
  864. '113222', /* 15 */
  865. '123122', /* 16 */
  866. '123221', /* 17 */
  867. '223211', /* 18 */
  868. '221132', /* 19 */
  869. '221231', /* 20 */
  870. '213212', /* 21 */
  871. '223112', /* 22 */
  872. '312131', /* 23 */
  873. '311222', /* 24 */
  874. '321122', /* 25 */
  875. '321221', /* 26 */
  876. '312212', /* 27 */
  877. '322112', /* 28 */
  878. '322211', /* 29 */
  879. '212123', /* 30 */
  880. '212321', /* 31 */
  881. '232121', /* 32 */
  882. '111323', /* 33 */
  883. '131123', /* 34 */
  884. '131321', /* 35 */
  885. '112313', /* 36 */
  886. '132113', /* 37 */
  887. '132311', /* 38 */
  888. '211313', /* 39 */
  889. '231113', /* 40 */
  890. '231311', /* 41 */
  891. '112133', /* 42 */
  892. '112331', /* 43 */
  893. '132131', /* 44 */
  894. '113123', /* 45 */
  895. '113321', /* 46 */
  896. '133121', /* 47 */
  897. '313121', /* 48 */
  898. '211331', /* 49 */
  899. '231131', /* 50 */
  900. '213113', /* 51 */
  901. '213311', /* 52 */
  902. '213131', /* 53 */
  903. '311123', /* 54 */
  904. '311321', /* 55 */
  905. '331121', /* 56 */
  906. '312113', /* 57 */
  907. '312311', /* 58 */
  908. '332111', /* 59 */
  909. '314111', /* 60 */
  910. '221411', /* 61 */
  911. '431111', /* 62 */
  912. '111224', /* 63 */
  913. '111422', /* 64 */
  914. '121124', /* 65 */
  915. '121421', /* 66 */
  916. '141122', /* 67 */
  917. '141221', /* 68 */
  918. '112214', /* 69 */
  919. '112412', /* 70 */
  920. '122114', /* 71 */
  921. '122411', /* 72 */
  922. '142112', /* 73 */
  923. '142211', /* 74 */
  924. '241211', /* 75 */
  925. '221114', /* 76 */
  926. '413111', /* 77 */
  927. '241112', /* 78 */
  928. '134111', /* 79 */
  929. '111242', /* 80 */
  930. '121142', /* 81 */
  931. '121241', /* 82 */
  932. '114212', /* 83 */
  933. '124112', /* 84 */
  934. '124211', /* 85 */
  935. '411212', /* 86 */
  936. '421112', /* 87 */
  937. '421211', /* 88 */
  938. '212141', /* 89 */
  939. '214121', /* 90 */
  940. '412121', /* 91 */
  941. '111143', /* 92 */
  942. '111341', /* 93 */
  943. '131141', /* 94 */
  944. '114113', /* 95 */
  945. '114311', /* 96 */
  946. '411113', /* 97 */
  947. '411311', /* 98 */
  948. '113141', /* 99 */
  949. '114131', /* 100 */
  950. '311141', /* 101 */
  951. '411131', /* 102 */
  952. '211412', /* 103 START A */
  953. '211214', /* 104 START B */
  954. '211232', /* 105 START C */
  955. '233111', /* STOP */
  956. '200000' /* END */
  957. );
  958. $keys = '';
  959. switch(strtoupper($type)) {
  960. case 'A': {
  961. $startid = 103;
  962. $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
  963. for ($i = 0; $i < 32; ++$i) {
  964. $keys .= chr($i);
  965. }
  966. break;
  967. }
  968. case 'B': {
  969. $startid = 104;
  970. $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
  971. break;
  972. }
  973. case 'C': {
  974. $startid = 105;
  975. $keys = '';
  976. if ((strlen($code) % 2) != 0) {
  977. // The length of barcode value must be even ($code). You must pad the number with zeros
  978. return false;
  979. }
  980. for ($i = 0; $i <= 99; ++$i) {
  981. $keys .= chr($i);
  982. }
  983. $new_code = '';
  984. $hclen = (strlen($code) / 2);
  985. for ($i = 0; $i < $hclen; ++$i) {
  986. $new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)}));
  987. }
  988. $code = $new_code;
  989. break;
  990. }
  991. default: {
  992. return false;
  993. }
  994. }
  995. // calculate check character
  996. $sum = $startid;
  997. if ($ean) { $code = chr(102) . $code; } // Add FNC 1 - which identifies it as EAN-128
  998. $clen = strlen($code);
  999. for ($i = 0; $i < $clen; ++$i) {
  1000. if ($ean && $i==0) { $sum += 102; }
  1001. else { $sum += (strpos($keys, $code[$i]) * ($i+1)); }
  1002. }
  1003. $check = ($sum % 103);
  1004. $checkdigit = $check ;
  1005. // add start, check and stop codes
  1006. $code = chr($startid).$code.chr($check).chr(106).chr(107);
  1007. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1008. $k = 0;
  1009. $len = strlen($code);
  1010. for ($i = 0; $i < $len; ++$i) {
  1011. $ck = strpos($keys, $code[$i]);
  1012. if (($i == 0) || ($ean && $i==1) | ($i > ($len-4))) {
  1013. $char_num = ord($code[$i]);
  1014. $seq = $chr[$char_num];
  1015. } elseif(($ck >= 0) AND isset($chr[$ck])) {
  1016. $seq = $chr[$ck];
  1017. } else {
  1018. // invalid character
  1019. return false;
  1020. }
  1021. for ($j = 0; $j < 6; ++$j) {
  1022. if (($j % 2) == 0) {
  1023. $t = true; // bar
  1024. } else {
  1025. $t = false; // space
  1026. }
  1027. $w = $seq[$j];
  1028. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  1029. $bararray['maxw'] += $w;
  1030. ++$k;
  1031. }
  1032. }
  1033. $bararray['checkdigit'] = $checkdigit;
  1034. return $bararray;
  1035. }
  1036. /**
  1037. * EAN13 and UPC-A barcodes.
  1038. * EAN13: European Article Numbering international retail product code
  1039. * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
  1040. * UPC-E: Short version of UPC symbol
  1041. */
  1042. protected function barcode_eanupc($code, $len=13) {
  1043. $upce = false;
  1044. $checkdigit = false;
  1045. if ($len == 6) {
  1046. $len = 12; // UPC-A
  1047. $upce = true; // UPC-E mode
  1048. }
  1049. $data_len = $len - 1;
  1050. //Padding
  1051. $code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
  1052. $code_len = strlen($code);
  1053. // calculate check digit
  1054. $sum_a = 0;
  1055. for ($i = 1; $i < $data_len; $i+=2) {
  1056. $sum_a += $code[$i];
  1057. }
  1058. if ($len > 12) {
  1059. $sum_a *= 3;
  1060. }
  1061. $sum_b = 0;
  1062. for ($i = 0; $i < $data_len; $i+=2) {
  1063. $sum_b += ($code[$i]);
  1064. }
  1065. if ($len < 13) {
  1066. $sum_b *= 3;
  1067. }
  1068. $r = ($sum_a + $sum_b) % 10;
  1069. if($r > 0) {
  1070. $r = (10 - $r);
  1071. }
  1072. if ($code_len == $data_len) {
  1073. // add check digit
  1074. $code .= $r;
  1075. $checkdigit = $r;
  1076. } elseif ($r !== intval($code[$data_len])) {
  1077. // wrong checkdigit
  1078. return false;
  1079. }
  1080. if ($len == 12) {
  1081. // UPC-A
  1082. $code = '0'.$code;
  1083. ++$len;
  1084. }
  1085. if ($upce) {
  1086. // convert UPC-A to UPC-E
  1087. $tmp = substr($code, 4, 3);
  1088. $prod_code = intval(substr($code,7,5)); // product code
  1089. $invalid_upce = false;
  1090. if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
  1091. // manufacturer code ends in 000, 100, or 200
  1092. $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1);
  1093. if ($prod_code > 999) { $invalid_upce = true; }
  1094. } else {
  1095. $tmp = substr($code, 5, 2);
  1096. if ($tmp == '00') {
  1097. // manufacturer code ends in 00
  1098. $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3';
  1099. if ($prod_code > 99) { $invalid_upce = true; }
  1100. } else {
  1101. $tmp = substr($code, 6, 1);
  1102. if ($tmp == '0') {
  1103. // manufacturer code ends in 0
  1104. $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4';
  1105. if ($prod_code > 9) { $invalid_upce = true; }
  1106. } else {
  1107. // manufacturer code does not end in zero
  1108. $upce_code = substr($code, 2, 5).substr($code, 11, 1);
  1109. if ($prod_code > 9) { $invalid_upce = true; }
  1110. }
  1111. }
  1112. }
  1113. if ($invalid_upce) { die("Error - UPC-A cannot produce a valid UPC-E barcode"); } // Error generating a UPCE code
  1114. }
  1115. //Convert digits to bars
  1116. $codes = array(
  1117. 'A'=>array( // left odd parity
  1118. '0'=>'0001101',
  1119. '1'=>'0011001',
  1120. '2'=>'0010011',
  1121. '3'=>'0111101',
  1122. '4'=>'0100011',
  1123. '5'=>'0110001',
  1124. '6'=>'0101111',
  1125. '7'=>'0111011',
  1126. '8'=>'0110111',
  1127. '9'=>'0001011'),
  1128. 'B'=>array( // left even parity
  1129. '0'=>'0100111',
  1130. '1'=>'0110011',
  1131. '2'=>'0011011',
  1132. '3'=>'0100001',
  1133. '4'=>'0011101',
  1134. '5'=>'0111001',
  1135. '6'=>'0000101',
  1136. '7'=>'0010001',
  1137. '8'=>'0001001',
  1138. '9'=>'0010111'),
  1139. 'C'=>array( // right
  1140. '0'=>'1110010',
  1141. '1'=>'1100110',
  1142. '2'=>'1101100',
  1143. '3'=>'1000010',
  1144. '4'=>'1011100',
  1145. '5'=>'1001110',
  1146. '6'=>'1010000',
  1147. '7'=>'1000100',
  1148. '8'=>'1001000',
  1149. '9'=>'1110100')
  1150. );
  1151. $parities = array(
  1152. '0'=>array('A','A','A','A','A','A'),
  1153. '1'=>array('A','A','B','A','B','B'),
  1154. '2'=>array('A','A','B','B','A','B'),
  1155. '3'=>array('A','A','B','B','B','A'),
  1156. '4'=>array('A','B','A','A','B','B'),
  1157. '5'=>array('A','B','B','A','A','B'),
  1158. '6'=>array('A','B','B','B','A','A'),
  1159. '7'=>array('A','B','A','B','A','B'),
  1160. '8'=>array('A','B','A','B','B','A'),
  1161. '9'=>array('A','B','B','A','B','A')
  1162. );
  1163. $upce_parities = array();
  1164. $upce_parities[0] = array(
  1165. '0'=>array('B','B','B','A','A','A'),
  1166. '1'=>array('B','B','A','B','A','A'),
  1167. '2'=>array('B','B','A','A','B','A'),
  1168. '3'=>array('B','B','A','A','A','B'),
  1169. '4'=>array('B','A','B','B','A','A'),
  1170. '5'=>array('B','A','A','B','B','A'),
  1171. '6'=>array('B','A','A','A','B','B'),
  1172. '7'=>array('B','A','B','A','B','A'),
  1173. '8'=>array('B','A','B','A','A','B'),
  1174. '9'=>array('B','A','A','B','A','B')
  1175. );
  1176. $upce_parities[1] = array(
  1177. '0'=>array('A','A','A','B','B','B'),
  1178. '1'=>array('A','A','B','A','B','B'),
  1179. '2'=>array('A','A','B','B','A','B'),
  1180. '3'=>array('A','A','B','B','B','A'),
  1181. '4'=>array('A','B','A','A','B','B'),
  1182. '5'=>array('A','B','B','A','A','B'),
  1183. '6'=>array('A','B','B','B','A','A'),
  1184. '7'=>array('A','B','A','B','A','B'),
  1185. '8'=>array('A','B','A','B','B','A'),
  1186. '9'=>array('A','B','B','A','B','A')
  1187. );
  1188. $k = 0;
  1189. $seq = '101'; // left guard bar
  1190. if ($upce) {
  1191. $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1192. $p = $upce_parities[$code{1}][$r];
  1193. for ($i = 0; $i < 6; ++$i) {
  1194. $seq .= $codes[$p[$i]][$upce_code[$i]];
  1195. }
  1196. $seq .= '010101'; // right guard bar
  1197. } else {
  1198. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1199. $half_len = ceil($len / 2);
  1200. if ($len == 8) {
  1201. for ($i = 0; $i < $half_len; ++$i) {
  1202. $seq .= $codes['A'][$code[$i]];
  1203. }
  1204. } else {
  1205. $p = $parities[$code{0}];
  1206. for ($i = 1; $i < $half_len; ++$i) {
  1207. $seq .= $codes[$p[$i-1]][$code[$i]];
  1208. }
  1209. }
  1210. $seq .= '01010'; // center guard bar
  1211. for ($i = $half_len; $i < $len; ++$i) {
  1212. $seq .= $codes['C'][$code[$i]];
  1213. }
  1214. $seq .= '101'; // right guard bar
  1215. }
  1216. $clen = strlen($seq);
  1217. $w = 0;
  1218. for ($i = 0; $i < $clen; ++$i) {
  1219. $w += 1;
  1220. if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq[$i] != $seq[($i+1)]))) {
  1221. if ($seq[$i] == '1') {
  1222. $t = true; // bar
  1223. } else {
  1224. $t = false; // space
  1225. }
  1226. $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
  1227. $bararray['maxw'] += $w;
  1228. ++$k;
  1229. $w = 0;
  1230. }
  1231. }
  1232. $bararray['checkdigit'] = $checkdigit;
  1233. return $bararray;
  1234. }
  1235. /**
  1236. * UPC-Based Extentions
  1237. * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers
  1238. * 5-Digit Ext.: Used to mark suggested retail price of books
  1239. */
  1240. protected function barcode_eanext($code, $len=5) {
  1241. //Padding
  1242. $code = str_pad($code, $len, '0', STR_PAD_LEFT);
  1243. // calculate check digit
  1244. if ($len == 2) {
  1245. $r = $code % 4;
  1246. } elseif ($len == 5) {
  1247. $r = (3 * ($code{0} + $code{2} + $code{4})) + (9 * ($code{1} + $code{3}));
  1248. $r %= 10;
  1249. } else {
  1250. return false;
  1251. }
  1252. //Convert digits to bars
  1253. $codes = array(
  1254. 'A'=>array( // left odd parity
  1255. '0'=>'0001101',
  1256. '1'=>'0011001',
  1257. '2'=>'0010011',
  1258. '3'=>'0111101',
  1259. '4'=>'0100011',
  1260. '5'=>'0110001',
  1261. '6'=>'0101111',
  1262. '7'=>'0111011',
  1263. '8'=>'0110111',
  1264. '9'=>'0001011'),
  1265. 'B'=>array( // left even parity
  1266. '0'=>'0100111',
  1267. '1'=>'0110011',
  1268. '2'=>'0011011',
  1269. '3'=>'0100001',
  1270. '4'=>'0011101',
  1271. '5'=>'0111001',
  1272. '6'=>'0000101',
  1273. '7'=>'0010001',
  1274. '8'=>'0001001',
  1275. '9'=>'0010111')
  1276. );
  1277. $parities = array();
  1278. $parities[2] = array(
  1279. '0'=>array('A','A'),
  1280. '1'=>array('A','B'),
  1281. '2'=>array('B','A'),
  1282. '3'=>array('B','B')
  1283. );
  1284. $parities[5] = array(
  1285. '0'=>array('B','B','A','A','A'),
  1286. '1'=>array('B','A','B','A','A'),
  1287. '2'=>array('B','A','A','B','A'),
  1288. '3'=>array('B','A','A','A','B'),
  1289. '4'=>array('A','B','B','A','A'),
  1290. '5'=>array('A','A','B','B','A'),
  1291. '6'=>array('A','A','A','B','B'),
  1292. '7'=>array('A','B','A','B','A'),
  1293. '8'=>array('A','B','A','A','B'),
  1294. '9'=>array('A','A','B','A','B')
  1295. );
  1296. $p = $parities[$len][$r];
  1297. $seq = '1011'; // left guard bar
  1298. $seq .= $codes[$p[0]][$code{0}];
  1299. for ($i = 1; $i < $len; ++$i) {
  1300. $seq .= '01'; // separator
  1301. $seq .= $codes[$p[$i]][$code[$i]];
  1302. }
  1303. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
  1304. return $this->binseq_to_array($seq, $bararray);
  1305. }
  1306. /**
  1307. * POSTNET and PLANET barcodes.
  1308. * Used by U.S. Postal Service for automated mail sorting
  1309. */
  1310. protected function barcode_postnet($code, $planet=false) {
  1311. // bar lenght
  1312. if ($planet) {
  1313. $barlen = Array(
  1314. 0 => Array(1,1,2,2,2),
  1315. 1 => Array(2,2,2,1,1),
  1316. 2 => Array(2,2,1,2,1),
  1317. 3 => Array(2,2,1,1,2),
  1318. 4 => Array(2,1,2,2,1),
  1319. 5 => Array(2,1,2,1,2),
  1320. 6 => Array(2,1,1,2,2),
  1321. 7 => Array(1,2,2,2,1),
  1322. 8 => Array(1,2,2,1,2),
  1323. 9 => Array(1,2,1,2,2)
  1324. );
  1325. } else {
  1326. $barlen = Array(
  1327. 0 => Array(2,2,1,1,1),
  1328. 1 => Array(1,1,1,2,2),
  1329. 2 => Array(1,1,2,1,2),
  1330. 3 => Array(1,1,2,2,1),
  1331. 4 => Array(1,2,1,1,2),
  1332. 5 => Array(1,2,1,2,1),
  1333. 6 => Array(1,2,2,1,1),
  1334. 7 => Array(2,1,1,1,2),
  1335. 8 => Array(2,1,1,2,1),
  1336. 9 => Array(2,1,2,1,1)
  1337. );
  1338. }
  1339. $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 5, 'bcode' => array());
  1340. $k = 0;
  1341. $code = str_replace('-', '', $code);
  1342. $code = str_replace(' ', '', $code);
  1343. $len = strlen($code);
  1344. // calculate checksum
  1345. $sum = 0;
  1346. for ($i = 0; $i < $len; ++$i) {
  1347. $sum += intval($code[$i]);
  1348. }
  1349. $chkd = ($sum % 10);
  1350. if($chkd > 0) {
  1351. $chkd = (10 - $chkd);
  1352. }
  1353. $code .= $chkd;
  1354. $checkdigit = $chkd;
  1355. $len = strlen($code);
  1356. // start bar
  1357. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 5, 'p' => 0);
  1358. $bararray['bcode'][$k++] = array('t' => 0, 'w' => $this->gapwidth , 'h' => 5, 'p' => 0);
  1359. $bararray['maxw'] += (1 + $this->gapwidth );
  1360. for ($i = 0; $i < $len; ++$i) {
  1361. for ($j = 0; $j < 5; ++$j) {
  1362. $bh = $barlen[$code[$i]][$j];
  1363. if ($bh == 2) {
  1364. $h = 5;
  1365. $p = 0;
  1366. }
  1367. else {
  1368. $h = 2;
  1369. $p = 3;
  1370. }
  1371. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
  1372. $bararray['bcode'][$k++] = array('t' => 0, 'w' => $this->gapwidth , 'h' => 2, 'p' => 0);
  1373. $bararray['maxw'] += (1 + $this->gapwidth );
  1374. }
  1375. }
  1376. // end bar
  1377. $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 5, 'p' => 0);
  1378. $bararray['maxw'] += 1;
  1379. $bararray['checkdigit'] = $checkdigit;
  1380. return $bararray;
  1381. }
  1382. /**
  1383. * RM4SCC - CBC - KIX
  1384. * RM4SCC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index)
  1385. * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service.
  1386. */
  1387. protected function barcode_rm4scc($code, $kix=false) {
  1388. $notkix = !$kix;
  1389. // bar mode
  1390. // 1 = pos 1, length 2
  1391. // 2 = pos 1, length 3
  1392. // 3 = pos 2, length 1
  1393. // 4 = pos 2, length 2
  1394. $barmode = array(
  1395. '0' => array(3,3,2,2),
  1396. '1' => array(3,4,1,2),
  1397. '2' => array(3,4,2,1),
  1398. '3' => array(4,3,1,2),
  1399. '4' => array(4,3,2,1),
  1400. '5' => array(4,4,1,1),
  1401. '6' => array(3,1,4,2),
  1402. '7' => array(3,2,3,2),
  1403. '8' => array(3,2,4,1),
  1404. '9' => array(4,1,3,2),
  1405. 'A' => array(4,1,4,1),
  1406. 'B' => array(4,2,3,1),
  1407. 'C' => array(3,1,2,4),
  1408. 'D' => array(3,2,1,4),
  1409. 'E' => array(3,2,2,3),
  1410. 'F' => array(4,1,1,4),
  1411. 'G' => array(4,1,2,3),
  1412. 'H' => array(4,2,1,3),
  1413. 'I' => array(1,3,4,2),
  1414. 'J' => array(1,4,3,2),
  1415. 'K' => array(1,4,4,1),
  1416. 'L' => array(2,3,3,2),
  1417. 'M' => array(2,3,4,1),
  1418. 'N' => array(2,4,3,1),
  1419. 'O' => array(1,3,2,4),
  1420. 'P' => array(1,4,1,4),
  1421. 'Q' => array(1,4,2,3),
  1422. 'R' => array(2,3,1,4),
  1423. 'S' => array(2,3,2,3),
  1424. 'T' => array(2,4,1,3),
  1425. 'U' => array(1,1,4,4),
  1426. 'V' => array(1,2,3,4),
  1427. 'W' => array(1,2,4,3),
  1428. 'X' => array(2,1,3,4),
  1429. 'Y' =

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