B
    0\O                  @   sL   d dl mZ ddlmZmZ d dlZdZG dd deZG dd	 d	eZ	dS )
    )print_function   )Image_imagingmorphNi   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 )
LutBuildera~  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   -lib/python3.7/site-packages/PIL/ImageMorph.py__init__3   s&    
zLutBuilder.__init__c             C   s   |  j |7  _ d S )N)r   )r   r   r   r   r   add_patternsL   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>R   s    z/LutBuilder.build_default_lut.<locals>.<genexpr>)	bytearrayrangeLUT_SIZEr	   )r   r   )r   r   r   build_default_lutO   s    zLutBuilder.build_default_lutc             C   s   | j S )N)r	   )r   r   r   r   get_lutT   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 )Nr   )r   p)patternr   r   r   \   s    z-LutBuilder._string_permute.<locals>.<genexpr>)lenAssertionErrorjoin)r   r   Zpermutationr   )r   r   _string_permuteW   s    zLutBuilder._string_permutec       	      C   s  ||fg}d|kr`|d d }x@t dD ]4}|| |d d ddddddd	d
dg	|f q(W d|krt|}x@|d| D ]0\}}|| |dddd
ddd	ddg	|f q~W d|krt|}xN|d| D ]>\}}|dddddd}dt| }|||f qW |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                     MN0Z1)r   appendr#   r    replaceint)	r   Zbasic_patternoptionsZbasic_resultr   Zresr   nr   r   r   r   _pattern_permute^   s2    

zLutBuilder._pattern_permutec       
      C   sL  |    g }x~| jD ]t}td|dd}|s@td| d |d}|d}t|d}|d	ddd}|| |||7 }qW xFt	|D ]:\}}|d
 dddd}t
|}||d f||< qW xpttD ]d}t|dd }ddt|  | ddd }x0|D ](\}}	||rd
dg|	 | j|< qW qW | 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]Nr/   r   r%   )r   r   researchr3   r
   groupr4   r7   	enumeratecompiler   r   binr    matchr	   )
r   r   r   r   r5   r   resultr   Z
bitpatternrr   r   r   	build_lut   s.    


zLutBuilder.build_lut)NN)__name__
__module____qualname____doc__r   r   r   r   r#   r7   rF   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   rF   )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 imageNzNo operator loadedLz0Image must be binary, meaning it must use mode L)r	   r
   moder   newsizer   applybytesimid)r   imageZoutimagecountr   r   r   rP      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`.NzNo operator loadedrL   z0Image must be binary, meaning it must use mode L)r	   r
   rM   r   rC   rQ   rR   rS   )r   rT   r   r   r   rC      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`.rL   z0Image must be binary, meaning it must use mode L)rM   r
   r   get_on_pixelsrR   rS   )r   rT   r   r   r   rV      s    
zMorphOp.get_on_pixelsc          	   C   sD   t |d}t| | _W d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 dQ R X dS )zSave an operator to an mrl fileNzNo operator loadedwb)r	   r
   rX   write)r   rZ   r[   r   r   r   save_lut   s    
zMorphOp.save_lutc             C   s
   || _ dS )z#Set the lut from an external sourceN)r	   )r   r	   r   r   r   set_lut   s    zMorphOp.set_lut)NNN)rG   rH   rI   rJ   r   rP   rC   rV   r\   r_   r`   r   r   r   r   rK      s     

	rK   )
Z
__future__r   r   r   r   r=   r   objectr   rK   r   r   r   r   <module>   s     