Leptonica  1.82.0
Image processing and image analysis suite
sel2.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 
64 #ifdef HAVE_CONFIG_H
65 #include <config_auto.h>
66 #endif /* HAVE_CONFIG_H */
67 
68 #include <math.h>
69 #include "allheaders.h"
70 
71 #define L_BUF_SIZE 512
72 
73  /* Linear brick sel sizes, including all those that are required
74  * for decomposable sels up to size 63. */
75 static const l_int32 num_linear = 25;
76 static const l_int32 basic_linear[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
77  12, 13, 14, 15, 20, 21, 25, 30, 31, 35, 40, 41, 45, 50, 51};
78 
79 
80 /* ------------------------------------------------------------------- *
81  * Basic brick structuring elements *
82  * ------------------------------------------------------------------- */
98 SELA *
100 {
101 char name[L_BUF_SIZE];
102 l_int32 i, size;
103 SEL *sel;
104 
105  PROCNAME("selaAddBasic");
106 
107  if (!sela) {
108  if ((sela = selaCreate(0)) == NULL)
109  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
110  }
111 
112  /*--------------------------------------------------------------*
113  * Linear horizontal and vertical sels *
114  *--------------------------------------------------------------*/
115  for (i = 0; i < num_linear; i++) {
116  size = basic_linear[i];
117  sel = selCreateBrick(1, size, 0, size / 2, 1);
118  snprintf(name, L_BUF_SIZE, "sel_%dh", size);
119  selaAddSel(sela, sel, name, 0);
120  }
121  for (i = 0; i < num_linear; i++) {
122  size = basic_linear[i];
123  sel = selCreateBrick(size, 1, size / 2, 0, 1);
124  snprintf(name, L_BUF_SIZE, "sel_%dv", size);
125  selaAddSel(sela, sel, name, 0);
126  }
127 
128  /*-----------------------------------------------------------*
129  * 2-d Bricks *
130  *-----------------------------------------------------------*/
131  for (i = 2; i <= 5; i++) {
132  sel = selCreateBrick(i, i, i / 2, i / 2, 1);
133  snprintf(name, L_BUF_SIZE, "sel_%d", i);
134  selaAddSel(sela, sel, name, 0);
135  }
136 
137  /*-----------------------------------------------------------*
138  * Diagonals *
139  *-----------------------------------------------------------*/
140  /* 0c 1
141  1 0 */
142  sel = selCreateBrick(2, 2, 0, 0, 1);
143  selSetElement(sel, 0, 0, 0);
144  selSetElement(sel, 1, 1, 0);
145  selaAddSel(sela, sel, "sel_2dp", 0);
146 
147  /* 1c 0
148  0 1 */
149  sel = selCreateBrick(2, 2, 0, 0, 1);
150  selSetElement(sel, 0, 1, 0);
151  selSetElement(sel, 1, 0, 0);
152  selaAddSel(sela, sel, "sel_2dm", 0);
153 
154  /* Diagonal, slope +, size 5 */
155  sel = selCreate(5, 5, "sel_5dp");
156  selSetOrigin(sel, 2, 2);
157  selSetElement(sel, 0, 4, 1);
158  selSetElement(sel, 1, 3, 1);
159  selSetElement(sel, 2, 2, 1);
160  selSetElement(sel, 3, 1, 1);
161  selSetElement(sel, 4, 0, 1);
162  selaAddSel(sela, sel, "sel_5dp", 0);
163 
164  /* Diagonal, slope -, size 5 */
165  sel = selCreate(5, 5, "sel_5dm");
166  selSetOrigin(sel, 2, 2);
167  selSetElement(sel, 0, 0, 1);
168  selSetElement(sel, 1, 1, 1);
169  selSetElement(sel, 2, 2, 1);
170  selSetElement(sel, 3, 3, 1);
171  selSetElement(sel, 4, 4, 1);
172  selaAddSel(sela, sel, "sel_5dm", 0);
173 
174  return sela;
175 }
176 
177 
178 /* ------------------------------------------------------------------- *
179  * Simple hit-miss structuring elements *
180  * ------------------------------------------------------------------- */
187 SELA *
189 {
190 SEL *sel;
191 
192  PROCNAME("selaAddHitMiss");
193 
194  if (!sela) {
195  if ((sela = selaCreate(0)) == NULL)
196  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
197  }
198 
199 #if 0 /* use just for testing */
200  sel = selCreateBrick(3, 3, 1, 1, 2);
201  selaAddSel(sela, sel, "sel_bad", 0);
202 #endif
203 
204 
205  /*--------------------------------------------------------------*
206  * Isolated foreground pixel *
207  *--------------------------------------------------------------*/
208  sel = selCreateBrick(3, 3, 1, 1, SEL_MISS);
209  selSetElement(sel, 1, 1, SEL_HIT);
210  selaAddSel(sela, sel, "sel_3hm", 0);
211 
212  /*--------------------------------------------------------------*
213  * Horizontal and vertical edges *
214  *--------------------------------------------------------------*/
215  sel = selCreateBrick(2, 3, 0, 1, SEL_HIT);
216  selSetElement(sel, 1, 0, SEL_MISS);
217  selSetElement(sel, 1, 1, SEL_MISS);
218  selSetElement(sel, 1, 2, SEL_MISS);
219  selaAddSel(sela, sel, "sel_3de", 0);
220 
221  sel = selCreateBrick(2, 3, 1, 1, SEL_HIT);
222  selSetElement(sel, 0, 0, SEL_MISS);
223  selSetElement(sel, 0, 1, SEL_MISS);
224  selSetElement(sel, 0, 2, SEL_MISS);
225  selaAddSel(sela, sel, "sel_3ue", 0);
226 
227  sel = selCreateBrick(3, 2, 1, 0, SEL_HIT);
228  selSetElement(sel, 0, 1, SEL_MISS);
229  selSetElement(sel, 1, 1, SEL_MISS);
230  selSetElement(sel, 2, 1, SEL_MISS);
231  selaAddSel(sela, sel, "sel_3re", 0);
232 
233  sel = selCreateBrick(3, 2, 1, 1, SEL_HIT);
234  selSetElement(sel, 0, 0, SEL_MISS);
235  selSetElement(sel, 1, 0, SEL_MISS);
236  selSetElement(sel, 2, 0, SEL_MISS);
237  selaAddSel(sela, sel, "sel_3le", 0);
238 
239  /*--------------------------------------------------------------*
240  * Slanted edge *
241  *--------------------------------------------------------------*/
242  sel = selCreateBrick(13, 6, 6, 2, SEL_DONT_CARE);
243  selSetElement(sel, 0, 3, SEL_MISS);
244  selSetElement(sel, 0, 5, SEL_HIT);
245  selSetElement(sel, 4, 2, SEL_MISS);
246  selSetElement(sel, 4, 4, SEL_HIT);
247  selSetElement(sel, 8, 1, SEL_MISS);
248  selSetElement(sel, 8, 3, SEL_HIT);
249  selSetElement(sel, 12, 0, SEL_MISS);
250  selSetElement(sel, 12, 2, SEL_HIT);
251  selaAddSel(sela, sel, "sel_sl1", 0);
252 
253  /*--------------------------------------------------------------*
254  * Corners *
255  * This allows for up to 3 missing edge pixels at the corner *
256  *--------------------------------------------------------------*/
257  sel = selCreateBrick(4, 4, 1, 1, SEL_MISS);
258  selSetElement(sel, 1, 1, SEL_DONT_CARE);
259  selSetElement(sel, 1, 2, SEL_DONT_CARE);
260  selSetElement(sel, 2, 1, SEL_DONT_CARE);
261  selSetElement(sel, 1, 3, SEL_HIT);
262  selSetElement(sel, 2, 2, SEL_HIT);
263  selSetElement(sel, 2, 3, SEL_HIT);
264  selSetElement(sel, 3, 1, SEL_HIT);
265  selSetElement(sel, 3, 2, SEL_HIT);
266  selSetElement(sel, 3, 3, SEL_HIT);
267  selaAddSel(sela, sel, "sel_ulc", 0);
268 
269  sel = selCreateBrick(4, 4, 1, 2, SEL_MISS);
270  selSetElement(sel, 1, 1, SEL_DONT_CARE);
271  selSetElement(sel, 1, 2, SEL_DONT_CARE);
272  selSetElement(sel, 2, 2, SEL_DONT_CARE);
273  selSetElement(sel, 1, 0, SEL_HIT);
274  selSetElement(sel, 2, 0, SEL_HIT);
275  selSetElement(sel, 2, 1, SEL_HIT);
276  selSetElement(sel, 3, 0, SEL_HIT);
277  selSetElement(sel, 3, 1, SEL_HIT);
278  selSetElement(sel, 3, 2, SEL_HIT);
279  selaAddSel(sela, sel, "sel_urc", 0);
280 
281  sel = selCreateBrick(4, 4, 2, 1, SEL_MISS);
282  selSetElement(sel, 1, 1, SEL_DONT_CARE);
283  selSetElement(sel, 2, 1, SEL_DONT_CARE);
284  selSetElement(sel, 2, 2, SEL_DONT_CARE);
285  selSetElement(sel, 0, 1, SEL_HIT);
286  selSetElement(sel, 0, 2, SEL_HIT);
287  selSetElement(sel, 0, 3, SEL_HIT);
288  selSetElement(sel, 1, 2, SEL_HIT);
289  selSetElement(sel, 1, 3, SEL_HIT);
290  selSetElement(sel, 2, 3, SEL_HIT);
291  selaAddSel(sela, sel, "sel_llc", 0);
292 
293  sel = selCreateBrick(4, 4, 2, 2, SEL_MISS);
294  selSetElement(sel, 1, 2, SEL_DONT_CARE);
295  selSetElement(sel, 2, 1, SEL_DONT_CARE);
296  selSetElement(sel, 2, 2, SEL_DONT_CARE);
297  selSetElement(sel, 0, 0, SEL_HIT);
298  selSetElement(sel, 0, 1, SEL_HIT);
299  selSetElement(sel, 0, 2, SEL_HIT);
300  selSetElement(sel, 1, 0, SEL_HIT);
301  selSetElement(sel, 1, 1, SEL_HIT);
302  selSetElement(sel, 2, 0, SEL_HIT);
303  selaAddSel(sela, sel, "sel_lrc", 0);
304 
305  return sela;
306 }
307 
308 
309 /* ------------------------------------------------------------------- *
310  * Structuring elements for comparing with DWA operations *
311  * ------------------------------------------------------------------- */
325 SELA *
327 {
328 char name[L_BUF_SIZE];
329 l_int32 i;
330 SEL *sel;
331 
332  PROCNAME("selaAddDwaLinear");
333 
334  if (!sela) {
335  if ((sela = selaCreate(0)) == NULL)
336  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
337  }
338 
339  for (i = 2; i < 64; i++) {
340  sel = selCreateBrick(1, i, 0, i / 2, 1);
341  snprintf(name, L_BUF_SIZE, "sel_%dh", i);
342  selaAddSel(sela, sel, name, 0);
343  }
344  for (i = 2; i < 64; i++) {
345  sel = selCreateBrick(i, 1, i / 2, 0, 1);
346  snprintf(name, L_BUF_SIZE, "sel_%dv", i);
347  selaAddSel(sela, sel, name, 0);
348  }
349  return sela;
350 }
351 
352 
367 SELA *
369 {
370 char name[L_BUF_SIZE];
371 l_int32 i, f1, f2, prevsize, size;
372 SEL *selh, *selv;
373 
374  PROCNAME("selaAddDwaCombs");
375 
376  if (!sela) {
377  if ((sela = selaCreate(0)) == NULL)
378  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
379  }
380 
381  prevsize = 0;
382  for (i = 4; i < 64; i++) {
383  selectComposableSizes(i, &f1, &f2);
384  size = f1 * f2;
385  if (size == prevsize)
386  continue;
387  selectComposableSels(i, L_HORIZ, NULL, &selh);
388  if (selh) {
389  snprintf(name, L_BUF_SIZE, "sel_comb_%dh", size);
390  selaAddSel(sela, selh, name, 0);
391  } else {
392  L_ERROR("selh not made for i = %d\n", procName, i);
393  }
394  selectComposableSels(i, L_VERT, NULL, &selv);
395  if (selv) {
396  snprintf(name, L_BUF_SIZE, "sel_comb_%dv", size);
397  selaAddSel(sela, selv, name, 0);
398  } else {
399  L_ERROR("selv not made for i = %d\n", procName, i);
400  }
401  prevsize = size;
402  }
403 
404  return sela;
405 }
406 
407 
408 /* ------------------------------------------------------------------- *
409  * Structuring elements for the intersection of lines *
410  * ------------------------------------------------------------------- */
437 SELA *
439  l_float32 hlsize,
440  l_float32 mdist,
441  l_int32 norient,
442  l_int32 debugflag)
443 {
444 char name[L_BUF_SIZE];
445 l_int32 i, j, w, xc, yc;
446 l_float64 pi, halfpi, radincr, radang;
447 l_float64 angle;
448 PIX *pixc, *pixm, *pixt;
449 PIXA *pixa;
450 PTA *pta1, *pta2, *pta3, *pta4;
451 SEL *sel;
452 
453  PROCNAME("selaAddCrossJunctions");
454 
455  if (hlsize <= 0)
456  return (SELA *)ERROR_PTR("hlsize not > 0", procName, NULL);
457  if (norient < 1 || norient > 8)
458  return (SELA *)ERROR_PTR("norient not in [1, ... 8]", procName, NULL);
459 
460  if (!sela) {
461  if ((sela = selaCreate(0)) == NULL)
462  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
463  }
464 
465  pi = 3.1415926535;
466  halfpi = 3.1415926535 / 2.0;
467  radincr = halfpi / (l_float64)norient;
468  w = (l_int32)(2.2 * (L_MAX(hlsize, mdist) + 0.5));
469  if (w % 2 == 0)
470  w++;
471  xc = w / 2;
472  yc = w / 2;
473 
474  pixa = pixaCreate(norient);
475  for (i = 0; i < norient; i++) {
476 
477  /* Set the don't cares */
478  pixc = pixCreate(w, w, 32);
479  pixSetAll(pixc);
480 
481  /* Add the green lines of hits */
482  pixm = pixCreate(w, w, 1);
483  radang = (l_float32)i * radincr;
484  pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang);
485  pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + halfpi);
486  pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi);
487  pta4 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi + halfpi);
488  ptaJoin(pta1, pta2, 0, -1);
489  ptaJoin(pta1, pta3, 0, -1);
490  ptaJoin(pta1, pta4, 0, -1);
491  pixRenderPta(pixm, pta1, L_SET_PIXELS);
492  pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
493  ptaDestroy(&pta1);
494  ptaDestroy(&pta2);
495  ptaDestroy(&pta3);
496  ptaDestroy(&pta4);
497 
498  /* Add red misses between the lines */
499  for (j = 0; j < 4; j++) {
500  angle = radang + (j - 0.5) * halfpi;
501  pixSetPixel(pixc, xc + (l_int32)(mdist * cos(angle)),
502  yc + (l_int32)(mdist * sin(angle)), 0xff000000);
503  }
504 
505  /* Add dark green for origin */
506  pixSetPixel(pixc, xc, yc, 0x00550000);
507 
508  /* Generate the sel */
509  sel = selCreateFromColorPix(pixc, NULL);
510  snprintf(name, sizeof(name), "sel_cross_%d", i);
511  selaAddSel(sela, sel, name, 0);
512 
513  if (debugflag) {
514  pixt = pixScaleBySampling(pixc, 10.0, 10.0);
515  pixaAddPix(pixa, pixt, L_INSERT);
516  }
517  pixDestroy(&pixm);
518  pixDestroy(&pixc);
519  }
520 
521  if (debugflag) {
522  l_int32 w;
523  lept_mkdir("lept/sel");
524  pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
525  pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 1, 0, 10, 2);
526  pixWriteDebug("/tmp/lept/sel/xsel1.png", pixt, IFF_PNG);
527  pixDisplay(pixt, 0, 100);
528  pixDestroy(&pixt);
529  pixt = selaDisplayInPix(sela, 15, 2, 20, 1);
530  pixWriteDebug("/tmp/lept/sel/xsel2.png", pixt, IFF_PNG);
531  pixDisplay(pixt, 500, 100);
532  pixDestroy(&pixt);
533  selaWriteStream(stderr, sela);
534  }
535  pixaDestroy(&pixa);
536 
537  return sela;
538 }
539 
540 
562 SELA *
564  l_float32 hlsize,
565  l_float32 mdist,
566  l_int32 norient,
567  l_int32 debugflag)
568 {
569 char name[L_BUF_SIZE];
570 l_int32 i, j, k, w, xc, yc;
571 l_float64 pi, halfpi, radincr, jang, radang;
572 l_float64 angle[3], dist[3];
573 PIX *pixc, *pixm, *pixt;
574 PIXA *pixa;
575 PTA *pta1, *pta2, *pta3;
576 SEL *sel;
577 
578  PROCNAME("selaAddTJunctions");
579 
580  if (hlsize <= 2)
581  return (SELA *)ERROR_PTR("hlsizel not > 1", procName, NULL);
582  if (norient < 1 || norient > 8)
583  return (SELA *)ERROR_PTR("norient not in [1, ... 8]", procName, NULL);
584 
585  if (!sela) {
586  if ((sela = selaCreate(0)) == NULL)
587  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
588  }
589 
590  pi = 3.1415926535;
591  halfpi = 3.1415926535 / 2.0;
592  radincr = halfpi / (l_float32)norient;
593  w = (l_int32)(2.4 * (L_MAX(hlsize, mdist) + 0.5));
594  if (w % 2 == 0)
595  w++;
596  xc = w / 2;
597  yc = w / 2;
598 
599  pixa = pixaCreate(4 * norient);
600  for (i = 0; i < norient; i++) {
601  for (j = 0; j < 4; j++) { /* 4 orthogonal orientations */
602  jang = (l_float32)j * halfpi;
603 
604  /* Set the don't cares */
605  pixc = pixCreate(w, w, 32);
606  pixSetAll(pixc);
607 
608  /* Add the green lines of hits */
609  pixm = pixCreate(w, w, 1);
610  radang = (l_float32)i * radincr;
611  pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, jang + radang);
612  pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1,
613  jang + radang + halfpi);
614  pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1,
615  jang + radang + pi);
616  ptaJoin(pta1, pta2, 0, -1);
617  ptaJoin(pta1, pta3, 0, -1);
618  pixRenderPta(pixm, pta1, L_SET_PIXELS);
619  pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
620  ptaDestroy(&pta1);
621  ptaDestroy(&pta2);
622  ptaDestroy(&pta3);
623 
624  /* Add red misses between the lines */
625  angle[0] = radang + jang - halfpi;
626  angle[1] = radang + jang + 0.5 * halfpi;
627  angle[2] = radang + jang + 1.5 * halfpi;
628  dist[0] = 0.8 * mdist;
629  dist[1] = dist[2] = mdist;
630  for (k = 0; k < 3; k++) {
631  pixSetPixel(pixc, xc + (l_int32)(dist[k] * cos(angle[k])),
632  yc + (l_int32)(dist[k] * sin(angle[k])),
633  0xff000000);
634  }
635 
636  /* Add dark green for origin */
637  pixSetPixel(pixc, xc, yc, 0x00550000);
638 
639  /* Generate the sel */
640  sel = selCreateFromColorPix(pixc, NULL);
641  snprintf(name, sizeof(name), "sel_cross_%d", 4 * i + j);
642  selaAddSel(sela, sel, name, 0);
643 
644  if (debugflag) {
645  pixt = pixScaleBySampling(pixc, 10.0, 10.0);
646  pixaAddPix(pixa, pixt, L_INSERT);
647  }
648  pixDestroy(&pixm);
649  pixDestroy(&pixc);
650  }
651  }
652 
653  if (debugflag) {
654  l_int32 w;
655  lept_mkdir("lept/sel");
656  pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
657  pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 4, 0, 10, 2);
658  pixWriteDebug("/tmp/lept/sel/tsel1.png", pixt, IFF_PNG);
659  pixDisplay(pixt, 0, 100);
660  pixDestroy(&pixt);
661  pixt = selaDisplayInPix(sela, 15, 2, 20, 4);
662  pixWriteDebug("/tmp/lept/sel/tsel2.png", pixt, IFF_PNG);
663  pixDisplay(pixt, 500, 100);
664  pixDestroy(&pixt);
665  selaWriteStream(stderr, sela);
666  }
667  pixaDestroy(&pixa);
668 
669  return sela;
670 }
671 
672 
673 /* -------------------------------------------------------------------------- *
674  * Structuring elements for connectivity-preserving thinning operations *
675  * -------------------------------------------------------------------------- */
676 
677  /* ------------------------------------------------------------
678  * These sels (and their rotated counterparts) are the useful
679  * 3x3 Sels for thinning. The notation is based on
680  * "Connectivity-preserving morphological image transformations,"
681  * a version of which can be found at
682  * http://www.leptonica.com/papers/conn.pdf
683  * ------------------------------------------------------------ */
684 
685  /* Sels for 4-connected thinning */
686 static const char *sel_4_1 = " x"
687  "oCx"
688  " x";
689 static const char *sel_4_2 = " x"
690  "oCx"
691  " o ";
692 static const char *sel_4_3 = " o "
693  "oCx"
694  " x";
695 static const char *sel_4_4 = " o "
696  "oCx"
697  " o ";
698 static const char *sel_4_5 = " ox"
699  "oCx"
700  " o ";
701 static const char *sel_4_6 = " o "
702  "oCx"
703  " ox";
704 static const char *sel_4_7 = " xx"
705  "oCx"
706  " o ";
707 static const char *sel_4_8 = " x"
708  "oCx"
709  "o x";
710 static const char *sel_4_9 = "o x"
711  "oCx"
712  " x";
713 
714  /* Sels for 8-connected thinning */
715 static const char *sel_8_1 = " x "
716  "oCx"
717  " x ";
718 static const char *sel_8_2 = " x "
719  "oCx"
720  "o ";
721 static const char *sel_8_3 = "o "
722  "oCx"
723  " x ";
724 static const char *sel_8_4 = "o "
725  "oCx"
726  "o ";
727 static const char *sel_8_5 = "o x"
728  "oCx"
729  "o ";
730 static const char *sel_8_6 = "o "
731  "oCx"
732  "o x";
733 static const char *sel_8_7 = " x "
734  "oCx"
735  "oo ";
736 static const char *sel_8_8 = " x "
737  "oCx"
738  "ox ";
739 static const char *sel_8_9 = "ox "
740  "oCx"
741  " x ";
742 
743  /* Sels for both 4 and 8-connected thinning */
744 static const char *sel_48_1 = " xx"
745  "oCx"
746  "oo ";
747 static const char *sel_48_2 = "o x"
748  "oCx"
749  "o x";
750 
751 
763 SELA *
765 {
766 SEL *sel;
767 
768  if (!sela) sela = selaCreate(9);
769 
770  sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1");
771  selaAddSel(sela, sel, NULL, 0);
772  sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2");
773  selaAddSel(sela, sel, NULL, 0);
774  sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3");
775  selaAddSel(sela, sel, NULL, 0);
776  sel = selCreateFromString(sel_4_4, 3, 3, "sel_4_4");
777  selaAddSel(sela, sel, NULL, 0);
778  sel = selCreateFromString(sel_4_5, 3, 3, "sel_4_5");
779  selaAddSel(sela, sel, NULL, 0);
780  sel = selCreateFromString(sel_4_6, 3, 3, "sel_4_6");
781  selaAddSel(sela, sel, NULL, 0);
782  sel = selCreateFromString(sel_4_7, 3, 3, "sel_4_7");
783  selaAddSel(sela, sel, NULL, 0);
784  sel = selCreateFromString(sel_4_8, 3, 3, "sel_4_8");
785  selaAddSel(sela, sel, NULL, 0);
786  sel = selCreateFromString(sel_4_9, 3, 3, "sel_4_9");
787  selaAddSel(sela, sel, NULL, 0);
788 
789  return sela;
790 }
791 
792 
804 SELA *
806 {
807 SEL *sel;
808 
809  if (!sela) sela = selaCreate(9);
810 
811  sel = selCreateFromString(sel_8_1, 3, 3, "sel_8_1");
812  selaAddSel(sela, sel, NULL, 0);
813  sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2");
814  selaAddSel(sela, sel, NULL, 0);
815  sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3");
816  selaAddSel(sela, sel, NULL, 0);
817  sel = selCreateFromString(sel_8_4, 3, 3, "sel_8_4");
818  selaAddSel(sela, sel, NULL, 0);
819  sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5");
820  selaAddSel(sela, sel, NULL, 0);
821  sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6");
822  selaAddSel(sela, sel, NULL, 0);
823  sel = selCreateFromString(sel_8_7, 3, 3, "sel_8_7");
824  selaAddSel(sela, sel, NULL, 0);
825  sel = selCreateFromString(sel_8_8, 3, 3, "sel_8_8");
826  selaAddSel(sela, sel, NULL, 0);
827  sel = selCreateFromString(sel_8_9, 3, 3, "sel_8_9");
828  selaAddSel(sela, sel, NULL, 0);
829 
830  return sela;
831 }
832 
833 
845 SELA *
847 {
848 SEL *sel;
849 
850  if (!sela) sela = selaCreate(2);
851 
852  sel = selCreateFromString(sel_48_1, 3, 3, "sel_48_1");
853  selaAddSel(sela, sel, NULL, 0);
854  sel = selCreateFromString(sel_48_2, 3, 3, "sel_48_2");
855  selaAddSel(sela, sel, NULL, 0);
856 
857  return sela;
858 }
859 
860 
861 /* -------------------------------------------------------------------------- *
862  * Other structuring elements *
863  * -------------------------------------------------------------------------- */
877 SEL *
878 selMakePlusSign(l_int32 size,
879  l_int32 linewidth)
880 {
881 PIX *pix;
882 SEL *sel;
883 
884  PROCNAME("selMakePlusSign");
885 
886  if (size < 3 || linewidth > size)
887  return (SEL *)ERROR_PTR("invalid input", procName, NULL);
888 
889  pix = pixCreate(size, size, 1);
890  pixRenderLine(pix, size / 2, 0, size / 2, size - 1,
891  linewidth, L_SET_PIXELS);
892  pixRenderLine(pix, 0, size / 2, size, size / 2,
893  linewidth, L_SET_PIXELS);
894  sel = selCreateFromPix(pix, size / 2, size / 2, "plus_sign");
895  pixDestroy(&pix);
896  return sel;
897 }
#define L_BUF_SIZE
Definition: classapp.c:59
l_ok pixRenderLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_int32 op)
pixRenderLine()
Definition: graphics.c:1496
PTA * generatePtaLineFromPt(l_int32 x, l_int32 y, l_float64 length, l_float64 radang)
generatePtaLineFromPt()
Definition: graphics.c:907
l_ok pixRenderPta(PIX *pix, PTA *pta, l_int32 op)
pixRenderPta()
Definition: graphics.c:1267
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1132
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:263
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:626
@ L_SET_PIXELS
Definition: pix.h:772
@ L_INSERT
Definition: pix.h:711
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
l_ok pixaGetPixDimensions(PIXA *pixa, l_int32 index, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixaGetPixDimensions()
Definition: pixabasic.c:726
PIX * pixaDisplayTiledAndScaled(PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledAndScaled()
Definition: pixafunc2.c:1045
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:167
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
SEL * selCreateFromPix(PIX *pix, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPix()
Definition: sel1.c:2008
l_ok selaWriteStream(FILE *fp, SELA *sela)
selaWriteStream()
Definition: sel1.c:1484
SEL * selCreateFromString(const char *text, l_int32 h, l_int32 w, const char *name)
selCreateFromString()
Definition: sel1.c:1607
l_ok selSetOrigin(SEL *sel, l_int32 cy, l_int32 cx)
selSetOrigin()
Definition: sel1.c:878
SELA * selaCreate(l_int32 n)
selaCreate()
Definition: sel1.c:251
l_ok selaAddSel(SELA *sela, SEL *sel, const char *selname, l_int32 copyflag)
selaAddSel()
Definition: sel1.c:559
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:819
PIX * selaDisplayInPix(SELA *sela, l_int32 size, l_int32 gthick, l_int32 spacing, l_int32 ncols)
selaDisplayInPix()
Definition: sel1.c:2373
SEL * selCreate(l_int32 height, l_int32 width, const char *name)
selCreate()
Definition: sel1.c:310
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
SEL * selCreateFromColorPix(PIX *pixs, const char *selname)
Definition: sel1.c:2117
SELA * sela8ccThin(SELA *sela)
sela8ccThin()
Definition: sel2.c:805
SELA * selaAddHitMiss(SELA *sela)
selaAddHitMiss()
Definition: sel2.c:188
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
SELA * sela4and8ccThin(SELA *sela)
sela4and8ccThin()
Definition: sel2.c:846
SELA * selaAddDwaCombs(SELA *sela)
selaAddDwaCombs()
Definition: sel2.c:368
SELA * selaAddTJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddTJunctions()
Definition: sel2.c:563
SELA * sela4ccThin(SELA *sela)
sela4ccThin()
Definition: sel2.c:764
SELA * selaAddDwaLinear(SELA *sela)
selaAddDwaLinear()
Definition: sel2.c:326
SEL * selMakePlusSign(l_int32 size, l_int32 linewidth)
selMakePlusSign()
Definition: sel2.c:878
SELA * selaAddCrossJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddCrossJunctions()
Definition: sel2.c:438
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517
Definition: morph.h:74
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218