Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 /*! 00017 * Top-level fast binary morphology with auto-generated sels 00018 * 00019 * PIX *pixMorphDwa_2() 00020 * PIX *pixFMorphopGen_2() 00021 */ 00022 00023 #include <string.h> 00024 #include "allheaders.h" 00025 00026 PIX *pixMorphDwa_2(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); 00027 PIX *pixFMorphopGen_2(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); 00028 l_int32 fmorphopgen_low_2(l_uint32 *datad, l_int32 w, 00029 l_int32 h, l_int32 wpld, 00030 l_uint32 *datas, l_int32 wpls, 00031 l_int32 index); 00032 00033 static l_int32 NUM_SELS_GENERATED = 76; 00034 static char SEL_NAMES[][80] = { 00035 "sel_comb_4h", 00036 "sel_comb_4v", 00037 "sel_comb_5h", 00038 "sel_comb_5v", 00039 "sel_comb_6h", 00040 "sel_comb_6v", 00041 "sel_comb_7h", 00042 "sel_comb_7v", 00043 "sel_comb_8h", 00044 "sel_comb_8v", 00045 "sel_comb_9h", 00046 "sel_comb_9v", 00047 "sel_comb_10h", 00048 "sel_comb_10v", 00049 "sel_comb_12h", 00050 "sel_comb_12v", 00051 "sel_comb_14h", 00052 "sel_comb_14v", 00053 "sel_comb_15h", 00054 "sel_comb_15v", 00055 "sel_comb_16h", 00056 "sel_comb_16v", 00057 "sel_comb_18h", 00058 "sel_comb_18v", 00059 "sel_comb_20h", 00060 "sel_comb_20v", 00061 "sel_comb_21h", 00062 "sel_comb_21v", 00063 "sel_comb_22h", 00064 "sel_comb_22v", 00065 "sel_comb_24h", 00066 "sel_comb_24v", 00067 "sel_comb_25h", 00068 "sel_comb_25v", 00069 "sel_comb_27h", 00070 "sel_comb_27v", 00071 "sel_comb_28h", 00072 "sel_comb_28v", 00073 "sel_comb_30h", 00074 "sel_comb_30v", 00075 "sel_comb_32h", 00076 "sel_comb_32v", 00077 "sel_comb_33h", 00078 "sel_comb_33v", 00079 "sel_comb_35h", 00080 "sel_comb_35v", 00081 "sel_comb_36h", 00082 "sel_comb_36v", 00083 "sel_comb_39h", 00084 "sel_comb_39v", 00085 "sel_comb_40h", 00086 "sel_comb_40v", 00087 "sel_comb_42h", 00088 "sel_comb_42v", 00089 "sel_comb_44h", 00090 "sel_comb_44v", 00091 "sel_comb_45h", 00092 "sel_comb_45v", 00093 "sel_comb_48h", 00094 "sel_comb_48v", 00095 "sel_comb_49h", 00096 "sel_comb_49v", 00097 "sel_comb_50h", 00098 "sel_comb_50v", 00099 "sel_comb_52h", 00100 "sel_comb_52v", 00101 "sel_comb_54h", 00102 "sel_comb_54v", 00103 "sel_comb_55h", 00104 "sel_comb_55v", 00105 "sel_comb_56h", 00106 "sel_comb_56v", 00107 "sel_comb_60h", 00108 "sel_comb_60v", 00109 "sel_comb_63h", 00110 "sel_comb_63v"}; 00111 00112 /*! 00113 * pixMorphDwa_2() 00114 * 00115 * Input: pixd (usual 3 choices: null, == pixs, != pixs) 00116 * pixs (1 bpp) 00117 * operation (L_MORPH_DILATE, L_MORPH_ERODE, 00118 * L_MORPH_OPEN, L_MORPH_CLOSE) 00119 * sel name 00120 * Return: pixd 00121 * 00122 * Notes: 00123 * (1) This simply adds a border, calls the appropriate 00124 * pixFMorphopGen_*(), and removes the border. 00125 * See the notes for that function. 00126 * (2) The size of the border depends on the operation 00127 * and the boundary conditions. 00128 */ 00129 PIX * 00130 pixMorphDwa_2(PIX *pixd, 00131 PIX *pixs, 00132 l_int32 operation, 00133 char *selname) 00134 { 00135 l_int32 bordercolor, bordersize; 00136 PIX *pixt1, *pixt2, *pixt3; 00137 00138 PROCNAME("pixMorphDwa_2"); 00139 00140 if (!pixs) 00141 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); 00142 if (pixGetDepth(pixs) != 1) 00143 return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); 00144 00145 /* Set the border size */ 00146 bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); 00147 bordersize = 32; 00148 if (bordercolor == 0 && operation == L_MORPH_CLOSE) 00149 bordersize += 32; 00150 00151 pixt1 = pixAddBorder(pixs, bordersize, 0); 00152 pixt2 = pixFMorphopGen_2(NULL, pixt1, operation, selname); 00153 pixt3 = pixRemoveBorder(pixt2, bordersize); 00154 pixDestroy(&pixt1); 00155 pixDestroy(&pixt2); 00156 00157 if (!pixd) 00158 return pixt3; 00159 00160 pixCopy(pixd, pixt3); 00161 pixDestroy(&pixt3); 00162 return pixd; 00163 } 00164 00165 00166 /*! 00167 * pixFMorphopGen_2() 00168 * 00169 * Input: pixd (usual 3 choices: null, == pixs, != pixs) 00170 * pixs (1 bpp) 00171 * operation (L_MORPH_DILATE, L_MORPH_ERODE, 00172 * L_MORPH_OPEN, L_MORPH_CLOSE) 00173 * sel name 00174 * Return: pixd 00175 * 00176 * Notes: 00177 * (1) This is a dwa operation, and the Sels must be limited in 00178 * size to not more than 31 pixels about the origin. 00179 * (2) A border of appropriate size (32 pixels, or 64 pixels 00180 * for safe closing with asymmetric b.c.) must be added before 00181 * this function is called. 00182 * (3) This handles all required setting of the border pixels 00183 * before erosion and dilation. 00184 * (4) The closing operation is safe; no pixels can be removed 00185 * near the boundary. 00186 */ 00187 PIX * 00188 pixFMorphopGen_2(PIX *pixd, 00189 PIX *pixs, 00190 l_int32 operation, 00191 char *selname) 00192 { 00193 l_int32 i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop; 00194 l_uint32 *datad, *datas, *datat; 00195 PIX *pixt; 00196 00197 PROCNAME("pixFMorphopGen_2"); 00198 00199 if (!pixs) 00200 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); 00201 if (pixGetDepth(pixs) != 1) 00202 return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); 00203 00204 /* Get boundary colors to use */ 00205 bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); 00206 if (bordercolor == 1) 00207 erodeop = PIX_SET; 00208 else 00209 erodeop = PIX_CLR; 00210 00211 found = FALSE; 00212 for (i = 0; i < NUM_SELS_GENERATED; i++) { 00213 if (strcmp(selname, SEL_NAMES[i]) == 0) { 00214 found = TRUE; 00215 index = 2 * i; 00216 break; 00217 } 00218 } 00219 if (found == FALSE) 00220 return (PIX *)ERROR_PTR("sel index not found", procName, pixd); 00221 00222 if (!pixd) { 00223 if ((pixd = pixCreateTemplate(pixs)) == NULL) 00224 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00225 } 00226 else /* for in-place or pre-allocated */ 00227 pixResizeImageData(pixd, pixs); 00228 wpls = pixGetWpl(pixs); 00229 wpld = pixGetWpl(pixd); 00230 00231 /* The images must be surrounded, in advance, with a border of 00232 * size 32 pixels (or 64, for closing), that we'll read from. 00233 * Fabricate a "proper" image as the subimage within the 32 00234 * pixel border, having the following parameters: */ 00235 w = pixGetWidth(pixs) - 64; 00236 h = pixGetHeight(pixs) - 64; 00237 datas = pixGetData(pixs) + 32 * wpls + 1; 00238 datad = pixGetData(pixd) + 32 * wpld + 1; 00239 00240 if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) { 00241 borderop = PIX_CLR; 00242 if (operation == L_MORPH_ERODE) { 00243 borderop = erodeop; 00244 index++; 00245 } 00246 if (pixd == pixs) { /* in-place; generate a temp image */ 00247 if ((pixt = pixCopy(NULL, pixs)) == NULL) 00248 return (PIX *)ERROR_PTR("pixt not made", procName, pixd); 00249 datat = pixGetData(pixt) + 32 * wpls + 1; 00250 pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop); 00251 fmorphopgen_low_2(datad, w, h, wpld, datat, wpls, index); 00252 pixDestroy(&pixt); 00253 } 00254 else { /* not in-place */ 00255 pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop); 00256 fmorphopgen_low_2(datad, w, h, wpld, datas, wpls, index); 00257 } 00258 } 00259 else { /* opening or closing; generate a temp image */ 00260 if ((pixt = pixCreateTemplate(pixs)) == NULL) 00261 return (PIX *)ERROR_PTR("pixt not made", procName, pixd); 00262 datat = pixGetData(pixt) + 32 * wpls + 1; 00263 if (operation == L_MORPH_OPEN) { 00264 pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop); 00265 fmorphopgen_low_2(datat, w, h, wpls, datas, wpls, index+1); 00266 pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR); 00267 fmorphopgen_low_2(datad, w, h, wpld, datat, wpls, index); 00268 } 00269 else { /* closing */ 00270 pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR); 00271 fmorphopgen_low_2(datat, w, h, wpls, datas, wpls, index); 00272 pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop); 00273 fmorphopgen_low_2(datad, w, h, wpld, datat, wpls, index+1); 00274 } 00275 pixDestroy(&pixt); 00276 } 00277 00278 return pixd; 00279 } 00280