@@ -13,6 +13,25 @@ extern "C" {
1313
1414using namespace cv ;
1515
16+ // Fix for https://github.com/sparkfun/micropython-opencv/issues/17
17+ //
18+ // TLDR; The `g_codecs` object (which stores all image encoders and decoders) is
19+ // allocated once, whenever the first OpenCV function that needs it happens to
20+ // be called. That will only happen from the user's code, after the GC has been
21+ // initialized, meaning it gets allocated on the GC heap (see `__wrap_malloc()`)
22+ // If a soft reset occurs, the GC gets reset and overwrites the memory location,
23+ // but the same memory location is still referenced for the the `g_codecs`
24+ // object, resulting in bogus values and subsequent `imread()` and `imwrite()`
25+ // calls fail
26+ //
27+ // The solution here is to create a global variable that subsequently creates
28+ // the `g_codecs` object before the GC has been initialized, so it's allocated
29+ // on the C heap and persists through soft resets. `g_codecs` is initialized
30+ // when calling `getCodecs()`, which is not publicly exposed. The next best
31+ // option is to call `haveImageWriter()`, which calls `findEncoder()`, which
32+ // calls `getCodecs()`
33+ volatile bool haveImageWriterPNG = haveImageWriter(" .png" );
34+
1635// Helper macro to create an empty mp_map_t, derived from MP_DEFINE_CONST_MAP.
1736// Primarily used for function calls with no keyword arguments, since we can't
1837// just pass `NULL` or mp_const_none (crash occurs otherwise)
0 commit comments