U
    ARdM                     @   s  U d Z ddlZddlZddlZddlZddlmZ ddlmZm	Z	m
Z
mZmZmZ ddlmZ ddlZddlmZmZmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZ ddl m!Z" ddl#m$Z$ ddl%m&Z& erddlm'Z' ddl(mZ) ddl*m+Z+ ee,Z-ee.d< dZ/ee0 e.d< eejejej1f Z2ee.d< ee2dej3e4f Z5ee.d< ee5e	e5 f Z6ee.d< e
eed e7f  Z8ee.d< ed Z9ee.d< ed Z:ee.d< ee:df Z;ee.d< G dd  d eZ<d!e<j=_ d"e<j>_ d#e<j?_ G d$d% d%Z@e2e7d&d'd(ZAe2e7d&d)d*ZBeeCe2f e4e:d+d,d-ZDdMe2e:e0eCd0d1d2ZEej3eCd3d4d5ZFdNdeCd6d7d8ZGde	d d6d9d:ZHddd6d;d<ZIe:e4d=d>d?ZJeCe0e:eCd@dAdBZKde7ddCdDdEZLe5e0e7e9e;e4e4dFdGdHZMdOe4e6e
ee4de	e4 f  ee0e<f e"e7e9e;ddJ	dKdLZNdS )PzImage marshalling.    N)IntEnum)TYPE_CHECKINGListOptionalSequenceUnioncast)urlparse)GifImagePluginImage	ImageFile)FinalLiteral	TypeAlias)runtime)StreamlitAPIException)
get_logger)	ImageList)caching)gather_metrics)Any)DeltaGeneratorLOGGERi  MAXIMUM_CONTENT_WIDTHPILImagenpt.NDArray[Any]AtomicImageImageOrImageList)autoalwaysneverUseColumnWith)RGBBGRChannels)JPEGPNGGIFImageFormatr   ImageFormatOrAutoc                   @   s   e Zd ZdZdZdZdZdS )WidthBehaviourz|
    Special values that are recognized by the frontend and allow us to change the
    behavior of the displayed image.
    N)__name__
__module____qualname____doc__ORIGINALCOLUMNAUTO r5   r5   </tmp/pip-unpacked-wheel-b9et7o5g/streamlit/elements/image.pyr*   C   s   r*   z'Display the image at its original widthz5Display the image at the width of the column it's in.zDisplay the image at its original width, unless it
would exceed the width of its column in which case clamp it to
its column widthc                   @   sX   e Zd Zeddeeeeee f  ee	 e
eeedddd	Zedd
ddZdS )
ImageMixinimageNFr"   r   r   )r8   captionwidthuse_column_widthclampchannelsoutput_formatreturnc           	   	   C   s   |dks|dkr |dkr t j}n8|dks0|dkr8t j}n |dkrHt j}n|dkrXtdt }t| j ||||||| | j	d|S )a
  Display an image or list of images.

        Parameters
        ----------
        image : numpy.ndarray, [numpy.ndarray], BytesIO, str, or [str]
            Monochrome image of shape (w,h) or (w,h,1)
            OR a color image of shape (w,h,3)
            OR an RGBA image of shape (w,h,4)
            OR a URL to fetch the image from
            OR a path of a local image file
            OR an SVG XML string like `<svg xmlns=...</svg>`
            OR a list of one of the above, to display multiple images.
        caption : str or list of str
            Image caption. If displaying multiple images, caption should be a
            list of captions (one for each image).
        width : int or None
            Image width. None means use the image width,
            but do not exceed the width of the column.
            Should be set for SVG images, as they have no default image width.
        use_column_width : 'auto' or 'always' or 'never' or bool
            If 'auto', set the image's width to its natural size,
            but do not exceed the width of the column.
            If 'always' or True, set the image's width to the column width.
            If 'never' or False, set the image's width to its natural size.
            Note: if set, `use_column_width` takes precedence over the `width` parameter.
        clamp : bool
            Clamp image pixel values to a valid range ([0-255] per channel).
            This is only meaningful for byte array images; the parameter is
            ignored for image URLs. If this is not set, and an image has an
            out-of-range value, an error will be thrown.
        channels : 'RGB' or 'BGR'
            If image is an nd.array, this parameter denotes the format used to
            represent color information. Defaults to 'RGB', meaning
            `image[:, :, 0]` is the red channel, `image[:, :, 1]` is green, and
            `image[:, :, 2]` is blue. For images coming from libraries like
            OpenCV you should set this to 'BGR', instead.
        output_format : 'JPEG', 'PNG', or 'auto'
            This parameter specifies the format to use when transferring the
            image data. Photos should use the JPEG format for lossy compression
            while diagrams should use the PNG format for lossless compression.
            Defaults to 'auto' which identifies the compression type based
            on the type and format of the image argument.

        Example
        -------
        >>> import streamlit as st
        >>> from PIL import Image
        >>>
        >>> image = Image.open('sunrise.jpg')
        >>>
        >>> st.image(image, caption='Sunrise by the mountains')

        .. output::
           https://doc-image.streamlitapp.com/
           height: 710px

        r   Nr   Tr   zImage width must be positive.imgs)
r*   r4   r3   r2   r   ImageListProtomarshall_imagesdgZ_get_delta_path_strZ_enqueue)	selfr8   r9   r:   r;   r<   r=   r>   Zimage_list_protor5   r5   r6   r8   X   s(    G
zImageMixin.image)r?   c                 C   s
   t d| S )zGet our DeltaGenerator.r   )r   )rD   r5   r5   r6   rC      s    zImageMixin.dg)NNNFr"   r   )r.   r/   r0   r   r   r   r   strr   intr!   boolr$   r)   r8   propertyrC   r5   r5   r5   r6   r7   W   s&         \r7   )r8   r?   c                 C   s   | j dkrdS dS d S )N)ZRGBAZLAPTF)moder8   r5   r5   r6   _image_may_have_alpha_channel   s    
rL   c                 C   s   t | jdkS )Nr'   )rG   formatrK   r5   r5   r6   _image_is_gif   s    rN   )
image_datarM   r?   c                 C   sj   |  }|dks|dkr"tt|S |dkr.dS t| trJtt| }n| }t	|rZdS t
|rfdS dS )aq  Return either "JPEG", "PNG", or "GIF", based on the input `format` string.

    - If `format` is "JPEG" or "JPG" (or any capitalization thereof), return "JPEG"
    - If `format` is "PNG" (or any capitalization thereof), return "PNG"
    - For all other strings, return "PNG" if the image has an alpha channel,
    "GIF" if the image is a GIF, and "JPEG" otherwise.
    r%   r&   ZJPGr'   )upperr   r(   
isinstancebytesr   openioBytesIOrN   rL   )rO   rM   Z	pil_imager5   r5   r6   _validate_image_format_string   s    


rV   r%   d   )r8   rM   qualityr?   c                 C   s:   t  }|dkr"t| r"| d} | j|||d | S )zConvert a PIL image to bytes.r%   r"   rM   rX   )rT   rU   rL   convertsavegetvalue)r8   rM   rX   tmpr5   r5   r6   _PIL_to_bytes   s
    
r^   )datar?   c                 C   s   |  d |  S )Nr   )seekr\   )r_   r5   r5   r6   _BytesIO_to_bytes   s    
ra   )arrayr?   c                 C   s&   t | tj}t||}t||S N)r   Z	fromarrayZastypenpZuint8rV   r^   )rb   r>   imgrM   r5   r5   r6   _np_array_to_bytes   s    
rf   c                    s    fddt d jd D S )Nc                    s(   g | ] } |d d d d d d f qS rc   r5   ).0irb   r5   r6   
<listcomp>  s     z"_4d_to_list_3d.<locals>.<listcomp>r   )rangeshaperi   r5   ri   r6   _4d_to_list_3d  s    rm   c                 C   s   t | jdkrtdt | jdkrN| jd dkrNtd| jd t| jf t | jdkr| jd dkr| d d d d df } | S )	N)      z'Numpy shape has to be of length 2 or 3.ro   r+   )   ro      z2Channel can only be 1, 3, or 4 got %d. Shape is %srp   r   )lenrl   r   rE   ri   r5   r5   r6   _verify_np_shape  s    rs   )image_formatr?   c                 C   s   d|    S )z2Get the mimetype string for the given ImageFormat.zimage/)lower)rt   r5   r5   r6   _get_image_format_mimetype  s    rv   )rO   r:   rt   r?   c                 C   s   t t| }|j\}}|dk r.|tkr.t}|dkrt||krttd| | | }|j||ft jd}t	||ddS t
d| }|| krt	||ddS | S )zResize an image if it exceeds the given width, or if exceeds
    MAXIMUM_CONTENT_WIDTH. Ensure the image's format corresponds to the given
    ImageFormat. Return the (possibly resized and reformatted) image bytes.
    r         ?)ZresampleZ   rY   N)r   rS   rT   rU   sizer   rF   resizeZBILINEARr^   imghdrwhatru   )rO   r:   rt   r8   Zactual_widthZactual_heightZ
new_heightextr5   r5   r6   _ensure_image_size_and_format  s    
r~   )r8   r<   r?   c                 C   s   | }t | jjtjrV|r(t| dd}n$t| dk sDt| dkrLtd|d }n8|rjt| dd}n$t| dk st| dkrtd|S )Nr   rw   g        z0Data is outside [0.0, 1.0] and clamp is not set.   z.Data is outside [0, 255] and clamp is not set.)	
issubclassZdtypetyperd   ZfloatingZclipZaminZamaxRuntimeError)r8   r<   r_   r5   r5   r6   _clip_image8  s    
r   )r8   r:   r<   r=   r>   image_idr?   c              	   C   s  t | trzt| }|jr | W S W n tk
r6   Y nX z"t| d}| }W 5 Q R X W nT tk
r   t	| \}	}
|	dkrd}	t
 j| |	|}t| |	| | Y S X nt | tjtjfrt| |}t| |}nt | tjrt| }ntt | tjr`tt| |} |dkrLt| jdkrD| dddddddgf } ntd	ttd
| |d}n| }t||}t |||}t!|}	t
" rt
 j||	|}t||	| |S dS dS )a0  Return a URL that an image can be served from.
    If `image` is already a URL, return it unmodified.
    Otherwise, add the image to the MediaFileManager and return the URL.

    (When running in "raw" mode, we won't actually load data into the
    MediaFileManager, and we'll return an empty URL.)
    rbNzapplication/octet-streamr#   ro   rn   rp   r   zQWhen using `channels="BGR"`, the input image should have exactly 3 color channelsr   )rb   r>    )#rQ   rE   r	   schemeUnicodeDecodeErrorrS   read	Exception	mimetypes
guess_typer   Zget_instanceZmedia_file_mgraddr   Zsave_media_datar   r   rV   r^   rT   rU   ra   rd   ndarrayr   rs   rr   rl   r   rf   r   r~   rv   exists)r8   r:   r<   r=   r>   r   pfrO   mimetype_urlrM   rt   r5   r5   r6   image_to_urlJ  s\    




	

r   r"   )	coordinatesr8   r9   r:   
proto_imgsr<   r=   r>   r?   c              
   C   s  t t| }t|tr|}n*t|tjrBt|jdkrBt	|}n|g}t
|tkrZ|}	nXt|trl|g}	nFt|tjrt|jdkr| }	n"|dkrdgt| }	n
t|g}	t
|	tkstdt|	t|kstdt|	t|f t||_tt||	D ]\}
\}}|j }|dk	r0t||_d| |
f }d}t|tr|dr|d	st|}| }W 5 Q R X td
|rd|ksd|krd| |_nd| |_d}|st|||||||_qdS )a  Fill an ImageListProto with a list of images and their captions.

    The images will be resized and reformatted as necessary.

    Parameters
    ----------
    coordinates
        A string indentifying the images' location in the frontend.
    image
        The image or images to include in the ImageListProto.
    caption
        Image caption. If displaying multiple images, caption should be a
        list of captions (one for each image).
    width
        The desired width of the image or images. This parameter will be
        passed to the frontend.
        Positive values set the image width explicitly.
        Negative values has some special. For details, see: `WidthBehaviour`
    proto_imgs
        The ImageListProto to fill in.
    clamp
        Clamp image pixel values to a valid range ([0-255] per channel).
        This is only meaningful for byte array images; the parameter is
        ignored for image URLs. If this is not set, and an image has an
        out-of-range value, an error will be thrown.
    channels
        If image is an nd.array, this parameter denotes the format used to
        represent color information. Defaults to 'RGB', meaning
        `image[:, :, 0]` is the red channel, `image[:, :, 1]` is green, and
        `image[:, :, 2]` is blue. For images coming from libraries like
        OpenCV you should set this to 'BGR', instead.
    output_format
        This parameter specifies the format to use when transferring the
        image data. Photos should use the JPEG format for lossy compression
        while diagrams should use the PNG format for lossless compression.
        Defaults to 'auto' which identifies the compression type based
        on the type and format of the image argument.
    rq   rp   Nz1If image is a list then caption should be as wellz'Cannot pair %d captions with %d images.z%s-%iFz.svg)zhttp://zhttps://z2(^\s?(<\?xml[\s\S]*<svg\s)|^\s?<svg\s|^\s?<svg>\s)xlinkxmlnszdata:image/svg+xml,T)r   r$   rP   rQ   listrd   r   rr   rl   rm   r   rE   tolistAssertionErrorrF   r:   	enumeratezipr@   r   r9   endswith
startswithrS   r   researchZmarkupr   r   )r   r8   r9   r:   r   r<   r=   r>   ZimagesZcaptionsZcoord_suffixZ	proto_imgr   Zis_svgZtextfiler5   r5   r6   rB     sZ    0









     rB   )r%   rW   )r%   )r"   r   )Or1   r{   rT   r   r   enumr   typingr   r   r   r   r   r   urllib.parser	   Znumpyrd   ZPILr
   r   r   Ztyping_extensionsr   r   r   Z	streamlitr   Zstreamlit.errorsr   Zstreamlit.loggerr   Zstreamlit.proto.Image_pb2r   rA   Zstreamlit.runtimer   Zstreamlit.runtime.metrics_utilr   r   Znumpy.typingZnptZstreamlit.delta_generatorr   r.   r   __annotations__r   rF   ZGifImageFiler   rU   rE   r   r   rG   r!   r$   r(   r)   r*   r2   r3   r4   r7   rL   rN   rR   rV   r^   ra   rf   rm   rs   rv   r~   r   r   rB   r5   r5   r5   r6   <module>   s    d
 "    j  
