How to mount a .jpg centered into a .pdf (using defined page size and borders)?

I assume you want to add a border of, say 30px, on all four sides. Use the -border option for the size and -bordercolor for the colour:

convert -border 30 -bordercolor white input.png output.pdf

More information can be found here: Imagemagick - Adding/Removing Image Edges

If you want the final PDF to be of a particular size, you can use the following options:

convert \
  -page A4 \
  -gravity northwest \
  -border 30 \
  -bordercolor white \
  input.png output.pdf

Here is a little script that does what you want, and can do it to multiple .jpg files at the same time, converting each into its own one-page .pdf file.

Save the script as imgs_to_pdfs.sh and call it with one or multiple filename arguments, like this:

./imgs_to_pdfs.sh myimg1.jpg myimg2.jpg img-*.jpg

Output filenames will correspond to input filenames with .jpg replaced with .pdf. So make sure the script will not accidentally overwrite existing files!

How it works

  • For the page to mount the image on, the script uses A4 format. It calculates the A4 dimensions itself, since the A4 keyword is seemingly not supported in recent ImageMagick versions anymore.
  • The image is not resampled ("scaled") by the script, just shown centered with a certain resolution on the A4 PDF page canvas. So, no image information is lost by scaling down, and no useless file size added by scaling up.
  • Instead of a 30 pixel minimum margin all around, the script leaves a space between image and PDF page borders. The advantage of this over adding a white border to the image is that it does not add to the file size, and that you can extract the unmodified image later from the PDF if desired, using a command like pdfimages -j file.pdf img.
  • By default, the border around the image will be set to ≥5% of each page dimension. The image is scaled proportionally to achieve this, so x dimension borders will be 5% and y dimension borders will be lager, or the other way round, depending on image proportions. You can adapt the size of the borders by adapting the resolution factor in the script. Currently it is 1.1, leading to 110% of the resolution for an A4 page fit. So the image covers only 90% of the A4 page dimensions, leaving two 5% borders. If you set the factor to 1.2, you get two 10% borders and so on.

Other details

  • Here's the proof how the formulas in the script lead to 5% borders:
    1. Page size in pixels is calculated as page_size_x = density * 8.27
    2. Density is calculated as density = img_size_x / 8.27 * 1.1. (This assumes the case where the x dimension needs the higher density to leave a 5% border empty.)
    3. Line 2 in line 1 yields: page_size_x = (img_size_x/8.27*1.1) * 8.27 = img_size_x * 1.1. So indeed, the page is 110% the pixel width of the image, giving two 5% borders.
  • Some people seem to need a -repage operation (like here) to prevent page size from being slightly "off". Did not need it, but if you do, try -repage ${page_size_x}x${page_size_y} or -repage A4 as last operation in the convert call.

Script source code

#!/bin/bash
# Converts input images to one-page PDF files each, without changing image data.
# The image is centered on a A4 page with a 5% border.

# bc function to calculate maximum of two floats
bc_functions="
define max(a,b) {
  if (a>b) {
    return(a)
  } else {
   return(b)
  }
} ";

for file in "$@"; do \
  # Determine image dimensions in pixels.
  img_size_x=$(identify -format "%w" "$file");
  img_size_y=$(identify -format "%h" "$file");

  # Calculate image density (in dpi) needed to fit the image and a 5% 
  # border all around on an A4 page (8.27x11.69"). Factor 1.1 creates 
  # 2*5% borders, see https://unix.stackexchange.com/a/220114 for details.
  min_density_x=$(echo "$img_size_x/8.27*1.1"  | bc -l);
  min_density_y=$(echo "$img_size_y/11.69*1.1" | bc -l);
  # Use the higher density to prevent any dimension exceeding the required fit.
  density=$(echo "$bc_functions max($min_density_x,$min_density_y)" | bc -l);

  # Calculate canvas dimensions in pixels.
  # (Canvas is an A4 page (8.27x11.69") with the calculated density.)
  page_size_x=$(echo  "8.27*$density" | bc -l);
  page_size_y=$(echo "11.69*$density" | bc -l);

  # Center image on a larger canvas (with a size given by "-extent").
  convert "$file" \
    -gravity center -extent ${page_size_x}x${page_size_y} \
    -units PixelsPerInch -density $density \
    -format pdf -compress jpeg \
    "${file/.jpg/.pdf}";
done;

References

  • The technique to use just -extent to mount an image on a canvas.
  • Calculating max. of two floats in bash, via bc.
  • Using -format pdf to fix some issues. (Seems optional here, others needed it though.)