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:
parent
481f1ed702
commit
a3c87fcde4
1 changed files with 37 additions and 1 deletions
38
src/main.rs
38
src/main.rs
|
|
@ -842,7 +842,8 @@ fn path_hash(path: &Path) -> u64 {
|
||||||
/// Print the currently active document to the system printer via CUPS (lp).
|
/// Print the currently active document to the system printer via CUPS (lp).
|
||||||
///
|
///
|
||||||
/// - **PDF** → sent directly to CUPS via `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`
|
/// - **SVG** → converted to PDF via `pdftocairo` → `img2pdf`
|
||||||
fn print_document_sync(path: &Path, kind: DocumentKind) -> Result<(), String> {
|
fn print_document_sync(path: &Path, kind: DocumentKind) -> Result<(), String> {
|
||||||
let pdf_path = match kind {
|
let pdf_path = match kind {
|
||||||
|
|
@ -861,10 +862,45 @@ fn convert_raster_to_pdf(path: &Path) -> Result<PathBuf, String> {
|
||||||
return Ok(result);
|
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
|
// Fallback: ImageMagick convert
|
||||||
convert_with_cmd("convert", vec![path.to_string_lossy().into_owned()], path)
|
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> {
|
fn convert_svg_to_pdf(path: &Path) -> Result<PathBuf, String> {
|
||||||
// Render SVG to PNG with pdftocairo, then convert PNG to PDF
|
// Render SVG to PNG with pdftocairo, then convert PNG to PDF
|
||||||
let prefix = temp_prefix(path, "svg");
|
let prefix = temp_prefix(path, "svg");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue