Note that it should be possible to copy paste the below commands in a bash shell. In the following examples, I have used
Exploring Perl Modules - Part 1: On-The-Fly Graphics with GD LG #81 to generate a png image on the fly; here are some other dependencies:
Code: Select all
# dependencies, if needed..
# in texlive, ebb is in dvipdfm package
tlmgr install dvipdfm
# use libgd-gd2-perl, so no need for perl -MCPAN -e shell, cpan[1]> install GD
sudo apt-get install libgd-gd2-perl
# for convert:
sudo apt-get install imagemagick
Here is a basic example (done in a new directory, test):
Code: Select all
mkdir test
cd test
# create red background image
perl -e "use GD; \$im = new GD::Image(100,100); \$red = \$im->colorAllocate(255,0,0); open(PICTURE, \">picture.png\") or die(\"Cannot open file for writing\"); binmode PICTURE; print PICTURE \$im->png; close PICTURE;"
cat > imgtest.tex <<EOF
\documentclass{article}
\usepackage{graphicx}
\begin{document}
This is a test document. \\
\begin{figure}[h]
\centering
\includegraphics{picture.png}
\caption{Some caption.}
\end{figure}
\end{document}
EOF
pdflatex imgtest.tex
# Output written on imgtest.pdf (1 page, 15115 bytes).
latex imgtest.tex
# ! LaTeX Error: Cannot determine size of graphic in picture.png (no BoundingBox)
# http://www.mps.mpg.de/homes/daly/latex/grf.htm#Q1-1-14
# The solution is to determine the bounding box coordinates somehow (see next point) and to include them, either in the \includegraphics command, or by editing the graphics file itself. However, if there really is no bounding box information in the file, it is unlikely to conform to the encapsulated standard and will cause other problems.
# OH NO, should we look for all bounding box data manually?
# maybe not: http://bmeps.sourceforge.net/examples.html#l12
# "The \DeclareGraphicsRule{.png}{eps}{.bb}{`bmeps #1} command tells LaTeX that PNG (*.png) files can be converted to EPS. The bounding box information for such files can be found in a file with the same name but the suffix ``.bb''. For the image fbt.png we have to create a file fbt.bb"
# also: http://kile.sourceforge.net/Documentation/html/build_epsgraphics.html
# so let's try with DeclareGraphicsRule:
cat > imgtest-decl.tex <<EOF
\documentclass{article}
\usepackage{graphicx}
\DeclareGraphicsRule{.png}{eps}{.bb}{\`convert #1 eps:-}% PNG
\begin{document}
This is a test document. \\\\
\begin{figure}[h]
\centering
\includegraphics{picture.png}
\caption{Some caption.}
\end{figure}
\end{document}
EOF
pdflatex imgtest-decl.tex
# ! LaTeX Error: File `picture.bb' not found.
ebb picture.png
# produces picture.bb
pdflatex imgtest-decl.tex
# Output written on imgtest-decl.pdf (1 page, 26466 bytes).
# notice, previous pdf was 15115 bytes
# however, there is only a frame and the text "‘convert picture.png eps:-" written in it in the pdf
# test the command itself
convert picture.png eps:-
# %!PS-Adobe-3.0 EPSF-3.0
# %%Creator: (ImageMagick)
# ...
# %%PageBoundingBox: 0 0 100 100
# userdict begin
# DisplayImage
# ...
# 1
# FF0000
# 0000000000000000000000000000000000000000000000000000000000000000000000000000
# ...
# it seems to work...
# so we must use the DeclareGraphicsRule only in dvi mode!
cat > imgtest-decl.tex <<EOF
\documentclass{article}
\usepackage{graphicx}
\usepackage{ifpdf}
\ifpdf
% do nothing
\else
\DeclareGraphicsRule{.png}{eps}{.bb}{\`convert #1 eps:-}% PNG
\fi
\begin{document}
This is a test document. \\\\
\begin{figure}[h]
\centering
\includegraphics{picture.png}
\caption{Some caption.}
\end{figure}
\end{document}
EOF
pdflatex imgtest-decl.tex
# Output written on imgtest-decl.pdf (1 page, 15361 bytes).
# looks OK now..
latex imgtest-decl.tex
# Output written on imgtest-decl.dvi (1 page, 384 bytes).
evince imgtest-decl.dvi
# you can see the bounding box, but not the image..
grep --text "convert" imgtest-decl.dvi
# cmr10?This?ETXUUis?a?test?do?G[GS]cumen???t.
# ?l6?9????]q?FPSfile="`convert picture.png eps:-" #llx=0 lly=0 urx=72 ury=72 ....
This means that, contrary to my expectation, the 'convert' command is not ran during a latex run with \DeclareGraphicsRule, but is in fact verbatim included as a link to the final (converted) image. Which is probably why 'evince' will not render the image at all..
We can now try to simply remove the extension from the includegraphics command, and thereby force pdflatex and latex to choose their own extension...
Code: Select all
cat > imgtest-noext.tex <<EOF
\documentclass{article}
\usepackage{graphicx}
\begin{document}
This is a test document. \\
\begin{figure}[h]
\centering
\includegraphics{picture}
\caption{Some caption.}
\end{figure}
\end{document}
EOF
pdflatex imgtest-noext.tex
# Output written on imgtest-noext.pdf (1 page, 15360 bytes).
# looks OK..
latex imgtest-noext.tex
# ! LaTeX Error: File `picture' not found.
# lets try generate an eps file then..
convert -compress zip picture.png eps2:picture.eps
latex imgtest-noext.tex
# Output written on imgtest-noext.dvi (1 page, 368 bytes).
evince imgtest-noext.dvi
# now the image shows!
grep --text "picture" imgtest-noext.dvi
# cmr10?This?[ETX]UUis?a?test?do?G[GS]cumen???t.?QǍ?9????P?:PSfile="picture.eps" llx=0 lly=0 urx=100 ury=100 rwi=1000 ?[SYN]?????[NAK]Figure?[ETX]UU1:?[EOT]q?Some?caption.?[RS]???1??*[SOH]???[FS];[ETX]?[STX]y[SOH]?[SOH]?K?`y
So just like previously, simply a link to "picture.eps" is stored in the .dvi file - however, this one can be now easily interpreted by evince. (In fact, you could also open the imgtest-noext.dvi file in scite, and manually change "picture.eps" to "picture.png" - evince will still show the .dvi, but no image will be shown; although evince by itself can display png images)
Conclusion - DeclareGraphicsRule can be useful if you want to use full filenames, so it redirects requests for .png to say .eps - but it still will not take care of image conversion on the fly. So, seems that safest way to have the images correct in .dvi is to have eps versions of each requested image.
But is there a way to take care of this conversion on the fly, so we don't have to do all these conversion steps manually, if we want to switch from pdflatex to latex?
The only thing I can think of, is to interrupt the process whenever latex requests an image, do a system call that does an image conversion, and only then allow \includegraphics to execute. And that means that latex would have to be called with -shell-enable so it can run system commands - but it would have to be called like that only once; and that \includegraphics would have to be "overloaded". So let's try that (
note that the code includes also a commented example, which uses bash to get the new eps filename in a file):
Code: Select all
rm * # delete everything in test dir
# create red background image
perl -e "use GD; \$im = new GD::Image(100,100); \$red = \$im->colorAllocate(255,0,0); open(PICTURE, \">picture.png\") or die(\"Cannot open file for writing\"); binmode PICTURE; print PICTURE \$im->png; close PICTURE;"
cat > imgtest-shl.tex <<EOF
\documentclass{article}
\usepackage{graphicx}
\usepackage{ifpdf}
\ifpdf
% do nothing
\else
% we will need explicit filenames here...
\let\oldIncludegraphics\includegraphics % save original snapshot
\renewcommand\includegraphics[2][]{% "overload" command
%\message{FILENAME: #2}
% create .bb file - not really needed
\immediate\write18{ebb #2}
% get eps filename based on png filename.
% better to do it directly in Latex, than invoking system calls and reading files, as below
% get substring: "picture.png" -> "picture" as \plainfilename
\def\temp ##1.png{%
\def\plainfilename{##1}% "picture"
\def\epsfilename{##1.eps}}% "picture.eps"
\expandafter\temp#2 % this prepares both plainfilename and epsfilename
%% generate eps filename, store it in fname.txt
%\immediate\write18{echo #2 | sed "s/png/eps/" > fname.txt}
%
%% read file contents into 'variable' / command: file fname.txt as \epsfilename
%\def\tfn{fname.txt}
%\newread\traux
%\openin\traux=\tfn\relax
%\read\traux to \InLine
%\closein\traux
%
%% however, must get rid of the final space " " which is added..
%\def\temp ##1 {%
% \def\epsfilename{##1}}% was \def\InLineNoSpace
%\expandafter\temp\InLine % this should prepare epsfilename, by calling def
% convert image to eps
\immediate\write18{convert #2 \epsfilename}% create .eps file
\message{EPSNAME: \epsfilename }
\oldIncludegraphics[#1]{\plainfilename}% \plainfilename instead of #2
}
\fi
\begin{document}
This is a test document. \\
\begin{figure}[h]
\centering
\includegraphics{picture.png}
\caption{Some caption.}
\end{figure}
\end{document}
EOF
pdflatex imgtest-shl.tex
# Output written on imgtest-shl.pdf (1 page, 15360 bytes).
latex imgtest-shl.tex
# ! LaTeX Error: File `picture' not found.
latex --enable-write18 imgtest-shl.tex
# Output written on imgtest-shl.dvi (1 page, 368 bytes).
# generates also picture.eps
latex imgtest-shl.tex
# Output written on imgtest-shl.dvi (1 page, 368 bytes). - now it works fine
evince imgtest-shl.dvi
# picture can be seen fine
grep --text picture imgtest-shl.dvi
# cmr10?This?[ETX]UUis?a?test?do?G[GS]cumen???t.?QǍ?9????P?:PSfile="picture.eps" llx=0 lly=0 urx=100 ury=100 rwi=1000 ???????[NAK]Figure?[ETX]UU1:??q?Some?caption.?????1??*[SOH]????;[ETX]??y[SOH]?[SOH]?K?`y
Seems to work... And since we started with html and odt:
Code: Select all
mk4ht oolatex imgtest-shl.tex
# System call: cd sxw-imgtest-shl.dir; zip -r imgtest-shl.odt * ; cd ..
# generates imgtest-shl.odt
oowriter imgtest-shl.odt
# picture seen fine - though captions seem not supported..
htlatex imgtest-shl.tex
# [1 file imgtest-shl.html
# System call: convert -trim +repage -density 110x110 -transparent '#FFFFFF' zzimgtest-shl.ps imgtest-shl0x.png
# generates imgtest-shl.html, imgtest-shl0x.png
firefox imgtest-shl.html
# picture seems ok, but it is imgtest-shl0x.png - unfortunately, we needlessly go png-eps-png this way..
Just as a note, some nice resources that were helpful (especially with reading file contents into a command in latex):
TeX: Reference and Examples by David Bausum: read,
Macros: A Tutorial on \exapndafter,
TEX beauties and oddities,
LaTeX Community • View topic - Input text?
Cheers!