feat: make pdfa-image-compression=auto lossless at -O0

Ghostscript's `auto` image compression heuristic can transcode lossless
images to JPEG during PDF/A generation, which is surprising at
optimization levels that otherwise promise lossless-only operations
(issue #1124).

`--pdfa-image-compression=auto` (the default) now coerces to lossless at
-O0 so Ghostscript will not transcode lossless images to JPEG. -O1 and
above continue to defer to Ghostscript's heuristic; -O1 (the default
level) is kept as a historical exception because coercing it to lossless
substantially bloats output. Users wanting guaranteed lossless image
handling can pass --pdfa-image-compression=lossless or use -O0.

Also make `lossless` pass existing JPEGs through unchanged
(-dPassThroughJPEGImages=true) instead of re-encoding them with a
lossless codec, which only inflates already-lossy data.
This commit is contained in:
James R. Barlow
2026-06-10 13:10:43 -07:00
parent 5cb5d7a682
commit 7e42d3c771
5 changed files with 125 additions and 8 deletions
+11 -4
View File
@@ -178,10 +178,17 @@ v17 addresses through alternative codepaths. When Ghostscript is used:
encoding, which may introduce compression artifacts, if Ghostscript
PDF/A is enabled.
- Ghostscript may transcode grayscale and color images, potentially
lossily, based on an internal algorithm. This
behavior can be suppressed by setting `--pdfa-image-compression` to
`jpeg` or `lossless` to set all images to one type or the other.
Ghostscript lacks an option to maintain the input image's format.
lossily, based on an internal algorithm. By default
(`--pdfa-image-compression=auto`) OCRmyPDF selects lossless image
compression at `-O0` so Ghostscript will not transcode lossless images
to JPEG. At `-O1` (the default optimization level) and above, `auto`
defers to Ghostscript's heuristic instead; `-O1` is a historical
exception, kept for backwards compatibility because coercing it to
lossless can substantially bloat output. You can override this by
setting `--pdfa-image-compression` to `jpeg` or `lossless` to force all
images to one type or the other. `lossless` passes existing JPEGs
through untouched (re-encoding them losslessly would only inflate them)
while encoding non-JPEG images losslessly.
(Modern Ghostscript can copy JPEG images without transcoding them.)
Advanced users can also tune Ghostscript's image recompression with
`--ghostscript-jpeg-quality` and `--ghostscript-jpeg-maxdpi`; see
+12
View File
@@ -5,6 +5,18 @@
## v17.6.0
- `--pdfa-image-compression=auto` (the default) now selects lossless image
compression at `-O0` so Ghostscript no longer transcodes lossless images to
JPEG during PDF/A generation. At `-O1` and above, `auto` continues to defer
to Ghostscript's heuristic, which may recompress images lossily. `-O1` (the
default level) is kept as a historical exception because coercing it to
lossless can substantially bloat output; users who want guaranteed lossless
image handling should pass `--pdfa-image-compression=lossless` or use `-O0`
({issue}`1124`).
- `--pdfa-image-compression=lossless` now passes existing JPEG images through
unchanged rather than re-encoding them with a lossless codec. Re-encoding an
already-lossy JPEG losslessly cannot recover quality and only inflates the
file, so JPEGs are preserved while non-JPEG images are encoded losslessly.
- OCRmyPDF now validates and repairs malformed page-boundary boxes
(``/MediaBox``, ``/CropBox``, ``/TrimBox``, ``/ArtBox``, ``/BleedBox``) in its
input, following the PDF 2.0 specification. Coordinates written in invalid