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:]
Beispiel #3
0
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:]