4

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

Mathematica graphics

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: \[email protected]}\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.

1 Answer 1

4

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:

enter image description here

11
  • 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).
    – Yai0Phah
    Jan 30, 2019 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.
    – michal.h21
    Jan 30, 2019 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?
    – Yai0Phah
    Jan 30, 2019 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
    – michal.h21
    Jan 30, 2019 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.
    – Yai0Phah
    Jan 31, 2019 at 15:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .