Reputation: 5580
What is the best library to do this?
I am surprised this question has not been asked before. Is it impossible? That would be surprising too.
Thanks for your help.
Upvotes: 3
Views: 7202
Reputation: 91
Another solution to create a PNG image from LaTeX provided that LaTeX (for instance: MiKTeX) is installed on the computer...
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)\gs\gs9.10\bin
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).
LaTeX file, called New21.tex (for instance):
\documentclass[border=0.50001bp,convert={convertexe={imgconvert},outext=.png}]{standalone}
\usepackage{amsfonts}
\usepackage{amsmath}
\begin{document}
$\begin{array}{l}
\forall\varepsilon\in\mathbb{R}_+^*\ \exists\eta>0\ |x-x_0|\leq\eta\Longrightarrow|f(x)-f(x_0)|\leq\varepsilon\\
\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)}\\
{\sideset{_\alpha^\beta}{_\gamma^\delta}{\mathop{\begin{pmatrix}a&b\\c&d\end{pmatrix}}}}\\
\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}}}\\
\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} )\\
\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 .}\\
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\\
\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}\\
\end{array}$
\end{document}
Command line:
pdflatex -shell-escape New21.tex
This should generate a file New21.png containing the below picture:
3. 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();
}
}
}
}
The above code should create the below frame:
Nicolas
Upvotes: 0
Reputation: 91
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, especially the use of JLatexMath. The purpose is just to give alternatives.
Example of result:
Code leading to this 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:
int bytesRead;
byte[] buffer = new byte[BUFFER_SIZE];
ArrayList<byte[]> al = new ArrayList<byte[]>();
while ((bytesRead = bis.read(buffer)) != -1) {
al.add(buffer.clone());
}
// 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));
jframe.add(button2, BorderLayout.CENTER);
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.add(button3, BorderLayout.SOUTH);
jframe.pack();
jframe.setLocationRelativeTo(null);
jframe.setVisible(true);
}
}
Nicolas
Upvotes: 1
Reputation: 311
Perhaps this? Haven't used it myself.
http://forge.scilab.org/index.php/p/jlatexmath/
Brief example code here:
http://forge.scilab.org/index.php/p/jlatexmath/page/ServerUsage/
EDIT:
Oops, sorry, noticed that this library was included in the linked post above, thought it wasn't. Never mind.
Upvotes: 0
Reputation: 3325
Displaying fancy equations with Java Generate Images for formulas in Java
Roughly I'd say your options are:
EDIT
As Stephen C said, these are only for fragments of Latex. If you want to convert a full Latex document, you'll need a full Latex implementation - none of the above. And those need to be somewhat large and complex because they are full "development environments" for typesetting documents by writing Latex code. If this is what you need, you don't have much choice but to use one of the standard Latex distributions via exec (and I guess fail gracefully if the Latex interpreter reports errors in the Latex code).
That said, there have been at least a couple of attempts to port Latex to Java (including two called "JavaTex"). Most likely these aren't in a state that would suit you - but see the summary of some recent attempts to judge for yourself:
http://www.monperrus.net/martin/running+tex+on+a+java+virtual+machine
Upvotes: 3
Reputation: 719709
It is not impossible to do this. (Java is Turing complete ...). But it is (IMO) unlikely that you will find an existing library to process TeX / LaTeX in Java, and impractical for you to implement this yourself.
I'd look for command-line applications that convert TeX / LaTeX to something (e.g. pdf or postscript), and then that something to png page images. Then I'd create a wrapper script that combines the applications as required, and use Process.exec(...)
to run the script.
EDIT
If you are just wanting to render LaTeX mathematical equations, try the options suggested by the answers linked by @RD1.
Upvotes: 0