Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
distance_transform.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2021 Hanno Schwalm.
4 Copyright (C) 2021 Pascal Obry.
5 Copyright (C) 2022 Martin Bařinka.
6 Copyright (C) 2023, 2026 Aurélien PIERRE.
7 Copyright (C) 2024 Alynx Zhou.
8
9 darktable is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 darktable is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with darktable. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#ifndef DT_PIXEL_DISTANCE_TRANSFORM_H
24#define DT_PIXEL_DISTANCE_TRANSFORM_H
25
26/*
27 eucledian distance transform for darktable Hanno Schwalm (hanno@schwalm-bremen.de) 2021/09
28 - adopted to C
29 - omp support
30 - reduced alloc/free using dt_alloc_align variants for better debug support
31 - tuned for performance in collaboration with Ingo Weyrich (heckflosse67@gmx.de) from rawtherapee
32
33 The original code is from:
34
35 *** Original copyright note ***
36 Implementation of the distance transform algorithm described in:
37
38 Distance Transforms of Sampled Functions
39 Pedro F. Felzenszwalb and Daniel P. Huttenlocher
40 Cornell Computing and Information Science TR2004-1963
41 Copyright (C) 2006 Pedro Felzenszwalb
42
43 This program is free software; you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
45 the Free Software Foundation; either version 2 of the License, or
46 (at your option) any later version.
47*/
48
49/* Howto
50 float dt_image_distance_transform(float *const restrict src, float *const restrict out, const size_t width, const size_t height,
51 const float clip, const dt_distance_transform_t mode)
52 writes data to an 1-ch image at 'out' with dimensions given. 'out' must be aligned as by dt_alloc_align_float.
53 You may either
54 - prepare the 'out' image before calling the distance transform, in this case use DT_DISTANCE_TRANSFORM_NONE as mode.
55 you should have filled 'out' with either 0.0f or DT_DISTANCE_TRANSFORM_MAX marking the positions as on/off
56 - use DT_DISTANCE_TRANSFORM_MASK, in this case data found in src is checked vs clip, dt_image_distance_transform
57 will fill in the zeros / DT_DISTANCE_TRANSFORM_MAX
58 The returned float of this function is the maximum calculated distance
59*/
60
61#include "common/imagebuf.h"
63
69
70#define DT_DISTANCE_TRANSFORM_MAX (1e20)
71
72static void _image_distance_transform(const float *f, float *z, float *d, int *v, const int n)
73{
74 int k = 0;
75 v[0] = 0;
78 for(int q = 1; q <= n-1; q++)
79 {
80 float s = (f[q] + sqf((float)q)) - (f[v[k]] + sqf((float)v[k]));
81 while(s <= z[k] * (float)(2*q - 2*v[k]))
82 {
83 k--;
84 s = (f[q] + sqf((float)q)) - (f[v[k]] + sqf((float)v[k]));
85 }
86 s /= (float)(2*q - 2*v[k]);
87 k++;
88 v[k] = q;
89 z[k] = s;
91 }
92
93 k = 0;
94 for(int q = 0; q <= n-1; q++)
95 {
96 while(z[k+1] < (float)q)
97 k++;
98 d[q] = sqf((float)(q-v[k])) + f[v[k]];
99 }
100}
101
102float dt_image_distance_transform(float *const restrict src, float *const restrict out, const size_t width, const size_t height, const float clip, const dt_distance_transform_t mode)
103{
104 switch(mode)
105 {
107 break;
109 __OMP_FOR_SIMD__(aligned(src, out : 64))
110 for(size_t i = 0; i < width * height; i++)
111 out[i] = (src[i] < clip) ? 0.0f : DT_DISTANCE_TRANSFORM_MAX;
112 break;
113 default:
114 dt_iop_image_fill(out, 0.0f, width, height, 1);
115 fprintf(stderr,"[dt_image_distance_transform] called with unsupported mode %i\n", mode);
116 return 0.0f;
117 }
118
119 const size_t maxdim = MAX(width, height);
120 float max_distance = 0.0f;
121#ifdef _OPENMP
122 #pragma omp parallel \
123 reduction(max : max_distance)
124#endif
125 {
127 float *z = dt_pixelpipe_cache_alloc_align_float_cache(maxdim + 1, 0);
129 int *v = dt_pixelpipe_cache_alloc_align_cache(maxdim * sizeof(int), 0);
130
131 // transform along columns
132#ifdef _OPENMP
133 #pragma omp for
134#endif
135 for(size_t x = 0; x < width; x++)
136 {
137 for(size_t y = 0; y < height; y++)
138 f[y] = out[y*width + x];
140 for(size_t y = 0; y < height; y++)
141 out[y*width + x] = d[y];
142 }
143 // implicit barrier :-)
144 // transform along rows
145#ifdef _OPENMP
146 #pragma omp for nowait
147#endif
148 for(size_t y = 0; y < height; y++)
149 {
151 for(size_t x = 0; x < width; x++)
152 {
153 const float val = sqrtf(d[x]);
154 out[y*width + x] = val;
155 max_distance = fmaxf(max_distance, val);
156 }
157 }
162 }
163 return max_distance;
164}
165
166#endif // DT_PIXEL_DISTANCE_TRANSFORM_H
167
168// clang-format off
169// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
170// vim: shiftwidth=2 expandtab tabstop=2 cindent
171// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
172// clang-format on
static const float x
const float f
const float v
const dt_colormatrix_t dt_aligned_pixel_t out
dt_distance_transform_t
@ DT_DISTANCE_TRANSFORM_NONE
@ DT_DISTANCE_TRANSFORM_MASK
float dt_image_distance_transform(float *const restrict src, float *const restrict out, const size_t width, const size_t height, const float clip, const dt_distance_transform_t mode)
#define DT_DISTANCE_TRANSFORM_MAX
static void _image_distance_transform(const float *f, float *z, float *d, int *v, const int n)
__DT_CLONE_TARGETS__ void dt_iop_image_fill(float *const buf, const float fill_value, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.c:218
float *const restrict const size_t k
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
#define __OMP_FOR_SIMD__(...)
Definition openmp.h:97
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
#define dt_pixelpipe_cache_free_align(mem)
#define MAX(a, b)
Definition thinplate.c:29