45#include "../util/assert.h"
46#include "../util/tracing.h"
47#include "../util/testimg.h"
69 check_expected_ptr(module);
70 check_expected(update);
80 assert_string_equal(
name(),
"filmic rgb");
90 for (
float x = -0.5f;
x <= 1.5f;
x += 0.1f)
111 TR_STEP(
"verify that norm is correct and in ]0.0; 1.0] for rgb values "
117 float norm = pixel_rgb_norm_power(
p);
118 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
119 float numerator =
p[0] *
p[0] *
p[0] +
p[1] *
p[1] *
p[1] +
p[2] *
p[2] *
p[2];
120 float denominator =
p[0] *
p[0] +
p[1] *
p[1] +
p[2] *
p[2];
121 float exp_norm = numerator / denominator;
123 assert_true(norm > 0.0f);
124 assert_true(norm <= 1.0f + 1e-6f);
128 TR_STEP(
"verify that norm is equal to pixel (r=g=b) value on greyscale "
134 float norm = pixel_rgb_norm_power(
p);
135 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
140 TR_STEP(
"verify that norm is in ]0; +inf[ for bad greyscale pixels in "
142 TR_BUG(
"norm is undefined for extreme values, thus values outside "
143 "[1e-6; 1e6] are excluded from assertion.");
147 float norm = pixel_rgb_norm_power(
p);
148 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
149 if (
p[0] > 1e-6 &&
p[0] < 1e6)
151 assert_true(norm > 0.0f);
152 assert_true(norm <= FLT_MAX);
157 TR_STEP(
"verify that norm is in ]0; +inf[ for bad negative greyscale pixels "
159 TR_BUG(
"norm is undefined for extreme values, thus values outside "
160 "[1e-6; 1e6] are excluded from assertion.");
161 TR_BUG(
"norm is 0 if input is 0.");
165 float norm = pixel_rgb_norm_power(
p);
166 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
167 if (fabsf(
p[0]) > 1e-6 && fabsf(
p[0]) < 1e6)
169 assert_true(norm > 0.0f);
170 assert_true(norm <= FLT_MAX);
172 if (
p[0] > -FLT_MIN &&
p[0] < FLT_MIN)
185 TR_STEP(
"verify that max-rgb norm is correct and in ]0.0; 1.0] for rgb "
186 "values in ]0.0; 1.0]");
192 TR_DEBUG(
"pixel={%e, %e, %e, %e} => norm=%e",
p[0],
p[1],
p[2],
p[3], norm);
194 assert_true(norm > 0.0f);
195 assert_true(norm <= 1.0f +
E);
199 TR_STEP(
"verify that max-rgb norm is equal to pixel (r=g=b) value on "
206 TR_DEBUG(
"pixel={%e, %e, %e) => norm=%e",
p[0],
p[1],
p[2], norm);
211 TR_STEP(
"verify that max-rgb norm is in ]0; +inf[ for bad greyscale pixels "
217 TR_DEBUG(
"pixel={%e, %e, %e, %e} => norm=%e",
p[0],
p[1],
p[2],
p[3], norm);
218 assert_true(norm > 0.0f);
219 assert_true(norm <= FLT_MAX);
223 TR_STEP(
"verify that max-rgb norm is in ]0; +inf[ for bad negative greyscale "
224 "pixels in ]-inf; 0]");
225 TR_BUG(
"max-rgb norm is unbounded and negative for pixels with all-negative "
231 TR_DEBUG(
"pixel={%e, %e, %e, %e} => norm=%e",
p[0],
p[1],
p[2],
p[3], norm);
233 assert_true(norm <= FLT_MAX);
237 TR_STEP(
"verify luminance-y norm (verify subsequent function calls)");
240 TR_STEP(
"verify power norm (verify subsequent function calls)");
249 float grey = 0.1845f;
251 float black = log2f(1.0f/grey) - dyn_range;
252 const float MIN = 0.0f;
253 const float MAX = 1.0f;
255 TR_STEP(
"verify that output is equal to log-mapped input for equal dynamic "
256 "range and grey/black points");
260 float ret = log_tonemapping_v2(
p[0], grey, black, dyn_range);
274 TR_STEP(
"verify that output is 1 EV brighter (and clipped to [0; 1]) when "
275 "grey is set to half");
279 float ret = log_tonemapping_v2(
p[0], (grey / 2.0f), black, dyn_range);
297 TR_STEP(
"verify that output is bound to [0; 1] for all non-negative values");
301 float ret = log_tonemapping_v2(
p[0], grey, black, dyn_range);
302 TR_DEBUG(
"{%e, %e, %e, %e} => %e",
p[0],
p[1],
p[2],
p[3], ret);
303 assert_true(ret >=
MIN);
304 assert_true(ret <=
MAX);
308 TR_STEP(
"verify that output is bound to [0; 1] for all negative values "
313 float ret = log_tonemapping_v2(
p[0], grey, black, dyn_range);
314 TR_DEBUG(
"{%e, %e, %e, %e} => %e",
p[0],
p[1],
p[2],
p[3], ret);
315 assert_true(ret >=
MIN);
316 assert_true(ret <=
MAX);
332 TR_NOTE(
"method verified by code review only since it is hard to test it and "
333 "the benefit is questionable");
344 TR_BUG(
"saturation conversion from gui to internal is wrong");
345 return (2.0f * saturation_percent / 100.0f + 1.0f);
354 float lattitude_min = 0.2;
355 float lattitude_max = 0.2;
356 float saturation_percent = 5.0f;
360 float sigma_toe = powf(lattitude_min / 3.0f, 2.0f);
361 float sigma_shoulder = powf(lattitude_max / 3.0f, 2.0f);
365 TR_STEP(
"verify values are correct for different latitudes");
366 TR_BUG(
"values inside latitude are not always 1.0 (but very close), "
367 "especially at the borders");
368 for (
float latitude_min = 0.1f; latitude_min < 0.5f +
E; latitude_min += 0.1f)
370 for (
float latitude_max = 0.1f; latitude_max < 0.5f +
E; latitude_max += 0.1f)
372 TR_DEBUG(
"saturation=%e", saturation);
373 TR_DEBUG(
"latitude_min=%e", latitude_min);
374 TR_DEBUG(
"latitude_max=%e", latitude_max);
377 sigma_toe = powf(lattitude_min / 3.0f, 2.0f);
378 sigma_shoulder = powf(lattitude_max / 3.0f, 2.0f);
380 TR_DEBUG(
"sigma_toe=%e", sigma_toe);
381 TR_DEBUG(
"sigma_shoulder=%e", sigma_shoulder);
389 filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
392 if (lattitude_min == lattitude_max)
396 float exp = filmic_desaturate_v1(p1[0], sigma_toe, sigma_shoulder,
402 if (
x == 0 ||
x == ti->
width - 1)
408 if (
x > (lattitude_min * ti->
width) &&
409 x < ((1.0f - lattitude_max) * ti->
width - 1))
418 TR_STEP(
"verify return value is always 1.0 when saturation is set to maximum");
419 TR_BUG(
"values inside latitude are not always 1.0 (but very close), "
420 "especially at the borders");
426 float ret = filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
435 TR_STEP(
"verify output is in ]0; 1] for bad values in ]0; +inf[");
439 float ret = filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
441 assert_true(ret > 0.0f);
442 assert_true(ret <= 1.0f);
446 TR_STEP(
"verify output is in ]0; 1] for bad negative values in ]-inf; 0]");
450 float ret = filmic_desaturate_v1(
p[0], sigma_toe, sigma_shoulder, saturation);
452 assert_true(ret > 0.0f);
453 assert_true(ret <= 1.0f);
463 float saturation = 0.05f;
464 float ratios[] = { 0.2126, 0.7152, 0.0722 };
466 TR_STEP(
"verify that output is equal to value for greyscale values");
474 TR_DEBUG(
"pixel={%e, %e, %e) => linear_saturation={%e, %e, %e}",
475 p[0],
p[1],
p[2], s0, s1, s2);
482 TR_STEP(
"verify that output is equal to value for rgb values when saturation "
488 luminance =
p[0] * ratios[0] +
p[1] * ratios[1] +
p[2] * ratios[2];
492 TR_DEBUG(
"pixel={%e, %e, %e) => linear_saturation={%e, %e, %e}",
493 p[0],
p[1],
p[2], s0, s1, s2);
500 TR_STEP(
"verify that output is pure grey, equal to luminance, for rgb values "
501 "when saturation is 0.0");
506 luminance =
p[0] * ratios[0] +
p[1] * ratios[1] +
p[2] * ratios[2];
510 TR_DEBUG(
"pixel={%e, %e, %e) => linear_saturation={%e, %e, %e}",
511 p[0],
p[1],
p[2], s0, s1, s2);
522int main(
int argc,
char* argv[])
524 const struct CMUnitTest tests[] = {
538 return cmocka_run_group_tests(tests, NULL, NULL);
#define assert_float_equal(a, b, epsilon)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
@ DT_FILMIC_METHOD_MAX_RGB
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_v2(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)
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)
#define TESTIMG_STD_WIDTH
#define for_testimg_pixels_p_yx(ti)
float * get_pixel(const Testimg *const ti, const int x, const int y)
#define for_testimg_pixels_p_xy(ti)
#define TESTIMG_STD_DYN_RANGE_EV
#define TR_DEBUG(msg,...)