o
    i5                     @   s`  d Z ddlmZ ddlmZmZ ddlmZmZ zddl	Z
dZW n ey+   dZY nw zddlZddlmZ dZW n eyE   dZY nw dd	lmZ dd
lmZ ddlmZ ddlmZ erlddlmZ ddlmZ ddddZdddddZ	dHdddddeeB dB ddfddZ				dIddddd d!d"e dB d#edB ddfd$d%Z!dJd'd(Z"dJd)d*Z#e"Z$	dKdddd&d+e d,e%ddf
d-d.Z&dLdddd&d+e ddfd/d0Z'dLdddd&d+e ddfd1d2Z(	dMddd3ed4ed5e%ddf
d6d7Z)dNd8d9Z*dNd:d;Z+		<		dOddd=e,d"e dB d#edB dd>f
d?d@Z-		dHdAe.e dBf dCedDe dB dEe dB de/e  f
dFdGZ0dS )Pz Pixel data processing functions.    )BytesIO)unpackunpack_from)TYPE_CHECKINGcastNTF)ImageCms)get_palette_files)warn_and_log)UID)VR)Iterable)DatasetsRGBXYZLAB)SRGBr   r   
proceduralzrelative colorimetric
saturationzabsolute colorimetric)r            arr
np.ndarraydszDataset | Nonepalettereturnc              	      s  |s|st d|r_dddddddd	d
}t|js;zddddddddd}|| }W n ty:   t d| dw zddlm} || }|t|d }W n ty^   t d| dw td|}t|dddv rpt dd|vrxt dtt	t
 |j}|d pd}|d  }	|d! }
td"|
d# g }d$|v rtt|j}tt|j}tt|j}ttdB t|d%d}t|| d& }td"|d# | fd'd(||||fD  nd)|v ratt|j}tt|j}tt|j}ttdB t|d*d}t|d+r|jjd  }n|jd  }|du r td,t|j d-d.| }|
d& }|d kr/d/nd0}|
}||||fD ]&}|r^t|| }| | | }tt|||}| tj!| d1 q9nt d|d2vrst d3|d4d5d6d7 |D t"fd8d(d d D st d9tj#| j$ d1}| |	k}| | t%|	 ||< tj&|d|d  |d: tj't	| j$t|g  d1}t(|D ]\}}|| |d;|f< q|S )<a  Apply a color palette lookup table to `arr`.

    If (0028,1201-1203) *Palette Color Lookup Table Data* are missing
    then (0028,1221-1223) *Segmented Palette Color Lookup Table Data* must be
    present and vice versa. The presence of (0028,1204) *Alpha Palette Color
    Lookup Table Data* or (0028,1224) *Alpha Segmented Palette Color Lookup
    Table Data* is optional.

    Use of this function with the :dcm:`Enhanced Palette Color Lookup Table
    Module<part03/sect_C.7.6.23.html>` or :dcm:`Supplemental Palette Color LUT
    Module<part03/sect_C.7.6.19.html>` is not currently supported.

    Parameters
    ----------
    arr : numpy.ndarray
        The pixel data to apply the color palette to.
    ds : dataset.Dataset, optional
        Required if `palette` is not supplied. A
        :class:`~pydicom.dataset.Dataset` containing a suitable
        :dcm:`Image Pixel<part03/sect_C.7.6.3.html>` or
        :dcm:`Palette Color Lookup Table<part03/sect_C.7.9.html>` Module.
    palette : str or uid.UID, optional
        Required if `ds` is not supplied. The name of one of the
        :dcm:`well-known<part06/chapter_B.html>` color palettes defined by the
        DICOM Standard. One of: ``'HOT_IRON'``, ``'PET'``,
        ``'HOT_METAL_BLUE'``, ``'PET_20_STEP'``, ``'SPRING'``, ``'SUMMER'``,
        ``'FALL'``, ``'WINTER'`` or the corresponding well-known (0008,0018)
        *SOP Instance UID*.

    Returns
    -------
    numpy.ndarray
        The RGB or RGBA pixel data as an array of ``np.uint8`` or ``np.uint16``
        values, depending on the 3rd value of (0028,1201) *Red Palette Color
        Lookup Table Descriptor*.

    References
    ----------

    * :dcm:`Image Pixel Module<part03/sect_C.7.6.3.html>`
    * :dcm:`Supplemental Palette Color LUT Module<part03/sect_C.7.6.19.html>`
    * :dcm:`Enhanced Palette Color LUT Module<part03/sect_C.7.6.23.html>`
    * :dcm:`Palette Colour LUT Module<part03/sect_C.7.9.html>`
    * :dcm:`Supplemental Palette Color LUTs
      <part03/sect_C.8.16.2.html#sect_C.8.16.2.1.1.1>`
    z$Either 'ds' or 'palette' is requiredzhotiron.dcmzpet.dcmzhotmetalblue.dcmzpet20step.dcmz
spring.dcmz
summer.dcmzfall.dcmz
winter.dcm)1.2.840.10008.1.5.11.2.840.10008.1.5.21.2.840.10008.1.5.31.2.840.10008.1.5.41.2.840.10008.1.5.51.2.840.10008.1.5.61.2.840.10008.1.5.71.2.840.10008.1.5.8r   r   r   r   r    r!   r#   r"   )HOT_IRONPETHOT_METAL_BLUEPET_20_STEPSPRINGSUMMERFALLWINTERzUnknown palette ''r   )dcmreadr   PixelPresentationN)MIXEDCOLORzgUse of this function with the Supplemental Palette Color Lookup Table Module is not currently supported$RedPaletteColorLookupTableDescriptorz3No suitable Palette Color Lookup Table Module found   r   r   uintz.0fRedPaletteColorLookupTableData AlphaPaletteColorLookupTableData   c                 3   s"    | ]}|rt j| d V  qdS )dtypeN)np
frombuffer).0	lut_bytesr7    O/mnt/sdb/aimis/docanh/lib/python3.10/site-packages/pydicom/pixels/processing.py	<genexpr>   s    
z"apply_color_lut.<locals>.<genexpr>'SegmentedRedPaletteColorLookupTableData)SegmentedAlphaPaletteColorLookupTableData	file_metaeUnable to determine the endianness of the dataset, please set an appropriate Transfer Syntax UID in '.file_meta'><BHr7   )r6      zThe bit depth of the LUT data 'z.1fz2' is invalid (only 8 or 16 bits per entry allowed)c                 S      g | ]}t |qS r=   )lenr;   iir=   r=   r>   
<listcomp>       z#apply_color_lut.<locals>.<listcomp>c                 3   s    | ]	}| d  kV  qdS )r   Nr=   rK   )lut_lengthsr=   r>   r?      s    z LUT data must be the same lengthout.))
ValueErrorr
   is_validKeyErrorpydicomr-   r   r   getattrlistintr1   r9   r8   bytesr4    GreenPaletteColorLookupTableDataBluePaletteColorLookupTableDatarJ   extendr@   )SegmentedGreenPaletteColorLookupTableData(SegmentedBluePaletteColorLookupTableDatahasattrrB   _tsyntax_encodingoriginal_encodingAttributeErrortype__name___expand_segmented_lutr   appendasarrayallzerosshapeint32clipempty	enumerate)r   r   r   datasetsuidsr-   fnamelut_desc
nr_entries	first_mapnominal_depthlutsr_lutg_lutb_luta_lutactual_depthis_little_endian
endianness
byte_depthfmtseglen_segs_fmtlut_ints
clipped_ivmapped_pixelsrQ   rL   lutr=   )r8   rO   r>   apply_color_lut*   s   3









 r   	transformz%PIL.ImageCms.ImageCmsTransform | Noneintentcolor_spacec                 C   s   t std|du r|std|dur|rtd| jdvr'td| j | jd dkr6td	| j |s?t|||d
}| jdkrdt| D ]\}}tj	|}t
j||dd t|| |< qH| S tj	| }t
j||dd t|| d< | S )a{  Apply an `ICC Profile <https://www.color.org/iccprofile.xalter>`_ to `arr`,
    either from the dataset `ds` or an existing Pillow color transformation object
    `transform`.

    .. versionadded:: 3.0

    .. warning::

        This function requires `NumPy <https://numpy.org/>`_ and `Pillow
        <https://pillow.readthedocs.io/en/stable/>`_.


    Parameters
    ----------
    arr : numpy.ndarray
        8-bit RGB pixel data to apply an ICC profile to, shaped as either (rows,
        columns, samples) or (frames, rows, columns, samples).
    ds : pydicom.dataset.Dataset, optional
        Required if `transform` is not supplied, a :class:`~pydicom.dataset.Dataset`
        containing elements from the :dcm:`ICC Profile<part03/sect_C.11.15.html>`
        module.
    transform : PIL.ImageCms.ImageCmsTransform, optional
        An :class:`~PIL.ImageCms.ImageCmsTransform` instance such as is returned by
        the :func:`create_icc_transform` function. Required if `ds` is not used and
        recommended when the same ICC profile is to be re-used on multiple ndarrays.
    intent : int, optional
        If `transform` is not supplied this is the rendering intent of the
        transformation that will be created from `ds`, one of:

        * ``0``: perceptual
        * ``1``: relative colorimetric
        * ``2``: saturation
        * ``3``: absolute colorimetric

        If no `intent` is specified then the default rendering intent in the ICC
        profile will be used.
    color_space : str, optional
        If `transform` is not supplied this is the output color space to use
        for the transformation created from `ds`. If not used then defaults to the
        (0028,2002) *Color Space* value if its present in `ds`, otherwise defaults to
        ``"sRGB"``. If used then it will override the (0028,2002) *Color Space* element
        value (if present). Must be one of the :func:`supported Pillow color spaces
        <PIL.ImageCms.createProfile>`, although in practice only ``"sRGB"`` is likely
        to be used.

    Returns
    -------
    np.ndarray
        The input ndarray with the color transformation applied in-place.
    z8Pillow is required to apply an ICC profile to an ndarrayNz+Either 'ds' or 'transform' must be suppliedz9Only one of 'ds' and 'transform' should be used, not both)r      z-The ndarray must have 3 or 4 dimensions, not r   zUInvalid ndarray shape, must be (rows, columns, 3) or (frames, rows, columns, 3), not )r   r   r   r   T)inPlace.)HAVE_PILImportErrorrR   ndimrj   create_icc_transformrn   PILImage	fromarrayr   applyTransformr9   array)r   r   r   r   r   idxframeimr=   r=   r>   apply_icc_profile   s<   9

r   r   c                 C   s  | drttd |jd }ttt |jd pd}ttt |jd }ttt |jd }d| }|d jtjkrqt|d	rH|j	j
d }n|jd }|d
u r\tdt|j dd| }| | d}	t|	tt|j}
nttt |j}
tj|
|d}tj| j| jd}| |k}| | | ||< tj|d|d |d || S d|v rd|v r| tjtt|j } | tt|j7 } | S )a  Apply a modality lookup table or rescale operation to `arr`.

    Parameters
    ----------
    arr : numpy.ndarray
        The :class:`~numpy.ndarray` to apply the modality LUT or rescale
        operation to.
    ds : dataset.Dataset
        A dataset containing a :dcm:`Modality LUT Module
        <part03/sect_C.11.html#sect_C.11.1>`.

    Returns
    -------
    numpy.ndarray
        An array with applied modality LUT or rescale operation. If
        (0028,3000) *Modality LUT Sequence* is present then returns an array
        of ``np.uint8`` or ``np.uint16``, depending on the 3rd value of
        (0028,3002) *LUT Descriptor*. If (0028,1052) *Rescale Intercept* and
        (0028,1053) *Rescale Slope* are present then returns an array of
        ``np.float64``. If neither are present then `arr` will be returned
        unchanged.

    Notes
    -----
    When *Rescale Slope* and *Rescale Intercept* are used, the output range
    is from (min. pixel value * Rescale Slope + Rescale Intercept) to
    (max. pixel value * Rescale Slope + Rescale Intercept), where min. and
    max. pixel value are determined from (0028,0101) *Bits Stored* and
    (0028,0103) *Pixel Representation*.

    References
    ----------
    * DICOM Standard, Part 3, :dcm:`Annex C.11.1
      <part03/sect_C.11.html#sect_C.11.1>`
    * DICOM Standard, Part 4, :dcm:`Annex N.2.1.1
      <part04/sect_N.2.html#sect_N.2.1.1>`
    ModalityLUTSequencer   r   r2   r   r   r3   LUTDatarB   NrC   rD   rE   rG   r7   rP   RescaleSlopeRescaleIntercept)getr   rW   r   rX   LUTDescriptorr   OWr_   rB   r`   ra   rb   rc   rd   r   rY   r   r9   rg   ri   rj   r8   rl   astypefloat64floatr   r   )r   r   itemrs   rt   ru   r8   r|   r}   
unpack_fmtunc_datalut_datar   r   r=   r=   r>   apply_modality_lutO  s<   
&


r   c                 C   sT  d|v r|j d }|j\}}}|dkrdn|}|dkrdnd}||d  }|d }|jtjkr8tj|jdd}	ntj|jd	| d
| d}	||  }
re|	j	j
sU|	 }	tj|	|
|	d tj|	|
|	d | d} | |  8 } | |  |d   } | d} td|	|  S d|v r|j  }|dvrtd|j d|dkr|  |  } | S )a-  Apply a Presentation LUT to `arr` and return the P-values.

    Parameters
    ----------
    arr : numpy.ndarray
        The :class:`~numpy.ndarray` to apply the presentation LUT operation to.
    ds : dataset.Dataset
        A dataset containing :dcm:`Presentation LUT Module
        <part03/sect_C.11.4.html>` elements.

    Returns
    -------
    numpy.ndarray
        If a Presentation LUT Module is present in `ds` then returns an array
        of P-values, otherwise returns `arr` unchanged.

    Notes
    -----
    If the dataset the *Pixel Data* originated from contains a Modality LUT
    and/or VOI LUT then they must be applied before the Presentation LUT.

    See Also
    --------
    :func:`~pydicom.pixels.processing.apply_modality_lut`
    :func:`~pydicom.pixels.processing.apply_voi_lut`
    PresentationLUTSequencer   r2   r6   rH   r   u2r7   Nr3   rP   float32r   uint16r   PresentationLUTShape)IDENTITYINVERSEz1A (2050,0020) 'Presentation LUT Shape' value of 'z' is not supportedr   )r   r   r   USr9   rg   valuer:   r   flags	writeablecopy
left_shiftright_shiftr   minmaxr   r   stripupperNotImplementedError)r   r   r   rs   rt   	bit_depthitemsizenr_byteselemr   	bit_shiftr   r=   r=   r>   apply_presentation_lut  s>   


r   index
prefer_lutc                 C   s   d}| dr$ttd |j|_d|jd  dd|jd  ddfv}d| dd| d	dfv}|rD|rD|r>t| ||S t| ||S |rLt| ||S |rTt| ||S | S )
a  Apply a VOI lookup table or windowing operation to `arr`.

    .. versionchanged:: 2.1

        Added the `prefer_lut` keyword parameter

    Parameters
    ----------
    arr : numpy.ndarray
        The :class:`~numpy.ndarray` to apply the VOI LUT or windowing operation
        to.
    ds : dataset.Dataset
        A dataset containing a :dcm:`VOI LUT Module<part03/sect_C.11.2.html>`.
        If (0028,3010) *VOI LUT Sequence* is present then returns an array
        of ``np.uint8`` or ``np.uint16``, depending on the 3rd value of
        (0028,3002) *LUT Descriptor*. If (0028,1050) *Window Center* and
        (0028,1051) *Window Width* are present then returns an array of
        ``np.float64``. If neither are present then `arr` will be returned
        unchanged.
    index : int, optional
        When the VOI LUT Module contains multiple alternative views, this is
        the index of the view to return (default ``0``).
    prefer_lut : bool
        When the VOI LUT Module contains both *Window Width*/*Window Center*
        and *VOI LUT Sequence*, if ``True`` (default) then apply the VOI LUT,
        otherwise apply the windowing operation.

    Returns
    -------
    numpy.ndarray
        An array with applied VOI LUT or windowing operation.

    Notes
    -----
    When the dataset requires a modality LUT or rescale operation as part of
    the Modality LUT module then that must be applied before any windowing
    operation.

    See Also
    --------
    :func:`~pydicom.pixels.processing.apply_modality_lut`
    :func:`~pydicom.pixels.processing.apply_voi`
    :func:`~pydicom.pixels.processing.apply_windowing`

    References
    ----------
    * DICOM Standard, Part 3, :dcm:`Annex C.11.2
      <part03/sect_C.11.html#sect_C.11.2>`
    * DICOM Standard, Part 3, :dcm:`Annex C.8.11.3.1.5
      <part03/sect_C.8.11.3.html#sect_C.8.11.3.1.5>`
    * DICOM Standard, Part 4, :dcm:`Annex N.2.1.1
      <part04/sect_N.2.html#sect_N.2.1.1>`
    FVOILUTSequencer   Nr   r   r   WindowCenterWindowWidth)r   r   rW   r   	apply_voiapply_windowing)r   r   r   r   	valid_voivalid_windowingr=   r=   r>   apply_voi_lut  s(   8


r   c                 C   s|  | ds| S t| jtjstd ttd |j| }ttt	 |j
}|d p*d}|d }|d }|ttdd	v r?d
}n|dkrFd}ntd| d|d jtjkrt|drb|jjd }	n|jd }	|	du rvtdt|j dd|	  | d}
t|
tt|j}nttt	 |j}tj||d}tj| j|d}| |k}| | | ||< tj|d|d |d td|| S )a  Apply a VOI lookup table to `arr`.

    .. versionadded:: 2.1

    See :func:`~pydicom.pixels.processing.apply_voi_lut` for applying *Window
    Width*/*Window Center* as a fallback if no *VOI LUT Sequence* is present.

    Parameters
    ----------
    arr : numpy.ndarray
        The :class:`~numpy.ndarray` to apply the VOI LUT to.
    ds : dataset.Dataset
        A dataset containing a :dcm:`VOI LUT Module<part03/sect_C.11.2.html>`.
        If (0028,3010) *VOI LUT Sequence* is present then returns an array
        of ``np.uint8`` or ``np.uint16``, depending on the 3rd value of
        (0028,3002) *LUT Descriptor*, otherwise `arr` will be returned
        unchanged.
    index : int, optional
        When the VOI LUT Module contains multiple alternative views, this is
        the index of the view to return (default ``0``).

    Returns
    -------
    numpy.ndarray
        An array with applied VOI LUT.

    See Also
    --------
    :func:`~pydicom.pixels.processing.apply_modality_lut`
    :func:`~pydicom.pixels.processing.apply_windowing`
    :func:`~pydicom.pixels.processing.apply_voi_lut`

    References
    ----------
    * DICOM Standard, Part 3, :dcm:`Annex C.11.2
      <part03/sect_C.11.html#sect_C.11.2>`
    * DICOM Standard, Part 3, :dcm:`Annex C.8.11.3.1.5
      <part03/sect_C.8.11.3.html#sect_C.8.11.3.1.5>`
    * DICOM Standard, Part 4, :dcm:`Annex N.2.1.1
      <part04/sect_N.2.html#sect_N.2.1.1>`
    r   zDApplying a VOI LUT on a float input array may give incorrect resultsr   r   r2   r   r   
      r   r6   uint8r,   z%' bits per LUT entry is not supportedr   rB   NrC   rD   rE   rG   r7   rP   r   )r   r9   
issubdtyper8   integerr	   r   rW   r   rX   r   ranger   r   r   r_   rB   r`   ra   rb   rc   rd   r   rY   r   rg   ri   rj   rl   )r   r   r   r   lut_descriptorrs   rt   ru   r8   r|   r   r   r   r   r   r=   r=   r>   r   G  sJ   
*


r   c                 C   s  d|vr
d|vr
| S |j dvrtdttt|dd }|d }|jdkr1ttt |j	| n|j	}tt|}|d }|jdkrLttt |j	| n|j	}tt|}tt
|j|_|dr}d	}ttd
 |jd	 }ttt
 |jd }	d|	 d }
n |jd	krd	}d|j d }
nd|jd   }d|jd  d }
|dd}|dd}|dur|durtt|j|_tt|j|_||j |j }|
|j |j }
|
| }| d} |dv r1|dkr|dk rtd|d8 }|d8 }n|d	krtd| ||d  k}| ||d  k}t| | }|| |< |
| |< | r/| | | | d | | | |< | S |dkrR|d	kr?td|dtd| |  |   | } | S td| d)a  Apply a windowing operation to `arr`.

    .. versionadded:: 2.1

    Parameters
    ----------
    arr : numpy.ndarray
        The :class:`~numpy.ndarray` to apply the windowing operation to.
    ds : dataset.Dataset
        A dataset containing a :dcm:`VOI LUT Module<part03/sect_C.11.2.html>`.
        If (0028,1050) *Window Center* and (0028,1051) *Window Width* are
        present then returns an array of ``np.float64``, otherwise `arr` will
        be returned unchanged.
    index : int, optional
        When the VOI LUT Module contains multiple alternative views, this is
        the index of the view to return (default ``0``).

    Returns
    -------
    numpy.ndarray
        An array with applied windowing operation.

    Notes
    -----
    When the dataset requires a modality LUT or rescale operation as part of
    the Modality LUT module then that must be applied before any windowing
    operation.

    See Also
    --------
    :func:`~pydicom.pixels.processing.apply_modality_lut`
    :func:`~pydicom.pixels.processing.apply_voi`
    :func:`~pydicom.pixels.processing.apply_voi_lut`

    References
    ----------
    * DICOM Standard, Part 3, :dcm:`Annex C.11.2
      <part03/sect_C.11.html#sect_C.11.2>`
    * DICOM Standard, Part 3, :dcm:`Annex C.8.11.3.1.5
      <part03/sect_C.8.11.3.html#sect_C.8.11.3.1.5>`
    * DICOM Standard, Part 4, :dcm:`Annex N.2.1.1
      <part04/sect_N.2.html#sect_N.2.1.1>`
    r   r   )MONOCHROME1MONOCHROME2zWhen performing a windowing operation only 'MONOCHROME1' and 'MONOCHROME2' are allowed for (0028,0004) Photometric InterpretationVOILUTFunctionLINEARr   r   r   r   r   r   Nr   r   )r   LINEAR_EXACTzbThe (0028,1051) Window Width must be greater than or equal to 1 for a 'LINEAR' windowing operation      ?z\The (0028,1051) Window Width must be greater than 0 for a 'LINEAR_EXACT' windowing operationSIGMOIDzWThe (0028,1051) Window Width must be greater than 0 for a 'SIGMOID' windowing operationz0Unsupported (0028,1056) VOI LUT Function value 'r,   )PhotometricInterpretationrR   r   strrV   r   VMrW   r   r   rX   
BitsStoredr   r   r   PixelRepresentationr   r   r   r9   logical_andanyexp)r   r   r   voi_funcr   centerwidthy_minr   r   y_maxslope	intercepty_rangebelowabovebetweenr=   r=   r>   r     sz   ,
$
$






 

"r   currentdesired	per_framec           	   	   C   s   | j t dkrtd| j  dddd}||td	||td
|ttdd	}z|| | }W n tyB   td| d| dw t| jdkr]|r]t	| D ]
\}}||| |< qP| S || S )a  Convert the image(s) in `arr` from one color space to another.

    .. versionchanged:: 2.2

        Added `per_frame` keyword parameter.

    Parameters
    ----------
    arr : numpy.ndarray
        The image(s) as :class:`numpy.ndarray` with :attr:`~numpy.ndarray.shape`
        (frames, rows, columns, 3) or (rows, columns, 3) and a 'uint8'
        :class:`~numpy.dtype` (unsigned 8-bit).
    current : str
        The current color space, should be a valid value for (0028,0004)
        *Photometric Interpretation*. One of ``'RGB'``, ``'YBR_FULL'``,
        ``'YBR_FULL_422'``.
    desired : str
        The desired color space, should be a valid value for (0028,0004)
        *Photometric Interpretation*. One of ``'RGB'``, ``'YBR_FULL'``,
        ``'YBR_FULL_422'``.
    per_frame : bool, optional
        If ``True`` and the input array contains multiple frames then process
        each frame individually and update `arr` in-place to reduce memory
        usage. Default ``False``.

    Returns
    -------
    numpy.ndarray
        The image(s) converted to the desired color space. If `per_frame` is
        ``False`` (the default) then a new :class:`~numpy.ndarray` will be
        returned, otherwise `arr` will be updated in-place.

    References
    ----------

    * DICOM Standard, Part 3,
      :dcm:`Annex C.7.6.3.1.2<part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2>`
    * ISO/IEC 10918-5:2012 (`ITU T.871
      <https://www.ijg.org/files/T-REC-T.871-201105-I!!PDF-E.pdf>`_),
      Section 7
    u1zInvalid ndarray.dtype 'z>' for color space conversion, must be 'uint8' or an equivalentr   r   r   c                 S   s   | S )Nr=   )r   r=   r=   r>   
_no_changee  s   z'convert_color_space.<locals>._no_change)YBR_FULL_422YBR_FULLRGB)r   r   r   )r   r   r   zConversion from z to z is not supported.r   Nr   r   r   r   )
r8   r9   rR   _convert_YBR_FULL_to_RGB_convert_RGB_to_YBR_FULLrT   r   rJ   rj   rn   )	r   r   r   r   r   _converters	converterr   r   r=   r=   r>   convert_color_space3  s<   ,
r   c                 C   sp   | j }tjg dg dg dgtjd}tj| |tjd} | g d7 } tj| | d tj| dd| d | |S )	a  Return an ndarray converted from RGB to YBR_FULL color space.

    Parameters
    ----------
    arr : numpy.ndarray
        An ndarray of an 8-bit per channel images in RGB color space.

    Returns
    -------
    numpy.ndarray
        The array in YBR_FULL color space.

    References
    ----------

    * DICOM Standard, Part 3,
      :dcm:`Annex C.7.6.3.1.2<part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2>`
    * ISO/IEC 10918-5:2012 (`ITU T.871
      <https://www.ijg.org/files/T-REC-T.871-201105-I!!PDF-E.pdf>`_),
      Section 7
    )gA`"?g$@#ſr   )gbX9?g_n3տg{Fڿ)gv/?r   gRдr7   )r        `@r   rP   r      )r8   r9   rg   r   matmulfloorrl   r   )r   
orig_dtype
rgb_to_ybrr=   r=   r>   r     s   	
r   c                 C   s   | j }tjg dg dg dgtjd}| tj} | g d8 } tj| || d | d7 } tj| | d tj| dd	| d | |S )
a  Return an ndarray converted from YBR_FULL to RGB color space.

    Parameters
    ----------
    arr : numpy.ndarray
        An ndarray of an 8-bit per channel images in YBR_FULL color space.

    Returns
    -------
    numpy.ndarray
        The array in RGB color space.

    References
    ----------

    * DICOM Standard, Part 3,
      :dcm:`Annex C.7.6.3.1.2<part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2>`
    * ISO/IEC 10918-5:2012, Section 7
    )      ?r  r  )        gk3Tֿg'1Z?)g;On?gbCW4r  r7   )r      r  rP   r   r   r   )r8   r9   rg   r   r   r   r   rl   )r   r  
ybr_to_rgbr=   r=   r>   r     s   	
r       icc_profilezPIL.ImageCms.ImageCmsTransformc                 C   s   t std| du r|std| r|rtdt| d|}|s$td|r(|nt| dd}|rL| tvrL|sBd	| d
}t|d| d}t|t|  }tt|}|r]|nt	|}|t
vrntd| dtjt||ddt|dS )am  Return a Pillow color transformation object from either the dataset `ds` or an
    ICC profile `icc_profile`.

    .. versionadded:: 3.0

    .. warning::

        This function requires `NumPy <https://numpy.org/>`_ and `Pillow
        <https://pillow.readthedocs.io/en/stable/>`_.

    Parameters
    ----------
    ds : pydicom.dataset.Dataset, optional
        Required if `icc_profile` is not supplied, a :class:`~pydicom.dataset.Dataset`
        containing elements from the :dcm:`ICC Profile<part03/sect_C.11.15.html>` module.
    icc_profile : bytes, optional
        Required if `ds` is not supplied, an ICC profile encoded as :class:`bytes`.
    intent : int, optional
        The rendering intent of the transformation, one of:

        * ``0``: perceptual
        * ``1``: relative colorimetric
        * ``2``: saturation
        * ``3``: absolute colorimetric

        If no `intent` is specified then the default rendering intent in the ICC
        profile will be used.
    color_space : str, optional
        The output color space to use for the transformation created from `ds`. If not
        used then defaults to the (0028,2002) *Color Space* value if its present in
        `ds`, otherwise defaults to ``"sRGB"``. If used then it will override the
        (0028,2002) *Color Space* element value (if present). Must be one of the
        :func:`supported Pillow color spaces<PIL.ImageCms.createProfile>`, although in
        practice only ``"sRGB"`` is likely to be used.

    Returns
    -------
    PIL.ImageCms.ImageCmsTransform
        A color transformation object that can be used with :func:`apply_icc_profile`.
    z:Pillow is required to create a color transformation objectNz-Either 'ds' or 'icc_profile' must be suppliedz;Only one of 'ds' and 'icc_profile' should be used, not both
ICCProfilez6No (0028,2000) 'ICC Profile' element was found in 'ds'
ColorSpacer   z%The (0028,2002) 'Color Space' value 'z`' is not supported by Pillow, please use the 'color_space' argument to specify a supported valuez!Unsupported 'color_space' value 'z!', must be 'sRGB', 'LAB' or 'XYZ'zInvalid 'intent' value 'z', must be 0, 1, 2 or 3r   )outputProfileinputProfileinModeoutModerenderingIntent)r   r   rR   rV   r   _CMS_COLOR_SPACESr   ImageCmsProfiler   getDefaultIntent_CMS_INTENTSbuildTransformcreateProfileIntent)r   r  r   r   csmsgprofiler=   r=   r>   r     s<   .

r   data.r   nr_segments
last_valuec                    s  d|v rg dng d}g }dd}d t  k r  } d  }d7 |dkr<| |   |7 n|dkr|rG|d }	n	|rL|}	ntd  }
d7 |	|
kre||
g|  ny|
|	 | }tt|	| |
|}|d	d
 |D  n\|dkr|stdd|v r fdd
|D }|d d> |d B d> |d d> |d B B }d7 n d  d>   B }d7 |t |d |||d  ntd| d|d7 }||kr|S d t  k s|S )a  Return a list containing the expanded lookup table data.

    Parameters
    ----------
    data : tuple of int
        The decoded segmented palette lookup table data. May be padded by a
        trailing null.
    fmt : str
        The format of the data, should contain `'B'` for 8-bit, `'H'` for
        16-bit, `'<'` for little endian and `'>'` for big endian.
    nr_segments : int, optional
        Expand at most `nr_segments` from the data. Should be used when
        the opcode is ``2`` (indirect). If used then `last_value` should also
        be used.
    last_value : int, optional
        The previous value in the expanded lookup table. Should be used when
        the opcode is ``2`` (indirect). If used then `nr_segments` should also
        be used.

    Returns
    -------
    list of int
        The reconstructed lookup table data.

    References
    ----------

    * DICOM Standard, Part 3, Annex C.7.9
    <)r   r   r   r   )r   r   r   r   r   r   r   r   zdError expanding a segmented palette color lookup table: the first segment cannot be a linear segmentc                 S   rI   r=   )rX   r;   vvr=   r=   r>   rM     rN   z)_expand_segmented_lut.<locals>.<listcomp>zgError expanding a segmented palette color lookup table: the first segment cannot be an indirect segmentrF   c                    s   g | ]} |  qS r=   r=   r  r  offsetr=   r>   rM     s    r6   rH   r   r   NzHError expanding a segmented palette lookup table: unknown segment type 'r,   )rJ   r\   rR   r9   aroundlinspacere   )r  r   r  r  indirect_iir   segments_readopcodelengthy0y1stepvalsrL   byte_offsetr=   r   r>   re   ?  s`   %

,
"<re   )NN)NNNN)r   r   r   r   r   r   )r   T)r   )Fr   )Nr  NN)1__doc__ior   structr   r   typingr   r   numpyr9   HAVE_NPr   r   r   r   pydicom.datar   pydicom.miscr	   pydicom.uidr
   pydicom.valuerepr   collections.abcr   pydicom.datasetr   r  r  r   r   rX   r   r   r   apply_rescaleboolr   r   r   r   r   r   rY   r   tuplerW   re   r=   r=   r=   r>   <module>   s   	

 E

c
VL
Se 	

V
,.
`
