pic_scale/scaler_f16.rs
1/*
2 * Copyright (c) Radzivon Bartoshyk. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#![forbid(unsafe_code)]
30use crate::image_store::ImageStoreMut;
31use crate::plan::Resampling;
32use crate::scaler::ScalingOptions;
33use crate::validation::PicScaleError;
34use crate::{
35 CbCrF16ImageStore, ImageSize, ImageStoreScaling, PlanarF16ImageStore, RgbF16ImageStore,
36 RgbaF16ImageStore, Scaler,
37};
38use core::f16;
39use std::sync::Arc;
40
41/// Implements `f16` type support
42#[cfg_attr(docsrs, doc(cfg(feature = "nightly_f16")))]
43impl Scaler {
44 /// Creates a resampling plan for a single-channel (planar/grayscale) `f16` image.
45 ///
46 /// The `f16` variant of [`plan_planar_resampling`], suitable for half-precision
47 /// grayscale content such as HDR render targets or compressed texture data.
48 /// Filter weights are accumulated in `f32` to avoid precision loss during convolution.
49 ///
50 /// # Arguments
51 ///
52 /// - `source_size` — Dimensions of the input image.
53 /// - `target_size` — Desired dimensions of the output image.
54 ///
55 /// # Example
56 ///
57 /// ```rust,no_run,ignore
58 /// let plan = scaler.plan_planar_resampling_f16(source_size, target_size)?;
59 /// plan.resample(&store, &mut target_store)?;
60 /// ```
61 pub fn plan_planar_resampling_f16(
62 &self,
63 source_size: ImageSize,
64 target_size: ImageSize,
65 ) -> Result<Arc<Resampling<f16, 1>>, PicScaleError> {
66 self.plan_generic_resize::<f16, f32, 1>(source_size, target_size, 8)
67 }
68
69 /// Creates a resampling plan for a two-channel chroma (`CbCr`) `f16` image.
70 ///
71 /// The `f16` variant of [`plan_cbcr_resampling`], intended for half-precision chroma
72 /// planes of YCbCr content. Both channels are treated as independent signals with no
73 /// alpha relationship. Filter weights are accumulated in `f32` to avoid precision
74 /// loss during convolution.
75 ///
76 /// # Arguments
77 ///
78 /// - `source_size` — Dimensions of the input chroma plane.
79 /// - `target_size` — Desired dimensions of the output chroma plane.
80 ///
81 /// # Example
82 ///
83 /// ```rust,no_run,ignore
84 /// let plan = scaler.plan_cbcr_resampling_f16(source_size, target_size)?;
85 /// plan.resample(&cbcr_store, &mut target_cbcr_store)?;
86 /// ```
87 pub fn plan_cbcr_resampling_f16(
88 &self,
89 source_size: ImageSize,
90 target_size: ImageSize,
91 ) -> Result<Arc<Resampling<f16, 2>>, PicScaleError> {
92 self.plan_generic_resize::<f16, f32, 2>(source_size, target_size, 8)
93 }
94
95 /// Creates a resampling plan for a three-channel RGB `f16` image.
96 ///
97 /// The `f16` variant of [`plan_rgb_resampling`], suitable for half-precision color
98 /// images such as HDR render targets or OpenEXR content. All three channels are
99 /// resampled independently with no alpha relationship. Filter weights are accumulated
100 /// in `f32` to avoid precision loss during convolution.
101 ///
102 /// # Arguments
103 ///
104 /// - `source_size` — Dimensions of the input image.
105 /// - `target_size` — Desired dimensions of the output image.
106 ///
107 /// # Example
108 ///
109 /// ```rust,no_run,ignore
110 /// let plan = scaler.plan_rgb_resampling_f16(source_size, target_size)?;
111 /// plan.resample(&store, &mut target_store)?;
112 /// ```
113 pub fn plan_rgb_resampling_f16(
114 &self,
115 source_size: ImageSize,
116 target_size: ImageSize,
117 ) -> Result<Arc<Resampling<f16, 3>>, PicScaleError> {
118 self.plan_generic_resize::<f16, f32, 3>(source_size, target_size, 8)
119 }
120
121 /// Creates a resampling plan for a four-channel RGBA `f16` image.
122 ///
123 /// The `f16` variant of [`plan_rgba_resampling`]. Alpha premultiplication is always
124 /// applied — RGB channels are pre-multiplied by alpha before resampling and
125 /// un-multiplied afterward — regardless of the `premultiply_alpha` flag.
126 ///
127 /// # Arguments
128 ///
129 /// - `source_size` — Dimensions of the input image.
130 /// - `target_size` — Desired dimensions of the output image.
131 /// - `premultiply_alpha` — Whether to premultiply alpha before resampling.
132 ///
133 /// # Example
134 ///
135 /// ```rust,no_run,ignore
136 /// let plan = scaler.plan_rgba_resampling_f16(source_size, target_size, true)?;
137 /// plan.resample(&store, &mut target_store)?;
138 /// ```
139 pub fn plan_rgba_resampling_f16(
140 &self,
141 source_size: ImageSize,
142 target_size: ImageSize,
143 premultiply_alpha: bool,
144 ) -> Result<Arc<Resampling<f16, 4>>, PicScaleError> {
145 self.plan_generic_resize_with_alpha::<f16, f32, 4>(
146 source_size,
147 target_size,
148 8,
149 premultiply_alpha,
150 )
151 }
152}
153
154#[cfg_attr(docsrs, doc(cfg(feature = "nightly_f16")))]
155impl<'b> ImageStoreScaling<'b, f16, 1> for PlanarF16ImageStore<'b> {
156 fn scale(
157 &self,
158 store: &mut ImageStoreMut<'b, f16, 1>,
159 options: ScalingOptions,
160 ) -> Result<(), PicScaleError> {
161 let mut scaler = Scaler::new(options.resampling_function);
162 scaler.set_threading_policy(options.threading_policy);
163 let plan = scaler.plan_generic_resize(self.size(), store.size(), store.bit_depth)?;
164 plan.resample(self, store)
165 }
166}
167
168#[cfg_attr(docsrs, doc(cfg(feature = "nightly_f16")))]
169impl<'b> ImageStoreScaling<'b, f16, 2> for CbCrF16ImageStore<'b> {
170 fn scale(
171 &self,
172 store: &mut ImageStoreMut<'b, f16, 2>,
173 options: ScalingOptions,
174 ) -> Result<(), PicScaleError> {
175 let mut scaler = Scaler::new(options.resampling_function);
176 scaler.set_threading_policy(options.threading_policy);
177 let plan = scaler.plan_generic_resize(self.size(), store.size(), store.bit_depth)?;
178 plan.resample(self, store)
179 }
180}
181
182#[cfg_attr(docsrs, doc(cfg(feature = "nightly_f16")))]
183impl<'b> ImageStoreScaling<'b, f16, 3> for RgbF16ImageStore<'b> {
184 fn scale(
185 &self,
186 store: &mut ImageStoreMut<'b, f16, 3>,
187 options: ScalingOptions,
188 ) -> Result<(), PicScaleError> {
189 let mut scaler = Scaler::new(options.resampling_function);
190 scaler.set_threading_policy(options.threading_policy);
191 let plan = scaler.plan_generic_resize(self.size(), store.size(), store.bit_depth)?;
192 plan.resample(self, store)
193 }
194}
195
196#[cfg_attr(docsrs, doc(cfg(feature = "nightly_f16")))]
197impl<'b> ImageStoreScaling<'b, f16, 4> for RgbaF16ImageStore<'b> {
198 fn scale(
199 &self,
200 store: &mut ImageStoreMut<'b, f16, 4>,
201 options: ScalingOptions,
202 ) -> Result<(), PicScaleError> {
203 let mut scaler = Scaler::new(options.resampling_function);
204 scaler.set_threading_policy(options.threading_policy);
205 let plan = scaler.plan_generic_resize_with_alpha(
206 self.size(),
207 store.size(),
208 store.bit_depth,
209 options.premultiply_alpha,
210 )?;
211 plan.resample(self, store)
212 }
213}