skia_safe/encode_/
jpeg_encoder.rs1use crate::{
2 interop::RustWStream, prelude::*, ColorSpace, Data, EncodedOrigin, Pixmap, YUVAPixmaps,
3};
4use skia_bindings::{SkJpegEncoder_AlphaOption, SkJpegEncoder_Downsample};
5use std::io;
6
7pub type AlphaOption = SkJpegEncoder_AlphaOption;
8variant_name!(AlphaOption::BlendOnBlack);
9
10#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
11pub enum Downsample {
12 BothDirections,
13 Horizontal,
14 No,
15}
16
17impl Downsample {
18 fn native(&self) -> SkJpegEncoder_Downsample {
19 match self {
20 Downsample::BothDirections => SkJpegEncoder_Downsample::k420,
21 Downsample::Horizontal => SkJpegEncoder_Downsample::k422,
22 Downsample::No => SkJpegEncoder_Downsample::k444,
23 }
24 }
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct Options {
29 pub quality: u32,
30 pub downsample: Downsample,
31 pub alpha_option: AlphaOption,
32 pub xmp_metadata: Option<String>,
33 pub origin: Option<EncodedOrigin>,
34}
35
36impl Default for Options {
37 fn default() -> Self {
38 Self {
39 quality: 100,
40 downsample: Downsample::BothDirections,
41 alpha_option: AlphaOption::Ignore,
42 xmp_metadata: None,
43 origin: None,
44 }
45 }
46}
47
48pub fn encode<W: io::Write>(pixmap: &Pixmap, writer: &mut W, options: &Options) -> bool {
49 let xml_metadata = options.xmp_metadata.as_ref().map(Data::new_str);
50 let mut stream = RustWStream::new(writer);
51
52 unsafe {
53 skia_bindings::C_SkJpegEncoder_Encode(
54 stream.stream_mut(),
55 pixmap.native(),
56 options.quality as _,
57 options.downsample.native(),
58 options.alpha_option,
59 xml_metadata.as_ref().native_ptr_or_null(),
60 options.origin.as_ref().native_ptr_or_null(),
61 )
62 }
63}
64
65pub fn encode_yuva_pixmaps<W: io::Write>(
66 writer: &mut W,
67 src: &YUVAPixmaps,
68 src_color_space: Option<&ColorSpace>,
69 options: &Options,
70) -> bool {
71 let xmp_metadata = options.xmp_metadata.as_ref().map(Data::new_str);
72 let mut stream = RustWStream::new(writer);
73
74 unsafe {
75 skia_bindings::C_SkJpegEncoder_EncodeYUVAPixmaps(
76 stream.stream_mut(),
77 src.native(),
78 src_color_space.native_ptr_or_null(),
79 options.quality as _,
80 options.downsample.native(),
81 options.alpha_option,
82 xmp_metadata.as_ref().native_ptr_or_null(),
83 options.origin.as_ref().native_ptr_or_null(),
84 )
85 }
86}
87
88pub fn encode_pixmap(src: &Pixmap, options: &Options) -> Option<crate::Data> {
89 let xmp_metadata = options.xmp_metadata.as_ref().map(Data::new_str);
90
91 Data::from_ptr(unsafe {
92 skia_bindings::C_SkJpegEncoder_EncodePixmap(
93 src.native(),
94 options.quality as _,
95 options.downsample.native(),
96 options.alpha_option,
97 xmp_metadata.as_ref().native_ptr_or_null(),
98 options.origin.as_ref().native_ptr_or_null(),
99 )
100 })
101}
102
103pub fn encode_image<'a>(
104 context: impl Into<Option<&'a mut crate::gpu::DirectContext>>,
105 img: &crate::Image,
106 options: &Options,
107) -> Option<crate::Data> {
108 let xmp_metadata = options.xmp_metadata.as_ref().map(Data::new_str);
109
110 Data::from_ptr(unsafe {
111 skia_bindings::C_SkJpegEncoder_EncodeImage(
112 context.into().native_ptr_or_null_mut(),
113 img.native(),
114 options.quality as _,
115 options.downsample.native(),
116 options.alpha_option,
117 xmp_metadata.as_ref().native_ptr_or_null(),
118 options.origin.as_ref().native_ptr_or_null(),
119 )
120 })
121}
122
123