quirc 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/ext/quirc/embed/lib/decode.c +16 -2
- data/ext/quirc/embed/lib/identify.c +65 -66
- data/ext/quirc/embed/lib/quirc.c +3 -13
- data/ext/quirc/embed/lib/quirc.h +6 -1
- data/ext/quirc/embed/lib/quirc_internal.h +2 -2
- data/ext/quirc/extconf.rb +1 -1
- data/lib/quirc/version.rb +1 -1
- data/test/test_decode.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d88ac4b65801a83205e14ffa1b9b7154bc53410dcab9110f3e397c320c415e09
|
4
|
+
data.tar.gz: 305c828b7db112e3ecff1bf7ee6a082a437c8a3cbd1292430401494847b84c13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19d8b284668492e248faf07f6c68ce23c873f38d0d2b1242157b59f41332107e4ec5886c8e5d8f50f3bf5b34b2b25eef29d1b803b15001b67fd64eefb40537a1
|
7
|
+
data.tar.gz: 29fee645c7acdedf4f242c6138164641ae79109e57de7950d0ccdb729744eead0a0354f0f2e0240098266bc76024098027244c0e7c524cf4696652db8cad53e2
|
data/LICENSE
CHANGED
@@ -409,7 +409,6 @@ struct datastream {
|
|
409
409
|
static inline int grid_bit(const struct quirc_code *code, int x, int y)
|
410
410
|
{
|
411
411
|
int p = y * code->size + x;
|
412
|
-
|
413
412
|
return (code->cell_bitmap[p >> 3] >> (p & 7)) & 1;
|
414
413
|
}
|
415
414
|
|
@@ -874,7 +873,7 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data,
|
|
874
873
|
done:
|
875
874
|
|
876
875
|
/* Add nul terminator to all payloads */
|
877
|
-
if (data->payload_len >= sizeof(data->payload))
|
876
|
+
if (data->payload_len >= (int) sizeof(data->payload))
|
878
877
|
data->payload_len--;
|
879
878
|
data->payload[data->payload_len] = 0;
|
880
879
|
|
@@ -917,3 +916,18 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code,
|
|
917
916
|
|
918
917
|
return QUIRC_SUCCESS;
|
919
918
|
}
|
919
|
+
|
920
|
+
void quirc_flip(struct quirc_code *code)
|
921
|
+
{
|
922
|
+
struct quirc_code flipped = {0};
|
923
|
+
unsigned int offset = 0;
|
924
|
+
for (int y = 0; y < code->size; y++) {
|
925
|
+
for (int x = 0; x < code->size; x++) {
|
926
|
+
if (grid_bit(code, y, x)) {
|
927
|
+
flipped.cell_bitmap[offset >> 3u] |= (1u << (offset & 7u));
|
928
|
+
}
|
929
|
+
offset++;
|
930
|
+
}
|
931
|
+
}
|
932
|
+
memcpy(&code->cell_bitmap, &flipped.cell_bitmap, sizeof(flipped.cell_bitmap));
|
933
|
+
}
|
@@ -14,6 +14,7 @@
|
|
14
14
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
15
15
|
*/
|
16
16
|
|
17
|
+
#include <limits.h>
|
17
18
|
#include <string.h>
|
18
19
|
#include <stdlib.h>
|
19
20
|
#include <math.h>
|
@@ -98,8 +99,8 @@ static void perspective_map(const double *c,
|
|
98
99
|
double x = (c[0]*u + c[1]*v + c[2]) / den;
|
99
100
|
double y = (c[3]*u + c[4]*v + c[5]) / den;
|
100
101
|
|
101
|
-
ret->x = rint(x);
|
102
|
-
ret->y = rint(y);
|
102
|
+
ret->x = (int) rint(x);
|
103
|
+
ret->y = (int) rint(y);
|
103
104
|
}
|
104
105
|
|
105
106
|
static void perspective_unmap(const double *c,
|
@@ -174,60 +175,55 @@ static void flood_fill_seed(struct quirc *q, int x, int y, int from, int to,
|
|
174
175
|
* Adaptive thresholding
|
175
176
|
*/
|
176
177
|
|
177
|
-
|
178
|
-
#define THRESHOLD_S_DEN 8
|
179
|
-
#define THRESHOLD_T 5
|
180
|
-
|
181
|
-
static void threshold(struct quirc *q)
|
178
|
+
static uint8_t otsu(const struct quirc *q)
|
182
179
|
{
|
183
|
-
int
|
184
|
-
|
185
|
-
|
186
|
-
int
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
*/
|
195
|
-
if (threshold_s < THRESHOLD_S_MIN)
|
196
|
-
threshold_s = THRESHOLD_S_MIN;
|
197
|
-
|
198
|
-
for (y = 0; y < q->h; y++) {
|
199
|
-
memset(q->row_average, 0, q->w * sizeof(int));
|
200
|
-
|
201
|
-
for (x = 0; x < q->w; x++) {
|
202
|
-
int w, u;
|
180
|
+
int numPixels = q->w * q->h;
|
181
|
+
|
182
|
+
// Calculate histogram
|
183
|
+
unsigned int histogram[UINT8_MAX + 1];
|
184
|
+
(void)memset(histogram, 0, sizeof(histogram));
|
185
|
+
uint8_t* ptr = q->image;
|
186
|
+
int length = numPixels;
|
187
|
+
while (length--) {
|
188
|
+
uint8_t value = *ptr++;
|
189
|
+
histogram[value]++;
|
190
|
+
}
|
203
191
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
}
|
192
|
+
// Calculate weighted sum of histogram values
|
193
|
+
unsigned int sum = 0;
|
194
|
+
unsigned int i = 0;
|
195
|
+
for (i = 0; i <= UINT8_MAX; ++i) {
|
196
|
+
sum += i * histogram[i];
|
197
|
+
}
|
211
198
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
199
|
+
// Compute threshold
|
200
|
+
int sumB = 0;
|
201
|
+
int q1 = 0;
|
202
|
+
double max = 0;
|
203
|
+
uint8_t threshold = 0;
|
204
|
+
for (i = 0; i <= UINT8_MAX; ++i) {
|
205
|
+
// Weighted background
|
206
|
+
q1 += histogram[i];
|
207
|
+
if (q1 == 0)
|
208
|
+
continue;
|
216
209
|
|
217
|
-
|
218
|
-
|
219
|
-
|
210
|
+
// Weighted foreground
|
211
|
+
const int q2 = numPixels - q1;
|
212
|
+
if (q2 == 0)
|
213
|
+
break;
|
220
214
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
215
|
+
sumB += i * histogram[i];
|
216
|
+
const double m1 = (double)sumB / q1;
|
217
|
+
const double m2 = ((double)sum - sumB) / q2;
|
218
|
+
const double m1m2 = m1 - m2;
|
219
|
+
const double variance = m1m2 * m1m2 * q1 * q2;
|
220
|
+
if (variance >= max) {
|
221
|
+
threshold = i;
|
222
|
+
max = variance;
|
227
223
|
}
|
228
|
-
|
229
|
-
row += q->w;
|
230
224
|
}
|
225
|
+
|
226
|
+
return threshold;
|
231
227
|
}
|
232
228
|
|
233
229
|
static void area_count(void *user_data, int y, int left, int right)
|
@@ -660,8 +656,11 @@ static int measure_timing_pattern(struct quirc *q, int index)
|
|
660
656
|
/* Choose the nearest allowable grid size */
|
661
657
|
size = scan * 2 + 13;
|
662
658
|
ver = (size - 15) / 4;
|
663
|
-
|
659
|
+
if (ver > QUIRC_MAX_VERSION) {
|
660
|
+
return -1;
|
661
|
+
}
|
664
662
|
|
663
|
+
qr->grid_size = ver * 4 + 17;
|
665
664
|
return 0;
|
666
665
|
}
|
667
666
|
|
@@ -856,8 +855,8 @@ static void rotate_capstone(struct quirc_capstone *cap,
|
|
856
855
|
{
|
857
856
|
struct quirc_point copy[4];
|
858
857
|
int j;
|
859
|
-
int best;
|
860
|
-
int best_score;
|
858
|
+
int best = 0;
|
859
|
+
int best_score = INT_MAX;
|
861
860
|
|
862
861
|
for (j = 0; j < 4; j++) {
|
863
862
|
struct quirc_point *p = &cap->corners[j];
|
@@ -1074,17 +1073,18 @@ static void test_grouping(struct quirc *q, int i)
|
|
1074
1073
|
test_neighbours(q, i, &hlist, &vlist);
|
1075
1074
|
}
|
1076
1075
|
|
1077
|
-
static void pixels_setup(struct quirc *q)
|
1076
|
+
static void pixels_setup(struct quirc *q, uint8_t threshold)
|
1078
1077
|
{
|
1079
|
-
if (
|
1078
|
+
if (QUIRC_PIXEL_ALIAS_IMAGE) {
|
1080
1079
|
q->pixels = (quirc_pixel_t *)q->image;
|
1081
|
-
}
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
uint8_t* source = q->image;
|
1083
|
+
quirc_pixel_t* dest = q->pixels;
|
1084
|
+
int length = q->w * q->h;
|
1085
|
+
while (length--) {
|
1086
|
+
uint8_t value = *source++;
|
1087
|
+
*dest++ = (value < threshold) ? QUIRC_PIXEL_BLACK : QUIRC_PIXEL_WHITE;
|
1088
1088
|
}
|
1089
1089
|
}
|
1090
1090
|
|
@@ -1106,8 +1106,8 @@ void quirc_end(struct quirc *q)
|
|
1106
1106
|
{
|
1107
1107
|
int i;
|
1108
1108
|
|
1109
|
-
|
1110
|
-
|
1109
|
+
uint8_t threshold = otsu(q);
|
1110
|
+
pixels_setup(q, threshold);
|
1111
1111
|
|
1112
1112
|
for (i = 0; i < q->h; i++)
|
1113
1113
|
finder_scan(q, i);
|
@@ -1138,11 +1138,10 @@ void quirc_extract(const struct quirc *q, int index,
|
|
1138
1138
|
|
1139
1139
|
for (y = 0; y < qr->grid_size; y++) {
|
1140
1140
|
int x;
|
1141
|
-
|
1142
1141
|
for (x = 0; x < qr->grid_size; x++) {
|
1143
|
-
if (read_cell(q, index, x, y) > 0)
|
1142
|
+
if (read_cell(q, index, x, y) > 0) {
|
1144
1143
|
code->cell_bitmap[i >> 3] |= (1 << (i & 7));
|
1145
|
-
|
1144
|
+
}
|
1146
1145
|
i++;
|
1147
1146
|
}
|
1148
1147
|
}
|
data/ext/quirc/embed/lib/quirc.c
CHANGED
@@ -39,9 +39,8 @@ void quirc_destroy(struct quirc *q)
|
|
39
39
|
free(q->image);
|
40
40
|
/* q->pixels may alias q->image when their type representation is of the
|
41
41
|
same size, so we need to be careful here to avoid a double free */
|
42
|
-
if (
|
42
|
+
if (!QUIRC_PIXEL_ALIAS_IMAGE)
|
43
43
|
free(q->pixels);
|
44
|
-
free(q->row_average);
|
45
44
|
free(q);
|
46
45
|
}
|
47
46
|
|
@@ -49,7 +48,6 @@ int quirc_resize(struct quirc *q, int w, int h)
|
|
49
48
|
{
|
50
49
|
uint8_t *image = NULL;
|
51
50
|
quirc_pixel_t *pixels = NULL;
|
52
|
-
int *row_average = NULL;
|
53
51
|
|
54
52
|
/*
|
55
53
|
* XXX: w and h should be size_t (or at least unsigned) as negatives
|
@@ -82,35 +80,27 @@ int quirc_resize(struct quirc *q, int w, int h)
|
|
82
80
|
(void)memcpy(image, q->image, min);
|
83
81
|
|
84
82
|
/* alloc a new buffer for q->pixels if needed */
|
85
|
-
if (
|
83
|
+
if (!QUIRC_PIXEL_ALIAS_IMAGE) {
|
86
84
|
pixels = calloc(newdim, sizeof(quirc_pixel_t));
|
87
85
|
if (!pixels)
|
88
86
|
goto fail;
|
89
87
|
}
|
90
88
|
|
91
|
-
/* alloc a new buffer for q->row_average */
|
92
|
-
row_average = calloc(w, sizeof(int));
|
93
|
-
if (!row_average)
|
94
|
-
goto fail;
|
95
|
-
|
96
89
|
/* alloc succeeded, update `q` with the new size and buffers */
|
97
90
|
q->w = w;
|
98
91
|
q->h = h;
|
99
92
|
free(q->image);
|
100
93
|
q->image = image;
|
101
|
-
if (
|
94
|
+
if (!QUIRC_PIXEL_ALIAS_IMAGE) {
|
102
95
|
free(q->pixels);
|
103
96
|
q->pixels = pixels;
|
104
97
|
}
|
105
|
-
free(q->row_average);
|
106
|
-
q->row_average = row_average;
|
107
98
|
|
108
99
|
return 0;
|
109
100
|
/* NOTREACHED */
|
110
101
|
fail:
|
111
102
|
free(image);
|
112
103
|
free(pixels);
|
113
|
-
free(row_average);
|
114
104
|
|
115
105
|
return -1;
|
116
106
|
}
|
data/ext/quirc/embed/lib/quirc.h
CHANGED
@@ -78,7 +78,9 @@ typedef enum {
|
|
78
78
|
const char *quirc_strerror(quirc_decode_error_t err);
|
79
79
|
|
80
80
|
/* Limits on the maximum size of QR-codes and their content. */
|
81
|
-
#define
|
81
|
+
#define QUIRC_MAX_VERSION 40
|
82
|
+
#define QUIRC_MAX_GRID_SIZE (QUIRC_MAX_VERSION * 4 + 17)
|
83
|
+
#define QUIRC_MAX_BITMAP (((QUIRC_MAX_GRID_SIZE * QUIRC_MAX_GRID_SIZE) + 7) / 8)
|
82
84
|
#define QUIRC_MAX_PAYLOAD 8896
|
83
85
|
|
84
86
|
/* QR-code ECC types. */
|
@@ -166,6 +168,9 @@ void quirc_extract(const struct quirc *q, int index,
|
|
166
168
|
quirc_decode_error_t quirc_decode(const struct quirc_code *code,
|
167
169
|
struct quirc_data *data);
|
168
170
|
|
171
|
+
/* Flip a QR-code according to optional mirror feature of ISO 18004:2015 */
|
172
|
+
void quirc_flip(struct quirc_code *code);
|
173
|
+
|
169
174
|
#ifdef __cplusplus
|
170
175
|
}
|
171
176
|
#endif
|
@@ -28,12 +28,13 @@
|
|
28
28
|
#endif
|
29
29
|
#define QUIRC_MAX_CAPSTONES 32
|
30
30
|
#define QUIRC_MAX_GRIDS 8
|
31
|
-
|
32
31
|
#define QUIRC_PERSPECTIVE_PARAMS 8
|
33
32
|
|
34
33
|
#if QUIRC_MAX_REGIONS < UINT8_MAX
|
34
|
+
#define QUIRC_PIXEL_ALIAS_IMAGE 1
|
35
35
|
typedef uint8_t quirc_pixel_t;
|
36
36
|
#elif QUIRC_MAX_REGIONS < UINT16_MAX
|
37
|
+
#define QUIRC_PIXEL_ALIAS_IMAGE 0
|
37
38
|
typedef uint16_t quirc_pixel_t;
|
38
39
|
#else
|
39
40
|
#error "QUIRC_MAX_REGIONS > 65534 is not supported"
|
@@ -77,7 +78,6 @@ struct quirc_grid {
|
|
77
78
|
struct quirc {
|
78
79
|
uint8_t *image;
|
79
80
|
quirc_pixel_t *pixels;
|
80
|
-
int *row_average; /* used by threshold() */
|
81
81
|
int w;
|
82
82
|
int h;
|
83
83
|
|
data/ext/quirc/extconf.rb
CHANGED
data/lib/quirc/version.rb
CHANGED
data/test/test_decode.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quirc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jacob Middag
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 1.4.1
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 1.4.1
|
69
69
|
description: Ruby bindings for C library quirc that extracts and decode QR images
|
70
70
|
email: jacob@gaddim.nl
|
71
71
|
executables: []
|
@@ -106,14 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
106
106
|
requirements:
|
107
107
|
- - ">="
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: '2.
|
109
|
+
version: '2.4'
|
110
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
111
|
requirements:
|
112
112
|
- - ">="
|
113
113
|
- !ruby/object:Gem::Version
|
114
114
|
version: '0'
|
115
115
|
requirements: []
|
116
|
-
rubygems_version: 3.0.
|
116
|
+
rubygems_version: 3.0.6
|
117
117
|
signing_key:
|
118
118
|
specification_version: 4
|
119
119
|
summary: QR decoder based on quirc
|