zune_core/options/
encoder.rs

1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software;
5 *
6 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7 */
8
9use crate::bit_depth::BitDepth;
10use crate::colorspace::ColorSpace;
11
12/// Encoder options that are flags
13#[derive(Copy, Debug, Clone, Default)]
14struct EncoderFlags {
15    /// Whether JPEG images should be encoded as progressive images
16    jpeg_encode_progressive: bool,
17    /// Whether JPEG images should use optimized huffman tables
18    jpeg_optimize_huffman:   bool,
19    /// Whether to not preserve metadata across image transformations
20    image_strip_metadata:    bool
21}
22
23/// Options shared by some of the encoders in
24/// the `zune-` family of image crates
25#[derive(Debug, Copy, Clone)]
26pub struct EncoderOptions {
27    width:       usize,
28    height:      usize,
29    colorspace:  ColorSpace,
30    quality:     u8,
31    depth:       BitDepth,
32    num_threads: u8,
33    effort:      u8,
34    flags:       EncoderFlags
35}
36
37impl Default for EncoderOptions {
38    fn default() -> Self {
39        Self {
40            width:       0,
41            height:      0,
42            colorspace:  ColorSpace::RGB,
43            quality:     80,
44            depth:       BitDepth::Eight,
45            num_threads: 4,
46            effort:      4,
47            flags:       EncoderFlags::default()
48        }
49    }
50}
51
52impl EncoderOptions {
53    ///  Create  new encode options
54    ///
55    /// # Arguments
56    ///  
57    /// * `width`: Image width
58    /// * `height`: Image height
59    /// * `colorspace`:  Image colorspaces
60    /// * `depth`: Image depth
61    ///
62    /// returns: EncoderOptions
63    ///
64    pub fn new(
65        width: usize, height: usize, colorspace: ColorSpace, depth: BitDepth
66    ) -> EncoderOptions {
67        EncoderOptions {
68            width,
69            height,
70            colorspace,
71            depth,
72            ..Default::default()
73        }
74    }
75    /// Get the width for which the image will be encoded in
76    pub const fn get_width(&self) -> usize {
77        self.width
78    }
79
80    /// Get height for which the image will be encoded in
81    ///
82    /// returns: usize
83    ///
84    /// # Panics
85    /// If height is zero
86    pub fn get_height(&self) -> usize {
87        assert_ne!(self.height, 0);
88        self.height
89    }
90    /// Get the depth for which the image will be encoded in
91    pub const fn get_depth(&self) -> BitDepth {
92        self.depth
93    }
94    /// Get the quality for which the image will be encoded with
95    ///
96    ///  # Lossy
97    /// - Higher quality means some images take longer to write and
98    /// are big but they look good
99    ///
100    /// - Lower quality means small images and low quality.
101    ///
102    /// # Lossless
103    /// - High quality indicates more time is spent in making the file
104    /// smaller
105    ///
106    /// - Low quality indicates less time is spent in making the file bigger
107    pub const fn get_quality(&self) -> u8 {
108        self.quality
109    }
110    /// Get the colorspace for which the image will be encoded in
111    pub const fn get_colorspace(&self) -> ColorSpace {
112        self.colorspace
113    }
114    pub const fn get_effort(&self) -> u8 {
115        self.effort
116    }
117
118    /// Set width for the image to be encoded
119    pub fn set_width(mut self, width: usize) -> Self {
120        self.width = width;
121        self
122    }
123
124    /// Set height for the image to be encoded
125    pub fn set_height(mut self, height: usize) -> Self {
126        self.height = height;
127        self
128    }
129    /// Set depth for the image to be encoded
130    pub fn set_depth(mut self, depth: BitDepth) -> Self {
131        self.depth = depth;
132        self
133    }
134    /// Set quality of the image to be encoded
135    ///
136    /// Quality is clamped from 0..100
137    ///
138    /// Quality means different options depending on the encoder, see
139    /// [get_quality](Self::get_quality)
140    pub fn set_quality(mut self, quality: u8) -> Self {
141        self.quality = quality.clamp(0, 100);
142        self
143    }
144    /// Set colorspace for the image to be encoded
145    pub fn set_colorspace(mut self, colorspace: ColorSpace) -> Self {
146        self.colorspace = colorspace;
147        self
148    }
149    /// Set the number of threads allowed for multithreaded encoding
150    /// where supported
151    ///
152    /// Zero means use a single thread
153    pub fn set_num_threads(mut self, threads: u8) -> Self {
154        self.num_threads = threads;
155
156        self
157    }
158    pub fn set_effort(mut self, effort: u8) -> Self {
159        self.effort = effort;
160        self
161    }
162
163    /// Return number of threads configured for multithreading
164    /// where possible
165    ///
166    /// This is used for multi-threaded encoders,
167    /// currently only jpeg-xl
168    pub const fn get_num_threads(&self) -> u8 {
169        self.num_threads
170    }
171
172    /// Set whether the encoder should remove metadata from the image
173    ///
174    /// When set to `true`, supported encoders will strip away metadata
175    /// from the resulting image. If set to false, where supported, encoders
176    /// will not remove metadata from images
177    pub fn set_strip_metadata(mut self, yes: bool) -> Self {
178        self.flags.image_strip_metadata = yes;
179        self
180    }
181    /// Whether or not the encoder should remove metadata from the image
182    ///
183    /// The default value is false, and encoders that respect this try to preserve as much
184    /// data as possible from one image to another
185    pub const fn strip_metadata(&self) -> bool {
186        !self.flags.image_strip_metadata
187    }
188}
189
190/// JPEG options
191impl EncoderOptions {
192    /// Whether the jpeg encoder should encode the image in progressive mode
193    ///
194    /// Default is `false`.
195    ///
196    /// This may be used to create slightly smaller images at the cost of more processing
197    /// time
198    pub const fn jpeg_encode_progressive(&self) -> bool {
199        self.flags.jpeg_encode_progressive
200    }
201
202    /// Whether the jpeg encoder should optimize huffman tables to create smaller files
203    /// at the cost of processing time
204    ///
205    /// Default is `false`.
206    pub const fn jpeg_optimized_huffman_tables(&self) -> bool {
207        self.flags.jpeg_optimize_huffman
208    }
209
210    /// Set whether the jpeg encoder should encode the imagei in progressive mode
211    ///
212    /// Default is `false`
213    pub fn set_jpeg_encode_progressive(mut self, yes: bool) -> Self {
214        self.flags.jpeg_optimize_huffman = yes;
215        self
216    }
217}