
    9iT>                         S r SSKrSSKJr  SSKrSSKJr  SSKJr  SSKrSSK	J
r
  SSKJr  / SQrS	 rS
 rS r " S S5      rS r " S S\5      rg)zEData structures to hold collections of images, with optional caching.    N)glob)Sequence)copy)Image)TiffFile)
MultiImageImageCollectionconcatenate_imagesimread_collection_wrapperc                     U  Vs/ s H  o[         R                  S4   PM     nn [         R                  " U5      nU$ s  snf ! [         a    [        S5      ef = f)a$  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       U/var/www/html/land-doc-ocr/venv/lib/python3.13/site-packages/skimage/io/collection.pyr
   r
      s`    8 799bU

C(bJ99NN:.	  :  97889s   >A Ac                     [         R                  " SU 5       Vs/ s H$  oR                  5       (       a  [        U5      OUPM&     nnU$ s  snf )a  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   ;   sA    , 02xx
A/FG/F!99;;QA	%/FAGH 	Hs   +A	c                    [        U [        5      =(       a    [        R                  U ;   n[        U [        5      (       + n[        U [        5      n[        S U  5       5      nU=(       d    U=(       a    U=(       a    UnU$ )zhHelping function. Returns True if pattern contains a tuple, list, or a
string separated with os.pathsep.c              3   B   #    U  H  n[        U[        5      v   M     g 7fN)
isinstancestr).0pats     r   	<genexpr>#_is_multipattern.<locals>.<genexpr>\   s     Dmsjc**ms   )r"   r#   ospathsepr   all)input_patternhas_str_ospathsepnot_a_stringhas_iterablehas_stringsis_multipatterns         r   _is_multipatternr1   U   sl     #=#6V2::;V!-55LmX6LDmDDK' 55+      c                   x    \ rS rSrSr SS jr\S 5       r\S 5       rS r	S r
S	 rS
 rS rS rSS jrS rSrg)r	   d   a   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                 l   / U l         [        U5      (       a  [        U[        5      (       a  UR	                  [
        R                  5      nU H'  nU R                   R                  [        U5      5        M)     [        U R                   [        S9U l         O[        U[        5      (       aB  U R                   R                  [        U5      5        [        U R                   [        S9U l         O4[        U[        5      (       a  Ub  [        U5      U l         O[        S5      eUc"  SSKJn  X`l        U R#                  5       U l        O'X0l        ['        U R                   5      U l        SU l        U(       a  SnOU R$                  nX l        SU l        X@l        [0        R2                  " U[4        S9U l        g)z'Load and manage a collection of images.)keyNzInvalid pattern as input.   imreaddtype)_filesr1   r"   r#   r   r(   r)   extendr   sortedr   r   list	TypeError_ior9   	load_func_find_images
_numframeslen_frame_index_conserve_memory_cachedload_func_kwargsr   emptyobjectdata)selfload_patternconserve_memoryrB   rI   patternr9   memory_slotss           r   __init__ImageCollection.__init__   s<    L)),,,+11"**='""4=1 ( 2BCDKc**KKtL12 2BCDKh//I4I|,DK788##N"//1DO&N!$++.DO $DL??L / 0HH\8	r2   c                     U R                   $ r!   )r<   rM   s    r   filesImageCollection.files   s    {{r2   c                     U R                   $ r!   )rG   rU   s    r   rO   ImageCollection.conserve_memory   s    $$$r2   c                    / nU R                    H  nUR                  5       R                  S5      (       aU  [        US5       n[	        U5      nU[        [        UR                  5      5       Vs/ s H  oRU4PM     sn-  nS S S 5        M|   [        R                  " U5      nUR                  S5        Sn  UR                  U5        UR                  X%45        US-  nM+     Xl        [        U5      $ s  snf ! , (       d  f       M  = f! [         a     GM
  f = f! [         a     Of = f[        US5      (       d  GM2  UR                  (       d  GMF  UR                  R                  5         GMc  )N)z.tiffz.tifrbr   r7   fp)r<   lowerendswithopenr   rangerE   pagesr   seekOSErrorEOFErrorappendhasattrr\   closerF   )rM   indexfnamefimgiims          r   rC   ImageCollection._find_images   s5   [[E{{}%%&788%&!"1+C%CII2GH2GQaj2GHHE '&E*BGGAJ 
 LL%,FA  !* "5z% I '&   $  2t$$EEKKMsB   -C9/C4
<C9'D7D4C99
D	
DD
D*)D*c                    [        US5      (       a  UR                  5       n[        U[        [        45      (       d  [        S5      e[        U[        5      (       a  U R                  U5      nU[        U R                  5      -  nU R                  (       a  XR                  :w  d  U R                  U   c  U R                  nU R                  (       a:  U R                  U   u  pEUb  XSS'    U R                  " U40 UD6U R                  U'   O-U R                  " U R                  U   40 UD6U R                  U'   Xl
        U R                  U   $ [!        U R"                  5      U   n[%        U 5      nU R                  (       aL  U V	s/ s H  oR                  U	   S   PM     sn	Ul        U V	s/ s H  oR                  U	   PM     sn	Ul        O$U V	s/ s H  oR&                  U	   PM     sn	Ul        [        U5      Ul        U R                  (       ax  U R                  U;   aG  UR)                  U R                  5      Ul
        [*        R$                  " U R                  5      Ul        U$ [*        R,                  " S[.        S9Ul         U$ U R                  U   Ul        U$ ! [
         a>  nS[        U5      ;   a)  US	 U R                  " U40 UD6U R                  U'    SnAGNe SnAff = fs  sn	f s  sn	f s  sn	f )	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   r7   r:   )rf   rp   r"   r   slicer@   _check_imgnumrE   rL   rO   rH   rI   rF   rB   r#   rV   r`   rD   r   r<   rh   r   rJ   rK   )
rM   nidxkwargsri   rq   efidxnew_icrl   s
             r   __getitem__ImageCollection.__getitem__  sk   " 1k""A!c5\**IJJa""1%Ac$))n$C$$ll):		#@V..$$%)%6%6q%9NE*,3y)")-)H)H		# &*^^DJJqM%LV%LDIIcN 99S>! )!,D$ZF  BF G$Q!2!21!5a!8$ GEI&JT'8'8';T&J#9= >AQ > #D	F##<<4'%)ZZ%=FN"$''$))"4FK
 M #%((1F";FK M #iioMG % "Bc!fL &y 1-1^^E-LV-LDIIcN!"( !H&J >s0   , J" K-.K2K7"
K*,2K%$K%%K*c                 f    U R                   nU* Us=::  a  U:  a	  O  OX-  nU$ [        SU S35      e)z+Check that the given image number is valid.zThere are only z images in the collection)rD   
IndexError)rM   rt   nums      r   rs   ImageCollection._check_imgnumc  s=    oo41?s?A  se3LMNNr2   c              #   N   #    [        [        U 5      5       H	  nX   v   M     g7f)zIterate over the images.N)r`   rE   )rM   rl   s     r   __iter__ImageCollection.__iter__l  s     s4y!A'M "s   #%c                     U R                   $ )zNumber of images in collection.)rD   rU   s    r   __len__ImageCollection.__len__q  s    r2   c                 ,    [        U R                  5      $ r!   )r#   rV   rU   s    r   __str__ImageCollection.__str__u  s    4::r2   c                 N    [         R                  " U R                  5      U l        g)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_likerL   )rM   rt   s     r   reloadImageCollection.reloadx  s     MM$)),	r2   c                     [        U 5      $ )aA  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
   rU   s    r   r   ImageCollection.concatenate  s    $ "$''r2   )rH   rG   r<   rF   rD   rL   rB   rI   TNr!   )__name__
__module____qualname____firstlineno____doc__rR   propertyrV   rO   rC   rz   rs   r   r   r   r   r   __static_attributes__ r2   r   r	   r	   d   sg    iX =A&9P   % %4GR

-(r2   r	   c                    ^  SU 4S jjnU$ )Nc                    > [        XTS9$ )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.

)rO   rB   )r	   )rN   rO   r9   s     r   imread_collection4imread_collection_wrapper.<locals>.imread_collection  s    ( V
 	
r2   )Tr   )r9   r   s   ` r   r   r     s    
0 r2   c                   @   ^  \ rS rSrSrSU 4S jjr\S 5       rSrU =r	$ )r   i  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                 D   > SSK Jn  Xl        [        TU ]  " X4SU0UD6  g)zLoad a multi-img.r7   r8   rB   N)rA   r9   	_filenamesuperrR   )rM   filenamerO   r;   imread_kwargsr9   	__class__s         r   rR   MultiImage.__init__  s"    !VfVVr2   c                     U R                   $ r!   r   rU   s    r   r   MultiImage.filename  s    ~~r2   r   r   )
r   r   r   r   r   rR   r   r   r   __classcell__)r   s   @r   r   r     s#    ,\W  r2   r   )r   r(   r   r   collections.abcr   r   numpyr   PILr   tifffiler   __all__r
   r   r1   r	   r   r   r   r2   r   <module>r      sU    K 	  	 $    !H4r( r(j	88 8r2   