o
    Z#ûa]  ã                   @   sL   d dl Z ddlmZmZ dZg d¢Zg d¢ZG dd„ dƒZG d	d
„ d
ƒZdS )é    Né   )ÚImageÚ_imagingmorphi   )	é   é   r   é   é   r   é   é   é   )	r   r   r   r
   r   r   r	   r   r   c                   @   óJ   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
dS )Ú
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                 C   st   |d ur|| _ ng | _ d | _|d ur8ddgdgddgdgddgg d¢dœ}||vr1td	| d
 ƒ‚|| | _ d S d S )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 ú!)ÚpatternsÚlutÚ	Exception)Úselfr   Úop_nameÚknown_patterns© r   ú0/usr/lib/python3/dist-packages/PIL/ImageMorph.pyÚ__init__@   s    úðzLutBuilder.__init__c                 C   s   |  j |7  _ d S ©N©r   )r   r   r   r   r   Úadd_patternsX   s   zLutBuilder.add_patternsc                    s.   ddg‰d‰ t ‡ ‡fdd„ttƒD ƒƒ| _d S )Nr   r   é   c                 3   s    � | ]}ˆ|ˆ @ d k V  qdS )r   Nr   )Ú.0Úi©ÚmÚsymbolsr   r   Ú	<genexpr>^   s   € z/LutBuilder.build_default_lut.<locals>.<genexpr>)Ú	bytearrayÚrangeÚLUT_SIZEr   ©r   r   r%   r   Úbuild_default_lut[   s   "zLutBuilder.build_default_lutc                 C   s   | j S r   ©r   r,   r   r   r   Úget_lut`   s   zLutBuilder.get_lutc                    s(   t |ƒdksJ ‚d ‡ fdd„|D ƒ¡S )z„string_permute takes a pattern and a permutation and returns the
        string permuted according to the permutation list.
        é	   Ú c                 3   s   � | ]}ˆ | V  qd S r   r   )r#   Úp©Úpatternr   r   r(   h   s   € z-LutBuilder._string_permute.<locals>.<genexpr>)ÚlenÚjoin)r   r4   Úpermutationr   r3   r   Ú_string_permutec   s   zLutBuilder._string_permutec           	      C   sæ   ||fg}d|v r%|d d }t dƒD ]}| |  |d d t¡|f¡ qd|v rCt|ƒ}|d|… D ]\}}| |  |t¡|f¡ q3d|v rqt|ƒ}|d|… D ]\}}| dd	¡ d
d¡ d	d
¡}dt|ƒ }| ||f¡ qQ|S )zÉpattern_permute 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   ÚMÚNÚ0ÚZÚ1)r*   Úappendr8   ÚROTATION_MATRIXr5   ÚMIRROR_MATRIXÚreplaceÚint)	r   Úbasic_patternÚoptionsÚbasic_resultr   Úresr$   Únr4   r   r   r   Ú_pattern_permutej   s$   
ÿzLutBuilder._pattern_permutec           
      C   s8  |   ¡  g }| jD ]:}t d| dd¡¡}|std| d ƒ‚| d¡}| d¡}t| d¡ƒ}| d	d¡ dd¡}||  |||¡7 }q	t	|ƒD ]\}}|d
  dd¡ dd¡}t 
|¡}||d f||< qHttƒD ].}t|ƒdd… }ddt|ƒ  | ddd… }|D ]\}}	| |¡r—d
dg|	 | j|< q…qj| jS )zlCompile all patterns into a morphology lut.

        TBD :Build based on (file) morphlut:modify_lut
        z(\w*):?\s*\((.+?)\)\s*->\s*(\d)Ú
r1   zSyntax error in pattern "ú"r   r   r   ú r   Ú.ÚXz[01]Nr=   r0   r:   )r-   r   ÚreÚsearchrC   r   ÚgrouprD   rJ   Ú	enumerateÚcompiler*   r+   Úbinr5   Úmatchr   )
r   r   r2   r&   rF   r4   Úresultr$   Ú
bitpatternÚrr   r   r   Ú	build_lutˆ   s0   




€þzLutBuilder.build_lut)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r!   r-   r/   r8   rJ   rZ   r   r   r   r   r      s    
#r   c                   @   r   )ÚMorphOpz*A class for binary morphological operatorsNc                 C   sB   || _ |durt|d� ¡ | _ dS |durt|d� ¡ | _ dS dS )z&Create a binary morphological operatorN)r   r    )r   r   rZ   )r   r   r   r   r   r   r   r   ¶   s   ÿzMorphOp.__init__c                 C   sZ   | j du r	tdƒ‚|jdkrtdƒ‚t |j|jd¡}t t	| j ƒ|j
j|j
j¡}||fS )z‡Run a single morphological operation on an image

        Returns a tuple of the number of changed pixels and the
        morphed imageNúNo operator loadedÚLúImage mode must be L)r   r   ÚmodeÚ
ValueErrorr   ÚnewÚsizer   ÚapplyÚbytesÚimÚid)r   ÚimageÚoutimageÚcountr   r   r   rg   ¾   s   

zMorphOp.applyc                 C   s:   | j du r	tdƒ‚|jdkrtdƒ‚t t| j ƒ|jj¡S )zÈ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`.Nr`   ra   rb   )	r   r   rc   rd   r   rV   rh   ri   rj   ©r   rk   r   r   r   rV   Ì   s
   

zMorphOp.matchc                 C   s    |j dkr	tdƒ‚t |jj¡S )z©Get a list of all turned on pixels in a binary image

        Returns a list of tuples of (x,y) coordinates
        of all matching pixels. See :ref:`coordinate-system`.ra   rb   )rc   rd   r   Úget_on_pixelsri   rj   rn   r   r   r   ro   Ù   s   
zMorphOp.get_on_pixelsc                 C   sX   t |dƒ�}t| ¡ ƒ| _W d  ƒ n1 sw   Y  t| jƒtkr*d| _tdƒ‚dS )z!Load an operator from an mrl fileÚrbNzWrong size operator file!)Úopenr)   Úreadr   r5   r+   r   ©r   ÚfilenameÚfr   r   r   Úload_lutã   s   ÿþzMorphOp.load_lutc                 C   sN   | j du r	tdƒ‚t|dƒ�}| | j ¡ W d  ƒ dS 1 s w   Y  dS )zSave an operator to an mrl fileNr`   Úwb)r   r   rq   Úwriters   r   r   r   Úsave_lutì   s
   
"ÿzMorphOp.save_lutc                 C   s
   || _ dS )z#Set the lut from an external sourceNr.   )r   r   r   r   r   Úset_lutó   s   
zMorphOp.set_lut)NNN)r[   r\   r]   r^   r   rg   rV   ro   rv   ry   rz   r   r   r   r   r_   ³   s    

	r_   )	rP   r1   r   r   r+   rA   rB   r   r_   r   r   r   r   Ú<module>   s    