Skip to content

Commit 9354c92

Browse files
authored
Merge pull request #8467 from pypewpew/qrio-find
Add qrio.QRDecoder.find() to locate codes without decoding
2 parents c3cc76d + 12b6a9b commit 9354c92

File tree

5 files changed

+141
-15
lines changed

5 files changed

+141
-15
lines changed

shared-bindings/qrio/QRDecoder.c

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,19 @@ STATIC mp_obj_t qrio_qrdecoder_make_new(const mp_obj_type_t *type, size_t n_args
5656
return self;
5757
}
5858

59+
60+
STATIC void verify_buffer_size(qrio_qrdecoder_obj_t *self, mp_obj_t *buffer, size_t len, qrio_pixel_policy_t policy) {
61+
int width = shared_module_qrio_qrdecoder_get_width(self);
62+
int height = shared_module_qrio_qrdecoder_get_height(self);
63+
64+
// verify that the buffer is big enough
65+
int sz = width * height;
66+
if (policy != QRIO_EVERY_BYTE) {
67+
sz *= 2;
68+
}
69+
mp_get_index(mp_obj_get_type(*buffer), len, MP_OBJ_NEW_SMALL_INT(sz - 1), false);
70+
}
71+
5972
//| def decode(
6073
//| self, buffer: ReadableBuffer, pixel_policy: PixelPolicy = PixelPolicy.EVERY_BYTE
6174
//| ) -> List[QRInfo]:
@@ -73,22 +86,39 @@ STATIC mp_obj_t qrio_qrdecoder_decode(size_t n_args, const mp_obj_t *pos_args, m
7386

7487
mp_buffer_info_t bufinfo;
7588
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
76-
77-
int width = shared_module_qrio_qrdecoder_get_width(self);
78-
int height = shared_module_qrio_qrdecoder_get_height(self);
79-
80-
// verify that the buffer is big enough
81-
int sz = width * height;
8289
qrio_pixel_policy_t policy = cp_enum_value(&qrio_pixel_policy_type, args[ARG_pixel_policy].u_obj, MP_QSTR_pixel_policy);
83-
if (policy != QRIO_EVERY_BYTE) {
84-
sz *= 2;
85-
}
86-
mp_get_index(mp_obj_get_type(args[ARG_buffer].u_obj), bufinfo.len, MP_OBJ_NEW_SMALL_INT(sz - 1), false);
90+
verify_buffer_size(self, &args[ARG_buffer].u_obj, bufinfo.len, policy);
8791

8892
return shared_module_qrio_qrdecoder_decode(self, &bufinfo, policy);
8993
}
9094
MP_DEFINE_CONST_FUN_OBJ_KW(qrio_qrdecoder_decode_obj, 1, qrio_qrdecoder_decode);
9195

96+
97+
//| def find(
98+
//| self, buffer: ReadableBuffer, pixel_policy: PixelPolicy = PixelPolicy.EVERY_BYTE
99+
//| ) -> List[QRPosition]:
100+
//| """Find all visible QR codes from the given image. The size of the buffer must be at least ``length``×``width`` bytes for `EVERY_BYTE`, and 2×``length``×``width`` bytes for `EVEN_BYTES` or `ODD_BYTES`."""
101+
STATIC mp_obj_t qrio_qrdecoder_find(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
102+
qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
103+
104+
enum { ARG_buffer, ARG_pixel_policy };
105+
static const mp_arg_t allowed_args[] = {
106+
{ MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_int = 0} },
107+
{ MP_QSTR_pixel_policy, MP_ARG_OBJ, {.u_obj = MP_ROM_PTR((mp_obj_t *)&qrio_pixel_policy_EVERY_BYTE_obj)} },
108+
};
109+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
110+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
111+
112+
mp_buffer_info_t bufinfo;
113+
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
114+
qrio_pixel_policy_t policy = cp_enum_value(&qrio_pixel_policy_type, args[ARG_pixel_policy].u_obj, MP_QSTR_pixel_policy);
115+
verify_buffer_size(self, &args[ARG_buffer].u_obj, bufinfo.len, policy);
116+
117+
return shared_module_qrio_qrdecoder_find(self, &bufinfo, policy);
118+
}
119+
MP_DEFINE_CONST_FUN_OBJ_KW(qrio_qrdecoder_find_obj, 1, qrio_qrdecoder_find);
120+
121+
92122
//| width: int
93123
//| """The width of image the decoder expects"""
94124
STATIC mp_obj_t qrio_qrdecoder_get_width(mp_obj_t self_in) {
@@ -135,6 +165,7 @@ STATIC const mp_rom_map_elem_t qrio_qrdecoder_locals_table[] = {
135165
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&qrio_qrdecoder_width_obj) },
136166
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&qrio_qrdecoder_height_obj) },
137167
{ MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&qrio_qrdecoder_decode_obj) },
168+
{ MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&qrio_qrdecoder_find_obj) },
138169
};
139170

140171
STATIC MP_DEFINE_CONST_DICT(qrio_qrdecoder_locals, qrio_qrdecoder_locals_table);

shared-bindings/qrio/QRInfo.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,66 @@ const mp_obj_namedtuple_type_t qrio_qrinfo_type_obj = {
4747
MP_QSTR_data_type,
4848
},
4949
};
50+
51+
//| class QRPosition:
52+
//| """Information about a non-decoded QR code"""
53+
//|
54+
//| top_left_x: int
55+
//| """X coordinate of the top left corner"""
56+
//|
57+
//| top_left_y: int
58+
//| """Y coordinate of the top left corner"""
59+
//|
60+
//| top_right_x: int
61+
//| """X coordinate of the top right corner"""
62+
//|
63+
//| top_right_y: int
64+
//| """Y coordinate of the top right corner"""
65+
//|
66+
//| bottom_right_x: int
67+
//| """X coordinate of the bottom right corner"""
68+
//|
69+
//| bottom_right_y: int
70+
//| """Y coordinate of the bottom right corner"""
71+
//|
72+
//| bottom_left_x: int
73+
//| """X coordinate of the bottom left corner"""
74+
//|
75+
//| bottom_left_y: int
76+
//| """Y coordinate of the bottom left corner"""
77+
//|
78+
//| size: int
79+
//| """The number of bits the code contains"""
80+
//|
81+
82+
const mp_obj_namedtuple_type_t qrio_qrposition_type_obj = {
83+
.base = {
84+
.base = {
85+
.type = &mp_type_type
86+
},
87+
.flags = MP_TYPE_FLAG_EXTENDED,
88+
.name = MP_QSTR_QRPosition,
89+
.print = namedtuple_print,
90+
.parent = &mp_type_tuple,
91+
.make_new = namedtuple_make_new,
92+
.attr = namedtuple_attr,
93+
MP_TYPE_EXTENDED_FIELDS(
94+
.unary_op = mp_obj_tuple_unary_op,
95+
.binary_op = mp_obj_tuple_binary_op,
96+
.subscr = mp_obj_tuple_subscr,
97+
.getiter = mp_obj_tuple_getiter,
98+
),
99+
},
100+
.n_fields = 9,
101+
.fields = {
102+
MP_QSTR_top_left_x,
103+
MP_QSTR_top_left_y,
104+
MP_QSTR_top_right_x,
105+
MP_QSTR_top_right_y,
106+
MP_QSTR_bottom_right_x,
107+
MP_QSTR_bottom_right_y,
108+
MP_QSTR_bottom_left_x,
109+
MP_QSTR_bottom_left_y,
110+
MP_QSTR_size,
111+
},
112+
};

shared-bindings/qrio/QRInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@
2929
#include "py/objnamedtuple.h"
3030

3131
extern const mp_obj_namedtuple_type_t qrio_qrinfo_type_obj;
32+
extern const mp_obj_namedtuple_type_t qrio_qrposition_type_obj;

shared-module/qrio/QRDecoder.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,21 @@ STATIC mp_obj_t data_type(int type) {
9898
return mp_obj_new_int(type);
9999
}
100100

101-
mp_obj_t shared_module_qrio_qrdecoder_decode(qrdecoder_qrdecoder_obj_t *self, const mp_buffer_info_t *bufinfo, qrio_pixel_policy_t policy) {
101+
STATIC void quirc_fill_buffer(qrdecoder_qrdecoder_obj_t *self, void *buf, qrio_pixel_policy_t policy) {
102102
int width, height;
103103
uint8_t *framebuffer = quirc_begin(self->quirc, &width, &height);
104-
uint8_t *src = bufinfo->buf;
104+
uint8_t *src = buf;
105105

106106
switch (policy) {
107107
case QRIO_RGB565: {
108-
uint16_t *src16 = bufinfo->buf;
108+
uint16_t *src16 = buf;
109109
for (int i = 0; i < width * height; i++) {
110110
framebuffer[i] = (src16[i] >> 3) & 0xfc;
111111
}
112112
break;
113113
}
114114
case QRIO_RGB565_SWAPPED: {
115-
uint16_t *src16 = bufinfo->buf;
115+
uint16_t *src16 = buf;
116116
for (int i = 0; i < width * height; i++) {
117117
framebuffer[i] = (__builtin_bswap16(src16[i]) >> 3) & 0xfc;
118118
}
@@ -133,19 +133,49 @@ mp_obj_t shared_module_qrio_qrdecoder_decode(qrdecoder_qrdecoder_obj_t *self, co
133133
break;
134134
}
135135
quirc_end(self->quirc);
136+
}
136137

138+
139+
mp_obj_t shared_module_qrio_qrdecoder_decode(qrdecoder_qrdecoder_obj_t *self, const mp_buffer_info_t *bufinfo, qrio_pixel_policy_t policy) {
140+
quirc_fill_buffer(self, bufinfo->buf, policy);
137141
int count = quirc_count(self->quirc);
138142
mp_obj_t result = mp_obj_new_list(0, NULL);
139143
for (int i = 0; i < count; i++) {
140144
quirc_extract(self->quirc, i, &self->code);
145+
mp_obj_t code_obj;
141146
if (quirc_decode(&self->code, &self->data) != QUIRC_SUCCESS) {
142147
continue;
143148
}
144149
mp_obj_t elems[2] = {
145150
mp_obj_new_bytes(self->data.payload, self->data.payload_len),
146151
data_type(self->data.data_type),
147152
};
148-
mp_obj_t code_obj = namedtuple_make_new((const mp_obj_type_t *)&qrio_qrinfo_type_obj, 2, 0, elems);
153+
code_obj = namedtuple_make_new((const mp_obj_type_t *)&qrio_qrinfo_type_obj, 2, 0, elems);
154+
mp_obj_list_append(result, code_obj);
155+
}
156+
return result;
157+
}
158+
159+
160+
mp_obj_t shared_module_qrio_qrdecoder_find(qrdecoder_qrdecoder_obj_t *self, const mp_buffer_info_t *bufinfo, qrio_pixel_policy_t policy) {
161+
quirc_fill_buffer(self, bufinfo->buf, policy);
162+
int count = quirc_count(self->quirc);
163+
mp_obj_t result = mp_obj_new_list(0, NULL);
164+
for (int i = 0; i < count; i++) {
165+
quirc_extract(self->quirc, i, &self->code);
166+
mp_obj_t code_obj;
167+
mp_obj_t elems[9] = {
168+
mp_obj_new_int(self->code.corners[0].x),
169+
mp_obj_new_int(self->code.corners[0].y),
170+
mp_obj_new_int(self->code.corners[1].x),
171+
mp_obj_new_int(self->code.corners[1].y),
172+
mp_obj_new_int(self->code.corners[2].x),
173+
mp_obj_new_int(self->code.corners[2].y),
174+
mp_obj_new_int(self->code.corners[3].x),
175+
mp_obj_new_int(self->code.corners[3].y),
176+
mp_obj_new_int(self->code.size),
177+
};
178+
code_obj = namedtuple_make_new((const mp_obj_type_t *)&qrio_qrposition_type_obj, 9, 0, elems);
149179
mp_obj_list_append(result, code_obj);
150180
}
151181
return result;

shared-module/qrio/QRDecoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ int shared_module_qrio_qrdecoder_get_width(qrdecoder_qrdecoder_obj_t *);
4343
void shared_module_qrio_qrdecoder_set_height(qrdecoder_qrdecoder_obj_t *, int height);
4444
void shared_module_qrio_qrdecoder_set_width(qrdecoder_qrdecoder_obj_t *, int width);
4545
mp_obj_t shared_module_qrio_qrdecoder_decode(qrdecoder_qrdecoder_obj_t *, const mp_buffer_info_t *bufinfo, qrio_pixel_policy_t policy);
46+
mp_obj_t shared_module_qrio_qrdecoder_find(qrdecoder_qrdecoder_obj_t *, const mp_buffer_info_t *bufinfo, qrio_pixel_policy_t policy);

0 commit comments

Comments
 (0)