719016
719016

Reputation: 10441

imagemagick construct document with two images per A4 page

Using Ubuntu 14.04 Linux, I have a list of .jpg images in a folder called Capture 01.jpg, Capture 02.jpg, etc. and I would like to compose a command-line that creates a multi-page document with A4 sized pages where each page contains 2 of the images in order as given, with the name of the file as header, and with the pages containing the footer like 'Page 1 of 41'. See, e.g.:

------
Capture 01.jpg

[image]

Capture 02.jpg

[image]
Page 1 of 41
------
Capture 03.jpg

[image]

Capture 04.jpg

[image]
Page 2 of 41
------
...

The images are all the same size, roughly 1600x1200 pixels.

Knowing a bit about how ImageMagick works, I presume this will involve some sort of collate or montage command, but I am unsure how to make it fit A4 sized pages and how to format them for printing (pdf?).

Any recommendations?

EDIT: I found a question which relates to adding the file name for the image:

Overlaying an image's filename using ImageMagick (or similar)

Upvotes: 2

Views: 921

Answers (2)

AkselA
AkselA

Reputation: 8846

On fmw42's request, here is my version, which I believe is an improvement due to better handling of 'difficult' file names.

First some setup.
Create directory, download image, copy x6 and give new wacky names.

#!/bin/bash

cd ~/Desktop
mkdir testimagesSO
cd testimagesSO
wget "https://i.imgur.com/GeaEv21.png"

mv *.png testimage.png

Names=("Drøbaksundet\n img #1*" "Drøbaksundet\n img #2*" "Drøbaksundet\n img #3*" \
       "Drøbaksundet\n img #4*" "Drøbaksundet\n img #5*" "Drøbaksundet\n img #6*" )

echo "${#Names[@]}"

for f in "${Names[@]}"
do
  cp testimage.png "$f".png
done

rm testimage.png

The meat of the command is very similar to that of fmw42, except it's entirely array based. I also stepped around the use of bc.

arr=(*)
num=${#arr[*]}
numm1=$((num-1))
npp=2
numpages=$((($num+$npp-1)/$npp))
echo "numpages=$numpages"
pagenum=1
(
for ((i=0; i<numm1; i=i+2)); do
  j=$((i+1))
  convert "${arr[$i]}" "${arr[$j]}" -background white -gravity center -append \
  -resize 595x842 -extent 595x842 +repage \
  -font arial -pointsize 18 -undercolor white -fill black \
  -gravity north -annotate +0+10 "${arr[$i]}" \
  -annotate +0+431 "${arr[$j]}" \
  -gravity south  -annotate +0+10 "Page $pagenum of $numpages" miff:-
  pagenum+=1
done
) | convert - ../result2.pdf

I don't have a handy place for hosting PDFs, but this is more or less the output I get (imagine it divided over 3 A4 pages.

enter image description here

Upvotes: 2

fmw42
fmw42

Reputation: 53154

First I would recommend not having spaces in your filenames and using enough leading zeros that the files in your directory are in alphabetic order.

I took this one image:

enter image description here


and duplicated it 5 more times and numbered them in sequence as:

lena_01.png
lena_02.png
lena_03.png
lena_04.png
lena_05.png
lena_06.png

and put them into a new folder called "test" on my desktop on my Mac.

Then using ImageMagick 6 with Unix bash shell scripting, I created a loop inside a subshell so that I could save the intermediate images to MIFF: format without having to save them individually. I then piped the output to a new convert to save as PDF. Note the subshell is indicated by the parenthesis surrounding the for loop.

Here is the set of commands:

#!/bin/bash

cd
cd desktop/test
arr=(`ls`)
num=${#arr[*]}
numm1=$((num-1))
numpages=`echo "scale=0; ($num+0.5)/2" | bc`
pagenum=1
(
for ((i=0; i<numm1; i=i+2)); do
  j=$((i+1))
  convert "${arr[$i]}" "${arr[$j]}" -background white -gravity center -append \
  -resize 595x842 -extent 595x842 +repage \
  -font arial -pointsize 18 -undercolor white -fill black \
  -gravity north -annotate +0+10 "${arr[$i]}" -annotate +0+431 "${arr[$j]}" \
  -gravity south -annotate +0+10 "Page $pagenum of $numpages" miff:-
  pagenum=$((pagenum+1))
  done
) | convert - ../result.pdf


where arr is an array of the image names in the test directory. Note that an A4 page size is 595x842 and at 72 dpi prints as 8.27 × 11.7 inches

result.pdf

If you do want to keep spaces in your file names, then you can change the IFS to a new line before the arr statement and then change it back to a space afterwards. For example:

lena 01.png
lena 02.png
lena 03.png
lena 04.png
lena 05.png
lena 06.png

The code would change to the following:

cd
cd desktop/test
OLDIFS=$IFS
IFS=$'\n'
arr=(`ls`)
num=${#arr[*]}
numm1=$((num-1))
numpages=`echo "scale=0; ($num+0.5)/2" | bc`
echo "numpages=$numpages"
pagenum=1
IFS=$OLDIFS
(
for ((i=0; i<numm1; i=i+2)); do
j=$((i+1))
convert "${arr[$i]}" "${arr[$j]}" -background white -gravity center -append \
-resize 595x842 -extent 595x842 +repage \
-font arial -pointsize 18 -undercolor white -fill black \
-gravity north -annotate +0+10 "${arr[$i]}" \
-annotate +0+431 "${arr[$j]}" \
-gravity south  -annotate +0+10 "Page $pagenum of $numpages" miff:-
pagenum=$((pagenum+1))
done
) | convert - ../result2.pdf

result2.pdf

Upvotes: 3

Related Questions