Issues (4542)

config/qrcode/qrspec.php (2 issues)

1
<?php
2
/*
3
 * PHP QR Code encoder
4
 *
5
 * QR Code specifications
6
 *
7
 * Based on libqrencode C library distributed under LGPL 2.1
8
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
9
 *
10
 * PHP QR Code is distributed under LGPL 3
11
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
12
 *
13
 * The following data / specifications are taken from
14
 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
15
 *  or
16
 * "Automatic identification and data capture techniques --
17
 *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
18
 *
19
 * This library is free software; you can redistribute it and/or
20
 * modify it under the terms of the GNU Lesser General Public
21
 * License as published by the Free Software Foundation; either
22
 * version 3 of the License, or any later version.
23
 *
24
 * This library is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27
 * Lesser General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU Lesser General Public
30
 * License along with this library; if not, write to the Free Software
31
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32
 */
33
34
    define('QRSPEC_VERSION_MAX', 40);
35
    define('QRSPEC_WIDTH_MAX', 177);
36
37
    define('QRCAP_WIDTH', 0);
38
    define('QRCAP_WORDS', 1);
39
    define('QRCAP_REMINDER', 2);
40
    define('QRCAP_EC', 3);
41
42
    class qrspec
43
    {
44
        public static $capacity = [
45
            [0, 0, 0, [0, 0, 0, 0]],
46
            [21, 26, 0, [7, 10, 13, 17]], // 1
47
            [25, 44, 7, [10, 16, 22, 28]],
48
            [29, 70, 7, [15, 26, 36, 44]],
49
            [33, 100, 7, [20, 36, 52, 64]],
50
            [37, 134, 7, [26, 48, 72, 88]], // 5
51
            [41, 172, 7, [36, 64, 96, 112]],
52
            [45, 196, 0, [40, 72, 108, 130]],
53
            [49, 242, 0, [48, 88, 132, 156]],
54
            [53, 292, 0, [60, 110, 160, 192]],
55
            [57, 346, 0, [72, 130, 192, 224]], //10
56
            [61, 404, 0, [80, 150, 224, 264]],
57
            [65, 466, 0, [96, 176, 260, 308]],
58
            [69, 532, 0, [104, 198, 288, 352]],
59
            [73, 581, 3, [120, 216, 320, 384]],
60
            [77, 655, 3, [132, 240, 360, 432]], //15
61
            [81, 733, 3, [144, 280, 408, 480]],
62
            [85, 815, 3, [168, 308, 448, 532]],
63
            [89, 901, 3, [180, 338, 504, 588]],
64
            [93, 991, 3, [196, 364, 546, 650]],
65
            [97, 1085, 3, [224, 416, 600, 700]], //20
66
            [101, 1156, 4, [224, 442, 644, 750]],
67
            [105, 1258, 4, [252, 476, 690, 816]],
68
            [109, 1364, 4, [270, 504, 750, 900]],
69
            [113, 1474, 4, [300, 560, 810, 960]],
70
            [117, 1588, 4, [312, 588, 870, 1050]], //25
71
            [121, 1706, 4, [336, 644, 952, 1110]],
72
            [125, 1828, 4, [360, 700, 1020, 1200]],
73
            [129, 1921, 3, [390, 728, 1050, 1260]],
74
            [133, 2051, 3, [420, 784, 1140, 1350]],
75
            [137, 2185, 3, [450, 812, 1200, 1440]], //30
76
            [141, 2323, 3, [480, 868, 1290, 1530]],
77
            [145, 2465, 3, [510, 924, 1350, 1620]],
78
            [149, 2611, 3, [540, 980, 1440, 1710]],
79
            [153, 2761, 3, [570, 1036, 1530, 1800]],
80
            [157, 2876, 0, [570, 1064, 1590, 1890]], //35
81
            [161, 3034, 0, [600, 1120, 1680, 1980]],
82
            [165, 3196, 0, [630, 1204, 1770, 2100]],
83
            [169, 3362, 0, [660, 1260, 1860, 2220]],
84
            [173, 3532, 0, [720, 1316, 1950, 2310]],
85
            [177, 3706, 0, [750, 1372, 2040, 2430]], //40
86
        ];
87
88
        //----------------------------------------------------------------------
89
        public static function getDataLength($version, $level)
90
        {
91
            return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
92
        }
93
94
        //----------------------------------------------------------------------
95
        public static function getECCLength($version, $level)
96
        {
97
            return self::$capacity[$version][QRCAP_EC][$level];
98
        }
99
100
        //----------------------------------------------------------------------
101
        public static function getWidth($version)
102
        {
103
            return self::$capacity[$version][QRCAP_WIDTH];
104
        }
105
106
        //----------------------------------------------------------------------
107
        public static function getRemainder($version)
108
        {
109
            return self::$capacity[$version][QRCAP_REMINDER];
110
        }
111
112
        //----------------------------------------------------------------------
113
        public static function getMinimumVersion($size, $level)
114
        {
115
            for ($i = 1; $i <= QRSPEC_VERSION_MAX; $i++) {
116
                $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
117
                if ($words >= $size) {
118
                    return $i;
119
                }
120
            }
121
122
            return -1;
123
        }
124
125
        //######################################################################
126
127
        public static $lengthTableBits = [
128
            [10, 12, 14],
129
            [9, 11, 13],
130
            [8, 16, 16],
131
            [8, 10, 12],
132
        ];
133
134
        //----------------------------------------------------------------------
135
        public static function lengthIndicator($mode, $version)
136
        {
137
            if ($mode == QR_MODE_STRUCTURE) {
138
                return 0;
139
            }
140
141
            if ($version <= 9) {
142
                $l = 0;
143
            } elseif ($version <= 26) {
144
                $l = 1;
145
            } else {
146
                $l = 2;
147
            }
148
149
            return self::$lengthTableBits[$mode][$l];
150
        }
151
152
        //----------------------------------------------------------------------
153
        public static function maximumWords($mode, $version)
154
        {
155
            if ($mode == QR_MODE_STRUCTURE) {
156
                return 3;
157
            }
158
159
            if ($version <= 9) {
160
                $l = 0;
161
            } elseif ($version <= 26) {
162
                $l = 1;
163
            } else {
164
                $l = 2;
165
            }
166
167
            $bits = self::$lengthTableBits[$mode][$l];
168
            $words = (1 << $bits) - 1;
169
170
            if ($mode == QR_MODE_KANJI) {
171
                $words *= 2; // the number of bytes is required
172
            }
173
174
            return $words;
175
        }
176
177
        // Error correction code -----------------------------------------------
178
        // Table of the error correction code (Reed-Solomon block)
179
        // See Table 12-16 (pp.30-36), JIS X0510:2004.
180
181
        public static $eccTable = [
182
            [[0, 0], [0, 0], [0, 0], [0, 0]],
183
            [[1, 0], [1, 0], [1, 0], [1, 0]], // 1
184
            [[1, 0], [1, 0], [1, 0], [1, 0]],
185
            [[1, 0], [1, 0], [2, 0], [2, 0]],
186
            [[1, 0], [2, 0], [2, 0], [4, 0]],
187
            [[1, 0], [2, 0], [2, 2], [2, 2]], // 5
188
            [[2, 0], [4, 0], [4, 0], [4, 0]],
189
            [[2, 0], [4, 0], [2, 4], [4, 1]],
190
            [[2, 0], [2, 2], [4, 2], [4, 2]],
191
            [[2, 0], [3, 2], [4, 4], [4, 4]],
192
            [[2, 2], [4, 1], [6, 2], [6, 2]], //10
193
            [[4, 0], [1, 4], [4, 4], [3, 8]],
194
            [[2, 2], [6, 2], [4, 6], [7, 4]],
195
            [[4, 0], [8, 1], [8, 4], [12, 4]],
196
            [[3, 1], [4, 5], [11, 5], [11, 5]],
197
            [[5, 1], [5, 5], [5, 7], [11, 7]], //15
198
            [[5, 1], [7, 3], [15, 2], [3, 13]],
199
            [[1, 5], [10, 1], [1, 15], [2, 17]],
200
            [[5, 1], [9, 4], [17, 1], [2, 19]],
201
            [[3, 4], [3, 11], [17, 4], [9, 16]],
202
            [[3, 5], [3, 13], [15, 5], [15, 10]], //20
203
            [[4, 4], [17, 0], [17, 6], [19, 6]],
204
            [[2, 7], [17, 0], [7, 16], [34, 0]],
205
            [[4, 5], [4, 14], [11, 14], [16, 14]],
206
            [[6, 4], [6, 14], [11, 16], [30, 2]],
207
            [[8, 4], [8, 13], [7, 22], [22, 13]], //25
208
            [[10, 2], [19, 4], [28, 6], [33, 4]],
209
            [[8, 4], [22, 3], [8, 26], [12, 28]],
210
            [[3, 10], [3, 23], [4, 31], [11, 31]],
211
            [[7, 7], [21, 7], [1, 37], [19, 26]],
212
            [[5, 10], [19, 10], [15, 25], [23, 25]], //30
213
            [[13, 3], [2, 29], [42, 1], [23, 28]],
214
            [[17, 0], [10, 23], [10, 35], [19, 35]],
215
            [[17, 1], [14, 21], [29, 19], [11, 46]],
216
            [[13, 6], [14, 23], [44, 7], [59, 1]],
217
            [[12, 7], [12, 26], [39, 14], [22, 41]], //35
218
            [[6, 14], [6, 34], [46, 10], [2, 64]],
219
            [[17, 4], [29, 14], [49, 10], [24, 46]],
220
            [[4, 18], [13, 32], [48, 14], [42, 32]],
221
            [[20, 4], [40, 7], [43, 22], [10, 67]],
222
            [[19, 6], [18, 31], [34, 34], [20, 61]], //40
223
        ];
224
225
        //----------------------------------------------------------------------
226
        // CACHEABLE!!!
227
228
        public static function getEccSpec($version, $level, array &$spec)
229
        {
230
            if (count($spec) < 5) {
231
                $spec = [0, 0, 0, 0, 0];
232
            }
233
234
            $b1 = self::$eccTable[$version][$level][0];
235
            $b2 = self::$eccTable[$version][$level][1];
236
            $data = self::getDataLength($version, $level);
237
            $ecc = self::getECCLength($version, $level);
238
239
            if ($b2 == 0) {
240
                $spec[0] = $b1;
241
                $spec[1] = (int) ($data / $b1);
242
                $spec[2] = (int) ($ecc / $b1);
243
                $spec[3] = 0;
244
                $spec[4] = 0;
245
            } else {
246
                $spec[0] = $b1;
247
                $spec[1] = (int) ($data / ($b1 + $b2));
248
                $spec[2] = (int) ($ecc / ($b1 + $b2));
249
                $spec[3] = $b2;
250
                $spec[4] = $spec[1] + 1;
251
            }
252
        }
253
254
        // Alignment pattern ---------------------------------------------------
255
256
        // Positions of alignment patterns.
257
        // This array includes only the second and the third position of the
258
        // alignment patterns. Rest of them can be calculated from the distance
259
        // between them.
260
261
        // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
262
263
        public static $alignmentPattern = [
264
            [0, 0],
265
            [0, 0], [18, 0], [22, 0], [26, 0], [30, 0], // 1- 5
266
            [34, 0], [22, 38], [24, 42], [26, 46], [28, 50], // 6-10
267
            [30, 54], [32, 58], [34, 62], [26, 46], [26, 48], //11-15
268
            [26, 50], [30, 54], [30, 56], [30, 58], [34, 62], //16-20
269
            [28, 50], [26, 50], [30, 54], [28, 54], [32, 58], //21-25
270
            [30, 58], [34, 62], [26, 50], [30, 54], [26, 52], //26-30
271
            [30, 56], [34, 60], [30, 58], [34, 62], [30, 54], //31-35
272
            [24, 50], [28, 54], [32, 58], [26, 54], [30, 58], //35-40
273
        ];
274
275
        /** --------------------------------------------------------------------
276
         * Put an alignment marker.
277
         *
278
         * @param frame
279
         * @param width
280
         * @param ox,oy     center coordinate of the pattern
0 ignored issues
show
The type center was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
281
         */
282
        public static function putAlignmentMarker(array &$frame, $ox, $oy)
283
        {
284
            $finder = [
285
                "\xa1\xa1\xa1\xa1\xa1",
286
                "\xa1\xa0\xa0\xa0\xa1",
287
                "\xa1\xa0\xa1\xa0\xa1",
288
                "\xa1\xa0\xa0\xa0\xa1",
289
                "\xa1\xa1\xa1\xa1\xa1",
290
            ];
291
292
            $yStart = $oy - 2;
293
            $xStart = $ox - 2;
294
295
            for ($y = 0; $y < 5; $y++) {
296
                QRstr::set($frame, $xStart, $yStart + $y, $finder[$y]);
297
            }
298
        }
299
300
        //----------------------------------------------------------------------
301
        public static function putAlignmentPattern($version, &$frame, $width)
302
        {
303
            if ($version < 2) {
304
                return;
305
            }
306
307
            $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
308
            if ($d < 0) {
309
                $w = 2;
310
            } else {
311
                $w = (int) (($width - self::$alignmentPattern[$version][0]) / $d + 2);
312
            }
313
314
            if ($w * $w - 3 == 1) {
315
                $x = self::$alignmentPattern[$version][0];
316
                $y = self::$alignmentPattern[$version][0];
317
                self::putAlignmentMarker($frame, $x, $y);
318
319
                return;
320
            }
321
322
            $cx = self::$alignmentPattern[$version][0];
323
            for ($x = 1; $x < $w - 1; $x++) {
324
                self::putAlignmentMarker($frame, 6, $cx);
325
                self::putAlignmentMarker($frame, $cx, 6);
326
                $cx += $d;
327
            }
328
329
            $cy = self::$alignmentPattern[$version][0];
330
            for ($y = 0; $y < $w - 1; $y++) {
331
                $cx = self::$alignmentPattern[$version][0];
332
                for ($x = 0; $x < $w - 1; $x++) {
333
                    self::putAlignmentMarker($frame, $cx, $cy);
334
                    $cx += $d;
335
                }
336
                $cy += $d;
337
            }
338
        }
339
340
        // Version information pattern -----------------------------------------
341
342
        // Version information pattern (BCH coded).
343
        // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
344
345
        // size: [QRSPEC_VERSION_MAX - 6]
346
347
        public static $versionPattern = [
348
            0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
349
            0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
350
            0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
351
            0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
352
            0x27541, 0x28c69,
353
        ];
354
355
        //----------------------------------------------------------------------
356
        public static function getVersionPattern($version)
357
        {
358
            if ($version < 7 || $version > QRSPEC_VERSION_MAX) {
359
                return 0;
360
            }
361
362
            return self::$versionPattern[$version - 7];
363
        }
364
365
        // Format information --------------------------------------------------
366
        // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
367
368
        public static $formatInfo = [
369
            [0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976],
370
            [0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0],
371
            [0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed],
372
            [0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b],
373
        ];
374
375
        public static function getFormatInfo($mask, $level)
376
        {
377
            if ($mask < 0 || $mask > 7) {
378
                return 0;
379
            }
380
381
            if ($level < 0 || $level > 3) {
382
                return 0;
383
            }
384
385
            return self::$formatInfo[$level][$mask];
386
        }
387
388
        // Frame ---------------------------------------------------------------
389
        // Cache of initial frames.
390
391
        public static $frames = [];
392
393
        /** --------------------------------------------------------------------
394
         * Put a finder pattern.
395
         *
396
         * @param frame
397
         * @param width
398
         * @param ox,oy  upper-left coordinate of the pattern
0 ignored issues
show
Documentation Bug introduced by
The doc comment upper-left at position 0 could not be parsed: Unknown type name 'upper-left' at position 0 in upper-left.
Loading history...
399
         */
400
        public static function putFinderPattern(&$frame, $ox, $oy)
401
        {
402
            $finder = [
403
                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
404
                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
405
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
406
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
407
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
408
                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
409
                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
410
            ];
411
412
            for ($y = 0; $y < 7; $y++) {
413
                QRstr::set($frame, $ox, $oy + $y, $finder[$y]);
414
            }
415
        }
416
417
        //----------------------------------------------------------------------
418
        public static function createFrame($version)
419
        {
420
            $width = self::$capacity[$version][QRCAP_WIDTH];
421
            $frameLine = str_repeat("\0", $width);
422
            $frame = array_fill(0, $width, $frameLine);
423
424
            // Finder pattern
425
            self::putFinderPattern($frame, 0, 0);
426
            self::putFinderPattern($frame, $width - 7, 0);
427
            self::putFinderPattern($frame, 0, $width - 7);
428
429
            // Separator
430
            $yOffset = $width - 7;
431
432
            for ($y = 0; $y < 7; $y++) {
433
                $frame[$y][7] = "\xc0";
434
                $frame[$y][$width - 8] = "\xc0";
435
                $frame[$yOffset][7] = "\xc0";
436
                $yOffset++;
437
            }
438
439
            $setPattern = str_repeat("\xc0", 8);
440
441
            QRstr::set($frame, 0, 7, $setPattern);
442
            QRstr::set($frame, $width - 8, 7, $setPattern);
443
            QRstr::set($frame, 0, $width - 8, $setPattern);
444
445
            // Format info
446
            $setPattern = str_repeat("\x84", 9);
447
            QRstr::set($frame, 0, 8, $setPattern);
448
            QRstr::set($frame, $width - 8, 8, $setPattern, 8);
449
450
            $yOffset = $width - 8;
451
452
            for ($y = 0; $y < 8; $y++, $yOffset++) {
453
                $frame[$y][8] = "\x84";
454
                $frame[$yOffset][8] = "\x84";
455
            }
456
457
            // Timing pattern
458
459
            for ($i = 1; $i < $width - 15; $i++) {
460
                $frame[6][7 + $i] = chr(0x90 | ($i & 1));
461
                $frame[7 + $i][6] = chr(0x90 | ($i & 1));
462
            }
463
464
            // Alignment pattern
465
            self::putAlignmentPattern($version, $frame, $width);
466
467
            // Version information
468
            if ($version >= 7) {
469
                $vinf = self::getVersionPattern($version);
470
471
                $v = $vinf;
472
473
                for ($x = 0; $x < 6; $x++) {
474
                    for ($y = 0; $y < 3; $y++) {
475
                        $frame[($width - 11) + $y][$x] = chr(0x88 | ($v & 1));
476
                        $v = $v >> 1;
477
                    }
478
                }
479
480
                $v = $vinf;
481
                for ($y = 0; $y < 6; $y++) {
482
                    for ($x = 0; $x < 3; $x++) {
483
                        $frame[$y][$x + ($width - 11)] = chr(0x88 | ($v & 1));
484
                        $v = $v >> 1;
485
                    }
486
                }
487
            }
488
489
            // and a little bit...
490
            $frame[$width - 8][8] = "\x81";
491
492
            return $frame;
493
        }
494
495
        //----------------------------------------------------------------------
496
        public static function debug($frame, $binary_mode = false)
497
        {
498
            if ($binary_mode) {
499
                foreach ($frame as &$frameLine) {
500
                    $frameLine = implode('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
501
                    $frameLine = implode('&#9608;&#9608;', explode('1', $frameLine));
502
                } ?>
503
                <style>
504
                    .m { background-color: white; }
505
                </style>
506
                <?php
507
                    echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
508
                echo implode('<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', $frame);
509
                echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
510
            } else {
511
                foreach ($frame as &$frameLine) {
512
                    $frameLine = implode('<span class="m">&nbsp;</span>', explode("\xc0", $frameLine));
513
                    $frameLine = implode('<span class="m">&#9618;</span>', explode("\xc1", $frameLine));
514
                    $frameLine = implode('<span class="p">&nbsp;</span>', explode("\xa0", $frameLine));
515
                    $frameLine = implode('<span class="p">&#9618;</span>', explode("\xa1", $frameLine));
516
                    $frameLine = implode('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0
517
                    $frameLine = implode('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1
518
                    $frameLine = implode('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit
519
                    $frameLine = implode('<span class="c">&nbsp;</span>', explode("\x90", $frameLine)); //clock 0
520
                    $frameLine = implode('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1
521
                    $frameLine = implode('<span class="f">&nbsp;</span>', explode("\x88", $frameLine)); //version
522
                    $frameLine = implode('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version
523
                    $frameLine = implode('&#9830;', explode("\x01", $frameLine));
524
                    $frameLine = implode('&#8901;', explode("\0", $frameLine));
525
                } ?>
526
                <style>
527
                    .p { background-color: yellow; }
528
                    .m { background-color: #00FF00; }
529
                    .s { background-color: #FF0000; }
530
                    .c { background-color: aqua; }
531
                    .x { background-color: pink; }
532
                    .f { background-color: gold; }
533
                </style>
534
                <?php
535
                echo '<pre><tt>';
536
                echo implode('<br/ >', $frame);
537
                echo '</tt></pre>';
538
            }
539
        }
540
541
        //----------------------------------------------------------------------
542
        public static function serial($frame)
543
        {
544
            return gzcompress(implode("\n", $frame), 9);
545
        }
546
547
        //----------------------------------------------------------------------
548
        public static function unserial($code)
549
        {
550
            return explode("\n", gzuncompress($code));
551
        }
552
553
        //----------------------------------------------------------------------
554
        public static function newFrame($version)
555
        {
556
            if ($version < 1 || $version > QRSPEC_VERSION_MAX) {
557
                return;
558
            }
559
560
            if (!isset(self::$frames[$version])) {
561
                $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
562
563
                if (QR_CACHEABLE) {
564
                    if (file_exists($fileName)) {
565
                        self::$frames[$version] = self::unserial(file_get_contents($fileName));
566
                    } else {
567
                        self::$frames[$version] = self::createFrame($version);
568
                        file_put_contents($fileName, self::serial(self::$frames[$version]));
569
                    }
570
                } else {
571
                    self::$frames[$version] = self::createFrame($version);
572
                }
573
            }
574
575
            if (is_null(self::$frames[$version])) {
576
                return;
577
            }
578
579
            return self::$frames[$version];
580
        }
581
582
        //----------------------------------------------------------------------
583
        public static function rsBlockNum($spec)
584
        {
585
            return $spec[0] + $spec[3];
586
        }
587
588
        public static function rsBlockNum1($spec)
589
        {
590
            return $spec[0];
591
        }
592
593
        public static function rsDataCodes1($spec)
594
        {
595
            return $spec[1];
596
        }
597
598
        public static function rsEccCodes1($spec)
599
        {
600
            return $spec[2];
601
        }
602
603
        public static function rsBlockNum2($spec)
604
        {
605
            return $spec[3];
606
        }
607
608
        public static function rsDataCodes2($spec)
609
        {
610
            return $spec[4];
611
        }
612
613
        public static function rsEccCodes2($spec)
614
        {
615
            return $spec[2];
616
        }
617
618
        public static function rsDataLength($spec)
619
        {
620
            return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);
621
        }
622
623
        public static function rsEccLength($spec)
624
        {
625
            return ($spec[0] + $spec[3]) * $spec[2];
626
        }
627
    }
628