fix: normalize raster images before img2pdf retry

img2pdf refuses images with alpha channels or more than 8 bits per
channel (common for screenshots). Normalize such images to opaque
8-bit with ImageMagick and retry img2pdf before falling back to a
full ImageMagick PDF conversion.
This commit is contained in:
Lionel DARNIS 2026-08-09 11:34:07 +02:00
parent 481f1ed702
commit a3c87fcde4

View file

@ -842,7 +842,8 @@ fn path_hash(path: &Path) -> u64 {
/// Print the currently active document to the system printer via CUPS (lp).
///
/// - **PDF** → sent directly to CUPS via `lp`
/// - **Raster images** → converted to PDF via `img2pdf` (or `convert` as fallback)
/// - **Raster images** → converted to PDF via `img2pdf` (normalized to
/// opaque 8-bit when needed, or `convert` as fallback)
/// - **SVG** → converted to PDF via `pdftocairo` → `img2pdf`
fn print_document_sync(path: &Path, kind: DocumentKind) -> Result<(), String> {
let pdf_path = match kind {
@ -861,10 +862,45 @@ fn convert_raster_to_pdf(path: &Path) -> Result<PathBuf, String> {
return Ok(result);
}
// img2pdf refuses alpha channels and >8 bit channels: normalize to
// opaque 8-bit and retry before falling back to ImageMagick.
if let Ok(normalized) = normalize_raster(path) {
let result = convert_with_cmd(
"img2pdf",
vec![normalized.to_string_lossy().into_owned()],
path,
);
let _ = std::fs::remove_file(&normalized);
if let Ok(result) = result {
return Ok(result);
}
}
// Fallback: ImageMagick convert
convert_with_cmd("convert", vec![path.to_string_lossy().into_owned()], path)
}
fn normalize_raster(path: &Path) -> Result<PathBuf, String> {
let extension = path.extension().and_then(OsStr::to_str).unwrap_or("png");
let output_path = temp_prefix(path, "normalized").with_extension(extension);
let status = Command::new("convert")
.arg(path)
.args(["-depth", "8", "-alpha", "off"])
.arg(&output_path)
.status()
.map_err(|e| format!("Failed to run convert: {e}"))?;
if !status.success() {
return Err("convert failed".to_string());
}
if output_path.exists() {
Ok(output_path)
} else {
Err("convert did not produce output".to_string())
}
}
fn convert_svg_to_pdf(path: &Path) -> Result<PathBuf, String> {
// Render SVG to PNG with pdftocairo, then convert PNG to PDF
let prefix = temp_prefix(path, "svg");