Add outline feature to ImageDraw.text()

This change adds an additional method argument to the draw() method
which draws the text in black, before drawing it in the color selected
in the fill parameter.

Additionally due to the positional requirements enforced on the method
by using **kwargs, move to using an explicit signature with default values.

* Helps improve readability
* Allows for easier modification later.
This commit is contained in:
Paddez 2016-11-15 10:48:31 +00:00
parent 76d156bef0
commit a22eedad07
No known key found for this signature in database
GPG Key ID: 1DB178216DA02CD1
3 changed files with 25 additions and 7 deletions

View File

@ -217,13 +217,13 @@ class ImageDraw(object):
return text.split(split_character) return text.split(split_character)
def text(self, xy, text, fill=None, font=None, anchor=None, def text(self, xy, text, fill=None, font=None, anchor=None, spacing=4,
*args, **kwargs): align="left", outline=None):
if self._multiline_check(text): if self._multiline_check(text):
return self.multiline_text(xy, text, fill, font, anchor, return self.multiline_text(xy, text, fill, font, anchor,
*args, **kwargs) spacing, align, outline)
ink, fill = self._getink(fill) ink, fill = self._getink(fill)
print("Outline: %s" % outline)
if font is None: if font is None:
font = self.getfont() font = self.getfont()
if ink is None: if ink is None:
@ -237,10 +237,17 @@ class ImageDraw(object):
mask = font.getmask(text, self.fontmode) mask = font.getmask(text, self.fontmode)
except TypeError: except TypeError:
mask = font.getmask(text) mask = font.getmask(text)
if outline is not None:
color, _ = self._getink(outline)
for offset in range(0, 2):
tmp_xy = list(xy)
for difference in [-1, 1]:
tmp_xy[offset] = xy[offset] + difference
self.draw.draw_bitmap(tmp_xy, mask, color)
self.draw.draw_bitmap(xy, mask, ink) self.draw.draw_bitmap(xy, mask, ink)
def multiline_text(self, xy, text, fill=None, font=None, anchor=None, def multiline_text(self, xy, text, fill=None, font=None, anchor=None,
spacing=4, align="left"): spacing=4, align="left", outline=None):
widths = [] widths = []
max_width = 0 max_width = 0
lines = self._multiline_split(text) lines = self._multiline_split(text)
@ -259,10 +266,9 @@ class ImageDraw(object):
left += (max_width - widths[idx]) left += (max_width - widths[idx])
else: else:
assert False, 'align must be "left", "center" or "right"' assert False, 'align must be "left", "center" or "right"'
self.text((left, top), line, fill, font, anchor) self.text((left, top), line, fill, font, anchor, outline=outline)
top += line_spacing top += line_spacing
left = xy[0] left = xy[0]
def textsize(self, text, font=None, *args, **kwargs): def textsize(self, text, font=None, *args, **kwargs):
"""Get the size of a given string, in pixels.""" """Get the size of a given string, in pixels."""
if self._multiline_check(text): if self._multiline_check(text):

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -127,6 +127,18 @@ try:
target_img = Image.open(target) target_img = Image.open(target)
self.assert_image_similar(im, target_img, .5) self.assert_image_similar(im, target_img, .5)
def test_stroke_text(self):
im = Image.new(mode='RGB', size=(300, 100))
draw = ImageDraw.Draw(im)
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
draw.text((5, 5), TEST_TEXT, 'black', font=ttf,
outline='white')
target = 'Tests/images/stroked_text_image.png'
target_img = Image.open(target)
self.assert_image_similar(im, target_img, .5)
def test_render_multiline(self): def test_render_multiline(self):
im = Image.new(mode='RGB', size=(300, 100)) im = Image.new(mode='RGB', size=(300, 100))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)