
    |hT>                         d Z ddlZddlmZ ddlZddlmZ ddlmZ ddlZddl	m
Z
 ddlmZ g dZd	 Zd
 Zd Z G d d      Zd Z G d de      Zy)zEData structures to hold collections of images, with optional caching.    N)glob)Sequence)copy)Image)TiffFile)
MultiImageImageCollectionconcatenate_imagesimread_collection_wrapperc                     | D cg c]  }|t         j                  df    }}	 t        j                  |      }|S c c}w # t        $ r t        d      w xY w)ax  Concatenate all images in the image collection into an array.

    Parameters
    ----------
    ic : an iterable of images
        The images to be concatenated.

    Returns
    -------
    array_cat : ndarray
        An array having one more dimension than the images in `ic`.

    See Also
    --------
    ImageCollection.concatenate
    MultiImage.concatenate

    Raises
    ------
    ValueError
        If images in `ic` don't have identical shapes.

    Notes
    -----
    ``concatenate_images`` receives any iterable object containing images,
    including ImageCollection and MultiImage, and returns a NumPy array.
    .zImage dimensions must agree.)npnewaxisconcatenate
ValueError)icimage
all_images	array_cats       T/var/www/html/test/engine/venv/lib/python3.12/site-packages/skimage/io/collection.pyr
   r
      sa    8 799U%

C(9J99NN:.	  :  97889s   ;A   Ac                     t        j                  d|       D cg c]  }|j                         rt        |      n|! }}|S c c}w )aA  Convert string to list of strings and ints that gives intuitive sorting.

    Parameters
    ----------
    s : string

    Returns
    -------
    k : a list of strings and ints

    Examples
    --------
    >>> alphanumeric_key('z23a')
    ['z', 23, 'a']
    >>> filenames = ['f9.10.png', 'e10.png', 'f9.9.png', 'f10.10.png',
    ...              'f10.9.png']
    >>> sorted(filenames)
    ['e10.png', 'f10.10.png', 'f10.9.png', 'f9.10.png', 'f9.9.png']
    >>> sorted(filenames, key=alphanumeric_key)
    ['e10.png', 'f9.9.png', 'f9.10.png', 'f10.9.png', 'f10.10.png']
    z([0-9]+))resplitisdigitint)scks      r   alphanumeric_keyr   ;   s>    , 02xx
A/FG!199;QA	%GAGH 	Hs   $Ac                     t        | t              xr t        j                  | v }t        | t               }t        | t              }t        d | D              }|xs
 |xr |xr |}|S )zlHelping function. Returns True if pattern contains a tuple, list, or a
    string separated with os.pathsep.c              3   <   K   | ]  }t        |t                y wN)
isinstancestr).0pats     r   	<genexpr>z#_is_multipattern.<locals>.<genexpr>\   s     Dsjc*Ds   )r"   r#   ospathsepr   all)input_patternhas_str_ospathsepnot_a_stringhas_iterablehas_stringsis_multipatterns         r   _is_multipatternr0   U   sl     #=#6V2::;V!-55LmX6LDmDDK' 55+      c                   l    e Zd ZdZ	 ddZed        Zed        Zd Zd Z	d Z
d	 Zd
 Zd ZddZd Zy)r	   aH  Load and manage a collection of image files.

    Parameters
    ----------
    load_pattern : str or list of str
        Pattern string or list of strings to load. The filename path can be
        absolute or relative.
    conserve_memory : bool, optional
        If True, :class:`skimage.io.ImageCollection` does not keep more than one in
        memory at a specific time. Otherwise, images will be cached once they are loaded.

    Other parameters
    ----------------
    load_func : callable
        ``imread`` by default. See Notes below.
    **load_func_kwargs : dict
        Any other keyword arguments are passed to `load_func`.

    Attributes
    ----------
    files : list of str
        If a pattern string is given for `load_pattern`, this attribute
        stores the expanded file list. Otherwise, this is equal to
        `load_pattern`.

    Notes
    -----
    Note that files are always returned in alphanumerical order. Also note that slicing
    returns a new :class:`skimage.io.ImageCollection`, *not* a view into the data.

    ImageCollection image loading can be customized through
    `load_func`. For an ImageCollection ``ic``, ``ic[5]`` calls
    ``load_func(load_pattern[5])`` to load that image.

    For example, here is an ImageCollection that, for each video provided,
    loads every second frame::

      import imageio.v3 as iio3
      import itertools

      def vidread_step(f, step):
          vid = iio3.imiter(f)
          return list(itertools.islice(vid, None, None, step)

      video_file = 'no_time_for_that_tiny.gif'
      ic = ImageCollection(video_file, load_func=vidread_step, step=2)

      ic  # is an ImageCollection object of length 1 because 1 video is provided

      x = ic[0]
      x[5]  # the 10th frame of the first video

    Alternatively, if `load_func` is provided and `load_pattern` is a
    sequence, an :class:`skimage.io.ImageCollection` of corresponding length will
    be created, and the individual images will be loaded by calling `load_func` with the
    matching element of the `load_pattern` as its first argument. In this
    case, the elements of the sequence do not need to be names of existing
    files (or strings at all). For example, to create an :class:`skimage.io.ImageCollection`
    containing 500 images from a video::

      class FrameReader:
          def __init__ (self, f):
              self.f = f
          def __call__ (self, index):
              return iio3.imread(self.f, index=index)

      ic = ImageCollection(range(500), load_func=FrameReader('movie.mp4'))

      ic  # is an ImageCollection object of length 500

    Another use of `load_func` would be to convert all images to ``uint8``::

      def imread_convert(f):
          return imread(f).astype(np.uint8)

      ic = ImageCollection('/tmp/*.png', load_func=imread_convert)

    Examples
    --------
    >>> import imageio.v3 as iio3
    >>> import skimage.io as io

    # Where your images are located
    >>> data_dir = os.path.join(os.path.dirname(__file__), '../data')

    >>> coll = io.ImageCollection(data_dir + '/chess*.png')
    >>> len(coll)
    2
    >>> coll[0].shape
    (200, 200)

    >>> image_col = io.ImageCollection([f'{data_dir}/*.png', '{data_dir}/*.jpg'])

    >>> class MultiReader:
    ...     def __init__ (self, f):
    ...         self.f = f
    ...     def __call__ (self, index):
    ...         return iio3.imread(self.f, index=index)
    ...
    >>> filename = data_dir + '/no_time_for_that_tiny.gif'
    >>> ic = io.ImageCollection(range(24), load_func=MultiReader(filename))
    >>> len(image_col)
    23
    >>> isinstance(ic[0], np.ndarray)
    True
    Nc                 J   g | _         t        |      r{t        |t              r|j	                  t
        j                        }|D ]&  }| j                   j                  t        |             ( t        | j                   t              | _         nt        |t              rE| j                   j                  t        |             t        | j                   t              | _         n.t        |t              r|t        |      | _         nt        d      |#ddlm} || _        | j#                         | _        n(|| _        t'        | j                         | _        d| _        |rd}n| j$                  }|| _        d| _        || _        t1        j2                  |t4              | _        y)z'Load and manage a collection of images.)keyNzInvalid pattern as input.   imreaddtype)_filesr0   r"   r#   r   r'   r(   extendr   sortedr   r   list	TypeError_ior7   	load_func_find_images
_numframeslen_frame_index_conserve_memory_cachedload_func_kwargsr   emptyobjectdata)selfload_patternconserve_memoryr@   rG   patternr7   memory_slotss           r   __init__zImageCollection.__init__   s=    L),,+11"**=' 2""4=12 2BCDKc*KKtL12 2BCDKh/I4I|,DK788##DN"//1DO&DN!$++.DO $DL??L / 0HH\8	r1   c                     | j                   S r!   )r:   rK   s    r   fileszImageCollection.files   s    {{r1   c                     | j                   S r!   )rE   rR   s    r   rM   zImageCollection.conserve_memory   s    $$$r1   c                    g }| j                   D ]  }|j                         j                  d      rRt        |d      5 }t	        |      }|t        t        |j                              D cg c]  }||f c}z  }d d d        t	 t        j                  |      }|j                  d       d}	 	 |j                  |       |j                  ||f       |dz  }+ || _        t        |      S c c}w # 1 sw Y   xY w# t        $ r Y w xY w# t        $ r Y nw xY wt        |d      s|j                  s'|j                  j                          C)N)z.tiffz.tifrbr   r5   fp)r:   lowerendswithopenr   rangerC   pagesr   seekOSErrorEOFErrorappendhasattrrW   closerD   )rK   indexfnamefimgiims          r   rA   zImageCollection._find_images   s@   [[ 	"E{{}%%&78%& I!"1+C%CII2GHQuajHHEI IE*BGGAJ 
 LL%,FA 	"* "5z% II I   $  2t$EEKKMsA   -C0*C+
5C0&C<.D+C00C9	<	DD	DDc                    t        |d      r|j                         }t        |t        t        f      st        d      t        |t              r| j                  |      }|t        | j                        z  }| j                  r|| j                  k7  s| j                  |   | j                  }| j                  r;| j                  |   \  }}|||d<   	  | j                  |fi || j                  |<   n- | j                  | j                  |   fi || j                  |<   || _
        | j                  |   S t!        | j"                        |   }t%        |       }| j                  rH|D 	cg c]  }	| j                  |	   d    c}	|_        |D 	cg c]  }	| j                  |	    c}	|_        n"|D 	cg c]  }	| j&                  |	    c}	|_        t        |      |_        | j                  rv| j                  |v rF|j)                  | j                        |_
        t+        j$                  | j                        |_        |S t+        j,                  dt.              |_        |S | j                  |   |_        |S # t
        $ r=}dt        |      v r$|d=  | j                  |fi || j                  |<   n Y d}~d}~ww xY wc c}	w c c}	w c c}	w )	a  Return selected image(s) in the collection.

        Loading is done on demand.

        Parameters
        ----------
        n : int or slice
            The image number to be returned, or a slice selecting the images
            and ordering to be returned in a new ImageCollection.

        Returns
        -------
        img : ndarray or :class:`skimage.io.ImageCollection`
            The `n`-th image in the collection, or a new ImageCollection with
            the selected images.
        	__index__z+slicing must be with an int or slice objectNimg_numz%unexpected keyword argument 'img_num'r   r5   r8   )ra   rj   r"   r   slicer>   _check_imgnumrC   rJ   rM   rF   rG   rD   r@   r#   rS   r[   rB   r   r:   rc   r   rH   rI   )
rK   nidxkwargsrd   rk   efidxnew_icrg   s
             r   __getitem__zImageCollection.__getitem__  so   " 1k"A!c5\*IJJa""1%Ac$))n$C$$dll):		#@V..$$%)%6%6q%9NE7*,3y)")7)H)H		# &4T^^DJJqM%LV%LDIIcN 99S>! )!,D$ZF  BF GQ!2!21!5a!8 GEI&Jt'8'8';&J#9= >AQ > #D	F##<<4'%)ZZ%=FN"$''$))"4FK
 M #%((1F";FK M #iioMG % "Bc!fL &y 1-;T^^E-LV-LDIIcN! +"( !H&J >s*    I8 *KK2K8	J>2J99J>c                 d    | j                   }| |cxk  r|k  r
n n||z  }|S t        d| d      )z+Check that the given image number is valid.zThere are only z images in the collection)rB   
IndexError)rK   rn   nums      r   rm   zImageCollection._check_imgnumc  s?    oo41?s?CA  se3LMNNr1   c              #   L   K   t        t        |             D ]	  }| |     yw)zIterate over the images.N)r[   rC   )rK   rg   s     r   __iter__zImageCollection.__iter__l  s'     s4y! 	Aq'M	s   "$c                     | j                   S )zNumber of images in collection.)rB   rR   s    r   __len__zImageCollection.__len__q  s    r1   c                 ,    t        | j                        S r!   )r#   rS   rR   s    r   __str__zImageCollection.__str__u  s    4::r1   c                 L    t        j                  | j                        | _        y)zClear the image cache.

        Parameters
        ----------
        n : None or int
            Clear the cache for this image only. By default, the
            entire cache is erased.

        N)r   
empty_likerJ   )rK   rn   s     r   reloadzImageCollection.reloadx  s     MM$)),	r1   c                     t        |       S )a  Concatenate all images in the collection into an array.

        Returns
        -------
        ar : np.ndarray
            An array having one more dimension than the images in `self`.

        See Also
        --------
        skimage.io.concatenate_images

        Raises
        ------
        ValueError
            If images in the :class:`skimage.io.ImageCollection` do not have identical
            shapes.
        )r
   rR   s    r   r   zImageCollection.concatenate  s    $ "$''r1   TNr!   )__name__
__module____qualname____doc__rP   propertyrS   rM   rA   rt   rm   ry   r{   r}   r   r    r1   r   r	   r	   d   sg    iX =A&9P   % %4GR

-(r1   r	   c                      d fd	}|S )Nc                      t        | |      S )a  Return an `ImageCollection` from files matching the given pattern.

        Note that files are always stored in alphabetical order. Also note that
        slicing returns a new ImageCollection, *not* a view into the data.

        See `skimage.io.ImageCollection` for details.

        Parameters
        ----------
        load_pattern : str or list
            Pattern glob or filenames to load. The path can be absolute or
            relative.  Multiple patterns should be separated by a colon,
            e.g. ``/tmp/work/*.png:/tmp/other/*.jpg``.  Also see
            implementation notes below.
        conserve_memory : bool, optional
            If True, never keep more than one in memory at a specific
            time.  Otherwise, images will be cached once they are loaded.

        )rM   r@   )r	   )rL   rM   r7   s     r   imread_collectionz4imread_collection_wrapper.<locals>.imread_collection  s    ( /V
 	
r1   )Tr   )r7   r   s   ` r   r   r     s    
0 r1   c                   4     e Zd ZdZd fd	Zed        Z xZS )r   a   A class containing all frames from multi-frame TIFF images.

    Parameters
    ----------
    load_pattern : str or list of str
        Pattern glob or filenames to load. The path can be absolute or
        relative.
    conserve_memory : bool, optional
        Whether to conserve memory by only caching the frames of a single
        image. Default is True.

    Notes
    -----
    `MultiImage` returns a list of image-data arrays. In this
    regard, it is very similar to `ImageCollection`, but the two differ in
    their treatment of multi-frame images.

    For a TIFF image containing N frames of size WxH, `MultiImage` stores
    all frames of that image as a single element of shape `(N, W, H)` in the
    list. `ImageCollection` instead creates N elements of shape `(W, H)`.

    For an animated GIF image, `MultiImage` reads only the first frame, while
    `ImageCollection` reads all frames by default.

    Examples
    --------
    # Where your images are located
    >>> data_dir = os.path.join(os.path.dirname(__file__), '../data')

    >>> multipage_tiff = data_dir + '/multipage.tif'
    >>> multi_img = MultiImage(multipage_tiff)
    >>> len(multi_img)  # multi_img contains one element
    1
    >>> multi_img[0].shape  # this element is a two-frame image of shape:
    (2, 15, 10)

    >>> image_col = ImageCollection(multipage_tiff)
    >>> len(image_col)  # image_col contains two elements
    2
    >>> for frame in image_col:
    ...     print(frame.shape)  # each element is a frame of shape (15, 10)
    ...
    (15, 10)
    (15, 10)
    c                 F    ddl m} || _        t        |   ||fd|i| y)zLoad a multi-img.r5   r6   r@   N)r?   r7   	_filenamesuperrP   )rK   filenamerM   r9   imread_kwargsr7   	__class__s         r   rP   zMultiImage.__init__  s&    !?VfVVr1   c                     | j                   S r!   )r   rR   s    r   r   zMultiImage.filename  s    ~~r1   r   )r   r   r   r   rP   r   r   __classcell__)r   s   @r   r   r     s#    ,\W  r1   r   )r   r'   r   r   collections.abcr   r   numpyr   PILr   tifffiler   __all__r
   r   r0   r	   r   r   r   r1   r   <module>r      sU    K 	  	 $    !H4r( r(j	88 8r1   