Leptonica 1.68
C Image Processing Library

fmorphauto.c

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines