a :jg#@sNUddlmZddlZddlZddlmZddlmZddlm Z m Z m Z m Z m Z mZddlmZmZddlmZdd lmZd ed <z ejjZWneydZYn0e rdd lmZmZe eeed fe fZ!GdddZ"d,ddddddZ#d-ddddddZ$d.ddddddd d!d"Z%d#d$dd%d&d'd(Z&dddd)d*d+Z'dS)/) annotationsN)Sequence) ModuleType) TYPE_CHECKINGAnyAnyStrCallableUnioncast)Image ImageColor) deprecate)Coordsz(Callable[[], Image.core._Outline] | NoneOutline) ImageDraw2 ImageFont.c@seZdZUdZded<dhdddddd Zd d d d Zdd dddZdiddddddZdjdddddddddZ dkdddddd d!Z dldddddddd"d#d$Z dmdddddd%d&d'Z dnd(dddddd)d*d+Z dodddddd-d.d/Zdpd0dddd1d2d3Zdqdddddddd"d4d5Zdrdddd6d7d8Zdsdddddd%d9d:Zdtd;ddddddd<d=d>Zdudddddd%d?d@ZdvddAddddddBddCdDdEZdFdGdHdIdJZdFdKdHdLdMZd ddddNdOdPZdwdTdFdddddUddVddddGdWdWddXdYdZZdxdd[dTdFdddddUddVddddGddd\d]d^Zdydd[dFdddVddGddd_d`daZdzdd[dTdFddddUddVdddGddbdc dddeZd{dd[dTdFddddUddVdddGddbdc dfdgZdS)| ImageDrawNzNImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont | Nonefont Image.Image str | NoneNoneimmodereturncCs||jr|d}|dur(|j}||jkrV|dkrJ|jdkrJd}n d}t||dkrh|j|_nd|_||_|j|_tj |j||_ ||_|dvr|j d|_ n|j d |_ |d vrd |_ nd |_ d |_dS)a Create a drawing instance. :param im: The image to draw in. :param mode: Optional mode to use for color values. For RGB images, this argument can be RGB or RGBA (to blend the drawing into the image). For all other modes, this argument must be the same as the image mode. If omitted, the mode defaults to the mode of the image. rNRGBARGBr z mode mismatchP)IF)1rrr r"LF)loadreadonlyZ_copyr ValueErrorpalette_imagerr coredrawdraw_inkinkfontmodefill)selfrrblendmsgr27/usr/local/lib/python3.9/site-packages/PIL/ImageDraw.py__init__Es2   zImageDraw.__init__zGImageFont.ImageFont | ImageFont.FreeTypeFont | ImageFont.TransposedFont)rcCs"|jsddlm}||_|jS)a= Get the current default font. To set the default font for this ImageDraw instance:: from PIL import ImageDraw, ImageFont draw.font = ImageFont.truetype("Tests/fonts/FreeMono.ttf") To set the default font for all future ImageDraw instances:: from PIL import ImageDraw, ImageFont ImageDraw.ImageDraw.font = ImageFont.truetype("Tests/fonts/FreeMono.ttf") If the current default font is ``None``, it is initialized with ``ImageFont.load_default()``. :returns: An image font.r r)rr load_default)r/rr2r2r3getfontos  zImageDraw.getfontz float | None) font_sizercCs*|durddlm}||S|SdS)Nr r5)r6rr7r8)r/r9rr2r2r3_getfonts  zImageDraw._getfont _Ink | Noneztuple[int | None, int | None])r,r.rcCsd}d}|dur.|dur.|jr&|j}q|j}n|durzt|trNt||j}|jrnt|trn|j||j }|j |}|durt|trt||j}|jrt|tr|j||j }|j |}||fSN) r.r, isinstancestrr Zgetcolorrr'tupler(r*r+)r/r,r.Z result_inkZ result_fillr2r2r3_getinks&    zImageDraw._getinkr rfloatint)xystartendr.widthrcCs.||\}}|dur*|j|||||dS)z Draw an arc.N)r@r*draw_arc)r/rCrDrEr.rFr,r2r2r3arcs z ImageDraw.arcz Sequence[int])rCbitmapr.rcCs@|||\}}|dur"|}|dur<|j||j|dS)zDraw a bitmap.N)r$r@r* draw_bitmapr)r/rCrIr.r,r2r2r3rIs zImageDraw.bitmap)rCrDrEr.outlinerFrc Cs^|||\}}|dur,|j||||d|durZ||krZ|dkrZ|j||||d|dS)z Draw a chord.Nr r)r@r*Z draw_chord r/rCrDrEr.rKrFr,fill_inkr2r2r3chords zImageDraw.chord)rCr.rKrFrcCsV|||\}}|dur(|j||d|durR||krR|dkrR|j||d|dS)zDraw an ellipse.Nr r)r@r*Z draw_ellipser/rCr.rKrFr,rMr2r2r3ellipses zImageDraw.ellipseSequence[float])rCradiusr.rKrFrcCs@|d||d||d||d|f}|||||dS)z4Draw a circle given center coordinates and a radius.rr N)rP)r/rCrRr.rKrFZ ellipse_xyr2r2r3circles ,zImageDraw.circler)rCr.rFjointrcsV||d}|durR|j||dkrRdkrRtdttfrbtttt}nfddt dt dD}t dt |dD]}||}d d||d|f|||dffD} | d| dkrqd d d d fdd } | d| dkr| dd| dkp>| d| dko>| dd| dk} |ddd|dddf|ddd|dddfg} | r| dd| dd} }n| dd| dd} }| | | d|d|dkr| r| || dd|| || ddg}n&| || dd|| || ddg}|j ||ddqdS)z6Draw a line, or a connected sequence of line segments.rNZcurvec s*g|]"}tttt||dqS))r rrAr?.0i)rCr2r3 sz"ImageDraw.line..rVr c Ss>g|]6\}}tt|d|d|d|ddqS)rr h)mathdegreesatan2)rXrDrEr2r2r3rZs(rQrAztuple[float, ...])coordanglerc sZ|\}}|d8}dd}tdd||tt|f||tt|ffDS)NZrVr css2|]*\}}||dkrt|nt|VqdS)rN)r\floorceil)rXpZp_dr2r2r3 sz9ImageDraw.line..coord_at_angle..)r?r\cosradianssin)r_r`xyZdistancerFr2r3coord_at_angles z&ImageDraw.line..coord_at_anglerark) r@r*Z draw_linesr=listr?r rrArangelenpiesliceline)r/rCr.rFrTr,ZpointsrYpointanglesrlZflippedZcoordsrDrEZ gap_coordsr2)rFrCr3rtsR  $$&&zImageDraw.linezImage.core._Outline)shaper.rKrcCsT||||\}}|dur0|j||d|durP||krP|j||ddS)z(Experimental) Draw a shape.Nr r)closer@r*Z draw_outline)r/rwr.rKr,rMr2r2r3rw<s zImageDraw.shapec Cs^|||\}}|dur,|j||||d|durZ||krZ|dkrZ|j||||d|dS)zDraw a pieslice.Nr r)r@r* draw_pieslicerLr2r2r3rsJs zImageDraw.pieslice)rCr.rcCs(||\}}|dur$|j||dS)z#Draw one or more individual pixels.N)r@r*Z draw_points)r/rCr.r,r2r2r3ruZszImageDraw.pointc Cs2|||\}}|dur(|j||d|dur.||kr.|dkr.|dkrb|j||d|n|jdur.td|jj}|dd}|} t| } | j||d|} t| } |dd}| j||d||j | | dt|j |jj} t| } | j||d||j | jd| j|jdS)zDraw a polygon.Nr rr"rV)maskrr) r@r*Z draw_polygonrr newsizecopyDrawpaster) r/rCr.rKrFr,rMrzZmask_inkZfill_imr*Zink_imrr2r2r3polygon`s*  zImageDraw.polygon!Sequence[Sequence[float] | float])bounding_circlen_sidesrotationr.rKrFrcCs t|||}|||||dS)zDraw a regular polygon.N)!_compute_regular_polygon_verticesr)r/rrrr.rKrFrCr2r2r3regular_polygons zImageDraw.regular_polygoncCsV|||\}}|dur(|j||d|durR||krR|dkrR|j||d|dS)zDraw a rectangle.Nr r)r@r*draw_rectanglerOr2r2r3 rectangles zImageDraw.rectanglecornersz$tuple[bool, bool, bool, bool] | None)rCrRr.rKrFrrc srt|dttfr2tttt|\\ \ nttt|\ kr\d}t| krpd}t|dur|d|dtt  t  t  d\tr  dkr҈  dkr r r  |||Sdkst s. |||St d} ||\d d d  f d d } dur| drj |d |dfdnB |d|dkrj|d |d fdss | g} dr2| d|d7<drP| d|d8<j| d | g} dr| d|d7<dr| d|d8<j| ddurnkrndkrn| ds dg} dr| d|d7<dr8| d|d8<j| d d g} drz| d|d7<dr| d|d8<j| dsn d g} dr| d|d7<dr| d|d8<j| d d g} dr@| d|d7<dr^| d|d8<j| ddS)zDraw a rounded rectangle.rz&x1 must be greater than or equal to x0z&y1 must be greater than or equal to y0N)TTTTrV)FFr boolr)rsrc s,r:  fddf  fddff}nrt  fddf  fddff}nztfddt  fddf  fddf   fddf  fddffD}|D]4}|rjj|dfqjj|fqdS) Nrmr[rrac3s|]\}}|r|VqdSr<r2)rXrYpartrr2r3reszDImageDraw.rounded_rectangle..draw_corners..r )r? enumerater*ryrG)rspartsr rdrMZfull_xZfull_yr,r/rFZx0x1Zy0y1r2r3 draw_cornerss*  z1ImageDraw.rounded_rectangle..draw_cornersTroF)r=rpr?r rrAr&roundallrPanyrrBr@r*r)r/rCrRr.rKrFrr1rrleftrighttopbottomr2rr3rounded_rectangles     *" *(             zImageDraw.rounded_rectanglerr)textrcCst|trdnd}||vSN  )r=r>)r/rZsplit_characterr2r2r3_multiline_check+szImageDraw._multiline_checkz list[AnyStr]cCs|t|trdndSr)splitr=r>)r/rr2r2r3_multiline_split0szImageDraw._multiline_split)rspacing stroke_widthrcCs|jdd||dd||S)Nr{A)rro)textbbox)r/rrrr2r2r3_multiline_spacing3s zImageDraw._multiline_spacingrUrFtuple[float, float]r>list[str] | Noner)rCrr.ranchorralign directionfeatureslanguager stroke_fillembedded_colorargskwargsrcsrjdvrd}t|dur2d r^ |||| |  Sdddfdd }ddd d d  f dd }||}|durd}| r| dur|| n|}|dur||| ||d n||dS)z Draw text.rr3Embedded color supported only in RGB and RGBA modesNr9r;rB)r.rcs*|\}}|dur&|dus"J|S|Sr<)r@)r.r,rM)r/r2r3getinkos  zImageDraw.text..getinkrrAr)r,rrc sj}|dkrrd}g}tdD]}|t |q"t ddt ddf}zRj |gR|||d\}}|d|d|d|dg}Wnbtyz.j |||gRd|i}Wnt y  }Yn0Yn0|dkr|| d}}t d|d} | d| |\} } jdurj|| | | |jd| |jdf|nj|||dS) NrrrVr )rrrrrr,rDrDrorY)r-rqappendrBr\modfZgetmask2AttributeErrorZgetmask TypeErrorZgetbandstructpackZfillbandrrr}r*rJ) r,rrr_rYrDrzoffsetcolorZ ink_alpharirj rrrrrrrrr/rrCr2r3 draw_textvsn  $   $       "z!ImageDraw.text..draw_text)r)rr&r:getrmultiline_text)r/rCrr.rrrrrrrrrrrrr1rrr,Z stroke_inkr2rr3r?s@ ,6  zImageDraw.text)r9)rCrr.rrrrrrrrrrr9rcCs|dkrd}t||dur"d}n2t|dkrWdS||||f<WnttfydYdS0||fh} t} | rjt} | D]\}}|d|f|d|f||df||dffD]\} } | | f| vs| dks| dkrqz|| | f}WnttfyYq0| | | f|dur2t|||k}n |||fv}|r||| | f<| | | fqq| } | } qvdS)a .. warning:: This method is experimental. Fills a bounded region with a given color. :param image: Target image. :param xy: Seed position (a 2-item coordinate tuple). See :ref:`coordinate-system`. :param value: Fill color. :param border: Optional border value. If given, the region consists of pixels with a color different from the border color. If not given, the region consists of pixels having the same color as the seed pixel. :param thresh: Optional threshold value which specifies a maximum tolerable difference of a pixel value from the 'background' in order for it to be replaced. Useful for filling regions of non-homogeneous, but similar, colors. Nr r)r$ _color_diffr& IndexErrorsetadd)rrCrrrZpixelrirj backgroundedgeZ full_edgeZnew_edgestrdr.r2r2r3 floodfills>    4   rrrBzlist[tuple[float, float]])rrrrcst|tsd}t||dkr*d}t|t|ttfsDd}t|t|dkrtdd|Dsnd}t|ttt t|^nt|dkr t|d ttfr td d|d Drt|d tt fsd}t|t|d dkrd }t|ttt t|d tt |d n d }t|d krBd}t|t|tt fs^d}t|ddddfdd dddfdd dddddd}|||}fdd|DS)u Generate a list of vertices for a 2D regular polygon. :param bounding_circle: The bounding circle is a sequence defined by a point and radius. The polygon is inscribed in this circle. (e.g. ``bounding_circle=(x, y, r)`` or ``((x, y), r)``) :param n_sides: Number of sides (e.g. ``n_sides=3`` for a triangle, ``6`` for a hexagon) :param rotation: Apply an arbitrary rotation to the polygon (e.g. ``rotation=90``, applies a 90 degree rotation) :return: List of regular polygon vertices (e.g. ``[(25, 50), (50, 50), (50, 25), (25, 25)]``) How are the vertices computed? 1. Compute the following variables - theta: Angle between the apothem & the nearest polygon vertex - side_length: Length of each polygon edge - centroid: Center of bounding circle (1st, 2nd elements of bounding_circle) - polygon_radius: Polygon radius (last element of bounding_circle) - angles: Location of each polygon vertex in polar grid (e.g. A square with 0 degree rotation => [225.0, 315.0, 45.0, 135.0]) 2. For each angle in angles, get the polygon vertex at that angle The vertex is computed using the equation below. X= xcos(φ) + ysin(φ) Y= −xsin(φ) + ycos(φ) Note: φ = angle in degrees x = 0 y = polygon_radius The formula above assumes rotation around the origin. In our case, we are rotating around the centroid. To account for this, we use the formula below X = xcos(φ) + ysin(φ) + centroid_x Y = −xsin(φ) + ycos(φ) + centroid_y zn_sides should be an introzn_sides should be an int > 2z$bounding_circle should be a sequencecss|]}t|ttfVqdSr<r=rBrArWr2r2r3reoz4_compute_regular_polygon_vertices..z0bounding_circle should only contain numeric datarVrcss|]}t|ttfVqdSr<rrWr2r2r3reusr zBbounding_circle centre should contain 2D coordinates (e.g. (x, y))z[bounding_circle should contain 2D coordinates and a radius (e.g. (x, y, r) or ((x, y), r) )z$bounding_circle radius should be > 0z"rotation should be an int or floatz list[float]rAr)rur]rc st|dttd||dttd|ddt|dttd||dttd|ddfS)Nrr[r rV)rr\rfrgrh)rur])centroidr2r3_apply_rotations"z:_compute_regular_polygon_vertices.._apply_rotation)r`rcsdg}||S)Nrr2)r`Z start_point)rpolygon_radiusr2r3_compute_polygon_vertexszB_compute_regular_polygon_vertices.._compute_polygon_vertexrB)rrrcSsRg}d|}dd||}td|D]&}||||7}|dkr&|d8}q&|S)Nr[rg?r)rqr)rrrvr]Z current_angle_r2r2r3 _get_angless  z6_compute_regular_polygon_vertices.._get_anglescsg|] }|qSr2r2)rXr`)rr2r3rZrz5_compute_regular_polygon_vertices..) r=rBrr&rpr?rrrr rA)rrrr1rrvr2)rrrrr3r7sR+  "  r)color1color2rcsJt|tr|n|ft|tr"|n|ftfddtdtDS)zJ Uses 1-norm distance to calculate difference between two values. c3s"|]}t||VqdSr<)absrWfirstsecondr2r3rerz_color_diff..r)r=r?sumrqrr)rrr2rr3rsr)N)NN)Nr)( __future__rr\rcollections.abcrtypesrtypingrrrrr r r6r r Z _deprecaterZ_typingrrr)rKrrrrrAr?rBr>Z_Inkrrrrrrr2r2r2r3 sB         A