45#include "../util/assert.h"
46#include "../util/tracing.h"
47#include "../util/testimg.h"
69 check_expected_ptr(module);
70 check_expected(update);
81 assert_string_equal(
name(),
"fil_mic");
91 for (
float x = -0.5f;
x <= 1.5f;
x += 0.1f)
112 TR_STEP(
"verify that norm is correct and in ]0.0; 1.0] for rgb values "
118 float norm = pixel_rgb_norm_power(
p);
119 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
120 float numerator =
p[0] *
p[0] *
p[0] +
p[1] *
p[1] *
p[1] +
p[2] *
p[2] *
p[2];
121 float denominator =
p[0] *
p[0] +
p[1] *
p[1] +
p[2] *
p[2];
122 float exp_norm = numerator / denominator;
124 assert_true(norm > 0.0f);
125 assert_true(norm <= 1.0f + 1e-6f);
129 TR_STEP(
"verify that norm is equal to pixel (r=g=b) value on greyscale "
135 float norm = pixel_rgb_norm_power(
p);
136 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
141 TR_STEP(
"verify that norm is in ]0; +inf[ for bad greyscale pixels in "
143 TR_BUG(
"norm is undefined for extreme values, thus values outside "
144 "[1e-6; 1e6] are excluded from assertion.");
148 float norm = pixel_rgb_norm_power(
p);
149 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
150 if (
p[0] > 1e-6 &&
p[0] < 1e6)
152 assert_true(norm > 0.0f);
153 assert_true(norm <= FLT_MAX);
158 TR_STEP(
"verify that norm is in ]0; +inf[ for bad negative greyscale pixels "
160 TR_BUG(
"norm is undefined for extreme values, thus values outside "
161 "[1e-6; 1e6] are excluded from assertion.");
162 TR_BUG(
"norm is 0 if input is 0.");
166 float norm = pixel_rgb_norm_power(
p);
167 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
168 if (fabsf(
p[0]) > 1e-6 && fabsf(
p[0]) < 1e6)
170 assert_true(norm > 0.0f);
171 assert_true(norm <= FLT_MAX);
173 if (
p[0] > -FLT_MIN &&
p[0] < FLT_MIN)
186 TR_STEP(
"verify that max-rgb norm is correct and in ]0.0; 1.0] for rgb "
187 "values in ]0.0; 1.0]");
193 TR_DEBUG(
"pixel={%e, %e, %e, %e} => norm=%e",
p[0],
p[1],
p[2],
p[3], norm);
195 assert_true(norm > 0.0f);
196 assert_true(norm <= 1.0f +
E);
200 TR_STEP(
"verify that max-rgb norm is equal to pixel (r=g=b) value on "
207 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
212 TR_STEP(
"verify that max-rgb norm is in ]0; +inf[ for bad greyscale pixels "
218 TR_DEBUG(
"pixel={%e, %e, %e, %e} => norm=%e",
p[0],
p[1],
p[2],
p[3], norm);
219 assert_true(norm > 0.0f);
220 assert_true(norm <= FLT_MAX);
224 TR_STEP(
"verify that max-rgb norm is in ]0; +inf[ for bad negative greyscale "
225 "pixels in ]-inf; 0]");
226 TR_BUG(
"max-rgb norm is unbounded and negative for pixels with all-negative "
232 TR_DEBUG(
"pixel={%e, %e, %e, %e} => norm=%e",
p[0],
p[1],
p[2],
p[3], norm);
234 assert_true(norm <= FLT_MAX);
238 TR_STEP(
"verify luminance-y norm (verify subsequent function calls)");
241 TR_STEP(
"verify power norm (verify subsequent function calls)");
250 float grey = 0.1845f;
252 float black = log2f(1.0f/grey) - dyn_range;
253 const float MIN = 0.0f;
254 const float MAX = 1.0f;
256 TR_STEP(
"verify that output is equal to log-mapped input for equal dynamic "
257 "range and grey/black points");
275 TR_STEP(
"verify that output is 1 EV brighter (and clipped to [0; 1]) when "
276 "grey is set to half");
298 TR_STEP(
"verify that output is bound to [0; 1] for all non-negative values");
303 TR_DEBUG(
"{%e, %e, %e, %e} => %e",
p[0],
p[1],
p[2],
p[3], ret);
304 assert_true(ret >=
MIN);
305 assert_true(ret <=
MAX);
309 TR_STEP(
"verify that output is bound to [0; 1] for all negative values "
315 TR_DEBUG(
"{%e, %e, %e, %e} => %e",
p[0],
p[1],
p[2],
p[3], ret);
316 assert_true(ret >=
MIN);
317 assert_true(ret <=
MAX);
333 TR_NOTE(
"method verified by code review only since it is hard to test it and "
334 "the benefit is questionable");
345 TR_BUG(
"saturation conversion from gui to internal is wrong");
346 return (2.0f * saturation_percent / 100.0f + 1.0f);
355 float lattitude_min = 0.2;
356 float lattitude_max = 0.2;
357 float saturation_percent = 5.0f;
361 float sigma_toe = powf(lattitude_min / 3.0f, 2.0f);
362 float sigma_shoulder = powf(lattitude_max / 3.0f, 2.0f);
366 TR_STEP(
"verify values are correct for different latitudes");
367 TR_BUG(
"values inside latitude are not always 1.0 (but very close), "
368 "especially at the borders");
369 for (
float latitude_min = 0.1f; latitude_min < 0.5f +
E; latitude_min += 0.1f)
371 for (
float latitude_max = 0.1f; latitude_max < 0.5f +
E; latitude_max += 0.1f)
373 TR_DEBUG(
"saturation=%e", saturation);
374 TR_DEBUG(
"latitude_min=%e", latitude_min);
375 TR_DEBUG(
"latitude_max=%e", latitude_max);
378 sigma_toe = powf(lattitude_min / 3.0f, 2.0f);
379 sigma_shoulder = powf(lattitude_max / 3.0f, 2.0f);
381 TR_DEBUG(
"sigma_toe=%e", sigma_toe);
382 TR_DEBUG(
"sigma_shoulder=%e", sigma_shoulder);
390 filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
393 if (lattitude_min == lattitude_max)
397 float exp = filmic_desaturate_v1(p1[0], sigma_toe, sigma_shoulder,
403 if (
x == 0 ||
x == ti->
width - 1)
409 if (
x > (lattitude_min * ti->
width) &&
410 x < ((1.0f - lattitude_max) * ti->
width - 1))
419 TR_STEP(
"verify return value is always 1.0 when saturation is set to maximum");
420 TR_BUG(
"values inside latitude are not always 1.0 (but very close), "
421 "especially at the borders");
427 float ret = filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
436 TR_STEP(
"verify output is in ]0; 1] for bad values in ]0; +inf[");
440 float ret = filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
442 assert_true(ret > 0.0f);
443 assert_true(ret <= 1.0f);
447 TR_STEP(
"verify output is in ]0; 1] for bad negative values in ]-inf; 0]");
451 float ret = filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
453 assert_true(ret > 0.0f);
454 assert_true(ret <= 1.0f);
464 float saturation = 0.05f;
465 float ratios[] = { 0.2126, 0.7152, 0.0722 };
467 TR_STEP(
"verify that output is equal to value for greyscale values");
475 TR_DEBUG(
"pixel={%e, %e, %e) => linear_saturation={%e, %e, %e}",
476 p[0],
p[1],
p[2], s0, s1, s2);
483 TR_STEP(
"verify that output is equal to value for rgb values when saturation "
489 luminance =
p[0] * ratios[0] +
p[1] * ratios[1] +
p[2] * ratios[2];
493 TR_DEBUG(
"pixel={%e, %e, %e) => linear_saturation={%e, %e, %e}",
494 p[0],
p[1],
p[2], s0, s1, s2);
501 TR_STEP(
"verify that output is pure grey, equal to luminance, for rgb values "
502 "when saturation is 0.0");
507 luminance =
p[0] * ratios[0] +
p[1] * ratios[1] +
p[2] * ratios[2];
511 TR_DEBUG(
"pixel={%e, %e, %e) => linear_saturation={%e, %e, %e}",
512 p[0],
p[1],
p[2], s0, s1, s2);
523int main(
int argc,
char* argv[])
525 const struct CMUnitTest tests[] = {
539 return cmocka_run_group_tests(tests, NULL, NULL);
#define assert_float_equal(a, b, epsilon)
@ DT_FILMIC_METHOD_MAX_RGB
static float log_tonemapping(const float x, const float grey, const float black, const float dynamic_range)
static float linear_saturation(const float x, const float luminance, const float saturation)
float *const restrict luminance
static float clamp_simd(const float x)
const float uint32_t state[4]
static void test_filmic_desaturate_v1(void **state)
static float saturation_gui_to_internal(float saturation_percent)
static void test_log_tonemapping(void **state)
static void test_default_group(void **state)
static void test_get_pixel_norm(void **state)
static void test_linear_saturation(void **state)
static void test_pixel_rgb_norm_power(void **state)
static void test_filmic_spline(void **state)
static void test_name(void **state)
void __wrap_dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean update)
static void test_clamp_simd(void **state)
void testimg_free(Testimg *const ti)
Testimg * testimg_gen_grey_max_dr_neg()
float testimg_val_to_log(const float val)
Testimg * testimg_to_log(Testimg *ti)
Testimg * testimg_gen_grey_space(const int width)
Testimg * testimg_gen_grey_max_dr()
Testimg * testimg_gen_rgb_space(const int width)
static float * get_pixel(const Testimg *const ti, const int x, const int y)
#define TESTIMG_STD_WIDTH
#define for_testimg_pixels_p_yx(ti)
#define for_testimg_pixels_p_xy(ti)
#define TESTIMG_STD_DYN_RANGE_EV
#define TR_DEBUG(msg,...)