|
|
1
|
+<?php
|
|
|
2
|
+
|
|
|
3
|
+/**
|
|
|
4
|
+ * General PHP Barcode Generator
|
|
|
5
|
+ *
|
|
|
6
|
+ * @author Casper Bakker - picqer.com
|
|
|
7
|
+ * Based on TCPDF Barcode Generator
|
|
|
8
|
+ */
|
|
|
9
|
+
|
|
|
10
|
+// Copyright (C) 2002-2015 Nicola Asuni - Tecnick.com LTD
|
|
|
11
|
+//
|
|
|
12
|
+// This file is part of TCPDF software library.
|
|
|
13
|
+//
|
|
|
14
|
+// TCPDF is free software: you can redistribute it and/or modify it
|
|
|
15
|
+// under the terms of the GNU Lesser General Public License as
|
|
|
16
|
+// published by the Free Software Foundation, either version 3 of the
|
|
|
17
|
+// License, or (at your option) any later version.
|
|
|
18
|
+//
|
|
|
19
|
+// TCPDF is distributed in the hope that it will be useful, but
|
|
|
20
|
+// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
21
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
22
|
+// See the GNU Lesser General Public License for more details.
|
|
|
23
|
+//
|
|
|
24
|
+// You should have received a copy of the License
|
|
|
25
|
+// along with TCPDF. If not, see
|
|
|
26
|
+// <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>.
|
|
|
27
|
+//
|
|
|
28
|
+// See LICENSE.TXT file for more information.
|
|
|
29
|
+
|
|
|
30
|
+namespace Picqer\Barcode;
|
|
|
31
|
+
|
|
|
32
|
+use Picqer\Barcode\Exceptions\BarcodeException;
|
|
|
33
|
+use Picqer\Barcode\Exceptions\InvalidCharacterException;
|
|
|
34
|
+use Picqer\Barcode\Exceptions\InvalidCheckDigitException;
|
|
|
35
|
+use Picqer\Barcode\Exceptions\InvalidFormatException;
|
|
|
36
|
+use Picqer\Barcode\Exceptions\InvalidLengthException;
|
|
|
37
|
+use Picqer\Barcode\Exceptions\UnknownTypeException;
|
|
|
38
|
+
|
|
|
39
|
+abstract class BarcodeGenerator
|
|
|
40
|
+{
|
|
|
41
|
+ const TYPE_CODE_39 = 'C39';
|
|
|
42
|
+ const TYPE_CODE_39_CHECKSUM = 'C39+';
|
|
|
43
|
+ const TYPE_CODE_39E = 'C39E';
|
|
|
44
|
+ const TYPE_CODE_39E_CHECKSUM = 'C39E+';
|
|
|
45
|
+ const TYPE_CODE_93 = 'C93';
|
|
|
46
|
+ const TYPE_STANDARD_2_5 = 'S25';
|
|
|
47
|
+ const TYPE_STANDARD_2_5_CHECKSUM = 'S25+';
|
|
|
48
|
+ const TYPE_INTERLEAVED_2_5 = 'I25';
|
|
|
49
|
+ const TYPE_INTERLEAVED_2_5_CHECKSUM = 'I25+';
|
|
|
50
|
+ const TYPE_CODE_128 = 'C128';
|
|
|
51
|
+ const TYPE_CODE_128_A = 'C128A';
|
|
|
52
|
+ const TYPE_CODE_128_B = 'C128B';
|
|
|
53
|
+ const TYPE_CODE_128_C = 'C128C';
|
|
|
54
|
+ const TYPE_EAN_2 = 'EAN2';
|
|
|
55
|
+ const TYPE_EAN_5 = 'EAN5';
|
|
|
56
|
+ const TYPE_EAN_8 = 'EAN8';
|
|
|
57
|
+ const TYPE_EAN_13 = 'EAN13';
|
|
|
58
|
+ const TYPE_UPC_A = 'UPCA';
|
|
|
59
|
+ const TYPE_UPC_E = 'UPCE';
|
|
|
60
|
+ const TYPE_MSI = 'MSI';
|
|
|
61
|
+ const TYPE_MSI_CHECKSUM = 'MSI+';
|
|
|
62
|
+ const TYPE_POSTNET = 'POSTNET';
|
|
|
63
|
+ const TYPE_PLANET = 'PLANET';
|
|
|
64
|
+ const TYPE_RMS4CC = 'RMS4CC';
|
|
|
65
|
+ const TYPE_KIX = 'KIX';
|
|
|
66
|
+ const TYPE_IMB = 'IMB';
|
|
|
67
|
+ const TYPE_CODABAR = 'CODABAR';
|
|
|
68
|
+ const TYPE_CODE_11 = 'CODE11';
|
|
|
69
|
+ const TYPE_PHARMA_CODE = 'PHARMA';
|
|
|
70
|
+ const TYPE_PHARMA_CODE_TWO_TRACKS = 'PHARMA2T';
|
|
|
71
|
+
|
|
|
72
|
+ /**
|
|
|
73
|
+ * Get the barcode data
|
|
|
74
|
+ *
|
|
|
75
|
+ * @param string $code code to print
|
|
|
76
|
+ * @param string $type type of barcode
|
|
|
77
|
+ * @return array barcode array
|
|
|
78
|
+ * @public
|
|
|
79
|
+ */
|
|
|
80
|
+ protected function getBarcodeData($code, $type)
|
|
|
81
|
+ {
|
|
|
82
|
+ switch (strtoupper($type)) {
|
|
|
83
|
+ case self::TYPE_CODE_39: { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
|
|
|
84
|
+ $arrcode = $this->barcode_code39($code, false, false);
|
|
|
85
|
+ break;
|
|
|
86
|
+ }
|
|
|
87
|
+ case self::TYPE_CODE_39_CHECKSUM: { // CODE 39 with checksum
|
|
|
88
|
+ $arrcode = $this->barcode_code39($code, false, true);
|
|
|
89
|
+ break;
|
|
|
90
|
+ }
|
|
|
91
|
+ case self::TYPE_CODE_39E: { // CODE 39 EXTENDED
|
|
|
92
|
+ $arrcode = $this->barcode_code39($code, true, false);
|
|
|
93
|
+ break;
|
|
|
94
|
+ }
|
|
|
95
|
+ case self::TYPE_CODE_39E_CHECKSUM: { // CODE 39 EXTENDED + CHECKSUM
|
|
|
96
|
+ $arrcode = $this->barcode_code39($code, true, true);
|
|
|
97
|
+ break;
|
|
|
98
|
+ }
|
|
|
99
|
+ case self::TYPE_CODE_93: { // CODE 93 - USS-93
|
|
|
100
|
+ $arrcode = $this->barcode_code93($code);
|
|
|
101
|
+ break;
|
|
|
102
|
+ }
|
|
|
103
|
+ case self::TYPE_STANDARD_2_5: { // Standard 2 of 5
|
|
|
104
|
+ $arrcode = $this->barcode_s25($code, false);
|
|
|
105
|
+ break;
|
|
|
106
|
+ }
|
|
|
107
|
+ case self::TYPE_STANDARD_2_5_CHECKSUM: { // Standard 2 of 5 + CHECKSUM
|
|
|
108
|
+ $arrcode = $this->barcode_s25($code, true);
|
|
|
109
|
+ break;
|
|
|
110
|
+ }
|
|
|
111
|
+ case self::TYPE_INTERLEAVED_2_5: { // Interleaved 2 of 5
|
|
|
112
|
+ $arrcode = $this->barcode_i25($code, false);
|
|
|
113
|
+ break;
|
|
|
114
|
+ }
|
|
|
115
|
+ case self::TYPE_INTERLEAVED_2_5_CHECKSUM: { // Interleaved 2 of 5 + CHECKSUM
|
|
|
116
|
+ $arrcode = $this->barcode_i25($code, true);
|
|
|
117
|
+ break;
|
|
|
118
|
+ }
|
|
|
119
|
+ case self::TYPE_CODE_128: { // CODE 128
|
|
|
120
|
+ $arrcode = $this->barcode_c128($code, '');
|
|
|
121
|
+ break;
|
|
|
122
|
+ }
|
|
|
123
|
+ case self::TYPE_CODE_128_A: { // CODE 128 A
|
|
|
124
|
+ $arrcode = $this->barcode_c128($code, 'A');
|
|
|
125
|
+ break;
|
|
|
126
|
+ }
|
|
|
127
|
+ case self::TYPE_CODE_128_B: { // CODE 128 B
|
|
|
128
|
+ $arrcode = $this->barcode_c128($code, 'B');
|
|
|
129
|
+ break;
|
|
|
130
|
+ }
|
|
|
131
|
+ case self::TYPE_CODE_128_C: { // CODE 128 C
|
|
|
132
|
+ $arrcode = $this->barcode_c128($code, 'C');
|
|
|
133
|
+ break;
|
|
|
134
|
+ }
|
|
|
135
|
+ case self::TYPE_EAN_2: { // 2-Digits UPC-Based Extention
|
|
|
136
|
+ $arrcode = $this->barcode_eanext($code, 2);
|
|
|
137
|
+ break;
|
|
|
138
|
+ }
|
|
|
139
|
+ case self::TYPE_EAN_5: { // 5-Digits UPC-Based Extention
|
|
|
140
|
+ $arrcode = $this->barcode_eanext($code, 5);
|
|
|
141
|
+ break;
|
|
|
142
|
+ }
|
|
|
143
|
+ case self::TYPE_EAN_8: { // EAN 8
|
|
|
144
|
+ $arrcode = $this->barcode_eanupc($code, 8);
|
|
|
145
|
+ break;
|
|
|
146
|
+ }
|
|
|
147
|
+ case self::TYPE_EAN_13: { // EAN 13
|
|
|
148
|
+ $arrcode = $this->barcode_eanupc($code, 13);
|
|
|
149
|
+ break;
|
|
|
150
|
+ }
|
|
|
151
|
+ case self::TYPE_UPC_A: { // UPC-A
|
|
|
152
|
+ $arrcode = $this->barcode_eanupc($code, 12);
|
|
|
153
|
+ break;
|
|
|
154
|
+ }
|
|
|
155
|
+ case self::TYPE_UPC_E: { // UPC-E
|
|
|
156
|
+ $arrcode = $this->barcode_eanupc($code, 6);
|
|
|
157
|
+ break;
|
|
|
158
|
+ }
|
|
|
159
|
+ case self::TYPE_MSI: { // MSI (Variation of Plessey code)
|
|
|
160
|
+ $arrcode = $this->barcode_msi($code, false);
|
|
|
161
|
+ break;
|
|
|
162
|
+ }
|
|
|
163
|
+ case self::TYPE_MSI_CHECKSUM: { // MSI + CHECKSUM (modulo 11)
|
|
|
164
|
+ $arrcode = $this->barcode_msi($code, true);
|
|
|
165
|
+ break;
|
|
|
166
|
+ }
|
|
|
167
|
+ case self::TYPE_POSTNET: { // POSTNET
|
|
|
168
|
+ $arrcode = $this->barcode_postnet($code, false);
|
|
|
169
|
+ break;
|
|
|
170
|
+ }
|
|
|
171
|
+ case self::TYPE_PLANET: { // PLANET
|
|
|
172
|
+ $arrcode = $this->barcode_postnet($code, true);
|
|
|
173
|
+ break;
|
|
|
174
|
+ }
|
|
|
175
|
+ case self::TYPE_RMS4CC: { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
|
|
|
176
|
+ $arrcode = $this->barcode_rms4cc($code, false);
|
|
|
177
|
+ break;
|
|
|
178
|
+ }
|
|
|
179
|
+ case self::TYPE_KIX: { // KIX (Klant index - Customer index)
|
|
|
180
|
+ $arrcode = $this->barcode_rms4cc($code, true);
|
|
|
181
|
+ break;
|
|
|
182
|
+ }
|
|
|
183
|
+ case self::TYPE_IMB: { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
|
|
|
184
|
+ $arrcode = $this->barcode_imb($code);
|
|
|
185
|
+ break;
|
|
|
186
|
+ }
|
|
|
187
|
+ case self::TYPE_CODABAR: { // CODABAR
|
|
|
188
|
+ $arrcode = $this->barcode_codabar($code);
|
|
|
189
|
+ break;
|
|
|
190
|
+ }
|
|
|
191
|
+ case self::TYPE_CODE_11: { // CODE 11
|
|
|
192
|
+ $arrcode = $this->barcode_code11($code);
|
|
|
193
|
+ break;
|
|
|
194
|
+ }
|
|
|
195
|
+ case self::TYPE_PHARMA_CODE: { // PHARMACODE
|
|
|
196
|
+ $arrcode = $this->barcode_pharmacode($code);
|
|
|
197
|
+ break;
|
|
|
198
|
+ }
|
|
|
199
|
+ case self::TYPE_PHARMA_CODE_TWO_TRACKS: { // PHARMACODE TWO-TRACKS
|
|
|
200
|
+ $arrcode = $this->barcode_pharmacode2t($code);
|
|
|
201
|
+ break;
|
|
|
202
|
+ }
|
|
|
203
|
+ default: {
|
|
|
204
|
+ throw new UnknownTypeException();
|
|
|
205
|
+ break;
|
|
|
206
|
+ }
|
|
|
207
|
+ }
|
|
|
208
|
+
|
|
|
209
|
+ if ( ! isset($arrcode['maxWidth'])) {
|
|
|
210
|
+ $arrcode = $this->convertBarcodeArrayToNewStyle($arrcode);
|
|
|
211
|
+ }
|
|
|
212
|
+
|
|
|
213
|
+ return $arrcode;
|
|
|
214
|
+ }
|
|
|
215
|
+
|
|
|
216
|
+ /**
|
|
|
217
|
+ * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
|
|
|
218
|
+ * General-purpose code in very wide use world-wide
|
|
|
219
|
+ *
|
|
|
220
|
+ * @param $code (string) code to represent.
|
|
|
221
|
+ * @param $extended (boolean) if true uses the extended mode.
|
|
|
222
|
+ * @param $checksum (boolean) if true add a checksum to the code.
|
|
|
223
|
+ * @return array barcode representation.
|
|
|
224
|
+ * @protected
|
|
|
225
|
+ */
|
|
|
226
|
+ protected function barcode_code39($code, $extended = false, $checksum = false)
|
|
|
227
|
+ {
|
|
|
228
|
+ $chr = [];
|
|
|
229
|
+ $chr['0'] = '111331311';
|
|
|
230
|
+ $chr['1'] = '311311113';
|
|
|
231
|
+ $chr['2'] = '113311113';
|
|
|
232
|
+ $chr['3'] = '313311111';
|
|
|
233
|
+ $chr['4'] = '111331113';
|
|
|
234
|
+ $chr['5'] = '311331111';
|
|
|
235
|
+ $chr['6'] = '113331111';
|
|
|
236
|
+ $chr['7'] = '111311313';
|
|
|
237
|
+ $chr['8'] = '311311311';
|
|
|
238
|
+ $chr['9'] = '113311311';
|
|
|
239
|
+ $chr['A'] = '311113113';
|
|
|
240
|
+ $chr['B'] = '113113113';
|
|
|
241
|
+ $chr['C'] = '313113111';
|
|
|
242
|
+ $chr['D'] = '111133113';
|
|
|
243
|
+ $chr['E'] = '311133111';
|
|
|
244
|
+ $chr['F'] = '113133111';
|
|
|
245
|
+ $chr['G'] = '111113313';
|
|
|
246
|
+ $chr['H'] = '311113311';
|
|
|
247
|
+ $chr['I'] = '113113311';
|
|
|
248
|
+ $chr['J'] = '111133311';
|
|
|
249
|
+ $chr['K'] = '311111133';
|
|
|
250
|
+ $chr['L'] = '113111133';
|
|
|
251
|
+ $chr['M'] = '313111131';
|
|
|
252
|
+ $chr['N'] = '111131133';
|
|
|
253
|
+ $chr['O'] = '311131131';
|
|
|
254
|
+ $chr['P'] = '113131131';
|
|
|
255
|
+ $chr['Q'] = '111111333';
|
|
|
256
|
+ $chr['R'] = '311111331';
|
|
|
257
|
+ $chr['S'] = '113111331';
|
|
|
258
|
+ $chr['T'] = '111131331';
|
|
|
259
|
+ $chr['U'] = '331111113';
|
|
|
260
|
+ $chr['V'] = '133111113';
|
|
|
261
|
+ $chr['W'] = '333111111';
|
|
|
262
|
+ $chr['X'] = '131131113';
|
|
|
263
|
+ $chr['Y'] = '331131111';
|
|
|
264
|
+ $chr['Z'] = '133131111';
|
|
|
265
|
+ $chr['-'] = '131111313';
|
|
|
266
|
+ $chr['.'] = '331111311';
|
|
|
267
|
+ $chr[' '] = '133111311';
|
|
|
268
|
+ $chr['$'] = '131313111';
|
|
|
269
|
+ $chr['/'] = '131311131';
|
|
|
270
|
+ $chr['+'] = '131113131';
|
|
|
271
|
+ $chr['%'] = '111313131';
|
|
|
272
|
+ $chr['*'] = '131131311';
|
|
|
273
|
+
|
|
|
274
|
+ $code = strtoupper($code);
|
|
|
275
|
+
|
|
|
276
|
+ if ($extended) {
|
|
|
277
|
+ // extended mode
|
|
|
278
|
+ $code = $this->encode_code39_ext($code);
|
|
|
279
|
+ }
|
|
|
280
|
+
|
|
|
281
|
+ if ($checksum) {
|
|
|
282
|
+ // checksum
|
|
|
283
|
+ $code .= $this->checksum_code39($code);
|
|
|
284
|
+ }
|
|
|
285
|
+
|
|
|
286
|
+ // add start and stop codes
|
|
|
287
|
+ $code = '*' . $code . '*';
|
|
|
288
|
+
|
|
|
289
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
290
|
+ $k = 0;
|
|
|
291
|
+ $clen = strlen($code);
|
|
|
292
|
+ for ($i = 0; $i < $clen; ++$i) {
|
|
|
293
|
+ $char = $code[$i];
|
|
|
294
|
+ if ( ! isset($chr[$char])) {
|
|
|
295
|
+ throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
|
|
|
296
|
+ }
|
|
|
297
|
+ for ($j = 0; $j < 9; ++$j) {
|
|
|
298
|
+ if (($j % 2) == 0) {
|
|
|
299
|
+ $t = true; // bar
|
|
|
300
|
+ } else {
|
|
|
301
|
+ $t = false; // space
|
|
|
302
|
+ }
|
|
|
303
|
+ $w = $chr[$char][$j];
|
|
|
304
|
+ $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
305
|
+ $bararray['maxw'] += $w;
|
|
|
306
|
+ ++$k;
|
|
|
307
|
+ }
|
|
|
308
|
+ // intercharacter gap
|
|
|
309
|
+ $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
|
|
|
310
|
+ $bararray['maxw'] += 1;
|
|
|
311
|
+ ++$k;
|
|
|
312
|
+ }
|
|
|
313
|
+
|
|
|
314
|
+ return $bararray;
|
|
|
315
|
+ }
|
|
|
316
|
+
|
|
|
317
|
+ /**
|
|
|
318
|
+ * Encode a string to be used for CODE 39 Extended mode.
|
|
|
319
|
+ *
|
|
|
320
|
+ * @param string $code code to represent.
|
|
|
321
|
+ * @return bool|string encoded string.
|
|
|
322
|
+ * @protected
|
|
|
323
|
+ */
|
|
|
324
|
+ protected function encode_code39_ext($code)
|
|
|
325
|
+ {
|
|
|
326
|
+ $encode = array(
|
|
|
327
|
+ chr(0) => '%U',
|
|
|
328
|
+ chr(1) => '$A',
|
|
|
329
|
+ chr(2) => '$B',
|
|
|
330
|
+ chr(3) => '$C',
|
|
|
331
|
+ chr(4) => '$D',
|
|
|
332
|
+ chr(5) => '$E',
|
|
|
333
|
+ chr(6) => '$F',
|
|
|
334
|
+ chr(7) => '$G',
|
|
|
335
|
+ chr(8) => '$H',
|
|
|
336
|
+ chr(9) => '$I',
|
|
|
337
|
+ chr(10) => '$J',
|
|
|
338
|
+ chr(11) => '£K',
|
|
|
339
|
+ chr(12) => '$L',
|
|
|
340
|
+ chr(13) => '$M',
|
|
|
341
|
+ chr(14) => '$N',
|
|
|
342
|
+ chr(15) => '$O',
|
|
|
343
|
+ chr(16) => '$P',
|
|
|
344
|
+ chr(17) => '$Q',
|
|
|
345
|
+ chr(18) => '$R',
|
|
|
346
|
+ chr(19) => '$S',
|
|
|
347
|
+ chr(20) => '$T',
|
|
|
348
|
+ chr(21) => '$U',
|
|
|
349
|
+ chr(22) => '$V',
|
|
|
350
|
+ chr(23) => '$W',
|
|
|
351
|
+ chr(24) => '$X',
|
|
|
352
|
+ chr(25) => '$Y',
|
|
|
353
|
+ chr(26) => '$Z',
|
|
|
354
|
+ chr(27) => '%A',
|
|
|
355
|
+ chr(28) => '%B',
|
|
|
356
|
+ chr(29) => '%C',
|
|
|
357
|
+ chr(30) => '%D',
|
|
|
358
|
+ chr(31) => '%E',
|
|
|
359
|
+ chr(32) => ' ',
|
|
|
360
|
+ chr(33) => '/A',
|
|
|
361
|
+ chr(34) => '/B',
|
|
|
362
|
+ chr(35) => '/C',
|
|
|
363
|
+ chr(36) => '/D',
|
|
|
364
|
+ chr(37) => '/E',
|
|
|
365
|
+ chr(38) => '/F',
|
|
|
366
|
+ chr(39) => '/G',
|
|
|
367
|
+ chr(40) => '/H',
|
|
|
368
|
+ chr(41) => '/I',
|
|
|
369
|
+ chr(42) => '/J',
|
|
|
370
|
+ chr(43) => '/K',
|
|
|
371
|
+ chr(44) => '/L',
|
|
|
372
|
+ chr(45) => '-',
|
|
|
373
|
+ chr(46) => '.',
|
|
|
374
|
+ chr(47) => '/O',
|
|
|
375
|
+ chr(48) => '0',
|
|
|
376
|
+ chr(49) => '1',
|
|
|
377
|
+ chr(50) => '2',
|
|
|
378
|
+ chr(51) => '3',
|
|
|
379
|
+ chr(52) => '4',
|
|
|
380
|
+ chr(53) => '5',
|
|
|
381
|
+ chr(54) => '6',
|
|
|
382
|
+ chr(55) => '7',
|
|
|
383
|
+ chr(56) => '8',
|
|
|
384
|
+ chr(57) => '9',
|
|
|
385
|
+ chr(58) => '/Z',
|
|
|
386
|
+ chr(59) => '%F',
|
|
|
387
|
+ chr(60) => '%G',
|
|
|
388
|
+ chr(61) => '%H',
|
|
|
389
|
+ chr(62) => '%I',
|
|
|
390
|
+ chr(63) => '%J',
|
|
|
391
|
+ chr(64) => '%V',
|
|
|
392
|
+ chr(65) => 'A',
|
|
|
393
|
+ chr(66) => 'B',
|
|
|
394
|
+ chr(67) => 'C',
|
|
|
395
|
+ chr(68) => 'D',
|
|
|
396
|
+ chr(69) => 'E',
|
|
|
397
|
+ chr(70) => 'F',
|
|
|
398
|
+ chr(71) => 'G',
|
|
|
399
|
+ chr(72) => 'H',
|
|
|
400
|
+ chr(73) => 'I',
|
|
|
401
|
+ chr(74) => 'J',
|
|
|
402
|
+ chr(75) => 'K',
|
|
|
403
|
+ chr(76) => 'L',
|
|
|
404
|
+ chr(77) => 'M',
|
|
|
405
|
+ chr(78) => 'N',
|
|
|
406
|
+ chr(79) => 'O',
|
|
|
407
|
+ chr(80) => 'P',
|
|
|
408
|
+ chr(81) => 'Q',
|
|
|
409
|
+ chr(82) => 'R',
|
|
|
410
|
+ chr(83) => 'S',
|
|
|
411
|
+ chr(84) => 'T',
|
|
|
412
|
+ chr(85) => 'U',
|
|
|
413
|
+ chr(86) => 'V',
|
|
|
414
|
+ chr(87) => 'W',
|
|
|
415
|
+ chr(88) => 'X',
|
|
|
416
|
+ chr(89) => 'Y',
|
|
|
417
|
+ chr(90) => 'Z',
|
|
|
418
|
+ chr(91) => '%K',
|
|
|
419
|
+ chr(92) => '%L',
|
|
|
420
|
+ chr(93) => '%M',
|
|
|
421
|
+ chr(94) => '%N',
|
|
|
422
|
+ chr(95) => '%O',
|
|
|
423
|
+ chr(96) => '%W',
|
|
|
424
|
+ chr(97) => '+A',
|
|
|
425
|
+ chr(98) => '+B',
|
|
|
426
|
+ chr(99) => '+C',
|
|
|
427
|
+ chr(100) => '+D',
|
|
|
428
|
+ chr(101) => '+E',
|
|
|
429
|
+ chr(102) => '+F',
|
|
|
430
|
+ chr(103) => '+G',
|
|
|
431
|
+ chr(104) => '+H',
|
|
|
432
|
+ chr(105) => '+I',
|
|
|
433
|
+ chr(106) => '+J',
|
|
|
434
|
+ chr(107) => '+K',
|
|
|
435
|
+ chr(108) => '+L',
|
|
|
436
|
+ chr(109) => '+M',
|
|
|
437
|
+ chr(110) => '+N',
|
|
|
438
|
+ chr(111) => '+O',
|
|
|
439
|
+ chr(112) => '+P',
|
|
|
440
|
+ chr(113) => '+Q',
|
|
|
441
|
+ chr(114) => '+R',
|
|
|
442
|
+ chr(115) => '+S',
|
|
|
443
|
+ chr(116) => '+T',
|
|
|
444
|
+ chr(117) => '+U',
|
|
|
445
|
+ chr(118) => '+V',
|
|
|
446
|
+ chr(119) => '+W',
|
|
|
447
|
+ chr(120) => '+X',
|
|
|
448
|
+ chr(121) => '+Y',
|
|
|
449
|
+ chr(122) => '+Z',
|
|
|
450
|
+ chr(123) => '%P',
|
|
|
451
|
+ chr(124) => '%Q',
|
|
|
452
|
+ chr(125) => '%R',
|
|
|
453
|
+ chr(126) => '%S',
|
|
|
454
|
+ chr(127) => '%T'
|
|
|
455
|
+ );
|
|
|
456
|
+ $code_ext = '';
|
|
|
457
|
+ $clen = strlen($code);
|
|
|
458
|
+ for ($i = 0; $i < $clen; ++$i) {
|
|
|
459
|
+ if (ord($code[$i]) > 127) {
|
|
|
460
|
+ throw new InvalidCharacterException('Only supports till char 127');
|
|
|
461
|
+ }
|
|
|
462
|
+ $code_ext .= $encode[$code[$i]];
|
|
|
463
|
+ }
|
|
|
464
|
+
|
|
|
465
|
+ return $code_ext;
|
|
|
466
|
+ }
|
|
|
467
|
+
|
|
|
468
|
+ /**
|
|
|
469
|
+ * Calculate CODE 39 checksum (modulo 43).
|
|
|
470
|
+ *
|
|
|
471
|
+ * @param string $code code to represent.
|
|
|
472
|
+ * @return string char checksum.
|
|
|
473
|
+ * @protected
|
|
|
474
|
+ */
|
|
|
475
|
+ protected function checksum_code39($code)
|
|
|
476
|
+ {
|
|
|
477
|
+ $chars = array(
|
|
|
478
|
+ '0',
|
|
|
479
|
+ '1',
|
|
|
480
|
+ '2',
|
|
|
481
|
+ '3',
|
|
|
482
|
+ '4',
|
|
|
483
|
+ '5',
|
|
|
484
|
+ '6',
|
|
|
485
|
+ '7',
|
|
|
486
|
+ '8',
|
|
|
487
|
+ '9',
|
|
|
488
|
+ 'A',
|
|
|
489
|
+ 'B',
|
|
|
490
|
+ 'C',
|
|
|
491
|
+ 'D',
|
|
|
492
|
+ 'E',
|
|
|
493
|
+ 'F',
|
|
|
494
|
+ 'G',
|
|
|
495
|
+ 'H',
|
|
|
496
|
+ 'I',
|
|
|
497
|
+ 'J',
|
|
|
498
|
+ 'K',
|
|
|
499
|
+ 'L',
|
|
|
500
|
+ 'M',
|
|
|
501
|
+ 'N',
|
|
|
502
|
+ 'O',
|
|
|
503
|
+ 'P',
|
|
|
504
|
+ 'Q',
|
|
|
505
|
+ 'R',
|
|
|
506
|
+ 'S',
|
|
|
507
|
+ 'T',
|
|
|
508
|
+ 'U',
|
|
|
509
|
+ 'V',
|
|
|
510
|
+ 'W',
|
|
|
511
|
+ 'X',
|
|
|
512
|
+ 'Y',
|
|
|
513
|
+ 'Z',
|
|
|
514
|
+ '-',
|
|
|
515
|
+ '.',
|
|
|
516
|
+ ' ',
|
|
|
517
|
+ '$',
|
|
|
518
|
+ '/',
|
|
|
519
|
+ '+',
|
|
|
520
|
+ '%'
|
|
|
521
|
+ );
|
|
|
522
|
+ $sum = 0;
|
|
|
523
|
+ $codelength = strlen($code);
|
|
|
524
|
+ for ($i = 0; $i < $codelength; ++$i) {
|
|
|
525
|
+ $k = array_keys($chars, $code[$i]);
|
|
|
526
|
+ $sum += $k[0];
|
|
|
527
|
+ }
|
|
|
528
|
+ $j = ($sum % 43);
|
|
|
529
|
+
|
|
|
530
|
+ return $chars[$j];
|
|
|
531
|
+ }
|
|
|
532
|
+
|
|
|
533
|
+ /**
|
|
|
534
|
+ * CODE 93 - USS-93
|
|
|
535
|
+ * Compact code similar to Code 39
|
|
|
536
|
+ *
|
|
|
537
|
+ * @param $code (string) code to represent.
|
|
|
538
|
+ * @return array barcode representation.
|
|
|
539
|
+ * @protected
|
|
|
540
|
+ */
|
|
|
541
|
+ protected function barcode_code93($code)
|
|
|
542
|
+ {
|
|
|
543
|
+ $chr = [];
|
|
|
544
|
+ $chr[48] = '131112'; // 0
|
|
|
545
|
+ $chr[49] = '111213'; // 1
|
|
|
546
|
+ $chr[50] = '111312'; // 2
|
|
|
547
|
+ $chr[51] = '111411'; // 3
|
|
|
548
|
+ $chr[52] = '121113'; // 4
|
|
|
549
|
+ $chr[53] = '121212'; // 5
|
|
|
550
|
+ $chr[54] = '121311'; // 6
|
|
|
551
|
+ $chr[55] = '111114'; // 7
|
|
|
552
|
+ $chr[56] = '131211'; // 8
|
|
|
553
|
+ $chr[57] = '141111'; // 9
|
|
|
554
|
+ $chr[65] = '211113'; // A
|
|
|
555
|
+ $chr[66] = '211212'; // B
|
|
|
556
|
+ $chr[67] = '211311'; // C
|
|
|
557
|
+ $chr[68] = '221112'; // D
|
|
|
558
|
+ $chr[69] = '221211'; // E
|
|
|
559
|
+ $chr[70] = '231111'; // F
|
|
|
560
|
+ $chr[71] = '112113'; // G
|
|
|
561
|
+ $chr[72] = '112212'; // H
|
|
|
562
|
+ $chr[73] = '112311'; // I
|
|
|
563
|
+ $chr[74] = '122112'; // J
|
|
|
564
|
+ $chr[75] = '132111'; // K
|
|
|
565
|
+ $chr[76] = '111123'; // L
|
|
|
566
|
+ $chr[77] = '111222'; // M
|
|
|
567
|
+ $chr[78] = '111321'; // N
|
|
|
568
|
+ $chr[79] = '121122'; // O
|
|
|
569
|
+ $chr[80] = '131121'; // P
|
|
|
570
|
+ $chr[81] = '212112'; // Q
|
|
|
571
|
+ $chr[82] = '212211'; // R
|
|
|
572
|
+ $chr[83] = '211122'; // S
|
|
|
573
|
+ $chr[84] = '211221'; // T
|
|
|
574
|
+ $chr[85] = '221121'; // U
|
|
|
575
|
+ $chr[86] = '222111'; // V
|
|
|
576
|
+ $chr[87] = '112122'; // W
|
|
|
577
|
+ $chr[88] = '112221'; // X
|
|
|
578
|
+ $chr[89] = '122121'; // Y
|
|
|
579
|
+ $chr[90] = '123111'; // Z
|
|
|
580
|
+ $chr[45] = '121131'; // -
|
|
|
581
|
+ $chr[46] = '311112'; // .
|
|
|
582
|
+ $chr[32] = '311211'; //
|
|
|
583
|
+ $chr[36] = '321111'; // $
|
|
|
584
|
+ $chr[47] = '112131'; // /
|
|
|
585
|
+ $chr[43] = '113121'; // +
|
|
|
586
|
+ $chr[37] = '211131'; // %
|
|
|
587
|
+ $chr[128] = '121221'; // ($)
|
|
|
588
|
+ $chr[129] = '311121'; // (/)
|
|
|
589
|
+ $chr[130] = '122211'; // (+)
|
|
|
590
|
+ $chr[131] = '312111'; // (%)
|
|
|
591
|
+ $chr[42] = '111141'; // start-stop
|
|
|
592
|
+ $code = strtoupper($code);
|
|
|
593
|
+ $encode = array(
|
|
|
594
|
+ chr(0) => chr(131) . 'U',
|
|
|
595
|
+ chr(1) => chr(128) . 'A',
|
|
|
596
|
+ chr(2) => chr(128) . 'B',
|
|
|
597
|
+ chr(3) => chr(128) . 'C',
|
|
|
598
|
+ chr(4) => chr(128) . 'D',
|
|
|
599
|
+ chr(5) => chr(128) . 'E',
|
|
|
600
|
+ chr(6) => chr(128) . 'F',
|
|
|
601
|
+ chr(7) => chr(128) . 'G',
|
|
|
602
|
+ chr(8) => chr(128) . 'H',
|
|
|
603
|
+ chr(9) => chr(128) . 'I',
|
|
|
604
|
+ chr(10) => chr(128) . 'J',
|
|
|
605
|
+ chr(11) => '£K',
|
|
|
606
|
+ chr(12) => chr(128) . 'L',
|
|
|
607
|
+ chr(13) => chr(128) . 'M',
|
|
|
608
|
+ chr(14) => chr(128) . 'N',
|
|
|
609
|
+ chr(15) => chr(128) . 'O',
|
|
|
610
|
+ chr(16) => chr(128) . 'P',
|
|
|
611
|
+ chr(17) => chr(128) . 'Q',
|
|
|
612
|
+ chr(18) => chr(128) . 'R',
|
|
|
613
|
+ chr(19) => chr(128) . 'S',
|
|
|
614
|
+ chr(20) => chr(128) . 'T',
|
|
|
615
|
+ chr(21) => chr(128) . 'U',
|
|
|
616
|
+ chr(22) => chr(128) . 'V',
|
|
|
617
|
+ chr(23) => chr(128) . 'W',
|
|
|
618
|
+ chr(24) => chr(128) . 'X',
|
|
|
619
|
+ chr(25) => chr(128) . 'Y',
|
|
|
620
|
+ chr(26) => chr(128) . 'Z',
|
|
|
621
|
+ chr(27) => chr(131) . 'A',
|
|
|
622
|
+ chr(28) => chr(131) . 'B',
|
|
|
623
|
+ chr(29) => chr(131) . 'C',
|
|
|
624
|
+ chr(30) => chr(131) . 'D',
|
|
|
625
|
+ chr(31) => chr(131) . 'E',
|
|
|
626
|
+ chr(32) => ' ',
|
|
|
627
|
+ chr(33) => chr(129) . 'A',
|
|
|
628
|
+ chr(34) => chr(129) . 'B',
|
|
|
629
|
+ chr(35) => chr(129) . 'C',
|
|
|
630
|
+ chr(36) => chr(129) . 'D',
|
|
|
631
|
+ chr(37) => chr(129) . 'E',
|
|
|
632
|
+ chr(38) => chr(129) . 'F',
|
|
|
633
|
+ chr(39) => chr(129) . 'G',
|
|
|
634
|
+ chr(40) => chr(129) . 'H',
|
|
|
635
|
+ chr(41) => chr(129) . 'I',
|
|
|
636
|
+ chr(42) => chr(129) . 'J',
|
|
|
637
|
+ chr(43) => chr(129) . 'K',
|
|
|
638
|
+ chr(44) => chr(129) . 'L',
|
|
|
639
|
+ chr(45) => '-',
|
|
|
640
|
+ chr(46) => '.',
|
|
|
641
|
+ chr(47) => chr(129) . 'O',
|
|
|
642
|
+ chr(48) => '0',
|
|
|
643
|
+ chr(49) => '1',
|
|
|
644
|
+ chr(50) => '2',
|
|
|
645
|
+ chr(51) => '3',
|
|
|
646
|
+ chr(52) => '4',
|
|
|
647
|
+ chr(53) => '5',
|
|
|
648
|
+ chr(54) => '6',
|
|
|
649
|
+ chr(55) => '7',
|
|
|
650
|
+ chr(56) => '8',
|
|
|
651
|
+ chr(57) => '9',
|
|
|
652
|
+ chr(58) => chr(129) . 'Z',
|
|
|
653
|
+ chr(59) => chr(131) . 'F',
|
|
|
654
|
+ chr(60) => chr(131) . 'G',
|
|
|
655
|
+ chr(61) => chr(131) . 'H',
|
|
|
656
|
+ chr(62) => chr(131) . 'I',
|
|
|
657
|
+ chr(63) => chr(131) . 'J',
|
|
|
658
|
+ chr(64) => chr(131) . 'V',
|
|
|
659
|
+ chr(65) => 'A',
|
|
|
660
|
+ chr(66) => 'B',
|
|
|
661
|
+ chr(67) => 'C',
|
|
|
662
|
+ chr(68) => 'D',
|
|
|
663
|
+ chr(69) => 'E',
|
|
|
664
|
+ chr(70) => 'F',
|
|
|
665
|
+ chr(71) => 'G',
|
|
|
666
|
+ chr(72) => 'H',
|
|
|
667
|
+ chr(73) => 'I',
|
|
|
668
|
+ chr(74) => 'J',
|
|
|
669
|
+ chr(75) => 'K',
|
|
|
670
|
+ chr(76) => 'L',
|
|
|
671
|
+ chr(77) => 'M',
|
|
|
672
|
+ chr(78) => 'N',
|
|
|
673
|
+ chr(79) => 'O',
|
|
|
674
|
+ chr(80) => 'P',
|
|
|
675
|
+ chr(81) => 'Q',
|
|
|
676
|
+ chr(82) => 'R',
|
|
|
677
|
+ chr(83) => 'S',
|
|
|
678
|
+ chr(84) => 'T',
|
|
|
679
|
+ chr(85) => 'U',
|
|
|
680
|
+ chr(86) => 'V',
|
|
|
681
|
+ chr(87) => 'W',
|
|
|
682
|
+ chr(88) => 'X',
|
|
|
683
|
+ chr(89) => 'Y',
|
|
|
684
|
+ chr(90) => 'Z',
|
|
|
685
|
+ chr(91) => chr(131) . 'K',
|
|
|
686
|
+ chr(92) => chr(131) . 'L',
|
|
|
687
|
+ chr(93) => chr(131) . 'M',
|
|
|
688
|
+ chr(94) => chr(131) . 'N',
|
|
|
689
|
+ chr(95) => chr(131) . 'O',
|
|
|
690
|
+ chr(96) => chr(131) . 'W',
|
|
|
691
|
+ chr(97) => chr(130) . 'A',
|
|
|
692
|
+ chr(98) => chr(130) . 'B',
|
|
|
693
|
+ chr(99) => chr(130) . 'C',
|
|
|
694
|
+ chr(100) => chr(130) . 'D',
|
|
|
695
|
+ chr(101) => chr(130) . 'E',
|
|
|
696
|
+ chr(102) => chr(130) . 'F',
|
|
|
697
|
+ chr(103) => chr(130) . 'G',
|
|
|
698
|
+ chr(104) => chr(130) . 'H',
|
|
|
699
|
+ chr(105) => chr(130) . 'I',
|
|
|
700
|
+ chr(106) => chr(130) . 'J',
|
|
|
701
|
+ chr(107) => chr(130) . 'K',
|
|
|
702
|
+ chr(108) => chr(130) . 'L',
|
|
|
703
|
+ chr(109) => chr(130) . 'M',
|
|
|
704
|
+ chr(110) => chr(130) . 'N',
|
|
|
705
|
+ chr(111) => chr(130) . 'O',
|
|
|
706
|
+ chr(112) => chr(130) . 'P',
|
|
|
707
|
+ chr(113) => chr(130) . 'Q',
|
|
|
708
|
+ chr(114) => chr(130) . 'R',
|
|
|
709
|
+ chr(115) => chr(130) . 'S',
|
|
|
710
|
+ chr(116) => chr(130) . 'T',
|
|
|
711
|
+ chr(117) => chr(130) . 'U',
|
|
|
712
|
+ chr(118) => chr(130) . 'V',
|
|
|
713
|
+ chr(119) => chr(130) . 'W',
|
|
|
714
|
+ chr(120) => chr(130) . 'X',
|
|
|
715
|
+ chr(121) => chr(130) . 'Y',
|
|
|
716
|
+ chr(122) => chr(130) . 'Z',
|
|
|
717
|
+ chr(123) => chr(131) . 'P',
|
|
|
718
|
+ chr(124) => chr(131) . 'Q',
|
|
|
719
|
+ chr(125) => chr(131) . 'R',
|
|
|
720
|
+ chr(126) => chr(131) . 'S',
|
|
|
721
|
+ chr(127) => chr(131) . 'T'
|
|
|
722
|
+ );
|
|
|
723
|
+ $code_ext = '';
|
|
|
724
|
+ $clen = strlen($code);
|
|
|
725
|
+ for ($i = 0; $i < $clen; ++$i) {
|
|
|
726
|
+ if (ord($code[$i]) > 127) {
|
|
|
727
|
+ throw new InvalidCharacterException('Only supports till char 127');
|
|
|
728
|
+ }
|
|
|
729
|
+ $code_ext .= $encode[$code[$i]];
|
|
|
730
|
+ }
|
|
|
731
|
+ // checksum
|
|
|
732
|
+ $code_ext .= $this->checksum_code93($code_ext);
|
|
|
733
|
+ // add start and stop codes
|
|
|
734
|
+ $code = '*' . $code_ext . '*';
|
|
|
735
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
736
|
+ $k = 0;
|
|
|
737
|
+ $clen = strlen($code);
|
|
|
738
|
+ for ($i = 0; $i < $clen; ++$i) {
|
|
|
739
|
+ $char = ord($code[$i]);
|
|
|
740
|
+ if ( ! isset($chr[$char])) {
|
|
|
741
|
+ throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
|
|
|
742
|
+ }
|
|
|
743
|
+ for ($j = 0; $j < 6; ++$j) {
|
|
|
744
|
+ if (($j % 2) == 0) {
|
|
|
745
|
+ $t = true; // bar
|
|
|
746
|
+ } else {
|
|
|
747
|
+ $t = false; // space
|
|
|
748
|
+ }
|
|
|
749
|
+ $w = $chr[$char][$j];
|
|
|
750
|
+ $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
751
|
+ $bararray['maxw'] += $w;
|
|
|
752
|
+ ++$k;
|
|
|
753
|
+ }
|
|
|
754
|
+ }
|
|
|
755
|
+ $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
|
|
|
756
|
+ $bararray['maxw'] += 1;
|
|
|
757
|
+
|
|
|
758
|
+ return $bararray;
|
|
|
759
|
+ }
|
|
|
760
|
+
|
|
|
761
|
+ /**
|
|
|
762
|
+ * Calculate CODE 93 checksum (modulo 47).
|
|
|
763
|
+ *
|
|
|
764
|
+ * @param $code (string) code to represent.
|
|
|
765
|
+ * @return string checksum code.
|
|
|
766
|
+ * @protected
|
|
|
767
|
+ */
|
|
|
768
|
+ protected function checksum_code93($code)
|
|
|
769
|
+ {
|
|
|
770
|
+ $chars = array(
|
|
|
771
|
+ '0',
|
|
|
772
|
+ '1',
|
|
|
773
|
+ '2',
|
|
|
774
|
+ '3',
|
|
|
775
|
+ '4',
|
|
|
776
|
+ '5',
|
|
|
777
|
+ '6',
|
|
|
778
|
+ '7',
|
|
|
779
|
+ '8',
|
|
|
780
|
+ '9',
|
|
|
781
|
+ 'A',
|
|
|
782
|
+ 'B',
|
|
|
783
|
+ 'C',
|
|
|
784
|
+ 'D',
|
|
|
785
|
+ 'E',
|
|
|
786
|
+ 'F',
|
|
|
787
|
+ 'G',
|
|
|
788
|
+ 'H',
|
|
|
789
|
+ 'I',
|
|
|
790
|
+ 'J',
|
|
|
791
|
+ 'K',
|
|
|
792
|
+ 'L',
|
|
|
793
|
+ 'M',
|
|
|
794
|
+ 'N',
|
|
|
795
|
+ 'O',
|
|
|
796
|
+ 'P',
|
|
|
797
|
+ 'Q',
|
|
|
798
|
+ 'R',
|
|
|
799
|
+ 'S',
|
|
|
800
|
+ 'T',
|
|
|
801
|
+ 'U',
|
|
|
802
|
+ 'V',
|
|
|
803
|
+ 'W',
|
|
|
804
|
+ 'X',
|
|
|
805
|
+ 'Y',
|
|
|
806
|
+ 'Z',
|
|
|
807
|
+ '-',
|
|
|
808
|
+ '.',
|
|
|
809
|
+ ' ',
|
|
|
810
|
+ '$',
|
|
|
811
|
+ '/',
|
|
|
812
|
+ '+',
|
|
|
813
|
+ '%',
|
|
|
814
|
+ '<',
|
|
|
815
|
+ '=',
|
|
|
816
|
+ '>',
|
|
|
817
|
+ '?'
|
|
|
818
|
+ );
|
|
|
819
|
+ // translate special characters
|
|
|
820
|
+ $code = strtr($code, chr(128) . chr(131) . chr(129) . chr(130), '<=>?');
|
|
|
821
|
+ $len = strlen($code);
|
|
|
822
|
+ // calculate check digit C
|
|
|
823
|
+ $p = 1;
|
|
|
824
|
+ $check = 0;
|
|
|
825
|
+ for ($i = ($len - 1); $i >= 0; --$i) {
|
|
|
826
|
+ $k = array_keys($chars, $code[$i]);
|
|
|
827
|
+ $check += ($k[0] * $p);
|
|
|
828
|
+ ++$p;
|
|
|
829
|
+ if ($p > 20) {
|
|
|
830
|
+ $p = 1;
|
|
|
831
|
+ }
|
|
|
832
|
+ }
|
|
|
833
|
+ $check %= 47;
|
|
|
834
|
+ $c = $chars[$check];
|
|
|
835
|
+ $code .= $c;
|
|
|
836
|
+ // calculate check digit K
|
|
|
837
|
+ $p = 1;
|
|
|
838
|
+ $check = 0;
|
|
|
839
|
+ for ($i = $len; $i >= 0; --$i) {
|
|
|
840
|
+ $k = array_keys($chars, $code[$i]);
|
|
|
841
|
+ $check += ($k[0] * $p);
|
|
|
842
|
+ ++$p;
|
|
|
843
|
+ if ($p > 15) {
|
|
|
844
|
+ $p = 1;
|
|
|
845
|
+ }
|
|
|
846
|
+ }
|
|
|
847
|
+ $check %= 47;
|
|
|
848
|
+ $k = $chars[$check];
|
|
|
849
|
+ $checksum = $c . $k;
|
|
|
850
|
+ // resto respecial characters
|
|
|
851
|
+ $checksum = strtr($checksum, '<=>?', chr(128) . chr(131) . chr(129) . chr(130));
|
|
|
852
|
+
|
|
|
853
|
+ return $checksum;
|
|
|
854
|
+ }
|
|
|
855
|
+
|
|
|
856
|
+ /**
|
|
|
857
|
+ * Checksum for standard 2 of 5 barcodes.
|
|
|
858
|
+ *
|
|
|
859
|
+ * @param $code (string) code to process.
|
|
|
860
|
+ * @return int checksum.
|
|
|
861
|
+ * @protected
|
|
|
862
|
+ */
|
|
|
863
|
+ protected function checksum_s25($code)
|
|
|
864
|
+ {
|
|
|
865
|
+ $len = strlen($code);
|
|
|
866
|
+ $sum = 0;
|
|
|
867
|
+ for ($i = 0; $i < $len; $i += 2) {
|
|
|
868
|
+ $sum += $code[$i];
|
|
|
869
|
+ }
|
|
|
870
|
+ $sum *= 3;
|
|
|
871
|
+ for ($i = 1; $i < $len; $i += 2) {
|
|
|
872
|
+ $sum += ($code[$i]);
|
|
|
873
|
+ }
|
|
|
874
|
+ $r = $sum % 10;
|
|
|
875
|
+ if ($r > 0) {
|
|
|
876
|
+ $r = (10 - $r);
|
|
|
877
|
+ }
|
|
|
878
|
+
|
|
|
879
|
+ return $r;
|
|
|
880
|
+ }
|
|
|
881
|
+
|
|
|
882
|
+ /**
|
|
|
883
|
+ * MSI.
|
|
|
884
|
+ * Variation of Plessey code, with similar applications
|
|
|
885
|
+ * Contains digits (0 to 9) and encodes the data only in the width of bars.
|
|
|
886
|
+ *
|
|
|
887
|
+ * @param $code (string) code to represent.
|
|
|
888
|
+ * @param $checksum (boolean) if true add a checksum to the code (modulo 11)
|
|
|
889
|
+ * @return array barcode representation.
|
|
|
890
|
+ * @protected
|
|
|
891
|
+ */
|
|
|
892
|
+ protected function barcode_msi($code, $checksum = false)
|
|
|
893
|
+ {
|
|
|
894
|
+ $chr['0'] = '100100100100';
|
|
|
895
|
+ $chr['1'] = '100100100110';
|
|
|
896
|
+ $chr['2'] = '100100110100';
|
|
|
897
|
+ $chr['3'] = '100100110110';
|
|
|
898
|
+ $chr['4'] = '100110100100';
|
|
|
899
|
+ $chr['5'] = '100110100110';
|
|
|
900
|
+ $chr['6'] = '100110110100';
|
|
|
901
|
+ $chr['7'] = '100110110110';
|
|
|
902
|
+ $chr['8'] = '110100100100';
|
|
|
903
|
+ $chr['9'] = '110100100110';
|
|
|
904
|
+ $chr['A'] = '110100110100';
|
|
|
905
|
+ $chr['B'] = '110100110110';
|
|
|
906
|
+ $chr['C'] = '110110100100';
|
|
|
907
|
+ $chr['D'] = '110110100110';
|
|
|
908
|
+ $chr['E'] = '110110110100';
|
|
|
909
|
+ $chr['F'] = '110110110110';
|
|
|
910
|
+ if ($checksum) {
|
|
|
911
|
+ // add checksum
|
|
|
912
|
+ $clen = strlen($code);
|
|
|
913
|
+ $p = 2;
|
|
|
914
|
+ $check = 0;
|
|
|
915
|
+ for ($i = ($clen - 1); $i >= 0; --$i) {
|
|
|
916
|
+ $check += (hexdec($code[$i]) * $p);
|
|
|
917
|
+ ++$p;
|
|
|
918
|
+ if ($p > 7) {
|
|
|
919
|
+ $p = 2;
|
|
|
920
|
+ }
|
|
|
921
|
+ }
|
|
|
922
|
+ $check %= 11;
|
|
|
923
|
+ if ($check > 0) {
|
|
|
924
|
+ $check = 11 - $check;
|
|
|
925
|
+ }
|
|
|
926
|
+ $code .= $check;
|
|
|
927
|
+ }
|
|
|
928
|
+ $seq = '110'; // left guard
|
|
|
929
|
+ $clen = strlen($code);
|
|
|
930
|
+ for ($i = 0; $i < $clen; ++$i) {
|
|
|
931
|
+ $digit = $code[$i];
|
|
|
932
|
+ if ( ! isset($chr[$digit])) {
|
|
|
933
|
+ throw new InvalidCharacterException('Char ' . $digit . ' is unsupported');
|
|
|
934
|
+ }
|
|
|
935
|
+ $seq .= $chr[$digit];
|
|
|
936
|
+ }
|
|
|
937
|
+ $seq .= '1001'; // right guard
|
|
|
938
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
939
|
+
|
|
|
940
|
+ return $this->binseq_to_array($seq, $bararray);
|
|
|
941
|
+ }
|
|
|
942
|
+
|
|
|
943
|
+ /**
|
|
|
944
|
+ * Standard 2 of 5 barcodes.
|
|
|
945
|
+ * Used in airline ticket marking, photofinishing
|
|
|
946
|
+ * Contains digits (0 to 9) and encodes the data only in the width of bars.
|
|
|
947
|
+ *
|
|
|
948
|
+ * @param $code (string) code to represent.
|
|
|
949
|
+ * @param $checksum (boolean) if true add a checksum to the code
|
|
|
950
|
+ * @return array barcode representation.
|
|
|
951
|
+ * @protected
|
|
|
952
|
+ */
|
|
|
953
|
+ protected function barcode_s25($code, $checksum = false)
|
|
|
954
|
+ {
|
|
|
955
|
+ $chr['0'] = '10101110111010';
|
|
|
956
|
+ $chr['1'] = '11101010101110';
|
|
|
957
|
+ $chr['2'] = '10111010101110';
|
|
|
958
|
+ $chr['3'] = '11101110101010';
|
|
|
959
|
+ $chr['4'] = '10101110101110';
|
|
|
960
|
+ $chr['5'] = '11101011101010';
|
|
|
961
|
+ $chr['6'] = '10111011101010';
|
|
|
962
|
+ $chr['7'] = '10101011101110';
|
|
|
963
|
+ $chr['8'] = '10101110111010';
|
|
|
964
|
+ $chr['9'] = '10111010111010';
|
|
|
965
|
+ if ($checksum) {
|
|
|
966
|
+ // add checksum
|
|
|
967
|
+ $code .= $this->checksum_s25($code);
|
|
|
968
|
+ }
|
|
|
969
|
+ if ((strlen($code) % 2) != 0) {
|
|
|
970
|
+ // add leading zero if code-length is odd
|
|
|
971
|
+ $code = '0' . $code;
|
|
|
972
|
+ }
|
|
|
973
|
+ $seq = '11011010';
|
|
|
974
|
+ $clen = strlen($code);
|
|
|
975
|
+ for ($i = 0; $i < $clen; ++$i) {
|
|
|
976
|
+ $digit = $code[$i];
|
|
|
977
|
+ if ( ! isset($chr[$digit])) {
|
|
|
978
|
+ throw new InvalidCharacterException('Char ' . $digit . ' is unsupported');
|
|
|
979
|
+ }
|
|
|
980
|
+ $seq .= $chr[$digit];
|
|
|
981
|
+ }
|
|
|
982
|
+ $seq .= '1101011';
|
|
|
983
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
984
|
+
|
|
|
985
|
+ return $this->binseq_to_array($seq, $bararray);
|
|
|
986
|
+ }
|
|
|
987
|
+
|
|
|
988
|
+ /**
|
|
|
989
|
+ * Convert binary barcode sequence to TCPDF barcode array.
|
|
|
990
|
+ *
|
|
|
991
|
+ * @param $seq (string) barcode as binary sequence.
|
|
|
992
|
+ * @param $bararray (array) barcode array.
|
|
|
993
|
+ * òparam array $bararray TCPDF barcode array to fill up
|
|
|
994
|
+ * @return array barcode representation.
|
|
|
995
|
+ * @protected
|
|
|
996
|
+ */
|
|
|
997
|
+ protected function binseq_to_array($seq, $bararray)
|
|
|
998
|
+ {
|
|
|
999
|
+ $len = strlen($seq);
|
|
|
1000
|
+ $w = 0;
|
|
|
1001
|
+ $k = 0;
|
|
|
1002
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
1003
|
+ $w += 1;
|
|
|
1004
|
+ if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq[$i] != $seq[($i + 1)]))) {
|
|
|
1005
|
+ if ($seq[$i] == '1') {
|
|
|
1006
|
+ $t = true; // bar
|
|
|
1007
|
+ } else {
|
|
|
1008
|
+ $t = false; // space
|
|
|
1009
|
+ }
|
|
|
1010
|
+ $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
1011
|
+ $bararray['maxw'] += $w;
|
|
|
1012
|
+ ++$k;
|
|
|
1013
|
+ $w = 0;
|
|
|
1014
|
+ }
|
|
|
1015
|
+ }
|
|
|
1016
|
+
|
|
|
1017
|
+ return $bararray;
|
|
|
1018
|
+ }
|
|
|
1019
|
+
|
|
|
1020
|
+ /**
|
|
|
1021
|
+ * Interleaved 2 of 5 barcodes.
|
|
|
1022
|
+ * Compact numeric code, widely used in industry, air cargo
|
|
|
1023
|
+ * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
|
|
|
1024
|
+ *
|
|
|
1025
|
+ * @param $code (string) code to represent.
|
|
|
1026
|
+ * @param $checksum (boolean) if true add a checksum to the code
|
|
|
1027
|
+ * @return array barcode representation.
|
|
|
1028
|
+ * @protected
|
|
|
1029
|
+ */
|
|
|
1030
|
+ protected function barcode_i25($code, $checksum = false)
|
|
|
1031
|
+ {
|
|
|
1032
|
+ $chr['0'] = '11221';
|
|
|
1033
|
+ $chr['1'] = '21112';
|
|
|
1034
|
+ $chr['2'] = '12112';
|
|
|
1035
|
+ $chr['3'] = '22111';
|
|
|
1036
|
+ $chr['4'] = '11212';
|
|
|
1037
|
+ $chr['5'] = '21211';
|
|
|
1038
|
+ $chr['6'] = '12211';
|
|
|
1039
|
+ $chr['7'] = '11122';
|
|
|
1040
|
+ $chr['8'] = '21121';
|
|
|
1041
|
+ $chr['9'] = '12121';
|
|
|
1042
|
+ $chr['A'] = '11';
|
|
|
1043
|
+ $chr['Z'] = '21';
|
|
|
1044
|
+ if ($checksum) {
|
|
|
1045
|
+ // add checksum
|
|
|
1046
|
+ $code .= $this->checksum_s25($code);
|
|
|
1047
|
+ }
|
|
|
1048
|
+ if ((strlen($code) % 2) != 0) {
|
|
|
1049
|
+ // add leading zero if code-length is odd
|
|
|
1050
|
+ $code = '0' . $code;
|
|
|
1051
|
+ }
|
|
|
1052
|
+ // add start and stop codes
|
|
|
1053
|
+ $code = 'AA' . strtolower($code) . 'ZA';
|
|
|
1054
|
+
|
|
|
1055
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
1056
|
+ $k = 0;
|
|
|
1057
|
+ $clen = strlen($code);
|
|
|
1058
|
+ for ($i = 0; $i < $clen; $i = ($i + 2)) {
|
|
|
1059
|
+ $char_bar = $code[$i];
|
|
|
1060
|
+ $char_space = $code[$i + 1];
|
|
|
1061
|
+ if ( ! isset($chr[$char_bar]) || ! isset($chr[$char_space])) {
|
|
|
1062
|
+ throw new InvalidCharacterException();
|
|
|
1063
|
+ }
|
|
|
1064
|
+ // create a bar-space sequence
|
|
|
1065
|
+ $seq = '';
|
|
|
1066
|
+ $chrlen = strlen($chr[$char_bar]);
|
|
|
1067
|
+ for ($s = 0; $s < $chrlen; $s++) {
|
|
|
1068
|
+ $seq .= $chr[$char_bar][$s] . $chr[$char_space][$s];
|
|
|
1069
|
+ }
|
|
|
1070
|
+ $seqlen = strlen($seq);
|
|
|
1071
|
+ for ($j = 0; $j < $seqlen; ++$j) {
|
|
|
1072
|
+ if (($j % 2) == 0) {
|
|
|
1073
|
+ $t = true; // bar
|
|
|
1074
|
+ } else {
|
|
|
1075
|
+ $t = false; // space
|
|
|
1076
|
+ }
|
|
|
1077
|
+ $w = $seq[$j];
|
|
|
1078
|
+ $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
1079
|
+ $bararray['maxw'] += $w;
|
|
|
1080
|
+ ++$k;
|
|
|
1081
|
+ }
|
|
|
1082
|
+ }
|
|
|
1083
|
+
|
|
|
1084
|
+ return $bararray;
|
|
|
1085
|
+ }
|
|
|
1086
|
+
|
|
|
1087
|
+ /**
|
|
|
1088
|
+ * C128 barcodes.
|
|
|
1089
|
+ * Very capable code, excellent density, high reliability; in very wide use world-wide
|
|
|
1090
|
+ *
|
|
|
1091
|
+ * @param $code (string) code to represent.
|
|
|
1092
|
+ * @param $type (string) barcode type: A, B, C or empty for automatic switch (AUTO mode)
|
|
|
1093
|
+ * @return array barcode representation.
|
|
|
1094
|
+ * @protected
|
|
|
1095
|
+ */
|
|
|
1096
|
+ protected function barcode_c128($code, $type = '')
|
|
|
1097
|
+ {
|
|
|
1098
|
+ $chr = array(
|
|
|
1099
|
+ '212222', /* 00 */
|
|
|
1100
|
+ '222122', /* 01 */
|
|
|
1101
|
+ '222221', /* 02 */
|
|
|
1102
|
+ '121223', /* 03 */
|
|
|
1103
|
+ '121322', /* 04 */
|
|
|
1104
|
+ '131222', /* 05 */
|
|
|
1105
|
+ '122213', /* 06 */
|
|
|
1106
|
+ '122312', /* 07 */
|
|
|
1107
|
+ '132212', /* 08 */
|
|
|
1108
|
+ '221213', /* 09 */
|
|
|
1109
|
+ '221312', /* 10 */
|
|
|
1110
|
+ '231212', /* 11 */
|
|
|
1111
|
+ '112232', /* 12 */
|
|
|
1112
|
+ '122132', /* 13 */
|
|
|
1113
|
+ '122231', /* 14 */
|
|
|
1114
|
+ '113222', /* 15 */
|
|
|
1115
|
+ '123122', /* 16 */
|
|
|
1116
|
+ '123221', /* 17 */
|
|
|
1117
|
+ '223211', /* 18 */
|
|
|
1118
|
+ '221132', /* 19 */
|
|
|
1119
|
+ '221231', /* 20 */
|
|
|
1120
|
+ '213212', /* 21 */
|
|
|
1121
|
+ '223112', /* 22 */
|
|
|
1122
|
+ '312131', /* 23 */
|
|
|
1123
|
+ '311222', /* 24 */
|
|
|
1124
|
+ '321122', /* 25 */
|
|
|
1125
|
+ '321221', /* 26 */
|
|
|
1126
|
+ '312212', /* 27 */
|
|
|
1127
|
+ '322112', /* 28 */
|
|
|
1128
|
+ '322211', /* 29 */
|
|
|
1129
|
+ '212123', /* 30 */
|
|
|
1130
|
+ '212321', /* 31 */
|
|
|
1131
|
+ '232121', /* 32 */
|
|
|
1132
|
+ '111323', /* 33 */
|
|
|
1133
|
+ '131123', /* 34 */
|
|
|
1134
|
+ '131321', /* 35 */
|
|
|
1135
|
+ '112313', /* 36 */
|
|
|
1136
|
+ '132113', /* 37 */
|
|
|
1137
|
+ '132311', /* 38 */
|
|
|
1138
|
+ '211313', /* 39 */
|
|
|
1139
|
+ '231113', /* 40 */
|
|
|
1140
|
+ '231311', /* 41 */
|
|
|
1141
|
+ '112133', /* 42 */
|
|
|
1142
|
+ '112331', /* 43 */
|
|
|
1143
|
+ '132131', /* 44 */
|
|
|
1144
|
+ '113123', /* 45 */
|
|
|
1145
|
+ '113321', /* 46 */
|
|
|
1146
|
+ '133121', /* 47 */
|
|
|
1147
|
+ '313121', /* 48 */
|
|
|
1148
|
+ '211331', /* 49 */
|
|
|
1149
|
+ '231131', /* 50 */
|
|
|
1150
|
+ '213113', /* 51 */
|
|
|
1151
|
+ '213311', /* 52 */
|
|
|
1152
|
+ '213131', /* 53 */
|
|
|
1153
|
+ '311123', /* 54 */
|
|
|
1154
|
+ '311321', /* 55 */
|
|
|
1155
|
+ '331121', /* 56 */
|
|
|
1156
|
+ '312113', /* 57 */
|
|
|
1157
|
+ '312311', /* 58 */
|
|
|
1158
|
+ '332111', /* 59 */
|
|
|
1159
|
+ '314111', /* 60 */
|
|
|
1160
|
+ '221411', /* 61 */
|
|
|
1161
|
+ '431111', /* 62 */
|
|
|
1162
|
+ '111224', /* 63 */
|
|
|
1163
|
+ '111422', /* 64 */
|
|
|
1164
|
+ '121124', /* 65 */
|
|
|
1165
|
+ '121421', /* 66 */
|
|
|
1166
|
+ '141122', /* 67 */
|
|
|
1167
|
+ '141221', /* 68 */
|
|
|
1168
|
+ '112214', /* 69 */
|
|
|
1169
|
+ '112412', /* 70 */
|
|
|
1170
|
+ '122114', /* 71 */
|
|
|
1171
|
+ '122411', /* 72 */
|
|
|
1172
|
+ '142112', /* 73 */
|
|
|
1173
|
+ '142211', /* 74 */
|
|
|
1174
|
+ '241211', /* 75 */
|
|
|
1175
|
+ '221114', /* 76 */
|
|
|
1176
|
+ '413111', /* 77 */
|
|
|
1177
|
+ '241112', /* 78 */
|
|
|
1178
|
+ '134111', /* 79 */
|
|
|
1179
|
+ '111242', /* 80 */
|
|
|
1180
|
+ '121142', /* 81 */
|
|
|
1181
|
+ '121241', /* 82 */
|
|
|
1182
|
+ '114212', /* 83 */
|
|
|
1183
|
+ '124112', /* 84 */
|
|
|
1184
|
+ '124211', /* 85 */
|
|
|
1185
|
+ '411212', /* 86 */
|
|
|
1186
|
+ '421112', /* 87 */
|
|
|
1187
|
+ '421211', /* 88 */
|
|
|
1188
|
+ '212141', /* 89 */
|
|
|
1189
|
+ '214121', /* 90 */
|
|
|
1190
|
+ '412121', /* 91 */
|
|
|
1191
|
+ '111143', /* 92 */
|
|
|
1192
|
+ '111341', /* 93 */
|
|
|
1193
|
+ '131141', /* 94 */
|
|
|
1194
|
+ '114113', /* 95 */
|
|
|
1195
|
+ '114311', /* 96 */
|
|
|
1196
|
+ '411113', /* 97 */
|
|
|
1197
|
+ '411311', /* 98 */
|
|
|
1198
|
+ '113141', /* 99 */
|
|
|
1199
|
+ '114131', /* 100 */
|
|
|
1200
|
+ '311141', /* 101 */
|
|
|
1201
|
+ '411131', /* 102 */
|
|
|
1202
|
+ '211412', /* 103 START A */
|
|
|
1203
|
+ '211214', /* 104 START B */
|
|
|
1204
|
+ '211232', /* 105 START C */
|
|
|
1205
|
+ '233111', /* STOP */
|
|
|
1206
|
+ '200000' /* END */
|
|
|
1207
|
+ );
|
|
|
1208
|
+ // ASCII characters for code A (ASCII 00 - 95)
|
|
|
1209
|
+ $keys_a = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
|
|
|
1210
|
+ $keys_a .= chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8) . chr(9);
|
|
|
1211
|
+ $keys_a .= chr(10) . chr(11) . chr(12) . chr(13) . chr(14) . chr(15) . chr(16) . chr(17) . chr(18) . chr(19);
|
|
|
1212
|
+ $keys_a .= chr(20) . chr(21) . chr(22) . chr(23) . chr(24) . chr(25) . chr(26) . chr(27) . chr(28) . chr(29);
|
|
|
1213
|
+ $keys_a .= chr(30) . chr(31);
|
|
|
1214
|
+ // ASCII characters for code B (ASCII 32 - 127)
|
|
|
1215
|
+ $keys_b = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' . chr(127);
|
|
|
1216
|
+ // special codes
|
|
|
1217
|
+ $fnc_a = array(241 => 102, 242 => 97, 243 => 96, 244 => 101);
|
|
|
1218
|
+ $fnc_b = array(241 => 102, 242 => 97, 243 => 96, 244 => 100);
|
|
|
1219
|
+ // array of symbols
|
|
|
1220
|
+ $code_data = array();
|
|
|
1221
|
+ // length of the code
|
|
|
1222
|
+ $len = strlen($code);
|
|
|
1223
|
+ switch (strtoupper($type)) {
|
|
|
1224
|
+ case 'A': { // MODE A
|
|
|
1225
|
+ $startid = 103;
|
|
|
1226
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
1227
|
+ $char = $code[$i];
|
|
|
1228
|
+ $char_id = ord($char);
|
|
|
1229
|
+ if (($char_id >= 241) AND ($char_id <= 244)) {
|
|
|
1230
|
+ $code_data[] = $fnc_a[$char_id];
|
|
|
1231
|
+ } elseif (($char_id >= 0) AND ($char_id <= 95)) {
|
|
|
1232
|
+ $code_data[] = strpos($keys_a, $char);
|
|
|
1233
|
+ } else {
|
|
|
1234
|
+ throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
|
|
|
1235
|
+ }
|
|
|
1236
|
+ }
|
|
|
1237
|
+ break;
|
|
|
1238
|
+ }
|
|
|
1239
|
+ case 'B': { // MODE B
|
|
|
1240
|
+ $startid = 104;
|
|
|
1241
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
1242
|
+ $char = $code[$i];
|
|
|
1243
|
+ $char_id = ord($char);
|
|
|
1244
|
+ if (($char_id >= 241) AND ($char_id <= 244)) {
|
|
|
1245
|
+ $code_data[] = $fnc_b[$char_id];
|
|
|
1246
|
+ } elseif (($char_id >= 32) AND ($char_id <= 127)) {
|
|
|
1247
|
+ $code_data[] = strpos($keys_b, $char);
|
|
|
1248
|
+ } else {
|
|
|
1249
|
+ throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
|
|
|
1250
|
+ }
|
|
|
1251
|
+ }
|
|
|
1252
|
+ break;
|
|
|
1253
|
+ }
|
|
|
1254
|
+ case 'C': { // MODE C
|
|
|
1255
|
+ $startid = 105;
|
|
|
1256
|
+ if (ord($code[0]) == 241) {
|
|
|
1257
|
+ $code_data[] = 102;
|
|
|
1258
|
+ $code = substr($code, 1);
|
|
|
1259
|
+ --$len;
|
|
|
1260
|
+ }
|
|
|
1261
|
+ if (($len % 2) != 0) {
|
|
|
1262
|
+ throw new InvalidLengthException('Length must be even');
|
|
|
1263
|
+ }
|
|
|
1264
|
+ for ($i = 0; $i < $len; $i += 2) {
|
|
|
1265
|
+ $chrnum = $code[$i] . $code[$i + 1];
|
|
|
1266
|
+ if (preg_match('/([0-9]{2})/', $chrnum) > 0) {
|
|
|
1267
|
+ $code_data[] = intval($chrnum);
|
|
|
1268
|
+ } else {
|
|
|
1269
|
+ throw new InvalidCharacterException();
|
|
|
1270
|
+ }
|
|
|
1271
|
+ }
|
|
|
1272
|
+ break;
|
|
|
1273
|
+ }
|
|
|
1274
|
+ default: { // MODE AUTO
|
|
|
1275
|
+ // split code into sequences
|
|
|
1276
|
+ $sequence = array();
|
|
|
1277
|
+ // get numeric sequences (if any)
|
|
|
1278
|
+ $numseq = array();
|
|
|
1279
|
+ preg_match_all('/([0-9]{4,})/', $code, $numseq, PREG_OFFSET_CAPTURE);
|
|
|
1280
|
+ if (isset($numseq[1]) AND ! empty($numseq[1])) {
|
|
|
1281
|
+ $end_offset = 0;
|
|
|
1282
|
+ foreach ($numseq[1] as $val) {
|
|
|
1283
|
+ $offset = $val[1];
|
|
|
1284
|
+
|
|
|
1285
|
+ // numeric sequence
|
|
|
1286
|
+ $slen = strlen($val[0]);
|
|
|
1287
|
+ if (($slen % 2) != 0) {
|
|
|
1288
|
+ // the length must be even
|
|
|
1289
|
+ ++$offset;
|
|
|
1290
|
+ $val[0] = substr($val[0],1);
|
|
|
1291
|
+ }
|
|
|
1292
|
+
|
|
|
1293
|
+ if ($offset > $end_offset) {
|
|
|
1294
|
+ // non numeric sequence
|
|
|
1295
|
+ $sequence = array_merge($sequence,
|
|
|
1296
|
+ $this->get128ABsequence(substr($code, $end_offset, ($offset - $end_offset))));
|
|
|
1297
|
+ }
|
|
|
1298
|
+ // numeric sequence fallback
|
|
|
1299
|
+ $slen = strlen($val[0]);
|
|
|
1300
|
+ if (($slen % 2) != 0) {
|
|
|
1301
|
+ // the length must be even
|
|
|
1302
|
+ --$slen;
|
|
|
1303
|
+ }
|
|
|
1304
|
+ $sequence[] = array('C', substr($code, $offset, $slen), $slen);
|
|
|
1305
|
+ $end_offset = $offset + $slen;
|
|
|
1306
|
+ }
|
|
|
1307
|
+ if ($end_offset < $len) {
|
|
|
1308
|
+ $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset)));
|
|
|
1309
|
+ }
|
|
|
1310
|
+ } else {
|
|
|
1311
|
+ // text code (non C mode)
|
|
|
1312
|
+ $sequence = array_merge($sequence, $this->get128ABsequence($code));
|
|
|
1313
|
+ }
|
|
|
1314
|
+ // process the sequence
|
|
|
1315
|
+ foreach ($sequence as $key => $seq) {
|
|
|
1316
|
+ switch ($seq[0]) {
|
|
|
1317
|
+ case 'A': {
|
|
|
1318
|
+ if ($key == 0) {
|
|
|
1319
|
+ $startid = 103;
|
|
|
1320
|
+ } elseif ($sequence[($key - 1)][0] != 'A') {
|
|
|
1321
|
+ if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'B') AND ( ! isset($sequence[($key - 1)][3]))) {
|
|
|
1322
|
+ // single character shift
|
|
|
1323
|
+ $code_data[] = 98;
|
|
|
1324
|
+ // mark shift
|
|
|
1325
|
+ $sequence[$key][3] = true;
|
|
|
1326
|
+ } elseif ( ! isset($sequence[($key - 1)][3])) {
|
|
|
1327
|
+ $code_data[] = 101;
|
|
|
1328
|
+ }
|
|
|
1329
|
+ }
|
|
|
1330
|
+ for ($i = 0; $i < $seq[2]; ++$i) {
|
|
|
1331
|
+ $char = $seq[1][$i];
|
|
|
1332
|
+ $char_id = ord($char);
|
|
|
1333
|
+ if (($char_id >= 241) AND ($char_id <= 244)) {
|
|
|
1334
|
+ $code_data[] = $fnc_a[$char_id];
|
|
|
1335
|
+ } else {
|
|
|
1336
|
+ $code_data[] = strpos($keys_a, $char);
|
|
|
1337
|
+ }
|
|
|
1338
|
+ }
|
|
|
1339
|
+ break;
|
|
|
1340
|
+ }
|
|
|
1341
|
+ case 'B': {
|
|
|
1342
|
+ if ($key == 0) {
|
|
|
1343
|
+ $tmpchr = ord($seq[1][0]);
|
|
|
1344
|
+ if (($seq[2] == 1) AND ($tmpchr >= 241) AND ($tmpchr <= 244) AND isset($sequence[($key + 1)]) AND ($sequence[($key + 1)][0] != 'B')) {
|
|
|
1345
|
+ switch ($sequence[($key + 1)][0]) {
|
|
|
1346
|
+ case 'A': {
|
|
|
1347
|
+ $startid = 103;
|
|
|
1348
|
+ $sequence[$key][0] = 'A';
|
|
|
1349
|
+ $code_data[] = $fnc_a[$tmpchr];
|
|
|
1350
|
+ break;
|
|
|
1351
|
+ }
|
|
|
1352
|
+ case 'C': {
|
|
|
1353
|
+ $startid = 105;
|
|
|
1354
|
+ $sequence[$key][0] = 'C';
|
|
|
1355
|
+ $code_data[] = $fnc_a[$tmpchr];
|
|
|
1356
|
+ break;
|
|
|
1357
|
+ }
|
|
|
1358
|
+ }
|
|
|
1359
|
+ break;
|
|
|
1360
|
+ } else {
|
|
|
1361
|
+ $startid = 104;
|
|
|
1362
|
+ }
|
|
|
1363
|
+ } elseif ($sequence[($key - 1)][0] != 'B') {
|
|
|
1364
|
+ if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'A') AND ( ! isset($sequence[($key - 1)][3]))) {
|
|
|
1365
|
+ // single character shift
|
|
|
1366
|
+ $code_data[] = 98;
|
|
|
1367
|
+ // mark shift
|
|
|
1368
|
+ $sequence[$key][3] = true;
|
|
|
1369
|
+ } elseif ( ! isset($sequence[($key - 1)][3])) {
|
|
|
1370
|
+ $code_data[] = 100;
|
|
|
1371
|
+ }
|
|
|
1372
|
+ }
|
|
|
1373
|
+ for ($i = 0; $i < $seq[2]; ++$i) {
|
|
|
1374
|
+ $char = $seq[1][$i];
|
|
|
1375
|
+ $char_id = ord($char);
|
|
|
1376
|
+ if (($char_id >= 241) AND ($char_id <= 244)) {
|
|
|
1377
|
+ $code_data[] = $fnc_b[$char_id];
|
|
|
1378
|
+ } else {
|
|
|
1379
|
+ $code_data[] = strpos($keys_b, $char);
|
|
|
1380
|
+ }
|
|
|
1381
|
+ }
|
|
|
1382
|
+ break;
|
|
|
1383
|
+ }
|
|
|
1384
|
+ case 'C': {
|
|
|
1385
|
+ if ($key == 0) {
|
|
|
1386
|
+ $startid = 105;
|
|
|
1387
|
+ } elseif ($sequence[($key - 1)][0] != 'C') {
|
|
|
1388
|
+ $code_data[] = 99;
|
|
|
1389
|
+ }
|
|
|
1390
|
+ for ($i = 0; $i < $seq[2]; $i += 2) {
|
|
|
1391
|
+ $chrnum = $seq[1][$i] . $seq[1][$i + 1];
|
|
|
1392
|
+ $code_data[] = intval($chrnum);
|
|
|
1393
|
+ }
|
|
|
1394
|
+ break;
|
|
|
1395
|
+ }
|
|
|
1396
|
+ }
|
|
|
1397
|
+ }
|
|
|
1398
|
+ }
|
|
|
1399
|
+ }
|
|
|
1400
|
+ // calculate check character
|
|
|
1401
|
+ $sum = $startid;
|
|
|
1402
|
+ foreach ($code_data as $key => $val) {
|
|
|
1403
|
+ $sum += ($val * ($key + 1));
|
|
|
1404
|
+ }
|
|
|
1405
|
+ // add check character
|
|
|
1406
|
+ $code_data[] = ($sum % 103);
|
|
|
1407
|
+ // add stop sequence
|
|
|
1408
|
+ $code_data[] = 106;
|
|
|
1409
|
+ $code_data[] = 107;
|
|
|
1410
|
+ // add start code at the beginning
|
|
|
1411
|
+ array_unshift($code_data, $startid);
|
|
|
1412
|
+ // build barcode array
|
|
|
1413
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
1414
|
+ foreach ($code_data as $val) {
|
|
|
1415
|
+ $seq = $chr[$val];
|
|
|
1416
|
+ for ($j = 0; $j < 6; ++$j) {
|
|
|
1417
|
+ if (($j % 2) == 0) {
|
|
|
1418
|
+ $t = true; // bar
|
|
|
1419
|
+ } else {
|
|
|
1420
|
+ $t = false; // space
|
|
|
1421
|
+ }
|
|
|
1422
|
+ $w = $seq[$j];
|
|
|
1423
|
+ $bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
1424
|
+ $bararray['maxw'] += $w;
|
|
|
1425
|
+ }
|
|
|
1426
|
+ }
|
|
|
1427
|
+
|
|
|
1428
|
+ return $bararray;
|
|
|
1429
|
+ }
|
|
|
1430
|
+
|
|
|
1431
|
+ /**
|
|
|
1432
|
+ * Split text code in A/B sequence for 128 code
|
|
|
1433
|
+ *
|
|
|
1434
|
+ * @param $code (string) code to split.
|
|
|
1435
|
+ * @return array sequence
|
|
|
1436
|
+ * @protected
|
|
|
1437
|
+ */
|
|
|
1438
|
+ protected function get128ABsequence($code)
|
|
|
1439
|
+ {
|
|
|
1440
|
+ $len = strlen($code);
|
|
|
1441
|
+ $sequence = array();
|
|
|
1442
|
+ // get A sequences (if any)
|
|
|
1443
|
+ $numseq = array();
|
|
|
1444
|
+ preg_match_all('/([\x00-\x1f])/', $code, $numseq, PREG_OFFSET_CAPTURE);
|
|
|
1445
|
+ if (isset($numseq[1]) AND ! empty($numseq[1])) {
|
|
|
1446
|
+ $end_offset = 0;
|
|
|
1447
|
+ foreach ($numseq[1] as $val) {
|
|
|
1448
|
+ $offset = $val[1];
|
|
|
1449
|
+ if ($offset > $end_offset) {
|
|
|
1450
|
+ // B sequence
|
|
|
1451
|
+ $sequence[] = array(
|
|
|
1452
|
+ 'B',
|
|
|
1453
|
+ substr($code, $end_offset, ($offset - $end_offset)),
|
|
|
1454
|
+ ($offset - $end_offset)
|
|
|
1455
|
+ );
|
|
|
1456
|
+ }
|
|
|
1457
|
+ // A sequence
|
|
|
1458
|
+ $slen = strlen($val[0]);
|
|
|
1459
|
+ $sequence[] = array('A', substr($code, $offset, $slen), $slen);
|
|
|
1460
|
+ $end_offset = $offset + $slen;
|
|
|
1461
|
+ }
|
|
|
1462
|
+ if ($end_offset < $len) {
|
|
|
1463
|
+ $sequence[] = array('B', substr($code, $end_offset), ($len - $end_offset));
|
|
|
1464
|
+ }
|
|
|
1465
|
+ } else {
|
|
|
1466
|
+ // only B sequence
|
|
|
1467
|
+ $sequence[] = array('B', $code, $len);
|
|
|
1468
|
+ }
|
|
|
1469
|
+
|
|
|
1470
|
+ return $sequence;
|
|
|
1471
|
+ }
|
|
|
1472
|
+
|
|
|
1473
|
+ /**
|
|
|
1474
|
+ * EAN13 and UPC-A barcodes.
|
|
|
1475
|
+ * EAN13: European Article Numbering international retail product code
|
|
|
1476
|
+ * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
|
|
|
1477
|
+ * UPC-E: Short version of UPC symbol
|
|
|
1478
|
+ *
|
|
|
1479
|
+ * @param $code (string) code to represent.
|
|
|
1480
|
+ * @param $len (string) barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A
|
|
|
1481
|
+ * @return array barcode representation.
|
|
|
1482
|
+ * @protected
|
|
|
1483
|
+ */
|
|
|
1484
|
+ protected function barcode_eanupc($code, $len = 13)
|
|
|
1485
|
+ {
|
|
|
1486
|
+ $upce = false;
|
|
|
1487
|
+ if ($len == 6) {
|
|
|
1488
|
+ $len = 12; // UPC-A
|
|
|
1489
|
+ $upce = true; // UPC-E mode
|
|
|
1490
|
+ }
|
|
|
1491
|
+ $data_len = $len - 1;
|
|
|
1492
|
+ //Padding
|
|
|
1493
|
+ $code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
|
|
|
1494
|
+ $code_len = strlen($code);
|
|
|
1495
|
+ // calculate check digit
|
|
|
1496
|
+ $sum_a = 0;
|
|
|
1497
|
+ for ($i = 1; $i < $data_len; $i += 2) {
|
|
|
1498
|
+ $sum_a += $code[$i];
|
|
|
1499
|
+ }
|
|
|
1500
|
+ if ($len > 12) {
|
|
|
1501
|
+ $sum_a *= 3;
|
|
|
1502
|
+ }
|
|
|
1503
|
+ $sum_b = 0;
|
|
|
1504
|
+ for ($i = 0; $i < $data_len; $i += 2) {
|
|
|
1505
|
+ $sum_b += intval(($code[$i]));
|
|
|
1506
|
+ }
|
|
|
1507
|
+ if ($len < 13) {
|
|
|
1508
|
+ $sum_b *= 3;
|
|
|
1509
|
+ }
|
|
|
1510
|
+ $r = ($sum_a + $sum_b) % 10;
|
|
|
1511
|
+ if ($r > 0) {
|
|
|
1512
|
+ $r = (10 - $r);
|
|
|
1513
|
+ }
|
|
|
1514
|
+ if ($code_len == $data_len) {
|
|
|
1515
|
+ // add check digit
|
|
|
1516
|
+ $code .= $r;
|
|
|
1517
|
+ } elseif ($r !== intval($code[$data_len])) {
|
|
|
1518
|
+ throw new InvalidCheckDigitException();
|
|
|
1519
|
+ }
|
|
|
1520
|
+ if ($len == 12) {
|
|
|
1521
|
+ // UPC-A
|
|
|
1522
|
+ $code = '0' . $code;
|
|
|
1523
|
+ ++$len;
|
|
|
1524
|
+ }
|
|
|
1525
|
+ if ($upce) {
|
|
|
1526
|
+ // convert UPC-A to UPC-E
|
|
|
1527
|
+ $tmp = substr($code, 4, 3);
|
|
|
1528
|
+ if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
|
|
|
1529
|
+ // manufacturer code ends in 000, 100, or 200
|
|
|
1530
|
+ $upce_code = substr($code, 2, 2) . substr($code, 9, 3) . substr($code, 4, 1);
|
|
|
1531
|
+ } else {
|
|
|
1532
|
+ $tmp = substr($code, 5, 2);
|
|
|
1533
|
+ if ($tmp == '00') {
|
|
|
1534
|
+ // manufacturer code ends in 00
|
|
|
1535
|
+ $upce_code = substr($code, 2, 3) . substr($code, 10, 2) . '3';
|
|
|
1536
|
+ } else {
|
|
|
1537
|
+ $tmp = substr($code, 6, 1);
|
|
|
1538
|
+ if ($tmp == '0') {
|
|
|
1539
|
+ // manufacturer code ends in 0
|
|
|
1540
|
+ $upce_code = substr($code, 2, 4) . substr($code, 11, 1) . '4';
|
|
|
1541
|
+ } else {
|
|
|
1542
|
+ // manufacturer code does not end in zero
|
|
|
1543
|
+ $upce_code = substr($code, 2, 5) . substr($code, 11, 1);
|
|
|
1544
|
+ }
|
|
|
1545
|
+ }
|
|
|
1546
|
+ }
|
|
|
1547
|
+ }
|
|
|
1548
|
+ //Convert digits to bars
|
|
|
1549
|
+ $codes = array(
|
|
|
1550
|
+ 'A' => array( // left odd parity
|
|
|
1551
|
+ '0' => '0001101',
|
|
|
1552
|
+ '1' => '0011001',
|
|
|
1553
|
+ '2' => '0010011',
|
|
|
1554
|
+ '3' => '0111101',
|
|
|
1555
|
+ '4' => '0100011',
|
|
|
1556
|
+ '5' => '0110001',
|
|
|
1557
|
+ '6' => '0101111',
|
|
|
1558
|
+ '7' => '0111011',
|
|
|
1559
|
+ '8' => '0110111',
|
|
|
1560
|
+ '9' => '0001011'
|
|
|
1561
|
+ ),
|
|
|
1562
|
+ 'B' => array( // left even parity
|
|
|
1563
|
+ '0' => '0100111',
|
|
|
1564
|
+ '1' => '0110011',
|
|
|
1565
|
+ '2' => '0011011',
|
|
|
1566
|
+ '3' => '0100001',
|
|
|
1567
|
+ '4' => '0011101',
|
|
|
1568
|
+ '5' => '0111001',
|
|
|
1569
|
+ '6' => '0000101',
|
|
|
1570
|
+ '7' => '0010001',
|
|
|
1571
|
+ '8' => '0001001',
|
|
|
1572
|
+ '9' => '0010111'
|
|
|
1573
|
+ ),
|
|
|
1574
|
+ 'C' => array( // right
|
|
|
1575
|
+ '0' => '1110010',
|
|
|
1576
|
+ '1' => '1100110',
|
|
|
1577
|
+ '2' => '1101100',
|
|
|
1578
|
+ '3' => '1000010',
|
|
|
1579
|
+ '4' => '1011100',
|
|
|
1580
|
+ '5' => '1001110',
|
|
|
1581
|
+ '6' => '1010000',
|
|
|
1582
|
+ '7' => '1000100',
|
|
|
1583
|
+ '8' => '1001000',
|
|
|
1584
|
+ '9' => '1110100'
|
|
|
1585
|
+ )
|
|
|
1586
|
+ );
|
|
|
1587
|
+ $parities = array(
|
|
|
1588
|
+ '0' => array('A', 'A', 'A', 'A', 'A', 'A'),
|
|
|
1589
|
+ '1' => array('A', 'A', 'B', 'A', 'B', 'B'),
|
|
|
1590
|
+ '2' => array('A', 'A', 'B', 'B', 'A', 'B'),
|
|
|
1591
|
+ '3' => array('A', 'A', 'B', 'B', 'B', 'A'),
|
|
|
1592
|
+ '4' => array('A', 'B', 'A', 'A', 'B', 'B'),
|
|
|
1593
|
+ '5' => array('A', 'B', 'B', 'A', 'A', 'B'),
|
|
|
1594
|
+ '6' => array('A', 'B', 'B', 'B', 'A', 'A'),
|
|
|
1595
|
+ '7' => array('A', 'B', 'A', 'B', 'A', 'B'),
|
|
|
1596
|
+ '8' => array('A', 'B', 'A', 'B', 'B', 'A'),
|
|
|
1597
|
+ '9' => array('A', 'B', 'B', 'A', 'B', 'A')
|
|
|
1598
|
+ );
|
|
|
1599
|
+ $upce_parities = array();
|
|
|
1600
|
+ $upce_parities[0] = array(
|
|
|
1601
|
+ '0' => array('B', 'B', 'B', 'A', 'A', 'A'),
|
|
|
1602
|
+ '1' => array('B', 'B', 'A', 'B', 'A', 'A'),
|
|
|
1603
|
+ '2' => array('B', 'B', 'A', 'A', 'B', 'A'),
|
|
|
1604
|
+ '3' => array('B', 'B', 'A', 'A', 'A', 'B'),
|
|
|
1605
|
+ '4' => array('B', 'A', 'B', 'B', 'A', 'A'),
|
|
|
1606
|
+ '5' => array('B', 'A', 'A', 'B', 'B', 'A'),
|
|
|
1607
|
+ '6' => array('B', 'A', 'A', 'A', 'B', 'B'),
|
|
|
1608
|
+ '7' => array('B', 'A', 'B', 'A', 'B', 'A'),
|
|
|
1609
|
+ '8' => array('B', 'A', 'B', 'A', 'A', 'B'),
|
|
|
1610
|
+ '9' => array('B', 'A', 'A', 'B', 'A', 'B')
|
|
|
1611
|
+ );
|
|
|
1612
|
+ $upce_parities[1] = array(
|
|
|
1613
|
+ '0' => array('A', 'A', 'A', 'B', 'B', 'B'),
|
|
|
1614
|
+ '1' => array('A', 'A', 'B', 'A', 'B', 'B'),
|
|
|
1615
|
+ '2' => array('A', 'A', 'B', 'B', 'A', 'B'),
|
|
|
1616
|
+ '3' => array('A', 'A', 'B', 'B', 'B', 'A'),
|
|
|
1617
|
+ '4' => array('A', 'B', 'A', 'A', 'B', 'B'),
|
|
|
1618
|
+ '5' => array('A', 'B', 'B', 'A', 'A', 'B'),
|
|
|
1619
|
+ '6' => array('A', 'B', 'B', 'B', 'A', 'A'),
|
|
|
1620
|
+ '7' => array('A', 'B', 'A', 'B', 'A', 'B'),
|
|
|
1621
|
+ '8' => array('A', 'B', 'A', 'B', 'B', 'A'),
|
|
|
1622
|
+ '9' => array('A', 'B', 'B', 'A', 'B', 'A')
|
|
|
1623
|
+ );
|
|
|
1624
|
+ $k = 0;
|
|
|
1625
|
+ $seq = '101'; // left guard bar
|
|
|
1626
|
+ if ($upce) {
|
|
|
1627
|
+ $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
1628
|
+ $p = $upce_parities[$code[1]][$r];
|
|
|
1629
|
+ for ($i = 0; $i < 6; ++$i) {
|
|
|
1630
|
+ $seq .= $codes[$p[$i]][$upce_code[$i]];
|
|
|
1631
|
+ }
|
|
|
1632
|
+ $seq .= '010101'; // right guard bar
|
|
|
1633
|
+ } else {
|
|
|
1634
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
1635
|
+ $half_len = intval(ceil($len / 2));
|
|
|
1636
|
+ if ($len == 8) {
|
|
|
1637
|
+ for ($i = 0; $i < $half_len; ++$i) {
|
|
|
1638
|
+ $seq .= $codes['A'][$code[$i]];
|
|
|
1639
|
+ }
|
|
|
1640
|
+ } else {
|
|
|
1641
|
+ $p = $parities[$code[0]];
|
|
|
1642
|
+ for ($i = 1; $i < $half_len; ++$i) {
|
|
|
1643
|
+ $seq .= $codes[$p[$i - 1]][$code[$i]];
|
|
|
1644
|
+ }
|
|
|
1645
|
+ }
|
|
|
1646
|
+ $seq .= '01010'; // center guard bar
|
|
|
1647
|
+ for ($i = $half_len; $i < $len; ++$i) {
|
|
|
1648
|
+ if ( ! isset($codes['C'][$code[$i]])) {
|
|
|
1649
|
+ throw new InvalidCharacterException('Char ' . $code[$i] . ' not allowed');
|
|
|
1650
|
+ }
|
|
|
1651
|
+ $seq .= $codes['C'][$code[$i]];
|
|
|
1652
|
+ }
|
|
|
1653
|
+ $seq .= '101'; // right guard bar
|
|
|
1654
|
+ }
|
|
|
1655
|
+ $clen = strlen($seq);
|
|
|
1656
|
+ $w = 0;
|
|
|
1657
|
+ for ($i = 0; $i < $clen; ++$i) {
|
|
|
1658
|
+ $w += 1;
|
|
|
1659
|
+ if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq[$i] != $seq[($i + 1)]))) {
|
|
|
1660
|
+ if ($seq[$i] == '1') {
|
|
|
1661
|
+ $t = true; // bar
|
|
|
1662
|
+ } else {
|
|
|
1663
|
+ $t = false; // space
|
|
|
1664
|
+ }
|
|
|
1665
|
+ $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
1666
|
+ $bararray['maxw'] += $w;
|
|
|
1667
|
+ ++$k;
|
|
|
1668
|
+ $w = 0;
|
|
|
1669
|
+ }
|
|
|
1670
|
+ }
|
|
|
1671
|
+
|
|
|
1672
|
+ return $bararray;
|
|
|
1673
|
+ }
|
|
|
1674
|
+
|
|
|
1675
|
+ /**
|
|
|
1676
|
+ * UPC-Based Extensions
|
|
|
1677
|
+ * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers
|
|
|
1678
|
+ * 5-Digit Ext.: Used to mark suggested retail price of books
|
|
|
1679
|
+ *
|
|
|
1680
|
+ * @param $code (string) code to represent.
|
|
|
1681
|
+ * @param $len (string) barcode type: 2 = 2-Digit, 5 = 5-Digit
|
|
|
1682
|
+ * @return array barcode representation.
|
|
|
1683
|
+ * @protected
|
|
|
1684
|
+ */
|
|
|
1685
|
+ protected function barcode_eanext($code, $len = 5)
|
|
|
1686
|
+ {
|
|
|
1687
|
+ //Padding
|
|
|
1688
|
+ $code = str_pad($code, $len, '0', STR_PAD_LEFT);
|
|
|
1689
|
+ // calculate check digit
|
|
|
1690
|
+ if ($len == 2) {
|
|
|
1691
|
+ $r = $code % 4;
|
|
|
1692
|
+ } elseif ($len == 5) {
|
|
|
1693
|
+ $r = (3 * ($code[0] + $code[2] + $code[4])) + (9 * ($code[1] + $code[3]));
|
|
|
1694
|
+ $r %= 10;
|
|
|
1695
|
+ } else {
|
|
|
1696
|
+ throw new InvalidCheckDigitException();
|
|
|
1697
|
+ }
|
|
|
1698
|
+ //Convert digits to bars
|
|
|
1699
|
+ $codes = array(
|
|
|
1700
|
+ 'A' => array( // left odd parity
|
|
|
1701
|
+ '0' => '0001101',
|
|
|
1702
|
+ '1' => '0011001',
|
|
|
1703
|
+ '2' => '0010011',
|
|
|
1704
|
+ '3' => '0111101',
|
|
|
1705
|
+ '4' => '0100011',
|
|
|
1706
|
+ '5' => '0110001',
|
|
|
1707
|
+ '6' => '0101111',
|
|
|
1708
|
+ '7' => '0111011',
|
|
|
1709
|
+ '8' => '0110111',
|
|
|
1710
|
+ '9' => '0001011'
|
|
|
1711
|
+ ),
|
|
|
1712
|
+ 'B' => array( // left even parity
|
|
|
1713
|
+ '0' => '0100111',
|
|
|
1714
|
+ '1' => '0110011',
|
|
|
1715
|
+ '2' => '0011011',
|
|
|
1716
|
+ '3' => '0100001',
|
|
|
1717
|
+ '4' => '0011101',
|
|
|
1718
|
+ '5' => '0111001',
|
|
|
1719
|
+ '6' => '0000101',
|
|
|
1720
|
+ '7' => '0010001',
|
|
|
1721
|
+ '8' => '0001001',
|
|
|
1722
|
+ '9' => '0010111'
|
|
|
1723
|
+ )
|
|
|
1724
|
+ );
|
|
|
1725
|
+ $parities = array();
|
|
|
1726
|
+ $parities[2] = array(
|
|
|
1727
|
+ '0' => array('A', 'A'),
|
|
|
1728
|
+ '1' => array('A', 'B'),
|
|
|
1729
|
+ '2' => array('B', 'A'),
|
|
|
1730
|
+ '3' => array('B', 'B')
|
|
|
1731
|
+ );
|
|
|
1732
|
+ $parities[5] = array(
|
|
|
1733
|
+ '0' => array('B', 'B', 'A', 'A', 'A'),
|
|
|
1734
|
+ '1' => array('B', 'A', 'B', 'A', 'A'),
|
|
|
1735
|
+ '2' => array('B', 'A', 'A', 'B', 'A'),
|
|
|
1736
|
+ '3' => array('B', 'A', 'A', 'A', 'B'),
|
|
|
1737
|
+ '4' => array('A', 'B', 'B', 'A', 'A'),
|
|
|
1738
|
+ '5' => array('A', 'A', 'B', 'B', 'A'),
|
|
|
1739
|
+ '6' => array('A', 'A', 'A', 'B', 'B'),
|
|
|
1740
|
+ '7' => array('A', 'B', 'A', 'B', 'A'),
|
|
|
1741
|
+ '8' => array('A', 'B', 'A', 'A', 'B'),
|
|
|
1742
|
+ '9' => array('A', 'A', 'B', 'A', 'B')
|
|
|
1743
|
+ );
|
|
|
1744
|
+ $p = $parities[$len][$r];
|
|
|
1745
|
+ $seq = '1011'; // left guard bar
|
|
|
1746
|
+ $seq .= $codes[$p[0]][$code[0]];
|
|
|
1747
|
+ for ($i = 1; $i < $len; ++$i) {
|
|
|
1748
|
+ $seq .= '01'; // separator
|
|
|
1749
|
+ $seq .= $codes[$p[$i]][$code[$i]];
|
|
|
1750
|
+ }
|
|
|
1751
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
1752
|
+
|
|
|
1753
|
+ return $this->binseq_to_array($seq, $bararray);
|
|
|
1754
|
+ }
|
|
|
1755
|
+
|
|
|
1756
|
+ /**
|
|
|
1757
|
+ * POSTNET and PLANET barcodes.
|
|
|
1758
|
+ * Used by U.S. Postal Service for automated mail sorting
|
|
|
1759
|
+ *
|
|
|
1760
|
+ * @param $code (string) zip code to represent. Must be a string containing a zip code of the form DDDDD or
|
|
|
1761
|
+ * DDDDD-DDDD.
|
|
|
1762
|
+ * @param $planet (boolean) if true print the PLANET barcode, otherwise print POSTNET
|
|
|
1763
|
+ * @return array barcode representation.
|
|
|
1764
|
+ * @protected
|
|
|
1765
|
+ */
|
|
|
1766
|
+ protected function barcode_postnet($code, $planet = false)
|
|
|
1767
|
+ {
|
|
|
1768
|
+ // bar length
|
|
|
1769
|
+ if ($planet) {
|
|
|
1770
|
+ $barlen = Array(
|
|
|
1771
|
+ 0 => Array(1, 1, 2, 2, 2),
|
|
|
1772
|
+ 1 => Array(2, 2, 2, 1, 1),
|
|
|
1773
|
+ 2 => Array(2, 2, 1, 2, 1),
|
|
|
1774
|
+ 3 => Array(2, 2, 1, 1, 2),
|
|
|
1775
|
+ 4 => Array(2, 1, 2, 2, 1),
|
|
|
1776
|
+ 5 => Array(2, 1, 2, 1, 2),
|
|
|
1777
|
+ 6 => Array(2, 1, 1, 2, 2),
|
|
|
1778
|
+ 7 => Array(1, 2, 2, 2, 1),
|
|
|
1779
|
+ 8 => Array(1, 2, 2, 1, 2),
|
|
|
1780
|
+ 9 => Array(1, 2, 1, 2, 2)
|
|
|
1781
|
+ );
|
|
|
1782
|
+ } else {
|
|
|
1783
|
+ $barlen = Array(
|
|
|
1784
|
+ 0 => Array(2, 2, 1, 1, 1),
|
|
|
1785
|
+ 1 => Array(1, 1, 1, 2, 2),
|
|
|
1786
|
+ 2 => Array(1, 1, 2, 1, 2),
|
|
|
1787
|
+ 3 => Array(1, 1, 2, 2, 1),
|
|
|
1788
|
+ 4 => Array(1, 2, 1, 1, 2),
|
|
|
1789
|
+ 5 => Array(1, 2, 1, 2, 1),
|
|
|
1790
|
+ 6 => Array(1, 2, 2, 1, 1),
|
|
|
1791
|
+ 7 => Array(2, 1, 1, 1, 2),
|
|
|
1792
|
+ 8 => Array(2, 1, 1, 2, 1),
|
|
|
1793
|
+ 9 => Array(2, 1, 2, 1, 1)
|
|
|
1794
|
+ );
|
|
|
1795
|
+ }
|
|
|
1796
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
|
|
|
1797
|
+ $k = 0;
|
|
|
1798
|
+ $code = str_replace('-', '', $code);
|
|
|
1799
|
+ $code = str_replace(' ', '', $code);
|
|
|
1800
|
+ $len = strlen($code);
|
|
|
1801
|
+ // calculate checksum
|
|
|
1802
|
+ $sum = 0;
|
|
|
1803
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
1804
|
+ $sum += intval($code[$i]);
|
|
|
1805
|
+ }
|
|
|
1806
|
+ $chkd = ($sum % 10);
|
|
|
1807
|
+ if ($chkd > 0) {
|
|
|
1808
|
+ $chkd = (10 - $chkd);
|
|
|
1809
|
+ }
|
|
|
1810
|
+ $code .= $chkd;
|
|
|
1811
|
+ $len = strlen($code);
|
|
|
1812
|
+ // start bar
|
|
|
1813
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
1814
|
+ $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
1815
|
+ $bararray['maxw'] += 2;
|
|
|
1816
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
1817
|
+ for ($j = 0; $j < 5; ++$j) {
|
|
|
1818
|
+ $h = $barlen[$code[$i]][$j];
|
|
|
1819
|
+ $p = floor(1 / $h);
|
|
|
1820
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
|
|
|
1821
|
+ $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
1822
|
+ $bararray['maxw'] += 2;
|
|
|
1823
|
+ }
|
|
|
1824
|
+ }
|
|
|
1825
|
+ // end bar
|
|
|
1826
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
1827
|
+ $bararray['maxw'] += 1;
|
|
|
1828
|
+
|
|
|
1829
|
+ return $bararray;
|
|
|
1830
|
+ }
|
|
|
1831
|
+
|
|
|
1832
|
+ /**
|
|
|
1833
|
+ * RMS4CC - CBC - KIX
|
|
|
1834
|
+ * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index)
|
|
|
1835
|
+ * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service.
|
|
|
1836
|
+ *
|
|
|
1837
|
+ * @param $code (string) code to print
|
|
|
1838
|
+ * @param $kix (boolean) if true prints the KIX variation (doesn't use the start and end symbols, and the checksum)
|
|
|
1839
|
+ * - in this case the house number must be sufficed with an X and placed at the end of the code.
|
|
|
1840
|
+ * @return array barcode representation.
|
|
|
1841
|
+ * @protected
|
|
|
1842
|
+ */
|
|
|
1843
|
+ protected function barcode_rms4cc($code, $kix = false)
|
|
|
1844
|
+ {
|
|
|
1845
|
+ $notkix = ! $kix;
|
|
|
1846
|
+ // bar mode
|
|
|
1847
|
+ // 1 = pos 1, length 2
|
|
|
1848
|
+ // 2 = pos 1, length 3
|
|
|
1849
|
+ // 3 = pos 2, length 1
|
|
|
1850
|
+ // 4 = pos 2, length 2
|
|
|
1851
|
+ $barmode = array(
|
|
|
1852
|
+ '0' => array(3, 3, 2, 2),
|
|
|
1853
|
+ '1' => array(3, 4, 1, 2),
|
|
|
1854
|
+ '2' => array(3, 4, 2, 1),
|
|
|
1855
|
+ '3' => array(4, 3, 1, 2),
|
|
|
1856
|
+ '4' => array(4, 3, 2, 1),
|
|
|
1857
|
+ '5' => array(4, 4, 1, 1),
|
|
|
1858
|
+ '6' => array(3, 1, 4, 2),
|
|
|
1859
|
+ '7' => array(3, 2, 3, 2),
|
|
|
1860
|
+ '8' => array(3, 2, 4, 1),
|
|
|
1861
|
+ '9' => array(4, 1, 3, 2),
|
|
|
1862
|
+ 'A' => array(4, 1, 4, 1),
|
|
|
1863
|
+ 'B' => array(4, 2, 3, 1),
|
|
|
1864
|
+ 'C' => array(3, 1, 2, 4),
|
|
|
1865
|
+ 'D' => array(3, 2, 1, 4),
|
|
|
1866
|
+ 'E' => array(3, 2, 2, 3),
|
|
|
1867
|
+ 'F' => array(4, 1, 1, 4),
|
|
|
1868
|
+ 'G' => array(4, 1, 2, 3),
|
|
|
1869
|
+ 'H' => array(4, 2, 1, 3),
|
|
|
1870
|
+ 'I' => array(1, 3, 4, 2),
|
|
|
1871
|
+ 'J' => array(1, 4, 3, 2),
|
|
|
1872
|
+ 'K' => array(1, 4, 4, 1),
|
|
|
1873
|
+ 'L' => array(2, 3, 3, 2),
|
|
|
1874
|
+ 'M' => array(2, 3, 4, 1),
|
|
|
1875
|
+ 'N' => array(2, 4, 3, 1),
|
|
|
1876
|
+ 'O' => array(1, 3, 2, 4),
|
|
|
1877
|
+ 'P' => array(1, 4, 1, 4),
|
|
|
1878
|
+ 'Q' => array(1, 4, 2, 3),
|
|
|
1879
|
+ 'R' => array(2, 3, 1, 4),
|
|
|
1880
|
+ 'S' => array(2, 3, 2, 3),
|
|
|
1881
|
+ 'T' => array(2, 4, 1, 3),
|
|
|
1882
|
+ 'U' => array(1, 1, 4, 4),
|
|
|
1883
|
+ 'V' => array(1, 2, 3, 4),
|
|
|
1884
|
+ 'W' => array(1, 2, 4, 3),
|
|
|
1885
|
+ 'X' => array(2, 1, 3, 4),
|
|
|
1886
|
+ 'Y' => array(2, 1, 4, 3),
|
|
|
1887
|
+ 'Z' => array(2, 2, 3, 3)
|
|
|
1888
|
+ );
|
|
|
1889
|
+ $code = strtoupper($code);
|
|
|
1890
|
+ $len = strlen($code);
|
|
|
1891
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
|
|
|
1892
|
+ if ($notkix) {
|
|
|
1893
|
+ // table for checksum calculation (row,col)
|
|
|
1894
|
+ $checktable = array(
|
|
|
1895
|
+ '0' => array(1, 1),
|
|
|
1896
|
+ '1' => array(1, 2),
|
|
|
1897
|
+ '2' => array(1, 3),
|
|
|
1898
|
+ '3' => array(1, 4),
|
|
|
1899
|
+ '4' => array(1, 5),
|
|
|
1900
|
+ '5' => array(1, 0),
|
|
|
1901
|
+ '6' => array(2, 1),
|
|
|
1902
|
+ '7' => array(2, 2),
|
|
|
1903
|
+ '8' => array(2, 3),
|
|
|
1904
|
+ '9' => array(2, 4),
|
|
|
1905
|
+ 'A' => array(2, 5),
|
|
|
1906
|
+ 'B' => array(2, 0),
|
|
|
1907
|
+ 'C' => array(3, 1),
|
|
|
1908
|
+ 'D' => array(3, 2),
|
|
|
1909
|
+ 'E' => array(3, 3),
|
|
|
1910
|
+ 'F' => array(3, 4),
|
|
|
1911
|
+ 'G' => array(3, 5),
|
|
|
1912
|
+ 'H' => array(3, 0),
|
|
|
1913
|
+ 'I' => array(4, 1),
|
|
|
1914
|
+ 'J' => array(4, 2),
|
|
|
1915
|
+ 'K' => array(4, 3),
|
|
|
1916
|
+ 'L' => array(4, 4),
|
|
|
1917
|
+ 'M' => array(4, 5),
|
|
|
1918
|
+ 'N' => array(4, 0),
|
|
|
1919
|
+ 'O' => array(5, 1),
|
|
|
1920
|
+ 'P' => array(5, 2),
|
|
|
1921
|
+ 'Q' => array(5, 3),
|
|
|
1922
|
+ 'R' => array(5, 4),
|
|
|
1923
|
+ 'S' => array(5, 5),
|
|
|
1924
|
+ 'T' => array(5, 0),
|
|
|
1925
|
+ 'U' => array(0, 1),
|
|
|
1926
|
+ 'V' => array(0, 2),
|
|
|
1927
|
+ 'W' => array(0, 3),
|
|
|
1928
|
+ 'X' => array(0, 4),
|
|
|
1929
|
+ 'Y' => array(0, 5),
|
|
|
1930
|
+ 'Z' => array(0, 0)
|
|
|
1931
|
+ );
|
|
|
1932
|
+ $row = 0;
|
|
|
1933
|
+ $col = 0;
|
|
|
1934
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
1935
|
+ $row += $checktable[$code[$i]][0];
|
|
|
1936
|
+ $col += $checktable[$code[$i]][1];
|
|
|
1937
|
+ }
|
|
|
1938
|
+ $row %= 6;
|
|
|
1939
|
+ $col %= 6;
|
|
|
1940
|
+ $chk = array_keys($checktable, array($row, $col));
|
|
|
1941
|
+ $code .= $chk[0];
|
|
|
1942
|
+ ++$len;
|
|
|
1943
|
+ }
|
|
|
1944
|
+ $k = 0;
|
|
|
1945
|
+ if ($notkix) {
|
|
|
1946
|
+ // start bar
|
|
|
1947
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
1948
|
+ $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
1949
|
+ $bararray['maxw'] += 2;
|
|
|
1950
|
+ }
|
|
|
1951
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
1952
|
+ for ($j = 0; $j < 4; ++$j) {
|
|
|
1953
|
+ switch ($barmode[$code[$i]][$j]) {
|
|
|
1954
|
+ case 1: {
|
|
|
1955
|
+ $p = 0;
|
|
|
1956
|
+ $h = 2;
|
|
|
1957
|
+ break;
|
|
|
1958
|
+ }
|
|
|
1959
|
+ case 2: {
|
|
|
1960
|
+ $p = 0;
|
|
|
1961
|
+ $h = 3;
|
|
|
1962
|
+ break;
|
|
|
1963
|
+ }
|
|
|
1964
|
+ case 3: {
|
|
|
1965
|
+ $p = 1;
|
|
|
1966
|
+ $h = 1;
|
|
|
1967
|
+ break;
|
|
|
1968
|
+ }
|
|
|
1969
|
+ case 4: {
|
|
|
1970
|
+ $p = 1;
|
|
|
1971
|
+ $h = 2;
|
|
|
1972
|
+ break;
|
|
|
1973
|
+ }
|
|
|
1974
|
+ }
|
|
|
1975
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
|
|
|
1976
|
+ $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
1977
|
+ $bararray['maxw'] += 2;
|
|
|
1978
|
+ }
|
|
|
1979
|
+ }
|
|
|
1980
|
+ if ($notkix) {
|
|
|
1981
|
+ // stop bar
|
|
|
1982
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
|
|
|
1983
|
+ $bararray['maxw'] += 1;
|
|
|
1984
|
+ }
|
|
|
1985
|
+
|
|
|
1986
|
+ return $bararray;
|
|
|
1987
|
+ }
|
|
|
1988
|
+
|
|
|
1989
|
+ /**
|
|
|
1990
|
+ * CODABAR barcodes.
|
|
|
1991
|
+ * Older code often used in library systems, sometimes in blood banks
|
|
|
1992
|
+ *
|
|
|
1993
|
+ * @param $code (string) code to represent.
|
|
|
1994
|
+ * @return array barcode representation.
|
|
|
1995
|
+ * @protected
|
|
|
1996
|
+ */
|
|
|
1997
|
+ protected function barcode_codabar($code)
|
|
|
1998
|
+ {
|
|
|
1999
|
+ $chr = array(
|
|
|
2000
|
+ '0' => '11111221',
|
|
|
2001
|
+ '1' => '11112211',
|
|
|
2002
|
+ '2' => '11121121',
|
|
|
2003
|
+ '3' => '22111111',
|
|
|
2004
|
+ '4' => '11211211',
|
|
|
2005
|
+ '5' => '21111211',
|
|
|
2006
|
+ '6' => '12111121',
|
|
|
2007
|
+ '7' => '12112111',
|
|
|
2008
|
+ '8' => '12211111',
|
|
|
2009
|
+ '9' => '21121111',
|
|
|
2010
|
+ '-' => '11122111',
|
|
|
2011
|
+ '$' => '11221111',
|
|
|
2012
|
+ ':' => '21112121',
|
|
|
2013
|
+ '/' => '21211121',
|
|
|
2014
|
+ '.' => '21212111',
|
|
|
2015
|
+ '+' => '11222221',
|
|
|
2016
|
+ 'A' => '11221211',
|
|
|
2017
|
+ 'B' => '12121121',
|
|
|
2018
|
+ 'C' => '11121221',
|
|
|
2019
|
+ 'D' => '11122211'
|
|
|
2020
|
+ );
|
|
|
2021
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
2022
|
+ $k = 0;
|
|
|
2023
|
+ $w = 0;
|
|
|
2024
|
+ $seq = '';
|
|
|
2025
|
+ $code = 'A' . strtoupper($code) . 'A';
|
|
|
2026
|
+ $len = strlen($code);
|
|
|
2027
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
2028
|
+ if ( ! isset($chr[$code[$i]])) {
|
|
|
2029
|
+ throw new InvalidCharacterException('Char ' . $code[$i] . ' is unsupported');
|
|
|
2030
|
+ }
|
|
|
2031
|
+ $seq = $chr[$code[$i]];
|
|
|
2032
|
+ for ($j = 0; $j < 8; ++$j) {
|
|
|
2033
|
+ if (($j % 2) == 0) {
|
|
|
2034
|
+ $t = true; // bar
|
|
|
2035
|
+ } else {
|
|
|
2036
|
+ $t = false; // space
|
|
|
2037
|
+ }
|
|
|
2038
|
+ $w = $seq[$i];
|
|
|
2039
|
+ $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
2040
|
+ $bararray['maxw'] += $w;
|
|
|
2041
|
+ ++$k;
|
|
|
2042
|
+ }
|
|
|
2043
|
+ }
|
|
|
2044
|
+
|
|
|
2045
|
+ return $bararray;
|
|
|
2046
|
+ }
|
|
|
2047
|
+
|
|
|
2048
|
+ /**
|
|
|
2049
|
+ * CODE11 barcodes.
|
|
|
2050
|
+ * Used primarily for labeling telecommunications equipment
|
|
|
2051
|
+ *
|
|
|
2052
|
+ * @param $code (string) code to represent.
|
|
|
2053
|
+ * @return array barcode representation.
|
|
|
2054
|
+ * @protected
|
|
|
2055
|
+ */
|
|
|
2056
|
+ protected function barcode_code11($code)
|
|
|
2057
|
+ {
|
|
|
2058
|
+ $chr = array(
|
|
|
2059
|
+ '0' => '111121',
|
|
|
2060
|
+ '1' => '211121',
|
|
|
2061
|
+ '2' => '121121',
|
|
|
2062
|
+ '3' => '221111',
|
|
|
2063
|
+ '4' => '112121',
|
|
|
2064
|
+ '5' => '212111',
|
|
|
2065
|
+ '6' => '122111',
|
|
|
2066
|
+ '7' => '111221',
|
|
|
2067
|
+ '8' => '211211',
|
|
|
2068
|
+ '9' => '211111',
|
|
|
2069
|
+ '-' => '112111',
|
|
|
2070
|
+ 'S' => '112211'
|
|
|
2071
|
+ );
|
|
|
2072
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
2073
|
+ $k = 0;
|
|
|
2074
|
+ $w = 0;
|
|
|
2075
|
+ $seq = '';
|
|
|
2076
|
+ $len = strlen($code);
|
|
|
2077
|
+ // calculate check digit C
|
|
|
2078
|
+ $p = 1;
|
|
|
2079
|
+ $check = 0;
|
|
|
2080
|
+ for ($i = ($len - 1); $i >= 0; --$i) {
|
|
|
2081
|
+ $digit = $code[$i];
|
|
|
2082
|
+ if ($digit == '-') {
|
|
|
2083
|
+ $dval = 10;
|
|
|
2084
|
+ } else {
|
|
|
2085
|
+ $dval = intval($digit);
|
|
|
2086
|
+ }
|
|
|
2087
|
+ $check += ($dval * $p);
|
|
|
2088
|
+ ++$p;
|
|
|
2089
|
+ if ($p > 10) {
|
|
|
2090
|
+ $p = 1;
|
|
|
2091
|
+ }
|
|
|
2092
|
+ }
|
|
|
2093
|
+ $check %= 11;
|
|
|
2094
|
+ if ($check == 10) {
|
|
|
2095
|
+ $check = '-';
|
|
|
2096
|
+ }
|
|
|
2097
|
+ $code .= $check;
|
|
|
2098
|
+ if ($len > 10) {
|
|
|
2099
|
+ // calculate check digit K
|
|
|
2100
|
+ $p = 1;
|
|
|
2101
|
+ $check = 0;
|
|
|
2102
|
+ for ($i = $len; $i >= 0; --$i) {
|
|
|
2103
|
+ $digit = $code[$i];
|
|
|
2104
|
+ if ($digit == '-') {
|
|
|
2105
|
+ $dval = 10;
|
|
|
2106
|
+ } else {
|
|
|
2107
|
+ $dval = intval($digit);
|
|
|
2108
|
+ }
|
|
|
2109
|
+ $check += ($dval * $p);
|
|
|
2110
|
+ ++$p;
|
|
|
2111
|
+ if ($p > 9) {
|
|
|
2112
|
+ $p = 1;
|
|
|
2113
|
+ }
|
|
|
2114
|
+ }
|
|
|
2115
|
+ $check %= 11;
|
|
|
2116
|
+ $code .= $check;
|
|
|
2117
|
+ ++$len;
|
|
|
2118
|
+ }
|
|
|
2119
|
+ $code = 'S' . $code . 'S';
|
|
|
2120
|
+ $len += 3;
|
|
|
2121
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
2122
|
+ if ( ! isset($chr[$code[$i]])) {
|
|
|
2123
|
+ throw new InvalidCharacterException('Char ' . $code[$i] . ' is unsupported');
|
|
|
2124
|
+ }
|
|
|
2125
|
+ $seq = $chr[$code[$i]];
|
|
|
2126
|
+ for ($j = 0; $j < 6; ++$j) {
|
|
|
2127
|
+ if (($j % 2) == 0) {
|
|
|
2128
|
+ $t = true; // bar
|
|
|
2129
|
+ } else {
|
|
|
2130
|
+ $t = false; // space
|
|
|
2131
|
+ }
|
|
|
2132
|
+ $w = $seq[$j];
|
|
|
2133
|
+ $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
|
|
|
2134
|
+ $bararray['maxw'] += $w;
|
|
|
2135
|
+ ++$k;
|
|
|
2136
|
+ }
|
|
|
2137
|
+ }
|
|
|
2138
|
+
|
|
|
2139
|
+ return $bararray;
|
|
|
2140
|
+ }
|
|
|
2141
|
+
|
|
|
2142
|
+ /**
|
|
|
2143
|
+ * Pharmacode
|
|
|
2144
|
+ * Contains digits (0 to 9)
|
|
|
2145
|
+ *
|
|
|
2146
|
+ * @param $code (string) code to represent.
|
|
|
2147
|
+ * @return array barcode representation.
|
|
|
2148
|
+ * @protected
|
|
|
2149
|
+ */
|
|
|
2150
|
+ protected function barcode_pharmacode($code)
|
|
|
2151
|
+ {
|
|
|
2152
|
+ $seq = '';
|
|
|
2153
|
+ $code = intval($code);
|
|
|
2154
|
+ while ($code > 0) {
|
|
|
2155
|
+ if (($code % 2) == 0) {
|
|
|
2156
|
+ $seq .= '11100';
|
|
|
2157
|
+ $code -= 2;
|
|
|
2158
|
+ } else {
|
|
|
2159
|
+ $seq .= '100';
|
|
|
2160
|
+ $code -= 1;
|
|
|
2161
|
+ }
|
|
|
2162
|
+ $code /= 2;
|
|
|
2163
|
+ }
|
|
|
2164
|
+ $seq = substr($seq, 0, -2);
|
|
|
2165
|
+ $seq = strrev($seq);
|
|
|
2166
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
|
|
|
2167
|
+
|
|
|
2168
|
+ return $this->binseq_to_array($seq, $bararray);
|
|
|
2169
|
+ }
|
|
|
2170
|
+
|
|
|
2171
|
+ /**
|
|
|
2172
|
+ * Pharmacode two-track
|
|
|
2173
|
+ * Contains digits (0 to 9)
|
|
|
2174
|
+ *
|
|
|
2175
|
+ * @param $code (string) code to represent.
|
|
|
2176
|
+ * @return array barcode representation.
|
|
|
2177
|
+ * @protected
|
|
|
2178
|
+ */
|
|
|
2179
|
+ protected function barcode_pharmacode2t($code)
|
|
|
2180
|
+ {
|
|
|
2181
|
+ $seq = '';
|
|
|
2182
|
+ $code = intval($code);
|
|
|
2183
|
+ do {
|
|
|
2184
|
+ switch ($code % 3) {
|
|
|
2185
|
+ case 0: {
|
|
|
2186
|
+ $seq .= '3';
|
|
|
2187
|
+ $code = ($code - 3) / 3;
|
|
|
2188
|
+ break;
|
|
|
2189
|
+ }
|
|
|
2190
|
+ case 1: {
|
|
|
2191
|
+ $seq .= '1';
|
|
|
2192
|
+ $code = ($code - 1) / 3;
|
|
|
2193
|
+ break;
|
|
|
2194
|
+ }
|
|
|
2195
|
+ case 2: {
|
|
|
2196
|
+ $seq .= '2';
|
|
|
2197
|
+ $code = ($code - 2) / 3;
|
|
|
2198
|
+ break;
|
|
|
2199
|
+ }
|
|
|
2200
|
+ }
|
|
|
2201
|
+ } while ($code != 0);
|
|
|
2202
|
+ $seq = strrev($seq);
|
|
|
2203
|
+ $k = 0;
|
|
|
2204
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
|
|
|
2205
|
+ $len = strlen($seq);
|
|
|
2206
|
+ for ($i = 0; $i < $len; ++$i) {
|
|
|
2207
|
+ switch ($seq[$i]) {
|
|
|
2208
|
+ case '1': {
|
|
|
2209
|
+ $p = 1;
|
|
|
2210
|
+ $h = 1;
|
|
|
2211
|
+ break;
|
|
|
2212
|
+ }
|
|
|
2213
|
+ case '2': {
|
|
|
2214
|
+ $p = 0;
|
|
|
2215
|
+ $h = 1;
|
|
|
2216
|
+ break;
|
|
|
2217
|
+ }
|
|
|
2218
|
+ case '3': {
|
|
|
2219
|
+ $p = 0;
|
|
|
2220
|
+ $h = 2;
|
|
|
2221
|
+ break;
|
|
|
2222
|
+ }
|
|
|
2223
|
+ }
|
|
|
2224
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
|
|
|
2225
|
+ $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
2226
|
+ $bararray['maxw'] += 2;
|
|
|
2227
|
+ }
|
|
|
2228
|
+ unset($bararray['bcode'][($k - 1)]);
|
|
|
2229
|
+ --$bararray['maxw'];
|
|
|
2230
|
+
|
|
|
2231
|
+ return $bararray;
|
|
|
2232
|
+ }
|
|
|
2233
|
+
|
|
|
2234
|
+ /**
|
|
|
2235
|
+ * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
|
|
|
2236
|
+ * (requires PHP bcmath extension)
|
|
|
2237
|
+ * Intelligent Mail barcode is a 65-bar code for use on mail in the United States.
|
|
|
2238
|
+ * The fields are described as follows:<ul><li>The Barcode Identifier shall be assigned by USPS to encode the
|
|
|
2239
|
+ * presort identification that is currently printed in human readable form on the optional endorsement line (OEL)
|
|
|
2240
|
+ * as well as for future USPS use. This shall be two digits, with the second digit in the range of 0–4. The
|
|
|
2241
|
+ * allowable encoding ranges shall be 00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and
|
|
|
2242
|
+ * 90–94.</li><li>The Service Type Identifier shall be assigned by USPS for any combination of services requested
|
|
|
2243
|
+ * on the mailpiece. The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999.
|
|
|
2244
|
+ * Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s). Each
|
|
|
2245
|
+ * service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier
|
|
|
2246
|
+ * values.</li><li>The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number
|
|
|
2247
|
+ * that identifies a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000-
|
|
|
2248
|
+ * 899999, while the allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.</li><li>The
|
|
|
2249
|
+ * Serial or Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces. The
|
|
|
2250
|
+ * allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999 when
|
|
|
2251
|
+ * used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing the
|
|
|
2252
|
+ * mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point. The length may be
|
|
|
2253
|
+ * 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999, 000000000–999999999,
|
|
|
2254
|
+ * and 00000000000–99999999999.</li></ul>
|
|
|
2255
|
+ *
|
|
|
2256
|
+ * @param $code (string) code to print, separate the ZIP (routing code) from the rest using a minus char '-'
|
|
|
2257
|
+ * (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode)
|
|
|
2258
|
+ * @return array barcode representation.
|
|
|
2259
|
+ * @protected
|
|
|
2260
|
+ */
|
|
|
2261
|
+ protected function barcode_imb($code)
|
|
|
2262
|
+ {
|
|
|
2263
|
+ $asc_chr = array(
|
|
|
2264
|
+ 4,
|
|
|
2265
|
+ 0,
|
|
|
2266
|
+ 2,
|
|
|
2267
|
+ 6,
|
|
|
2268
|
+ 3,
|
|
|
2269
|
+ 5,
|
|
|
2270
|
+ 1,
|
|
|
2271
|
+ 9,
|
|
|
2272
|
+ 8,
|
|
|
2273
|
+ 7,
|
|
|
2274
|
+ 1,
|
|
|
2275
|
+ 2,
|
|
|
2276
|
+ 0,
|
|
|
2277
|
+ 6,
|
|
|
2278
|
+ 4,
|
|
|
2279
|
+ 8,
|
|
|
2280
|
+ 2,
|
|
|
2281
|
+ 9,
|
|
|
2282
|
+ 5,
|
|
|
2283
|
+ 3,
|
|
|
2284
|
+ 0,
|
|
|
2285
|
+ 1,
|
|
|
2286
|
+ 3,
|
|
|
2287
|
+ 7,
|
|
|
2288
|
+ 4,
|
|
|
2289
|
+ 6,
|
|
|
2290
|
+ 8,
|
|
|
2291
|
+ 9,
|
|
|
2292
|
+ 2,
|
|
|
2293
|
+ 0,
|
|
|
2294
|
+ 5,
|
|
|
2295
|
+ 1,
|
|
|
2296
|
+ 9,
|
|
|
2297
|
+ 4,
|
|
|
2298
|
+ 3,
|
|
|
2299
|
+ 8,
|
|
|
2300
|
+ 6,
|
|
|
2301
|
+ 7,
|
|
|
2302
|
+ 1,
|
|
|
2303
|
+ 2,
|
|
|
2304
|
+ 4,
|
|
|
2305
|
+ 3,
|
|
|
2306
|
+ 9,
|
|
|
2307
|
+ 5,
|
|
|
2308
|
+ 7,
|
|
|
2309
|
+ 8,
|
|
|
2310
|
+ 3,
|
|
|
2311
|
+ 0,
|
|
|
2312
|
+ 2,
|
|
|
2313
|
+ 1,
|
|
|
2314
|
+ 4,
|
|
|
2315
|
+ 0,
|
|
|
2316
|
+ 9,
|
|
|
2317
|
+ 1,
|
|
|
2318
|
+ 7,
|
|
|
2319
|
+ 0,
|
|
|
2320
|
+ 2,
|
|
|
2321
|
+ 4,
|
|
|
2322
|
+ 6,
|
|
|
2323
|
+ 3,
|
|
|
2324
|
+ 7,
|
|
|
2325
|
+ 1,
|
|
|
2326
|
+ 9,
|
|
|
2327
|
+ 5,
|
|
|
2328
|
+ 8
|
|
|
2329
|
+ );
|
|
|
2330
|
+ $dsc_chr = array(
|
|
|
2331
|
+ 7,
|
|
|
2332
|
+ 1,
|
|
|
2333
|
+ 9,
|
|
|
2334
|
+ 5,
|
|
|
2335
|
+ 8,
|
|
|
2336
|
+ 0,
|
|
|
2337
|
+ 2,
|
|
|
2338
|
+ 4,
|
|
|
2339
|
+ 6,
|
|
|
2340
|
+ 3,
|
|
|
2341
|
+ 5,
|
|
|
2342
|
+ 8,
|
|
|
2343
|
+ 9,
|
|
|
2344
|
+ 7,
|
|
|
2345
|
+ 3,
|
|
|
2346
|
+ 0,
|
|
|
2347
|
+ 6,
|
|
|
2348
|
+ 1,
|
|
|
2349
|
+ 7,
|
|
|
2350
|
+ 4,
|
|
|
2351
|
+ 6,
|
|
|
2352
|
+ 8,
|
|
|
2353
|
+ 9,
|
|
|
2354
|
+ 2,
|
|
|
2355
|
+ 5,
|
|
|
2356
|
+ 1,
|
|
|
2357
|
+ 7,
|
|
|
2358
|
+ 5,
|
|
|
2359
|
+ 4,
|
|
|
2360
|
+ 3,
|
|
|
2361
|
+ 8,
|
|
|
2362
|
+ 7,
|
|
|
2363
|
+ 6,
|
|
|
2364
|
+ 0,
|
|
|
2365
|
+ 2,
|
|
|
2366
|
+ 5,
|
|
|
2367
|
+ 4,
|
|
|
2368
|
+ 9,
|
|
|
2369
|
+ 3,
|
|
|
2370
|
+ 0,
|
|
|
2371
|
+ 1,
|
|
|
2372
|
+ 6,
|
|
|
2373
|
+ 8,
|
|
|
2374
|
+ 2,
|
|
|
2375
|
+ 0,
|
|
|
2376
|
+ 4,
|
|
|
2377
|
+ 5,
|
|
|
2378
|
+ 9,
|
|
|
2379
|
+ 6,
|
|
|
2380
|
+ 7,
|
|
|
2381
|
+ 5,
|
|
|
2382
|
+ 2,
|
|
|
2383
|
+ 6,
|
|
|
2384
|
+ 3,
|
|
|
2385
|
+ 8,
|
|
|
2386
|
+ 5,
|
|
|
2387
|
+ 1,
|
|
|
2388
|
+ 9,
|
|
|
2389
|
+ 8,
|
|
|
2390
|
+ 7,
|
|
|
2391
|
+ 4,
|
|
|
2392
|
+ 0,
|
|
|
2393
|
+ 2,
|
|
|
2394
|
+ 6,
|
|
|
2395
|
+ 3
|
|
|
2396
|
+ );
|
|
|
2397
|
+ $asc_pos = array(
|
|
|
2398
|
+ 3,
|
|
|
2399
|
+ 0,
|
|
|
2400
|
+ 8,
|
|
|
2401
|
+ 11,
|
|
|
2402
|
+ 1,
|
|
|
2403
|
+ 12,
|
|
|
2404
|
+ 8,
|
|
|
2405
|
+ 11,
|
|
|
2406
|
+ 10,
|
|
|
2407
|
+ 6,
|
|
|
2408
|
+ 4,
|
|
|
2409
|
+ 12,
|
|
|
2410
|
+ 2,
|
|
|
2411
|
+ 7,
|
|
|
2412
|
+ 9,
|
|
|
2413
|
+ 6,
|
|
|
2414
|
+ 7,
|
|
|
2415
|
+ 9,
|
|
|
2416
|
+ 2,
|
|
|
2417
|
+ 8,
|
|
|
2418
|
+ 4,
|
|
|
2419
|
+ 0,
|
|
|
2420
|
+ 12,
|
|
|
2421
|
+ 7,
|
|
|
2422
|
+ 10,
|
|
|
2423
|
+ 9,
|
|
|
2424
|
+ 0,
|
|
|
2425
|
+ 7,
|
|
|
2426
|
+ 10,
|
|
|
2427
|
+ 5,
|
|
|
2428
|
+ 7,
|
|
|
2429
|
+ 9,
|
|
|
2430
|
+ 6,
|
|
|
2431
|
+ 8,
|
|
|
2432
|
+ 2,
|
|
|
2433
|
+ 12,
|
|
|
2434
|
+ 1,
|
|
|
2435
|
+ 4,
|
|
|
2436
|
+ 2,
|
|
|
2437
|
+ 0,
|
|
|
2438
|
+ 1,
|
|
|
2439
|
+ 5,
|
|
|
2440
|
+ 4,
|
|
|
2441
|
+ 6,
|
|
|
2442
|
+ 12,
|
|
|
2443
|
+ 1,
|
|
|
2444
|
+ 0,
|
|
|
2445
|
+ 9,
|
|
|
2446
|
+ 4,
|
|
|
2447
|
+ 7,
|
|
|
2448
|
+ 5,
|
|
|
2449
|
+ 10,
|
|
|
2450
|
+ 2,
|
|
|
2451
|
+ 6,
|
|
|
2452
|
+ 9,
|
|
|
2453
|
+ 11,
|
|
|
2454
|
+ 2,
|
|
|
2455
|
+ 12,
|
|
|
2456
|
+ 6,
|
|
|
2457
|
+ 7,
|
|
|
2458
|
+ 5,
|
|
|
2459
|
+ 11,
|
|
|
2460
|
+ 0,
|
|
|
2461
|
+ 3,
|
|
|
2462
|
+ 2
|
|
|
2463
|
+ );
|
|
|
2464
|
+ $dsc_pos = array(
|
|
|
2465
|
+ 2,
|
|
|
2466
|
+ 10,
|
|
|
2467
|
+ 12,
|
|
|
2468
|
+ 5,
|
|
|
2469
|
+ 9,
|
|
|
2470
|
+ 1,
|
|
|
2471
|
+ 5,
|
|
|
2472
|
+ 4,
|
|
|
2473
|
+ 3,
|
|
|
2474
|
+ 9,
|
|
|
2475
|
+ 11,
|
|
|
2476
|
+ 5,
|
|
|
2477
|
+ 10,
|
|
|
2478
|
+ 1,
|
|
|
2479
|
+ 6,
|
|
|
2480
|
+ 3,
|
|
|
2481
|
+ 4,
|
|
|
2482
|
+ 1,
|
|
|
2483
|
+ 10,
|
|
|
2484
|
+ 0,
|
|
|
2485
|
+ 2,
|
|
|
2486
|
+ 11,
|
|
|
2487
|
+ 8,
|
|
|
2488
|
+ 6,
|
|
|
2489
|
+ 1,
|
|
|
2490
|
+ 12,
|
|
|
2491
|
+ 3,
|
|
|
2492
|
+ 8,
|
|
|
2493
|
+ 6,
|
|
|
2494
|
+ 4,
|
|
|
2495
|
+ 4,
|
|
|
2496
|
+ 11,
|
|
|
2497
|
+ 0,
|
|
|
2498
|
+ 6,
|
|
|
2499
|
+ 1,
|
|
|
2500
|
+ 9,
|
|
|
2501
|
+ 11,
|
|
|
2502
|
+ 5,
|
|
|
2503
|
+ 3,
|
|
|
2504
|
+ 7,
|
|
|
2505
|
+ 3,
|
|
|
2506
|
+ 10,
|
|
|
2507
|
+ 7,
|
|
|
2508
|
+ 11,
|
|
|
2509
|
+ 8,
|
|
|
2510
|
+ 2,
|
|
|
2511
|
+ 10,
|
|
|
2512
|
+ 3,
|
|
|
2513
|
+ 5,
|
|
|
2514
|
+ 8,
|
|
|
2515
|
+ 0,
|
|
|
2516
|
+ 3,
|
|
|
2517
|
+ 12,
|
|
|
2518
|
+ 11,
|
|
|
2519
|
+ 8,
|
|
|
2520
|
+ 4,
|
|
|
2521
|
+ 5,
|
|
|
2522
|
+ 1,
|
|
|
2523
|
+ 3,
|
|
|
2524
|
+ 0,
|
|
|
2525
|
+ 7,
|
|
|
2526
|
+ 12,
|
|
|
2527
|
+ 9,
|
|
|
2528
|
+ 8,
|
|
|
2529
|
+ 10
|
|
|
2530
|
+ );
|
|
|
2531
|
+ $code_arr = explode('-', $code);
|
|
|
2532
|
+ $tracking_number = $code_arr[0];
|
|
|
2533
|
+ if (isset($code_arr[1])) {
|
|
|
2534
|
+ $routing_code = $code_arr[1];
|
|
|
2535
|
+ } else {
|
|
|
2536
|
+ $routing_code = '';
|
|
|
2537
|
+ }
|
|
|
2538
|
+ // Conversion of Routing Code
|
|
|
2539
|
+ switch (strlen($routing_code)) {
|
|
|
2540
|
+ case 0: {
|
|
|
2541
|
+ $binary_code = 0;
|
|
|
2542
|
+ break;
|
|
|
2543
|
+ }
|
|
|
2544
|
+ case 5: {
|
|
|
2545
|
+ $binary_code = bcadd($routing_code, '1');
|
|
|
2546
|
+ break;
|
|
|
2547
|
+ }
|
|
|
2548
|
+ case 9: {
|
|
|
2549
|
+ $binary_code = bcadd($routing_code, '100001');
|
|
|
2550
|
+ break;
|
|
|
2551
|
+ }
|
|
|
2552
|
+ case 11: {
|
|
|
2553
|
+ $binary_code = bcadd($routing_code, '1000100001');
|
|
|
2554
|
+ break;
|
|
|
2555
|
+ }
|
|
|
2556
|
+ default: {
|
|
|
2557
|
+ throw new BarcodeException('Routing code unknown');
|
|
|
2558
|
+ break;
|
|
|
2559
|
+ }
|
|
|
2560
|
+ }
|
|
|
2561
|
+ $binary_code = bcmul($binary_code, 10);
|
|
|
2562
|
+ $binary_code = bcadd($binary_code, $tracking_number[0]);
|
|
|
2563
|
+ $binary_code = bcmul($binary_code, 5);
|
|
|
2564
|
+ $binary_code = bcadd($binary_code, $tracking_number[1]);
|
|
|
2565
|
+ $binary_code .= substr($tracking_number, 2, 18);
|
|
|
2566
|
+ // convert to hexadecimal
|
|
|
2567
|
+ $binary_code = $this->dec_to_hex($binary_code);
|
|
|
2568
|
+ // pad to get 13 bytes
|
|
|
2569
|
+ $binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT);
|
|
|
2570
|
+ // convert string to array of bytes
|
|
|
2571
|
+ $binary_code_arr = chunk_split($binary_code, 2, "\r");
|
|
|
2572
|
+ $binary_code_arr = substr($binary_code_arr, 0, -1);
|
|
|
2573
|
+ $binary_code_arr = explode("\r", $binary_code_arr);
|
|
|
2574
|
+ // calculate frame check sequence
|
|
|
2575
|
+ $fcs = $this->imb_crc11fcs($binary_code_arr);
|
|
|
2576
|
+ // exclude first 2 bits from first byte
|
|
|
2577
|
+ $first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2));
|
|
|
2578
|
+ $binary_code_102bit = $first_byte . substr($binary_code, 2);
|
|
|
2579
|
+ // convert binary data to codewords
|
|
|
2580
|
+ $codewords = array();
|
|
|
2581
|
+ $data = $this->hex_to_dec($binary_code_102bit);
|
|
|
2582
|
+ $codewords[0] = bcmod($data, 636) * 2;
|
|
|
2583
|
+ $data = bcdiv($data, 636);
|
|
|
2584
|
+ for ($i = 1; $i < 9; ++$i) {
|
|
|
2585
|
+ $codewords[$i] = bcmod($data, 1365);
|
|
|
2586
|
+ $data = bcdiv($data, 1365);
|
|
|
2587
|
+ }
|
|
|
2588
|
+ $codewords[9] = $data;
|
|
|
2589
|
+ if (($fcs >> 10) == 1) {
|
|
|
2590
|
+ $codewords[9] += 659;
|
|
|
2591
|
+ }
|
|
|
2592
|
+ // generate lookup tables
|
|
|
2593
|
+ $table2of13 = $this->imb_tables(2, 78);
|
|
|
2594
|
+ $table5of13 = $this->imb_tables(5, 1287);
|
|
|
2595
|
+ // convert codewords to characters
|
|
|
2596
|
+ $characters = array();
|
|
|
2597
|
+ $bitmask = 512;
|
|
|
2598
|
+ foreach ($codewords as $k => $val) {
|
|
|
2599
|
+ if ($val <= 1286) {
|
|
|
2600
|
+ $chrcode = $table5of13[$val];
|
|
|
2601
|
+ } else {
|
|
|
2602
|
+ $chrcode = $table2of13[($val - 1287)];
|
|
|
2603
|
+ }
|
|
|
2604
|
+ if (($fcs & $bitmask) > 0) {
|
|
|
2605
|
+ // bitwise invert
|
|
|
2606
|
+ $chrcode = ((~$chrcode) & 8191);
|
|
|
2607
|
+ }
|
|
|
2608
|
+ $characters[] = $chrcode;
|
|
|
2609
|
+ $bitmask /= 2;
|
|
|
2610
|
+ }
|
|
|
2611
|
+ $characters = array_reverse($characters);
|
|
|
2612
|
+ // build bars
|
|
|
2613
|
+ $k = 0;
|
|
|
2614
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
|
|
|
2615
|
+ for ($i = 0; $i < 65; ++$i) {
|
|
|
2616
|
+ $asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0);
|
|
|
2617
|
+ $dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0);
|
|
|
2618
|
+ if ($asc AND $dsc) {
|
|
|
2619
|
+ // full bar (F)
|
|
|
2620
|
+ $p = 0;
|
|
|
2621
|
+ $h = 3;
|
|
|
2622
|
+ } elseif ($asc) {
|
|
|
2623
|
+ // ascender (A)
|
|
|
2624
|
+ $p = 0;
|
|
|
2625
|
+ $h = 2;
|
|
|
2626
|
+ } elseif ($dsc) {
|
|
|
2627
|
+ // descender (D)
|
|
|
2628
|
+ $p = 1;
|
|
|
2629
|
+ $h = 2;
|
|
|
2630
|
+ } else {
|
|
|
2631
|
+ // tracker (T)
|
|
|
2632
|
+ $p = 1;
|
|
|
2633
|
+ $h = 1;
|
|
|
2634
|
+ }
|
|
|
2635
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
|
|
|
2636
|
+ $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
2637
|
+ $bararray['maxw'] += 2;
|
|
|
2638
|
+ }
|
|
|
2639
|
+ unset($bararray['bcode'][($k - 1)]);
|
|
|
2640
|
+ --$bararray['maxw'];
|
|
|
2641
|
+
|
|
|
2642
|
+ return $bararray;
|
|
|
2643
|
+ }
|
|
|
2644
|
+
|
|
|
2645
|
+ /**
|
|
|
2646
|
+ * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
|
|
|
2647
|
+ *
|
|
|
2648
|
+ * @param $code (string) pre-formatted IMB barcode (65 chars "FADT")
|
|
|
2649
|
+ * @return array barcode representation.
|
|
|
2650
|
+ * @protected
|
|
|
2651
|
+ */
|
|
|
2652
|
+ protected function barcode_imb_pre($code)
|
|
|
2653
|
+ {
|
|
|
2654
|
+ if ( ! preg_match('/^[fadtFADT]{65}$/', $code) == 1) {
|
|
|
2655
|
+ throw new InvalidFormatException();
|
|
|
2656
|
+ }
|
|
|
2657
|
+ $characters = str_split(strtolower($code), 1);
|
|
|
2658
|
+ // build bars
|
|
|
2659
|
+ $k = 0;
|
|
|
2660
|
+ $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
|
|
|
2661
|
+ for ($i = 0; $i < 65; ++$i) {
|
|
|
2662
|
+ switch ($characters[$i]) {
|
|
|
2663
|
+ case 'f': {
|
|
|
2664
|
+ // full bar
|
|
|
2665
|
+ $p = 0;
|
|
|
2666
|
+ $h = 3;
|
|
|
2667
|
+ break;
|
|
|
2668
|
+ }
|
|
|
2669
|
+ case 'a': {
|
|
|
2670
|
+ // ascender
|
|
|
2671
|
+ $p = 0;
|
|
|
2672
|
+ $h = 2;
|
|
|
2673
|
+ break;
|
|
|
2674
|
+ }
|
|
|
2675
|
+ case 'd': {
|
|
|
2676
|
+ // descender
|
|
|
2677
|
+ $p = 1;
|
|
|
2678
|
+ $h = 2;
|
|
|
2679
|
+ break;
|
|
|
2680
|
+ }
|
|
|
2681
|
+ case 't': {
|
|
|
2682
|
+ // tracker (short)
|
|
|
2683
|
+ $p = 1;
|
|
|
2684
|
+ $h = 1;
|
|
|
2685
|
+ break;
|
|
|
2686
|
+ }
|
|
|
2687
|
+ }
|
|
|
2688
|
+ $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
|
|
|
2689
|
+ $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
|
|
|
2690
|
+ $bararray['maxw'] += 2;
|
|
|
2691
|
+ }
|
|
|
2692
|
+ unset($bararray['bcode'][($k - 1)]);
|
|
|
2693
|
+ --$bararray['maxw'];
|
|
|
2694
|
+
|
|
|
2695
|
+ return $bararray;
|
|
|
2696
|
+ }
|
|
|
2697
|
+
|
|
|
2698
|
+ /**
|
|
|
2699
|
+ * Convert large integer number to hexadecimal representation.
|
|
|
2700
|
+ * (requires PHP bcmath extension)
|
|
|
2701
|
+ *
|
|
|
2702
|
+ * @param $number (string) number to convert specified as a string
|
|
|
2703
|
+ * @return string hexadecimal representation
|
|
|
2704
|
+ */
|
|
|
2705
|
+ protected function dec_to_hex($number)
|
|
|
2706
|
+ {
|
|
|
2707
|
+ if ($number == 0) {
|
|
|
2708
|
+ return '00';
|
|
|
2709
|
+ }
|
|
|
2710
|
+
|
|
|
2711
|
+ $hex = [];
|
|
|
2712
|
+
|
|
|
2713
|
+ while ($number > 0) {
|
|
|
2714
|
+ array_push($hex, strtoupper(dechex(bcmod($number, '16'))));
|
|
|
2715
|
+ $number = bcdiv($number, '16', 0);
|
|
|
2716
|
+ }
|
|
|
2717
|
+ $hex = array_reverse($hex);
|
|
|
2718
|
+
|
|
|
2719
|
+ return implode($hex);
|
|
|
2720
|
+ }
|
|
|
2721
|
+
|
|
|
2722
|
+ /**
|
|
|
2723
|
+ * Convert large hexadecimal number to decimal representation (string).
|
|
|
2724
|
+ * (requires PHP bcmath extension)
|
|
|
2725
|
+ *
|
|
|
2726
|
+ * @param $hex (string) hexadecimal number to convert specified as a string
|
|
|
2727
|
+ * @return string hexadecimal representation
|
|
|
2728
|
+ */
|
|
|
2729
|
+ protected function hex_to_dec($hex)
|
|
|
2730
|
+ {
|
|
|
2731
|
+ $dec = 0;
|
|
|
2732
|
+ $bitval = 1;
|
|
|
2733
|
+ $len = strlen($hex);
|
|
|
2734
|
+ for ($pos = ($len - 1); $pos >= 0; --$pos) {
|
|
|
2735
|
+ $dec = bcadd($dec, bcmul(hexdec($hex[$pos]), $bitval));
|
|
|
2736
|
+ $bitval = bcmul($bitval, 16);
|
|
|
2737
|
+ }
|
|
|
2738
|
+
|
|
|
2739
|
+ return $dec;
|
|
|
2740
|
+ }
|
|
|
2741
|
+
|
|
|
2742
|
+ /**
|
|
|
2743
|
+ * Intelligent Mail Barcode calculation of Frame Check Sequence
|
|
|
2744
|
+ *
|
|
|
2745
|
+ * @param $code_arr (string) array of hexadecimal values (13 bytes holding 102 bits right justified).
|
|
|
2746
|
+ * @return int 11 bit Frame Check Sequence as integer (decimal base)
|
|
|
2747
|
+ * @protected
|
|
|
2748
|
+ */
|
|
|
2749
|
+ protected function imb_crc11fcs($code_arr)
|
|
|
2750
|
+ {
|
|
|
2751
|
+ $genpoly = 0x0F35; // generator polynomial
|
|
|
2752
|
+ $fcs = 0x07FF; // Frame Check Sequence
|
|
|
2753
|
+ // do most significant byte skipping the 2 most significant bits
|
|
|
2754
|
+ $data = hexdec($code_arr[0]) << 5;
|
|
|
2755
|
+ for ($bit = 2; $bit < 8; ++$bit) {
|
|
|
2756
|
+ if (($fcs ^ $data) & 0x400) {
|
|
|
2757
|
+ $fcs = ($fcs << 1) ^ $genpoly;
|
|
|
2758
|
+ } else {
|
|
|
2759
|
+ $fcs = ($fcs << 1);
|
|
|
2760
|
+ }
|
|
|
2761
|
+ $fcs &= 0x7FF;
|
|
|
2762
|
+ $data <<= 1;
|
|
|
2763
|
+ }
|
|
|
2764
|
+ // do rest of bytes
|
|
|
2765
|
+ for ($byte = 1; $byte < 13; ++$byte) {
|
|
|
2766
|
+ $data = hexdec($code_arr[$byte]) << 3;
|
|
|
2767
|
+ for ($bit = 0; $bit < 8; ++$bit) {
|
|
|
2768
|
+ if (($fcs ^ $data) & 0x400) {
|
|
|
2769
|
+ $fcs = ($fcs << 1) ^ $genpoly;
|
|
|
2770
|
+ } else {
|
|
|
2771
|
+ $fcs = ($fcs << 1);
|
|
|
2772
|
+ }
|
|
|
2773
|
+ $fcs &= 0x7FF;
|
|
|
2774
|
+ $data <<= 1;
|
|
|
2775
|
+ }
|
|
|
2776
|
+ }
|
|
|
2777
|
+
|
|
|
2778
|
+ return $fcs;
|
|
|
2779
|
+ }
|
|
|
2780
|
+
|
|
|
2781
|
+ /**
|
|
|
2782
|
+ * Reverse unsigned short value
|
|
|
2783
|
+ *
|
|
|
2784
|
+ * @param $num (int) value to reversr
|
|
|
2785
|
+ * @return int reversed value
|
|
|
2786
|
+ * @protected
|
|
|
2787
|
+ */
|
|
|
2788
|
+ protected function imb_reverse_us($num)
|
|
|
2789
|
+ {
|
|
|
2790
|
+ $rev = 0;
|
|
|
2791
|
+ for ($i = 0; $i < 16; ++$i) {
|
|
|
2792
|
+ $rev <<= 1;
|
|
|
2793
|
+ $rev |= ($num & 1);
|
|
|
2794
|
+ $num >>= 1;
|
|
|
2795
|
+ }
|
|
|
2796
|
+
|
|
|
2797
|
+ return $rev;
|
|
|
2798
|
+ }
|
|
|
2799
|
+
|
|
|
2800
|
+ /**
|
|
|
2801
|
+ * generate Nof13 tables used for Intelligent Mail Barcode
|
|
|
2802
|
+ *
|
|
|
2803
|
+ * @param $n (int) is the type of table: 2 for 2of13 table, 5 for 5of13table
|
|
|
2804
|
+ * @param $size (int) size of table (78 for n=2 and 1287 for n=5)
|
|
|
2805
|
+ * @return array requested table
|
|
|
2806
|
+ * @protected
|
|
|
2807
|
+ */
|
|
|
2808
|
+ protected function imb_tables($n, $size)
|
|
|
2809
|
+ {
|
|
|
2810
|
+ $table = array();
|
|
|
2811
|
+ $lli = 0; // LUT lower index
|
|
|
2812
|
+ $lui = $size - 1; // LUT upper index
|
|
|
2813
|
+ for ($count = 0; $count < 8192; ++$count) {
|
|
|
2814
|
+ $bit_count = 0;
|
|
|
2815
|
+ for ($bit_index = 0; $bit_index < 13; ++$bit_index) {
|
|
|
2816
|
+ $bit_count += intval(($count & (1 << $bit_index)) != 0);
|
|
|
2817
|
+ }
|
|
|
2818
|
+ // if we don't have the right number of bits on, go on to the next value
|
|
|
2819
|
+ if ($bit_count == $n) {
|
|
|
2820
|
+ $reverse = ($this->imb_reverse_us($count) >> 3);
|
|
|
2821
|
+ // if the reverse is less than count, we have already visited this pair before
|
|
|
2822
|
+ if ($reverse >= $count) {
|
|
|
2823
|
+ // If count is symmetric, place it at the first free slot from the end of the list.
|
|
|
2824
|
+ // Otherwise, place it at the first free slot from the beginning of the list AND place $reverse ath the next free slot from the beginning of the list
|
|
|
2825
|
+ if ($reverse == $count) {
|
|
|
2826
|
+ $table[$lui] = $count;
|
|
|
2827
|
+ --$lui;
|
|
|
2828
|
+ } else {
|
|
|
2829
|
+ $table[$lli] = $count;
|
|
|
2830
|
+ ++$lli;
|
|
|
2831
|
+ $table[$lli] = $reverse;
|
|
|
2832
|
+ ++$lli;
|
|
|
2833
|
+ }
|
|
|
2834
|
+ }
|
|
|
2835
|
+ }
|
|
|
2836
|
+ }
|
|
|
2837
|
+
|
|
|
2838
|
+ return $table;
|
|
|
2839
|
+ }
|
|
|
2840
|
+
|
|
|
2841
|
+ protected function convertBarcodeArrayToNewStyle($oldBarcodeArray)
|
|
|
2842
|
+ {
|
|
|
2843
|
+ $newBarcodeArray = [];
|
|
|
2844
|
+ $newBarcodeArray['code'] = $oldBarcodeArray['code'];
|
|
|
2845
|
+ $newBarcodeArray['maxWidth'] = $oldBarcodeArray['maxw'];
|
|
|
2846
|
+ $newBarcodeArray['maxHeight'] = $oldBarcodeArray['maxh'];
|
|
|
2847
|
+ $newBarcodeArray['bars'] = [];
|
|
|
2848
|
+ foreach ($oldBarcodeArray['bcode'] as $oldbar) {
|
|
|
2849
|
+ $newBar = [];
|
|
|
2850
|
+ $newBar['width'] = $oldbar['w'];
|
|
|
2851
|
+ $newBar['height'] = $oldbar['h'];
|
|
|
2852
|
+ $newBar['positionVertical'] = $oldbar['p'];
|
|
|
2853
|
+ $newBar['drawBar'] = $oldbar['t'];
|
|
|
2854
|
+ $newBar['drawSpacing'] = ! $oldbar['t'];
|
|
|
2855
|
+
|
|
|
2856
|
+ $newBarcodeArray['bars'][] = $newBar;
|
|
|
2857
|
+ }
|
|
|
2858
|
+
|
|
|
2859
|
+ return $newBarcodeArray;
|
|
|
2860
|
+ }
|
|
|
2861
|
+} |