11/*
22 Distance_transform computation using the fast sweeping method
33 =========================================================================
4- v0.0.1
4+ v0.1.0
55 Licensed under the MIT License
6- (c) 2020 Vincent Cruz
6+ (c) 2020-2023 Vincent Cruz
77
88 This header file provides a function to compute the distance transform of an image.
99 The implementation is based upon the following papers:
2020 Before including this file, add the following line in the file where you want to have the
2121 implementation.
2222 #define DISTANCE_TRANSFORM_IMPLEMENTATION
23-
24- You can define DISTANCE_TRANSFORM_MALLOC and DISTANCE_TRANSFORM_FREE before the include
25- to replace malloc and free.
2623
2724 * Usage:
2825
29- float* distance_transform(const uint8_t *in, int width, int height);
26+ void distance_transform(const uint8_t *in, float *out , int width, int height);
3027
3128 "in" is the pointer an 8bpp greyscale image.
29+ "output" is the pointer to the a floating point array of at least width*height elements.
30+ It will contain the distance map.
3231 "width" and "height" are its dimension.
3332 All pixels with a value of 0 are considered to be "inside", whereas any non-zero pixel is
3433 considered outside. As a consequence, a pixel is considered to be on the boundary if its
3534 value is 0 and at least one of its 8-neighbour is not zero.
36-
37- "distance_transform" returns a pointer to an array of "width*height" floating point numbers
38- containing for each pixel the distance to the closest boundary point.
39- This array is allocated with `DISTANCE_TRANSFORM_MALLOC`. Use `DISTANCE_TRANSFORM_FREE`
40- to delete it.
41-
35+
4236 * Note:
4337 This piece of code is not meant to be "production ready".
4438
5549extern "C" {
5650#endif
5751
58- float * distance_transform (const uint8_t * in , int width , int height );
52+ void distance_transform (const uint8_t * in , float * output , int width , int height );
5953
6054#ifdef __cplusplus
6155}
@@ -65,31 +59,13 @@ float* distance_transform(const uint8_t *in, int width, int height);
6559
6660#ifdef DISTANCE_TRANSFORM_IMPLEMENTATION
6761
68- #if defined(DISTANCE_TRANSFORM_MALLOC ) && defined(DISTANCE_TRANSFORM_FREE )
69- // ok
70- #elif !defined(DISTANCE_TRANSFORM_MALLOC ) && !defined(DISTANCE_TRANSFORM_FREE )
71- // ok
72- #else
73- #error "Must define all or none of DISTANCE_TRANSFORM_MALLOC and DISTANCE_TRANSFORM_FREE"
74- #endif
75-
76- #if !defined(DISTANCE_TRANSFORM_MALLOC )
77- #define DISTANCE_TRANSFORM_MALLOC (sz ) malloc(sz)
78- #define DISTANCE_TRANSFORM_FREE (p ) free(p)
79- #endif
80-
81- float * distance_transform (const uint8_t * in , int width , int height ) {
62+ void distance_transform (const uint8_t * in , float * out , int width , int height ) {
8263 int i , j ;
8364 uint8_t c ;
84- const float max_dist = width * width + height * height ;
85- float * out = (float * )DISTANCE_TRANSFORM_MALLOC (width * height * sizeof (float ));
65+ const float max_dist = (float )(width * width + height * height );
8666 float * ptr = out ;
8767 float * line ;
8868
89- if (out == NULL ) {
90- return NULL ;
91- }
92-
9369 // Initialize distance map by setting distance at boundary point to 0 and any other points to the maximal possible distance (width^2 + height^2).
9470 // A boundary point is a pixel with a value of 0 and with a least one of its 8-neightbours different from 0.
9571 c = ~in [0 ] & (in [1 ] | in [width ] | in [width + 1 ]);
@@ -137,110 +113,108 @@ float* distance_transform(const uint8_t *in, int width, int height) {
137113 // Update distance in the 4 sweeping directions.
138114#define update_distance (dx ,dy ,inc ) \
139115do { \
140- ptr[0] = fmin (ptr[0], (fabs((dx)-(dy)) >= 1) ? (fmin ((dx), (dy)) + 1.f) : (((dx) + (dy) + sqrt (2.f - ((dx)-(dy))*((dx)-(dy)))) / 2.f)); \
116+ ptr[0] = fminf (ptr[0], (fabs((dx)-(dy)) >= 1) ? (fminf ((dx), (dy)) + 1.f) : (((dx) + (dy) + sqrtf (2.f - ((dx)-(dy))*((dx)-(dy)))) / 2.f)); \
141117 ptr += (inc); \
142118} while(0)
143119
144120 // y=[0,height[ x=[0,width[
145121 ptr = out ;
146122 update_distance (ptr [1 ], ptr [width ], +1 );
147123 for (i = 1 ; i < (width - 1 ); i ++ ) {
148- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [width ], +1 );
124+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [width ], +1 );
149125 }
150126 update_distance (ptr [-1 ], ptr [width ], +1 );
151127
152128 line = ptr ;
153129 for (j = 1 ; j < (height - 1 ); j ++ , line += width ) {
154130 ptr = line ;
155- update_distance (ptr [1 ], fmin (ptr [- width ], ptr [width ]), +1 );
131+ update_distance (ptr [1 ], fminf (ptr [- width ], ptr [width ]), +1 );
156132 for (i = 1 ; i < (width - 1 ); i ++ ) {
157- update_distance (fmin (ptr [-1 ], ptr [1 ]), fmin (ptr [- width ], ptr [width ]), +1 );
133+ update_distance (fminf (ptr [-1 ], ptr [1 ]), fminf (ptr [- width ], ptr [width ]), +1 );
158134 }
159- update_distance (ptr [-1 ], fmin (ptr [- width ], ptr [width ]), +1 );
135+ update_distance (ptr [-1 ], fminf (ptr [- width ], ptr [width ]), +1 );
160136 }
161137
162138 update_distance (ptr [1 ], ptr [- width ], +1 );
163139 for (i = 1 ; i < (width - 1 ); i ++ ) {
164- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [- width ], +1 );
140+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [- width ], +1 );
165141 }
166142 update_distance (ptr [-1 ], ptr [- width ], +1 );
167143
168144 // y=[0,height[ x=]width,0]
169145 ptr = out + width - 1 ;
170146 update_distance (ptr [-1 ], ptr [width ], -1 );
171147 for (i = 1 ; i < (width - 1 ); i ++ ) {
172- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [width ], -1 );
148+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [width ], -1 );
173149 }
174150 update_distance (ptr [1 ], ptr [width ], -1 );
175151
176152 line = out + width ;
177153 for (j = 1 ; j < (height - 1 ); j ++ , line += width ) {
178154 ptr = line + width - 1 ;
179155
180- update_distance (ptr [-1 ], fmin (ptr [- width ], ptr [width ]), -1 );
156+ update_distance (ptr [-1 ], fminf (ptr [- width ], ptr [width ]), -1 );
181157 for (i = 1 ; i < (width - 1 ); i ++ ) {
182- update_distance (fmin (ptr [-1 ], ptr [1 ]), fmin (ptr [- width ], ptr [width ]), -1 );
158+ update_distance (fminf (ptr [-1 ], ptr [1 ]), fminf (ptr [- width ], ptr [width ]), -1 );
183159 }
184- update_distance (ptr [1 ], fmin (ptr [- width ], ptr [width ]), -1 );
160+ update_distance (ptr [1 ], fminf (ptr [- width ], ptr [width ]), -1 );
185161 }
186162
187163 ptr = line + width - 1 ;
188164 update_distance (ptr [-1 ], ptr [- width ], -1 );
189165 for (i = 1 ; i < (width - 1 ); i ++ ) {
190- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [- width ], -1 );
166+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [- width ], -1 );
191167 }
192168 update_distance (ptr [1 ], ptr [- width ], -1 );
193169
194170 // y=]height,0] x=]width,0]
195171 ptr = out + width - 1 + (height - 1 )* width ;
196172 update_distance (ptr [-1 ], ptr [- width ], -1 );
197173 for (i = 1 ; i < (width - 1 ); i ++ ) {
198- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [- width ], -1 );
174+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [- width ], -1 );
199175 }
200176 update_distance (ptr [1 ], ptr [- width ], -1 );
201177
202178 for (j = 1 ; j < (height - 1 ); j ++ ) {
203- update_distance (ptr [-1 ], fmin (ptr [- width ], ptr [width ]), -1 );
179+ update_distance (ptr [-1 ], fminf (ptr [- width ], ptr [width ]), -1 );
204180 for (i = 1 ; i < (width - 1 ); i ++ ) {
205- update_distance (fmin (ptr [-1 ], ptr [1 ]), fmin (ptr [- width ], ptr [width ]), -1 );
181+ update_distance (fminf (ptr [-1 ], ptr [1 ]), fminf (ptr [- width ], ptr [width ]), -1 );
206182 }
207- update_distance (ptr [1 ], fmin (ptr [- width ], ptr [width ]), -1 );
183+ update_distance (ptr [1 ], fminf (ptr [- width ], ptr [width ]), -1 );
208184 }
209185
210186 update_distance (ptr [-1 ], ptr [width ], -1 );
211187 for (i = 1 ; i < (width - 1 ); i ++ ) {
212- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [width ], -1 );
188+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [width ], -1 );
213189 }
214190 update_distance (ptr [1 ], ptr [width ], -1 );
215191
216192 // y=]height,0] x=[0,width[
217193 line = ptr = out + (height - 1 )* width ;
218194 update_distance (ptr [1 ], ptr [- width ], +1 );
219195 for (i = 1 ; i < (width - 1 ); i ++ ) {
220- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [- width ], +1 );
196+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [- width ], +1 );
221197 }
222198 update_distance (ptr [-1 ], ptr [- width ], +1 );
223199
224200 line -= width ;
225201 for (j = 1 ; j < (height - 1 ); j ++ , line -= width ) {
226202 ptr = line ;
227- update_distance (ptr [1 ], fmin (ptr [- width ], ptr [width ]), +1 );
203+ update_distance (ptr [1 ], fminf (ptr [- width ], ptr [width ]), +1 );
228204 for (i = 1 ; i < (width - 1 ); i ++ ) {
229- update_distance (fmin (ptr [-1 ], ptr [1 ]), fmin (ptr [- width ], ptr [width ]), +1 );
205+ update_distance (fminf (ptr [-1 ], ptr [1 ]), fminf (ptr [- width ], ptr [width ]), +1 );
230206 }
231- update_distance (ptr [-1 ], fmin (ptr [- width ], ptr [width ]), +1 );
207+ update_distance (ptr [-1 ], fminf (ptr [- width ], ptr [width ]), +1 );
232208 }
233209
234210 ptr = line ;
235211 update_distance (ptr [1 ], ptr [width ], +1 );
236212 for (i = 1 ; i < (width - 1 ); i ++ ) {
237- update_distance (fmin (ptr [-1 ], ptr [1 ]), ptr [width ], +1 );
213+ update_distance (fminf (ptr [-1 ], ptr [1 ]), ptr [width ], +1 );
238214 }
239215 update_distance (ptr [-1 ], ptr [width ], +1 );
240216
241217#undef update_distance
242-
243- return out ;
244218}
245219
246220#endif /* DISTANCE_TRANSFORM_IMPLEMENTATION */
0 commit comments