Skip to content

Commit 5a05457

Browse files
add qrdecode_rgb565
1 parent 2534efb commit 5a05457

File tree

1 file changed

+59
-58
lines changed

1 file changed

+59
-58
lines changed

c_mpos/src/quirc_decode.c

Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,158 @@
11
#include <stdio.h>
2-
#include <stdlib.h> // For malloc and free
2+
#include <stdlib.h>
33
#include <string.h>
4-
4+
#include <stdint.h>
55
#include "py/obj.h"
66
#include "py/runtime.h"
77
#include "py/mperrno.h"
88

99
#ifdef __xtensa__
10-
#include "freertos/FreeRTOS.h" // For uxTaskGetStackHighWaterMark
11-
#include "freertos/task.h" // For task-related functions
10+
#include "freertos/FreeRTOS.h"
11+
#include "freertos/task.h"
1212
#else
1313
size_t uxTaskGetStackHighWaterMark(void * unused) {
1414
return 99999999;
1515
}
16-
#endif // __xtensa__
16+
#endif
1717

1818
#include "../quirc/lib/quirc.h"
1919

20-
#define QRDECODE_DEBUG_PRINT(...) mp_printf(&mp_plat_print, __VA_ARGS__);
20+
#define QRDECODE_DEBUG_PRINT(...) mp_printf(&mp_plat_print, __VA_ARGS__)
2121

22-
// Function to decode a QR code from a grayscale image buffer
2322
static mp_obj_t qrdecode(mp_uint_t n_args, const mp_obj_t *args) {
2423
QRDECODE_DEBUG_PRINT("qrdecode: Starting\n");
2524
QRDECODE_DEBUG_PRINT("qrdecode: Stack high-water mark: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
2625

27-
// Check argument count (expecting buffer, width, height)
28-
QRDECODE_DEBUG_PRINT("qrdecode: Checking argument count\n");
2926
if (n_args != 3) {
3027
mp_raise_ValueError(MP_ERROR_TEXT("quirc_decode expects 3 arguments: buffer, width, height"));
3128
}
3229

33-
// Extract buffer
34-
QRDECODE_DEBUG_PRINT("qrdecode: Extracting buffer\n");
3530
mp_buffer_info_t bufinfo;
3631
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
3732

38-
// Extract width and height
39-
QRDECODE_DEBUG_PRINT("qrdecode: Extracting width and height\n");
4033
mp_int_t width = mp_obj_get_int(args[1]);
4134
mp_int_t height = mp_obj_get_int(args[2]);
4235
QRDECODE_DEBUG_PRINT("qrdecode: Width=%u, Height=%u\n", width, height);
4336

44-
// Validate dimensions
45-
QRDECODE_DEBUG_PRINT("qrdecode: Validating dimensions\n");
4637
if (width <= 0 || height <= 0) {
4738
mp_raise_ValueError(MP_ERROR_TEXT("width and height must be positive"));
4839
}
4940
if (bufinfo.len != (size_t)(width * height)) {
5041
mp_raise_ValueError(MP_ERROR_TEXT("buffer size must match width * height"));
5142
}
52-
QRDECODE_DEBUG_PRINT("qrdecode: Dimensions validated\n");
5343

54-
// Initialize quirc
55-
QRDECODE_DEBUG_PRINT("qrdecode: Initializing quirc\n");
5644
struct quirc *qr = quirc_new();
5745
if (!qr) {
5846
mp_raise_OSError(MP_ENOMEM);
5947
}
60-
QRDECODE_DEBUG_PRINT("qrdecode: quirc initialized\n");
6148

62-
// Resize quirc for the image dimensions
63-
QRDECODE_DEBUG_PRINT("qrdecode: Resizing quirc\n");
6449
if (quirc_resize(qr, width, height) < 0) {
6550
quirc_destroy(qr);
6651
mp_raise_OSError(MP_ENOMEM);
6752
}
68-
QRDECODE_DEBUG_PRINT("qrdecode: quirc resized\n");
6953

70-
// Get quirc image buffer and copy grayscale data
71-
QRDECODE_DEBUG_PRINT("qrdecode: Beginning quirc processing\n");
7254
uint8_t *image;
7355
quirc_begin(qr, NULL, NULL);
74-
image = quirc_begin(qr, NULL, NULL); // Get pointer to quirc's image buffer
75-
QRDECODE_DEBUG_PRINT("qrdecode: quirc image buffer obtained\n");
76-
QRDECODE_DEBUG_PRINT("qrdecode: Copying buffer, size=%u\n", (size_t)(width * height));
56+
image = quirc_begin(qr, NULL, NULL);
7757
memcpy(image, bufinfo.buf, width * height);
78-
QRDECODE_DEBUG_PRINT("qrdecode: Buffer copied\n");
7958
quirc_end(qr);
80-
QRDECODE_DEBUG_PRINT("qrdecode: quirc processing ended\n");
8159

82-
// Check for QR codes
83-
QRDECODE_DEBUG_PRINT("qrdecode: Counting QR codes\n");
84-
QRDECODE_DEBUG_PRINT("qrdecode: Stack high-water mark: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
8560
int count = quirc_count(qr);
86-
QRDECODE_DEBUG_PRINT("qrdecode: Found %d QR codes\n", count);
87-
QRDECODE_DEBUG_PRINT("qrdecode: Stack high-water mark: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
8861
if (count == 0) {
8962
quirc_destroy(qr);
9063
mp_raise_ValueError(MP_ERROR_TEXT("no QR code found"));
9164
}
9265

93-
// Extract and decode the first QR code
94-
QRDECODE_DEBUG_PRINT("qrdecode: Extracting first QR code\n");
9566
struct quirc_code *code = (struct quirc_code *)malloc(sizeof(struct quirc_code));
9667
if (!code) {
9768
quirc_destroy(qr);
9869
mp_raise_OSError(MP_ENOMEM);
9970
}
100-
QRDECODE_DEBUG_PRINT("qrdecode: Allocated quirc_code on heap\n");
101-
QRDECODE_DEBUG_PRINT("qrdecode: Stack high-water mark: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
10271
quirc_extract(qr, 0, code);
103-
QRDECODE_DEBUG_PRINT("qrdecode: QR code extracted\n");
104-
QRDECODE_DEBUG_PRINT("qrdecode: Stack high-water mark: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
105-
// it works until here!
10672

107-
// Decode the QR code - this is the part that fails:
108-
QRDECODE_DEBUG_PRINT("qrdecode: Decoding QR code\n");
10973
struct quirc_data *data = (struct quirc_data *)malloc(sizeof(struct quirc_data));
11074
if (!data) {
11175
free(code);
11276
quirc_destroy(qr);
11377
mp_raise_OSError(MP_ENOMEM);
11478
}
115-
QRDECODE_DEBUG_PRINT("qrdecode: Allocated quirc_data on heap\n");
116-
QRDECODE_DEBUG_PRINT("qrdecode: Stack high-water mark: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
11779
int err = quirc_decode(code, data);
11880
if (err != QUIRC_SUCCESS) {
11981
free(data);
12082
free(code);
12183
quirc_destroy(qr);
12284
mp_raise_ValueError(MP_ERROR_TEXT("failed to decode QR code"));
12385
}
124-
QRDECODE_DEBUG_PRINT("qrdecode: QR code decoded, payload_len=%d\n", data->payload_len);
125-
QRDECODE_DEBUG_PRINT("qrdecode: Stack high-water mark: %u bytes\n", uxTaskGetStackHighWaterMark(NULL));
126-
//QRDECODE_DEBUG_PRINT("qrdecode: got result: %s\n", data->payload);
12786

128-
// Convert decoded data to Python string
129-
QRDECODE_DEBUG_PRINT("qrdecode: Creating Python string\n");
13087
mp_obj_t result = mp_obj_new_bytes((const uint8_t *)data->payload, data->payload_len);
131-
QRDECODE_DEBUG_PRINT("qrdecode: Python string created\n");
13288

133-
// Clean up
134-
QRDECODE_DEBUG_PRINT("qrdecode: Cleaning up\n");
13589
free(data);
13690
free(code);
13791
quirc_destroy(qr);
138-
QRDECODE_DEBUG_PRINT("qrdecode: quirc destroyed, returning result\n");
13992
return result;
14093
}
14194

142-
// Wrapper function to fix incompatible pointer type warning
95+
static mp_obj_t qrdecode_rgb565(mp_uint_t n_args, const mp_obj_t *args) {
96+
QRDECODE_DEBUG_PRINT("qrdecode_rgb565: Starting\n");
97+
98+
if (n_args != 3) {
99+
mp_raise_ValueError(MP_ERROR_TEXT("qrdecode_rgb565 expects 3 arguments: buffer, width, height"));
100+
}
101+
102+
mp_buffer_info_t bufinfo;
103+
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
104+
105+
mp_int_t width = mp_obj_get_int(args[1]);
106+
mp_int_t height = mp_obj_get_int(args[2]);
107+
QRDECODE_DEBUG_PRINT("qrdecode_rgb565: Width=%u, Height=%u\n", width, height);
108+
109+
if (width <= 0 || height <= 0) {
110+
mp_raise_ValueError(MP_ERROR_TEXT("width and height must be positive"));
111+
}
112+
if (bufinfo.len != (size_t)(width * height * 2)) {
113+
mp_raise_ValueError(MP_ERROR_TEXT("buffer size must match width * height * 2 for RGB565"));
114+
}
115+
116+
uint8_t *gray_buffer = (uint8_t *)malloc(width * height * sizeof(uint8_t));
117+
if (!gray_buffer) {
118+
mp_raise_OSError(MP_ENOMEM);
119+
}
120+
121+
uint16_t *rgb565 = (uint16_t *)bufinfo.buf;
122+
for (size_t i = 0; i < (size_t)(width * height); i++) {
123+
uint16_t pixel = rgb565[i];
124+
uint8_t r = ((pixel >> 11) & 0x1F) << 3;
125+
uint8_t g = ((pixel >> 5) & 0x3F) << 2;
126+
uint8_t b = (pixel & 0x1F) << 3;
127+
gray_buffer[i] = (uint8_t)((0.299 * r + 0.587 * g + 0.114 * b) + 0.5);
128+
}
129+
130+
mp_obj_t gray_args[3] = {
131+
mp_obj_new_bytes(gray_buffer, width * height),
132+
mp_obj_new_int(width),
133+
mp_obj_new_int(height)
134+
};
135+
136+
mp_obj_t result = qrdecode(3, gray_args);
137+
free(gray_buffer);
138+
return result;
139+
}
140+
143141
static mp_obj_t qrdecode_wrapper(size_t n_args, const mp_obj_t *args) {
144142
return qrdecode(n_args, args);
145143
}
146144

147-
// Define the MicroPython function
145+
static mp_obj_t qrdecode_rgb565_wrapper(size_t n_args, const mp_obj_t *args) {
146+
return qrdecode_rgb565(n_args, args);
147+
}
148+
148149
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qrdecode_obj, 3, 3, qrdecode_wrapper);
150+
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(qrdecode_rgb565_obj, 3, 3, qrdecode_rgb565_wrapper);
149151

150-
// Module definition
151152
static const mp_rom_map_elem_t qrdecode_module_globals_table[] = {
152153
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_qrdecode) },
153154
{ MP_ROM_QSTR(MP_QSTR_qrdecode), MP_ROM_PTR(&qrdecode_obj) },
155+
{ MP_ROM_QSTR(MP_QSTR_qrdecode_rgb565), MP_ROM_PTR(&qrdecode_rgb565_obj) },
154156
};
155157

156158
static MP_DEFINE_CONST_DICT(qrdecode_module_globals, qrdecode_module_globals_table);
@@ -160,5 +162,4 @@ const mp_obj_module_t qrdecode_module = {
160162
.globals = (mp_obj_dict_t *)&qrdecode_module_globals,
161163
};
162164

163-
// Register the module
164165
MP_REGISTER_MODULE(MP_QSTR_qrdecode, qrdecode_module);

0 commit comments

Comments
 (0)