U
    a+d8                     @   s   d Z ddlmZ ddlmZmZmZmZ ddlZddl	Z	ddl
ZddlZddlmZmZmZ ddlmZmZ ddlmZ d	d
 Zdd ZG dd deZdS )a  Read/Write TIFF files using tifffile.

.. note::
    To use this plugin you need to have `tifffile
    <https://github.com/cgohlke/tifffile>`_ installed::

        pip install tifffile

This plugin wraps tifffile, a powerfull library to manipulate TIFF files. It
superseeds our previous tifffile plugin and aims to expose all the features of
tifffile.

The plugin treats individual TIFF series as ndimages. A series is a sequence of
TIFF pages that, when combined describe a meaningful unit, e.g., a volumetric
image (where each slice is stored on an individual page) or a multi-color
staining picture (where each stain is stored on an individual page). Different
TIFF flavors/variants use series in different ways and, as such, the resulting
reading behavior may vary depending on the program used while creating a
particular TIFF file.

Methods
-------
.. note::
    Check the respective function for a list of supported kwargs and detailed
    documentation.

.. autosummary::
    :toctree:

    TifffilePlugin.read
    TifffilePlugin.iter
    TifffilePlugin.write
    TifffilePlugin.properties
    TifffilePlugin.metadata

Additional methods available inside the :func:`imopen <imageio.v3.imopen>`
context:

.. autosummary::
    :toctree:

    TifffilePlugin.iter_pages

    )BytesIO)AnyDictOptionalcastN   )	URI_BYTESInitializationErrorRequest)ImagePropertiesPluginV3)	ArrayLikec                 C   s   i }d| j kr | j d jj|d< d| j krd| j krd| j kr| j d j}| j d j}|d dksn|d dkr|tdt n$|d |d  |d |d  f|d< |S )	z,Get the resolution in a py3.7 compatible wayi(  Zresolution_uniti  i     r   zQIgnoring resulution metadata, because at least one direction has a 0 denominator.
resolution)tagsvaluewarningswarnRuntimeWarning)pagemetadataZresolution_xZresolution_y r   ?/tmp/pip-unpacked-wheel-xbmu82vq/imageio/plugins/tifffile_v3.py_get_resolution;   s    
r   c                 C   s<   i }zt j | jd jd|d< W n tk
r6   Y nX |S )z/Get the datetime in a python 3.7 compatible wayi2  z%Y:%m:%d %H:%M:%Sdatetime)r   strptimer   r   KeyError)r   r   r   r   r   _get_datatimeZ   s    
 r   c                       s   e Zd ZdZedd fddZdddeeejddd	Z	ejd
ddZ
ddeeee dddZedddeeeeeef dddZdddeeedddZdd
 fddZdddZ  ZS )TifffilePlugina  Support for tifffile as backend.

    Parameters
    ----------
    request : iio.Request
        A request object that represents the users intent. It provides a
        standard interface for a plugin to access the various ImageResources.
        Check the docs for details.
    kwargs : Any
        Additional kwargs are forwarded to tifffile's constructor, i.e.
        to ``TiffFile`` for reading or ``TiffWriter`` for writing.

    N)requestreturnc                    sr   t  | d | _|jjdkrZztj| f|| _W qn tjjk
rV   t	dY qnX ntj
| f|| _d S )Nrz Tifffile can not read this file.)super__init___fhmodeZio_modetifffileZTiffFileget_fileZTiffFileErrorr	   Z
TiffWriter)selfr   kwargs	__class__r   r   r#   {   s    zTifffilePlugin.__init__)indexr   )r,   r   r    c                K   s   d|kr||d< n|dk	r"t d|dk	r<d|kr<t dn"d|krP|d}n|dk	rZnd}|tkr|dkrtdd | jf |D }n&|tkrdn|}| jjf d|i|}|S )	a  Read a ndimage or page.

        The ndimage returned depends on the value of both ``index`` and
        ``page``. ``index`` selects the series to read and ``page`` allows
        selecting a single page from the selected series. If ``index=None``,
        ``page`` is understood as a flat index, i.e., the selection ignores
        individual series inside the file. If both ``index`` and ``page`` are
        ``None``, then all the series are read and returned as a batch.

        Parameters
        ----------
        index : int
            If ``int``, select the ndimage (series) located at that index inside
            the file and return ``page`` from it. If ``None`` and ``page`` is
            ``int`` read the page located at that (flat) index inside the file.
            If ``None`` and ``page=None``, read all ndimages from the file and
            return them as a batch.
        page : int
            If ``None`` return the full selected ndimage. If ``int``, read the
            page at the selected index and return it.
        kwargs : Any
            Additional kwargs are forwarded to TiffFile's ``as_array`` method.

        Returns
        -------
        ndarray : np.ndarray
            The decoded ndimage or page.
        keyNz,Can't use `page` and `key` at the same time.seriesz0Can't use `series` and `index` at the same time.r   c                 S   s   g | ]}|qS r   r   ).0xr   r   r   
<listcomp>   s     z'TifffilePlugin.read.<locals>.<listcomp>)
ValueErrorpopEllipsisnpstackiterr$   asarray)r(   r,   r   r)   ndimager   r   r   read   s     

zTifffilePlugin.read)r    c                 k   s    | j jD ]}|jf |V  qdS )a!  Yield ndimages from the TIFF.

        Parameters
        ----------
        kwargs : Any
            Additional kwargs are forwarded to the TiffPageSeries' ``as_array``
            method.

        Yields
        ------
        ndimage : np.ndarray
            A decoded ndimage.
        N)r$   r.   r8   )r(   r)   sequencer   r   r   r7      s    zTifffilePlugin.iterF)is_batch)r9   r<   r    c                K   sf   |st |dddf }|D ]}| jj|f| q| jjtkrb| j  tt	| j
 }| S dS )a_  Save a ndimage as TIFF.

        Parameters
        ----------
        ndimage : ArrayLike
            The ndimage to encode and write to the ImageResource.
        is_batch : bool
            If True, the first dimension of the given ndimage is treated as a
            batch dimension and each element will create a new series.
        kwargs : Any
            Additional kwargs are forwarded to TiffWriter's ``write`` method.

        Returns
        -------
        encoded_image : bytes
            If the ImageResource is ``"<bytes>"``, return the encoded bytes.
            Otherwise write returns None.

        Notes
        -----
        Incremental writing is supported. Subsequent calls to ``write`` will
        create new series unless ``contiguous=True`` is used, in which case the
        call to write will append to the current series.

        N)r5   r8   r$   write_requestZ	_uri_typer   closer   r   r'   getvalue)r(   r9   r<   r)   imagefiler   r   r   r=      s    
zTifffilePlugin.writeT)r,   r   exclude_applied)r,   r   rC   r    c          	   
   C   sJ  |t k	r$|dk	r$| jj| j| }nF|t k	rH|dkrH| jj| jd }n"|t krf|dk	rf| jj| }nd}i }|dkr| jj|d< tjjD ]h}t| jd| }||d| < |rt	| j|d rt| j|d }t
|tr||d  q|| qnP|j}|dd |jD  ||j|j|jd|j|j|jdt|t| |S )	as  Format-Specific TIFF metadata.

        The metadata returned depends on the value of both ``index`` and
        ``page``. ``index`` selects a series and ``page`` allows selecting a
        single page from the selected series. If ``index=Ellipsis``, ``page`` is
        understood as a flat index, i.e., the selection ignores individual
        series inside the file. If ``index=Ellipsis`` and ``page=None`` then
        global (file-level) metadata is returned.

        Parameters
        ----------
        index : int
            Select the series of which to extract metadata from. If Ellipsis, treat
            page as a flat index into the file's pages.
        page : int
            If not None, select the page of which to extract metadata from. If
            None, read series-level metadata or, if ``index=...`` global,
            file-level metadata.
        exclude_applied : bool
            For API compatibility. Currently ignored.

        Returns
        -------
        metadata : dict
            A dictionary with information regarding the tiff flavor (file-level)
            or tiff tags (page-level).
        Nr   	byteorderis_	_metadatac                 S   s   i | ]}|j |jqS r   )namer   )r/   tagr   r   r   
<dictcomp>8  s      z+TifffilePlugin.metadata.<locals>.<dictcomp>)Zplanar_configurationcompression	predictorZorientationdescription1descriptionsoftware)r4   r$   r.   pagesrD   r&   ZTIFFZ
FILE_FLAGSgetattrhasattr
isinstancetupleupdateZkeyframer   ZplanarconfigrJ   rK   rL   rM   rN   r   r   )	r(   r,   r   rC   targetr   flag
flag_valueZflavor_metadatar   r   r   r      sD    
	zTifffilePlugin.metadatac                C   s   |pd}|pd}|t kr&| jj| }n| jj| j| }|t krx|dkrxt| jj}t|f|j|jdt|d d}nt|j|jdt|d d}|S )a  Standardized metadata.

        The properties returned depend on the value of both ``index`` and
        ``page``. ``index`` selects a series and ``page`` allows selecting a
        single page from the selected series. If ``index=Ellipsis``, ``page`` is
        understood as a flat index, i.e., the selection ignores individual
        series inside the file. If ``index=Ellipsis`` and ``page=None`` then
        global (file-level) properties is returned.

        Parameters
        ----------
        index : int
            If ``int``, select the ndimage (series) located at that index inside
            the file. If ``Ellipsis`` and ``page`` is ``int`` extract the
            properties of the page located at that (flat) index inside the file.
            If ``Ellipsis`` and ``page=None``, return the properties for the
            batch of all ndimages in the file.
        page : int
            If ``None`` return the properties of the full ndimage. If ``int``,
            return the properties of the page at the selected index only.

        Returns
        -------
        image_properties : ImageProperties
            The standardized metadata (properties) of the selected ndimage or series.

        r   NTr   )shapedtyper<   spacingF)	r4   r$   rO   r.   lenr   rX   rY   r   )r(   r,   r   Zpage_idxZtarget_pageZn_seriespropsr   r   r   
propertiesJ  s(    


zTifffilePlugin.propertiesc                    s"   | j d k	r| j   t   d S )N)r$   r?   r"   )r(   r*   r   r   r?     s    

zTifffilePlugin.close.c                 k   s:   |t kr| jj}n| jj| }|D ]}|jf |V  q"dS )a7  Yield pages from a TIFF file.

        This generator walks over the flat index of the pages inside an
        ImageResource and yields them in order.

        Parameters
        ----------
        index : int
            The index of the series to yield pages from. If Ellipsis, walk over
            the file's flat index (and ignore individual series).
        kwargs : Any
            Additional kwargs are passed to TiffPage's ``as_array`` method.

        Yields
        ------
        page : np.ndarray
            A page stored inside the TIFF file.

        N)r4   r$   rO   r.   r8   )r(   r,   r)   rO   r   r   r   r   
iter_pages  s
    
zTifffilePlugin.iter_pages).)__name__
__module____qualname____doc__r
   r#   intr5   Zndarrayr:   r7   r   boolr   bytesr=   r4   r   strr   r   r   r]   r?   r^   __classcell__r   r   r*   r   r   l   s,   6 )    
O6
r   )rb   ior   typingr   r   r   r   r   r   Znumpyr5   r&   Zcore.requestr   r	   r
   Zcore.v3_plugin_apir   r   r   r   r   r   r   r   r   r   <module>   s   -