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