Leptonica  1.83.1
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  if (!sela) {
106  if ((sela = selaCreate(0)) == NULL)
107  return (SELA *)ERROR_PTR("sela not made", __func__, NULL);
108  }
109 
110  /*--------------------------------------------------------------*
111  * Linear horizontal and vertical sels *
112  *--------------------------------------------------------------*/
113  for (i = 0; i < num_linear; i++) {
114  size = basic_linear[i];
115  sel = selCreateBrick(1, size, 0, size / 2, 1);
116  snprintf(name, L_BUF_SIZE, "sel_%dh", size);
117  selaAddSel(sela, sel, name, 0);
118  }
119  for (i = 0; i < num_linear; i++) {
120  size = basic_linear[i];
121  sel = selCreateBrick(size, 1, size / 2, 0, 1);
122  snprintf(name, L_BUF_SIZE, "sel_%dv", size);
123  selaAddSel(sela, sel, name, 0);
124  }
125 
126  /*-----------------------------------------------------------*
127  * 2-d Bricks *
128  *-----------------------------------------------------------*/
129  for (i = 2; i <= 5; i++) {
130  sel = selCreateBrick(i, i, i / 2, i / 2, 1);
131  snprintf(name, L_BUF_SIZE, "sel_%d", i);
132  selaAddSel(sela, sel, name, 0);
133  }
134 
135  /*-----------------------------------------------------------*
136  * Diagonals *
137  *-----------------------------------------------------------*/
138  /* 0c 1
139  1 0 */
140  sel = selCreateBrick(2, 2, 0, 0, 1);
141  selSetElement(sel, 0, 0, 0);
142  selSetElement(sel, 1, 1, 0);
143  selaAddSel(sela, sel, "sel_2dp", 0);
144 
145  /* 1c 0
146  0 1 */
147  sel = selCreateBrick(2, 2, 0, 0, 1);
148  selSetElement(sel, 0, 1, 0);
149  selSetElement(sel, 1, 0, 0);
150  selaAddSel(sela, sel, "sel_2dm", 0);
151 
152  /* Diagonal, slope +, size 5 */
153  sel = selCreate(5, 5, "sel_5dp");
154  selSetOrigin(sel, 2, 2);
155  selSetElement(sel, 0, 4, 1);
156  selSetElement(sel, 1, 3, 1);
157  selSetElement(sel, 2, 2, 1);
158  selSetElement(sel, 3, 1, 1);
159  selSetElement(sel, 4, 0, 1);
160  selaAddSel(sela, sel, "sel_5dp", 0);
161 
162  /* Diagonal, slope -, size 5 */
163  sel = selCreate(5, 5, "sel_5dm");
164  selSetOrigin(sel, 2, 2);
165  selSetElement(sel, 0, 0, 1);
166  selSetElement(sel, 1, 1, 1);
167  selSetElement(sel, 2, 2, 1);
168  selSetElement(sel, 3, 3, 1);
169  selSetElement(sel, 4, 4, 1);
170  selaAddSel(sela, sel, "sel_5dm", 0);
171 
172  return sela;
173 }
174 
175 
176 /* ------------------------------------------------------------------- *
177  * Simple hit-miss structuring elements *
178  * ------------------------------------------------------------------- */
185 SELA *
187 {
188 SEL *sel;
189 
190  if (!sela) {
191  if ((sela = selaCreate(0)) == NULL)
192  return (SELA *)ERROR_PTR("sela not made", __func__, NULL);
193  }
194 
195 #if 0 /* use just for testing */
196  sel = selCreateBrick(3, 3, 1, 1, 2);
197  selaAddSel(sela, sel, "sel_bad", 0);
198 #endif
199 
200 
201  /*--------------------------------------------------------------*
202  * Isolated foreground pixel *
203  *--------------------------------------------------------------*/
204  sel = selCreateBrick(3, 3, 1, 1, SEL_MISS);
205  selSetElement(sel, 1, 1, SEL_HIT);
206  selaAddSel(sela, sel, "sel_3hm", 0);
207 
208  /*--------------------------------------------------------------*
209  * Horizontal and vertical edges *
210  *--------------------------------------------------------------*/
211  sel = selCreateBrick(2, 3, 0, 1, SEL_HIT);
212  selSetElement(sel, 1, 0, SEL_MISS);
213  selSetElement(sel, 1, 1, SEL_MISS);
214  selSetElement(sel, 1, 2, SEL_MISS);
215  selaAddSel(sela, sel, "sel_3de", 0);
216 
217  sel = selCreateBrick(2, 3, 1, 1, SEL_HIT);
218  selSetElement(sel, 0, 0, SEL_MISS);
219  selSetElement(sel, 0, 1, SEL_MISS);
220  selSetElement(sel, 0, 2, SEL_MISS);
221  selaAddSel(sela, sel, "sel_3ue", 0);
222 
223  sel = selCreateBrick(3, 2, 1, 0, SEL_HIT);
224  selSetElement(sel, 0, 1, SEL_MISS);
225  selSetElement(sel, 1, 1, SEL_MISS);
226  selSetElement(sel, 2, 1, SEL_MISS);
227  selaAddSel(sela, sel, "sel_3re", 0);
228 
229  sel = selCreateBrick(3, 2, 1, 1, SEL_HIT);
230  selSetElement(sel, 0, 0, SEL_MISS);
231  selSetElement(sel, 1, 0, SEL_MISS);
232  selSetElement(sel, 2, 0, SEL_MISS);
233  selaAddSel(sela, sel, "sel_3le", 0);
234 
235  /*--------------------------------------------------------------*
236  * Slanted edge *
237  *--------------------------------------------------------------*/
238  sel = selCreateBrick(13, 6, 6, 2, SEL_DONT_CARE);
239  selSetElement(sel, 0, 3, SEL_MISS);
240  selSetElement(sel, 0, 5, SEL_HIT);
241  selSetElement(sel, 4, 2, SEL_MISS);
242  selSetElement(sel, 4, 4, SEL_HIT);
243  selSetElement(sel, 8, 1, SEL_MISS);
244  selSetElement(sel, 8, 3, SEL_HIT);
245  selSetElement(sel, 12, 0, SEL_MISS);
246  selSetElement(sel, 12, 2, SEL_HIT);
247  selaAddSel(sela, sel, "sel_sl1", 0);
248 
249  /*--------------------------------------------------------------*
250  * Corners *
251  * This allows for up to 3 missing edge pixels at the corner *
252  *--------------------------------------------------------------*/
253  sel = selCreateBrick(4, 4, 1, 1, SEL_MISS);
254  selSetElement(sel, 1, 1, SEL_DONT_CARE);
255  selSetElement(sel, 1, 2, SEL_DONT_CARE);
256  selSetElement(sel, 2, 1, SEL_DONT_CARE);
257  selSetElement(sel, 1, 3, SEL_HIT);
258  selSetElement(sel, 2, 2, SEL_HIT);
259  selSetElement(sel, 2, 3, SEL_HIT);
260  selSetElement(sel, 3, 1, SEL_HIT);
261  selSetElement(sel, 3, 2, SEL_HIT);
262  selSetElement(sel, 3, 3, SEL_HIT);
263  selaAddSel(sela, sel, "sel_ulc", 0);
264 
265  sel = selCreateBrick(4, 4, 1, 2, SEL_MISS);
266  selSetElement(sel, 1, 1, SEL_DONT_CARE);
267  selSetElement(sel, 1, 2, SEL_DONT_CARE);
268  selSetElement(sel, 2, 2, SEL_DONT_CARE);
269  selSetElement(sel, 1, 0, SEL_HIT);
270  selSetElement(sel, 2, 0, SEL_HIT);
271  selSetElement(sel, 2, 1, SEL_HIT);
272  selSetElement(sel, 3, 0, SEL_HIT);
273  selSetElement(sel, 3, 1, SEL_HIT);
274  selSetElement(sel, 3, 2, SEL_HIT);
275  selaAddSel(sela, sel, "sel_urc", 0);
276 
277  sel = selCreateBrick(4, 4, 2, 1, SEL_MISS);
278  selSetElement(sel, 1, 1, SEL_DONT_CARE);
279  selSetElement(sel, 2, 1, SEL_DONT_CARE);
280  selSetElement(sel, 2, 2, SEL_DONT_CARE);
281  selSetElement(sel, 0, 1, SEL_HIT);
282  selSetElement(sel, 0, 2, SEL_HIT);
283  selSetElement(sel, 0, 3, SEL_HIT);
284  selSetElement(sel, 1, 2, SEL_HIT);
285  selSetElement(sel, 1, 3, SEL_HIT);
286  selSetElement(sel, 2, 3, SEL_HIT);
287  selaAddSel(sela, sel, "sel_llc", 0);
288 
289  sel = selCreateBrick(4, 4, 2, 2, SEL_MISS);
290  selSetElement(sel, 1, 2, SEL_DONT_CARE);
291  selSetElement(sel, 2, 1, SEL_DONT_CARE);
292  selSetElement(sel, 2, 2, SEL_DONT_CARE);
293  selSetElement(sel, 0, 0, SEL_HIT);
294  selSetElement(sel, 0, 1, SEL_HIT);
295  selSetElement(sel, 0, 2, SEL_HIT);
296  selSetElement(sel, 1, 0, SEL_HIT);
297  selSetElement(sel, 1, 1, SEL_HIT);
298  selSetElement(sel, 2, 0, SEL_HIT);
299  selaAddSel(sela, sel, "sel_lrc", 0);
300 
301  return sela;
302 }
303 
304 
305 /* ------------------------------------------------------------------- *
306  * Structuring elements for comparing with DWA operations *
307  * ------------------------------------------------------------------- */
321 SELA *
323 {
324 char name[L_BUF_SIZE];
325 l_int32 i;
326 SEL *sel;
327 
328  if (!sela) {
329  if ((sela = selaCreate(0)) == NULL)
330  return (SELA *)ERROR_PTR("sela not made", __func__, NULL);
331  }
332 
333  for (i = 2; i < 64; i++) {
334  sel = selCreateBrick(1, i, 0, i / 2, 1);
335  snprintf(name, L_BUF_SIZE, "sel_%dh", i);
336  selaAddSel(sela, sel, name, 0);
337  }
338  for (i = 2; i < 64; i++) {
339  sel = selCreateBrick(i, 1, i / 2, 0, 1);
340  snprintf(name, L_BUF_SIZE, "sel_%dv", i);
341  selaAddSel(sela, sel, name, 0);
342  }
343  return sela;
344 }
345 
346 
361 SELA *
363 {
364 char name[L_BUF_SIZE];
365 l_int32 i, f1, f2, prevsize, size;
366 SEL *selh, *selv;
367 
368  if (!sela) {
369  if ((sela = selaCreate(0)) == NULL)
370  return (SELA *)ERROR_PTR("sela not made", __func__, NULL);
371  }
372 
373  prevsize = 0;
374  for (i = 4; i < 64; i++) {
375  selectComposableSizes(i, &f1, &f2);
376  size = f1 * f2;
377  if (size == prevsize)
378  continue;
379  selectComposableSels(i, L_HORIZ, NULL, &selh);
380  if (selh) {
381  snprintf(name, L_BUF_SIZE, "sel_comb_%dh", size);
382  selaAddSel(sela, selh, name, 0);
383  } else {
384  L_ERROR("selh not made for i = %d\n", __func__, i);
385  }
386  selectComposableSels(i, L_VERT, NULL, &selv);
387  if (selv) {
388  snprintf(name, L_BUF_SIZE, "sel_comb_%dv", size);
389  selaAddSel(sela, selv, name, 0);
390  } else {
391  L_ERROR("selv not made for i = %d\n", __func__, i);
392  }
393  prevsize = size;
394  }
395 
396  return sela;
397 }
398 
399 
400 /* ------------------------------------------------------------------- *
401  * Structuring elements for the intersection of lines *
402  * ------------------------------------------------------------------- */
429 SELA *
431  l_float32 hlsize,
432  l_float32 mdist,
433  l_int32 norient,
434  l_int32 debugflag)
435 {
436 char name[L_BUF_SIZE];
437 l_int32 i, j, w, xc, yc;
438 l_float64 pi, halfpi, radincr, radang;
439 l_float64 angle;
440 PIX *pixc, *pixm, *pixt;
441 PIXA *pixa;
442 PTA *pta1, *pta2, *pta3, *pta4;
443 SEL *sel;
444 
445  if (hlsize <= 0)
446  return (SELA *)ERROR_PTR("hlsize not > 0", __func__, NULL);
447  if (norient < 1 || norient > 8)
448  return (SELA *)ERROR_PTR("norient not in [1, ... 8]", __func__, NULL);
449 
450  if (!sela) {
451  if ((sela = selaCreate(0)) == NULL)
452  return (SELA *)ERROR_PTR("sela not made", __func__, NULL);
453  }
454 
455  pi = 3.1415926535;
456  halfpi = 3.1415926535 / 2.0;
457  radincr = halfpi / (l_float64)norient;
458  w = (l_int32)(2.2 * (L_MAX(hlsize, mdist) + 0.5));
459  if (w % 2 == 0)
460  w++;
461  xc = w / 2;
462  yc = w / 2;
463 
464  pixa = pixaCreate(norient);
465  for (i = 0; i < norient; i++) {
466 
467  /* Set the don't cares */
468  pixc = pixCreate(w, w, 32);
469  pixSetAll(pixc);
470 
471  /* Add the green lines of hits */
472  pixm = pixCreate(w, w, 1);
473  radang = (l_float32)i * radincr;
474  pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang);
475  pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + halfpi);
476  pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi);
477  pta4 = generatePtaLineFromPt(xc, yc, hlsize + 1, radang + pi + halfpi);
478  ptaJoin(pta1, pta2, 0, -1);
479  ptaJoin(pta1, pta3, 0, -1);
480  ptaJoin(pta1, pta4, 0, -1);
481  pixRenderPta(pixm, pta1, L_SET_PIXELS);
482  pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
483  ptaDestroy(&pta1);
484  ptaDestroy(&pta2);
485  ptaDestroy(&pta3);
486  ptaDestroy(&pta4);
487 
488  /* Add red misses between the lines */
489  for (j = 0; j < 4; j++) {
490  angle = radang + (j - 0.5) * halfpi;
491  pixSetPixel(pixc, xc + (l_int32)(mdist * cos(angle)),
492  yc + (l_int32)(mdist * sin(angle)), 0xff000000);
493  }
494 
495  /* Add dark green for origin */
496  pixSetPixel(pixc, xc, yc, 0x00550000);
497 
498  /* Generate the sel */
499  sel = selCreateFromColorPix(pixc, NULL);
500  snprintf(name, sizeof(name), "sel_cross_%d", i);
501  selaAddSel(sela, sel, name, 0);
502 
503  if (debugflag) {
504  pixt = pixScaleBySampling(pixc, 10.0, 10.0);
505  pixaAddPix(pixa, pixt, L_INSERT);
506  }
507  pixDestroy(&pixm);
508  pixDestroy(&pixc);
509  }
510 
511  if (debugflag) {
512  l_int32 w;
513  lept_mkdir("lept/sel");
514  pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
515  pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 1, 0, 10, 2);
516  pixWriteDebug("/tmp/lept/sel/xsel1.png", pixt, IFF_PNG);
517  pixDisplay(pixt, 0, 100);
518  pixDestroy(&pixt);
519  pixt = selaDisplayInPix(sela, 15, 2, 20, 1);
520  pixWriteDebug("/tmp/lept/sel/xsel2.png", pixt, IFF_PNG);
521  pixDisplay(pixt, 500, 100);
522  pixDestroy(&pixt);
523  selaWriteStream(stderr, sela);
524  }
525  pixaDestroy(&pixa);
526 
527  return sela;
528 }
529 
530 
552 SELA *
554  l_float32 hlsize,
555  l_float32 mdist,
556  l_int32 norient,
557  l_int32 debugflag)
558 {
559 char name[L_BUF_SIZE];
560 l_int32 i, j, k, w, xc, yc;
561 l_float64 pi, halfpi, radincr, jang, radang;
562 l_float64 angle[3], dist[3];
563 PIX *pixc, *pixm, *pixt;
564 PIXA *pixa;
565 PTA *pta1, *pta2, *pta3;
566 SEL *sel;
567 
568  if (hlsize <= 2)
569  return (SELA *)ERROR_PTR("hlsizel not > 1", __func__, NULL);
570  if (norient < 1 || norient > 8)
571  return (SELA *)ERROR_PTR("norient not in [1, ... 8]", __func__, NULL);
572 
573  if (!sela) {
574  if ((sela = selaCreate(0)) == NULL)
575  return (SELA *)ERROR_PTR("sela not made", __func__, NULL);
576  }
577 
578  pi = 3.1415926535;
579  halfpi = 3.1415926535 / 2.0;
580  radincr = halfpi / (l_float32)norient;
581  w = (l_int32)(2.4 * (L_MAX(hlsize, mdist) + 0.5));
582  if (w % 2 == 0)
583  w++;
584  xc = w / 2;
585  yc = w / 2;
586 
587  pixa = pixaCreate(4 * norient);
588  for (i = 0; i < norient; i++) {
589  for (j = 0; j < 4; j++) { /* 4 orthogonal orientations */
590  jang = (l_float32)j * halfpi;
591 
592  /* Set the don't cares */
593  pixc = pixCreate(w, w, 32);
594  pixSetAll(pixc);
595 
596  /* Add the green lines of hits */
597  pixm = pixCreate(w, w, 1);
598  radang = (l_float32)i * radincr;
599  pta1 = generatePtaLineFromPt(xc, yc, hlsize + 1, jang + radang);
600  pta2 = generatePtaLineFromPt(xc, yc, hlsize + 1,
601  jang + radang + halfpi);
602  pta3 = generatePtaLineFromPt(xc, yc, hlsize + 1,
603  jang + radang + pi);
604  ptaJoin(pta1, pta2, 0, -1);
605  ptaJoin(pta1, pta3, 0, -1);
606  pixRenderPta(pixm, pta1, L_SET_PIXELS);
607  pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000);
608  ptaDestroy(&pta1);
609  ptaDestroy(&pta2);
610  ptaDestroy(&pta3);
611 
612  /* Add red misses between the lines */
613  angle[0] = radang + jang - halfpi;
614  angle[1] = radang + jang + 0.5 * halfpi;
615  angle[2] = radang + jang + 1.5 * halfpi;
616  dist[0] = 0.8 * mdist;
617  dist[1] = dist[2] = mdist;
618  for (k = 0; k < 3; k++) {
619  pixSetPixel(pixc, xc + (l_int32)(dist[k] * cos(angle[k])),
620  yc + (l_int32)(dist[k] * sin(angle[k])),
621  0xff000000);
622  }
623 
624  /* Add dark green for origin */
625  pixSetPixel(pixc, xc, yc, 0x00550000);
626 
627  /* Generate the sel */
628  sel = selCreateFromColorPix(pixc, NULL);
629  snprintf(name, sizeof(name), "sel_cross_%d", 4 * i + j);
630  selaAddSel(sela, sel, name, 0);
631 
632  if (debugflag) {
633  pixt = pixScaleBySampling(pixc, 10.0, 10.0);
634  pixaAddPix(pixa, pixt, L_INSERT);
635  }
636  pixDestroy(&pixm);
637  pixDestroy(&pixc);
638  }
639  }
640 
641  if (debugflag) {
642  l_int32 w;
643  lept_mkdir("lept/sel");
644  pixaGetPixDimensions(pixa, 0, &w, NULL, NULL);
645  pixt = pixaDisplayTiledAndScaled(pixa, 32, w, 4, 0, 10, 2);
646  pixWriteDebug("/tmp/lept/sel/tsel1.png", pixt, IFF_PNG);
647  pixDisplay(pixt, 0, 100);
648  pixDestroy(&pixt);
649  pixt = selaDisplayInPix(sela, 15, 2, 20, 4);
650  pixWriteDebug("/tmp/lept/sel/tsel2.png", pixt, IFF_PNG);
651  pixDisplay(pixt, 500, 100);
652  pixDestroy(&pixt);
653  selaWriteStream(stderr, sela);
654  }
655  pixaDestroy(&pixa);
656 
657  return sela;
658 }
659 
660 
661 /* -------------------------------------------------------------------------- *
662  * Structuring elements for connectivity-preserving thinning operations *
663  * -------------------------------------------------------------------------- */
664 
665  /* ------------------------------------------------------------
666  * These sels (and their rotated counterparts) are the useful
667  * 3x3 Sels for thinning. The notation is based on
668  * "Connectivity-preserving morphological image transformations,"
669  * a version of which can be found at
670  * http://www.leptonica.com/papers/conn.pdf
671  * ------------------------------------------------------------ */
672 
673  /* Sels for 4-connected thinning */
674 static const char *sel_4_1 = " x"
675  "oCx"
676  " x";
677 static const char *sel_4_2 = " x"
678  "oCx"
679  " o ";
680 static const char *sel_4_3 = " o "
681  "oCx"
682  " x";
683 static const char *sel_4_4 = " o "
684  "oCx"
685  " o ";
686 static const char *sel_4_5 = " ox"
687  "oCx"
688  " o ";
689 static const char *sel_4_6 = " o "
690  "oCx"
691  " ox";
692 static const char *sel_4_7 = " xx"
693  "oCx"
694  " o ";
695 static const char *sel_4_8 = " x"
696  "oCx"
697  "o x";
698 static const char *sel_4_9 = "o x"
699  "oCx"
700  " x";
701 
702  /* Sels for 8-connected thinning */
703 static const char *sel_8_1 = " x "
704  "oCx"
705  " x ";
706 static const char *sel_8_2 = " x "
707  "oCx"
708  "o ";
709 static const char *sel_8_3 = "o "
710  "oCx"
711  " x ";
712 static const char *sel_8_4 = "o "
713  "oCx"
714  "o ";
715 static const char *sel_8_5 = "o x"
716  "oCx"
717  "o ";
718 static const char *sel_8_6 = "o "
719  "oCx"
720  "o x";
721 static const char *sel_8_7 = " x "
722  "oCx"
723  "oo ";
724 static const char *sel_8_8 = " x "
725  "oCx"
726  "ox ";
727 static const char *sel_8_9 = "ox "
728  "oCx"
729  " x ";
730 
731  /* Sels for both 4 and 8-connected thinning */
732 static const char *sel_48_1 = " xx"
733  "oCx"
734  "oo ";
735 static const char *sel_48_2 = "o x"
736  "oCx"
737  "o x";
738 
739 
751 SELA *
753 {
754 SEL *sel;
755 
756  if (!sela) sela = selaCreate(9);
757 
758  sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1");
759  selaAddSel(sela, sel, NULL, 0);
760  sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2");
761  selaAddSel(sela, sel, NULL, 0);
762  sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3");
763  selaAddSel(sela, sel, NULL, 0);
764  sel = selCreateFromString(sel_4_4, 3, 3, "sel_4_4");
765  selaAddSel(sela, sel, NULL, 0);
766  sel = selCreateFromString(sel_4_5, 3, 3, "sel_4_5");
767  selaAddSel(sela, sel, NULL, 0);
768  sel = selCreateFromString(sel_4_6, 3, 3, "sel_4_6");
769  selaAddSel(sela, sel, NULL, 0);
770  sel = selCreateFromString(sel_4_7, 3, 3, "sel_4_7");
771  selaAddSel(sela, sel, NULL, 0);
772  sel = selCreateFromString(sel_4_8, 3, 3, "sel_4_8");
773  selaAddSel(sela, sel, NULL, 0);
774  sel = selCreateFromString(sel_4_9, 3, 3, "sel_4_9");
775  selaAddSel(sela, sel, NULL, 0);
776 
777  return sela;
778 }
779 
780 
792 SELA *
794 {
795 SEL *sel;
796 
797  if (!sela) sela = selaCreate(9);
798 
799  sel = selCreateFromString(sel_8_1, 3, 3, "sel_8_1");
800  selaAddSel(sela, sel, NULL, 0);
801  sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2");
802  selaAddSel(sela, sel, NULL, 0);
803  sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3");
804  selaAddSel(sela, sel, NULL, 0);
805  sel = selCreateFromString(sel_8_4, 3, 3, "sel_8_4");
806  selaAddSel(sela, sel, NULL, 0);
807  sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5");
808  selaAddSel(sela, sel, NULL, 0);
809  sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6");
810  selaAddSel(sela, sel, NULL, 0);
811  sel = selCreateFromString(sel_8_7, 3, 3, "sel_8_7");
812  selaAddSel(sela, sel, NULL, 0);
813  sel = selCreateFromString(sel_8_8, 3, 3, "sel_8_8");
814  selaAddSel(sela, sel, NULL, 0);
815  sel = selCreateFromString(sel_8_9, 3, 3, "sel_8_9");
816  selaAddSel(sela, sel, NULL, 0);
817 
818  return sela;
819 }
820 
821 
833 SELA *
835 {
836 SEL *sel;
837 
838  if (!sela) sela = selaCreate(2);
839 
840  sel = selCreateFromString(sel_48_1, 3, 3, "sel_48_1");
841  selaAddSel(sela, sel, NULL, 0);
842  sel = selCreateFromString(sel_48_2, 3, 3, "sel_48_2");
843  selaAddSel(sela, sel, NULL, 0);
844 
845  return sela;
846 }
847 
848 
849 /* -------------------------------------------------------------------------- *
850  * Other structuring elements *
851  * -------------------------------------------------------------------------- */
865 SEL *
866 selMakePlusSign(l_int32 size,
867  l_int32 linewidth)
868 {
869 PIX *pix;
870 SEL *sel;
871 
872  if (size < 3 || linewidth > size)
873  return (SEL *)ERROR_PTR("invalid input", __func__, NULL);
874 
875  pix = pixCreate(size, size, 1);
876  pixRenderLine(pix, size / 2, 0, size / 2, size - 1,
877  linewidth, L_SET_PIXELS);
878  pixRenderLine(pix, 0, size / 2, size, size / 2,
879  linewidth, L_SET_PIXELS);
880  sel = selCreateFromPix(pix, size / 2, size / 2, "plus_sign");
881  pixDestroy(&pix);
882  return sel;
883 }
#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:1455
PTA * generatePtaLineFromPt(l_int32 x, l_int32 y, l_float64 length, l_float64 radang)
generatePtaLineFromPt()
Definition: graphics.c:882
l_ok pixRenderPta(PIX *pix, PTA *pta, l_int32 op)
pixRenderPta()
Definition: graphics.c:1232
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1104
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
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:799
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:618
@ L_SET_PIXELS
Definition: pix.h:565
@ L_INSERT
Definition: pix.h:504
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:404
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:680
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:1025
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:166
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1306
SEL * selCreateFromPix(PIX *pix, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPix()
Definition: sel1.c:1932
l_ok selaWriteStream(FILE *fp, SELA *sela)
selaWriteStream()
Definition: sel1.c:1424
SEL * selCreateFromString(const char *text, l_int32 h, l_int32 w, const char *name)
selCreateFromString()
Definition: sel1.c:1541
l_ok selSetOrigin(SEL *sel, l_int32 cy, l_int32 cx)
selSetOrigin()
Definition: sel1.c:844
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:545
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:789
PIX * selaDisplayInPix(SELA *sela, l_int32 size, l_int32 gthick, l_int32 spacing, l_int32 ncols)
selaDisplayInPix()
Definition: sel1.c:2287
SEL * selCreate(l_int32 height, l_int32 width, const char *name)
selCreate()
Definition: sel1.c:308
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:410
SEL * selCreateFromColorPix(PIX *pixs, const char *selname)
Definition: sel1.c:2037
SELA * sela8ccThin(SELA *sela)
sela8ccThin()
Definition: sel2.c:793
SELA * selaAddHitMiss(SELA *sela)
selaAddHitMiss()
Definition: sel2.c:186
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
SELA * sela4and8ccThin(SELA *sela)
sela4and8ccThin()
Definition: sel2.c:834
SELA * selaAddDwaCombs(SELA *sela)
selaAddDwaCombs()
Definition: sel2.c:362
SELA * selaAddTJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddTJunctions()
Definition: sel2.c:553
SELA * sela4ccThin(SELA *sela)
sela4ccThin()
Definition: sel2.c:752
SELA * selaAddDwaLinear(SELA *sela)
selaAddDwaLinear()
Definition: sel2.c:322
SEL * selMakePlusSign(l_int32 size, l_int32 linewidth)
selMakePlusSign()
Definition: sel2.c:866
SELA * selaAddCrossJunctions(SELA *sela, l_float32 hlsize, l_float32 mdist, l_int32 norient, l_int32 debugflag)
selaAddCrossJunctions()
Definition: sel2.c:430
Definition: morph.h:74
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2138