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