emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Creating animated gif from latex src blocks


From: Edouard Debry
Subject: Re: Creating animated gif from latex src blocks
Date: Thu, 09 Feb 2023 11:32:43 +0100
User-agent: Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM-LB/1.14.9 (Gojō) APEL-LB/10.8 EasyPG/1.0.0 Emacs/30.0.50 (x86_64-w64-mingw32) MULE/6.0 (HANACHIRUSATO)

Hi,

In reply to an old thread initiated, here is how I get animated pictures
from latex src blocks.

<=========================== GIF image ===============================>

#+NAME: before-make-gif
#+begin_src elisp :lexical no :results none
(setq org-format-latex-header "\\documentclass[tikz]{standalone}")
(setq org-latex-default-packages-alist nil)
(setq org-latex-packages-alist nil)
#+end_src

#+NAME: after-make-gif
#+begin_src elisp :lexical no :results none
(custom-reevaluate-setting 'org-format-latex-header)
(custom-reevaluate-setting 'org-latex-packages-alist)
(custom-reevaluate-setting 'org-latex-default-packages-alist)
#+end_src

#+NAME: make-gif
#+header: :file test1.gif
#+header: :exports results
#+header: :results output silent graphics file
#+header: :imagemagick yes
#+header: :iminoptions -density 600 -delay 8 -loop 0 -background white -alpha 
remove
#+header: :headers '("\\usepackage{tikz}" "")
#+begin_src latex
\foreach \angle in {0,10,...,360} %
{
  \begin{tikzpicture}
    % fill circle and plot
    \fill[blue!50] (-1,0) arc (0:\angle:1) -- (-2,0) -- cycle;
    \fill[blue!50] plot[smooth,domain=0:\angle] (pi/180*\x,{sin(\x)}) |- (0,0);
    % draw connection
    \draw (-2,0) +(\angle:1) circle (2pt) -- (pi/180*\angle,{sin(\angle)}) 
circle (2pt);
    % draw axes an ticks
    \draw (-3.5,0) -- (7,0);
    \foreach \deg in {90, 180, 270, 360}
      \draw (pi/180*\deg,2pt) -- (pi/180*\deg,-2pt) node[below] {$\deg^\circ$};
    \draw (0,-1.2) -- (0,1.2);
    \foreach \y in {-1,-0.5,0.5,1}
      \draw (2pt,\y) -- (-2pt,\y) node[left] {$\y$};
    % draw plot and circle outline
    \draw plot[smooth,domain=0:360] (pi/180*\x,{sin(\x)});
    \draw (-2,0) circle (1);
  \end{tikzpicture}
}
#+end_src

#+ATTR_ORG: :width 1500 :height 600
[[file:test1.gif]]

<=========================== GIF image ===============================>



<=========================== SVG image ===============================>

#+NAME: before-make-svg
#+begin_src elisp :lexical no :results none
(setq org-format-latex-header "\\documentclass[dvisvgm]{standalone}")
(setq org-latex-default-packages-alist nil)
(setq org-latex-packages-alist nil)
#+end_src

#+NAME: after-make-svg
#+begin_src elisp :lexical no :results none
(custom-reevaluate-setting 'org-format-latex-header)
(custom-reevaluate-setting 'org-latex-packages-alist)
(custom-reevaluate-setting 'org-latex-default-packages-alist)
#+end_src

#+NAME: make-svg
#+header: :file test1.svg
#+header: :exports results
#+header: :results output silent graphics file
#+header: :headers '("\\usepackage{animate}" "\\usepackage{tikz}" 
"\\pgfmathsetmacro{\\pendulumswing}{40}" 
"\\pgfmathsetmacro{\\pendulumlength}{5}")
#+begin_src latex
\begin{animateinline}[controls, palindrome]{45}
  \multiframe{45}{rt=0+4}{%
    \begin{tikzpicture}[line width=1pt]
      \draw[dashed] (0:0) -- (90:{-\pendulumlength}) coordinate (o);
      \draw[dashed] ({90-\pendulumswing}:{-\pendulumlength}) coordinate (a)
      arc[start angle={90-\pendulumswing}, end angle={90+\pendulumswing}, 
radius={-\pendulumlength}] coordinate (b);
      \draw[dashed, red] (a) -- (a |- o) coordinate (c) node[below] {$-x_m$};
      \draw[dashed, red] (b) -- (b |- o) coordinate (d) node[below] {$x_m$};
      \draw[-stealth, red] ([xshift=-1cm]c) -- ([xshift=1cm]d);

      % variable \rt goes from 0 to 180
      % cos(\rt) returns a value between -1 and 1 following a (co)sine curve
      \pgfmathsetmacro{\pendulumangle}{cos(\rt)*\pendulumswing}
      \draw (0:0) -- ({90+\pendulumangle}:{-\pendulumlength})
      node[circle, fill=blue, text=white] {$\mathbf{m}$};
    \end{tikzpicture}%
  }%
\end{animateinline}
#+end_src

#+ATTR_ORG: :width 1500 :height 600
[[file:test1.svg]]

<=========================== SVG image ===============================>

The GIF generation first goes through generating a PDF file and then, converts 
it
afterwards to gif with ImageMagick. It only uses "tikz" latex package.

The SVG generation uses "tikz" and "animate" latex packages. This latter is 
initiated
with "dvisvgm" and therefore, the src block is configured to produce a svg file
("dvisvgm" again under the hood).

The GIF image shows up correctly animated in emacs, either as a plain file or 
as a link in
orgmode (org-inline-animate).

The SVG file is statically well displayed in emacs, but not animated. As far as 
I understand
the "animate" package uses javascript under the hood and indeed, the SVG file is
correctly animated in (e.g.) the chromium browser.

That is to note that for correct image generation, I had to tweak
'org-format-latex-header, , 'org-latex-packages-alist and
'org-latex-default-packages-alist orgmode variables. Setting nil for two 
latters is probably
a bit too harsh, but I did not have enough time to figure out which package was 
causing
problems.

So, as you may have guessed, before evaluating the latex block, I evaluate the 
first
elisp block and after, the second elisp block's evaluation reverts orgmode 
variables to
their previous settings.

This is a bit annoying, I wonder if there is a way to automatically evaluate 
both
elisp blocks when running the latex block, one before and one after. I know 
that some
blocks can be called within other code blocks but obviously, with the same 
language.

Perhaps the "#+CALL:" syntax can call several code blocks ?

#+CALL : before-gif() make-gif() after-gif()

Let me know if you find a lighter way to generate animated images from src code 
blocks.

Hope this helps

Regards

Edouard Debry



reply via email to

[Prev in Thread] Current Thread [Next in Thread]