U
    ॡc[                  	   @   sh   d dl Z ddlmZmZ dZddd dddd	d
dg	Zddd d
ddd	ddg	ZG dd dZG dd dZdS )    N   )Image_imagingmorphi                        c                   @   sJ   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   sr   |d k	r|| _ ng | _ d | _|d k	rnddgdgddgdgddgdddgd	}||krdtd
| d || | _ d S )Nz1:(... ... ...)->0z4:(00. 01. ...)->1z4:(... .0. .1.)->1z4:(... .0. ..1)->1z4:(... .1. .0.)->0z4:(... .1. ..0)->0z4:(.0. .1. ...)->1z4:(01. .1. ...)->1)ZcornerZ	dilation4Z	dilation8Zerosion4Zerosion8ZedgezUnknown pattern !)patternslut	Exception)selfr   op_nameZknown_patterns r   2/tmp/pip-unpacked-wheel-h_ukwjmx/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td fdd|D S )zstring_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AssertionErrorjoin)r   r+   Zpermutationr   r*   r   _string_permutec   s    zLutBuilder._string_permutec           	      C   s   ||fg}d|krJ|d d }t dD ]"}|| |d d t|f q&d|krt|}|d| D ]\}}|| |t|f qfd|krt|}|d| D ]>\}}|d	d
dd	d
d}dt| }|||f q|S )zpattern_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.4r   r   r   MNN0Z1)r!   appendr/   ROTATION_MATRIXr,   MIRROR_MATRIXreplaceint)	r   Zbasic_patternoptionsZbasic_resultr   resr   nr+   r   r   r   _pattern_permutej   s$    
zLutBuilder._pattern_permutec           
      C   s<  |    g }| jD ]t}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||< qttD ]`}t|dd }ddt|  | ddd }|D ](\}}	||r
d
dg|	 | j|< q
q| jS )zlCompile all patterns into a morphology lut.

        TBD :Build based on (file) morphlut:modify_lut
        z(\w*):?\s*\((.+?)\)\s*->\s*(\d)
r(   zSyntax error in pattern ""r   r   r    r   .Xz[01]Nr4   r'   r1   )r$   r   researchr:   r   groupr;   r?   	enumeratecompiler!   r"   binr,   matchr   )
r   r   r)   r   r<   r+   resultr   Z
bitpatternrr   r   r   	build_lut   s,    



zLutBuilder.build_lut)NN)__name__
__module____qualname____doc__r   r   r$   r&   r/   r?   rN   r   r   r   r   r      s   #
r   c                   @   sJ   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 )MorphOpz*A class for binary morphological operatorsNc                 C   s<   || _ |dk	r t|d | _ n|dk	r8t|d | _ dS )z&Create a binary morphological operatorN)r   r   )r   r   rN   )r   r   r   r   r   r   r   r      s
    zMorphOp.__init__c                 C   sZ   | j dkrtd|jdkr$tdt|j|jd}tt	| j |j
j|j
j}||fS )zRun 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   imageZoutimagecountr   r   r   r[      s    

zMorphOp.applyc                 C   s:   | j dkrtd|jdkr$tdtt| j |jjS )zGet 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`.NrT   rU   rV   )	r   r   rW   rX   r   rK   r\   r]   r^   r   r_   r   r   r   rK      s
    

zMorphOp.matchc                 C   s    |j dkrtdt|jjS )zGet 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`.rU   rV   )rW   rX   r   get_on_pixelsr]   r^   ra   r   r   r   rb      s    
zMorphOp.get_on_pixelsc              	   C   sD   t |d}t| | _W 5 Q R X 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   r,   r"   r   r   filenamefr   r   r   load_lut   s
    zMorphOp.load_lutc              	   C   s8   | j dkrtdt|d}|| j  W 5 Q R X dS )zSave an operator to an mrl fileNrT   wb)r   r   rd   writerf   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)rO   rP   rQ   rR   r   r[   rK   rb   ri   rl   rm   r   r   r   r   rS      s   

	rS   )	rE   r(   r   r   r"   r8   r9   r   rS   r   r   r   r   <module>   s2                