From 831ab61445fe6b55a3e704161592c1797224e4ad Mon Sep 17 00:00:00 2001 From: James Date: Mon, 23 Mar 2026 12:20:36 -0400 Subject: [PATCH] fix: add JPEG 2000 and RLE support via gdcmconv (install libgdcm-tools) The decompressDICOM path used gdcmconv which wasn't installed on the server, silently failing all compressed DICOM imports. Fix: - Install libgdcm-tools (gdcmconv 3.0.22) on forge - Expand isCompressedTransferSyntax to explicitly cover: - JPEG 2000 Lossless (1.2.840.10008.1.2.4.90) - JPEG 2000 Lossy (1.2.840.10008.1.2.4.91) - JPEG 2000 Multi-component (1.2.840.10008.1.2.4.92/.93) - RLE Lossless (1.2.840.10008.1.2.5) - Deflated Explicit VR (1.2.840.10008.1.2.1.99) - JPEG-LS already covered by 1.2.840.10008.1.2.4 prefix - gdcmconv -w handles all of these natively gdcmconv is now available at /usr/bin/gdcmconv (v3.0.22). JPEG 2000 lossless DICOMs from any scanner will now import correctly. --- lib/dicom.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/dicom.go b/lib/dicom.go index 7640c3e..700f997 100644 --- a/lib/dicom.go +++ b/lib/dicom.go @@ -832,10 +832,21 @@ func getTransferSyntax(data []byte) string { } func isCompressedTransferSyntax(ts string) bool { - return strings.HasPrefix(ts, "1.2.840.10008.1.2.4") + // JPEG family: 1.2.840.10008.1.2.4.x (baseline, extended, lossless, JPEG 2000, etc.) + // JPEG-LS: 1.2.840.10008.1.2.4.80 / .81 + // JPEG 2000 Lossless: 1.2.840.10008.1.2.4.90 + // JPEG 2000 Lossy: 1.2.840.10008.1.2.4.91 + // JPEG 2000 Multi: 1.2.840.10008.1.2.4.92 / .93 + // RLE Lossless: 1.2.840.10008.1.2.5 + // Deflated: 1.2.840.10008.1.2.1.99 + return strings.HasPrefix(ts, "1.2.840.10008.1.2.4") || + ts == "1.2.840.10008.1.2.5" || + ts == "1.2.840.10008.1.2.1.99" } -// decompressDICOM uses gdcmconv to decompress any JPEG-compressed DICOM. +// decompressDICOM uses gdcmconv to decompress any compressed DICOM transfer +// syntax (JPEG, JPEG 2000 Lossless/Lossy, JPEG-LS, RLE, Deflated). +// Requires gdcmconv from libgdcm-tools (apt install libgdcm-tools). func decompressDICOM(dicomPath string) ([]byte, error) { tmpFile := fmt.Sprintf("/tmp/dcm_%d_%d.dcm", os.Getpid(), time.Now().UnixNano()) defer os.Remove(tmpFile)