You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust使用image crate调整图片透明度时编码错误的解决

Rust image crate 保存图片编码错误解决

使用Rust的image crate遍历目录中的JPG、PNG格式图片,调整透明度为50%后保存时,出现如下编码错误:

Failed to save image: Encoding(EncodingError { format: Exact(Png), underlying: Some(ColorType(Rgba32F)) })

错误原因

该错误的核心是Rgba32F颜色类型不被PNG编码器支持。原始代码中调用.to_rgba32f()将图片转为32位浮点RGBA格式,但image crate的PNG编码器仅支持8位整数格式(如Rgba8)的图像保存。

原始代码

use clap::Parser;
use std::{process, thread};
#[derive(Parser,Debug)]
#[command(author,version,about,long_about=None)]
struct Args {
    #[arg(long,value_hint=clap::ValueHint::DirPath, default_value="./")]
    picture_dir: std::path::PathBuf,
    #[arg(long, default_value="300")]
    draw_time: u64,
    #[arg(long, default_value="3")]
    start_delay: u64,
    #[arg(long)]
    dry_run: bool,
}


fn main() {
    let args = Args::parse();
    println!("{}", args.picture_dir.as_os_str().to_str().unwrap());
    let dir = args.picture_dir.as_os_str().to_str().unwrap();
    let dir = format!("{}/*.*", dir);
    let extensions_supported = vec!("png","jpg","bmp");
    for path in glob::glob(&dir).expect("Failed to list directory") {
        let path = path.unwrap();
        let copy_from_path = path.clone();
        let file_name = path.file_name().unwrap();
        let mut cachepath = std::env::temp_dir();
        cachepath.push(file_name.to_str().unwrap());
        let str_path = cachepath.to_str().unwrap();
        let path_extension = path.extension().unwrap().to_str().unwrap();
        if !extensions_supported.contains(&path_extension) {
            println!("We don't support that file type");
            continue;
        }
        println!("{}", str_path);
        let start = std::time::Instant::now();
        // 启动外部程序
        let cmd_str = format!("cmd.exe /C clipstudiopaint.exe {}", str_path);
        let mut child: Option<process::Child> = None;
        if args.dry_run {
            println!("{}",cmd_str);
        } else {
            std::fs::copy(copy_from_path,cachepath.clone()).expect("Failed to create temporary file");
            let cache_image_path = cachepath.clone();
            let cache_image_path = cache_image_path.to_str().unwrap();
            let save_image_path = cachepath.clone();
            let mut image = image::open(cache_image_path)
            .expect("Failed to open image for editing").to_rgba32f();
            image.pixels_mut().for_each(|p| p[3] /= 2.0);
            
            image.save(save_image_path.to_str().unwrap()).expect("Failed to save image");
            child = Some(process::Command::new("cmd")
            .arg("/C")
            .arg("clipstudiopaint.exe")
            .arg(cachepath.to_str().unwrap())
            .spawn()
            .expect("Failed to run clipstudiopaint"));
        }
        // 等待程序加载
        loop {
            if start.elapsed().as_secs() > args.start_delay {
                break;
            }
        }
        let start = std::time::Instant::now();
        // 等待指定绘制时间
        println!("Starting timer");
        loop {
            if start.elapsed().as_secs() > args.draw_time {
                break;
            }
        }   
        // 终止进程
        if !args.dry_run {
            child.unwrap().kill().expect("Failed to kill childprocess");
            std::fs::remove_file(cachepath).expect("Failed to remove temp file");
        }
        let start = std::time::Instant::now();
        loop {
            if start.elapsed().as_secs() > 2 {
                break;
            }
        }  
    }
}

修正后的关键代码片段

std::fs::copy(copy_from_path,cachepath.clone()).expect("Failed to create temporary file");
let image_edit_path = image_edit_path.clone();
let image_edit_path = image_edit_path.to_str().unwrap();
let save_image_path = cachepath.clone();
println!("Opening: {} for editing", image_edit_path);
let mut image = image::open(image_edit_path)
.expect("Failed to open image for editing");
let mut target_image = image::DynamicImage::new_rgba8(image.width(), image.height());
let mut target_image = target_image.to_rgba8();
target_image.pixels_mut().for_each(|p| *p = image::Rgba{0: [246, 244, 237, 255]});
let mut image = image.to_rgba8();
image.pixels_mut().for_each(|p| p[3] = 127); // 127对应50%透明度
image::imageops::overlay(&mut target_image, &image, 0, 0);
let target_image = image::DynamicImage::ImageRgba8(target_image);

target_image.save(save_image_path.to_str().unwrap()).expect("Failed to save image");

修正要点

  • 替换Rgba32F格式为编码器支持的Rgba8(8位整数RGBA)格式,彻底解决编码不兼容问题
  • 直接设置alpha通道的整数值(127对应50%透明度,可按需调整)
  • 通过创建纯色背景图并叠加处理后的图像,确保最终图像格式完全符合PNG编码器要求

内容的提问来源于stack exchange,提问作者J. Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:35:00