Skip to content

Commit 4675add

Browse files
committed
[object] turn all object into tokens
- make better FileMetaTableBuilder errors - tweak FileMetaTableBuilder to automatically fill in meta group length - add RootDicomObject::new_empty_with_meta - add means to turn FileMetaTable into data elements (then into tokens) - add RootDicomObject::write_to_file
1 parent a161fe5 commit 4675add

File tree

3 files changed

+305
-12
lines changed

3 files changed

+305
-12
lines changed

object/src/lib.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ pub use dicom_parser::error::{Error, Result};
4848
/// The default implementation of a root DICOM object.
4949
pub type DefaultDicomObject = RootDicomObject<mem::InMemDicomObject<StandardDataDictionary>>;
5050

51+
use std::fs::File;
52+
use std::io::{BufWriter, Write};
53+
use std::path::Path;
5154
use dicom_core::header::Header;
55+
use dicom_encoding::{transfer_syntax::TransferSyntaxIndex, text::SpecificCharacterSet};
56+
use dicom_parser::dataset::{DataSetWriter, IntoTokens};
57+
use dicom_transfer_syntax_registry::TransferSyntaxRegistry;
5258

5359
/// Trait type for a DICOM object.
5460
/// This is a high-level abstraction where an object is accessed and
@@ -96,6 +102,39 @@ impl<T> RootDicomObject<T> {
96102
}
97103
}
98104

105+
impl<T> RootDicomObject<T>
106+
where
107+
for<'a> &'a T: IntoTokens,
108+
{
109+
pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
110+
let file = File::create(path)?;
111+
let mut to = BufWriter::new(file);
112+
113+
// write preamble
114+
to.write(&[0_u8; 128][..])?;
115+
116+
// write magic sequence
117+
to.write(b"DICM")?;
118+
119+
// write meta group
120+
self.meta.write(&mut to)?;
121+
122+
// prepare encoder
123+
let registry = TransferSyntaxRegistry::default();
124+
let ts = registry
125+
.get(&self.meta.transfer_syntax)
126+
.ok_or_else(|| Error::UnsupportedTransferSyntax)?;
127+
let cs = SpecificCharacterSet::Default;
128+
let mut dset_writer = DataSetWriter::with_ts_cs(to, ts, cs)?;
129+
130+
// write object
131+
132+
dset_writer.write_sequence((&self.obj).into_tokens())?;
133+
134+
Ok(())
135+
}
136+
}
137+
99138
impl<T> ::std::ops::Deref for RootDicomObject<T> {
100139
type Target = T;
101140

@@ -157,4 +196,23 @@ where
157196
}
158197

159198
#[cfg(test)]
160-
mod tests {}
199+
mod tests {
200+
use crate::RootDicomObject;
201+
use crate::meta::FileMetaTableBuilder;
202+
203+
#[test]
204+
fn smoke_test() {
205+
let meta = FileMetaTableBuilder::new()
206+
.transfer_syntax(dicom_transfer_syntax_registry::entries::EXPLICIT_VR_LITTLE_ENDIAN.uid().to_owned() + "\0")
207+
.media_storage_sop_class_uid("1.2.840.10008.5.1.4.1.1.1\0".to_owned())
208+
.media_storage_sop_instance_uid("1.2.3.456\0".to_owned())
209+
.implementation_class_uid("1.2.345.6.7890.1.234".to_owned())
210+
.build()
211+
.unwrap();
212+
let obj = RootDicomObject::new_empty_with_meta(
213+
meta);
214+
215+
obj.write_to_file(".smoke-test.dcm").unwrap();
216+
let _ = std::fs::remove_file(".smoke-test.dcm");
217+
}
218+
}

object/src/mem.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,20 @@ where
224224
}
225225
}
226226

227+
impl RootDicomObject<InMemDicomObject<StandardDataDictionary>> {
228+
/// Create a new empty object, using the given file meta table.
229+
pub fn new_empty_with_meta(meta: FileMetaTable) -> Self {
230+
RootDicomObject {
231+
meta,
232+
obj: InMemDicomObject {
233+
entries: BTreeMap::new(),
234+
dict: StandardDataDictionary,
235+
len: Length::UNDEFINED,
236+
},
237+
}
238+
}
239+
}
240+
227241
impl<D> InMemDicomObject<D>
228242
where
229243
D: DataDictionary,

0 commit comments

Comments
 (0)