Skip to content

Commit 997e5d1

Browse files
Highlights reconstruction uses exif tag LinearResponseLimit
It's better to set the clip level to what we got via exif LinearResponseLimit instead of defaulting to 1.0 in `reload_defaults()` Otherwise code style maintenance - removed struct in function headers - use 'd' for 'data' - missed a case using a magic float instead of value from highlights_clip_magics - avoid overcast
1 parent 14d595c commit 997e5d1

File tree

4 files changed

+56
-55
lines changed

4 files changed

+56
-55
lines changed

src/common/exif.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,8 @@ static void _check_linear_response_limit(Exiv2::ExifData &exifData,
863863
{
864864
bool found_one = false;
865865

866+
// currently this only reads the dng tag, could also be used for other raws
867+
866868
Exiv2::ExifData::const_iterator linr =
867869
exifData.findKey(Exiv2::ExifKey("Exif.Image.LinearResponseLimit"));
868870
if(linr != exifData.end() && linr->count() == 1)
@@ -871,7 +873,6 @@ static void _check_linear_response_limit(Exiv2::ExifData &exifData,
871873
found_one = true;
872874
}
873875

874-
// currently this only reads the dng tag, could also be used for other raws
875876
if(found_one)
876877
dt_print(DT_DEBUG_IMAGEIO, "[exif] `%s` has LinearResponseLimit %.4f",
877878
img->filename, img->linear_response_limit);

src/iop/highlights.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,11 @@ void modify_roi_in(dt_iop_module_t *self,
385385
roi_in->scale = 1.0f;
386386
}
387387

388-
void tiling_callback(struct dt_iop_module_t *self,
389-
struct dt_dev_pixelpipe_iop_t *piece,
388+
void tiling_callback(dt_iop_module_t *self,
389+
dt_dev_pixelpipe_iop_t *piece,
390390
const dt_iop_roi_t *roi_in,
391391
const dt_iop_roi_t *roi_out,
392-
struct dt_develop_tiling_t *tiling)
392+
dt_develop_tiling_t *tiling)
393393
{
394394
dt_iop_highlights_data_t *d = piece->data;
395395
const uint32_t filters = piece->pipe->dsc.filters;
@@ -407,8 +407,7 @@ void tiling_callback(struct dt_iop_module_t *self,
407407
tiling->overhead = 0;
408408
tiling->overlap = 0;
409409

410-
dt_develop_blend_params_t *const bldata =
411-
(dt_develop_blend_params_t *const)piece->blendop_data;
410+
dt_develop_blend_params_t *const bldata = piece->blendop_data;
412411
if(bldata
413412
&& (piece->pipe->store_all_raster_masks || dt_iop_is_raster_mask_used(self, BLEND_RASTER_ID)))
414413
{
@@ -464,7 +463,7 @@ void tiling_callback(struct dt_iop_module_t *self,
464463
}
465464

466465
#ifdef HAVE_OPENCL
467-
int process_cl(struct dt_iop_module_t *self,
466+
int process_cl(dt_iop_module_t *self,
468467
dt_dev_pixelpipe_iop_t *piece,
469468
cl_mem dev_in,
470469
cl_mem dev_out,
@@ -673,15 +672,15 @@ static void process_visualize(dt_dev_pixelpipe_iop_t *piece,
673672
void *const ovoid,
674673
const dt_iop_roi_t *const roi_in,
675674
const dt_iop_roi_t *const roi_out,
676-
dt_iop_highlights_data_t *data)
675+
dt_iop_highlights_data_t *d)
677676
{
678677
const uint8_t(*const xtrans)[6] = (const uint8_t(*const)[6])piece->pipe->dsc.xtrans;
679678
const uint32_t filters = piece->pipe->dsc.filters;
680679
const gboolean is_xtrans = (filters == 9u);
681680
const float *const in = (const float *const)ivoid;
682681
float *const out = (float *const)ovoid;
683682

684-
const float mclip = data->clip * highlights_clip_magics[data->mode];
683+
const float mclip = d->clip * highlights_clip_magics[d->mode];
685684
const float *cf = piece->pipe->dsc.temperature.coeffs;
686685
const float clips[4] = { mclip * (cf[RED] <= 0.0f ? 1.0f : cf[RED]),
687686
mclip * (cf[GREEN] <= 0.0f ? 1.0f : cf[GREEN]),
@@ -724,27 +723,28 @@ static void process_visualize(dt_dev_pixelpipe_iop_t *piece,
724723
}
725724
}
726725

727-
void process(struct dt_iop_module_t *self,
726+
void process(dt_iop_module_t *self,
728727
dt_dev_pixelpipe_iop_t *piece,
729728
const void *const ivoid,
730729
void *const ovoid,
731730
const dt_iop_roi_t *const roi_in,
732731
const dt_iop_roi_t *const roi_out)
733732
{
734733
const uint32_t filters = piece->pipe->dsc.filters;
735-
dt_iop_highlights_data_t *data = piece->data;
734+
dt_iop_highlights_data_t *d = piece->data;
736735
dt_iop_highlights_gui_data_t *g = self->gui_data;
737736

738737
const gboolean fullpipe = piece->pipe->type & DT_DEV_PIXELPIPE_FULL;
739738
const gboolean fastmode = piece->pipe->type & DT_DEV_PIXELPIPE_FAST;
739+
740740
if(g && fullpipe)
741741
{
742742
if(g->hlr_mask_mode != DT_HIGHLIGHTS_MASK_OFF)
743743
{
744744
piece->pipe->mask_display = DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU;
745745
if(g->hlr_mask_mode == DT_HIGHLIGHTS_MASK_CLIPPED)
746746
{
747-
process_visualize(piece, ivoid, ovoid, roi_in, roi_out, data);
747+
process_visualize(piece, ivoid, ovoid, roi_in, roi_out, d);
748748
return;
749749
}
750750
}
@@ -760,11 +760,11 @@ void process(struct dt_iop_module_t *self,
760760
high_quality = (level >= min_s);
761761
}
762762

763-
const float clip = data->clip * dt_iop_get_processed_minimum(piece);
763+
const float clip = d->clip * dt_iop_get_processed_minimum(piece);
764764

765765
if(filters == 0)
766766
{
767-
if(data->mode == DT_IOP_HIGHLIGHTS_CLIP)
767+
if(d->mode == DT_IOP_HIGHLIGHTS_CLIP)
768768
{
769769
process_clip(self, piece, ivoid, ovoid, roi_in, roi_out, clip);
770770
const float m = dt_iop_get_processed_minimum(piece);
@@ -778,13 +778,13 @@ void process(struct dt_iop_module_t *self,
778778
return;
779779
}
780780

781-
const dt_iop_highlights_mode_t dmode = fastmode && (data->mode == DT_IOP_HIGHLIGHTS_SEGMENTS)
782-
? DT_IOP_HIGHLIGHTS_OPPOSED : data->mode;
781+
const dt_iop_highlights_mode_t dmode = fastmode && (d->mode == DT_IOP_HIGHLIGHTS_SEGMENTS)
782+
? DT_IOP_HIGHLIGHTS_OPPOSED : d->mode;
783783
switch(dmode)
784784
{
785785
case DT_IOP_HIGHLIGHTS_INPAINT: // a1ex's (magiclantern) idea of color inpainting:
786786
{
787-
const float clipper = data->clip * highlights_clip_magics[DT_IOP_HIGHLIGHTS_INPAINT];
787+
const float clipper = d->clip * highlights_clip_magics[DT_IOP_HIGHLIGHTS_INPAINT];
788788
const float clips[4] = { clipper * piece->pipe->dsc.processed_maximum[0],
789789
clipper * piece->pipe->dsc.processed_maximum[1],
790790
clipper * piece->pipe->dsc.processed_maximum[2], clip };
@@ -840,7 +840,7 @@ void process(struct dt_iop_module_t *self,
840840

841841
float *tmp = _process_opposed(self, piece, ivoid, ovoid, roi_in, roi_out, TRUE, TRUE);
842842
if(tmp)
843-
_process_segmentation(piece, ivoid, ovoid, roi_in, roi_out, data, vmode, tmp);
843+
_process_segmentation(piece, ivoid, ovoid, roi_in, roi_out, d, vmode, tmp);
844844
dt_free_align(tmp);
845845
break;
846846
}
@@ -853,7 +853,7 @@ void process(struct dt_iop_module_t *self,
853853

854854
case DT_IOP_HIGHLIGHTS_LAPLACIAN:
855855
{
856-
const float clipper = data->clip * highlights_clip_magics[DT_IOP_HIGHLIGHTS_LAPLACIAN];
856+
const float clipper = d->clip * highlights_clip_magics[DT_IOP_HIGHLIGHTS_LAPLACIAN];
857857
const dt_aligned_pixel_t clips = { clipper * piece->pipe->dsc.processed_maximum[0],
858858
clipper * piece->pipe->dsc.processed_maximum[1],
859859
clipper * piece->pipe->dsc.processed_maximum[2], clip };
@@ -869,7 +869,7 @@ void process(struct dt_iop_module_t *self,
869869
}
870870

871871
// update processed maximum
872-
if((data->mode != DT_IOP_HIGHLIGHTS_LAPLACIAN) && (data->mode != DT_IOP_HIGHLIGHTS_SEGMENTS) && (data->mode != DT_IOP_HIGHLIGHTS_OPPOSED))
872+
if((d->mode != DT_IOP_HIGHLIGHTS_LAPLACIAN) && (d->mode != DT_IOP_HIGHLIGHTS_SEGMENTS) && (d->mode != DT_IOP_HIGHLIGHTS_OPPOSED))
873873
{
874874
// The guided laplacian, inpaint opposed and segmentation modes keep signal scene-referred and don't clip highlights to 1
875875
// For the other modes, we need to notify the pipeline that white point has changed
@@ -878,7 +878,7 @@ void process(struct dt_iop_module_t *self,
878878
}
879879
}
880880

881-
void commit_params(struct dt_iop_module_t *self,
881+
void commit_params(dt_iop_module_t *self,
882882
dt_iop_params_t *p1,
883883
dt_dev_pixelpipe_t *pipe,
884884
dt_dev_pixelpipe_iop_t *piece)
@@ -919,8 +919,7 @@ void commit_params(struct dt_iop_module_t *self,
919919
void init_global(dt_iop_module_so_t *module)
920920
{
921921
const int program = 2; // basic.cl, from programs.conf
922-
dt_iop_highlights_global_data_t *gd
923-
= (dt_iop_highlights_global_data_t *)malloc(sizeof(dt_iop_highlights_global_data_t));
922+
dt_iop_highlights_global_data_t *gd = malloc(sizeof(dt_iop_highlights_global_data_t));
924923
module->data = gd;
925924
gd->kernel_highlights_1f_clip = dt_opencl_create_kernel(program, "highlights_1f_clip");
926925
gd->kernel_highlights_1f_lch_bayer = dt_opencl_create_kernel(program, "highlights_1f_lch_bayer");
@@ -1050,7 +1049,7 @@ void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
10501049
}
10511050
}
10521051

1053-
void gui_update(struct dt_iop_module_t *self)
1052+
void gui_update(dt_iop_module_t *self)
10541053
{
10551054
dt_iop_highlights_gui_data_t *g = self->gui_data;
10561055
const dt_image_t *img = &self->dev->image_storage;
@@ -1124,6 +1123,7 @@ void reload_defaults(dt_iop_module_t *self)
11241123
dt_bauhaus_widget_set_quad_active(g->strength, FALSE);
11251124
g->hlr_mask_mode = DT_HIGHLIGHTS_MASK_OFF;
11261125
}
1126+
d->clip = MIN(d->clip, img->linear_response_limit);
11271127
}
11281128

11291129
static void _visualize_callback(GtkWidget *quad, dt_iop_module_t *self)

src/iop/hlreconstruct/opposed.c

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,13 @@ static inline char _mask_dilated(const char *in, const size_t w1)
9191

9292

9393
// A slightly modified version for sraws
94-
static void _process_linear_opposed(
95-
struct dt_iop_module_t *self,
96-
dt_dev_pixelpipe_iop_t *piece,
97-
const float *const input,
98-
float *const output,
99-
const dt_iop_roi_t *const roi_in,
100-
const dt_iop_roi_t *const roi_out,
101-
const gboolean quality)
94+
static void _process_linear_opposed(dt_iop_module_t *self,
95+
dt_dev_pixelpipe_iop_t *piece,
96+
const float *const input,
97+
float *const output,
98+
const dt_iop_roi_t *const roi_in,
99+
const dt_iop_roi_t *const roi_out,
100+
const gboolean quality)
102101
{
103102
dt_iop_highlights_data_t *d = piece->data;
104103
const float clipval = highlights_clip_magics[DT_IOP_HIGHLIGHTS_OPPOSED] * d->clip;
@@ -203,20 +202,20 @@ static void _process_linear_opposed(
203202
}
204203
}
205204

206-
static float *_process_opposed(
207-
struct dt_iop_module_t *self,
208-
dt_dev_pixelpipe_iop_t *piece,
209-
const float *const input,
210-
float *const output,
211-
const dt_iop_roi_t *const roi_in,
212-
const dt_iop_roi_t *const roi_out,
213-
const gboolean keep,
214-
const gboolean quality)
205+
static float *_process_opposed(dt_iop_module_t *self,
206+
dt_dev_pixelpipe_iop_t *piece,
207+
const float *const input,
208+
float *const output,
209+
const dt_iop_roi_t *const roi_in,
210+
const dt_iop_roi_t *const roi_out,
211+
const gboolean keep,
212+
const gboolean quality)
215213
{
216214
dt_iop_highlights_data_t *d = piece->data;
217215
const uint8_t(*const xtrans)[6] = (const uint8_t(*const)[6])piece->pipe->dsc.xtrans;
218216
const uint32_t filters = piece->pipe->dsc.filters;
219217
const float clipval = highlights_clip_magics[DT_IOP_HIGHLIGHTS_OPPOSED] * d->clip;
218+
220219
const dt_iop_buffer_dsc_t *dsc = &piece->pipe->dsc;
221220
const gboolean wbon = dsc->temperature.enabled;
222221
const dt_aligned_pixel_t icoeffs = { wbon ? dsc->temperature.coeffs[0] : 1.0f,
@@ -398,19 +397,19 @@ static float *_process_opposed(
398397
}
399398

400399
#ifdef HAVE_OPENCL
401-
static cl_int process_opposed_cl(
402-
struct dt_iop_module_t *self,
403-
dt_dev_pixelpipe_iop_t *piece,
404-
cl_mem dev_in,
405-
cl_mem dev_out,
406-
const dt_iop_roi_t *const roi_in,
407-
const dt_iop_roi_t *const roi_out)
400+
static cl_int process_opposed_cl(dt_iop_module_t *self,
401+
dt_dev_pixelpipe_iop_t *piece,
402+
cl_mem dev_in,
403+
cl_mem dev_out,
404+
const dt_iop_roi_t *const roi_in,
405+
const dt_iop_roi_t *const roi_out)
408406
{
409407
dt_iop_highlights_data_t *d = piece->data;
410408
const dt_iop_highlights_global_data_t *gd = self->global_data;
411409

412410
const int devid = piece->pipe->devid;
413411
const uint32_t filters = piece->pipe->dsc.filters;
412+
414413
const float clipval = highlights_clip_magics[DT_IOP_HIGHLIGHTS_OPPOSED] * d->clip;
415414
const dt_iop_buffer_dsc_t *dsc = &piece->pipe->dsc;
416415
const gboolean wbon = dsc->temperature.enabled;

src/iop/hlreconstruct/segbased.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -453,14 +453,15 @@ static void _process_segmentation(dt_dev_pixelpipe_iop_t *piece,
453453
float *const output,
454454
const dt_iop_roi_t *const roi_in,
455455
const dt_iop_roi_t *const roi_out,
456-
dt_iop_highlights_data_t *data,
456+
dt_iop_highlights_data_t *d,
457457
const int vmode,
458458
float *tmpout)
459459
{
460460
const uint8_t(*const xtrans)[6] = (const uint8_t(*const)[6])piece->pipe->dsc.xtrans;
461461
const uint32_t filters = piece->pipe->dsc.filters;
462462
const gboolean fullpipe = piece->pipe->type & DT_DEV_PIXELPIPE_FULL;
463-
const float clipval = fmaxf(0.1f, 0.987f * data->clip);
463+
const float clipval = MAX(0.1f, highlights_clip_magics[DT_IOP_HIGHLIGHTS_SEGMENTS] * d->clip);
464+
464465
const dt_aligned_pixel_t icoeffs = { piece->pipe->dsc.temperature.coeffs[0], piece->pipe->dsc.temperature.coeffs[1], piece->pipe->dsc.temperature.coeffs[2]};
465466
const dt_aligned_pixel_t clips = { clipval * icoeffs[0], clipval * icoeffs[1], clipval * icoeffs[2]};
466467
const dt_aligned_pixel_t cube_coeffs = { powf(clips[0], 1.0f / HL_POWERF), powf(clips[1], 1.0f / HL_POWERF), powf(clips[2], 1.0f / HL_POWERF)};
@@ -471,8 +472,8 @@ static void _process_segmentation(dt_dev_pixelpipe_iop_t *piece,
471472
late ? (float)(chr->D65coeffs[1] / chr->as_shot[1]) : 1.0f,
472473
late ? (float)(chr->D65coeffs[2] / chr->as_shot[2]) : 1.0f,
473474
1.0f };
474-
const int recovery_mode = data->recovery;
475-
const float strength = data->strength;
475+
const int recovery_mode = d->recovery;
476+
const float strength = d->strength;
476477

477478
const int recovery_closing[NUM_RECOVERY_MODES] = { 0, 0, 0, 2, 2, 0, 2};
478479
const int recovery_close = recovery_closing[recovery_mode];
@@ -574,7 +575,7 @@ static void _process_segmentation(dt_dev_pixelpipe_iop_t *piece,
574575
_masks_extend_border(plane[i], pwidth, pheight, HL_BORDER);
575576

576577
for(int p = 0; p < HL_RGB_PLANES; p++)
577-
dt_segments_combine(&isegments[p], data->combine);
578+
dt_segments_combine(&isegments[p], d->combine);
578579

579580
if(dt_get_num_threads() >= HL_RGB_PLANES)
580581
{
@@ -590,7 +591,7 @@ static void _process_segmentation(dt_dev_pixelpipe_iop_t *piece,
590591
}
591592

592593
for(int p = 0; p < HL_RGB_PLANES; p++)
593-
_calc_plane_candidates(plane[p], refavg[p], &isegments[p], cube_coeffs[p], data->candidating);
594+
_calc_plane_candidates(plane[p], refavg[p], &isegments[p], cube_coeffs[p], d->candidating);
594595

595596
DT_OMP_FOR(collapse(2))
596597
for(int row = 1; row < roi_in->height-1; row++)
@@ -670,7 +671,7 @@ static void _process_segmentation(dt_dev_pixelpipe_iop_t *piece,
670671

671672
dt_gaussian_fast_blur(recout, gradient, pwidth, pheight, 1.2f, 0.0f, 20.0f, 1);
672673
// possibly add some noise
673-
const float noise_level = data->noise_level;
674+
const float noise_level = d->noise_level;
674675
if(noise_level > 0.0f)
675676
{
676677
for(uint32_t id = 2; id < segall->nr; id++)

0 commit comments

Comments
 (0)