Leptonica  1.82.0
Image processing and image analysis suite
fmorphauto.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
27 
99 #ifdef HAVE_CONFIG_H
100 #include <config_auto.h>
101 #endif /* HAVE_CONFIG_H */
102 
103 #include <string.h>
104 #include "allheaders.h"
105 
106 #define OUTROOT "fmorphgen"
107 #define TEMPLATE1 "morphtemplate1.txt"
108 #define TEMPLATE2 "morphtemplate2.txt"
109 
110 #define PROTOARGS "(l_uint32 *, l_int32, l_int32, l_int32, l_uint32 *, l_int32);"
111 
112 #define L_BUF_SIZE 512
113 
114 static char * makeBarrelshiftString(l_int32 delx, l_int32 dely);
115 static SARRAY * sarrayMakeInnerLoopDWACode(SEL *sel, l_int32 index);
116 static SARRAY * sarrayMakeWplsCode(SEL *sel);
117 
118 static char wpldecls[][53] = {
119  "l_int32 wpls2;",
120  "l_int32 wpls2, wpls3;",
121  "l_int32 wpls2, wpls3, wpls4;",
122  "l_int32 wpls5;",
123  "l_int32 wpls5, wpls6;",
124  "l_int32 wpls5, wpls6, wpls7;",
125  "l_int32 wpls5, wpls6, wpls7, wpls8;",
126  "l_int32 wpls9;",
127  "l_int32 wpls9, wpls10;",
128  "l_int32 wpls9, wpls10, wpls11;",
129  "l_int32 wpls9, wpls10, wpls11, wpls12;",
130  "l_int32 wpls13;",
131  "l_int32 wpls13, wpls14;",
132  "l_int32 wpls13, wpls14, wpls15;",
133  "l_int32 wpls13, wpls14, wpls15, wpls16;",
134  "l_int32 wpls17;",
135  "l_int32 wpls17, wpls18;",
136  "l_int32 wpls17, wpls18, wpls19;",
137  "l_int32 wpls17, wpls18, wpls19, wpls20;",
138  "l_int32 wpls21;",
139  "l_int32 wpls21, wpls22;",
140  "l_int32 wpls21, wpls22, wpls23;",
141  "l_int32 wpls21, wpls22, wpls23, wpls24;",
142  "l_int32 wpls25;",
143  "l_int32 wpls25, wpls26;",
144  "l_int32 wpls25, wpls26, wpls27;",
145  "l_int32 wpls25, wpls26, wpls27, wpls28;",
146  "l_int32 wpls29;",
147  "l_int32 wpls29, wpls30;",
148  "l_int32 wpls29, wpls30, wpls31;"};
149 
150 static char wplgendecls[][30] = {
151  "l_int32 wpls2;",
152  "l_int32 wpls3;",
153  "l_int32 wpls4;",
154  "l_int32 wpls5;",
155  "l_int32 wpls6;",
156  "l_int32 wpls7;",
157  "l_int32 wpls8;",
158  "l_int32 wpls9;",
159  "l_int32 wpls10;",
160  "l_int32 wpls11;",
161  "l_int32 wpls12;",
162  "l_int32 wpls13;",
163  "l_int32 wpls14;",
164  "l_int32 wpls15;",
165  "l_int32 wpls16;",
166  "l_int32 wpls17;",
167  "l_int32 wpls18;",
168  "l_int32 wpls19;",
169  "l_int32 wpls20;",
170  "l_int32 wpls21;",
171  "l_int32 wpls22;",
172  "l_int32 wpls23;",
173  "l_int32 wpls24;",
174  "l_int32 wpls25;",
175  "l_int32 wpls26;",
176  "l_int32 wpls27;",
177  "l_int32 wpls28;",
178  "l_int32 wpls29;",
179  "l_int32 wpls30;",
180  "l_int32 wpls31;"};
181 
182 static char wpldefs[][25] = {
183  " wpls2 = 2 * wpls;",
184  " wpls3 = 3 * wpls;",
185  " wpls4 = 4 * wpls;",
186  " wpls5 = 5 * wpls;",
187  " wpls6 = 6 * wpls;",
188  " wpls7 = 7 * wpls;",
189  " wpls8 = 8 * wpls;",
190  " wpls9 = 9 * wpls;",
191  " wpls10 = 10 * wpls;",
192  " wpls11 = 11 * wpls;",
193  " wpls12 = 12 * wpls;",
194  " wpls13 = 13 * wpls;",
195  " wpls14 = 14 * wpls;",
196  " wpls15 = 15 * wpls;",
197  " wpls16 = 16 * wpls;",
198  " wpls17 = 17 * wpls;",
199  " wpls18 = 18 * wpls;",
200  " wpls19 = 19 * wpls;",
201  " wpls20 = 20 * wpls;",
202  " wpls21 = 21 * wpls;",
203  " wpls22 = 22 * wpls;",
204  " wpls23 = 23 * wpls;",
205  " wpls24 = 24 * wpls;",
206  " wpls25 = 25 * wpls;",
207  " wpls26 = 26 * wpls;",
208  " wpls27 = 27 * wpls;",
209  " wpls28 = 28 * wpls;",
210  " wpls29 = 29 * wpls;",
211  " wpls30 = 30 * wpls;",
212  " wpls31 = 31 * wpls;"};
213 
214 static char wplstrp[][10] = {"+ wpls", "+ wpls2", "+ wpls3", "+ wpls4",
215  "+ wpls5", "+ wpls6", "+ wpls7", "+ wpls8",
216  "+ wpls9", "+ wpls10", "+ wpls11", "+ wpls12",
217  "+ wpls13", "+ wpls14", "+ wpls15", "+ wpls16",
218  "+ wpls17", "+ wpls18", "+ wpls19", "+ wpls20",
219  "+ wpls21", "+ wpls22", "+ wpls23", "+ wpls24",
220  "+ wpls25", "+ wpls26", "+ wpls27", "+ wpls28",
221  "+ wpls29", "+ wpls30", "+ wpls31"};
222 
223 static char wplstrm[][10] = {"- wpls", "- wpls2", "- wpls3", "- wpls4",
224  "- wpls5", "- wpls6", "- wpls7", "- wpls8",
225  "- wpls9", "- wpls10", "- wpls11", "- wpls12",
226  "- wpls13", "- wpls14", "- wpls15", "- wpls16",
227  "- wpls17", "- wpls18", "- wpls19", "- wpls20",
228  "- wpls21", "- wpls22", "- wpls23", "- wpls24",
229  "- wpls25", "- wpls26", "- wpls27", "- wpls28",
230  "- wpls29", "- wpls30", "- wpls31"};
231 
232 
248 l_ok
250  l_int32 fileindex,
251  const char *filename)
252 {
253 l_int32 ret1, ret2;
254 
255  PROCNAME("fmorphautogen");
256 
257  if (!sela)
258  return ERROR_INT("sela not defined", procName, 1);
259  ret1 = fmorphautogen1(sela, fileindex, filename);
260  ret2 = fmorphautogen2(sela, fileindex, filename);
261  if (ret1 || ret2)
262  return ERROR_INT("code generation problem", procName, 1);
263  return 0;
264 }
265 
266 
288 l_ok
290  l_int32 fileindex,
291  const char *filename)
292 {
293 char *filestr;
294 char *str_proto1, *str_proto2, *str_proto3;
295 char *str_doc1, *str_doc2, *str_doc3, *str_doc4;
296 char *str_def1, *str_def2, *str_proc1, *str_proc2;
297 char *str_dwa1, *str_low_dt, *str_low_ds, *str_low_ts;
298 char *str_low_tsp1, *str_low_dtp1;
299 char bigbuf[L_BUF_SIZE];
300 l_int32 i, nsels, nbytes, actstart, end, newstart;
301 size_t size;
302 SARRAY *sa1, *sa2, *sa3;
303 
304  PROCNAME("fmorphautogen1");
305 
306  if (!sela)
307  return ERROR_INT("sela not defined", procName, 1);
308  if (fileindex < 0)
309  fileindex = 0;
310  if ((nsels = selaGetCount(sela)) == 0)
311  return ERROR_INT("no sels in sela", procName, 1);
312 
313  /* Make array of textlines from morphtemplate1.txt */
314  if ((filestr = (char *)l_binaryRead(TEMPLATE1, &size)) == NULL)
315  return ERROR_INT("filestr not made", procName, 1);
316  sa2 = sarrayCreateLinesFromString(filestr, 1);
317  LEPT_FREE(filestr);
318  if (!sa2)
319  return ERROR_INT("sa2 not made", procName, 1);
320 
321  /* Make array of sel names */
322  sa1 = selaGetSelnames(sela);
323 
324  /* Make strings containing function call names */
325  sprintf(bigbuf, "PIX *pixMorphDwa_%d(PIX *pixd, PIX *pixs, "
326  "l_int32 operation, char *selname);", fileindex);
327  str_proto1 = stringNew(bigbuf);
328  sprintf(bigbuf, "PIX *pixFMorphopGen_%d(PIX *pixd, PIX *pixs, "
329  "l_int32 operation, char *selname);", fileindex);
330  str_proto2 = stringNew(bigbuf);
331  sprintf(bigbuf, "l_int32 fmorphopgen_low_%d(l_uint32 *datad, l_int32 w,\n"
332  " l_int32 h, l_int32 wpld,\n"
333  " l_uint32 *datas, l_int32 wpls,\n"
334  " l_int32 index);", fileindex);
335  str_proto3 = stringNew(bigbuf);
336  sprintf(bigbuf, " * PIX *pixMorphDwa_%d()", fileindex);
337  str_doc1 = stringNew(bigbuf);
338  sprintf(bigbuf, " * PIX *pixFMorphopGen_%d()", fileindex);
339  str_doc2 = stringNew(bigbuf);
340  sprintf(bigbuf, " * \\brief pixMorphDwa_%d()", fileindex);
341  str_doc3 = stringNew(bigbuf);
342  sprintf(bigbuf, " * \\brief pixFMorphopGen_%d()", fileindex);
343  str_doc4 = stringNew(bigbuf);
344  sprintf(bigbuf, "pixMorphDwa_%d(PIX *pixd,", fileindex);
345  str_def1 = stringNew(bigbuf);
346  sprintf(bigbuf, "pixFMorphopGen_%d(PIX *pixd,", fileindex);
347  str_def2 = stringNew(bigbuf);
348  sprintf(bigbuf, " PROCNAME(\"pixMorphDwa_%d\");", fileindex);
349  str_proc1 = stringNew(bigbuf);
350  sprintf(bigbuf, " PROCNAME(\"pixFMorphopGen_%d\");", fileindex);
351  str_proc2 = stringNew(bigbuf);
352  sprintf(bigbuf,
353  " pixt2 = pixFMorphopGen_%d(NULL, pixt1, operation, selname);",
354  fileindex);
355  str_dwa1 = stringNew(bigbuf);
356  sprintf(bigbuf,
357  " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index);",
358  fileindex);
359  str_low_dt = stringNew(bigbuf);
360  sprintf(bigbuf,
361  " fmorphopgen_low_%d(datad, w, h, wpld, datas, wpls, index);",
362  fileindex);
363  str_low_ds = stringNew(bigbuf);
364  sprintf(bigbuf,
365  " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index+1);",
366  fileindex);
367  str_low_tsp1 = stringNew(bigbuf);
368  sprintf(bigbuf,
369  " fmorphopgen_low_%d(datat, w, h, wpls, datas, wpls, index);",
370  fileindex);
371  str_low_ts = stringNew(bigbuf);
372  sprintf(bigbuf,
373  " fmorphopgen_low_%d(datad, w, h, wpld, datat, wpls, index+1);",
374  fileindex);
375  str_low_dtp1 = stringNew(bigbuf);
376 
377  /* Make the output sa */
378  sa3 = sarrayCreate(0);
379 
380  /* Copyright notice and info header */
381  sarrayParseRange(sa2, 0, &actstart, &end, &newstart, "--", 0);
382  sarrayAppendRange(sa3, sa2, actstart, end);
383 
384  /* Insert function names as documentation */
385  sarrayAddString(sa3, str_doc1, L_INSERT);
386  sarrayAddString(sa3, str_doc2, L_INSERT);
387 
388  /* Add '#include's */
389  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
390  sarrayAppendRange(sa3, sa2, actstart, end);
391 
392  /* Insert function prototypes */
393  sarrayAddString(sa3, str_proto1, L_INSERT);
394  sarrayAddString(sa3, str_proto2, L_INSERT);
395  sarrayAddString(sa3, str_proto3, L_INSERT);
396 
397  /* Add static globals */
398  sprintf(bigbuf, "\nstatic l_int32 NUM_SELS_GENERATED = %d;", nsels);
399  sarrayAddString(sa3, bigbuf, L_COPY);
400  sprintf(bigbuf, "static char SEL_NAMES[][80] = {");
401  sarrayAddString(sa3, bigbuf, L_COPY);
402  for (i = 0; i < nsels - 1; i++) {
403  sprintf(bigbuf, " \"%s\",",
404  sarrayGetString(sa1, i, L_NOCOPY));
405  sarrayAddString(sa3, bigbuf, L_COPY);
406  }
407  sprintf(bigbuf, " \"%s\"};",
408  sarrayGetString(sa1, i, L_NOCOPY));
409  sarrayAddString(sa3, bigbuf, L_COPY);
410 
411  /* Start pixMorphDwa_*() function description */
412  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
413  sarrayAppendRange(sa3, sa2, actstart, end);
414  sarrayAddString(sa3, str_doc3, L_INSERT);
415  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
416  sarrayAppendRange(sa3, sa2, actstart, end);
417 
418  /* Finish pixMorphDwa_*() function definition */
419  sarrayAddString(sa3, str_def1, L_INSERT);
420  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
421  sarrayAppendRange(sa3, sa2, actstart, end);
422  sarrayAddString(sa3, str_proc1, L_INSERT);
423  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
424  sarrayAppendRange(sa3, sa2, actstart, end);
425  sarrayAddString(sa3, str_dwa1, L_INSERT);
426  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
427  sarrayAppendRange(sa3, sa2, actstart, end);
428 
429  /* Start pixFMorphopGen_*() function description */
430  sarrayAddString(sa3, str_doc4, L_INSERT);
431  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
432  sarrayAppendRange(sa3, sa2, actstart, end);
433 
434  /* Finish pixFMorphopGen_*() function definition */
435  sarrayAddString(sa3, str_def2, L_INSERT);
436  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
437  sarrayAppendRange(sa3, sa2, actstart, end);
438  sarrayAddString(sa3, str_proc2, L_INSERT);
439  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
440  sarrayAppendRange(sa3, sa2, actstart, end);
441  sarrayAddString(sa3, str_low_dt, L_COPY);
442  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
443  sarrayAppendRange(sa3, sa2, actstart, end);
444  sarrayAddString(sa3, str_low_ds, L_INSERT);
445  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
446  sarrayAppendRange(sa3, sa2, actstart, end);
447  sarrayAddString(sa3, str_low_tsp1, L_INSERT);
448  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
449  sarrayAppendRange(sa3, sa2, actstart, end);
450  sarrayAddString(sa3, str_low_dt, L_INSERT);
451  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
452  sarrayAppendRange(sa3, sa2, actstart, end);
453  sarrayAddString(sa3, str_low_ts, L_INSERT);
454  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
455  sarrayAppendRange(sa3, sa2, actstart, end);
456  sarrayAddString(sa3, str_low_dtp1, L_INSERT);
457  sarrayParseRange(sa2, newstart, &actstart, &end, &newstart, "--", 0);
458  sarrayAppendRange(sa3, sa2, actstart, end);
459 
460  /* Output to file */
461  filestr = sarrayToString(sa3, 1);
462  nbytes = strlen(filestr);
463  if (filename)
464  snprintf(bigbuf, L_BUF_SIZE, "%s.%d.c", filename, fileindex);
465  else
466  sprintf(bigbuf, "%s.%d.c", OUTROOT, fileindex);
467  l_binaryWrite(bigbuf, "w", filestr, nbytes);
468  sarrayDestroy(&sa1);
469  sarrayDestroy(&sa2);
470  sarrayDestroy(&sa3);
471  LEPT_FREE(filestr);
472  return 0;
473 }
474 
475 
476 /*
477  * fmorphautogen2()
478  *
479  * Input: sela
480  * fileindex
481  * filename (<optional>; can be null)
482  * Return: 0 if OK; 1 on error
483  *
484  * Notes:
485  * (1) This function uses morphtemplate2.txt to create a
486  * low-level file that contains the low-level functions for
487  * implementing dilation and erosion for every sel
488  * in the input sela.
489  * (2) The fileindex parameter is inserted into the output
490  * filename, as described below.
491  * (3) If filename == NULL, the output file is fmorphgenlow.[n].c,
492  * where [n] is equal to the 'fileindex' parameter.
493  * (4) If filename != NULL, the output file is [filename]low.[n].c.
494  */
495 l_int32
496 fmorphautogen2(SELA *sela,
497  l_int32 fileindex,
498  const char *filename)
499 {
500 char *filestr, *linestr, *fname;
501 char *str_doc1, *str_doc2, *str_doc3, *str_doc4, *str_def1;
502 char bigbuf[L_BUF_SIZE];
503 char breakstring[] = " break;";
504 char staticstring[] = "static void";
505 l_int32 i, nsels, nbytes, actstart, end, newstart;
506 l_int32 argstart, argend, loopstart, loopend, finalstart, finalend;
507 size_t size;
508 SARRAY *sa1, *sa2, *sa3, *sa4, *sa5, *sa6;
509 SEL *sel;
510 
511  PROCNAME("fmorphautogen2");
512 
513  if (!sela)
514  return ERROR_INT("sela not defined", procName, 1);
515  if (fileindex < 0)
516  fileindex = 0;
517  if ((nsels = selaGetCount(sela)) == 0)
518  return ERROR_INT("no sels in sela", procName, 1);
519 
520  /* Make the array of textlines from morphtemplate2.txt */
521  if ((filestr = (char *)l_binaryRead(TEMPLATE2, &size)) == NULL)
522  return ERROR_INT("filestr not made", procName, 1);
523  sa1 = sarrayCreateLinesFromString(filestr, 1);
524  LEPT_FREE(filestr);
525  if (!sa1)
526  return ERROR_INT("sa1 not made", procName, 1);
527 
528  /* Make the array of static function names */
529  if ((sa2 = sarrayCreate(2 * nsels)) == NULL) {
530  sarrayDestroy(&sa1);
531  return ERROR_INT("sa2 not made", procName, 1);
532  }
533  for (i = 0; i < nsels; i++) {
534  sprintf(bigbuf, "fdilate_%d_%d", fileindex, i);
535  sarrayAddString(sa2, bigbuf, L_COPY);
536  sprintf(bigbuf, "ferode_%d_%d", fileindex, i);
537  sarrayAddString(sa2, bigbuf, L_COPY);
538  }
539 
540  /* Make the static prototype strings */
541  sa3 = sarrayCreate(2 * nsels); /* should be ok */
542  for (i = 0; i < 2 * nsels; i++) {
543  fname = sarrayGetString(sa2, i, L_NOCOPY);
544  sprintf(bigbuf, "static void %s%s", fname, PROTOARGS);
545  sarrayAddString(sa3, bigbuf, L_COPY);
546  }
547 
548  /* Make strings containing function names */
549  sprintf(bigbuf, " * l_int32 fmorphopgen_low_%d()",
550  fileindex);
551  str_doc1 = stringNew(bigbuf);
552  sprintf(bigbuf, " * void fdilate_%d_*()", fileindex);
553  str_doc2 = stringNew(bigbuf);
554  sprintf(bigbuf, " * void ferode_%d_*()", fileindex);
555  str_doc3 = stringNew(bigbuf);
556 
557  /* Output to this sa */
558  sa4 = sarrayCreate(0);
559 
560  /* Copyright notice and info header */
561  sarrayParseRange(sa1, 0, &actstart, &end, &newstart, "--", 0);
562  sarrayAppendRange(sa4, sa1, actstart, end);
563 
564  /* Insert function names as documentation */
565  sarrayAddString(sa4, str_doc1, L_INSERT);
566  sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
567  sarrayAppendRange(sa4, sa1, actstart, end);
568  sarrayAddString(sa4, str_doc2, L_INSERT);
569  sarrayAddString(sa4, str_doc3, L_INSERT);
570  sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
571  sarrayAppendRange(sa4, sa1, actstart, end);
572 
573  /* Insert static protos */
574  for (i = 0; i < 2 * nsels; i++) {
575  if ((linestr = sarrayGetString(sa3, i, L_COPY)) == NULL) {
576  sarrayDestroy(&sa1);
577  sarrayDestroy(&sa2);
578  sarrayDestroy(&sa3);
579  sarrayDestroy(&sa4);
580  return ERROR_INT("linestr not retrieved", procName, 1);
581  }
582  sarrayAddString(sa4, linestr, L_INSERT);
583  }
584 
585  /* More strings with function names */
586  sprintf(bigbuf, " * fmorphopgen_low_%d()", fileindex);
587  str_doc4 = stringNew(bigbuf);
588  sprintf(bigbuf, "fmorphopgen_low_%d(l_uint32 *datad,", fileindex);
589  str_def1 = stringNew(bigbuf);
590 
591  /* Insert function header */
592  sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
593  sarrayAppendRange(sa4, sa1, actstart, end);
594  sarrayAddString(sa4, str_doc4, L_INSERT);
595  sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
596  sarrayAppendRange(sa4, sa1, actstart, end);
597  sarrayAddString(sa4, str_def1, L_INSERT);
598  sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
599  sarrayAppendRange(sa4, sa1, actstart, end);
600 
601  /* Generate and insert the dispatcher code */
602  for (i = 0; i < 2 * nsels; i++) {
603  sprintf(bigbuf, " case %d:", i);
604  sarrayAddString(sa4, bigbuf, L_COPY);
605  sprintf(bigbuf, " %s(datad, w, h, wpld, datas, wpls);",
606  sarrayGetString(sa2, i, L_NOCOPY));
607  sarrayAddString(sa4, bigbuf, L_COPY);
608  sarrayAddString(sa4, breakstring, L_COPY);
609  }
610 
611  /* Finish the dispatcher and introduce the low-level code */
612  sarrayParseRange(sa1, newstart, &actstart, &end, &newstart, "--", 0);
613  sarrayAppendRange(sa4, sa1, actstart, end);
614 
615  /* Get the range for the args common to all functions */
616  sarrayParseRange(sa1, newstart, &argstart, &argend, &newstart, "--", 0);
617 
618  /* Get the range for the loop code common to all functions */
619  sarrayParseRange(sa1, newstart, &loopstart, &loopend, &newstart, "--", 0);
620 
621  /* Get the range for the ending code common to all functions */
622  sarrayParseRange(sa1, newstart, &finalstart, &finalend, &newstart, "--", 0);
623 
624  /* Do all the static functions */
625  for (i = 0; i < 2 * nsels; i++) {
626  /* Generate the function header and add the common args */
627  sarrayAddString(sa4, staticstring, L_COPY);
628  fname = sarrayGetString(sa2, i, L_NOCOPY);
629  sprintf(bigbuf, "%s(l_uint32 *datad,", fname);
630  sarrayAddString(sa4, bigbuf, L_COPY);
631  sarrayAppendRange(sa4, sa1, argstart, argend);
632 
633  /* Declare and define wplsN args, as necessary */
634  if ((sel = selaGetSel(sela, i/2)) == NULL) {
635  sarrayDestroy(&sa1);
636  sarrayDestroy(&sa2);
637  sarrayDestroy(&sa3);
638  sarrayDestroy(&sa4);
639  return ERROR_INT("sel not returned", procName, 1);
640  }
641  sa5 = sarrayMakeWplsCode(sel);
642  sarrayJoin(sa4, sa5);
643  sarrayDestroy(&sa5);
644 
645  /* Add the function loop code */
646  sarrayAppendRange(sa4, sa1, loopstart, loopend);
647 
648  /* Insert barrel-op code for *dptr */
649  sa6 = sarrayMakeInnerLoopDWACode(sel, i);
650  sarrayJoin(sa4, sa6);
651  sarrayDestroy(&sa6);
652 
653  /* Finish the function code */
654  sarrayAppendRange(sa4, sa1, finalstart, finalend);
655  }
656 
657  /* Output to file */
658  filestr = sarrayToString(sa4, 1);
659  nbytes = strlen(filestr);
660  if (filename)
661  snprintf(bigbuf, L_BUF_SIZE, "%slow.%d.c", filename, fileindex);
662  else
663  sprintf(bigbuf, "%slow.%d.c", OUTROOT, fileindex);
664  l_binaryWrite(bigbuf, "w", filestr, nbytes);
665  sarrayDestroy(&sa1);
666  sarrayDestroy(&sa2);
667  sarrayDestroy(&sa3);
668  sarrayDestroy(&sa4);
669  LEPT_FREE(filestr);
670  return 0;
671 }
672 
673 
674 /*--------------------------------------------------------------------------*
675  * Helper code for sel *
676  *--------------------------------------------------------------------------*/
680 static SARRAY *
682 {
683 char emptystring[] = "";
684 l_int32 i, j, ymax, dely, allvshifts;
685 l_int32 vshift[32];
686 SARRAY *sa;
687 
688  PROCNAME("sarrayMakeWplsCode");
689 
690  if (!sel)
691  return (SARRAY *)ERROR_PTR("sel not defined", procName, NULL);
692 
693  for (i = 0; i < 32; i++)
694  vshift[i] = 0;
695  ymax = 0;
696  for (i = 0; i < sel->sy; i++) {
697  for (j = 0; j < sel->sx; j++) {
698  if (sel->data[i][j] == 1) {
699  dely = L_ABS(i - sel->cy);
700  if (dely < 32)
701  vshift[dely] = 1;
702  ymax = L_MAX(ymax, dely);
703  }
704  }
705  }
706  if (ymax > 31) {
707  L_WARNING("ymax > 31; truncating to 31\n", procName);
708  ymax = 31;
709  }
710 
711  /* Test if this is a vertical brick */
712  allvshifts = TRUE;
713  for (i = 0; i < ymax; i++) {
714  if (vshift[i] == 0) {
715  allvshifts = FALSE;
716  break;
717  }
718  }
719 
720  sa = sarrayCreate(0);
721 
722  /* Add declarations */
723  if (allvshifts == TRUE) { /* packs them as well as possible */
724  if (ymax > 4)
725  sarrayAddString(sa, wpldecls[2], L_COPY);
726  if (ymax > 8)
727  sarrayAddString(sa, wpldecls[6], L_COPY);
728  if (ymax > 12)
729  sarrayAddString(sa, wpldecls[10], L_COPY);
730  if (ymax > 16)
731  sarrayAddString(sa, wpldecls[14], L_COPY);
732  if (ymax > 20)
733  sarrayAddString(sa, wpldecls[18], L_COPY);
734  if (ymax > 24)
735  sarrayAddString(sa, wpldecls[22], L_COPY);
736  if (ymax > 28)
737  sarrayAddString(sa, wpldecls[26], L_COPY);
738  if (ymax > 1)
739  sarrayAddString(sa, wpldecls[ymax - 2], L_COPY);
740  } else { /* puts them one/line */
741  for (i = 2; i <= ymax; i++) {
742  if (vshift[i])
743  sarrayAddString(sa, wplgendecls[i - 2], L_COPY);
744  }
745  }
746 
747  sarrayAddString(sa, emptystring, L_COPY);
748 
749  /* Add definitions */
750  for (i = 2; i <= ymax; i++) {
751  if (vshift[i])
752  sarrayAddString(sa, wpldefs[i - 2], L_COPY);
753  }
754 
755  return sa;
756 }
757 
758 
762 static SARRAY *
764  l_int32 index)
765 {
766 char *tstr, *string;
767 char logicalor[] = "|";
768 char logicaland[] = "&";
769 char bigbuf[L_BUF_SIZE];
770 l_int32 i, j, optype, count, nfound, delx, dely;
771 SARRAY *sa;
772 
773  PROCNAME("sarrayMakeInnerLoopDWACode");
774 
775  if (!sel)
776  return (SARRAY *)ERROR_PTR("sel not defined", procName, NULL);
777 
778  if (index % 2 == 0) {
779  optype = L_MORPH_DILATE;
780  tstr = logicalor;
781  } else {
782  optype = L_MORPH_ERODE;
783  tstr = logicaland;
784  }
785 
786  count = 0;
787  for (i = 0; i < sel->sy; i++) {
788  for (j = 0; j < sel->sx; j++) {
789  if (sel->data[i][j] == 1)
790  count++;
791  }
792  }
793 
794  sa = sarrayCreate(0);
795  if (count == 0) {
796  L_WARNING("no hits in Sel %d\n", procName, index);
797  return sa; /* no code inside! */
798  }
799 
800  nfound = 0;
801  for (i = 0; i < sel->sy; i++) {
802  for (j = 0; j < sel->sx; j++) {
803  if (sel->data[i][j] == 1) {
804  nfound++;
805  if (optype == L_MORPH_DILATE) {
806  dely = sel->cy - i;
807  delx = sel->cx - j;
808  } else { /* optype == L_MORPH_ERODE */
809  dely = i - sel->cy;
810  delx = j - sel->cx;
811  }
812  if ((string = makeBarrelshiftString(delx, dely)) == NULL) {
813  L_WARNING("barrel shift string not made\n", procName);
814  continue;
815  }
816  if (count == 1) /* just one item */
817  sprintf(bigbuf, " *dptr = %s;", string);
818  else if (nfound == 1)
819  sprintf(bigbuf, " *dptr = %s %s", string, tstr);
820  else if (nfound < count)
821  sprintf(bigbuf, " %s %s", string, tstr);
822  else /* nfound == count */
823  sprintf(bigbuf, " %s;", string);
824  sarrayAddString(sa, bigbuf, L_COPY);
825  LEPT_FREE(string);
826  }
827  }
828  }
829 
830  return sa;
831 }
832 
833 
837 static char *
838 makeBarrelshiftString(l_int32 delx, /* j - cx */
839  l_int32 dely) /* i - cy */
840 {
841 l_int32 absx, absy;
842 char bigbuf[L_BUF_SIZE];
843 
844  PROCNAME("makeBarrelshiftString");
845 
846  if (delx < -31 || delx > 31)
847  return (char *)ERROR_PTR("delx out of bounds", procName, NULL);
848  if (dely < -31 || dely > 31)
849  return (char *)ERROR_PTR("dely out of bounds", procName, NULL);
850  absx = L_ABS(delx);
851  absy = L_ABS(dely);
852 
853  if ((delx == 0) && (dely == 0))
854  sprintf(bigbuf, "(*sptr)");
855  else if ((delx == 0) && (dely < 0))
856  sprintf(bigbuf, "(*(sptr %s))", wplstrm[absy - 1]);
857  else if ((delx == 0) && (dely > 0))
858  sprintf(bigbuf, "(*(sptr %s))", wplstrp[absy - 1]);
859  else if ((delx < 0) && (dely == 0))
860  sprintf(bigbuf, "((*(sptr) >> %d) | (*(sptr - 1) << %d))",
861  absx, 32 - absx);
862  else if ((delx > 0) && (dely == 0))
863  sprintf(bigbuf, "((*(sptr) << %d) | (*(sptr + 1) >> %d))",
864  absx, 32 - absx);
865  else if ((delx < 0) && (dely < 0))
866  sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))",
867  wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx);
868  else if ((delx > 0) && (dely < 0))
869  sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))",
870  wplstrm[absy - 1], absx, wplstrm[absy - 1], 32 - absx);
871  else if ((delx < 0) && (dely > 0))
872  sprintf(bigbuf, "((*(sptr %s) >> %d) | (*(sptr %s - 1) << %d))",
873  wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx);
874  else /* ((delx > 0) && (dely > 0)) */
875  sprintf(bigbuf, "((*(sptr %s) << %d) | (*(sptr %s + 1) >> %d))",
876  wplstrp[absy - 1], absx, wplstrp[absy - 1], 32 - absx);
877 
878  return stringNew(bigbuf);
879 }
#define L_BUF_SIZE
Definition: classapp.c:59
static SARRAY * sarrayMakeInnerLoopDWACode(SEL *sel, l_int32 index)
sarrayMakeInnerLoopDWACode()
Definition: fmorphauto.c:763
l_ok fmorphautogen1(SELA *sela, l_int32 fileindex, const char *filename)
fmorphautogen1()
Definition: fmorphauto.c:289
static SARRAY * sarrayMakeWplsCode(SEL *sel)
sarrayMakeWplsCode()
Definition: fmorphauto.c:681
l_ok fmorphautogen(SELA *sela, l_int32 fileindex, const char *filename)
fmorphautogen()
Definition: fmorphauto.c:249
static char * makeBarrelshiftString(l_int32 delx, l_int32 dely)
makeBarrelshiftString()
Definition: fmorphauto.c:838
@ L_COPY
Definition: pix.h:712
@ L_NOCOPY
Definition: pix.h:710
@ L_INSERT
Definition: pix.h:711
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:170
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:703
l_ok sarrayJoin(SARRAY *sa1, SARRAY *sa2)
sarrayJoin()
Definition: sarray1.c:969
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:362
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:283
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:451
l_int32 sarrayParseRange(SARRAY *sa, l_int32 start, l_int32 *pactualstart, l_int32 *pend, l_int32 *pnewstart, const char *substr, l_int32 loc)
sarrayParseRange()
Definition: sarray1.c:1356
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:785
l_ok sarrayAppendRange(SARRAY *sa1, SARRAY *sa2, l_int32 start, l_int32 end)
sarrayAppendRange()
Definition: sarray1.c:1012
SARRAY * selaGetSelnames(SELA *sela)
selaGetSelnames()
Definition: sel1.c:1145
SEL * selaGetSel(SELA *sela, l_int32 i)
selaGetSel()
Definition: sel1.c:662
l_int32 selaGetCount(SELA *sela)
selaGetCount()
Definition: sel1.c:637
Definition: array.h:127
l_int32 sx
Definition: morph.h:64
l_int32 cy
Definition: morph.h:65
l_int32 cx
Definition: morph.h:66
l_int32 ** data
Definition: morph.h:67
l_int32 sy
Definition: morph.h:63
Definition: morph.h:74
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352