Rust图像处理库jxl-modular的使用:高效模块化JPEG XL编解码与图像格式转换

Rust图像处理库jxl-modular的使用:高效模块化JPEG XL编解码与图像格式转换

jxl-modular介绍

jxl-modular是一个JPEG XL Modular图像解码器库。Modular图像表示一组网格(二维数组)的整数值。Modular图像主要用于无损图像,但有损VarDCT图像也使用它们来存储各种信息,如量化LF图像和varblock配置。

安装

在项目目录中运行以下Cargo命令:

cargo add jxl-modular

或者在Cargo.toml中添加以下行:

jxl-modular = "0.11.2"

使用示例

以下是使用jxl-modular进行JPEG XL图像解码的基本示例:

use jxl_modular::Modular;
use std::fs::File;
use std::io::Read;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 读取JPEG XL文件
    let mut file = File::open("example.jxl")?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer)?;
    
    // 创建Modular解码器
    let modular = Modular::new();
    
    // 解码图像
    let result = modular.decode(&buffer)?;
    
    // 处理解码后的图像数据
    for channel in result.channels {
        println!("Channel dimensions: {}x{}", channel.width, channel.height);
        // 这里可以访问channel.data获取像素数据
    }
    
    Ok(())
}

高级用法

以下是一个更完整的示例,展示了如何将JPEG XL图像转换为PNG格式:

use jxl_modular::Modular;
use image::{ImageBuffer, RgbImage};
use std::fs::File;
use std::io::Read;

fn convert_jxl_to_png(input_path: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 读取输入文件
    let mut file = File::open(input_path)?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer)?;
    
    // 解码JPEG XL图像
    let modular = Modular::new();
    let decoded = modular.decode(&buffer)?;
    
    // 假设我们有一个RGB图像(3个通道)
    if decoded.channels.len() < 3 {
        return Err("Not enough color channels".into());
    }
    
    let width = decoded.channels[0].width;
    let height = decoded.channels[0].height;
    
    // 创建图像缓冲区
    let mut img: RgbImage = ImageBuffer::new(width as u32, height as u32);
    
    // 填充像素数据
    for y in 0..height {
        for x in 0..width {
            let r = decoded.channels[0].data[y * width + x];
            let g = decoded.channels[1].data[y * width + x];
            let b = decoded.channels[2].data[y * width + x];
            
            img.put_pixel(x as u32, y as u32, image::Rgb([r as u8, g as u8, b as u8]));
        }
    }
    
    // 保存为PNG
    img.save(output_path)?;
    
    Ok(())
}

fn main() {
    if let Err(e) = convert_jxl_to_png("input.jxl", "output.png") {
        eprintln!("Error: {}", e);
    }
}

完整示例代码

以下是一个完整的示例,展示了如何从JPEG XL解码图像并转换为多种格式:

use jxl_modular::Modular;
use image::{ImageBuffer, RgbImage, ImageFormat};
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn convert_jxl_image(
    input_path: &str,
    output_path: &str,
    format: ImageFormat
) -> Result<(), Box<dyn std::error::Error>> {
    // 读取输入文件
    let mut file = File::open(input_path)?;
    let mut buffer = Vec::new();
    file.read_to_end(&mut buffer)?;
    
    // 解码JPEG XL图像
    let modular = Modular::new();
    let decoded = modular.decode(&buffer)?;
    
    // 检查通道数量
    if decoded.channels.len() < 3 {
        return Err("需要至少3个颜色通道".into());
    }
    
    let width = decoded.channels[0].width;
    let height = decoded.channels[0].height;
    
    // 创建RGB图像缓冲区
    let mut img: RgbImage = ImageBuffer::new(width as u32, height as u32);
    
    // 填充像素数据
    for y in 0..height {
        for x in 0..width {
            let r = decoded.channels[0].data[y * width + x];
            let g = decoded.channels[1].data[y * width + x];
            let b = decoded.channels[2].data[y * width + x];
            
            img.put_pixel(x as u32, y as u32, image::Rgb([r as u8, g as u8, b as u8]));
        }
    }
    
    // 根据指定格式保存图像
    let output_file = File::create(output_path)?;
    match format {
        ImageFormat::Png => img.save_with_format(output_path, ImageFormat::Png)?,
        ImageFormat::Jpeg => img.save_with_format(output_path, ImageFormat::Jpeg)?,
        ImageFormat::Bmp => img.save_with_format(output_path, ImageFormat::Bmp)?,
        _ => return Err("不支持的输出格式".into()),
    }
    
    Ok(())
}

fn main() {
    // 转换为PNG
    if let Err(e) = convert_jxl_image("input.jxl", "output.png", ImageFormat::Png) {
        eprintln!("PNG转换错误: {}", e);
    }
    
    // 转换为JPEG
    if let Err(e) = convert_jxl_image("input.jxl", "output.jpg", ImageFormat::Jpeg) {
        eprintln!("JPEG转换错误: {}", e);
    }
    
    // 转换为BMP
    if let Err(e) = convert_jxl_image("input.jxl", "output.bmp", ImageFormat::Bmp) {
        eprintln!("BMP转换错误: {}", e);
    }
}

特性

  • 支持JPEG XL Modular图像解码
  • 高效处理无损图像
  • 支持多通道图像数据
  • 可与其他图像处理库(如image-rs)集成

许可证

jxl-modular采用MIT或Apache-2.0双重许可。


1 回复

Rust图像处理库jxl-modular的使用:高效模块化JPEG XL编解码与图像格式转换

完整示例代码

下面是一个完整的示例程序,展示了jxl-modular库的主要功能:

use jxl_modular::{
    decode::JxlDecoder,
    encode::{JxlEncoder, JxlEncodingOptions},
    metadata::JxlMetadata,
    transcode::ImageTranscoder
};
use image::open;
use std::{
    fs::File,
    path::Path,
    time::Instant
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例文件路径
    let input_jxl = "input.jxl";
    let input_png = "input.png";
    let output_jxl = "output.jxl";
    let output_png = "output.png";
    let converted_jxl = "converted.jxl";

    // 1. 解码JPEG XL图像
    let start = Instant::now();
    decode_jxl(input_jxl, output_png)?;
    println!("解码完成,耗时: {:?}", start.elapsed());

    // 2. 编码为JPEG XL
    let start = Instant::now();
    encode_to_jxl(input_png, output_jxl)?;
    println!("编码完成,耗时: {:?}", start.elapsed());

    // 3. 图像格式转换
    let start = Instant::now();
    convert_image(input_png, converted_jxl)?;
    println!("格式转换完成,耗时: {:?}", start.elapsed());

    // 4. 自定义编码参数
    let start = Instant::now();
    custom_encode(input_png, "custom_encoded.jxl")?;
    println!("自定义编码完成,耗时: {:?}", start.elapsed());

    // 5. 读取元数据
    read_metadata(input_jxl)?;

    Ok(())
}

/// 解码JPEG XL图像
fn decode_jxl(input_path: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 打开输入文件
    let mut file = File::open(input_path)?;
    
    // 创建解码器
    let mut decoder = JxlDecoder::new(&mut file)?;
    
    // 解码图像
    let image = decoder.decode()?;
    
    // 保存为PNG格式
    image.save(output_path)?;
    
    Ok(())
}

/// 编码为JPEG XL
fn encode_to_jxl(input_path: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 使用image库打开图像
    let img = open(input_path)?;
    
    // 创建编码器
    let mut encoder = JxlEncoder::new(img)?;
    
    // 创建输出文件
    let mut output_file = File::create(output_path)?;
    
    // 编码并写入文件
    encoder.encode_to(&mut output_file)?;
    
    Ok(())
}

/// 图像格式转换
fn convert_image(input_path: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 创建转码器
    let transcoder = ImageTranscoder::new(Path::new(input_path))?;
    
    // 转码为目标格式
    transcoder.transcode_to(Path::new(output_path))?;
    
    Ok(())
}

/// 自定义编码参数
fn custom_encode(input_path: &str, output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 使用image库打开图像
    let img = open(input_path)?;
    
    // 设置编码选项
    let options = JxlEncodingOptions {
        quality: 90,       // 质量设置 (0-100)
        effort: 7,          // 编码努力程度 (1-9)
        lossless: false,    // 非无损编码
        ..Default::default()
    };
    
    // 使用自定义选项创建编码器
    let mut encoder = JxlEncoder::with_options(img, options)?;
    
    // 创建输出文件
    let mut output_file = File::create(output_path)?;
    
    // 编码并写入文件
    encoder.encode_to(&mut output_file)?;
    
    Ok(())
}

/// 读取图像元数据
fn read_metadata(input_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 打开输入文件
    let mut file = File::open(input_path)?;
    
    // 读取元数据
    let metadata = JxlMetadata::read_from(&mut file)?;
    
    // 打印元数据信息
    println!("图像元数据:");
    println!("宽度: {}", metadata.width);
    println!("高度: {}", metadata.height);
    println!("色彩空间: {:?}", metadata.color_space);
    println!("包含的元数据块数量: {}", metadata.metadata_chunks.len());
    
    Ok(())
}

示例说明

这个完整示例展示了jxl-modular库的五个主要功能:

  1. 解码JPEG XL图像:将JPEG XL格式文件解码并保存为PNG格式
  2. 编码为JPEG XL:将普通图像格式(如PNG)编码为JPEG XL格式
  3. 图像格式转换:自动识别输入格式并转换为JPEG XL格式
  4. 自定义编码参数:使用自定义质量、压缩级别等参数进行编码
  5. 读取元数据:从JPEG XL文件中提取并显示元数据信息

每个操作都添加了计时功能,方便评估性能。要运行此示例,需要准备以下测试文件:

  • input.jxl (JPEG XL格式图像)
  • input.png (PNG格式图像)

性能优化建议

  1. 对于批量处理,可以重用编码器/解码器实例
  2. 大文件处理建议使用异步I/O
  3. 根据需求调整编码参数平衡速度和质量

依赖说明

运行此示例需要在Cargo.toml中添加以下依赖:

[dependencies]
jxl-modular = "0.3"
image = "0.24"

这个示例涵盖了jxl-modular库的主要功能,可以作为您项目开发的起点。

回到顶部