Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/leptonica/src/fmorphauto.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/leptonica/src/fmorphauto.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,867 @@ +/*====================================================================* + - Copyright (C) 2001 Leptonica. All rights reserved. + - + - Redistribution and use in source and binary forms, with or without + - modification, are permitted provided that the following conditions + - are met: + - 1. Redistributions of source code must retain the above copyright + - notice, this list of conditions and the following disclaimer. + - 2. Redistributions in binary form must reproduce the above + - copyright notice, this list of conditions and the following + - disclaimer in the documentation and/or other materials + - provided with the distribution. + - + - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY + - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *====================================================================*/ + + +/*! + * \file fmorphauto.c + * <pre> + * + * Main function calls: + * l_int32 fmorphautogen() + * l_int32 fmorphautogen1() + * l_int32 fmorphautogen2() + * + * Static helpers: + * static SARRAY *sarrayMakeWplsCode() + * static SARRAY *sarrayMakeInnerLoopDWACode() + * static char *makeBarrelshiftString() + * + * + * This automatically generates dwa code for erosion and dilation. + * Here's a road map for how it all works. + * + * (1) You generate an array (a SELA) of structuring elements (SELs). + * This can be done in several ways, including + * (a) calling the function selaAddBasic() for + * pre-compiled SELs + * (b) generating the SELA in code in line + * (c) reading in a SELA from file, using selaRead() or + * various other formats. + * + * (2) You call fmorphautogen() on this SELA. This in turn calls + * fmorphautogen1() and fmorphautogen2(), which use the text + * files morphtemplate1.txt and morphtemplate2.txt, respectively, + * for building up the source code. See the file + * prog/fmorphautogen.c for an example of how this is done. + * The output is written to files named fmorphgen.*.c + * and fmorphgenlow.*.c, where "*" is an integer that you + * input to this function. That integer labels both + * the output files, as well as all the functions that + * are generated. That way, using different integers, + * you can invoke fmorphautogen() any number of times + * to get functions that all have different names so that + * they can be linked into one program. + * + * (3) You copy the generated source files back to your src + * directory for compilation. Put their names in the + * Makefile, regenerate the allheaders.h prototype file, + * and recompile the library. Look at the Makefile to see how + * morphgen.1.c and fmorphgenlow.1.c are included. These files + * provide the single high-level interface for erosion, dilation, + * opening and closing, and the lower-level functions to + * do the actual work, for all 58 SELs in the SEL array. + * + * (4) In an application, you now use this interface. Again + * for the example files in the library, using integer "1": + * + * PIX *pixMorphDwa_1(PIX *pixd, PIX, *pixs, + * l_int32 operation, char *selname); + * + * where the operation is one of {L_MORPH_DILATE, L_MORPH_ERODE. + * L_MORPH_OPEN, L_MORPH_CLOSE}, and the selname is one + * of the set that were defined as the name field of sels. + * This set is listed at the beginning of the file fmorphgen.1.c. + * + * N.B. Although pixFMorphopGen_1() is global, you must NOT + * use it, because it assumes that 32 or 64 border pixels + * have been added to each side, and it will crash without those + * added pixels. + * + * For examples of use, see the file prog/binmorph_reg1.c, which + * verifies the consistency of the various implementations by + * comparing the dwa result with that of full-image rasterops. + * </pre> + */ + +#ifdef HAVE_CONFIG_H +#include <config_auto.h> +#endif /* HAVE_CONFIG_H */ + +#include <string.h> +#include "allheaders.h" + +#define OUTROOT "fmorphgen" +#define TEMPLATE1 "morphtemplate1.txt" +#define TEMPLATE2 "morphtemplate2.txt" + +#define PROTOARGS "(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);" + +#define L_BUF_SIZE 512 + +static char * makeBarrelshiftString(l_int32 delx, l_int32 dely); +static SARRAY * sarrayMakeInnerLoopDWACode(SEL *sel, l_int32 index); +static SARRAY * sarrayMakeWplsCode(SEL *sel); + +static char wpldecls[][53] = { + "l_int32 wpls2;", + "l_int32 wpls2, wpls3;", + "l_int32 wpls2, wpls3, wpls4;", + "l_int32 wpls5;", + "l_int32 wpls5, wpls6;", + "l_int32 wpls5, wpls6, wpls7;", + "l_int32 wpls5, wpls6, wpls7, wpls8;", + "l_int32 wpls9;", + "l_int32 wpls9, wpls10;", + "l_int32 wpls9, wpls10, wpls11;", + "l_int32 wpls9, wpls10, wpls11, wpls12;", + "l_int32 wpls13;", + "l_int32 wpls13, wpls14;", + "l_int32 wpls13, wpls14, wpls15;", + "l_int32 wpls13, wpls14, wpls15, wpls16;", + "l_int32 wpls17;", + "l_int32 wpls17, wpls18;", + "l_int32 wpls17, wpls18, wpls19;", + "l_int32 wpls17, wpls18, wpls19, wpls20;", + "l_int32 wpls21;", + "l_int32 wpls21, wpls22;", + "l_int32 wpls21, wpls22, wpls23;", + "l_int32 wpls21, wpls22, wpls23, wpls24;", + "l_int32 wpls25;", + "l_int32 wpls25, wpls26;", + "l_int32 wpls25, wpls26, wpls27;", + "l_int32 wpls25, wpls26, wpls27, wpls28;", + "l_int32 wpls29;", + "l_int32 wpls29, wpls30;", + "l_int32 wpls29, wpls30, wpls31;"}; + +static char wplgendecls[][30] = { + "l_int32 wpls2;", + "l_int32 wpls3;", + "l_int32 wpls4;", + "l_int32 wpls5;", + "l_int32 wpls6;", + "l_int32 wpls7;", + "l_int32 wpls8;", + "l_int32 wpls9;", + "l_int32 wpls10;", + "l_int32 wpls11;", + "l_int32 wpls12;", + "l_int32 wpls13;", + "l_int32 wpls14;", + "l_int32 wpls15;", + "l_int32 wpls16;", + "l_int32 wpls17;", + "l_int32 wpls18;", + "l_int32 wpls19;", + "l_int32 wpls20;", + "l_int32 wpls21;", + "l_int32 wpls22;", + "l_int32 wpls23;", + "l_int32 wpls24;", + "l_int32 wpls25;", + "l_int32 wpls26;", + "l_int32 wpls27;", + "l_int32 wpls28;", + "l_int32 wpls29;", + "l_int32 wpls30;", + "l_int32 wpls31;"}; + +static char wpldefs[][25] = { + " wpls2 = 2 * wpls;", + " wpls3 = 3 * wpls;", + " wpls4 = 4 * wpls;", + " wpls5 = 5 * wpls;", + " wpls6 = 6 * wpls;", + " wpls7 = 7 * wpls;", + " wpls8 = 8 * wpls;", + " wpls9 = 9 * wpls;", + " wpls10 = 10 * wpls;", + " wpls11 = 11 * wpls;", + " wpls12 = 12 * wpls;", + " wpls13 = 13 * wpls;", + " wpls14 = 14 * wpls;", + " wpls15 = 15 * wpls;", + " wpls16 = 16 * wpls;", + " wpls17 = 17 * wpls;", + " wpls18 = 18 * wpls;", + " wpls19 = 19 * wpls;", + " wpls20 = 20 * wpls;", + " wpls21 = 21 * wpls;", + " wpls22 = 22 * wpls;", + " wpls23 = 23 * wpls;", + " wpls24 = 24 * wpls;", + " wpls25 = 25 * wpls;", + " wpls26 = 26 * wpls;", + " wpls27 = 27 * wpls;", + " wpls28 = 28 * wpls;", + " wpls29 = 29 * wpls;", + " wpls30 = 30 * wpls;", + " wpls31 = 31 * wpls;"}; + +static char wplstrp[][10] = {"+ wpls", "+ wpls2", "+ wpls3", "+ wpls4", + "+ wpls5", "+ wpls6", "+ wpls7", "+ wpls8", + "+ wpls9", "+ wpls10", "+ wpls11", "+ wpls12", + "+ wpls13", "+ wpls14", "+ wpls15", "+ wpls16", + "+ wpls17", "+ wpls18", "+ wpls19", "+ wpls20", + "+ wpls21", "+ wpls22", "+ wpls23", "+ wpls24", + "+ wpls25", "+ wpls26", "+ wpls27", "+ wpls28", + "+ wpls29", "+ wpls30", "+ wpls31"}; + +static char wplstrm[][10] = {"- wpls", "- wpls2", "- wpls3", "- wpls4", + "- wpls5", "- wpls6", "- wpls7", "- wpls8", + "- wpls9", "- wpls10", "- wpls11", "- wpls12", + "- wpls13", "- wpls14", "- wpls15", "- wpls16", + "- wpls17", "- wpls18", "- wpls19", "- wpls20", + "- wpls21", "- wpls22", "- wpls23", "- wpls24", + "- wpls25", "- wpls26", "- wpls27", "- wpls28", + "- wpls29", "- wpls30", "- wpls31"}; + + +/*! + * \brief fmorphautogen() + * + * \param[in] sela + * \param[in] fileindex + * \param[in] filename [optional]; can be null + * \return 0 if OK; 1 on error + * + * <pre> + * Notes: + * (1) This function generates all the code for implementing + * dwa morphological operations using all the sels in the sela. + * (2) See fmorphautogen1() and fmorphautogen2() for details. + * </pre> + */ +l_ok +fmorphautogen(SELA *sela, + l_int32 fileindex, + const char *filename) +{ +l_int32 ret1, ret2; + + if (!sela) + return ERROR_INT("sela not defined", __func__, 1); + ret1 = fmorphautogen1(sela, fileindex, filename); + ret2 = fmorphautogen2(sela, fileindex, filename); + if (ret1 || ret2) + return ERROR_INT("code generation problem", __func__, 1); + return 0; +} + + +/*! + * \brief fmorphautogen1() + * + * \param[in] sela + * \param[in] fileindex + * \param[in] filename [optional]; can be null + * \return 0 if OK; 1 on error + * + * <pre> + * Notes: + * (1) This function uses morphtemplate1.txt to create a + * top-level file that contains two functions. These + * functions will carry out dilation, erosion, + * opening or closing for any of the sels in the input sela. + * (2) The fileindex parameter is inserted into the output + * filename, as described below. + * (3) If filename == NULL, the output file is fmorphgen.[n].c, + * where [n] is equal to the %fileindex parameter. + * (4) If filename != NULL, the output file is [%filename].[n].c. + * </pre> + */ +l_ok +fmorphautogen1(SELA *sela, + l_int32 fileindex, + const char *filename) +{ +char *filestr; +char *str_proto1, *str_proto2, *str_proto3; +char *str_doc1, *str_doc2, *str_doc3, *str_doc4; +char *str_def1, *str_def2, *str_proc1, *str_proc2; +char *str_dwa1, *str_low_dt, *str_low_ds, *str_low_ts; +char *str_low_tsp1, *str_low_dtp1; +char bigbuf[L_BUF_SIZE]; +l_int32 i, nsels, nbytes, actstart, end, newstart; +size_t size; +SARRAY *sa1, *sa2, *sa3; + + if (!sela) + return ERROR_INT("sela not defined", __func__, 1); + if (fileindex < 0) + fileindex = 0; + if ((nsels = selaGetCount(sela)) == 0) + return ERROR_INT("no sels in sela", __func__, 1); + + /* Make array of textlines from morphtemplate1.txt */ + if ((filestr = (char *)l_binaryRead(TEMPLATE1, &size)) == NULL) + return ERROR_INT("filestr not made", __func__, 1); + sa2 = sarrayCreateLinesFromString(filestr, 1); + LEPT_FREE(filestr); + if (!sa2) + return ERROR_INT("sa2 not made", __func__, 1); + + /* Make array of sel names */ + sa1 = selaGetSelnames(sela); + + /* Make strings containing function call names */ + sprintf(bigbuf, "PIX *pixMorphDwa_%d(PIX *pixd, PIX *pixs, " + "l_int32 operation, char *selname);", fileindex); + str_proto1 = stringNew(bigbuf); + sprintf(bigbuf, "PIX *pixFMorphopGen_%d(PIX *pixd, PIX *pixs, " + "l_int32 operation, char *selname);", fileindex); + str_proto2 = stringNew(bigbuf); + sprintf(bigbuf, "l_int32 fmorphopgen_low_%d(l_uint32 *datad, l_int32 w,\n" + " l_int32 h, l_int32 wpld,\n" + " l_uint32 *datas, l_int32 wpls,\n" + " l_int32 index);", fileindex); + str_proto3 = stringNew(bigbuf); + sprintf(bigbuf, " * PIX *pixMorphDwa_%d()", fileindex); + str_doc1 = stringNew(bigbuf); + sprintf(bigbuf, " * PIX *pixFMorphopGen_%d()", fileindex); + str_doc2 = stringNew(bigbuf); + sprintf(bigbuf, " * \\brief pixMorphDwa_%d()", fileindex); + str_doc3 = stringNew(bigbuf); + sprintf(bigbuf, " * \\brief pixFMorphopGen_%d()", fileindex); + str_doc4 = stringNew(bigbuf); + sprintf(bigbuf, "pixMorphDwa_%d(PIX *pixd,", fileindex); + str_def1 = stringNew(bigbuf); + sprintf(bigbuf, "pixFMorphopGen_%d(PIX *pixd,", fileindex); + str_def2 = stringNew(bigbuf); + sprintf(bigbuf, " PROCNAME(\"pixMorphDwa_%d\");", fileindex); + str_proc1 = stringNew(bigbuf); + sprintf(bigbuf, " PROCNAME(\"pixFMorphopGen_%d\");", fileindex); + str_proc2 = stringNew(bigbuf); + sprintf(bigbuf, + " pixt2 = pixFMorphopGen_%d(NULL, pixt1, operation, selname);", + fileindex); + str_dwa1 = stringNew(bigbuf); + sprintf(bigbuf, + " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index);", + fileindex); + str_low_dt = stringNew(bigbuf); + sprintf(bigbuf, + " fmorphopgen_low_%d(datad, w, h, wpld, datas, wpls, index);", + fileindex); + str_low_ds = stringNew(bigbuf); + sprintf(bigbuf, + " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index+1);", + fileindex); + str_low_tsp1 = stringNew(bigbuf); + sprintf(bigbuf, + " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index);", + fileindex); + str_low_ts = stringNew(bigbuf); + sprintf(bigbuf, + " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index+1);", + fileindex); + str_low_dtp1 = stringNew(bigbuf); + + /* Make the output sa */ + sa3 = sarrayCreate(0); + + /* Copyright notice and info header */ + sarrayParseRange(sa2, 0, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Insert function names as documentation */ + sarrayAddString(sa3, str_doc1, L_INSERT); + sarrayAddString(sa3, str_doc2, L_INSERT); + + /* Add '#include's */ + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Insert function prototypes */ + sarrayAddString(sa3, str_proto1, L_INSERT); + sarrayAddString(sa3, str_proto2, L_INSERT); + sarrayAddString(sa3, str_proto3, L_INSERT); + + /* Add static globals */ + sprintf(bigbuf, "\nstatic l_int32 NUM_SELS_GENERATED = %d;", nsels); + sarrayAddString(sa3, bigbuf, L_COPY); + sprintf(bigbuf, "static char SEL_NAMES[][80] = {"); + sarrayAddString(sa3, bigbuf, L_COPY); + for (i = 0; i < nsels - 1; i++) { + sprintf(bigbuf, " \"%s\",", + sarrayGetString(sa1, i, L_NOCOPY)); + sarrayAddString(sa3, bigbuf, L_COPY); + } + sprintf(bigbuf, " \"%s\"};", + sarrayGetString(sa1, i, L_NOCOPY)); + sarrayAddString(sa3, bigbuf, L_COPY); + + /* Start pixMorphDwa_*() function description */ + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_doc3, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Finish pixMorphDwa_*() function definition */ + sarrayAddString(sa3, str_def1, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_proc1, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_dwa1, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Start pixFMorphopGen_*() function description */ + sarrayAddString(sa3, str_doc4, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Finish pixFMorphopGen_*() function definition */ + sarrayAddString(sa3, str_def2, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_proc2, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_low_dt, L_COPY); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_low_ds, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_low_tsp1, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_low_dt, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_low_ts, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + sarrayAddString(sa3, str_low_dtp1, L_INSERT); + sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa3, sa2, actstart, end); + + /* Output to file */ + filestr = sarrayToString(sa3, 1); + nbytes = strlen(filestr); + if (filename) + snprintf(bigbuf, L_BUF_SIZE, "%s.%d.c", filename, fileindex); + else + sprintf(bigbuf, "%s.%d.c", OUTROOT, fileindex); + l_binaryWrite(bigbuf, "w", filestr, nbytes); + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + sarrayDestroy(&sa3); + LEPT_FREE(filestr); + return 0; +} + + +/* + * fmorphautogen2() + * + * Input: sela + * fileindex + * filename (<optional>; can be null) + * Return: 0 if OK; 1 on error + * + * Notes: + * (1) This function uses morphtemplate2.txt to create a + * low-level file that contains the low-level functions for + * implementing dilation and erosion for every sel + * in the input sela. + * (2) The fileindex parameter is inserted into the output + * filename, as described below. + * (3) If filename == NULL, the output file is fmorphgenlow.[n].c, + * where [n] is equal to the 'fileindex' parameter. + * (4) If filename != NULL, the output file is [filename]low.[n].c. + */ +l_int32 +fmorphautogen2(SELA *sela, + l_int32 fileindex, + const char *filename) +{ +char *filestr, *linestr, *fname; +char *str_doc1, *str_doc2, *str_doc3, *str_doc4, *str_def1; +char bigbuf[L_BUF_SIZE]; +char breakstring[] = " break;"; +char staticstring[] = "static void"; +l_int32 i, nsels, nbytes, actstart, end, newstart; +l_int32 argstart, argend, loopstart, loopend, finalstart, finalend; +size_t size; +SARRAY *sa1, *sa2, *sa3, *sa4, *sa5, *sa6; +SEL *sel; + + if (!sela) + return ERROR_INT("sela not defined", __func__, 1); + if (fileindex < 0) + fileindex = 0; + if ((nsels = selaGetCount(sela)) == 0) + return ERROR_INT("no sels in sela", __func__, 1); + + /* Make the array of textlines from morphtemplate2.txt */ + if ((filestr = (char *)l_binaryRead(TEMPLATE2, &size)) == NULL) + return ERROR_INT("filestr not made", __func__, 1); + sa1 = sarrayCreateLinesFromString(filestr, 1); + LEPT_FREE(filestr); + if (!sa1) + return ERROR_INT("sa1 not made", __func__, 1); + + /* Make the array of static function names */ + if ((sa2 = sarrayCreate(2 * nsels)) == NULL) { + sarrayDestroy(&sa1); + return ERROR_INT("sa2 not made", __func__, 1); + } + for (i = 0; i < nsels; i++) { + sprintf(bigbuf, "fdilate_%d_%d", fileindex, i); + sarrayAddString(sa2, bigbuf, L_COPY); + sprintf(bigbuf, "ferode_%d_%d", fileindex, i); + sarrayAddString(sa2, bigbuf, L_COPY); + } + + /* Make the static prototype strings */ + sa3 = sarrayCreate(2 * nsels); /* should be ok */ + for (i = 0; i < 2 * nsels; i++) { + fname = sarrayGetString(sa2, i, L_NOCOPY); + sprintf(bigbuf, "static void %s%s", fname, PROTOARGS); + sarrayAddString(sa3, bigbuf, L_COPY); + } + + /* Make strings containing function names */ + sprintf(bigbuf, " * l_int32 fmorphopgen_low_%d()", + fileindex); + str_doc1 = stringNew(bigbuf); + sprintf(bigbuf, " * void fdilate_%d_*()", fileindex); + str_doc2 = stringNew(bigbuf); + sprintf(bigbuf, " * void ferode_%d_*()", fileindex); + str_doc3 = stringNew(bigbuf); + + /* Output to this sa */ + sa4 = sarrayCreate(0); + + /* Copyright notice and info header */ + sarrayParseRange(sa1, 0, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa4, sa1, actstart, end); + + /* Insert function names as documentation */ + sarrayAddString(sa4, str_doc1, L_INSERT); + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa4, sa1, actstart, end); + sarrayAddString(sa4, str_doc2, L_INSERT); + sarrayAddString(sa4, str_doc3, L_INSERT); + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa4, sa1, actstart, end); + + /* Insert static protos */ + for (i = 0; i < 2 * nsels; i++) { + if ((linestr = sarrayGetString(sa3, i, L_COPY)) == NULL) { + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + sarrayDestroy(&sa3); + sarrayDestroy(&sa4); + return ERROR_INT("linestr not retrieved", __func__, 1); + } + sarrayAddString(sa4, linestr, L_INSERT); + } + + /* More strings with function names */ + sprintf(bigbuf, " * fmorphopgen_low_%d()", fileindex); + str_doc4 = stringNew(bigbuf); + sprintf(bigbuf, "fmorphopgen_low_%d(l_uint32 *datad,", fileindex); + str_def1 = stringNew(bigbuf); + + /* Insert function header */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa4, sa1, actstart, end); + sarrayAddString(sa4, str_doc4, L_INSERT); + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa4, sa1, actstart, end); + sarrayAddString(sa4, str_def1, L_INSERT); + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa4, sa1, actstart, end); + + /* Generate and insert the dispatcher code */ + for (i = 0; i < 2 * nsels; i++) { + sprintf(bigbuf, " case %d:", i); + sarrayAddString(sa4, bigbuf, L_COPY); + sprintf(bigbuf, " %s(datad, w, h, wpld, datas, wpls);", + sarrayGetString(sa2, i, L_NOCOPY)); + sarrayAddString(sa4, bigbuf, L_COPY); + sarrayAddString(sa4, breakstring, L_COPY); + } + + /* Finish the dispatcher and introduce the low-level code */ + sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0); + sarrayAppendRange(sa4, sa1, actstart, end); + + /* Get the range for the args common to all functions */ + sarrayParseRange(sa1, newstart, &argstart, &argend, &newstart, "--", 0); + + /* Get the range for the loop code common to all functions */ + sarrayParseRange(sa1, newstart, &loopstart, &loopend, &newstart, "--", 0); + + /* Get the range for the ending code common to all functions */ + sarrayParseRange(sa1, newstart, &finalstart, &finalend, &newstart, "--", 0); + + /* Do all the static functions */ + for (i = 0; i < 2 * nsels; i++) { + /* Generate the function header and add the common args */ + sarrayAddString(sa4, staticstring, L_COPY); + fname = sarrayGetString(sa2, i, L_NOCOPY); + sprintf(bigbuf, "%s(l_uint32 *datad,", fname); + sarrayAddString(sa4, bigbuf, L_COPY); + sarrayAppendRange(sa4, sa1, argstart, argend); + + /* Declare and define wplsN args, as necessary */ + if ((sel = selaGetSel(sela, i/2)) == NULL) { + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + sarrayDestroy(&sa3); + sarrayDestroy(&sa4); + return ERROR_INT("sel not returned", __func__, 1); + } + sa5 = sarrayMakeWplsCode(sel); + sarrayJoin(sa4, sa5); + sarrayDestroy(&sa5); + + /* Add the function loop code */ + sarrayAppendRange(sa4, sa1, loopstart, loopend); + + /* Insert barrel-op code for *dptr */ + sa6 = sarrayMakeInnerLoopDWACode(sel, i); + sarrayJoin(sa4, sa6); + sarrayDestroy(&sa6); + + /* Finish the function code */ + sarrayAppendRange(sa4, sa1, finalstart, finalend); + } + + /* Output to file */ + filestr = sarrayToString(sa4, 1); + nbytes = strlen(filestr); + if (filename) + snprintf(bigbuf, L_BUF_SIZE, "%slow.%d.c", filename, fileindex); + else + sprintf(bigbuf, "%slow.%d.c", OUTROOT, fileindex); + l_binaryWrite(bigbuf, "w", filestr, nbytes); + sarrayDestroy(&sa1); + sarrayDestroy(&sa2); + sarrayDestroy(&sa3); + sarrayDestroy(&sa4); + LEPT_FREE(filestr); + return 0; +} + + +/*--------------------------------------------------------------------------* + * Helper code for sel * + *--------------------------------------------------------------------------*/ +/*! + * \brief sarrayMakeWplsCode() + */ +static SARRAY * +sarrayMakeWplsCode(SEL *sel) +{ +char emptystring[] = ""; +l_int32 i, j, ymax, dely, allvshifts; +l_int32 vshift[32]; +SARRAY *sa; + + if (!sel) + return (SARRAY *)ERROR_PTR("sel not defined", __func__, NULL); + + for (i = 0; i < 32; i++) + vshift[i] = 0; + ymax = 0; + for (i = 0; i < sel->sy; i++) { + for (j = 0; j < sel->sx; j++) { + if (sel->data[i][j] == 1) { + dely = L_ABS(i - sel->cy); + if (dely < 32) + vshift[dely] = 1; + ymax = L_MAX(ymax, dely); + } + } + } + if (ymax > 31) { + L_WARNING("ymax > 31; truncating to 31\n", __func__); + ymax = 31; + } + + /* Test if this is a vertical brick */ + allvshifts = TRUE; + for (i = 0; i < ymax; i++) { + if (vshift[i] == 0) { + allvshifts = FALSE; + break; + } + } + + sa = sarrayCreate(0); + + /* Add declarations */ + if (allvshifts == TRUE) { /* packs them as well as possible */ + if (ymax > 4) + sarrayAddString(sa, wpldecls[2], L_COPY); + if (ymax > 8) + sarrayAddString(sa, wpldecls[6], L_COPY); + if (ymax > 12) + sarrayAddString(sa, wpldecls[10], L_COPY); + if (ymax > 16) + sarrayAddString(sa, wpldecls[14], L_COPY); + if (ymax > 20) + sarrayAddString(sa, wpldecls[18], L_COPY); + if (ymax > 24) + sarrayAddString(sa, wpldecls[22], L_COPY); + if (ymax > 28) + sarrayAddString(sa, wpldecls[26], L_COPY); + if (ymax > 1) + sarrayAddString(sa, wpldecls[ymax - 2], L_COPY); + } else { /* puts them one/line */ + for (i = 2; i <= ymax; i++) { + if (vshift[i]) + sarrayAddString(sa, wplgendecls[i - 2], L_COPY); + } + } + + sarrayAddString(sa, emptystring, L_COPY); + + /* Add definitions */ + for (i = 2; i <= ymax; i++) { + if (vshift[i]) + sarrayAddString(sa, wpldefs[i - 2], L_COPY); + } + + return sa; +} + + +/*! + * \brief sarrayMakeInnerLoopDWACode() + */ +static SARRAY * +sarrayMakeInnerLoopDWACode(SEL *sel, + l_int32 index) +{ +char *tstr, *string; +char logicalor[] = "|"; +char logicaland[] = "&"; +char bigbuf[L_BUF_SIZE]; +l_int32 i, j, optype, count, nfound, delx, dely; +SARRAY *sa; + + if (!sel) + return (SARRAY *)ERROR_PTR("sel not defined", __func__, NULL); + + if (index % 2 == 0) { + optype = L_MORPH_DILATE; + tstr = logicalor; + } else { + optype = L_MORPH_ERODE; + tstr = logicaland; + } + + count = 0; + for (i = 0; i < sel->sy; i++) { + for (j = 0; j < sel->sx; j++) { + if (sel->data[i][j] == 1) + count++; + } + } + + sa = sarrayCreate(0); + if (count == 0) { + L_WARNING("no hits in Sel %d\n", __func__, index); + return sa; /* no code inside! */ + } + + nfound = 0; + for (i = 0; i < sel->sy; i++) { + for (j = 0; j < sel->sx; j++) { + if (sel->data[i][j] == 1) { + nfound++; + if (optype == L_MORPH_DILATE) { + dely = sel->cy - i; + delx = sel->cx - j; + } else { /* optype == L_MORPH_ERODE */ + dely = i - sel->cy; + delx = j - sel->cx; + } + if ((string = makeBarrelshiftString(delx, dely)) == NULL) { + L_WARNING("barrel shift string not made\n", __func__); + continue; + } + if (count == 1) /* just one item */ + sprintf(bigbuf, " *dptr = %s;", string); + else if (nfound == 1) + sprintf(bigbuf, " *dptr = %s %s", string, tstr); + else if (nfound < count) + sprintf(bigbuf, " %s %s", string, tstr); + else /* nfound == count */ + sprintf(bigbuf, " %s;", string); + sarrayAddString(sa, bigbuf, L_COPY); + LEPT_FREE(string); + } + } + } + + return sa; +} + + +/*! + * \brief makeBarrelshiftString() + */ +static char * +makeBarrelshiftString(l_int32 delx, /* j - cx */ + l_int32 dely) /* i - cy */ +{ +l_int32 absx, absy; +char bigbuf[L_BUF_SIZE]; + + if (delx < -31 || delx > 31) + return (char *)ERROR_PTR("delx out of bounds", __func__, NULL); + if (dely < -31 || dely > 31) + return (char *)ERROR_PTR("dely out of bounds", __func__, NULL); + absx = L_ABS(delx); + absy = L_ABS(dely); + + if ((delx == 0) && (dely == 0)) + sprintf(bigbuf, "(*sptr)"); + else if ((delx == 0) && (dely < 0)) + sprintf(bigbuf, "(*(sptr %s))", wplstrm[absy - 1]); + else if ((delx == 0) && (dely > 0)) + sprintf(bigbuf, "(*(sptr %s))", wplstrp[absy - 1]); + else if ((delx < 0) && (dely == 0)) + sprintf(bigbuf, "((*(sptr) >> %d) | (*(sptr - 1) << %d))", + absx, 32 - absx); + else if ((delx > 0) && (dely == 0)) + sprintf(bigbuf, "((*(sptr) << %d) | (*(sptr + 1) >> %d))", + absx, 32 - absx); + else if ((delx < 0) && (dely < 0)) + sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))", + wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); + else if ((delx > 0) && (dely < 0)) + sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))", + wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx); + else if ((delx < 0) && (dely > 0)) + sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))", + wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); + else /* ((delx > 0) && (dely > 0)) */ + sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))", + wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx); + + return stringNew(bigbuf); +}
