o
    iȈ                     @   s  U d Z ddlmZmZmZ ddlZddlZddlZddlm	Z	m
Z
mZ zddlZW n	 ey2   Y nw ddlmZ ddlmZmZmZmZ ddlmZmZmZmZmZmZmZmZmZm Z m!Z! ergddl"m#Z# e$e%Z&ee'd	ge'e(B f Z)G d
d deddZ*G dd	 d	eZ+G dd deZ,e-e.e/ee/ ee/ ee/ f Z0eg deg dedddde1ddfdddde1ddfdddde1ddfdddde1ddfdddde1ddfgedddde1ddfdddde1ddfdddde1ddfdddde1ddfdddde1ddfgedddde1ddfdddde1ddfdddde1ddfdddde1dd fdddde1ddfgedddde1ddfdddde1ddfdddde1dd fdddde1ddfgedddd!e1dd"fdddd!e1dd"fdddde1ddfd#ddd!e1dd"fdddd!e1dd"fdddd!e1dd"fgedddd!e1dd"fdddd!e1dd"fd$ddd!e1dd"fdddd!e1dd"fdddd!e1dd"fge dddde1ddfdddde1ddfdddde1ddfdddde1dd fdddde1ddfgi	Z2e3ee4e0 f e5d%< e,e Z6e67g d& e,eZ8e89d'd( e,eZ:e:9d'd( e,eZ;e;9d)d* e,eZ<e<9d)d* e e6d+fee8d,fee:d,fee;d,fee<d,fiZ=d3d.d/Z>e>  d0e.d-e,fd1d2Z?dS )4zPixel data encoding.    )CallableIteratorIterableN)AnycastTYPE_CHECKING)config)Buffer
RunnerBase	CoderBaseRunnerOptions)UIDJPEGBaseline8BitJPEGExtended12BitJPEGLosslessJPEGLosslessSV1JPEGLSLosslessJPEGLSNearLosslessJPEG2000LosslessJPEG2000RLELosslessJPEGLSTransferSyntaxesDatasetEncodeRunnerc                   @   s:   e Zd ZU dZeed< eed< ee ed< ee ed< dS )EncodeOptionsz5Options accepted by EncodeRunner and encoding plugins	byteorder	jls_errorj2k_crj2k_psnrN)	__name__
__module____qualname____doc__str__annotations__intlistfloat r)   r)   R/mnt/sdb/aimis/docanh/lib/python3.10/site-packages/pydicom/pixels/encoders/base.pyr   )   s   
 r   F)totalc                   @   s   e Zd ZdZdeddfddZdedB defdd	ZdedB defd
dZ	dedB defddZ
dedB deeB fddZdeeef ddfddZd$ddZed%ddZdefddZd&ddZd&ddZd&d d!Zd&d"d#ZdS )'r   a   Class for managing the pixel data encoding process.

    .. versionadded:: 3.0

    This class is not intended to be used directly. For encoding pixel data
    use the :class:`~pydicom.pixels.encoders.base.Encoder` instance
    corresponding to the transfer syntax of the pixel data.
    tsyntaxreturnNc                 C   s&   |  |  |ddd| _ d| _i | _dS )zCreate a new runner for encoding data as `tsyntax`.

        Parameters
        ----------
        tsyntax : pydicom.uid.UID
            The transfer syntax UID corresponding to the pixel data to be
            encoded.
        <	PixelData)transfer_syntax_uidr   pixel_keyword)r0   r1   r   N)_opts_undeletable	_encoders)selfr,   r)   r)   r*   __init__G   s   	
zEncodeRunner.__init__indexc                 C   s   g }| j  D ]0\}}z|| || W   S  ty7 } zt| || d|  W Y d}~qd}~ww d|}td| )al  Return an encoded frame of pixel data as :class:`bytes`.

        Parameters
        ----------
        index : int | None
            If `index` is ``None`` then the pixel data only contains one frame,
            otherwise `index` is the frame number to be encoded.

        Returns
        ------
        bytes
            The encoded pixel data frame.
        : Nz
  zGUnable to encode as exceptions were raised by all available plugins:
  )	r4   items	get_frame	ExceptionLOGGER	exceptionappendjoinRuntimeError)r5   r7   failure_messagesnamefuncexcmessagesr)   r)   r*   encodeZ   s   
 
zEncodeRunner.encodec                 C   s0   | j r| |S | |}t|tst|S |S )a  Return a frame's worth of uncompressed pixel data as :class:`bytes`.

        Parameters
        ----------
        index : int | None
            If the pixel data only has one from then use ``None``, otherwise
            `index` is the index of the frame to be returned.
        )is_array_get_frame_array_get_frame_buffer
isinstancebytes)r5   r7   framer)   r)   r*   r:   v   s   	

zEncodeRunner.get_framec                 C   s   t tj|dur| j| n| j}| jdkrd}n/d| j  k r#dkr(n nd}nd| j  k r3dkr8n nd}nd| j  k rCdkrGn nd}|jj|krX||jj | }| j	t
v rn| jd	krn| jdkrn|dd
d}t t| S )zBReturn a frame's worth of uncompressed pixel data from an ndarray.N                   @      r   )r   npndarraysrcbits_storeddtypeitemsizeastypekindtransfer_syntaxr   samples_per_pixelplanar_configuration	transposerK   tobytes)r5   r7   arrrZ   r)   r)   r*   rH      s     



zEncodeRunner._get_frame_arrayc                 C   sd  t t| jdd}|du rdn|| }t t| j|||  }t t| jdd}t|| }| jdkr@|dkr9|S |dd| S d| j  k rKdkrsn n&|d	krS|S t|d	 }|dd| |ddd	< |dd| |ddd	< |S d| j  k r~d
krn nB|dkr|S t|d }|dd| |ddd< |dd| |ddd< |d	d| |d	dd< |dkr|dd| |ddd< |S |dkr|S t|d }|dd| |ddd< |dd| |ddd< |d	d| |d	dd< |dd| |ddd< |dd| |ddd< |dkr|S |dd| |ddd< |dkr$|S |dd| |ddd< |S )zCReturn a frame's worth of uncompressed pixel data from buffer-like.rK   unitNr   pixelsrM   rN   rO   rP   rQ   rR   rT         )r   r&   frame_lengthrK   rW   lenrX   	bytearray)r5   r7   bytes_per_framestartrW   expected_lengthbytes_per_pixeloutr)   r)   r*   rI      sN   



zEncodeRunner._get_frame_bufferencodersc                 C   s
   || _ dS )zSet the encoders use for encoding compressed pixel data.

        Parameters
        ----------
        encoders : dict[str, EncodeFunction]
            A dict of {name: encoder function}.
        N)r4   )r5   rp   r)   r)   r*   set_encoders   s   
zEncodeRunner.set_encodersrW   np.ndarray | Dataset | Bufferc                 C   s   ddl m} t||r| | |j| _d| _dS t|ttB t	B r*|| _d| _dS t|t
jrZtjdkr7dnd}|jj}|dkrC|n|}|dkrR||jd}|| _d	| _dS td
|jj d)a  Set the pixel data to be encoded.

        Parameters
        ----------
        src : bytes | bytearray | memoryview | pydicom.dataset.Dataset | numpy.ndarray

            * If a buffer-like then the encoded pixel data
            * If a :class:`~pydicom.dataset.Dataset` then a dataset containing
              the pixel data and associated group ``0x0028`` elements.
            * If a :class:`numpy.ndarray` then an array containing the image data.
        r   r   r   r	   littler.   >=ArrayzD'src' must be bytes, numpy.ndarray or pydicom.dataset.Dataset, not ''N)pydicom.datasetr   rJ   _set_options_dsr/   _src	_src_typerK   rj   
memoryviewrU   rV   sysr   rY   r[   newbyteorder	TypeError	__class__r    )r5   rW   r   sys_endiannessr   r)   r)   r*   
set_source   s*   




zEncodeRunner.set_sourceBuffer | np.ndarrayc                 C   s   | j S )zKReturn the buffer-like or :class:`numpy.ndarray` containing the pixel data.)rz   r5   r)   r)   r*   rW   &  s   zEncodeRunner.srcc                 C   sf   d| j j dg}|d |dd | j D  | jr.|d |dd | jD  d|S )	z)Return nice string output for the runner.zEncodeRunner for 'rw   Optionsc                 S   s    g | ]\}}d | d| qS )  r8   r)   ).0rB   valuer)   r)   r*   
<listcomp>/  s     z(EncodeRunner.__str__.<locals>.<listcomp>Encodersc                 S   s   g | ]}d | qS )r   r)   r   rB   r)   r)   r*   r   2  s    
)r]   rB   r>   extendoptionsr9   r4   r?   )r5   sr)   r)   r*   __str__+  s   


zEncodeRunner.__str__c                 C   s2   |    | js
| jr|   n|   |   dS )z4Validate the encoding options and source pixel data.N)_validate_options
is_dataset	is_buffer_validate_buffer_validate_array_validate_encoding_profiler   r)   r)   r*   validate6  s
   
zEncodeRunner.validatec              
   C   sB  t tj| j}|j}|j}t|dvrtdt| d| j| j	| j
| jg}|d dkr3|dd n|}|d dv rA|dd n|}|t|krUtd	t| d
| t|tjt|tjg}t|sotd| d| jdk}|| sddg| }td| d| j d| d|jt| jd k rtd| d| j d| | }}	|rd| jd   }
d| jd  d }n
dd| j d }
}||ks|	|
k rtd|
 d| d| j d| jtkr|r| dd}||| ko|	|
| k}|r|std| j d| d|
|  d||  d	dS dS dS dS )z4Check that the ndarray matches the supplied options.)rP   rT   rR   zUnable to encode z
D ndarraysr   rN   N)NrN   z,Mismatch between the expected ndarray shape z and the actual shape zThe ndarray's dtype 'z=' is not supported, must be a signed or unsigned integer typeunsignedsignedzB' is not consistent with a (0028,0103) 'Pixel Representation' of 'z' (z
 integers)rM   zB' is not consistent with a (0028,0100) 'Bits Allocated' value of 'rw   rP   zEThe ndarray contains values that are outside the allowable range of (, z,) for a (0028,0101) 'Bits Stored' value of 'r   zThe supported range of pixel values when performing lossy JPEG-LS encoding of signed integers with a (0028,0103) 'Bits Stored' value of 'z' and a 'jls_error' of 'z' is ())r   rU   rV   rW   shaperY   ri   
ValueErrornumber_of_framesrowscolumnsr^   tuple
issubdtypeunsignedintegersignedintegeranypixel_representationrZ   mathceilbits_allocatedmaxminrX   r]   r   
get_option)r5   rb   r   rY   expectedui	is_signedr   amaxaminminimummaximumerrorwithinr)   r)   r*   r   A  s   

	zEncodeRunner._validate_arrayc                 C   sB   | j dd}|| j }t| j }|k rtd| d| ddS )z(Validate the supplied pixel data buffer.rK   rc   zNThe length of the uncompressed pixel data doesn't match the expected length - z bytes actual vs. z	 expectedN)rh   r   ri   rW   r   )r5   length_bytesr   actualr)   r)   r*   r     s   
zEncodeRunner._validate_bufferc                 C   s   | j tvrdS t| j  }|D ]7\}}}}}z'| j|ksJ | j|ks$J | j|v s+J | j|v s2J | j|v s9J W  dS  tyE   Y qw td| j j	 d| j d| j d| j d| j d| j d)	ap  Perform  UID specific validation of encoding parameters based on
        Part 5, Section 8 of the DICOM Standard.

        Encoding profiles should be:

        Tuple[str, int, Iterable[int], Iterable[int], Iterable[int]] as
        (
            PhotometricInterpretation, SamplesPerPixel, PixelRepresentation,
            BitsAllocated, BitsStored
        )
        NzNOne or more of the following values is not valid for pixel data encoded with 'z$':
  (0028,0002) Samples per Pixel: z+
  (0028,0006) Photometric Interpretation: z
  (0028,0100) Bits Allocated: z
  (0028,0101) Bits Stored: z%
  (0028,0103) Pixel Representation: zC
See Part 5, Section 8.2 of the DICOM Standard for more information)
r]   ENCODING_PROFILESphotometric_interpretationr^   r   r   rX   AssertionErrorr   rB   )r5   profilepispppx_reprbits_abits_sr)   r)   r*   r     s:   

z'EncodeRunner._validate_encoding_profile)rW   rr   r-   N)r-   r   r-   N)r    r!   r"   r#   r   r6   r&   rK   rF   r:   rH   rj   rI   dictr$   EncodeFunctionrq   r   propertyrW   r   r   r   r   r   r)   r)   r)   r*   r   =   s     	#K

)


Zc                       s   e Zd ZdZdeddf fddZdddd	d
ddedB dedede	de
fddZdddd
ddedede	dee
 f
ddZ  ZS )Encodera  Factory class for data encoders.

    Every available ``Encoder`` instance in *pydicom* corresponds directly
    to a single DICOM *Transfer Syntax UID*, and provides a  mechanism for
    converting raw unencoded source data to meet the requirements of that
    transfer syntax using one or more :doc:`encoding plugins
    </guides/encoding/encoder_plugins>`.

    .. versionadded:: 2.2
    uidr-   Nc                    s   t  j|dd dS )zCreate a new data encoder.

        Parameters
        ----------
        uid : pydicom.uid.UID
            The *Transfer Syntax UID* that the encoder supports.
        F)decoderN)superr6   )r5   r   r   r)   r*   r6     s   zEncoder.__init__T )r7   r   encoding_pluginrW   zbytes | np.ndarray | Datasetr7   r   r   kwargsc                K   s   |dur|dk rt dt| j}|| |jdi | |tttdf | 	| t
jr5t| |r;|  |jdkrH|du rHt d||S )a  Return an encoded frame of the pixel data in `src` as
        :class:`bytes`.

        .. warning::

            With the exception of *RLE Lossless*, this method requires the
            installation of additional packages to perform the actual pixel
            data encoding. See the :doc:`encoding documentation
            </guides/user/image_data_compression>` for more information.

        Parameters
        ----------
        src : bytes, numpy.ndarray or pydicom.dataset.Dataset
            Single or multi-frame pixel data as one of the following:

            * :class:`~numpy.ndarray`: the uncompressed pixel data, should be
              :attr:`shaped<numpy.ndarray.shape>` as:

              * (rows, columns) for single frame, single sample data.
              * (rows, columns, planes) for single frame, multi-sample data.
              * (frames, rows, columns) for multi-frame, single sample data.
              * (frames, rows, columns, planes) for multi-frame and
                multi-sample data.

            * :class:`~pydicom.dataset.Dataset`: the dataset containing
              the uncompressed *Pixel Data* to be encoded.
            * :class:`bytes`: the uncompressed little-endian ordered pixel
              data. `src` should use 1, 2, 4 or 8 bytes per pixel, whichever
              of these is sufficient for the (0028,0103) *Bits Stored* value.
        index : int, optional
            Required when `src` contains multiple frames, this is the index
            of the frame to be encoded.
        validate : bool, optional
            If ``True`` (default) then validate the supplied encoding options
            and pixel data prior to encoding, otherwise if ``False`` no
            validation will be performed.
        encoding_plugin : str, optional
            The name of the pixel data encoding plugin to use. If
            `encoding_plugin` is not specified then all available
            plugins will be tried (default). For information on the available
            plugins for each encoder see the
            :mod:`API documentation<pydicom.pixels.encoders>`.
        **kwargs
            The following keyword parameters are required when `src` is
            :class:`bytes` or :class:`~numpy.ndarray`:

            * ``'rows'``: :class:`int` - the number of rows of pixels in `src`,
              maximum 65535.
            * ``'columns'``: :class:`int` - the number of columns of pixels in
              `src`, maximum 65535.
            * ``'number_of_frames'``: :class:`int` - the number of frames
              in `src`.
            * ``'samples_per_pixel'``: :class:`int` - the number of samples
              per pixel in `src`, should be 1 or 3.
            * ``'bits_allocated'``: :class:`int` - the number of bits used
              to contain each pixel, should be a multiple of 8.
            * ``'bits_stored'``: :class:`int` - the number of bits actually
              used per pixel. For example, an ``ndarray`` `src` might have a
              :class:`~numpy.dtype` of ``'uint16'`` (range 0 to 65535) but
              only contain 12-bit pixel values (range 0 to 4095).
            * ``'pixel_representation'``: :class:`int` - the type of data
              being encoded, ``0`` for unsigned, ``1`` for 2's complement
              (signed)
            * ``'photometric_interpretation'``: :class:`str` - the intended
              color space of the *encoded* pixel data, such as ``'YBR_FULL'``.

            Optional keyword parameters for the encoding plugin may also be
            present. See the :doc:`encoding plugin options
            </guides/encoding/encoder_plugin_options>` for more information.

        Returns
        -------
        bytes
            The encoded pixel data.
        Nr   z*'index' must be greater than or equal to 0r   rN   zMThe 'index' of the frame to be encoded is required for multi-frame pixel datar)   )r   r   r   r   set_optionsrq   r   r   r$   _validate_pluginsr   	debuggingr<   debugr   r   rF   )r5   rW   r7   r   r   r   runnerr)   r)   r*   rF     s(   T




zEncoder.encode)r   r   c                k   s    t | j}|| |jdi | |tttdf | | t	j
r*t| |r0|  |jdkr=|dV  dS t|jD ]}||V  qBdS )a"  Yield encoded frames of the pixel data in `src` as :class:`bytes`.

        .. warning::

            With the exception of *RLE Lossless*, this method requires the
            installation of additional packages to perform the actual pixel
            data encoding. See the :doc:`encoding documentation
            </guides/user/image_data_compression>` for more information.

        Parameters
        ----------
        src : bytes, numpy.ndarray or pydicom.dataset.Dataset
            Single or multi-frame pixel data as one of the following:

            * :class:`~numpy.ndarray`: the uncompressed pixel data, should be
              :attr:`shaped<numpy.ndarray.shape>` as:

              * (rows, columns) for single frame, single sample data.
              * (rows, columns, planes) for single frame, multi-sample data.
              * (frames, rows, columns) for multi-frame, single sample data.
              * (frames, rows, columns, planes) for multi-frame and
                multi-sample data.

            * :class:`~pydicom.dataset.Dataset`: the dataset containing
              the uncompressed *Pixel Data* to be encoded.
            * :class:`bytes`: the uncompressed little-endian ordered pixel
              data. `src` should use 1, 2, 4 or 8 bytes per pixel, whichever
              of these is sufficient for the (0028,0103) *Bits Stored* value.
        validate : bool, optional
            If ``True`` (default) then validate the supplied encoding options
            and pixel data prior to encoding, otherwise if ``False`` no
            validation will be performed.
        encoding_plugin : str, optional
            The name of the pixel data encoding plugin to use. If
            `encoding_plugin` is not specified then all available
            plugins will be tried (default). For information on the available
            plugins for each encoder see the
            :mod:`API documentation<pydicom.pixels.encoders>`.
        **kwargs
            The following keyword parameters are required when `src` is
            :class:`bytes` or :class:`~numpy.ndarray`:

            * ``'rows'``: :class:`int` - the number of rows of pixels in `src`,
              maximum 65535.
            * ``'columns'``: :class:`int` - the number of columns of pixels in
              `src`, maximum 65535.
            * ``'number_of_frames'``: :class:`int` - the number of frames
              in `src`.
            * ``'samples_per_pixel'``: :class:`int` - the number of samples
              per pixel in `src`, should be 1 or 3.
            * ``'bits_allocated'``: :class:`int` - the number of bits used
              to contain each pixel, should be a multiple of 8.
            * ``'bits_stored'``: :class:`int` - the number of bits actually
              used per pixel. For example, an ``ndarray`` `src` might have a
              :class:`~numpy.dtype` of ``'uint16'`` (range 0 to 65535) but
              only contain 12-bit pixel values (range 0 to 4095).
            * ``'pixel_representation'``: :class:`int` - the type of data
              being encoded, ``0`` for unsigned, ``1`` for 2's complement
              (signed)
            * ``'photometric_interpretation'``: :class:`str` - the intended
              color space of the encoded pixel data, such as ``'YBR_FULL'``.

            Optional keyword parameters for the encoding plugin may also be
            present. See the :doc:`encoding plugin options
            </guides/encoding/encoder_plugin_options>` for more information.

        Yields
        ------
        bytes
            An encoded frame of pixel data.
        r   rN   Nr)   )r   r   r   r   rq   r   r   r$   r   r   r   r<   r   r   r   rF   range)r5   rW   r   r   r   r   r7   r)   r)   r*   iter_encodeU  s(   
O



zEncoder.iter_encode)r    r!   r"   r#   r   r6   r&   boolr$   r   rK   rF   r   r   __classcell__r)   r)   r   r*   r     s@    
sr   )MONOCHROME1rN   r   rM   r   MONOCHROME2rN   r   r   r   )YBR_FULL_422rT   r   r   r   )RGBrT   r   r   r   )r   )r   rN   r   rO      r   )r   rN   r   r   r   r   rN   )r   rN   )rM   rO      r   zPALETTE COLORr   YBR_FULLrT   r   rP   r   	   )rM   rO      rQ   (   '   YBR_RCTYBR_ICTr   ))gdcm)zpydicom.pixels.encoders.gdcmencode_pixel_data)	pylibjpegz!pydicom.pixels.encoders.pylibjpeg_encode_frame)pydicom)zpydicom.pixels.encoders.nativer   pyjpegls)z pydicom.pixels.encoders.pyjpeglsr   r   r   z2.2z3.0r-   c                     s   ddddd t  D ]\\} }| j}| j }| j }t|t| } fddt|D }d|j d	| d
g}|	d |	d|  |	d |	dd
|  |	d |	d d
|| _qdS )z'Override the default Encoder docstring.z':ref:`pydicom <encoder_plugin_pydicom>`z+:ref:`pylibjpeg <encoder_plugin_pylibjpeg>`z!:ref:`gdcm <encoder_plugin_gdcm>`z):ref:`pyjpegls <encoder_plugin_pyjpegls>`)r   r   r   r   c                    s   g | ]} | qS r)   r)   r   plugin_doc_linksr)   r*   r   =  s    z-_build_encoder_docstrings.<locals>.<listcomp>zA *Pixel Data* encoder for *z* - ``z``r   z.. versionadded:: zEncoding plugins: r   zeSee the :class:`~pydicom.pixels.encoders.base.Encoder` reference for instance methods and attributes.r   N)_PIXEL_DATA_ENCODERSvaluesr   
_availablekeys_unavailabler'   sortedrB   r>   r?   r#   )encversionaddedr   	availableunavailablepluginsr   r)   r   r*   _build_encoder_docstrings.  s,   




r   r   c                 C   s8   t | } zt|  d W S  ty   td| j dw )a  Return the pixel data encoder corresponding to `uid`.

    .. versionadded:: 2.2

    +--------------------------------------------------+----------------+
    | Transfer Syntax                                  | Version added  |
    +-------------------------+------------------------+                +
    | Name                    | UID                    |                |
    +=========================+========================+================+
    | *JPEG-LS Lossless*      | 1.2.840.10008.1.2.4.80 | 3.0            |
    +-------------------------+------------------------+----------------+
    | *JPEG-LS Near Lossless* | 1.2.840.10008.1.2.4.81 | 3.0            |
    +-------------------------+------------------------+----------------+
    | *JPEG 2000 Lossless*    | 1.2.840.10008.1.2.4.90 | 3.0            |
    +-------------------------+------------------------+----------------+
    | *JPEG 2000*             | 1.2.840.10008.1.2.4.91 | 3.0            |
    +-------------------------+------------------------+----------------+
    | *RLE Lossless*          | 1.2.840.10008.1.2.5    | 2.2            |
    +-------------------------+------------------------+----------------+
    r   z2No pixel data encoders have been implemented for 'rw   )r   r   KeyErrorNotImplementedErrorrB   )r   r)   r)   r*   get_encoderO  s   r  r   )@r#   collections.abcr   r   r   loggingr   r}   typingr   r   r   numpyrU   ImportErrorr   r   pydicom.pixels.commonr	   r
   r   r   pydicom.uidr   r   r   r   r   r   r   r   r   r   r   rx   r   	getLoggerr    r<   rK   rj   r   r   r   r   r   r$   r&   ProfileTyper   r   r   r'   r%   RLELosslessEncoderadd_pluginsJPEGLSLosslessEncoder
add_pluginJPEGLSNearLosslessEncoderJPEG2000LosslessEncoderJPEG2000Encoderr   r   r  r)   r)   r)   r*   <module>   s   4
    tA

