OpenCV vs ImageMagick
Ajwad Imran / July 11, 2021
4 min read
Before we begin this comparison, I would like to share the I have used both libraries in production apps where thousands of users utilized features built on top of these libraries.
Background 📝
Back in 2018, when I joined Quixel I was tasked with building an image processor that can resize images, change image formats, channel pack textures, and gamma correct images. After discussing with other engineers we decided to use ImageMagick because it supports all the platforms that we ship Quixel Bridge on i.e. Windows, Mac, and Linux (Ubuntu/Cent).
Channel packing is widely used in games due to its optimization benefits. We don't have to sample separate textures for the data that they carry e.g. In the screenshot below we are channel packing Roughness, Metalness, and Displacement texture into a single file because all three of these are grayscale textures (contains the same data in RGB channels).
ImageMagick - Quixel Bridge Image Processor Version 1
ImageMagick is a really big time saver and it was straightforward to start using it to manipulate images. We didn't run into any issues shipping the ImageMagick binary with Quixel Bridge except for Mac OS where we had to use an older version of ImageMagick and sign the binary manually.
The biggest challenge was channel packing textures with ImageMagick since we cannot hold extracted channels in the memory to merge them later so we had to extract the channel and write the data to a temporary file. Read/Write operations did add to the whole processing time and on top of that image magick is not the fastest library out there.
It took us about two months to fully integrate it in Bridge (this includes time to design/implement frontend and testing of this feature.) and it could handle the following tasks:
- Channel pack textures.
- Apply gamma correction.
- Resize images.
- Convert 16-bit textures to 8-bit textures.
- Convert between the following formats: JPG/PNG/TGA/TIFF.
OpenCV - Quixel Bridge Image Processor Version 2
Pretty soon everyone realized that we need something that could process textures really fast and support more formats like EXR and 32-bit depth textures. I was tasked to research this a little bit and I was mainly considering two libraries i.e. FreeImage and OpenCV. FreeImage is being used in Quixel Mixer so I knew it can handle everything that we want but it was not as flexible as OpenCV.
After some initial tests, I proposed that we use OpenCV to build a standalone command-line tool and everyone liked the idea so we started building the second version of Image Processor using OpenCV / Python. I used OpenEXR
to add the support for EXR images and Numpy
to process textures super fast. Numpy really saved processing time e.g. Gamma correction on 8K texture was taking 33 seconds but numpy cut that time to less than 3 seconds which is bonkers.
Building binaries for Windows, Linux, and Mac presented some small challenges but we managed to overcome them easily.
It took us about four months to fully integrate it in Bridge since we had to define each process carefully but if you ask me was it worth it. I would say yes because not only we added support for new features but it was 2x-8x faster compared to its ImageMagick counterpart. Since it is a command-line tool we started using it in the Megascans pipeline too.
It could handle the following tasks:
- Channel pack textures.
- Apply gamma correction.
- Resize images.
- Convert between following bit depth: 8/16/32-bit.
- Convert between the following formats: JPG/PNG/TGA/TIFF/EXR.
Conclusion
OpenCV demands a little more time but it is worth it. ImageMagick is also a good library and you can ship really fast using it but unless you spend some time optimizing its source code it is not a viable option for production apps.