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 /* 00018 * fmorphauto.c 00019 * 00020 * Main function calls: 00021 * l_int32 fmorphautogen() 00022 * l_int32 fmorphautogen1() 00023 * l_int32 fmorphautogen2() 00024 * 00025 * Static helpers: 00026 * static SARRAY *sarrayMakeWplsCode() 00027 * static SARRAY *sarrayMakeInnerLoopDWACode() 00028 * static char *makeBarrelshiftString() 00029 * 00030 * 00031 * This automatically generates dwa code for erosion and dilation. 00032 * Here's a road map for how it all works. 00033 * 00034 * (1) You generate an array (a SELA) of structuring elements (SELs). 00035 * This can be done in several ways, including 00036 * (a) calling the function selaAddBasic() for 00037 * pre-compiled SELs 00038 * (b) generating the SELA in code in line 00039 * (c) reading in a SELA from file, using selaRead() or 00040 * various other formats. 00041 * 00042 * (2) You call fmorphautogen1() and fmorphautogen2() on this SELA. 00043 * These use the text files morphtemplate1.txt and 00044 * morphtemplate2.txt for building up the source code. See the file 00045 * prog/fmorphautogen.c for an example of how this is done. 00046 * The output is written to files named fmorphgen.*.c 00047 * and fmorphgenlow.*.c, where "*" is an integer that you 00048 * input to this function. That integer labels both 00049 * the output files, as well as all the functions that 00050 * are generated. That way, using different integers, 00051 * you can invoke fmorphautogen() any number of times 00052 * to get functions that all have different names so that 00053 * they can be linked into one program. 00054 * 00055 * (3) You copy the generated source files back to your src 00056 * directory for compilation. Put their names in the 00057 * Makefile, regenerate the prototypes, and recompile 00058 * the library. Look at the Makefile to see how I've 00059 * included morphgen.1.c and fmorphgenlow.1.c. These files 00060 * provide the high-level interfaces for erosion, dilation, 00061 * opening and closing, and the low-level interfaces to 00062 * do the actual work, for all 58 SELs in the SEL array. 00063 * 00064 * (4) In an application, you now use this interface. Again 00065 * for the example files in the library, using integer "1": 00066 * 00067 * PIX *pixMorphDwa_1(PIX *pixd, PIX, *pixs, 00068 * l_int32 operation, char *selname); 00069 * 00070 * or 00071 * 00072 * PIX *pixFMorphopGen_1(PIX *pixd, PIX *pixs, 00073 * l_int32 operation, char *selname); 00074 * 00075 * where the operation is one of {L_MORPH_DILATE, L_MORPH_ERODE. 00076 * L_MORPH_OPEN, L_MORPH_CLOSE}, and the selname is one 00077 * of the set that were defined as the name field of sels. 00078 * This set is listed at the beginning of the file fmorphgen.1.c. 00079 * For examples of use, see the file prog/binmorph_reg1.c, which 00080 * verifies the consistency of the various implementations by 00081 * comparing the dwa result with that of full-image rasterops. 00082 */ 00083 00084 #include <string.h> 00085 #include "allheaders.h" 00086 00087 #define OUTROOT "fmorphgen" 00088 #define TEMPLATE1 "morphtemplate1.txt" 00089 #define TEMPLATE2 "morphtemplate2.txt" 00090 00091 #define BUFFER_SIZE 512 00092 00093 #define PROTOARGS "(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);" 00094 00095 static char * makeBarrelshiftString(l_int32 delx, l_int32 dely); 00096 static SARRAY * sarrayMakeInnerLoopDWACode(SEL *sel, l_int32 index); 00097 static SARRAY * sarrayMakeWplsCode(SEL *sel); 00098 00099 static char wpldecls[][53] = { 00100 "l_int32 wpls2;", 00101 "l_int32 wpls2, wpls3;", 00102 "l_int32 wpls2, wpls3, wpls4;", 00103 "l_int32 wpls5;", 00104 "l_int32 wpls5, wpls6;", 00105 "l_int32 wpls5, wpls6, wpls7;", 00106 "l_int32 wpls5, wpls6, wpls7, wpls8;", 00107 "l_int32 wpls9;", 00108 "l_int32 wpls9, wpls10;", 00109 "l_int32 wpls9, wpls10, wpls11;", 00110 "l_int32 wpls9, wpls10, wpls11, wpls12;", 00111 "l_int32 wpls13;", 00112 "l_int32 wpls13, wpls14;", 00113 "l_int32 wpls13, wpls14, wpls15;", 00114 "l_int32 wpls13, wpls14, wpls15, wpls16;", 00115 "l_int32 wpls17;", 00116 "l_int32 wpls17, wpls18;", 00117 "l_int32 wpls17, wpls18, wpls19;", 00118 "l_int32 wpls17, wpls18, wpls19, wpls20;", 00119 "l_int32 wpls21;", 00120 "l_int32 wpls21, wpls22;", 00121 "l_int32 wpls21, wpls22, wpls23;", 00122 "l_int32 wpls21, wpls22, wpls23, wpls24;", 00123 "l_int32 wpls25;", 00124 "l_int32 wpls25, wpls26;", 00125 "l_int32 wpls25, wpls26, wpls27;", 00126 "l_int32 wpls25, wpls26, wpls27, wpls28;", 00127 "l_int32 wpls29;", 00128 "l_int32 wpls29, wpls30;", 00129 "l_int32 wpls29, wpls30, wpls31;"}; 00130 00131 static char wplgendecls[][30] = { 00132 "l_int32 wpls2;", 00133 "l_int32 wpls3;", 00134 "l_int32 wpls4;", 00135 "l_int32 wpls5;", 00136 "l_int32 wpls6;", 00137 "l_int32 wpls7;", 00138 "l_int32 wpls8;", 00139 "l_int32 wpls9;", 00140 "l_int32 wpls10;", 00141 "l_int32 wpls11;", 00142 "l_int32 wpls12;", 00143 "l_int32 wpls13;", 00144 "l_int32 wpls14;", 00145 "l_int32 wpls15;", 00146 "l_int32 wpls16;", 00147 "l_int32 wpls17;", 00148 "l_int32 wpls18;", 00149 "l_int32 wpls19;", 00150 "l_int32 wpls20;", 00151 "l_int32 wpls21;", 00152 "l_int32 wpls22;", 00153 "l_int32 wpls23;", 00154 "l_int32 wpls24;", 00155 "l_int32 wpls25;", 00156 "l_int32 wpls26;", 00157 "l_int32 wpls27;", 00158 "l_int32 wpls28;", 00159 "l_int32 wpls29;", 00160 "l_int32 wpls30;", 00161 "l_int32 wpls31;"}; 00162 00163 static char wpldefs[][25] = { 00164 " wpls2 = 2 * wpls;", 00165 " wpls3 = 3 * wpls;", 00166 " wpls4 = 4 * wpls;", 00167 " wpls5 = 5 * wpls;", 00168 " wpls6 = 6 * wpls;", 00169 " wpls7 = 7 * wpls;", 00170 " wpls8 = 8 * wpls;", 00171 " wpls9 = 9 * wpls;", 00172 " wpls10 = 10 * wpls;", 00173 " wpls11 = 11 * wpls;", 00174 " wpls12 = 12 * wpls;", 00175 " wpls13 = 13 * wpls;", 00176 " wpls14 = 14 * wpls;", 00177 " wpls15 = 15 * wpls;", 00178 " wpls16 = 16 * wpls;", 00179 " wpls17 = 17 * wpls;", 00180 " wpls18 = 18 * wpls;", 00181 " wpls19 = 19 * wpls;", 00182 " wpls20 = 20 * wpls;", 00183 " wpls21 = 21 * wpls;", 00184 " wpls22 = 22 * wpls;", 00185 " wpls23 = 23 * wpls;", 00186 " wpls24 = 24 * wpls;", 00187 " wpls25 = 25 * wpls;", 00188 " wpls26 = 26 * wpls;", 00189 " wpls27 = 27 * wpls;", 00190 " wpls28 = 28 * wpls;", 00191 " wpls29 = 29 * wpls;", 00192 " wpls30 = 30 * wpls;", 00193 " wpls31 = 31 * wpls;"}; 00194 00195 static char wplstrp[][10] = {"+ wpls", "+ wpls2", "+ wpls3", "+ wpls4", 00196 "+ wpls5", "+ wpls6", "+ wpls7", "+ wpls8", 00197 "+ wpls9", "+ wpls10", "+ wpls11", "+ wpls12", 00198 "+ wpls13", "+ wpls14", "+ wpls15", "+ wpls16", 00199 "+ wpls17", "+ wpls18", "+ wpls19", "+ wpls20", 00200 "+ wpls21", "+ wpls22", "+ wpls23", "+ wpls24", 00201 "+ wpls25", "+ wpls26", "+ wpls27", "+ wpls28", 00202 "+ wpls29", "+ wpls30", "+ wpls31"}; 00203 00204 static char wplstrm[][10] = {"- wpls", "- wpls2", "- wpls3", "- wpls4", 00205 "- wpls5", "- wpls6", "- wpls7", "- wpls8", 00206 "- wpls9", "- wpls10", "- wpls11", "- wpls12", 00207 "- wpls13", "- wpls14", "- wpls15", "- wpls16", 00208 "- wpls17", "- wpls18", "- wpls19", "- wpls20", 00209 "- wpls21", "- wpls22", "- wpls23", "- wpls24", 00210 "- wpls25", "- wpls26", "- wpls27", "- wpls28", 00211 "- wpls29", "- wpls30", "- wpls31"}; 00212 00213 00214 /*! 00215 * fmorphautogen() 00216 * 00217 * Input: sela 00218 * fileindex 00219 * filename (<optional>; can be null) 00220 * Return: 0 if OK; 1 on error 00221 * 00222 * Notes: 00223 * (1) This function generates all the code for implementing 00224 * dwa morphological operations using all the sels in the sela. 00225 * (2) See fmorphautogen1() and fmorphautogen2() for details. 00226 */ 00227 l_int32 00228 fmorphautogen(SELA *sela, 00229 l_int32 fileindex, 00230 const char *filename) 00231 { 00232 l_int32 ret1, ret2; 00233 00234 PROCNAME("fmorphautogen"); 00235 00236 if (!sela) 00237 return ERROR_INT("sela not defined", procName, 1); 00238 ret1 = fmorphautogen1(sela, fileindex, filename); 00239 ret2 = fmorphautogen2(sela, fileindex, filename); 00240 if (ret1 || ret2) 00241 return ERROR_INT("code generation problem", procName, 1); 00242 return 0; 00243 } 00244 00245 00246 /*! 00247 * fmorphautogen1() 00248 * 00249 * Input: sela 00250 * fileindex 00251 * filename (<optional>; can be null) 00252 * Return: 0 if OK; 1 on error 00253 * 00254 * Notes: 00255 * (1) This function uses morphtemplate1.txt to create a 00256 * top-level file that contains two functions. These 00257 * functions will carry out dilation, erosion, 00258 * opening or closing for any of the sels in the input sela. 00259 * (2) The fileindex parameter is inserted into the output 00260 * filename, as described below. 00261 * (3) If filename == NULL, the output file is fmorphgen.<n>.c, 00262 * where <n> is equal to the 'fileindex' parameter. 00263 * (4) If filename != NULL, the output file is <filename>.<n>.c. 00264 */ 00265 l_int32 00266 fmorphautogen1(SELA *sela, 00267 l_int32 fileindex, 00268 const char *filename) 00269 { 00270 char *filestr; 00271 char *str_proto1, *str_proto2, *str_proto3; 00272 char *str_doc1, *str_doc2, *str_doc3, *str_doc4; 00273 char *str_def1, *str_def2, *str_proc1, *str_proc2; 00274 char *str_dwa1, *str_low_dt, *str_low_ds, *str_low_ts; 00275 char *str_low_tsp1, *str_low_dtp1; 00276 char bigbuf[BUFFER_SIZE]; 00277 l_int32 i, nsels, nbytes, actstart, end, newstart; 00278 size_t size; 00279 SARRAY *sa1, *sa2, *sa3; 00280 00281 PROCNAME("fmorphautogen1"); 00282 00283 if (!sela) 00284 return ERROR_INT("sela not defined", procName, 1); 00285 if (fileindex < 0) 00286 fileindex = 0; 00287 if ((nsels = selaGetCount(sela)) == 0) 00288 return ERROR_INT("no sels in sela", procName, 1); 00289 00290 /* Make array of sel names */ 00291 sa1 = selaGetSelnames(sela); 00292 00293 /* Make array of textlines from morphtemplate1.txt */ 00294 if ((filestr = (char *)l_binaryRead(TEMPLATE1, &size)) == NULL) 00295 return ERROR_INT("filestr not made", procName, 1); 00296 if ((sa2 = sarrayCreateLinesFromString(filestr, 1)) == NULL) 00297 return ERROR_INT("sa2 not made", procName, 1); 00298 FREE(filestr); 00299 /* sarrayWriteStream(stderr, sa2); */ 00300 00301 /* Make strings containing function call names */ 00302 sprintf(bigbuf, "PIX *pixMorphDwa_%d(PIX *pixd, PIX *pixs, " 00303 "l_int32 operation, char *selname);", fileindex); 00304 str_proto1 = stringNew(bigbuf); 00305 sprintf(bigbuf, "PIX *pixFMorphopGen_%d(PIX *pixd, PIX *pixs, " 00306 "l_int32 operation, char *selname);", fileindex); 00307 str_proto2 = stringNew(bigbuf); 00308 sprintf(bigbuf, "l_int32 fmorphopgen_low_%d(l_uint32 *datad, l_int32 w,\n" 00309 " l_int32 h, l_int32 wpld,\n" 00310 " l_uint32 *datas, l_int32 wpls,\n" 00311 " l_int32 index);", fileindex); 00312 str_proto3 = stringNew(bigbuf); 00313 sprintf(bigbuf, " * PIX *pixMorphDwa_%d()", fileindex); 00314 str_doc1 = stringNew(bigbuf); 00315 sprintf(bigbuf, " * PIX *pixFMorphopGen_%d()", fileindex); 00316 str_doc2 = stringNew(bigbuf); 00317 sprintf(bigbuf, " * pixMorphDwa_%d()", fileindex); 00318 str_doc3 = stringNew(bigbuf); 00319 sprintf(bigbuf, " * pixFMorphopGen_%d()", fileindex); 00320 str_doc4 = stringNew(bigbuf); 00321 sprintf(bigbuf, "pixMorphDwa_%d(PIX *pixd,", fileindex); 00322 str_def1 = stringNew(bigbuf); 00323 sprintf(bigbuf, "pixFMorphopGen_%d(PIX *pixd,", fileindex); 00324 str_def2 = stringNew(bigbuf); 00325 sprintf(bigbuf, " PROCNAME(\"pixMorphDwa_%d\");", fileindex); 00326 str_proc1 = stringNew(bigbuf); 00327 sprintf(bigbuf, " PROCNAME(\"pixFMorphopGen_%d\");", fileindex); 00328 str_proc2 = stringNew(bigbuf); 00329 sprintf(bigbuf, 00330 " pixt2 = pixFMorphopGen_%d(NULL, pixt1, operation, selname);", 00331 fileindex); 00332 str_dwa1 = stringNew(bigbuf); 00333 sprintf(bigbuf, 00334 " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index);", 00335 fileindex); 00336 str_low_dt = stringNew(bigbuf); 00337 sprintf(bigbuf, 00338 " fmorphopgen_low_%d(datad, w, h, wpld, datas, wpls, index);", 00339 fileindex); 00340 str_low_ds = stringNew(bigbuf); 00341 sprintf(bigbuf, 00342 " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index+1);", 00343 fileindex); 00344 str_low_tsp1 = stringNew(bigbuf); 00345 sprintf(bigbuf, 00346 " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index);", 00347 fileindex); 00348 str_low_ts = stringNew(bigbuf); 00349 sprintf(bigbuf, 00350 " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index+1);", 00351 fileindex); 00352 str_low_dtp1 = stringNew(bigbuf); 00353 00354 /* Make the output sa */ 00355 if ((sa3 = sarrayCreate(0)) == NULL) 00356 return ERROR_INT("sa3 not made", procName, 1); 00357 00358 /* Copyright notice and info header */ 00359 sarrayParseRange(sa2, 0, &actstart, &end, &newstart, "--", 0); 00360 sarrayAppendRange(sa3, sa2, actstart, end); 00361 00362 /* Insert function names as documentation */ 00363 sarrayAddString(sa3, str_doc1, L_INSERT); 00364 sarrayAddString(sa3, str_doc2, L_INSERT); 00365 00366 /* Add '#include's */ 00367 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00368 sarrayAppendRange(sa3, sa2, actstart, end); 00369 00370 /* Insert function prototypes */ 00371 sarrayAddString(sa3, str_proto1, L_INSERT); 00372 sarrayAddString(sa3, str_proto2, L_INSERT); 00373 sarrayAddString(sa3, str_proto3, L_INSERT); 00374 00375 /* Add static globals */ 00376 sprintf(bigbuf, "\nstatic l_int32 NUM_SELS_GENERATED = %d;", nsels); 00377 sarrayAddString(sa3, bigbuf, L_COPY); 00378 sprintf(bigbuf, "static char SEL_NAMES[][80] = {"); 00379 sarrayAddString(sa3, bigbuf, L_COPY); 00380 for (i = 0; i < nsels - 1; i++) { 00381 sprintf(bigbuf, 00382 " \"%s\",", sarrayGetString(sa1, i, 0)); 00383 sarrayAddString(sa3, bigbuf, L_COPY); 00384 } 00385 sprintf(bigbuf, 00386 " \"%s\"};", sarrayGetString(sa1, i, 0)); 00387 sarrayAddString(sa3, bigbuf, L_COPY); 00388 00389 /* Start pixMorphDwa_*() function description */ 00390 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00391 sarrayAppendRange(sa3, sa2, actstart, end); 00392 sarrayAddString(sa3, str_doc3, L_INSERT); 00393 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00394 sarrayAppendRange(sa3, sa2, actstart, end); 00395 00396 /* Finish pixMorphDwa_*() function definition */ 00397 sarrayAddString(sa3, str_def1, L_INSERT); 00398 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00399 sarrayAppendRange(sa3, sa2, actstart, end); 00400 sarrayAddString(sa3, str_proc1, L_INSERT); 00401 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00402 sarrayAppendRange(sa3, sa2, actstart, end); 00403 sarrayAddString(sa3, str_dwa1, L_INSERT); 00404 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00405 sarrayAppendRange(sa3, sa2, actstart, end); 00406 00407 /* Start pixFMorphopGen_*() function description */ 00408 sarrayAddString(sa3, str_doc4, L_INSERT); 00409 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00410 sarrayAppendRange(sa3, sa2, actstart, end); 00411 00412 /* Finish pixFMorphopGen_*() function definition */ 00413 sarrayAddString(sa3, str_def2, L_INSERT); 00414 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00415 sarrayAppendRange(sa3, sa2, actstart, end); 00416 sarrayAddString(sa3, str_proc2, L_INSERT); 00417 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00418 sarrayAppendRange(sa3, sa2, actstart, end); 00419 sarrayAddString(sa3, str_low_dt, L_COPY); 00420 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00421 sarrayAppendRange(sa3, sa2, actstart, end); 00422 sarrayAddString(sa3, str_low_ds, L_INSERT); 00423 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00424 sarrayAppendRange(sa3, sa2, actstart, end); 00425 sarrayAddString(sa3, str_low_tsp1, L_INSERT); 00426 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00427 sarrayAppendRange(sa3, sa2, actstart, end); 00428 sarrayAddString(sa3, str_low_dt, L_INSERT); 00429 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00430 sarrayAppendRange(sa3, sa2, actstart, end); 00431 sarrayAddString(sa3, str_low_ts, L_INSERT); 00432 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00433 sarrayAppendRange(sa3, sa2, actstart, end); 00434 sarrayAddString(sa3, str_low_dtp1, L_INSERT); 00435 sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); 00436 sarrayAppendRange(sa3, sa2, actstart, end); 00437 00438 /* Output to file */ 00439 if ((filestr = sarrayToString(sa3, 1)) == NULL) 00440 return ERROR_INT("filestr from sa3 not made", procName, 1); 00441 nbytes = strlen(filestr); 00442 if (filename) 00443 sprintf(bigbuf, "%s.%d.c", filename, fileindex); 00444 else 00445 sprintf(bigbuf, "%s.%d.c", OUTROOT, fileindex); 00446 l_binaryWrite(bigbuf, "w", filestr, nbytes); 00447 sarrayDestroy(&sa1); 00448 sarrayDestroy(&sa2); 00449 sarrayDestroy(&sa3); 00450 FREE(filestr); 00451 return 0; 00452 } 00453 00454 00455 /* 00456 * fmorphautogen2() 00457 * 00458 * Input: sela 00459 * fileindex 00460 * filename (<optional>; can be null) 00461 * Return: 0 if OK; 1 on error 00462 * 00463 * Notes: 00464 * (1) This function uses morphtemplate2.txt to create a 00465 * low-level file that contains the low-level functions for 00466 * implementing dilation and erosion for every sel 00467 * in the input sela. 00468 * (2) The fileindex parameter is inserted into the output 00469 * filename, as described below. 00470 * (3) If filename == NULL, the output file is fmorphgenlow.<n>.c, 00471 * where <n> is equal to the 'fileindex' parameter. 00472 * (4) If filename != NULL, the output file is <filename>low.<n>.c. 00473 */ 00474 l_int32 00475 fmorphautogen2(SELA *sela, 00476 l_int32 fileindex, 00477 const char *filename) 00478 { 00479 char *filestr, *linestr, *fname; 00480 char *str_doc1, *str_doc2, *str_doc3, *str_doc4, *str_def1; 00481 char bigbuf[BUFFER_SIZE]; 00482 char breakstring[] = " break;"; 00483 char staticstring[] = "static void"; 00484 l_int32 i, nsels, nbytes, actstart, end, newstart; 00485 l_int32 argstart, argend, loopstart, loopend, finalstart, finalend; 00486 size_t size; 00487 SARRAY *sa1, *sa2, *sa3, *sa4, *sa5, *sa6; 00488 SEL *sel; 00489 00490 PROCNAME("fmorphautogen2"); 00491 00492 if (!sela) 00493 return ERROR_INT("sela not defined", procName, 1); 00494 if (fileindex < 0) 00495 fileindex = 0; 00496 if ((nsels = selaGetCount(sela)) == 0) 00497 return ERROR_INT("no sels in sela", procName, 1); 00498 00499 /* Make the array of textlines from morphtemplate2.txt */ 00500 if ((filestr = (char *)l_binaryRead(TEMPLATE2, &size)) == NULL) 00501 return ERROR_INT("filestr not made", procName, 1); 00502 if ((sa1 = sarrayCreateLinesFromString(filestr, 1)) == NULL) 00503 return ERROR_INT("sa1 not made", procName, 1); 00504 FREE(filestr); 00505 00506 /* Make the array of static function names */ 00507 if ((sa2 = sarrayCreate(2 * nsels)) == NULL) 00508 return ERROR_INT("sa2 not made", procName, 1); 00509 for (i = 0; i < nsels; i++) { 00510 sprintf(bigbuf, "fdilate_%d_%d", fileindex, i); 00511 sarrayAddString(sa2, bigbuf, 1); 00512 sprintf(bigbuf, "ferode_%d_%d", fileindex, i); 00513 sarrayAddString(sa2, bigbuf, 1); 00514 } 00515 00516 /* Make the static prototype strings */ 00517 if ((sa3 = sarrayCreate(2 * nsels)) == NULL) 00518 return ERROR_INT("sa3 not made", procName, 1); 00519 for (i = 0; i < 2 * nsels; i++) { 00520 fname = sarrayGetString(sa2, i, 0); 00521 sprintf(bigbuf, "static void %s%s", fname, PROTOARGS); 00522 sarrayAddString(sa3, bigbuf, 1); 00523 } 00524 00525 /* Make strings containing function names */ 00526 sprintf(bigbuf, " * l_int32 fmorphopgen_low_%d()", 00527 fileindex); 00528 str_doc1 = stringNew(bigbuf); 00529 sprintf(bigbuf, " * void fdilate_%d_*()", fileindex); 00530 str_doc2 = stringNew(bigbuf); 00531 sprintf(bigbuf, " * void ferode_%d_*()", fileindex); 00532 str_doc3 = stringNew(bigbuf); 00533 sprintf(bigbuf, " * fmorphopgen_low_%d()", fileindex); 00534 str_doc4 = stringNew(bigbuf); 00535 sprintf(bigbuf, "fmorphopgen_low_%d(l_uint32 *datad,", fileindex); 00536 str_def1 = stringNew(bigbuf); 00537 00538 /* Output to this sa */ 00539 if ((sa4 = sarrayCreate(0)) == NULL) 00540 return ERROR_INT("sa4 not made", procName, 1); 00541 00542 /* Copyright notice and info header */ 00543 sarrayParseRange(sa1, 0, &actstart, &end, &newstart, "--", 0); 00544 sarrayAppendRange(sa4, sa1, actstart, end); 00545 00546 /* Insert function names as documentation */ 00547 sarrayAddString(sa4, str_doc1, L_INSERT); 00548 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); 00549 sarrayAppendRange(sa4, sa1, actstart, end); 00550 sarrayAddString(sa4, str_doc2, L_INSERT); 00551 sarrayAddString(sa4, str_doc3, L_INSERT); 00552 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); 00553 sarrayAppendRange(sa4, sa1, actstart, end); 00554 00555 /* Insert static protos */ 00556 for (i = 0; i < 2 * nsels; i++) { 00557 if ((linestr = sarrayGetString(sa3, i, L_COPY)) == NULL) 00558 return ERROR_INT("linestr not retrieved", procName, 1); 00559 sarrayAddString(sa4, linestr, L_INSERT); 00560 } 00561 00562 /* Insert function header */ 00563 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); 00564 sarrayAppendRange(sa4, sa1, actstart, end); 00565 sarrayAddString(sa4, str_doc4, L_INSERT); 00566 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); 00567 sarrayAppendRange(sa4, sa1, actstart, end); 00568 sarrayAddString(sa4, str_def1, L_INSERT); 00569 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); 00570 sarrayAppendRange(sa4, sa1, actstart, end); 00571 00572 /* Generate and insert the dispatcher code */ 00573 for (i = 0; i < 2 * nsels; i++) { 00574 sprintf(bigbuf, " case %d:", i); 00575 sarrayAddString(sa4, bigbuf, L_COPY); 00576 sprintf(bigbuf, " %s(datad, w, h, wpld, datas, wpls);", 00577 sarrayGetString(sa2, i, L_NOCOPY)); 00578 sarrayAddString(sa4, bigbuf, L_COPY); 00579 sarrayAddString(sa4, breakstring, L_COPY); 00580 } 00581 00582 /* Finish the dispatcher and introduce the low-level code */ 00583 sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); 00584 sarrayAppendRange(sa4, sa1, actstart, end); 00585 00586 /* Get the range for the args common to all functions */ 00587 sarrayParseRange(sa1, newstart, &argstart, &argend, &newstart, "--", 0); 00588 00589 /* Get the range for the loop code common to all functions */ 00590 sarrayParseRange(sa1, newstart, &loopstart, &loopend, &newstart, "--", 0); 00591 00592 /* Get the range for the ending code common to all functions */ 00593 sarrayParseRange(sa1, newstart, &finalstart, &finalend, &newstart, "--", 0); 00594 00595 /* Do all the static functions */ 00596 for (i = 0; i < 2 * nsels; i++) { 00597 /* Generate the function header and add the common args */ 00598 sarrayAddString(sa4, staticstring, L_COPY); 00599 fname = sarrayGetString(sa2, i, L_NOCOPY); 00600 sprintf(bigbuf, "%s(l_uint32 *datad,", fname); 00601 sarrayAddString(sa4, bigbuf, L_COPY); 00602 sarrayAppendRange(sa4, sa1, argstart, argend); 00603 00604 /* Declare and define wplsN args, as necessary */ 00605 if ((sel = selaGetSel(sela, i/2)) == NULL) 00606 return ERROR_INT("sel not returned", procName, 1); 00607 if ((sa5 = sarrayMakeWplsCode(sel)) == NULL) 00608 return ERROR_INT("sa5 not made", procName, 1); 00609 sarrayConcatenate(sa4, sa5); 00610 sarrayDestroy(&sa5); 00611 00612 /* Add the function loop code */ 00613 sarrayAppendRange(sa4, sa1, loopstart, loopend); 00614 00615 /* Insert barrel-op code for *dptr */ 00616 if ((sa6 = sarrayMakeInnerLoopDWACode(sel, i)) == NULL) 00617 return ERROR_INT("sa6 not made", procName, 1); 00618 sarrayConcatenate(sa4, sa6); 00619 sarrayDestroy(&sa6); 00620 00621 /* Finish the function code */ 00622 sarrayAppendRange(sa4, sa1, finalstart, finalend); 00623 } 00624 00625 /* Output to file */ 00626 if ((filestr = sarrayToString(sa4, 1)) == NULL) 00627 return ERROR_INT("filestr from sa4 not made", procName, 1); 00628 nbytes = strlen(filestr); 00629 if (filename) 00630 sprintf(bigbuf, "%slow.%d.c", filename, fileindex); 00631 else 00632 sprintf(bigbuf, "%slow.%d.c", OUTROOT, fileindex); 00633 l_binaryWrite(bigbuf, "w", filestr, nbytes); 00634 sarrayDestroy(&sa1); 00635 sarrayDestroy(&sa2); 00636 sarrayDestroy(&sa3); 00637 sarrayDestroy(&sa4); 00638 FREE(filestr); 00639 00640 return 0; 00641 } 00642 00643 00644 /*--------------------------------------------------------------------------* 00645 * Helper code for sel * 00646 *--------------------------------------------------------------------------*/ 00647 /*! 00648 * sarrayMakeWplsCode() 00649 */ 00650 static SARRAY * 00651 sarrayMakeWplsCode(SEL *sel) 00652 { 00653 char spacestring[] = " "; 00654 l_int32 i, j, ymax, dely, allvshifts; 00655 l_int32 vshift[32]; 00656 SARRAY *sa; 00657 00658 PROCNAME("sarrayMakeWplsCode"); 00659 00660 if (!sel) 00661 return (SARRAY *)ERROR_PTR("sel not defined", procName, NULL); 00662 00663 for (i = 0; i < 32; i++) 00664 vshift[i] = 0; 00665 ymax = 0; 00666 for (i = 0; i < sel->sy; i++) { 00667 for (j = 0; j < sel->sx; j++) { 00668 if (sel->data[i][j] == 1) { 00669 dely = L_ABS(i - sel->cy); 00670 if (dely < 32) 00671 vshift[dely] = 1; 00672 ymax = L_MAX(ymax, dely); 00673 } 00674 } 00675 } 00676 if (ymax > 31) { 00677 L_WARNING("ymax > 31; truncating to 31", procName); 00678 ymax = 31; 00679 } 00680 00681 /* Test if this is a vertical brick */ 00682 allvshifts = TRUE; 00683 for (i = 0; i < ymax; i++) { 00684 if (vshift[i] == 0) { 00685 allvshifts = FALSE; 00686 break; 00687 } 00688 } 00689 00690 if ((sa = sarrayCreate(0)) == NULL) 00691 return (SARRAY *)ERROR_PTR("sa not made", procName, NULL); 00692 00693 /* Add declarations */ 00694 if (allvshifts == TRUE) { /* packs them as well as possible */ 00695 if (ymax > 4) 00696 sarrayAddString(sa, wpldecls[2], 1); 00697 if (ymax > 8) 00698 sarrayAddString(sa, wpldecls[6], 1); 00699 if (ymax > 12) 00700 sarrayAddString(sa, wpldecls[10], 1); 00701 if (ymax > 16) 00702 sarrayAddString(sa, wpldecls[14], 1); 00703 if (ymax > 20) 00704 sarrayAddString(sa, wpldecls[18], 1); 00705 if (ymax > 24) 00706 sarrayAddString(sa, wpldecls[22], 1); 00707 if (ymax > 28) 00708 sarrayAddString(sa, wpldecls[26], 1); 00709 if (ymax > 1) 00710 sarrayAddString(sa, wpldecls[ymax - 2], 1); 00711 } 00712 else { /* puts them one/line */ 00713 for (i = 2; i <= ymax; i++) { 00714 if (vshift[i]) 00715 sarrayAddString(sa, wplgendecls[i - 2], 1); 00716 } 00717 } 00718 00719 sarrayAddString(sa, spacestring, 1); 00720 00721 /* Add definitions */ 00722 for (i = 2; i <= ymax; i++) { 00723 if (vshift[i]) 00724 sarrayAddString(sa, wpldefs[i - 2], 1); 00725 } 00726 00727 return sa; 00728 } 00729 00730 00731 /*! 00732 * sarrayMakeInnerLoopDWACode() 00733 */ 00734 static SARRAY * 00735 sarrayMakeInnerLoopDWACode(SEL *sel, 00736 l_int32 index) 00737 { 00738 char *tstr, *string; 00739 char logicalor[] = "|"; 00740 char logicaland[] = "&"; 00741 char bigbuf[BUFFER_SIZE]; 00742 l_int32 i, j, optype, count, nfound, delx, dely; 00743 SARRAY *sa; 00744 00745 PROCNAME("sarrayMakeInnerLoopDWACode"); 00746 00747 if (!sel) 00748 return (SARRAY *)ERROR_PTR("sel not defined", procName, NULL); 00749 00750 if (index % 2 == 0) { 00751 optype = L_MORPH_DILATE; 00752 tstr = logicalor; 00753 } 00754 else { 00755 optype = L_MORPH_ERODE; 00756 tstr = logicaland; 00757 } 00758 00759 count = 0; 00760 for (i = 0; i < sel->sy; i++) { 00761 for (j = 0; j < sel->sx; j++) { 00762 if (sel->data[i][j] == 1) 00763 count++; 00764 } 00765 } 00766 00767 if ((sa = sarrayCreate(0)) == NULL) 00768 return (SARRAY *)ERROR_PTR("sa not made", procName, NULL); 00769 if (count == 0) { 00770 L_WARNING_INT("no hits in Sel %d", procName, index); 00771 return sa; /* no code inside! */ 00772 } 00773 00774 nfound = 0; 00775 for (i = 0; i < sel->sy; i++) { 00776 for (j = 0; j < sel->sx; j++) { 00777 if (sel->data[i][j] == 1) { 00778 nfound++; 00779 if (optype == L_MORPH_DILATE) { 00780 dely = sel->cy - i; 00781 delx = sel->cx - j; 00782 } 00783 else if (optype == L_MORPH_ERODE) { 00784 dely = i - sel->cy; 00785 delx = j - sel->cx; 00786 } 00787 if ((string = makeBarrelshiftString(delx, dely)) == NULL) { 00788 L_WARNING("barrel shift string not made", procName); 00789 continue; 00790 } 00791 if (count == 1) /* just one item */ 00792 sprintf(bigbuf, " *dptr = %s;", string); 00793 else if (nfound == 1) 00794 sprintf(bigbuf, " *dptr = %s %s", string, tstr); 00795 else if (nfound < count) 00796 sprintf(bigbuf, " %s %s", string, tstr); 00797 else /* nfound == count */ 00798 sprintf(bigbuf, " %s;", string); 00799 sarrayAddString(sa, bigbuf, 1); 00800 FREE(string); 00801 } 00802 } 00803 } 00804 00805 return sa; 00806 } 00807 00808 00809 /*! 00810 * makeBarrelshiftString() 00811 */ 00812 static char * 00813 makeBarrelshiftString(l_int32 delx, /* j - cx */ 00814 l_int32 dely) /* i - cy */ 00815 { 00816 l_int32 absx, absy; 00817 char bigbuf[BUFFER_SIZE]; 00818 00819 PROCNAME("makeBarrelshiftString"); 00820 00821 if (delx < -31 || delx > 31) 00822 return (char *)ERROR_PTR("delx out of bounds", procName, NULL); 00823 if (dely < -31 || dely > 31) 00824 return (char *)ERROR_PTR("dely out of bounds", procName, NULL); 00825 absx = L_ABS(delx); 00826 absy = L_ABS(dely); 00827 00828 if ((delx == 0) && (dely == 0)) 00829 sprintf(bigbuf, "(*sptr)"); 00830 else if ((delx == 0) && (dely < 0)) 00831 sprintf(bigbuf, "(*(sptr %s))", wplstrm[absy - 1]); 00832 else if ((delx == 0) && (dely > 0)) 00833 sprintf(bigbuf, "(*(sptr %s))", wplstrp[absy - 1]); 00834 else if ((delx < 0) && (dely == 0)) 00835 sprintf(bigbuf, "((*(sptr) >> %d) | (*(sptr - 1) << %d))", 00836 absx, 32 - absx); 00837 else if ((delx > 0) && (dely == 0)) 00838 sprintf(bigbuf, "((*(sptr) << %d) | (*(sptr + 1) >> %d))", 00839 absx, 32 - absx); 00840 else if ((delx < 0) && (dely < 0)) 00841 sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))", 00842 wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); 00843 else if ((delx > 0) && (dely < 0)) 00844 sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))", 00845 wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); 00846 else if ((delx < 0) && (dely > 0)) 00847 sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))", 00848 wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); 00849 else /* ((delx > 0) && (dely > 0)) */ 00850 sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))", 00851 wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); 00852 00853 return stringNew(bigbuf); 00854 } 00855