Skip to content

Instantly share code, notes, and snippets.

@lelegard
Last active August 29, 2022 14:39
Show Gist options
  • Save lelegard/050c31b7d7dea03ad9db0521d7aa7ccb to your computer and use it in GitHub Desktop.
Save lelegard/050c31b7d7dea03ad9db0521d7aa7ccb to your computer and use it in GitHub Desktop.
Create a one-page blank PDF file, optionally with same page size as an existing reference PDF file
#!/usr/bin/env bash
# Create a one-page blank PDF file.
# Optionally with same page size as an existing reference PDF file (default size: A4).
SCRIPT=$(basename "$0")
usage() { echo >&2 "usage: $SCRIPT output-file [reference-file]"; exit 1; }
error() { echo >&2 "$SCRIPT: error: $*"; exit 1; }
warning() { echo >&2 "$SCRIPT: warning: $*"; }
# Find various tools.
STAT=$(which stat 2>/dev/null)
[[ -z $STAT ]] && error "stat command not found"
SED=$(which gsed 2>/dev/null)
[[ -z $SED ]] && SED=$(which sed 2>/dev/null)
[[ -z $SED ]] && error "sed command not found"
PDFINFO=$(which pdfinfo 2>/dev/null)
QPDF=$(which qpdf 2>/dev/null)
JQ=$(which jq 2>/dev/null)
[[ ( -z $PDFINFO || -z $SED ) && ( -z $QPDF || -z $JQ ) ]] && warning "commands pdfinfo/sed and qpdf/jq not found, using A4 size by default"
# Get file size in bytes of a file.
file-size()
{
$STAT -c %s "$1"
}
# Get page "width height" of a PDF file, in points.
pdf-page-size()
{
local a4="595 842"
local file="$1"
local size=
if [[ -z $file ]]; then
# No file provided, use A4 as default.
size="$a4"
fi
if [[ -z $size && -n $PDFINFO && -n $SED ]]; then
# Command pdfinfo available, try it.
size=$($PDFINFO "$file" | $SED -e '/^Page size:/!d' -e 's/^Page size:[[:space:]]*//' -e 's/ *pts.*$//' -e 's/ *x */ /' | head -1)
fi
if [[ -z $size && -n $QPDF && -n $JQ ]]; then
# Command qpdf available, try it.
size=$($QPDF "$file" --json | $JQ -j 'first(.objects[] | select(."/MediaBox") | ."/MediaBox") | .[2]," ",.[3]' 2>/dev/null)
fi
if [[ -z $size ]]; then
# Size not found, use A4 as default.
size="$a4"
fi
echo $size
}
# Create a blank PDF file, with optional reference PDF file for page size.
create-blank-pdf()
{
local outfile="$1"
local reffile="$2"
local size=$(pdf-page-size "$reffile")
echo '%PDF-1.4' >"$outfile"
local obj1=$(file-size "$outfile")
echo '1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj' >>"$outfile"
local obj2=$(file-size "$outfile")
echo '2 0 obj<</Type/Pages/Count 1/Kids[3 0 R]>>endobj' >>"$outfile"
local obj3=$(file-size "$outfile")
printf '3 0 obj<</Type/Page/MediaBox[0 0 %s]/Parent 2 0 R/Resources<<>>>>endobj\n' "$size" >>"$outfile"
local xref=$(file-size "$outfile")
echo 'xref' >>"$outfile"
echo '0 4' >>"$outfile"
echo '0000000000 65535 f' >>"$outfile"
printf '%010d 00000 n\n' $obj1 >>"$outfile"
printf '%010d 00000 n\n' $obj2 >>"$outfile"
printf '%010d 00000 n\n' $obj3 >>"$outfile"
echo 'trailer<</Size 4/Root 1 0 R>>' >>"$outfile"
echo 'startxref' >>"$outfile"
printf '%d\n' $xref >>"$outfile"
echo '%%EOF' >>"$outfile"
}
[[ -z $1 ]] && usage
create-blank-pdf "$1" "$2"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment