mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-11 20:27:06 +03:00
0b178edbc8
This pull request adds support for languages that require complex text layout. We are using the Raqm library, that wraps FriBidi (for bidirectional text support) and HarfBuzz (for text shaping), and does proper BiDi and script itemization: https://github.com/HOST-Oman/libraqm This should fix #1089.
435 lines
19 KiB
Python
435 lines
19 KiB
Python
#
|
|
# 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
|
|
import os
|
|
import sys
|
|
|
|
|
|
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)
|
|
|
|
# delegate critical operations to internal type
|
|
self.getsize = self.font.getsize
|
|
self.getmask = self.font.getmask
|
|
|
|
|
|
##
|
|
# 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=""):
|
|
# FIXME: use service provider instead
|
|
|
|
self.path = font
|
|
self.size = size
|
|
self.index = index
|
|
self.encoding = encoding
|
|
|
|
if isPath(font):
|
|
self.font = core.getfont(font, size, index, encoding)
|
|
else:
|
|
self.font_bytes = font.read()
|
|
self.font = core.getfont(
|
|
"", size, index, encoding, self.font_bytes)
|
|
|
|
def getname(self):
|
|
return self.font.family, self.font.style
|
|
|
|
def getmetrics(self):
|
|
return self.font.ascent, self.font.descent
|
|
|
|
def getsize(self, text):
|
|
size, offset = self.font.getsize(text)
|
|
return (size[0] + offset[0], size[1] + offset[1])
|
|
|
|
def getoffset(self, text):
|
|
return self.font.getsize(text)[1]
|
|
|
|
def getmask(self, text, mode="", direction=None, features=[]):
|
|
return self.getmask2(text, mode, direction, features)[0]
|
|
|
|
def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, features=[]):
|
|
size, offset = self.font.getsize(text)
|
|
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):
|
|
"""
|
|
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)
|
|
|
|
|
|
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):
|
|
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=""):
|
|
im = self.font.getmask(text, mode)
|
|
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=""):
|
|
"""
|
|
Load a TrueType or OpenType font file, and create a font object.
|
|
This function loads a font object from the given file, and creates
|
|
a font object for a font of the given size.
|
|
|
|
This function requires the _imagingft service.
|
|
|
|
:param font: A truetype font file. 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.
|
|
:return: A font object.
|
|
:exception IOError: If the file could not be read.
|
|
"""
|
|
|
|
try:
|
|
return FreeTypeFont(font, size, index, encoding)
|
|
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)
|
|
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)
|
|
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)
|
|
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 bytes is str:
|
|
filename = filename.encode("utf-8")
|
|
else:
|
|
filename = filename.decode("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
|