Render each page of two PDF files to PNG and compare them page by page with odiff. This is useful for checking that rendered documents (for example clinical tables, listings and figures, or Quarto/R Markdown documents rendered to PDF) still look the same after a code, package or R upgrade.
Usage
compare_pdfs(
baseline,
current,
pages = NULL,
dpi = 150,
diff_dir = NULL,
threshold = 0.1,
antialiasing = FALSE,
ignore_regions = NULL,
parallel = FALSE,
...
)Arguments
- baseline
Path to the baseline (reference) PDF file.
- current
Path to the current PDF file to compare against
baseline.- pages
Integer vector of page numbers to compare, or
NULL(default) to compare all pages of both files (the union of their page ranges). Pages that do not exist in either file raise an error.- dpi
Resolution, in dots per inch, used to render the pages. Default is 150. Higher values detect smaller differences but take longer and produce larger images.
- diff_dir
Directory to save diff images. If
NULL(default), no diff images are created. When given, the rendered pages are also kept underfile.path(diff_dir, "pages")(inbaseline/andcurrent/subdirectories).- threshold
Numeric; colour difference threshold between 0.0 and 1.0. Default is 0.1.
- antialiasing
Logical; if
TRUE, ignore antialiased pixels. Default isFALSE.- ignore_regions
Regions to ignore on every compared page, as accepted by
compare_images()(seeignore_region()). Coordinates are in pixels of the rendered page, so they depend ondpi: a point atxinches from the left edge is at pixelx * dpi.- parallel
Logical; if
TRUE, compare pages in parallel. Seecompare_images_batch()for details.- ...
Additional arguments passed to
compare_images()viacompare_images_batch(), e.g.fail_on_layout = TRUE.
Value
A tibble (if available) or data.frame with class odiffr_batch,
with one row per compared page, containing the same columns as
compare_images_batch() (including error) plus a trailing integer
page column. img1 and img2 are the paths of the rendered page
images. The result can be passed to summary(), batch_report() and
the other functions that accept an odiffr_batch.
Details
Requires the pdftools package (and therefore the poppler library)
for rendering. Only PDF input is supported: convert RTF or DOCX outputs
to PDF first, for example with LibreOffice
(soffice --headless --convert-to pdf file.rtf).
Pages are rendered with pdftools::pdf_convert() to files named
<pdf name>_p001.png, <pdf name>_p002.png, ... in separate baseline/
and current/ directories. If diff_dir is NULL, they are written to
a new directory inside tempdir(), which persists until the R session
ends, so that reports showing the rendered pages can still be created
after compare_pdfs() returns.
When the two files have a different number of pages, a message is emitted and the pages present in only one file are reported using the existing reasons, so that summaries and reports work unchanged:
A page present in
baselinebut not incurrentis reported withmatch = FALSE,reason = "missing"and the error"Page N not present in current PDF"(like a file missing from the current directory incompare_image_dirs()).A page present in
currentbut not inbaselineis reported withmatch = FALSE,reason = "error"and the error"Page N not present in baseline PDF".
In both cases img1/img2 point to the rendered page that exists and
to the (nonexistent) path the other page would have had.
Pages with different sizes (e.g. portrait versus landscape) are compared
as images of different dimensions; by default odiff reports the
differing pixels, and with fail_on_layout = TRUE such pages are
reported with reason = "layout-diff".
An error is raised if a file does not exist or cannot be read as a PDF (for example a corrupt or password-protected file).
See also
compare_pdf_dirs() for comparing directories of PDF files,
compare_images_batch(), batch_report().
Examples
if (FALSE) { # \dontrun{
res <- compare_pdfs("qc/t_demog.pdf", "prod/t_demog.pdf",
diff_dir = "pdf-diffs")
summary(res)
res[!res$match, c("page", "reason", "diff_percentage")]
# Only the first two pages, at a higher resolution
compare_pdfs("old.pdf", "new.pdf", pages = 1:2, dpi = 300)
# Ignore a run-date footer: bottom 0.5 inch of a US Letter page at 150 dpi
compare_pdfs("old.pdf", "new.pdf", dpi = 150,
ignore_regions = ignore_region(0, 1575, 1275, 1650))
} # }
