compression: read plain LZ4 (HDF5 filter 32004), and name the filter when one is unsupported

DECTRIS Eiger firmware 1.x compressed its images with the HDF Group's plain LZ4 filter rather than
bitshuffle, and files from that era are still what a repository hands you. Read-only: nothing here
produces it, and the new enumerator goes last so the existing values do not move, the enum being
part of the CBOR stream.

The framing is the same as bitshuffle's - a 64-bit big-endian total size, a 32-bit big-endian block
size in bytes, then each block prefixed by its 32-bit big-endian compressed size - so only the
unshuffle step differs. Verified on a real chunk: the declared total matched width*height*4 exactly
and the block walk consumed the chunk to the byte. It cannot reuse the bitshuffle path, which
requires the block to be a multiple of BSHUF_BLOCKED_MULT elements: these files put the whole image
in ONE block, which is not.

The unsupported-filter message now names the filter it found and the ones it knows. Before, an
Eiger 1.x file did not report a codec problem at all - it reached spot finding with nothing decoded
and failed as "0 spots from 60 images" then "found no lattice", which reads as a crystallography
failure rather than a format one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-28 21:56:12 +02:00
co-authored by Claude Opus 5
parent 84d14696b1
commit a7615c8778
3 changed files with 77 additions and 4 deletions
+5 -1
View File
@@ -3,4 +3,8 @@
#pragma once
enum class CompressionAlgorithm {BSHUF_LZ4, BSHUF_ZSTD, BSHUF_ZSTD_RLE, BSHUF_ZSTD_RLE_HUFF, NO_COMPRESSION};
// LZ4_NO_SHUFFLE is READ-ONLY: HDF5 filter 32004, plain LZ4 with no bit shuffle, written by DECTRIS
// Eiger firmware 1.x. Nothing here produces it. It is last so the values of the others do not move -
// the enum crosses the CBOR stream.
enum class CompressionAlgorithm {BSHUF_LZ4, BSHUF_ZSTD, BSHUF_ZSTD_RLE, BSHUF_ZSTD_RLE_HUFF, NO_COMPRESSION,
LZ4_NO_SHUFFLE};