Skip to content

Commit

Permalink
Add suppport for encapsulated uncompressed
Browse files Browse the repository at this point in the history
  • Loading branch information
Enet4 committed Oct 11, 2023
1 parent b714dcc commit 352cf6b
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 4 deletions.
5 changes: 3 additions & 2 deletions encoding/src/transfer_syntax/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,10 @@ macro_rules! submit_ele_transfer_syntax {
pub enum Codec<D, R, W> {
/// No codec is required for this transfer syntax.
///
/// Pixel data, if any, should be in its native, unencapsulated form.
/// Pixel data, if any, should be in its _native_, unencapsulated format.
None,
/// Pixel data for this transfer syntax is encapsulated.
/// Pixel data for this transfer syntax is encapsulated
/// and likely subjected to a specific encoding process.
/// The first part of the tuple struct contains the pixel data decoder,
/// whereas the second item is for the pixel data encoder.
///
Expand Down
2 changes: 2 additions & 0 deletions transfer-syntax-registry/src/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub mod jpeg;
#[cfg(feature = "rle")]
pub mod rle_lossless;

pub mod uncompressed;

/// **Note:** This module is a stub.
/// Enable the `jpeg` feature to use this module.
#[cfg(not(feature = "jpeg"))]
Expand Down
109 changes: 109 additions & 0 deletions transfer-syntax-registry/src/adapters/uncompressed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//! Support for encapsulated uncompressed via pixel data adapter.
use dicom_core::{
ops::{AttributeAction, AttributeOp},
PrimitiveValue, Tag,
};
use dicom_encoding::{
adapters::{
decode_error, encode_error, DecodeResult, EncodeOptions, EncodeResult, PixelDataObject,
PixelDataReader, PixelDataWriter,
},
snafu::OptionExt,
};

/// Adapter for [Encapsulated Uncompressed Explicit VR Little Endian][1]
/// [1]: https://dicom.nema.org/medical/dicom/2023c/output/chtml/part05/sect_A.4.11.html
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct UncompressedAdapter;

impl PixelDataReader for UncompressedAdapter {
fn decode(&self, src: &dyn PixelDataObject, dst: &mut Vec<u8>) -> DecodeResult<()> {
// just flatten all fragments into the output vector
let pixeldata = src
.raw_pixel_data()
.context(decode_error::MissingAttributeSnafu { name: "Pixel Data" })?;

for fragment in pixeldata.fragments {
dst.extend_from_slice(&fragment);
}

Ok(())
}

fn decode_frame(
&self,
src: &dyn PixelDataObject,
frame: u32,
dst: &mut Vec<u8>,
) -> DecodeResult<()> {
// just copy the specific fragment into the output vector
let pixeldata = src
.raw_pixel_data()
.context(decode_error::MissingAttributeSnafu { name: "Pixel Data" })?;

let fragment = pixeldata
.fragments
.get(frame as usize)
.context(decode_error::FrameRangeOutOfBoundsSnafu)?;

dst.extend_from_slice(&fragment);

Check warning on line 50 in transfer-syntax-registry/src/adapters/uncompressed.rs

View workflow job for this annotation

GitHub Actions / Clippy

this expression creates a reference which is immediately dereferenced by the compiler

Ok(())
}
}

impl PixelDataWriter for UncompressedAdapter {
fn encode_frame(
&self,
src: &dyn PixelDataObject,
frame: u32,
_options: EncodeOptions,
dst: &mut Vec<u8>,
) -> EncodeResult<Vec<AttributeOp>> {
let cols = src
.cols()
.context(encode_error::MissingAttributeSnafu { name: "Columns" })?;
let rows = src
.rows()
.context(encode_error::MissingAttributeSnafu { name: "Rows" })?;
let samples_per_pixel =
src.samples_per_pixel()
.context(encode_error::MissingAttributeSnafu {
name: "SamplesPerPixel",
})?;
let bits_allocated = src
.bits_allocated()
.context(encode_error::MissingAttributeSnafu {
name: "BitsAllocated",
})?;

let bytes_per_sample = (bits_allocated / 8) as usize;
let frame_size =
cols as usize * rows as usize * samples_per_pixel as usize * bytes_per_sample;

// identify frame data using the frame index
let pixeldata_uncompressed = &src
.raw_pixel_data()
.context(encode_error::MissingAttributeSnafu { name: "Pixel Data" })?
.fragments[0];

let len_before = pixeldata_uncompressed.len();

let frame_data = pixeldata_uncompressed
.get(frame_size * frame as usize..frame_size * (frame as usize + 1))
.whatever_context("Frame index out of bounds")?;

// Copy the the data to the output
dst.extend_from_slice(&frame_data);

Check warning on line 98 in transfer-syntax-registry/src/adapters/uncompressed.rs

View workflow job for this annotation

GitHub Actions / Clippy

this expression creates a reference which is immediately dereferenced by the compiler

// provide attribute changes
Ok(vec![
// Encapsulated Pixel Data Value Total Length
AttributeOp::new(
Tag(0x7FE0, 0x0003),
AttributeAction::Set(PrimitiveValue::from(len_before as u64)),
),
])
}
}
13 changes: 12 additions & 1 deletion transfer-syntax-registry/src/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//! hence expanding support for those transfer syntaxes
//! to the registry.
use crate::create_ts_stub;
use crate::{adapters::uncompressed::UncompressedAdapter, create_ts_stub};
use byteordered::Endianness;
use dicom_encoding::transfer_syntax::{AdapterFreeTransferSyntax as Ts, Codec};

Expand Down Expand Up @@ -62,6 +62,17 @@ pub const EXPLICIT_VR_BIG_ENDIAN: Ts = Ts::new(
Codec::None,
);

/// **Fully implemented:** Encapsulated Uncompressed Explicit VR Little Endian
pub const ENCAPSULATED_UNCOMPRESSED_EXPLICIT_VR_LITTLE_ENDIAN: TransferSyntax<

Check failure on line 66 in transfer-syntax-registry/src/entries.rs

View workflow job for this annotation

GitHub Actions / Test (default) (stable)

cannot find type `TransferSyntax` in this scope

Check failure on line 66 in transfer-syntax-registry/src/entries.rs

View workflow job for this annotation

GitHub Actions / Test (default) (beta)

cannot find type `TransferSyntax` in this scope
NeverAdapter,

Check failure on line 67 in transfer-syntax-registry/src/entries.rs

View workflow job for this annotation

GitHub Actions / Test (default) (stable)

cannot find type `NeverAdapter` in this scope

Check failure on line 67 in transfer-syntax-registry/src/entries.rs

View workflow job for this annotation

GitHub Actions / Test (default) (beta)

cannot find type `NeverAdapter` in this scope
UncompressedAdapter,
UncompressedAdapter,
> = TransferSyntax::new_ele(

Check failure on line 70 in transfer-syntax-registry/src/entries.rs

View workflow job for this annotation

GitHub Actions / Test (default) (stable)

failed to resolve: use of undeclared type `TransferSyntax`

Check failure on line 70 in transfer-syntax-registry/src/entries.rs

View workflow job for this annotation

GitHub Actions / Test (default) (beta)

failed to resolve: use of undeclared type `TransferSyntax`
"1.2.840.10008.1.2.1.98",
"Encapsulated Uncompressed Explicit VR Little Endian",
Codec::EncapsulatedPixelData(Some(UncompressedAdapter), Some(UncompressedAdapter)),
);

// -- transfer syntaxes with pixel data adapters, fully supported --

/// **Implemented:** RLE Lossless
Expand Down
4 changes: 3 additions & 1 deletion transfer-syntax-registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,13 @@ lazy_static! {
};

use self::entries::*;
let built_in_ts: [TransferSyntax; 36] = [
let built_in_ts: [TransferSyntax; 37] = [
IMPLICIT_VR_LITTLE_ENDIAN.erased(),
EXPLICIT_VR_LITTLE_ENDIAN.erased(),
EXPLICIT_VR_BIG_ENDIAN.erased(),

ENCAPSULATED_UNCOMPRESSED_EXPLICIT_VR_LITTLE_ENDIAN.erased(),

DEFLATED_EXPLICIT_VR_LITTLE_ENDIAN.erased(),
JPIP_REFERENCED_DEFLATE.erased(),
JPEG_BASELINE.erased(),
Expand Down

0 comments on commit 352cf6b

Please sign in to comment.