#rgb #color-space #xyz #color-conversion #srgb #color #graphics

rgb_derivation

用于从白点和原色计算XYZ-RGB转换矩阵的程序

3个不稳定版本

0.2.0 2021年5月10日
0.1.2 2021年4月30日
0.1.1 2021年4月26日

6 in #xyz

Download history 19/week @ 2024-04-20 21/week @ 2024-04-27 18/week @ 2024-05-04 15/week @ 2024-05-11 18/week @ 2024-05-18 27/week @ 2024-05-25 29/week @ 2024-06-01 16/week @ 2024-06-08 14/week @ 2024-06-15 17/week @ 2024-06-22 4/week @ 2024-06-29 17/week @ 2024-07-13 12/week @ 2024-07-20 16/week @ 2024-07-27 10/week @ 2024-08-03

每月 55 次下载
用于 3 个crate(通过srgb

LGPL-3.0-or-later

25KB
292

RGB颜色系统导出程序

用于从给定RGB颜色系统(如sRGB颜色空间)导出RGB→XYZ和XYZ→RGB转换矩阵的函数。计算是从以参考白点的色域和红、绿、蓝原色形式提供的该系统的定义进行的。也可以从原色的XYZ坐标进行构造。

该crate支持有理数和大整数类型的算术运算,因此可以在需要的情况下进行计算而不会丢失精度。只要一个类型实现了四种基本运算,就可以与这个库一起使用。例如,f32num::Rational64num::BigRational 都可以用来。

用法

使用Cargo项目中的此包非常简单,只需添加单个依赖项

[dependencies]
rgb_derivation = "0.1"

有了这个依赖项,现在可以简单地编写一个将sRGB颜色转换为其他颜色空间的程序

type Scalar = num::rational::Ratio<i128>;
type Chromaticity = rgb_derivation::Chromaticity<Scalar>;

fn chromaticity(x: (i128, i128), y: (i128, i128)) -> Chromaticity {
    Chromaticity::new(Scalar::new(x.0, x.1), Scalar::new(y.0, y.1)).unwrap()
}

fn print_vector(header: &str, vector: &[Scalar; 3]) {
    print!("{}: [", header);
    for (idx, value) in vector.iter().enumerate() {
        print!("{} {} / {}",
               if idx == 0 { "" } else { "," },
               value.numer(), value.denom());
    }
    println!(" ]");
}

fn print_matrix(header: &str, matrix: &[[Scalar; 3]; 3]) {
    static OPEN: [char; 3] = ['', '', ''];
    static CLOSE: [char; 3] = ['', '', ''];

    fn make_array<T>(f: impl Fn(usize) -> T) -> [T; 3] { [f(0), f(1), f(2)] }

    let formatted = make_array(|row| make_array(|col| {
        let value = &matrix[row][col];
        (format!("{}", value.numer()), format!("{}", value.denom()))
    }));
    let lengths = make_array(|col| (
        formatted.iter().map(|row| row[col].0.len()).max().unwrap(),
        formatted.iter().map(|row| row[col].1.len()).max().unwrap(),
    ));

    let indent = header.chars().count();
    for (idx, row) in formatted.iter().enumerate() {
        if idx == 1 {
            print!("{}: {}", header, OPEN[idx]);
        } else {
            print!("{:indent$}  {}", "", OPEN[idx], indent = indent);
        }
        for (idx, value) in row.iter().enumerate() {
            print!("{comma} {numer:>numer_len$} / {denom:>denom_len$}",
                   comma = if idx == 0 { "" } else { "," },
                   numer = value.0, numer_len = lengths[idx].0,
                   denom = value.1, denom_len = lengths[idx].1);
        }
        println!(" {}", CLOSE[idx]);
    }
}

fn main() {
    let white_xy = chromaticity((312713, 1000000), (329016, 1000000));
    let primaries_xy = [
        chromaticity((64, 100), (33, 100)),
        chromaticity((30, 100), (60, 100)),
        chromaticity((15, 100), (6, 100)),
    ];

    let white_xyz = white_xy.to_xyz();
    let matrix = rgb_derivation::matrix::calculate(
        &white_xyz, &primaries_xy).unwrap();
    let inverse = rgb_derivation::matrix::inversed_copy(&matrix).unwrap();
    let primaries_xyz = rgb_derivation::matrix::transposed_copy(&matrix);

    print_vector("sRGB white point (D65)", &white_xyz);
    print_matrix("sRGB primaries", &primaries_xyz);
    print_matrix("sRGB→XYZ", &matrix);
    print_matrix("XYZ→sRGB", &inverse);
}

依赖项

~155KB