peniko/
image.rs

1// Copyright 2022 the Peniko Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4use super::{Blob, Extend};
5
6/// Defines the pixel format of an [image](Image).
7#[derive(Copy, Clone, PartialEq, Eq, Debug)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[non_exhaustive]
10#[repr(u8)]
11pub enum ImageFormat {
12    /// 32-bit RGBA with 8-bit channels.
13    Rgba8 = 0,
14    // NOTICE: If a new value is added, be sure to update the bytemuck CheckedBitPattern impl.
15}
16
17impl ImageFormat {
18    /// Returns the required size in bytes for an image in this format
19    /// of the given dimensions.
20    ///
21    /// A result of `None` indicates an overflow in the size calculation.
22    #[must_use]
23    pub fn size_in_bytes(self, width: u32, height: u32) -> Option<usize> {
24        match self {
25            Self::Rgba8 => 4_usize
26                .checked_mul(width as usize)
27                .and_then(|x| x.checked_mul(height as usize)),
28        }
29    }
30}
31
32/// Defines the desired quality for sampling an [image](Image).
33#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35#[repr(u8)]
36pub enum ImageQuality {
37    /// Lowest quality with best performance characteristics.
38    ///
39    /// This is typically nearest neighbor sampling.
40    Low = 0,
41    /// Medium quality with reasonable performance characteristics.
42    ///
43    /// This is typically bilinear sampling.
44    #[default]
45    Medium = 1,
46    /// Highest quality with worst performance characteristics.
47    ///
48    /// This is typically bicubic sampling.
49    High = 2,
50    // NOTICE: If a new value is added, be sure to update the bytemuck CheckedBitPattern impl.
51}
52
53/// Owned shareable image resource.
54#[derive(Clone, PartialEq, Debug)]
55#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
56pub struct Image {
57    /// Blob containing the image data.
58    pub data: Blob<u8>,
59    /// Pixel format of the image.
60    pub format: ImageFormat,
61    /// Width of the image.
62    pub width: u32,
63    /// Height of the image.
64    pub height: u32,
65    /// Extend mode in the horizontal direction.
66    pub x_extend: Extend,
67    /// Extend mode in the vertical direction.
68    pub y_extend: Extend,
69    /// Hint for desired rendering quality.
70    pub quality: ImageQuality,
71    /// An additional alpha multiplier to use with the image.
72    pub alpha: f32,
73}
74
75impl Image {
76    /// Creates a new image with the given data, [format](ImageFormat) and dimensions.
77    #[must_use]
78    pub fn new(data: Blob<u8>, format: ImageFormat, width: u32, height: u32) -> Self {
79        Self {
80            data,
81            format,
82            width,
83            height,
84            x_extend: Extend::Pad,
85            y_extend: Extend::Pad,
86            quality: ImageQuality::Medium,
87            // Opaque
88            alpha: 1.,
89        }
90    }
91
92    /// Builder method for setting the image [extend mode](Extend) in both
93    /// directions.
94    #[must_use]
95    pub fn with_extend(mut self, mode: Extend) -> Self {
96        self.x_extend = mode;
97        self.y_extend = mode;
98        self
99    }
100
101    /// Builder method for setting the image [extend mode](Extend) in the
102    /// horizontal direction.
103    #[must_use]
104    pub fn with_x_extend(mut self, mode: Extend) -> Self {
105        self.x_extend = mode;
106        self
107    }
108
109    /// Builder method for setting the image [extend mode](Extend) in the
110    /// vertical direction.
111    #[must_use]
112    pub fn with_y_extend(mut self, mode: Extend) -> Self {
113        self.y_extend = mode;
114        self
115    }
116
117    /// Builder method for setting a hint for the desired image [quality](ImageQuality)
118    /// when rendering.
119    #[must_use]
120    pub fn with_quality(mut self, quality: ImageQuality) -> Self {
121        self.quality = quality;
122        self
123    }
124
125    /// Returns the image with the alpha multiplier set to `alpha`.
126    #[must_use]
127    #[track_caller]
128    pub fn with_alpha(mut self, alpha: f32) -> Self {
129        debug_assert!(
130            alpha.is_finite() && alpha >= 0.0,
131            "A non-finite or negative alpha ({alpha}) is meaningless."
132        );
133        self.alpha = alpha;
134        self
135    }
136
137    /// Returns the image with the alpha multiplier multiplied again by `alpha`.
138    /// The behaviour of this transformation is undefined if `alpha` is negative.
139    #[must_use]
140    #[track_caller]
141    pub fn multiply_alpha(mut self, alpha: f32) -> Self {
142        debug_assert!(
143            alpha.is_finite() && alpha >= 0.0,
144            "A non-finite or negative alpha ({alpha}) is meaningless."
145        );
146        self.alpha *= alpha;
147        self
148    }
149}