Improve DeviceN color conversion guidance (#1623) (#1694)

When Ghostscript reports a DeviceN colorspace with an inappropriate
alternate, the resulting PDF/A may render blank in viewers such as Adobe
Reader (#1187). The error is gated on that Ghostscript warning, which is
the authoritative signal that the *output* is broken.

Previously the error message always told the user to "use
--color-conversion-strategy", which is confusing when they already set
one and it didn't help. Crucially, the warning persists for strategies
that don't actually normalize the colorspace -- notably
UseDeviceIndependentColor (confirmed in #1187) -- so silencing the error
for any non-default strategy would emit a silently-broken PDF/A.

Keep raising whenever Ghostscript still reports the warning, regardless
of strategy, but tailor the guidance: if no conversion was requested,
suggest RGB/CMYK/Gray; if a conversion was requested but the warning
persisted, say so and point at strategies that work or --output-type pdf.

Add unit tests (mocked Ghostscript) covering the default case, the
warning-persists-despite-strategy case for both an ineffective strategy
and a normally-effective one, and the no-warning happy path.
This commit is contained in:
jbarlow
2026-06-04 14:48:24 -07:00
committed by GitHub
parent 5d7b5742e4
commit c33f073d4f
3 changed files with 125 additions and 10 deletions
+5 -1
View File
@@ -405,4 +405,8 @@ def generate_pdfa(
for part in stderr.split('****'):
log.error(part)
if _gs_devicen_reported(stderr):
raise ColorConversionNeededError()
# Ghostscript could not normalize the DeviceN colorspace for PDF/A,
# even if the user requested a conversion strategy. The output is
# liable to render blank in some viewers, so raise regardless of the
# strategy and tailor the guidance to what was attempted.
raise ColorConversionNeededError(color_conversion_strategy)
+38 -9
View File
@@ -140,13 +140,42 @@ class TaggedPDFError(InputFileError):
class ColorConversionNeededError(BadArgsError):
"""PDF needs color conversion."""
"""PDF needs color conversion to a standard color space.
message = dedent(
"""\
The input PDF has an unusual color space. Use
--color-conversion-strategy to convert to a common color space
such as RGB, or use --output-type pdf to skip PDF/A conversion
and retain the original color space.
"""
)
Ghostscript reported a DeviceN colorspace with an inappropriate alternate.
The resulting PDF/A is liable to render incorrectly (often blank) in some
viewers such as Adobe Reader, so the colorspace must be normalized to a
common one. RGB, CMYK, and Gray are known to work; LeaveColorUnchanged
performs no conversion and UseDeviceIndependentColor does not resolve the
problem (see https://github.com/ocrmypdf/OCRmyPDF/issues/1187).
"""
# Strategies that can normalize an unusual DeviceN colorspace into one that
# PDF/A viewers render correctly.
_effective_strategies = "RGB, CMYK, or Gray"
def __init__(self, color_conversion_strategy: str = "LeaveColorUnchanged"):
"""Build guidance tailored to the conversion strategy that was used."""
super().__init__()
if color_conversion_strategy == "LeaveColorUnchanged":
self.message = dedent(
f"""\
The input PDF has an unusual DeviceN color space that cannot be
represented in PDF/A; the output may appear blank in some viewers
such as Adobe Reader. Convert it to a common color space with
--color-conversion-strategy ({self._effective_strategies}), or use
--output-type pdf to skip PDF/A conversion and retain the original
color space.
"""
)
else:
self.message = dedent(
f"""\
Color conversion with --color-conversion-strategy
{color_conversion_strategy} did not resolve the input PDF's unusual
DeviceN color space; the output may appear blank in some viewers
such as Adobe Reader. Try a different --color-conversion-strategy
({self._effective_strategies}), or use --output-type pdf to skip
PDF/A conversion and retain the original color space.
"""
)