Skip to content

Releases: Raster-Lab/DICOMKit

DICOMKit v2.2.9 — SwiftPM Build Hygiene

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 15 Jul 04:52
Immutable release. Only release title and notes can be modified.

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.md files from the dicom-3d and
    dicom-j2k executable 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
    DICOMKitTests and DICOMViewerTests targets. 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-jpip and dicom-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

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 11 Jul 06:47

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
    DICOMClient DIMSE 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 absolute libopenjp2.a path, 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
    LocalDatasets or SampleStudies corpora 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

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 10 Jul 14:20
d453599

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 generated Package.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 optional LocalDatasets corpus and are not part of this
    dependency-only patch gate.

v2.2.6 — Transfer-syntax negotiation list + backend/lossless reporting fixes

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 09 Jul 11:39

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 by dicom-retrieve/dicom-qr — the negotiation analogue of CompressionManager.supportedCodecs() (dicom-compress) and DICOMConverter.cliTokens (dicom-convert). Every token round-trips through TransferSyntax.parse().
  • The DICOMStudio CLI Workshop dicom-retrieve/dicom-qr pickers and the CLI --transfer-syntax help now derive from that shared list, adding the previously-missing JPEG-LS, JPEG XL, and JPEG 2000 Part 2 (plus explicit-vr-be, deflate, jpeg-extended, jpeg-lossless-sv1) syntaxes the old hand-maintained lists stopped short of.
  • CLI Workshop: the dicom-convert transfer-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 the both-capable general J2K/HTJ2K/JXL UIDs (.91/.93/.203/.112), isLossless and 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 reports Transfer Syntax: JPEG 2000 Lossless / Lossless: Yes consistently instead of contradicting itself.
  • --backend reporting 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), so auto/--backend metal previously reported "Metal (GPU)" for lossless/non-J2K encodes that actually ran on the CPU. An explicit --backend metal request that can't use the GPU is now downgraded with an explanatory note.
  • CodecBackend.accelerate.displayName reports "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)

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 09 Jul 08:56

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 (previously KeyError; 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

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 09 Jul 07:22

Fixes DICOMDIRReader dropping all but the last series when reading a DICOMDIR.

  • parseDirectoryRecordSequence rebuilt the PATIENT→STUDY→SERIES→IMAGE hierarchy from the flat record sequence, but (because DirectoryRecord is a value type) the .study/.series cases 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

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 09 Jul 07:22

Fixes DICOM Waveform (ECG / hemodynamic / audio) decoding so standards-compliant waveforms parse.

  • Tag groups corrected 0x54000x003A (PS3.6): all 25 acquisition/channel-definition attributes plus 9 Waveform Presentation attributes (e.g. Number of Waveform Channels 003A,0005, Sampling Frequency 003A,001A, Channel Position 003A,0245 VR FL). The genuinely group-5400 attributes (Waveform Sequence, Bits Allocated, Sample Interpretation, Waveform Data) are unchanged.
  • Number of Waveform Samples (003A,0010, VR UL): WaveformParser now reads it as a 32-bit UL (previously uint16, which threw "Missing Number of Waveform Samples" on real ECGs), and WaveformBuilder writes a proper binary UL instead of an ASCII string.
  • Added WaveformParseRegressionTests (full build→parse round-trip over group 003A).

Before this, WaveformParser rejected every conformant waveform.

v2.2.2 — Explicit VR Big Endian read fix

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 08 Jul 06:48

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

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 06 Jul 16:27

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 uses Task.result with 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 var locals converted to let; redundant try/try? removed from non-throwing DataSet accessor calls.
  • DICOMWeb: redundant await removed from synchronous same-isolation calls; unused guard let url binding 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 documented nonisolated(unsafe) + happens-before pattern; cine timer callback wrapped in MainActor.assumeIsolated; slider Binding setters 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

Choose a tag to compare

@SureshKViswanathan SureshKViswanathan released this 04 Jul 12:49

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-exif with --split-pages, dicom-dcmdir update, dicom-query --referring-physician.
  • Removed declared no-ops: dicom-json --format standard|dicomweb and --stream.

New Codec Support

  • JPEG XL lossy encode (…4.112) in dicom-compress via JXLSwift VarDCT.
  • JPEG XL JPEG recompression (…4.111) in dicom-convert — byte-identical JPEG reconstruction.
  • J2KSwift v3.2.0 integration; JLISwift/JXLSwift promoted to full registry codecs.

Fixes

  • DICOMWriter no 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.
  • PixelEditor now decodes encapsulated sources before editing (handles multi-frame).
  • dicom-pixedit --invert no longer renders solid white (VOI window now inverted correctly).

Testing

  • New DICOMRoundTripTest oracle-based regression suite (393 tests) covering all local dicom-* 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.