quirc 0.0.2 → 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 +5 -5
- data/LICENSE +1 -1
- data/README.md +30 -0
- data/ext/quirc/embed/Makefile +1 -1
- data/ext/quirc/embed/lib/decode.c +27 -7
- data/ext/quirc/embed/lib/identify.c +66 -69
- data/ext/quirc/embed/lib/quirc.c +55 -16
- data/ext/quirc/embed/lib/quirc.h +7 -2
- data/ext/quirc/embed/lib/quirc_internal.h +2 -1
- data/ext/quirc/extconf.rb +1 -0
- data/lib/quirc.rb +4 -0
- data/lib/quirc/version.rb +1 -1
- data/test/fixtures/hello.gz +1 -0
- data/test/helper.rb +11 -2
- data/test/test_decode.rb +25 -2
- metadata +14 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
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
data/README.md
CHANGED
@@ -3,5 +3,35 @@
|
|
3
3
|
[Quirc](https://github.com/dlbeer/quirc) is a small C library for extracting and decode QR codes from images.
|
4
4
|
This project is a Ruby binding for that library with the library embedded.
|
5
5
|
|
6
|
+
## Example
|
7
|
+
You have to supply a [ChunkyPNG](http://chunkypng.com/) object or a binary string of the grayscale image with width and height.
|
8
|
+
```ruby
|
9
|
+
require 'chunky_png'
|
10
|
+
require 'quirc'
|
11
|
+
|
12
|
+
img = ChunkyPNG::Image.from_file('path_to_image.png')
|
13
|
+
res = Quirc.decode(img).first
|
14
|
+
puts res.payload
|
15
|
+
```
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'base64'
|
19
|
+
require 'zlib'
|
20
|
+
require 'quirc'
|
21
|
+
|
22
|
+
encoded = <<~EOD
|
23
|
+
eJzt0kEOwyAMRNHe/9LpFo1mwK1IYqQ/mwQDfl5wXYQQQgghT+cziZ7Tb+Ue
|
24
|
+
7vvurL76Vvvhvuvqu0jvqHoP9wx3dh73fHdWxz3Hrc5TvYfbx01RP83j7uH2
|
25
|
+
cCtzuf+7g7uvr74ZrY9r967cedxebrrjZtK9tMbt4Y7+L/V/Tdzn3DRH+td5
|
26
|
+
0hq3h5veR+qjNTcPbh+3Mpd7Qzt6497vat+Voe9Oa7j93GpdrXGt+7i9XO3j
|
27
|
+
+jknzYB7huvmGM+7GXHPcWeOM3B7upV5Rlvvun3cHm6K+qt5qibucy4hhBBC
|
28
|
+
yN58AXWDGDc=
|
29
|
+
EOD
|
30
|
+
|
31
|
+
img = Zlib::Inflate.inflate(Base64.decode64(encoded))
|
32
|
+
res = Quirc.decode(img, 120, 120).first
|
33
|
+
puts res.payload
|
34
|
+
```
|
35
|
+
|
6
36
|
## License
|
7
37
|
This software is licensed under the MIT License. [View the license](LICENSE).
|
data/ext/quirc/embed/Makefile
CHANGED
@@ -117,7 +117,7 @@ static const uint8_t gf256_log[256] = {
|
|
117
117
|
0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
|
118
118
|
};
|
119
119
|
|
120
|
-
const
|
120
|
+
static const struct galois_field gf256 = {
|
121
121
|
.p = 255,
|
122
122
|
.log = gf256_log,
|
123
123
|
.exp = gf256_exp
|
@@ -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
|
|
@@ -790,12 +789,18 @@ static quirc_decode_error_t decode_kanji(struct quirc_data *data,
|
|
790
789
|
|
791
790
|
for (i = 0; i < count; i++) {
|
792
791
|
int d = take_bits(ds, 13);
|
792
|
+
int msB = d / 0xc0;
|
793
|
+
int lsB = d % 0xc0;
|
794
|
+
int intermediate = (msB << 8) | lsB;
|
793
795
|
uint16_t sjw;
|
794
796
|
|
795
|
-
if (
|
796
|
-
|
797
|
-
|
798
|
-
|
797
|
+
if (intermediate + 0x8140 <= 0x9ffc) {
|
798
|
+
/* bytes are in the range 0x8140 to 0x9FFC */
|
799
|
+
sjw = intermediate + 0x8140;
|
800
|
+
} else {
|
801
|
+
/* bytes are in the range 0xE040 to 0xEBBF */
|
802
|
+
sjw = intermediate + 0xc140;
|
803
|
+
}
|
799
804
|
|
800
805
|
data->payload[data->payload_len++] = sjw >> 8;
|
801
806
|
data->payload[data->payload_len++] = sjw & 0xff;
|
@@ -868,7 +873,7 @@ static quirc_decode_error_t decode_payload(struct quirc_data *data,
|
|
868
873
|
done:
|
869
874
|
|
870
875
|
/* Add nul terminator to all payloads */
|
871
|
-
if (data->payload_len >= sizeof(data->payload))
|
876
|
+
if (data->payload_len >= (int) sizeof(data->payload))
|
872
877
|
data->payload_len--;
|
873
878
|
data->payload[data->payload_len] = 0;
|
874
879
|
|
@@ -911,3 +916,18 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code,
|
|
911
916
|
|
912
917
|
return QUIRC_SUCCESS;
|
913
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,62 +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
|
-
int row_average[q->w];
|
200
|
-
|
201
|
-
memset(row_average, 0, sizeof(row_average));
|
202
|
-
|
203
|
-
for (x = 0; x < q->w; x++) {
|
204
|
-
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
|
+
}
|
205
191
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
}
|
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
|
+
}
|
213
198
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
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;
|
218
209
|
|
219
|
-
|
220
|
-
|
221
|
-
|
210
|
+
// Weighted foreground
|
211
|
+
const int q2 = numPixels - q1;
|
212
|
+
if (q2 == 0)
|
213
|
+
break;
|
222
214
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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;
|
229
223
|
}
|
230
|
-
|
231
|
-
row += q->w;
|
232
224
|
}
|
225
|
+
|
226
|
+
return threshold;
|
233
227
|
}
|
234
228
|
|
235
229
|
static void area_count(void *user_data, int y, int left, int right)
|
@@ -427,7 +421,7 @@ static void finder_scan(struct quirc *q, int y)
|
|
427
421
|
{
|
428
422
|
quirc_pixel_t *row = q->pixels + y * q->w;
|
429
423
|
int x;
|
430
|
-
int last_color;
|
424
|
+
int last_color = 0;
|
431
425
|
int run_length = 0;
|
432
426
|
int run_count = 0;
|
433
427
|
int pb[5];
|
@@ -662,8 +656,11 @@ static int measure_timing_pattern(struct quirc *q, int index)
|
|
662
656
|
/* Choose the nearest allowable grid size */
|
663
657
|
size = scan * 2 + 13;
|
664
658
|
ver = (size - 15) / 4;
|
665
|
-
|
659
|
+
if (ver > QUIRC_MAX_VERSION) {
|
660
|
+
return -1;
|
661
|
+
}
|
666
662
|
|
663
|
+
qr->grid_size = ver * 4 + 17;
|
667
664
|
return 0;
|
668
665
|
}
|
669
666
|
|
@@ -858,8 +855,8 @@ static void rotate_capstone(struct quirc_capstone *cap,
|
|
858
855
|
{
|
859
856
|
struct quirc_point copy[4];
|
860
857
|
int j;
|
861
|
-
int best;
|
862
|
-
int best_score;
|
858
|
+
int best = 0;
|
859
|
+
int best_score = INT_MAX;
|
863
860
|
|
864
861
|
for (j = 0; j < 4; j++) {
|
865
862
|
struct quirc_point *p = &cap->corners[j];
|
@@ -1076,17 +1073,18 @@ static void test_grouping(struct quirc *q, int i)
|
|
1076
1073
|
test_neighbours(q, i, &hlist, &vlist);
|
1077
1074
|
}
|
1078
1075
|
|
1079
|
-
static void pixels_setup(struct quirc *q)
|
1076
|
+
static void pixels_setup(struct quirc *q, uint8_t threshold)
|
1080
1077
|
{
|
1081
|
-
if (
|
1078
|
+
if (QUIRC_PIXEL_ALIAS_IMAGE) {
|
1082
1079
|
q->pixels = (quirc_pixel_t *)q->image;
|
1083
|
-
}
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
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;
|
1090
1088
|
}
|
1091
1089
|
}
|
1092
1090
|
|
@@ -1108,8 +1106,8 @@ void quirc_end(struct quirc *q)
|
|
1108
1106
|
{
|
1109
1107
|
int i;
|
1110
1108
|
|
1111
|
-
|
1112
|
-
|
1109
|
+
uint8_t threshold = otsu(q);
|
1110
|
+
pixels_setup(q, threshold);
|
1113
1111
|
|
1114
1112
|
for (i = 0; i < q->h; i++)
|
1115
1113
|
finder_scan(q, i);
|
@@ -1140,11 +1138,10 @@ void quirc_extract(const struct quirc *q, int index,
|
|
1140
1138
|
|
1141
1139
|
for (y = 0; y < qr->grid_size; y++) {
|
1142
1140
|
int x;
|
1143
|
-
|
1144
1141
|
for (x = 0; x < qr->grid_size; x++) {
|
1145
|
-
if (read_cell(q, index, x, y) > 0)
|
1142
|
+
if (read_cell(q, index, x, y) > 0) {
|
1146
1143
|
code->cell_bitmap[i >> 3] |= (1 << (i & 7));
|
1147
|
-
|
1144
|
+
}
|
1148
1145
|
i++;
|
1149
1146
|
}
|
1150
1147
|
}
|
data/ext/quirc/embed/lib/quirc.c
CHANGED
@@ -36,34 +36,73 @@ struct quirc *quirc_new(void)
|
|
36
36
|
|
37
37
|
void quirc_destroy(struct quirc *q)
|
38
38
|
{
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
free(q->image);
|
40
|
+
/* q->pixels may alias q->image when their type representation is of the
|
41
|
+
same size, so we need to be careful here to avoid a double free */
|
42
|
+
if (!QUIRC_PIXEL_ALIAS_IMAGE)
|
42
43
|
free(q->pixels);
|
43
|
-
|
44
44
|
free(q);
|
45
45
|
}
|
46
46
|
|
47
47
|
int quirc_resize(struct quirc *q, int w, int h)
|
48
48
|
{
|
49
|
-
uint8_t
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
49
|
+
uint8_t *image = NULL;
|
50
|
+
quirc_pixel_t *pixels = NULL;
|
51
|
+
|
52
|
+
/*
|
53
|
+
* XXX: w and h should be size_t (or at least unsigned) as negatives
|
54
|
+
* values would not make much sense. The downside is that it would break
|
55
|
+
* both the API and ABI. Thus, at the moment, let's just do a sanity
|
56
|
+
* check.
|
57
|
+
*/
|
58
|
+
if (w < 0 || h < 0)
|
59
|
+
goto fail;
|
60
|
+
|
61
|
+
/*
|
62
|
+
* alloc a new buffer for q->image. We avoid realloc(3) because we want
|
63
|
+
* on failure to be leave `q` in a consistant, unmodified state.
|
64
|
+
*/
|
65
|
+
image = calloc(w, h);
|
66
|
+
if (!image)
|
67
|
+
goto fail;
|
68
|
+
|
69
|
+
/* compute the "old" (i.e. currently allocated) and the "new"
|
70
|
+
(i.e. requested) image dimensions */
|
71
|
+
size_t olddim = q->w * q->h;
|
72
|
+
size_t newdim = w * h;
|
73
|
+
size_t min = (olddim < newdim ? olddim : newdim);
|
74
|
+
|
75
|
+
/*
|
76
|
+
* copy the data into the new buffer, avoiding (a) to read beyond the
|
77
|
+
* old buffer when the new size is greater and (b) to write beyond the
|
78
|
+
* new buffer when the new size is smaller, hence the min computation.
|
79
|
+
*/
|
80
|
+
(void)memcpy(image, q->image, min);
|
81
|
+
|
82
|
+
/* alloc a new buffer for q->pixels if needed */
|
83
|
+
if (!QUIRC_PIXEL_ALIAS_IMAGE) {
|
84
|
+
pixels = calloc(newdim, sizeof(quirc_pixel_t));
|
85
|
+
if (!pixels)
|
86
|
+
goto fail;
|
60
87
|
}
|
61
88
|
|
62
|
-
q
|
89
|
+
/* alloc succeeded, update `q` with the new size and buffers */
|
63
90
|
q->w = w;
|
64
91
|
q->h = h;
|
92
|
+
free(q->image);
|
93
|
+
q->image = image;
|
94
|
+
if (!QUIRC_PIXEL_ALIAS_IMAGE) {
|
95
|
+
free(q->pixels);
|
96
|
+
q->pixels = pixels;
|
97
|
+
}
|
65
98
|
|
66
99
|
return 0;
|
100
|
+
/* NOTREACHED */
|
101
|
+
fail:
|
102
|
+
free(image);
|
103
|
+
free(pixels);
|
104
|
+
|
105
|
+
return -1;
|
67
106
|
}
|
68
107
|
|
69
108
|
int quirc_count(const struct quirc *q)
|
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. */
|
@@ -121,7 +123,7 @@ struct quirc_code {
|
|
121
123
|
* is a bitmask giving the actual values of cells. If the cell
|
122
124
|
* at (x, y) is black, then the following bit is set:
|
123
125
|
*
|
124
|
-
* cell_bitmap[i
|
126
|
+
* cell_bitmap[i >> 3] & (1 << (i & 7))
|
125
127
|
*
|
126
128
|
* where i = (y * size) + x.
|
127
129
|
*/
|
@@ -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"
|
data/ext/quirc/extconf.rb
CHANGED
data/lib/quirc.rb
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
module Quirc
|
4
4
|
def self.decode(image, width=nil, height=nil)
|
5
|
+
unless image.respond_to?(:to_grayscale_stream) || (width && height)
|
6
|
+
raise ArgumentError, "Arguments width and height are required if binary string is passed"
|
7
|
+
end
|
8
|
+
|
5
9
|
width ||= image.public_send(:width)
|
6
10
|
height ||= image.public_send(:height)
|
7
11
|
if image.respond_to?(:to_grayscale_stream)
|
data/lib/quirc/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
x���A� D������f��Hb�?�~^p]�B!O�3���o����V����H�z�wv�|wV�=ǭ�S����MQ?�����p+s����������k���y�^n��fҽ�����/�M���4G��y�����G�57n�2�{C;z���jߕ��Nk���j]�q����\���9'̀{���ϻq�qg�3p{��yF[�}�n���y�&�s.!�B��|u�7
|
data/test/helper.rb
CHANGED
@@ -1,15 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "zlib"
|
4
|
+
|
3
5
|
require "minitest/autorun"
|
4
6
|
require "oily_png"
|
7
|
+
|
5
8
|
require "quirc"
|
6
9
|
|
7
10
|
module TestHelpers
|
11
|
+
def binary_fixture(*path)
|
12
|
+
Zlib::Inflate.inflate(File.binread(File.join(__dir__, "fixtures", *path)))
|
13
|
+
end
|
14
|
+
|
8
15
|
def image_fixture(*path)
|
9
16
|
ChunkyPNG::Image.from_file(File.join(__dir__, "fixtures", *path))
|
10
17
|
end
|
11
18
|
end
|
12
19
|
|
13
|
-
|
14
|
-
|
20
|
+
module Minitest
|
21
|
+
class Spec
|
22
|
+
include TestHelpers
|
23
|
+
end
|
15
24
|
end
|
data/test/test_decode.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "helper
|
3
|
+
require "helper"
|
4
4
|
|
5
5
|
describe Quirc do
|
6
|
+
describe "binary string" do
|
7
|
+
it "should decode" do
|
8
|
+
result = Quirc.decode(binary_fixture("hello.gz"), 120, 120).first
|
9
|
+
assert_equal 1, result.ecc_level
|
10
|
+
assert_equal "Hello World!", result.payload
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
describe "error levels" do
|
7
15
|
it "should decode all error levels" do
|
8
16
|
%i[m l h q].each_with_index do |level, no|
|
@@ -16,9 +24,24 @@ describe Quirc do
|
|
16
24
|
|
17
25
|
describe "errors" do
|
18
26
|
it "should throw error if image size is not equal to buffer" do
|
19
|
-
assert_raises ArgumentError
|
27
|
+
e = assert_raises ArgumentError do
|
20
28
|
Quirc::Decoder.new(1, 2).decode("abc")
|
21
29
|
end
|
30
|
+
assert_equal "Decoder is allocated for 1x2 images", e.message
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should throw error if width is not specified with binary string" do
|
34
|
+
e = assert_raises ArgumentError do
|
35
|
+
Quirc.decode("", nil, 1)
|
36
|
+
end
|
37
|
+
assert_equal "Arguments width and height are required if binary string is passed", e.message
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should throw error if width height not specified with binary string" do
|
41
|
+
e = assert_raises ArgumentError, "Decoder is allocated for 1x2 images" do
|
42
|
+
Quirc.decode("", nil, 1)
|
43
|
+
end
|
44
|
+
assert_equal "Arguments width and height are required if binary string is passed", e.message
|
22
45
|
end
|
23
46
|
end
|
24
47
|
end
|
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.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
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: oily_png
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
@@ -39,33 +39,33 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake-compiler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0
|
47
|
+
version: '1.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0
|
54
|
+
version: '1.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rubocop
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
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: []
|
@@ -91,9 +91,10 @@ files:
|
|
91
91
|
- test/fixtures/hello-120-utf8-l.png
|
92
92
|
- test/fixtures/hello-120-utf8-m.png
|
93
93
|
- test/fixtures/hello-120-utf8-q.png
|
94
|
+
- test/fixtures/hello.gz
|
94
95
|
- test/helper.rb
|
95
96
|
- test/test_decode.rb
|
96
|
-
homepage: https://github.com/middagj/quirc
|
97
|
+
homepage: https://github.com/middagj/quirc-ruby
|
97
98
|
licenses:
|
98
99
|
- MIT
|
99
100
|
metadata: {}
|
@@ -105,15 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
106
|
requirements:
|
106
107
|
- - ">="
|
107
108
|
- !ruby/object:Gem::Version
|
108
|
-
version: '2.
|
109
|
+
version: '2.4'
|
109
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
111
|
requirements:
|
111
112
|
- - ">="
|
112
113
|
- !ruby/object:Gem::Version
|
113
114
|
version: '0'
|
114
115
|
requirements: []
|
115
|
-
|
116
|
-
rubygems_version: 2.6.11
|
116
|
+
rubygems_version: 3.0.6
|
117
117
|
signing_key:
|
118
118
|
specification_version: 4
|
119
119
|
summary: QR decoder based on quirc
|
@@ -122,5 +122,6 @@ test_files:
|
|
122
122
|
- test/fixtures/hello-120-utf8-l.png
|
123
123
|
- test/fixtures/hello-120-utf8-m.png
|
124
124
|
- test/fixtures/hello-120-utf8-q.png
|
125
|
+
- test/fixtures/hello.gz
|
125
126
|
- test/helper.rb
|
126
127
|
- test/test_decode.rb
|