Ë
    !täit(  ã                  ód   — d dl mZ d dlZddlmZmZ dZg d¢Zg d¢Z G d„ d	«      Z	 G d
„ d«      Z
y)é    )ÚannotationsNé   )ÚImageÚ_imagingmorphi   )	é   é   r   é   é   r   é   é   é   )	r   r   r   r   r
   r   r   r	   r   c                  óf   — e Zd ZdZ	 d
	 	 	 	 	 dd„Zdd„Zdd„Zdd„Zdd„Z	 	 	 	 	 	 	 	 dd„Z	dd	„Z
y)Ú
LutBuilderaT  A class for building a MorphLut from a descriptive language

    The input patterns is a list of a strings sequences like these::

        4:(...
           .1.
           111)->1

    (whitespaces including linebreaks are ignored). The option 4
    describes a series of symmetry operations (in this case a
    4-rotation), the pattern is described by:

    - . or X - Ignore
    - 1 - Pixel is on
    - 0 - Pixel is off

    The result of the operation is described after "->" string.

    The default is to return the current pixel value, which is
    returned if no other match is found.

    Operations:

    - 4 - 4 way rotation
    - N - Negate
    - 1 - Dummy op for no other operation (an op must always be given)
    - M - Mirroring

    Example::

        lb = LutBuilder(patterns = ["4:(... .1. 111)->1"])
        lut = lb.build_lut()

    Nc                óž   — d| _         |�3ddgdgddgdgddgg d¢d	œ}||vrd
|› d�}t        |«      ‚||   | _        y|�|| _        yg | _        y)a  
        :param patterns: A list of input patterns, or None.
        :param op_name: The name of a known pattern. One of "corner", "dilation4",
           "dilation8", "erosion4", "erosion8" or "edge".
        :exception Exception: If the op_name is not recognized.
        Nú1:(... ... ...)->0z4:(00. 01. ...)->1z4:(... .0. .1.)->1z4:(... .0. ..1)->1z4:(... .1. .0.)->0z4:(... .1. ..0)->0)r   z4:(.0. .1. ...)->1z4:(01. .1. ...)->1)ÚcornerÚ	dilation4Ú	dilation8Úerosion4Úerosion8ÚedgezUnknown pattern Ú!)ÚlutÚ	ExceptionÚpatterns)Úselfr   Úop_nameÚknown_patternsÚmsgs        ú]/Volumes/fast/ai/experiments/MLX_z-image/.venv/lib/python3.12/site-packages/PIL/ImageMorph.pyÚ__init__zLutBuilder.__init__A   s†   € ð &*ˆŒØÐà/Ð1EÐFØ2Ð3Ø2Ð4HÐIØ1Ð2Ø1Ð3GÐHòñˆNð ˜nÑ,Ø(¨¨	°Ð3�Ü “nÐ$à*¨7Ñ3ˆD�MØÐ!Ø$ˆD�MàˆD�Mó    c                ó.   — | xj                   |z  c_         y)z\
        Append to list of patterns.

        :param patterns: Additional patterns.
        N)r   )r   r   s     r    Úadd_patternszLutBuilder.add_patternsb   s   € ð 	�Š˜Ñ!Žr"   c                óx   ‡‡— ddgŠdŠt        ˆˆfd„t        t        «      D «       «      | _        | j                  S )z‹
        Set the current LUT, and return it.

        This is the default LUT that patterns will be applied against when building.
        r   r   é   c              3  ó4   •K  — | ]  }‰|‰z  d kD     –— Œ y­w)r   N© )Ú.0ÚiÚmÚsymbolss     €€r    Ú	<genexpr>z/LutBuilder.build_default_lut.<locals>.<genexpr>r   s   øè ø€ ÐK¹?°a˜W a¨!¡e¨q¡[Õ1¹?ùs   ƒ)Ú	bytearrayÚrangeÚLUT_SIZEr   )r   r+   r,   s    @@r    Úbuild_default_lutzLutBuilder.build_default_lutj   s2   ù€ ð �a�&ˆØˆÜÔK¼5Ä¼?ÓKÓKˆŒØ�x‰xˆr"   c                ó   — | j                   S )z)
        Returns the current LUT
        ©r   )r   s    r    Úget_lutzLutBuilder.get_lutu   s   € ð �x‰xˆr"   c                óX   ‡— t        |«      dk(  sJ ‚dj                  ˆfd„|D «       «      S )zuTakes a pattern and a permutation and returns the
        string permuted according to the permutation list.
        é	   Ú c              3  ó(   •K  — | ]	  }‰|   –— Œ y ­w)Nr(   )r)   ÚpÚpatterns     €r    r-   z-LutBuilder._string_permute.<locals>.<genexpr>€   s   øè ø€ Ð7©; a�w˜q•z©;ùs   ƒ)ÚlenÚjoin)r   r:   Úpermutations    ` r    Ú_string_permutezLutBuilder._string_permute{   s-   ø€ ô �;Ó 1Ò$Ð$Ð$Ø�w‰wÓ7©;Ó7Ó7Ð7r"   c                ó  — ||fg}d|v rE|d   d   }t        d«      D ]/  }|j                  | j                  |d   d   t        «      |f«       Œ1 d|v r?t	        |«      }|d| D ],  \  }}|j                  | j                  |t
        «      |f«       Œ. d|v rkt	        |«      }|d| D ]X  \  }}|j                  d	d
«      j                  dd	«      j                  d
d«      }dt        |«      z
  }|j                  ||f«       ŒZ |S )z¹Takes a basic pattern and its result and clones
        the pattern according to the modifications described in the $options
        parameter. It returns a list of all cloned patterns.Ú4éÿÿÿÿr   r
   r   ÚMNÚNÚ0ÚZÚ1)r/   Úappendr>   ÚROTATION_MATRIXr;   ÚMIRROR_MATRIXÚreplaceÚint)	r   Úbasic_patternÚoptionsÚbasic_resultr   Úresr*   Únr:   s	            r    Ú_pattern_permutezLutBuilder._pattern_permute‚   s  € ð # LÐ1Ð2ˆð �'‰>Ø˜2‘,˜q‘/ˆCÜ˜1–X�Ø—‘Ø×)Ñ)¨(°2©,°q©/¼?ÓKÈSÐQõð ð
 �'‰>Ü�H“ˆAØ (¨¨!£‘�˜Ø—‘ ×!5Ñ!5°g¼}Ó!MÈsÐ SÕTð !-ð �'‰>Ü�H“ˆAØ (¨¨!£‘�˜à!Ÿ/™/¨#¨sÓ3×;Ñ;¸CÀÓE×MÑMÈcÐSVÓW�Øœ#˜c›(‘l�Ø—‘ ¨# Õ/ð	 !-ð ˆr"   c                ó`  — | j                  «        | j                  €J ‚g }| j                  D ]±  }t        j                  d|j                  dd«      «      }|sd|z   dz   }t        |«      ‚|j                  d«      }|j                  d«      }t        |j                  d	«      «      }|j                  d
d«      j                  dd«      }|| j                  |||«      z  }Œ³ g }|D ]P  }|d   j                  dd«      j                  dd«      }|j                  t        j                  |«      |d   f«       ŒR t        t        «      D ]Z  }	t        |	«      dd }
ddt        |
«      z
  z  |
z   ddd…   }
|D ]+  \  }}|j!                  |
«      sŒddg|   | j                  |	<   Œ- Œ\ | j                  S )zoCompile all patterns into a morphology LUT, and return it.

        This is the data to be passed into MorphOp.Nz(\w):?\s*\((.+?)\)\s*->\s*(\d)Ú
r7   zSyntax error in pattern "Ú"r   r   r   Ú r   Ú.ÚXz[01]rD   r6   rA   )r1   r   r   ÚreÚsearchrJ   r   ÚgrouprK   rQ   rG   Úcompiler/   r0   Úbinr;   Úmatch)r   r   r9   r+   r   rM   r:   ÚresultÚcompiled_patternsr*   Ú
bitpatternÚrs               r    Ú	build_lutzLutBuilder.build_lut¢   sž  € ð 	×ÑÔ Ø�x‰xÐ#Ð#Ð#Øˆð —”ˆAÜ—	‘	Ð;¸Q¿Y¹YÀtÈRÓ=PÓQˆAÙØ1°AÑ5¸Ñ;�Ü “nÐ$Ø—g‘g˜a“jˆGØ—g‘g˜a“jˆGÜ˜Ÿ™ ›“_ˆFð —o‘o c¨2Ó.×6Ñ6°t¸RÓ@ˆGà˜×-Ñ-¨g°wÀÓGÑG‰Hð ð ÐÛˆGØ˜‘
×"Ñ" 3¨Ó,×4Ñ4°S¸&ÓAˆAØ×$Ñ$¤b§j¡j°£m°W¸Q±ZÐ%@ÕAð  ô ”x–ˆAä˜Q›  ˜ˆJØ ¤S¨£_Ñ!4Ñ5¸
ÑBÁDÀbÀDÑIˆJã/‘
�˜Ø—=‘= Õ,Ø#$ a &¨¡)�D—H‘H˜Q’Kñ 0ð !ð �x‰xˆr"   )NN)r   úlist[str] | Noner   ú
str | NoneÚreturnÚNone)r   z	list[str]re   rf   )re   r.   )re   úbytearray | None)r:   Ústrr=   z	list[int]re   rh   )rL   rh   rM   rh   rN   rK   re   zlist[tuple[str, int]])Ú__name__Ú
__module__Ú__qualname__Ú__doc__r!   r$   r1   r4   r>   rQ   rb   r(   r"   r    r   r      sl   „ ñ!ðH HLðØ(ðØ:Dðà	óóB"ó	óó8ðØ ðØ+.ðØ>Aðà	óô@(r"   r   c                  ó^   — e Zd ZdZ	 	 	 d
	 	 	 	 	 	 	 dd„Zdd„Zdd„Zdd„Zdd„Zdd„Z	dd	„Z
y)ÚMorphOpz*A class for binary morphological operatorsNc                óZ   — |€
|€|| _         yt        ||«      j                  «       | _         y)aÈ  Create a binary morphological operator.

        If the LUT is not provided, then it is built using LutBuilder from the op_name
        or the patterns.

        :param lut: The LUT data.
        :param patterns: A list of input patterns, or None.
        :param op_name: The name of a known pattern. One of "corner", "dilation4",
        "dilation8", "erosion4", "erosion8", "edge".
        :exception Exception: If the op_name is not recognized.
        N)r   r   rb   )r   r   r   r   s       r    r!   zMorphOp.__init__Ð   s,   € ð" Ð  ØˆD�Hä! (¨GÓ4×>Ñ>Ó@ˆD�Hr"   c                óR  — | j                   €d}t        |«      ‚|j                  dvrd}t        |«      ‚t	        j
                  |j                  |j                  «      }t        j                  t        | j                   «      |j                  «       |j                  «       «      }||fS )a9  Run a single morphological operation on an image.

        Returns a tuple of the number of changed pixels and the
        morphed image.

        :param image: A 1-mode or L-mode image.
        :exception Exception: If the current operator is None.
        :exception ValueError: If the image is not 1 or L mode.úNo operator loaded©rF   ÚLúImage mode must be 1 or L)r   r   ÚmodeÚ
ValueErrorr   ÚnewÚsizer   ÚapplyÚbytesÚgetim)r   Úimager   ÚoutimageÚcounts        r    ry   zMorphOp.applyæ   sƒ   € ð �8‰8ÐØ&ˆCÜ˜C“.Ð à�:‰:˜ZÑ'Ø-ˆCÜ˜S“/Ð!Ü—9‘9˜UŸZ™Z¨¯©Ó4ˆÜ×#Ñ#¤E¨$¯(©(£O°U·[±[³]ÀHÇNÁNÓDTÓUˆØ�hˆÐr"   c                óØ   — | j                   €d}t        |«      ‚|j                  dvrd}t        |«      ‚t	        j
                  t        | j                   «      |j                  «       «      S )ax  Get a list of coordinates matching the morphological operation on
        an image.

        Returns a list of tuples of (x,y) coordinates of all matching pixels. See
        :ref:`coordinate-system`.

        :param image: A 1-mode or L-mode image.
        :exception Exception: If the current operator is None.
        :exception ValueError: If the image is not 1 or L mode.rq   rr   rt   )r   r   ru   rv   r   r]   rz   r{   ©r   r|   r   s      r    r]   zMorphOp.matchú   sY   € ð �8‰8ÐØ&ˆCÜ˜C“.Ð à�:‰:˜ZÑ'Ø-ˆCÜ˜S“/Ð!Ü×"Ñ"¤5¨¯©£?°E·K±K³MÓBÐBr"   c                ó~   — |j                   dvrd}t        |«      ‚t        j                  |j	                  «       «      S )a!  Get a list of all turned on pixels in a 1 or L mode image.

        Returns a list of tuples of (x,y) coordinates of all non-empty pixels. See
        :ref:`coordinate-system`.

        :param image: A 1-mode or L-mode image.
        :exception ValueError: If the image is not 1 or L mode.rr   rt   )ru   rv   r   Úget_on_pixelsr{   r€   s      r    r‚   zMorphOp.get_on_pixels  s6   € ð �:‰:˜ZÑ'Ø-ˆCÜ˜S“/Ð!Ü×*Ñ*¨5¯;©;«=Ó9Ð9r"   c                óâ   — t        |d«      5 }t        |j                  «       «      | _        ddd«       t	        | j                  «      t
        k7  rd| _        d}t        |«      ‚y# 1 sw Y   Œ:xY w)z­
        Load an operator from an mrl file

        :param filename: The file to read from.
        :exception Exception: If the length of the file data is not 512.
        ÚrbNzWrong size operator file!)Úopenr.   Úreadr   r;   r0   r   )r   ÚfilenameÚfr   s       r    Úload_lutzMorphOp.load_lut  s]   € ô �(˜DÔ! QÜ  §¡£Ó*ˆDŒH÷ "ô ˆt�x‰x‹=œHÒ$ØˆDŒHØ-ˆCÜ˜C“.Ð ð %÷ "Ð!ús   �A%Á%A.c                ó®   — | j                   €d}t        |«      ‚t        |d«      5 }|j                  | j                   «       ddd«       y# 1 sw Y   yxY w)z¡
        Save an operator to an mrl file.

        :param filename: The destination file.
        :exception Exception: If the current operator is None.
        Nrq   Úwb)r   r   r…   Úwrite)r   r‡   r   rˆ   s       r    Úsave_lutzMorphOp.save_lut*  sE   € ð �8‰8ÐØ&ˆCÜ˜C“.Ð Ü�(˜DÔ! QØ�G‰G�D—H‘HÔ÷ "×!Ñ!ús   ¦AÁAc                ó   — || _         y)zU
        Set the LUT from an external source

        :param lut: A new LUT.
        Nr3   )r   r   s     r    Úset_lutzMorphOp.set_lut7  s   € ð ˆ�r"   )NNN)r   rg   r   rd   r   rc   re   rf   )r|   úImage.Imagere   ztuple[int, Image.Image])r|   r�   re   zlist[tuple[int, int]])r‡   rh   re   rf   )r   rg   re   rf   )ri   rj   rk   rl   r!   ry   r]   r‚   r‰   r�   r�   r(   r"   r    rn   rn   Í   s_   „ Ù4ð !%Ø"Ø%)ð	AàðAð ðAð #ð	Að
 
óAó,ó(Có&:ó!óôr"   rn   )Ú
__future__r   rX   r7   r   r   r0   rH   rI   r   rn   r(   r"   r    Ú<module>r’      s<   ðõ #ã 	ç "à€ò€ò
€÷mñ m÷`pò pr"   