43#define DT_CRYSTGRAIN_LAYER_KERNELS 16
148 return _(
"Photographic grain");
153 return dt_iop_set_description(self, _(
"simulate photographic grain from stacked silver-halide crystal layers"),
155 _(
"non-linear, RGB, scene-referred"),
156 _(
"non-linear, RGB"),
157 _(
"non-linear, RGB, scene-referred"));
183 p.size_stddev = 0.25f;
184 p.layer_capture = 0.0f;
185 p.channel_correlation = 67.0f;
186 p.colorspace_saturation = 67.0f;
194 p.size_stddev = 0.25f;
195 p.layer_capture = 0.0f;
196 p.channel_correlation = 67.0f;
197 p.colorspace_saturation = 67.0f;
203 const int new_version)
205 if((old_version == 1 || old_version == 8) && new_version == 9)
223 while(*s) h = 33 * h ^ (
unsigned int)*s++;
246 return sqrtf(-2.0f * logf(u1)) * cosf(2.0f *
M_PI_F *
u2);
255 if(
max <= 1)
return 0;
257 while(i < 0 || i >=
max)
282 const float clamped_filling =
CLAMPS(filling, 0.0f, 0.9999f);
283 if(crystal_area <= 1.0f)
return clamped_filling;
284 return 1.0f - powf(1.0f - clamped_filling, 1.0f / crystal_area);
296static inline float _crystal_coverage(
const int dx,
const int dy,
const float radius_f,
const float vertices,
297 const float rotation)
299 const float local_radius = hypotf((
float)dx, (
float)dy);
300 float signed_distance = 0.0f;
301 const float theta = atan2f((
float)dy, (
float)dx);
303 / cosf((2.0f * asinf(cosf(vertices * (theta + rotation))) +
M_PI_F)
304 / (2.0f * vertices));
305 const float polygon_radius = radius_f *
envelope;
306 signed_distance = polygon_radius - local_radius;
307 return CLAMPS(signed_distance + 0.5f, 0.0f, 1.0f);
321 const float vertices,
const float rotation)
325 const int radius =
MAX((
int)ceilf(radius_f + 0.5f), 1);
326 const int width = 2 * radius + 1;
330 for(
int y = 0; y <
width; y++)
334 const float alpha =
_crystal_coverage(
x - radius, y - radius, radius_f, vertices, rotation);
335 if(alpha > FLT_EPSILON)
343 if(count <= 0 || area <= FLT_EPSILON)
return 1;
345 kernel->dx = malloc(
sizeof(
int) * count);
346 kernel->dy = malloc(
sizeof(
int) * count);
347 kernel->alpha = malloc(
sizeof(
float) * count);
359 kernel->radius_f = radius_f;
363 for(
int y = 0; y <
width; y++)
367 const float alpha =
_crystal_coverage(
x - radius, y - radius, radius_f, vertices, rotation);
368 if(alpha > FLT_EPSILON)
399 memset(entry, 0,
sizeof(*entry));
405 const float max_size =
MAX(3.0f * mean_size, 1.0f);
407 for(
int attempt = 0; attempt < 8; attempt++)
410 seed + 23u + attempt * 37u),
414 seed + 181u + attempt * 53u);
416 const float radius_f =
MAX(0.5f * (random_size - 1.0f), 0.5f);
448 const float mean_radius =
MAX(0.5f * (mean_size - 1.0f), 0.5f);
449 return M_PI_F * mean_radius * mean_radius;
469 const int sampled_layers =
MIN(rt->
layers, 4);
472 float total_area = 0.0f;
473 int total_kernels = 0;
475 for(
int layer = 0; layer < sampled_layers; layer++)
484 total_area += bank[
i].footprint.area;
490 return (total_area > FLT_EPSILON && total_kernels > 0)
491 ? total_area / total_kernels
510 const uint64_t kernel_seed = layer_seed ^ ((
uint64_t)(
i + 1) * 0xd1342543de82ef95ull);
513 for(
int k = 0;
k <
i;
k++) _free_crystal_kernel(&bank[
k].footprint);
551 const float remaining_fraction)
553 double capture = 0.0;
558 const float captured = fminf(remaining_fraction, area * layer_scale);
584 const float transmitted = 1.0f - remaining_fraction;
585 return (transmitted > FLT_EPSILON) ? 1.0f / transmitted : 1.0f;
588static inline size_t _rgb_index(
const size_t pixel,
const int channel)
590 return 4 * pixel + channel;
608 float *
const remaining,
float *
const exposure)
613 float predicted_remaining = 1.0f;
614 memset(result, 0,
sizeof(
float) * npixels);
615 memcpy(remaining, image,
sizeof(
float) * npixels);
617 for(
int layer = 0; layer < rt->
layers; layer++)
622 predicted_remaining = fmaxf(predicted_remaining
626 for(
int y = 0; y < rt->
height; y++)
631 const size_t index = (size_t)y * rt->
width +
x;
632 if(remaining[index] <= 0.0f)
continue;
636 ^ ((
uint64_t)(uint32_t)world_x << 32)
638 ^ (
uint64_t)(layer + 1) * 0x9e3779b97f4a7c15ull;
643 const int interior = (y >= radius && y < rt->
height - radius &&
x >= radius &&
x < rt->
width - radius);
644 float seed_energy = 0.0f;
645 float original_energy = 0.0f;
654 for(
int tap = 0; tap <
kernel->count; tap++)
657 int yy = y +
kernel->dy[tap];
664 const size_t dst = (size_t)yy *
width + xx;
668 seed_energy += remaining[dst] *
kernel->alpha[tap];
669 original_energy += image[dst] *
kernel->alpha[tap];
671 seed_energy /=
kernel->area;
675 seed_energy = fminf(seed_energy, original_energy);
676 if(seed_energy <= 0.0f)
continue;
678 for(
int tap = 0; tap <
kernel->count; tap++)
681 int yy = y +
kernel->dy[tap];
688 const size_t dst = (size_t)yy *
width + xx;
691 const float deposited = seed_energy *
kernel->alpha[tap];
692 result[dst] += deposited;
693 remaining[dst] = fmaxf(remaining[dst] - deposited, 0.0f);
718 float *
const exposure)
723 const int blue_layers = (rt->
layers + 2) / 3;
724 const int green_layers = (rt->
layers + 1) / 3;
725 float predicted_remaining[3] = { 1.0f, 1.0f, 1.0f };
727 0xa24baed4963ee407ull,
728 0x9fb21c651e98df25ull,
729 0xc13fa9a902a6328full
732 memset(
state->result, 0,
sizeof(
float) * npixels * 4);
733 memcpy(
state->remaining,
state->image,
sizeof(
float) * npixels * 4);
735 for(
int layer = 0; layer < rt->
layers; layer++)
738 const int c = (layer < blue_layers) ? 2 : ((layer < blue_layers + green_layers) ? 1 : 0);
739 const int sublayer = (c == 2) ? layer : ((c == 1) ? layer - blue_layers : layer - blue_layers - green_layers);
742 predicted_remaining[c] = fmaxf(predicted_remaining[c]
746 for(
int y = 0; y <
height; y++)
751 const size_t index = (size_t)y *
width +
x;
755 if(remaining_total <= 0.0f)
continue;
759 ^ ((
uint64_t)(uint32_t)world_x << 32)
761 ^ (
uint64_t)(sublayer + 1) * 0x9e3779b97f4a7c15ull;
762 const uint64_t channel_seed = shared_seed ^ channel_salt[c];
764 const uint64_t pixel_seed = use_shared ? shared_seed : channel_seed;
769 const int interior = (y >= radius && y <
height - radius &&
x >= radius &&
x <
width - radius);
770 float seed_energy = 0.0f;
771 float original_energy = 0.0f;
775 for(
int tap = 0; tap <
kernel->count; tap++)
778 int yy = y +
kernel->dy[tap];
785 const size_t dst = (size_t)yy *
width + xx;
793 seed_energy /=
kernel->area;
795 const float captured = fminf(seed_energy, original_energy);
796 if(captured <= 0.0f)
continue;
798 for(
int tap = 0; tap <
kernel->count; tap++)
801 int yy = y +
kernel->dy[tap];
808 const size_t dst = (size_t)yy *
width + xx;
809 const float deposited = captured *
kernel->alpha[tap];
836 for(
int y = 0; y <
height; y++)
838 const size_t row = (size_t)y *
width;
841 const size_t k =
row +
x;
843 ? dt_ioppr_get_rgb_matrix_luminance(in + 4 *
k, work_profile->
matrix_in, work_profile->
lut_in,
844 work_profile->unbounded_coeffs_in, work_profile->
lutsize,
865 for(
int y = 0; y <
height; y++)
867 const size_t row = (size_t)y *
width;
870 const size_t k =
row +
x;
871 const float red = fmaxf(in[4 *
k + 0], 0.0f);
872 const float green = fmaxf(in[4 *
k + 1], 0.0f);
873 const float blue = fmaxf(in[4 *
k + 2], 0.0f);
895 const float *
const restrict image,
const float *
const restrict result,
896 const int width,
const int height,
const float exposure)
899 for(
int y = 0; y <
height; y++)
901 const size_t row = (size_t)y *
width;
904 const size_t k =
row +
x;
905 const float grainy = fmaxf(result[
k] * exposure, 0.0f);
906 const float ratio = (image[
k] > 1e-6f) ? grainy / image[
k] : 0.0f;
908 out[4 *
k + 0] = fmaxf(in[4 *
k + 0] * ratio, 0.0f);
909 out[4 *
k + 1] = fmaxf(in[4 *
k + 1] * ratio, 0.0f);
910 out[4 *
k + 2] = fmaxf(in[4 *
k + 2] * ratio, 0.0f);
925 const float *
const restrict image,
const float *
const restrict result,
926 const int width,
const int height,
const float exposure_r,
927 const float exposure_g,
const float exposure_b,
const float colorfulness)
930 for(
int y = 0; y <
height; y++)
932 const size_t row = (size_t)y *
width;
935 const size_t k =
row +
x;
939 const float grain_r = (exposure_r > 0.0f) ? fmaxf(result[
_rgb_index(
k, 0)] * exposure_r, 0.0f) : image_r;
940 const float grain_g = (exposure_g > 0.0f) ? fmaxf(result[
_rgb_index(
k, 1)] * exposure_g, 0.0f) : image_g;
941 const float grain_b = (exposure_b > 0.0f) ? fmaxf(result[
_rgb_index(
k, 2)] * exposure_b, 0.0f) : image_b;
942 const float residual_r = grain_r - image_r;
943 const float residual_g = grain_g - image_g;
944 const float residual_b = grain_b - image_b;
945 const float mean = (residual_r + residual_g + residual_b) / 3.0f;
947 out[4 *
k + 0] = in[4 *
k + 0] + mean + (residual_r - mean) * colorfulness;
948 out[4 *
k + 1] = in[4 *
k + 1] + mean + (residual_g - mean) * colorfulness;
949 out[4 *
k + 2] = in[4 *
k + 2] + mean + (residual_b - mean) * colorfulness;
955#define DT_CRYSTGRAIN_CL_PROGRAM 36
956#define DT_CRYSTGRAIN_REDUCESIZE 64
969 cl_mem dev_remaining,
float *
const exposure)
971 cl_int err = CL_SUCCESS;
975 const size_t buffer_size =
sizeof(float) * (
size_t)
width *
height;
976 float predicted_remaining = 1.0f;
982 if(err != CL_SUCCESS)
return err;
985 if(err != CL_SUCCESS)
return err;
987 for(
int layer = 0; layer < rt->
layers; layer++)
991 cl_mem dev_kernel_bank = NULL;
993 const int roi_x = rt->
roi_x;
994 const int roi_y = rt->
roi_y;
996 const cl_ulong base_seed = (cl_ulong)rt->
base_seed;
1000 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
1003 predicted_remaining = fmaxf(predicted_remaining
1009 kernel_bank_cl[
i][0] = kernel_bank[
i].
vertices;
1010 kernel_bank_cl[
i][1] = kernel_bank[
i].
rotation;
1017 if(
IS_NULL_PTR(dev_kernel_bank))
return CL_MEM_OBJECT_ALLOCATION_FAILURE;
1033 if(err != CL_SUCCESS)
return err;
1067 module->data = NULL;
1071 cl_mem dev_in, cl_mem dev_out)
1078 const int devid = pipe->
devid;
1086 cl_int err = CL_SUCCESS;
1087 float exposure[3] = { 1.0f, 1.0f, 1.0f };
1089 if(
width <= 0 || height <= 0 || d->layers <= 0 || d->filling <= 0.0f)
1091 size_t origin[] = { 0, 0, 0 };
1092 size_t region[] = { (size_t)
width, (
size_t)
height, 1 };
1096 cl_mem dev_image = NULL;
1097 cl_mem dev_result = NULL;
1098 cl_mem dev_remaining = NULL;
1099 cl_mem dev_image_rgb = NULL;
1100 cl_mem dev_result_rgb = NULL;
1101 cl_mem dev_remaining_rgb = NULL;
1103 cl_float *profile_lut_cl = NULL;
1104 cl_mem dev_profile_info = NULL;
1105 cl_mem dev_profile_lut = NULL;
1112 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
1119 .roi_x = roi_out->
x,
1120 .roi_y = roi_out->
y,
1121 .layers =
d->layers,
1122 .layer_scale = 0.0f,
1123 .filling =
d->filling,
1124 .grain_size =
d->grain_size,
1125 .size_stddev =
d->size_stddev,
1126 .kernel_scale = kernel_scale,
1127 .inv_scale = 1.0f / kernel_scale,
1128 .channel_correlation =
d->channel_correlation,
1139 rt.
layer_scale =
d->layer_capture /
MAX((
float)
d->layers, 1.0f) /
MAX(current_surface, FLT_EPSILON);
1140 const int blue_layers = (rt.
layers + 2) / 3;
1141 const int green_layers = (rt.
layers + 1) / 3;
1148 &dev_profile_info, &dev_profile_lut);
1149 if(err != CL_SUCCESS)
goto error;
1151 const int use_work_profile = (!
IS_NULL_PTR(work_profile)) ? 1 : 0;
1160 if(err != CL_SUCCESS)
goto error;
1162 err =
_simulate_channel_cl(devid, gd, &rt, dev_image, dev_result, dev_remaining, &exposure[0]);
1163 if(err != CL_SUCCESS)
goto error;
1181 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
1190 if(err != CL_SUCCESS)
goto error;
1192 const size_t color_buffer_size =
sizeof(float) * (
size_t)
width *
height * 4;
1197 if(err != CL_SUCCESS)
goto error;
1200 if(err != CL_SUCCESS)
goto error;
1202 float predicted_remaining[3] = { 1.0f, 1.0f, 1.0f };
1212 const cl_ulong base_seed = (cl_ulong)rt.
base_seed;
1218 for(
int layer = 0; layer < rt.
layers; layer++)
1222 cl_mem dev_kernel_bank = NULL;
1223 const int active_channel = (layer < blue_layers) ? 2 : ((layer < blue_layers + green_layers) ? 1 : 0);
1224 const int sublayer = (active_channel == 2)
1226 : ((active_channel == 1) ? layer - blue_layers : layer - blue_layers - green_layers);
1229 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
1232 predicted_remaining[active_channel]
1233 = fmaxf(predicted_remaining[active_channel]
1239 kernel_bank_cl[
i][0] = kernel_bank[
i].
vertices;
1240 kernel_bank_cl[
i][1] = kernel_bank[
i].
rotation;
1249 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
1258 if(err != CL_SUCCESS)
goto error;
1283 return (err == CL_SUCCESS) ?
TRUE :
FALSE;
1294 d->filling =
p->filling * 0.01f;
1295 d->grain_size =
p->grain_size;
1296 d->layers =
p->layers;
1297 d->size_stddev =
p->size_stddev;
1298 d->layer_capture = exp2f(
p->layer_capture);
1299 d->channel_correlation =
p->channel_correlation * 0.01f;
1300 d->colorspace_saturation =
p->colorspace_saturation * 0.01f;
1316 const void *
const ivoid,
void *
const ovoid)
1322 const float *
const restrict in = (
const float *
const)ivoid;
1323 float *
const restrict
out = (
float *
const)
ovoid;
1329 if(
width <= 0 || height <= 0 || d->layers <= 0 || d->filling <= 0.0f)
1335 float *image = NULL;
1336 float *result = NULL;
1337 float *remaining = NULL;
1338 float *image_rgb = NULL;
1339 float *result_rgb = NULL;
1340 float *remaining_rgb = NULL;
1359 .roi_x = roi_out->
x,
1360 .roi_y = roi_out->
y,
1361 .layers =
d->layers,
1362 .layer_scale = 0.0f,
1363 .filling =
d->filling,
1364 .grain_size =
d->grain_size,
1365 .size_stddev =
d->size_stddev,
1366 .kernel_scale = kernel_scale,
1367 .inv_scale = 1.0f / kernel_scale,
1368 .channel_correlation =
d->channel_correlation,
1379 rt.
layer_scale =
d->layer_capture /
MAX((
float)
d->layers, 1.0f) /
MAX(current_surface, FLT_EPSILON);
1384 float mono_exposure = 1.0f;
1404 float color_exposure[3] = { 1.0f, 1.0f, 1.0f };
1407 .result = result_rgb,
1408 .remaining = remaining_rgb
1424 color_exposure[0], color_exposure[1], color_exposure[2],
1425 d->colorspace_saturation);
1443 gtk_widget_set_visible(
g->channel_correlation, is_color);
1444 gtk_widget_set_visible(
g->colorspace_saturation, is_color);
1457 gtk_widget_set_tooltip_text(
g->mode, _(
"simulate one shared B&W grain field or one shared blue/green/red-sensitive color grain stack"));
1458 g_signal_connect(G_OBJECT(
g->mode),
"value-changed", G_CALLBACK(
_mode_changed), self);
1462 gtk_widget_set_tooltip_text(
g->filling, _(
"surface ratio occupied by silver-halide crystals in each layer"));
1467 gtk_widget_set_tooltip_text(
g->grain_size, _(
"average crystal footprint at 100% zoom, clamped so zooming in does not enlarge it further"));
1471 gtk_widget_set_tooltip_text(
g->layers, _(
"number of crystal layers stacked through the emulsion"));
1476 gtk_widget_set_tooltip_text(
g->layer_capture, _(
"0 EV means one layer captures its neutral 1/layers share after normalization by the rasterized grain surface; positive values increase that capture and negative values decrease it"));
1480 gtk_widget_set_tooltip_text(
g->channel_correlation, _(
"probability that blue-, green- and red-sensitive sub-layers reuse the same crystal births and shapes at matching depths"));
1484 gtk_widget_set_tooltip_text(
g->colorspace_saturation, _(
"scale only the chromatic amplitude of the RGB grain residual while keeping its achromatic strength unchanged"));
1487 gtk_widget_set_tooltip_text(
g->size_stddev, _(
"log-normal standard deviation of crystal sizes"));
static void error(char *msg)
void dt_bauhaus_slider_set_soft_range(GtkWidget *widget, float soft_min, float soft_max)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
@ DEVELOP_BLEND_CS_RGB_SCENE
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static float dt_camera_rgb_luminance(const float4 rgb)
const dt_colormatrix_t dt_aligned_pixel_t out
static float envelope(const float xx)
static float _seed_probability(const float filling, const float crystal_area)
Map the requested filling ratio to the Bernoulli probability used to plant seeds.
static __DT_CLONE_TARGETS__ int _create_crystal_kernel(dt_iop_crystgrain_kernel_t *const kernel, const float radius_f, const float vertices, const float rotation)
Build one partially-occluding crystal footprint for a layer.
const char ** description(struct dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ float _predict_layer_capture(const dt_iop_crystgrain_layer_kernel_t *const bank, const float layer_scale, const float remaining_fraction)
Predict the mean captured energy of one flat-field layer.
#define DT_CRYSTGRAIN_CL_PROGRAM
#define DT_CRYSTGRAIN_LAYER_KERNELS
static float _uniform_random(const uint64_t seed)
Turn a 64-bit seed into a uniform random number in [0; 1).
static __DT_CLONE_TARGETS__ void _apply_mono_grain_kernel(const float *const restrict in, float *const restrict out, const float *const restrict image, const float *const restrict result, const int width, const int height, const float exposure)
Apply one monochrome grain field back onto the RGB image.
static int _reflect_index(int i, const int max)
Mirror indices outside the current buffer like scipy ‘boundary='symm’`.
static float _average_grain_surface(const dt_iop_crystgrain_runtime_t *const rt)
Estimate the reference grain surface used to normalize layer capture.
static size_t _rgb_index(const size_t pixel, const int channel)
static __DT_CLONE_TARGETS__ unsigned int _hash_string(const char *s)
Hash a string into a stable 32-bit seed.
static void _free_layer_kernel_bank(dt_iop_crystgrain_layer_kernel_t *const bank)
Release all crystal footprints from one layer bank.
static __DT_CLONE_TARGETS__ int _pick_layer_kernel(dt_iop_crystgrain_layer_kernel_t *const entry, const dt_iop_crystgrain_runtime_t *const rt, const uint64_t seed)
Pick one crystal geometry for one bank entry.
static __DT_CLONE_TARGETS__ void _extract_luminance_kernel(const float *const restrict in, float *const restrict image, const int width, const int height, const dt_iop_order_iccprofile_info_t *const work_profile)
Extract a luminance image from the RGB input buffer.
static void _mode_changed(GtkWidget *widget, dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ void _extract_rgb_kernels(const float *const restrict in, float *const restrict image, const int width, const int height)
Extract the three RGB light channels as scalar images.
static __DT_CLONE_TARGETS__ int _simulate_channel(const dt_iop_crystgrain_runtime_t *const rt, const float *const image, float *const result, float *const remaining, float *const exposure)
Simulate one monochrome grain field from one scalar image.
void gui_update(struct dt_iop_module_t *self)
static int _build_layer_kernel_bank(dt_iop_crystgrain_layer_kernel_t *const bank, const dt_iop_crystgrain_runtime_t *const rt, const uint64_t layer_seed)
Build the crystal bank for one layer.
void gui_init(struct dt_iop_module_t *self)
void commit_params(dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static __DT_CLONE_TARGETS__ void _finalize_color_grain_kernel(const float *const restrict in, float *const restrict out, const float *const restrict image, const float *const restrict result, const int width, const int height, const float exposure_r, const float exposure_g, const float exposure_b, const float colorfulness)
Finalize the three color grain channels in one pass.
void cleanup_global(dt_iop_module_so_t *module)
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static float _crystal_coverage(const int dx, const int dy, const float radius_f, const float vertices, const float rotation)
Estimate the partial coverage of one pixel by one crystal boundary.
static float _predict_stack_exposure(const float remaining_fraction)
Predict the exposure compensation of one monochrome grain stack.
static int _simulate_channel_cl(const int devid, dt_iop_crystgrain_global_data_t *const gd, const dt_iop_crystgrain_runtime_t *const rt, cl_mem dev_image, cl_mem dev_result, cl_mem dev_remaining, float *const exposure)
Simulate one grain field entirely on the OpenCL device.
void init_presets(dt_iop_module_so_t *self)
static float _gaussian_random(const uint64_t seed_a, const uint64_t seed_b)
Turn 2 seeds into one gaussian deviate.
int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static __DT_CLONE_TARGETS__ float _average_discrete_grain_surface(const dt_iop_crystgrain_runtime_t *const rt)
Estimate the actual rasterized grain surface at the current scale.
static __DT_CLONE_TARGETS__ int _simulate_color(const dt_iop_crystgrain_runtime_t *const rt, const dt_iop_crystgrain_color_state_t *const state, float *const exposure)
Simulate one color grain stack with shared crystal geometry.
void init_global(dt_iop_module_so_t *module)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define dt_pixelpipe_cache_free_align(mem)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static unsigned int splitmix32(const unsigned long seed)
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled, const dt_develop_blend_colorspace_t blend_cst)
int dt_iop_alloc_image_buffers(struct dt_iop_module_t *const module, const struct dt_iop_roi_t *const roi_in, const struct dt_iop_roi_t *const roi_out,...)
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
#define DT_IMGSZ_CLEARBUF
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
float dt_dev_get_module_scale(const dt_dev_pixelpipe_t *const pipe, const dt_iop_roi_t *const roi_in)
@ IOP_FLAGS_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
GtkWidget * dt_bauhaus_combobox_from_params(dt_iop_module_t *self, const char *param)
static float kernel(const float *x, const float *y)
dt_iop_order_iccprofile_info_t * dt_ioppr_get_pipe_work_profile_info(const struct dt_dev_pixelpipe_t *pipe)
void dt_ioppr_free_iccprofile_params_cl(dt_colorspaces_iccprofile_info_cl_t **_profile_info_cl, cl_float **_profile_lut_cl, cl_mem *_dev_profile_info, cl_mem *_dev_profile_lut)
cl_int dt_ioppr_build_iccprofile_params_cl(const dt_iop_order_iccprofile_info_t *const profile_info, const int devid, dt_colorspaces_iccprofile_info_cl_t **_profile_info_cl, cl_float **_profile_lut_cl, cl_mem *_dev_profile_info, cl_mem *_dev_profile_lut)
float *const restrict luminance
float *const restrict const size_t k
static const int max_size
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
int dt_opencl_create_kernel(const int prog, const char *name)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
int dt_opencl_enqueue_copy_buffer_to_buffer(const int devid, cl_mem src_buffer, cl_mem dst_buffer, size_t srcoffset, size_t dstoffset, size_t size)
void dt_opencl_release_mem_object(cl_mem mem)
struct _GtkWidget GtkWidget
const float uint32_t state[4]
unsigned __int64 uint64_t
struct dt_iop_module_t *void * data
struct dt_develop_t * dev
char filename[DT_MAX_FILENAME_LEN]
float channel_correlation
dt_iop_crystgrain_mode_t mode
float colorspace_saturation
int kernel_simulate_layer_color
int kernel_finalize_color
int kernel_simulate_layer
int kernel_extract_luminance
GtkWidget * colorspace_saturation
GtkWidget * layer_capture
GtkWidget * channel_correlation
dt_iop_crystgrain_kernel_t footprint
float colorspace_saturation
dt_iop_crystgrain_mode_t mode
float channel_correlation
float channel_correlation
GModule *dt_dev_operation_t op
dt_iop_global_data_t * data
dt_iop_gui_data_t * gui_data
dt_iop_global_data_t * global_data
dt_colormatrix_t matrix_in
Region of interest passed through the pixelpipe.