Skip to main content

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}