Skip to content

feat(io): have a fast 2D file writer

Didier WECKMANN requested to merge 950-feat-io-have-a-fast-2d-file-writer into dev

Description

A "fast" 2D image writer (sight::io::bitmap::Writer) and its associated service (sight::module::io::bitmap::SWriter) have been implemented. The writer uses NVidia CUDA accelerated JPEG / JPEG2000 encoding library: nvJPEG, if support has been compiled in and if a suitable GPU has been found. Alternatively, libjpeg-turbo, openJPEG, libtiff or libPNG can be used as CPU fallback. The performance should be better than VTK or even OpenCV because of direct API calls and avoided unneeded buffer copy.

VTK SImageWriter support for 2D bitmap format has been removed. The support was anyway bugged as the image were saved upsode down.

also added:

  • fix on LocationDialog::getCurrentSelection() that erased the first char to return an extension from a wildcard filter. Now there is a ILocationDialog::getSelectedExtensions() that returns a vector of extension, in case there are more than one extension from a filter.
  • some small fix for high dpi displays in the GUI tester code.

Library

nvJPEG, nvJPEG2K, libjpeg-turbo, libtiff and libPNG backends have a FAST and a BEST mode. FAST compress faster and BEST compress better, at the expanse of the speed. Options that affect quality are, for lossy codecs, set to the maximum the codec can provide.

Take a look at source code / doxygen comment and io_bitmapTest for a clue how to use the writer and select the codec and the mode.

Service

The service can be configured to select backends to use in several ways. Either you set the enable attribute of <backends> node to "all" or "cpu" or "gpu":

<config>
    <dialog description="Snapshot" policy="default" />
    <backends enable="all" mode="best"/>
</config>

Or you can specify explicitly the backend by name (i.e.: "libtiff", "libpng", "nvjpeg", ...). In all case you can also specify the mode, independently, for each backend:

<config>
    <dialog description="Snapshot" policy="default" />
    <backends mode="fast">
        <libtiff mode="best">
        <nvjpeg2k>
    </backends>
</config>

Take a look at module_io_bitmapTest for more example.

Closes #950 (closed)

How to test it?

  • Launch io_bitmapTest and module_io_bitmapTest, preferably after having enabled SIGHT_ENABLE_NVJPEG2K CMake option.

Some results

Some bugs have been corrected and affect png (fast mode is now really faster ~74 -> ~150 FPS, but compress slightly less) and nvJPEG (also a lilltle bit faster).

1000 iterations on 3 images coming from real US imager (GE lossy jpg, Acuson 500 lossy jpg and lossless raw)

BITMAPWRITERTEST_LOOP=1000 ./io_nvjpegtest && cat ./fwTest.log
CODEC Size (Byte) Time (ms) FPS PSNR
NVJPEG 662596 2,26 1330 51,61
LIBJPEG (F) 482892 4,12 728 41,97
LIBJPEG (B) 451837 10,65 282 41,97
OpenCV JPG 451837 12,53 239 41,97
NVJPEG2K (F) 703577 48,31 62
NVJPEG2K (B) 692651 89,10 34
OPENJPEG 692807 137,08 22
LIBTIFF (F) 1785304 6,74 445
LIBTIFF (B) 865902 8,49 353
OpenCV TIFF 1030046 25,51 118
LIBPNG (F) 691232 40,42 74
LIBPNG (B) 666602 100,55 30
OpenCV PNG (F) 944226 31,19 96
OpenCV PNG (B) 805060 546,32 5
OpenCV WEBP 603258 583,27 5

compression_lossy

For "lossy" codec:

  • NVJPEG speed is from another galaxy, and its quality is considered as "visually" lossless with an average PSNR > 50.
  • Pure CPU libjpeg-turbo can also be fast, but the maximum quality is inferior.
  • OpenCV also uses libjpeg-turbo, but since it involves some additional conversion steps, it is logically a bit slower, but still quite good. (VTK - not listed here - is more than 5 time slower !)

compression_lossless

For "lossless" codec:

  • NVJPEG2K speed and compression ratio are, in overall, good, even if we cannot say it is the faster, nor the smaller. Still, it is nearly 3 time faster than the pure CPU openJPEG.
  • LibTIFF, especially the "Best" variant (which use ZSTD as its compression engine) is a good alternative. It is the faster lossless CODEC, while still having some compression, and even largely beats openCV "Fast" PNG in both speed AND compression ratio. It is definitively my recommendation when CUDA is not available.
  • LibPNG offers interesting compression ratio in "Best" mode and is even fast enough in "Fast" mode.
  • OpenCV PNG is fast is really fast, but without great compression, and "Best" mode is horribly slow. No point to use it against LibTIFF "Best" mode when searching for speed, no point to use it against LibPNG when searching for compression ratio.
  • Webp compress very well, it is the best in that regard for the lossless encoders, ...but very slowly. Just too slow for real time application. It could have its usage for long live storage, if its reading speed is fast enough (that must be tested...).
Edited by Didier WECKMANN

Merge request reports