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 115 116 117 118 119 120
use super::*; extern crate lcms2_sys as ffi; use std; impl ToneCurve { pub fn new(gamma: f64) -> ToneCurve { Self::new_handle(unsafe { ffi::cmsBuildGamma(std::ptr::null_mut(), gamma) }) } pub fn new_tabulated(values: &[u16]) -> ToneCurve { assert!(values.len() < std::i32::MAX as usize); Self::new_handle(unsafe { ffi::cmsBuildTabulatedToneCurve16(std::ptr::null_mut(), values.len() as i32, values.as_ptr()) }) } pub fn new_tabulated_float(values: &[f32]) -> ToneCurve { assert!(values.len() < std::i32::MAX as usize); Self::new_handle(unsafe { ffi::cmsBuildTabulatedToneCurveFloat(std::ptr::null_mut(), values.len() as u32, values.as_ptr()) }) } fn new_handle(handle: *mut ffi::ToneCurve) -> ToneCurve { assert!(!handle.is_null()); ToneCurve { handle: handle } } pub fn reversed(&self) -> ToneCurve { Self::new_handle(unsafe { ffi::cmsReverseToneCurve(self.handle) }) } pub fn is_multisegment(&self) -> bool { unsafe { ffi::cmsIsToneCurveMultisegment(self.handle) != 0 } } pub fn is_linear(&self) -> bool { unsafe { ffi::cmsIsToneCurveLinear(self.handle) != 0 } } pub fn is_monotonic(&self) -> bool { unsafe { ffi::cmsIsToneCurveMonotonic(self.handle) != 0 } } pub fn is_descending(&self) -> bool { unsafe { ffi::cmsIsToneCurveDescending(self.handle) != 0 } } pub fn parametric_type(&self) -> i32 { unsafe { ffi::cmsGetToneCurveParametricType(self.handle) } } pub fn estimated_gamma(&self, precision: f64) -> f64 { unsafe { ffi::cmsEstimateGamma(self.handle, precision) } } pub fn smooth(&mut self, lambda: f64) -> bool { unsafe { ffi::cmsSmoothToneCurve(self.handle, lambda) != 0 } } pub fn estimated_entries(&self) -> &[u16] { unsafe { let len = ffi::cmsGetToneCurveEstimatedTableEntries(self.handle) as usize; let data = ffi::cmsGetToneCurveEstimatedTable(self.handle); std::slice::from_raw_parts(data, len) } } } impl Clone for ToneCurve { fn clone(&self) -> ToneCurve { Self::new_handle(unsafe { ffi::cmsDupToneCurve(self.handle) }) } } impl Drop for ToneCurve { fn drop(&mut self) { unsafe { ffi::cmsFreeToneCurve(self.handle); } } } #[test] fn tones() { let g = ToneCurve::new(1./2.2); let mut z = g.clone(); assert!(!z.is_linear()); assert!(z.is_monotonic()); assert!(!z.is_descending()); assert!(z.reversed().is_monotonic()); assert!(z.smooth(0.5)); assert_eq!(0, g.estimated_entries()[0]); assert_eq!(std::u16::MAX, *g.estimated_entries().last().unwrap()); }