# how to speed up tex4ht image generation process?

Currently, I tell tex4ht to use svg instead of png for math images. This results in better image quality. However, it is slow in image generation, as it takes about 1-2 seconds for each image to be generated since it has to load the idv file each time to make each image for each math expression.

Is there a way to speed this process up? I'll describe the current process I use for reference.

I edited sudo vi /usr/local/texlive/2014/texmf-dist/tex4ht/base/unix/tex4ht.env and add these 2 lines

G.svg
Gdvisvgm -n -p %%2 -c 1.2,1.2 -s %%1 > %%3


as shown in this image

Next, edited my tex4ht cfg file (called nma.cfg) and added svg entry

 \Preamble{ext=htm,charset="utf-8",p-width,pic-align}
\Configure{Picture}{.svg}
\makeatletter
\Configure{graphics*}
{svg}
{
{\Configure{Needs}{File: \Gin@base.svg}\Needs{}}
\Picture[\csname a:GraphicsAlt\endcsname]{\csname Gin@base\endcsname.svg
\csname a:Gin-dim\endcsname}
}
\begin{document}
\EndPreamble


Next, I call tex4ht on the latex file as follows

  make4ht -u foo.tex "nma,htm,pic-align,notoc*"


where make4ht is found in https://github.com/michal-h21/make4ht

If you do not have make4ht installed, then the command

  htlatex foo.tex "nma,htm,pic-align,charset=utf-8,notoc*" " -cunihtf -utf8"


will work as well. Here is foo.tex with 2 equations which will cause 2 images to be generated

\documentclass[11pt]{article}
\usepackage{graphicx} %must be included
\begin{document}
$x = \sin(y)$
and
$x2 = \sin(y)$
\end{document}


Now we see tex4ht loading the idv each time for each image:

......
t4ht.c (2012-07-25-19:28 kpathsea)
t4ht -f/foo.tex
(/usr/local/texlive/2014/texmf-dist/tex4ht/base/unix/tex4ht.env)

Entering foo.lg
System call: dvisvgm -n -p 1 -c 1.2,1.2 -s foo.idv > fo0x.svg
processing page 1
page size: 58.1681pt x 13.0909pt (20.4437mm x 4.60093mm)
page written to <stdout>
1 of 2 pages converted in 0.244021 seconds
System return: 0

System call: dvisvgm -n -p 2 -c 1.2,1.2 -s foo.idv > fo1x.svg
processing page 2
page size: 64.7136pt x 13.0909pt (22.7442mm x 4.60093mm)
page written to <stdout>
1 of 2 pages converted in 0.243742 seconds
System return: 0


Is there a way to speed this up to avoid loading the idv each time for each equation and do them all at once? Currently it takes 4 days to build my large latex file and I need a way to speed this up.

Each generated picture is placed on it's own page in special dvi file, with extension idv. By default, tex4ht calls converting commands on each page separately, which normally isn't problem, unless you have lot of pages as in your case. In this case, it may be faster to convert all pages in the idv file with one command. The catch is that we can't name the output files in the way we need, so we have to rename them after conversion.

If you call dvisvgm to convert all pages:

dvisvgm -n -p 1- filename.idv

files will be named like filename-01.svg, but we need them to be named like filename0x.svg

This is possible to fix using make4ht build file:

Make:add("dvisvgm","dvisvgm -n -TS1.25,1.25 -c 1.2,1.2 -p 1- ${input}.idv") local max_count = 5 local image_format = "${input}-${zeroes}${page}.${ext}" local oneimage_format = "${input}.${ext}" local function file_exists(fn) local f = io.open(fn,"r") if f == nil then return false else f:close() return true end end local function locate_file(par,ext, count) local count = count or 0 par.ext = ext local zeroes = string.rep("0",count) par.zeroes = zeroes if count > max_count then local one = oneimage_format % par if file_exists(one) then return one else return false, "max_count exceeded" end end local fn = image_format % par if file_exists(fn) then return fn else return locate_file(par, ext, count+1) end end Make:htlatex{} Make:htlatex{} Make:htlatex{} Make:tex4ht{} Make:t4ht{} Make:dvisvgm{} Make:image("svg$",function(arg)
arg.input = arg.source:gsub(".idv$","") local fn,msg = locate_file(arg, "svg") if not fn then print("Image processing error: "..msg) else arg.filename = fn local cmd = "mv${filename} ${output}" % arg print(cmd) os.execute(cmd) end end )  we should disseminate this file little bit: Make:add("dvisvgm","dvisvgm -n -c 1.2,1.2 -p 1-${input}.idv")


this register new command, dvisvgm, which will extract all svg files from the idv file. ${input} is special instruction which is replaced with a input file name. Make:htlatex{} Make:tex4ht{} Make:t4ht{} Make:dvisvgm{}  this is the build sequence, LaTeX is called only once, you may want to add more Make:htlatex calls if you use toc or references. The idv file is created after tex4ht run, so we need to call Make:tex4ht{} and Make:t4ht{} explicitly and after that to Make:dvisvgm{}. Make:image("svg$",function(arg)
arg.input = arg.source:gsub(".idv$","") local fn,msg = locate_file(arg, "svg") if not fn then print("Image processing error: "..msg) else arg.filename = fn local cmd = "mv${filename} \${output}" % arg
print(cmd)
os.execute(cmd)
end
end
)


this function is called for each image. arg is table with image properties, which is the idv file name, page number and the output file. to construct the file, we need to get the basename with deleting the .idv suffix from arg.source. we try to find the svg file filename with locate_file function, when we found it, it is moved to the correct location, which is in the arg.output variable.

local function locate_file(par,ext, count)
local count = count or 0
par.ext = ext
local zeroes = string.rep("0",count)
par.zeroes = zeroes
if count > max_count then
local one = oneimage_format % par
if file_exists(one) then
return one
else
return false, "max_count exceeded"
end
end
local fn = image_format % par
if file_exists(fn) then
return fn
else
return locate_file(par, ext, count+1)
end
end


because we don't know the exact file name produced by dvisvgm we need to locate it. the situation is worsened with the fact that dvisvgm may add leading zeroes before the page number, so we need to try several possibilities when we can't find the file on the first attempt.

Save the make file as foo.mk4. From the command line output:

Make4ht: dvisvgm -n -c 1.2,1.2 -p 1- foo.idv
processing page 1
page size: 58.1681pt x 13.0909pt (20.4437mm x 4.60093mm)
page written to foo-01.svg
processing page 2
page size: 64.7136pt x 13.0909pt (22.7442mm x 4.60093mm)
page written to foo-02.svg
2 of 2 pages converted in 0.193865 seconds


and:

mv foo-01.svg foo0x.svg
mv foo-02.svg foo1x.svg


and the result:

• Why do we need -TS and also -c? It seems that -TS and -c are equivalent, as claimed in the manpage, and I don't know why the scaling is necessary (it seems to me that some of the formulae exceed the page because of this). Jan 30 '19 at 18:40
• @FrankScience I don't remember, I guess that this was a mistake. The -c option should suffice. You can also choose a different value. Note that this answer is almost four years old and bit obsolete. It is best to use the dvisvgm_hashes extension for a fast generation of the SVG files. See the make4ht documentation for details. Jan 30 '19 at 19:41
• So I only need to call tex4ebook with option dvisvgm_hashes, and modify the .mk4 file, leaving only compilation (htlatex, tex4ht, t4ht) right? Jan 30 '19 at 20:05
• @FrankScience something like tex4ebook -f epub+dvisvgm_hashes filename.tex. You don't need Make:image in the build file then. You may still need to require the SVG format using \Configure{Picture}{.svg} in the .cfg file or using the svg option on the command line Jan 30 '19 at 20:11
• Is the following braces including \Configure{Needs} and \Picture still necessary in your answer? By the way, maybe it would be a bit beneficial to update that answer. Jan 31 '19 at 15:53