Advertisement
Guest User

Untitled

a guest
Jul 16th, 2019
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.47 KB | None | 0 0
  1. """
  2. PIL Line Writer
  3.  
  4. Simple class for writing multiline text centered on an image with even line
  5. spacing.
  6.  
  7. To use create a line writer object by passing a PIL image object and a padding
  8. value. Then to write text call the LineWriter's text method with the text you
  9. would like centered on the image over multiple lines. It also takes an optional
  10. line height argument which will scale the line heights. Additionally you can
  11. pass any keyword settings that are valid for ImageDraw.draw.text.
  12.  
  13. Example:
  14. image = Image.new("RGBA", (300, 300), "yellow")
  15. writer = LineWriter(image, 60)
  16. writer.text(
  17. "To the inspiration of necessity, we owe half the wise, beautiful, and useful blessings of the world.",
  18. 1.5,
  19. fill="black"
  20. )
  21. image.show()
  22. """
  23. from PIL import Image, ImageDraw
  24.  
  25.  
  26. class LineWriter:
  27. """ Simple class for writing multiline text centered on a PIL image with
  28. even line spacing. """
  29. def __init__(self, image: Image.Image, padding: int, offset_x: int = 0, offset_y: int = 0):
  30. self._image = image
  31. self._draw = ImageDraw.Draw(image)
  32. self._padding = padding
  33. self._last_line_y = 0
  34. self._offset_x = offset_x
  35. self._offset_y = offset_y
  36.  
  37. @property
  38. def height(self) -> int:
  39. """ Height of the image. """
  40. return self._image.size[1]
  41.  
  42. @property
  43. def last_line_y(self) -> int:
  44. """ Gives the y position after the last line drawn. """
  45. return self._last_line_y
  46.  
  47. @property
  48. def width(self) -> int:
  49. """ Width of the image. """
  50. return self._image.size[0]
  51.  
  52. def line_height(self, font) -> int:
  53. """ Height of our standard line. """
  54. return self._draw.textsize("hj", font=font)[0]
  55.  
  56. def text(self, message: str, line_height: float=1.0, **settings):
  57. """ Writes the text centered on the image. Takes a line height argument
  58. for scaling the line height and also takes all valid keywords for
  59. ImageDraw.Draw.text. """
  60. lines = self._build_lines(message, settings.get("font"))
  61. height = self.line_height(settings.get("font")) * line_height
  62. self._last_line_y = (self.height - len(lines) * height) // 2
  63. for line in lines:
  64. width, _ = self._draw.textsize(line, settings.get("font"))
  65. self._draw.text(
  66. (
  67. (self.width - width) // 2 + self._offset_x,
  68. self.last_line_y + self._offset_y
  69. ),
  70. line,
  71. **settings
  72. )
  73. self._last_line_y += height
  74.  
  75. def _build_lines(self, message: str, font):
  76. """ Breaks a line of text up into a series of lines that fit onto the
  77. image with the correct padding. """
  78. lines = []
  79. line = []
  80. for word in message.split(" "):
  81. test_line = list(line)
  82. test_line.append(word)
  83. width, _ = self._draw.textsize(" ".join(test_line), font=font)
  84. if width > self.width - self._padding * 2:
  85. lines.append(" ".join(line))
  86. line = [word]
  87. else:
  88. line = test_line
  89. if line:
  90. lines.append(" ".join(line))
  91. return lines
  92.  
  93.  
  94. if __name__ == "__main__":
  95. image = Image.new("RGBA", (300, 300), "yellow")
  96. writer = LineWriter(image, 60)
  97. writer.text(
  98. "To the inspiration of necessity, we owe half the wise, beautiful, and useful blessings of the world.",
  99. 1.5,
  100. fill="black"
  101. )
  102. image.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement