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
1313size_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
2322static 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+
143141static 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+
148149static 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
151152static 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
156158static 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
164165MP_REGISTER_MODULE (MP_QSTR_qrdecode , qrdecode_module );
0 commit comments