quirc 0.1.3 → 0.2.0
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/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
|