pbrt/shared/src/spectra/colorspace.rs

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