|
|
- #
- # The Python Imaging Library.
- # $Id$
- #
- # PIL raster font management
- #
- # History:
- # 1996-08-07 fl created (experimental)
- # 1997-08-25 fl minor adjustments to handle fonts from pilfont 0.3
- # 1999-02-06 fl rewrote most font management stuff in C
- # 1999-03-17 fl take pth files into account in load_path (from Richard Jones)
- # 2001-02-17 fl added freetype support
- # 2001-05-09 fl added TransposedFont wrapper class
- # 2002-03-04 fl make sure we have a "L" or "1" font
- # 2002-12-04 fl skip non-directory entries in the system path
- # 2003-04-29 fl add embedded default font
- # 2003-09-27 fl added support for truetype charmap encodings
- #
- # Todo:
- # Adapt to PILFONT2 format (16-bit fonts, compressed, single file)
- #
- # Copyright (c) 1997-2003 by Secret Labs AB
- # Copyright (c) 1996-2003 by Fredrik Lundh
- #
- # See the README file for information on usage and redistribution.
- #
-
- from . import Image
- from ._util import isDirectory, isPath, py3
- import os
- import sys
-
- LAYOUT_BASIC = 0
- LAYOUT_RAQM = 1
-
-
- class _imagingft_not_installed(object):
- # module placeholder
- def __getattr__(self, id):
- raise ImportError("The _imagingft C module is not installed")
-
-
- try:
- from . import _imagingft as core
- except ImportError:
- core = _imagingft_not_installed()
-
-
- # FIXME: add support for pilfont2 format (see FontFile.py)
-
- # --------------------------------------------------------------------
- # Font metrics format:
- # "PILfont" LF
- # fontdescriptor LF
- # (optional) key=value... LF
- # "DATA" LF
- # binary data: 256*10*2 bytes (dx, dy, dstbox, srcbox)
- #
- # To place a character, cut out srcbox and paste at dstbox,
- # relative to the character position. Then move the character
- # position according to dx, dy.
- # --------------------------------------------------------------------
-
-
- class ImageFont(object):
- "PIL font wrapper"
-
- def _load_pilfont(self, filename):
-
- with open(filename, "rb") as fp:
- for ext in (".png", ".gif", ".pbm"):
- try:
- fullname = os.path.splitext(filename)[0] + ext
- image = Image.open(fullname)
- except:
- pass
- else:
- if image and image.mode in ("1", "L"):
- break
- else:
- raise IOError("cannot find glyph data file")
-
- self.file = fullname
-
- return self._load_pilfont_data(fp, image)
-
- def _load_pilfont_data(self, file, image):
-
- # read PILfont header
- if file.readline() != b"PILfont\n":
- raise SyntaxError("Not a PILfont file")
- file.readline().split(b";")
- self.info = [] # FIXME: should be a dictionary
- while True:
- s = file.readline()
- if not s or s == b"DATA\n":
- break
- self.info.append(s)
-
- # read PILfont metrics
- data = file.read(256*20)
-
- # check image
- if image.mode not in ("1", "L"):
- raise TypeError("invalid font image mode")
-
- image.load()
-
- self.font = Image.core.font(image.im, data)
-
- def getsize(self, text, *args, **kwargs):
- return self.font.getsize(text)
-
- def getmask(self, text, mode="", *args, **kwargs):
- return self.font.getmask(text, mode)
-
-
- ##
- # Wrapper for FreeType fonts. Application code should use the
- # <b>truetype</b> factory function to create font objects.
-
- class FreeTypeFont(object):
- "FreeType font wrapper (requires _imagingft service)"
-
- def __init__(self, font=None, size=10, index=0, encoding="",
- layout_engine=None):
- # FIXME: use service provider instead
-
- self.path = font
- self.size = size
- self.index = index
- self.encoding = encoding
-
- if layout_engine not in (LAYOUT_BASIC, LAYOUT_RAQM):
- layout_engine = LAYOUT_BASIC
- if core.HAVE_RAQM:
- layout_engine = LAYOUT_RAQM
- if layout_engine == LAYOUT_RAQM and not core.HAVE_RAQM:
- layout_engine = LAYOUT_BASIC
-
- self.layout_engine = layout_engine
-
- if isPath(font):
- self.font = core.getfont(font, size, index, encoding,
- layout_engine=layout_engine)
- else:
- self.font_bytes = font.read()
- self.font = core.getfont(
- "", size, index, encoding, self.font_bytes, layout_engine)
-
- def _multiline_split(self, text):
- split_character = "\n" if isinstance(text, str) else b"\n"
- return text.split(split_character)
-
- def getname(self):
- return self.font.family, self.font.style
-
- def getmetrics(self):
- return self.font.ascent, self.font.descent
-
- def getsize(self, text, direction=None, features=None):
- size, offset = self.font.getsize(text, direction, features)
- return (size[0] + offset[0], size[1] + offset[1])
-
- def getsize_multiline(self, text, direction=None,
- spacing=4, features=None):
- max_width = 0
- lines = self._multiline_split(text)
- line_spacing = self.getsize('A')[1] + spacing
- for line in lines:
- line_width, line_height = self.getsize(line, direction, features)
- max_width = max(max_width, line_width)
-
- return max_width, len(lines)*line_spacing - spacing
-
- def getoffset(self, text):
- return self.font.getsize(text)[1]
-
- def getmask(self, text, mode="", direction=None, features=None):
- return self.getmask2(text, mode, direction=direction,
- features=features)[0]
-
- def getmask2(self, text, mode="", fill=Image.core.fill, direction=None,
- features=None, *args, **kwargs):
- size, offset = self.font.getsize(text, direction, features)
- im = fill("L", size, 0)
- self.font.render(text, im.id, mode == "1", direction, features)
- return im, offset
-
- def font_variant(self, font=None, size=None, index=None, encoding=None,
- layout_engine=None):
- """
- Create a copy of this FreeTypeFont object,
- using any specified arguments to override the settings.
-
- Parameters are identical to the parameters used to initialize this
- object.
-
- :return: A FreeTypeFont object.
- """
- return FreeTypeFont(
- font=self.path if font is None else font,
- size=self.size if size is None else size,
- index=self.index if index is None else index,
- encoding=self.encoding if encoding is None else encoding,
- layout_engine=self.layout_engine if layout_engine is None else layout_engine
- )
-
-
- class TransposedFont(object):
- "Wrapper for writing rotated or mirrored text"
-
- def __init__(self, font, orientation=None):
- """
- Wrapper that creates a transposed font from any existing font
- object.
-
- :param font: A font object.
- :param orientation: An optional orientation. If given, this should
- be one of Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM,
- Image.ROTATE_90, Image.ROTATE_180, or Image.ROTATE_270.
- """
- self.font = font
- self.orientation = orientation # any 'transpose' argument, or None
-
- def getsize(self, text, *args, **kwargs):
- w, h = self.font.getsize(text)
- if self.orientation in (Image.ROTATE_90, Image.ROTATE_270):
- return h, w
- return w, h
-
- def getmask(self, text, mode="", *args, **kwargs):
- im = self.font.getmask(text, mode, *args, **kwargs)
- if self.orientation is not None:
- return im.transpose(self.orientation)
- return im
-
-
- def load(filename):
- """
- Load a font file. This function loads a font object from the given
- bitmap font file, and returns the corresponding font object.
-
- :param filename: Name of font file.
- :return: A font object.
- :exception IOError: If the file could not be read.
- """
- f = ImageFont()
- f._load_pilfont(filename)
- return f
-
-
- def truetype(font=None, size=10, index=0, encoding="",
- layout_engine=None):
- """
- Load a TrueType or OpenType font from a file or file-like object,
- and create a font object.
- This function loads a font object from the given file or file-like
- object, and creates a font object for a font of the given size.
-
- This function requires the _imagingft service.
-
- :param font: A filename or file-like object containing a TrueType font.
- Under Windows, if the file is not found in this filename,
- the loader also looks in Windows :file:`fonts/` directory.
- :param size: The requested size, in points.
- :param index: Which font face to load (default is first available face).
- :param encoding: Which font encoding to use (default is Unicode). Common
- encodings are "unic" (Unicode), "symb" (Microsoft
- Symbol), "ADOB" (Adobe Standard), "ADBE" (Adobe Expert),
- and "armn" (Apple Roman). See the FreeType documentation
- for more information.
- :param layout_engine: Which layout engine to use, if available:
- `ImageFont.LAYOUT_BASIC` or `ImageFont.LAYOUT_RAQM`.
- :return: A font object.
- :exception IOError: If the file could not be read.
- """
-
- try:
- return FreeTypeFont(font, size, index, encoding, layout_engine)
- except IOError:
- ttf_filename = os.path.basename(font)
-
- dirs = []
- if sys.platform == "win32":
- # check the windows font repository
- # NOTE: must use uppercase WINDIR, to work around bugs in
- # 1.5.2's os.environ.get()
- windir = os.environ.get("WINDIR")
- if windir:
- dirs.append(os.path.join(windir, "fonts"))
- elif sys.platform in ('linux', 'linux2'):
- lindirs = os.environ.get("XDG_DATA_DIRS", "")
- if not lindirs:
- # According to the freedesktop spec, XDG_DATA_DIRS should
- # default to /usr/share
- lindirs = '/usr/share'
- dirs += [os.path.join(lindir, "fonts")
- for lindir in lindirs.split(":")]
- elif sys.platform == 'darwin':
- dirs += ['/Library/Fonts', '/System/Library/Fonts',
- os.path.expanduser('~/Library/Fonts')]
-
- ext = os.path.splitext(ttf_filename)[1]
- first_font_with_a_different_extension = None
- for directory in dirs:
- for walkroot, walkdir, walkfilenames in os.walk(directory):
- for walkfilename in walkfilenames:
- if ext and walkfilename == ttf_filename:
- fontpath = os.path.join(walkroot, walkfilename)
- return FreeTypeFont(fontpath, size, index,
- encoding, layout_engine)
- elif (not ext and
- os.path.splitext(walkfilename)[0] == ttf_filename):
- fontpath = os.path.join(walkroot, walkfilename)
- if os.path.splitext(fontpath)[1] == '.ttf':
- return FreeTypeFont(fontpath, size, index,
- encoding, layout_engine)
- if not ext \
- and first_font_with_a_different_extension is None:
- first_font_with_a_different_extension = fontpath
- if first_font_with_a_different_extension:
- return FreeTypeFont(first_font_with_a_different_extension, size,
- index, encoding, layout_engine)
- raise
-
-
- def load_path(filename):
- """
- Load font file. Same as :py:func:`~PIL.ImageFont.load`, but searches for a
- bitmap font along the Python path.
-
- :param filename: Name of font file.
- :return: A font object.
- :exception IOError: If the file could not be read.
- """
- for directory in sys.path:
- if isDirectory(directory):
- if not isinstance(filename, str):
- if py3:
- filename = filename.decode("utf-8")
- else:
- filename = filename.encode("utf-8")
- try:
- return load(os.path.join(directory, filename))
- except IOError:
- pass
- raise IOError("cannot find font file")
-
-
- def load_default():
- """Load a "better than nothing" default font.
-
- .. versionadded:: 1.1.4
-
- :return: A font object.
- """
- from io import BytesIO
- import base64
- f = ImageFont()
- f._load_pilfont_data(
- # courB08
- BytesIO(base64.b64decode(b'''
- UElMZm9udAo7Ozs7OzsxMDsKREFUQQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAA//8AAQAAAAAAAAABAAEA
- BgAAAAH/+gADAAAAAQAAAAMABgAGAAAAAf/6AAT//QADAAAABgADAAYAAAAA//kABQABAAYAAAAL
- AAgABgAAAAD/+AAFAAEACwAAABAACQAGAAAAAP/5AAUAAAAQAAAAFQAHAAYAAP////oABQAAABUA
- AAAbAAYABgAAAAH/+QAE//wAGwAAAB4AAwAGAAAAAf/5AAQAAQAeAAAAIQAIAAYAAAAB//kABAAB
- ACEAAAAkAAgABgAAAAD/+QAE//0AJAAAACgABAAGAAAAAP/6AAX//wAoAAAALQAFAAYAAAAB//8A
- BAACAC0AAAAwAAMABgAAAAD//AAF//0AMAAAADUAAQAGAAAAAf//AAMAAAA1AAAANwABAAYAAAAB
- //kABQABADcAAAA7AAgABgAAAAD/+QAFAAAAOwAAAEAABwAGAAAAAP/5AAYAAABAAAAARgAHAAYA
- AAAA//kABQAAAEYAAABLAAcABgAAAAD/+QAFAAAASwAAAFAABwAGAAAAAP/5AAYAAABQAAAAVgAH
- AAYAAAAA//kABQAAAFYAAABbAAcABgAAAAD/+QAFAAAAWwAAAGAABwAGAAAAAP/5AAUAAABgAAAA
- ZQAHAAYAAAAA//kABQAAAGUAAABqAAcABgAAAAD/+QAFAAAAagAAAG8ABwAGAAAAAf/8AAMAAABv
- AAAAcQAEAAYAAAAA//wAAwACAHEAAAB0AAYABgAAAAD/+gAE//8AdAAAAHgABQAGAAAAAP/7AAT/
- /gB4AAAAfAADAAYAAAAB//oABf//AHwAAACAAAUABgAAAAD/+gAFAAAAgAAAAIUABgAGAAAAAP/5
- AAYAAQCFAAAAiwAIAAYAAP////oABgAAAIsAAACSAAYABgAA////+gAFAAAAkgAAAJgABgAGAAAA
- AP/6AAUAAACYAAAAnQAGAAYAAP////oABQAAAJ0AAACjAAYABgAA////+gAFAAAAowAAAKkABgAG
- AAD////6AAUAAACpAAAArwAGAAYAAAAA//oABQAAAK8AAAC0AAYABgAA////+gAGAAAAtAAAALsA
- BgAGAAAAAP/6AAQAAAC7AAAAvwAGAAYAAP////oABQAAAL8AAADFAAYABgAA////+gAGAAAAxQAA
- AMwABgAGAAD////6AAUAAADMAAAA0gAGAAYAAP////oABQAAANIAAADYAAYABgAA////+gAGAAAA
- 2AAAAN8ABgAGAAAAAP/6AAUAAADfAAAA5AAGAAYAAP////oABQAAAOQAAADqAAYABgAAAAD/+gAF
- AAEA6gAAAO8ABwAGAAD////6AAYAAADvAAAA9gAGAAYAAAAA//oABQAAAPYAAAD7AAYABgAA////
- +gAFAAAA+wAAAQEABgAGAAD////6AAYAAAEBAAABCAAGAAYAAP////oABgAAAQgAAAEPAAYABgAA
- ////+gAGAAABDwAAARYABgAGAAAAAP/6AAYAAAEWAAABHAAGAAYAAP////oABgAAARwAAAEjAAYA
- BgAAAAD/+gAFAAABIwAAASgABgAGAAAAAf/5AAQAAQEoAAABKwAIAAYAAAAA//kABAABASsAAAEv
- AAgABgAAAAH/+QAEAAEBLwAAATIACAAGAAAAAP/5AAX//AEyAAABNwADAAYAAAAAAAEABgACATcA
- AAE9AAEABgAAAAH/+QAE//wBPQAAAUAAAwAGAAAAAP/7AAYAAAFAAAABRgAFAAYAAP////kABQAA
- AUYAAAFMAAcABgAAAAD/+wAFAAABTAAAAVEABQAGAAAAAP/5AAYAAAFRAAABVwAHAAYAAAAA//sA
- BQAAAVcAAAFcAAUABgAAAAD/+QAFAAABXAAAAWEABwAGAAAAAP/7AAYAAgFhAAABZwAHAAYAAP//
- //kABQAAAWcAAAFtAAcABgAAAAD/+QAGAAABbQAAAXMABwAGAAAAAP/5AAQAAgFzAAABdwAJAAYA
- AP////kABgAAAXcAAAF+AAcABgAAAAD/+QAGAAABfgAAAYQABwAGAAD////7AAUAAAGEAAABigAF
- AAYAAP////sABQAAAYoAAAGQAAUABgAAAAD/+wAFAAABkAAAAZUABQAGAAD////7AAUAAgGVAAAB
- mwAHAAYAAAAA//sABgACAZsAAAGhAAcABgAAAAD/+wAGAAABoQAAAacABQAGAAAAAP/7AAYAAAGn
- AAABrQAFAAYAAAAA//kABgAAAa0AAAGzAAcABgAA////+wAGAAABswAAAboABQAGAAD////7AAUA
- AAG6AAABwAAFAAYAAP////sABgAAAcAAAAHHAAUABgAAAAD/+wAGAAABxwAAAc0ABQAGAAD////7
- AAYAAgHNAAAB1AAHAAYAAAAA//sABQAAAdQAAAHZAAUABgAAAAH/+QAFAAEB2QAAAd0ACAAGAAAA
- Av/6AAMAAQHdAAAB3gAHAAYAAAAA//kABAABAd4AAAHiAAgABgAAAAD/+wAF//0B4gAAAecAAgAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAB
- //sAAwACAecAAAHpAAcABgAAAAD/+QAFAAEB6QAAAe4ACAAGAAAAAP/5AAYAAAHuAAAB9AAHAAYA
- AAAA//oABf//AfQAAAH5AAUABgAAAAD/+QAGAAAB+QAAAf8ABwAGAAAAAv/5AAMAAgH/AAACAAAJ
- AAYAAAAA//kABQABAgAAAAIFAAgABgAAAAH/+gAE//sCBQAAAggAAQAGAAAAAP/5AAYAAAIIAAAC
- DgAHAAYAAAAB//kABf/+Ag4AAAISAAUABgAA////+wAGAAACEgAAAhkABQAGAAAAAP/7AAX//gIZ
- AAACHgADAAYAAAAA//wABf/9Ah4AAAIjAAEABgAAAAD/+QAHAAACIwAAAioABwAGAAAAAP/6AAT/
- +wIqAAACLgABAAYAAAAA//kABP/8Ai4AAAIyAAMABgAAAAD/+gAFAAACMgAAAjcABgAGAAAAAf/5
- AAT//QI3AAACOgAEAAYAAAAB//kABP/9AjoAAAI9AAQABgAAAAL/+QAE//sCPQAAAj8AAgAGAAD/
- ///7AAYAAgI/AAACRgAHAAYAAAAA//kABgABAkYAAAJMAAgABgAAAAH//AAD//0CTAAAAk4AAQAG
- AAAAAf//AAQAAgJOAAACUQADAAYAAAAB//kABP/9AlEAAAJUAAQABgAAAAH/+QAF//4CVAAAAlgA
- BQAGAAD////7AAYAAAJYAAACXwAFAAYAAP////kABgAAAl8AAAJmAAcABgAA////+QAGAAACZgAA
- Am0ABwAGAAD////5AAYAAAJtAAACdAAHAAYAAAAA//sABQACAnQAAAJ5AAcABgAA////9wAGAAAC
- eQAAAoAACQAGAAD////3AAYAAAKAAAAChwAJAAYAAP////cABgAAAocAAAKOAAkABgAA////9wAG
- AAACjgAAApUACQAGAAD////4AAYAAAKVAAACnAAIAAYAAP////cABgAAApwAAAKjAAkABgAA////
- +gAGAAACowAAAqoABgAGAAAAAP/6AAUAAgKqAAACrwAIAAYAAP////cABQAAAq8AAAK1AAkABgAA
- ////9wAFAAACtQAAArsACQAGAAD////3AAUAAAK7AAACwQAJAAYAAP////gABQAAAsEAAALHAAgA
- BgAAAAD/9wAEAAACxwAAAssACQAGAAAAAP/3AAQAAALLAAACzwAJAAYAAAAA//cABAAAAs8AAALT
- AAkABgAAAAD/+AAEAAAC0wAAAtcACAAGAAD////6AAUAAALXAAAC3QAGAAYAAP////cABgAAAt0A
- AALkAAkABgAAAAD/9wAFAAAC5AAAAukACQAGAAAAAP/3AAUAAALpAAAC7gAJAAYAAAAA//cABQAA
- Au4AAALzAAkABgAAAAD/9wAFAAAC8wAAAvgACQAGAAAAAP/4AAUAAAL4AAAC/QAIAAYAAAAA//oA
- Bf//Av0AAAMCAAUABgAA////+gAGAAADAgAAAwkABgAGAAD////3AAYAAAMJAAADEAAJAAYAAP//
- //cABgAAAxAAAAMXAAkABgAA////9wAGAAADFwAAAx4ACQAGAAD////4AAYAAAAAAAoABwASAAYA
- AP////cABgAAAAcACgAOABMABgAA////+gAFAAAADgAKABQAEAAGAAD////6AAYAAAAUAAoAGwAQ
- AAYAAAAA//gABgAAABsACgAhABIABgAAAAD/+AAGAAAAIQAKACcAEgAGAAAAAP/4AAYAAAAnAAoA
- LQASAAYAAAAA//gABgAAAC0ACgAzABIABgAAAAD/+QAGAAAAMwAKADkAEQAGAAAAAP/3AAYAAAA5
- AAoAPwATAAYAAP////sABQAAAD8ACgBFAA8ABgAAAAD/+wAFAAIARQAKAEoAEQAGAAAAAP/4AAUA
- AABKAAoATwASAAYAAAAA//gABQAAAE8ACgBUABIABgAAAAD/+AAFAAAAVAAKAFkAEgAGAAAAAP/5
- AAUAAABZAAoAXgARAAYAAAAA//gABgAAAF4ACgBkABIABgAAAAD/+AAGAAAAZAAKAGoAEgAGAAAA
- AP/4AAYAAABqAAoAcAASAAYAAAAA//kABgAAAHAACgB2ABEABgAAAAD/+AAFAAAAdgAKAHsAEgAG
- AAD////4AAYAAAB7AAoAggASAAYAAAAA//gABQAAAIIACgCHABIABgAAAAD/+AAFAAAAhwAKAIwA
- EgAGAAAAAP/4AAUAAACMAAoAkQASAAYAAAAA//gABQAAAJEACgCWABIABgAAAAD/+QAFAAAAlgAK
- AJsAEQAGAAAAAP/6AAX//wCbAAoAoAAPAAYAAAAA//oABQABAKAACgClABEABgAA////+AAGAAAA
- pQAKAKwAEgAGAAD////4AAYAAACsAAoAswASAAYAAP////gABgAAALMACgC6ABIABgAA////+QAG
- AAAAugAKAMEAEQAGAAD////4AAYAAgDBAAoAyAAUAAYAAP////kABQACAMgACgDOABMABgAA////
- +QAGAAIAzgAKANUAEw==
- ''')), Image.open(BytesIO(base64.b64decode(b'''
- iVBORw0KGgoAAAANSUhEUgAAAx4AAAAUAQAAAAArMtZoAAAEwElEQVR4nABlAJr/AHVE4czCI/4u
- Mc4b7vuds/xzjz5/3/7u/n9vMe7vnfH/9++vPn/xyf5zhxzjt8GHw8+2d83u8x27199/nxuQ6Od9
- M43/5z2I+9n9ZtmDBwMQECDRQw/eQIQohJXxpBCNVE6QCCAAAAD//wBlAJr/AgALyj1t/wINwq0g
- LeNZUworuN1cjTPIzrTX6ofHWeo3v336qPzfEwRmBnHTtf95/fglZK5N0PDgfRTslpGBvz7LFc4F
- IUXBWQGjQ5MGCx34EDFPwXiY4YbYxavpnhHFrk14CDAAAAD//wBlAJr/AgKqRooH2gAgPeggvUAA
- Bu2WfgPoAwzRAABAAAAAAACQgLz/3Uv4Gv+gX7BJgDeeGP6AAAD1NMDzKHD7ANWr3loYbxsAD791
- NAADfcoIDyP44K/jv4Y63/Z+t98Ovt+ub4T48LAAAAD//wBlAJr/AuplMlADJAAAAGuAphWpqhMx
- in0A/fRvAYBABPgBwBUgABBQ/sYAyv9g0bCHgOLoGAAAAAAAREAAwI7nr0ArYpow7aX8//9LaP/9
- SjdavWA8ePHeBIKB//81/83ndznOaXx379wAAAD//wBlAJr/AqDxW+D3AABAAbUh/QMnbQag/gAY
- AYDAAACgtgD/gOqAAAB5IA/8AAAk+n9w0AAA8AAAmFRJuPo27ciC0cD5oeW4E7KA/wD3ECMAn2tt
- y8PgwH8AfAxFzC0JzeAMtratAsC/ffwAAAD//wBlAJr/BGKAyCAA4AAAAvgeYTAwHd1kmQF5chkG
- ABoMIHcL5xVpTfQbUqzlAAAErwAQBgAAEOClA5D9il08AEh/tUzdCBsXkbgACED+woQg8Si9VeqY
- lODCn7lmF6NhnAEYgAAA/NMIAAAAAAD//2JgjLZgVGBg5Pv/Tvpc8hwGBjYGJADjHDrAwPzAjv/H
- /Wf3PzCwtzcwHmBgYGcwbZz8wHaCAQMDOwMDQ8MCBgYOC3W7mp+f0w+wHOYxO3OG+e376hsMZjk3
- AAAAAP//YmCMY2A4wMAIN5e5gQETPD6AZisDAwMDgzSDAAPjByiHcQMDAwMDg1nOze1lByRu5/47
- c4859311AYNZzg0AAAAA//9iYGDBYihOIIMuwIjGL39/fwffA8b//xv/P2BPtzzHwCBjUQAAAAD/
- /yLFBrIBAAAA//9i1HhcwdhizX7u8NZNzyLbvT97bfrMf/QHI8evOwcSqGUJAAAA//9iYBB81iSw
- pEE170Qrg5MIYydHqwdDQRMrAwcVrQAAAAD//2J4x7j9AAMDn8Q/BgYLBoaiAwwMjPdvMDBYM1Tv
- oJodAAAAAP//Yqo/83+dxePWlxl3npsel9lvLfPcqlE9725C+acfVLMEAAAA//9i+s9gwCoaaGMR
- evta/58PTEWzr21hufPjA8N+qlnBwAAAAAD//2JiWLci5v1+HmFXDqcnULE/MxgYGBj+f6CaJQAA
- AAD//2Ji2FrkY3iYpYC5qDeGgeEMAwPDvwQBBoYvcTwOVLMEAAAA//9isDBgkP///0EOg9z35v//
- Gc/eeW7BwPj5+QGZhANUswMAAAD//2JgqGBgYGBgqEMXlvhMPUsAAAAA//8iYDd1AAAAAP//AwDR
- w7IkEbzhVQAAAABJRU5ErkJggg==
- '''))))
- return f
|