How to decode an image using Emscripten?
Hi, I've been trying to use OpenCV as a dependency in an Emscripten project.
Currently I'm having an issue with trying to decode an image.
When I try to use cv::imdecode(buf, flags)
I get the compilation (EDIT linker) error:
error: undefined symbol: _ZN2cv8imdecodeERKNS_11_InputArrayEi
The exact code I'm using is available on github, I've set up a minimalist example here: https://github.com/mpizenberg/emscrip...
The line causing the linker error is the commented line in hello.cpp
:
// this->decoded = cv::imdecode(this->buffer, IMREAD_GRAYSCALE);
I don't know what is the reason of this issue. Is there another way I can decode an image from a raw u8 buffer?
EDIT 1
As @berak commented I need to link to libopencv_imgcodecs.a
. But unfortunately this opens new undefined symbol
issues. In details, here is what I did.
- There is a line
"DBUILD_opencv_imgcodecs=OFF"
in thebuild_js.py
script file. So I've switched that toON
. - I deleted
build_wasm/
and rebuild it from scratch. Surprisingly, It did not created thelibopencv_imgcodecs.a
file. Apparently the build created the correct make files but I had to do amake
insidebuild_wasm/
to actually compile and produce thelibopencv_imgcodecs.a
file. I'll make a dedicated issue regarding that behavior on Github if that's ok. - In my repo files, cleaned
build/
dir and recompiled my project. That's when I get an awful lot of newundefined symbol
errors.
The new linking issues:
~/t/e/opencv * build emmake make
Scanning dependencies of target hello
[ 50%] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[100%] Linking CXX executable hello.js
error: undefined symbol: _Z7cvRoundRKN2cv10softdoubleE
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
error: undefined symbol: _Z7cvRoundRKN2cv9softfloatE
error: undefined symbol: _Z7cvTruncRKN2cv9softfloatE
error: undefined symbol: _ZN2cv10softdoubleC1Ei
error: undefined symbol: _ZN2cv3powERKNS_10softdoubleES2_
...
Error: Aborting compilation due to previous errors
shared:ERROR: '/home/matthieu/programs/emsdk/node/8.9.1_64bit/bin/node /usr/lib/emscripten/src/compiler.js /tmp/tmputw1eyfv.txt /usr/lib/emscripten/src/embind/emval.js /usr/lib/emscripten/src/embind/embind.js /usr/lib/emscripten/src/library_pthread_stub.js' failed (1)
make[2]: *** [CMakeFiles/hello.dir/build.make:97: hello.js] Error 1
make[1]: *** [CMakeFiles/Makefile2:73: CMakeFiles/hello.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
EDIT 2
Ok, so from reading parts of OpenCV.js tutorial, I realized that reading images was always done from already decoded data in a canvas (cf https://github.com/opencv/opencv/blob...). So I guess even though we can compile imgcodecs apparently, it does not include all the functionalities. I can't use canvas because I need decoding of 16bits png.
I've tried reading libpng doc (because that is the only format I need reading for now) and it is not very pleasant ... At least it seems to be already integrated with emscripten (https://github.com/emscripten-core/em...)
nope, that's a LINKER error.
a c++ program would need to link to
libopencv_imgcodecs.a
, where the actual code is.then, imdecode() is just a shallow wrapper about like a dozen 3rd party libs (think, libjpeg, libtiff, libpng, etc.) ,which do the actual job of decompressing various image codecs, -- good luck with your js effort ;(
main question i have here: why start from scratch ?
Ah yes, thanks for the correction. Regarding
libopencv_imgcodecs.a
I realized it was missing frombuild_wasm/lib
, so I edited"-DBUILD_opencv_imgcodecs=ON"
in thebuild_js.py
. Fun fact, after running OpenCV.js build, it was still missing (yet it created the make rules for it). I had to manually do amake
inside thebuild_wasm/
directory to buildlib/libopencv_imgcodecs.a
. Unfortunately this opened a can ofundefined symbol
:'(. I've updated the question with that info.Ah yes, well I had already read the Build OpenCV.js tutorial but didn't actually went to the other sections. I supposed it was for using the opencv.js directly in JavaScript. Ultimately I'm interesting in building some RGB-D slam algo the rely on OpenCV for few operations, including image decoding. But I'm probably wrong in supposing reading those tutorial won't be useful. So I'm gonna do that tomorrow!
Ok, so from reading parts of OpenCV.js tutorial, I realized that reading images was always done from already decoded data in a canvas (cf https://github.com/opencv/opencv/blob...). So I guess even though we can compile imgcodecs apparently, it does not include all the functionalities. I can't use canvas because I need decoding of 16bits png.
I've tried reading libpng doc (because that is the only format I need reading for now) and it is not very pleasant ... At least it seems to be already integrated with emscripten (https://github.com/emscripten-core/em...)