pdfsign/pdfsign.sh
2025-10-10 22:56:51 +00:00

102 lines
2.4 KiB
Bash
Executable file

#!/bin/bash
#################
# PREREQUISITES #
#################
# executables in PATH
for prereq in "python3" "gs" "pdftk"; do
if ! command -v "${prereq}" &> /dev/null; then
echo "required executable '${prereq}' not found!"
exit 1
fi
done
# python virtual env with PyMuPDF
VENV_DIR="pdfsign.venv"
if [ -d "${VENV_DIR}" ]; then
# venv exists, activate it
source "${VENV_DIR}/bin/activate"
else
for prereq in "venv"; do
if ! python3 -c "import ${prereq}" &> /dev/null; then
echo "python module '${prereq}' not found!"
exit 1
fi
done
# create venv and activate
python3 -m "venv" "${VENV_DIR}"
source "${VENV_DIR}/bin/activate"
# install PyMuPDF
python3 -m "pip" install PyMuPDF
fi
############
# CLI ARGS #
############
if [ $# -lt 2 ]; then
echo "Usage: ${0} <input.pdf> <signed.png> [PAGE]"
echo
echo "Replaces page PAGE with the signed version."
echo "If PAGE is not given, the last page is replaced."
exit 1
fi
IN_TEXT_PDF="${1}"
IN_SCAN_IMG="${2}"
OUT_PDF="${IN_TEXT_PDF%%.*}_pdfsign.pdf"
IN_TEXT_PDF_LEN="$( pdftk "${IN_TEXT_PDF}" dump_data | grep NumberOfPages | awk '{print $2}' )"
IN_PAGE="${3:-${IN_TEXT_PDF_LEN}}"
RANGES="B1"
if [ ${IN_PAGE} -gt 1 ]; then
RANGES="A1-$(( IN_PAGE - 1 )) ${RANGES}"
fi
if [ ${IN_PAGE} -lt ${IN_TEXT_PDF_LEN} ]; then
RANGES="${RANGES} A$(( IN_PAGE + 1 ))-${IN_TEXT_PDF_LEN}"
fi
################
# MAIN PROGRAM #
################
GSFLAGS="-sDEVICE=pdfwrite -dSAFER -dNOPAUSE -dQUIET -dBATCH"
set -e
# extract IN_PAGE (text-only) from IN_TEXT_PDF
gs ${GSFLAGS} \
-dFirstPage="${IN_PAGE}" -dLastPage="${IN_PAGE}" \
-dFILTERIMAGE -dFILTERVECTOR -dFILTERTEXT=false \
-sOutputFile=".pdfsign_textonly.pdf" \
"${IN_TEXT_PDF}"
# use IN_SCAN_IMG as background, layering text from extracted page on top
python3 ./pdfsign.py \
".pdfsign_textonly.pdf" "${IN_SCAN_IMG}" \
".pdfsign_signed.pdf"
rm ".pdfsign_textonly.pdf"
# replace IN_PAGE in IN_TEXT_PDF layered page
pdftk A="${IN_TEXT_PDF}" B=".pdfsign_signed.pdf" \
cat ${RANGES} \
output ".pdfsign_concat.pdf"
rm ".pdfsign_signed.pdf"
# postprocess/compress pdf
gs ${GSFLAGS} \
-sPAPERSIZE=a4 -dFIXEDMEDIA -dPDFFitPage \
-dCompatibilityLevel=1.7 -dPDFSETTINGS=/ebook \
-sOutputFile="${OUT_PDF}" \
".pdfsign_concat.pdf"
rm ".pdfsign_concat.pdf"