Skip to content

Instantly share code, notes, and snippets.

@zambonin
Last active July 9, 2026 21:21
Show Gist options
  • Select an option

  • Save zambonin/c3560bd31d5ac177278039f9656dc0d0 to your computer and use it in GitHub Desktop.

Select an option

Save zambonin/c3560bd31d5ac177278039f9656dc0d0 to your computer and use it in GitHub Desktop.
Convert PDF to PDF/A-1b using Ghostscript and check using veraPDF.
# PDF/A-2b (PDF 1.7) converter using Ghostscript.
#
# Annotations must already be marked printable, or Ghostscript drops them. Use
#
# \PassOptionsToPackage{pdfa}{hyperref}
#
# or similar in LaTeX.
#
# make IN=input.pdf OUT=output.pdf convert
# make FILE=file.pdf check
# make files
GS ?= gs
VERAPDF ?= verapdf
CURL ?= curl
override GS := $(shell command -v $(GS))
override VERAPDF := $(shell command -v $(VERAPDF))
override CURL := $(shell command -v $(CURL))
DPI ?= 200
TMPDIR ?= /tmp
WORKDIR := $(patsubst %/,%,$(TMPDIR))/pdfa-$(shell id -u)
FILESDIR := $(WORKDIR)/files
BUILDDIR := $(WORKDIR)/build
ICC := $(FILESDIR)/srgb.icc
TEMPLATE := $(FILESDIR)/PDFA_def.ps
PREFIX := $(BUILDDIR)/PDFA_def.ps
BASEURL := https://raw.githubusercontent.com/ArtifexSoftware/ghostpdl/ghostpdl-10.07.1
.DELETE_ON_ERROR:
.SUFFIXES:
MAKEFLAGS += --no-builtin-rules
.PHONY: convert check files
ifneq (,$(filter convert,$(MAKECMDGOALS)))
ifeq (,$(strip $(IN)))
$(error convert requires IN=<input.pdf>)
endif
ifeq (,$(strip $(OUT)))
$(error convert requires OUT=<output.pdf>)
endif
ifeq (,$(GS))
$(error Ghostscript not found -- install gs or pass GS=/path/to/gs)
endif
ifeq (,$(and $(wildcard $(ICC)),$(wildcard $(TEMPLATE))))
ifeq (,$(CURL))
$(error data files missing and curl not found -- install curl, or copy srgb.icc and PDFA_def.ps into $(FILESDIR))
endif
endif
endif
ifneq (,$(filter check,$(MAKECMDGOALS)))
ifeq (,$(strip $(FILE)))
$(error check requires FILE=<file.pdf>)
endif
ifeq (,$(VERAPDF))
$(error veraPDF not found -- install verapdf or pass VERAPDF=/path/to/verapdf)
endif
endif
ifneq (,$(filter files,$(MAKECMDGOALS)))
ifeq (,$(CURL))
$(error curl not found -- install curl or pass CURL=/path/to/curl)
endif
endif
convert: $(OUT)
$(OUT): $(IN) $(PREFIX) $(ICC)
$(GS) -dNOPAUSE -dBATCH -dQUIET -sDEVICE=pdfwrite -dCompatibilityLevel=1.7 \
-dPDFA=2 -dPDFACompatibilityPolicy=1 -sColorConversionStrategy=RGB \
-sProcessColorModel=DeviceRGB --permit-file-read=$(ICC) \
-dDownsampleColorImages=true -dColorImageResolution=$(DPI) \
-dColorImageFilter=/DCTEncode -dAutoFilterColorImages=false \
-dDownsampleGrayImages=true -dGrayImageResolution=$(DPI) \
-dGrayImageFilter=/DCTEncode -dAutoFilterGrayImages=false \
-sOutputFile=$@ $(PREFIX) $<
$(PREFIX): $(TEMPLATE) $(MAKEFILE_LIST) | $(BUILDDIR)
sed 's|^/ICCProfile (srgb.icc)|/ICCProfile ($(ICC))|' $< > $@
check: $(FILE)
$(VERAPDF) -f 2b --nonpdfext $<
files: $(ICC) $(TEMPLATE)
$(ICC): | $(FILESDIR)
$(CURL) -fsSL -o $@ $(BASEURL)/iccprofiles/srgb.icc
$(TEMPLATE): | $(FILESDIR)
$(CURL) -fsSL -o $@ $(BASEURL)/lib/PDFA_def.ps
$(BUILDDIR) $(FILESDIR):
mkdir -p $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment