tonhowtf/omniget · error

não gravei o PNG

Error message

não gravei o PNG: {}

What it means

This error is raised in `encode` in image_stitch.rs when the stitched RGBA image cannot be serialized to PNG bytes via `DynamicImage::write_to`. The `image` crate returns an error on buffer/format failures, and the code wraps it with anyhow to add context ('não gravei o PNG'). It indicates PNG encoding of the final stitched image failed, not that stitching failed.

Solutions

  1. Check the wrapped image::ImageError in the message for the root cause (e.g. 'Image too large' limits) and reduce input size or max_width/max dimensions.
  2. Ensure the `image` crate build includes the `png` feature and that the dimension limits are acceptable for your stitched output.
  3. If the failure is dimension-related, cap the canvas via cap_width or split the stitch into segments before encoding.

Example fix

// before
DynamicImage::ImageRgba8(img.clone())
    .write_to(&mut buf, image::ImageFormat::Png)
    .map_err(|e| anyhow!("não gravei o PNG: {}", e))?;
// after
let capped = cap_width(DynamicImage::ImageRgba8(img.clone()), max_width); // guard huge dimensions
let mut buf = Cursor::new(Vec::new());
capped.write_to(&mut buf, image::ImageFormat::Png)
    .map_err(|e| anyhow!("não gravei o PNG: {}", e))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// check image pixel count before encoding
let pixels = (img.width() as u64) * (img.height() as u64);
if pixels > 100_000_000 { return Err("imagem grande demais para codificar"); }

Type guard

fn is_encodable_size(img: &DynamicImage) -> bool {
    let (w, h) = (img.width() as u64, img.height() as u64);
    w > 0 && h > 0 && w * h <= 100_000_000
}

Try / catch

match encode(&opts, progress) {
    Ok(bytes) => write_out(&bytes),
    Err(e) if e.to_string().contains("não gravei o PNG") => {
        eprintln!("falha ao codificar PNG: {e:#}");
        // retry with reduced max_width
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `encode` with a format that is not jpeg/jpg, and the underlying `write_to(&mut buf, image::ImageFormat::Png)` call fails — e.g. image dimensions exceed the PNG or encoder limits, or an internal image-crate encoding error occurs.

Common situations: Stitching extremely tall screenshots whose pixel count exceeds PNG encoder limits; running in an environment where the image crate was compiled without PNG support; a corrupted in-memory frame producing an unencodable image.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/652b9ee4c5f87b06. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/image_stitch.rs:347

}

/// Encolhe proporcionalmente quando passa da largura pedida.
fn cap_width(img: RgbaImage, max_width: u32) -> RgbaImage {
    if max_width == 0 || img.width() <= max_width {
        return img;
    }
    let h = ((img.height() as f64 * max_width as f64 / img.width() as f64).round() as u32).max(1);
    imageops::resize(&img, max_width, h, imageops::FilterType::Lanczos3)
}

fn encode(img: &RgbaImage, format: &str, quality: u8) -> anyhow::Result<Vec<u8>> {
    if format.eq_ignore_ascii_case("jpeg") || format.eq_ignore_ascii_case("jpg") {
        super::image_compress::encode_jpeg(&DynamicImage::ImageRgba8(img.clone()), quality)
    } else {
        let mut buf = Cursor::new(Vec::new());
        DynamicImage::ImageRgba8(img.clone())
            .write_to(&mut buf, image::ImageFormat::Png)
            .map_err(|e| anyhow!("não gravei o PNG: {}", e))?;
        Ok(buf.into_inner())
    }
}

pub fn run(opts: &StitchOptions, progress: &ProgressFn) -> anyhow::Result<StitchResult> {
    if opts.inputs.is_empty() {
        return Err(anyhow!("escolha pelo menos um print"));
    }
    let total = opts.inputs.len() as u64;
    let mut frames: Vec<RgbaImage> = Vec::with_capacity(opts.inputs.len());
    for (i, path) in opts.inputs.iter().enumerate() {
        super::report(
            progress,
            "img-stitch",
            "progress",
            i as u64,
            Some(total),
            Some(path.clone()),

View on GitHub (pinned to 8600b91f42)