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}