# TeX rendering in a Java application

I want to render math formulas in my Java GUI application. I am looking for a library made for computer use, not web use, which can render TeX. I have already tried jLatexMath, but it's very slow when I use it in my application.

If there are any other/better, could you point me in the right direction?

(I originally asked this question on StackOverflow)

-
I can think of three libraries that might somehow help or inspire you: JEuclid, SnuggleTeX and JLaTeXMath. –  Paulo Cereda Jan 19 '12 at 16:42
I am using jLatexMath in one of my own projects, and the first time I got it to display equations I also thought it was very slow, until I realized this was only true for the first invocation of jLatexMath. For every start of your application, the first rendering will be slow but subsequent renderings are fast. –  propaganda Jan 20 '12 at 3:33

Friendly note: most of the conversion process involves input parsing, evaluation, font loading, rendering and output, so I wouldn't expect a nearly real-time conversion.

That said, let's go to business. :)

Warning: boring non-TeX technical Java stuff ahead. :)

I had a quick look at both SnuggleTeX and JEuclid in order to come up with this answer. Sorry, I didn't have time to come up with a better example.

The first one, SnuggleTeX, is described as "a free and open-source Java library for converting fragments of LaTeX to XML (usually XHTML + MathML)." The second one, JEuclid, is described as "a complete MathML rendering solution". What I actually did was to redirect one's output to the other's input.

First, with SnuggleTeX, you can obtain the needed code from the minimal example in its own homepage:

/* Create vanilla SnuggleEngine and new SnuggleSession */
SnuggleEngine engine = new SnuggleEngine();
SnuggleSession session = engine.createSession();

/* Parse some very basic Math Mode input */
SnuggleInput input = new SnuggleInput("$$x+2=3$$");
session.parseInput(input);

/* Convert the results to an XML String, which in this case will
* be a single MathML $...$ element. */
String xmlString = session.buildXMLString();


Now you have the MathML representation of your LaTeX input. Let's check JEuclid, from its API, there's the Converter class with the following method:

BufferedImage render(Node node, LayoutContext context)


Then you can use net.sourceforge.jeuclid.MathMLParserSupport to parse your XML string to org.w3c.dom.Document. Calling the render method with the correct parameters will give you a BufferedImage representing your input.

My attempt:

It took around 1.4 secs to render this image.

I didn't like the ouput, but to be honest, I just wrote this app in 2 minutes as a [cough... cough... bad...] proof of concept. :) I'm almost sure the rendering quality can be improved, but I'm quite busy ATM. Anyway, I think you can try something similar and then decide if this approach is worth a shot. :)

Update: It seems JEuclid has a JMathComponent in order to display MathML content in a Component.

-
That's great! Thanks for your time :) –  Hidde Jan 20 '12 at 16:03
What is the minimum library to include to go from the MathML output to a PNG image? I don't require any other conversions and would like to keep the software as light as possible. So for just converting MathML to an image file using JEuclid do I just need to include the core and nothing else? –  user32313 Jun 16 '13 at 6:10
@Ozzy: according to JEuclid's usage page, the minimal distribution covers .png output, so it's certainly safe to use it. :) –  Paulo Cereda Jun 16 '13 at 15:19

Using Java's Runtime class you can execute external processes, so you can easily generate some LaTeX input file that contains the LaTeX expressions, execute pdflatex on the input file, possibly use Runrime to convert the pdf output to a different format (with gs) and open the resulting picture.

If you know Java this should be easy to implement. I don't have time to do this myself, but I'm confident this shouldn't take more than an hour or so.

-

Another solution is to call mimetex.cgi (available here: http://www.forkosh.com/mimetex.html) from Java.

I do not pretend that this solution is "better" than the ones previously given. The purpose is just to give alternatives.

Example of result:

import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import javax.swing.*;

public class Exemple106_MimetexInterface {

private static String MIMETEX_EXE = "c:\\Program Files (x86)\\mimetex\\mimetex.cgi";

final private static int BUFFER_SIZE = 1024;

/**
* Convert LaTeX code to GIF
*
* @param latexString LaTeX code
* @return GIF image, under byte[] format
*/
public static byte[] getLaTeXImage(String latexString) {
byte[] imageData = null;
try {
// mimetex is asked (on the command line) to convert
// the LaTeX expression to .gif on standard output:
Process proc = Runtime.getRuntime().exec(MIMETEX_EXE + " -d \"" + latexString + "\"");
// get the output stream of the process:
BufferedInputStream bis = (BufferedInputStream) proc.getInputStream();
// read output process by bytes blocks (size: BUFFER_SIZE)
// and stores the result in a byte[] Arraylist:
byte[] buffer = new byte[BUFFER_SIZE];
ArrayList<byte[]> al = new ArrayList<byte[]>();
}
// convert the Arraylist in an unique array:
int nbOfArrays = al.size();
if (nbOfArrays == 1) {
imageData = buffer;
} else {
imageData = new byte[BUFFER_SIZE * nbOfArrays];
byte[] temp;
for (int k = 0; k < nbOfArrays; k++) {
temp = al.get(k);
for (int i = 0; i < BUFFER_SIZE; i++) {
imageData[BUFFER_SIZE * k + i] = temp[i];
}
}
}
bis.close();
proc.destroy();
} catch (IOException e) {
e.printStackTrace();
}
return imageData;
}

/**
* demonstration main
*
* @param args command line arguments
*/
public static void main(String[] args) {
JFrame jframe = new JFrame();
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setLayout(new BorderLayout());

String LATEX_EXPRESSION_1 = "4$A=\$$\\array{3,c.cccBCCC&1&2&3\\\\\\hdash~1&a_{11}&a_{12}&a_{13}\\\\2&a_{21}&a_{22}&a_{23}\\\\3&a_{31}&a_{32}&a_{33}}\$$ "; byte[] imageData1 = getLaTeXImage(LATEX_EXPRESSION_1); JLabel button1 = new JLabel(new ImageIcon(imageData1)); jframe.add(button1, BorderLayout.NORTH); String LATEX_EXPRESSION_2 = "4$\\array{rccclBCB$&f&\\longr[75]^{\\alpha:{-1$f\\rightar~g}}&g\\\\3$\\gamma&\\longd[50]&&\\longd[50]&3$\\gamma\\\\&u&\\longr[75]_\\beta&v}";
byte[] imageData2 = getLaTeXImage(LATEX_EXPRESSION_2);
JLabel button2 = new JLabel(new ImageIcon(imageData2));

String LATEX_EXPRESSION_3 = "4$\\hspace{5}\\unitlength{1}\\picture(175,100){~(50,50){\\circle(100)}(1,50){\\overbrace{\\line(46)}^{4$\\;\\;a}}(52,50) {\\line(125)}~(50,52;115;2){\\mid}~(52,55){\\longleftar[60]}(130,56){\\longrightar[35]}~(116,58){r}~(c85,50;80;2){\\bullet} (c85,36){3$-q}~(c165,36){3$q}(42,30){\\underbrace{\\line(32)}_{1\$a^2/r\\;\\;\\;}}~}";
byte[] imageData3 = getLaTeXImage(LATEX_EXPRESSION_3);
JLabel button3 = new JLabel(new ImageIcon(imageData3));

jframe.pack();
jframe.setLocationRelativeTo(null);
jframe.setVisible(true);
}
}


Nicolas

-

I know very little about Java programming, but I am pretty sure that there are free applications that use JLaTeXMath to render LaTeX that you can try and look at. I have pretty good experience with Geogebra. The rendering in Geogebra is pretty fast (generally does not seem to slow the application down in any way), and the output is rather nice, I think. It is a free software, so you can download the source code and see how they do it.

-