o
    i7                     @   sX  d Z ddlmZ ddlmZmZ zddlZddlZdZW n e	y'   dZY nw ddl
mZ ddlmZ dd	lmZmZ ddlZerHdd
lmZ dZddiZejjgZdefddZdedefddZdddefddZdddefddZd,dddeddfddZ de!de"e# fd d!Z$	d,d"e!d#e#d$e#d%e#d&e#d'ede%fd(d)Z&d"e!de%fd*d+Z'dS )-ah  Use the `numpy <https://numpy.org/>`_ package to convert RLE lossless *Pixel
Data* to a :class:`numpy.ndarray`.

**Supported transfer syntaxes**

* 1.2.840.10008.1.2.5 : RLE Lossless

**Supported data**

The RLE handler supports the conversion of data in the (7FE0,0010)
*Pixel Data* element to a numpy ndarray provided the related
:dcm:`Image Pixel<part03/sect_C.7.6.3.html>` module elements have values given
in the table below.

+------------------------------------------------+--------------+----------+
| Element                                        | Supported    |          |
+-------------+---------------------------+------+ values       |          |
| Tag         | Keyword                   | Type |              |          |
+=============+===========================+======+==============+==========+
| (0028,0002) | SamplesPerPixel           | 1    | N            | Required |
+-------------+---------------------------+------+--------------+----------+
| (0028,0006) | PlanarConfiguration       | 1C   | 1            | Optional |
+-------------+---------------------------+------+--------------+----------+
| (0028,0008) | NumberOfFrames            | 1C   | N            | Optional |
+-------------+---------------------------+------+--------------+----------+
| (0028,0010) | Rows                      | 1    | N            | Required |
+-------------+---------------------------+------+--------------+----------+
| (0028,0011) | Columns                   | 1    | N            | Required |
+-------------+---------------------------+------+--------------+----------+
| (0028,0100) | BitsAllocated             | 1    | 8, 16, 32    | Required |
+-------------+---------------------------+------+--------------+----------+
| (0028,0103) | PixelRepresentation       | 1    | 0, 1         | Required |
+-------------+---------------------------+------+--------------+----------+

    )unpack)TYPE_CHECKINGcastNTF)generate_frames)warn_and_log)pixel_dtypeget_nr_frames)DatasetzRLE Losslessnumpy)zhttps://numpy.org/NumPyreturnc                   C   s   t S )z8Return ``True`` if the handler has its dependencies met.)HAVE_RLE r   r   ]/mnt/sdb/aimis/docanh/lib/python3.10/site-packages/pydicom/pixel_data_handlers/rle_handler.pyis_available?   s   r   transfer_syntaxc                 C   s   | t v S )zReturn ``True`` if the handler supports the `transfer_syntax`.

    Parameters
    ----------
    transfer_syntax : uid.UID
        The Transfer Syntax UID of the *Pixel Data* that is to be used with
        the handler.
    )SUPPORTED_TRANSFER_SYNTAXES)r   r   r   r   supports_transfer_syntaxD   s   	r   dsr	   c                 C      dS )zReturn ``True`` if the *Pixel Data* should to be converted from YCbCr to
    RGB.

    This affects JPEG transfer syntaxes.
    Fr   r   r   r   r   needs_to_convert_to_RGBP      r   c                 C   r   )zReturn ``True`` if the *Photometric Interpretation* should be changed
    to RGB.

    This affects JPEG transfer syntaxes.
    Fr   r   r   r   r   .should_change_PhotometricInterpretation_to_RGBY   r   r   >rle_segment_order
np.ndarrayc                    s    j j}|tvrtdg d} fdd|D }|r$tdd| tt j}tt j	}t
 dd}tt j}tt j}	t }
t j|d	D ]}t|||	|||}|
| qLt|
t }t rld
 _td|S )av  Return an :class:`numpy.ndarray` of the *Pixel Data*.

    Parameters
    ----------
    ds : dataset.Dataset
        The :class:`Dataset` containing an Image Pixel module and the RLE
        encoded *Pixel Data* to be converted.
    rle_segment_order : str
        The order of segments used by the RLE decoder when dealing with *Bits
        Allocated* > 8. Each RLE segment contains 8-bits of the pixel data,
        and segments are supposed to be ordered from MSB to LSB. A value of
        ``'>'`` means interpret the segments as being in big endian order
        (default) while a value of ``'<'`` means interpret the segments as
        being in little endian order which may be possible if the encoded data
        is non-conformant.

    Returns
    -------
    numpy.ndarray
        The decoded contents of (7FE0,0010) *Pixel Data* as a 1D array.

    Raises
    ------
    AttributeError
        If `ds` is missing a required element.
    NotImplementedError
        If `ds` contains pixel data in an unsupported format.
    ValueError
        If the actual length of the pixel data doesn't match the expected
        length.
    zgUnable to convert the pixel data as the transfer syntax is not supported by the RLE pixel data handler.)	PixelDataBitsAllocatedRowsColumnsPixelRepresentationSamplesPerPixelc                    s   g | ]}| vr|qS r   r   ).0elemr   r   r   
<listcomp>   s    z!get_pixeldata.<locals>.<listcomp>zbUnable to convert the pixel data as the following required elements are missing from the dataset: z, F)warn)number_of_framesRGBr   )	file_metaTransferSyntaxUIDr   NotImplementedErrorAttributeErrorjoinr   intr   r"   r   r   r    	bytearrayr   r   _rle_decode_frameextendnp
frombufferr   r   PhotometricInterpretation)r   r   r   required_elementsmissingnr_bits
nr_samples	nr_framesrowscols
pixel_dataframeimarrr   r   r   get_pixeldatab   s8    
r@   headerc                 C   sl   t | dkr
tdtd| dd d }|dkr!td| d	td
| d| dd|d   }t|S )a  Return a list of byte offsets for the segments in RLE data.

    **RLE Header Format**

    The RLE Header contains the number of segments for the image and the
    starting offset of each segment. Each of these numbers is represented as
    an unsigned long stored in little-endian. The RLE Header is 16 long words
    in length (i.e. 64 bytes) which allows it to describe a compressed image
    with up to 15 segments. All unused segment offsets shall be set to zero.

    As an example, the table below describes an RLE Header with 3 segments as
    would typically be used with 8-bit RGB or YCbCr data (with 1 segment per
    channel).

    +--------------+---------------------------------+------------+
    | Byte  offset | Description                     | Value      |
    +==============+=================================+============+
    | 0            | Number of segments              | 3          |
    +--------------+---------------------------------+------------+
    | 4            | Offset of segment 1, N bytes    | 64         |
    +--------------+---------------------------------+------------+
    | 8            | Offset of segment 2, M bytes    | 64 + N     |
    +--------------+---------------------------------+------------+
    | 12           | Offset of segment 3             | 64 + N + M |
    +--------------+---------------------------------+------------+
    | 16           | Offset of segment 4 (not used)  | 0          |
    +--------------+---------------------------------+------------+
    | ...          | ...                             | 0          |
    +--------------+---------------------------------+------------+
    | 60           | Offset of segment 15 (not used) | 0          |
    +--------------+---------------------------------+------------+

    Parameters
    ----------
    header : bytes
        The RLE header data (i.e. the first 64 bytes of an RLE frame).

    Returns
    -------
    list of int
        The byte offsets for each segment in the RLE data.

    Raises
    ------
    ValueError
        If there are more than 15 segments or if the header is not 64 bytes
        long.

    References
    ----------
    DICOM Standard, Part 5, :dcm:`Annex G<part05/chapter_G.html>`
    @   z(The RLE header can only be 64 bytes longz<LN   r      z8The RLE header specifies an invalid number of segments ()<L   )len
ValueErrorr   list)rA   nr_segmentsoffsetsr   r   r   _parse_rle_header   s   5
"rN   datar:   columnsr8   r7   segment_orderc                 C   s|  |d rt d| t| dd }t|}|d }||| kr.td| d||  d|t|  t|| | | }	|| | }
t|D ]r}t|}|dkrU|nt|}|D ]_}|| | }t| || ||d	   }t|}||| k rtd
| d||  d||| krt	d| d||  d |dkr|| d	 }|||
  }|d||  |	|||
 |< q[qI|	S )a  Decodes a single frame of RLE encoded data.

    Each frame may contain up to 15 segments of encoded data.

    Parameters
    ----------
    data : bytes
        The RLE frame data
    rows : int
        The number of output rows
    columns : int
        The number of output columns
    nr_samples : int
        Number of samples per pixel (e.g. 3 for RGB data).
    nr_bits : int
        Number of bits per sample - must be a multiple of 8
    segment_order : str
        The segment order of the `data`, '>' for big endian (default),
        '<' for little endian (non-conformant).

    Returns
    -------
    bytearray
        The frame's decoded data in little endian and planar configuration 1
        byte ordering (i.e. for RGB data this is all red pixels then all
        green then all blue, with the bytes for each pixel ordered from
        MSB to LSB when reading left to right).
       zUUnable to decode RLE encoded pixel data with a (0028,0100) 'Bits Allocated' value of NrB   zPThe number of RLE segments in the pixel data doesn't match the expected amount (z vs. z
 segments)rF   rH   zJThe amount of decoded RLE segment data doesn't match the expected amount (z bytes)z:The decoded RLE segment contains non-conformant padding - z bytes expectedr   )
r+   rN   rI   rJ   appendr/   rangereversed_rle_decode_segmentr   )rO   r:   rP   r8   r7   rQ   rM   rL   bytes_per_sampledecodedstridesample_numberle_genbyte_offsetsbyte_offsetiisegmentactual_lengthstartr   r   r   r0      sf   $
r0   c                 C   s   t | } t  }d}|j}z5	 | | d }|d7 }|dkr/|| ||d  d|   |d7 }n|dk rA|| |||   ||7 }q tyK   Y |S w )zReturn a single segment of decoded RLE data as bytearray.

    Parameters
    ----------
    data : bytes
        The segment data to be decoded.

    Returns
    -------
    bytearray
        The decoded segment.
    r   TrH      i  )r/   r1   
IndexError)rO   resultposresult_extendheader_byter   r   r   rV   d  s&   
rV   )r   )(__doc__structr   typingr   r   r
   r2   r   ImportErrorpydicom.encapsr   pydicom.miscr   pydicom.pixels.utilsr   r   pydicom.uidpydicompydicom.datasetr	   HANDLER_NAMEDEPENDENCIESuidRLELosslessr   boolr   strr   r   r   r@   bytesrK   r.   rN   r/   r0   rV   r   r   r   r   <module>   sT   $
		NI
q