I know this is an old question. In my case I use Reportlab.
Sheet dimensions are expressed in points, not pixels, with a point equal to 1/72 inch. An A4 sheet is made up of 595.2 points width and 841.8 points height. The origin of the position coordinates (0, 0) is in the lower left corner. When creating an instance of canvas.Canvas, you can specify the size of the sheets using the pagesize parameter, passing a tuple whose first element represents the width in points and the second, the height.
The c.showPage () method tells ReportLab that it has already finished working on the current sheet and moves on to the next one. Although a second sheet has not yet been worked on (and will not appear in the document as long as nothing has been drawn) it is good practice to remember to do so before invoking c.save (). To insert images into a PDF document, ReportLab uses the Pillow library. The drawImage () method takes as its argument the path of an image (supports multiple formats such as PNG, JPEG and GIF) and the position (x, y) in the that you want to insert. The image can be reduced or enlarged indicating its dimensions via the width and height arguments.
The following code provides pdf file name, list with png files, coordinates to insert images as well as size to fit in portrait letter pages.
def pntopd(file, figs, x, y, wi, he):
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, letter, landscape, portrait
w, h = letter
c = canvas.Canvas(str(file), pagesize=portrait(letter))
for png in figs:
c.drawImage(png, x, h - y, width=wi, height=he)
c.showPage()
c.save()
from datetime import date
from pathlib import Path
ruta = "C:/SQLite"
today = date.today()
dat_dir = Path(ruta)
tit = today.strftime("%y%m%d") + '_ParameterAudit'
pdf_file = tit + ".pdf"
pdf_path = dat_dir / pdf_file
pnglist = ['C0.png', 'C4387.png', 'C9712.png', 'C9685.png', 'C4364.png']
pntopd(pdf_path, pnglist, 50, 550, 500, 500)