convert images to pdf: How to make PDF Pages same size
Solution 1
Last time I used convert
for such a task I explicitly specified the size of the destination via resizing:
$ i=150; convert a.png b.png -compress jpeg -quality 70 \
-density ${i}x${i} -units PixelsPerInch \
-resize $((i*827/100))x$((i*1169/100)) \
-repage $((i*827/100))x$((i*1169/100)) multipage.pdf
The convert
command doesn't always use DPI as default density/page format unit, thus we explicitly specify DPI with the -units
option (otherwise you may get different results with different versions/input format combinations). The new size (specified via -resize
) is the dimension of a DIN A4 page in pixels. The resize argument specifies the maximal page size. What resolution and quality to pick exactly depends on the use case - I selected 150 DPI and average quality to save some space while it doesn't look too bad when printed on paper.
Note that convert
by default does not change the aspect ratio with the resize operation:
Resize will fit the image into the requested size. It does NOT fill, the requested box size.
Depending on the ImageMagick version and the involved input formats it might be ok to omit the -repage
option. But sometimes it is required and without that option the PDF header might contain too small dimensions. In any case, the -repage
shouldn't hurt.
The computations use integer arithmetic since bash
only supports that. With zsh
the expressions can be simplified - i.e. replaced with $((i*8.27))x$((i*11.69))
.
Lineart Images
If the PNG files are bi-level (black & white a.k.a lineart) images then the img2pdf
tool yields superior results over ImageMagick convert
. That means img2pdf
is faster and yields smaller PDFs.
Example:
$ img2pdf -o multipage.pdf a.png b.png
or:
$ img2pdf --pagesize A4 -o multipage.pdf a.png b.png
Solution 2
What you really want to use is:
$ convert a.png b.png -compress jpeg -resize 1240x1753 \
-extent 1240x1753 -gravity center \
-units PixelsPerInch -density 150x150 multipage.pdf
-extent
actually extends the image to be 1240x1753, while -resize
keeps the image's ratio, fitting it into either 1240x...
or ...x1753
.
The -gravity
parameter is optional but can be used to center the image when extending.
Solution 3
Addition to caugner's answer:
having installed IM v6.6.9-7 i found out the -gravity
parameter needs to be placed in between -resize
and -extent
to have an effect.
additionally (altough not part of the o.p. question) i found setting a different background-color appealing which would result in the total command of
convert in.jpg -resize 1240x1750 -background black -compose Copy\
-gravity center -extent 1240x1750\
-units PixelsPerInch -density 150 out.pdf
another useful variation i often use when i don't want to re-scale an image that already comes in the correct aspect-ratio but keep its individual resolution is
convert in.jpg -units PixelsPerInch -set density '%[fx:w/8.27]'\
-repage a4 out.pdf
where the target density is dynamically determined by calculating the width divided by 8.27 (which is the width in inch of an A4 page). the -repage a4
parameter can be omitted most of the time but i've had a few cases where the resulting .pdf would have a different format sligtly off the A4 dimensions of 210x297mm (8.27x11.6")
Solution 4
I highly recommend the Python CLI program img2pdf
for lossless conversion:
https://gitlab.mister-muffin.de/josch/img2pdf
Example usage:
img2pdf img1.png img2.png -o out.pdf
Solution 5
I find the following script convenient which combines the answers listed here as well as some problems I had with the floating point calculation:
endInputArgs=$(($#-1))
quoted_args="$(printf " %q" "${@:1:$endInputArgs}")"
output_arg="$(printf " %q" "${@:$#:1}")"
ratiox=$(echo "150*8.27" | bc -l)
ratioy=$(echo "150*11.69" | bc -l)
bash -c "convert $quoted_args -compress jpeg -resize 1240x1753 \
-units PixelsPerInch -density 150x150 -repage ${ratiox}x${ratioy} $output_arg"
The script is called (saved as a file images2pdf)
images2pdf file\ 1.jpg file\ 2.jpg file\ 3.jpg output.pdf
/edit: Added "-l" flag according to comment by tanius for better precision.
Related videos on Youtube
Jiew Meng
Updated on September 18, 2022Comments
-
Jiew Meng over 1 year
I did something like
convert -page A4 -compress A4 *.png CH00.pdf
But the 1st page is much larger than the subsequent pages. This happens even though the image dimensions are similar. These images are scanned & cropped thus may have slight differences in dimensions
I thought
-page A4
should fix the size of the pages? -
brownian about 11 yearsThank you!
-extent
is really what I want to use :) -- please, add missed left quote in front of -extent, thanks! -
caugner almost 11 yearsThank you, I have eventually added the missing tick! ;-)
-
Scolytus about 10 yearswhen using
-repage a4
I get ainvalid argument for option '-repage': a4
-
maxschlepzig about 10 years@Scolytus, on a Fedora 19 system I've observed a similar issue - it seems that
-repage
does not support the a4 name anymore. I've worked around this via shell arithmetic:-repage $((150*8.27))x$((150*11.69))
-
Michael Scheper about 9 yearsI assume those magic numbers are 150dpi, and A4 expressed in legacy units?
-
maxschlepzig about 9 years@MichaelScheper, yes, dpi and inches.
-
dma_k about 9 yearsThanks, help me. Actually
-density 150
argument was important to add . -
Alen Milakovic almost 9 yearsI was only able to get this to work by leaving off
-density 150x150
(I was trying to convert a JPG). Why is it necessary to include the density, and how do you know what it is, anyway? -
tanius almost 9 yearsGeneral hint:
$(echo "150*8.27" | bc)
is still not great for floating point. Works here because it's a multiplication. For$(echo "150/8.27" | bc)
though, the result is18
(truncated to integer). Instead, callbc
with higherscale
:$(echo "150/8.27" | bc -l)
, the results is18.137847…
. -
Yotam almost 9 yearsIn the above, I had to change
-set density $ImgDens
into-density $ImgDens
-
maxschlepzig almost 8 years@FaheemMitha, the resize command in the above examples assumes a resulting resolution of 150 DPI such that we arrive at DIN A4 dimensions - the density option explicitly sets that attribute for the PDF format. Otherwise ImageMagick ends up writing the wrong dimensions in the PDF - at least the Fedora 23 version I currently use in combination with PNG/PBM files does so.
-
Alen Milakovic almost 8 yearsHi @maxschlepzig, thanks for the clarification. What made you reply after nearly a year? :-)
-
Marcus Junius Brutus over 7 yearsUsing the incantation as provided gave me
bash: i*8.27: syntax error: invalid arithmetic operator (error token is ".27")
inGNU bash 4.3.11
. I had to use the following form instead: ` -resize $(echo ${i}*8.27 | bc)x$(echo ${i}*11.69 | bc). BTW, the
-repage` was also necessary. -
maxschlepzig over 7 years@MarcusJuniusBrutus, I tested the last revision just in zsh and apparently bash doesn't support decimal arithmetic. As an alternative, you can also use intetger only arithmetic like this
echo $((i*827/100))x$((i*1169/100))
. This saves thebc
calls. I'll update my answer.