1 unstable release
new 0.5.0 | Jan 2, 2025 |
---|
#340 in Encoding
180 downloads per month
Used in 2 crates
3MB
64K
SLoC
medicom
This crate is the core DICOM reading/writing library. This crate is focused only on basic reading/writing of DICOM datasets and has few dependencies. It does not depend on the DICOM standard dictionary, instead it is able to parse through dicom based only on knowing a minimal set of DICOM constants.
Standard DICOM Dictionary
The standard DICOM dictionary is an optional feature of this crate. The reading and writing functionality is not dependent on the standard dictionary, however for parsing element values the dictionary can be used for Implicit VR encodings.
The standard dictionary can be included using the feature stddicom
.
The build script in the build
folder generates the standard DICOM dictionary.
Files generated by the build script:
src/dict/lookup.rs
src/dict/tags.rs
src/dict/transfer_syntaxes.rs
src/dict/uids.rs
Parsing Examples
Simple use of parsing a DICOM file and printing some element values to stdout.
let mut parser: Parser<'_, File> = ParserBuilder::default()
// Stops parsing once the PixelData element is seen.
.stop(TagStop::BeforeTagValue(&PixelData))
// The dictionary is used during parsing for Implicit VR transfer syntaxes,
// and associates the resolved VR to the resulting elements for parsing the
// element values.
.build(file, &STANDARD_DICOM_DICTIONARY);
// The parser is an iterator over elements.
for element_res in parser {
let element: DicomElement = element_res?;
let value: RawValue = element.parse_value()?;
match value {
RawValue::Strings(strings) => println!("{:?}", strings[0]),
RawValue::UShorts(ushorts) => println!("{:?}", ushorts[0]),
_ => {},
}
// Simplify handling of elements with single values. RawValue::string()
// returns Option<String> if the value could parse to a string.
let _string = value.string().unwrap();
// Parse using a VR separate from what was specified in the DICOM dataset.
let _value: Option<String> = element.parse_value_as(<)?.string();
}
Load the DICOM file into a DicomObject
, a hierarchical structure.
let mut parser: Parser<'_, File> = ParserBuilder::default()
.stop(TagStop::BeforeTagValue(&PixelData))
.build(file, &STANDARD_DICOM_DICTIONARY);
// Parsing into object returns Result<Option<DicomObject>>, returning Ok(None)
// if the file isn't DICOM.
let dcmroot: DicomRoot = DicomRoot::parse(parser)
.unwrap().unwrap();
// Builds a path for
// ReferencedFrameOfReferenceSequence[1]
// .RTReferencedStudySequence[1]
// .RTReferencedSeriesSequence[1]
// .ContourImageSequence[11]
// .ReferencedSOPInstanceUID
let tagpath = TagPath::from(vec![
TagNode::from(&ReferencedFrameofReferenceSequence),
TagNode::from(&RTReferencedStudySequence),
TagNode::from(&RTReferencedSeriesSequence),
TagNode::from((&ContourImageSequence, 11)),
TagNode::from(&ReferencedSOPInstanceUID),
]);
// If all desired indexes are `1` then this can be simplified:
let _ = TagPath::from(vec![&SourceImageSequence, &ReferencedSOPInstanceUID]);
// Tag paths can be parsed/represented as strings, including item indexing:
let _parsed: Option<TagPath> = TagPath::parse(
"SourceImageSequence[2].ReferencedSOPInstanceUID",
Some(&STANDARD_DICOM_DICTIONARY),
)
// Get the value for the element at the tag path.
let ref_sopuid: Option<RawValue> = dcmroot.get_value_by_tagpath(tagpath);
if let Some(RawValue::Uid(uid)) = ref_sopuid {
println!("Referenced SOP Instance UID: {}", uid);
}
Integration Tests
Test fixtures are files used by some tests. Due to the large size of these test datasets they are not included in the repository. To set up these test fixtures:
- Download the fixtures (700mb .7z).
- Extract the downloaded archive into this directory.
- The resulting extraction should create a
medicom/tests/fixtures
folder with subfolders containing the test datasets.
These fixtures are a suite of dicom files gathered from several open sources:
- gdcm, notably
- David Clunie, at the bottom of the page under
Images
Dependencies
~3.5–5MB
~151K SLoC