
    Aeit(                    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        A/var/www/card/venv/lib/python3.12/site-packages/PIL/ImageMorph.py__init__zLutBuilder.__init__A   s     &*/1EF2324HI1213GHN n,(	3n$*73DM!$DMDM    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     KaWa!eq[1Ks   )	bytearrayrangeLUT_SIZEr   )r   r+   r,   s    @@r    build_default_lutzLutBuilder.build_default_lutj   s2     a&K5?KKxxr"   c                    | j                   S )z)
        Returns the current LUT
        r   )r   s    r    get_lutzLutBuilder.get_lutu   s     xx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     7awqz7s   )lenjoin)r   r:   permutations    ` r    _string_permutezLutBuilder._string_permute{   s-     ;1$$$ww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 )zTakes 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.4r   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1X ))(2,q/?KSQ
 '>HA (! U!5!5g}!Ms STU '>HA (! 0!//#s3;;CEMMcSVW#c(l#/	0 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    	 xx###  	HA		;QYYtR=PQA1A5;n$ggajGggajG_F ooc2.66tR@G--gwGGH	H  	BG
""3,44S&AA$$bjjmWQZ%@A	B x 	,AQJS_!45
BDbDIJ/ ,
==,#$a&)DHHQK,	, xx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,    " DH!(G4>>@DHr"   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     88&CC. ::Z'-CS/!99UZZ4##E$((OU[[]HNNDT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     88&CC. ::Z'-CS/!""5?EKKM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  sd     (D! 	+Q *DH	+ txx=H$DH-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*  sN     88&CC. (D! 	QGGDHH	 	 	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"   