skia_safe/
encode_.rs

1use crate::{Bitmap, EncodedImageFormat, Pixmap};
2
3pub mod jpeg_encoder;
4pub mod png_encoder;
5#[cfg(feature = "webp-encode")]
6pub mod webp_encoder;
7
8impl Pixmap<'_> {
9    pub fn encode(
10        &self,
11        format: EncodedImageFormat,
12        quality: impl Into<Option<u32>>,
13    ) -> Option<Vec<u8>> {
14        crate::encode::pixmap(self, format, quality)
15    }
16}
17
18impl Bitmap {
19    pub fn encode(
20        &self,
21        format: EncodedImageFormat,
22        quality: impl Into<Option<u32>>,
23    ) -> Option<Vec<u8>> {
24        crate::encode::bitmap(self, format, quality)
25    }
26}
27
28impl crate::Image {
29    pub fn encode<'a>(
30        &self,
31        context: impl Into<Option<&'a mut crate::gpu::DirectContext>>,
32        format: EncodedImageFormat,
33        quality: impl Into<Option<u32>>,
34    ) -> Option<crate::Data> {
35        crate::encode::image(context, self, format, quality)
36    }
37}
38
39pub mod encode {
40    use super::{jpeg_encoder, png_encoder};
41    use crate::{Bitmap, EncodedImageFormat, Pixmap};
42
43    pub fn pixmap(
44        bitmap: &Pixmap,
45        format: EncodedImageFormat,
46        quality: impl Into<Option<u32>>,
47    ) -> Option<Vec<u8>> {
48        let mut data = Vec::new();
49        let quality = quality.into().unwrap_or(100).clamp(0, 100);
50        match format {
51            EncodedImageFormat::JPEG => {
52                let opts = jpeg_encoder::Options {
53                    quality,
54                    ..jpeg_encoder::Options::default()
55                };
56                jpeg_encoder::encode(bitmap, &mut data, &opts)
57            }
58            EncodedImageFormat::PNG => {
59                let opts = png_encoder::Options::default();
60                png_encoder::encode(bitmap, &mut data, &opts)
61            }
62            #[cfg(feature = "webp-encode")]
63            EncodedImageFormat::WEBP => {
64                use super::webp_encoder;
65                let mut opts = webp_encoder::Options::default();
66                if quality == 100 {
67                    opts.compression = webp_encoder::Compression::Lossless;
68                    opts.quality = 75.0;
69                } else {
70                    opts.compression = webp_encoder::Compression::Lossy;
71                    opts.quality = quality as _;
72                }
73                webp_encoder::encode(bitmap, &mut data, &opts)
74            }
75            _ => false,
76        }
77        .then_some(data)
78    }
79
80    pub fn bitmap(
81        bitmap: &Bitmap,
82        format: EncodedImageFormat,
83        quality: impl Into<Option<u32>>,
84    ) -> Option<Vec<u8>> {
85        let pixels = bitmap.peek_pixels()?;
86        pixmap(&pixels, format, quality)
87    }
88
89    pub fn image<'a>(
90        context: impl Into<Option<&'a mut crate::gpu::DirectContext>>,
91        image: &crate::Image,
92        image_format: EncodedImageFormat,
93        quality: impl Into<Option<u32>>,
94    ) -> Option<crate::Data> {
95        let quality = quality.into().unwrap_or(100).clamp(0, 100);
96        match image_format {
97            EncodedImageFormat::JPEG => {
98                let opts = jpeg_encoder::Options {
99                    quality,
100                    ..jpeg_encoder::Options::default()
101                };
102                jpeg_encoder::encode_image(context, image, &opts)
103            }
104            EncodedImageFormat::PNG => {
105                let opts = png_encoder::Options::default();
106                png_encoder::encode_image(context, image, &opts)
107            }
108            #[cfg(feature = "webp-encode")]
109            EncodedImageFormat::WEBP => {
110                use super::webp_encoder;
111                let mut opts = webp_encoder::Options::default();
112                if quality == 100 {
113                    opts.compression = webp_encoder::Compression::Lossless;
114                    opts.quality = 75.0;
115                } else {
116                    opts.compression = webp_encoder::Compression::Lossy;
117                    opts.quality = quality as _;
118                }
119                webp_encoder::encode_image(context, image, &opts)
120            }
121            _ => None,
122        }
123    }
124}