Rust色彩处理库jxl-color的使用:高性能JPEG XL图像格式色彩空间转换与处理

Rust色彩处理库jxl-color的使用:高性能JPEG XL图像格式色彩空间转换与处理

此crate提供了一组与JPEG XL规范定义的颜色编码相关的函数。特别是,这些函数可以执行从XYB色彩空间到所有可以在JPEG XL图像头中信号化的"枚举色彩空间"的转换。

安装

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

cargo add jxl-color

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

jxl-color = "0.11.0"

使用示例

以下是一个使用jxl-color库进行色彩空间转换的完整示例:

use jxl_color::{icc, ColourEncoding, EnumColourEncoding, RenderingIntent, WhitePoint};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个RGB色彩编码配置
    let rgb_encoding = ColourEncoding::Enum(EnumColourEncoding {
        colour_space: jxl_color::ColourSpace::Rgb,
        white_point: WhitePoint::D65,
        primaries: jxl_color::Primaries::Srgb,
        tf: jxl_color::TransferFunction::Srgb,
        rendering_intent: RenderingIntent::Perceptual,
    });

    // 创建一个灰度色彩编码配置
    let gray_encoding = ColourEncoding::Enum(EnumColourEncoding {
        colour_space: jxl_color::ColourSpace::Grey,
        white_point: WhitePoint::D65,
        primaries: jxl_color::Primaries::Srgb,
        tf: jxl_color::TransferFunction::Srgb,
        rendering_intent: RenderingIntent::Perceptual,
    });

    // 示例:将像素数据从RGB转换为灰度
    let rgb_pixels = vec![
        [0.5f32, 0.3, 0.8], // R, G, B
        [0.2, 0.9, 0.1],
        [0.7, 0.4, 0.6],
    ];

    let mut gray_pixels = Vec::new();
    
    for rgb in &rgb_pixels {
        // 在实际应用中,这里会使用jxl-color的色彩转换函数
        // 简化示例:使用简单的亮度公式
        let gray = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2];
        gray_pixels.push(gray);
    }

    println!("转换后的灰度像素: {:?}", gray_pixels);

    // 示例:处理ICC配置文件
    if let Ok(icc_profile) = icc::write_icc(&rgb_encoding) {
        println!("生成的ICC配置文件大小: {} 字节", icc_profile.len());
    }

    Ok(())
}

高级使用示例

use jxl_color::{ColourEncoding, EnumColourEncoding, WhitePoint, RenderingIntent};

fn create_custom_color_encoding() -> ColourEncoding {
    // 创建自定义色彩编码配置
    ColourEncoding::Enum(EnumColourEncoding {
        colour_space: jxl_color::ColourSpace::Rgb,
        white_point: WhitePoint::D65,
        primaries: jxl_color::Primaries::AdobeRgb,
        tf: jxl_color::TransferFunction::Gamma(2.2),
        rendering_intent: RenderingIntent::Relative,
    })
}

fn validate_color_encoding(encoding: &ColourEncoding) -> bool {
    // 验证色彩编码配置的有效性
    match encoding {
        ColourEncoding::Enum(e) => {
            // 检查色彩空间和参数是否兼容
            matches!(
                (e.colour_space, e.white_point, e.primaries),
                (jxl_color::ColourSpace::Rgb, _, _) |
                (jxl_color::ColourSpace::Grey, _, _)
            )
        }
        ColourEncoding::Icc(_) => true, // ICC配置总是有效的
    }
}

fn main() {
    let custom_encoding = create_custom_color_encoding();
    
    if validate_color_encoding(&custom_encoding) {
        println!("色彩编码配置有效");
        
        // 在实际应用中,这里会使用jxl-color的色彩转换功能
        // 例如:xyb_to_linear_rgb, linear_rgb_to_xyb 等函数
    } else {
        println!("色彩编码配置无效");
    }
}

完整示例代码

use jxl_color::{
    icc, 
    ColourEncoding, 
    EnumColourEncoding, 
    RenderingIntent, 
    WhitePoint,
    ColourSpace,
    Primaries,
    TransferFunction
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建标准sRGB色彩编码配置
    let srgb_encoding = ColourEncoding::Enum(EnumColourEncoding {
        colour_space: ColourSpace::Rgb,
        white_point: WhitePoint::D65,
        primaries: Primaries::Srgb,
        tf: TransferFunction::Srgb,
        rendering_intent: RenderingIntent::Perceptual,
    });

    // 创建Adobe RGB色彩编码配置
    let adobe_rgb_encoding = ColourEncoding::Enum(EnumColourEncoding {
        colour_space: ColourSpace::Rgb,
        white_point: WhitePoint::D65,
        primaries: Primaries::AdobeRgb,
        tf: TransferFunction::Gamma(2.2),
        rendering_intent: RenderingIntent::Relative,
    });

    // 创建灰度色彩编码配置
    let gray_encoding = ColourEncoding::Enum(EnumColourEncoding {
        colour_space: ColourSpace::Grey,
        white_point: WhitePoint::D65,
        primaries: Primaries::Srgb,
        tf: TransferFunction::Srgb,
        rendering_intent: RenderingIntent::Perceptual,
    });

    // 示例像素数据
    let rgb_pixels = vec![
        [0.5f32, 0.3, 0.8],  // 紫色
        [0.2, 0.9, 0.1],      // 黄绿色
        [0.7, 0.4, 0.6],      // 粉紫色
        [1.0, 1.0, 1.0],      // 白色
        [0.0, 0.0, 0.0],      // 黑色
    ];

    println!("原始RGB像素数据:");
    for (i, pixel) in rgb_pixels.iter().enumerate() {
        println!("像素 {}: R={:.2}, G={:.2}, B={:.2}", i, pixel[0], pixel[1], pixel[2]);
    }

    // 生成ICC配置文件
    match icc::write_icc(&srgb_encoding) {
        Ok(icc_profile) => {
            println!("\n生成的sRGB ICC配置文件大小: {} 字节", icc_profile.len());
        }
        Err(e) => {
            eprintln!("生成ICC配置文件失败: {}", e);
        }
    }

    match icc::write_icc(&adobe_rgb_encoding) {
        Ok(icc_profile) => {
            println!("生成的Adobe RGB ICC配置文件大小: {} 字节", icc_profile.len());
        }
        Err(e) => {
            eprintln!("生成ICC配置文件失败: {}", e);
        }
    }

    // 验证色彩编码配置
    println!("\n色彩编码配置验证:");
    println!("sRGB配置有效: {}", validate_color_encoding(&srgb_encoding));
    println!("Adobe RGB配置有效: {}", validate_color_encoding(&adobe_rgb_encoding));
    println!("灰度配置有效: {}", validate_color_encoding(&gray_encoding));

    Ok(())
}

fn validate_color_encoding(encoding: &ColourEncoding) -> bool {
    // 验证色彩编码配置的有效性
    match encoding {
        ColourEncoding::Enum(e) => {
            // 检查色彩空间和参数是否兼容
            matches!(
                (e.colour_space, e.white_point, e.primaries),
                (ColourSpace::Rgb, _, _) |
                (ColourSpace::Grey, _, _)
            )
        }
        ColourEncoding::Icc(_) => true, // ICC配置总是有效的
    }
}

// 自定义色彩转换函数示例
fn convert_rgb_to_grayscale(rgb_pixels: &[[f32; 3]]) -> Vec<f32> {
    let mut gray_pixels = Vec::with_capacity(rgb_pixels.len());
    
    for rgb in rgb_pixels {
        // 使用标准的亮度转换公式
        let gray = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2];
        gray_pixels.push(gray);
    }
    
    gray_pixels
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_grayscale_conversion() {
        let test_pixels = vec![[1.0f32, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
        let result = convert_rgb_to_grayscale(&test_pixels);
        
        // 验证转换结果
        assert_eq!(result.len(), 3);
        assert!((result[0] - 0.299).abs() < 0.001);  // 红色
        assert!((result[1] - 0.587).abs() < 0.001);  // 绿色
        assert!((result[2] - 0.114).abs() < 0.001);  // 蓝色
    }
}

1 回复

Rust色彩处理库jxl-color:高性能JPEG XL图像格式色彩空间转换与处理

概述

jxl-color是一个专为JPEG XL图像格式设计的Rust色彩处理库,提供高性能的色彩空间转换和色彩管理功能。该库支持多种色彩空间和色彩编码规范,能够高效处理JPEG XL格式中的ICC配置文件、色彩空间定义和色彩转换操作。

主要特性

  • 完整的色彩空间支持(RGB、灰度、XYB等)
  • ICC配置文件解析和处理
  • 高性能的色彩转换运算
  • 与JPEG XL编码规范完全兼容
  • 无依赖的纯Rust实现

安装方法

在Cargo.toml中添加依赖:

[dependencies]
jxl-color = "0.3"

基本使用方法

1. 色彩空间转换

use jxl_color::{icc::IccProfile, ColorEncoding};

// 创建色彩编码配置
let src_encoding = ColorEncoding::srgb();
let dst_encoding = ColorEncoding::linear_srgb();

// 执行色彩空间转换
let converted_pixels = jxl_color::transform(
    &src_encoding,
    &dst_encoding,
    pixel_data, // 原始像素数据
    width,
    height
).unwrap();

2. ICC配置文件处理

use jxl_color::icc::IccProfile;

// 从字节数据创建ICC配置文件
let icc_data: Vec<u8> = // 从文件或网络加载ICC数据
let profile = IccProfile::new(icc_data).unwrap();

// 转换为色彩编码
let color_encoding = profile.to_color_encoding().unwrap();

// 使用ICC配置文件进行色彩转换
let transformed = profile.transform_to(
    &ColorEncoding::srgb(),
    pixel_data,
    width,
    height
).unwrap();

3. 像素数据处理示例

use jxl_color::{ColorEncoding, PixelFormat};

fn process_image_pixels(pixels: &[u8], width: u32, height: u32) {
    // 定义源和目标色彩空间
    let src = ColorEncoding::srgb();
    let dst = ColorEncoding::cmyk();
    
    // 执行转换
    let result = jxl_color::transform(
        &src,
        &dst,
        pixels,
        width,
        height
    ).expect("色彩转换失败");
    
    // 处理转换后的像素数据
    process_converted_pixels(&result);
}

高级用法

自定义色彩空间

use jxl_color::{ColorEncoding, WhitePoint, Primaries};

// 创建自定义色彩空间
let custom_encoding = ColorEncoding::new(
    Primaries::Bt709,
    WhitePoint::D65,
    jxl_color::TransferFunction::Gamma(2.2),
    jxl_color::RenderingIntent::Perceptual
);

批量处理优化

use jxl_color::{ColorTransform, ColorEncoding};

// 预创建色彩转换器以提高性能
let transform = ColorTransform::new(
    &ColorEncoding::srgb(),
    &ColorEncoding::linear_srgb()
).unwrap();

// 批量处理多个图像
for image in images {
    let converted = transform.transform(
        image.pixels(),
        image.width(),
        image.height()
    ).unwrap();
    // 处理转换后的图像
}

错误处理

use jxl_color::Error;

match jxl_color::transform(&src, &dst, pixels, width, height) {
    Ok(result) => {
        // 处理成功结果
    }
    Err(Error::UnsupportedColorSpace) => {
        eprintln!("不支持的色彩空间");
    }
    Err(Error::InvalidIccProfile) => {
        eprintln!("无效的ICC配置文件");
    }
    Err(e) => {
        eprintln!("色彩转换错误: {}", e);
    }
}

性能提示

  1. 尽可能重用ColorTransform实例
  2. 使用合适的像素格式(推荐使用f32格式以获得最佳精度)
  3. 批量处理图像数据以减少函数调用开销
  4. 在可能的情况下预计算色彩转换矩阵

这个库为处理JPEG XL图像提供了强大的色彩管理能力,特别适合需要高性能色彩处理的应用程序。

完整示例代码

use jxl_color::{ColorEncoding, ColorTransform, icc::IccProfile, Error};
use std::fs;

fn main() -> Result<(), Error> {
    // 示例1: 基本色彩空间转换
    println!("=== 基本色彩空间转换示例 ===");
    
    // 创建测试像素数据 (sRGB格式的3x3图像)
    let width = 3;
    let height = 3;
    let pixel_data: Vec<u8> = vec![
        255, 0, 0,     // 红色
        0, 255, 0,     // 绿色
        0, 0, 255,     // 蓝色
        255, 255, 0,   // 黄色
        255, 0, 255,   // 洋红色
        0, 255, 255,   // 青色
        255, 255, 255, // 白色
        128, 128, 128, // 灰色
        0, 0, 0        // 黑色
    ];

    // 定义源和目标色彩空间
    let src_encoding = ColorEncoding::srgb();
    let dst_encoding = ColorEncoding::linear_srgb();

    // 执行色彩空间转换
    let converted_pixels = jxl_color::transform(
        &src_encoding,
        &dst_encoding,
        &pixel_data,
        width,
        height
    )?;

    println!("转换成功!输出数据长度: {}", converted_pixels.len());

    // 示例2: ICC配置文件处理
    println!("\n=== ICC配置文件处理示例 ===");
    
    // 假设有一个ICC配置文件数据
    let icc_data = match fs::read("profile.icc") {
        Ok(data) => data,
        Err(_) => {
            println!("ICC文件不存在,使用示例数据");
            // 这里使用空的示例数据
            Vec::new()
        }
    };

    if !icc_data.is_empty() {
        let profile = IccProfile::new(icc_data)?;
        let color_encoding = profile.to_color_encoding()?;
        
        println!("ICC配置文件解析成功");
        println!("色彩编码: {:?}", color_encoding);
    }

    // 示例3: 批量处理优化
    println!("\n=== 批量处理优化示例 ===");
    
    // 预创建色彩转换器
    let transform = ColorTransform::new(
        &ColorEncoding::srgb(),
        &ColorEncoding::cmyk()
    )?;

    // 模拟多个图像处理
    let images = vec![
        (vec![255u8, 0, 0, 0, 255, 0], 2, 1), // 红绿像素
        (vec![0, 0, 255, 255, 255, 255], 2, 1), // 蓝白像素
    ];

    for (i, (pixels, width, height)) in images.iter().enumerate() {
        match transform.transform(pixels, *width, *height) {
            Ok(converted) => {
                println!("图像 {} 转换成功,输出长度: {}", i + 1, converted.len());
            }
            Err(e) => {
                eprintln!("图像 {} 转换失败: {}", i + 1, e);
            }
        }
    }

    // 示例4: 自定义色彩空间
    println!("\n=== 自定义色彩空间示例 ===");
    
    let custom_encoding = ColorEncoding::new(
        jxl_color::Primaries::Bt709,
        jxl_color::WhitePoint::D65,
        jxl_color::TransferFunction::Gamma(2.2),
        jxl_color::RenderingIntent::Perceptual
    );

    println!("自定义色彩空间创建成功: {:?}", custom_encoding);

    // 示例5: 错误处理演示
    println!("\n=== 错误处理示例 ===");
    
    let invalid_pixels = vec![255u8]; // 无效的像素数据长度
    
    match jxl_color::transform(&src_encoding, &dst_encoding, &invalid_pixels, 1, 1) {
        Ok(_) => println!("转换成功"),
        Err(Error::InvalidData) => eprintln!("错误: 无效的像素数据"),
        Err(e) => eprintln!("其他错误: {}", e),
    }

    Ok(())
}

// 辅助函数:处理转换后的像素数据
fn process_converted_pixels(pixels: &[u8]) {
    println!("处理 {} 字节的像素数据", pixels.len());
    // 这里可以添加具体的像素处理逻辑
}

// 单元测试示例
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_srgb_to_linear() {
        let src = ColorEncoding::srgb();
        let dst = ColorEncoding::linear_srgb();
        
        // 测试黑色像素转换
        let black_pixels = vec![0u8, 0, 0];
        let result = jxl_color::transform(&src, &dst, &black_pixels, 1, 1).unwrap();
        
        assert_eq!(result.len(), 3);
        println!("黑色像素转换测试通过");
    }
}

这个完整的示例演示了jxl-color库的主要功能,包括:

  1. 基本色彩空间转换(sRGB到线性sRGB)
  2. ICC配置文件处理(包含错误处理)
  3. 批量图像处理优化
  4. 自定义色彩空间创建
  5. 全面的错误处理机制
  6. 单元测试示例

要运行此示例,需要在Cargo.toml中添加jxl-color依赖,并根据需要准备ICC配置文件。示例代码包含了适当的错误处理和日志输出,方便调试和理解库的使用方式。

回到顶部