3

I have many images, for example

image01.jpg
image02.jpg
...
image80.jpg

I want to put those images into a document, 8 images per page, 4 rows and 2 columns (assume they will fit into one page that way). How to do this with some tex programming like \foreach command?


I have tried this

\def\imagelist{
  image01,
  image02,
  ...
  image80
}

\foreach \f in \imagelist{
  \includegraphics[width=0.5\textwidth]{./folder/\f.jpg}%
}

But there will be indent before the first iamge, and separation between two images in the same row, resulting overfull boxes.


Update: Actually, it will be simpler if I can do nested lists, something like

\def\nestedlist{
{image01, image02, ..., image08},
...
}
\foreach \eightimages in \nestedlist{
  \foreach \f in \eightimages{
    % one figure environment
    \begin{figure}
      % 8 images here
    \end{figure}
  }
}

I have more control this way.


Update 2024.03.28: I chose the answer that makes use of lualatex engine, according to "Accept this answer if it solved your problem or was the most helpful in finding your solution". Other answers are valid solutions, too. Choose your solution based on your needs. They all work.

6
  • 2
    I find that copy and paste is just as easy as using a loop, and is usually easier to debug. Feb 26 at 3:39
  • @JohnKormylo, indeed. That will be my workaround if I can't do it with loops.
    – Lu Xu
    Feb 26 at 3:43
  • Do the 8 images on a page reside inside a table environment, each with a \caption directive? Please advise.
    – Mico
    Feb 26 at 3:46
  • Incidentally, are you free to use LuaLaTeX?
    – Mico
    Feb 26 at 3:46
  • 1
    @Mico, I haven't used tables to layout images, but I am free to do that here. As for lualatex, actually yes. I think I know what you are suggesting, will look into it later.
    – Lu Xu
    Feb 26 at 3:57

3 Answers 3

4

Here's a LuaLaTeX-based solution. Each group of 8 images is placed in a table[p] environment to assure vertical centering on the page.

% !TEX TS-program = lualatex
\documentclass{article}
%\usepackage[a4paper,margin=2.5cm]{geometry} % set page parameters as needed
\usepackage[demo]{graphicx} % remove 'demo' option in real document

\usepackage{luacode}
\begin{luacode}
function do_80()
  for i=0,9 do   -- outer loop
    tex.sprint ( "\\begin{table}[p]" )
    for j=1,8 do -- inner loop
      ij=string.format ( "%02d" , i*8+j )
      tex.sprint ( "\\includegraphics[width=0.485\\textwidth]{image"..ij..".jpg} \\hfill" )
      if (j%2==0) then
        tex.sprint ( "\\par\\medskip" )
      end
    end
    tex.sprint ( "\\end{table}" )
  end
end
\end{luacode}

\begin{document}
\directlua{do_80()} 
\end{document}

The first two pages would look like this (but remember to omit the demo option in your real code):

enter image description here

2
  • 1
    Thanks, this seems to be the solution I prefer, I will try later.
    – Lu Xu
    Feb 26 at 5:50
  • Glad you like the method. :-) I've added a screenshot of the first two pages (of 8 pages in all).
    – Mico
    Feb 26 at 6:45
5

Sometime back, I had a similar requirement and I did this with l3 programming layer, clists.

enter image description here

I will post the code in a few hours, as I am going out at the moment. Why a clist? You can choose the images, as you might want to skip some. A second version is more sophisticated, using a function, that can add an image to the imgdb etc. Many years back I used a LaTeX2e @for. Today one has many and better options with the l3 layer.

\makeatletter
\def\blist{fig189,fig145,fig161,fig162}
\@for \i:=\blist\do{%
  \expandafter\putgraphic{\i}%
}
\makeatother

To break every four images I would use a counter.

\documentclass{article}
\usepackage[demo]{graphicx}

\begin{document}
\ExplSyntaxOn
\int_new:N \my_counter_int
\cs_set:Npn \put_graphic:n #1 
   { \int_incr:N\my_counter_int
     \int_compare:nNnTF \my_counter_int=4 %par every 4
     { \includegraphics[width=1.5cm]{#1}~\par\int_set:Nn\my_counter_int{0}}
     { 
      \includegraphics[width=1.5cm]{#1}~
     }
   }
   
\clist_set:Nn \imgdb:n {fig145,fig161,fig162,fig163,fig164,fig165,fig166,fig145}

\clist_map_function:NN \imgdb:n \put_graphic:n 
 
\ExplSyntaxOff

\end{document}

One can extend the functions, to have a key-value interface. Note the space after the \includegraphics. Images included inline, are simply boxes, so if you had say 50 small images representing ancient Chinese characters, you can build paragraphs with them!

Changing the clist to include some more images, including the xcolor package and adding a \pagecolor{blue!10} with a count limit of 8, I get:

long figures

Run the examples with \usepackage[demo]{graphicx}, since you don't have the images. Some tips also:

  1. Prefer using .png images with transparency, as down the line you may want to place them on a colored bckground.
  2. Code can be extended to add a \label and a subcaption, just include the graphic in a parbox, and use a counter (int) for the subcption.
  3. Always test both with demo, as well as real images. With real images you can pick up any latent issues you haven't foreseen.
  4. Use \graphicspath to find these images to avoid mixing these images with your others used in your document.

Exercise a) Modify the code to read all the images automatically from a directory and populate the clist. b) Assume all the images have the same prefix, modify the code to include the prefix and to populate the clist appropriately. c) Modify the code so you can say fig140-150 to include the 10 images.

4
  • Thanks for the answer. I have read about l3 when researching this question. The grammar is weird compared to other programming languages, though :(
    – Lu Xu
    Feb 26 at 5:49
  • @LuXu Yes it has a strange syntax, but is easier than Haskel or Perl! Once you get familiar with the conventions, is much easier.
    – yannisl
    Feb 26 at 6:23
  • how can I split the image list into groups of 8, then do two nested for loops?
    – Lu Xu
    Feb 26 at 7:11
  • @LuXu See my edit. I would use a counter rather than 2 loops. So when the counter is equal to four, we simply insert a \par. A better method is to use MOD 4, but I wanted to keep the code as simple as possible.
    – yannisl
    Feb 26 at 9:33
5

Actually, adding the gaps between the rows and columns was the hard part.

\documentclass{article}
\usepackage{graphicx}
\usepackage{duckuments}
\usepackage{tikz}
\usepackage{showframe}% alignment tool

\def\imagelist{
  example-image/example-image-a,
  example-image-b/example-image-c,
  example-image-duck/example-image-duck,
  example-image-duck/example-image-duck
}
\begin{document}

\begin{figure}[p]
\setlength{\dimen9}{\dimexpr 0.5\textwidth-0.5\columnsep}%
\setlength{\dimen8}{\dimexpr 0.25\textheight-0.75\floatsep}%
\setlength{\lineskip}{\floatsep}%
\foreach \foo/\bar in \imagelist{%
  \includegraphics[width=\dimen9, height=\dimen8]{\foo}\hfill
  \includegraphics[width=\dimen9, height=\dimen8]{\bar}\par
}
\end{figure}

\end{document}

This shows a paracol solution. While you can put figures inside paracol, it adds a blank page for [p] floats.

\documentclass{article}
\usepackage{graphicx}
\usepackage{tikz}
\usepackage{paracol}
\globalcounter*
\usepackage{showframe}% alignment tool

\def\imagelist{
  example-image,
  example-image-a,
  example-image-b,
  example-image-c,
  example-image,
  example-image-a,
  example-image-b,
  example-image-c,  
  example-image,
  example-image-a,
  example-image-b,
  example-image-c,
  example-image,
  example-image-a,
  example-image-b,
  example-image-c
}
\newlength{\rowheight}
\setlength{\rowheight}{\dimexpr 0.25\textheight-0.76\floatsep}% roundoff error

\begin{document}

\begin{paracol}{2}
\parindent=0pt
\lineskip=0pt
\foreach \foo in \imagelist{%
  \includegraphics[width=\columnwidth, height=\rowheight]{\foo}
  \ifnum\thecolumn=0\relax
    \switchcolumn 
  \else
    \switchcolumn*[\vskip\floatsep]
  \fi
}
\end{paracol}
\end{document}
1
  • I know how to achieve this for one figure environment. I did it by setting width to 0.5 textwidth, adding % between two images in a row, and add newlines between rows. But I have trouble putting that into a loop. As you commented, the workaround is to manually repeat the tex code.
    – Lu Xu
    Feb 26 at 5:44

You must log in to answer this question.

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