From cb72c736fbbbd9e20abcd19cfcd45bbc6b5ab044 Mon Sep 17 00:00:00 2001 From: Nathan Richman Date: Tue, 21 Nov 2023 10:24:57 -0600 Subject: [PATCH 01/10] [dicom-dump] Add json output format --- Cargo.lock | 25 ++++++++++++++++++++++++- dump/Cargo.toml | 3 +++ dump/src/lib.rs | 38 ++++++++++++++++++++++---------------- dump/src/main.rs | 31 +++++++++++++++++++++++++------ 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de36e3e3e..981446bd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,17 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -394,13 +405,16 @@ dependencies = [ name = "dicom-dump" version = "0.6.2" dependencies = [ + "atty", "clap", "dicom-core", "dicom-dictionary-std", "dicom-encoding", + "dicom-json", "dicom-object", "dicom-transfer-syntax-registry", "owo-colors", + "serde_json", "snafu", "term_size", ] @@ -978,6 +992,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.3" @@ -1061,7 +1084,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.3", "rustix", "windows-sys 0.48.0", ] diff --git a/dump/Cargo.toml b/dump/Cargo.toml index d165e1b3d..b9a3f4e8e 100644 --- a/dump/Cargo.toml +++ b/dump/Cargo.toml @@ -34,3 +34,6 @@ dicom-object = { path = "../object/", version = "0.6.3" } dicom-transfer-syntax-registry = { path = "../transfer-syntax-registry/", version = "0.6.2", default-features = false } dicom-dictionary-std = { path = "../dictionary-std/", version = "0.6.1" } owo-colors = { version = "4.0.0-rc.1", features = ["supports-colors"] } +dicom-json = { version = "0.1.0", path = "../json" } +serde_json = "1.0.108" +atty = "0.2.14" diff --git a/dump/src/lib.rs b/dump/src/lib.rs index 724d6dbcf..121f7b096 100644 --- a/dump/src/lib.rs +++ b/dump/src/lib.rs @@ -32,6 +32,7 @@ //! options.width(100).dump_file(&obj)?; //! # Result::<(), Box>::Ok(()) //! ``` +use clap::ValueEnum; #[cfg(feature = "sop-class")] use dicom_core::dictionary::UidDictionary; use dicom_core::dictionary::{DataDictionary, DataDictionaryEntry}; @@ -41,6 +42,7 @@ use dicom_core::VR; #[cfg(feature = "sop-class")] use dicom_dictionary_std::StandardSopClassDictionary; use dicom_encoding::transfer_syntax::TransferSyntaxIndex; +use dicom_json::DicomJson; use dicom_object::mem::{InMemDicomObject, InMemElement}; use dicom_object::{FileDicomObject, FileMetaTable, StandardDataDictionary}; use dicom_transfer_syntax_registry::TransferSyntaxRegistry; @@ -50,12 +52,10 @@ use std::fmt::{self, Display, Formatter}; use std::io::{stdout, Result as IoResult, Write}; use std::str::FromStr; -/// An enum of all supported output formats for dumping DICOM data. -#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)] -#[non_exhaustive] +#[derive(ValueEnum, Clone, Debug, PartialEq, Default)] pub enum DumpFormat { - /// The main DICOM dump format adopted by the project. - /// + /// Text dump of DICOM file + /// /// It is primarily designed to be human readable, /// although its output can be used to recover the original object /// in its uncut form (no limit width). @@ -64,15 +64,12 @@ pub enum DumpFormat { /// /// Note that this format is not stabilized, /// and may change with subsequent versions of the crate. - Main, + #[default] + Text, + /// Dicom part 18 chapter F json format provided by the json crate + Json, } -/// The [main output format](DumpFormat::Main) is used by default. -impl Default for DumpFormat { - fn default() -> Self { - DumpFormat::Main - } -} /// Options and flags to configure how to dump a DICOM file or object. /// @@ -227,14 +224,23 @@ impl DumpOptions { } else { (true, true) }; + match self.format { + DumpFormat::Text => { + meta_dump(&mut to, meta, if no_limit { u32::MAX } else { width })?; - meta_dump(&mut to, meta, if no_limit { u32::MAX } else { width })?; + writeln!(to, "{:-<58}", "")?; - writeln!(to, "{:-<58}", "")?; + dump(&mut to, obj, width, 0, no_text_limit, no_limit)?; - dump(&mut to, obj, width, 0, no_text_limit, no_limit)?; + Ok(()) + }, + DumpFormat::Json => { + let json_obj = DicomJson::from(obj); + println!("{}", serde_json::to_string_pretty(&json_obj)?); + Ok(()) + } + } - Ok(()) } /// Dump the contents of a DICOM object to standard output. diff --git a/dump/src/main.rs b/dump/src/main.rs index aa374fccb..aeba91fff 100644 --- a/dump/src/main.rs +++ b/dump/src/main.rs @@ -1,7 +1,7 @@ //! A CLI tool for inspecting the contents of a DICOM file //! by printing it in a human readable format. use clap::Parser; -use dicom_dump::{ColorMode, DumpOptions}; +use dicom_dump::{ColorMode, DumpOptions, DumpFormat}; use dicom_object::open_file; use snafu::{Report, Whatever}; use std::io::ErrorKind; @@ -12,6 +12,7 @@ const ERROR_READ: i32 = -2; /// Exit code for when an error emerged while dumping the file. const ERROR_PRINT: i32 = -3; + /// Dump the contents of DICOM files #[derive(Debug, Parser)] #[command(version)] @@ -20,7 +21,10 @@ struct App { #[clap(required = true)] files: Vec, /// Print text values to the end - /// (limited to `width` by default) + /// (limited to `width` by default). + /// + /// Does not apply if output is not a tty + /// or if output type is json #[clap(long = "no-text-limit")] no_text_limit: bool, /// Print all values to the end @@ -28,7 +32,10 @@ struct App { #[clap(long = "no-limit")] no_limit: bool, /// The width of the display - /// (default is to check automatically) + /// (default is to check automatically). + /// + /// Does not apply if output is not a tty + /// or if output type is json #[clap(short = 'w', long = "width")] width: Option, /// The color mode @@ -37,6 +44,14 @@ struct App { /// Fail if any errors are encountered #[clap(long = "fail-first")] fail_first: bool, + /// Output format + #[arg(value_enum)] + #[clap(short = 'o', long = "output", default_value = "text")] + output_type: DumpFormat +} + +fn is_terminal() -> bool { + atty::is(atty::Stream::Stdout) } fn main() { @@ -54,6 +69,7 @@ fn run() -> Result<(), Whatever> { width, color, fail_first, + output_type, } = App::parse(); let width = width @@ -63,14 +79,17 @@ fn run() -> Result<(), Whatever> { let mut options = DumpOptions::new(); options .no_text_limit(no_text_limit) - .no_limit(no_limit) + // No limit when output is not a terminal + .no_limit(if !is_terminal() { true } else {no_limit}) .width(width) - .color_mode(color); + .color_mode(color) + .format(output_type); let fail_first = filenames.len() == 1 || fail_first; let mut errors: i32 = 0; for filename in &filenames { - println!("{}: ", filename.display()); + // Write filename to stderr to make piping easier, i.e. dicom-dump -o json file.dcm | jq + eprintln!("{}: ", filename.display()); match open_file(filename) { Err(e) => { eprintln!("{}", Report::from_error(e)); From a61b2dced066d2fe4d5de5cd3128d2f9d2213de5 Mon Sep 17 00:00:00 2001 From: Nathan Richman Date: Tue, 21 Nov 2023 14:55:31 -0600 Subject: [PATCH 02/10] MAIN: Review suggestions * Change option from output to format * Pretty print to writer instead of to string --- dump/src/lib.rs | 2 +- dump/src/main.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dump/src/lib.rs b/dump/src/lib.rs index 121f7b096..843bfe801 100644 --- a/dump/src/lib.rs +++ b/dump/src/lib.rs @@ -236,7 +236,7 @@ impl DumpOptions { }, DumpFormat::Json => { let json_obj = DicomJson::from(obj); - println!("{}", serde_json::to_string_pretty(&json_obj)?); + serde_json::to_writer_pretty(stdout(), &json_obj)?; Ok(()) } } diff --git a/dump/src/main.rs b/dump/src/main.rs index aeba91fff..841d32900 100644 --- a/dump/src/main.rs +++ b/dump/src/main.rs @@ -46,8 +46,8 @@ struct App { fail_first: bool, /// Output format #[arg(value_enum)] - #[clap(short = 'o', long = "output", default_value = "text")] - output_type: DumpFormat + #[clap(short = 'f', long = "format", default_value = "text")] + format: DumpFormat } fn is_terminal() -> bool { @@ -69,7 +69,7 @@ fn run() -> Result<(), Whatever> { width, color, fail_first, - output_type, + format, } = App::parse(); let width = width @@ -83,7 +83,7 @@ fn run() -> Result<(), Whatever> { .no_limit(if !is_terminal() { true } else {no_limit}) .width(width) .color_mode(color) - .format(output_type); + .format(format); let fail_first = filenames.len() == 1 || fail_first; let mut errors: i32 = 0; From 9da65af79cb0fb9711346d6f994797bfc25a70c0 Mon Sep 17 00:00:00 2001 From: Eduardo Pinho Date: Sat, 24 Feb 2024 11:04:58 +0000 Subject: [PATCH 03/10] [dump] Improve doc comment in DumpFormat::Json --- dump/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dump/src/lib.rs b/dump/src/lib.rs index 843bfe801..a4ea03a26 100644 --- a/dump/src/lib.rs +++ b/dump/src/lib.rs @@ -66,7 +66,8 @@ pub enum DumpFormat { /// and may change with subsequent versions of the crate. #[default] Text, - /// Dicom part 18 chapter F json format provided by the json crate + /// DICOM part 18 chapter F JSON format, + /// provided via [`dicom_json`] Json, } From 1eb4cf83a8ea4da93d71caa384f12d73ef7e21f8 Mon Sep 17 00:00:00 2001 From: Eduardo Pinho Date: Sat, 24 Feb 2024 11:13:47 +0000 Subject: [PATCH 04/10] [dump] Make dump_object work for Json output + add dump_json test --- dump/src/lib.rs | 66 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/dump/src/lib.rs b/dump/src/lib.rs index a4ea03a26..dd4b50c63 100644 --- a/dump/src/lib.rs +++ b/dump/src/lib.rs @@ -271,24 +271,33 @@ impl DumpOptions { where D: DataDictionary, { - match (self.color, to_stdout) { - (ColorMode::Never, _) => colored::control::set_override(false), - (ColorMode::Always, _) => colored::control::set_override(true), - (ColorMode::Auto, false) => colored::control::set_override(false), - (ColorMode::Auto, true) => colored::control::unset_override(), - } + match self.format { + DumpFormat::Text => { + match (self.color, to_stdout) { + (ColorMode::Never, _) => colored::control::set_override(false), + (ColorMode::Always, _) => colored::control::set_override(true), + (ColorMode::Auto, false) => colored::control::set_override(false), + (ColorMode::Auto, true) => colored::control::unset_override(), + } - let width = determine_width(self.width); + let width = determine_width(self.width); - let (no_text_limit, no_limit) = if to_stdout { - (self.no_text_limit, self.no_limit) - } else { - (true, true) - }; + let (no_text_limit, no_limit) = if to_stdout { + (self.no_text_limit, self.no_limit) + } else { + (true, true) + }; - dump(&mut to, obj, width, 0, no_text_limit, no_limit)?; + dump(&mut to, obj, width, 0, no_text_limit, no_limit)?; - Ok(()) + Ok(()) + } + DumpFormat::Json => { + let json_obj = DicomJson::from(obj); + serde_json::to_writer_pretty(to, &json_obj)?; + Ok(()) + } + } } } @@ -1103,4 +1112,33 @@ mod tests { assert_eq!(value, expected.3); } } + + #[test] + fn dump_json() { + // create object + let obj = InMemDicomObject::from_element_iter(vec![DataElement::new( + tags::SOP_INSTANCE_UID, + VR::UI, + PrimitiveValue::from("1.2.888.123"), + )]); + + let mut out = Vec::new(); + DumpOptions::new() + .color_mode(ColorMode::Never) + .format(crate::DumpFormat::Json) + .dump_object_to(&mut out, &obj) + .unwrap(); + + let json = std::str::from_utf8(&out).expect("output is not valid UTF-8"); + assert_eq!( + json, + r#"{ + "00080018": { + "vr": "UI", + "Value": [ + "1.2.888.123" + ] + } +}"#); + } } From 7f0704a45f69ed37bd3947952e3a8ded793e7da1 Mon Sep 17 00:00:00 2001 From: Eduardo Pinho Date: Sat, 24 Feb 2024 11:21:39 +0000 Subject: [PATCH 05/10] [dump] derive ValueEnum conditionally on "cli" cargo feature --- dump/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dump/src/lib.rs b/dump/src/lib.rs index dd4b50c63..6f864f3c2 100644 --- a/dump/src/lib.rs +++ b/dump/src/lib.rs @@ -32,6 +32,7 @@ //! options.width(100).dump_file(&obj)?; //! # Result::<(), Box>::Ok(()) //! ``` +#[cfg(feature = "cli")] use clap::ValueEnum; #[cfg(feature = "sop-class")] use dicom_core::dictionary::UidDictionary; @@ -52,7 +53,8 @@ use std::fmt::{self, Display, Formatter}; use std::io::{stdout, Result as IoResult, Write}; use std::str::FromStr; -#[derive(ValueEnum, Clone, Debug, PartialEq, Default)] +#[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "cli", derive(ValueEnum))] pub enum DumpFormat { /// Text dump of DICOM file /// From cacc762300c5b207f158d95e2803452601e73d4e Mon Sep 17 00:00:00 2001 From: Eduardo Pinho Date: Fri, 1 Mar 2024 08:13:07 +0000 Subject: [PATCH 06/10] [echoscu] Tweak msg_id check to avoid type inference bug --- echoscu/src/main.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/echoscu/src/main.rs b/echoscu/src/main.rs index 16856eca8..40ac7a9c7 100644 --- a/echoscu/src/main.rs +++ b/echoscu/src/main.rs @@ -158,15 +158,13 @@ fn run() -> Result<(), Whatever> { } // msg ID response, should be equal to sent msg ID - let msg_id_elem = obj + let got_msg_id: u16 = obj .element(tags::MESSAGE_ID_BEING_RESPONDED_TO) - .whatever_context("Could not retrieve Message ID from response")?; + .whatever_context("Could not retrieve Message ID from response")? + .to_int() + .whatever_context("Message ID is not a valid integer")?; - if message_id - != msg_id_elem - .to_int() - .whatever_context("Message ID is not a valid integer")? - { + if message_id != got_msg_id { whatever!("Message ID mismatch"); } } From eb10e305635a40b672a4c5b556a1fb809f42c2d6 Mon Sep 17 00:00:00 2001 From: Eduardo Pinho Date: Fri, 1 Mar 2024 08:28:42 +0000 Subject: [PATCH 07/10] [dump] Drop atty in favor of std::io::IsTerminal --- Cargo.lock | 23 +---------------------- dump/Cargo.toml | 1 - dump/src/main.rs | 4 ++-- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 981446bd0..8c27565de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,17 +80,6 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -405,7 +394,6 @@ dependencies = [ name = "dicom-dump" version = "0.6.2" dependencies = [ - "atty", "clap", "dicom-core", "dicom-dictionary-std", @@ -992,15 +980,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.3" @@ -1084,7 +1063,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi", "rustix", "windows-sys 0.48.0", ] diff --git a/dump/Cargo.toml b/dump/Cargo.toml index b9a3f4e8e..56a063100 100644 --- a/dump/Cargo.toml +++ b/dump/Cargo.toml @@ -36,4 +36,3 @@ dicom-dictionary-std = { path = "../dictionary-std/", version = "0.6.1" } owo-colors = { version = "4.0.0-rc.1", features = ["supports-colors"] } dicom-json = { version = "0.1.0", path = "../json" } serde_json = "1.0.108" -atty = "0.2.14" diff --git a/dump/src/main.rs b/dump/src/main.rs index 841d32900..bafb5aff2 100644 --- a/dump/src/main.rs +++ b/dump/src/main.rs @@ -4,7 +4,7 @@ use clap::Parser; use dicom_dump::{ColorMode, DumpOptions, DumpFormat}; use dicom_object::open_file; use snafu::{Report, Whatever}; -use std::io::ErrorKind; +use std::io::{ErrorKind, IsTerminal}; use std::path::PathBuf; /// Exit code for when an error emerged while reading the DICOM file. @@ -51,7 +51,7 @@ struct App { } fn is_terminal() -> bool { - atty::is(atty::Stream::Stdout) + std::io::stdout().is_terminal() } fn main() { From fdedb0fccd04d57ad1b737b239096093c4370cd3 Mon Sep 17 00:00:00 2001 From: Nate Richman Date: Mon, 5 Aug 2024 11:46:32 -0500 Subject: [PATCH 08/10] MAIN: Add serialization for encapsulated pixel data --- json/src/ser/mod.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/json/src/ser/mod.rs b/json/src/ser/mod.rs index f9a9fd1e4..bfb433fd1 100644 --- a/json/src/ser/mod.rs +++ b/json/src/ser/mod.rs @@ -3,7 +3,7 @@ use std::io::Write; use crate::DicomJson; -use dicom_core::{header::Header, DicomValue, PrimitiveValue, Tag, VR}; +use dicom_core::{header::Header, value::PixelFragmentSequence, DicomValue, PrimitiveValue, Tag, VR}; use dicom_dictionary_std::StandardDataDictionary; use dicom_object::{mem::InMemElement, DefaultDicomObject, InMemDicomObject}; use serde::{ser::SerializeMap, Serialize, Serializer}; @@ -216,8 +216,8 @@ impl Serialize for DicomJson<&'_ InMemElement> { DicomValue::Sequence(seq) => { serializer.serialize_entry("Value", &DicomJson(seq.items()))?; } - DicomValue::PixelSequence(_seq) => { - panic!("serialization of encapsulated pixel data is not supported") + DicomValue::PixelSequence(seq) => { + serializer.serialize_entry("Value", &DicomJson(seq))?; } DicomValue::Primitive(PrimitiveValue::Empty) => { // no-op @@ -281,6 +281,20 @@ impl Serialize for DicomJson> { } } +impl Serialize for DicomJson<&PixelFragmentSequence>> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let offset_table = self.inner().offset_table(); + let fragments = self.inner().fragments(); + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("Offset Table", offset_table)?; + map.serialize_entry("Pixel Fragments", fragments)?; + map.end() + } +} + impl From for DicomJson { fn from(value: Tag) -> Self { Self(value) From e59af6cf713832e53a5029f98c8f079911d77274 Mon Sep 17 00:00:00 2001 From: Nate Richman Date: Mon, 5 Aug 2024 11:57:17 -0500 Subject: [PATCH 09/10] MAIN: Remove unused import --- json/src/ser/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json/src/ser/mod.rs b/json/src/ser/mod.rs index 208a8b87b..03c11ec32 100644 --- a/json/src/ser/mod.rs +++ b/json/src/ser/mod.rs @@ -7,7 +7,7 @@ use dicom_core::{header::Header, value::PixelFragmentSequence, DicomValue, Primi use dicom_dictionary_std::StandardDataDictionary; use dicom_object::{mem::InMemElement, DefaultDicomObject, InMemDicomObject}; use serde::{ - ser::{Error as _, SerializeMap}, + ser::SerializeMap, Serialize, Serializer, }; From 69c49a3387bddb4a225d86b1651916971cf46762 Mon Sep 17 00:00:00 2001 From: Nate Richman Date: Wed, 7 Aug 2024 10:56:04 -0500 Subject: [PATCH 10/10] MAIN: Ignore encapsulated pixel data in json output --- dump/src/main.rs | 14 ++++++++++++-- json/src/ser/mod.rs | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/dump/src/main.rs b/dump/src/main.rs index cded31be7..ea860a19a 100644 --- a/dump/src/main.rs +++ b/dump/src/main.rs @@ -1,6 +1,7 @@ //! A CLI tool for inspecting the contents of a DICOM file //! by printing it in a human readable format. use clap::Parser; +use dicom_dictionary_std::tags; use dicom_dump::{ColorMode, DumpOptions, DumpFormat}; use dicom_object::open_file; use snafu::{Report, Whatever}; @@ -47,7 +48,7 @@ struct App { /// Output format #[arg(value_enum)] #[clap(short = 'f', long = "format", default_value = "text")] - format: DumpFormat + format: DumpFormat, } fn is_terminal() -> bool { @@ -98,7 +99,16 @@ fn run() -> Result<(), Whatever> { } errors += 1; } - Ok(obj) => { + Ok(mut obj) => { + if options.format == DumpFormat::Json { + // JSON output doesn't currently support encapsulated pixel data + if let Ok(elem) = obj.element(tags::PIXEL_DATA){ + if let dicom_core::value::Value::PixelSequence(_) = elem.value(){ + eprintln!("[WARN] Encapsulated pixel data not supported in JSON output, skipping"); + obj.remove_element(tags::PIXEL_DATA); + } + } + } if let Err(ref e) = options.dump_file(&obj) { if e.kind() == ErrorKind::BrokenPipe { // handle broken pipe separately with a no-op diff --git a/json/src/ser/mod.rs b/json/src/ser/mod.rs index 03c11ec32..525743f64 100644 --- a/json/src/ser/mod.rs +++ b/json/src/ser/mod.rs @@ -219,8 +219,8 @@ impl Serialize for DicomJson<&'_ InMemElement> { DicomValue::Sequence(seq) => { serializer.serialize_entry("Value", &DicomJson(seq.items()))?; } - DicomValue::PixelSequence(seq) => { - serializer.serialize_entry("Value", &DicomJson(seq))?; + DicomValue::PixelSequence(_seq) => { + //serializer.serialize_entry("Value", &DicomJson(seq))?; } DicomValue::Primitive(PrimitiveValue::Empty) => { // no-op