28

I have a function I am consuming that returns a string of latex code. I need to generate an image from this. Most of the methods I have seen for doing so suggest calling an external application via say the subprocess module which will generate the image for me.

However, management is not keen on this as it will require external users to install additional software in addition to our own which, with our user base, is not something we can assume to be a simple task.

So are there any python libraries that will accomplish the task of taking latex into a format (such as an image file) which is displayable in a GUI?

Mark Roddy
  • 27,122
  • 19
  • 67
  • 71
  • 2
    Do you want to render the LaTeX code, or just display the source? If the former, beware that reimplementing TeX in Python is crazy. – user57368 Sep 04 '09 at 22:15
  • I need to display rendered latex. If it helps for clarification, I need to display rendered math equations, not entire documents. – Mark Roddy Sep 04 '09 at 22:24

8 Answers8

36

SymPy has a builtin preview function that does this.

expr = sin(sqrt(x**2 + 20)) + 1
preview(expr, viewer='file', filename='output.png')

generates

enter image description here

There are lots of options to preview to change the format of the output (for instance, if you don't like the Euler font you can set euler=False).

preview also accepts a LaTeX string instead of a SymPy expression if you have that

preview(r'$$\int_0^1 e^x\,dx$$', viewer='file', filename='test.png', euler=False)

enter image description here

asmeurer
  • 86,894
  • 26
  • 169
  • 240
  • 1
    I am running this on my raspberry pi. When i do this i get `RuntimeError: latex program is not installed`. Do you know how i can install this. I tried texlive but i do not want a gigabyte file on my pi –  May 21 '18 at 10:42
  • @BenWebb sorry, LaTeX is not a small dependency. There may be a way to get a trimmed down installation more suitable for a pi. LaTeX comes with a lot of extra stuff that you won't need for this, like extra fonts, documentation, and so on. I would ask on https://raspberrypi.stackexchange.com/. Alternately, you might be able to get something using MathJax, though it likely won't be easy (see https://stackoverflow.com/questions/9969587/how-to-convert-mathjax-formula-to-img for some suggestions). Or just use matplotlib's renderer (not as good as LaTeX but easy to install). See the other answer. – asmeurer May 22 '18 at 02:25
  • Sorry, do you know we can adjust the resolution/dpi of the png output file? – snowflake Sep 27 '18 at 11:45
  • @snowflake you can pass flags through to dvipng, though unfortunately these affect the image size but not its resolution. The best solution I've found is to use PIL to modify the image resolution. Also be aware that image viewers sometimes ignore the resolution in the png file if it's too large. – asmeurer Sep 27 '18 at 14:12
  • Hey, thanks for the reply, I realised that i can add a "-D 300" flag to change the dpi in the default_option of preview. That worked out for me. :) – snowflake Sep 28 '18 at 15:13
  • 3
    For completeness sake, and for other people looking to adjust the resolution of the latex image, you can put the dvioptions=["-T", "tight", "-z", "0", "--truecolor", "-D 600"] for dpi 600 in the argument of preview function. – snowflake Sep 29 '18 at 03:41
  • @snowflake: Thanks! Why is that so bad documented?! You made my day! Is there a way to make the background transparent? – MuellerSeb Oct 01 '18 at 15:39
  • 2
    OK, found it myself. you have to append ["-bg", "Transparent"] to the dvioptions: dvioptions=["-T", "tight", "-z", "0", "--truecolor", "-D 600", "-bg", "Transparent"] – MuellerSeb Oct 01 '18 at 15:55
  • 1
    `man dvipng` will show you all the dvipng options. Though we would also accept a pull request to SymPy to document the common dvipng options in the `preview` docstring. – asmeurer Oct 02 '18 at 17:23
18

this answer might not have been available at the time when the question was asked, but i will add it for those seeking a solution as of 2015.

you can use matplotlib.pyplot to render an equation in a graph with axes, and then remove the axes manually. you can also generate the latex with sympy:

#!/usr/bin/env python2.7                                                        

import matplotlib.pyplot as plt                                                 
import sympy                                                                    

x = sympy.symbols('x')                                                          
y = 1 + sympy.sin(sympy.sqrt(x**2 + 20))                                         
lat = sympy.latex(y)                                                            

#add text                                                                       
plt.text(0, 0.6, r"$%s$" % lat, fontsize = 50)                                  

#hide axes                                                                      
fig = plt.gca()                                                                 
fig.axes.get_xaxis().set_visible(False)                                         
fig.axes.get_yaxis().set_visible(False)                                         
plt.draw() #or savefig                                                          
plt.show()

tested with sympy 0.7.6 and matplotlib 1.4.3

mulllhausen
  • 4,225
  • 7
  • 49
  • 71
  • But pyplot uses its own LaTeX renderer, which is not always the greatest (compared to real LaTeX). It will work without a LaTeX installation, though, which can be a plus. – asmeurer Mar 20 '17 at 21:31
7

This is a bit ugly solution I often use, but I found it easiest to use in many cases.

import matplotlib.pyplot as plt
import io
from PIL import Image, ImageChops

white = (255, 255, 255, 255)

def latex_to_img(tex):
    buf = io.BytesIO()
    plt.rc('text', usetex=True)
    plt.rc('font', family='serif')
    plt.axis('off')
    plt.text(0.05, 0.5, f'${tex}$', size=40)
    plt.savefig(buf, format='png')
    plt.close()

    im = Image.open(buf)
    bg = Image.new(im.mode, im.size, white)
    diff = ImageChops.difference(im, bg)
    diff = ImageChops.add(diff, diff, 2.0, -100)
    bbox = diff.getbbox()
    return im.crop(bbox)

latex_to_img(r'\frac{x}{y^2}').save('img.png')

Keep in mind, it requires pillow and matplotlib.

pip install matplotlib pillow
Andrew Slabko
  • 690
  • 8
  • 15
5

Take a look at mathtex.

Jouni K. Seppänen
  • 43,139
  • 5
  • 71
  • 100
1

Maybe you could use an online service such as this one: http://www.codecogs.com/components/equationeditor/equationeditor.php.


Following Joel A. Christophel's suggestion, here's a working similar website: http://arachnoid.com/latex/

Bastien Léonard
  • 60,478
  • 20
  • 78
  • 95
0

You're going to need to use LaTeX to process to string. The process of rendering LaTex/TeX is very involved (it generally takes a 100+MB package to do the work), you're just not going to be able toss in a little python module to get the work done.

D'Nabre
  • 2,226
  • 16
  • 13
0

If it is just math equations that you need, you will probably have better luck finding a mathml renderer in python. This page might provide some clues, including some latex-mathml translators.

Eduardo Leoni
  • 8,991
  • 6
  • 42
  • 49
0

In a Jupyter notebook, you can use the rendering features to display images generated with LaTeX.:

from IPython.display import Math
latex_string = r"""
$$
\left(
      \begin{array}{ r  r  r }
         1 & 0 & 0 \\ 
         0 & 1 & 0 \\ 
         0 & 0 & 1 \\ 
      \end{array}
\right)$$"""


Math(latex_string)

matrix

If you want to save the image to a file you can use this function:

def latex2png(latex, filename, fontsize=300):
    """
    Render latex code to png image
    """
    from sympy import preview
    return preview(latex,
                   viewer='file',
                   filename=filename,
                   euler=False,
                   dvioptions=['-D', f'{str(fontsize)}'])
Enrique Pérez Herrero
  • 3,699
  • 2
  • 32
  • 33