Releases: Raster-Lab/DICOMKit
Release list
DICOMKit v2.2.9 — SwiftPM Build Hygiene
DICOMKit v2.2.9
Patch release resolving SwiftPM consumer build-hygiene warnings and hardening
immutable release publication.
SwiftPM build hygiene
- Excluded the documentation-only
README.mdfiles from thedicom-3dand
dicom-j2kexecutable targets. Consumer package planning no longer emits the
two unhandled-file warnings reported by RasterOneImage V2-029. - Excluded the intentionally inactive complements of the explicitly sourced
DICOMKitTestsandDICOMViewerTeststargets. This removes two additional
planning warnings covering 102 test files without changing which tests compile. - Applied the existing optional-fixture contract to two HTJ2K benchmark tests;
clean checkouts now skip them when the gitignored MR corpus is unavailable. - No decoder, runtime, product API, ABI, resource, or command behavior changed.
Release infrastructure
- Release builds now compile with warnings as errors and reject any remaining
SwiftPM or compiler warning in captured build output. Release tests also fail
if an unhandled-file package-planning warning recurs. - The release artifact matrix now matches all 36 enabled CLI products, including
dicom-jpipanddicom-j2k. - Manually dispatched release jobs now check out the requested tag in every job,
preventing artifacts from a different ref from being locked into a release. - GitHub releases are assembled as drafts before publication so their tags and
assets can be locked by GitHub immutable releases.
Verification
swift package dump-package: passed.swift build -c release --product dicom-3d -Xswiftc -warnings-as-errors:
passed with zero warnings.swift build -c release --product dicom-j2k -Xswiftc -warnings-as-errors:
passed with zero warnings.swift test --filter dicom_j2kTests: 53 tests passed with zero warnings.swift build -Xswiftc -warnings-as-errors: passed with zero warnings.swift build -c release -Xswiftc -warnings-as-errors: passed with zero warnings.PARITY_STRICT=1 PARITY_COVERAGE_MIN=19.8 swift test --filter StudioParityTests:
160/160 scenarios matched with 26.5% output-flag coverage and zero warnings.
Validation used Swift 6.3.3 on macOS. GitHub Actions independently repeated the Swift 6.2 release and debug builds: the warnings-as-errors release build completed cleanly and 1,175 XCTest cases passed. The larger Swift Testing phase then reproduced the pre-existing, load-dependent CommandExecutor cancellation hang and was canceled after a 15-minute unchanged log; that test passes in isolated runs. The arm64 release archive was verified to contain all 36 CLI products, and its SHA-256 is published alongside it.
DICOMKit v2.2.8 — DIMSE Security & J2KSwift v11.0.2
DICOMKit v2.2.8
Patch release hardening DIMSE security propagation and updating the JPEG 2000
codec dependency.
Security and networking
- Preserved the complete TLS policy and user identity across every
DICOMClientDIMSE route, association setup, connection pooling, query,
retrieve, verification, and storage operation. - Tightened cancellation and timeout handling so cancelled work cannot submit a
late credential-bearing association, pending transports are aborted, and
abandoned batch C-STORE producers terminate promptly. - Redacted credential-bearing DIMSE values from descriptions and recursive
reflection while retaining useful non-secret diagnostics. - Added focused cross-platform and security-propagation regression coverage.
JPEG 2000 codecs
- Updated the J2KSwift dependency floor and tracked resolution to v11.0.2
(b1949084eeedaafb40bff8f1745bbab19e4bc36d). - Adopted upstream decoder fixes that stop truncated quality-layer decoding at
the exact coding-pass boundary and limit scratch clearing to the active
code-block region. - DICOMKit public APIs and J2KSwift codestream structure remain unchanged.
Build infrastructure
- CI and release workflows now select an installed Swift 6.2 toolchain instead
of assuming a single Xcode installation name. - Removed the optional DICOMStudio OpenJPEG comparison wrapper from
DICOMCore's default dependency graph. Standalone macOS consumers no longer
require Homebrew, an absolutelibopenjp2.apath, or an arm64-only build. - Production JPEG 2000 support remains provided by J2KSwift.
- Optional real-image codec tests now report as skipped when their gitignored
LocalDatasetsorSampleStudiescorpora are not installed in CI.
Validation
J2KSwiftCodecTests: 20/20 passed.DICOMClientSecurityPropagationTests: 17/17 passed.swift build -c release: passed.- The tag-triggered release workflow performs the repository's full test, CLI,
and documentation release gates before publishing assets.
DICOMKit v2.2.7 — J2KSwift v11.0.1
DICOMKit v2.2.7
Patch release updating the JPEG 2000 dependency used by DICOM pixel decoding.
Changed
- Updated the J2KSwift package requirement from v11.0.0 to v11.0.1.
- Verified SwiftPM resolution against the released v11.0.1 revision (the
repository intentionally ignores its generatedPackage.resolved). - Updated documentation to identify J2KSwift v11.0.1 as the supported codec
baseline.
Compatibility
- DICOMKit public APIs are unchanged.
- DICOM transfer syntax handling is unchanged.
- Decoded pixels remain bit-identical; the upstream change only removes
redundant EBCOT decoder scratch state and adds a zero-pass fast path.
Validation
swift build -c release- Focused DICOM/J2K integration coverage: 16 codec, registry, transfer-syntax,
and round-trip tests passed. - The full suite was attempted; existing fixture-dependent benchmarks require
the repository's optionalLocalDatasetscorpus and are not part of this
dependency-only patch gate.
v2.2.6 — Transfer-syntax negotiation list + backend/lossless reporting fixes
Shared transfer-syntax negotiation token list for dicom-retrieve/dicom-qr, plus two reporting-accuracy fixes (--backend, dicom-compress info lossless state). No association-negotiation or encode-behavior changes — this release only corrects what tools report and what token lists they offer.
Added
TransferSyntax.negotiableImageSyntaxTokens/negotiableImageTokens(DICOMCore) is now the single source of truth for the transfer-syntax lists offered bydicom-retrieve/dicom-qr— the negotiation analogue ofCompressionManager.supportedCodecs()(dicom-compress) andDICOMConverter.cliTokens(dicom-convert). Every token round-trips throughTransferSyntax.parse().- The DICOMStudio CLI Workshop
dicom-retrieve/dicom-qrpickers and the CLI--transfer-syntaxhelp now derive from that shared list, adding the previously-missing JPEG-LS, JPEG XL, and JPEG 2000 Part 2 (plusexplicit-vr-be,deflate,jpeg-extended,jpeg-lossless-sv1) syntaxes the old hand-maintained lists stopped short of. - CLI Workshop: the
dicom-converttransfer-syntax dropdown now shows the short kebab aliases (e.g.jpeg2000-lossless,htj2k-lossy) instead of CamelCase, matching the other tool pickers. The CLI resolves the alias identically, so generated commands are unchanged.
Fixed
dicom-compress info: for theboth-capable general J2K/HTJ2K/JXL UIDs (.91/.93/.203/.112),isLosslessand the transfer-syntax display name are now derived from Lossy Image Compression (0028,2110) instead of the UID-level flag, which always reported "Lossy". A file reversibly encoded into a general UID now reportsTransfer Syntax: JPEG 2000 Lossless/Lossless: Yesconsistently instead of contradicting itself.--backendreporting now reflects the backend an encode actually dispatches to, not the best available hardware. Metal (GPU) is only used for genuinely lossy JPEG 2000/HTJ2K encodes (the lossless GPU path isn't bit-exact on 12/16-bit medical data), soauto/--backend metalpreviously reported "Metal (GPU)" for lossless/non-J2K encodes that actually ran on the CPU. An explicit--backend metalrequest that can't use the GPU is now downgraded with an explanatory note.CodecBackend.accelerate.displayNamereports "Accelerate (CPU)" instead of the stale "Accelerate (not available)" now that the old J2KAccelerate SIMD probe has been removed upstream (J2KSwift v11.0.0) while Accelerate itself remains available.
v2.2.5 — DICOMDIR navigation offsets (cross-reader interop)
DICOMDIRWriter now computes the DICOMDIR navigation offsets it previously left as 0, so file-sets it writes are navigable by strict offset-following readers (pydicom FileSet, dcmtk), not only DICOMKit's own offset-tolerant reader.
- Computes Offset of the First/Last Directory Record (0004,1200/1202) and each record's Offset of Next Directory Record (0004,1400) / Offset of Referenced Lower-Level Directory Entity (0004,1420) — absolute file offsets to each record's
(FFFE,E000)item tag (PS3.3 F.3.2.2). - Two-pass encode: measure item byte positions with zero offsets, then re-encode with the real values (each a fixed 4-byte UL → byte-identical layout). File meta is generated once and reused across both passes (its fresh SOP Instance UID length would otherwise shift item positions).
- Verified against
pydicom.fileset.FileSet(previouslyKeyError; now reads a DICOMKit multi-series DICOMDIR) + a self-contained byte-offset oracle.
Fixes the interoperability limitation noted for DICOMDIR media export.
v2.2.4 — DICOMDIR reader multi-series fix
Fixes DICOMDIRReader dropping all but the last series when reading a DICOMDIR.
parseDirectoryRecordSequencerebuilt the PATIENT→STUDY→SERIES→IMAGE hierarchy from the flat record sequence, but (becauseDirectoryRecordis a value type) the.study/.seriescases mutated a copy of the current study/patient and never wrote it back. A study with N series round-tripped/imported as just its last image; every earlier series silently vanished.- The mutated records are now written back to
currentStudy/currentPatient. - Single-series-per-patient (the only shape the prior round-trip tests exercised) was unaffected, which is why it went unnoticed.
- Added
DcmdirRoundTripTests.testWriteReadMultiSeriesRoundTrip(1 study, 2 series, 2+1 images → recovers seriesCount 2 / imageCount 3).
v2.2.3 — Waveform (ECG) tag-group + UL sample-count fix
Fixes DICOM Waveform (ECG / hemodynamic / audio) decoding so standards-compliant waveforms parse.
- Tag groups corrected
0x5400→0x003A(PS3.6): all 25 acquisition/channel-definition attributes plus 9 Waveform Presentation attributes (e.g. Number of Waveform Channels003A,0005, Sampling Frequency003A,001A, Channel Position003A,0245VR FL). The genuinely group-5400attributes (Waveform Sequence, Bits Allocated, Sample Interpretation, Waveform Data) are unchanged. - Number of Waveform Samples (
003A,0010, VR UL):WaveformParsernow reads it as a 32-bit UL (previouslyuint16, which threw "Missing Number of Waveform Samples" on real ECGs), andWaveformBuilderwrites a proper binary UL instead of an ASCII string. - Added
WaveformParseRegressionTests(full build→parse round-trip over group003A).
Before this, WaveformParser rejected every conformant waveform.
v2.2.2 — Explicit VR Big Endian read fix
Fix: Explicit VR Big Endian (1.2.840.10008.1.2.2) reading
Big-endian datasets were mis-decoded on read — the parser read the element structure with the correct byte order but did not carry it onto the produced `DataElement`, so numeric accessors decoded little-endian. Bits Allocated 16 read back as 4096, and native 16-bit pixel samples were byte-swapped (noise). The write path and `TransferSyntaxConverter` already handled big endian; only the read path had the gap.
Changes
- `DataElement` gains `byteOrder` (defaults to `.littleEndian`); numeric accessors (US/UL/SS/SL/FL/FD + arrays) decode per byte order.
- `DICOMParser` threads the transfer syntax's byte order onto every constructed element (dataset, sequences, encapsulated, pixel data).
- Native uncompressed 16-bit pixels are normalized to little endian on extraction.
The little-endian path is byte-for-byte unchanged. Verified on a real Explicit VR Big Endian study (Philips IQon Spectral CT): Bits Allocated reads 16 and pixels decode correctly. New tests: `DataElementByteOrderTests`, `BigEndianParsingTests`; existing suites remain green.
DICOMKit v2.2.1 — Strict-Concurrency Bridge Fix & Warnings Cleanup
Patch release: Swift 6 strict-concurrency bridge fix plus package-wide warning cleanup. Both swift build and swift build -Xswiftc -warnings-as-errors pass cleanly; no runtime behavior changes.
Fixed — Swift 6 Strict-Concurrency Task Bridge in CLI Targets
- Fixed the
DispatchSemaphore+Task {}async-to-sync bridge pattern used by CLI entry points (dicom-jpip,dicom-3d,dicom-j2k,dicom-viewer) so strict concurrency no longer flags data-race sendability risks. The bridge now usesTask.resultwith an explicitly documented manually-synchronized capture (nonisolated(unsafe)), preserving runtime behavior. - Cleaned up adjacent strict/warnings-as-errors diagnostics in shared runtime files (
ScriptEngine,DICOMDIRReader/DICOMDIRWriter,ImagePreprocessor,ImageResizer,JP3DVolumeBridge,JP3DVolumeDocument,StudyManager, gateway helpers, compression manager).
Fixed — Remaining -warnings-as-errors Diagnostics Across the Package
- dicom-3d: never-mutated
varlocals converted tolet; redundanttry/try?removed from non-throwingDataSetaccessor calls. - DICOMWeb: redundant
awaitremoved from synchronous same-isolation calls; unusedguard let urlbinding replaced with an existence test; unused locals dropped. - DICOMStudio: pure static J2K test helpers marked
nonisolated(they already executed off the main actor); pipe-drain captures use the documentednonisolated(unsafe)+ happens-before pattern; cine timer callback wrapped inMainActor.assumeIsolated; sliderBindingsetters made Sendable-safe; unused locals removed.
Full changelog: https://github.com/Raster-Lab/DICOMKit/blob/main/CHANGELOG.md
DICOMKit v2.2.0 — CLI Parity Harness & JPEG XL Lossy/Recompression
Highlights
This release merges the feature/cli-parity-harness branch into main: a large batch of shared-core CLI/App parity work, new codec support, and a round-trip regression suite.
CLI ↔ App Parity (shared core, no more drift)
- Hoisted every remaining hand-duplicated console block and directory walk into shared DICOMKit/DICOMNetwork/DICOMWeb types used by both the CLI binaries and the DICOMStudio Workshop:
AnonConsole,PixelEditConsole,ImageConsole,ExportConsole,UIDConsole,UPSConsole,ConvertConsole,TagEditConsole,QRSessionState,DataExchangeWorkflow,FileGatherer,CompressionConsole,DICOMConverter,DICOMDIRDumpFormatter,DICOMDIRWorkflow,EncapsulatedDocumentWorkflow,NetworkConsoleFormatter,WADORetrieveConsoleFormatter,STOWResultFormatter,UPSResultFormatter. - Full network + DICOMweb CLI parity harness: QR, Retrieve, WADO (RS/URI), MWL, MPPS, and UPS-RS (full operation matrix + global subscribe).
- Fixed real drift found while hoisting: pixedit double-print, anon verbose/exit-code divergence, UPS response wording, dicom-merge sort order, dicom-mpps N-CREATE status guard, HL7 ORM^O01 field placement, WADO-URI endpoint resolution.
- Implemented previously inert flags:
dicom-merge --format enhanced-ct/mr/xa,dicom-script run --parallel,dicom-compress --backend,dicom-image --use-exifwith--split-pages,dicom-dcmdir update,dicom-query --referring-physician. - Removed declared no-ops:
dicom-json --format standard|dicomweband--stream.
New Codec Support
- JPEG XL lossy encode (
…4.112) indicom-compressvia JXLSwift VarDCT. - JPEG XL JPEG recompression (
…4.111) indicom-convert— byte-identical JPEG reconstruction. - J2KSwift v3.2.0 integration; JLISwift/JXLSwift promoted to full registry codecs.
Fixes
DICOMWriterno longer drops encapsulated (compressed) pixel data on transcode.DICOMFile.pixelData()no longer relabels YBR as RGB.- JPEG-LS NEAR parameter overflow fixed for 16-bit sources.
PixelEditornow decodes encapsulated sources before editing (handles multi-frame).dicom-pixedit --invertno longer renders solid white (VOI window now inverted correctly).
Testing
- New
DICOMRoundTripTestoracle-based regression suite (393 tests) covering all localdicom-*tools against a real anonymized corpus. - New DICOMKitTests parity/regression suite; Network CLI & DICOMweb test coverage expanded.
Also Included
- Network Utility panel with live-streaming terminal output.
- DICOM Standard Edition update.
See CHANGELOG.md for the full itemized history.