File indexing completed on 2024-04-28 03:43:54
0001 /* 0002 SPDX-FileCopyrightText: 1993-2011 Emmanuel Bertin -- IAP /CNRS/UPMC 0003 SPDX-FileCopyrightText: 2014 SEP developers 0004 0005 SPDX-License-Identifier: LGPL-3.0-or-later 0006 */ 0007 0008 /* Note: was extract.c in SExtractor. */ 0009 0010 #include <math.h> 0011 #include <stdio.h> 0012 #include <stdlib.h> 0013 #include <string.h> 0014 #include "sep.h" 0015 #include "sepcore.h" 0016 #include "extract.h" 0017 0018 #define NOBJ 256 /* starting number of obj. */ 0019 0020 void lutzsort(infostruct *, objliststruct *); 0021 0022 /*------------------------- Static buffers for lutz() -----------------------*/ 0023 0024 static infostruct *info=NULL, *store=NULL; 0025 static char *marker=NULL; 0026 static pixstatus *psstack=NULL; 0027 static int *start=NULL, *end=NULL, *discan=NULL; 0028 static int xmin, ymin, xmax, ymax; 0029 0030 0031 /******************************* lutzalloc ***********************************/ 0032 /* 0033 Allocate once for all memory space for buffers used by lutz(). 0034 */ 0035 int lutzalloc(int width, int height) 0036 { 0037 int *discant; 0038 int stacksize, i, status=RETURN_OK; 0039 0040 stacksize = width+1; 0041 xmin = ymin = 0; 0042 xmax = width-1; 0043 ymax = height-1; 0044 QMALLOC(info, infostruct, stacksize, status); 0045 QMALLOC(store, infostruct, stacksize, status); 0046 QMALLOC(marker, char, stacksize, status); 0047 QMALLOC(psstack, pixstatus, stacksize, status); 0048 QMALLOC(start, int, stacksize, status); 0049 QMALLOC(end, int, stacksize, status); 0050 QMALLOC(discan, int, stacksize, status); 0051 discant = discan; 0052 for (i=stacksize; i--;) 0053 *(discant++) = -1; 0054 0055 return status; 0056 0057 exit: 0058 lutzfree(); 0059 0060 return status; 0061 } 0062 0063 /******************************* lutzfree ************************************/ 0064 /* 0065 Free once for all memory space for buffers used by lutz(). 0066 */ 0067 void lutzfree() 0068 { 0069 free(discan); 0070 discan = NULL; 0071 free(info); 0072 info = NULL; 0073 free(store); 0074 store = NULL; 0075 free(marker); 0076 marker = NULL; 0077 free(psstack); 0078 psstack = NULL; 0079 free(start); 0080 start = NULL; 0081 free(end); 0082 end = NULL; 0083 return; 0084 } 0085 0086 0087 /********************************** lutz *************************************/ 0088 /* 0089 C implementation of R.K LUTZ' algorithm for the extraction of 8-connected pi- 0090 xels in an image 0091 */ 0092 int lutz(pliststruct *plistin, 0093 int *objrootsubmap, int subx, int suby, int subw, 0094 objstruct *objparent, objliststruct *objlist, int minarea) 0095 { 0096 static infostruct curpixinfo,initinfo; 0097 objstruct *obj; 0098 pliststruct *plist,*pixel, *plistint; 0099 0100 char newmarker; 0101 int cn, co, luflag, pstop, xl,xl2,yl, 0102 out, deb_maxarea, stx,sty,enx,eny, step, 0103 nobjm = NOBJ, 0104 inewsymbol, *iscan; 0105 short trunflag; 0106 PIXTYPE thresh; 0107 pixstatus cs, ps; 0108 0109 out = RETURN_OK; 0110 0111 deb_maxarea = minarea<MAXDEBAREA?minarea:MAXDEBAREA; /* 3 or less */ 0112 plistint = plistin; 0113 stx = objparent->xmin; 0114 sty = objparent->ymin; 0115 enx = objparent->xmax; 0116 eny = objparent->ymax; 0117 thresh = objlist->thresh; 0118 initinfo.pixnb = 0; 0119 initinfo.flag = 0; 0120 initinfo.firstpix = initinfo.lastpix = -1; 0121 cn = 0; 0122 0123 iscan = objrootsubmap + (sty-suby)*subw + (stx-subx); 0124 0125 /* As we only analyze a fraction of the map, a step occurs between lines */ 0126 step = subw - (++enx-stx); 0127 eny++; 0128 0129 /*------Allocate memory to store object data */ 0130 free(objlist->obj); 0131 0132 if (!(obj=objlist->obj=(objstruct *)malloc(nobjm*sizeof(objstruct)))) 0133 { 0134 out = MEMORY_ALLOC_ERROR; 0135 plist = NULL; /* To avoid gcc -Wall warnings */ 0136 goto exit_lutz; 0137 } 0138 0139 /*------Allocate memory for the pixel list */ 0140 free(objlist->plist); 0141 if (!(objlist->plist 0142 = (pliststruct *)malloc((eny-sty)*(enx-stx)*plistsize))) 0143 { 0144 out = MEMORY_ALLOC_ERROR; 0145 plist = NULL; /* To avoid gcc -Wall warnings */ 0146 goto exit_lutz; 0147 } 0148 0149 pixel = plist = objlist->plist; 0150 0151 /*----------------------------------------*/ 0152 for (xl=stx; xl<=enx; xl++) 0153 marker[xl] = 0; 0154 0155 objlist->nobj = 0; 0156 co = pstop = 0; 0157 curpixinfo.pixnb = 1; 0158 0159 for (yl=sty; yl<=eny; yl++, iscan += step) 0160 { 0161 ps = COMPLETE; 0162 cs = NONOBJECT; 0163 trunflag = (yl==0 || yl==ymax) ? SEP_OBJ_TRUNC : 0; 0164 if (yl==eny) 0165 iscan = discan; 0166 0167 for (xl=stx; xl<=enx; xl++) 0168 { 0169 newmarker = marker[xl]; 0170 marker[xl] = 0; 0171 if ((inewsymbol = (xl!=enx)?*(iscan++):-1) < 0) 0172 luflag = 0; 0173 else 0174 { 0175 curpixinfo.flag = trunflag; 0176 plistint = plistin+inewsymbol; 0177 luflag = (PLISTPIX(plistint, cdvalue) > thresh?1:0); 0178 } 0179 if (luflag) 0180 { 0181 if (xl==0 || xl==xmax) 0182 curpixinfo.flag |= SEP_OBJ_TRUNC; 0183 memcpy(pixel, plistint, (size_t)plistsize); 0184 PLIST(pixel, nextpix) = -1; 0185 curpixinfo.lastpix = curpixinfo.firstpix = cn; 0186 cn += plistsize; 0187 pixel += plistsize; 0188 0189 /*----------------- Start Segment -----------------------------*/ 0190 if (cs != OBJECT) 0191 { 0192 cs = OBJECT; 0193 if (ps == OBJECT) 0194 { 0195 if (start[co] == UNKNOWN) 0196 { 0197 marker[xl] = 'S'; 0198 start[co] = xl; 0199 } 0200 else marker[xl] = 's'; 0201 } 0202 else 0203 { 0204 psstack[pstop++] = ps; 0205 marker[xl] = 'S'; 0206 start[++co] = xl; 0207 ps = COMPLETE; 0208 info[co] = initinfo; 0209 } 0210 } 0211 } 0212 0213 /*-------------------Process New Marker ---------------------------*/ 0214 if (newmarker) 0215 { 0216 if (newmarker == 'S') 0217 { 0218 psstack[pstop++] = ps; 0219 if (cs == NONOBJECT) 0220 { 0221 psstack[pstop++] = COMPLETE; 0222 info[++co] = store[xl]; 0223 start[co] = UNKNOWN; 0224 } 0225 else 0226 update(&info[co], &store[xl], plist); 0227 ps = OBJECT; 0228 } 0229 0230 else if (newmarker == 's') 0231 { 0232 if ((cs == OBJECT) && (ps == COMPLETE)) 0233 { 0234 pstop--; 0235 xl2 = start[co]; 0236 update(&info[co-1], &info[co], plist); 0237 if (start[--co] == UNKNOWN) 0238 start[co] = xl2; 0239 else 0240 marker[xl2] = 's'; 0241 } 0242 ps = OBJECT; 0243 } 0244 else if (newmarker == 'f') 0245 ps = INCOMPLETE; 0246 else if (newmarker == 'F') 0247 { 0248 ps = psstack[--pstop]; 0249 if ((cs == NONOBJECT) && (ps == COMPLETE)) 0250 { 0251 if (start[co] == UNKNOWN) 0252 { 0253 if ((int)info[co].pixnb >= deb_maxarea) 0254 { 0255 if (objlist->nobj>=nobjm) 0256 if (!(obj = objlist->obj = (objstruct *) 0257 realloc(obj, (nobjm+=nobjm/2)* 0258 sizeof(objstruct)))) 0259 { 0260 out = MEMORY_ALLOC_ERROR; 0261 goto exit_lutz; 0262 } 0263 lutzsort(&info[co], objlist); 0264 } 0265 } 0266 else 0267 { 0268 marker[end[co]] = 'F'; 0269 store[start[co]] = info[co]; 0270 } 0271 co--; 0272 ps = psstack[--pstop]; 0273 } 0274 } 0275 } 0276 /* end process new marker -----------------------------------------*/ 0277 0278 if (luflag) 0279 update (&info[co],&curpixinfo, plist); 0280 else 0281 { 0282 /* ----------------- End Segment ------------------------------*/ 0283 if (cs == OBJECT) 0284 { 0285 cs = NONOBJECT; 0286 if (ps != COMPLETE) 0287 { 0288 marker[xl] = 'f'; 0289 end[co] = xl; 0290 } 0291 else 0292 { 0293 ps = psstack[--pstop]; 0294 marker[xl] = 'F'; 0295 store[start[co]] = info[co]; 0296 co--; 0297 } 0298 } 0299 } 0300 } 0301 } 0302 0303 exit_lutz: 0304 0305 if (objlist->nobj && out == RETURN_OK) 0306 { 0307 if (!(objlist->obj= 0308 (objstruct *)realloc(obj, objlist->nobj*sizeof(objstruct)))) 0309 out = MEMORY_ALLOC_ERROR; 0310 } 0311 else 0312 { 0313 free(obj); 0314 objlist->obj = NULL; 0315 } 0316 0317 if (cn && out == RETURN_OK) 0318 { 0319 if (!(objlist->plist=(pliststruct *)realloc(plist,cn))) 0320 out = MEMORY_ALLOC_ERROR; 0321 } 0322 else 0323 { 0324 free(objlist->plist); 0325 objlist->plist = NULL; 0326 } 0327 0328 return out; 0329 } 0330 0331 /********************************* lutzsort ***********************************/ 0332 /* 0333 Add an object to the object list based on info (pixel info) 0334 */ 0335 void lutzsort(infostruct *info, objliststruct *objlist) 0336 { 0337 objstruct *obj = objlist->obj+objlist->nobj; 0338 0339 memset(obj, 0, (size_t)sizeof(objstruct)); 0340 obj->firstpix = info->firstpix; 0341 obj->lastpix = info->lastpix; 0342 obj->flag = info->flag; 0343 objlist->npix += info->pixnb; 0344 0345 preanalyse(objlist->nobj, objlist); 0346 0347 objlist->nobj++; 0348 0349 return; 0350 } 0351 0352 /********************************* update ************************************/ 0353 /* 0354 update object's properties each time one of its pixels is scanned by lutz() 0355 */ 0356 void update(infostruct *infoptr1, infostruct *infoptr2, pliststruct *pixel) 0357 { 0358 infoptr1->pixnb += infoptr2->pixnb; 0359 infoptr1->flag |= infoptr2->flag; 0360 if (infoptr1->firstpix == -1) 0361 { 0362 infoptr1->firstpix = infoptr2->firstpix; 0363 infoptr1->lastpix = infoptr2->lastpix; 0364 } 0365 else if (infoptr2->lastpix != -1) 0366 { 0367 PLIST(pixel+infoptr1->lastpix, nextpix) = infoptr2->firstpix; 0368 infoptr1->lastpix = infoptr2->lastpix; 0369 } 0370 0371 return; 0372 }