fastqr 1.0.20 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/BUILD.md +10 -74
- data/CHANGELOG.md +1 -1
- data/CMakeLists.txt +1 -1
- data/DISTRIBUTION.md +14 -14
- data/INSTALL.md +4 -4
- data/LICENSE +1 -3
- data/PREBUILT.md +3 -3
- data/README.md +285 -149
- data/VERSION +1 -1
- data/bindings/nodejs/README.md +448 -0
- data/bindings/nodejs/package.json +1 -2
- data/bindings/php/src/FastQR.php +89 -127
- data/bindings/ruby/extconf.rb +4 -4
- data/bindings/ruby/lib/fastqr/version.rb +1 -1
- data/bindings/ruby/prebuilt/linux-aarch64/bin/fastqr +0 -0
- data/bindings/ruby/prebuilt/linux-aarch64.tar.gz +0 -0
- data/bindings/ruby/prebuilt/linux-x86_64/bin/fastqr +0 -0
- data/bindings/ruby/prebuilt/linux-x86_64.tar.gz +0 -0
- data/bindings/ruby/prebuilt/macos-arm64/bin/fastqr +0 -0
- data/bindings/ruby/prebuilt/macos-arm64.tar.gz +0 -0
- data/bindings/ruby/prebuilt/macos-x86_64/bin/fastqr +0 -0
- data/bindings/ruby/prebuilt/macos-x86_64.tar.gz +0 -0
- data/build.sh +5 -5
- data/composer.json +1 -2
- data/docs/NODEJS_USAGE.md +2 -2
- data/docs/README.md +5 -4
- data/prebuilt/README.md +5 -6
- data/src/fastqr.cpp +2 -44
- metadata +5 -4
data/bindings/php/src/FastQR.php
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* FastQR - Fast QR Code Generator
|
|
5
|
-
* PHP Binding using FFI
|
|
5
|
+
* PHP Binding using CLI binary (no FFI needed!)
|
|
6
6
|
*
|
|
7
7
|
* Copyright (C) 2025 FastQR Project
|
|
8
8
|
* Licensed under LGPL-2.1
|
|
@@ -10,21 +10,19 @@
|
|
|
10
10
|
|
|
11
11
|
namespace FastQR;
|
|
12
12
|
|
|
13
|
-
use FFI;
|
|
14
13
|
use RuntimeException;
|
|
15
14
|
|
|
16
15
|
class FastQR
|
|
17
16
|
{
|
|
18
|
-
private static ?
|
|
19
|
-
private static bool $initialized = false;
|
|
17
|
+
private static ?string $cliPath = null;
|
|
20
18
|
|
|
21
19
|
/**
|
|
22
|
-
*
|
|
20
|
+
* Find CLI binary
|
|
23
21
|
*/
|
|
24
|
-
private static function
|
|
22
|
+
private static function findBinary(): string
|
|
25
23
|
{
|
|
26
|
-
if (self::$
|
|
27
|
-
return;
|
|
24
|
+
if (self::$cliPath !== null) {
|
|
25
|
+
return self::$cliPath;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
// Detect platform
|
|
@@ -33,58 +31,30 @@ class FastQR
|
|
|
33
31
|
if ($arch === 'x86_64' || $arch === 'amd64') {
|
|
34
32
|
$arch = 'x86_64';
|
|
35
33
|
} elseif ($arch === 'aarch64' || $arch === 'arm64') {
|
|
36
|
-
$arch = 'arm64';
|
|
34
|
+
$arch = $os === 'macos' ? 'arm64' : 'aarch64';
|
|
37
35
|
}
|
|
38
36
|
$platform = "$os-$arch";
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'/usr/
|
|
45
|
-
'/
|
|
46
|
-
__DIR__ . '/../../../build/libfastqr.' . $ext, // Local build
|
|
37
|
+
|
|
38
|
+
// Try to find the binary (pre-built first, then system)
|
|
39
|
+
$binaryPaths = [
|
|
40
|
+
__DIR__ . "/../../prebuilt/$platform/bin/fastqr", // Pre-built binary
|
|
41
|
+
'/usr/local/bin/fastqr', // System install
|
|
42
|
+
'/usr/bin/fastqr',
|
|
43
|
+
__DIR__ . '/../../../build/fastqr', // Local build
|
|
47
44
|
];
|
|
48
45
|
|
|
49
|
-
$
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
break;
|
|
46
|
+
foreach ($binaryPaths as $path) {
|
|
47
|
+
if (file_exists($path) && is_executable($path)) {
|
|
48
|
+
self::$cliPath = $path;
|
|
49
|
+
return $path;
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Define C interface
|
|
65
|
-
$header = '
|
|
66
|
-
typedef struct {
|
|
67
|
-
int size;
|
|
68
|
-
int optimize_size;
|
|
69
|
-
unsigned char foreground_r;
|
|
70
|
-
unsigned char foreground_g;
|
|
71
|
-
unsigned char foreground_b;
|
|
72
|
-
unsigned char background_r;
|
|
73
|
-
unsigned char background_g;
|
|
74
|
-
unsigned char background_b;
|
|
75
|
-
int ec_level;
|
|
76
|
-
const char* logo_path;
|
|
77
|
-
int logo_size_percent;
|
|
78
|
-
const char* format;
|
|
79
|
-
int quality;
|
|
80
|
-
} QROptions;
|
|
81
|
-
|
|
82
|
-
bool fastqr_generate(const char* data, const char* output_path, QROptions* options);
|
|
83
|
-
const char* fastqr_version(void);
|
|
84
|
-
';
|
|
85
|
-
|
|
86
|
-
self::$ffi = FFI::cdef($header, $libPath);
|
|
87
|
-
self::$initialized = true;
|
|
53
|
+
throw new RuntimeException(
|
|
54
|
+
"FastQR CLI binary not found for platform: $platform\n" .
|
|
55
|
+
"Searched in:\n" . implode("\n", $binaryPaths) . "\n" .
|
|
56
|
+
"Please install fastqr or build from source."
|
|
57
|
+
);
|
|
88
58
|
}
|
|
89
59
|
|
|
90
60
|
/**
|
|
@@ -127,8 +97,6 @@ class FastQR
|
|
|
127
97
|
*/
|
|
128
98
|
public static function generate(string $data, string $outputPath, array $options = []): bool
|
|
129
99
|
{
|
|
130
|
-
self::init();
|
|
131
|
-
|
|
132
100
|
if (empty($data)) {
|
|
133
101
|
throw new RuntimeException('Data cannot be empty');
|
|
134
102
|
}
|
|
@@ -136,56 +104,64 @@ class FastQR
|
|
|
136
104
|
throw new RuntimeException('Output path cannot be empty');
|
|
137
105
|
}
|
|
138
106
|
|
|
139
|
-
|
|
140
|
-
|
|
107
|
+
$cliPath = self::findBinary();
|
|
108
|
+
|
|
109
|
+
// Build command arguments
|
|
110
|
+
$args = [
|
|
111
|
+
escapeshellarg($cliPath),
|
|
112
|
+
escapeshellarg($data),
|
|
113
|
+
escapeshellarg($outputPath)
|
|
114
|
+
];
|
|
141
115
|
|
|
142
116
|
// Size (preferred) or width/height (backward compatibility)
|
|
143
117
|
if (isset($options['size'])) {
|
|
144
|
-
$
|
|
118
|
+
$args[] = '-s ' . (int)$options['size'];
|
|
145
119
|
} elseif (isset($options['width']) || isset($options['height'])) {
|
|
146
|
-
$
|
|
147
|
-
|
|
148
|
-
$opts->size = 300;
|
|
120
|
+
$size = $options['width'] ?? $options['height'] ?? 300;
|
|
121
|
+
$args[] = '-s ' . (int)$size;
|
|
149
122
|
}
|
|
150
123
|
|
|
151
124
|
// Optimize size
|
|
152
|
-
|
|
125
|
+
if (!empty($options['optimizeSize'])) {
|
|
126
|
+
$args[] = '-o';
|
|
127
|
+
}
|
|
153
128
|
|
|
154
129
|
// Foreground color
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
130
|
+
if (isset($options['foreground'])) {
|
|
131
|
+
$fg = $options['foreground'];
|
|
132
|
+
$args[] = '-f ' . implode(',', $fg);
|
|
133
|
+
}
|
|
159
134
|
|
|
160
135
|
// Background color
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
136
|
+
if (isset($options['background'])) {
|
|
137
|
+
$bg = $options['background'];
|
|
138
|
+
$args[] = '-b ' . implode(',', $bg);
|
|
139
|
+
}
|
|
165
140
|
|
|
166
141
|
// Error correction level
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
'M' => 1,
|
|
171
|
-
'Q' => 2,
|
|
172
|
-
'H' => 3,
|
|
173
|
-
default => 1
|
|
174
|
-
};
|
|
142
|
+
if (isset($options['errorLevel'])) {
|
|
143
|
+
$args[] = '-e ' . escapeshellarg($options['errorLevel']);
|
|
144
|
+
}
|
|
175
145
|
|
|
176
146
|
// Logo
|
|
177
|
-
|
|
178
|
-
|
|
147
|
+
if (isset($options['logo'])) {
|
|
148
|
+
$args[] = '-l ' . escapeshellarg($options['logo']);
|
|
149
|
+
}
|
|
150
|
+
if (isset($options['logoSize'])) {
|
|
151
|
+
$args[] = '-p ' . (int)$options['logoSize'];
|
|
152
|
+
}
|
|
179
153
|
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
154
|
+
// Quality
|
|
155
|
+
if (isset($options['quality'])) {
|
|
156
|
+
$args[] = '-q ' . (int)$options['quality'];
|
|
157
|
+
}
|
|
183
158
|
|
|
184
|
-
//
|
|
185
|
-
$
|
|
159
|
+
// Execute command
|
|
160
|
+
$cmd = implode(' ', $args) . ' 2>&1';
|
|
161
|
+
exec($cmd, $output, $returnCode);
|
|
186
162
|
|
|
187
|
-
if (
|
|
188
|
-
throw new RuntimeException('Failed to generate QR code');
|
|
163
|
+
if ($returnCode !== 0) {
|
|
164
|
+
throw new RuntimeException('Failed to generate QR code: ' . implode("\n", $output));
|
|
189
165
|
}
|
|
190
166
|
|
|
191
167
|
return true;
|
|
@@ -198,8 +174,15 @@ class FastQR
|
|
|
198
174
|
*/
|
|
199
175
|
public static function version(): string
|
|
200
176
|
{
|
|
201
|
-
self::
|
|
202
|
-
|
|
177
|
+
$cliPath = self::findBinary();
|
|
178
|
+
$cmd = escapeshellarg($cliPath) . ' -v 2>&1';
|
|
179
|
+
$output = shell_exec($cmd);
|
|
180
|
+
|
|
181
|
+
if ($output === null) {
|
|
182
|
+
return 'unknown';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return trim(str_replace('FastQR v', '', $output));
|
|
203
186
|
}
|
|
204
187
|
|
|
205
188
|
/**
|
|
@@ -241,65 +224,45 @@ class FastQR
|
|
|
241
224
|
try {
|
|
242
225
|
file_put_contents($tempFile, implode("\n", $dataArray));
|
|
243
226
|
|
|
244
|
-
|
|
245
|
-
$os = PHP_OS_FAMILY === 'Darwin' ? 'macos' : (PHP_OS_FAMILY === 'Linux' ? 'linux' : 'unknown');
|
|
246
|
-
$arch = php_uname('m');
|
|
247
|
-
if ($arch === 'x86_64' || $arch === 'amd64') {
|
|
248
|
-
$arch = 'x86_64';
|
|
249
|
-
} elseif ($arch === 'aarch64' || $arch === 'arm64') {
|
|
250
|
-
$arch = 'arm64';
|
|
251
|
-
}
|
|
252
|
-
$platform = "$os-$arch";
|
|
253
|
-
|
|
254
|
-
$cliPaths = [
|
|
255
|
-
__DIR__ . "/../../prebuilt/$platform/bin/fastqr",
|
|
256
|
-
'/usr/local/bin/fastqr',
|
|
257
|
-
__DIR__ . '/../../../build/fastqr',
|
|
258
|
-
];
|
|
259
|
-
|
|
260
|
-
$cliPath = null;
|
|
261
|
-
foreach ($cliPaths as $path) {
|
|
262
|
-
if (file_exists($path)) {
|
|
263
|
-
$cliPath = $path;
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if ($cliPath === null) {
|
|
269
|
-
throw new RuntimeException("FastQR CLI not found for platform: $platform");
|
|
270
|
-
}
|
|
227
|
+
$cliPath = self::findBinary();
|
|
271
228
|
|
|
272
229
|
// Build command
|
|
273
|
-
$
|
|
230
|
+
$args = [
|
|
231
|
+
escapeshellarg($cliPath),
|
|
232
|
+
'-F',
|
|
233
|
+
escapeshellarg($tempFile),
|
|
234
|
+
escapeshellarg($outputDir)
|
|
235
|
+
];
|
|
274
236
|
|
|
275
237
|
if (isset($options['size'])) {
|
|
276
|
-
$
|
|
238
|
+
$args[] = '-s ' . (int)$options['size'];
|
|
277
239
|
}
|
|
278
240
|
if (!empty($options['optimizeSize'])) {
|
|
279
|
-
$
|
|
241
|
+
$args[] = '-o';
|
|
280
242
|
}
|
|
281
243
|
if (isset($options['foreground'])) {
|
|
282
244
|
$fg = $options['foreground'];
|
|
283
|
-
$
|
|
245
|
+
$args[] = '-f ' . implode(',', $fg);
|
|
284
246
|
}
|
|
285
247
|
if (isset($options['background'])) {
|
|
286
248
|
$bg = $options['background'];
|
|
287
|
-
$
|
|
249
|
+
$args[] = '-b ' . implode(',', $bg);
|
|
288
250
|
}
|
|
289
251
|
if (isset($options['errorLevel'])) {
|
|
290
|
-
$
|
|
252
|
+
$args[] = '-e ' . escapeshellarg($options['errorLevel']);
|
|
291
253
|
}
|
|
292
254
|
if (isset($options['logo'])) {
|
|
293
|
-
$
|
|
255
|
+
$args[] = '-l ' . escapeshellarg($options['logo']);
|
|
294
256
|
}
|
|
295
257
|
if (isset($options['logoSize'])) {
|
|
296
|
-
$
|
|
258
|
+
$args[] = '-p ' . (int)$options['logoSize'];
|
|
297
259
|
}
|
|
298
260
|
if (isset($options['quality'])) {
|
|
299
|
-
$
|
|
261
|
+
$args[] = '-q ' . (int)$options['quality'];
|
|
300
262
|
}
|
|
301
263
|
|
|
302
|
-
|
|
264
|
+
$cmd = implode(' ', $args) . ' 2>&1';
|
|
265
|
+
exec($cmd, $output, $returnCode);
|
|
303
266
|
|
|
304
267
|
if ($returnCode !== 0) {
|
|
305
268
|
throw new RuntimeException('Batch generation failed: ' . implode("\n", $output));
|
|
@@ -313,4 +276,3 @@ class FastQR
|
|
|
313
276
|
}
|
|
314
277
|
}
|
|
315
278
|
}
|
|
316
|
-
|
data/bindings/ruby/extconf.rb
CHANGED
|
@@ -64,8 +64,8 @@ unless have_library('qrencode')
|
|
|
64
64
|
abort "ERROR: libqrencode is required. Install it first."
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
unless have_library('
|
|
68
|
-
abort "ERROR:
|
|
67
|
+
unless have_library('png')
|
|
68
|
+
abort "ERROR: libpng is required. Install it first."
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# Check for headers
|
|
@@ -73,8 +73,8 @@ unless have_header('qrencode.h')
|
|
|
73
73
|
abort "ERROR: qrencode.h not found"
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
unless have_header('
|
|
77
|
-
abort "ERROR:
|
|
76
|
+
unless have_header('png.h')
|
|
77
|
+
abort "ERROR: png.h not found"
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
# Add C++14 support
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/build.sh
CHANGED
|
@@ -49,16 +49,16 @@ if ! pkg-config --exists libqrencode; then
|
|
|
49
49
|
fi
|
|
50
50
|
echo "✅ libqrencode found: $(pkg-config --modversion libqrencode)"
|
|
51
51
|
|
|
52
|
-
if ! pkg-config --exists
|
|
53
|
-
echo "❌
|
|
52
|
+
if ! pkg-config --exists libpng; then
|
|
53
|
+
echo "❌ libpng not found. Install with:"
|
|
54
54
|
if [[ "$OS" == "macos" ]]; then
|
|
55
|
-
echo " brew install
|
|
55
|
+
echo " brew install libpng"
|
|
56
56
|
else
|
|
57
|
-
echo " sudo apt-get install
|
|
57
|
+
echo " sudo apt-get install libpng-dev"
|
|
58
58
|
fi
|
|
59
59
|
exit 1
|
|
60
60
|
fi
|
|
61
|
-
echo "✅
|
|
61
|
+
echo "✅ libpng found: $(pkg-config --modversion libpng)"
|
|
62
62
|
|
|
63
63
|
# Build
|
|
64
64
|
echo ""
|
data/composer.json
CHANGED
data/docs/NODEJS_USAGE.md
CHANGED
|
@@ -5,13 +5,13 @@ Complete guide for using FastQR in Node.js and JavaScript applications.
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install fastqr
|
|
8
|
+
npm install fastqr-pro
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
Or with Yarn:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
yarn add fastqr
|
|
14
|
+
yarn add fastqr-pro
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
**Note:** No system dependencies required! Pre-built binaries are included. 🎉
|
data/docs/README.md
CHANGED
|
@@ -40,10 +40,10 @@ FastQR is a fast, powerful QR code generator with full UTF-8 support, custom col
|
|
|
40
40
|
### 📦 No Dependencies!
|
|
41
41
|
Starting from v1.0.0, all language packages include pre-built binaries:
|
|
42
42
|
- Ruby: `gem install fastqr` ✅
|
|
43
|
-
- Node.js: `npm install fastqr` ✅
|
|
43
|
+
- Node.js: `npm install fastqr-pro` ✅
|
|
44
44
|
- PHP: `composer require fastqr/fastqr` ✅
|
|
45
45
|
|
|
46
|
-
No need to install libqrencode
|
|
46
|
+
No need to install libqrencode separately!
|
|
47
47
|
|
|
48
48
|
## Quick Start
|
|
49
49
|
|
|
@@ -69,7 +69,7 @@ FastQR.generate("Hello World", "qr.png", width: 500, height: 500)
|
|
|
69
69
|
|
|
70
70
|
### Node.js
|
|
71
71
|
```javascript
|
|
72
|
-
npm install fastqr
|
|
72
|
+
npm install fastqr-pro
|
|
73
73
|
|
|
74
74
|
const fastqr = require('fastqr');
|
|
75
75
|
fastqr.generate('Hello World', 'qr.png', { width: 500, height: 500 });
|
|
@@ -160,7 +160,8 @@ fastqr -s 2000x2000 -q 100 -e H "SKU-12345" product_qr.png
|
|
|
160
160
|
|
|
161
161
|
FastQR is built on:
|
|
162
162
|
- **[libqrencode](https://fukuchi.org/works/qrencode/)** (LGPL v2.1) - QR code generation
|
|
163
|
-
- **[
|
|
163
|
+
- **[libpng](http://www.libpng.org/pub/png/libpng.html)** - PNG image encoding
|
|
164
|
+
- **[stb_image](https://github.com/nothings/stb)** (Public Domain) - Image loading
|
|
164
165
|
|
|
165
166
|
Pre-built binaries are automatically generated for:
|
|
166
167
|
- macOS (Intel & Apple Silicon)
|
data/prebuilt/README.md
CHANGED
|
@@ -48,7 +48,7 @@ Pre-built binaries are automatically included in the gem and loaded via FFI.
|
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
50
|
gem install fastqr
|
|
51
|
-
# No need to install qrencode
|
|
51
|
+
# No need to install qrencode!
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
### For Node.js
|
|
@@ -56,8 +56,8 @@ gem install fastqr
|
|
|
56
56
|
Pre-built binaries are automatically included in the npm package.
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
npm install fastqr
|
|
60
|
-
# No need to install qrencode
|
|
59
|
+
npm install fastqr-pro
|
|
60
|
+
# No need to install qrencode!
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
### For PHP
|
|
@@ -66,7 +66,7 @@ Pre-built binaries are included in the Composer package.
|
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
68
|
composer require fastqr/fastqr
|
|
69
|
-
# No need to install qrencode
|
|
69
|
+
# No need to install qrencode!
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
### Manual Installation
|
|
@@ -105,7 +105,7 @@ The bindings automatically detect your platform and load the appropriate binary:
|
|
|
105
105
|
|
|
106
106
|
## Notes
|
|
107
107
|
|
|
108
|
-
- Binaries are built with static linking of libqrencode
|
|
108
|
+
- Binaries are built with static linking of libqrencode
|
|
109
109
|
- No external dependencies required at runtime
|
|
110
110
|
- Binaries are built on GitHub Actions for consistency
|
|
111
111
|
- All binaries are tested before release
|
|
@@ -125,7 +125,6 @@ This will trigger the `build-binaries.yml` workflow which builds for all platfor
|
|
|
125
125
|
|
|
126
126
|
The pre-built binaries include statically linked libraries:
|
|
127
127
|
- libqrencode (LGPL 2.1)
|
|
128
|
-
- libvips (LGPL 2.1+)
|
|
129
128
|
|
|
130
129
|
As required by LGPL, users can rebuild with different versions. See BUILD.md for instructions.
|
|
131
130
|
|
data/src/fastqr.cpp
CHANGED
|
@@ -20,12 +20,8 @@
|
|
|
20
20
|
#include <vector>
|
|
21
21
|
#include <algorithm>
|
|
22
22
|
#include <cstdio>
|
|
23
|
-
#include <chrono>
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
// #define FASTQR_BENCHMARK
|
|
27
|
-
|
|
28
|
-
#define FASTQR_VERSION "1.0.20"
|
|
24
|
+
#define FASTQR_VERSION "1.0.22"
|
|
29
25
|
|
|
30
26
|
namespace fastqr {
|
|
31
27
|
|
|
@@ -343,21 +339,12 @@ static void add_logo_to_image(std::vector<unsigned char>& qr_img, int qr_size, i
|
|
|
343
339
|
}
|
|
344
340
|
|
|
345
341
|
bool generate(const std::string& data, const std::string& output_path, const QROptions& options) {
|
|
346
|
-
#ifdef FASTQR_BENCHMARK
|
|
347
|
-
auto t_start = std::chrono::high_resolution_clock::now();
|
|
348
|
-
#endif
|
|
349
|
-
|
|
350
342
|
// Generate QR code
|
|
351
343
|
auto qr = generate_qr_code(data, options.ec_level);
|
|
352
344
|
if (!qr) {
|
|
353
345
|
return false;
|
|
354
346
|
}
|
|
355
347
|
|
|
356
|
-
#ifdef FASTQR_BENCHMARK
|
|
357
|
-
auto t_qr_gen = std::chrono::high_resolution_clock::now();
|
|
358
|
-
auto dur_qr = std::chrono::duration_cast<std::chrono::microseconds>(t_qr_gen - t_start).count();
|
|
359
|
-
#endif
|
|
360
|
-
|
|
361
348
|
int qr_size = qr->width;
|
|
362
349
|
unsigned char* qr_data = qr->data;
|
|
363
350
|
|
|
@@ -381,15 +368,6 @@ bool generate(const std::string& data, const std::string& output_path, const QRO
|
|
|
381
368
|
// Pack 8 pixels into 1 byte
|
|
382
369
|
int scale = final_size / qr_size;
|
|
383
370
|
|
|
384
|
-
#ifdef FASTQR_BENCHMARK
|
|
385
|
-
FILE* debug_log = fopen("/tmp/fastqr_debug.log", "a");
|
|
386
|
-
if (debug_log) {
|
|
387
|
-
fprintf(debug_log, "DEBUG: is_bw=%d, qr_size=%d, final_size=%d, scale=%d, scale*qr=%d\n",
|
|
388
|
-
is_bw, qr_size, final_size, scale, scale*qr_size);
|
|
389
|
-
fclose(debug_log);
|
|
390
|
-
}
|
|
391
|
-
#endif
|
|
392
|
-
|
|
393
371
|
if (scale * qr_size == final_size) {
|
|
394
372
|
// Integer scaling - optimized bit packing
|
|
395
373
|
int bytes_per_row = (final_size + 7) / 8;
|
|
@@ -424,27 +402,7 @@ bool generate(const std::string& data, const std::string& output_path, const QRO
|
|
|
424
402
|
}
|
|
425
403
|
}
|
|
426
404
|
|
|
427
|
-
|
|
428
|
-
auto t_scale = std::chrono::high_resolution_clock::now();
|
|
429
|
-
auto dur_scale = std::chrono::duration_cast<std::chrono::microseconds>(t_scale - t_qr_gen).count();
|
|
430
|
-
#endif
|
|
431
|
-
|
|
432
|
-
bool result = write_indexed_png(output_path.c_str(), packed_data, final_size, final_size);
|
|
433
|
-
|
|
434
|
-
#ifdef FASTQR_BENCHMARK
|
|
435
|
-
auto t_write = std::chrono::high_resolution_clock::now();
|
|
436
|
-
auto dur_write = std::chrono::duration_cast<std::chrono::microseconds>(t_write - t_scale).count();
|
|
437
|
-
auto dur_total = std::chrono::duration_cast<std::chrono::microseconds>(t_write - t_start).count();
|
|
438
|
-
|
|
439
|
-
FILE* timing_log = fopen("/tmp/fastqr_timing.log", "a");
|
|
440
|
-
if (timing_log) {
|
|
441
|
-
fprintf(timing_log, "TIMING: QR=%ldus, Scale=%ldus, Write=%ldus, Total=%ldus\n",
|
|
442
|
-
dur_qr, dur_scale, dur_write, dur_total);
|
|
443
|
-
fclose(timing_log);
|
|
444
|
-
}
|
|
445
|
-
#endif
|
|
446
|
-
|
|
447
|
-
return result;
|
|
405
|
+
return write_indexed_png(output_path.c_str(), packed_data, final_size, final_size);
|
|
448
406
|
} else {
|
|
449
407
|
// Non-integer scaling - use grayscale
|
|
450
408
|
std::vector<unsigned char> final_image(final_size * final_size);
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fastqr
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.22
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- FastQR Project
|
|
@@ -52,8 +52,8 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '5.0'
|
|
55
|
-
description:
|
|
56
|
-
|
|
55
|
+
description: Generate 1,000 QR codes in **0.37 seconds**. Full UTF-8 support. Custom
|
|
56
|
+
colors. Logo embedding. Precise size control.
|
|
57
57
|
email:
|
|
58
58
|
- fastqr@example.com
|
|
59
59
|
executables: []
|
|
@@ -71,6 +71,7 @@ files:
|
|
|
71
71
|
- PREBUILT.md
|
|
72
72
|
- README.md
|
|
73
73
|
- VERSION
|
|
74
|
+
- bindings/nodejs/README.md
|
|
74
75
|
- bindings/nodejs/index.d.ts
|
|
75
76
|
- bindings/nodejs/index.js
|
|
76
77
|
- bindings/nodejs/lib/platform.js
|
|
@@ -158,5 +159,5 @@ requirements: []
|
|
|
158
159
|
rubygems_version: 3.4.19
|
|
159
160
|
signing_key:
|
|
160
161
|
specification_version: 4
|
|
161
|
-
summary:
|
|
162
|
+
summary: The fastest QR code generator on the planet.
|
|
162
163
|
test_files: []
|