def test_invalid_byteorder_raises(self): """Test big endian `src` raises an exception.""" msg = ( r"Unsupported option for the 'pydicom' encoding plugin: " r"\"byteorder = '>'\"" ) with pytest.raises(ValueError, match=msg): _encode_frame(b'', byteorder='>')
def test_single_row_3sample(self): """Test encoding a single row of 3 samples/pixel data.""" # Rows 1, Columns 5, SamplesPerPixel 3 arr = np.asarray( [[[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]], dtype='uint8' ) assert (1, 5, 3) == arr.shape encoded = _encode_frame( arr.tobytes(), rows=1, columns=5, samples_per_pixel=3, bits_allocated=8 ) header = ( b'\x03\x00\x00\x00' b'\x40\x00\x00\x00' b'\x46\x00\x00\x00' b'\x4c\x00\x00\x00' ) header += b'\x00' * (64 - len(header)) assert header == encoded[:64] assert ( b'\x04\x00\x01\x02\x03\x04' b'\x04\x00\x01\x02\x03\x04' b'\x04\x00\x01\x02\x03\x04' ) == encoded[64:]
def rle_encode_frame(arr: "numpy.ndarray") -> bytes: """Return an :class:`numpy.ndarray` image frame as RLE encoded :class:`bytearray`. .. versionadded:: 1.3 .. deprecated:: 2.2 Use :meth:`~pydicom.dataset.Dataset.compress` instead Parameters ---------- arr : numpy.ndarray A 2D (if *Samples Per Pixel* = 1) or 3D (if *Samples Per Pixel* = 3) ndarray containing a single frame of the image to be RLE encoded. Returns ------- bytes An RLE encoded frame, including the RLE header, following the format specified by the DICOM Standard, Part 5, :dcm:`Annex G<part05/chapter_G.html>`. """ shape = arr.shape if len(shape) > 3: # Note: only raises if multi-sample pixel data with multiple frames raise ValueError( "Unable to encode multiple frames at once, please encode one " "frame at a time" ) # Check the expected number of segments nr_segments = arr.dtype.itemsize if len(shape) == 3: # Number of samples * bytes per sample nr_segments *= shape[-1] if nr_segments > 15: raise ValueError( "Unable to encode as the DICOM standard only allows " "a maximum of 15 segments in RLE encoded data" ) dtype = arr.dtype kwargs = { 'bits_allocated': arr.dtype.itemsize * 8, 'rows': shape[0], 'columns': shape[1], 'samples_per_pixel': 3 if len(shape) == 3 else 1, 'byteorder': '<', } sys_endianness = '<' if sys.byteorder == 'little' else '>' byteorder = dtype.byteorder byteorder = sys_endianness if byteorder == '=' else byteorder if byteorder == '>': arr = arr.astype(dtype.newbyteorder('<')) return _encode_frame(arr.tobytes(), **kwargs)
def test_16_segments_raises(self): """Test trying to encode more than 15 segments raises exception.""" arr = np.asarray( [[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]]], dtype='uint8' ) assert (1, 1, 16) == arr.shape assert 1 == arr.dtype.itemsize msg = ( r"Unable to encode as the DICOM standard only allows " r"a maximum of 15 segments in RLE encoded data" ) with pytest.raises(ValueError, match=msg): _encode_frame( arr.tobytes(), rows=1, columns=1, samples_per_pixel=16, bits_allocated=8 )
def test_single_row_1sample(self): """Test encoding a single row of 1 sample/pixel data.""" # Rows 1, Columns 5, SamplesPerPixel 1 arr = np.asarray([[0, 1, 2, 3, 4]], dtype='uint8') encoded = _encode_frame( arr.tobytes(), rows=1, columns=5, samples_per_pixel=1, bits_allocated=8 ) header = b'\x01\x00\x00\x00\x40\x00\x00\x00' + b'\x00' * 56 assert header == encoded[:64] assert b'\x04\x00\x01\x02\x03\x04' == encoded[64:]
def test_cycle_32bit_1sample(self): """Test an encode/decode cycle for 32-bit 1 sample/pixel.""" ds = dcmread(EXPL_32_1_1F) ref = ds.pixel_array assert 32 == ds.BitsAllocated assert 1 == ds.SamplesPerPixel kwargs = RLELosslessEncoder.kwargs_from_ds(ds) encoded = _encode_frame(ds.PixelData, **kwargs) decoded = _rle_decode_frame( encoded, ds.Rows, ds.Columns, ds.SamplesPerPixel, ds.BitsAllocated ) arr = np.frombuffer(decoded, '<u4') arr = reshape_pixel_array(ds, arr) assert np.array_equal(ref, arr)
def test_cycle_32bit_3sample(self): """Test an encode/decode cycle for 32-bit 3 sample/pixel.""" ds = dcmread(EXPL_32_3_1F) ref = ds.pixel_array assert ds.BitsAllocated == 32 assert ds.SamplesPerPixel == 3 assert ds.PixelRepresentation == 0 kwargs = RLELosslessEncoder.kwargs_from_ds(ds) encoded = _encode_frame(ds.PixelData, **kwargs) decoded = _rle_decode_frame( encoded, ds.Rows, ds.Columns, ds.SamplesPerPixel, ds.BitsAllocated ) # The decoded data is planar configuration 1 ds.PlanarConfiguration = 1 arr = np.frombuffer(decoded, '<u4') arr = reshape_pixel_array(ds, arr) assert np.array_equal(ref, arr)
def test_15_segment(self): """Test encoding 15 segments works as expected.""" arr = np.asarray( [[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]]], dtype='uint8' ) assert (1, 1, 15) == arr.shape assert 1 == arr.dtype.itemsize encoded = _encode_frame( arr.tobytes(), rows=1, columns=1, samples_per_pixel=15, bits_allocated=8 ) header = ( b'\x0f\x00\x00\x00' b'\x40\x00\x00\x00' b'\x42\x00\x00\x00' b'\x44\x00\x00\x00' b'\x46\x00\x00\x00' b'\x48\x00\x00\x00' b'\x4a\x00\x00\x00' b'\x4c\x00\x00\x00' b'\x4e\x00\x00\x00' b'\x50\x00\x00\x00' b'\x52\x00\x00\x00' b'\x54\x00\x00\x00' b'\x56\x00\x00\x00' b'\x58\x00\x00\x00' b'\x5a\x00\x00\x00' b'\x5c\x00\x00\x00' ) assert header == encoded[:64] assert ( b'\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06' b'\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c' b'\x00\x0d\x00\x0e\x00\x0f' ) == encoded[64:]