Get a list of all available fonts in PIL - python

I'm trying to find out what fonts are available to be used in PIL with the font = ImageFont.load() and/or ImageFont.truetype() function. I want to create a list from which I can sample a random font to be used. I haven't found anything in the documentation so far, unfortunately.

I have so far not found a solution with PIL but matplotlib has a function to get all the available fonts on from the system:
system_fonts = matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf')
The font can then be loaded using fnt = ImageFont.truetype(font, 60)

Related

It's possible to create a blurred text with reportlab?

I'm trying to reproduce a blurred/text-shadow effect using reportlab. Something like this.
So far my approach was to work with the filling color (the text itself or the background), but I don't think I'm going to be successful if I follow this path because the class only accepts an opacity (alpha) paramater besides the ones that defines the color itself. Now I'm trying to find some font that will mimic this effect.
So, It's possible to reproduce the desirable effect with reportlab? If yes, which approach should I use to achieve it?
Thank you very much!
I don't see any straightforward way to achieve a blurry effect as you can achieve with CSS or even with the PIL library using reportlab.
You can try one of the following fonts that more-less mimic this effect: Acidic, ExtraBlur, Erthqake Font, Static Buzz Font
, vtks trunkset Font and use the pdfmetrics.registerFont() and TTFont() methods (e.g. using the Static Buzz Font):
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen.canvas import Canvas
canvas = Canvas('temp.pdf')
pdfmetrics.registerFont(TTFont('StaticBuzz', '/path/to/TTF-file/StaticBuzz.ttf')) #Change the path to the .ttf file.
canvas.setFont('StaticBuzz', 32)
canvas.drawString(0, 700, "Sample usage of StaticBuzz Font.")
canvas.save()
If it is an option (free standing text / headline), you could transform the text to a picture first and then blur it using the PIL library.
The filter can be adapted by setting radius so a strong blur effect can be achieved:
from PIL import ImageFilter
from PIL import Image
img = Image.open('test.png')
blurred_img = img.filter(ImageFilter.GaussianBlur(radius=5))
blurred_img.show()

matplotlib + latex + custom ttf font

I have to make a figure in python. I need it to use the font Palatino. I downloaded the font here. I placed it under *\matplotlib\mpl-data\fonts\ttf (which turned out to be useless since I had to provide full path to make it work).
Using the following lines allows me to use the font:
prop = fm.FontProperties(fname='C:/Users/MyPC/pyApp/venv/Lib/site-packages/matplotlib/mpl-data/fonts/ttf/Palatino-Roman.ttf')
mpl.rcParams['font.family'] = prop.get_name()
Yay.
Now when I want to use Latex in matplotlib,
rc('text',usetex=True)
the font is now not the one I want. I tried to follow the official page about that and instead use:
rc('font',**{'family':'serif','serif':['Palatino']})
rc('text', usetex=True)
but I cannot see any difference. I tried all possibilities and it looks like the same font.
What am I doing wrong? Perhaps its the latex side that's lacking the required font package...
You can load any latex packages when using rc('text',usetex=True)
You can add this in your code:
plt.rcParams['text.latex.preamble'] = [r'\usepackage{palatino, mathpazo}']

How to save a ReportLab Canvas as PNG image?

I'm using reportlab to draw a PDF normaly used for printing. How can i save the canvas as a PNG image instead, without using additional binary tools to convert the generated pdf?
I assume i need to convert it to a reportlab Drawing, but don't see a way to do so.
from reportlab.pdfgen import canvas
c = canvas.Canvas("form.pdf", pagesize=(100, 50))
c.drawString(20, 20, 'Example …')
c.save() # but as image
From the 'reportlab-userguide', I found a piece of code, not sure it is useful?
from reportlab.graphics import renderPM
d = Drawing(400, 200)
d.add(Rect(50, 50, 300, 100, fillColor=colors.yellow))
d.add(String(150, 100, 'Hello World', fontSize=18, fillColor=colors.red))
d.add(String(180, 86, 'Special characters \
\xc2\xa2\xc2\xa9\xc2\xae\xc2\xa3\xce\xb1\xce\xb2',
fillColor=colors.red))
renderPM.drawToFile(d, 'example1.png', 'PNG')
It seems that there're no functions in reportlab package to convert Canvas object to PNG image. But you can use another packages (f.e. pdf2image) to convert Canvas to PNG image.
Installation
To use pdf2image package you should install poppler and pdf2image packages. You can find installation instructions here (section "How to install")
After installation you can solve your problem using this approach:
from reportlab.pdfgen import canvas
from pdf2image import convert_from_bytes
c = canvas.Canvas("form.pdf", pagesize=(100, 50))
c.drawString(20, 20, 'Example …')
image = convert_from_bytes(c.getpdfdata())[0]
image.save('form.png')
I found the suggestion in Yan Weitao's answer very helpful. Here's the equivalent of the example in your question:
from reportlab.graphics.renderPM import drawToFile
from reportlab.graphics.shapes import Drawing, String
drawing = Drawing(width=100, height=50)
drawing.contents.append(String(20, 20, 'Example …'))
drawToFile(drawing, 'example.png')
After digging into the drawToFile() function, I think you might be able to use the reportlab.graphics.renderPM.PMCanvas class instead of the standard canvas. It has a saveToFile() method, but my first attempt just generated a blank image, so you'll have to do some experimenting.

What's the name of this font used in this figure?

I want to use this font in matplotlib plotting, but I can not find out the name. Does anyone know?
This figure is got by IDL plotting on Mac OS (10.9) like:
filename = 'name.eps'
myDevice = !D.NAME
SET_PLOT,'ps'
DEVICE,DECOMPOSED=1,ENCAPSULATED=1,/COLOR,FILENAME=filename
......
DEVICE, /CLOSE
SET_PLOT, myDevice
I'm not a font expert, but this looks a lot to me like the font that was used with pen plotters. Looking around for "pen plotter font", turns up "Hershey Vector Font", which looks quite close.
The font is indeed a Hershey vector font: Hershey Simplex Light. This user on Github has the font definition files (otf) that you can copy/clone into your system and set as the default fonts in your matplotlibrc. Not all the characters are included, but you can use fontforge to open the otf and/or sfd files and merge/copy/create missing glyphs.
(updated in 2022)
I think this font is a kind of vector font belonging to the Hershey family.
Here is a set of TTF fonts that are based on the Hershey font https://github.com/yangcht/Hershey_font_TTF.
You can download them and load them when you make plots.

Matplotlib PDF export uses wrong font

I want to generate high-quality diagrams for a presentation. I’m using Python’s matplotlib to generate the graphics. Unfortunately, the PDF export seems to ignore my font settings.
I tried setting the font both by passing a FontProperties object to the text drawing functions and by setting the option globally. For the record, here is a MWE to reproduce the problem:
import scipy
import matplotlib
matplotlib.use('cairo')
import matplotlib.pylab as pylab
import matplotlib.font_manager as fm
data = scipy.arange(5)
for font in ['Helvetica', 'Gill Sans']:
fig = pylab.figure()
ax = fig.add_subplot(111)
ax.bar(data, data)
ax.set_xticks(data)
ax.set_xticklabels(data, fontproperties = fm.FontProperties(family = font))
pylab.savefig('foo-%s.pdf' % font)
In both cases, the produced output is identical and uses Helvetica (and yes, I do have both fonts installed).
Just to be sure, the following doesn’t help either:
matplotlib.rc('font', family = 'Gill Sans')
Finally, if I replace the backend, instead using the native viewer:
matplotlib.use('MacOSX')
I do get the correct font displayed – but only in the viewer GUI. The PDF output is once again wrong.
To be sure – I can set other fonts – but only other classes of font families: I can set serif fonts or fantasy or monospace. But all sans-serif fonts seem to default to Helvetica.
Basically, #Jouni’s is the right answer but since I still had some trouble getting it to work, here’s my final solution:
#!/usr/bin/env python2.6
import scipy
import matplotlib
matplotlib.use('cairo')
import matplotlib.pylab as pylab
import matplotlib.font_manager as fm
font = fm.FontProperties(
family = 'Gill Sans', fname = '/Library/Fonts/GillSans.ttc')
data = scipy.arange(5)
fig = pylab.figure()
ax = fig.add_subplot(111)
ax.bar(data, data)
ax.set_yticklabels(ax.get_yticks(), fontproperties = font)
ax.set_xticklabels(ax.get_xticks(), fontproperties = font)
pylab.savefig('foo.pdf')
Notice that the font has to be set explicitly using the fontproperties key. Apparently, there’s no rc setting for the fname property (at least I didn’t find it).
Giving a family key in the instantiation of font isn’t strictly necessary here, it will be ignored by the PDF backend.
This code works with the cairo backend only. Using MacOSX won’t work.
The "family" argument and the corresponding rc parameter are not meant to specify the name of the font can actually be used this way. There's an (arguably baroque) CSS-like font selection system that helps the same script work on different computers, selecting the closest font available. The usually recommended way to use e.g. Gill Sans is to add it to the front of the value of the rc parameter font.sans-serif (see sample rc file), and then set font.family to sans-serif.
This can be annoying if the font manager decides for some obscure reason that Gill Sans is not the closest match to your specification. A way to bypass the font selection logic is to use FontProperties(fname='/path/to/font.ttf') (docstring).
In your case, I suspect that the MacOSX backend uses fonts via the operating system's mechanisms and so automatically supports all kinds of fonts, but the pdf backend has its own font support code that doesn't support your version of Gill Sans.
This is an addition to the answers above if you came here for a non-cairo backend.
The pdf-backend of matplotlib does not yet support true type font collections (saved as .ttc files). See this issue.
The currently suggested workaround is to extract the font-of-interest from a .ttc file and save it as a .ttf file. And then use that font in the way described by Konrad Rudolph.
You can use the python-package fonttools to achieve this:
font = TTFont("/System/Library/Fonts/Helvetica.ttc", fontNumber=0)
font.save("Helvetica-regular.ttf")
As far as I can see, it is not possible to make this setting "global" by passing the path to this new .ttf file to the rc. If you are really desperate, you could try to extract all fonts from a .ttc into separate .ttf files, uninstall the .ttc and install the ttfs separately. To have the extracted font side-by-side with the original font from the .ttc, you need to change the font name with tools like FontForge. I haven't tested this, though.
Check if you are rendering the text with LaTeX, i.e., if text.usetex is set to True. Because LaTeX rendering only supports a few fonts, it largely ignores/overwrites your other fonts settings. This might be the cause.

Categories

Resources