Add qrio: Decode QR codes with quirc lib

This commit is contained in:
Jeff Epler 2021-08-03 08:42:53 -05:00 committed by Jeff Epler
parent 38f392f318
commit bd903f2f03
14 changed files with 561 additions and 11 deletions

3
.gitmodules vendored
View File

@ -188,3 +188,6 @@
[submodule "frozen/Adafruit_CircuitPython_SimpleIO"] [submodule "frozen/Adafruit_CircuitPython_SimpleIO"]
path = frozen/Adafruit_CircuitPython_SimpleIO path = frozen/Adafruit_CircuitPython_SimpleIO
url = https://github.com/adafruit/adafruit_circuitpython_simpleio url = https://github.com/adafruit/adafruit_circuitpython_simpleio
[submodule "lib/quirc"]
path = lib/quirc
url = https://github.com/adafruit/quirc.git

1
lib/quirc Submodule

@ -0,0 +1 @@
Subproject commit 7f4001e71921e9e17405119e369775f5b4289a8b

View File

@ -1185,11 +1185,6 @@ msgstr ""
msgid "Input/output error" msgid "Input/output error"
msgstr "" msgstr ""
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format
msgid "Missing jmp_pin. Instruction %d jumps on pin"
msgstr ""
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format #, c-format
msgid "Instruction %d shifts in more bits than pin count" msgid "Instruction %d shifts in more bits than pin count"
@ -1506,6 +1501,11 @@ msgstr ""
msgid "Missing first_set_pin. Instruction %d sets pin(s)" msgid "Missing first_set_pin. Instruction %d sets pin(s)"
msgstr "" msgstr ""
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format
msgid "Missing jmp_pin. Instruction %d jumps on pin"
msgstr ""
#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c #: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c
msgid "Must be a %q subclass." msgid "Must be a %q subclass."
msgstr "" msgstr ""
@ -2063,7 +2063,6 @@ msgid "Size not supported"
msgstr "" msgstr ""
#: ports/raspberrypi/common-hal/alarm/SleepMemory.c #: ports/raspberrypi/common-hal/alarm/SleepMemory.c
#: ports/stm/common-hal/alarm/SleepMemory.c
msgid "Sleep Memory not available" msgid "Sleep Memory not available"
msgstr "" msgstr ""
@ -2510,7 +2509,7 @@ msgid "argument name reused"
msgstr "" msgstr ""
#: py/argcheck.c shared-bindings/_stage/__init__.c #: py/argcheck.c shared-bindings/_stage/__init__.c
#: shared-bindings/digitalio/DigitalInOut.c shared-bindings/gamepad/GamePad.c #: shared-bindings/digitalio/DigitalInOut.c
msgid "argument num/types mismatch" msgid "argument num/types mismatch"
msgstr "" msgstr ""
@ -3594,10 +3593,6 @@ msgstr ""
msgid "no active exception to reraise" msgid "no active exception to reraise"
msgstr "" msgstr ""
#: shared-bindings/socket/__init__.c shared-module/network/__init__.c
msgid "no available NIC"
msgstr ""
#: py/compile.c #: py/compile.c
msgid "no binding for nonlocal found" msgid "no binding for nonlocal found"
msgstr "" msgstr ""

View File

@ -224,6 +224,9 @@ endif
ifeq ($(CIRCUITPY_PIXELBUF),1) ifeq ($(CIRCUITPY_PIXELBUF),1)
SRC_PATTERNS += adafruit_pixelbuf/% SRC_PATTERNS += adafruit_pixelbuf/%
endif endif
ifeq ($(CIRCUITPY_QRIO),1)
SRC_PATTERNS += qrio/%
endif
ifeq ($(CIRCUITPY_RAINBOWIO),1) ifeq ($(CIRCUITPY_RAINBOWIO),1)
SRC_PATTERNS += rainbowio/% SRC_PATTERNS += rainbowio/%
endif endif
@ -529,6 +532,8 @@ SRC_SHARED_MODULE_ALL = \
network/__init__.c \ network/__init__.c \
msgpack/__init__.c \ msgpack/__init__.c \
os/__init__.c \ os/__init__.c \
qrio/__init__.c \
qrio/QRDecoder.c \
rainbowio/__init__.c \ rainbowio/__init__.c \
random/__init__.c \ random/__init__.c \
rgbmatrix/RGBMatrix.c \ rgbmatrix/RGBMatrix.c \
@ -664,6 +669,12 @@ SRC_CIRCUITPY_COMMON = \
lib/utils/stdout_helpers.c \ lib/utils/stdout_helpers.c \
lib/utils/sys_stdio_mphal.c lib/utils/sys_stdio_mphal.c
ifeq ($(CIRCUITPY_QRIO),1)
SRC_CIRCUITPY_COMMON += lib/quirc/lib/decode.c lib/quirc/lib/identify.c lib/quirc/lib/quirc.c lib/quirc/lib/version_db.c
$(BUILD)/lib/quirc/lib/%.o: CFLAGS += -Wno-shadow -Wno-sign-compare -include shared-module/qrio/quirc_alloc.h
endif
ifdef LD_TEMPLATE_FILE ifdef LD_TEMPLATE_FILE
# Generate a linker script (.ld file) from a template, for those builds that use it. # Generate a linker script (.ld file) from a template, for those builds that use it.
GENERATED_LD_FILE = $(BUILD)/$(notdir $(patsubst %.template.ld,%.ld,$(LD_TEMPLATE_FILE))) GENERATED_LD_FILE = $(BUILD)/$(notdir $(patsubst %.template.ld,%.ld,$(LD_TEMPLATE_FILE)))

View File

@ -621,6 +621,13 @@ extern const struct _mp_obj_module_t pwmio_module;
#define PWMIO_MODULE #define PWMIO_MODULE
#endif #endif
#if CIRCUITPY_QRIO
extern const struct _mp_obj_module_t qrio_module;
#define QRIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_qrio), (mp_obj_t)&qrio_module },
#else
#define QRIO_MODULE
#endif
#if CIRCUITPY_RAINBOWIO #if CIRCUITPY_RAINBOWIO
extern const struct _mp_obj_module_t rainbowio_module; extern const struct _mp_obj_module_t rainbowio_module;
#define RAINBOWIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rainbowio), (mp_obj_t)&rainbowio_module }, #define RAINBOWIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_rainbowio), (mp_obj_t)&rainbowio_module },
@ -898,6 +905,7 @@ extern const struct _mp_obj_module_t msgpack_module;
PS2IO_MODULE \ PS2IO_MODULE \
PULSEIO_MODULE \ PULSEIO_MODULE \
PWMIO_MODULE \ PWMIO_MODULE \
QRIO_MODULE \
RAINBOWIO_MODULE \ RAINBOWIO_MODULE \
RANDOM_MODULE \ RANDOM_MODULE \
RE_MODULE \ RE_MODULE \

View File

@ -239,6 +239,9 @@ CFLAGS += -DCIRCUITPY_PULSEIO=$(CIRCUITPY_PULSEIO)
CIRCUITPY_PWMIO ?= 1 CIRCUITPY_PWMIO ?= 1
CFLAGS += -DCIRCUITPY_PWMIO=$(CIRCUITPY_PWMIO) CFLAGS += -DCIRCUITPY_PWMIO=$(CIRCUITPY_PWMIO)
CIRCUITPY_QRIO ?= $(CIRCUITPY_IMAGECAPTURE)
CFLAGS += -DCIRCUITPY_QRIO=$(CIRCUITPY_QRIO)
CIRCUITPY_RAINBOWIO ?= 1 CIRCUITPY_RAINBOWIO ?= 1
CFLAGS += -DCIRCUITPY_RAINBOWIO=$(CIRCUITPY_RAINBOWIO) CFLAGS += -DCIRCUITPY_RAINBOWIO=$(CIRCUITPY_RAINBOWIO)

View File

@ -0,0 +1,151 @@
/*
* This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jeff Epler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/qrio/__init__.h"
#include "shared-bindings/qrio/QRDecoder.h"
#include "shared-module/qrio/QRDecoder.h"
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/enum.h"
//| class QRDecoder:
//|
//| def __init__(self, width: int, height: int) -> None:
//| """Construct a QRDecoder object"""
//|
STATIC mp_obj_t qrio_qrdecoder_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_width, ARG_height };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_width, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} },
{ MP_QSTR_height, MP_ARG_INT | MP_ARG_REQUIRED, {.u_int = 0} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
qrio_qrdecoder_obj_t *self = m_new_obj(qrio_qrdecoder_obj_t);
self->base.type = &qrio_qrdecoder_type_obj;
shared_module_qrio_qrdecoder_construct(self, args[ARG_width].u_int, args[ARG_height].u_int);
return self;
}
//| def decode(self, buffer: ReadableBuffer) -> List[qrinfo]:
//| """Decode zero or more QR codes from the given image in L8 format"""
//|
STATIC mp_obj_t qrio_qrdecoder_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
enum { ARG_buffer, ARG_pixel_policy };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_int = 0} },
{ MP_QSTR_pixel_policy, MP_ARG_OBJ, {.u_int = 0} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
int width = shared_module_qrio_qrdecoder_get_width(self);
int height = shared_module_qrio_qrdecoder_get_height(self);
// verify that the buffer is big enough
int sz = width * height;
qrio_pixel_policy_t policy = cp_enum_value(&qrio_pixel_policy_type, args[ARG_pixel_policy].u_obj);
if (policy != QRIO_EVERY_BYTE) {
sz *= 2;
}
mp_get_index(mp_obj_get_type(args[ARG_buffer].u_obj), bufinfo.len, MP_OBJ_NEW_SMALL_INT(sz - 1), false);
return shared_module_qrio_qrdecoder_decode(self, &bufinfo, policy);
}
MP_DEFINE_CONST_FUN_OBJ_KW(qrio_qrdecoder_decode_obj, 2, qrio_qrdecoder_decode);
//| width: int
//| """The width of image the decoder expects"""
//|
STATIC mp_obj_t qrio_qrdecoder_get_width(mp_obj_t self_in) {
qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_int(shared_module_qrio_qrdecoder_get_width(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(qrio_qrdecoder_get_width_obj, qrio_qrdecoder_get_width);
STATIC mp_obj_t qrio_qrdecoder_set_width(mp_obj_t self_in, mp_obj_t width_in) {
qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
int width = mp_obj_get_int(width_in);
shared_module_qrio_qrdecoder_set_width(self, width);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(qrio_qrdecoder_set_width_obj, qrio_qrdecoder_set_width);
const mp_obj_property_t qrio_qrdecoder_width_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&qrio_qrdecoder_get_width_obj,
(mp_obj_t)&qrio_qrdecoder_set_width_obj,
MP_ROM_NONE},
};
//| height: int
//| """The height of image the decoder expects"""
//|
STATIC mp_obj_t qrio_qrdecoder_get_height(mp_obj_t self_in) {
qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_int(shared_module_qrio_qrdecoder_get_height(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(qrio_qrdecoder_get_height_obj, qrio_qrdecoder_get_height);
STATIC mp_obj_t qrio_qrdecoder_set_height(mp_obj_t self_in, mp_obj_t height_in) {
qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(self_in);
int height = mp_obj_get_int(height_in);
shared_module_qrio_qrdecoder_set_height(self, height);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(qrio_qrdecoder_set_height_obj, qrio_qrdecoder_set_height);
const mp_obj_property_t qrio_qrdecoder_height_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&qrio_qrdecoder_get_height_obj,
(mp_obj_t)&qrio_qrdecoder_set_height_obj,
MP_ROM_NONE},
};
STATIC const mp_rom_map_elem_t qrio_qrdecoder_locals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_QRDecoder) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&qrio_qrdecoder_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&qrio_qrdecoder_height_obj) },
{ MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&qrio_qrdecoder_decode_obj) },
};
STATIC MP_DEFINE_CONST_DICT(qrio_qrdecoder_locals, qrio_qrdecoder_locals_table);
const mp_obj_type_t qrio_qrdecoder_type_obj = {
{ &mp_type_type },
.name = MP_QSTR_QRDecoder,
.make_new = qrio_qrdecoder_make_new,
.locals_dict = (mp_obj_dict_t *)&qrio_qrdecoder_locals,
};

View File

@ -0,0 +1,37 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
typedef struct qrio_qrdecoder_obj qrio_qrdecoder_obj_t;
extern const mp_obj_type_t qrio_qrdecoder_type_obj;
void common_hal_qrio_qrdecoder_construct(qrio_qrdecoder_obj_t *self);
mp_obj_t common_hal_qrio_qrdecoder_recognize(qrio_qrdecoder_obj_t *self, int width, int height, mp_buffer_info_t *buf);

View File

@ -0,0 +1,111 @@
/*
* This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jeff Epler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/qrio/__init__.h"
#include "shared-bindings/qrio/QRDecoder.h"
#include "py/obj.h"
#include "py/enum.h"
//| """`qrio` module.
//|
//| Provides the `QRDecoder` object."""
//|
//| class PixelPolicy:
//| EVERY_BYTE: object
//| """The input buffer to `QRDecoder.decode` consists of greyscale values in every byte"""
//|
//| EVEN_BYTES: object
//| """The input buffer to `QRDecoder.decode` consists of greyscale values in positions 0, 2, ..., and ignored bytes in positions 1, 3, ..."""
//| ODD_BYTES: object
//| """The input buffer to `QRDecoder.decode` consists of greyscale values in positions 1, 3, ..., and ignored bytes in positions 0, 2, ..."""
//|
MAKE_ENUM_VALUE(qrio_pixel_policy_type, qrio_pixel_policy, EVERY_BYTE, QRIO_EVERY_BYTE);
MAKE_ENUM_VALUE(qrio_pixel_policy_type, qrio_pixel_policy, EVEN_BYTES, QRIO_EVEN_BYTES);
MAKE_ENUM_VALUE(qrio_pixel_policy_type, qrio_pixel_policy, ODD_BYTES, QRIO_EVEN_BYTES);
MAKE_ENUM_MAP(qrio_pixel_policy) {
MAKE_ENUM_MAP_ENTRY(qrio_pixel_policy, EVERY_BYTE),
MAKE_ENUM_MAP_ENTRY(qrio_pixel_policy, EVEN_BYTES),
MAKE_ENUM_MAP_ENTRY(qrio_pixel_policy, ODD_BYTES),
};
STATIC MP_DEFINE_CONST_DICT(qrio_pixel_policy_locals_dict, qrio_pixel_policy_locals_table);
MAKE_PRINTER(qrio, qrio_pixel_policy);
MAKE_ENUM_TYPE(qrio, PixelPolicy, qrio_pixel_policy);
//| class qrinfo:
//| """Information about a decoded QR code"""
//|
//| payload: bytes
//| """The content of the QR code"""
//|
//| data_type: Union[str, int]
//| """The encoding of the payload as a string (if a standard encoding) or int (if not standard)"""
const mp_obj_namedtuple_type_t qrio_qrinfo_type_obj = {
.base = {
.base = {
.type = &mp_type_type
},
.flags = MP_TYPE_FLAG_EXTENDED,
.name = MP_QSTR_qrinfo,
.print = namedtuple_print,
.parent = &mp_type_tuple,
.make_new = namedtuple_make_new,
.attr = namedtuple_attr,
MP_TYPE_EXTENDED_FIELDS(
.unary_op = mp_obj_tuple_unary_op,
.binary_op = mp_obj_tuple_binary_op,
.subscr = mp_obj_tuple_subscr,
.getiter = mp_obj_tuple_getiter,
),
},
.n_fields = 2,
.fields = {
MP_QSTR_payload,
MP_QSTR_data_type,
},
};
STATIC const mp_rom_map_elem_t qrio_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_qrio) },
{ MP_ROM_QSTR(MP_QSTR_qrinfo), MP_ROM_PTR(&qrio_qrinfo_type_obj) },
{ MP_ROM_QSTR(MP_QSTR_QRDecoder), MP_ROM_PTR(&qrio_qrdecoder_type_obj) },
{ MP_ROM_QSTR(MP_QSTR_PixelPolicy), MP_ROM_PTR(&qrio_pixel_policy_type) },
};
STATIC MP_DEFINE_CONST_DICT(qrio_module_globals, qrio_module_globals_table);
const mp_obj_module_t qrio_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&qrio_module_globals,
};
MP_REGISTER_MODULE(MP_QSTR_qrio, qrio_module, CIRCUITPY_QRIO);

View File

@ -0,0 +1,38 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
#include "py/objnamedtuple.h"
extern const mp_obj_namedtuple_type_t qrio_qrinfo_type_obj;
extern const mp_obj_type_t qrio_pixel_policy_type;
typedef enum {
QRIO_EVERY_BYTE, QRIO_EVEN_BYTES, QRIO_ODD_BYTES
} qrio_pixel_policy_t;

View File

@ -0,0 +1,136 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/gc.h"
#include "py/objnamedtuple.h"
#include "shared-bindings/qrio/__init__.h"
#include "shared-module/qrio/QRDecoder.h"
void shared_module_qrio_qrdecoder_construct(qrdecoder_qrdecoder_obj_t *self, int width, int height) {
self->quirc = quirc_new();
quirc_resize(self->quirc, width, height);
}
int shared_module_qrio_qrdecoder_get_height(qrdecoder_qrdecoder_obj_t *self) {
int height;
quirc_begin(self->quirc, NULL, &height);
return height;
}
int shared_module_qrio_qrdecoder_get_width(qrdecoder_qrdecoder_obj_t *self) {
int width;
quirc_begin(self->quirc, &width, NULL);
return width;
}
void shared_module_qrio_qrdecoder_set_height(qrdecoder_qrdecoder_obj_t *self, int height) {
if (height != shared_module_qrio_qrdecoder_get_height(self)) {
int width = shared_module_qrio_qrdecoder_get_width(self);
quirc_resize(self->quirc, width, height);
}
}
void shared_module_qrio_qrdecoder_set_width(qrdecoder_qrdecoder_obj_t *self, int width) {
if (width != shared_module_qrio_qrdecoder_get_width(self)) {
int height = shared_module_qrio_qrdecoder_get_height(self);
quirc_resize(self->quirc, width, height);
}
}
STATIC mp_obj_t data_type(int type) {
switch (type) {
case QUIRC_ECI_ISO_8859_1:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_1);
case QUIRC_ECI_IBM437:
return MP_OBJ_NEW_QSTR(MP_QSTR_cp437);
case QUIRC_ECI_ISO_8859_2:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_2);
case QUIRC_ECI_ISO_8859_3:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_3);
case QUIRC_ECI_ISO_8859_4:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_4);
case QUIRC_ECI_ISO_8859_5:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_5);
case QUIRC_ECI_ISO_8859_6:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_6);
case QUIRC_ECI_ISO_8859_7:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_7);
case QUIRC_ECI_ISO_8859_8:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_8);
case QUIRC_ECI_ISO_8859_9:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_9);
case QUIRC_ECI_WINDOWS_874:
return MP_OBJ_NEW_QSTR(MP_QSTR_cp874);
case QUIRC_ECI_ISO_8859_13:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_13);
case QUIRC_ECI_ISO_8859_15:
return MP_OBJ_NEW_QSTR(MP_QSTR_iso_8859_hyphen_15);
case QUIRC_ECI_SHIFT_JIS:
return MP_OBJ_NEW_QSTR(MP_QSTR_shift_underscore_jis);
case QUIRC_ECI_UTF_8:
return MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8);
}
return mp_obj_new_int(type);
}
mp_obj_t shared_module_qrio_qrdecoder_decode(qrdecoder_qrdecoder_obj_t *self, const mp_buffer_info_t *bufinfo, qrio_pixel_policy_t policy) {
int width, height;
uint8_t *framebuffer = quirc_begin(self->quirc, &width, &height);
uint8_t *src = bufinfo->buf;
switch (policy) {
case QRIO_EVERY_BYTE:
memcpy(framebuffer, src, width * height);
break;
case QRIO_ODD_BYTES:
src++;
MP_FALLTHROUGH;
case QRIO_EVEN_BYTES:
for (int i = 0; i < width * height; i++) {
framebuffer[i] = src[2 * i];
}
}
quirc_end(self->quirc);
int count = quirc_count(self->quirc);
mp_obj_t result = mp_obj_new_list(0, NULL);
for (int i = 0; i < count; i++) {
quirc_extract(self->quirc, i, &self->code);
if (quirc_decode(&self->code, &self->data) != QUIRC_SUCCESS) {
continue;
}
mp_obj_t elems[2] = {
mp_obj_new_bytes(self->data.payload, self->data.payload_len),
data_type(self->data.data_type),
};
mp_obj_t code_obj = namedtuple_make_new((const mp_obj_type_t *)&qrio_qrinfo_type_obj, 2, elems, NULL);
mp_obj_list_append(result, code_obj);
}
return result;
}

View File

@ -0,0 +1,44 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
#include "lib/quirc/lib/quirc.h"
typedef struct qrio_qrdecoder_obj {
mp_obj_base_t base;
struct quirc *quirc;
struct quirc_code code;
struct quirc_data data;
} qrdecoder_qrdecoder_obj_t;
void shared_module_qrio_qrdecoder_construct(qrdecoder_qrdecoder_obj_t *, int width, int height);
int shared_module_qrio_qrdecoder_get_height(qrdecoder_qrdecoder_obj_t *);
int shared_module_qrio_qrdecoder_get_width(qrdecoder_qrdecoder_obj_t *);
void shared_module_qrio_qrdecoder_set_height(qrdecoder_qrdecoder_obj_t *, int height);
void shared_module_qrio_qrdecoder_set_width(qrdecoder_qrdecoder_obj_t *, int width);
mp_obj_t shared_module_qrio_qrdecoder_decode(qrdecoder_qrdecoder_obj_t *, const mp_buffer_info_t *bufinfo, qrio_pixel_policy_t policy);

View File

View File

@ -0,0 +1,12 @@
#pragma once
#include "py/gc.h"
#if !MICROPY_GC_CONSERVATIVE_CLEAR
// so that we can implement calloc as m_malloc
#error Requires MICROPY_GC_CONSERVATIVE_CLEAR
#endif
#define QUIRC_MALLOC(x) gc_alloc((x), 0, false)
#define QUIRC_CALLOC(x,y) gc_alloc((x) * (y), 0, false)
#define QUIRC_FREE(x) gc_free((x))