How to decode an image using Emscripten?

asked 2019-04-30 14:21:12 -0600

Mattpiz gravatar image

updated 2019-05-02 04:09:13 -0600

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.

  1. There is a line "DBUILD_opencv_imgcodecs=OFF" in the build_js.py script file. So I've switched that to ON.
  2. I deleted build_wasm/ and rebuild it from scratch. Surprisingly, It did not created the libopencv_imgcodecs.a file. Apparently the build created the correct make files but I had to do a make inside build_wasm/ to actually compile and produce the libopencv_imgcodecs.a file. I'll make a dedicated issue regarding that behavior on Github if that's ok.
  3. In my repo files, cleaned build/ dir and recompiled my project. That's when I get an awful lot of new undefined 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...)

edit retag flag offensive close merge delete

Comments

1

I get the compilation error

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 ;(

berak gravatar imageberak ( 2019-04-30 14:48:37 -0600 )edit

main question i have here: why start from scratch ?

berak gravatar imageberak ( 2019-04-30 15:51:34 -0600 )edit

Ah yes, thanks for the correction. Regarding libopencv_imgcodecs.a I realized it was missing from build_wasm/lib, so I edited "-DBUILD_opencv_imgcodecs=ON" in the build_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 a make inside the build_wasm/ directory to build lib/libopencv_imgcodecs.a. Unfortunately this opened a can of undefined symbol :'(. I've updated the question with that info.

Mattpiz gravatar imageMattpiz ( 2019-04-30 16:54:13 -0600 )edit

"main question i have here: why start from scratch ?"

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!

Mattpiz gravatar imageMattpiz ( 2019-04-30 17:04:05 -0600 )edit

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...)

Mattpiz gravatar imageMattpiz ( 2019-05-02 04:07:02 -0600 )edit