pbrt/src/utils/colorspace.rs

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)
}
}