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_1() 00020 * PIX *pixFMorphopGen_1() 00021 */ 00022 00023 #include <string.h> 00024 #include "allheaders.h" 00025 00026 PIX *pixMorphDwa_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); 00027 PIX *pixFMorphopGen_1(PIX *pixd, PIX *pixs, l_int32 operation, char *selname); 00028 l_int32 fmorphopgen_low_1(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 = 58; 00034 static char SEL_NAMES[][80] = { 00035 "sel_2h", 00036 "sel_3h", 00037 "sel_4h", 00038 "sel_5h", 00039 "sel_6h", 00040 "sel_7h", 00041 "sel_8h", 00042 "sel_9h", 00043 "sel_10h", 00044 "sel_11h", 00045 "sel_12h", 00046 "sel_13h", 00047 "sel_14h", 00048 "sel_15h", 00049 "sel_20h", 00050 "sel_21h", 00051 "sel_25h", 00052 "sel_30h", 00053 "sel_31h", 00054 "sel_35h", 00055 "sel_40h", 00056 "sel_41h", 00057 "sel_45h", 00058 "sel_50h", 00059 "sel_51h", 00060 "sel_2v", 00061 "sel_3v", 00062 "sel_4v", 00063 "sel_5v", 00064 "sel_6v", 00065 "sel_7v", 00066 "sel_8v", 00067 "sel_9v", 00068 "sel_10v", 00069 "sel_11v", 00070 "sel_12v", 00071 "sel_13v", 00072 "sel_14v", 00073 "sel_15v", 00074 "sel_20v", 00075 "sel_21v", 00076 "sel_25v", 00077 "sel_30v", 00078 "sel_31v", 00079 "sel_35v", 00080 "sel_40v", 00081 "sel_41v", 00082 "sel_45v", 00083 "sel_50v", 00084 "sel_51v", 00085 "sel_2", 00086 "sel_3", 00087 "sel_4", 00088 "sel_5", 00089 "sel_2dp", 00090 "sel_2dm", 00091 "sel_5dp", 00092 "sel_5dm"}; 00093 00094 /*! 00095 * pixMorphDwa_1() 00096 * 00097 * Input: pixd (usual 3 choices: null, == pixs, != pixs) 00098 * pixs (1 bpp) 00099 * operation (L_MORPH_DILATE, L_MORPH_ERODE, 00100 * L_MORPH_OPEN, L_MORPH_CLOSE) 00101 * sel name 00102 * Return: pixd 00103 * 00104 * Notes: 00105 * (1) This simply adds a border, calls the appropriate 00106 * pixFMorphopGen_*(), and removes the border. 00107 * See the notes for that function. 00108 * (2) The size of the border depends on the operation 00109 * and the boundary conditions. 00110 */ 00111 PIX * 00112 pixMorphDwa_1(PIX *pixd, 00113 PIX *pixs, 00114 l_int32 operation, 00115 char *selname) 00116 { 00117 l_int32 bordercolor, bordersize; 00118 PIX *pixt1, *pixt2, *pixt3; 00119 00120 PROCNAME("pixMorphDwa_1"); 00121 00122 if (!pixs) 00123 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); 00124 if (pixGetDepth(pixs) != 1) 00125 return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); 00126 00127 /* Set the border size */ 00128 bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); 00129 bordersize = 32; 00130 if (bordercolor == 0 && operation == L_MORPH_CLOSE) 00131 bordersize += 32; 00132 00133 pixt1 = pixAddBorder(pixs, bordersize, 0); 00134 pixt2 = pixFMorphopGen_1(NULL, pixt1, operation, selname); 00135 pixt3 = pixRemoveBorder(pixt2, bordersize); 00136 pixDestroy(&pixt1); 00137 pixDestroy(&pixt2); 00138 00139 if (!pixd) 00140 return pixt3; 00141 00142 pixCopy(pixd, pixt3); 00143 pixDestroy(&pixt3); 00144 return pixd; 00145 } 00146 00147 00148 /*! 00149 * pixFMorphopGen_1() 00150 * 00151 * Input: pixd (usual 3 choices: null, == pixs, != pixs) 00152 * pixs (1 bpp) 00153 * operation (L_MORPH_DILATE, L_MORPH_ERODE, 00154 * L_MORPH_OPEN, L_MORPH_CLOSE) 00155 * sel name 00156 * Return: pixd 00157 * 00158 * Notes: 00159 * (1) This is a dwa operation, and the Sels must be limited in 00160 * size to not more than 31 pixels about the origin. 00161 * (2) A border of appropriate size (32 pixels, or 64 pixels 00162 * for safe closing with asymmetric b.c.) must be added before 00163 * this function is called. 00164 * (3) This handles all required setting of the border pixels 00165 * before erosion and dilation. 00166 * (4) The closing operation is safe; no pixels can be removed 00167 * near the boundary. 00168 */ 00169 PIX * 00170 pixFMorphopGen_1(PIX *pixd, 00171 PIX *pixs, 00172 l_int32 operation, 00173 char *selname) 00174 { 00175 l_int32 i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop; 00176 l_uint32 *datad, *datas, *datat; 00177 PIX *pixt; 00178 00179 PROCNAME("pixFMorphopGen_1"); 00180 00181 if (!pixs) 00182 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd); 00183 if (pixGetDepth(pixs) != 1) 00184 return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd); 00185 00186 /* Get boundary colors to use */ 00187 bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1); 00188 if (bordercolor == 1) 00189 erodeop = PIX_SET; 00190 else 00191 erodeop = PIX_CLR; 00192 00193 found = FALSE; 00194 for (i = 0; i < NUM_SELS_GENERATED; i++) { 00195 if (strcmp(selname, SEL_NAMES[i]) == 0) { 00196 found = TRUE; 00197 index = 2 * i; 00198 break; 00199 } 00200 } 00201 if (found == FALSE) 00202 return (PIX *)ERROR_PTR("sel index not found", procName, pixd); 00203 00204 if (!pixd) { 00205 if ((pixd = pixCreateTemplate(pixs)) == NULL) 00206 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00207 } 00208 else /* for in-place or pre-allocated */ 00209 pixResizeImageData(pixd, pixs); 00210 wpls = pixGetWpl(pixs); 00211 wpld = pixGetWpl(pixd); 00212 00213 /* The images must be surrounded, in advance, with a border of 00214 * size 32 pixels (or 64, for closing), that we'll read from. 00215 * Fabricate a "proper" image as the subimage within the 32 00216 * pixel border, having the following parameters: */ 00217 w = pixGetWidth(pixs) - 64; 00218 h = pixGetHeight(pixs) - 64; 00219 datas = pixGetData(pixs) + 32 * wpls + 1; 00220 datad = pixGetData(pixd) + 32 * wpld + 1; 00221 00222 if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) { 00223 borderop = PIX_CLR; 00224 if (operation == L_MORPH_ERODE) { 00225 borderop = erodeop; 00226 index++; 00227 } 00228 if (pixd == pixs) { /* in-place; generate a temp image */ 00229 if ((pixt = pixCopy(NULL, pixs)) == NULL) 00230 return (PIX *)ERROR_PTR("pixt not made", procName, pixd); 00231 datat = pixGetData(pixt) + 32 * wpls + 1; 00232 pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop); 00233 fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index); 00234 pixDestroy(&pixt); 00235 } 00236 else { /* not in-place */ 00237 pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop); 00238 fmorphopgen_low_1(datad, w, h, wpld, datas, wpls, index); 00239 } 00240 } 00241 else { /* opening or closing; generate a temp image */ 00242 if ((pixt = pixCreateTemplate(pixs)) == NULL) 00243 return (PIX *)ERROR_PTR("pixt not made", procName, pixd); 00244 datat = pixGetData(pixt) + 32 * wpls + 1; 00245 if (operation == L_MORPH_OPEN) { 00246 pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop); 00247 fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index+1); 00248 pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR); 00249 fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index); 00250 } 00251 else { /* closing */ 00252 pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR); 00253 fmorphopgen_low_1(datat, w, h, wpls, datas, wpls, index); 00254 pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop); 00255 fmorphopgen_low_1(datad, w, h, wpld, datat, wpls, index+1); 00256 } 00257 pixDestroy(&pixt); 00258 } 00259 00260 return pixd; 00261 } 00262