v1.3.0
Upgrade from 1.2.0 without delay. The
ItemTagconstant in 1.2.0 was wrong, so the
nested sequence parsing introduced in that release failed on every real DICOM file
containing a sequence. 1.2.0 should be skipped.
Added
- C-GET sub-operations — a C-GET previously invoked the handler and returned a status
but transferred nothing. The SCP now sends matching instances back as C-STORE
sub-operations over the same association (PS3.4 Annex C.4.3), each on the presentation
context negotiated for its own SOP Class, with pending responses carrying the
remaining/completed/failed/warning counts. The SCU dispatches incoming C-STORE-RQ
messages toSCUConfig.OnCStoreand acknowledges each one.CGetResponse.Instancessupplies the instances to transferSCUConfig.OnCStorereceives them on the requesting sideqrscpretains received datasets and serves them, making it a working
in-memory query/retrieve server
- C-MOVE sub-operations — the SCP now opens an association to the move destination and
sends the matching instances there as C-STORE sub-operations (PS3.4 Annex C.4.2),
reporting progress back to the requestor. This completes query/retrieve: C-FIND,
C-GET, and C-MOVE all work as both SCU and SCP.CMoveResponse.Instancessupplies the instances to moveQueryRetrieveHandler.OnMoveInstancesreturns them from a handler; the older
OnMove, which could not transfer anything, is deprecated but still honoredSCPConfig.MoveDestinationsandSCPConfig.ResolveMoveDestinationresolve a
destination AE title to an address; an unresolvable title is answered with
StatusMoveDestUnknownqrscp -move-dest AETITLE=host:portconfigures destinations from the CLI
- Sequence writing in
filewriter—DataElement.Itemsholds nested
SequenceItemvalues, closing the read → write → read round trip. Items are written
with explicit lengths and implicit-style item headers as PS3.5 Section 7.5 requires. - Raw DICOM data sets without a file meta header —
ReadDICOMFilerequired the
128-byte preamble and DICM prefix, so a raw stream, which is what modalities produce and
what travels on the network, could not be read despite the README listing it as
supported. The reader now detects which form the stream is and falls back to implicit VR
little endian per PS3.5 Section 10.1, recording the outcome inDICOMFile.HasPreamble. DICOMFile.MetaElements— the group-0002 elements as they appeared in the file,
for callers that need to display the header verbatim.- Interoperability testing against pynetdicom and dcmtk —
scripts/interop-test.sh
plus a CI job. Exercises C-ECHO and C-STORE in both directions and C-GET
sub-operations, using pydicom'sCT_small.dcmas the fixture and pydicom as the
verifier rather than this library's own reader. Fails when no third-party peer is
available, so a broken install cannot pass by skipping.
Fixed
- The CLI parsed files with a second, broken parser —
show,info,convert, and
codifyused a parser incli/helpers.goseparate fromfilereader, which received
none of this cycle's fixes. It read the file in 64 KiB chunks and parsed each
independently, so an element straddling a boundary desynchronized the stream: on a
268 KB file where pydicom reports 258 elements it printed roughly 38 and ended with an
invented element whose VR was two arbitrary bytes. It also never descended into
sequences, and classified SQ and UT as short-form VRs. The CLI now usesfilereader,
reports 269 elements for the same file, and indents sequence contents by nesting depth. ItemTagwas0xFFFE0000, not0xFFFEE000(critical) — the constant was missing
a digit and decoded as (FFFE,0000). Sequence parsing, added in 1.2.0, therefore failed
on every real DICOM file containing a sequence, rejecting the correct item tag as
unexpected. The unit tests passed because they built their fixtures with the same wrong
constant.tag.FromBytesandtag.ToBytestransposed group and element — both treated the
4-byte tag as a single uint32 rather than two consecutive 16-bit values. Undetected
because the only test case was PatientName (0010,0010), where group equals element, and
because the two functions were each other's inverse.- Sequences were lost over the network —
EncodeDatasetskipped sequence elements,
andstorescubuilt its dataset fromelem.Value, which is nil for a sequence. An
instance sent to a peer arrived with its sequence present but empty. - An empty data set sent no PDU at all —
SendPDatalooped over the payload, so a
zero-length data set produced nothing after the command had already announced one,
leaving the peer blocked until the DIMSE timeout. Reachable with any keyless C-FIND or
C-GET identifier. QueryRetrieveHandler.OnGetresults are now transferred rather than only counted.
Install
go install github.com/amrshadid/go-dicom@v1.3.0Or download a binary below and place it on your PATH:
| Platform | File |
|---|---|
| Linux x86-64 | dicom-linux-amd64 |
| Linux ARM64 | dicom-linux-arm64 |
| macOS Intel | dicom-macos-amd64 |
| macOS Apple Silicon | dicom-macos-arm64 |
| Windows x86-64 | dicom-windows-amd64.exe |
Checksums are in SHA256SUMS:
sha256sum -c SHA256SUMS