116 lines
3.3 KiB
Rust
116 lines
3.3 KiB
Rust
use crate::core::color::{RGB, RGBSigmoidPolynomial, RGBToSpectrumTable, XYZ};
|
|
use crate::core::geometry::Point2f;
|
|
use crate::core::pbrt::Float;
|
|
use crate::spectra::{DenselySampledSpectrum, SampledSpectrum};
|
|
use crate::utils::math::SquareMatrix3f;
|
|
use crate::utils::ptr::Ptr;
|
|
use core::cmp::{Eq, PartialEq};
|
|
|
|
#[repr(C)]
|
|
#[derive(Copy, Debug, Clone)]
|
|
pub struct DeviceStandardColorSpaces {
|
|
pub srgb: Ptr<RGBColorSpace>,
|
|
pub dci_p3: Ptr<RGBColorSpace>,
|
|
pub rec2020: Ptr<RGBColorSpace>,
|
|
pub aces2065_1: Ptr<RGBColorSpace>,
|
|
}
|
|
|
|
impl DeviceStandardColorSpaces {
|
|
#[cfg(not(target_arch = "nvptx64"))]
|
|
pub fn get_named(&self, name: &str) -> Option<Ptr<RGBColorSpace>> {
|
|
let lower = name.as_bytes();
|
|
match lower {
|
|
b if b.eq_ignore_ascii_case(b"srgb") => Some(self.srgb),
|
|
b if b.eq_ignore_ascii_case(b"dci-p3") => Some(self.dci_p3),
|
|
b if b.eq_ignore_ascii_case(b"rec2020") => Some(self.rec2020),
|
|
b if b.eq_ignore_ascii_case(b"aces2065-1") => Some(self.aces2065_1),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn get_by_id(&self, id: ColorSpaceId) -> Ptr<RGBColorSpace> {
|
|
match id {
|
|
ColorSpaceId::SRGB => self.srgb,
|
|
ColorSpaceId::DciP3 => self.dci_p3,
|
|
ColorSpaceId::Rec2020 => self.rec2020,
|
|
ColorSpaceId::Aces2065_1 => self.aces2065_1,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(u8)]
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
pub enum ColorSpaceId {
|
|
SRGB = 0,
|
|
DciP3 = 1,
|
|
Rec2020 = 2,
|
|
Aces2065_1 = 3,
|
|
}
|
|
|
|
impl ColorSpaceId {
|
|
#[cfg(not(target_arch = "nvptx64"))]
|
|
pub fn from_name(name: &str) -> Option<Self> {
|
|
let lower = name.as_bytes();
|
|
match lower {
|
|
b if b.eq_ignore_ascii_case(b"srgb") => Some(Self::SRGB),
|
|
b if b.eq_ignore_ascii_case(b"dci-p3") => Some(Self::DciP3),
|
|
b if b.eq_ignore_ascii_case(b"rec2020") => Some(Self::Rec2020),
|
|
b if b.eq_ignore_ascii_case(b"aces2065-1") => Some(Self::Aces2065_1),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct RGBColorSpace {
|
|
pub r: Point2f,
|
|
pub g: Point2f,
|
|
pub b: Point2f,
|
|
pub w: Point2f,
|
|
pub xyz_from_rgb: SquareMatrix3f,
|
|
pub rgb_from_xyz: SquareMatrix3f,
|
|
pub illuminant: Ptr<DenselySampledSpectrum>,
|
|
pub rgb_to_spectrum_table: Ptr<RGBToSpectrumTable>,
|
|
}
|
|
|
|
|
|
impl RGBColorSpace {
|
|
pub fn to_xyz(&self, rgb: RGB) -> XYZ {
|
|
self.xyz_from_rgb * rgb
|
|
}
|
|
|
|
pub fn to_rgb(&self, xyz: XYZ) -> RGB {
|
|
self.rgb_from_xyz * xyz
|
|
}
|
|
|
|
pub fn to_rgb_coeffs(&self, rgb: RGB) -> RGBSigmoidPolynomial {
|
|
self.rgb_to_spectrum_table.evaluate(rgb)
|
|
}
|
|
|
|
pub fn convert_colorspace(&self, other: &RGBColorSpace) -> SquareMatrix3f {
|
|
if self == other {
|
|
return SquareMatrix3f::default();
|
|
}
|
|
|
|
self.rgb_from_xyz * other.xyz_from_rgb
|
|
}
|
|
|
|
pub fn luminance_vector(&self) -> RGB {
|
|
RGB::new(
|
|
self.xyz_from_rgb[1][0],
|
|
self.xyz_from_rgb[1][1],
|
|
self.xyz_from_rgb[1][2],
|
|
)
|
|
}
|
|
}
|
|
|
|
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
|
|
&& self.rgb_to_spectrum_table == other.rgb_to_spectrum_table
|
|
}
|
|
}
|