1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 #ifndef LIB_JXL_ENC_PARAMS_H_
7 #define LIB_JXL_ENC_PARAMS_H_
8
9 // Parameters and flags that govern JXL compression.
10
11 #include <stddef.h>
12 #include <stdint.h>
13
14 #include <string>
15
16 #include "lib/jxl/base/override.h"
17 #include "lib/jxl/butteraugli/butteraugli.h"
18 #include "lib/jxl/frame_header.h"
19 #include "lib/jxl/modular/options.h"
20
21 namespace jxl {
22
23 enum class SpeedTier {
24 // Turns on FindBestQuantizationHQ loop. Equivalent to "guetzli" mode.
25 kTortoise = 1,
26 // Turns on FindBestQuantization butteraugli loop.
27 kKitten = 2,
28 // Turns on dots, patches, and spline detection by default, as well as full
29 // context clustering. Default.
30 kSquirrel = 3,
31 // Turns on error diffusion and full AC strategy heuristics. Equivalent to
32 // "fast" mode.
33 kWombat = 4,
34 // Turns on gaborish by default, non-default cmap, initial quant field.
35 kHare = 5,
36 // Turns on simple heuristics for AC strategy, quant field, and clustering;
37 // also enables coefficient reordering.
38 kCheetah = 6,
39 // Turns off most encoder features. Does context clustering.
40 // Modular: uses fixed tree with Weighted predictor.
41 kFalcon = 7,
42 // Currently fastest possible setting for VarDCT.
43 // Modular: uses fixed tree with Gradient predictor.
44 kThunder = 8,
45 // VarDCT: same as kThunder.
46 // Modular: no tree, Gradient predictor, fast histograms
47 kLightning = 9
48 };
49
ParseSpeedTier(const std::string & s,SpeedTier * out)50 inline bool ParseSpeedTier(const std::string& s, SpeedTier* out) {
51 if (s == "lightning") {
52 *out = SpeedTier::kLightning;
53 return true;
54 } else if (s == "thunder") {
55 *out = SpeedTier::kThunder;
56 return true;
57 } else if (s == "falcon") {
58 *out = SpeedTier::kFalcon;
59 return true;
60 } else if (s == "cheetah") {
61 *out = SpeedTier::kCheetah;
62 return true;
63 } else if (s == "hare") {
64 *out = SpeedTier::kHare;
65 return true;
66 } else if (s == "fast" || s == "wombat") {
67 *out = SpeedTier::kWombat;
68 return true;
69 } else if (s == "squirrel") {
70 *out = SpeedTier::kSquirrel;
71 return true;
72 } else if (s == "kitten") {
73 *out = SpeedTier::kKitten;
74 return true;
75 } else if (s == "guetzli" || s == "tortoise") {
76 *out = SpeedTier::kTortoise;
77 return true;
78 }
79 size_t st = 10 - static_cast<size_t>(strtoull(s.c_str(), nullptr, 0));
80 if (st <= static_cast<size_t>(SpeedTier::kLightning) &&
81 st >= static_cast<size_t>(SpeedTier::kTortoise)) {
82 *out = SpeedTier(st);
83 return true;
84 }
85 return false;
86 }
87
SpeedTierName(SpeedTier speed_tier)88 inline const char* SpeedTierName(SpeedTier speed_tier) {
89 switch (speed_tier) {
90 case SpeedTier::kLightning:
91 return "lightning";
92 case SpeedTier::kThunder:
93 return "thunder";
94 case SpeedTier::kFalcon:
95 return "falcon";
96 case SpeedTier::kCheetah:
97 return "cheetah";
98 case SpeedTier::kHare:
99 return "hare";
100 case SpeedTier::kWombat:
101 return "wombat";
102 case SpeedTier::kSquirrel:
103 return "squirrel";
104 case SpeedTier::kKitten:
105 return "kitten";
106 case SpeedTier::kTortoise:
107 return "tortoise";
108 }
109 return "INVALID";
110 }
111
112 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
113 struct CompressParams {
114 float butteraugli_distance = 1.0f;
115 size_t target_size = 0;
116 float target_bitrate = 0.0f;
117
118 // 0.0 means search for the adaptive quantization map that matches the
119 // butteraugli distance, positive values mean quantize everywhere with that
120 // value.
121 float uniform_quant = 0.0f;
122 float quant_border_bias = 0.0f;
123
124 // Try to achieve a maximum pixel-by-pixel error on each channel.
125 bool max_error_mode = false;
126 float max_error[3] = {0.0, 0.0, 0.0};
127
128 SpeedTier speed_tier = SpeedTier::kSquirrel;
129
130 // 0 = default.
131 // 1 = slightly worse quality.
132 // 4 = fastest speed, lowest quality
133 // TODO(veluca): hook this up to the C API.
134 size_t decoding_speed_tier = 0;
135
136 int max_butteraugli_iters = 4;
137
138 int max_butteraugli_iters_guetzli_mode = 100;
139
140 ColorTransform color_transform = ColorTransform::kXYB;
141 YCbCrChromaSubsampling chroma_subsampling;
142
143 // If true, the "modular mode options" members below are used.
144 bool modular_mode = false;
145
146 // Change group size in modular mode (0=128, 1=256, 2=512, 3=1024).
147 size_t modular_group_size_shift = 1;
148
149 Override preview = Override::kDefault;
150 Override noise = Override::kDefault;
151 Override dots = Override::kDefault;
152 Override patches = Override::kDefault;
153 Override gaborish = Override::kDefault;
154 int epf = -1;
155
156 // Progressive mode.
157 bool progressive_mode = false;
158
159 // Quantized-progressive mode.
160 bool qprogressive_mode = false;
161
162 // Put center groups first in the bitstream.
163 bool centerfirst = false;
164
165 // Pixel coordinates of the center. First group will contain that center.
166 size_t center_x = static_cast<size_t>(-1);
167 size_t center_y = static_cast<size_t>(-1);
168
169 int progressive_dc = -1;
170
171 // If on: preserve color of invisible pixels (if off: don't care)
172 // Default: on for lossless, off for lossy
173 Override keep_invisible = Override::kDefault;
174
175 // Progressive-mode saliency.
176 //
177 // How many progressive saliency-encoding steps to perform.
178 // - 1: Encode only DC and lowest-frequency AC. Does not need a saliency-map.
179 // - 2: Encode only DC+LF, dropping all HF AC data.
180 // Does not need a saliency-map.
181 // - 3: Encode DC+LF+{salient HF}, dropping all non-salient HF data.
182 // - 4: Encode DC+LF+{salient HF}+{other HF}.
183 // - 5: Encode DC+LF+{quantized HF}+{low HF bits}.
184 size_t saliency_num_progressive_steps = 3;
185 // Every saliency-heatmap cell with saliency >= threshold will be considered
186 // as 'salient'. The default value of 0.0 will consider every AC-block
187 // as salient, hence not require a saliency-map, and not actually generate
188 // a 4th progressive step.
189 float saliency_threshold = 0.0f;
190 // Saliency-map (owned by caller).
191 ImageF* saliency_map = nullptr;
192
193 // Input and output file name. Will be used to provide pluggable saliency
194 // extractor with paths.
195 const char* file_in = nullptr;
196 const char* file_out = nullptr;
197
198 // Currently unused as of 2020-01.
199 bool clear_metadata = false;
200
201 // Prints extra information during/after encoding.
202 bool verbose = false;
203
204 ButteraugliParams ba_params;
205
206 // Force usage of CfL when doing JPEG recompression. This can have unexpected
207 // effects on the decoded pixels, while still being JPEG-compliant and
208 // allowing reconstruction of the original JPEG.
209 bool force_cfl_jpeg_recompression = true;
210
211 // Set the noise to what it would approximately be if shooting at the nominal
212 // exposure for a given ISO setting on a 35mm camera.
213 float photon_noise_iso = 0;
214
215 // modular mode options below
216 ModularOptions options;
217 int responsive = -1;
218 // A pair of <quality, cquality>.
219 std::pair<float, float> quality_pair{100.f, 100.f};
220 int colorspace = -1;
221 // Use Global channel palette if #colors < this percentage of range
222 float channel_colors_pre_transform_percent = 95.f;
223 // Use Local channel palette if #colors < this percentage of range
224 float channel_colors_percent = 80.f;
225 int palette_colors = 1 << 10; // up to 10-bit palette is probably worthwhile
226 bool lossy_palette = false;
227
228 // Returns whether these params are lossless as defined by SetLossless();
IsLosslessCompressParams229 bool IsLossless() const {
230 return modular_mode && quality_pair.first == 100 &&
231 quality_pair.second == 100 &&
232 color_transform == jxl::ColorTransform::kNone;
233 }
234
235 // Sets the parameters required to make the codec lossless.
SetLosslessCompressParams236 void SetLossless() {
237 modular_mode = true;
238 quality_pair.first = 100;
239 quality_pair.second = 100;
240 color_transform = jxl::ColorTransform::kNone;
241 }
242
243 bool use_new_heuristics = false;
244
245 // Down/upsample the image before encoding / after decoding by this factor.
246 // The resampling value can also be set to 0 to automatically choose based
247 // on distance, however EncodeFrame doesn't support this, so it is
248 // required to process the CompressParams to set a valid positive resampling
249 // value and altered butteraugli score if this is used.
250 size_t resampling = 1;
251 size_t ec_resampling = 1;
252 // Skip the downsampling before encoding if this is true.
253 bool already_downsampled = false;
254 };
255
256 static constexpr float kMinButteraugliForDynamicAR = 0.5f;
257 static constexpr float kMinButteraugliForDots = 3.0f;
258 static constexpr float kMinButteraugliToSubtractOriginalPatches = 3.0f;
259 static constexpr float kMinButteraugliDistanceForProgressiveDc = 4.5f;
260
261 // Always off
262 static constexpr float kMinButteraugliForNoise = 99.0f;
263
264 // Minimum butteraugli distance the encoder accepts.
265 static constexpr float kMinButteraugliDistance = 0.01f;
266
267 // Tile size for encoder-side processing. Must be equal to color tile dim in the
268 // current implementation.
269 static constexpr size_t kEncTileDim = 64;
270 static constexpr size_t kEncTileDimInBlocks = kEncTileDim / kBlockDim;
271
272 } // namespace jxl
273
274 #endif // LIB_JXL_ENC_PARAMS_H_
275