pub mod allocation;
pub mod cdl;
pub mod exponent;
pub mod exposure_contrast;
pub mod fixed_function;
pub mod gamma;
pub mod grading_hue_curve;
pub mod grading_primary;
pub mod grading_rgb_curve;
pub mod grading_tone;
pub mod log;
pub mod lut1d;
pub mod lut3d;
pub mod matrix;
pub mod noop;
pub mod range;
pub(crate) mod sse;
#[path = "cdl/gpu.rs"]
pub(crate) mod cdl_gpu;
pub(crate) mod exponent_gpu;
#[path = "exposure_contrast/gpu.rs"]
pub(crate) mod exposure_contrast_gpu;
#[path = "fixed_function/gpu.rs"]
pub(crate) mod fixed_function_gpu;
#[path = "gamma/gpu.rs"]
pub(crate) mod gamma_gpu;
pub(crate) mod grading_hue_curve_gpu;
pub(crate) mod grading_primary_gpu;
pub(crate) mod grading_rgb_curve_gpu;
pub(crate) mod grading_tone_gpu;
#[path = "log/gpu.rs"]
pub(crate) mod log_gpu;
#[path = "lut1d/gpu.rs"]
pub(crate) mod lut1d_gpu;
#[path = "lut3d/gpu.rs"]
pub(crate) mod lut3d_gpu;
#[path = "matrix/gpu.rs"]
pub(crate) mod matrix_gpu;
pub(crate) mod range_gpu;
use crate::dynamic_property::DynamicProperty;
use crate::transforms::Transform;
use crate::types::{DynamicPropertyType, OptimizationFlags};
use std::any::Any;
use std::fmt::Debug;
use std::sync::Arc;
pub type OpRc = Arc<dyn Op>;
pub type OpVec = Vec<OpRc>;
pub type Pixel = [f32; 4];
pub trait Op: Debug + Send + Sync + Any {
fn name(&self) -> &'static str;
fn apply(&self, pixels: &mut [Pixel]);
fn is_no_op(&self) -> bool {
false
}
fn is_no_op_type(&self) -> bool {
false
}
fn is_identity(&self) -> bool {
self.is_no_op()
}
fn has_channel_crosstalk(&self) -> bool {
true
}
fn cache_id(&self) -> String;
fn as_any(&self) -> &dyn Any;
fn combine_with(&self, _next: &dyn Op, _flags: OptimizationFlags) -> Option<OpVec> {
None
}
fn simplify(&self, _flags: OptimizationFlags) -> Option<OpVec> {
None
}
fn is_dynamic(&self) -> bool {
false
}
fn dynamic_property(&self, _ty: DynamicPropertyType) -> Option<DynamicProperty> {
None
}
fn replace_dynamic_property(&mut self, _prop: &DynamicProperty) {}
fn make_non_dynamic(&self) -> Option<OpRc> {
None
}
fn to_transform(&self) -> Option<Transform> {
None
}
fn finalize(&self) -> Option<OpRc> {
None
}
fn cpu_op(&self, _fast_log_exp_pow: bool) -> Option<OpRc> {
None
}
fn clone_box(&self) -> Box<dyn Op>;
fn extract_gpu_shader_info(
&self,
shader_creator: &mut dyn crate::gpu::GpuShaderCreator,
) -> crate::error::Result<()> {
crate::gpu::default_extract_gpu_shader_info(self.as_any(), shader_creator)
}
}
impl dyn Op {
pub fn downcast_ref<T: Op>(&self) -> Option<&T> {
self.as_any().downcast_ref::<T>()
}
}
pub fn ops_cache_id(ops: &[OpRc]) -> String {
let mut s = String::new();
for op in ops {
s.push_str(&op.cache_id());
s.push(' ');
}
s
}
pub fn ops_are_no_op(ops: &[OpRc]) -> bool {
ops.iter().all(|o| o.is_no_op())
}
pub fn apply_ops(ops: &[OpRc], pixels: &mut [Pixel]) {
for op in ops {
op.apply(pixels);
}
}
pub fn hash_f32(values: &[f32]) -> String {
let mut bytes = Vec::with_capacity(values.len() * 4);
for v in values {
bytes.extend_from_slice(&v.to_le_bytes());
}
format!("{:x}", md5::compute(&bytes))
}
pub fn hash_f64(values: &[f64]) -> String {
let mut bytes = Vec::with_capacity(values.len() * 8);
for v in values {
bytes.extend_from_slice(&v.to_le_bytes());
}
format!("{:x}", md5::compute(&bytes))
}