aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2023-12-23 03:03:47 +0100
committerJay Berkenbilt <ejb@ql.org>2023-12-23 03:22:34 +0100
commitc0c7cef16cb666524e4809834063cfee5262eca1 (patch)
tree38cb6da6567e7cbcac97766629d568363cd9ec16
parent1f4568684341ec3a0abb0c7ce72580b07b73d646 (diff)
downloadqpdf-c0c7cef16cb666524e4809834063cfee5262eca1.tar.zst
Generate a UNIX man page (fixes #874)
-rw-r--r--CMakeLists.txt12
-rw-r--r--ChangeLog3
-rwxr-xr-xgenerate_auto_job60
-rw-r--r--job.sums9
-rw-r--r--libqpdf/qpdf/auto_job_help.hh8
-rw-r--r--manual/CMakeLists.txt4
-rw-r--r--manual/cli.rst8
-rw-r--r--manual/qpdf.11109
-rw-r--r--manual/release-notes.rst5
9 files changed, 1198 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c264bfa3..e0e3976b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,8 @@ cmake_minimum_required(VERSION 3.16)
# make_dist expects the version line to be on a line by itself after
# the project line. When updating the version, check make_dist for all
# the places it has to be updated. The doc configuration and CI build
-# also find the version number here.
+# also find the version number here. generate_auto_job also reads the
+# version from here.
project(qpdf
VERSION 11.7.0
LANGUAGES C CXX)
@@ -312,9 +313,12 @@ endif()
set(auto_job_inputs
# Keep in sync with SOURCES in generate_auto_job
generate_auto_job
+ CMakeLists.txt
manual/_ext/qpdf.py
job.yml
- manual/cli.rst)
+ manual/cli.rst
+ manual/qpdf.1.in
+)
set(auto_job_outputs
# Keep in sync with DESTS in generate_auto_job
@@ -323,7 +327,9 @@ set(auto_job_outputs
libqpdf/qpdf/auto_job_help.hh
libqpdf/qpdf/auto_job_schema.hh
libqpdf/qpdf/auto_job_json_decl.hh
- libqpdf/qpdf/auto_job_json_init.hh)
+ libqpdf/qpdf/auto_job_json_init.hh
+ manual/qpdf.1
+)
if(GENERATE_AUTO_JOB)
add_custom_command(
diff --git a/ChangeLog b/ChangeLog
index 8ccb689c..55c5112c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2023-12-22 Jay Berkenbilt <ejb@ql.org>
+ * Generate a more complete qpdf "man page" from the same source as
+ qpdf --help. Fixes #874.
+
* Allow the syntax "--encrypt --user-password=user-password
--owner-password=owner-password --bits={40,128,256}" when
encrypting PDF files. This is an alternative to the syntax
diff --git a/generate_auto_job b/generate_auto_job
index 10d74d89..d4143d5a 100755
--- a/generate_auto_job
+++ b/generate_auto_job
@@ -134,6 +134,12 @@ BANNER = f'''//
// clang-format off
//'''
+MAN_BANNER = f'''.\\"
+.\\" This file is automatically generated by {whoami}.
+.\\" Edits will be automatically overwritten if the build is
+.\\" run in maintainer mode.
+.\\"
+'''
def warn(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
@@ -156,9 +162,11 @@ class Main:
SOURCES = [
# Keep this list in sync with CMakeLists.txt: auto_job_inputs
whoami,
+ 'CMakeLists.txt',
'manual/_ext/qpdf.py',
'job.yml',
'manual/cli.rst',
+ 'manual/qpdf.1.in',
]
# DESTS is a map to the output files this code generates. These
# generated files, as well as those added to DESTS later in the
@@ -172,6 +180,7 @@ class Main:
'schema': 'libqpdf/qpdf/auto_job_schema.hh',
'json_decl': 'libqpdf/qpdf/auto_job_json_decl.hh',
'json_init': 'libqpdf/qpdf/auto_job_json_init.hh',
+ 'man': 'manual/qpdf.1',
# Others are added in top
}
# SUMS contains a checksum for each source and destination and is
@@ -277,7 +286,7 @@ class Main:
for k, v in hashes.items():
print(f'{k} {v}', file=f)
- def generate_doc(self, df, f):
+ def generate_doc(self, df, f, f_man):
st_top = 0
st_topic = 1
st_option = 2
@@ -324,6 +333,23 @@ class Main:
return True
return False
+ def manify(text):
+ lines = text.split('\n')
+ out = []
+ last_was_item = False
+ for line in lines:
+ if line.startswith('- '):
+ last_was_item = True
+ out.append('.IP \\[bu]')
+ out.append(line[2:])
+ elif last_was_item and line.startswith(' '):
+ out.append(line[2:])
+ else:
+ last_was_item = False
+ out.append(line)
+ return '\n'.join(out)
+
+ last_option_topic = ''
lineno = 0
for line in df.readlines():
if help_lines == 0:
@@ -366,6 +392,8 @@ class Main:
self.all_topics.add(topic)
print(f'ap.addHelpTopic("{topic}", "{short_text}",'
f' R"({long_text})");', file=f)
+ print(f'.SH {topic.upper()} ({short_text})', file=f_man)
+ print(manify(long_text), file=f_man, end='')
help_lines += 1
state = st_top
elif state == st_option:
@@ -389,6 +417,11 @@ class Main:
self.jdata[option[2:]]['help'] = short_text
print(f'ap.addOptionHelp("{option}", "{topic}",'
f' "{short_text}", R"({long_text})");', file=f)
+ if last_option_topic != topic:
+ print('.PP\nRelated Options:', file=f_man)
+ last_option_topic = topic
+ print(f'.TP\n.B {option} \\-\\- {short_text}', file=f_man)
+ print(manify(long_text), file=f_man, end='')
help_lines += 1
state = st_top
if help_lines == 20:
@@ -400,6 +433,11 @@ class Main:
print('ap.addHelpFooter("For detailed help, visit'
' the qpdf manual: https://qpdf.readthedocs.io\\n");', file=f)
print('}\n', file=f)
+ print('''.SH SEE ALSO
+.PP
+For a summary of qpdf's options, please run \\fBqpdf \\-\\-help\\fR.
+A complete manual can be found at https://qpdf.readthedocs.io.
+''', file=f_man, end='')
for i in self.referenced_topics:
if i not in self.all_topics:
raise Exception(f'help text referenced --help={i}')
@@ -412,6 +450,14 @@ class Main:
warn(f'{whoami}: regenerating auto job files')
self.validate(data)
+ version = None
+ with open('CMakeLists.txt', 'r') as f:
+ for line in f.readlines():
+ if line.strip().startswith('VERSION '):
+ version = line.strip().split(' ')[1]
+ if version is None:
+ raise Exception("can't read version from CMakeLists.txt")
+
# Keep track of which options are help options since they are
# handled specially. Add the built-in help options to tables
# that we populate as we read job.yml since we won't encounter
@@ -436,9 +482,15 @@ class Main:
for i in self.init:
print(i, file=f)
with write_file(self.DESTS['help']) as f:
- with open('manual/cli.rst', 'r') as df:
- print(BANNER, file=f)
- self.generate_doc(df, f)
+ with write_file(self.DESTS['man']) as f_man:
+ print(MAN_BANNER, file=f_man, end='')
+ with open('manual/qpdf.1.in', 'r') as m_in:
+ for line in m_in.readlines():
+ line = line.replace('@PROJECT_VERSION@', version)
+ print(line, file=f_man, end='')
+ with open('manual/cli.rst', 'r') as df:
+ print(BANNER, file=f)
+ self.generate_doc(df, f, f_man)
# Compute the json files after the config and arg parsing
# files. We need to have full information about all the
diff --git a/job.sums b/job.sums
index 46acb1c6..58931220 100644
--- a/job.sums
+++ b/job.sums
@@ -1,5 +1,6 @@
# Generated by generate_auto_job
-generate_auto_job bf44181b610d335511a41b6c2b9c3497d0b023a1ca2c8e4537b34cb6262ce173
+CMakeLists.txt 66e8f9bf15a0c3394b1b13baaf5a709f7af35a6f733cd173092168e87202c7a5
+generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86
include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42
include/qpdf/auto_job_c_enc.hh 28446f3c32153a52afa239ea40503e6cc8ac2c026813526a349e0cd4ae17ddd5
@@ -8,10 +9,12 @@ include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c
include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1
job.yml 4f89fc7b622df897d30d403d8035aa36fc7de8d8c43042c736e0300d904cb05c
libqpdf/qpdf/auto_job_decl.hh 9c6f701c29f3f764d620186bed92685a2edf2e4d11e4f4532862c05470cfc4d2
-libqpdf/qpdf/auto_job_help.hh ea1fdca2aa405bdf193732c5a2789c602efe2add3aa6e2dceecfacee175ce65c
+libqpdf/qpdf/auto_job_help.hh bbd37ac0e8b3e38892a328ca08829d6e71c31ea3ab6c1a91b5f6983018695ef9
libqpdf/qpdf/auto_job_init.hh b4c2b3724fba61f1206fd3bae81951636852592f67a63ef9539839c2c5995065
libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297
libqpdf/qpdf/auto_job_json_init.hh f5acb9aa103131cb68dec0e12c4d237a6459bdb49b24773c24f0c2724a462b8f
libqpdf/qpdf/auto_job_schema.hh b53c006fec2e75b1b73588d242d49a32f7d3db820b1541de106c5d4c27fbb4d9
manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
-manual/cli.rst 28cc6b36b26377404022bab467e6a16085023fdfa5d9d419595ffcae6c69d531
+manual/cli.rst 7bbeb2f234ca3d095c069f52e4a3c5e42a525b5ef6231955d036a6313eaffcd2
+manual/qpdf.1 745cb32c1772e6d84ef962aca7a439ee045226ae547330778a4a3ba3cd8d25df
+manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b
diff --git a/libqpdf/qpdf/auto_job_help.hh b/libqpdf/qpdf/auto_job_help.hh
index b96c2564..4a0f3a8f 100644
--- a/libqpdf/qpdf/auto_job_help.hh
+++ b/libqpdf/qpdf/auto_job_help.hh
@@ -37,10 +37,10 @@ description of the JSON input file format.
)");
ap.addHelpTopic("exit-status", "meanings of qpdf's exit codes", R"(Meaning of exit codes:
-0: no errors or warnings
-1: not used by qpdf but may be used by the shell if unable to invoke qpdf
-2: errors detected
-3: warnings detected, unless --warning-exit-0 is given
+- 0: no errors or warnings
+- 1: not used by qpdf but may be used by the shell if unable to invoke qpdf
+- 2: errors detected
+- 3: warnings detected, unless --warning-exit-0 is given
)");
ap.addOptionHelp("--warning-exit-0", "exit-status", "exit 0 even with warnings", R"(Use exit status 0 instead of 3 when warnings are present. When
combined with --no-warn, warnings are completely ignored.
diff --git a/manual/CMakeLists.txt b/manual/CMakeLists.txt
index 53109937..6f4c0a33 100644
--- a/manual/CMakeLists.txt
+++ b/manual/CMakeLists.txt
@@ -22,7 +22,7 @@ if(BUILD_DOC)
endif()
set(MANUAL_SRC ${qpdf_SOURCE_DIR}/manual)
-foreach(F qpdf.1 fix-qdf.1 zlib-flate.1)
+foreach(F fix-qdf.1 zlib-flate.1)
configure_file(
${MANUAL_SRC}/${F}.in
${CMAKE_CURRENT_BINARY_DIR}/${F}
@@ -129,7 +129,7 @@ if(NOT WIN32)
# environment, especially when all they do is refer people to the
# manual.
install(FILES
- ${CMAKE_CURRENT_BINARY_DIR}/qpdf.1
+ ${qpdf_SOURCE_DIR}/manual/qpdf.1
${CMAKE_CURRENT_BINARY_DIR}/fix-qdf.1
${CMAKE_CURRENT_BINARY_DIR}/zlib-flate.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
diff --git a/manual/cli.rst b/manual/cli.rst
index 9f173ed8..93131542 100644
--- a/manual/cli.rst
+++ b/manual/cli.rst
@@ -184,10 +184,10 @@ Exit Status
Meaning of exit codes:
- 0: no errors or warnings
- 1: not used by qpdf but may be used by the shell if unable to invoke qpdf
- 2: errors detected
- 3: warnings detected, unless --warning-exit-0 is given
+ - 0: no errors or warnings
+ - 1: not used by qpdf but may be used by the shell if unable to invoke qpdf
+ - 2: errors detected
+ - 3: warnings detected, unless --warning-exit-0 is given
The exit status of :command:`qpdf` may be interpreted as follows:
diff --git a/manual/qpdf.1 b/manual/qpdf.1
new file mode 100644
index 00000000..b8bf5033
--- /dev/null
+++ b/manual/qpdf.1
@@ -0,0 +1,1109 @@
+.\"
+.\" This file is automatically generated by generate_auto_job.
+.\" Edits will be automatically overwritten if the build is
+.\" run in maintainer mode.
+.\"
+.TH QPDF "1" "" "qpdf version 11.7.0" "User Commands"
+.SH NAME
+qpdf \- PDF transformation software
+.SH SYNOPSIS
+.B qpdf
+.RI "[ " options " ] " infilename " [ " outfilename " ]"
+.SH DESCRIPTION
+The qpdf program is used to convert one PDF file to another equivalent
+PDF file. It is capable of performing a variety of transformations
+such as linearization (also known as web optimization or fast web
+viewing), encryption, and decryption of PDF files. It also has many
+options for inspecting or checking PDF files, some of which are
+useful primarily to PDF developers.
+.PP
+For a summary of qpdf's options, please run \fBqpdf \-\-help\fR. A
+complete manual can be found at https://qpdf.readthedocs.io.
+.SH USAGE (basic invocation)
+Read a PDF file, apply transformations or modifications, and write
+a new PDF file.
+
+Usage: qpdf [infile] [options] [outfile]
+ OR qpdf --help[={topic|--option}]
+
+.IP \[bu]
+infile, options, and outfile may be in any order as long as infile
+precedes outfile.
+.IP \[bu]
+Use --empty in place of an input file for a zero-page, empty input
+.IP \[bu]
+Use --replace-input in place of an output file to overwrite the
+input file with the output
+.IP \[bu]
+outfile may be - to write to stdout; reading from stdin is not supported
+.IP \[bu]
+@filename is an argument file; each line is treated as a separate
+command-line argument
+.IP \[bu]
+@- may be used to read arguments from stdin
+.IP \[bu]
+Later options may override earlier options if contradictory
+.PP
+Related Options:
+.TP
+.B --empty \-\- use empty file as input
+Use in place of infile for an empty input. Especially useful
+with --pages.
+.TP
+.B --replace-input \-\- overwrite input with output
+Use in place of outfile to overwrite the input file with the output.
+.TP
+.B --job-json-file \-\- job JSON file
+--job-json-file=file
+
+Specify the name of a file whose contents are expected to
+contain a QPDFJob JSON file. Run qpdf --job-json-help for a
+description of the JSON input file format.
+.SH EXIT-STATUS (meanings of qpdf's exit codes)
+Meaning of exit codes:
+
+.IP \[bu]
+0: no errors or warnings
+.IP \[bu]
+1: not used by qpdf but may be used by the shell if unable to invoke qpdf
+.IP \[bu]
+2: errors detected
+.IP \[bu]
+3: warnings detected, unless --warning-exit-0 is given
+.PP
+Related Options:
+.TP
+.B --warning-exit-0 \-\- exit 0 even with warnings
+Use exit status 0 instead of 3 when warnings are present. When
+combined with --no-warn, warnings are completely ignored.
+.SH COMPLETION (shell completion)
+Shell completion is supported with bash and zsh. Use
+eval $(qpdf --completion-bash) or eval $(qpdf --completion-zsh)
+to enable. The QPDF_EXECUTABLE environment variable overrides the
+path to qpdf that these commands output.
+.PP
+Related Options:
+.TP
+.B --completion-bash \-\- enable bash completion
+Output a command that enables bash completion
+.TP
+.B --completion-zsh \-\- enable zsh completion
+Output a command that enables zsh completion
+.SH HELP (information about qpdf)
+Help options provide some information about qpdf itself. Help
+options are only valid as the first and only command-line argument.
+.PP
+Related Options:
+.TP
+.B --help \-\- provide help
+--help[=--option|topic]
+
+--help: provide general information and a list of topics
+--help=--option: provide help on a specific option
+--help=topic: provide help on a topic
+.TP
+.B --version \-\- show qpdf version
+Display the version of qpdf.
+.TP
+.B --copyright \-\- show copyright information
+Display copyright and license information.
+.TP
+.B --show-crypto \-\- show available crypto providers
+Show a list of available crypto providers, one per line. The
+default provider is shown first.
+.TP
+.B --job-json-help \-\- show format of job JSON
+Describe the format of the QPDFJob JSON input used by
+--job-json-file.
+.SH GENERAL (general options)
+General options control qpdf's behavior in ways that are not
+directly related to the operation it is performing.
+.PP
+Related Options:
+.TP
+.B --password \-\- password for encrypted file
+--password=password
+
+Specify a password for an encrypted, password-protected file.
+Not needed for encrypted files without a password.
+.TP
+.B --password-file \-\- read password from a file
+--password-file=filename
+
+The first line of the specified file is used as the password.
+This is used in place of the --password option.
+.TP
+.B --verbose \-\- print additional information
+Output additional information about various things qpdf is
+doing, including information about files created and operations
+performed.
+.TP
+.B --progress \-\- show progress when writing
+Indicate progress when writing files.
+.TP
+.B --no-warn \-\- suppress printing of warning messages
+Suppress printing of warning messages. If warnings were
+encountered, qpdf still exits with exit status 3.
+Use --warning-exit-0 with --no-warn to completely ignore
+warnings.
+.TP
+.B --deterministic-id \-\- generate ID deterministically
+Generate a secure, random document ID only using static
+information, such as the page contents. Does not use the file's
+name or attributes or the current time.
+.TP
+.B --allow-weak-crypto \-\- allow insecure cryptographic algorithms
+Allow creation of files with weak cryptographic algorithms. This
+option is necessary to create 40-bit files or 128-bit files that
+use RC4 encryption.
+.TP
+.B --keep-files-open \-\- manage keeping multiple files open
+--keep-files-open=[y|n]
+
+When qpdf needs to work with many files, as when merging large
+numbers of files, explicitly indicate whether files should be
+kept open. The default behavior is to determine this based on
+the number of files.
+.TP
+.B --keep-files-open-threshold \-\- set threshold for --keep-files-open
+--keep-files-open-threshold=count
+
+Set the threshold used by --keep-files-open, overriding the
+default value of 200.
+.SH ADVANCED-CONTROL (tweak qpdf's behavior)
+Advanced control options control qpdf's behavior in ways that would
+normally never be needed by a user but that may be useful to
+developers or people investigating problems with specific files.
+.PP
+Related Options:
+.TP
+.B --password-is-hex-key \-\- provide hex-encoded encryption key
+Provide the underlying file encryption key as a hex-encoded
+string rather than supplying a password. This is an expert
+option.
+.TP
+.B --suppress-password-recovery \-\- don't try different password encodings
+Suppress qpdf's usual behavior of attempting different encodings
+of a password that contains non-ASCII Unicode characters if the
+first attempt doesn't succeed.
+.TP
+.B --password-mode \-\- tweak how qpdf encodes passwords
+--password-mode=mode
+
+Fine-tune how qpdf controls encoding of Unicode passwords. Valid
+options are auto, bytes, hex-bytes, and unicode.
+.TP
+.B --suppress-recovery \-\- suppress error recovery
+Avoid attempting to recover when errors are found in a file's
+cross reference table or stream lengths.
+.TP
+.B --ignore-xref-streams \-\- use xref tables rather than streams
+Ignore any cross-reference streams in the file, falling back to
+cross-reference tables or triggering document recovery.
+.SH TRANSFORMATION (make structural PDF changes)
+The options below tell qpdf to apply transformations that change
+the structure without changing the content.
+.PP
+Related Options:
+.TP
+.B --linearize \-\- linearize (web-optimize) output
+Create linearized (web-optimized) output files.
+.TP
+.B --encrypt \-\- start encryption options
+--encrypt [options] --
+
+Run qpdf --help=encryption for details.
+.TP
+.B --decrypt \-\- remove encryption from input file
+Create an unencrypted output file even if the input file was
+encrypted. Normally qpdf preserves whatever encryption was
+present on the input file. This option overrides that behavior.
+.TP
+.B --remove-restrictions \-\- remove security restrictions from input file
+Remove restrictions associated with digitally signed PDF files.
+This may be combined with --decrypt to allow free editing of
+previously signed/encrypted files. This option invalidates the
+signature but leaves its visual appearance intact.
+.TP
+.B --copy-encryption \-\- copy another file's encryption details
+--copy-encryption=file
+
+Copy encryption details from the specified file instead of
+preserving the input file's encryption. Use --encryption-file-password
+to specify the encryption file's password.
+.TP
+.B --encryption-file-password \-\- supply password for --copy-encryption
+--encryption-file-password=password
+
+If the file named in --copy-encryption requires a password, use
+this option to supply the password.
+.TP
+.B --qdf \-\- enable viewing PDF code in a text editor
+Create a PDF file suitable for viewing in a text editor and even
+editing. This is for editing the PDF code, not the page contents.
+All streams that can be uncompressed are uncompressed, and
+content streams are normalized, among other changes. The
+companion tool "fix-qdf" can be used to repair hand-edited QDF
+files. QDF is a feature specific to the qpdf tool. Please see
+the "QDF Mode" chapter in the manual.
+.TP
+.B --no-original-object-ids \-\- omit original object IDs in qdf
+Omit comments in a QDF file indicating the object ID an object
+had in the original file.
+.TP
+.B --compress-streams \-\- compress uncompressed streams
+--compress-streams=[y|n]
+
+Setting --compress-streams=n prevents qpdf from compressing
+uncompressed streams. This can be useful if you are leaving some
+streams uncompressed intentionally.
+.TP
+.B --decode-level \-\- control which streams to uncompress
+--decode-level=parameter
+
+When uncompressing streams, control which types of compression
+schemes should be uncompressed:
+.IP \[bu]
+none: don't uncompress anything. This is the default with
+--json-output.
+.IP \[bu]
+generalized: uncompress streams compressed with a
+general-purpose compression algorithm. This is the default
+except when --json-output is given.
+.IP \[bu]
+specialized: in addition to generalized, also uncompress
+streams compressed with a special-purpose but non-lossy
+compression scheme
+.IP \[bu]
+all: in addition to specialized, uncompress streams compressed
+with lossy compression schemes like JPEG (DCT)
+qpdf does not know how to uncompress all compression schemes.
+.TP
+.B --stream-data \-\- control stream compression
+--stream-data=parameter
+
+This option controls how streams are compressed in the output.
+It is less granular than the newer options, --compress-streams
+and --decode-level.
+
+Parameters:
+.IP \[bu]
+compress: same as --compress-streams=y --decode-level=generalized
+.IP \[bu]
+preserve: same as --compress-streams=n --decode-level=none
+.IP \[bu]
+uncompress: same as --compress-streams=n --decode-level=generalized
+.TP
+.B --recompress-flate \-\- uncompress and recompress flate
+The default generalized compression scheme used by PDF is flate,
+which is the same as used by zip and gzip. Usually qpdf just
+leaves these alone. This option tells qpdf to uncompress and
+recompress streams compressed with flate. This can be useful
+when combined with --compression-level.
+.TP
+.B --compression-level \-\- set compression level for flate
+--compression-level=level
+
+Set a compression level from 1 (least, fastest) to 9 (most,
+slowest) when compressing files with flate (used in zip and
+gzip), which is the default compression for most PDF files.
+You need --recompress-flate with this option if you want to
+change already compressed streams.
+.TP
+.B --normalize-content \-\- fix newlines in content streams
+--normalize-content=[y|n]
+
+Normalize newlines to UNIX-style newlines in PDF content
+streams, which is useful for viewing them in a programmer's text
+editor across multiple platforms. This is also turned on by
+--qdf.
+.TP
+.B --object-streams \-\- control use of object streams
+--object-streams=mode
+
+Control what qpdf does regarding object streams. Options:
+.IP \[bu]
+preserve: preserve original object streams, if any (the default)
+.IP \[bu]
+disable: create output files with no object streams
+.IP \[bu]
+generate: create object streams, and compress objects when possible
+.TP
+.B --preserve-unreferenced \-\- preserve unreferenced objects
+Preserve all objects from the input even if not referenced.
+.TP
+.B --remove-unreferenced-resources \-\- remove unreferenced page resources
+--remove-unreferenced-resources=parameter
+
+Remove from a page's resource dictionary any resources that are
+not referenced in the page's contents. Parameters: "auto"
+(default), "yes", "no".
+.TP
+.B --preserve-unreferenced-resources \-\- use --remove-unreferenced-resources=no
+Synonym for --remove-unreferenced-resources=no. Use that instead.
+.TP
+.B --newline-before-endstream \-\- force a newline before endstream
+For an extra newline before endstream. Using this option enables
+qpdf to preserve PDF/A when rewriting such files.
+.TP
+.B --coalesce-contents \-\- combine content streams
+If a page has an array of content streams, concatenate them into
+a single content stream.
+.TP
+.B --externalize-inline-images \-\- convert inline to regular images
+Convert inline images to regular images.
+.TP
+.B --ii-min-bytes \-\- set minimum size for --externalize-inline-images
+--ii-min-bytes=size-in-bytes
+
+Don't externalize inline images smaller than this size. The
+default is 1,024. Use 0 for no minimum.
+.TP
+.B --min-version \-\- set minimum PDF version
+--min-version=version
+
+Force the PDF version of the output to be at least the specified
+version. The version number format is
+"major.minor[.extension-level]", which sets the version header
+to "major.minor" and the extension level, if specified, to
+"extension-level".
+.TP
+.B --force-version \-\- set output PDF version
+--force-version=version
+
+Force the output PDF file's PDF version header to be the specified
+value, even if the file uses features that may not be available
+in that version.
+.SH PAGE-RANGES (page range syntax)
+A full description of the page range syntax, with examples, can be
+found in the manual. Summary:
+
+.IP \[bu]
+a,b,c pages a, b, and c
+.IP \[bu]
+a-b pages a through b inclusive; if a > b, this counts down
+.IP \[bu]
+r<n> where <n> represents a number is the <n>th page from the end
+.IP \[bu]
+z the last page, same as r1
+
+You can append :even or :odd to select every other page from the
+resulting set of pages, where :odd starts with the first page and
+:even starts with the second page. These are odd and even pages
+from the resulting set, not based on the original page numbers.
+.SH MODIFICATION (change parts of the PDF)
+Modification options make systematic changes to certain parts of
+the PDF, causing the PDF to render differently from the original.
+.PP
+Related Options:
+.TP
+.B --pages \-\- begin page selection
+--pages file [--password=password] [page-range] [...] --
+
+Run qpdf --help=page-selection for details.
+.TP
+.B --collate \-\- collate with --pages
+--collate[=n]
+
+Collate rather than concatenate pages specified with --pages.
+With a numeric parameter, collate in groups of n. The default
+is 1. Run qpdf --help=page-selection for additional details.
+.TP
+.B --split-pages \-\- write pages to separate files
+--split-pages[=n]
+
+This option causes qpdf to create separate output files for each
+page or group of pages rather than a single output file.
+
+File names are generated from the specified output file as follows:
+
+.IP \[bu]
+If the string %d appears in the output file name, it is replaced with a
+zero-padded page range starting from 1
+.IP \[bu]
+Otherwise, if the output file name ends in .pdf (case insensitive), a
+zero-padded page range, preceded by a dash, is inserted before the file
+extension
+.IP \[bu]
+Otherwise, the file name is appended with a zero-padded page range
+preceded by a dash.
+
+Page ranges are single page numbers for single-page groups or first-last
+for multi-page groups.
+.TP
+.B --overlay \-\- begin overlay options
+--overlay file [options] --
+
+Overlay pages from another file on the output.
+Run qpdf --help=overlay-underlay for details.
+.TP
+.B --underlay \-\- begin underlay options
+--underlay file [options] --
+
+Underlay pages from another file on the output.
+Run qpdf --help=overlay-underlay for details.
+.TP
+.B --flatten-rotation \-\- remove rotation from page dictionary
+For each page that is rotated using the /Rotate key in the
+page's dictionary, remove the /Rotate key and implement the
+identical rotation semantics by modifying the page's contents.
+This can be useful if a broken PDF viewer fails to properly
+consider page rotation metadata.
+.TP
+.B --flatten-annotations \-\- push annotations into content
+--flatten-annotations=parameter
+
+Push page annotations into the content streams. This may be
+necessary in some case when printing or splitting files.
+Parameters: "all", "print", "screen".
+.TP
+.B --rotate \-\- rotate pages
+--rotate=[+|-]angle[:page-range]
+
+Rotate specified pages by multiples of 90 degrees specifying
+either absolute or relative angles. "angle" may be 0, 90, 180,
+or 270. You almost always want to use +angle or -angle rather
+than just angle, as discussed in the manual. Run
+qpdf --help=page-ranges for help with page ranges.
+.TP
+.B --generate-appearances \-\- generate appearances for form fields
+PDF form fields consist of values and appearances, which may be
+inconsistent with each other if a form field value has been
+modified without updating its appearance. This option tells qpdf
+to generate new appearance streams. There are some limitations,
+which are discussed in the manual.
+.TP
+.B --optimize-images \-\- use efficient compression for images
+Attempt to use DCT (JPEG) compression for images that fall
+within certain constraints as long as doing so decreases the
+size in bytes of the image. See also help for the following
+options:
+ --oi-min-width
+ --oi-min-height
+ --oi-min-area
+ --keep-inline-images
+.TP
+.B --oi-min-width \-\- minimum width for --optimize-images
+--oi-min-width=width
+
+Don't optimize images whose width is below the specified value.
+.TP
+.B --oi-min-height \-\- minimum height for --optimize-images
+--oi-min-height=height
+
+Don't optimize images whose height is below the specified value.
+.TP
+.B --oi-min-area \-\- minimum area for --optimize-images
+--oi-min-area=area-in-pixels
+
+Don't optimize images whose area in pixels is below the specified value.
+.TP
+.B --keep-inline-images \-\- exclude inline images from optimization
+Prevent inline images from being considered by --optimize-images.
+.TP
+.B --remove-page-labels \-\- remove explicit page numbers
+Exclude page labels (explicit page numbers) from the output file.
+.SH ENCRYPTION (create encrypted files)
+Create encrypted files. Usage:
+
+--encrypt \
+ [--user-password=user-password] \
+ [--owner-password=owner-password] \
+ --bits=key-length [options] --
+
+OR
+
+--encrypt user-password owner-password key-length [options] --
+
+The first form, with flags for the passwords and bit length, was
+introduced in qpdf 11.7.0. Only the --bits option is is mandatory.
+This form allows you to use any text as the password. If passwords
+are specified, they must be given before the --bits option.
+
+The second form has been in qpdf since the beginning and wil
+continue to be supported. Either or both of user-password and
+owner-password may be empty strings.
+
+The key-length parameter must be either 40, 128, or 256. The user
+and/or owner password may be omitted. Omitting either pasword
+enables the PDF file to be opened without a password. Specifying
+the same value for the user and owner password and specifying an
+empty owner password are both considered insecure.
+
+Encryption options are terminated by "--" by itself.
+
+40-bit encryption is insecure, as is 128-bit encryption without
+AES. Use 256-bit encryption unless you have a specific reason to
+use an insecure format, such as testing or compatibility with very
+old viewers. You must use the --allow-weak-crypto to create
+encrypted files that use insecure cryptographic algorithms. The
+--allow-weak-crypto flag appears outside of --encrypt ... --
+(before --encrypt or after --).
+
+Available options vary by key length. Not all readers respect all
+restrictions. Different PDF readers respond differently to various
+combinations of options. Sometimes a PDF viewer may show you
+restrictions that differ from what you selected. This is probably
+not a bug in qpdf.
+
+Options for 40-bit only:
+ --annotate=[y|n] restrict comments, filling forms, and signing
+ --extract=[y|n] restrict text/graphic extraction
+ --modify=[y|n] restrict document modification
+ --print=[y|n] restrict printing
+
+Options for 128-bit or 256-bit:
+ --accessibility=[y|n] restrict accessibility (usually ignored)
+ --annotate=[y|n] restrict commenting/filling form fields
+ --assemble=[y|n] restrict document assembly
+ --extract=[y|n] restrict text/graphic extraction
+ --form=[y|n] restrict filling form fields
+ --modify-other=[y|n] restrict other modifications
+ --modify=modify-opt control modify access by level
+ --print=print-opt control printing access
+ --cleartext-metadata prevent encryption of metadata
+
+For 128-bit only:
+ --use-aes=[y|n] indicates whether to use AES encryption
+ --force-V4 forces use of V=4 encryption handler
+
+For 256-bit only:
+ --force-R5 forces use of deprecated R=5 encryption
+ --allow-insecure allow user password with empty owner password
+
+Values for print-opt:
+ none disallow printing
+ low allow only low-resolution printing
+ full allow full printing
+
+Values for modify-opt:
+ none allow no modifications
+ assembly allow document assembly only
+ form assembly + filling in form fields and signing
+ annotate form + commenting and modifying forms
+ all allow full document modification
+.PP
+Related Options:
+.TP
+.B --user-password \-\- specify user password
+--user-password=user-password
+
+Set the user password of the encrypted file.
+.TP
+.B --owner-password \-\- specify owner password
+--owner-password=owner-password
+
+Set the owner password of the encrypted file.
+.TP
+.B --bits \-\- specify encryption key length
+--bits={48|128|256}
+
+Specify the encryption key length. For best security, always use
+a key length of 256.
+.TP
+.B --accessibility \-\- restrict document accessibility
+--accessibility=[y|n]
+
+This option is ignored except with very old encryption formats.
+The current PDF specification does not allow restriction of
+document accessibility. This option is not available with 40-bit
+encryption.
+.TP
+.B --annotate \-\- restrict document annotation
+--annotate=[y|n]
+
+Enable/disable modifying annotations including making comments
+and filling in form fields. For 128-bit and 256-bit encryption,
+this also enables editing, creating, and deleting form fields
+unless --modify-other=n or --modify=none is also specified.
+.TP
+.B --assemble \-\- restrict document assembly
+--assemble=[y|n]
+
+Enable/disable document assembly (rotation and reordering of
+pages). This option is not available with 40-bit encryption.
+.TP
+.B --extract \-\- restrict text/graphic extraction
+--extract=[y|n]
+
+Enable/disable text/graphic extraction for purposes other than
+accessibility.
+.TP
+.B --form \-\- restrict form filling
+--form=[y|n]
+
+Enable/disable whether filling form fields is allowed even if
+modification of annotations is disabled. This option is not
+available with 40-bit encryption.
+.TP
+.B --modify-other \-\- restrict other modifications
+--modify-other=[y|n]
+
+Enable/disable modifications not controlled by --assemble,
+--annotate, or --form. --modify-other=n is implied by any of the
+other --modify options. This option is not available with 40-bit
+encryption.
+.TP
+.B --modify \-\- restrict document modification
+--modify=modify-opt
+
+For 40-bit files, modify-opt may only be y or n and controls all
+aspects of document modification.
+
+For 128-bit and 256-bit encryption, modify-opt values allow
+enabling and disabling levels of restriction in a manner similar
+to how some PDF creation tools do it. modify-opt values map to
+other combinations of options as follows:
+
+all: allow full modification (the default)
+annotate: --modify-other=n
+form: --modify-other=n --annotate=n
+assembly: --modify-other=n --annotate=n --form=n
+none: --modify-other=n --annotate=n --form=n --assemble=n
+.TP
+.B --print \-\- restrict printing
+--print=print-opt
+
+Control what kind of printing is allowed. For 40-bit encryption,
+print-opt may only be y or n and enables or disables all
+printing. For 128-bit and 256-bit encryption, print-opt may have
+the following values:
+
+none: disallow printing
+low: allow low-resolution printing only
+full: allow full printing (the default)
+.TP
+.B --cleartext-metadata \-\- don't encrypt metadata
+If specified, don't encrypt document metadata even when
+encrypting the rest of the document. This option is not
+available with 40-bit encryption.
+.TP
+.B --use-aes \-\- use AES with 128-bit encryption
+--use-aes=[y|n]
+
+Enables/disables use of the more secure AES encryption with
+128-bit encryption. Specifying --use-aes=y forces the PDF
+version to be at least 1.6. This option is only available with
+128-bit encryption. The default is "n" for compatibility
+reasons. Use 256-bit encryption instead.
+.TP
+.B --allow-insecure \-\- allow empty owner passwords
+Allow creation of PDF files with empty owner passwords and
+non-empty user passwords when using 256-bit encryption.
+.TP
+.B --force-V4 \-\- force V=4 in encryption dictionary
+This option is for testing and is never needed in practice since
+qpdf does this automatically when needed.
+.TP
+.B --force-R5 \-\- use unsupported R=5 encryption
+Use an undocumented, unsupported, deprecated encryption
+algorithm that existed only in Acrobat version IX. This option
+should not be used except for compatibility testing.
+.SH PAGE-SELECTION (select pages from one or more files)
+Use the --pages option to select pages from multiple files. Usage:
+
+qpdf in.pdf --pages input-file [--password=password] [page-range] \
+ [...] -- out.pdf
+
+Between --pages and the -- that terminates pages option, repeat
+the following:
+
+filename [--password=password] [page-range]
+
+Document-level information, such as outlines, tags, etc., is taken
+from in.pdf and is preserved in out.pdf. You can use --empty in place
+of an input file to start from an empty file and just copy pages
+equally from all files. You can use "." as a shorthand for the
+primary input file (if not --empty). In the above example, "."
+would refer to in.pdf.
+
+Use --password=password to specify the password for a
+password-protected input file. If the same input file is used more
+than once, you only need to supply the password the first time. If
+the page range is omitted, all pages are selected.
+
+Run qpdf --help=page-ranges for help with page ranges.
+
+Use --collate=n to cause pages to be collated in groups of n pages
+(default 1) instead of concatenating the input.
+
+Examples:
+
+.IP \[bu]
+Start with in.pdf and append all pages from a.pdf and the even
+pages from b.pdf, and write the output to out.pdf. Document-level
+information from in.pdf is retained. Note the use of "." to refer
+to in.pdf.
+
+ qpdf in.pdf --pages . a.pdf b.pdf:even -- out.pdf
+
+.IP \[bu]
+Take all the pages from a.pdf, all the pages from b.pdf in
+reverse, and only pages 3 and 6 from c.pdf and write the result
+to out.pdf. Use password "x" to open b.pdf:
+
+ qpdf --empty --pages a.pdf b.pdf --password=x z-1 c.pdf 3,6
+
+More examples are in the manual.
+.SH OVERLAY-UNDERLAY (overlay/underlay pages from other files)
+These options allow pages from another file to be overlaid or
+underlaid on the primary output. Overlaid pages are drawn on top of
+the destination page and may obscure the page. Underlaid pages are
+drawn below the destination page. Usage:
+
+{--overlay|--underlay} file
+ [--password=password]
+ [--to=page-range]
+ [--from=[page-range]]
+ [--repeat=page-range]
+ --
+
+Note the use of "--" by itself to terminate overlay/underlay options.
+
+For overlay and underlay, a file and optional password are specified, along
+with a series of optional page ranges. The default behavior is that each
+page of the overlay or underlay file is imposed on the corresponding page
+of the primary output until it runs out of pages, and any extra pages are
+ignored. You can also give a page range with --repeat to cause
+those pages to be repeated after the original pages are exhausted.
+
+Run qpdf --help=page-ranges for help with page ranges.
+.PP
+Related Options:
+.TP
+.B --to \-\- destination pages for underlay/overlay
+--to=page-range
+
+Specify the range of pages in the primary output to apply
+overlay/underlay to. See qpdf --help=page-ranges for help with
+the page range syntax.
+.TP
+.B --from \-\- source pages for underlay/overlay
+--from=[page-range]
+
+Specify pages from the overlay/underlay file that are applied to
+the destination pages. See qpdf --help=page-ranges for help
+with the page range syntax. The page range may be omitted
+if --repeat is used.
+.TP
+.B --repeat \-\- overlay/underlay pages to repeat
+--repeat=page-range
+
+Specify pages from the overlay/underlay that are repeated after
+"from" pages have been exhausted. See qpdf --help=page-ranges
+for help with the page range syntax.
+.SH ATTACHMENTS (work with embedded files)
+It is possible to list, add, or delete embedded files (also known
+as attachments) and to copy attachments from other files. See help
+on individual options for details. Run qpdf --help=add-attachment
+for additional details about adding attachments. See also
+--help=--list-attachments and --help=--show-attachment.
+.PP
+Related Options:
+.TP
+.B --add-attachment \-\- start add attachment options
+--add-attachment file [options] --
+
+The --add-attachment flag and its options may be repeated to add
+multiple attachments. Run qpdf --help=add-attachment for details.
+.TP
+.B --copy-attachments-from \-\- start copy attachment options
+--copy-attachments-from file [options] --
+
+The --copy-attachments-from flag and its options may be repeated
+to copy attachments from multiple files. Run
+qpdf --help=copy-attachments for details.
+.TP
+.B --remove-attachment \-\- remove an embedded file
+--remove-attachment=key
+
+Remove an embedded file using its key. Get the key with
+--list-attachments.
+.SH PDF-DATES (PDF date format)
+When a date is required, the date should conform to the PDF date
+format specification, which is "D:yyyymmddhhmmssz" where "z" is
+either literally upper case "Z" for UTC or a timezone offset in
+the form "-hh'mm'" or "+hh'mm'". Negative timezone offsets indicate
+time before UTC. Positive offsets indicate how far after. For
+example, US Eastern Standard Time (America/New_York) is "-05'00'",
+and Indian Standard Time (Asia/Calcutta) is "+05'30'".
+
+Examples:
+.IP \[bu]
+D:20210207161528-05'00' February 7, 2021 at 4:15:28 p.m.
+.IP \[bu]
+D:20210207211528Z February 7, 2021 at 21:15:28 UTC
+.SH ADD-ATTACHMENT (attach (embed) files)
+The options listed below appear between --add-attachment and its
+terminating "--".
+.PP
+Related Options:
+.TP
+.B --key \-\- specify attachment key
+--key=key
+
+Specify the key to use for the attachment in the embedded files
+table. It defaults to the last element (basename) of the
+attached file's filename.
+.TP
+.B --filename \-\- set attachment's displayed filename
+--filename=name
+
+Specify the filename to be used for the attachment. This is what
+is usually displayed to the user and is the name most graphical
+PDF viewers will use when saving a file. It defaults to the last
+element (basename) of the attached file's filename.
+.TP
+.B --creationdate \-\- set attachment's creation date
+--creationdate=date
+
+Specify the attachment's creation date in PDF format; defaults
+to the current time. Run qpdf --help=pdf-dates for information
+about the date format.
+.TP
+.B --moddate \-\- set attachment's modification date
+--moddate=date
+
+Specify the attachment's modification date in PDF format;
+defaults to the current time. Run qpdf --help=pdf-dates for
+information about the date format.
+.TP
+.B --mimetype \-\- attachment mime type, e.g. application/pdf
+--mimetype=type/subtype
+
+Specify the mime type for the attachment, such as text/plain,
+application/pdf, image/png, etc.
+.TP
+.B --description \-\- set attachment's description
+--description="text"
+
+Supply descriptive text for the attachment, displayed by some
+PDF viewers.
+.TP
+.B --replace \-\- replace attachment with same key
+Indicate that any existing attachment with the same key should
+be replaced by the new attachment. Otherwise, qpdf gives an
+error if an attachment with that key is already present.
+.SH COPY-ATTACHMENTS (copy attachments from another file)
+The options listed below appear between --copy-attachments-from and
+its terminating "--".
+
+To copy attachments from a password-protected file, use
+the --password option after the file name.
+.PP
+Related Options:
+.TP
+.B --prefix \-\- key prefix for copying attachments
+--prefix=prefix
+
+Prepend a prefix to each key; may be needed if there are
+duplicate attachment keys. This affects the key only, not the
+file name.
+.SH INSPECTION (inspect PDF files)
+These options provide tools for inspecting PDF files. When any of
+the options in this section are specified, no output file may be
+given.
+.PP
+Related Options:
+.TP
+.B --is-encrypted \-\- silently test whether a file is encrypted
+Silently exit with a code indicating the file's encryption status:
+
+0: the file is encrypted
+1: not used
+2: the file is not encrypted
+
+This can be used with password-protected files even if you don't
+know the password.
+.TP
+.B --requires-password \-\- silently test a file's password
+Silently exit with a code indicating the file's password status:
+
+0: a password, other than as supplied, is required
+1: not used
+2: the file is not encrypted
+3: the file is encrypted, and correct password (if any) has been supplied
+.TP
+.B --check \-\- partially check whether PDF is valid
+Check the structure of the PDF file as well as a number of other
+aspects of the file, and write information about the file to
+standard output. Note that qpdf does not perform any validation
+of the actual PDF page content or semantic correctness of the
+PDF file. It merely checks that the PDF file is syntactically
+valid. See also qpdf --help=exit-status.
+.TP
+.B --show-encryption \-\- information about encrypted files
+Show document encryption parameters. Also show the document's
+user password if the owner password is given and the file was
+encrypted using older encryption formats that allow user
+password recovery.
+.TP
+.B --show-encryption-key \-\- show key with --show-encryption
+When used with --show-encryption or --check, causes the
+underlying encryption key to be displayed.
+.TP
+.B --check-linearization \-\- check linearization tables
+Check to see whether a file is linearized and, if so, whether
+the linearization hint tables are correct.
+.TP
+.B --show-linearization \-\- show linearization hint tables
+Check and display all data in the linearization hint tables.
+.TP
+.B --show-xref \-\- show cross reference data
+Show the contents of the cross-reference table or stream (object
+locations in the file) in a human-readable form. This is
+especially useful for files with cross-reference streams, which
+are stored in a binary format.
+.TP
+.B --show-object \-\- show contents of an object
+--show-object={trailer|obj[,gen]}
+
+Show the contents of the given object. This is especially useful
+for inspecting objects that are inside of object streams (also
+known as "compressed objects").
+.TP
+.B --raw-stream-data \-\- show raw stream data
+When used with --show-object, if the object is a stream, write
+the raw (compressed) binary stream data to standard output
+instead of the object's contents. See also
+--filtered-stream-data.
+.TP
+.B --filtered-stream-data \-\- show filtered stream data
+When used with --show-object, if the object is a stream, write
+the filtered (uncompressed, potentially binary) stream data to
+standard output instead of the object's contents. See also
+--raw-stream-data.
+.TP
+.B --show-npages \-\- show number of pages
+Print the number of pages in the input file on a line by itself.
+Useful for scripts.
+.TP
+.B --show-pages \-\- display page dictionary information
+Show the object and generation number for each page dictionary
+object and for each content stream associated with the page.
+.TP
+.B --with-images \-\- include image details with --show-pages
+When used with --show-pages, also shows the object and
+generation numbers for the image objects on each page.
+.TP
+.B --list-attachments \-\- list embedded files
+Show the key and stream number for each embedded file. Combine
+with --verbose for more detailed information.
+.TP
+.B --show-attachment \-\- export an embedded file
+--show-attachment=key
+
+Write the contents of the specified attachment to standard
+output as binary data. Get the key with --list-attachments.
+.SH JSON (JSON output for PDF information)
+Show information about the PDF file in JSON format. Please see the
+JSON chapter in the qpdf manual for details.
+.PP
+Related Options:
+.TP
+.B --json \-\- show file in JSON format
+--json[=version]
+
+Generate a JSON representation of the file. This is described in
+depth in the JSON section of the manual. "version" may be a
+specific version or "latest" (the default). Run qpdf --json-help
+for a description of the generated JSON object.
+.TP
+.B --json-help \-\- show format of JSON output
+--json-help[=version]
+
+Describe the format of the JSON output by writing to standard
+output a JSON object with the same keys and with values
+containing descriptive text.
+.TP
+.B --json-key \-\- limit which keys are in JSON output
+--json-key=key
+
+This option is repeatable. If given, only the specified
+top-level keys will be included in the JSON output. Otherwise,
+all keys will be included. With --json-output, when not given,
+only the "qpdf" key will appear in the output.
+.TP
+.B --json-object \-\- limit which objects are in JSON
+--json-object={trailer|obj[,gen]}
+
+This option is repeatable. If given, only specified objects will
+be shown in the "objects" key of the JSON output. Otherwise, all
+objects will be shown.
+.TP
+.B --json-stream-data \-\- how to handle streams in json output
+--json-stream-data={none|inline|file}
+
+When used with --json, this option controls whether streams in
+json output should be omitted, written inline (base64-encoded)
+or written to a file. If "file" is chosen, the file will be the
+name of the output file appended with -nnn where nnn is the
+object number. The prefix can be overridden with
+--json-stream-prefix. The default is "none", except
+when --json-output is specified, in which case the default is
+"inline".
+.TP
+.B --json-stream-prefix \-\- prefix for json stream data files
+--json-stream-prefix=file-prefix
+
+When used with --json-stream-data=file, --json-stream-data=file-prefix
+sets the prefix for stream data files, overriding the default,
+which is to use the output file name. Whatever is given here
+will be appended with -nnn to create the name of the file that
+will contain the data for the stream stream in object nnn.
+.TP
+.B --json-output \-\- apply defaults for JSON serialization
+--json-output[=version]
+
+Implies --json=version. Changes default values for certain
+options so that the JSON output written is the most faithful
+representation of the original PDF and contains no additional
+JSON keys. See also --json-stream-data, --json-stream-prefix,
+and --decode-level.
+.TP
+.B --json-input \-\- input file is qpdf JSON
+Treat the input file as a JSON file in qpdf JSON format. See the
+"qpdf JSON Format" section of the manual for information about
+how to use this option.
+.TP
+.B --update-from-json \-\- update a PDF from qpdf JSON
+--update-from-json=qpdf-json-file
+
+Update a PDF file from a JSON file. Please see the "qpdf JSON"
+chapter of the manual for information about how to use this
+option.
+.SH TESTING (options for testing or debugging)
+The options below are useful when writing automated test code that
+includes files created by qpdf or when testing qpdf itself.
+.PP
+Related Options:
+.TP
+.B --static-id \-\- use a fixed document ID
+Use a fixed value for the document ID. This is intended for
+testing only. Never use it for production files. See also
+qpdf --help=--deterministic-id.
+.TP
+.B --static-aes-iv \-\- use a fixed AES vector
+Use a static initialization vector for AES-CBC. This is intended
+for testing only so that output files can be reproducible. Never
+use it for production files. This option is not secure since it
+significantly weakens the encryption.
+.TP
+.B --linearize-pass1 \-\- save pass 1 of linearization
+--linearize-pass1=file
+
+Write the first pass of linearization to the named file. The
+resulting file is not a valid PDF file. This option is useful only
+for debugging qpdf.
+.TP
+.B --test-json-schema \-\- test generated json against schema
+This is used by qpdf's test suite to check consistency between
+the output of qpdf --json and the output of qpdf --json-help.
+.TP
+.B --report-memory-usage \-\- best effort report of memory usage
+This is used by qpdf's performance test suite to report the
+maximum amount of memory used in supported environments.
+.SH SEE ALSO
+.PP
+For a summary of qpdf's options, please run \fBqpdf \-\-help\fR.
+A complete manual can be found at https://qpdf.readthedocs.io.
diff --git a/manual/release-notes.rst b/manual/release-notes.rst
index 50b0aec3..443a4b01 100644
--- a/manual/release-notes.rst
+++ b/manual/release-notes.rst
@@ -80,6 +80,11 @@ Planned changes for future 12.x (subject to change):
``README-maintainer.md`` for a detailed explanation of how to
maintain this.
+ - Package Enhancements:
+
+ - A UNIX man page is now automatically generated from the
+ documentation. It contains the same text as ``qpdf --help=all``.
+
- Library Enhancements:
- Add C++ functions ``qpdf_c_wrap`` and ``qpdf_c_get_qpdf`` to the