How can java tex rendering happen?
I want to render maths 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?
The LaTeX standalone package allows the creation of a PNG output file, the size of which exactly corresponds to the size of the formula or of the text.
So, we just have to call LaTeX from Java, and get the PNG output file.
1. Prerequisites
a) LaTeX shall be installed on the computer
... with all packages necessary for the formula (in the below example: amsfonts and amsmath)
... with standalone package
GhostScript shall be installed (necessary for standalone package)
The directory containing gswin32c.exe shall be added to PATH.
On my computer: C:Program Files (x86)gsgs9.10in
ImageMagick shall be installed (necessary for standalone package)
convert.exe shall be renamed as imgconvert.exe
The directory containing imgconvert.exe shall be added to PATH.
On my computer: C:Program Files (x86)ImageMagick-6.8.8-9
2. Check that LaTeX (with standalone package) succeeds in generating the PNG file (no Java at this stage).
Reference : Compile a LaTeX document into a PNG image that's as short as possible
LaTeX file, called New21.tex (for instance):
documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone}
usepackage{amsfonts}
usepackage{amsmath}
egin{document}
$egin{array}{l}
orallarepsiloninmathbb{R}_+^* existseta>0 |x-x_0|leqetaLongrightarrow|f(x)-f(x_0)|leqarepsilon\
detegin{bmatrix}a_{11}&a_{12}&cdots&a_{1n}\a_{21}&ddots&&dots\dots&&ddots&dots\a_{n1}&cdots&cdots&a_{nn}end{bmatrix}overset{mathrm{def}}{=}sum_{sigmainmathfrak{S}_n}arepsilon(sigma)prod_{k=1}^n a_{ksigma(k)}\
{sideset{_lpha^eta}{_gamma^delta}{mathop{egin{pmatrix}a&b\c&dend{pmatrix}}}}\
int_0^infty{x^{2n} e^{-a x^2},dx} = rac{2n-1}{2a} int_0^infty{x^{2(n-1)} e^{-a x^2},dx} = rac{(2n-1)!!}{2^{n+1}} sqrt{rac{pi}{a^{2n+1}}}\
int_a^b{f(x),dx} = (b - a) sumlimits_{n = 1}^infty {sumlimits_{m = 1}^{2^n - 1} {left( { - 1}
ight)^{m + 1} } } 2^{ - n} f(a + mleft( {b - a}
ight)2^{-n} )\
int_{-pi}^{pi} sin(lpha x) sin^n(eta x) dx = extstyle{left { egin{array}{cc} (-1)^{(n+1)/2} (-1)^m rac{2 pi}{2^n} inom{n}{m} & n mbox{ odd}, lpha = eta (2m-n) \ 0 & mbox{otherwise} \ end{array}
ight .}\
L = int_a^b sqrt{ left|sum_{i,j=1}^ng_{ij}(gamma(t))left(rac{d}{dt}x^icircgamma(t)
ight)left(rac{d}{dt}x^jcircgamma(t)
ight)
ight|},dt\
egin{array}{rl} s &= int_a^bleft|rac{d}{dt}ec{r},(u(t),v(t))
ight|,dt \ &= int_a^b sqrt{u'(t)^2,ec{r}_ucdotec{r}_u + 2u'(t)v'(t), ec{r}_ucdotec{r}_v+ v'(t)^2,ec{r}_vcdotec{r}_v},,, dt. end{array}\
end{array}$
end{document}
Command line:
pdflatex -shell-escape New21.tex
Generation of the PNG file from Java, through a call to LaTeX
Code:
import java.awt.FlowLayout;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
class StreamPrinter implements Runnable {
// Source: http://labs.excilys.com/2012/06/26/runtime-exec-pour-les-nuls-et-processbuilder/
private final InputStream inputStream;
private boolean print;
StreamPrinter(InputStream inputStream, boolean print) {
this.inputStream = inputStream;
this.print = print;
}
private BufferedReader getBufferedReader(InputStream is) {
return new BufferedReader(new InputStreamReader(is));
}
@Override
public void run() {
BufferedReader br = getBufferedReader(inputStream);
String ligne = "";
try {
while ((ligne = br.readLine()) != null) {
if (print) {
System.out.println(ligne);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Exemple141_LaTeX_to_PNG_using_installed_LaTeX_distribution {
public static void main(String[] args) {
String TEMP_DIRECTORY = "D:\_tmp";
String TEMP_TEX_FILE_NAME = "New22"; // for New22.tex
// 1. Prepare the .tex file
String newLineWithSeparation = System.getProperty("line.separator")+System.getProperty("line.separator");
String math = "";
math += "\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone}" + newLineWithSeparation;
math += "\usepackage{amsfonts}" + newLineWithSeparation;
math += "\usepackage{amsmath}" + newLineWithSeparation;
math += "\begin{document}" + newLineWithSeparation;
math += "$\begin{array}{l}" + newLineWithSeparation;
math += "\forall\varepsilon\in\mathbb{R}_+^*\ \exists\eta>0\ |x-x_0|\leq\eta\Longrightarrow|f(x)-f(x_0)|\leq\varepsilon\\" + newLineWithSeparation;
math += "\det\begin{bmatrix}a_{11}&a_{12}&\cdots&a_{1n}\\a_{21}&\ddots&&\vdots\\\vdots&&\ddots&\vdots\\a_{n1}&\cdots&\cdots&a_{nn}\end{bmatrix}\overset{\mathrm{def}}{=}\sum_{\sigma\in\mathfrak{S}_n}\varepsilon(\sigma)\prod_{k=1}^n a_{k\sigma(k)}\\" + newLineWithSeparation;
math += "{\sideset{_\alpha^\beta}{_\gamma^\delta}{\mathop{\begin{pmatrix}a&b\\c&d\end{pmatrix}}}}\\" + newLineWithSeparation;
math += "\int_0^\infty{x^{2n} e^{-a x^2}\,dx} = \frac{2n-1}{2a} \int_0^\infty{x^{2(n-1)} e^{-a x^2}\,dx} = \frac{(2n-1)!!}{2^{n+1}} \sqrt{\frac{\pi}{a^{2n+1}}}\\" + newLineWithSeparation;
math += "\int_a^b{f(x)\,dx} = (b - a) \sum\limits_{n = 1}^\infty {\sum\limits_{m = 1}^{2^n - 1} {\left( { - 1} \right)^{m + 1} } } 2^{ - n} f(a + m\left( {b - a} \right)2^{-n} )\\" + newLineWithSeparation;
math += "\int_{-\pi}^{\pi} \sin(\alpha x) \sin^n(\beta x) dx = \textstyle{\left \{ \begin{array}{cc} (-1)^{(n+1)/2} (-1)^m \frac{2 \pi}{2^n} \binom{n}{m} & n \mbox{ odd},\ \alpha = \beta (2m-n) \\ 0 & \mbox{otherwise} \\ \end{array} \right .}\\" + newLineWithSeparation;
math += "L = \int_a^b \sqrt{ \left|\sum_{i,j=1}^ng_{ij}(\gamma(t))\left(\frac{d}{dt}x^i\circ\gamma(t)\right)\left(\frac{d}{dt}x^j\circ\gamma(t)\right)\right|}\,dt\\" + newLineWithSeparation;
math += "\begin{array}{rl} s &= \int_a^b\left\|\frac{d}{dt}\vec{r}\,(u(t),v(t))\right\|\,dt \\ &= \int_a^b \sqrt{u'(t)^2\,\vec{r}_u\cdot\vec{r}_u + 2u'(t)v'(t)\, \vec{r}_u\cdot\vec{r}_v+ v'(t)^2\,\vec{r}_v\cdot\vec{r}_v}\,\,\, dt. \end{array}\\" + newLineWithSeparation;
math += "\end{array}$" + newLineWithSeparation;
math += "\end{document}";
// 2. Create the .tex file
FileWriter writer = null;
try {
writer = new FileWriter(TEMP_DIRECTORY + "\" + TEMP_TEX_FILE_NAME + ".tex", false);
writer.write(math, 0, math.length());
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
// 3. Execute LaTeX from command line to generate picture
ProcessBuilder pb = new ProcessBuilder("pdflatex", "-shell-escape", TEMP_TEX_FILE_NAME + ".tex");
pb.directory(new File(TEMP_DIRECTORY));
try {
Process p = pb.start();
StreamPrinter fluxSortie = new StreamPrinter(p.getInputStream(), false);
StreamPrinter fluxErreur = new StreamPrinter(p.getErrorStream(), false);
new Thread(fluxSortie).start();
new Thread(fluxErreur).start();
p.waitFor();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
// 4. Display picture
JFrame maFrame = new JFrame();
maFrame.setResizable(false);
maFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
maFrame.setSize(400, 400);
maFrame.getContentPane().setLayout(new FlowLayout());
maFrame.getContentPane().add(new JLabel(new ImageIcon(TEMP_DIRECTORY + "\" + TEMP_TEX_FILE_NAME + ".png")));
maFrame.pack();
maFrame.setVisible(true);
// 5. Delete files
for (File file : (new File(TEMP_DIRECTORY).listFiles())) {
if (file.getName().startsWith(TEMP_TEX_FILE_NAME + ".")) {
file.delete();
}
}
}
}