1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use super::*;
use eval::FloatOrU16;
use std::fmt;
use std::ptr;
use foreign_types::ForeignTypeRef;
use context::Context;
foreign_type! {
type CType = ffi::Stage;
fn drop = ffi::cmsStageFree;
pub struct Stage;
pub struct StageRef;
}
impl Stage {
pub fn new_identity(channels: u32) -> Stage {
unsafe {Error::if_null(
ffi::cmsStageAllocIdentity(GlobalContext::new().as_ptr(), channels)
)}.unwrap()
}
pub fn new_tone_curves(curves: &[&ToneCurveRef]) -> LCMSResult<Stage> {
let ptrs: Vec<_> = curves.iter().map(|c| c.as_ptr() as *const _).collect();
unsafe {Error::if_null(
ffi::cmsStageAllocToneCurves(GlobalContext::new().as_ptr(), ptrs.len() as u32, ptrs.as_ptr())
)}
}
pub fn new_matrix(matrix2d: &[f64], rows: usize, cols: usize, offsets: Option<&[f64]>) -> LCMSResult<Self> {
if matrix2d.len() < rows * cols {
return Err(Error::MissingData);
}
if let Some(offsets) = offsets {
if offsets.len() < cols {
return Err(Error::MissingData);
}
}
unsafe {Error::if_null(
ffi::cmsStageAllocMatrix(GlobalContext::new().as_ptr(), rows as u32, cols as u32, matrix2d.as_ptr(),
offsets.map(|p|p.as_ptr()).unwrap_or(ptr::null()))
)}
}
pub fn new_clut<Value: FloatOrU16>(grid_point_nodes: usize, input_channels: u32, output_channels: u32, table: Option<&[Value]>) -> LCMSResult<Self> {
if let Some(table) = table {
if table.len() < grid_point_nodes {
return Err(Error::MissingData)
}
}
unsafe {Error::if_null(
Value::stage_alloc_clut(GlobalContext::new().as_ptr(), grid_point_nodes as u32, input_channels, output_channels,
table.map(|p|p.as_ptr()).unwrap_or(ptr::null()))
)}
}
}
impl StageRef {
pub fn input_channels(&self) -> usize {
unsafe { ffi::cmsStageInputChannels(self.as_ptr()) as usize }
}
pub fn output_channels(&self) -> usize {
unsafe { ffi::cmsStageOutputChannels(self.as_ptr()) as usize }
}
pub fn stage_type(&self) -> ffi::StageSignature {
unsafe { ffi::cmsStageType(self.as_ptr()) }
}
}
pub struct StagesIter<'a>(pub Option<&'a StageRef>);
impl<'a> Iterator for StagesIter<'a> {
type Item = &'a StageRef;
fn next(&mut self) -> Option<Self::Item> {
let it = self.0;
if let Some(mpe) = it {
self.0 = unsafe {
let s = ffi::cmsStageNext(mpe.as_ptr());
if s.is_null() {
None
} else {
Some(ForeignTypeRef::from_ptr(s))
}
};
}
it
}
}
impl fmt::Debug for StageRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Stage({:?})", self.stage_type())
}
}