1 /*****************************************************************************
2 
3         Dither.h
4         Author: Laurent de Soras, 2021
5 
6 --- Legal stuff ---
7 
8 This program is free software. It comes without any warranty, to
9 the extent permitted by applicable law. You can redistribute it
10 and/or modify it under the terms of the Do What The Fuck You Want
11 To Public License, Version 2, as published by Sam Hocevar. See
12 http://www.wtfpl.net/ for more details.
13 
14 *Tab=3***********************************************************************/
15 
16 
17 
18 #pragma once
19 #if ! defined (fmtcl_Dither_HEADER_INCLUDED)
20 #define fmtcl_Dither_HEADER_INCLUDED
21 
22 
23 
24 /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
25 
26 #include "conc/ObjPool.h"
27 #include "fmtcl/ColorFamily.h"
28 #include "fmtcl/BitBltConv.h"
29 #include "fmtcl/ErrDifBuf.h"
30 #include "fmtcl/ErrDifBufFactory.h"
31 #include "fmtcl/MatrixWrap.h"
32 #include "fmtcl/SplFmt.h"
33 #include "fstb/def.h"
34 #include "fstb/ArrayAlign.h"
35 
36 #if (fstb_ARCHI == fstb_ARCHI_X86)
37 	#include <emmintrin.h>
38 #endif // fstb_ARCHI_X86
39 
40 #include <array>
41 #include <memory>
42 #include <vector>
43 
44 
45 
46 namespace fmtcl
47 {
48 
49 
50 
51 class Dither
52 {
53 
54 /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
55 
56 public:
57 
58 	static constexpr int _max_nbr_planes = 4;
59 
60 	// Maximum width in pixels for the halftone patterns. Must be a power of 2.
61 	static constexpr int _pat_max_size   = 1024;
62 
63 	enum DMode
64 	{
65 		DMode_ROUND_ALIAS = -1,
66 		DMode_BAYER = 0,
67 		DMode_ROUND,      // 1
68 		DMode_FAST,       // 2
69 		DMode_FILTERLITE, // 3
70 		DMode_STUCKI,     // 4
71 		DMode_ATKINSON,   // 5
72 		DMode_FLOYD,      // 6
73 		DMode_OSTRO,      // 7
74 		DMode_VOIDCLUST,  // 8
75 		DMode_QUASIRND,   // 9
76 
77 		DMode_NBR_ELT,
78 
79 		DMode_VERY_LARGE = 0x12345678
80 	};
81 
82 	explicit       Dither (
83 		SplFmt src_fmt, int src_res, bool src_full_flag,
84 		SplFmt dst_fmt, int dst_res, bool dst_full_flag,
85 		ColorFamily color_fam, int nbr_planes, int w,
86 		DMode dmode, int pat_size, double ampo, double ampn,
87 		bool dyn_flag, bool static_noise_flag, bool correlated_planes_flag,
88 		bool tpdfo_flag, bool tpdfn_flag,
89 		bool sse2_flag, bool avx2_flag
90 	);
91 
92 	void           process_plane (uint8_t *dst_ptr, int dst_stride, const uint8_t *src_ptr, int src_stride, int w, int h, int frame_index, int plane_index);
93 
94 
95 
96 /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
97 
98 protected:
99 
100 
101 
102 /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
103 
104 private:
105 
106 	// Must be a power of 2 (because cycled with & as modulo)
107 	static constexpr int _pat_period    =     4;
108 
109 	// Minimum pattern size to execute operations, constrained by SIMD vector
110 	// sizes. Original pattern can be smaller. Must be a power of 2
111 	static constexpr int _pat_min_size  =     8;
112 
113 	// Bit depth of the amplitude fractionnal part. The whole thing is 7 bits,
114 	// and we need a few bits for the integer part.
115 	static constexpr int _amp_bits      =     5;
116 
117 	// Resolution (bits) of the temporary data for error diffusion when source
118 	// bitdepth is not high enough (relative to the destination bitdepth) to
119 	// guarantee an accurate error diffusion.
120 	static constexpr int _err_res       =    24;
121 
122 	// Maximum width (pixels) for variable formats
123 	static constexpr int _max_unk_width = 65536;
124 
125 	class SclInf
126 	{
127 	public:
128 		BitBltConv::ScaleInfo
129 		               _info;
130 		BitBltConv::ScaleInfo *   // 0 if _info is not used.
131 		               _ptr = 0;
132 	};
133 
134 	typedef int16_t PatDataType;
135 	typedef MatrixWrap <PatDataType> PatData;
136 	typedef std::array <PatData, _pat_period> PatDataArray;
137 
138 	class AmpInfo
139 	{
140 	public:
141 		int            _o_i = 0;   // [0 ;  127], 1.0 = 1 << _amp_bits
142 		int            _n_i = 0;   // [0 ;  127], 1.0 = 1 << _amp_bits
143 		int            _e_i = 0;   // [0 ; 2047], 1.0 = 256
144 		float          _e_f = 0;
145 		float          _n_f = 0;
146 	};
147 
148 	class SegContext
149 	{
150 	public:
151 		inline const PatDataType *
152 		               extract_pattern_row () const noexcept;
153 		const PatData* _pattern_ptr = nullptr; // Ordered dithering
154 		uint32_t       _rnd_state   = 0;       // Anything excepted fast mode
155 		const BitBltConv::ScaleInfo *          // Float processing
156 		               _scale_info_ptr = nullptr;
157 		ErrDifBuf *                            // Error diffusion
158 		               _ed_buf_ptr  = nullptr;
159 		int            _y           = -1;      // Ordered dithering and error diffusion
160 		uint32_t       _qrs_seed    = 0;       // For the quasirandom sequences
161 		AmpInfo        _amp;
162 	};
163 
164 	void           build_dither_pat ();
165 	void           build_dither_pat_round ();
166 	void           build_dither_pat_bayer ();
167 	void           build_dither_pat_void_and_cluster (bool aztec_flag);
168 	void           expand_dither_pat (const PatData &small);
169 	void           build_next_dither_pat ();
170 	void           copy_dither_pat_rotate (PatData &dst, const PatData &src, int angle) noexcept;
171 	void           init_fnc_fast () noexcept;
172 	void           init_fnc_ordered () noexcept;
173 	void           init_fnc_quasirandom () noexcept;
174 	void           init_fnc_errdiff () noexcept;
175 
176 	void           dither_plane (uint8_t *dst_ptr, int dst_stride, const uint8_t *src_ptr, int src_stride, int w, int h, const BitBltConv::ScaleInfo &scale_info, int frame_index, int plane_index);
177 
178 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
179 	static void    process_seg_fast_int_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &/*ctx*/) noexcept;
180 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE>
181 	static void    process_seg_fast_flt_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
182 
183 #if (fstb_ARCHI == fstb_ARCHI_X86)
184 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT, int SRC_BITS>
185 	static void    process_seg_fast_int_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &/*ctx*/) noexcept;
186 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT>
187 	static void    process_seg_fast_flt_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
188 #endif
189 
190 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
191 	static void    process_seg_ord_int_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
192 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE>
193 	static void    process_seg_ord_flt_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
194 
195 #if (fstb_ARCHI == fstb_ARCHI_X86)
196 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT, int SRC_BITS>
197 	static void    process_seg_ord_int_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
198 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT>
199 	static void    process_seg_ord_flt_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
200 #endif
201 
202 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
203 	static void    process_seg_qrs_int_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
204 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE>
205 	static void    process_seg_qrs_flt_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
206 
207 #if (fstb_ARCHI == fstb_ARCHI_X86)
208 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT, int SRC_BITS>
209 	static void    process_seg_qrs_int_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
210 	template <bool S_FLAG, bool TO_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT>
211 	static void    process_seg_qrs_flt_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
212 #endif
213 
214 	template <bool S_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS, typename DFNC>
215 	static fstb_FORCEINLINE void
216 	               process_seg_common_int_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx, DFNC dither_fnc) noexcept;
217 	template <bool S_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE, typename DFNC>
218 	static fstb_FORCEINLINE void
219 	               process_seg_common_flt_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx, DFNC dither_fnc) noexcept;
220 	template <bool T_FLAG>
221 	static fstb_FORCEINLINE int
222 	               generate_dith_n_scalar (uint32_t &rnd_state) noexcept;
223 	static fstb_FORCEINLINE int
224 	               remap_tpdf_scalar (int d) noexcept;
225 
226 #if (fstb_ARCHI == fstb_ARCHI_X86)
227 	template <bool S_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT, int SRC_BITS, typename DFNC>
228 	static fstb_FORCEINLINE void
229 	               process_seg_common_int_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx, DFNC dither_fnc) noexcept;
230 	template <bool S_FLAG, bool TN_FLAG, SplFmt DST_FMT, int DST_BITS, SplFmt SRC_FMT, typename DFNC>
231 	static fstb_FORCEINLINE void
232 	               process_seg_common_flt_int_sse2 (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx, DFNC dither_fnc) noexcept;
233 	template <bool T_FLAG>
234 	static fstb_FORCEINLINE __m128i
235 	               generate_dith_n_vec (uint32_t &rnd_state) noexcept;
236 	static fstb_FORCEINLINE __m128i
237 	               remap_tpdf_vec (__m128i d) noexcept;
238 #endif
239 
240 	template <bool S_FLAG, bool TN_FLAG, class ERRDIF>
241 	static void    process_seg_errdif_int_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
242 	template <bool S_FLAG, bool TN_FLAG, class ERRDIF>
243 	static void    process_seg_errdif_flt_int_cpp (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) noexcept;
244 
245 	static inline void
246 	               generate_rnd (uint32_t &state) noexcept;
247 	static inline void
248 	               generate_rnd_eol (uint32_t &state) noexcept;
249 
250 	template <bool S_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
251 	static inline void
252 	               quantize_pix_int (DST_TYPE * fstb_RESTRICT dst_ptr, const SRC_TYPE * fstb_RESTRICT src_ptr, SRC_TYPE &src_raw, int x, int & fstb_RESTRICT err, uint32_t &rnd_state, int ampe_i, int ampn_i) noexcept;
253 	template <bool S_FLAG, bool TN_FLAG, class DST_TYPE, int DST_BITS, class SRC_TYPE>
254 	static inline void
255 	               quantize_pix_flt (DST_TYPE * fstb_RESTRICT dst_ptr, const SRC_TYPE * fstb_RESTRICT src_ptr, SRC_TYPE &src_raw, int x, float & fstb_RESTRICT err, uint32_t &rnd_state, float ampe_f, float ampn_f, float mul, float add) noexcept;
256 
257 	template <class DT, int DB, class ST, int SB, int EL>
258 	class ErrDifAddParam
259 	{
260 	public:
261 		typedef DT DstType;
262 		typedef ST SrcType;
263 		static constexpr int _dst_bits      = DB;
264 		static constexpr int _src_bits      = SB;
265 		static constexpr int _nbr_err_lines = EL;
266 	};
267 
268 	template <class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
269 	class DiffuseFloydSteinberg
270 	:	public ErrDifAddParam <DST_TYPE, DST_BITS, SRC_TYPE, SRC_BITS, 1>
271 	{
272 	public:
273 		template <int DIR>
274 		static fstb_FORCEINLINE void
275 		               diffuse (int err, int & fstb_RESTRICT err_nxt0, int & fstb_RESTRICT err_nxt1, int16_t * fstb_RESTRICT err0_ptr, int16_t * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
276 		template <int DIR>
277 		static fstb_FORCEINLINE void
278 		               diffuse (float err, float & fstb_RESTRICT err_nxt0, float & fstb_RESTRICT err_nxt1, float * fstb_RESTRICT err0_ptr, float * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
279 		template <typename EB>
280 		static fstb_FORCEINLINE void
281 		               prepare_next_line (EB * fstb_RESTRICT err_ptr) noexcept;
282 	private:
283 		template <int DIR, typename ET, typename EB>
284 		static fstb_FORCEINLINE void
285 		               spread_error (ET e1, ET e3, ET e5, ET e7, ET & fstb_RESTRICT err_nxt0, EB * fstb_RESTRICT err0_ptr) noexcept;
286 	};
287 
288 	template <class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
289 	class DiffuseFilterLite
290 	:	public ErrDifAddParam <DST_TYPE, DST_BITS, SRC_TYPE, SRC_BITS, 1>
291 	{
292 	public:
293 		template <int DIR>
294 		static fstb_FORCEINLINE void
295 		               diffuse (int err, int & fstb_RESTRICT err_nxt0, int & fstb_RESTRICT err_nxt1, int16_t * fstb_RESTRICT err0_ptr, int16_t * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
296 		template <int DIR>
297 		static fstb_FORCEINLINE void
298 		               diffuse (float err, float & fstb_RESTRICT err_nxt0, float & fstb_RESTRICT err_nxt1, float * fstb_RESTRICT err0_ptr, float * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
299 		template <typename EB>
300 		static fstb_FORCEINLINE void
301 		               prepare_next_line (EB * fstb_RESTRICT err_ptr) noexcept;
302 	private:
303 		template <int DIR, typename ET, typename EB>
304 		static fstb_FORCEINLINE void
305 		               spread_error (ET e1, ET e2, ET & fstb_RESTRICT err_nxt0, EB * fstb_RESTRICT err0_ptr) noexcept;
306 	};
307 
308 	template <class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
309 	class DiffuseStucki
310 	:	public ErrDifAddParam <DST_TYPE, DST_BITS, SRC_TYPE, SRC_BITS, 2>
311 	{
312 	public:
313 		template <int DIR>
314 		static fstb_FORCEINLINE void
315 		               diffuse (int err, int & fstb_RESTRICT err_nxt0, int & fstb_RESTRICT err_nxt1, int16_t * fstb_RESTRICT err0_ptr, int16_t * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
316 		template <int DIR>
317 		static fstb_FORCEINLINE void
318 		               diffuse (float err, float & fstb_RESTRICT err_nxt0, float & fstb_RESTRICT err_nxt1, float * fstb_RESTRICT err0_ptr, float * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
319 		template <typename EB>
320 		static fstb_FORCEINLINE void
321 		               prepare_next_line (EB * fstb_RESTRICT err_ptr) noexcept;
322 	private:
323 		template <int DIR, typename ET, typename EB>
324 		static fstb_FORCEINLINE void
325 		               spread_error (ET e1, ET e2, ET e4, ET e8, ET & fstb_RESTRICT err_nxt0, ET & fstb_RESTRICT err_nxt1, EB * fstb_RESTRICT err0_ptr, EB * fstb_RESTRICT err1_ptr) noexcept;
326 	};
327 
328 	template <class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
329 	class DiffuseAtkinson
330 	:	public ErrDifAddParam <DST_TYPE, DST_BITS, SRC_TYPE, SRC_BITS, 2>
331 	{
332 	public:
333 		template <int DIR>
334 		static fstb_FORCEINLINE void
335 		               diffuse (int err, int & fstb_RESTRICT err_nxt0, int & fstb_RESTRICT err_nxt1, int16_t * fstb_RESTRICT err0_ptr, int16_t * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
336 		template <int DIR>
337 		static fstb_FORCEINLINE void
338 		               diffuse (float err, float & fstb_RESTRICT err_nxt0, float & fstb_RESTRICT err_nxt1, float * fstb_RESTRICT err0_ptr, float * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
339 		template <typename EB>
340 		static fstb_FORCEINLINE void
341 		               prepare_next_line (EB * fstb_RESTRICT err_ptr) noexcept;
342 	private:
343 		template <int DIR, typename ET, typename EB>
344 		static fstb_FORCEINLINE void
345 		               spread_error (ET e1, ET & fstb_RESTRICT err_nxt0, ET & fstb_RESTRICT err_nxt1, EB * fstb_RESTRICT err0_ptr, EB * fstb_RESTRICT err1_ptr) noexcept;
346 	};
347 
348 	class DiffuseOstromoukhovBase
349 	{
350 	public:
351 		struct TableEntry
352 		{
353 			int            _c0;
354 			int            _c1;
355 			int            _c2;        // Actually not used
356 			int            _sum;
357 			float          _inv_sum;   // Possible optimization: store 1/_c0 and 1/_c1 instead of this field.
358 		};
359 
360 		static constexpr int _t_bits = 8;
361 		static constexpr int _t_len  = 1 << _t_bits;
362 		static constexpr int _t_mask = _t_len - 1;
363 
364 		static const std::array <TableEntry, _t_len>
365 		               _table;
366 	};
367 
368 	template <int DST_BITS, int SRC_BITS>
369 	class DiffuseOstromoukhovBase2
370 	:	public DiffuseOstromoukhovBase
371 	{
372 	public:
373 		template <class SRC_TYPE>
374 		static inline int
375 		               get_index (SRC_TYPE src_raw) noexcept;
376 		static inline int
377 		               get_index (float src_raw) noexcept;
378 	};
379 
380 	template <class DST_TYPE, int DST_BITS, class SRC_TYPE, int SRC_BITS>
381 	class DiffuseOstromoukhov
382 	:	public ErrDifAddParam <DST_TYPE, DST_BITS, SRC_TYPE, SRC_BITS, 1>
383 	,	public DiffuseOstromoukhovBase2 <DST_BITS, SRC_BITS>
384 	{
385 	public:
386 		typedef DiffuseOstromoukhov <DST_TYPE, DST_BITS, SRC_TYPE, SRC_BITS> ThisType;
387 		template <int DIR>
388 		static fstb_FORCEINLINE void
389 		               diffuse (int err, int & fstb_RESTRICT err_nxt0, int & fstb_RESTRICT err_nxt1, int16_t * fstb_RESTRICT err0_ptr, int16_t * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
390 		template <int DIR>
391 		static fstb_FORCEINLINE void
392 		               diffuse (float err, float & fstb_RESTRICT err_nxt0, float & fstb_RESTRICT err_nxt1, float * fstb_RESTRICT err0_ptr, float * fstb_RESTRICT err1_ptr, SRC_TYPE src_raw) noexcept;
393 		template <typename EB>
394 		static fstb_FORCEINLINE void
395 		               prepare_next_line (EB * fstb_RESTRICT err_ptr) noexcept;
396 	private:
397 		template <int DIR, typename ET, typename EB>
398 		static fstb_FORCEINLINE void
399 		               spread_error (ET e1, ET e2, ET e3, ET & fstb_RESTRICT err_nxt0, EB * fstb_RESTRICT err0_ptr) noexcept;
400 	};
401 
402 	SplFmt         _splfmt_src = SplFmt_ILLEGAL;
403 	SplFmt         _splfmt_dst = SplFmt_ILLEGAL;
404 	int            _src_res    = 0;
405 	int            _dst_res    = 0;
406 	bool           _full_range_in_flag  = false;
407 	bool           _full_range_out_flag = false;
408 	ColorFamily    _color_fam  = ColorFamily_INVALID;
409 	int            _nbr_planes = 0;
410 
411 	std::array <SclInf, _max_nbr_planes>
412 	               _scale_info_arr;
413 	bool           _upconv_flag = false;
414 	bool           _sse2_flag   = false;
415 	bool           _avx2_flag   = false;
416 	bool           _range_def_flag = false;
417 
418 	int            _dmode    = DMode_FAST;
419 	bool           _alt_flag = false;
420 	int            _pat_size = 32;         // Must be a power of 2
421 	double         _ampo     = 1;
422 	double         _ampn     = 0;
423 	bool           _dyn_flag = false;
424 	bool           _static_noise_flag      = false;
425 	bool           _correlated_planes_flag = false;
426 	bool           _tpdfo_flag = false;
427 	bool           _tpdfn_flag = false;
428 
429 	bool           _errdif_flag = false;   // Indicates a dithering method using error diffusion.
430 	bool           _simple_flag = false;   // Simplified implementation for ampo == 1 and ampn == 0
431 	PatDataArray   _dither_pat_arr;        // Contains levels for ordered dithering
432 
433 	AmpInfo        _amp;
434 
435 	conc::ObjPool <ErrDifBuf>
436 						_buf_pool;
437 	std::unique_ptr <ErrDifBufFactory>
438 	               _buf_factory_uptr;
439 
440 	void (*        _process_seg_int_int_ptr) (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) = nullptr;
441 	void (*        _process_seg_flt_int_ptr) (uint8_t * fstb_RESTRICT dst_ptr, const uint8_t * fstb_RESTRICT src_ptr, int w, SegContext &ctx) = nullptr;
442 
443 
444 
445 /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
446 
447 private:
448 
449 	               Dither ()                               = delete;
450 	               Dither (const Dither &other)            = delete;
451 	               Dither (Dither &&other)                 = delete;
452 	Dither &       operator = (const Dither &other)        = delete;
453 	Dither &       operator = (Dither &&other)             = delete;
454 	bool           operator == (const Dither &other) const = delete;
455 	bool           operator != (const Dither &other) const = delete;
456 
457 }; // class Dither
458 
459 
460 
461 }  // namespace fmtcl
462 
463 
464 
465 //#include "fmtcl/Dither.hpp"
466 
467 
468 
469 #endif   // fmtcl_Dither_HEADER_INCLUDED
470 
471 
472 
473 /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
474