Every number here was measured on real camera files with the tools in this repository, and can be reproduced with them. FlashRaw is compared, on the same files and the same machines, with the open-source RAW decoders people use today, each built from source (or installed the way its users install it):
- LibRaw, the most widely used RAW library (C++), decode and its
dcraw_process()development to RGB; - the LibRaw + Little CMS pipeline: LibRaw develops to a linear wide-gamut image and the Little CMS colour-management engine converts it to sRGB, the usual way to get colour-managed output from LibRaw (Little CMS is not a RAW decoder: it is measured as that pipeline's colour stage);
- RawSpeed, darktable's decoder (C++, raw data only);
- rawler, the Rust decoder of
dnglab, decode and its
RawDeveloppipeline; - rawpy, the Python binding of LibRaw (what a Python user
gets from
pip install rawpy); - dcraw, the C program LibRaw grew out of.
Median speedup of FlashRaw over the 62 files of
benches/popular-cameras.tsv (other library's time ÷
FlashRaw's on the same file; > 1 = FlashRaw faster), its geometric mean, and the number of
files where FlashRaw is faster, out of the files both decode. dcraw has no threads: its
one-thread time is used in the all-cores rows.
| Comparison | threads | 🐧 median | 🐧 geomean | 🐧 FlashRaw faster | 🍎 median | 🍎 geomean | 🍎 FlashRaw faster |
|---|---|---|---|---|---|---|---|
| decode vs LibRaw | all | 7.87× | 6.20× | 57/59 | 11.4× | 9.11× | 59/59 |
| decode vs LibRaw | 1 | 2.90× | 2.40× | 57/59 | 1.81× | 2.02× | 57/59 |
| decode vs RawSpeed | all | 2.15× | 2.00× | 46/49 | 1.50× | 2.00× | 38/49 |
| decode vs RawSpeed | 1 | 1.29× | 1.27× | 41/49 | 0.83× | 0.85× | 13/49 |
| decode vs rawler | all | 2.95× | 2.61× | 58/59 | 2.66× | 3.08× | 58/59 |
| decode vs rawler | 1 | 1.66× | 1.71× | 57/59 | 1.50× | 1.54× | 56/59 |
| decode vs rawpy | all | 8.37× | 6.74× | 58/59 | 14.3× | 13.6× | 59/59 |
| decode vs rawpy | 1 | 3.08× | 2.61× | 58/59 | 1.85× | 2.07× | 57/59 |
| decode vs dcraw | all | 14.5× | 14.3× | 42/42 | 29.1× | 27.6× | 42/42 |
| decode vs dcraw | 1 | 3.72× | 3.99× | 40/42 | 3.98× | 4.24× | 40/42 |
| RAW→RGB vs LibRaw | all | 8.81× | 7.91× | 59/59 | 15.4× | 14.1× | 59/59 |
| RAW→RGB vs LibRaw | 1 | 2.06× | 1.88× | 59/59 | 1.77× | 1.74× | 59/59 |
| RAW→sRGB vs LibRaw + Little CMS | all | 15.0× | 15.0× | 59/59 | 21.8× | 19.9× | 59/59 |
| RAW→sRGB vs LibRaw + Little CMS | 1 | 12.8× | 12.2× | 59/59 | 10.6× | 11.0× | 59/59 |
| RAW→RGB vs rawler | all | 6.56× | 6.42× | 58/59 | 6.67× | 5.81× | 58/59 |
| RAW→RGB vs rawler | 1 | 4.70× | 4.38× | 58/59 | 3.61× | 3.55× | 58/59 |
| RAW→RGB vs rawpy | all | 9.50× | 8.72× | 59/59 | 20.5× | 17.3× | 59/59 |
| RAW→RGB vs rawpy | 1 | 2.20× | 2.09× | 59/59 | 1.77× | 1.75× | 59/59 |
| RAW→RGB vs dcraw | all | 9.98× | 9.17× | 42/42 | 23.0× | 19.0× | 42/42 |
| RAW→RGB vs dcraw | 1 | 1.98× | 1.81× | 40/42 | 1.95× | 1.87× | 40/42 |
| RAW→RGB, FlashRaw GPU vs LibRaw | all | – | – | – | 17.9× | 17.1× | 52/52 |
- With all cores FlashRaw is the fastest decoder on almost every file. It decodes in parallel even the codecs whose data is one sequential stream (lossless JPEG, Nikon, Pentax, Hasselblad, Panasonic v8, Sony ARW1), which the others decode on one thread; LibRaw parallelises only its CR3, Fuji-compressed and Panasonic v8 decoders.
- RAW → sRGB is where the gap is largest: FlashRaw develops in one fused, multithreaded pass, where LibRaw (and rawpy, which is LibRaw), dcraw and rawler run several full-image passes (LibRaw's and dcraw's mostly on one thread). Colour management with Little CMS adds yet another full-image pass to a LibRaw pipeline (see the stages).
- On one thread the decoders are much closer, and RawSpeed is often as fast or faster, especially on Apple Silicon; see where FlashRaw is not the fastest.
- Charts:
charts/(generated bytools/bench/charts.py, numbers incharts/data.json). Raw data and the full per-machine reports:benches/results/.
| Library | Version, build | decode | RAW → RGB |
|---|---|---|---|
| FlashRaw | this repository, version 0.1.0 (the development tree at the time of the runs; the commit the results were produced from was rewritten out of the history, so the exact state is not recorded — reproduce with the commands below), cargo build --release -p flashraw-cli --features jpegxl (+ gpu on macOS) |
flashraw benchmark --output raw-u16 --backend simd: open + full sensor decode to 16-bit samples, CPU |
--output rgba8 --backend simd: decode + bilinear demosaic + as-shot WB + colour matrix + sRGB 8-bit RGBA + orientation, one fused pass |
| FlashRaw GPU (macOS) | same, --features gpu |
– | --backend gpu --output rgba8: CPU decode (or GPU unpack for packed data), Metal develop, image downloaded to host memory |
| LibRaw | 0.22.0, its Makefile.dist, -O3 (+ -march=native on x86-64), zlib; all cores = OpenMP build, 1 thread = default build |
open_buffer() + unpack() |
+ dcraw_process() (user_qual=0 bilinear, use_camera_wb=1, output_bps=8, sRGB) + dcraw_make_mem_image() |
| LibRaw + Little CMS | LibRaw as above + Little CMS 2.19.1 (static, -O3) |
– | LibRaw unpack() + dcraw_process() to 16-bit linear ProPhoto RGB (bilinear, camera WB, gamm = 1, 1, no_auto_bright) + dcraw_make_mem_image(), then an lcms2 transform (linear ProPhoto → sRGB IEC 61966-2.1, perceptual, TYPE_RGB_16 → TYPE_RGBA_8); profiles and transform created per image. All cores: the transform runs over 32-row blocks with OpenMP (a shared transform is reentrant); 1 thread: one cmsDoTransform call |
| RawSpeed | develop c835b05, CMake Release, WITH_OPENMP=ON, WITH_JPEG=OFF (+ -march=native on x86-64) |
RawParser::getDecoder() + checkSupport() + decodeRaw() + decodeMetaData() |
no RGB pipeline |
| rawler (dnglab) | 0.8.0 from crates.io, cargo build --release, rayon |
rawler::decode() of an in-memory source: sensor data + metadata |
+ RawDevelop::default().develop_intermediate() (scaling, PPG demosaic, WB, camera matrix, crop, sRGB gamma, f32) + conversion to 8-bit RGB |
| rawpy | 0.27.1 wheel from PyPI (bundles LibRaw 0.22.1), CPython 3.13 (Linux), 3.9 (macOS) | rawpy.imread(BytesIO) + raw_image (unpack) |
+ postprocess(demosaic_algorithm=LINEAR, use_camera_wb=True, output_bps=8) |
| dcraw | 9.28, cc -O3 -DNODEPS (+ -march=native on x86-64), one thread (it has no threading) |
dcraw -c -D -4 FILE > /dev/null (raw sensor values written as 16-bit PGM) |
dcraw -c -q 0 -w FILE > /dev/null (bilinear, camera WB, 8-bit sRGB PPM) |
- Every value is the median of 7 timed runs after one warm-up, in a fresh process per
(file, library, mode, thread count). The input file is read into memory before timing
(RawSpeed gets a padded copy, as its own reader provides) — except dcraw, a program rather
than a library: each of its runs is a whole process (start-up, reading the file from the page
cache, writing the image to
/dev/null), so its times include a few ms the others do not pay. - Memory is the peak resident set size (
ru_maxrss) of that process: the input file held in memory, the library's working buffers and its output. The process decodes one file 8 times in a row, freeing everything between decodes, so the peak is that of one decode. rawpy includes the Python interpreter and NumPy (about 27 MB before anything is decoded). - All cores = each library's default parallelism: FlashRaw's thread pool, OpenMP for
LibRaw, RawSpeed and the lcms2 transform, rayon for rawler; rawpy's wheels use OpenMP on
Linux but not on macOS. One thread:
RAYON_NUM_THREADS=1,OMP_NUM_THREADS=1, LibRaw's default build. dcraw runs on one thread in both columns. - Files a library does not decode (error, or unsupported format) are left out of its comparisons. dcraw 9.28 "succeeds" on some files it cannot decode and writes an all-zero image (Canon CR3, whose decoder is an empty stub, and the Fujifilm compressed RAFs of current bodies): the script checks dcraw's output and counts those files as unsupported.
The libraries do not produce byte-identical results, so the comparison is of equivalent work, not identical output:
- decode: every library decodes the full sensor buffer. FlashRaw and LibRaw report it whole, masked (optical black) borders included; RawSpeed reports a view cropped to the camera's active area. All return black/white levels and white balance. FlashRaw applies DNG opcode lists by default (bad pixels, gain maps, …); RawSpeed applies a subset of list 1, the others none.
- RAW → sRGB: FlashRaw, LibRaw, rawpy and dcraw demosaic bilinearly with the camera white balance and convert to 8-bit sRGB; rawler uses its PPG demosaic (more work than bilinear) in 32-bit floats. LibRaw, rawpy and dcraw also run an automatic-brightness histogram and write 3-channel RGB with a BT.709-style gamma; FlashRaw writes RGBA with the sRGB curve, applies DNG opcode list 3 and the orientation. The LibRaw + Little CMS pipeline skips the auto-brightness (it develops linear data) and writes RGBA, like FlashRaw.
python3 tools/corpus/fetch.py # CC0 corpus (raw.pixls.us)
cargo build --release -p flashraw-cli --features jpegxl # add gpu for the GPU column
# FlashRaw alone (regression tracking):
python3 tools/bench/run.py benches/benchmark-set.tsv --iterations 5 \
--out benches/results/<host>.jsonl --markdown benches/results/<host>.md
# Against the other libraries: see the header of tools/bench/compare.py for how to get and
# build them (nothing is vendored); then
tools/bench/compare.py build --libraw-src <LibRaw> --rawspeed-src <rawspeed> --rawspeed-build <build> \
--lcms-src <Little-CMS> --dcraw-src <dcraw.c> --rawler-version 0.8.0 --rawpy rawpy==0.27.1
tools/bench/compare.py run benches/popular-cameras.tsv \
--libs flashraw libraw rawspeed rawler rawpy dcraw lcms --out pass1.jsonl [--max-busy 0.15]
tools/bench/compare.py run benches/benchmark-set.tsv --libs flashraw libraw rawspeed --out set.jsonl
tools/bench/compare.py merge pass1.jsonl pass2.jsonl set.jsonl --out benches/results/<host>-compare.jsonl
tools/bench/compare.py report benches/results/<host>-compare.jsonl --popular benches/popular-cameras.tsv \
--markdown benches/results/<host>-compare.md
tools/bench/charts.py # docs/charts/*.svg + data.json
cargo bench -p flashraw --bench kernels # micro-benchmarks (criterion)
cargo bench -p flashraw-gpu --bench gpu_pipeline # GPU (needs an adapter)| 🐧 Linux x86-64 | 🍎 macOS Apple Silicon | |
|---|---|---|
| CPU | AMD Ryzen 7 9700X, 8 cores / 16 threads, 32 MB L3 | Apple M1 Ultra, 16 performance + 4 efficiency cores |
| Memory, OS | 64 GB DDR5, Linux 6.12 (Debian 13) | 64 GB, macOS 27.0 |
| Compilers | rustc 1.99, GCC 14.2 | rustc 1.95, Apple clang 17.0 |
| Threads (all cores) | 16 | 20 |
| Conditions | shared with other jobs (builds, browser tests; load average 2–15): before each measurement the script waited up to 20–60 s for other processes to use under 15 % of the CPU (they did for 97 % of the kept values, median 1.3 %); one full pass, a second pass over 37 of the 62 popular cameras, and every measurement taken while the machine was busier measured again; lowest median kept | desktop session with background services (a virtual machine, storage indexing) using about 10–20 % of the CPU (top: 77–92 % idle); two full passes of the popular cameras, one of the 159-file set, lowest median kept; the two passes agree within 0.8 % (median) / 3.2 % (90th percentile) |
| Results | linux-x86_64-compare.md |
macos-arm64-compare.md |
Times in ms, all cores, bold = fastest. ² dcraw has no threads (one-thread time). One-thread tables: result file.
| Camera | Format · compression | MP | FlashRaw | LibRaw | RawSpeed | rawler | rawpy | dcraw ² |
|---|---|---|---|---|---|---|---|---|
| Canon EOS R5 (RAW) | CR3 · canon-crx | 46.7 | 80.9 | 138.0 | ❌ | 237.3 | 444.4 | ❌ |
| Canon EOS R5 (C-RAW) | CR3 · canon-crx | 46.7 | 100.7 | 141.0 | ❌ | 196.5 | 368.0 | ❌ |
| Canon EOS R5 Mark II (RAW) | CR3 · canon-crx | 47.9 | 83.2 | 141.4 | ❌ | 234.0 | 451.7 | ❌ |
| Canon EOS R6 Mark II (RAW) | CR3 · canon-crx | 25.5 | 45.7 | 76.9 | ❌ | 136.2 | 235.8 | ❌ |
| Canon EOS R6 Mark III (RAW) | CR3 · canon-crx | 34.0 | 59.6 | 100.4 | ❌ | 144.6 | 321.8 | ❌ |
| Canon EOS R7 (RAW) | CR3 · canon-crx | 33.7 | 60.0 | 100.6 | ❌ | 170.9 | 317.6 | ❌ |
| Canon EOS R8 (RAW) | CR3 · canon-crx | 25.5 | 45.4 | 75.3 | ❌ | 130.7 | 240.1 | ❌ |
| Canon EOS R50 (RAW) | CR3 · canon-crx | 25.1 | 44.8 | 75.3 | ❌ | 123.2 | 230.8 | ❌ |
| Canon EOS 90D (RAW) | CR3 · canon-crx | 33.7 | 31.2 | 99.7 | ❌ | 111.6 | 315.7 | ❌ |
| Canon EOS 5D Mark IV (RAW) | CR2 · lossless-jpeg | 31.3 | 20.5 | 431.4 | 110.2 | 251.5 | 428.3 | 587.6 |
| Canon EOS 6D Mark II (RAW) | CR2 · lossless-jpeg | 27.0 | 17.6 | 389.7 | 121.2 | 238.2 | 379.3 | 541.9 |
| Canon EOS Rebel T7 / 2000D (RAW) | CR2 · lossless-jpeg | 24.7 | 19.0 | 397.3 | 121.8 | 230.1 | 383.9 | 527.9 |
| Nikon Z8 (14-bit lossless) | NEF · nikon-huffman | 45.7 | 44.0 | 544.4 | 218.3 | 356.5 | 570.7 | 857.1 |
| Nikon Z9 (14-bit lossless) | NEF · nikon-huffman | 45.7 | 48.2 | 499.0 | 186.5 | 332.7 | 515.6 | 792.7 |
| Nikon Z6III (lossless) | NEF · nikon-huffman | 24.5 | 25.0 | 284.6 | 110.5 | 186.2 | 297.6 | 452.9 |
| Nikon Zf (lossless) | NEF · nikon-huffman | 24.5 | 24.9 | 267.5 | 95.9 | 174.1 | 279.5 | 426.7 |
| Nikon Z7II (lossless) | NEF · nikon-huffman | 45.7 | 45.4 | 488.2 | 168.9 | 320.4 | 499.5 | 775.7 |
| Nikon Z50 (lossless) | NEF · nikon-huffman | 20.9 | 22.0 | 246.9 | 96.3 | 157.7 | 261.8 | 389.9 |
| Nikon D850 (14-bit lossless) | NEF · nikon-huffman | 45.7 | 45.1 | 487.7 | 170.4 | 324.9 | 504.4 | 769.8 |
| Nikon D750 (14-bit lossless) | NEF · nikon-huffman | 24.3 | 24.8 | 255.8 | 84.8 | 166.3 | 263.2 | 413.2 |
| Sony A7 IV (lossless) | ARW · sony-lossless | 36.7 | 19.2 | 413.6 | 11.7 | 38.7 | 427.2 | ❌ |
| Sony A7 IV (compressed) | ARW · sony-arw2 | 33.0 | 5.86 | 87.4 | 8.77 | 8.38 | 85.0 | 260.1 |
| Sony A7R V (lossless) | ARW · sony-lossless | 64.7 | 33.2 | 760.9 | 24.2 | 61.3 | 765.4 | ❌ |
| Sony A1 (compressed) | ARW · sony-arw2 | 50.2 | 8.14 | 132.0 | 13.4 | 11.8 | 127.5 | 401.3 |
| Sony A7 III (compressed) | ARW · sony-arw2 | 24.3 | 4.49 | 64.7 | 7.20 | 6.43 | 62.5 | 198.7 |
| Sony A7C II (compressed) | ARW · sony-arw2 | 33.0 | 5.83 | 87.1 | 8.55 | 8.28 | 85.9 | 267.8 |
| Sony A9 III (compressed) | ARW · sony-arw2 | 24.3 | 4.65 | 63.6 | 6.83 | 6.82 | 62.9 | 197.3 |
| Sony A6700 (lossless) | ARW · sony-lossless | 30.7 | 16.9 | 373.3 | 13.0 | 42.2 | 374.6 | ❌ |
| Sony A6400 (compressed) | ARW · sony-arw2 | 24.3 | 4.47 | 63.0 | 6.54 | 6.41 | 62.2 | 202.5 |
| Sony ZV-E10 (compressed) | ARW · sony-arw2 | 24.3 | 4.47 | 64.7 | 6.60 | 6.40 | 64.0 | 203.0 |
| Fujifilm X-T5 (lossless compressed) | RAF · fuji-compressed | 40.9 | 35.5 | 150.6 | 44.4 | 93.9 | 1167.2 | ❌ |
| Fujifilm X-H2 (compressed) | RAF · fuji-compressed | 40.9 | 46.5 | 172.8 | ❌ | 127.0 | 1477.7 | ❌ |
| Fujifilm X-S20 (lossless compressed) | RAF · fuji-compressed | 26.5 | 28.3 | 127.0 | 36.3 | 81.0 | 816.4 | ❌ |
| Fujifilm X100VI (lossless compressed) | RAF · fuji-compressed | 40.9 | 35.6 | 154.5 | 44.5 | 94.7 | 1178.0 | ❌ |
| Fujifilm X-T4 (uncompressed) | RAF · uncompressed | 26.7 | 1.60 | 18.8 | 1.18 | 3.26 | 16.7 | 160.5 |
| Fujifilm GFX100 II (lossless compressed) | RAF · fuji-compressed | 103.4 | 67.3 | 267.2 | 76.6 | 143.1 | 2614.4 | ❌ |
| Panasonic Lumix S5II | RW2 · panasonic-v8 | 24.1 | 15.1 | 131.1 | 62.4 | 119.1 | 238.6 | 234.5 |
| Panasonic Lumix GH6 | RW2 · panasonic-v8 | 25.2 | 17.0 | 133.2 | 63.5 | 117.0 | 251.2 | 253.0 |
| Panasonic Lumix G9II | RW2 · panasonic-v8 | 25.1 | 15.3 | 137.9 | 58.7 | 122.9 | 273.5 | 249.7 |
| Panasonic Lumix S5 | RW2 · panasonic-v7 | 24.3 | 2.61 | 8.48 | 0.60 | 3.79 | 8.58 | 241.4 |
| Panasonic Lumix S1R | RW2 · panasonic-v6 | 47.6 | 8.46 | 122.8 | 8.63 | 10.7 | 120.6 | 464.6 |
| Panasonic Lumix GH5 | RW2 · panasonic-v4 | 20.6 | 4.68 | 91.0 | 4.77 | 7.02 | 91.2 | 204.0 |
| OM System OM-1 Mark II | ORF · olympus | 20.4 | 115.8 | 381.5 | 162.2 | 225.0 | 385.4 | 149.0 |
| OM System OM-5 | ORF · olympus | 20.5 | 126.0 | 350.9 | 152.2 | 220.9 | 351.0 | 147.2 |
| Olympus E-M1 Mark III | ORF · olympus | 20.5 | 122.2 | 339.7 | 147.6 | 197.9 | 339.1 | 443.1 |
| Pentax K-3 Mark III | PEF · pentax-huffman | 26.6 | 29.8 | 204.3 | 83.6 | 173.5 | 292.7 | 448.3 |
| Pentax K-1 Mark II | PEF · pentax-huffman | 36.6 | 38.0 | 293.4 | 131.2 | 257.3 | 406.4 | 639.9 |
| Ricoh GR III | DNG · lossless-jpeg | 24.8 | 18.1 | 316.2 | 96.2 | 214.5 | 331.7 | 477.1 |
| Leica Q2 | DNG · uncompressed | 47.4 | 4.04 | 292.9 | 49.2 | 4.54 | 366.0 | 674.9 |
| Leica SL2 | DNG · uncompressed | 47.4 | 4.09 | 289.9 | 48.6 | 4.70 | 371.6 | 681.0 |
| Leica M10-R | DNG · lossless-jpeg | 41.0 | 28.9 | 559.0 | 197.3 | 380.5 | 553.8 | 845.6 |
| Hasselblad X2D 100C (compressed) | FFF · hasselblad | 105.3 | 76.6 | 1012.8 | 451.1 | ❌ | 1108.5 | 2216.0 |
| Phase One IQ4 150MP (IIQ L) | IIQ · phaseone | 154.0 | 42.1 | 1006.4 | ❌ | 341.0 | 1058.7 | 4147.3 |
| Sigma fp L | DNG · lossless-jpeg | 60.5 | 28.0 | 761.2 | 22.4 | 40.9 | 763.0 | 1183.4 |
| Apple iPhone 12 Pro (ProRAW) | DNG · lossless-jpeg | 12.2 | 15.4 | 469.0 | ❌ | 27.8 | 465.2 | 577.1 |
| Google Pixel 8 Pro | DNG · lossless-jpeg | 50.1 | 23.1 | 655.7 | 18.9 | 34.2 | 645.2 | 996.0 |
| Google Pixel 6 Pro | DNG · lossless-jpeg | 12.5 | 6.45 | 163.5 | 4.92 | 10.6 | 163.3 | 254.0 |
| Samsung Galaxy S23 Ultra | DNG · lossless-jpeg | 49.9 | 128.7 | 1916.4 | 549.6 | 1134.9 | 1803.2 | 2277.8 |
| Samsung Galaxy S22 (JPEG XL) | DNG · jpeg-xl | 12.0 | 272.5 | ❌ | ❌ | 172.6 | ❌ | ❌ |
| DJI Phantom 4 Pro | DNG · uncompressed | 20.0 | 1.22 | 17.0 | 0.99 | 1.36 | 17.0 | 142.4 |
| GoPro HERO11 Black (GPR) | DNG · gopro-vc5 | 27.1 | 39.8 | ❌ | 18.5 | ❌ | ❌ | ❌ |
| GoPro HERO10 Black (GPR) | DNG · gopro-vc5 | 23.3 | 35.9 | ❌ | 18.0 | ❌ | ❌ | ❌ |
| Camera | FlashRaw | LibRaw | LibRaw + Little CMS | rawler | rawpy | dcraw ² | FlashRaw GPU |
|---|---|---|---|---|---|---|---|
| Canon EOS R5 (RAW) | 109.3 | 736.8 | 1104.5 | 491.8 | 1112.9 | ❌ | 99.1 |
| Canon EOS R5 (C-RAW) | 129.4 | 738.9 | 1116.2 | 438.1 | 1028.6 | ❌ | 119.7 |
| Canon EOS R5 Mark II (RAW) | 111.7 | 740.0 | 1122.9 | 510.2 | 1135.1 | ❌ | 103.0 |
| Canon EOS R6 Mark II (RAW) | 61.0 | 406.5 | 617.0 | 265.1 | 596.6 | ❌ | 56.8 |
| Canon EOS R6 Mark III (RAW) | 80.4 | 538.4 | 815.7 | 349.9 | 804.0 | ❌ | 73.9 |
| Canon EOS R7 (RAW) | 80.3 | 538.8 | 818.9 | 363.0 | 803.4 | ❌ | 74.2 |
| Canon EOS R8 (RAW) | 60.8 | 414.6 | 612.5 | 251.9 | 606.1 | ❌ | 55.8 |
| Canon EOS R50 (RAW) | 60.3 | 405.2 | 610.7 | 266.1 | 588.5 | ❌ | 56.3 |
| Canon EOS 90D (RAW) | 52.7 | 543.5 | 822.0 | 294.4 | 810.2 | ❌ | 45.5 |
| Canon EOS 5D Mark IV (RAW) | 39.8 | 837.5 | 1100.4 | 414.8 | 881.3 | 965.0 | 31.2 |
| Canon EOS 6D Mark II (RAW) | 33.7 | 744.3 | 968.6 | 384.6 | 764.2 | 857.4 | 28.4 |
| Canon EOS Rebel T7 / 2000D (RAW) | 34.3 | 719.3 | 931.9 | 369.3 | 750.9 | 824.5 | 28.3 |
| Nikon Z8 (14-bit lossless) | 72.4 | 1155.6 | 1541.7 | 601.2 | 1262.6 | 1296.1 | 63.7 |
| Nikon Z9 (14-bit lossless) | 72.4 | 1118.3 | 1484.4 | 581.4 | 1206.7 | 1251.3 | 63.0 |
| Nikon Z6III (lossless) | 41.5 | 628.9 | 824.4 | 320.0 | 668.4 | 681.6 | 36.5 |
| Nikon Zf (lossless) | 41.9 | 609.3 | 819.7 | 314.4 | 642.9 | 668.4 | 35.8 |
| Nikon Z7II (lossless) | 73.6 | 1096.1 | 1491.2 | 576.3 | 1191.8 | 1212.5 | 65.3 |
| Nikon Z50 (lossless) | 36.3 | 541.1 | 716.7 | 274.9 | 573.6 | 591.2 | 31.5 |
| Nikon D850 (14-bit lossless) | 72.7 | 1102.0 | 1495.6 | 574.7 | 1190.5 | 1317.3 | 63.4 |
| Nikon D750 (14-bit lossless) | 40.3 | 597.7 | 800.2 | 295.0 | 620.6 | 677.3 | 36.8 |
| Sony A7 IV (lossless) | 40.8 | 869.8 | 1158.2 | 220.2 | 922.5 | ❌ | 31.9 |
| Sony A7 IV (compressed) | 26.3 | 535.9 | 814.1 | 192.5 | 574.2 | 662.9 | 16.8 |
| Sony A7R V (lossless) | 70.5 | 1537.6 | 2097.5 | 395.2 | 1678.6 | ❌ | 54.4 |
| Sony A1 (compressed) | 39.3 | 797.4 | 1220.4 | 283.0 | 855.0 | 998.0 | 23.9 |
| Sony A7 III (compressed) | 21.2 | 393.1 | 604.4 | 144.2 | 410.2 | 491.4 | 13.0 |
| Sony A7C II (compressed) | 27.5 | 527.0 | 817.9 | 190.4 | 574.2 | 662.9 | 16.9 |
| Sony A9 III (compressed) | 20.1 | 389.4 | 604.3 | 140.9 | 419.1 | 489.3 | 13.5 |
| Sony A6700 (lossless) | 34.2 | 735.7 | 952.2 | 187.1 | 766.1 | ❌ | 27.1 |
| Sony A6400 (compressed) | 19.9 | 396.9 | 605.1 | 143.7 | 422.3 | 487.9 | 13.3 |
| Sony ZV-E10 (compressed) | 17.7 | 397.5 | 604.1 | 145.1 | 426.6 | 430.1 | 12.6 |
| Fujifilm X-T5 (lossless compressed) | 74.4 | 696.6 | 1031.5 | 387.9 | 1808.9 | ❌ | 55.1 |
| Fujifilm X-H2 (compressed) | 94.8 | 878.0 | 1203.3 | 420.2 | 2268.9 | ❌ | 65.1 |
| Fujifilm X-S20 (lossless compressed) | 54.0 | 488.6 | 711.3 | 273.1 | 1217.9 | ❌ | 41.1 |
| Fujifilm X100VI (lossless compressed) | 83.6 | 904.0 | 1212.0 | 385.5 | 2015.8 | ❌ | 54.4 |
| Fujifilm X-T4 (uncompressed) | 28.3 | 380.5 | 603.4 | 195.8 | 419.3 | 434.4 | 9.09 |
| Fujifilm GFX100 II (lossless compressed) | 125.4 | 1568.7 | 2451.3 | 688.2 | 4106.0 | ❌ | 99.8 |
| Panasonic Lumix S5II | 30.4 | 476.9 | 686.2 | 225.8 | 622.1 | 471.1 | 26.5 |
| Panasonic Lumix GH6 | 32.9 | 498.3 | 717.5 | 231.5 | 674.3 | 508.6 | 27.4 |
| Panasonic Lumix G9II | 32.1 | 494.5 | 719.4 | 229.7 | 684.6 | 552.6 | 25.0 |
| Panasonic Lumix S5 | 18.2 | 361.6 | 569.6 | 113.0 | 405.3 | 482.1 | 10.8 |
| Panasonic Lumix S1R | 38.0 | 798.7 | 1205.6 | 214.5 | 894.5 | 896.3 | 22.9 |
| Panasonic Lumix GH5 | 17.7 | 391.0 | 567.6 | 97.8 | 427.4 | 443.1 | 12.0 |
| OM System OM-1 Mark II | 126.4 | 677.6 | 845.5 | 341.3 | 694.8 | 338.4 | 124.5 |
| OM System OM-5 | 138.8 | 639.5 | 821.2 | 336.7 | 654.6 | 348.1 | 132.5 |
| Olympus E-M1 Mark III | 137.9 | 628.6 | 809.8 | 314.0 | 634.8 | 690.3 | 131.6 |
| Pentax K-3 Mark III | 48.2 | 562.4 | 772.3 | 321.4 | 671.4 | 764.4 | 41.3 |
| Pentax K-1 Mark II | 60.9 | 777.3 | 1094.8 | 457.9 | 934.7 | 1073.3 | 54.1 |
| Ricoh GR III | 34.1 | 658.9 | 863.8 | 343.4 | 695.1 | 779.0 | 28.5 |
| Leica Q2 | 33.1 | 926.5 | 1323.7 | 259.4 | 1079.4 | 1233.0 | CPU¹ |
| Leica SL2 | 33.8 | 920.6 | 1301.5 | 257.6 | 1072.0 | 1229.3 | CPU¹ |
| Leica M10-R | 54.9 | 1085.2 | 1456.2 | 605.4 | 1162.4 | 1320.6 | 45.5 |
| Hasselblad X2D 100C (compressed) | 144.2 | 2315.9 | 3203.9 | ❌ | 2614.4 | 3216.0 | 118.9 |
| Phase One IQ4 150MP (IIQ L) | 133.0 | 4304.9 | 5691.9 | 952.2 | 4751.1 | 5987.5 | 92.5 |
| Sigma fp L | 72.1 | 1565.7 | 2081.1 | 364.3 | 1666.2 | 1898.8 | CPU¹ |
| Apple iPhone 12 Pro (ProRAW) | 24.3 | 591.8 | 687.6 | 74.4 | 594.3 | 679.3 | 21.0 |
| Google Pixel 8 Pro | 59.1 | 1445.9 | 1891.3 | 303.5 | 1530.9 | 1566.9 | CPU¹ |
| Google Pixel 6 Pro | 16.7 | 350.0 | 453.8 | 85.5 | 348.8 | 401.4 | CPU¹ |
| Samsung Galaxy S23 Ultra | 177.7 | 2194.2 | 2507.1 | 1292.4 | 2114.0 | 2609.3 | CPU¹ |
| Samsung Galaxy S22 (JPEG XL) | 289.3 | ❌ | ❌ | 212.3 | ❌ | ❌ | CPU¹ |
| DJI Phantom 4 Pro | 18.9 | 291.5 | 474.1 | 116.9 | 315.3 | 394.8 | CPU¹ |
| GoPro HERO11 Black (GPR) | 60.2 | ❌ | ❌ | ❌ | ❌ | ❌ | CPU¹ |
| GoPro HERO10 Black (GPR) | 53.9 | ❌ | ❌ | ❌ | ❌ | ❌ | CPU¹ |
FlashRaw GPU = --backend gpu --output rgba8: CPU decode or GPU unpack, GPU develop, frame downloaded to host memory. ¹ FlashRaw's GPU pipeline does not handle this file's processing yet and ran it on the CPU.
Times in ms, all cores, bold = fastest. One-thread tables: result file.
| Camera | Format · compression | MP | FlashRaw | LibRaw | RawSpeed | rawler | rawpy | dcraw ² |
|---|---|---|---|---|---|---|---|---|
| Canon EOS R5 (RAW) | CR3 · canon-crx | 46.7 | 57.2 | 57.9 | ❌ | 181.1 | 59.8 | ❌ |
| Canon EOS R5 (C-RAW) | CR3 · canon-crx | 46.7 | 71.9 | 68.5 | ❌ | 150.7 | 67.4 | ❌ |
| Canon EOS R5 Mark II (RAW) | CR3 · canon-crx | 47.9 | 57.0 | 59.0 | ❌ | 180.9 | 60.9 | ❌ |
| Canon EOS R6 Mark II (RAW) | CR3 · canon-crx | 25.5 | 33.1 | 32.8 | ❌ | 97.6 | 33.8 | ❌ |
| Canon EOS R6 Mark III (RAW) | CR3 · canon-crx | 34.0 | 41.6 | 42.6 | ❌ | 126.7 | 43.8 | ❌ |
| Canon EOS R7 (RAW) | CR3 · canon-crx | 33.7 | 42.5 | 45.6 | ❌ | 127.1 | 43.7 | ❌ |
| Canon EOS R8 (RAW) | CR3 · canon-crx | 25.5 | 32.1 | 33.0 | ❌ | 101.3 | 33.8 | ❌ |
| Canon EOS R50 (RAW) | CR3 · canon-crx | 25.1 | 30.9 | 31.6 | ❌ | 94.6 | 32.8 | ❌ |
| Canon EOS 90D (RAW) | CR3 · canon-crx | 33.7 | 33.8 | 41.9 | ❌ | 98.6 | 46.2 | ❌ |
| Canon EOS 5D Mark IV (RAW) | CR2 · lossless-jpeg | 31.3 | 23.9 | 346.8 | 68.9 | 129.8 | 363.6 | 403.2 |
| Canon EOS 6D Mark II (RAW) | CR2 · lossless-jpeg | 27.0 | 20.5 | 262.3 | 82.5 | 126.7 | 274.2 | 305.8 |
| Canon EOS Rebel T7 / 2000D (RAW) | CR2 · lossless-jpeg | 24.7 | 24.5 | 308.9 | 88.0 | 131.4 | 324.8 | 344.6 |
| Nikon Z8 (14-bit lossless) | NEF · nikon-huffman | 45.7 | 46.5 | 421.0 | 178.0 | 203.3 | 450.6 | 498.7 |
| Nikon Z9 (14-bit lossless) | NEF · nikon-huffman | 45.7 | 51.8 | 407.3 | 133.7 | 172.6 | 423.4 | 484.8 |
| Nikon Z6III (lossless) | NEF · nikon-huffman | 24.5 | 28.3 | 228.7 | 85.4 | 104.4 | 243.0 | 269.9 |
| Nikon Zf (lossless) | NEF · nikon-huffman | 24.5 | 27.8 | 216.9 | 68.6 | 90.5 | 231.2 | 263.2 |
| Nikon Z7II (lossless) | NEF · nikon-huffman | 45.7 | 51.2 | 403.1 | 117.1 | 159.8 | 422.8 | 481.2 |
| Nikon Z50 (lossless) | NEF · nikon-huffman | 20.9 | 24.3 | 201.4 | 72.8 | 86.9 | 213.7 | 237.1 |
| Nikon D850 (14-bit lossless) | NEF · nikon-huffman | 45.7 | 51.5 | 414.7 | 118.6 | 159.7 | 422.3 | 480.0 |
| Nikon D750 (14-bit lossless) | NEF · nikon-huffman | 24.3 | 28.6 | 204.0 | 57.6 | 78.8 | 218.9 | 252.8 |
| Sony A7 IV (lossless) | ARW · sony-lossless | 36.7 | 14.9 | 314.2 | 15.9 | 36.9 | 339.5 | ❌ |
| Sony A7 IV (compressed) | ARW · sony-arw2 | 33.0 | 8.02 | 80.2 | 10.9 | 11.9 | 96.6 | 172.5 |
| Sony A7R V (lossless) | ARW · sony-lossless | 64.7 | 25.6 | 576.4 | 31.3 | 60.8 | 611.9 | ❌ |
| Sony A1 (compressed) | ARW · sony-arw2 | 50.2 | 10.8 | 117.8 | 17.3 | 18.5 | 142.2 | 257.8 |
| Sony A7 III (compressed) | ARW · sony-arw2 | 24.3 | 5.45 | 59.1 | 8.18 | 8.09 | 71.4 | 128.4 |
| Sony A7C II (compressed) | ARW · sony-arw2 | 33.0 | 7.47 | 79.3 | 10.5 | 11.9 | 95.4 | 173.1 |
| Sony A9 III (compressed) | ARW · sony-arw2 | 24.3 | 5.69 | 59.7 | 8.41 | 8.47 | 71.7 | 130.1 |
| Sony A6700 (lossless) | ARW · sony-lossless | 30.7 | 13.7 | 275.5 | 15.0 | 34.8 | 294.2 | ❌ |
| Sony A6400 (compressed) | ARW · sony-arw2 | 24.3 | 5.25 | 52.7 | 8.22 | 8.23 | 65.7 | 124.0 |
| Sony ZV-E10 (compressed) | ARW · sony-arw2 | 24.3 | 5.62 | 54.0 | 7.78 | 8.23 | 66.5 | 125.5 |
| Fujifilm X-T5 (lossless compressed) | RAF · fuji-compressed | 40.9 | 53.1 | 155.4 | 112.1 | 132.1 | 153.5 | ❌ |
| Fujifilm X-H2 (compressed) | RAF · fuji-compressed | 40.9 | 67.0 | 168.3 | ❌ | 147.6 | 183.9 | ❌ |
| Fujifilm X-S20 (lossless compressed) | RAF · fuji-compressed | 26.5 | 39.4 | 115.0 | 83.5 | 101.1 | 120.9 | ❌ |
| Fujifilm X100VI (lossless compressed) | RAF · fuji-compressed | 40.9 | 53.1 | 156.1 | 121.5 | 133.2 | 157.7 | ❌ |
| Fujifilm X-T4 (uncompressed) | RAF · uncompressed | 26.7 | 3.35 | 16.1 | 4.24 | 11.8 | 16.7 | 114.6 |
| Fujifilm GFX100 II (lossless compressed) | RAF · fuji-compressed | 103.4 | 101.6 | 252.4 | 202.5 | 227.5 | 251.9 | ❌ |
| Panasonic Lumix S5II | RW2 · panasonic-v8 | 24.1 | 24.8 | 87.5 | 89.0 | 81.7 | 84.7 | 174.1 |
| Panasonic Lumix GH6 | RW2 · panasonic-v8 | 25.2 | 28.8 | 90.9 | 95.1 | 85.5 | 103.1 | 188.0 |
| Panasonic Lumix G9II | RW2 · panasonic-v8 | 25.1 | 28.1 | 92.3 | 95.5 | 86.9 | 89.1 | 182.0 |
| Panasonic Lumix S5 | RW2 · panasonic-v7 | 24.3 | 4.80 | 10.5 | 4.58 | 9.47 | 9.67 | 171.8 |
| Panasonic Lumix S1R | RW2 · panasonic-v6 | 47.6 | 12.4 | 85.7 | 15.3 | 17.9 | 92.9 | 344.6 |
| Panasonic Lumix GH5 | RW2 · panasonic-v4 | 20.6 | 6.75 | 60.5 | 17.0 | 9.83 | 59.9 | 130.4 |
| OM System OM-1 Mark II | ORF · olympus | 20.4 | 64.0 | 331.8 | 142.2 | 187.5 | 323.8 | 80.5 |
| OM System OM-5 | ORF · olympus | 20.5 | 60.3 | 275.8 | 143.7 | 198.4 | 266.7 | 81.0 |
| Olympus E-M1 Mark III | ORF · olympus | 20.5 | 57.1 | 250.7 | 132.0 | 166.2 | 247.5 | 334.1 |
| Pentax K-3 Mark III | PEF · pentax-huffman | 26.6 | 40.2 | 273.4 | 57.2 | 86.6 | 250.6 | 269.0 |
| Pentax K-1 Mark II | PEF · pentax-huffman | 36.6 | 42.6 | 316.9 | 91.6 | 134.9 | 356.6 | 376.8 |
| Ricoh GR III | DNG · lossless-jpeg | 24.8 | 25.7 | 372.0 | 68.5 | 104.5 | 363.5 | 309.3 |
| Leica Q2 | DNG · uncompressed | 47.4 | 8.37 | 191.7 | 33.2 | 9.21 | 237.0 | 270.4 |
| Leica SL2 | DNG · uncompressed | 47.4 | 8.47 | 191.0 | 32.5 | 9.31 | 236.8 | 271.8 |
| Leica M10-R | DNG · lossless-jpeg | 41.0 | 43.3 | 471.7 | 150.6 | 192.3 | 553.3 | 505.3 |
| Hasselblad X2D 100C (compressed) | FFF · hasselblad | 105.3 | 91.7 | 849.8 | 490.0 | ❌ | 1043.7 | 1203.7 |
| Phase One IQ4 150MP (IIQ L) | IIQ · phaseone | 154.0 | 55.7 | 666.5 | ❌ | 356.8 | 960.3 | 1701.1 |
| Sigma fp L | DNG · lossless-jpeg | 60.5 | 17.7 | 653.5 | 23.7 | 53.6 | 714.9 | 747.3 |
| Apple iPhone 12 Pro (ProRAW) | DNG · lossless-jpeg | 12.2 | 19.6 | 316.5 | ❌ | 25.5 | 350.4 | 325.5 |
| Google Pixel 8 Pro | DNG · lossless-jpeg | 50.1 | 13.8 | 520.7 | 18.8 | 42.5 | 556.8 | 645.2 |
| Google Pixel 6 Pro | DNG · lossless-jpeg | 12.5 | 3.32 | 130.2 | 4.09 | 12.3 | 142.8 | 160.7 |
| Samsung Galaxy S23 Ultra | DNG · lossless-jpeg | 49.9 | 102.5 | 1274.9 | 380.9 | 485.1 | 1408.4 | 1293.7 |
| Samsung Galaxy S22 (JPEG XL) | DNG · jpeg-xl | 12.0 | 236.6 | ❌ | ❌ | 156.4 | ❌ | ❌ |
| DJI Phantom 4 Pro | DNG · uncompressed | 20.0 | 2.63 | 10.7 | 3.30 | 4.85 | 25.6 | 79.2 |
| GoPro HERO11 Black (GPR) | DNG · gopro-vc5 | 27.1 | 48.3 | ❌ | 27.9 | ❌ | ❌ | ❌ |
| GoPro HERO10 Black (GPR) | DNG · gopro-vc5 | 23.3 | 48.4 | ❌ | 23.4 | ❌ | ❌ | ❌ |
| Camera | FlashRaw | LibRaw | LibRaw + Little CMS | rawler | rawpy | dcraw ² |
|---|---|---|---|---|---|---|
| Canon EOS R5 (RAW) | 101.2 | 481.1 | 1080.1 | 640.5 | 529.9 | ❌ |
| Canon EOS R5 (C-RAW) | 115.0 | 492.0 | 1087.4 | 611.6 | 539.3 | ❌ |
| Canon EOS R5 Mark II (RAW) | 99.9 | 484.3 | 1081.5 | 646.8 | 531.6 | ❌ |
| Canon EOS R6 Mark II (RAW) | 55.6 | 264.0 | 579.4 | 346.3 | 289.4 | ❌ |
| Canon EOS R6 Mark III (RAW) | 72.8 | 349.8 | 788.4 | 462.2 | 382.6 | ❌ |
| Canon EOS R7 (RAW) | 72.7 | 351.1 | 790.5 | 463.7 | 386.3 | ❌ |
| Canon EOS R8 (RAW) | 55.8 | 262.2 | 580.4 | 344.7 | 288.8 | ❌ |
| Canon EOS R50 (RAW) | 54.7 | 260.0 | 585.2 | 342.7 | 287.2 | ❌ |
| Canon EOS 90D (RAW) | 69.9 | 353.4 | 790.8 | 433.1 | 385.8 | ❌ |
| Canon EOS 5D Mark IV (RAW) | 55.0 | 633.7 | 1072.1 | 446.6 | 688.4 | 663.9 |
| Canon EOS 6D Mark II (RAW) | 45.5 | 514.9 | 869.8 | 395.8 | 552.8 | 530.1 |
| Canon EOS Rebel T7 / 2000D (RAW) | 47.6 | 537.0 | 856.0 | 379.8 | 585.8 | 553.2 |
| Nikon Z8 (14-bit lossless) | 91.0 | 856.4 | 1457.4 | 662.7 | 922.8 | 806.9 |
| Nikon Z9 (14-bit lossless) | 95.2 | 838.5 | 1438.0 | 631.9 | 904.3 | 791.8 |
| Nikon Z6III (lossless) | 52.3 | 464.5 | 785.8 | 356.7 | 502.7 | 435.4 |
| Nikon Zf (lossless) | 53.0 | 450.1 | 772.5 | 343.2 | 488.6 | 428.8 |
| Nikon Z7II (lossless) | 95.0 | 835.5 | 1431.8 | 627.7 | 902.9 | 792.1 |
| Nikon Z50 (lossless) | 44.3 | 402.1 | 696.6 | 302.6 | 434.0 | 378.8 |
| Nikon D850 (14-bit lossless) | 94.5 | 835.0 | 1445.6 | 619.9 | 896.5 | 870.5 |
| Nikon D750 (14-bit lossless) | 53.2 | 434.5 | 748.2 | 325.4 | 473.4 | 460.9 |
| Sony A7 IV (lossless) | 47.3 | 628.4 | 1073.4 | 372.3 | 692.5 | ❌ |
| Sony A7 IV (compressed) | 40.8 | 393.7 | 834.7 | 344.8 | 443.0 | 457.4 |
| Sony A7R V (lossless) | 84.7 | 1151.4 | 1958.7 | 671.3 | 1261.4 | ❌ |
| Sony A1 (compressed) | 60.6 | 592.8 | 1267.4 | 519.3 | 667.6 | 689.7 |
| Sony A7 III (compressed) | 31.2 | 291.1 | 609.7 | 258.0 | 330.7 | 338.1 |
| Sony A7C II (compressed) | 40.8 | 391.0 | 834.0 | 350.3 | 442.3 | 455.0 |
| Sony A9 III (compressed) | 30.1 | 289.9 | 613.1 | 257.1 | 330.4 | 337.2 |
| Sony A6700 (lossless) | 39.4 | 525.2 | 880.9 | 301.1 | 573.6 | ❌ |
| Sony A6400 (compressed) | 29.7 | 284.1 | 601.4 | 258.0 | 320.6 | 332.4 |
| Sony ZV-E10 (compressed) | 26.4 | 285.1 | 602.4 | 257.5 | 323.4 | 289.3 |
| Fujifilm X-T5 (lossless compressed) | 115.6 | 539.0 | 1089.3 | 610.4 | 573.2 | ❌ |
| Fujifilm X-H2 (compressed) | 144.6 | 581.7 | 1112.9 | 623.9 | 636.9 | ❌ |
| Fujifilm X-S20 (lossless compressed) | 78.9 | 370.9 | 723.9 | 413.6 | 398.7 | ❌ |
| Fujifilm X100VI (lossless compressed) | 130.8 | 567.2 | 1098.7 | 613.4 | 607.8 | ❌ |
| Fujifilm X-T4 (uncompressed) | 43.6 | 266.9 | 618.7 | 323.6 | 293.1 | 312.3 |
| Fujifilm GFX100 II (lossless compressed) | 199.5 | 1208.7 | 2583.7 | 1241.5 | 1305.5 | ❌ |
| Panasonic Lumix S5II | 52.2 | 352.0 | 664.1 | 299.3 | 388.9 | 342.4 |
| Panasonic Lumix GH6 | 56.2 | 366.9 | 728.8 | 312.1 | 404.8 | 360.4 |
| Panasonic Lumix G9II | 51.1 | 364.3 | 700.8 | 312.6 | 401.9 | 401.2 |
| Panasonic Lumix S5 | 29.3 | 273.5 | 589.0 | 225.2 | 312.1 | 339.4 |
| Panasonic Lumix S1R | 59.2 | 595.0 | 1210.6 | 430.9 | 672.6 | 671.3 |
| Panasonic Lumix GH5 | 26.6 | 280.0 | 638.6 | 193.0 | 317.9 | 305.7 |
| OM System OM-1 Mark II | 86.2 | 527.6 | 801.4 | 396.1 | 539.2 | 213.7 |
| OM System OM-5 | 89.5 | 470.5 | 769.1 | 398.8 | 489.6 | 212.6 |
| Olympus E-M1 Mark III | 78.1 | 461.6 | 775.8 | 418.6 | 485.0 | 507.5 |
| Pentax K-3 Mark III | 64.1 | 475.4 | 879.8 | 370.1 | 663.0 | 498.3 |
| Pentax K-1 Mark II | 88.5 | 659.5 | 1194.2 | 514.8 | 738.9 | 691.4 |
| Ricoh GR III | 86.6 | 730.6 | 1235.3 | 376.4 | 584.3 | 517.1 |
| Leica Q2 | 53.9 | 640.7 | 1268.2 | 490.5 | 735.2 | 677.3 |
| Leica SL2 | 54.3 | 639.4 | 1245.3 | 481.8 | 733.1 | 679.1 |
| Leica M10-R | 85.1 | 950.1 | 1377.6 | 605.2 | 902.7 | 857.2 |
| Hasselblad X2D 100C (compressed) | 193.6 | 1821.3 | 4040.5 | ❌ | 2097.8 | 1916.8 |
| Phase One IQ4 150MP (IIQ L) | 227.2 | 2442.2 | 4703.7 | 1670.4 | 3177.4 | 3009.8 |
| Sigma fp L | 96.4 | 1192.7 | 2083.7 | 823.5 | 1323.3 | 1270.6 |
| Apple iPhone 12 Pro (ProRAW) | 35.7 | 382.5 | 535.8 | 121.9 | 427.8 | 458.4 |
| Google Pixel 8 Pro | 69.6 | 1088.7 | 1766.2 | 805.6 | 1217.3 | 1065.2 |
| Google Pixel 6 Pro | 18.2 | 250.8 | 419.4 | 143.1 | 283.3 | 267.7 |
| Samsung Galaxy S23 Ultra | 202.4 | 1490.4 | 2079.0 | 850.6 | 1709.5 | 1836.7 |
| Samsung Galaxy S22 (JPEG XL) | 293.2 | ❌ | ❌ | 251.4 | ❌ | ❌ |
| DJI Phantom 4 Pro | 33.8 | 201.8 | 473.8 | 214.2 | 237.2 | 250.9 |
| GoPro HERO11 Black (GPR) | 77.2 | ❌ | ❌ | ❌ | ❌ | ❌ |
| GoPro HERO10 Black (GPR) | 67.2 | ❌ | ❌ | ❌ | ❌ | ❌ |
Peak resident memory of the benchmark process (input file included), as a ratio to FlashRaw's on the same file (> 1 = FlashRaw needs less), median over the popular cameras, and the number of files where FlashRaw needs less:
| Comparison | threads | 🐧 ratio | 🐧 less | 🍎 ratio | 🍎 less |
|---|---|---|---|---|---|
| decode vs LibRaw | all | 0.91× | 1/59 | 0.81× | 1/59 |
| decode vs LibRaw | 1 | 0.98× | 2/59 | 0.94× | 2/59 |
| decode vs RawSpeed | all | 0.98× | 21/49 | 0.90× | 0/49 |
| decode vs RawSpeed | 1 | 1.01× | 42/49 | 0.99× | 0/49 |
| decode vs rawler | all | 1.14× | 40/59 | 1.54× | 39/59 |
| decode vs rawler | 1 | 1.49× | 57/59 | 1.61× | 57/59 |
| decode vs rawpy | all | 1.05× | 30/59 | 0.98× | 28/59 |
| decode vs rawpy | 1 | 1.17× | 45/59 | 1.11× | 45/59 |
| decode vs dcraw | all | 2.02× | 38/42 | 1.94× | 33/42 |
| decode vs dcraw | 1 | 2.86× | 40/42 | 2.75× | 40/42 |
| RAW→RGB vs LibRaw | all | 1.88× | 59/59 | 1.48× | 54/59 |
| RAW→RGB vs LibRaw | 1 | 1.92× | 59/59 | 1.88× | 59/59 |
| RAW→sRGB vs LibRaw + Little CMS | all | 2.78× | 59/59 | 2.21× | 59/59 |
| RAW→sRGB vs LibRaw + Little CMS | 1 | 2.86× | 59/59 | 2.79× | 59/59 |
| RAW→RGB vs rawler | all | 4.14× | 59/59 | 4.55× | 59/59 |
| RAW→RGB vs rawler | 1 | 4.32× | 59/59 | 5.14× | 59/59 |
| RAW→RGB vs rawpy | all | 1.97× | 59/59 | 1.55× | 56/59 |
| RAW→RGB vs rawpy | 1 | 2.03× | 59/59 | 1.97× | 59/59 |
| RAW→RGB vs dcraw | all | 1.31× | 36/42 | 0.94× | 20/42 |
| RAW→RGB vs dcraw | 1 | 1.34× | 40/42 | 1.32× | 40/42 |
Median peaks in MB:
| Median peak RSS (MB), all cores | FlashRaw | LibRaw | RawSpeed | rawler | rawpy | dcraw | LibRaw + Little CMS |
|---|---|---|---|---|---|---|---|
| 🐧 decode | 183 | 104 | 109 | 178 | 129 | 247 | – |
| 🐧 RAW → sRGB | 274 | 415 | – | 848 | 440 | 247 | 619 |
| 🍎 decode | 174 | 104 | 109 | 196 | 122 | 247 | – |
| 🍎 RAW → sRGB | 303 | 416 | – | 1083 | 435 | 247 | 620 |
Each median is over the files that library decodes, so the columns are not over identical sets; the ratios above are per file.
- RAW → sRGB: FlashRaw needs less memory than every library pipeline, typically half to two thirds of LibRaw's (and rawpy's) and less than half of the LibRaw + Little CMS pipeline's. It develops in one fused pass straight into the output image, so it never holds full-size intermediates: LibRaw keeps a 4-channel 16-bit working image plus its output, the Little CMS pipeline adds a 16-bit RGB copy and the 8-bit result, and rawler develops in 32-bit floats (4–5× FlashRaw's peak). Only dcraw, a single program with one 4 × 16-bit image buffer and no threads, needs about as little: its peak is a median 1.3× FlashRaw's on Linux and 0.94× on the M1 Ultra (all cores).
- Decode only: about the same on one thread, more for FlashRaw on all cores. Every decoder holds the file and a 16-bit image. On one thread FlashRaw's peak is within a few percent of LibRaw's and RawSpeed's. With all cores, FlashRaw's parallel decoders of single entropy-coded streams and tiled codecs add per-thread working buffers (for example, each thread decodes its chunk of the stream into its own buffer of differences before the rows are rebuilt; see architecture): LibRaw's peak is a median 0.9× of FlashRaw's on Linux and 0.8× on the M1 Ultra. That is the price of decoding Nikon, lossless-JPEG or Pentax streams 5–10× faster.
Per camera (Apple M1 Ultra, all cores, MB):
| Camera | MP | decode: FlashRaw | LibRaw | RawSpeed | rawler | rawpy | dcraw ² | RGB: FlashRaw | LibRaw | LibRaw + Little CMS | rawler | rawpy | dcraw ² |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Canon EOS R5 (RAW) | 46.7 | 227 | 134 | ❌ | 409 | 152 | ❌ | 409 | 604 | 904 | 1886 | 621 | ❌ |
| Canon EOS R5 (C-RAW) | 46.7 | 216 | 127 | ❌ | 397 | 141 | ❌ | 394 | 596 | 896 | 1875 | 611 | ❌ |
| Canon EOS R5 Mark II (RAW) | 47.9 | 247 | 149 | ❌ | 427 | 168 | ❌ | 427 | 622 | 926 | 1916 | 642 | ❌ |
| Canon EOS R6 Mark II (RAW) | 25.5 | 137 | 83 | ❌ | 239 | 101 | ❌ | 233 | 337 | 499 | 1039 | 356 | ❌ |
| Canon EOS R6 Mark III (RAW) | 34.0 | 173 | 104 | ❌ | 278 | 122 | ❌ | 303 | 442 | 659 | 1347 | 460 | ❌ |
| Canon EOS R7 (RAW) | 33.7 | 172 | 102 | ❌ | 275 | 119 | ❌ | 300 | 444 | 661 | 1342 | 461 | ❌ |
| Canon EOS R8 (RAW) | 25.5 | 136 | 81 | ❌ | 239 | 99 | ❌ | 233 | 337 | 500 | 1038 | 354 | ❌ |
| Canon EOS R50 (RAW) | 25.1 | 138 | 85 | ❌ | 239 | 103 | ❌ | 234 | 337 | 497 | 1034 | 354 | ❌ |
| Canon EOS 90D (RAW) | 33.7 | 174 | 104 | ❌ | 278 | 122 | ❌ | 303 | 445 | 664 | 1347 | 463 | ❌ |
| Canon EOS 5D Mark IV (RAW) | 31.3 | 294 | 97 | 100 | 190 | 115 | 294 | 414 | 416 | 620 | 1126 | 435 | 294 |
| Canon EOS 6D Mark II (RAW) | 27.0 | 237 | 91 | 95 | 126 | 110 | 254 | 333 | 368 | 544 | 984 | 387 | 254 |
| Canon EOS Rebel T7 / 2000D (RAW) | 24.7 | 266 | 89 | 92 | 170 | 107 | 234 | 363 | 344 | 506 | 911 | 362 | 234 |
| Nikon Z8 (14-bit lossless) | 45.7 | 294 | 149 | 153 | 235 | 169 | 439 | 477 | 630 | 936 | 1719 | 648 | 439 |
| Nikon Z9 (14-bit lossless) | 45.7 | 304 | 147 | 150 | 228 | 165 | 439 | 476 | 627 | 934 | 1712 | 646 | 439 |
| Nikon Z6III (lossless) | 24.5 | 184 | 83 | 86 | 144 | 102 | 236 | 276 | 340 | 505 | 940 | 358 | 236 |
| Nikon Zf (lossless) | 24.5 | 176 | 81 | 84 | 141 | 99 | 236 | 258 | 339 | 503 | 937 | 358 | 236 |
| Nikon Z7II (lossless) | 45.7 | 293 | 144 | 147 | 224 | 162 | 439 | 478 | 626 | 931 | 1709 | 643 | 439 |
| Nikon Z50 (lossless) | 20.9 | 165 | 74 | 78 | 133 | 93 | 202 | 250 | 294 | 434 | 810 | 312 | 202 |
| Nikon D850 (14-bit lossless) | 45.7 | 294 | 144 | 148 | 224 | 164 | 439 | 474 | 626 | 932 | 1710 | 643 | 439 |
| Nikon D750 (14-bit lossless) | 24.3 | 166 | 76 | 79 | 133 | 95 | 235 | 257 | 332 | 495 | 925 | 351 | 235 |
| Sony A7 IV (lossless) | 36.7 | 140 | 122 | 126 | 216 | 141 | ❌ | 267 | 468 | 688 | 1323 | 487 | ❌ |
| Sony A7 IV (compressed) | 33.0 | 112 | 106 | 111 | 180 | 125 | 318 | 242 | 452 | 674 | 1251 | 471 | 317 |
| Sony A7R V (lossless) | 64.7 | 230 | 211 | 215 | 343 | 229 | ❌ | 460 | 852 | 1259 | 2359 | 869 | ❌ |
| Sony A1 (compressed) | 50.2 | 166 | 160 | 165 | 257 | 180 | 481 | 367 | 687 | 1022 | 1883 | 705 | 481 |
| Sony A7 III (compressed) | 24.3 | 81 | 76 | 80 | 134 | 95 | 234 | 177 | 330 | 493 | 924 | 348 | 234 |
| Sony A7C II (compressed) | 33.0 | 111 | 105 | 110 | 179 | 124 | 318 | 242 | 453 | 673 | 1250 | 472 | 318 |
| Sony A9 III (compressed) | 24.3 | 84 | 79 | 83 | 141 | 97 | 234 | 181 | 333 | 496 | 930 | 352 | 234 |
| Sony A6700 (lossless) | 30.7 | 127 | 105 | 109 | 196 | 124 | ❌ | 224 | 378 | 553 | 1083 | 397 | ❌ |
| Sony A6400 (compressed) | 24.3 | 80 | 74 | 79 | 135 | 94 | 234 | 177 | 330 | 493 | 922 | 348 | 234 |
| Sony ZV-E10 (compressed) | 24.3 | 80 | 74 | 79 | 135 | 94 | 234 | 162 | 330 | 494 | 923 | 349 | 234 |
| Fujifilm X-T5 (lossless compressed) | 40.9 | 130 | 126 | 128 | 197 | 143 | ❌ | 287 | 547 | 816 | 1508 | 565 | ❌ |
| Fujifilm X-H2 (compressed) | 40.9 | 117 | 113 | ❌ | 175 | 130 | ❌ | 275 | 534 | 803 | 1487 | 551 | ❌ |
| Fujifilm X-S20 (lossless compressed) | 26.5 | 93 | 89 | 91 | 150 | 107 | ❌ | 197 | 363 | 539 | 1000 | 381 | ❌ |
| Fujifilm X100VI (lossless compressed) | 40.9 | 135 | 132 | 134 | 208 | 149 | ❌ | 293 | 554 | 822 | 1517 | 570 | ❌ |
| Fujifilm X-T4 (uncompressed) | 26.7 | 115 | 110 | 113 | 197 | 129 | 252 | 220 | 384 | 560 | 998 | 403 | 252 |
| Fujifilm GFX100 II (lossless compressed) | 103.4 | 314 | 311 | 312 | 455 | 327 | ❌ | 713 | 1382 | 2062 | 3779 | 1398 | ❌ |
| Panasonic Lumix S5II | 24.1 | 271 | 89 | 89 | 151 | 107 | 232 | 370 | 343 | 505 | 931 | 359 | 232 |
| Panasonic Lumix GH6 | 25.2 | 290 | 100 | 98 | 169 | 115 | 243 | 386 | 364 | 532 | 982 | 380 | 243 |
| Panasonic Lumix G9II | 25.1 | 262 | 96 | 95 | 162 | 113 | 242 | 360 | 359 | 528 | 977 | 377 | 242 |
| Panasonic Lumix S5 | 24.3 | 97 | 92 | 96 | 169 | 111 | 234 | 195 | 347 | 509 | 951 | 367 | 234 |
| Panasonic Lumix S1R | 47.6 | 167 | 161 | 166 | 264 | 181 | 453 | 355 | 658 | 973 | 1787 | 677 | 453 |
| Panasonic Lumix GH5 | 20.6 | 72 | 66 | 71 | 125 | 86 | 197 | 153 | 281 | 418 | 783 | 299 | 197 |
| OM System OM-1 Mark II | 20.4 | 71 | 65 | 68 | 120 | 84 | 197 | 154 | 281 | 418 | 782 | 298 | 197 |
| OM System OM-5 | 20.5 | 70 | 63 | 65 | 114 | 82 | 198 | 150 | 278 | 416 | 781 | 297 | 198 |
| Olympus E-M1 Mark III | 20.5 | 67 | 60 | 64 | 112 | 80 | 198 | 149 | 277 | 415 | 777 | 295 | 198 |
| Pentax K-3 Mark III | 26.6 | 182 | 85 | 89 | 121 | 105 | 257 | 285 | 359 | 532 | 968 | 376 | 257 |
| Pentax K-1 Mark II | 36.6 | 260 | 120 | 123 | 153 | 138 | 352 | 405 | 502 | 746 | 1337 | 521 | 352 |
| Ricoh GR III | 24.8 | 257 | 84 | 87 | 166 | 102 | 235 | 352 | 338 | 501 | 911 | 357 | 235 |
| Leica Q2 | 47.4 | 184 | 177 | 181 | 213 | 197 | 454 | 374 | 675 | 992 | 1748 | 693 | 454 |
| Leica SL2 | 47.4 | 186 | 180 | 183 | 216 | 199 | 454 | 375 | 675 | 991 | 1749 | 693 | 454 |
| Leica M10-R | 41.0 | 407 | 134 | 138 | 248 | 153 | 394 | 564 | 567 | 841 | 1500 | 585 | 394 |
| Hasselblad X2D 100C (compressed) | 105.3 | 596 | 359 | 362 | ❌ | 377 | 1007 | 1066 | 1431 | 2113 | ❌ | 1448 | 1007 |
| Phase One IQ4 150MP (IIQ L) | 154.0 | 466 | 458 | ❌ | 655 | 477 | 1451 | 1059 | 2342 | 3352 | 5586 | 2360 | 1451 |
| Sigma fp L | 60.5 | 218 | 208 | 213 | 375 | 227 | 580 | 457 | 844 | 1249 | 2224 | 862 | 580 |
| Apple iPhone 12 Pro (ProRAW) | 12.2 | 124 | 126 | ❌ | 191 | 144 | 96 | 173 | 254 | 337 | 716 | 272 | 96 |
| Google Pixel 8 Pro | 50.1 | 153 | 144 | 148 | 291 | 163 | 481 | 348 | 671 | 1007 | 1822 | 689 | 481 |
| Google Pixel 6 Pro | 12.5 | 49 | 40 | 44 | 111 | 59 | 122 | 98 | 174 | 257 | 494 | 190 | 122 |
| Samsung Galaxy S23 Ultra | 49.9 | 728 | 463 | 371 | 687 | 481 | 384 | 744 | 986 | 1320 | 2402 | 1006 | 384 |
| Samsung Galaxy S22 (JPEG XL) | 12.0 | 655 | ❌ | ❌ | 506 | ❌ | ❌ | 695 | ❌ | ❌ | 991 | ❌ | ❌ |
| DJI Phantom 4 Pro | 20.0 | 86 | 80 | 84 | 115 | 99 | 193 | 210 | 292 | 425 | 763 | 310 | 193 |
| GoPro HERO11 Black (GPR) | 27.1 | 340 | ❌ | 287 | ❌ | ❌ | ❌ | 440 | ❌ | ❌ | ❌ | ❌ | ❌ |
| GoPro HERO10 Black (GPR) | 23.3 | 290 | ❌ | 247 | ❌ | ❌ | ❌ | 375 | ❌ | ❌ | ❌ | ❌ | ❌ |
The colour-managed pipeline split into its stages, all cores. Medians over the popular cameras: on the M1 Ultra the pipeline takes a median 846 ms (LibRaw decode 194, develop 348, Little CMS 282); on the Ryzen 856 ms (194, 280 and 430). On one thread the Little CMS stage dominates (84–85 % of the pipeline): a 16-bit → 8-bit matrix-shaper transform through Little CMS's generic optimised pipeline costs 90–130 ns per pixel, which is why it was run over row blocks on all cores here (Little CMS's own multithreading and SIMD plugins are GPL-3 or commercial, and were not used). FlashRaw needs no separate colour stage: its single pass applies the white balance, the camera-to-sRGB matrix and the sRGB curve per pixel while demosaicing.
Per camera (Apple M1 Ultra, ms):
decode = LibRaw open_buffer + unpack; develop = dcraw_process to 16-bit linear ProPhoto + dcraw_make_mem_image; Little CMS = profiles, transform and conversion to 8-bit sRGB RGBA; FlashRaw = RAW → RGBA8 in one pass.
| Camera | LibRaw decode | LibRaw develop | Little CMS | total | FlashRaw | speedup |
|---|---|---|---|---|---|---|
| Canon EOS R5 (RAW) | 136.6 | 561.0 | 406.6 | 1104.5 | 109.3 | 10.1× |
| Canon EOS R5 (C-RAW) | 140.9 | 566.0 | 409.2 | 1116.2 | 129.4 | 8.63× |
| Canon EOS R5 Mark II (RAW) | 142.4 | 566.8 | 413.0 | 1122.9 | 111.7 | 10.0× |
| Canon EOS R6 Mark II (RAW) | 78.3 | 318.3 | 222.7 | 617.0 | 61.0 | 10.1× |
| Canon EOS R6 Mark III (RAW) | 100.6 | 416.8 | 297.2 | 815.7 | 80.4 | 10.2× |
| Canon EOS R7 (RAW) | 101.2 | 417.9 | 298.6 | 818.9 | 80.3 | 10.2× |
| Canon EOS R8 (RAW) | 76.6 | 316.2 | 224.5 | 612.5 | 60.8 | 10.1× |
| Canon EOS R50 (RAW) | 75.8 | 313.1 | 224.7 | 610.7 | 60.3 | 10.1× |
| Canon EOS 90D (RAW) | 101.7 | 418.9 | 301.8 | 822.0 | 52.7 | 15.6× |
| Canon EOS 5D Mark IV (RAW) | 430.2 | 387.7 | 282.5 | 1100.4 | 39.8 | 27.7× |
| Canon EOS 6D Mark II (RAW) | 388.7 | 341.4 | 242.3 | 968.6 | 33.7 | 28.7× |
| Canon EOS Rebel T7 / 2000D (RAW) | 394.9 | 316.0 | 216.4 | 931.9 | 34.3 | 27.2× |
| Nikon Z8 (14-bit lossless) | 545.7 | 583.8 | 411.3 | 1541.7 | 72.4 | 21.3× |
| Nikon Z9 (14-bit lossless) | 495.2 | 571.7 | 414.1 | 1484.4 | 72.4 | 20.5× |
| Nikon Z6III (lossless) | 282.0 | 312.2 | 227.0 | 824.4 | 41.5 | 19.9× |
| Nikon Zf (lossless) | 269.2 | 322.3 | 230.1 | 819.7 | 41.9 | 19.5× |
| Nikon Z7II (lossless) | 493.9 | 579.2 | 417.9 | 1491.2 | 73.6 | 20.3× |
| Nikon Z50 (lossless) | 248.4 | 276.5 | 193.1 | 716.7 | 36.3 | 19.7× |
| Nikon D850 (14-bit lossless) | 488.1 | 586.7 | 423.9 | 1495.6 | 72.7 | 20.6× |
| Nikon D750 (14-bit lossless) | 259.5 | 322.2 | 218.9 | 800.2 | 40.3 | 19.9× |
| Sony A7 IV (lossless) | 425.3 | 423.4 | 305.7 | 1158.2 | 40.8 | 28.4× |
| Sony A7 IV (compressed) | 86.8 | 424.7 | 299.6 | 814.1 | 26.3 | 30.9× |
| Sony A7R V (lossless) | 773.3 | 764.8 | 558.6 | 2097.5 | 70.5 | 29.7× |
| Sony A1 (compressed) | 130.7 | 633.2 | 457.9 | 1220.4 | 39.3 | 31.1× |
| Sony A7 III (compressed) | 63.7 | 319.4 | 223.3 | 604.4 | 21.2 | 28.6× |
| Sony A7C II (compressed) | 88.9 | 418.4 | 307.7 | 817.9 | 27.5 | 29.7× |
| Sony A9 III (compressed) | 63.4 | 318.9 | 222.7 | 604.3 | 20.1 | 30.0× |
| Sony A6700 (lossless) | 375.4 | 334.6 | 244.3 | 952.2 | 34.2 | 27.9× |
| Sony A6400 (compressed) | 64.2 | 314.3 | 224.8 | 605.1 | 19.9 | 30.5× |
| Sony ZV-E10 (compressed) | 64.2 | 319.0 | 222.6 | 604.1 | 17.7 | 34.1× |
| Fujifilm X-T5 (lossless compressed) | 151.5 | 507.7 | 368.7 | 1031.5 | 74.4 | 13.9× |
| Fujifilm X-H2 (compressed) | 176.5 | 667.5 | 361.1 | 1203.3 | 94.8 | 12.7× |
| Fujifilm X-S20 (lossless compressed) | 128.1 | 341.2 | 245.8 | 711.3 | 54.0 | 13.2× |
| Fujifilm X100VI (lossless compressed) | 154.5 | 695.9 | 363.8 | 1212.0 | 83.6 | 14.5× |
| Fujifilm X-T4 (uncompressed) | 19.9 | 341.5 | 243.0 | 603.4 | 28.3 | 21.3× |
| Fujifilm GFX100 II (lossless compressed) | 277.1 | 1258.5 | 919.7 | 2451.3 | 125.4 | 19.5× |
| Panasonic Lumix S5II | 130.4 | 335.4 | 220.6 | 686.2 | 30.4 | 22.6× |
| Panasonic Lumix GH6 | 133.7 | 348.0 | 232.7 | 717.5 | 32.9 | 21.8× |
| Panasonic Lumix G9II | 138.3 | 348.0 | 235.7 | 719.4 | 32.1 | 22.4× |
| Panasonic Lumix S5 | 9.57 | 335.6 | 224.7 | 569.6 | 18.2 | 31.3× |
| Panasonic Lumix S1R | 124.2 | 652.0 | 429.2 | 1205.6 | 38.0 | 31.7× |
| Panasonic Lumix GH5 | 91.5 | 282.4 | 194.4 | 567.6 | 17.7 | 32.1× |
| OM System OM-1 Mark II | 389.5 | 273.8 | 187.8 | 845.5 | 126.4 | 6.69× |
| OM System OM-5 | 355.0 | 267.0 | 193.6 | 821.2 | 138.8 | 5.92× |
| Olympus E-M1 Mark III | 344.9 | 271.2 | 192.2 | 809.8 | 137.9 | 5.87× |
| Pentax K-3 Mark III | 193.5 | 336.4 | 241.0 | 772.3 | 48.2 | 16.0× |
| Pentax K-1 Mark II | 291.0 | 464.9 | 336.9 | 1094.8 | 60.9 | 18.0× |
| Ricoh GR III | 322.1 | 314.6 | 225.5 | 863.8 | 34.1 | 25.3× |
| Leica Q2 | 285.9 | 594.7 | 435.7 | 1323.7 | 33.1 | 40.0× |
| Leica SL2 | 288.0 | 593.7 | 417.4 | 1301.5 | 33.8 | 38.5× |
| Leica M10-R | 556.7 | 524.1 | 375.6 | 1456.2 | 54.9 | 26.5× |
| Hasselblad X2D 100C (compressed) | 1001.1 | 1264.5 | 930.3 | 3203.9 | 144.2 | 22.2× |
| Phase One IQ4 150MP (IIQ L) | 1036.0 | 3305.0 | 1347.6 | 5691.9 | 133.0 | 42.8× |
| Sigma fp L | 765.9 | 761.8 | 554.5 | 2081.1 | 72.1 | 28.9× |
| Apple iPhone 12 Pro (ProRAW) | 466.7 | 110.8 | 110.2 | 687.6 | 24.3 | 28.3× |
| Google Pixel 8 Pro | 652.0 | 783.8 | 457.3 | 1891.3 | 59.1 | 32.0× |
| Google Pixel 6 Pro | 163.9 | 172.4 | 117.5 | 453.8 | 16.7 | 27.2× |
| Samsung Galaxy S23 Ultra | 1899.3 | 252.7 | 353.6 | 2507.1 | 177.7 | 14.1× |
| DJI Phantom 4 Pro | 19.3 | 271.0 | 185.1 | 474.1 | 18.9 | 25.0× |
Geometric mean speedup of FlashRaw per (format, codec), all cores, Apple M1 Ultra: LibRaw and RawSpeed over the 159 files of both lists, the other libraries over the popular cameras. ❌ = the other library decoded none of these files; – = not measured. Linux: result file.
| Format | Compression | files | decode vs LibRaw | decode vs RawSpeed | decode vs rawler | decode vs rawpy | decode vs dcraw | RGB vs LibRaw | RGB vs LibRaw + LCMS | RGB vs rawler | RGB vs rawpy | RGB vs dcraw |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3FR | hasselblad | 2 | 12.2× | 5.62× | – | – | – | 16.1× | – | – | – | – |
| 3FR | uncompressed | 2 | 0.81× | 0.52× | – | – | – | 18.7× | – | – | – | – |
| ARW | other | 2 | 11.2× | ❌ | – | – | – | 10.2× | – | – | – | – |
| ARW | sony-arw1 | 2 | 6.21× | 3.41× | – | – | – | 11.8× | – | – | – | – |
| ARW | sony-arw2 | 9 | 12.7× | 1.40× | 1.44× | 14.4× | 45.3× | 18.3× | 30.7× | 7.23× | 21.4× | 24.4× |
| ARW | sony-lossless | 4 | 17.2× | 0.70× | 2.10× | 22.5× | ❌ | 16.1× | 28.7× | 5.49× | 22.9× | ❌ |
| ARW | uncompressed | 2 | 8.59× | 0.43× | – | – | – | 12.9× | – | – | – | – |
| CR2 | canon-sraw | 2 | 16.1× | 3.94× | – | – | – | 14.5× | – | – | – | – |
| CR2 | lossless-jpeg | 5 | 20.6× | 5.88× | 12.6× | 20.9× | 29.1× | 20.7× | 27.9× | 10.9× | 22.2× | 24.6× |
| CR3 | canon-crx | 11 | 1.74× | ❌ | 2.76× | 5.48× | ❌ | 6.81× | 10.4× | 4.39× | 10.2× | ❌ |
| CRW | canon-crw | 2 | 2.71× | 2.00× | – | – | – | 5.17× | – | – | – | – |
| CRW | uncompressed | 1 | 7.72× | ❌ | – | – | – | 12.7× | – | – | – | – |
| DCR | kodak-65000 | 2 | 2.65× | 3.54× | – | – | – | 7.81× | – | – | – | – |
| DCS | lossless-jpeg | 1 | 11.2× | 2.95× | – | – | – | 15.5× | – | – | – | – |
| DCS | uncompressed | 2 | 4.66× | 34.9× | – | – | – | 20.8× | – | – | – | – |
| DNG | deflate | 2 | 13.7× | 1.03× | – | – | – | 17.7× | – | – | – | – |
| DNG | gopro-vc5 | 2 | ❌ | 0.48× | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| DNG | jpeg-xl | 1 | ❌ | ❌ | 0.63× | ❌ | ❌ | ❌ | ❌ | 0.73× | ❌ | ❌ |
| DNG | lossless-jpeg | 9 | 21.5× | 2.63× | 3.67× | 22.5× | 32.3× | 19.4× | 25.4× | 6.14× | 20.6× | 23.4× |
| DNG | uncompressed | 5 | 28.5× | 4.45× | 1.13× | 48.6× | 148.2× | 20.3× | 33.8× | 7.17× | 25.8× | 30.5× |
| ERF | uncompressed | 2 | 8.74× | 1.44× | – | – | – | 15.4× | – | – | – | – |
| FFF | hasselblad | 2 | 12.8× | 5.87× | ❌ | 14.5× | 28.9× | 16.0× | 22.2× | ❌ | 18.1× | 22.3× |
| IIQ | phaseone | 3 | 22.5× | 28.4× | 8.10× | 25.2× | 98.6× | 31.3× | 42.8× | 7.16× | 35.7× | 45.0× |
| IIQ | phaseone-s | 2 | 14.2× | ❌ | – | – | – | 28.0× | – | – | – | – |
| IIQ | uncompressed | 1 | 0.77× | ❌ | – | – | – | 37.2× | – | – | – | – |
| KDC | kodak-dc120 | 1 | 1.97× | ❌ | – | – | – | 4.49× | – | – | – | – |
| KDC | other | 1 | 1.48× | ❌ | – | – | – | 2.89× | – | – | – | – |
| KDC | uncompressed | 2 | 52.7× | 10.8× | – | – | – | 22.4× | – | – | – | – |
| MEF | uncompressed | 1 | 55.5× | 11.1× | – | – | – | 26.8× | – | – | – | – |
| MOS | leaf | 2 | 12.6× | ❌ | – | – | – | 15.9× | – | – | – | – |
| MOS | uncompressed | 1 | 11.9× | 11.3× | – | – | – | 21.9× | – | – | – | – |
| MRW | minolta-packed | 2 | 56.0× | 11.6× | – | – | – | 22.4× | – | – | – | – |
| MRW | uncompressed | 2 | 9.00× | 8.29× | – | – | – | 19.5× | – | – | – | – |
| NEF | nikon-huffman | 9 | 10.8× | 3.99× | 7.19× | 11.4× | 17.4× | 15.0× | 20.2× | 7.77× | 16.2× | 16.9× |
| NEF | uncompressed | 2 | 6.19× | 2.75× | – | – | – | 20.8× | – | – | – | – |
| NRW | uncompressed | 2 | 2.99× | 1.34× | – | – | – | 18.4× | – | – | – | – |
| ORF | olympus | 5 | 2.93× | 1.26× | 1.77× | 2.95× | 1.76× | 4.79× | 6.15× | 2.46× | 4.92× | 3.23× |
| ORF | uncompressed | 2 | 16.3× | 2.69× | – | – | – | 20.2× | – | – | – | – |
| PEF | pentax-huffman | 4 | 7.36× | 3.16× | 6.28× | 10.2× | 15.9× | 12.4× | 17.0× | 7.08× | 14.6× | 16.7× |
| PEF | uncompressed | 2 | 18.6× | 8.09× | – | – | – | 21.4× | – | – | – | – |
| RAF | fuji-compressed | 7 | 4.26× | 1.22× | 2.59× | 32.9× | ❌ | 10.2× | 14.6× | 4.95× | 25.3× | ❌ |
| RAF | uncompressed | 3 | 4.48× | 0.78× | 2.03× | 10.4× | 100.0× | 15.2× | 21.3× | 6.91× | 14.8× | 15.3× |
| RAW | uncompressed | 3 | 7.81× | 12.5× | – | – | – | 16.0× | – | – | – | – |
| RW2 | panasonic-v4 | 3 | 18.7× | 1.02× | 1.50× | 19.5× | 43.6× | 21.6× | 32.1× | 5.53× | 24.2× | 25.0× |
| RW2 | panasonic-v5 | 2 | 6.23× | 0.63× | – | – | – | 18.8× | – | – | – | – |
| RW2 | panasonic-v6 | 2 | 13.0× | 0.94× | 1.27× | 14.3× | 54.9× | 20.6× | 31.7× | 5.64× | 23.5× | 23.6× |
| RW2 | panasonic-v7 | 3 | 3.62× | 0.25× | 1.45× | 3.28× | 92.3× | 20.3× | 31.3× | 6.21× | 22.3× | 26.5× |
| RW2 | panasonic-v8 | 5 | 8.09× | 3.70× | 7.58× | 16.1× | 15.6× | 15.3× | 22.3× | 7.20× | 20.7× | 16.0× |
| RW2 | uncompressed | 2 | 8.52× | 0.73× | – | – | – | 19.2× | – | – | – | – |
| SRW | samsung-v0 | 2 | 10.5× | 3.47× | – | – | – | 15.8× | – | – | – | – |
| SRW | samsung-v1 | 2 | 2.67× | 1.10× | – | – | – | 5.12× | – | – | – | – |
| SRW | samsung-v2 | 2 | 1.75× | 0.92× | – | – | – | 3.82× | – | – | – | – |
| SRW | uncompressed | 2 | 49.1× | 9.60× | – | – | – | 23.6× | – | – | – | – |
| X3F | sigma-x3f | 2 | 6.27× | ❌ | – | – | – | 7.07× | – | – | – | – |
| other | kodak-ycbcr | 1 | 8.75× | ❌ | – | – | – | 9.59× | – | – | – | – |
| other | uncompressed | 2 | 8.54× | 11.4× | – | – | – | 19.6× | – | – | – | – |
Honest list, from the result files (popular cameras and the 159-file set):
- RAW → sRGB with all cores: never, against any library, on either machine, except the one JPEG XL DNG (Samsung Galaxy S22), where rawler, whose JPEG XL decoder is faster, wins by 1.2× (Linux) and 1.4× (macOS). On one thread LibRaw is faster on 5 (Linux) and 4 (macOS) of 156 files, mostly large uncompressed files and old Kodak formats (up to 2.8× on a Kodak DC120), and dcraw on the two OM System ORFs (1.04–1.14×).
- Decode with all cores, Linux: 16 losses in 442 comparisons (file × other library).
- Canon CR3: close to LibRaw's OpenMP build, which also decodes CR3 in parallel; LibRaw is 1–6 % faster on three CR3 files (rawpy, which is LibRaw, is 7 % faster on one) and slower on the others (on the M1 Ultra FlashRaw is 1.7× faster on all of them). LibRaw is also faster on two small uncompressed files (Nikon Coolpix A1000, GITUP: 1.3×).
- RawSpeed, 9 of 126 files: GoPro GPR (1.7–2.1×), the Sony pixel-shift ARQ (3.1×), small uncompressed files that take 1–4 ms (Nikon Coolpix A1000, GITUP, Epson R-D1, Fujifilm X-E2: up to 1.5×), a Canon EOS 500D CR2 and the Panasonic Lumix S5 (v7).
- rawler: the JPEG XL DNG (1.5×).
- Decode with all cores, Apple M1 Ultra: 38 losses in 442 comparisons, mostly against
RawSpeed (30 of 126 files):
- Memory-bound uncompressed and packed data (3FR, RAF, NEF, NRW, ARW, RW2, Panasonic v5–v7): RawSpeed 1.1–2× faster, and 4× on Panasonic v7 (Lumix S5) and the Sony pixel-shift ARQ. These take 1–10 ms in every library; FlashRaw caps such copy kernels at a few threads, which is right on the Ryzen but leaves bandwidth unused on the M1 Ultra. LibRaw is also faster on 7 of these files (1.1–1.4×).
- Sony lossless ARW: RawSpeed 1.3–1.6× faster. Tiled lossless-JPEG DNG from phones and the Sigma fp L: RawSpeed 1.2–1.3× faster. GoPro GPR: RawSpeed 2× faster. Samsung NX1/NX500 (V2): RawSpeed 1.1× faster (a strictly sequential codec).
- rawler: the JPEG XL DNG (1.6×).
- One thread (decode): FlashRaw beats LibRaw on 143 (Linux) and 139 (macOS) of 156 files, rawler on 57 and 56 of 59, rawpy on 58 and 57 of 59, dcraw on 40 of 42 (both machines; the exceptions are the two OM System ORFs). Against RawSpeed it is faster on 96 of 126 files on Linux, but only 40 of 126 on the M1 Ultra (13 of the 49 popular cameras), where RawSpeed's single-threaded decoders are 1.2× faster on the popular cameras (geometric mean). FlashRaw's lead with all cores comes from parallelising the codecs the others run on one thread.
- Memory: a plain decode on all cores needs more memory with FlashRaw than with LibRaw or RawSpeed (see Memory); for RAW → sRGB on all cores dcraw's peak is about the same as FlashRaw's (lower on 22 of 42 files on the M1 Ultra).
- Formats the others do not decode at all are not in these counts: Canon CR3 (RawSpeed, dcraw), Phase One IIQ S and 150 MP, Sigma X3F (RawSpeed), GoPro GPR (LibRaw, rawpy, rawler, dcraw), JPEG XL DNG (LibRaw, rawpy, RawSpeed, dcraw), iPhone ProRAW (RawSpeed), current Fujifilm compressed RAF (dcraw), Hasselblad X2D compressed FFF (rawler).
Results of tools/bench/run.py (all formats of the benchmark set, both modes):
linux-x86_64.md,
macos-arm64.md. Median throughput over the set:
| decode | RAW → RGBA8 | |
|---|---|---|
| Linux, Ryzen 7 9700X (16 threads, CPU) | 2,061 MP/s | 583 MP/s |
macOS, M1 Ultra (20 threads, Backend::Auto: GPU develop where it wins) |
3,148 MP/s | 1,122 MP/s |
Uncompressed and packed formats run at memory bandwidth; entropy-coded formats are bound by their entropy decoder (parallel over tiles, strips or blocks where the format has them, and by speculation over single streams otherwise — see architecture.md). Single sequential streams are decoded in parallel by speculation (lossless JPEG, Hasselblad, Nikon, Pentax, Panasonic v8 strips, Sony ARW1). Samsung V2 cannot be: rows start wherever the previous one ended and are predicted from earlier rows, so it runs on one thread with a staged block decoder.
| Kernel | Throughput |
|---|---|
| 12-bit MSB unpack, scalar reference | 1.05 G samples/s |
| 12-bit MSB unpack, SSE4.1 | 8.8 G samples/s |
| 16-bit LE unpack (fast / SIMD) | 35–37 G samples/s |
| Lossless JPEG decode, 2 components (synthetic) | 617 M samples/s |
Unpack/copy kernels are memory-bound: on the Ryzen they peak at ~4 threads and get
1.7–1.9× slower at 16 threads (memory-controller and page-fault contention), e.g. a
24.6 MP 14-bit DNG unpacks in 7.8 ms (1 thread), 3.0 ms (4), 5.2 ms (16). FlashRaw caps
such kernels with par::memory_bound_workers() (threads/4, clamped to 2–8) while
entropy decoders and the develop pass use all cores. Large output buffers are
advised as transparent huge pages (MADV_HUGEPAGE), cutting page faults ~500×.
A single-threaded decode (threads: 1, --threads 1) runs on the calling thread, exactly like
RAYON_NUM_THREADS=1. (It used to run on a dedicated one-worker pool, whose thread macOS
could schedule on an efficiency core: about 3× slower on the M1 Ultra in one benchmark round.)
Explicit pools (threads: n) run their workers with the user-initiated quality of service on
Apple platforms.
The "FlashRaw GPU" column of the macOS tables is end to end through the CLI (per-process
timing, frame downloaded to host memory). The GPU develop pass replaces the CPU one, so it
helps most where development dominates: on the popular cameras RAW → RGB is 1.3× faster with
the GPU than with 20 CPU threads (geometric mean over the 52 files where it ran; up to 3.1×
for packed and uncompressed data) and 17.1× faster than LibRaw. Some files fall back to the CPU
(marked CPU¹ in the result file). Resident output (no download) and per-kernel timings are in
gpu.md (cargo bench -p flashraw-gpu --bench gpu_pipeline, median of 7):
| File | Case | CPU | GPU (download) | GPU (resident) |
|---|---|---|---|---|
| Leica Q2 47 MP, packed 14-bit | raw u16 unpack | 2.3 ms | 6.4 ms | 3.4 ms |
| Leica Q2 | RAW → RGBA8 | 34.5 ms | 13.9 ms | 8.5 ms |
| Leica Q2 | RAW → RGBA8 half-size | 23.7 ms | 6.9 ms | 5.3 ms |
| Nokia 1020 38 MP, packed 10-bit | RAW → RGBA8 | 27.8 ms | 11.4 ms | 6.6 ms |
| Leica CL 24.6 MP | RAW → RGBA8 | 19.2 ms | 7.7 ms | 4.8 ms |
| Pentax 645Z 52 MP, LJPEG | RAW → RGBA8 | 278.0 ms | 261.1 ms | 258.1 ms |
The GPU wins the development pipeline (2.5–4× resident) and loses raw unpacking (the
CPU is at memory bandwidth); for entropy-coded files the CPU decode dominates.
Backend::Auto picks the faster side. No discrete GPU was available for measurement.
From wasm.md: single-threaded WASM runs lossless JPEG at 1.2–1.6× native single-thread time and the RAW → RGBA8 pipeline at 1.2–1.4×; the threaded build lands at 1.3–2.2× native all-core time on 46–103 MP files (M1 Ultra), and WebGPU develops a 42 MP uncompressed ARW to a resident texture in 15 ms. SIMD128 halves packed unpack time vs the non-SIMD build.
Bundle size with all decoders (wasm-opt -O3), from wasm.md, which has every variant (threads, WebGPU, JPEG XL):
| Binary | Raw | gzip -9 | brotli -11 |
|---|---|---|---|
flashraw_simd.wasm |
2897 KiB | 1006 KiB | 756 KiB |
flashraw.wasm (fallback) |
2847 KiB | 986 KiB | 738 KiB |
tools/bench/run.py ... --baseline <old.jsonl> --tolerance 15 prints per-file
before/after and fails on slowdowns beyond the tolerance (used by perf.yml, which
benchmarks the PR and main on the same runner).