dbXapp 2.0
RAD, CMS, Module und Runtime-IDE fuer dbXapp
Loading...
Searching...
No Matches
dbxBarcode.class.php
Go to the documentation of this file.
1<?php
2
3/****************************************************************************\
4
5barcode.php - Generate barcodes from a single PHP file. MIT license.
6
7Copyright (c) 2016-2018 Kreative Software.
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27
28
29if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
30 if (isset($_POST['s']) && isset($_POST['d'])) {
31 $generator = new barcode_generator();
32 $format = (isset($_POST['f']) ? $_POST['f'] : 'png');
33 $generator->output_image($format, $_POST['s'], $_POST['d'], $_POST);
34 exit(0);
35 }
36 if (isset($_GET['s']) && isset($_GET['d'])) {
37 $generator = new barcode_generator();
38 $format = (isset($_GET['f']) ? $_GET['f'] : 'png');
39 $generator->output_image($format, $_GET['s'], $_GET['d'], $_GET);
40 exit(0);
41 }
42}
43\****************************************************************************/
45
46 public function get_image_html($format, $symbology, $data, $options): string {
47 ob_start();
48
49 switch (strtolower(preg_replace('/[^A-Za-z0-9]/', '', $format))) {
50 case 'png':
51 $image = $this->render_image($symbology, $data, $options);
52 imagepng($image);
53 imagedestroy($image);
54 $mime = 'image/png';
55 break;
56 case 'gif':
57 $image = $this->render_image($symbology, $data, $options);
58 imagegif($image);
59 imagedestroy($image);
60 $mime = 'image/gif';
61 break;
62 case 'jpg': case 'jpe': case 'jpeg':
63 $image = $this->render_image($symbology, $data, $options);
64 imagejpeg($image);
65 imagedestroy($image);
66 $mime = 'image/jpeg';
67 break;
68 case 'svg':
69 $svg = $this->render_svg($symbology, $data, $options);
70 return '<img src="data:image/svg+xml;base64,' . base64_encode($svg) . '" />';
71 default:
72 return ''; // Ungültiges Format
73 }
74
75 $data = ob_get_clean();
76 return '<img src="data:' . $mime . ';base64,' . base64_encode($data) . '" />';
77 }
78
79
80 public function output_image($format, $symbology, $data, $options) {
81 switch (strtolower(preg_replace('/[^A-Za-z0-9]/', '', $format))) {
82 case 'png':
83 header('Content-Type: image/png');
84 $image = $this->render_image($symbology, $data, $options);
85 imagepng($image);
86 imagedestroy($image);
87 break;
88 case 'gif':
89 header('Content-Type: image/gif');
90 $image = $this->render_image($symbology, $data, $options);
91 imagegif($image);
92 imagedestroy($image);
93 break;
94 case 'jpg': case 'jpe': case 'jpeg':
95 header('Content-Type: image/jpeg');
96 $image = $this->render_image($symbology, $data, $options);
97 imagejpeg($image);
98 imagedestroy($image);
99 break;
100 case 'svg':
101 header('Content-Type: image/svg+xml');
102 echo $this->render_svg($symbology, $data, $options);
103 break;
104 }
105 }
106
107 public function render_image($symbology, $data, $options) {
108 list($code, $widths, $width, $height, $x, $y, $w, $h) =
109 $this->encode_and_calculate_size($symbology, $data, $options);
110 $image = imagecreatetruecolor($width, $height);
111 imagesavealpha($image, true);
112 $bgcolor = (isset($options['bc']) ? $options['bc'] : 'FFF');
113 $bgcolor = 'FFF';
114 $bgcolor = $this->allocate_color($image, $bgcolor);
115 imagefill($image, 0, 0, $bgcolor);
116 $colors = array(
117 (isset($options['cs']) ? $options['cs'] : ''),
118 (isset($options['cm']) ? $options['cm'] : '000'),
119 (isset($options['c2']) ? $options['c2'] : 'F00'),
120 (isset($options['c3']) ? $options['c3'] : 'FF0'),
121 (isset($options['c4']) ? $options['c4'] : '0F0'),
122 (isset($options['c5']) ? $options['c5'] : '0FF'),
123 (isset($options['c6']) ? $options['c6'] : '00F'),
124 (isset($options['c7']) ? $options['c7'] : 'F0F'),
125 (isset($options['c8']) ? $options['c8'] : 'FFF'),
126 (isset($options['c9']) ? $options['c9'] : '000'),
127 );
128 foreach ($colors as $i => $color) {
129 $colors[$i] = $this->allocate_color($image, $color);
130 }
131 $this->dispatch_render_image(
132 $image, $code, $x, $y, $w, $h, $colors, $widths, $options
133 );
134 return $image;
135 }
136
137 public function render_svg($symbology, $data, $options) {
138 list($code, $widths, $width, $height, $x, $y, $w, $h) =
139 $this->encode_and_calculate_size($symbology, $data, $options);
140 $svg = '<?xml version="1.0"?>';
141 $svg .= '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"';
142 $svg .= ' width="' . $width . '" height="' . $height . '"';
143 $svg .= ' viewBox="0 5 ' . $width . ' ' . $height . '"><g>';
144 $bgcolor = (isset($options['bc']) ? $options['bc'] : 'white');
145 if ($bgcolor) {
146 $svg .= '<rect x="0" y="0"';
147 $svg .= ' width="' . $width . '" height="' . $height . '"';
148 $svg .= ' fill="' . htmlspecialchars($bgcolor) . '"/>';
149 }
150 $colors = array(
151 (isset($options['cs']) ? $options['cs'] : ''),
152 (isset($options['cm']) ? $options['cm'] : 'black'),
153 (isset($options['c2']) ? $options['c2'] : '#FF0000'),
154 (isset($options['c3']) ? $options['c3'] : '#FFFF00'),
155 (isset($options['c4']) ? $options['c4'] : '#00FF00'),
156 (isset($options['c5']) ? $options['c5'] : '#00FFFF'),
157 (isset($options['c6']) ? $options['c6'] : '#0000FF'),
158 (isset($options['c7']) ? $options['c7'] : '#FF00FF'),
159 (isset($options['c8']) ? $options['c8'] : 'white'),
160 (isset($options['c9']) ? $options['c9'] : 'black'),
161 );
162 $svg .= $this->dispatch_render_svg(
163 $code, $x, $y, $w, $h, $colors, $widths, $options
164 );
165 $svg .= '</g></svg>';
166 return $svg;
167 }
168
169 /* - - - - INTERNAL FUNCTIONS - - - - */
170
171 private function encode_and_calculate_size($symbology, $data, $options) {
172 $code = $this->dispatch_encode($symbology, $data, $options);
173 $widths = array(
174 (isset($options['wq']) ? (int)$options['wq'] : 1),
175 (isset($options['wm']) ? (int)$options['wm'] : 1),
176 (isset($options['ww']) ? (int)$options['ww'] : 3),
177 (isset($options['wn']) ? (int)$options['wn'] : 1),
178 (isset($options['w4']) ? (int)$options['w4'] : 1),
179 (isset($options['w5']) ? (int)$options['w5'] : 1),
180 (isset($options['w6']) ? (int)$options['w6'] : 1),
181 (isset($options['w7']) ? (int)$options['w7'] : 1),
182 (isset($options['w8']) ? (int)$options['w8'] : 1),
183 (isset($options['w9']) ? (int)$options['w9'] : 1),
184 );
185 $size = $this->dispatch_calculate_size($code, $widths, $options);
186 $dscale = ($code && isset($code['g']) && $code['g'] == 'm') ? 4 : 1;
187 $scale = (isset($options['sf']) ? (float)$options['sf'] : $dscale);
188 $scalex = (isset($options['sx']) ? (float)$options['sx'] : $scale);
189 $scaley = (isset($options['sy']) ? (float)$options['sy'] : $scale);
190 $dpadding = ($code && isset($code['g']) && $code['g'] == 'm') ? 0 : 10;
191 $padding = (isset($options['p']) ? (int)$options['p'] : $dpadding);
192 $vert = (isset($options['pv']) ? (int)$options['pv'] : $padding);
193 $horiz = (isset($options['ph']) ? (int)$options['ph'] : $padding);
194 $top = (isset($options['pt']) ? (int)$options['pt'] : $vert);
195 $left = (isset($options['pl']) ? (int)$options['pl'] : $horiz);
196 $right = (isset($options['pr']) ? (int)$options['pr'] : $horiz);
197 $bottom = (isset($options['pb']) ? (int)$options['pb'] : $vert);
198 $dwidth = ceil($size[0] * $scalex) + $left + $right;
199 $dheight = ceil($size[1] * $scaley) + $top + $bottom;
200 $iwidth = (isset($options['w']) ? (int)$options['w'] : $dwidth);
201 $iheight = (isset($options['h']) ? (int)$options['h'] : $dheight);
202 $swidth = $iwidth - $left - $right;
203 $sheight = $iheight - $top - $bottom;
204 return array(
205 $code, $widths, $iwidth, $iheight,
206 $left, $top, $swidth, $sheight
207 );
208 }
209
210 private function allocate_color($image, $color) {
211 $color = preg_replace('/[^0-9A-Fa-f]/', '', $color);
212 switch (strlen($color)) {
213 case 1:
214 $v = hexdec($color) * 17;
215 return imagecolorallocate($image, $v, $v, $v);
216 case 2:
217 $v = hexdec($color);
218 return imagecolorallocate($image, $v, $v, $v);
219 case 3:
220 $r = hexdec(substr($color, 0, 1)) * 17;
221 $g = hexdec(substr($color, 1, 1)) * 17;
222 $b = hexdec(substr($color, 2, 1)) * 17;
223 return imagecolorallocate($image, $r, $g, $b);
224 case 4:
225 $a = hexdec(substr($color, 0, 1)) * 17;
226 $r = hexdec(substr($color, 1, 1)) * 17;
227 $g = hexdec(substr($color, 2, 1)) * 17;
228 $b = hexdec(substr($color, 3, 1)) * 17;
229 $a = round((255 - $a) * 127 / 255);
230 return imagecolorallocatealpha($image, $r, $g, $b, $a);
231 case 6:
232 $r = hexdec(substr($color, 0, 2));
233 $g = hexdec(substr($color, 2, 2));
234 $b = hexdec(substr($color, 4, 2));
235 return imagecolorallocate($image, $r, $g, $b);
236 case 8:
237 $a = hexdec(substr($color, 0, 2));
238 $r = hexdec(substr($color, 2, 2));
239 $g = hexdec(substr($color, 4, 2));
240 $b = hexdec(substr($color, 6, 2));
241 $a = round((255 - $a) * 127 / 255);
242 return imagecolorallocatealpha($image, $r, $g, $b, $a);
243 default:
244 return imagecolorallocatealpha($image, 0, 0, 0, 127);
245 }
246 }
247
248 /* - - - - DISPATCH - - - - */
249
250 private function dispatch_encode($symbology, $data, $options) {
251 switch (strtolower(preg_replace('/[^A-Za-z0-9]/', '', $symbology))) {
252 case 'upca' : return $this->upc_a_encode($data);
253 case 'upce' : return $this->upc_e_encode($data);
254 case 'ean13nopad' : return $this->ean_13_encode($data, ' ');
255 case 'ean13pad' : return $this->ean_13_encode($data, '>');
256 case 'ean13' : return $this->ean_13_encode($data, '>');
257 case 'ean8' : return $this->ean_8_encode($data);
258 case 'code39' : return $this->code_39_encode($data);
259 case 'code39ascii': return $this->code_39_ascii_encode($data);
260 case 'code93' : return $this->code_93_encode($data);
261 case 'code93ascii': return $this->code_93_ascii_encode($data);
262 case 'code128' : return $this->code_128_encode($data, 0,false);
263 case 'code128a' : return $this->code_128_encode($data, 1,false);
264 case 'code128b' : return $this->code_128_encode($data, 2,false);
265 case 'code128c' : return $this->code_128_encode($data, 3,false);
266 case 'code128ac' : return $this->code_128_encode($data,-1,false);
267 case 'code128bc' : return $this->code_128_encode($data,-2,false);
268 case 'ean128' : return $this->code_128_encode($data, 0, true);
269 case 'ean128a' : return $this->code_128_encode($data, 1, true);
270 case 'ean128b' : return $this->code_128_encode($data, 2, true);
271 case 'ean128c' : return $this->code_128_encode($data, 3, true);
272 case 'ean128ac' : return $this->code_128_encode($data,-1, true);
273 case 'ean128bc' : return $this->code_128_encode($data,-2, true);
274 case 'codabar' : return $this->codabar_encode($data);
275 case 'itf' : return $this->itf_encode($data);
276 case 'itf14' : return $this->itf_encode($data);
277 case 'qr' : return $this->qr_encode($data, 0);
278 case 'qrl' : return $this->qr_encode($data, 0);
279 case 'qrm' : return $this->qr_encode($data, 1);
280 case 'qrq' : return $this->qr_encode($data, 2);
281 case 'qrh' : return $this->qr_encode($data, 3);
282 case 'dmtx' : return $this->dmtx_encode($data, false, false);
283 case 'dmtxs' : return $this->dmtx_encode($data, false, false);
284 case 'dmtxr' : return $this->dmtx_encode($data, true , false);
285 case 'gs1dmtx' : return $this->dmtx_encode($data, false, true);
286 case 'gs1dmtxs' : return $this->dmtx_encode($data, false, true);
287 case 'gs1dmtxr' : return $this->dmtx_encode($data, true , true);
288 }
289 return null;
290 }
291
292 private function dispatch_calculate_size($code, $widths, $options) {
293 if ($code && isset($code['g']) && $code['g']) {
294 switch ($code['g']) {
295 case 'l':
296 return $this->linear_calculate_size($code, $widths);
297 case 'm':
298 return $this->matrix_calculate_size($code, $widths);
299 }
300 }
301 return array(0, 0);
302 }
303
304 private function dispatch_render_image(
305 $image, $code, $x, $y, $w, $h, $colors, $widths, $options
306 ) {
307 if ($code && isset($code['g']) && $code['g']) {
308 switch ($code['g']) {
309 case 'l':
310 $this->linear_render_image(
311 $image, $code, $x, $y, $w, $h,
312 $colors, $widths, $options
313 );
314 break;
315 case 'm':
316 $this->matrix_render_image(
317 $image, $code, $x, $y, $w, $h,
318 $colors, $widths, $options
319 );
320 break;
321 }
322 }
323 }
324
325 private function dispatch_render_svg(
326 $code, $x, $y, $w, $h, $colors, $widths, $options
327 ) {
328 if ($code && isset($code['g']) && $code['g']) {
329 switch ($code['g']) {
330 case 'l':
331 return $this->linear_render_svg(
332 $code, $x, $y, $w, $h,
333 $colors, $widths, $options
334 );
335 case 'm':
336 return $this->matrix_render_svg(
337 $code, $x, $y, $w, $h,
338 $colors, $widths, $options
339 );
340 }
341 }
342 return '';
343 }
344
345 /* - - - - LINEAR BARCODE RENDERER - - - - */
346
347 private function linear_calculate_size($code, $widths) {
348 $width = 0;
349 foreach ($code['b'] as $block) {
350 foreach ($block['m'] as $module) {
351 $width += $module[1] * $widths[$module[2]];
352 }
353 }
354 return array($width, 80);
355 }
356
357 private function linear_render_image(
358 $image, $code, $x, $y, $w, $h, $colors, $widths, $options
359 ) {
360 $textheight = (isset($options['th']) ? (int)$options['th'] : 10);
361 $textsize = (isset($options['ts']) ? (int)$options['ts'] : 1);
362 $textcolor = (isset($options['tc']) ? $options['tc'] : '000');
363 $textcolor = $this->allocate_color($image, $textcolor);
364 $width = 0;
365 foreach ($code['b'] as $block) {
366 foreach ($block['m'] as $module) {
367 $width += $module[1] * $widths[$module[2]];
368 }
369 }
370 if ($width) {
371 $scale = $w / $width;
372 $scale = (($scale > 1) ? floor($scale) : 1);
373 $x = floor($x + ($w - $width * $scale) / 2);
374 } else {
375 $scale = 1;
376 $x = floor($x + $w / 2);
377 }
378 foreach ($code['b'] as $block) {
379 if (isset($block['l'])) {
380 $label = $block['l'][0];
381 $ly = (isset($block['l'][1]) ? (float)$block['l'][1] : 1);
382 $lx = (isset($block['l'][2]) ? (float)$block['l'][2] : 0.5);
383 $my = round($y + min($h, $h + ($ly - 1) * $textheight));
384 $ly = ($y + $h + $ly * $textheight);
385 $ly = round($ly - imagefontheight($textsize));
386 } else {
387 $label = null;
388 $my = $y + $h;
389 }
390 $mx = $x;
391 foreach ($block['m'] as $module) {
392 $mc = $colors[$module[0]];
393 $mw = $mx + $module[1] * $widths[$module[2]] * $scale;
394 imagefilledrectangle($image, $mx, $y, $mw - 1, $my - 1, $mc);
395 $mx = $mw;
396 }
397 if (!is_null($label)) {
398 $lx = ($x + ($mx - $x) * $lx);
399 $lw = imagefontwidth($textsize) * strlen($label);
400 $lx = round($lx - $lw / 2);
401 imagestring($image, $textsize, $lx, $ly, $label, $textcolor);
402 }
403 $x = $mx;
404 }
405 }
406
407 private function linear_render_svg(
408 $code, $x, $y, $w, $h, $colors, $widths, $options
409 ) {
410 $textheight = (isset($options['th']) ? (int)$options['th'] : 10);
411 $textfont = (isset($options['tf']) ? $options['tf'] : 'monospace');
412 $textsize = (isset($options['ts']) ? (int)$options['ts'] : 10);
413 $textcolor = (isset($options['tc']) ? $options['tc'] : 'black');
414 $width = 0;
415 foreach ($code['b'] as $block) {
416 foreach ($block['m'] as $module) {
417 $width += $module[1] * $widths[$module[2]];
418 }
419 }
420 if ($width) {
421 $scale = $w / $width;
422 if ($scale > 1) {
423 $scale = floor($scale);
424 $x = floor($x + ($w - $width * $scale) / 2);
425 }
426 } else {
427 $scale = 1;
428 $x = floor($x + $w / 2);
429 }
430 $tx = 'translate(' . $x . ' ' . $y . ')';
431 if ($scale != 1) $tx .= ' scale(' . $scale . ' 1)';
432 $svg = '<g transform="' . htmlspecialchars($tx) . '">';
433 $x = 0;
434 foreach ($code['b'] as $block) {
435 if (isset($block['l'])) {
436 $label = $block['l'][0];
437 $ly = (isset($block['l'][1]) ? (float)$block['l'][1] : 1);
438 $lx = (isset($block['l'][2]) ? (float)$block['l'][2] : 0.5);
439 $mh = min($h, $h + ($ly - 1) * $textheight);
440 $ly = $h + $ly * $textheight;
441 } else {
442 $label = null;
443 $mh = $h;
444 }
445 $svg .= '<g>';
446 $mx = $x;
447 foreach ($block['m'] as $module) {
448 $mc = htmlspecialchars($colors[$module[0]]);
449 $mw = $module[1] * $widths[$module[2]];
450 if ($mc) {
451 $svg .= '<rect';
452 $svg .= ' x="' . $mx . '" y="0"';
453 $svg .= ' width="' . $mw . '"';
454 $svg .= ' height="' . $mh . '"';
455 $svg .= ' fill="' . $mc . '"/>';
456 }
457 $mx += $mw;
458 }
459 if (!is_null($label)) {
460 $lx = ($x + ($mx - $x) * $lx);
461 $svg .= '<text';
462 $svg .= ' x="' . $lx . '" y="' . $ly . '"';
463 $svg .= ' text-anchor="middle"';
464 $svg .= ' font-family="'.htmlspecialchars($textfont).'"';
465 $svg .= ' font-size="'.htmlspecialchars($textsize).'"';
466 $svg .= ' fill="'.htmlspecialchars($textcolor).'">';
467 $svg .= htmlspecialchars($label);
468 $svg .= '</text>';
469 }
470 $svg .= '</g>';
471 $x = $mx;
472 }
473 return $svg . '</g>';
474 }
475
476 /* - - - - MATRIX BARCODE RENDERER - - - - */
477
478 private function matrix_calculate_size($code, $widths) {
479 $width = (
480 $code['q'][3] * $widths[0] +
481 $code['s'][0] * $widths[1] +
482 $code['q'][1] * $widths[0]
483 );
484 $height = (
485 $code['q'][0] * $widths[0] +
486 $code['s'][1] * $widths[1] +
487 $code['q'][2] * $widths[0]
488 );
489 return array($width, $height);
490 }
491
492 private function matrix_render_image(
493 $image, $code, $x, $y, $w, $h, $colors, $widths, $options
494 ) {
495 $shape = (isset($options['ms']) ? strtolower($options['ms']) : '');
496 $density = (isset($options['md']) ? (float)$options['md'] : 1);
497 list($width, $height) = $this->matrix_calculate_size($code, $widths);
498 if ($width && $height) {
499 $scale = min($w / $width, $h / $height);
500 $scale = (($scale > 1) ? floor($scale) : 1);
501 $x = floor($x + ($w - $width * $scale) / 2);
502 $y = floor($y + ($h - $height * $scale) / 2);
503 } else {
504 $scale = 1;
505 $x = floor($x + $w / 2);
506 $y = floor($y + $h / 2);
507 }
508 $x += $code['q'][3] * $widths[0] * $scale;
509 $y += $code['q'][0] * $widths[0] * $scale;
510 $wh = $widths[1] * $scale;
511 foreach ($code['b'] as $by => $row) {
512 $y1 = $y + $by * $wh;
513 foreach ($row as $bx => $color) {
514 $x1 = $x + $bx * $wh;
515 $mc = $colors[$color];
516 $this->matrix_dot_image(
517 $image, $x1, $y1, $wh, $wh, $mc, $shape, $density
518 );
519 }
520 }
521 }
522
523 private function matrix_render_svg(
524 $code, $x, $y, $w, $h, $colors, $widths, $options
525 ) {
526 $shape = (isset($options['ms']) ? strtolower($options['ms']) : '');
527 $density = (isset($options['md']) ? (float)$options['md'] : 1);
528 list($width, $height) = $this->matrix_calculate_size($code, $widths);
529 if ($width && $height) {
530 $scale = min($w / $width, $h / $height);
531 if ($scale > 1) $scale = floor($scale);
532 $x = floor($x + ($w - $width * $scale) / 2);
533 $y = floor($y + ($h - $height * $scale) / 2);
534 } else {
535 $scale = 1;
536 $x = floor($x + $w / 2);
537 $y = floor($y + $h / 2);
538 }
539 $tx = 'translate(' . $x . ' ' . $y . ')';
540 if ($scale != 1) $tx .= ' scale(' . $scale . ' ' . $scale . ')';
541 $svg = '<g transform="' . htmlspecialchars($tx) . '">';
542 $x = $code['q'][3] * $widths[0];
543 $y = $code['q'][0] * $widths[0];
544 $wh = $widths[1];
545 foreach ($code['b'] as $by => $row) {
546 $y1 = $y + $by * $wh;
547 foreach ($row as $bx => $color) {
548 $x1 = $x + $bx * $wh;
549 $mc = $colors[$color];
550 if ($mc) {
551 $svg .= $this->matrix_dot_svg(
552 $x1, $y1, $wh, $wh, $mc, $shape, $density
553 );
554 }
555 }
556 }
557 return $svg . '</g>';
558 }
559
560 private function matrix_dot_image($image, $x, $y, $w, $h, $mc, $ms, $md) {
561 switch ($ms) {
562 default:
563 $x = floor($x + (1 - $md) * $w / 2);
564 $y = floor($y + (1 - $md) * $h / 2);
565 $w = ceil($w * $md);
566 $h = ceil($h * $md);
567 imagefilledrectangle($image, $x, $y, $x+$w-1, $y+$h-1, $mc);
568 break;
569 case 'r':
570 $cx = floor($x + $w / 2);
571 $cy = floor($y + $h / 2);
572 $dx = ceil($w * $md);
573 $dy = ceil($h * $md);
574 imagefilledellipse($image, $cx, $cy, $dx, $dy, $mc);
575 break;
576 case 'x':
577 $x = floor($x + (1 - $md) * $w / 2);
578 $y = floor($y + (1 - $md) * $h / 2);
579 $w = ceil($w * $md);
580 $h = ceil($h * $md);
581 imageline($image, $x, $y, $x+$w-1, $y+$h-1, $mc);
582 imageline($image, $x, $y+$h-1, $x+$w-1, $y, $mc);
583 break;
584 }
585 }
586
587 private function matrix_dot_svg($x, $y, $w, $h, $mc, $ms, $md) {
588 switch ($ms) {
589 default:
590 $x += (1 - $md) * $w / 2;
591 $y += (1 - $md) * $h / 2;
592 $w *= $md;
593 $h *= $md;
594 $svg = '<rect x="' . $x . '" y="' . $y . '"';
595 $svg .= ' width="' . $w . '" height="' . $h . '"';
596 $svg .= ' fill="' . $mc . '"/>';
597 return $svg;
598 case 'r':
599 $cx = $x + $w / 2;
600 $cy = $y + $h / 2;
601 $rx = $w * $md / 2;
602 $ry = $h * $md / 2;
603 $svg = '<ellipse cx="' . $cx . '" cy="' . $cy . '"';
604 $svg .= ' rx="' . $rx . '" ry="' . $ry . '"';
605 $svg .= ' fill="' . $mc . '"/>';
606 return $svg;
607 case 'x':
608 $x1 = $x + (1 - $md) * $w / 2;
609 $y1 = $y + (1 - $md) * $h / 2;
610 $x2 = $x + $w - (1 - $md) * $w / 2;
611 $y2 = $y + $h - (1 - $md) * $h / 2;
612 $svg = '<line x1="' . $x1 . '" y1="' . $y1 . '"';
613 $svg .= ' x2="' . $x2 . '" y2="' . $y2 . '"';
614 $svg .= ' stroke="' . $mc . '"';
615 $svg .= ' stroke-width="' . ($md / 5) . '"/>';
616 $svg .= '<line x1="' . $x1 . '" y1="' . $y2 . '"';
617 $svg .= ' x2="' . $x2 . '" y2="' . $y1 . '"';
618 $svg .= ' stroke="' . $mc . '"';
619 $svg .= ' stroke-width="' . ($md / 5) . '"/>';
620 return '<g>' . $svg . '</g>';
621 }
622 }
623
624 /* - - - - UPC FAMILY ENCODER - - - - */
625
626 private function upc_a_encode($data) {
627 $data = $this->upc_a_normalize($data);
628 $blocks = array();
629 /* Quiet zone, start, first digit. */
630 $digit = substr($data, 0, 1);
631 $blocks[] = array(
632 'm' => array(array(0, 9, 0)),
633 'l' => array($digit, 0, 1/3)
634 );
635 $blocks[] = array(
636 'm' => array(
637 array(1, 1, 1),
638 array(0, 1, 1),
639 array(1, 1, 1),
640 )
641 );
642 $blocks[] = array(
643 'm' => array(
644 array(0, $this->upc_alphabet[$digit][0], 1),
645 array(1, $this->upc_alphabet[$digit][1], 1),
646 array(0, $this->upc_alphabet[$digit][2], 1),
647 array(1, $this->upc_alphabet[$digit][3], 1),
648 )
649 );
650 /* Left zone. */
651 for ($i = 1; $i < 6; $i++) {
652 $digit = substr($data, $i, 1);
653 $blocks[] = array(
654 'm' => array(
655 array(0, $this->upc_alphabet[$digit][0], 1),
656 array(1, $this->upc_alphabet[$digit][1], 1),
657 array(0, $this->upc_alphabet[$digit][2], 1),
658 array(1, $this->upc_alphabet[$digit][3], 1),
659 ),
660 'l' => array($digit, 0.5, (6 - $i) / 6)
661 );
662 }
663 /* Middle. */
664 $blocks[] = array(
665 'm' => array(
666 array(0, 1, 1),
667 array(1, 1, 1),
668 array(0, 1, 1),
669 array(1, 1, 1),
670 array(0, 1, 1),
671 )
672 );
673 /* Right zone. */
674 for ($i = 6; $i < 11; $i++) {
675 $digit = substr($data, $i, 1);
676 $blocks[] = array(
677 'm' => array(
678 array(1, $this->upc_alphabet[$digit][0], 1),
679 array(0, $this->upc_alphabet[$digit][1], 1),
680 array(1, $this->upc_alphabet[$digit][2], 1),
681 array(0, $this->upc_alphabet[$digit][3], 1),
682 ),
683 'l' => array($digit, 0.5, (11 - $i) / 6)
684 );
685 }
686 /* Last digit, end, quiet zone. */
687 $digit = substr($data, 11, 1);
688 $blocks[] = array(
689 'm' => array(
690 array(1, $this->upc_alphabet[$digit][0], 1),
691 array(0, $this->upc_alphabet[$digit][1], 1),
692 array(1, $this->upc_alphabet[$digit][2], 1),
693 array(0, $this->upc_alphabet[$digit][3], 1),
694 )
695 );
696 $blocks[] = array(
697 'm' => array(
698 array(1, 1, 1),
699 array(0, 1, 1),
700 array(1, 1, 1),
701 )
702 );
703 $blocks[] = array(
704 'm' => array(array(0, 9, 0)),
705 'l' => array($digit, 0, 2/3)
706 );
707 /* Return code. */
708 return array('g' => 'l', 'b' => $blocks);
709 }
710
711 private function upc_e_encode($data) {
712 $data = $this->upc_e_normalize($data);
713 $blocks = array();
714 /* Quiet zone, start. */
715 $blocks[] = array(
716 'm' => array(array(0, 9, 0))
717 );
718 $blocks[] = array(
719 'm' => array(
720 array(1, 1, 1),
721 array(0, 1, 1),
722 array(1, 1, 1),
723 )
724 );
725 /* Digits */
726 $system = substr($data, 0, 1) & 1;
727 $check = substr($data, 7, 1);
728 $pbits = $this->upc_parity[$check];
729 for ($i = 1; $i < 7; $i++) {
730 $digit = substr($data, $i, 1);
731 $pbit = $pbits[$i - 1] ^ $system;
732 $blocks[] = array(
733 'm' => array(
734 array(0, $this->upc_alphabet[$digit][$pbit ? 3 : 0], 1),
735 array(1, $this->upc_alphabet[$digit][$pbit ? 2 : 1], 1),
736 array(0, $this->upc_alphabet[$digit][$pbit ? 1 : 2], 1),
737 array(1, $this->upc_alphabet[$digit][$pbit ? 0 : 3], 1),
738 ),
739 'l' => array($digit, 0.5, (7 - $i) / 7)
740 );
741 }
742 /* End, quiet zone. */
743 $blocks[] = array(
744 'm' => array(
745 array(0, 1, 1),
746 array(1, 1, 1),
747 array(0, 1, 1),
748 array(1, 1, 1),
749 array(0, 1, 1),
750 array(1, 1, 1),
751 )
752 );
753 $blocks[] = array(
754 'm' => array(array(0, 9, 0))
755 );
756 /* Return code. */
757 return array('g' => 'l', 'b' => $blocks);
758 }
759
760 private function ean_13_encode($data, $pad) {
761 $data = $this->ean_13_normalize($data);
762 $blocks = array();
763 /* Quiet zone, start, first digit (as parity). */
764 $system = substr($data, 0, 1);
765 $pbits = (
766 (int)$system ?
767 $this->upc_parity[$system] :
768 array(1, 1, 1, 1, 1, 1)
769 );
770 $blocks[] = array(
771 'm' => array(array(0, 9, 0)),
772 'l' => array($system, 0.5, 1/3)
773 );
774 $blocks[] = array(
775 'm' => array(
776 array(1, 1, 1),
777 array(0, 1, 1),
778 array(1, 1, 1),
779 )
780 );
781 /* Left zone. */
782 for ($i = 1; $i < 7; $i++) {
783 $digit = substr($data, $i, 1);
784 $pbit = $pbits[$i - 1];
785 $blocks[] = array(
786 'm' => array(
787 array(0, $this->upc_alphabet[$digit][$pbit ? 0 : 3], 1),
788 array(1, $this->upc_alphabet[$digit][$pbit ? 1 : 2], 1),
789 array(0, $this->upc_alphabet[$digit][$pbit ? 2 : 1], 1),
790 array(1, $this->upc_alphabet[$digit][$pbit ? 3 : 0], 1),
791 ),
792 'l' => array($digit, 0.5, (7 - $i) / 7)
793 );
794 }
795 /* Middle. */
796 $blocks[] = array(
797 'm' => array(
798 array(0, 1, 1),
799 array(1, 1, 1),
800 array(0, 1, 1),
801 array(1, 1, 1),
802 array(0, 1, 1),
803 )
804 );
805 /* Right zone. */
806 for ($i = 7; $i < 13; $i++) {
807 $digit = substr($data, $i, 1);
808 $blocks[] = array(
809 'm' => array(
810 array(1, $this->upc_alphabet[$digit][0], 1),
811 array(0, $this->upc_alphabet[$digit][1], 1),
812 array(1, $this->upc_alphabet[$digit][2], 1),
813 array(0, $this->upc_alphabet[$digit][3], 1),
814 ),
815 'l' => array($digit, 0.5, (13 - $i) / 7)
816 );
817 }
818 /* End, quiet zone. */
819 $blocks[] = array(
820 'm' => array(
821 array(1, 1, 1),
822 array(0, 1, 1),
823 array(1, 1, 1),
824 )
825 );
826 $blocks[] = array(
827 'm' => array(array(0, 9, 0)),
828 'l' => array($pad, 0.5, 2/3)
829 );
830 /* Return code. */
831 return array('g' => 'l', 'b' => $blocks);
832 }
833
834 private function ean_8_encode($data) {
835 $data = $this->ean_8_normalize($data);
836 $blocks = array();
837 /* Quiet zone, start. */
838 $blocks[] = array(
839 'm' => array(array(0, 9, 0)),
840 'l' => array('<', 0.5, 1/3)
841 );
842 $blocks[] = array(
843 'm' => array(
844 array(1, 1, 1),
845 array(0, 1, 1),
846 array(1, 1, 1),
847 )
848 );
849 /* Left zone. */
850 for ($i = 0; $i < 4; $i++) {
851 $digit = substr($data, $i, 1);
852 $blocks[] = array(
853 'm' => array(
854 array(0, $this->upc_alphabet[$digit][0], 1),
855 array(1, $this->upc_alphabet[$digit][1], 1),
856 array(0, $this->upc_alphabet[$digit][2], 1),
857 array(1, $this->upc_alphabet[$digit][3], 1),
858 ),
859 'l' => array($digit, 0.5, (4 - $i) / 5)
860 );
861 }
862 /* Middle. */
863 $blocks[] = array(
864 'm' => array(
865 array(0, 1, 1),
866 array(1, 1, 1),
867 array(0, 1, 1),
868 array(1, 1, 1),
869 array(0, 1, 1),
870 )
871 );
872 /* Right zone. */
873 for ($i = 4; $i < 8; $i++) {
874 $digit = substr($data, $i, 1);
875 $blocks[] = array(
876 'm' => array(
877 array(1, $this->upc_alphabet[$digit][0], 1),
878 array(0, $this->upc_alphabet[$digit][1], 1),
879 array(1, $this->upc_alphabet[$digit][2], 1),
880 array(0, $this->upc_alphabet[$digit][3], 1),
881 ),
882 'l' => array($digit, 0.5, (8 - $i) / 5)
883 );
884 }
885 /* End, quiet zone. */
886 $blocks[] = array(
887 'm' => array(
888 array(1, 1, 1),
889 array(0, 1, 1),
890 array(1, 1, 1),
891 )
892 );
893 $blocks[] = array(
894 'm' => array(array(0, 9, 0)),
895 'l' => array('>', 0.5, 2/3)
896 );
897 /* Return code. */
898 return array('g' => 'l', 'b' => $blocks);
899 }
900
901 private function upc_a_normalize($data) {
902 $data = preg_replace('/[^0-9*]/', '', $data);
903 /* Set length to 12 digits. */
904 if (strlen($data) < 5) {
905 $data = str_repeat('0', 12);
906 } else if (strlen($data) < 12) {
907 $system = substr($data, 0, 1);
908 $edata = substr($data, 1, -2);
909 $epattern = (int)substr($data, -2, 1);
910 $check = substr($data, -1);
911 if ($epattern < 3) {
912 $left = $system . substr($edata, 0, 2) . $epattern;
913 $right = substr($edata, 2) . $check;
914 } else if ($epattern < strlen($edata)) {
915 $left = $system . substr($edata, 0, $epattern);
916 $right = substr($edata, $epattern) . $check;
917 } else {
918 $left = $system . $edata;
919 $right = $epattern . $check;
920 }
921 $center = str_repeat('0', 12 - strlen($left . $right));
922 $data = $left . $center . $right;
923 } else if (strlen($data) > 12) {
924 $left = substr($data, 0, 6);
925 $right = substr($data, -6);
926 $data = $left . $right;
927 }
928 /* Replace * with missing or check digit. */
929 while (($o = strrpos($data, '*')) !== false) {
930 $checksum = 0;
931 for ($i = 0; $i < 12; $i++) {
932 $digit = substr($data, $i, 1);
933 $checksum += (($i % 2) ? 1 : 3) * $digit;
934 }
935 $checksum *= (($o % 2) ? 9 : 3);
936 $left = substr($data, 0, $o);
937 $center = substr($checksum, -1);
938 $right = substr($data, $o + 1);
939 $data = $left . $center . $right;
940 }
941 return $data;
942 }
943
944 private function upc_e_normalize($data) {
945 $data = preg_replace('/[^0-9*]/', '', $data);
946 /* If exactly 8 digits, use verbatim even if check digit is wrong. */
947 if (preg_match(
948 '/^([01])([0-9][0-9][0-9][0-9][0-9][0-9])([0-9])$/',
949 $data, $m
950 )) {
951 return $data;
952 }
953 /* If unknown check digit, use verbatim but calculate check digit. */
954 if (preg_match(
955 '/^([01])([0-9][0-9][0-9][0-9][0-9][0-9])([*])$/',
956 $data, $m
957 )) {
958 $data = $this->upc_a_normalize($data);
959 return $m[1] . $m[2] . substr($data, -1);
960 }
961 /* Otherwise normalize to UPC-A and convert back. */
962 $data = $this->upc_a_normalize($data);
963 if (preg_match(
964 '/^([01])([0-9][0-9])([0-2])0000([0-9][0-9][0-9])([0-9])$/',
965 $data, $m
966 )) {
967 return $m[1] . $m[2] . $m[4] . $m[3] . $m[5];
968 }
969 if (preg_match(
970 '/^([01])([0-9][0-9][0-9])00000([0-9][0-9])([0-9])$/',
971 $data, $m
972 )) {
973 return $m[1] . $m[2] . $m[3] . '3' . $m[4];
974 }
975 if (preg_match(
976 '/^([01])([0-9][0-9][0-9][0-9])00000([0-9])([0-9])$/',
977 $data, $m
978 )) {
979 return $m[1] . $m[2] . $m[3] . '4' . $m[4];
980 }
981 if (preg_match(
982 '/^([01])([0-9][0-9][0-9][0-9][0-9])0000([5-9])([0-9])$/',
983 $data, $m
984 )) {
985 return $m[1] . $m[2] . $m[3] . $m[4];
986 }
987 return str_repeat('0', 8);
988 }
989
990 private function ean_13_normalize($data) {
991 $data = preg_replace('/[^0-9*]/', '', $data);
992 /* Set length to 13 digits. */
993 if (strlen($data) < 13) {
994 return '0' . $this->upc_a_normalize($data);
995 } else if (strlen($data) > 13) {
996 $left = substr($data, 0, 7);
997 $right = substr($data, -6);
998 $data = $left . $right;
999 }
1000 /* Replace * with missing or check digit. */
1001 while (($o = strrpos($data, '*')) !== false) {
1002 $checksum = 0;
1003 for ($i = 0; $i < 13; $i++) {
1004 $digit = substr($data, $i, 1);
1005 $checksum += (($i % 2) ? 3 : 1) * $digit;
1006 }
1007 $checksum *= (($o % 2) ? 3 : 9);
1008 $left = substr($data, 0, $o);
1009 $center = substr($checksum, -1);
1010 $right = substr($data, $o + 1);
1011 $data = $left . $center . $right;
1012 }
1013 return $data;
1014 }
1015
1016 private function ean_8_normalize($data) {
1017 $data = preg_replace('/[^0-9*]/', '', $data);
1018 /* Set length to 8 digits. */
1019 if (strlen($data) < 8) {
1020 $midpoint = floor(strlen($data) / 2);
1021 $left = substr($data, 0, $midpoint);
1022 $center = str_repeat('0', 8 - strlen($data));
1023 $right = substr($data, $midpoint);
1024 $data = $left . $center . $right;
1025 } else if (strlen($data) > 8) {
1026 $left = substr($data, 0, 4);
1027 $right = substr($data, -4);
1028 $data = $left . $right;
1029 }
1030 /* Replace * with missing or check digit. */
1031 while (($o = strrpos($data, '*')) !== false) {
1032 $checksum = 0;
1033 for ($i = 0; $i < 8; $i++) {
1034 $digit = substr($data, $i, 1);
1035 $checksum += (($i % 2) ? 1 : 3) * $digit;
1036 }
1037 $checksum *= (($o % 2) ? 9 : 3);
1038 $left = substr($data, 0, $o);
1039 $center = substr($checksum, -1);
1040 $right = substr($data, $o + 1);
1041 $data = $left . $center . $right;
1042 }
1043 return $data;
1044 }
1045
1046 private $upc_alphabet = array(
1047 '0' => array(3, 2, 1, 1),
1048 '1' => array(2, 2, 2, 1),
1049 '2' => array(2, 1, 2, 2),
1050 '3' => array(1, 4, 1, 1),
1051 '4' => array(1, 1, 3, 2),
1052 '5' => array(1, 2, 3, 1),
1053 '6' => array(1, 1, 1, 4),
1054 '7' => array(1, 3, 1, 2),
1055 '8' => array(1, 2, 1, 3),
1056 '9' => array(3, 1, 1, 2),
1057 );
1058
1059 private $upc_parity = array(
1060 '0' => array(1, 1, 1, 0, 0, 0),
1061 '1' => array(1, 1, 0, 1, 0, 0),
1062 '2' => array(1, 1, 0, 0, 1, 0),
1063 '3' => array(1, 1, 0, 0, 0, 1),
1064 '4' => array(1, 0, 1, 1, 0, 0),
1065 '5' => array(1, 0, 0, 1, 1, 0),
1066 '6' => array(1, 0, 0, 0, 1, 1),
1067 '7' => array(1, 0, 1, 0, 1, 0),
1068 '8' => array(1, 0, 1, 0, 0, 1),
1069 '9' => array(1, 0, 0, 1, 0, 1),
1070 );
1071
1072 /* - - - - CODE 39 FAMILY ENCODER - - - - */
1073
1074 private function code_39_encode($data) {
1075 $data = strtoupper(preg_replace('/[^0-9A-Za-z%$\/+ .-]/', '', $data));
1076 $blocks = array();
1077 /* Start */
1078 $blocks[] = array(
1079 'm' => array(
1080 array(1, 1, 1), array(0, 1, 2), array(1, 1, 1),
1081 array(0, 1, 1), array(1, 1, 2), array(0, 1, 1),
1082 array(1, 1, 2), array(0, 1, 1), array(1, 1, 1),
1083 ),
1084 'l' => array('*')
1085 );
1086 /* Data */
1087 for ($i = 0, $n = strlen($data); $i < $n; $i++) {
1088 $blocks[] = array(
1089 'm' => array(array(0, 1, 3))
1090 );
1091 $char = substr($data, $i, 1);
1092 $block = $this->code_39_alphabet[$char];
1093 $blocks[] = array(
1094 'm' => array(
1095 array(1, 1, $block[0]),
1096 array(0, 1, $block[1]),
1097 array(1, 1, $block[2]),
1098 array(0, 1, $block[3]),
1099 array(1, 1, $block[4]),
1100 array(0, 1, $block[5]),
1101 array(1, 1, $block[6]),
1102 array(0, 1, $block[7]),
1103 array(1, 1, $block[8]),
1104 ),
1105 'l' => array($char)
1106 );
1107 }
1108 $blocks[] = array(
1109 'm' => array(array(0, 1, 3))
1110 );
1111 /* End */
1112 $blocks[] = array(
1113 'm' => array(
1114 array(1, 1, 1), array(0, 1, 2), array(1, 1, 1),
1115 array(0, 1, 1), array(1, 1, 2), array(0, 1, 1),
1116 array(1, 1, 2), array(0, 1, 1), array(1, 1, 1),
1117 ),
1118 'l' => array('*')
1119 );
1120 /* Return */
1121 return array('g' => 'l', 'b' => $blocks);
1122 }
1123
1124 private function code_39_ascii_encode($data) {
1125 $modules = array();
1126 /* Start */
1127 $modules[] = array(1, 1, 1);
1128 $modules[] = array(0, 1, 2);
1129 $modules[] = array(1, 1, 1);
1130 $modules[] = array(0, 1, 1);
1131 $modules[] = array(1, 1, 2);
1132 $modules[] = array(0, 1, 1);
1133 $modules[] = array(1, 1, 2);
1134 $modules[] = array(0, 1, 1);
1135 $modules[] = array(1, 1, 1);
1136 /* Data */
1137 $label = '';
1138 for ($i = 0, $n = strlen($data); $i < $n; $i++) {
1139 $char = substr($data, $i, 1);
1140 $ch = ord($char);
1141 if ($ch < 128) {
1142 if ($ch < 32 || $ch >= 127) {
1143 $label .= ' ';
1144 } else {
1145 $label .= $char;
1146 }
1147 $ch = $this->code_39_asciibet[$ch];
1148 for ($j = 0, $m = strlen($ch); $j < $m; $j++) {
1149 $c = substr($ch, $j, 1);
1150 $b = $this->code_39_alphabet[$c];
1151 $modules[] = array(0, 1, 3);
1152 $modules[] = array(1, 1, $b[0]);
1153 $modules[] = array(0, 1, $b[1]);
1154 $modules[] = array(1, 1, $b[2]);
1155 $modules[] = array(0, 1, $b[3]);
1156 $modules[] = array(1, 1, $b[4]);
1157 $modules[] = array(0, 1, $b[5]);
1158 $modules[] = array(1, 1, $b[6]);
1159 $modules[] = array(0, 1, $b[7]);
1160 $modules[] = array(1, 1, $b[8]);
1161 }
1162 }
1163 }
1164 $modules[] = array(0, 1, 3);
1165 /* End */
1166 $modules[] = array(1, 1, 1);
1167 $modules[] = array(0, 1, 2);
1168 $modules[] = array(1, 1, 1);
1169 $modules[] = array(0, 1, 1);
1170 $modules[] = array(1, 1, 2);
1171 $modules[] = array(0, 1, 1);
1172 $modules[] = array(1, 1, 2);
1173 $modules[] = array(0, 1, 1);
1174 $modules[] = array(1, 1, 1);
1175 /* Return */
1176 $blocks = array(array('m' => $modules, 'l' => array($label)));
1177 return array('g' => 'l', 'b' => $blocks);
1178 }
1179
1180 private function code_93_encode($data) {
1181 $data = strtoupper(preg_replace('/[^0-9A-Za-z%+\/$ .-]/', '', $data));
1182 $modules = array();
1183 /* Start */
1184 $modules[] = array(1, 1, 1);
1185 $modules[] = array(0, 1, 1);
1186 $modules[] = array(1, 1, 1);
1187 $modules[] = array(0, 1, 1);
1188 $modules[] = array(1, 4, 1);
1189 $modules[] = array(0, 1, 1);
1190 /* Data */
1191 $values = array();
1192 for ($i = 0, $n = strlen($data); $i < $n; $i++) {
1193 $char = substr($data, $i, 1);
1194 $block = $this->code_93_alphabet[$char];
1195 $modules[] = array(1, $block[0], 1);
1196 $modules[] = array(0, $block[1], 1);
1197 $modules[] = array(1, $block[2], 1);
1198 $modules[] = array(0, $block[3], 1);
1199 $modules[] = array(1, $block[4], 1);
1200 $modules[] = array(0, $block[5], 1);
1201 $values[] = $block[6];
1202 }
1203 /* Check Digits */
1204 for ($i = 0; $i < 2; $i++) {
1205 $index = count($values);
1206 $weight = 0;
1207 $checksum = 0;
1208 while ($index) {
1209 $index--;
1210 $weight++;
1211 $checksum += $weight * $values[$index];
1212 $checksum %= 47;
1213 $weight %= ($i ? 15 : 20);
1214 }
1215 $values[] = $checksum;
1216 }
1217 $alphabet = array_values($this->code_93_alphabet);
1218 for ($i = count($values) - 2, $n = count($values); $i < $n; $i++) {
1219 $block = $alphabet[$values[$i]];
1220 $modules[] = array(1, $block[0], 1);
1221 $modules[] = array(0, $block[1], 1);
1222 $modules[] = array(1, $block[2], 1);
1223 $modules[] = array(0, $block[3], 1);
1224 $modules[] = array(1, $block[4], 1);
1225 $modules[] = array(0, $block[5], 1);
1226 }
1227 /* End */
1228 $modules[] = array(1, 1, 1);
1229 $modules[] = array(0, 1, 1);
1230 $modules[] = array(1, 1, 1);
1231 $modules[] = array(0, 1, 1);
1232 $modules[] = array(1, 4, 1);
1233 $modules[] = array(0, 1, 1);
1234 $modules[] = array(1, 1, 1);
1235 /* Return */
1236 $blocks = array(array('m' => $modules, 'l' => array($data)));
1237 return array('g' => 'l', 'b' => $blocks);
1238 }
1239
1240 private function code_93_ascii_encode($data) {
1241 $modules = array();
1242 /* Start */
1243 $modules[] = array(1, 1, 1);
1244 $modules[] = array(0, 1, 1);
1245 $modules[] = array(1, 1, 1);
1246 $modules[] = array(0, 1, 1);
1247 $modules[] = array(1, 4, 1);
1248 $modules[] = array(0, 1, 1);
1249 /* Data */
1250 $label = '';
1251 $values = array();
1252 for ($i = 0, $n = strlen($data); $i < $n; $i++) {
1253 $char = substr($data, $i, 1);
1254 $ch = ord($char);
1255 if ($ch < 128) {
1256 if ($ch < 32 || $ch >= 127) {
1257 $label .= ' ';
1258 } else {
1259 $label .= $char;
1260 }
1261 $ch = $this->code_93_asciibet[$ch];
1262 for ($j = 0, $m = strlen($ch); $j < $m; $j++) {
1263 $c = substr($ch, $j, 1);
1264 $b = $this->code_93_alphabet[$c];
1265 $modules[] = array(1, $b[0], 1);
1266 $modules[] = array(0, $b[1], 1);
1267 $modules[] = array(1, $b[2], 1);
1268 $modules[] = array(0, $b[3], 1);
1269 $modules[] = array(1, $b[4], 1);
1270 $modules[] = array(0, $b[5], 1);
1271 $values[] = $b[6];
1272 }
1273 }
1274 }
1275 /* Check Digits */
1276 for ($i = 0; $i < 2; $i++) {
1277 $index = count($values);
1278 $weight = 0;
1279 $checksum = 0;
1280 while ($index) {
1281 $index--;
1282 $weight++;
1283 $checksum += $weight * $values[$index];
1284 $checksum %= 47;
1285 $weight %= ($i ? 15 : 20);
1286 }
1287 $values[] = $checksum;
1288 }
1289 $alphabet = array_values($this->code_93_alphabet);
1290 for ($i = count($values) - 2, $n = count($values); $i < $n; $i++) {
1291 $block = $alphabet[$values[$i]];
1292 $modules[] = array(1, $block[0], 1);
1293 $modules[] = array(0, $block[1], 1);
1294 $modules[] = array(1, $block[2], 1);
1295 $modules[] = array(0, $block[3], 1);
1296 $modules[] = array(1, $block[4], 1);
1297 $modules[] = array(0, $block[5], 1);
1298 }
1299 /* End */
1300 $modules[] = array(1, 1, 1);
1301 $modules[] = array(0, 1, 1);
1302 $modules[] = array(1, 1, 1);
1303 $modules[] = array(0, 1, 1);
1304 $modules[] = array(1, 4, 1);
1305 $modules[] = array(0, 1, 1);
1306 $modules[] = array(1, 1, 1);
1307 /* Return */
1308 $blocks = array(array('m' => $modules, 'l' => array($label)));
1309 return array('g' => 'l', 'b' => $blocks);
1310 }
1311
1312 private $code_39_alphabet = array(
1313 '1' => array(2, 1, 1, 2, 1, 1, 1, 1, 2),
1314 '2' => array(1, 1, 2, 2, 1, 1, 1, 1, 2),
1315 '3' => array(2, 1, 2, 2, 1, 1, 1, 1, 1),
1316 '4' => array(1, 1, 1, 2, 2, 1, 1, 1, 2),
1317 '5' => array(2, 1, 1, 2, 2, 1, 1, 1, 1),
1318 '6' => array(1, 1, 2, 2, 2, 1, 1, 1, 1),
1319 '7' => array(1, 1, 1, 2, 1, 1, 2, 1, 2),
1320 '8' => array(2, 1, 1, 2, 1, 1, 2, 1, 1),
1321 '9' => array(1, 1, 2, 2, 1, 1, 2, 1, 1),
1322 '0' => array(1, 1, 1, 2, 2, 1, 2, 1, 1),
1323 'A' => array(2, 1, 1, 1, 1, 2, 1, 1, 2),
1324 'B' => array(1, 1, 2, 1, 1, 2, 1, 1, 2),
1325 'C' => array(2, 1, 2, 1, 1, 2, 1, 1, 1),
1326 'D' => array(1, 1, 1, 1, 2, 2, 1, 1, 2),
1327 'E' => array(2, 1, 1, 1, 2, 2, 1, 1, 1),
1328 'F' => array(1, 1, 2, 1, 2, 2, 1, 1, 1),
1329 'G' => array(1, 1, 1, 1, 1, 2, 2, 1, 2),
1330 'H' => array(2, 1, 1, 1, 1, 2, 2, 1, 1),
1331 'I' => array(1, 1, 2, 1, 1, 2, 2, 1, 1),
1332 'J' => array(1, 1, 1, 1, 2, 2, 2, 1, 1),
1333 'K' => array(2, 1, 1, 1, 1, 1, 1, 2, 2),
1334 'L' => array(1, 1, 2, 1, 1, 1, 1, 2, 2),
1335 'M' => array(2, 1, 2, 1, 1, 1, 1, 2, 1),
1336 'N' => array(1, 1, 1, 1, 2, 1, 1, 2, 2),
1337 'O' => array(2, 1, 1, 1, 2, 1, 1, 2, 1),
1338 'P' => array(1, 1, 2, 1, 2, 1, 1, 2, 1),
1339 'Q' => array(1, 1, 1, 1, 1, 1, 2, 2, 2),
1340 'R' => array(2, 1, 1, 1, 1, 1, 2, 2, 1),
1341 'S' => array(1, 1, 2, 1, 1, 1, 2, 2, 1),
1342 'T' => array(1, 1, 1, 1, 2, 1, 2, 2, 1),
1343 'U' => array(2, 2, 1, 1, 1, 1, 1, 1, 2),
1344 'V' => array(1, 2, 2, 1, 1, 1, 1, 1, 2),
1345 'W' => array(2, 2, 2, 1, 1, 1, 1, 1, 1),
1346 'X' => array(1, 2, 1, 1, 2, 1, 1, 1, 2),
1347 'Y' => array(2, 2, 1, 1, 2, 1, 1, 1, 1),
1348 'Z' => array(1, 2, 2, 1, 2, 1, 1, 1, 1),
1349 '-' => array(1, 2, 1, 1, 1, 1, 2, 1, 2),
1350 '.' => array(2, 2, 1, 1, 1, 1, 2, 1, 1),
1351 ' ' => array(1, 2, 2, 1, 1, 1, 2, 1, 1),
1352 '*' => array(1, 2, 1, 1, 2, 1, 2, 1, 1),
1353 '+' => array(1, 2, 1, 1, 1, 2, 1, 2, 1),
1354 '/' => array(1, 2, 1, 2, 1, 1, 1, 2, 1),
1355 '$' => array(1, 2, 1, 2, 1, 2, 1, 1, 1),
1356 '%' => array(1, 1, 1, 2, 1, 2, 1, 2, 1),
1357 );
1358
1359 private $code_39_asciibet = array(
1360 '%U', '$A', '$B', '$C', '$D', '$E', '$F', '$G',
1361 '$H', '$I', '$J', '$K', '$L', '$M', '$N', '$O',
1362 '$P', '$Q', '$R', '$S', '$T', '$U', '$V', '$W',
1363 '$X', '$Y', '$Z', '%A', '%B', '%C', '%D', '%E',
1364 ' ' , '/A', '/B', '/C', '/D', '/E', '/F', '/G',
1365 '/H', '/I', '/J', '/K', '/L', '-' , '.' , '/O',
1366 '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
1367 '8' , '9' , '/Z', '%F', '%G', '%H', '%I', '%J',
1368 '%V', 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
1369 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
1370 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
1371 'X' , 'Y' , 'Z' , '%K', '%L', '%M', '%N', '%O',
1372 '%W', '+A', '+B', '+C', '+D', '+E', '+F', '+G',
1373 '+H', '+I', '+J', '+K', '+L', '+M', '+N', '+O',
1374 '+P', '+Q', '+R', '+S', '+T', '+U', '+V', '+W',
1375 '+X', '+Y', '+Z', '%P', '%Q', '%R', '%S', '%T',
1376 );
1377
1378 private $code_93_alphabet = array(
1379 '0' => array(1, 3, 1, 1, 1, 2, 0),
1380 '1' => array(1, 1, 1, 2, 1, 3, 1),
1381 '2' => array(1, 1, 1, 3, 1, 2, 2),
1382 '3' => array(1, 1, 1, 4, 1, 1, 3),
1383 '4' => array(1, 2, 1, 1, 1, 3, 4),
1384 '5' => array(1, 2, 1, 2, 1, 2, 5),
1385 '6' => array(1, 2, 1, 3, 1, 1, 6),
1386 '7' => array(1, 1, 1, 1, 1, 4, 7),
1387 '8' => array(1, 3, 1, 2, 1, 1, 8),
1388 '9' => array(1, 4, 1, 1, 1, 1, 9),
1389 'A' => array(2, 1, 1, 1, 1, 3, 10),
1390 'B' => array(2, 1, 1, 2, 1, 2, 11),
1391 'C' => array(2, 1, 1, 3, 1, 1, 12),
1392 'D' => array(2, 2, 1, 1, 1, 2, 13),
1393 'E' => array(2, 2, 1, 2, 1, 1, 14),
1394 'F' => array(2, 3, 1, 1, 1, 1, 15),
1395 'G' => array(1, 1, 2, 1, 1, 3, 16),
1396 'H' => array(1, 1, 2, 2, 1, 2, 17),
1397 'I' => array(1, 1, 2, 3, 1, 1, 18),
1398 'J' => array(1, 2, 2, 1, 1, 2, 19),
1399 'K' => array(1, 3, 2, 1, 1, 1, 20),
1400 'L' => array(1, 1, 1, 1, 2, 3, 21),
1401 'M' => array(1, 1, 1, 2, 2, 2, 22),
1402 'N' => array(1, 1, 1, 3, 2, 1, 23),
1403 'O' => array(1, 2, 1, 1, 2, 2, 24),
1404 'P' => array(1, 3, 1, 1, 2, 1, 25),
1405 'Q' => array(2, 1, 2, 1, 1, 2, 26),
1406 'R' => array(2, 1, 2, 2, 1, 1, 27),
1407 'S' => array(2, 1, 1, 1, 2, 2, 28),
1408 'T' => array(2, 1, 1, 2, 2, 1, 29),
1409 'U' => array(2, 2, 1, 1, 2, 1, 30),
1410 'V' => array(2, 2, 2, 1, 1, 1, 31),
1411 'W' => array(1, 1, 2, 1, 2, 2, 32),
1412 'X' => array(1, 1, 2, 2, 2, 1, 33),
1413 'Y' => array(1, 2, 2, 1, 2, 1, 34),
1414 'Z' => array(1, 2, 3, 1, 1, 1, 35),
1415 '-' => array(1, 2, 1, 1, 3, 1, 36),
1416 '.' => array(3, 1, 1, 1, 1, 2, 37),
1417 ' ' => array(3, 1, 1, 2, 1, 1, 38),
1418 '$' => array(3, 2, 1, 1, 1, 1, 39),
1419 '/' => array(1, 1, 2, 1, 3, 1, 40),
1420 '+' => array(1, 1, 3, 1, 2, 1, 41),
1421 '%' => array(2, 1, 1, 1, 3, 1, 42),
1422 '#' => array(1, 2, 1, 2, 2, 1, 43), /* ($) */
1423 '&' => array(3, 1, 2, 1, 1, 1, 44), /* (%) */
1424 '|' => array(3, 1, 1, 1, 2, 1, 45), /* (/) */
1425 '=' => array(1, 2, 2, 2, 1, 1, 46), /* (+) */
1426 '*' => array(1, 1, 1, 1, 4, 1, 0),
1427 );
1428
1429 private $code_93_asciibet = array(
1430 '&U', '#A', '#B', '#C', '#D', '#E', '#F', '#G',
1431 '#H', '#I', '#J', '#K', '#L', '#M', '#N', '#O',
1432 '#P', '#Q', '#R', '#S', '#T', '#U', '#V', '#W',
1433 '#X', '#Y', '#Z', '&A', '&B', '&C', '&D', '&E',
1434 ' ' , '|A', '|B', '|C', '$' , '%' , '|F', '|G',
1435 '|H', '|I', '|J', '+' , '|L', '-' , '.' , '/' ,
1436 '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
1437 '8' , '9' , '|Z', '&F', '&G', '&H', '&I', '&J',
1438 '&V', 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
1439 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
1440 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
1441 'X' , 'Y' , 'Z' , '&K', '&L', '&M', '&N', '&O',
1442 '&W', '=A', '=B', '=C', '=D', '=E', '=F', '=G',
1443 '=H', '=I', '=J', '=K', '=L', '=M', '=N', '=O',
1444 '=P', '=Q', '=R', '=S', '=T', '=U', '=V', '=W',
1445 '=X', '=Y', '=Z', '&P', '&Q', '&R', '&S', '&T',
1446 );
1447
1448 /* - - - - CODE 128 ENCODER - - - - */
1449
1450 private function code_128_encode($data, $dstate, $fnc1) {
1451 $data = preg_replace('/[\x80-\xFF]/', '', $data);
1452 $label = preg_replace('/[\x00-\x1F\x7F]/', ' ', $data);
1453 $chars = $this->code_128_normalize($data, $dstate, $fnc1);
1454 $checksum = $chars[0] % 103;
1455 for ($i = 1, $n = count($chars); $i < $n; $i++) {
1456 $checksum += $i * $chars[$i];
1457 $checksum %= 103;
1458 }
1459 $chars[] = $checksum;
1460 $chars[] = 106;
1461 $modules = array();
1462 $modules[] = array(0, 10, 0);
1463 foreach ($chars as $char) {
1464 $block = $this->code_128_alphabet[$char];
1465 foreach ($block as $i => $module) {
1466 $modules[] = array(($i & 1) ^ 1, $module, 1);
1467 }
1468 }
1469 $modules[] = array(0, 10, 0);
1470 $blocks = array(array('m' => $modules, 'l' => array($label)));
1471 return array('g' => 'l', 'b' => $blocks);
1472 }
1473
1474 private function code_128_normalize($data, $dstate, $fnc1) {
1475 $detectcba = '/(^[0-9]{4,}|^[0-9]{2}$)|([\x60-\x7F])|([\x00-\x1F])/';
1476 $detectc = '/(^[0-9]{6,}|^[0-9]{4,}$)/';
1477 $detectba = '/([\x60-\x7F])|([\x00-\x1F])/';
1478 $consumec = '/(^[0-9]{2})/';
1479 $state = (($dstate > 0 && $dstate < 4) ? $dstate : 0);
1480 $abstate = ((abs($dstate) == 2) ? 2 : 1);
1481 $chars = array(102 + ($state ? $state : $abstate));
1482 if ($fnc1) $chars[] = 102;
1483 while (strlen($data)) {
1484 switch ($state) {
1485 case 0:
1486 if (preg_match($detectcba, $data, $m)) {
1487 if ($m[1]) {
1488 $state = 3;
1489 } else if ($m[2]) {
1490 $state = 2;
1491 } else {
1492 $state = 1;
1493 }
1494 } else {
1495 $state = $abstate;
1496 }
1497 $chars = array(102 + $state);
1498 if ($fnc1) $chars[] = 102;
1499 break;
1500 case 1:
1501 if ($dstate <= 0 && preg_match($detectc, $data, $m)) {
1502 if (strlen($m[0]) % 2) {
1503 $data = substr($data, 1);
1504 $chars[] = 16 + substr($m[0], 0, 1);
1505 }
1506 $state = 3;
1507 $chars[] = 99;
1508 } else {
1509 $ch = ord(substr($data, 0, 1));
1510 $data = substr($data, 1);
1511 if ($ch < 32) {
1512 $chars[] = $ch + 64;
1513 } else if ($ch < 96) {
1514 $chars[] = $ch - 32;
1515 } else {
1516 if (preg_match($detectba, $data, $m)) {
1517 if ($m[1]) {
1518 $state = 2;
1519 $chars[] = 100;
1520 } else {
1521 $chars[] = 98;
1522 }
1523 } else {
1524 $chars[] = 98;
1525 }
1526 $chars[] = $ch - 32;
1527 }
1528 }
1529 break;
1530 case 2:
1531 if ($dstate <= 0 && preg_match($detectc, $data, $m)) {
1532 if (strlen($m[0]) % 2) {
1533 $data = substr($data, 1);
1534 $chars[] = 16 + substr($m[0], 0, 1);
1535 }
1536 $state = 3;
1537 $chars[] = 99;
1538 } else {
1539 $ch = ord(substr($data, 0, 1));
1540 $data = substr($data, 1);
1541 if ($ch >= 32) {
1542 $chars[] = $ch - 32;
1543 } else {
1544 if (preg_match($detectba, $data, $m)) {
1545 if ($m[2]) {
1546 $state = 1;
1547 $chars[] = 101;
1548 } else {
1549 $chars[] = 98;
1550 }
1551 } else {
1552 $chars[] = 98;
1553 }
1554 $chars[] = $ch + 64;
1555 }
1556 }
1557 break;
1558 case 3:
1559 if (preg_match($consumec, $data, $m)) {
1560 $data = substr($data, 2);
1561 $chars[] = (int)$m[0];
1562 } else {
1563 if (preg_match($detectba, $data, $m)) {
1564 if ($m[1]) {
1565 $state = 2;
1566 } else {
1567 $state = 1;
1568 }
1569 } else {
1570 $state = $abstate;
1571 }
1572 $chars[] = 102 - $state;
1573 }
1574 break;
1575 }
1576 }
1577 return $chars;
1578 }
1579
1580 private $code_128_alphabet = array(
1581 array(2, 1, 2, 2, 2, 2), array(2, 2, 2, 1, 2, 2),
1582 array(2, 2, 2, 2, 2, 1), array(1, 2, 1, 2, 2, 3),
1583 array(1, 2, 1, 3, 2, 2), array(1, 3, 1, 2, 2, 2),
1584 array(1, 2, 2, 2, 1, 3), array(1, 2, 2, 3, 1, 2),
1585 array(1, 3, 2, 2, 1, 2), array(2, 2, 1, 2, 1, 3),
1586 array(2, 2, 1, 3, 1, 2), array(2, 3, 1, 2, 1, 2),
1587 array(1, 1, 2, 2, 3, 2), array(1, 2, 2, 1, 3, 2),
1588 array(1, 2, 2, 2, 3, 1), array(1, 1, 3, 2, 2, 2),
1589 array(1, 2, 3, 1, 2, 2), array(1, 2, 3, 2, 2, 1),
1590 array(2, 2, 3, 2, 1, 1), array(2, 2, 1, 1, 3, 2),
1591 array(2, 2, 1, 2, 3, 1), array(2, 1, 3, 2, 1, 2),
1592 array(2, 2, 3, 1, 1, 2), array(3, 1, 2, 1, 3, 1),
1593 array(3, 1, 1, 2, 2, 2), array(3, 2, 1, 1, 2, 2),
1594 array(3, 2, 1, 2, 2, 1), array(3, 1, 2, 2, 1, 2),
1595 array(3, 2, 2, 1, 1, 2), array(3, 2, 2, 2, 1, 1),
1596 array(2, 1, 2, 1, 2, 3), array(2, 1, 2, 3, 2, 1),
1597 array(2, 3, 2, 1, 2, 1), array(1, 1, 1, 3, 2, 3),
1598 array(1, 3, 1, 1, 2, 3), array(1, 3, 1, 3, 2, 1),
1599 array(1, 1, 2, 3, 1, 3), array(1, 3, 2, 1, 1, 3),
1600 array(1, 3, 2, 3, 1, 1), array(2, 1, 1, 3, 1, 3),
1601 array(2, 3, 1, 1, 1, 3), array(2, 3, 1, 3, 1, 1),
1602 array(1, 1, 2, 1, 3, 3), array(1, 1, 2, 3, 3, 1),
1603 array(1, 3, 2, 1, 3, 1), array(1, 1, 3, 1, 2, 3),
1604 array(1, 1, 3, 3, 2, 1), array(1, 3, 3, 1, 2, 1),
1605 array(3, 1, 3, 1, 2, 1), array(2, 1, 1, 3, 3, 1),
1606 array(2, 3, 1, 1, 3, 1), array(2, 1, 3, 1, 1, 3),
1607 array(2, 1, 3, 3, 1, 1), array(2, 1, 3, 1, 3, 1),
1608 array(3, 1, 1, 1, 2, 3), array(3, 1, 1, 3, 2, 1),
1609 array(3, 3, 1, 1, 2, 1), array(3, 1, 2, 1, 1, 3),
1610 array(3, 1, 2, 3, 1, 1), array(3, 3, 2, 1, 1, 1),
1611 array(3, 1, 4, 1, 1, 1), array(2, 2, 1, 4, 1, 1),
1612 array(4, 3, 1, 1, 1, 1), array(1, 1, 1, 2, 2, 4),
1613 array(1, 1, 1, 4, 2, 2), array(1, 2, 1, 1, 2, 4),
1614 array(1, 2, 1, 4, 2, 1), array(1, 4, 1, 1, 2, 2),
1615 array(1, 4, 1, 2, 2, 1), array(1, 1, 2, 2, 1, 4),
1616 array(1, 1, 2, 4, 1, 2), array(1, 2, 2, 1, 1, 4),
1617 array(1, 2, 2, 4, 1, 1), array(1, 4, 2, 1, 1, 2),
1618 array(1, 4, 2, 2, 1, 1), array(2, 4, 1, 2, 1, 1),
1619 array(2, 2, 1, 1, 1, 4), array(4, 1, 3, 1, 1, 1),
1620 array(2, 4, 1, 1, 1, 2), array(1, 3, 4, 1, 1, 1),
1621 array(1, 1, 1, 2, 4, 2), array(1, 2, 1, 1, 4, 2),
1622 array(1, 2, 1, 2, 4, 1), array(1, 1, 4, 2, 1, 2),
1623 array(1, 2, 4, 1, 1, 2), array(1, 2, 4, 2, 1, 1),
1624 array(4, 1, 1, 2, 1, 2), array(4, 2, 1, 1, 1, 2),
1625 array(4, 2, 1, 2, 1, 1), array(2, 1, 2, 1, 4, 1),
1626 array(2, 1, 4, 1, 2, 1), array(4, 1, 2, 1, 2, 1),
1627 array(1, 1, 1, 1, 4, 3), array(1, 1, 1, 3, 4, 1),
1628 array(1, 3, 1, 1, 4, 1), array(1, 1, 4, 1, 1, 3),
1629 array(1, 1, 4, 3, 1, 1), array(4, 1, 1, 1, 1, 3),
1630 array(4, 1, 1, 3, 1, 1), array(1, 1, 3, 1, 4, 1),
1631 array(1, 1, 4, 1, 3, 1), array(3, 1, 1, 1, 4, 1),
1632 array(4, 1, 1, 1, 3, 1), array(2, 1, 1, 4, 1, 2),
1633 array(2, 1, 1, 2, 1, 4), array(2, 1, 1, 2, 3, 2),
1634 array(2, 3, 3, 1, 1, 1, 2)
1635 );
1636
1637 /* - - - - CODABAR ENCODER - - - - */
1638
1639 private function codabar_encode($data) {
1640 $data = strtoupper(preg_replace(
1641 '/[^0-9ABCDENTabcdent*.\/:+$-]/', '', $data
1642 ));
1643 $blocks = array();
1644 for ($i = 0, $n = strlen($data); $i < $n; $i++) {
1645 if ($blocks) {
1646 $blocks[] = array(
1647 'm' => array(array(0, 1, 3))
1648 );
1649 }
1650 $char = substr($data, $i, 1);
1651 $block = $this->codabar_alphabet[$char];
1652 $blocks[] = array(
1653 'm' => array(
1654 array(1, 1, $block[0]),
1655 array(0, 1, $block[1]),
1656 array(1, 1, $block[2]),
1657 array(0, 1, $block[3]),
1658 array(1, 1, $block[4]),
1659 array(0, 1, $block[5]),
1660 array(1, 1, $block[6]),
1661 ),
1662 'l' => array($char)
1663 );
1664 }
1665 return array('g' => 'l', 'b' => $blocks);
1666 }
1667
1668 private $codabar_alphabet = array(
1669 '0' => array(1, 1, 1, 1, 1, 2, 2),
1670 '1' => array(1, 1, 1, 1, 2, 2, 1),
1671 '4' => array(1, 1, 2, 1, 1, 2, 1),
1672 '5' => array(2, 1, 1, 1, 1, 2, 1),
1673 '2' => array(1, 1, 1, 2, 1, 1, 2),
1674 '-' => array(1, 1, 1, 2, 2, 1, 1),
1675 '$' => array(1, 1, 2, 2, 1, 1, 1),
1676 '9' => array(2, 1, 1, 2, 1, 1, 1),
1677 '6' => array(1, 2, 1, 1, 1, 1, 2),
1678 '7' => array(1, 2, 1, 1, 2, 1, 1),
1679 '8' => array(1, 2, 2, 1, 1, 1, 1),
1680 '3' => array(2, 2, 1, 1, 1, 1, 1),
1681 'C' => array(1, 1, 1, 2, 1, 2, 2),
1682 'D' => array(1, 1, 1, 2, 2, 2, 1),
1683 'A' => array(1, 1, 2, 2, 1, 2, 1),
1684 'B' => array(1, 2, 1, 2, 1, 1, 2),
1685 '*' => array(1, 1, 1, 2, 1, 2, 2),
1686 'E' => array(1, 1, 1, 2, 2, 2, 1),
1687 'T' => array(1, 1, 2, 2, 1, 2, 1),
1688 'N' => array(1, 2, 1, 2, 1, 1, 2),
1689 '.' => array(2, 1, 2, 1, 2, 1, 1),
1690 '/' => array(2, 1, 2, 1, 1, 1, 2),
1691 ':' => array(2, 1, 1, 1, 2, 1, 2),
1692 '+' => array(1, 1, 2, 1, 2, 1, 2),
1693 );
1694
1695 /* - - - - ITF ENCODER - - - - */
1696
1697 private function itf_encode($data) {
1698 $data = preg_replace('/[^0-9]/', '', $data);
1699 if (strlen($data) % 2) $data = '0' . $data;
1700 $blocks = array();
1701 /* Quiet zone, start. */
1702 $blocks[] = array(
1703 'm' => array(array(0, 10, 0))
1704 );
1705 $blocks[] = array(
1706 'm' => array(
1707 array(1, 1, 1),
1708 array(0, 1, 1),
1709 array(1, 1, 1),
1710 array(0, 1, 1),
1711 )
1712 );
1713 /* Data. */
1714 for ($i = 0, $n = strlen($data); $i < $n; $i += 2) {
1715 $c1 = substr($data, $i, 1);
1716 $c2 = substr($data, $i+1, 1);
1717 $b1 = $this->itf_alphabet[$c1];
1718 $b2 = $this->itf_alphabet[$c2];
1719 $blocks[] = array(
1720 'm' => array(
1721 array(1, 1, $b1[0]),
1722 array(0, 1, $b2[0]),
1723 array(1, 1, $b1[1]),
1724 array(0, 1, $b2[1]),
1725 array(1, 1, $b1[2]),
1726 array(0, 1, $b2[2]),
1727 array(1, 1, $b1[3]),
1728 array(0, 1, $b2[3]),
1729 array(1, 1, $b1[4]),
1730 array(0, 1, $b2[4]),
1731 ),
1732 'l' => array($c1 . $c2)
1733 );
1734 }
1735 /* End, quiet zone. */
1736 $blocks[] = array(
1737 'm' => array(
1738 array(1, 1, 2),
1739 array(0, 1, 1),
1740 array(1, 1, 1),
1741 )
1742 );
1743 $blocks[] = array(
1744 'm' => array(array(0, 10, 0))
1745 );
1746 /* Return code. */
1747 return array('g' => 'l', 'b' => $blocks);
1748 }
1749
1750 private $itf_alphabet = array(
1751 '0' => array(1, 1, 2, 2, 1),
1752 '1' => array(2, 1, 1, 1, 2),
1753 '2' => array(1, 2, 1, 1, 2),
1754 '3' => array(2, 2, 1, 1, 1),
1755 '4' => array(1, 1, 2, 1, 2),
1756 '5' => array(2, 1, 2, 1, 1),
1757 '6' => array(1, 2, 2, 1, 1),
1758 '7' => array(1, 1, 1, 2, 2),
1759 '8' => array(2, 1, 1, 2, 1),
1760 '9' => array(1, 2, 1, 2, 1),
1761 );
1762
1763 /* - - - - QR ENCODER - - - - */
1764
1765 private function qr_encode($data, $ecl) {
1766 list($mode, $vers, $ec, $data) = $this->qr_encode_data($data, $ecl);
1767 $data = $this->qr_encode_ec($data, $ec, $vers);
1768 list($size, $mtx) = $this->qr_create_matrix($vers, $data);
1769 list($mask, $mtx) = $this->qr_apply_best_mask($mtx, $size);
1770 $mtx = $this->qr_finalize_matrix($mtx, $size, $ecl, $mask, $vers);
1771 return array(
1772 'g' => 'm',
1773 'q' => array(4, 4, 4, 4),
1774 's' => array($size, $size),
1775 'b' => $mtx
1776 );
1777 }
1778
1779 private function qr_encode_data($data, $ecl) {
1780 $mode = $this->qr_detect_mode($data);
1781 $version = $this->qr_detect_version($data, $mode, $ecl);
1782 $version_group = (($version < 10) ? 0 : (($version < 27) ? 1 : 2));
1783 $ec_params = $this->qr_ec_params[($version - 1) * 4 + $ecl];
1784 /* Don't cut off mid-character if exceeding capacity. */
1785 $max_chars = $this->qr_capacity[$version - 1][$ecl][$mode];
1786 if ($mode == 3) $max_chars <<= 1;
1787 $data = substr($data, 0, $max_chars);
1788 /* Convert from character level to bit level. */
1789 switch ($mode) {
1790 case 0:
1791 $code = $this->qr_encode_numeric($data, $version_group);
1792 break;
1793 case 1:
1794 $code = $this->qr_encode_alphanumeric($data, $version_group);
1795 break;
1796 case 2:
1797 $code = $this->qr_encode_binary($data, $version_group);
1798 break;
1799 case 3:
1800 $code = $this->qr_encode_kanji($data, $version_group);
1801 break;
1802 }
1803 for ($i = 0; $i < 4; $i++) $code[] = 0;
1804 while (count($code) % 8) $code[] = 0;
1805 /* Convert from bit level to byte level. */
1806 $data = array();
1807 for ($i = 0, $n = count($code); $i < $n; $i += 8) {
1808 $byte = 0;
1809 if ($code[$i + 0]) $byte |= 0x80;
1810 if ($code[$i + 1]) $byte |= 0x40;
1811 if ($code[$i + 2]) $byte |= 0x20;
1812 if ($code[$i + 3]) $byte |= 0x10;
1813 if ($code[$i + 4]) $byte |= 0x08;
1814 if ($code[$i + 5]) $byte |= 0x04;
1815 if ($code[$i + 6]) $byte |= 0x02;
1816 if ($code[$i + 7]) $byte |= 0x01;
1817 $data[] = $byte;
1818 }
1819 for (
1820 $i = count($data), $a = 1, $n = $ec_params[0];
1821 $i < $n; $i++, $a ^= 1
1822 ) {
1823 $data[] = $a ? 236 : 17;
1824 }
1825 /* Return. */
1826 return array($mode, $version, $ec_params, $data);
1827 }
1828
1829 private function qr_detect_mode($data) {
1830 $numeric = '/^[0-9]*$/';
1831 $alphanumeric = '/^[0-9A-Z .\/:$%*+-]*$/';
1832 $kanji = '/^([\x81-\x9F\xE0-\xEA][\x40-\xFC]|[\xEB][\x40-\xBF])*$/';
1833 if (preg_match($numeric, $data)) return 0;
1834 if (preg_match($alphanumeric, $data)) return 1;
1835 if (preg_match($kanji, $data)) return 3;
1836 return 2;
1837 }
1838
1839 private function qr_detect_version($data, $mode, $ecl) {
1840 $length = strlen($data);
1841 if ($mode == 3) $length >>= 1;
1842 for ($v = 0; $v < 40; $v++) {
1843 if ($length <= $this->qr_capacity[$v][$ecl][$mode]) {
1844 return $v + 1;
1845 }
1846 }
1847 return 40;
1848 }
1849
1850 private function qr_encode_numeric($data, $version_group) {
1851 $code = array(0, 0, 0, 1);
1852 $length = strlen($data);
1853 switch ($version_group) {
1854 case 2: /* 27 - 40 */
1855 $code[] = $length & 0x2000;
1856 $code[] = $length & 0x1000;
1857 case 1: /* 10 - 26 */
1858 $code[] = $length & 0x0800;
1859 $code[] = $length & 0x0400;
1860 case 0: /* 1 - 9 */
1861 $code[] = $length & 0x0200;
1862 $code[] = $length & 0x0100;
1863 $code[] = $length & 0x0080;
1864 $code[] = $length & 0x0040;
1865 $code[] = $length & 0x0020;
1866 $code[] = $length & 0x0010;
1867 $code[] = $length & 0x0008;
1868 $code[] = $length & 0x0004;
1869 $code[] = $length & 0x0002;
1870 $code[] = $length & 0x0001;
1871 }
1872 for ($i = 0; $i < $length; $i += 3) {
1873 $group = substr($data, $i, 3);
1874 switch (strlen($group)) {
1875 case 3:
1876 $code[] = $group & 0x200;
1877 $code[] = $group & 0x100;
1878 $code[] = $group & 0x080;
1879 case 2:
1880 $code[] = $group & 0x040;
1881 $code[] = $group & 0x020;
1882 $code[] = $group & 0x010;
1883 case 1:
1884 $code[] = $group & 0x008;
1885 $code[] = $group & 0x004;
1886 $code[] = $group & 0x002;
1887 $code[] = $group & 0x001;
1888 }
1889 }
1890 return $code;
1891 }
1892
1893 private function qr_encode_alphanumeric($data, $version_group) {
1894 $alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:';
1895 $code = array(0, 0, 1, 0);
1896 $length = strlen($data);
1897 switch ($version_group) {
1898 case 2: /* 27 - 40 */
1899 $code[] = $length & 0x1000;
1900 $code[] = $length & 0x0800;
1901 case 1: /* 10 - 26 */
1902 $code[] = $length & 0x0400;
1903 $code[] = $length & 0x0200;
1904 case 0: /* 1 - 9 */
1905 $code[] = $length & 0x0100;
1906 $code[] = $length & 0x0080;
1907 $code[] = $length & 0x0040;
1908 $code[] = $length & 0x0020;
1909 $code[] = $length & 0x0010;
1910 $code[] = $length & 0x0008;
1911 $code[] = $length & 0x0004;
1912 $code[] = $length & 0x0002;
1913 $code[] = $length & 0x0001;
1914 }
1915 for ($i = 0; $i < $length; $i += 2) {
1916 $group = substr($data, $i, 2);
1917 if (strlen($group) > 1) {
1918 $c1 = strpos($alphabet, substr($group, 0, 1));
1919 $c2 = strpos($alphabet, substr($group, 1, 1));
1920 $ch = $c1 * 45 + $c2;
1921 $code[] = $ch & 0x400;
1922 $code[] = $ch & 0x200;
1923 $code[] = $ch & 0x100;
1924 $code[] = $ch & 0x080;
1925 $code[] = $ch & 0x040;
1926 $code[] = $ch & 0x020;
1927 $code[] = $ch & 0x010;
1928 $code[] = $ch & 0x008;
1929 $code[] = $ch & 0x004;
1930 $code[] = $ch & 0x002;
1931 $code[] = $ch & 0x001;
1932 } else {
1933 $ch = strpos($alphabet, $group);
1934 $code[] = $ch & 0x020;
1935 $code[] = $ch & 0x010;
1936 $code[] = $ch & 0x008;
1937 $code[] = $ch & 0x004;
1938 $code[] = $ch & 0x002;
1939 $code[] = $ch & 0x001;
1940 }
1941 }
1942 return $code;
1943 }
1944
1945 private function qr_encode_binary($data, $version_group) {
1946 $code = array(0, 1, 0, 0);
1947 $length = strlen($data);
1948 switch ($version_group) {
1949 case 2: /* 27 - 40 */
1950 case 1: /* 10 - 26 */
1951 $code[] = $length & 0x8000;
1952 $code[] = $length & 0x4000;
1953 $code[] = $length & 0x2000;
1954 $code[] = $length & 0x1000;
1955 $code[] = $length & 0x0800;
1956 $code[] = $length & 0x0400;
1957 $code[] = $length & 0x0200;
1958 $code[] = $length & 0x0100;
1959 case 0: /* 1 - 9 */
1960 $code[] = $length & 0x0080;
1961 $code[] = $length & 0x0040;
1962 $code[] = $length & 0x0020;
1963 $code[] = $length & 0x0010;
1964 $code[] = $length & 0x0008;
1965 $code[] = $length & 0x0004;
1966 $code[] = $length & 0x0002;
1967 $code[] = $length & 0x0001;
1968 }
1969 for ($i = 0; $i < $length; $i++) {
1970 $ch = ord(substr($data, $i, 1));
1971 $code[] = $ch & 0x80;
1972 $code[] = $ch & 0x40;
1973 $code[] = $ch & 0x20;
1974 $code[] = $ch & 0x10;
1975 $code[] = $ch & 0x08;
1976 $code[] = $ch & 0x04;
1977 $code[] = $ch & 0x02;
1978 $code[] = $ch & 0x01;
1979 }
1980 return $code;
1981 }
1982
1983 private function qr_encode_kanji($data, $version_group) {
1984 $code = array(1, 0, 0, 0);
1985 $length = strlen($data);
1986 switch ($version_group) {
1987 case 2: /* 27 - 40 */
1988 $code[] = $length & 0x1000;
1989 $code[] = $length & 0x0800;
1990 case 1: /* 10 - 26 */
1991 $code[] = $length & 0x0400;
1992 $code[] = $length & 0x0200;
1993 case 0: /* 1 - 9 */
1994 $code[] = $length & 0x0100;
1995 $code[] = $length & 0x0080;
1996 $code[] = $length & 0x0040;
1997 $code[] = $length & 0x0020;
1998 $code[] = $length & 0x0010;
1999 $code[] = $length & 0x0008;
2000 $code[] = $length & 0x0004;
2001 $code[] = $length & 0x0002;
2002 }
2003 for ($i = 0; $i < $length; $i += 2) {
2004 $group = substr($data, $i, 2);
2005 $c1 = ord(substr($group, 0, 1));
2006 $c2 = ord(substr($group, 1, 1));
2007 if ($c1 >= 0x81 && $c1 <= 0x9F && $c2 >= 0x40 && $c2 <= 0xFC) {
2008 $ch = ($c1 - 0x81) * 0xC0 + ($c2 - 0x40);
2009 } else if (
2010 ($c1 >= 0xE0 && $c1 <= 0xEA && $c2 >= 0x40 && $c2 <= 0xFC) ||
2011 ($c1 == 0xEB && $c2 >= 0x40 && $c2 <= 0xBF)
2012 ) {
2013 $ch = ($c1 - 0xC1) * 0xC0 + ($c2 - 0x40);
2014 } else {
2015 $ch = 0;
2016 }
2017 $code[] = $ch & 0x1000;
2018 $code[] = $ch & 0x0800;
2019 $code[] = $ch & 0x0400;
2020 $code[] = $ch & 0x0200;
2021 $code[] = $ch & 0x0100;
2022 $code[] = $ch & 0x0080;
2023 $code[] = $ch & 0x0040;
2024 $code[] = $ch & 0x0020;
2025 $code[] = $ch & 0x0010;
2026 $code[] = $ch & 0x0008;
2027 $code[] = $ch & 0x0004;
2028 $code[] = $ch & 0x0002;
2029 $code[] = $ch & 0x0001;
2030 }
2031 return $code;
2032 }
2033
2034 private function qr_encode_ec($data, $ec_params, $version) {
2035 $blocks = $this->qr_ec_split($data, $ec_params);
2036 $ec_blocks = array();
2037 for ($i = 0, $n = count($blocks); $i < $n; $i++) {
2038 $ec_blocks[] = $this->qr_ec_divide($blocks[$i], $ec_params);
2039 }
2040 $data = $this->qr_ec_interleave($blocks);
2041 $ec_data = $this->qr_ec_interleave($ec_blocks);
2042 $code = array();
2043 foreach ($data as $ch) {
2044 $code[] = $ch & 0x80;
2045 $code[] = $ch & 0x40;
2046 $code[] = $ch & 0x20;
2047 $code[] = $ch & 0x10;
2048 $code[] = $ch & 0x08;
2049 $code[] = $ch & 0x04;
2050 $code[] = $ch & 0x02;
2051 $code[] = $ch & 0x01;
2052 }
2053 foreach ($ec_data as $ch) {
2054 $code[] = $ch & 0x80;
2055 $code[] = $ch & 0x40;
2056 $code[] = $ch & 0x20;
2057 $code[] = $ch & 0x10;
2058 $code[] = $ch & 0x08;
2059 $code[] = $ch & 0x04;
2060 $code[] = $ch & 0x02;
2061 $code[] = $ch & 0x01;
2062 }
2063 for ($n = $this->qr_remainder_bits[$version - 1]; $n > 0; $n--) {
2064 $code[] = 0;
2065 }
2066 return $code;
2067 }
2068
2069 private function qr_ec_split($data, $ec_params) {
2070 $blocks = array();
2071 $offset = 0;
2072 for ($i = $ec_params[2], $length = $ec_params[3]; $i > 0; $i--) {
2073 $blocks[] = array_slice($data, $offset, $length);
2074 $offset += $length;
2075 }
2076 for ($i = $ec_params[4], $length = $ec_params[5]; $i > 0; $i--) {
2077 $blocks[] = array_slice($data, $offset, $length);
2078 $offset += $length;
2079 }
2080 return $blocks;
2081 }
2082
2083 private function qr_ec_divide($data, $ec_params) {
2084 $num_data = count($data);
2085 $num_error = $ec_params[1];
2086 $generator = $this->qr_ec_polynomials[$num_error];
2087 $message = $data;
2088 for ($i = 0; $i < $num_error; $i++) {
2089 $message[] = 0;
2090 }
2091 for ($i = 0; $i < $num_data; $i++) {
2092 if ($message[$i]) {
2093 $leadterm = $this->qr_log[$message[$i]];
2094 for ($j = 0; $j <= $num_error; $j++) {
2095 $term = ($generator[$j] + $leadterm) % 255;
2096 $message[$i + $j] ^= $this->qr_exp[$term];
2097 }
2098 }
2099 }
2100 return array_slice($message, $num_data, $num_error);
2101 }
2102
2103 private function qr_ec_interleave($blocks) {
2104 $data = array();
2105 $num_blocks = count($blocks);
2106 for ($offset = 0; true; $offset++) {
2107 $break = true;
2108 for ($i = 0; $i < $num_blocks; $i++) {
2109 if (isset($blocks[$i][$offset])) {
2110 $data[] = $blocks[$i][$offset];
2111 $break = false;
2112 }
2113 }
2114 if ($break) break;
2115 }
2116 return $data;
2117 }
2118
2119 private function qr_create_matrix($version, $data) {
2120 $size = $version * 4 + 17;
2121 $matrix = array();
2122 for ($i = 0; $i < $size; $i++) {
2123 $row = array();
2124 for ($j = 0; $j < $size; $j++) {
2125 $row[] = 0;
2126 }
2127 $matrix[] = $row;
2128 }
2129 /* Finder patterns. */
2130 for ($i = 0; $i < 8; $i++) {
2131 for ($j = 0; $j < 8; $j++) {
2132 $m = (($i == 7 || $j == 7) ? 2 :
2133 (($i == 0 || $j == 0 || $i == 6 || $j == 6) ? 3 :
2134 (($i == 1 || $j == 1 || $i == 5 || $j == 5) ? 2 : 3)));
2135 $matrix[$i][$j] = $m;
2136 $matrix[$size - $i - 1][$j] = $m;
2137 $matrix[$i][$size - $j - 1] = $m;
2138 }
2139 }
2140 /* Alignment patterns. */
2141 if ($version >= 2) {
2142 $alignment = $this->qr_alignment_patterns[$version - 2];
2143 foreach ($alignment as $i) {
2144 foreach ($alignment as $j) {
2145 if (!$matrix[$i][$j]) {
2146 for ($ii = -2; $ii <= 2; $ii++) {
2147 for ($jj = -2; $jj <= 2; $jj++) {
2148 $m = (max(abs($ii), abs($jj)) & 1) ^ 3;
2149 $matrix[$i + $ii][$j + $jj] = $m;
2150 }
2151 }
2152 }
2153 }
2154 }
2155 }
2156 /* Timing patterns. */
2157 for ($i = $size - 9; $i >= 8; $i--) {
2158 $matrix[$i][6] = ($i & 1) ^ 3;
2159 $matrix[6][$i] = ($i & 1) ^ 3;
2160 }
2161 /* Dark module. Such an ominous name for such an innocuous thing. */
2162 $matrix[$size - 8][8] = 3;
2163 /* Format information area. */
2164 for ($i = 0; $i <= 8; $i++) {
2165 if (!$matrix[$i][8]) $matrix[$i][8] = 1;
2166 if (!$matrix[8][$i]) $matrix[8][$i] = 1;
2167 if ($i && !$matrix[$size - $i][8]) $matrix[$size - $i][8] = 1;
2168 if ($i && !$matrix[8][$size - $i]) $matrix[8][$size - $i] = 1;
2169 }
2170 /* Version information area. */
2171 if ($version >= 7) {
2172 for ($i = 9; $i < 12; $i++) {
2173 for ($j = 0; $j < 6; $j++) {
2174 $matrix[$size - $i][$j] = 1;
2175 $matrix[$j][$size - $i] = 1;
2176 }
2177 }
2178 }
2179 /* Data. */
2180 $col = $size - 1;
2181 $row = $size - 1;
2182 $dir = -1;
2183 $offset = 0;
2184 $length = count($data);
2185 while ($col > 0 && $offset < $length) {
2186 if (!$matrix[$row][$col]) {
2187 $matrix[$row][$col] = $data[$offset] ? 5 : 4;
2188 $offset++;
2189 }
2190 if (!$matrix[$row][$col - 1]) {
2191 $matrix[$row][$col - 1] = $data[$offset] ? 5 : 4;
2192 $offset++;
2193 }
2194 $row += $dir;
2195 if ($row < 0 || $row >= $size) {
2196 $dir = -$dir;
2197 $row += $dir;
2198 $col -= 2;
2199 if ($col == 6) $col--;
2200 }
2201 }
2202 return array($size, $matrix);
2203 }
2204
2205 private function qr_apply_best_mask($matrix, $size) {
2206 $best_mask = 0;
2207 $best_matrix = $this->qr_apply_mask($matrix, $size, $best_mask);
2208 $best_penalty = $this->qr_penalty($best_matrix, $size);
2209 for ($test_mask = 1; $test_mask < 8; $test_mask++) {
2210 $test_matrix = $this->qr_apply_mask($matrix, $size, $test_mask);
2211 $test_penalty = $this->qr_penalty($test_matrix, $size);
2212 if ($test_penalty < $best_penalty) {
2213 $best_mask = $test_mask;
2214 $best_matrix = $test_matrix;
2215 $best_penalty = $test_penalty;
2216 }
2217 }
2218 return array($best_mask, $best_matrix);
2219 }
2220
2221 private function qr_apply_mask($matrix, $size, $mask) {
2222 for ($i = 0; $i < $size; $i++) {
2223 for ($j = 0; $j < $size; $j++) {
2224 if ($matrix[$i][$j] >= 4) {
2225 if ($this->qr_mask($mask, $i, $j)) {
2226 $matrix[$i][$j] ^= 1;
2227 }
2228 }
2229 }
2230 }
2231 return $matrix;
2232 }
2233
2234 private function qr_mask($mask, $r, $c) {
2235 switch ($mask) {
2236 case 0: return !( ($r + $c) % 2 );
2237 case 1: return !( ($r ) % 2 );
2238 case 2: return !( ( $c) % 3 );
2239 case 3: return !( ($r + $c) % 3 );
2240 case 4: return !( (floor(($r) / 2) + floor(($c) / 3)) % 2 );
2241 case 5: return !( ((($r * $c) % 2) + (($r * $c) % 3)) );
2242 case 6: return !( ((($r * $c) % 2) + (($r * $c) % 3)) % 2 );
2243 case 7: return !( ((($r + $c) % 2) + (($r * $c) % 3)) % 2 );
2244 }
2245 }
2246
2247 private function qr_penalty(&$matrix, $size) {
2248 $score = $this->qr_penalty_1($matrix, $size);
2249 $score += $this->qr_penalty_2($matrix, $size);
2250 $score += $this->qr_penalty_3($matrix, $size);
2251 $score += $this->qr_penalty_4($matrix, $size);
2252 return $score;
2253 }
2254
2255 private function qr_penalty_1(&$matrix, $size) {
2256 $score = 0;
2257 for ($i = 0; $i < $size; $i++) {
2258 $rowvalue = 0;
2259 $rowcount = 0;
2260 $colvalue = 0;
2261 $colcount = 0;
2262 for ($j = 0; $j < $size; $j++) {
2263 $rv = ($matrix[$i][$j] == 5 || $matrix[$i][$j] == 3) ? 1 : 0;
2264 $cv = ($matrix[$j][$i] == 5 || $matrix[$j][$i] == 3) ? 1 : 0;
2265 if ($rv == $rowvalue) {
2266 $rowcount++;
2267 } else {
2268 if ($rowcount >= 5) $score += $rowcount - 2;
2269 $rowvalue = $rv;
2270 $rowcount = 1;
2271 }
2272 if ($cv == $colvalue) {
2273 $colcount++;
2274 } else {
2275 if ($colcount >= 5) $score += $colcount - 2;
2276 $colvalue = $cv;
2277 $colcount = 1;
2278 }
2279 }
2280 if ($rowcount >= 5) $score += $rowcount - 2;
2281 if ($colcount >= 5) $score += $colcount - 2;
2282 }
2283 return $score;
2284 }
2285
2286 private function qr_penalty_2(&$matrix, $size) {
2287 $score = 0;
2288 for ($i = 1; $i < $size; $i++) {
2289 for ($j = 1; $j < $size; $j++) {
2290 $v1 = $matrix[$i - 1][$j - 1];
2291 $v2 = $matrix[$i - 1][$j ];
2292 $v3 = $matrix[$i ][$j - 1];
2293 $v4 = $matrix[$i ][$j ];
2294 $v1 = ($v1 == 5 || $v1 == 3) ? 1 : 0;
2295 $v2 = ($v2 == 5 || $v2 == 3) ? 1 : 0;
2296 $v3 = ($v3 == 5 || $v3 == 3) ? 1 : 0;
2297 $v4 = ($v4 == 5 || $v4 == 3) ? 1 : 0;
2298 if ($v1 == $v2 && $v2 == $v3 && $v3 == $v4) $score += 3;
2299 }
2300 }
2301 return $score;
2302 }
2303
2304 private function qr_penalty_3(&$matrix, $size) {
2305 $score = 0;
2306 for ($i = 0; $i < $size; $i++) {
2307 $rowvalue = 0;
2308 $colvalue = 0;
2309 for ($j = 0; $j < 11; $j++) {
2310 $rv = ($matrix[$i][$j] == 5 || $matrix[$i][$j] == 3) ? 1 : 0;
2311 $cv = ($matrix[$j][$i] == 5 || $matrix[$j][$i] == 3) ? 1 : 0;
2312 $rowvalue = (($rowvalue << 1) & 0x7FF) | $rv;
2313 $colvalue = (($colvalue << 1) & 0x7FF) | $cv;
2314 }
2315 if ($rowvalue == 0x5D0 || $rowvalue == 0x5D) $score += 40;
2316 if ($colvalue == 0x5D0 || $colvalue == 0x5D) $score += 40;
2317 for ($j = 11; $j < $size; $j++) {
2318 $rv = ($matrix[$i][$j] == 5 || $matrix[$i][$j] == 3) ? 1 : 0;
2319 $cv = ($matrix[$j][$i] == 5 || $matrix[$j][$i] == 3) ? 1 : 0;
2320 $rowvalue = (($rowvalue << 1) & 0x7FF) | $rv;
2321 $colvalue = (($colvalue << 1) & 0x7FF) | $cv;
2322 if ($rowvalue == 0x5D0 || $rowvalue == 0x5D) $score += 40;
2323 if ($colvalue == 0x5D0 || $colvalue == 0x5D) $score += 40;
2324 }
2325 }
2326 return $score;
2327 }
2328
2329 private function qr_penalty_4(&$matrix, $size) {
2330 $dark = 0;
2331 for ($i = 0; $i < $size; $i++) {
2332 for ($j = 0; $j < $size; $j++) {
2333 if ($matrix[$i][$j] == 5 || $matrix[$i][$j] == 3) {
2334 $dark++;
2335 }
2336 }
2337 }
2338 $dark *= 20;
2339 $dark /= $size * $size;
2340 $a = abs(floor($dark) - 10);
2341 $b = abs(ceil($dark) - 10);
2342 return min($a, $b) * 10;
2343 }
2344
2345 private function qr_finalize_matrix(
2346 $matrix, $size, $ecl, $mask, $version
2347 ) {
2348 /* Format Info */
2349 $format = $this->qr_format_info[$ecl * 8 + $mask];
2350 $matrix[8][0] = $format[0];
2351 $matrix[8][1] = $format[1];
2352 $matrix[8][2] = $format[2];
2353 $matrix[8][3] = $format[3];
2354 $matrix[8][4] = $format[4];
2355 $matrix[8][5] = $format[5];
2356 $matrix[8][7] = $format[6];
2357 $matrix[8][8] = $format[7];
2358 $matrix[7][8] = $format[8];
2359 $matrix[5][8] = $format[9];
2360 $matrix[4][8] = $format[10];
2361 $matrix[3][8] = $format[11];
2362 $matrix[2][8] = $format[12];
2363 $matrix[1][8] = $format[13];
2364 $matrix[0][8] = $format[14];
2365 $matrix[$size - 1][8] = $format[0];
2366 $matrix[$size - 2][8] = $format[1];
2367 $matrix[$size - 3][8] = $format[2];
2368 $matrix[$size - 4][8] = $format[3];
2369 $matrix[$size - 5][8] = $format[4];
2370 $matrix[$size - 6][8] = $format[5];
2371 $matrix[$size - 7][8] = $format[6];
2372 $matrix[8][$size - 8] = $format[7];
2373 $matrix[8][$size - 7] = $format[8];
2374 $matrix[8][$size - 6] = $format[9];
2375 $matrix[8][$size - 5] = $format[10];
2376 $matrix[8][$size - 4] = $format[11];
2377 $matrix[8][$size - 3] = $format[12];
2378 $matrix[8][$size - 2] = $format[13];
2379 $matrix[8][$size - 1] = $format[14];
2380 /* Version Info */
2381 if ($version >= 7) {
2382 $version = $this->qr_version_info[$version - 7];
2383 for ($i = 0; $i < 18; $i++) {
2384 $r = $size - 9 - ($i % 3);
2385 $c = 5 - floor($i / 3);
2386 $matrix[$r][$c] = $version[$i];
2387 $matrix[$c][$r] = $version[$i];
2388 }
2389 }
2390 /* Patterns & Data */
2391 for ($i = 0; $i < $size; $i++) {
2392 for ($j = 0; $j < $size; $j++) {
2393 $matrix[$i][$j] &= 1;
2394 }
2395 }
2396 return $matrix;
2397 }
2398
2399 /* maximum encodable characters = $qr_capacity [ (version - 1) ] */
2400 /* [ (0 for L, 1 for M, 2 for Q, 3 for H) ] */
2401 /* [ (0 for numeric, 1 for alpha, 2 for binary, 3 for kanji) ] */
2402 private $qr_capacity = array(
2403 array(array( 41, 25, 17, 10), array( 34, 20, 14, 8),
2404 array( 27, 16, 11, 7), array( 17, 10, 7, 4)),
2405 array(array( 77, 47, 32, 20), array( 63, 38, 26, 16),
2406 array( 48, 29, 20, 12), array( 34, 20, 14, 8)),
2407 array(array( 127, 77, 53, 32), array( 101, 61, 42, 26),
2408 array( 77, 47, 32, 20), array( 58, 35, 24, 15)),
2409 array(array( 187, 114, 78, 48), array( 149, 90, 62, 38),
2410 array( 111, 67, 46, 28), array( 82, 50, 34, 21)),
2411 array(array( 255, 154, 106, 65), array( 202, 122, 84, 52),
2412 array( 144, 87, 60, 37), array( 106, 64, 44, 27)),
2413 array(array( 322, 195, 134, 82), array( 255, 154, 106, 65),
2414 array( 178, 108, 74, 45), array( 139, 84, 58, 36)),
2415 array(array( 370, 224, 154, 95), array( 293, 178, 122, 75),
2416 array( 207, 125, 86, 53), array( 154, 93, 64, 39)),
2417 array(array( 461, 279, 192, 118), array( 365, 221, 152, 93),
2418 array( 259, 157, 108, 66), array( 202, 122, 84, 52)),
2419 array(array( 552, 335, 230, 141), array( 432, 262, 180, 111),
2420 array( 312, 189, 130, 80), array( 235, 143, 98, 60)),
2421 array(array( 652, 395, 271, 167), array( 513, 311, 213, 131),
2422 array( 364, 221, 151, 93), array( 288, 174, 119, 74)),
2423 array(array( 772, 468, 321, 198), array( 604, 366, 251, 155),
2424 array( 427, 259, 177, 109), array( 331, 200, 137, 85)),
2425 array(array( 883, 535, 367, 226), array( 691, 419, 287, 177),
2426 array( 489, 296, 203, 125), array( 374, 227, 155, 96)),
2427 array(array(1022, 619, 425, 262), array( 796, 483, 331, 204),
2428 array( 580, 352, 241, 149), array( 427, 259, 177, 109)),
2429 array(array(1101, 667, 458, 282), array( 871, 528, 362, 223),
2430 array( 621, 376, 258, 159), array( 468, 283, 194, 120)),
2431 array(array(1250, 758, 520, 320), array( 991, 600, 412, 254),
2432 array( 703, 426, 292, 180), array( 530, 321, 220, 136)),
2433 array(array(1408, 854, 586, 361), array(1082, 656, 450, 277),
2434 array( 775, 470, 322, 198), array( 602, 365, 250, 154)),
2435 array(array(1548, 938, 644, 397), array(1212, 734, 504, 310),
2436 array( 876, 531, 364, 224), array( 674, 408, 280, 173)),
2437 array(array(1725, 1046, 718, 442), array(1346, 816, 560, 345),
2438 array( 948, 574, 394, 243), array( 746, 452, 310, 191)),
2439 array(array(1903, 1153, 792, 488), array(1500, 909, 624, 384),
2440 array(1063, 644, 442, 272), array( 813, 493, 338, 208)),
2441 array(array(2061, 1249, 858, 528), array(1600, 970, 666, 410),
2442 array(1159, 702, 482, 297), array( 919, 557, 382, 235)),
2443 array(array(2232, 1352, 929, 572), array(1708, 1035, 711, 438),
2444 array(1224, 742, 509, 314), array( 969, 587, 403, 248)),
2445 array(array(2409, 1460, 1003, 618), array(1872, 1134, 779, 480),
2446 array(1358, 823, 565, 348), array(1056, 640, 439, 270)),
2447 array(array(2620, 1588, 1091, 672), array(2059, 1248, 857, 528),
2448 array(1468, 890, 611, 376), array(1108, 672, 461, 284)),
2449 array(array(2812, 1704, 1171, 721), array(2188, 1326, 911, 561),
2450 array(1588, 963, 661, 407), array(1228, 744, 511, 315)),
2451 array(array(3057, 1853, 1273, 784), array(2395, 1451, 997, 614),
2452 array(1718, 1041, 715, 440), array(1286, 779, 535, 330)),
2453 array(array(3283, 1990, 1367, 842), array(2544, 1542, 1059, 652),
2454 array(1804, 1094, 751, 462), array(1425, 864, 593, 365)),
2455 array(array(3517, 2132, 1465, 902), array(2701, 1637, 1125, 692),
2456 array(1933, 1172, 805, 496), array(1501, 910, 625, 385)),
2457 array(array(3669, 2223, 1528, 940), array(2857, 1732, 1190, 732),
2458 array(2085, 1263, 868, 534), array(1581, 958, 658, 405)),
2459 array(array(3909, 2369, 1628, 1002), array(3035, 1839, 1264, 778),
2460 array(2181, 1322, 908, 559), array(1677, 1016, 698, 430)),
2461 array(array(4158, 2520, 1732, 1066), array(3289, 1994, 1370, 843),
2462 array(2358, 1429, 982, 604), array(1782, 1080, 742, 457)),
2463 array(array(4417, 2677, 1840, 1132), array(3486, 2113, 1452, 894),
2464 array(2473, 1499, 1030, 634), array(1897, 1150, 790, 486)),
2465 array(array(4686, 2840, 1952, 1201), array(3693, 2238, 1538, 947),
2466 array(2670, 1618, 1112, 684), array(2022, 1226, 842, 518)),
2467 array(array(4965, 3009, 2068, 1273), array(3909, 2369, 1628, 1002),
2468 array(2805, 1700, 1168, 719), array(2157, 1307, 898, 553)),
2469 array(array(5253, 3183, 2188, 1347), array(4134, 2506, 1722, 1060),
2470 array(2949, 1787, 1228, 756), array(2301, 1394, 958, 590)),
2471 array(array(5529, 3351, 2303, 1417), array(4343, 2632, 1809, 1113),
2472 array(3081, 1867, 1283, 790), array(2361, 1431, 983, 605)),
2473 array(array(5836, 3537, 2431, 1496), array(4588, 2780, 1911, 1176),
2474 array(3244, 1966, 1351, 832), array(2524, 1530, 1051, 647)),
2475 array(array(6153, 3729, 2563, 1577), array(4775, 2894, 1989, 1224),
2476 array(3417, 2071, 1423, 876), array(2625, 1591, 1093, 673)),
2477 array(array(6479, 3927, 2699, 1661), array(5039, 3054, 2099, 1292),
2478 array(3599, 2181, 1499, 923), array(2735, 1658, 1139, 701)),
2479 array(array(6743, 4087, 2809, 1729), array(5313, 3220, 2213, 1362),
2480 array(3791, 2298, 1579, 972), array(2927, 1774, 1219, 750)),
2481 array(array(7089, 4296, 2953, 1817), array(5596, 3391, 2331, 1435),
2482 array(3993, 2420, 1663, 1024), array(3057, 1852, 1273, 784)),
2483 );
2484
2485 /* $qr_ec_params[ */
2486 /* 4 * (version - 1) + (0 for L, 1 for M, 2 for Q, 3 for H) */
2487 /* ] = array( */
2488 /* total number of data codewords, */
2489 /* number of error correction codewords per block, */
2490 /* number of blocks in first group, */
2491 /* number of data codewords per block in first group, */
2492 /* number of blocks in second group, */
2493 /* number of data codewords per block in second group */
2494 /* ); */
2495 private $qr_ec_params = array(
2496 array( 19, 7, 1, 19, 0, 0 ),
2497 array( 16, 10, 1, 16, 0, 0 ),
2498 array( 13, 13, 1, 13, 0, 0 ),
2499 array( 9, 17, 1, 9, 0, 0 ),
2500 array( 34, 10, 1, 34, 0, 0 ),
2501 array( 28, 16, 1, 28, 0, 0 ),
2502 array( 22, 22, 1, 22, 0, 0 ),
2503 array( 16, 28, 1, 16, 0, 0 ),
2504 array( 55, 15, 1, 55, 0, 0 ),
2505 array( 44, 26, 1, 44, 0, 0 ),
2506 array( 34, 18, 2, 17, 0, 0 ),
2507 array( 26, 22, 2, 13, 0, 0 ),
2508 array( 80, 20, 1, 80, 0, 0 ),
2509 array( 64, 18, 2, 32, 0, 0 ),
2510 array( 48, 26, 2, 24, 0, 0 ),
2511 array( 36, 16, 4, 9, 0, 0 ),
2512 array( 108, 26, 1, 108, 0, 0 ),
2513 array( 86, 24, 2, 43, 0, 0 ),
2514 array( 62, 18, 2, 15, 2, 16 ),
2515 array( 46, 22, 2, 11, 2, 12 ),
2516 array( 136, 18, 2, 68, 0, 0 ),
2517 array( 108, 16, 4, 27, 0, 0 ),
2518 array( 76, 24, 4, 19, 0, 0 ),
2519 array( 60, 28, 4, 15, 0, 0 ),
2520 array( 156, 20, 2, 78, 0, 0 ),
2521 array( 124, 18, 4, 31, 0, 0 ),
2522 array( 88, 18, 2, 14, 4, 15 ),
2523 array( 66, 26, 4, 13, 1, 14 ),
2524 array( 194, 24, 2, 97, 0, 0 ),
2525 array( 154, 22, 2, 38, 2, 39 ),
2526 array( 110, 22, 4, 18, 2, 19 ),
2527 array( 86, 26, 4, 14, 2, 15 ),
2528 array( 232, 30, 2, 116, 0, 0 ),
2529 array( 182, 22, 3, 36, 2, 37 ),
2530 array( 132, 20, 4, 16, 4, 17 ),
2531 array( 100, 24, 4, 12, 4, 13 ),
2532 array( 274, 18, 2, 68, 2, 69 ),
2533 array( 216, 26, 4, 43, 1, 44 ),
2534 array( 154, 24, 6, 19, 2, 20 ),
2535 array( 122, 28, 6, 15, 2, 16 ),
2536 array( 324, 20, 4, 81, 0, 0 ),
2537 array( 254, 30, 1, 50, 4, 51 ),
2538 array( 180, 28, 4, 22, 4, 23 ),
2539 array( 140, 24, 3, 12, 8, 13 ),
2540 array( 370, 24, 2, 92, 2, 93 ),
2541 array( 290, 22, 6, 36, 2, 37 ),
2542 array( 206, 26, 4, 20, 6, 21 ),
2543 array( 158, 28, 7, 14, 4, 15 ),
2544 array( 428, 26, 4, 107, 0, 0 ),
2545 array( 334, 22, 8, 37, 1, 38 ),
2546 array( 244, 24, 8, 20, 4, 21 ),
2547 array( 180, 22, 12, 11, 4, 12 ),
2548 array( 461, 30, 3, 115, 1, 116 ),
2549 array( 365, 24, 4, 40, 5, 41 ),
2550 array( 261, 20, 11, 16, 5, 17 ),
2551 array( 197, 24, 11, 12, 5, 13 ),
2552 array( 523, 22, 5, 87, 1, 88 ),
2553 array( 415, 24, 5, 41, 5, 42 ),
2554 array( 295, 30, 5, 24, 7, 25 ),
2555 array( 223, 24, 11, 12, 7, 13 ),
2556 array( 589, 24, 5, 98, 1, 99 ),
2557 array( 453, 28, 7, 45, 3, 46 ),
2558 array( 325, 24, 15, 19, 2, 20 ),
2559 array( 253, 30, 3, 15, 13, 16 ),
2560 array( 647, 28, 1, 107, 5, 108 ),
2561 array( 507, 28, 10, 46, 1, 47 ),
2562 array( 367, 28, 1, 22, 15, 23 ),
2563 array( 283, 28, 2, 14, 17, 15 ),
2564 array( 721, 30, 5, 120, 1, 121 ),
2565 array( 563, 26, 9, 43, 4, 44 ),
2566 array( 397, 28, 17, 22, 1, 23 ),
2567 array( 313, 28, 2, 14, 19, 15 ),
2568 array( 795, 28, 3, 113, 4, 114 ),
2569 array( 627, 26, 3, 44, 11, 45 ),
2570 array( 445, 26, 17, 21, 4, 22 ),
2571 array( 341, 26, 9, 13, 16, 14 ),
2572 array( 861, 28, 3, 107, 5, 108 ),
2573 array( 669, 26, 3, 41, 13, 42 ),
2574 array( 485, 30, 15, 24, 5, 25 ),
2575 array( 385, 28, 15, 15, 10, 16 ),
2576 array( 932, 28, 4, 116, 4, 117 ),
2577 array( 714, 26, 17, 42, 0, 0 ),
2578 array( 512, 28, 17, 22, 6, 23 ),
2579 array( 406, 30, 19, 16, 6, 17 ),
2580 array( 1006, 28, 2, 111, 7, 112 ),
2581 array( 782, 28, 17, 46, 0, 0 ),
2582 array( 568, 30, 7, 24, 16, 25 ),
2583 array( 442, 24, 34, 13, 0, 0 ),
2584 array( 1094, 30, 4, 121, 5, 122 ),
2585 array( 860, 28, 4, 47, 14, 48 ),
2586 array( 614, 30, 11, 24, 14, 25 ),
2587 array( 464, 30, 16, 15, 14, 16 ),
2588 array( 1174, 30, 6, 117, 4, 118 ),
2589 array( 914, 28, 6, 45, 14, 46 ),
2590 array( 664, 30, 11, 24, 16, 25 ),
2591 array( 514, 30, 30, 16, 2, 17 ),
2592 array( 1276, 26, 8, 106, 4, 107 ),
2593 array( 1000, 28, 8, 47, 13, 48 ),
2594 array( 718, 30, 7, 24, 22, 25 ),
2595 array( 538, 30, 22, 15, 13, 16 ),
2596 array( 1370, 28, 10, 114, 2, 115 ),
2597 array( 1062, 28, 19, 46, 4, 47 ),
2598 array( 754, 28, 28, 22, 6, 23 ),
2599 array( 596, 30, 33, 16, 4, 17 ),
2600 array( 1468, 30, 8, 122, 4, 123 ),
2601 array( 1128, 28, 22, 45, 3, 46 ),
2602 array( 808, 30, 8, 23, 26, 24 ),
2603 array( 628, 30, 12, 15, 28, 16 ),
2604 array( 1531, 30, 3, 117, 10, 118 ),
2605 array( 1193, 28, 3, 45, 23, 46 ),
2606 array( 871, 30, 4, 24, 31, 25 ),
2607 array( 661, 30, 11, 15, 31, 16 ),
2608 array( 1631, 30, 7, 116, 7, 117 ),
2609 array( 1267, 28, 21, 45, 7, 46 ),
2610 array( 911, 30, 1, 23, 37, 24 ),
2611 array( 701, 30, 19, 15, 26, 16 ),
2612 array( 1735, 30, 5, 115, 10, 116 ),
2613 array( 1373, 28, 19, 47, 10, 48 ),
2614 array( 985, 30, 15, 24, 25, 25 ),
2615 array( 745, 30, 23, 15, 25, 16 ),
2616 array( 1843, 30, 13, 115, 3, 116 ),
2617 array( 1455, 28, 2, 46, 29, 47 ),
2618 array( 1033, 30, 42, 24, 1, 25 ),
2619 array( 793, 30, 23, 15, 28, 16 ),
2620 array( 1955, 30, 17, 115, 0, 0 ),
2621 array( 1541, 28, 10, 46, 23, 47 ),
2622 array( 1115, 30, 10, 24, 35, 25 ),
2623 array( 845, 30, 19, 15, 35, 16 ),
2624 array( 2071, 30, 17, 115, 1, 116 ),
2625 array( 1631, 28, 14, 46, 21, 47 ),
2626 array( 1171, 30, 29, 24, 19, 25 ),
2627 array( 901, 30, 11, 15, 46, 16 ),
2628 array( 2191, 30, 13, 115, 6, 116 ),
2629 array( 1725, 28, 14, 46, 23, 47 ),
2630 array( 1231, 30, 44, 24, 7, 25 ),
2631 array( 961, 30, 59, 16, 1, 17 ),
2632 array( 2306, 30, 12, 121, 7, 122 ),
2633 array( 1812, 28, 12, 47, 26, 48 ),
2634 array( 1286, 30, 39, 24, 14, 25 ),
2635 array( 986, 30, 22, 15, 41, 16 ),
2636 array( 2434, 30, 6, 121, 14, 122 ),
2637 array( 1914, 28, 6, 47, 34, 48 ),
2638 array( 1354, 30, 46, 24, 10, 25 ),
2639 array( 1054, 30, 2, 15, 64, 16 ),
2640 array( 2566, 30, 17, 122, 4, 123 ),
2641 array( 1992, 28, 29, 46, 14, 47 ),
2642 array( 1426, 30, 49, 24, 10, 25 ),
2643 array( 1096, 30, 24, 15, 46, 16 ),
2644 array( 2702, 30, 4, 122, 18, 123 ),
2645 array( 2102, 28, 13, 46, 32, 47 ),
2646 array( 1502, 30, 48, 24, 14, 25 ),
2647 array( 1142, 30, 42, 15, 32, 16 ),
2648 array( 2812, 30, 20, 117, 4, 118 ),
2649 array( 2216, 28, 40, 47, 7, 48 ),
2650 array( 1582, 30, 43, 24, 22, 25 ),
2651 array( 1222, 30, 10, 15, 67, 16 ),
2652 array( 2956, 30, 19, 118, 6, 119 ),
2653 array( 2334, 28, 18, 47, 31, 48 ),
2654 array( 1666, 30, 34, 24, 34, 25 ),
2655 array( 1276, 30, 20, 15, 61, 16 ),
2656 );
2657
2658 private $qr_ec_polynomials = array(
2659 7 => array(
2660 0, 87, 229, 146, 149, 238, 102, 21
2661 ),
2662 10 => array(
2663 0, 251, 67, 46, 61, 118, 70, 64, 94, 32, 45
2664 ),
2665 13 => array(
2666 0, 74, 152, 176, 100, 86, 100,
2667 106, 104, 130, 218, 206, 140, 78
2668 ),
2669 15 => array(
2670 0, 8, 183, 61, 91, 202, 37, 51,
2671 58, 58, 237, 140, 124, 5, 99, 105
2672 ),
2673 16 => array(
2674 0, 120, 104, 107, 109, 102, 161, 76, 3,
2675 91, 191, 147, 169, 182, 194, 225, 120
2676 ),
2677 17 => array(
2678 0, 43, 139, 206, 78, 43, 239, 123, 206,
2679 214, 147, 24, 99, 150, 39, 243, 163, 136
2680 ),
2681 18 => array(
2682 0, 215, 234, 158, 94, 184, 97, 118, 170, 79,
2683 187, 152, 148, 252, 179, 5, 98, 96, 153
2684 ),
2685 20 => array(
2686 0, 17, 60, 79, 50, 61, 163, 26, 187, 202, 180,
2687 221, 225, 83, 239, 156, 164, 212, 212, 188, 190
2688 ),
2689 22 => array(
2690 0, 210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200,
2691 74, 8, 172, 98, 80, 219, 134, 160, 105, 165, 231
2692 ),
2693 24 => array(
2694 0, 229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169,
2695 152, 192, 226, 228, 218, 111, 0, 117, 232, 87, 96, 227, 21
2696 ),
2697 26 => array(
2698 0, 173, 125, 158, 2, 103, 182, 118, 17,
2699 145, 201, 111, 28, 165, 53, 161, 21, 245,
2700 142, 13, 102, 48, 227, 153, 145, 218, 70
2701 ),
2702 28 => array(
2703 0, 168, 223, 200, 104, 224, 234, 108, 180,
2704 110, 190, 195, 147, 205, 27, 232, 201, 21, 43,
2705 245, 87, 42, 195, 212, 119, 242, 37, 9, 123
2706 ),
2707 30 => array(
2708 0, 41, 173, 145, 152, 216, 31, 179, 182, 50, 48,
2709 110, 86, 239, 96, 222, 125, 42, 173, 226, 193,
2710 224, 130, 156, 37, 251, 216, 238, 40, 192, 180
2711 ),
2712 );
2713
2714 private $qr_log = array(
2715 0, 0, 1, 25, 2, 50, 26, 198,
2716 3, 223, 51, 238, 27, 104, 199, 75,
2717 4, 100, 224, 14, 52, 141, 239, 129,
2718 28, 193, 105, 248, 200, 8, 76, 113,
2719 5, 138, 101, 47, 225, 36, 15, 33,
2720 53, 147, 142, 218, 240, 18, 130, 69,
2721 29, 181, 194, 125, 106, 39, 249, 185,
2722 201, 154, 9, 120, 77, 228, 114, 166,
2723 6, 191, 139, 98, 102, 221, 48, 253,
2724 226, 152, 37, 179, 16, 145, 34, 136,
2725 54, 208, 148, 206, 143, 150, 219, 189,
2726 241, 210, 19, 92, 131, 56, 70, 64,
2727 30, 66, 182, 163, 195, 72, 126, 110,
2728 107, 58, 40, 84, 250, 133, 186, 61,
2729 202, 94, 155, 159, 10, 21, 121, 43,
2730 78, 212, 229, 172, 115, 243, 167, 87,
2731 7, 112, 192, 247, 140, 128, 99, 13,
2732 103, 74, 222, 237, 49, 197, 254, 24,
2733 227, 165, 153, 119, 38, 184, 180, 124,
2734 17, 68, 146, 217, 35, 32, 137, 46,
2735 55, 63, 209, 91, 149, 188, 207, 205,
2736 144, 135, 151, 178, 220, 252, 190, 97,
2737 242, 86, 211, 171, 20, 42, 93, 158,
2738 132, 60, 57, 83, 71, 109, 65, 162,
2739 31, 45, 67, 216, 183, 123, 164, 118,
2740 196, 23, 73, 236, 127, 12, 111, 246,
2741 108, 161, 59, 82, 41, 157, 85, 170,
2742 251, 96, 134, 177, 187, 204, 62, 90,
2743 203, 89, 95, 176, 156, 169, 160, 81,
2744 11, 245, 22, 235, 122, 117, 44, 215,
2745 79, 174, 213, 233, 230, 231, 173, 232,
2746 116, 214, 244, 234, 168, 80, 88, 175,
2747 );
2748
2749 private $qr_exp = array(
2750 1, 2, 4, 8, 16, 32, 64, 128,
2751 29, 58, 116, 232, 205, 135, 19, 38,
2752 76, 152, 45, 90, 180, 117, 234, 201,
2753 143, 3, 6, 12, 24, 48, 96, 192,
2754 157, 39, 78, 156, 37, 74, 148, 53,
2755 106, 212, 181, 119, 238, 193, 159, 35,
2756 70, 140, 5, 10, 20, 40, 80, 160,
2757 93, 186, 105, 210, 185, 111, 222, 161,
2758 95, 190, 97, 194, 153, 47, 94, 188,
2759 101, 202, 137, 15, 30, 60, 120, 240,
2760 253, 231, 211, 187, 107, 214, 177, 127,
2761 254, 225, 223, 163, 91, 182, 113, 226,
2762 217, 175, 67, 134, 17, 34, 68, 136,
2763 13, 26, 52, 104, 208, 189, 103, 206,
2764 129, 31, 62, 124, 248, 237, 199, 147,
2765 59, 118, 236, 197, 151, 51, 102, 204,
2766 133, 23, 46, 92, 184, 109, 218, 169,
2767 79, 158, 33, 66, 132, 21, 42, 84,
2768 168, 77, 154, 41, 82, 164, 85, 170,
2769 73, 146, 57, 114, 228, 213, 183, 115,
2770 230, 209, 191, 99, 198, 145, 63, 126,
2771 252, 229, 215, 179, 123, 246, 241, 255,
2772 227, 219, 171, 75, 150, 49, 98, 196,
2773 149, 55, 110, 220, 165, 87, 174, 65,
2774 130, 25, 50, 100, 200, 141, 7, 14,
2775 28, 56, 112, 224, 221, 167, 83, 166,
2776 81, 162, 89, 178, 121, 242, 249, 239,
2777 195, 155, 43, 86, 172, 69, 138, 9,
2778 18, 36, 72, 144, 61, 122, 244, 245,
2779 247, 243, 251, 235, 203, 139, 11, 22,
2780 44, 88, 176, 125, 250, 233, 207, 131,
2781 27, 54, 108, 216, 173, 71, 142, 1,
2782 );
2783
2784 private $qr_remainder_bits = array(
2785 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3,
2786 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0,
2787 );
2788
2789 private $qr_alignment_patterns = array(
2790 array(6, 18),
2791 array(6, 22),
2792 array(6, 26),
2793 array(6, 30),
2794 array(6, 34),
2795 array(6, 22, 38),
2796 array(6, 24, 42),
2797 array(6, 26, 46),
2798 array(6, 28, 50),
2799 array(6, 30, 54),
2800 array(6, 32, 58),
2801 array(6, 34, 62),
2802 array(6, 26, 46, 66),
2803 array(6, 26, 48, 70),
2804 array(6, 26, 50, 74),
2805 array(6, 30, 54, 78),
2806 array(6, 30, 56, 82),
2807 array(6, 30, 58, 86),
2808 array(6, 34, 62, 90),
2809 array(6, 28, 50, 72, 94),
2810 array(6, 26, 50, 74, 98),
2811 array(6, 30, 54, 78, 102),
2812 array(6, 28, 54, 80, 106),
2813 array(6, 32, 58, 84, 110),
2814 array(6, 30, 58, 86, 114),
2815 array(6, 34, 62, 90, 118),
2816 array(6, 26, 50, 74, 98, 122),
2817 array(6, 30, 54, 78, 102, 126),
2818 array(6, 26, 52, 78, 104, 130),
2819 array(6, 30, 56, 82, 108, 134),
2820 array(6, 34, 60, 86, 112, 138),
2821 array(6, 30, 58, 86, 114, 142),
2822 array(6, 34, 62, 90, 118, 146),
2823 array(6, 30, 54, 78, 102, 126, 150),
2824 array(6, 24, 50, 76, 102, 128, 154),
2825 array(6, 28, 54, 80, 106, 132, 158),
2826 array(6, 32, 58, 84, 110, 136, 162),
2827 array(6, 26, 54, 82, 110, 138, 166),
2828 array(6, 30, 58, 86, 114, 142, 170),
2829 );
2830
2831 /* format info string = $qr_format_info[ */
2832 /* (0 for L, 8 for M, 16 for Q, 24 for H) + mask */
2833 /* ]; */
2834 private $qr_format_info = array(
2835 array( 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0 ),
2836 array( 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1 ),
2837 array( 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 ),
2838 array( 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1 ),
2839 array( 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1 ),
2840 array( 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0 ),
2841 array( 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 ),
2842 array( 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0 ),
2843 array( 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 ),
2844 array( 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1 ),
2845 array( 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0 ),
2846 array( 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 ),
2847 array( 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1 ),
2848 array( 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 ),
2849 array( 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1 ),
2850 array( 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 ),
2851 array( 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1 ),
2852 array( 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0 ),
2853 array( 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 ),
2854 array( 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0 ),
2855 array( 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0 ),
2856 array( 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1 ),
2857 array( 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0 ),
2858 array( 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1 ),
2859 array( 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1 ),
2860 array( 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0 ),
2861 array( 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 ),
2862 array( 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0 ),
2863 array( 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0 ),
2864 array( 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 ),
2865 array( 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0 ),
2866 array( 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1 ),
2867 );
2868
2869 /* version info string = $qr_version_info[ (version - 7) ] */
2870 private $qr_version_info = array(
2871 array( 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0 ),
2872 array( 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0 ),
2873 array( 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 ),
2874 array( 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1 ),
2875 array( 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0 ),
2876 array( 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0 ),
2877 array( 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1 ),
2878 array( 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1 ),
2879 array( 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0 ),
2880 array( 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0 ),
2881 array( 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1 ),
2882 array( 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1 ),
2883 array( 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0 ),
2884 array( 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0 ),
2885 array( 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1 ),
2886 array( 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 ),
2887 array( 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0 ),
2888 array( 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0 ),
2889 array( 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 ),
2890 array( 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1 ),
2891 array( 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 ),
2892 array( 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0 ),
2893 array( 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 ),
2894 array( 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 ),
2895 array( 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0 ),
2896 array( 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1 ),
2897 array( 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0 ),
2898 array( 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0 ),
2899 array( 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 ),
2900 array( 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1 ),
2901 array( 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0 ),
2902 array( 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0 ),
2903 array( 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 ),
2904 array( 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1 ),
2905 );
2906
2907 /* - - - - DATA MATRIX ENCODER - - - - */
2908
2909 private function dmtx_encode($data, $rect, $fnc1) {
2910 list($data, $ec) = $this->dmtx_encode_data($data, $rect, $fnc1);
2911 $data = $this->dmtx_encode_ec($data, $ec);
2912 list($h, $w, $mtx) = $this->dmtx_create_matrix($ec, $data);
2913 return array(
2914 'g' => 'm',
2915 'q' => array(1, 1, 1, 1),
2916 's' => array($w, $h),
2917 'b' => $mtx
2918 );
2919 }
2920
2921 private function dmtx_encode_data($data, $rect, $fnc1) {
2922 /* Convert to data codewords. */
2923 $edata = ($fnc1 ? array(232) : array());
2924 $length = strlen($data);
2925 $offset = 0;
2926 while ($offset < $length) {
2927 $ch1 = ord(substr($data, $offset, 1));
2928 $offset++;
2929 if ($ch1 >= 0x30 && $ch1 <= 0x39) {
2930 $ch2 = ord(substr($data, $offset, 1));
2931 if ($ch2 >= 0x30 && $ch2 <= 0x39) {
2932 $offset++;
2933 $edata[] = (($ch1 - 0x30) * 10) + ($ch2 - 0x30) + 130;
2934 } else {
2935 $edata[] = $ch1 + 1;
2936 }
2937 } else if ($ch1 < 0x80) {
2938 $edata[] = $ch1 + 1;
2939 } else {
2940 $edata[] = 235;
2941 $edata[] = ($ch1 - 0x80) + 1;
2942 }
2943 }
2944 /* Add padding. */
2945 $length = count($edata);
2946 $ec_params = $this->dmtx_detect_version($length, $rect);
2947 if ($length > $ec_params[0]) {
2948 $length = $ec_params[0];
2949 $edata = array_slice($edata, 0, $length);
2950 if ($edata[$length - 1] == 235) {
2951 $edata[$length - 1] = 129;
2952 }
2953 } else if ($length < $ec_params[0]) {
2954 $length++;
2955 $edata[] = 129;
2956 while ($length < $ec_params[0]) {
2957 $length++;
2958 $r = (($length * 149) % 253) + 1;
2959 $edata[] = ($r + 129) % 254;
2960 }
2961 }
2962 /* Return. */
2963 return array($edata, $ec_params);
2964 }
2965
2966 private function dmtx_detect_version($length, $rect) {
2967 for ($i = ($rect ? 24 : 0), $j = ($rect ? 30 : 24); $i < $j; $i++) {
2968 if ($length <= $this->dmtx_ec_params[$i][0]) {
2969 return $this->dmtx_ec_params[$i];
2970 }
2971 }
2972 return $this->dmtx_ec_params[$j - 1];
2973 }
2974
2975 private function dmtx_encode_ec($data, $ec_params) {
2976 $blocks = $this->dmtx_ec_split($data, $ec_params);
2977 for ($i = 0, $n = count($blocks); $i < $n; $i++) {
2978 $ec_block = $this->dmtx_ec_divide($blocks[$i], $ec_params);
2979 $blocks[$i] = array_merge($blocks[$i], $ec_block);
2980 }
2981 return $this->dmtx_ec_interleave($blocks);
2982 }
2983
2984 private function dmtx_ec_split($data, $ec_params) {
2985 $blocks = array();
2986 $num_blocks = $ec_params[2] + $ec_params[4];
2987 for ($i = 0; $i < $num_blocks; $i++) {
2988 $blocks[$i] = array();
2989 }
2990 for ($i = 0, $length = count($data); $i < $length; $i++) {
2991 $blocks[$i % $num_blocks][] = $data[$i];
2992 }
2993 return $blocks;
2994 }
2995
2996 private function dmtx_ec_divide($data, $ec_params) {
2997 $num_data = count($data);
2998 $num_error = $ec_params[1];
2999 $generator = $this->dmtx_ec_polynomials[$num_error];
3000 $message = $data;
3001 for ($i = 0; $i < $num_error; $i++) {
3002 $message[] = 0;
3003 }
3004 for ($i = 0; $i < $num_data; $i++) {
3005 if ($message[$i]) {
3006 $leadterm = $this->dmtx_log[$message[$i]];
3007 for ($j = 0; $j <= $num_error; $j++) {
3008 $term = ($generator[$j] + $leadterm) % 255;
3009 $message[$i + $j] ^= $this->dmtx_exp[$term];
3010 }
3011 }
3012 }
3013 return array_slice($message, $num_data, $num_error);
3014 }
3015
3016 private function dmtx_ec_interleave($blocks) {
3017 $data = array();
3018 $num_blocks = count($blocks);
3019 for ($offset = 0; true; $offset++) {
3020 $break = true;
3021 for ($i = 0; $i < $num_blocks; $i++) {
3022 if (isset($blocks[$i][$offset])) {
3023 $data[] = $blocks[$i][$offset];
3024 $break = false;
3025 }
3026 }
3027 if ($break) break;
3028 }
3029 return $data;
3030 }
3031
3032 private function dmtx_create_matrix($ec_params, $data) {
3033 /* Create matrix. */
3034 $rheight = $ec_params[8] + 2;
3035 $rwidth = $ec_params[9] + 2;
3036 $height = $ec_params[6] * $rheight;
3037 $width = $ec_params[7] * $rwidth;
3038 $bitmap = array();
3039 for ($y = 0; $y < $height; $y++) {
3040 $row = array();
3041 for ($x = 0; $x < $width; $x++) {
3042 $row[] = ((
3043 ((($x + $y) % 2) == 0) ||
3044 (($x % $rwidth) == 0) ||
3045 (($y % $rheight) == ($rheight - 1))
3046 ) ? 1 : 0);
3047 }
3048 $bitmap[] = $row;
3049 }
3050 /* Create data region. */
3051 $rows = $ec_params[6] * $ec_params[8];
3052 $cols = $ec_params[7] * $ec_params[9];
3053 $matrix = array();
3054 for ($y = 0; $y < $rows; $y++) {
3055 $row = array();
3056 for ($x = 0; $x < $width; $x++) {
3057 $row[] = null;
3058 }
3059 $matrix[] = $row;
3060 }
3061 $this->dmtx_place_data($matrix, $rows, $cols, $data);
3062 /* Copy into matrix. */
3063 for ($yy = 0; $yy < $ec_params[6]; $yy++) {
3064 for ($xx = 0; $xx < $ec_params[7]; $xx++) {
3065 for ($y = 0; $y < $ec_params[8]; $y++) {
3066 for ($x = 0; $x < $ec_params[9]; $x++) {
3067 $row = $yy * $ec_params[8] + $y;
3068 $col = $xx * $ec_params[9] + $x;
3069 $b = $matrix[$row][$col];
3070 if (is_null($b)) continue;
3071 $row = $yy * $rheight + $y + 1;
3072 $col = $xx * $rwidth + $x + 1;
3073 $bitmap[$row][$col] = $b;
3074 }
3075 }
3076 }
3077 }
3078 /* Return matrix. */
3079 return array($height, $width, $bitmap);
3080 }
3081
3082 private function dmtx_place_data(&$mtx, $rows, $cols, $data) {
3083 $row = 4;
3084 $col = 0;
3085 $offset = 0;
3086 $length = count($data);
3087 while (($row < $rows || $col < $cols) && $offset < $length) {
3088 /* Corner cases. Literally. */
3089 if ($row == $rows && $col == 0) {
3090 $this->dmtx_place_1($mtx, $rows, $cols, $data[$offset++]);
3091 } else if ($row == $rows - 2 && $col == 0 && $cols % 4 != 0) {
3092 $this->dmtx_place_2($mtx, $rows, $cols, $data[$offset++]);
3093 } else if ($row == $rows - 2 && $col == 0 && $cols % 8 == 4) {
3094 $this->dmtx_place_3($mtx, $rows, $cols, $data[$offset++]);
3095 } else if ($row == $rows + 4 && $col == 2 && $cols % 8 == 0) {
3096 $this->dmtx_place_4($mtx, $rows, $cols, $data[$offset++]);
3097 }
3098 /* Up and to the right. */
3099 while ($row >= 0 && $col < $cols && $offset < $length) {
3100 if ($row < $rows && $col >= 0 && is_null($mtx[$row][$col])) {
3101 $b = $data[$offset++];
3102 $this->dmtx_place_0($mtx, $rows, $cols, $row, $col, $b);
3103 }
3104 $row -= 2;
3105 $col += 2;
3106 }
3107 $row += 1;
3108 $col += 3;
3109 /* Down and to the left. */
3110 while ($row < $rows && $col >= 0 && $offset < $length) {
3111 if ($row >= 0 && $col < $cols && is_null($mtx[$row][$col])) {
3112 $b = $data[$offset++];
3113 $this->dmtx_place_0($mtx, $rows, $cols, $row, $col, $b);
3114 }
3115 $row += 2;
3116 $col -= 2;
3117 }
3118 $row += 3;
3119 $col += 1;
3120 }
3121 }
3122
3123 private function dmtx_place_1(&$matrix, $rows, $cols, $b) {
3124 $matrix[$rows - 1][0] = (($b & 0x80) ? 1 : 0);
3125 $matrix[$rows - 1][1] = (($b & 0x40) ? 1 : 0);
3126 $matrix[$rows - 1][2] = (($b & 0x20) ? 1 : 0);
3127 $matrix[0][$cols - 2] = (($b & 0x10) ? 1 : 0);
3128 $matrix[0][$cols - 1] = (($b & 0x08) ? 1 : 0);
3129 $matrix[1][$cols - 1] = (($b & 0x04) ? 1 : 0);
3130 $matrix[2][$cols - 1] = (($b & 0x02) ? 1 : 0);
3131 $matrix[3][$cols - 1] = (($b & 0x01) ? 1 : 0);
3132 }
3133
3134 private function dmtx_place_2(&$matrix, $rows, $cols, $b) {
3135 $matrix[$rows - 3][0] = (($b & 0x80) ? 1 : 0);
3136 $matrix[$rows - 2][0] = (($b & 0x40) ? 1 : 0);
3137 $matrix[$rows - 1][0] = (($b & 0x20) ? 1 : 0);
3138 $matrix[0][$cols - 4] = (($b & 0x10) ? 1 : 0);
3139 $matrix[0][$cols - 3] = (($b & 0x08) ? 1 : 0);
3140 $matrix[0][$cols - 2] = (($b & 0x04) ? 1 : 0);
3141 $matrix[0][$cols - 1] = (($b & 0x02) ? 1 : 0);
3142 $matrix[1][$cols - 1] = (($b & 0x01) ? 1 : 0);
3143 }
3144
3145 private function dmtx_place_3(&$matrix, $rows, $cols, $b) {
3146 $matrix[$rows - 3][0] = (($b & 0x80) ? 1 : 0);
3147 $matrix[$rows - 2][0] = (($b & 0x40) ? 1 : 0);
3148 $matrix[$rows - 1][0] = (($b & 0x20) ? 1 : 0);
3149 $matrix[0][$cols - 2] = (($b & 0x10) ? 1 : 0);
3150 $matrix[0][$cols - 1] = (($b & 0x08) ? 1 : 0);
3151 $matrix[1][$cols - 1] = (($b & 0x04) ? 1 : 0);
3152 $matrix[2][$cols - 1] = (($b & 0x02) ? 1 : 0);
3153 $matrix[3][$cols - 1] = (($b & 0x01) ? 1 : 0);
3154 }
3155
3156 private function dmtx_place_4(&$matrix, $rows, $cols, $b) {
3157 $matrix[$rows - 1][ 0] = (($b & 0x80) ? 1 : 0);
3158 $matrix[$rows - 1][$cols - 1] = (($b & 0x40) ? 1 : 0);
3159 $matrix[ 0][$cols - 3] = (($b & 0x20) ? 1 : 0);
3160 $matrix[ 0][$cols - 2] = (($b & 0x10) ? 1 : 0);
3161 $matrix[ 0][$cols - 1] = (($b & 0x08) ? 1 : 0);
3162 $matrix[ 1][$cols - 3] = (($b & 0x04) ? 1 : 0);
3163 $matrix[ 1][$cols - 2] = (($b & 0x02) ? 1 : 0);
3164 $matrix[ 1][$cols - 1] = (($b & 0x01) ? 1 : 0);
3165 }
3166
3167 private function dmtx_place_0(&$matrix, $rows, $cols, $row, $col, $b) {
3168 $this->dmtx_place_b($matrix, $rows, $cols, $row-2, $col-2, $b & 0x80);
3169 $this->dmtx_place_b($matrix, $rows, $cols, $row-2, $col-1, $b & 0x40);
3170 $this->dmtx_place_b($matrix, $rows, $cols, $row-1, $col-2, $b & 0x20);
3171 $this->dmtx_place_b($matrix, $rows, $cols, $row-1, $col-1, $b & 0x10);
3172 $this->dmtx_place_b($matrix, $rows, $cols, $row-1, $col-0, $b & 0x08);
3173 $this->dmtx_place_b($matrix, $rows, $cols, $row-0, $col-2, $b & 0x04);
3174 $this->dmtx_place_b($matrix, $rows, $cols, $row-0, $col-1, $b & 0x02);
3175 $this->dmtx_place_b($matrix, $rows, $cols, $row-0, $col-0, $b & 0x01);
3176 }
3177
3178 private function dmtx_place_b(&$matrix, $rows, $cols, $row, $col, $b) {
3179 if ($row < 0) {
3180 $row += $rows;
3181 $col += (4 - (($rows + 4) % 8));
3182 }
3183 if ($col < 0) {
3184 $col += $cols;
3185 $row += (4 - (($cols + 4) % 8));
3186 }
3187 $matrix[$row][$col] = ($b ? 1 : 0);
3188 }
3189
3190 /* $dmtx_ec_params[] = array( */
3191 /* total number of data codewords, */
3192 /* number of error correction codewords per block, */
3193 /* number of blocks in first group, */
3194 /* number of data codewords per block in first group, */
3195 /* number of blocks in second group, */
3196 /* number of data codewords per block in second group, */
3197 /* number of data regions (vertical), */
3198 /* number of data regions (horizontal), */
3199 /* number of rows per data region, */
3200 /* number of columns per data region */
3201 /* ); */
3202 private $dmtx_ec_params = array(
3203 array( 3, 5, 1, 3, 0, 0, 1, 1, 8, 8 ),
3204 array( 5, 7, 1, 5, 0, 0, 1, 1, 10, 10 ),
3205 array( 8, 10, 1, 8, 0, 0, 1, 1, 12, 12 ),
3206 array( 12, 12, 1, 12, 0, 0, 1, 1, 14, 14 ),
3207 array( 18, 14, 1, 18, 0, 0, 1, 1, 16, 16 ),
3208 array( 22, 18, 1, 22, 0, 0, 1, 1, 18, 18 ),
3209 array( 30, 20, 1, 30, 0, 0, 1, 1, 20, 20 ),
3210 array( 36, 24, 1, 36, 0, 0, 1, 1, 22, 22 ),
3211 array( 44, 28, 1, 44, 0, 0, 1, 1, 24, 24 ),
3212 array( 62, 36, 1, 62, 0, 0, 2, 2, 14, 14 ),
3213 array( 86, 42, 1, 86, 0, 0, 2, 2, 16, 16 ),
3214 array( 114, 48, 1, 114, 0, 0, 2, 2, 18, 18 ),
3215 array( 144, 56, 1, 144, 0, 0, 2, 2, 20, 20 ),
3216 array( 174, 68, 1, 174, 0, 0, 2, 2, 22, 22 ),
3217 array( 204, 42, 2, 102, 0, 0, 2, 2, 24, 24 ),
3218 array( 280, 56, 2, 140, 0, 0, 4, 4, 14, 14 ),
3219 array( 368, 36, 4, 92, 0, 0, 4, 4, 16, 16 ),
3220 array( 456, 48, 4, 114, 0, 0, 4, 4, 18, 18 ),
3221 array( 576, 56, 4, 144, 0, 0, 4, 4, 20, 20 ),
3222 array( 696, 68, 4, 174, 0, 0, 4, 4, 22, 22 ),
3223 array( 816, 56, 6, 136, 0, 0, 4, 4, 24, 24 ),
3224 array( 1050, 68, 6, 175, 0, 0, 6, 6, 18, 18 ),
3225 array( 1304, 62, 8, 163, 0, 0, 6, 6, 20, 20 ),
3226 array( 1558, 62, 8, 156, 2, 155, 6, 6, 22, 22 ),
3227 array( 5, 7, 1, 5, 0, 0, 1, 1, 6, 16 ),
3228 array( 10, 11, 1, 10, 0, 0, 1, 2, 6, 14 ),
3229 array( 16, 14, 1, 16, 0, 0, 1, 1, 10, 24 ),
3230 array( 22, 18, 1, 22, 0, 0, 1, 2, 10, 16 ),
3231 array( 32, 24, 1, 32, 0, 0, 1, 2, 14, 16 ),
3232 array( 49, 28, 1, 49, 0, 0, 1, 2, 14, 22 ),
3233 );
3234
3235 private $dmtx_ec_polynomials = array(
3236 5 => array(
3237 0, 235, 207, 210, 244, 15
3238 ),
3239 7 => array(
3240 0, 177, 30, 214, 218, 42, 197, 28
3241 ),
3242 10 => array(
3243 0, 199, 50, 150, 120, 237, 131, 172, 83, 243, 55
3244 ),
3245 11 => array(
3246 0, 213, 173, 212, 156, 103, 109, 174, 242, 215, 12, 66
3247 ),
3248 12 => array(
3249 0, 168, 142, 35, 173, 94, 185, 107, 199, 74, 194, 233, 78
3250 ),
3251 14 => array(
3252 0, 83, 171, 33, 39, 8, 12, 248,
3253 27, 38, 84, 93, 246, 173, 105
3254 ),
3255 18 => array(
3256 0, 164, 9, 244, 69, 177, 163, 161, 231, 94,
3257 250, 199, 220, 253, 164, 103, 142, 61, 171
3258 ),
3259 20 => array(
3260 0, 127, 33, 146, 23, 79, 25, 193, 122, 209, 233,
3261 230, 164, 1, 109, 184, 149, 38, 201, 61, 210
3262 ),
3263 24 => array(
3264 0, 65, 141, 245, 31, 183, 242, 236, 177, 127, 225, 106,
3265 22, 131, 20, 202, 22, 106, 137, 103, 231, 215, 136, 85, 45
3266 ),
3267 28 => array(
3268 0, 150, 32, 109, 149, 239, 213, 198, 48, 94,
3269 50, 12, 195, 167, 130, 196, 253, 99, 166, 239,
3270 222, 146, 190, 245, 184, 173, 125, 17, 151
3271 ),
3272 36 => array(
3273 0, 57, 86, 187, 69, 140, 153, 31, 66, 135, 67, 248, 84,
3274 90, 81, 219, 197, 2, 1, 39, 16, 75, 229, 20, 51, 252,
3275 108, 213, 181, 183, 87, 111, 77, 232, 168, 176, 156
3276 ),
3277 42 => array(
3278 0, 225, 38, 225, 148, 192, 254, 141, 11, 82, 237,
3279 81, 24, 13, 122, 0, 106, 167, 13, 207, 160, 88,
3280 203, 38, 142, 84, 66, 3, 168, 102, 156, 1, 200,
3281 88, 60, 233, 134, 115, 114, 234, 90, 65, 138
3282 ),
3283 48 => array(
3284 0, 114, 69, 122, 30, 94, 11, 66, 230, 132, 73, 145, 137,
3285 135, 79, 214, 33, 12, 220, 142, 213, 136, 124, 215, 166,
3286 9, 222, 28, 154, 132, 4, 100, 170, 145, 59, 164, 215, 17,
3287 249, 102, 249, 134, 128, 5, 245, 131, 127, 221, 156
3288 ),
3289 56 => array(
3290 0, 29, 179, 99, 149, 159, 72, 125, 22, 55, 60, 217,
3291 176, 156, 90, 43, 80, 251, 235, 128, 169, 254, 134,
3292 249, 42, 121, 118, 72, 128, 129, 232, 37, 15, 24, 221,
3293 143, 115, 131, 40, 113, 254, 19, 123, 246, 68, 166,
3294 66, 118, 142, 47, 51, 195, 242, 249, 131, 38, 66
3295 ),
3296 62 => array(
3297 0, 182, 133, 162, 126, 236, 58, 172, 163, 53, 121, 159, 2,
3298 166, 137, 234, 158, 195, 164, 77, 228, 226, 145, 91, 180,
3299 232, 23, 241, 132, 135, 206, 184, 14, 6, 66, 238, 83, 100,
3300 111, 85, 202, 91, 156, 68, 218, 57, 83, 222, 188, 25, 179,
3301 144, 169, 164, 82, 154, 103, 89, 42, 141, 175, 32, 168
3302 ),
3303 68 => array(
3304 0, 33, 79, 190, 245, 91, 221, 233, 25, 24, 6, 144,
3305 151, 121, 186, 140, 127, 45, 153, 250, 183, 70, 131,
3306 198, 17, 89, 245, 121, 51, 140, 252, 203, 82, 83, 233,
3307 152, 220, 155, 18, 230, 210, 94, 32, 200, 197, 192,
3308 194, 202, 129, 10, 237, 198, 94, 176, 36, 40, 139,
3309 201, 132, 219, 34, 56, 113, 52, 20, 34, 247, 15, 51
3310 ),
3311 );
3312
3313 private $dmtx_log = array(
3314 0, 0, 1, 240, 2, 225, 241, 53,
3315 3, 38, 226, 133, 242, 43, 54, 210,
3316 4, 195, 39, 114, 227, 106, 134, 28,
3317 243, 140, 44, 23, 55, 118, 211, 234,
3318 5, 219, 196, 96, 40, 222, 115, 103,
3319 228, 78, 107, 125, 135, 8, 29, 162,
3320 244, 186, 141, 180, 45, 99, 24, 49,
3321 56, 13, 119, 153, 212, 199, 235, 91,
3322 6, 76, 220, 217, 197, 11, 97, 184,
3323 41, 36, 223, 253, 116, 138, 104, 193,
3324 229, 86, 79, 171, 108, 165, 126, 145,
3325 136, 34, 9, 74, 30, 32, 163, 84,
3326 245, 173, 187, 204, 142, 81, 181, 190,
3327 46, 88, 100, 159, 25, 231, 50, 207,
3328 57, 147, 14, 67, 120, 128, 154, 248,
3329 213, 167, 200, 63, 236, 110, 92, 176,
3330 7, 161, 77, 124, 221, 102, 218, 95,
3331 198, 90, 12, 152, 98, 48, 185, 179,
3332 42, 209, 37, 132, 224, 52, 254, 239,
3333 117, 233, 139, 22, 105, 27, 194, 113,
3334 230, 206, 87, 158, 80, 189, 172, 203,
3335 109, 175, 166, 62, 127, 247, 146, 66,
3336 137, 192, 35, 252, 10, 183, 75, 216,
3337 31, 83, 33, 73, 164, 144, 85, 170,
3338 246, 65, 174, 61, 188, 202, 205, 157,
3339 143, 169, 82, 72, 182, 215, 191, 251,
3340 47, 178, 89, 151, 101, 94, 160, 123,
3341 26, 112, 232, 21, 51, 238, 208, 131,
3342 58, 69, 148, 18, 15, 16, 68, 17,
3343 121, 149, 129, 19, 155, 59, 249, 70,
3344 214, 250, 168, 71, 201, 156, 64, 60,
3345 237, 130, 111, 20, 93, 122, 177, 150,
3346 );
3347
3348 private $dmtx_exp = array(
3349 1, 2, 4, 8, 16, 32, 64, 128,
3350 45, 90, 180, 69, 138, 57, 114, 228,
3351 229, 231, 227, 235, 251, 219, 155, 27,
3352 54, 108, 216, 157, 23, 46, 92, 184,
3353 93, 186, 89, 178, 73, 146, 9, 18,
3354 36, 72, 144, 13, 26, 52, 104, 208,
3355 141, 55, 110, 220, 149, 7, 14, 28,
3356 56, 112, 224, 237, 247, 195, 171, 123,
3357 246, 193, 175, 115, 230, 225, 239, 243,
3358 203, 187, 91, 182, 65, 130, 41, 82,
3359 164, 101, 202, 185, 95, 190, 81, 162,
3360 105, 210, 137, 63, 126, 252, 213, 135,
3361 35, 70, 140, 53, 106, 212, 133, 39,
3362 78, 156, 21, 42, 84, 168, 125, 250,
3363 217, 159, 19, 38, 76, 152, 29, 58,
3364 116, 232, 253, 215, 131, 43, 86, 172,
3365 117, 234, 249, 223, 147, 11, 22, 44,
3366 88, 176, 77, 154, 25, 50, 100, 200,
3367 189, 87, 174, 113, 226, 233, 255, 211,
3368 139, 59, 118, 236, 245, 199, 163, 107,
3369 214, 129, 47, 94, 188, 85, 170, 121,
3370 242, 201, 191, 83, 166, 97, 194, 169,
3371 127, 254, 209, 143, 51, 102, 204, 181,
3372 71, 142, 49, 98, 196, 165, 103, 206,
3373 177, 79, 158, 17, 34, 68, 136, 61,
3374 122, 244, 197, 167, 99, 198, 161, 111,
3375 222, 145, 15, 30, 60, 120, 240, 205,
3376 183, 67, 134, 33, 66, 132, 37, 74,
3377 148, 5, 10, 20, 40, 80, 160, 109,
3378 218, 153, 31, 62, 124, 248, 221, 151,
3379 3, 6, 12, 24, 48, 96, 192, 173,
3380 119, 238, 241, 207, 179, 75, 150, 1,
3381 );
3382
3383}
$index['name']
Definition .dd.php:162
output_image($format, $symbology, $data, $options)
render_image($symbology, $data, $options)
get_image_html($format, $symbology, $data, $options)
render_svg($symbology, $data, $options)