a :jgs!@sXddlmZddlZddlmZmZdZgdZgdZGdd d Z Gd d d Z dS) ) annotationsN)Image _imagingmorphi) rr) r rrr r rr rrc@seZdZdZd ddddddZd dd d d Zdd ddZdd ddZddddddZdddddddZ dd ddZ dS)! LutBuilderaTA 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() Nlist[str] | None str | NoneNone)patternsop_namereturncCst|dur||_ng|_d|_|durpddgdgddgdgddggdd}||vrfd |d }t||||_dS) N1:(... ... ...)->0z4:(00. 01. ...)->1z4:(... .0. .1.)->1z4:(... .0. ..1)->1z4:(... .1. .0.)->0z4:(... .1. ..0)->0)rz4:(.0. .1. ...)->1z4:(01. .1. ...)->1)ZcornerZ dilation4Z dilation8Zerosion4Zerosion8edgezUnknown pattern !)rlut Exception)selfrrZknown_patternsmsgr8/usr/local/lib/python3.9/site-packages/PIL/ImageMorph.py__init__As   zLutBuilder.__init__z list[str])rrcCs|j|7_dSNr)rrrrr add_patterns\szLutBuilder.add_patterns)rcs.ddgdtfddttD|_dS)Nrrc3s|]}|@dkVqdS)rNr).0imsymbolsrr bz/LutBuilder.build_default_lut..) bytearrayrangeLUT_SIZErrrr$rbuild_default_lut_szLutBuilder.build_default_lutbytearray | NonecCs|jSrrr,rrrget_lutdszLutBuilder.get_lutstrz list[int])pattern permutationrcs(t|dksJdfdd|DS)zstring_permute takes a pattern and a permutation and returns the string permuted according to the permutation list. c3s|]}|VqdSrr)r"pr2rrr'lr(z-LutBuilder._string_permute..)lenjoin)rr2r3rr7r_string_permutegszLutBuilder._string_permuteintzlist[tuple[str, int]]) basic_patternoptions basic_resultrc Cs||fg}d|vrJ|dd}tdD]"}|||ddt|fq&d|vrt|}|d|D]\}}|||t|fqfd|vrt|}|d|D]>\}}|d d d d d d }dt|}|||fq|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.4rr rMNN0Z1)r*appendr:ROTATION_MATRIXr8 MIRROR_MATRIXreplacer;) rr<r=r>rresr#nr2rrr_pattern_permutens$    zLutBuilder._pattern_permuter)c CsH||jdusJg}|jD]x}td|dd}|sPd|d}t||d}|d}t|d }|d ddd}|| |||7}q g}|D]4}|d d d d d}| t ||dfqt t D]`} t| dd} ddt| | ddd} |D](\}} || rd dg| |j| <qq|jS)zlCompile all patterns into a morphology lut. TBD :Build based on (file) morphlut:modify_lut Nz(\w*):?\s*\((.+?)\)\s*->\s*(\d) r5zSyntax error in pattern ""rr r r.Xz[01]rCr4r@)r-rrresearchrIrgroupr;rLrFcompiler*r+binr8match) rrr6r%rr=r2resultZcompiled_patternsr#Z bitpatternrrrr build_luts0       zLutBuilder.build_lut)NN) __name__ __module__ __qualname____doc__rr r-r0r:rLrZrrrrr s$ r c@seZdZdZdddddddd Zd d d d dZd dd ddZd dd ddZdddddZdddddZ dddddZ dS)MorphOpz*A class for binary morphological operatorsNr.rrr)rrrrcCs<||_|dur t|d|_n|dur8t|d|_dS)z&Create a binary morphological operatorN)rr)rr rZ)rrrrrrrrs zMorphOp.__init__z Image.Imageztuple[int, Image.Image])imagercCsb|jdurd}t||jdkr,d}t|t|j|jd}tt |j| | }||fS)zRun a single morphological operation on an image Returns a tuple of the number of changed pixels and the morphed imageNNo operator loadedLImage mode must be L) rrmode ValueErrorrnewsizerapplybytesgetim)rr`rZoutimagecountrrrrhs  z MorphOp.applyzlist[tuple[int, int]]cCsB|jdurd}t||jdkr,d}t|tt|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`.Nrarbrc)rrrdrerrWrirjrr`rrrrrWs  z MorphOp.matchcCs$|jdkrd}t|t|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`.rbrc)rdrer get_on_pixelsrjrlrrrrms zMorphOp.get_on_pixelsr1)filenamercCs\t|d}t||_Wdn1s.0Yt|jtkrXd|_d}t|dS)z!Load an operator from an mrl filerbNzWrong size operator file!)openr)readrr8r+r)rrnfrrrrload_luts  ,zMorphOp.load_lutcCsP|jdurd}t|t|d}||jWdn1sB0YdS)zSave an operator to an mrl fileNrawb)rrrpwrite)rrnrrrrrrsave_luts   zMorphOp.save_lut)rrcCs ||_dS)z#Set the lut from an external sourceNr/)rrrrrset_lutszMorphOp.set_lut)NNN) r[r\r]r^rrhrWrmrsrvrwrrrrr_s   r_) __future__rrRr5rrr+rGrHr r_rrrrs