
    1-PhT>                         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dS )zEData structures to hold collections of images, with optional caching.    N)glob)Sequence)copy)Image)TiffFile)
MultiImageImageCollectionconcatenate_imagesimread_collection_wrapperc                     d | D             }	 t          j        |          }n# t          $ r t          d          w xY w|S )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.
    c                 6    g | ]}|t           j        d f         S ).)npnewaxis).0images     U/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/skimage/io/collection.py
<listcomp>z&concatenate_images.<locals>.<listcomp>3   s#    999U%
C(999    zImage dimensions must agree.)r   concatenate
ValueError)ic
all_images	array_cats      r   r
   r
      s]    8 :9b999J9N:..		 9 9 978889s   # =c                 D    d t          j        d|           D             }|S )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']
    c                 X    g | ]'}|                                 rt          |          n|(S  )isdigitint)r   cs     r   r   z$alphanumeric_key.<locals>.<listcomp>Q   s/    GGG!199;;	%QAGGGr   z([0-9]+))resplit)sks     r   alphanumeric_keyr$   ;   s)    , 	HGrx
A/F/FGGGAHr   c                     t          | t                    ot          j        | v }t          | t                     }t          | t                    }t          d | D                       }|p|o|o|}|S )zlHelping function. Returns True if pattern contains a tuple, list, or a
    string separated with os.pathsep.c              3   @   K   | ]}t          |t                    V  d S N)
isinstancestr)r   pats     r   	<genexpr>z#_is_multipattern.<locals>.<genexpr>\   s,      DDsjc**DDDDDDr   )r(   r)   ospathsepr   all)input_patternhas_str_ospathsepnot_a_stringhas_iterablehas_stringsis_multipatterns         r   _is_multipatternr5   U   s     #=#66V2:;V!-555LmX66LDDmDDDDDK' 55+  r   c                   z    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dS )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
    TNc                    g | _         t          |          rt          |t                    r|                    t
          j                  }|D ])}| j                             t          |                     *t          | j         t                    | _         nt          |t                    rH| j                             t          |                     t          | j         t                    | _         n;t          |t                    r|t          |          | _         nt          d          |'ddlm} || _        |                                 | _        n'|| _        t'          | j                   | _        d| _        |rd}n| j        }|| _        d| _        || _        t1          j        |t4                    | _        dS )z'Load and manage a collection of images.)keyNzInvalid pattern as input.   imreaddtype)_filesr5   r(   r)   r!   r,   r-   extendr   sortedr$   r   list	TypeError_ior;   	load_func_find_images
_numframeslen_frame_index_conserve_memory_cachedload_func_kwargsr   emptyobjectdata)selfload_patternconserve_memoryrD   rK   patternr;   memory_slotss           r   __init__zImageCollection.__init__   s    L)) 	9,,, >+11"*==' 2 2""4==1111 2BCCCDKKc** 	9KtL11222 2BCCCDKKh// 	9I4I|,,DKK7888#######DN"//11DOO&DN!$+..DO $D 	+LL?L / 0H\888			r   c                     | j         S r'   r>   rO   s    r   fileszImageCollection.files   s
    {r   c                     | j         S r'   )rI   rW   s    r   rQ   zImageCollection.conserve_memory   s    $$r   c           	         g }| j         D ]D                                                    d          rht          d          5 }t	          |          }|fdt          t          |j                            D             z  }d d d            n# 1 swxY w Y   	 t          j                  }|	                    d           n# t          $ r Y w xY wd}	 	 |	                    |           n# t          $ r Y n!w xY w|                    |f           |dz  }Dt          |d          r |j        r|j                                         F|| _        t          |          S )N)z.tiffz.tifrbc                     g | ]}|fS r   r   )r   ifnames     r   r   z0ImageCollection._find_images.<locals>.<listcomp>  s    HHHQuajHHHr   r   Tr9   fp)r>   lowerendswithopenr   rangerG   pagesr   seekOSErrorEOFErrorappendhasattrr_   closerH   )rO   indexfimgimr]   r^   s         @r   rE   zImageCollection._find_images   s   [ 	" 	"E{{}}%%&788 "%&& I!"1++CHHHH%CI2G2GHHHHEI I I I I I I I I I I I I I IE**BGGAJJJJ   H



#   LL%,,,FA 2t$$ " "EKKMMM!5zzs7   A BB	B	)C
CCC22
C?>C?c                     t          |d          r|                                }t          |t          t          f          st          d          t          |t                    r                      |          }|t           j                  z  } j	        r| j
        k    s j        |          j        } j        rr j        |         \  }}|||d<   	   j        |fi | j        |<   nd# t
          $ r6}dt          |          v r|d=   j        |fi | j        |<   n Y d}~n)d}~ww xY w  j         j        |         fi | j        |<   | _
         j        |         S t!           j                  |         }t%                     } j        r' fd|D             |_         fd|D             |_        n fd|D             |_        t          |          |_         j	        rh j
        |v r>|                     j
                  |_
        t+          j         j                  |_        n3t+          j        d	t.          
          |_        n j        |         |_        |S )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'c                 6    g | ]}j         |         d          S )r   rH   r   r]   rO   s     r   r   z/ImageCollection.__getitem__.<locals>.<listcomp>R  s&     G G GQ!21!5a!8 G G Gr   c                 *    g | ]}j         |         S r   rs   rt   s     r   r   z/ImageCollection.__getitem__.<locals>.<listcomp>S  s!    &J&J&Jt'8';&J&J&Jr   c                 *    g | ]}j         |         S r   rV   rt   s     r   r   z/ImageCollection.__getitem__.<locals>.<listcomp>U  s     > > >AQ > > >r   r9   r<   )ri   rp   r(   r   slicerB   _check_imgnumrG   rN   rQ   rJ   rK   rH   rD   r)   rX   rc   rF   r   r>   rk   r   rL   rM   )	rO   nidxkwargsr^   rq   efidxnew_ics	   `        r   __getitem__zImageCollection.__getitem__  s   " 1k"" 	A!c5\** 	KIJJJa 0	""1%%Ac$)nn$C$ !dl):):	#@V.$ M%)%6q%9NE7*,3y)")7)H)H)H)H	#$ " " "Bc!ffLL &y 1-;T^E-L-LV-L-LDIcNN! +NNNN" &4T^DJqM%L%LV%L%LDIcN 9S>! ))!,D$ZZF  ? G G G G$ G G G&J&J&J&JT&J&J&J## > > > > > > > #D		F# .<4''%)ZZ%=%=FN"$'$)"4"4FKK"$(1F";";";FKK"ioMs   C/ /
D/9,D**D/c                 h    | j         }| |cxk    r|k     r	n n||z  }nt          d| d          |S )z+Check that the given image number is valid.zThere are only z images in the collection)rF   
IndexError)rO   ry   nums      r   rx   zImageCollection._check_imgnumc  sN    o41????s?????CAAMsMMMNNNr   c              #   \   K   t          t          |                     D ]}| |         V  dS )zIterate over the images.N)rc   rG   )rO   r]   s     r   __iter__zImageCollection.__iter__l  s<      s4yy!! 	 	Aq'MMMM	 	r   c                     | j         S )zNumber of images in collection.)rF   rW   s    r   __len__zImageCollection.__len__q  s
    r   c                 *    t          | j                  S r'   )r)   rX   rW   s    r   __str__zImageCollection.__str__u  s    4:r   c                 B    t          j        | j                  | _        dS )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_likerN   )rO   ry   s     r   reloadzImageCollection.reloadx  s     M$),,			r   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
   rW   s    r   r   zImageCollection.concatenate  s    $ "$'''r   TNr'   )__name__
__module____qualname____doc__rT   propertyrX   rQ   rE   r   rx   r   r   r   r   r   r   r   r   r	   r	   d   s        i iX =A&9 &9 &9 &9P   X % % X%  4G G GR    
    
- 
- 
- 
-( ( ( ( (r   r	   c                      d fd	}|S )NTc                 (    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.

        )rQ   rD   )r	   )rP   rQ   r;   s     r   imread_collectionz4imread_collection_wrapper.<locals>.imread_collection  s#    ( /V
 
 
 	
r   )Tr   )r;   r   s   ` r   r   r     s)    
 
 
 
 
 
0 r   c                   :     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)
    TNc                 \    ddl m} || _         t                      j        ||fd|i| dS )zLoad a multi-img.r9   r:   rD   N)rC   r;   	_filenamesuperrT   )rO   filenamerQ   r=   imread_kwargsr;   	__class__s         r   rT   zMultiImage.__init__  sH    !?VVfVVVVVVr   c                     | j         S r'   )r   rW   s    r   r   zMultiImage.filename  s
    ~r   r   )r   r   r   r   rT   r   r   __classcell__)r   s   @r   r   r     si        , ,\W W W W W W   X    r   r   )r   r,   r   r    collections.abcr   r   numpyr   PILr   tifffiler   __all__r
   r$   r5   r	   r   r   r   r   r   <module>r      s6   K K 				       				 $ $ $ $ $ $                        ! ! !H  4  r( r( r( r( r( r( r( r(j	  88 8 8 8 8 8 8 8 8 8r   