75 lines
2.5 KiB
Rust
75 lines
2.5 KiB
Rust
use crate::core::pbrt::Float;
|
|
use super::geometry::Point2f;
|
|
use super::transform::SquareMatrix;
|
|
use super::color::{RGBSigmoidPolynomial, RGBToSpectrumTable, RGB, XYZ};
|
|
use super::spectrum::{DenselySampledSpectrum, Spectrum, SampledSpectrum};
|
|
|
|
use std::cmp::{Eq, PartialEq};
|
|
use std::sync::Arc;
|
|
|
|
#[derive(Clone)]
|
|
pub struct RGBColorspace {
|
|
r: Point2f,
|
|
g: Point2f,
|
|
b: Point2f,
|
|
w: Point2f,
|
|
illuminant: Spectrum,
|
|
rgb_to_spectrum_table: Arc<RGBToSpectrumTable>,
|
|
xyz_from_rgb: SquareMatrix<Float, 3>,
|
|
rgb_from_xyz: SquareMatrix<Float, 3>,
|
|
|
|
}
|
|
|
|
impl RGBColorspace {
|
|
pub fn new(r: Point2f,
|
|
g: Point2f,
|
|
b: Point2f,
|
|
illuminant: Spectrum,
|
|
rgb_to_spectrum_table: RGBToSpectrumTable) -> Self {
|
|
let w_xyz = illuminant.to_xyz();
|
|
let w = w_xyz.xy();
|
|
let r_xyz = XYZ::from_xyy(r, 1.0);
|
|
let g_xyz = XYZ::from_xyy(g, 1.0);
|
|
let b_xyz = XYZ::from_xyy(b, 1.0);
|
|
let rgb_values = [[r_xyz.x(), g_xyz.x(), b_xyz.x()], [r_xyz.y(), g_xyz.y(), b_xyz.y()], [r_xyz.z(), g_xyz.z(), g_xyz.z()]];
|
|
let rgb: SquareMatrix<Float, 3> = SquareMatrix { m: rgb_values };
|
|
let c = match rgb.inverse() {
|
|
Some(inv_matrix) => { inv_matrix * w_xyz },
|
|
None => { panic!("Cannot create RGBColorspace: The RGB primaries form a singular matrix."); }
|
|
};
|
|
let xyz_from_rgb_m = [[c[0], 0.0, 0.0], [0.0, c[1], 0.0], [0.0, 0.0, c[2]]];
|
|
let xyz_from_rgb = rgb * SquareMatrix { m: xyz_from_rgb_m };
|
|
let rgb_from_xyz = xyz_from_rgb.inverse().expect("Failed to invert the XYZfromRGB matrix. Is it singular?");
|
|
|
|
Self { r, g, b, w, illuminant, rgb_to_spectrum_table: Arc::new(rgb_to_spectrum_table), xyz_from_rgb, rgb_from_xyz }
|
|
}
|
|
|
|
pub fn to_xyz(&self, rgb: RGB) -> XYZ {
|
|
self.xyz_from_rgb.transform_to_xyz(rgb)
|
|
}
|
|
|
|
pub fn to_rgb(&self, xyz: XYZ) -> RGB {
|
|
self.rgb_from_xyz.transform_to_rgb(xyz)
|
|
}
|
|
|
|
pub fn to_rgb_coeffs(&self, rgb: RGB) -> RGBSigmoidPolynomial {
|
|
self.rgb_to_spectrum_table.to_polynomial(rgb)
|
|
|
|
}
|
|
|
|
pub fn convert_colorspace(&self, other: &RGBColorspace) -> SquareMatrix<Float, 3> {
|
|
if self == other {
|
|
return SquareMatrix::default()
|
|
}
|
|
|
|
self.rgb_from_xyz * other.xyz_from_rgb
|
|
}
|
|
}
|
|
|
|
impl PartialEq for RGBColorspace {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.r == other.r && self.g == other.g && self.b == other.b && self.w == other.w &&
|
|
Arc::ptr_eq(&self.rgb_to_spectrum_table, &other.rgb_to_spectrum_table)
|
|
}
|
|
}
|
|
|