Skip to content

Commit 1e2cf01

Browse files
authored
Merge pull request #20891 from jenshannoschwalm/fix_interpolators_lens
Fix interpolators lens
2 parents fd2ad03 + 7486c4c commit 1e2cf01

8 files changed

Lines changed: 423 additions & 516 deletions

File tree

data/kernels/basic.cl

Lines changed: 339 additions & 401 deletions
Large diffs are not rendered by default.

data/kernels/demosaic_other.cl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
This file is part of darktable,
3-
Copyright (C) 2015-2025 darktable developers.
3+
Copyright (C) 2015-2026 darktable developers.
44
55
darktable is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@ passthrough_monochrome (__read_only image2d_t in, __write_only image2d_t out, co
2929

3030
if(x >= width || y >= height) return;
3131

32-
const float pc = fmax(0.0f, read_imagef(in, sampleri, (int2)(x, y)).x);
32+
const float pc = readsingle(in, x, y);
3333
write_imagef(out, (int2)(x, y), (float4)pc);
3434
}
3535

@@ -46,7 +46,7 @@ passthrough_color(__read_only image2d_t in,
4646

4747
if(x >= width || y >= height) return;
4848

49-
const float ival = fmax(0.0f, read_imagef(in, sampleri, (int2)(x, y)).x);
49+
const float ival = readsingle(in, x, y);
5050
const int c = fcol(y, x, filters, xtrans);
5151

5252
float4 oval = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
@@ -96,7 +96,7 @@ clip_and_zoom_demosaic_passthrough_monochrome(__read_only image2d_t in,
9696
const float xfilter = (i == 0) ? 1.0f - d.x : ((i == samples+1) ? d.x : 1.0f);
9797
const float yfilter = (j == 0) ? 1.0f - d.y : ((j == samples+1) ? d.y : 1.0f);
9898

99-
const float px = fmax(0.0f, read_imagef(in, sampleri, (int2)(xx, yy)).x);
99+
const float px = readsingle(in, xx, yy);
100100
color += yfilter*xfilter*(float4)(px, px, px, 0.0f);
101101
weight += yfilter*xfilter;
102102
}

data/kernels/demosaic_ppg.cl

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -461,37 +461,6 @@ color_smoothing(read_only image2d_t in,
461461
#undef cas
462462

463463

464-
465-
/**
466-
* downscale and clip a buffer (in) to the given roi (r_*) and write it to out.
467-
* output will be linear in memory.
468-
* operates on float4 -> float4 textures.
469-
*/
470-
kernel void
471-
clip_and_zoom(read_only image2d_t in, write_only image2d_t out, const int width, const int height,
472-
const int r_x, const int r_y, const int r_wd, const int r_ht, const float r_scale)
473-
{
474-
// global id is pixel in output image (float4)
475-
const int x = get_global_id(0);
476-
const int y = get_global_id(1);
477-
478-
if(x >= width || y >= height) return;
479-
480-
float4 color = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
481-
482-
const float px_footprint = 0.5f/r_scale;
483-
const int samples = ((int)px_footprint);
484-
const float2 p = backtransformf((float2)(x+0.5f, y+0.5f), r_x, r_y, r_wd, r_ht, r_scale);
485-
for(int j=-samples;j<=samples;j++) for(int i=-samples;i<=samples;i++)
486-
{
487-
const float4 px = read_imagef(in, samplerf, (float2)(p.x+i, p.y+j));
488-
color += px;
489-
}
490-
color /= (float4)((2*samples+1)*(2*samples+1));
491-
write_imagef (out, (int2)(x, y), fmax(color, 0.0f));
492-
}
493-
494-
495464
/**
496465
* downscales and clips a mosaiced buffer (in) to the given region of interest (r_*)
497466
* and writes it to out in float4 format.
@@ -552,10 +521,10 @@ clip_and_zoom_demosaic_half_size(__read_only image2d_t in,
552521
const float yfilter = (j == 0) ? 1.0f - d.y : ((j == samples+1) ? d.y : 1.0f);
553522

554523
// get four mosaic pattern uint16:
555-
const float p1 = read_imagef(in, sampleri, (int2)(xx, yy )).x;
556-
const float p2 = read_imagef(in, sampleri, (int2)(xx+1, yy )).x;
557-
const float p3 = read_imagef(in, sampleri, (int2)(xx, yy+1)).x;
558-
const float p4 = read_imagef(in, sampleri, (int2)(xx+1, yy+1)).x;
524+
const float p1 = readsingle(in, xx, yy );
525+
const float p2 = readsingle(in, xx+1, yy );
526+
const float p3 = readsingle(in, xx, yy+1);
527+
const float p4 = readsingle(in, xx+1, yy+1);
559528
color += yfilter*xfilter*(float4)(p1, (p2+p3)*0.5f, p4, 0.0f);
560529
weight += yfilter*xfilter;
561530
}

data/kernels/denoiseprofile.cl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ denoiseprofile_finish(read_only image2d_t in, global float4* U2, write_only imag
324324
if(x >= width || y >= height) return;
325325

326326
float4 u2 = U2[gidx];
327-
const float alpha = read_imagef(in, sampleri, (int2)(x, y)).w;
327+
const float alpha = readalpha(in, x, y);
328328

329329
float4 px = ((float4)u2.w > (float4)0.0f ? u2/u2.w : (float4)0.0f);
330330

@@ -349,7 +349,7 @@ denoiseprofile_finish_v2(read_only image2d_t in, global float4* U2, write_only i
349349
if(x >= width || y >= height) return;
350350

351351
float4 u2 = U2[gidx];
352-
const float alpha = read_imagef(in, sampleri, (int2)(x, y)).w;
352+
const float alpha = readalpha(in, x, y);
353353

354354
float4 px = ((float4)u2.w > (float4)0.0f ? u2/u2.w : (float4)0.0f);
355355

data/kernels/retouch.cl

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
This file is part of darktable,
3-
copyright (c) 2017 edgardo hoszowski.
3+
Copyright (C) 2017-2026 darktable developers.
44
55
darktable is free software: you can redistribute it and/or modify
66
it under the terms of the GNU General Public License as published by
@@ -38,22 +38,28 @@ retouch_clear_alpha(global float4 *in, int width, int height)
3838
}
3939

4040
kernel void
41-
retouch_copy_alpha(__read_only image2d_t in, global float4 *out, int width, int height)
41+
retouch_copy_alpha(__read_only image2d_t in,
42+
global float4 *out,
43+
int width,
44+
int height)
4245
{
4346
const int x = get_global_id(0);
4447
const int y = get_global_id(1);
4548

4649
if(x >= width || y >= height) return;
4750

48-
float4 pixel = read_imagef(in, sampleri, (int2)(x, y));
51+
float alpha = readalpha(in, x, y);
4952
const int idx = mad24(y, width, x);
50-
out[idx].w = pixel.w;
53+
out[idx].w = alpha;
5154
}
5255

5356
kernel void
54-
retouch_copy_buffer_to_image(global float4 *in, global dt_iop_roi_t *roi_in,
55-
__write_only image2d_t out, global dt_iop_roi_t *roi_out, const int xoffs,
56-
const int yoffs)
57+
retouch_copy_buffer_to_image(global float4 *in,
58+
global dt_iop_roi_t *roi_in,
59+
__write_only image2d_t out,
60+
global dt_iop_roi_t *roi_out,
61+
const int xoffs,
62+
const int yoffs)
5763
{
5864
const int x = get_global_id(0);
5965
const int y = get_global_id(1);
@@ -66,8 +72,12 @@ retouch_copy_buffer_to_image(global float4 *in, global dt_iop_roi_t *roi_in,
6672
}
6773

6874
kernel void
69-
retouch_copy_buffer_to_buffer(global float4 *in, global dt_iop_roi_t *roi_in, global float4 *out,
70-
global dt_iop_roi_t *roi_out, const int xoffs, const int yoffs)
75+
retouch_copy_buffer_to_buffer(global float4 *in,
76+
global dt_iop_roi_t *roi_in,
77+
global float4 *out,
78+
global dt_iop_roi_t *roi_out,
79+
const int xoffs,
80+
const int yoffs)
7181
{
7282
const int x = get_global_id(0);
7383
const int y = get_global_id(1);
@@ -79,39 +89,45 @@ retouch_copy_buffer_to_buffer(global float4 *in, global dt_iop_roi_t *roi_in, gl
7989
}
8090

8191
kernel void
82-
retouch_copy_mask_to_alpha(global float4 *in, global dt_iop_roi_t *roi_in, global float *mask_scaled,
83-
global dt_iop_roi_t *roi_mask_scaled, const float opacity)
92+
retouch_copy_mask_to_alpha(global float4 *in,
93+
global dt_iop_roi_t *roi_in,
94+
global float *mask_scaled,
95+
global dt_iop_roi_t *roi_mask_scaled,
96+
const float opacity)
8497
{
8598
const int x = get_global_id(0);
8699
const int y = get_global_id(1);
87100

88101
if(x >= roi_mask_scaled->width || y >= roi_mask_scaled->height) return;
89102

90103
const int mask_index = mad24(y, roi_mask_scaled->width, x);
91-
const int dest_index
92-
= mad24(y + roi_mask_scaled->y - roi_in->y, roi_in->width, x + roi_mask_scaled->x - roi_in->x);
104+
const int dest_index = mad24(y + roi_mask_scaled->y - roi_in->y, roi_in->width, x + roi_mask_scaled->x - roi_in->x);
93105

94-
const float f = mask_scaled[mask_index] * opacity;
106+
const float f = clipf(mask_scaled[mask_index] * opacity);
95107

96108
if(f > in[dest_index].w) in[dest_index].w = f;
97109
}
98110

99111
kernel void
100-
retouch_fill(global float4 *in, global dt_iop_roi_t *roi_in, global float *mask_scaled,
101-
global dt_iop_roi_t *roi_mask_scaled, const float opacity, const float color_x,
102-
const float color_y, const float color_z)
112+
retouch_fill(global float4 *in,
113+
global dt_iop_roi_t *roi_in,
114+
global float *mask_scaled,
115+
global dt_iop_roi_t *roi_mask_scaled,
116+
const float opacity,
117+
const float color_x,
118+
const float color_y,
119+
const float color_z)
103120
{
104121
const int x = get_global_id(0);
105122
const int y = get_global_id(1);
106123

107124
if(x >= roi_mask_scaled->width || y >= roi_mask_scaled->height) return;
108125

109126
const int mask_index = mad24(y, roi_mask_scaled->width, x);
110-
const int dest_index
111-
= mad24(y + roi_mask_scaled->y - roi_in->y, roi_in->width, x + roi_mask_scaled->x - roi_in->x);
127+
const int dest_index = mad24(y + roi_mask_scaled->y - roi_in->y, roi_in->width, x + roi_mask_scaled->x - roi_in->x);
112128

113129
float4 fill_color = { color_x, color_y, color_z, 0.f };
114-
const float f = mask_scaled[mask_index] * opacity;
130+
const float f = clipf(mask_scaled[mask_index] * opacity);
115131
const float w = in[dest_index].w;
116132

117133
in[dest_index] = in[dest_index] * (1.0f - f) + fill_color * f;
@@ -120,9 +136,12 @@ retouch_fill(global float4 *in, global dt_iop_roi_t *roi_in, global float *mask_
120136
}
121137

122138
kernel void
123-
retouch_copy_buffer_to_buffer_masked(global float4 *buffer_src, global float4 *buffer_dest,
124-
global dt_iop_roi_t *roi_buffer_dest, global float *mask_scaled,
125-
global dt_iop_roi_t *roi_mask_scaled, const float opacity)
139+
retouch_copy_buffer_to_buffer_masked(global float4 *buffer_src,
140+
global float4 *buffer_dest,
141+
global dt_iop_roi_t *roi_buffer_dest,
142+
global float *mask_scaled,
143+
global dt_iop_roi_t *roi_mask_scaled,
144+
const float opacity)
126145
{
127146
const int x = get_global_id(0);
128147
const int y = get_global_id(1);
@@ -134,7 +153,7 @@ retouch_copy_buffer_to_buffer_masked(global float4 *buffer_src, global float4 *b
134153
const int idx_src = mad24(y, roi_mask_scaled->width, x);
135154
const int idx_mask = mad24(y, roi_mask_scaled->width, x);
136155

137-
const float f = mask_scaled[idx_mask] * opacity;
156+
const float f = clipf(mask_scaled[idx_mask] * opacity);
138157
const float w = buffer_dest[idx_dest].w;
139158

140159
buffer_dest[idx_dest] = buffer_dest[idx_dest] * (1.0f - f) + buffer_src[idx_src] * f;
@@ -143,9 +162,12 @@ retouch_copy_buffer_to_buffer_masked(global float4 *buffer_src, global float4 *b
143162
}
144163

145164
kernel void
146-
retouch_copy_image_to_buffer_masked(__read_only image2d_t buffer_src, global float4 *buffer_dest,
147-
global dt_iop_roi_t *roi_buffer_dest, global float *mask_scaled,
148-
global dt_iop_roi_t *roi_mask_scaled, const float opacity)
165+
retouch_copy_image_to_buffer_masked(__read_only image2d_t buffer_src,
166+
global float4 *buffer_dest,
167+
global dt_iop_roi_t *roi_buffer_dest,
168+
global float *mask_scaled,
169+
global dt_iop_roi_t *roi_mask_scaled,
170+
const float opacity)
149171
{
150172
const int x = get_global_id(0);
151173
const int y = get_global_id(1);
@@ -156,17 +178,19 @@ retouch_copy_image_to_buffer_masked(__read_only image2d_t buffer_src, global flo
156178
x + roi_mask_scaled->x - roi_buffer_dest->x);
157179
const int idx_mask = mad24(y, roi_mask_scaled->width, x);
158180

159-
const float f = mask_scaled[idx_mask] * opacity;
181+
const float f = clipf(mask_scaled[idx_mask] * opacity);
160182
const float w = buffer_dest[idx_dest].w;
161183

162-
float4 pix = read_imagef(buffer_src, sampleri, (int2)(x, y));
184+
float4 pix = readpixel(buffer_src, x, y);
163185
buffer_dest[idx_dest] = buffer_dest[idx_dest] * (1.0f - f) + pix * f;
164186

165187
buffer_dest[idx_dest].w = w;
166188
}
167189

168190
kernel void
169-
retouch_image_rgb2lab(global float4 *in, int width, int height)
191+
retouch_image_rgb2lab(global float4 *in,
192+
int width,
193+
int height)
170194
{
171195
const int x = get_global_id(0);
172196
const int y = get_global_id(1);
@@ -179,7 +203,9 @@ retouch_image_rgb2lab(global float4 *in, int width, int height)
179203
}
180204

181205
kernel void
182-
retouch_image_lab2rgb(global float4 *in, int width, int height)
206+
retouch_image_lab2rgb(global float4 *in,
207+
int width,
208+
int height)
183209
{
184210
const int x = get_global_id(0);
185211
const int y = get_global_id(1);

src/common/interpolation.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ static inline void _compute_downsampling_kernel(const dt_interpolation_t *itor,
490490
}
491491

492492
/* --------------------------------------------------------------------------
493-
* Sample interpolation function (see usage in iop/lens.c and iop/clipping.c)
493+
* Sample interpolation function (see usage in iop/lens.c and mask distortions)
494494
* ------------------------------------------------------------------------*/
495495

496496
#define MAX_KERNEL_REQ ((2 * (MAX_HALF_FILTER_WIDTH) + 3) & (~3))
@@ -516,11 +516,11 @@ float dt_interpolation_compute_sample(const dt_interpolation_t *itor,
516516
int ix = (int)x;
517517
int iy = (int)y;
518518

519+
float s = 0.0f;
519520
/* Now 2 cases, the pixel + filter width goes outside the image
520521
* in that case we have to use index clipping to keep all reads
521522
* in the input image (slow path) or we are sure it won't fall
522523
* outside and can do more simple code */
523-
float r;
524524
if(ix >= (itor->width - 1)
525525
&& iy >= (itor->width - 1)
526526
&& ix < (width - itor->width)
@@ -533,7 +533,6 @@ float dt_interpolation_compute_sample(const dt_interpolation_t *itor,
533533
in = in - (itor->width - 1) * (samplestride + linestride);
534534

535535
// Apply the kernel
536-
float s = 0.f;
537536
for(int i = 0; i < 2 * itor->width; i++)
538537
{
539538
float h = 0.0f;
@@ -544,7 +543,7 @@ float dt_interpolation_compute_sample(const dt_interpolation_t *itor,
544543
s += kernelv[i] * h;
545544
in += linestride;
546545
}
547-
r = s / (normh * normv);
546+
s = s / (normh * normv);
548547
}
549548
else if(ix >= 0 && iy >= 0 && ix < width && iy < height)
550549
{
@@ -568,7 +567,6 @@ float dt_interpolation_compute_sample(const dt_interpolation_t *itor,
568567
bordermode, 2 * itor->width, iy, height);
569568

570569
// Apply the kernel
571-
float s = 0.f;
572570
for(ssize_t i = ytap_first; i < ytap_last; i++)
573571
{
574572
const ssize_t clip_y = _clip(iy + i, 0, height - 1, bordermode);
@@ -581,19 +579,13 @@ float dt_interpolation_compute_sample(const dt_interpolation_t *itor,
581579
}
582580
s += kernelv[i] * h;
583581
}
584-
585-
r = s / (normh * normv);
586-
}
587-
else
588-
{
589-
// invalid coordinate
590-
r = 0.0f;
582+
s = s / (normh * normv);
591583
}
592-
return fmaxf(0.0f, r); // make sure we don't push NaNs
584+
return s; // if called for masks make sure to CLIP to avoid interpolator under/overshoots
593585
}
594586

595587
/* --------------------------------------------------------------------------
596-
* Pixel interpolation function (see usage in iop/lens.c and iop/clipping.c)
588+
* Pixel interpolation function (see usage in ashift.c)
597589
* ------------------------------------------------------------------------*/
598590

599591
void dt_interpolation_compute_pixel4c(const dt_interpolation_t *itor,

0 commit comments

Comments
 (0)