pic_scale/colors/
sigmoidal_scaler.rs1use crate::colors::common_splitter::{SplitPlanInterceptor, Splitter};
30use crate::plan::Resampling;
31use crate::validation::PicScaleError;
32use crate::{ImageSize, ImageStore, ImageStoreMut, ResamplingFunction, Scaler, ThreadingPolicy};
33use colorutils_rs::{
34 SRGB_TO_XYZ_D65, TransferFunction, XYZ_TO_SRGB_D65, rgb_to_sigmoidal, rgba_to_xyz_with_alpha,
35 sigmoidal_to_rgb, xyz_with_alpha_to_rgba,
36};
37use std::sync::Arc;
38
39#[derive(Debug, Copy, Clone)]
40pub struct SigmoidalScaler {
42 pub(crate) scaler: Scaler,
43}
44
45impl SigmoidalScaler {
46 pub fn new(filter: ResamplingFunction) -> Self {
47 SigmoidalScaler {
48 scaler: Scaler::new(filter),
49 }
50 }
51}
52
53struct SigmoidalRgbSplitter {}
54
55impl Splitter<u8, f32, 3> for SigmoidalRgbSplitter {
56 fn split(
57 &self,
58 from: &ImageStore<'_, u8, 3>,
59 into: &mut ImageStoreMut<'_, f32, 3>,
60 ) -> Result<(), PicScaleError> {
61 let mut dst_buffer = into.to_colorutils_buffer_mut();
62
63 rgb_to_sigmoidal(&from.to_colorutils_buffer(), &mut dst_buffer)
64 .map_err(|x| PicScaleError::Generic(x.to_string()))
65 }
66
67 fn merge(
68 &self,
69 from: &ImageStore<'_, f32, 3>,
70 into: &mut ImageStoreMut<'_, u8, 3>,
71 ) -> Result<(), PicScaleError> {
72 let mut dst_buffer = into.to_colorutils_buffer_mut();
73 sigmoidal_to_rgb(&from.to_colorutils_buffer(), &mut dst_buffer)
74 .map_err(|x| PicScaleError::Generic(x.to_string()))
75 }
76
77 fn bit_depth(&self) -> usize {
78 8
79 }
80}
81
82struct SigmoidalRgbaSplitter {}
83
84impl Splitter<u8, f32, 4> for SigmoidalRgbaSplitter {
85 fn split(
86 &self,
87 from: &ImageStore<'_, u8, 4>,
88 into: &mut ImageStoreMut<'_, f32, 4>,
89 ) -> Result<(), PicScaleError> {
90 let mut dst_buffer = into.to_colorutils_buffer_mut();
91 rgba_to_xyz_with_alpha(
92 &from.to_colorutils_buffer(),
93 &mut dst_buffer,
94 &SRGB_TO_XYZ_D65,
95 TransferFunction::Srgb,
96 )
97 .map_err(|x| PicScaleError::Generic(x.to_string()))
98 }
99
100 fn merge(
101 &self,
102 from: &ImageStore<'_, f32, 4>,
103 into: &mut ImageStoreMut<'_, u8, 4>,
104 ) -> Result<(), PicScaleError> {
105 let mut dst_buffer = into.to_colorutils_buffer_mut();
106 xyz_with_alpha_to_rgba(
107 &from.to_colorutils_buffer(),
108 &mut dst_buffer,
109 &XYZ_TO_SRGB_D65,
110 TransferFunction::Srgb,
111 )
112 .map_err(|x| PicScaleError::Generic(x.to_string()))
113 }
114
115 fn bit_depth(&self) -> usize {
116 8
117 }
118}
119
120impl SigmoidalScaler {
121 pub fn set_threading_policy(&mut self, threading_policy: ThreadingPolicy) -> Self {
122 self.scaler.set_threading_policy(threading_policy);
123 *self
124 }
125
126 pub fn plan_rgb_resampling(
127 &self,
128 source_size: ImageSize,
129 target_size: ImageSize,
130 ) -> Result<Arc<Resampling<u8, 3>>, PicScaleError> {
131 let intercept = self
132 .scaler
133 .plan_rgb_resampling_f32(source_size, target_size)?;
134 let scratch_size = intercept.scratch_size();
135 Ok(Arc::new(SplitPlanInterceptor {
136 intercept,
137 splitter: Arc::new(SigmoidalRgbSplitter {}),
138 inner_scratch: scratch_size,
139 }))
140 }
141
142 pub fn plan_rgba_resampling(
143 &self,
144 source_size: ImageSize,
145 target_size: ImageSize,
146 premultiply_alpha: bool,
147 ) -> Result<Arc<Resampling<u8, 4>>, PicScaleError> {
148 let intercept =
149 self.scaler
150 .plan_rgba_resampling_f32(source_size, target_size, premultiply_alpha)?;
151 let scratch_size = intercept.scratch_size();
152 Ok(Arc::new(SplitPlanInterceptor {
153 intercept,
154 splitter: Arc::new(SigmoidalRgbaSplitter {}),
155 inner_scratch: scratch_size,
156 }))
157 }
158}