Okay, let's break this down.
Yes, it is possible to achieve a color inversion effect in Ghostscript, similar to the invert(100%)
part of your CSS filter. Replicating the hue-rotate(180deg)
part exactly is significantly more complex within Ghostscript's standard processing model, but the simple inversion often gets you 90% of the way to a usable "dark mode".
The core idea is to use PostScript's transfer functions. These functions modify color component values just before they are rendered. To invert a color component c
(where c
is between 0 and 1), the function is simply 1 - c
.
We need to apply this function to all relevant color spaces commonly found in PDFs: DeviceGray, DeviceRGB, and DeviceCMYK.
Here is the Ghostscript command you can use in a Bash shell script:
#!/bin/bash
# Input PDF file
input_pdf="input.pdf"
# Output PDF file (dark mode)
output_pdf="output_dark.pdf"
# Check if input file exists
if [[ ! -f "$input_pdf" ]]; then
echo "Error: Input file '$input_pdf' not found."
exit 1
fi
echo "Applying color inversion to '$input_pdf' -> '$output_pdf'..."
# Ghostscript command
gs \
-o "$output_pdf" \
-sDEVICE=pdfwrite \
-dPDFSETTINGS=/default \
-dNOPAUSE \
-dBATCH \
-c '<</TransferFunction {1 exch sub} /TransferFunctionRGB [ {1 exch sub} {1 exch sub} {1 exch sub} ] /TransferFunctionCMYK [ {1 exch sub} {1 exch sub} {1 exch sub} {1 exch sub} ]>> setpagedevice' \
-f "$input_pdf"
# Check if Ghostscript was successful
if [[ $? -eq 0 ]]; then
echo "Successfully created '$output_pdf'."
else
echo "Error during Ghostscript processing."
# Optional: remove potentially incomplete output file
# rm -f "$output_pdf"
exit 1
fi
exit 0
Explanation:
#!/bin/bash
: Shebang line for Bash scripts.input_pdf="..."
,output_pdf="..."
: Variables for filenames.if [[ ! -f ... ]]
: Basic check to ensure the input file exists.gs
: The Ghostscript command.-o "$output_pdf"
: Specifies the output file name.-sDEVICE=pdfwrite
: Tells Ghostscript to output a PDF file. This device re-interprets and re-generates the PDF.-dPDFSETTINGS=/default
: A general preset for compatibility and size. You could try/printer
or/prepress
for potentially higher quality if needed.-dNOPAUSE -dBATCH
: Essential for running Ghostscript non-interactively in a script.-c '...'
: Executes the following PostScript code string.<< ... >> setpagedevice
: This is the PostScript syntax for setting page device parameters. We are modifying how colors are handled for the entire page./TransferFunction {1 exch sub}
: Sets the transfer function forDeviceGray
color space.{1 exch sub}
is PostScript code: it takes the input gray value (which is left on the stack), pushes1
, swaps them (exch
), and subtracts (sub
), effectively calculating1 - input_gray
./TransferFunctionRGB [ {1 exch sub} {1 exch sub} {1 exch sub} ]
: Sets the transfer functions forDeviceRGB
. It takes an array of three procedures, one for Red, one for Green, one for Blue. We use the same inversion logic for all three./TransferFunctionCMYK [ {1 exch sub} {1 exch sub} {1 exch sub} {1 exch sub} ]
: Sets the transfer functions forDeviceCMYK
, applying the inversion to Cyan, Magenta, Yellow, and Black components.
-f "$input_pdf"
: Specifies the input PDF file. Crucially, the-c
code runs before Ghostscript starts processing the pages from this file, setting up the color inversion environment.if [[ $? -eq 0 ]]
: Checks the exit status of thegs
command to report success or failure.
Limitations & Considerations:
- Hue Rotation: This command only performs the
invert(100%)
. Replicatinghue-rotate(180deg)
would require intercepting and transforming every color specification (e.g., viasetrgbcolor
,setcmykcolor
, image data, etc.) through a color space conversion (like RGB -> HSL -> modify H -> HSL -> RGB), which is extremely complex and fragile to implement robustly in Ghostscript for arbitrary PDFs. The simple inversion is usually sufficient for a dark mode effect. - Color Spaces: This handles the most common device color spaces. PDFs using ICC profiles, Indexed colors, or Separation colors might behave differently or not be inverted correctly.
- Transparency & Blend Modes: Complex transparency and blend modes might produce unexpected results after inversion.
- Images vs. Vectors: The inversion applies universally, affecting both vector elements (text, lines) and raster images.
- Quality/Fidelity:
pdfwrite
re-generates the PDF. While generally good, it's not guaranteed to be a 100% perfect replica of the original structure, only the visual appearance (as modified by the transfer functions).
Save the script (e.g., pdf_darkmode.sh
), make it executable (chmod +x pdf_darkmode.sh
), place your input PDF as input.pdf
in the same directory, and run it (./pdf_darkmode.sh
). It will create output_dark.pdf
.