##// END OF EJS Templates
latex_to_png returns None when the backend cannot be used...
Takafumi Arakaki -
Show More
@@ -1,167 +1,174 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for handling LaTeX.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2010-2011, IPython Development Team.
10 10 #
11 11 # Distributed under the terms of the Modified BSD License.
12 12 #
13 13 # The full license is in the file COPYING.txt, distributed with this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 from StringIO import StringIO
21 21 from base64 import encodestring
22 22 import os
23 23 import tempfile
24 24 import shutil
25 25 import subprocess
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Tools
29 29 #-----------------------------------------------------------------------------
30 30
31 31
32 32 def latex_to_png(s, encode=False, backend='mpl'):
33 33 """Render a LaTeX string to PNG.
34 34
35 35 Parameters
36 36 ----------
37 37 s : str
38 38 The raw string containing valid inline LaTeX.
39 39 encode : bool, optional
40 40 Should the PNG data bebase64 encoded to make it JSON'able.
41 41 backend : {mpl, dvipng}
42 42 Backend for producing PNG data.
43 43
44 None is returned when the backend cannot be used.
45
44 46 """
45 47 if backend == 'mpl':
46 48 f = latex_to_png_mpl
47 49 elif backend == 'dvipng':
48 50 f = latex_to_png_dvipng
49 51 else:
50 52 raise ValueError('No such backend {0}'.format(backend))
51 53 bin_data = f(s)
52 if encode:
54 if encode and bin_data:
53 55 bin_data = encodestring(bin_data)
54 56 return bin_data
55 57
56 58
57 59 def latex_to_png_mpl(s):
58 from matplotlib import mathtext
60 try:
61 from matplotlib import mathtext
62 except ImportError:
63 return None
59 64
60 65 mt = mathtext.MathTextParser('bitmap')
61 66 f = StringIO()
62 67 mt.to_png(f, s, fontsize=12)
63 68 return f.getvalue()
64 69
65 70
66 71 def latex_to_png_dvipng(s):
67 72 try:
68 73 workdir = tempfile.mkdtemp()
69 74 tmpfile = os.path.join(workdir, "tmp.tex")
70 75 dvifile = os.path.join(workdir, "tmp.dvi")
71 76 outfile = os.path.join(workdir, "tmp.png")
72 77
73 78 with open(tmpfile, "w") as f:
74 79 f.write(_latex_header)
75 80 f.write(s)
76 81 f.write(_latex_footer)
77 82
78 83 subprocess.check_call(
79 84 ["latex", "-halt-on-errror", tmpfile], cwd=workdir)
80 85
81 86 subprocess.check_call(
82 87 ["dvipng", "-T", "tight", "-x", "1500", "-z", "9",
83 88 "-bg", "transparent", "-o", outfile, dvifile], cwd=workdir)
84 89
85 90 with open(outfile) as f:
86 91 bin_data = f.read()
92 except subprocess.CalledProcessError:
93 bin_data = None
87 94 finally:
88 95 shutil.rmtree(workdir)
89 96 return bin_data
90 97
91 98
92
93 99 _latex_header = r'''
94 100 \documentclass{article}
95 101 \usepackage{amsmath}
96 102 \usepackage{amsthm}
97 103 \usepackage{amssymb}
98 104 \usepackage{bm}
99 105 \pagestyle{empty}
100 106 \begin{document}
101 107 '''
102 108
103 109 _latex_footer = r'\end{document}'
104 110
105 111
106 112 _data_uri_template_png = """<img src="data:image/png;base64,%s" alt=%s />"""
107 113
108 114 def latex_to_html(s, alt='image'):
109 115 """Render LaTeX to HTML with embedded PNG data using data URIs.
110 116
111 117 Parameters
112 118 ----------
113 119 s : str
114 120 The raw string containing valid inline LateX.
115 121 alt : str
116 122 The alt text to use for the HTML.
117 123 """
118 124 base64_data = latex_to_png(s, encode=True)
119 return _data_uri_template_png % (base64_data, alt)
125 if base64_data:
126 return _data_uri_template_png % (base64_data, alt)
120 127
121 128
122 129 # From matplotlib, thanks to mdboom. Once this is in matplotlib releases, we
123 130 # will remove.
124 131 def math_to_image(s, filename_or_obj, prop=None, dpi=None, format=None):
125 132 """
126 133 Given a math expression, renders it in a closely-clipped bounding
127 134 box to an image file.
128 135
129 136 *s*
130 137 A math expression. The math portion should be enclosed in
131 138 dollar signs.
132 139
133 140 *filename_or_obj*
134 141 A filepath or writable file-like object to write the image data
135 142 to.
136 143
137 144 *prop*
138 145 If provided, a FontProperties() object describing the size and
139 146 style of the text.
140 147
141 148 *dpi*
142 149 Override the output dpi, otherwise use the default associated
143 150 with the output format.
144 151
145 152 *format*
146 153 The output format, eg. 'svg', 'pdf', 'ps' or 'png'. If not
147 154 provided, will be deduced from the filename.
148 155 """
149 156 from matplotlib import figure
150 157 # backend_agg supports all of the core output formats
151 158 from matplotlib.backends import backend_agg
152 159 from matplotlib.font_manager import FontProperties
153 160 from matplotlib.mathtext import MathTextParser
154 161
155 162 if prop is None:
156 163 prop = FontProperties()
157 164
158 165 parser = MathTextParser('path')
159 166 width, height, depth, _, _ = parser.parse(s, dpi=72, prop=prop)
160 167
161 168 fig = figure.Figure(figsize=(width / 72.0, height / 72.0))
162 169 fig.text(0, depth/height, s, fontproperties=prop)
163 170 backend_agg.FigureCanvasAgg(fig)
164 171 fig.savefig(filename_or_obj, dpi=dpi, format=format)
165 172
166 173 return depth
167 174
General Comments 0
You need to be logged in to leave comments. Login now