GeneralArrange content in a variable number of columns / Ignore ‘extra alignment tab has been changed to \cr’

LaTeX specific issues not fitting into one of the other forums of this category.
Post Reply
ZYXW9876
Posts: 2
Joined: Fri Oct 18, 2019 10:11 pm

Arrange content in a variable number of columns / Ignore ‘extra alignment tab has been changed to \cr’

Post by ZYXW9876 »

Hello all

I am trying to arrange a large number of pictures in rows. The pictures have a standardised height and variable widths depending on the aspect ratio.

Plan A

I am wondering whether there is a package that more or less does this:

1. in each row, print as many pictures as will fit the \textwidth (let the number of pictures in the row be x); and
2. in each row, create a table with x columns of equal width, with each column containing one picture.

Ideally, this means that each row could contain a different number of pictures from one another. This also means that, if I decide to change the page size later, I will be able to do that easily.

Plan B

If there is no such package, I would be happy to settle with a solution with the same x for each row, but which still allows me to change the value of x reasonably easily. Again, this is so that I do not have to commit to a particular paper size at this stage.

To that end, I can put the pictures in a longtable with a \begin{longtable}{XXX} statement, where ‘XXX’ is a statement like ‘@{}p{0.3333\textwidth}@{}p{0.3334\textwidth}@{}p{0.3333\textwidth}@{}’ (for a three-column table for example).

I am wondering whether there is a command that I can define and insert between each picture (call this \PictureSeparator) that expands either to ‘&’ or ‘\\’ depending on how many columns are specified. For example, the following (pseudo-)code:

\includegraphics{a}\PictureSeparator
\includegraphics{b}\PictureSeparator
\includegraphics{c}\PictureSeparator
\includegraphics{d}\PictureSeparator
\includegraphics{e}\PictureSeparator
\includegraphics{f}\PictureSeparator

should print as 3 columns in 2 rows if x is specified to be 3, and 2 columns in 3 rows if x is specified to be 2.

Plan C

If there is no way to define such a command, Plan C is to define \PictureSeparator as ‘&’.

As expected, when I compile the document, compilation will pause and I will get the error message ‘Extra alignment tab has been changed to \cr’. I can press enter to ignore the ‘error’ (which is in fact precisely what I would like to achieve) and I will get the output I expect.

In that event, I am wondering whether there is a way to turn off that particular ‘error’ message? Just to clarify, I would still like compilation to pause if there are any other errors.

Other solutions

If there is any other solution that you can think of which can achieve what I have tried to describe above, I would be grateful if you could let me know.

There is definitely no need for a complete coded solution! Just some pointers as to what might possibly work would be much appreciated — I can (try to) figure out the rest! However, please do not hesitate to let me know if you think an MWE would assist regardless.

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org

NEW: TikZ book now 40% off at Amazon.com for a short time.

Ijon Tichy
Posts: 640
Joined: Mon Dec 24, 2018 10:12 am

Arrange content in a variable number of columns / Ignore ‘extra alignment tab has been changed to \cr’

Post by Ijon Tichy »

I do not think, that this makes much sense, but here is a suggestion to do plan A without tabular:

Code: Select all

\documentclass{article}
\usepackage{graphicx}

\makeatletter
\newenvironment{picturerows}{%
  \par
  \setlength{\parindent}{0pt}% no paragraph indent
  \setlength{\parskip}{0pt}% no paragraph skip
  \setlength{\parfillskip}{0pt}% fill the row completely
  \let\@picturerowsincludegraphics\includegraphics
  \let\includegraphics\@picturerowsnextgraphics
  \setlength{\maxpicturewidth}{0pt}%
  \setcounter{picturesinrow}{0}%
  \let\@picturerowsstorage\@empty
}{%
  \@picturerowsoutputrow
}
\newlength{\maxpicturewidth}
\newlength{\thispicturewidth}
\newcounter{picturesinrow}
\newcommand*{\@picturerowsnextgraphics}[2][]{%
  \settowidth{\thispicturewidth}{\@picturerowsincludegraphics[{#1}]{#2}}%
  \ifdim\thispicturewidth>\maxpicturewidth \maxpicturewidth=\thispicturewidth\fi
  \ifdim\dimexpr \numexpr\value{picturesinrow}+1\relax\maxpicturewidth\relax
    >\linewidth\relax
    \@picturerowsoutputrow
    \maxpicturewidth=\thispicturewidth
  \fi
  \stepcounter{picturesinrow}%
  \g@addto@macro\@picturerowsstorage{%
    \makebox[\maxpicturewidth]{\hfil\@picturerowsincludegraphics[{#1}]{#2}\hfil}%
  }%
}
\newcommand*{\@picturerowsoutputrow}{%
  \ifnum \value{picturesinrow}>\z@
    \setlength{\maxpicturewidth}{\dimexpr\linewidth / \value{picturesinrow}\relax}%
    \@picturerowsstorage
    \par
  \fi
  \setlength{\maxpicturewidth}{0pt}%
  \setcounter{picturesinrow}{0}%
  \let\@picturerowsstorage\@empty
}
\makeatother

\usepackage{mwe}

\begin{document}
\blindtext
\begin{picturerows}
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-a}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image-b}%
  \includegraphics[width=.4\textwidth,height=2cm]{example-image-c}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-a}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image-b}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-c}%
  \includegraphics[width=.1\textwidth,height=2cm]{example-image}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-a}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image-b}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-c}%
  \includegraphics[width=.5\textwidth,height=2cm]{example-image}%
\end{picturerows}
\blindtext
\end{document}
or here the same with one tabularx per row:

Code: Select all

\documentclass{article}
\usepackage{graphicx}
\usepackage{tabularx}
\makeatletter
\newenvironment{picturerows}{%
  \par
  \setlength{\parindent}{0pt}% no paragraph indent
  \setlength{\parskip}{0pt}% no paragraph skip
  \setlength{\parfillskip}{0pt}% fill the row completely
  \let\@picturerowsincludegraphics\includegraphics
  \let\includegraphics\@picturerowsnextgraphics
  \setlength{\maxpicturewidth}{0pt}%
  \setcounter{picturesinrow}{0}%
  \let\@picturerowsstorage\@empty
}{%
  \@picturerowsoutputrow
}
\newlength{\maxpicturewidth}
\newlength{\thispicturewidth}
\newcounter{picturesinrow}
\newcommand*{\@picturerowsnextgraphics}[2][]{%
  \settowidth{\thispicturewidth}{\@picturerowsincludegraphics[{#1}]{#2}}%
  \ifdim\thispicturewidth>\maxpicturewidth \maxpicturewidth=\thispicturewidth\fi
  \ifdim\dimexpr \numexpr\value{picturesinrow}+1\relax\maxpicturewidth\relax
    >\linewidth\relax
    \@picturerowsoutputrow
    \maxpicturewidth=\thispicturewidth
  \fi
  \ifnum\value{picturesinrow}>\z@
    \g@addto@macro\@picturerowsstorage{&}%
  \fi
  \stepcounter{picturesinrow}%
  \g@addto@macro\@picturerowsstorage{%
    \@picturerowsincludegraphics[{#1}]{#2}%
  }%
}
\newcommand*{\@picturerowsoutputrow}{%
  \ifnum \value{picturesinrow}>\z@
    \begin{tabularx}{\linewidth}{@{}*{\value{picturesinrow}}{>{\centering}X@{}}}
      \@picturerowsstorage\tabularnewline
    \end{tabularx}
    \par
  \fi
  \setlength{\maxpicturewidth}{0pt}%
  \setcounter{picturesinrow}{0}%
  \let\@picturerowsstorage\@empty
}
\makeatother

\usepackage{mwe}

\begin{document}
\blindtext
\begin{picturerows}
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-a}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image-b}%
  \includegraphics[width=.4\textwidth,height=2cm]{example-image-c}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-a}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image-b}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-c}%
  \includegraphics[width=.1\textwidth,height=2cm]{example-image}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-a}%
  \includegraphics[width=.3\textwidth,height=2cm]{example-image-b}%
  \includegraphics[width=.2\textwidth,height=2cm]{example-image-c}%
  \includegraphics[width=.5\textwidth,height=2cm]{example-image}%
\end{picturerows}
\blindtext
\end{document}
Despite the fact, that I cannot see any advantage in using this instead of simply adding \hfill between the images, measuring and storage can be used for several different approaches. So I've posted it, because it could be useful for other suggestions too.
Sorry, but I can no longer participate here as the administrator is trampling on my wishes on one of his other platforms. :cry:
ZYXW9876
Posts: 2
Joined: Fri Oct 18, 2019 10:11 pm

Arrange content in a variable number of columns / Ignore ‘extra alignment tab has been changed to \cr’

Post by ZYXW9876 »

Hi Ijon Tichy

Thanks so much for this! I really appreciate this very fast and comprehensive reply. This looks like just what I need — and sorry for any confusion: I was definitely not attached to using tabularx when there is a better alternative!
User avatar
Ijon Tichy
Posts: 640
Joined: Mon Dec 24, 2018 10:12 am

Arrange content in a variable number of columns / Ignore ‘extra alignment tab has been changed to \cr’

Post by Ijon Tichy »

I just wanted to also show one of the very simple hfil-alternatives:

Code: Select all

\documentclass{article}
\usepackage{mwe}
\begin{document}
\blindtext

\begin{center}
\includegraphics[width=.2\textwidth,height=2cm]{example-image-a}\hfil
\includegraphics[width=.3\textwidth,height=2cm]{example-image-b}\hfil
\includegraphics[width=.4\textwidth,height=2cm]{example-image-c}\hfil
\includegraphics[width=.3\textwidth,height=2cm]{example-image}\hfil
\includegraphics[width=.2\textwidth,height=2cm]{example-image-a}\hfil
\includegraphics[width=.3\textwidth,height=2cm]{example-image-b}\hfil
\includegraphics[width=.2\textwidth,height=2cm]{example-image-c}\hfil
\includegraphics[width=.1\textwidth,height=2cm]{example-image}\hfil
\includegraphics[width=.2\textwidth,height=2cm]{example-image-a}\hfil
\includegraphics[width=.3\textwidth,height=2cm]{example-image-b}\hfil
\includegraphics[width=.2\textwidth,height=2cm]{example-image-c}\hfil
\includegraphics[width=.5\textwidth,height=2cm]{example-image}%
\end{center}

\blindtext
\end{document}
If you do not want centering, you can omit the center environment. Instead of \hfil you can alternatively use something like \hspace{1em plus 1fil}% to have a minimum distance of 1em between the the images.

Yes, in this example the width of the image cells differ from image to image. But IHMO this would be an advantage not a disadvantage.
Sorry, but I can no longer participate here as the administrator is trampling on my wishes on one of his other platforms. :cry:
Post Reply