Leptonica  1.82.0
Image processing and image analysis suite
sel1.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 
142 #ifdef HAVE_CONFIG_H
143 #include <config_auto.h>
144 #endif /* HAVE_CONFIG_H */
145 
146 #include <string.h>
147 #include "allheaders.h"
148 
149  /* Bounds on sel ptr array size */
150 static const l_uint32 MaxPtrArraySize = 10000;
151 static const l_int32 InitialPtrArraySize = 50;
153  /* Bounds on kernel size */
154 static const l_uint32 MaxKernelSize = 10000;
155 
156  /* Bounds on pix template size */
157 static const l_uint32 MaxPixTemplateSize = 100;
158 static const l_uint32 MaxPixTemplateHits = 1000;
159 
160  /* Static functions */
161 static l_int32 selaExtendArray(SELA *sela);
162 static SEL *selCreateFromSArray(SARRAY *sa, l_int32 first, l_int32 last);
163 
165 {
166  l_int32 size;
167  l_int32 size1;
168  l_int32 size2;
169  char selnameh1[20];
170  char selnameh2[20];
171  char selnamev1[20];
172  char selnamev2[20];
173 };
174 
175 static const struct CompParameterMap comp_parameter_map[] =
176  { { 2, 2, 1, "sel_2h", "", "sel_2v", "" },
177  { 3, 3, 1, "sel_3h", "", "sel_3v", "" },
178  { 4, 2, 2, "sel_2h", "sel_comb_4h", "sel_2v", "sel_comb_4v" },
179  { 5, 5, 1, "sel_5h", "", "sel_5v", "" },
180  { 6, 3, 2, "sel_3h", "sel_comb_6h", "sel_3v", "sel_comb_6v" },
181  { 7, 7, 1, "sel_7h", "", "sel_7v", "" },
182  { 8, 4, 2, "sel_4h", "sel_comb_8h", "sel_4v", "sel_comb_8v" },
183  { 9, 3, 3, "sel_3h", "sel_comb_9h", "sel_3v", "sel_comb_9v" },
184  { 10, 5, 2, "sel_5h", "sel_comb_10h", "sel_5v", "sel_comb_10v" },
185  { 11, 4, 3, "sel_4h", "sel_comb_12h", "sel_4v", "sel_comb_12v" },
186  { 12, 4, 3, "sel_4h", "sel_comb_12h", "sel_4v", "sel_comb_12v" },
187  { 13, 4, 3, "sel_4h", "sel_comb_12h", "sel_4v", "sel_comb_12v" },
188  { 14, 7, 2, "sel_7h", "sel_comb_14h", "sel_7v", "sel_comb_14v" },
189  { 15, 5, 3, "sel_5h", "sel_comb_15h", "sel_5v", "sel_comb_15v" },
190  { 16, 4, 4, "sel_4h", "sel_comb_16h", "sel_4v", "sel_comb_16v" },
191  { 17, 4, 4, "sel_4h", "sel_comb_16h", "sel_4v", "sel_comb_16v" },
192  { 18, 6, 3, "sel_6h", "sel_comb_18h", "sel_6v", "sel_comb_18v" },
193  { 19, 5, 4, "sel_5h", "sel_comb_20h", "sel_5v", "sel_comb_20v" },
194  { 20, 5, 4, "sel_5h", "sel_comb_20h", "sel_5v", "sel_comb_20v" },
195  { 21, 7, 3, "sel_7h", "sel_comb_21h", "sel_7v", "sel_comb_21v" },
196  { 22, 11, 2, "sel_11h", "sel_comb_22h", "sel_11v", "sel_comb_22v" },
197  { 23, 6, 4, "sel_6h", "sel_comb_24h", "sel_6v", "sel_comb_24v" },
198  { 24, 6, 4, "sel_6h", "sel_comb_24h", "sel_6v", "sel_comb_24v" },
199  { 25, 5, 5, "sel_5h", "sel_comb_25h", "sel_5v", "sel_comb_25v" },
200  { 26, 5, 5, "sel_5h", "sel_comb_25h", "sel_5v", "sel_comb_25v" },
201  { 27, 9, 3, "sel_9h", "sel_comb_27h", "sel_9v", "sel_comb_27v" },
202  { 28, 7, 4, "sel_7h", "sel_comb_28h", "sel_7v", "sel_comb_28v" },
203  { 29, 6, 5, "sel_6h", "sel_comb_30h", "sel_6v", "sel_comb_30v" },
204  { 30, 6, 5, "sel_6h", "sel_comb_30h", "sel_6v", "sel_comb_30v" },
205  { 31, 6, 5, "sel_6h", "sel_comb_30h", "sel_6v", "sel_comb_30v" },
206  { 32, 8, 4, "sel_8h", "sel_comb_32h", "sel_8v", "sel_comb_32v" },
207  { 33, 11, 3, "sel_11h", "sel_comb_33h", "sel_11v", "sel_comb_33v" },
208  { 34, 7, 5, "sel_7h", "sel_comb_35h", "sel_7v", "sel_comb_35v" },
209  { 35, 7, 5, "sel_7h", "sel_comb_35h", "sel_7v", "sel_comb_35v" },
210  { 36, 6, 6, "sel_6h", "sel_comb_36h", "sel_6v", "sel_comb_36v" },
211  { 37, 6, 6, "sel_6h", "sel_comb_36h", "sel_6v", "sel_comb_36v" },
212  { 38, 6, 6, "sel_6h", "sel_comb_36h", "sel_6v", "sel_comb_36v" },
213  { 39, 13, 3, "sel_13h", "sel_comb_39h", "sel_13v", "sel_comb_39v" },
214  { 40, 8, 5, "sel_8h", "sel_comb_40h", "sel_8v", "sel_comb_40v" },
215  { 41, 7, 6, "sel_7h", "sel_comb_42h", "sel_7v", "sel_comb_42v" },
216  { 42, 7, 6, "sel_7h", "sel_comb_42h", "sel_7v", "sel_comb_42v" },
217  { 43, 7, 6, "sel_7h", "sel_comb_42h", "sel_7v", "sel_comb_42v" },
218  { 44, 11, 4, "sel_11h", "sel_comb_44h", "sel_11v", "sel_comb_44v" },
219  { 45, 9, 5, "sel_9h", "sel_comb_45h", "sel_9v", "sel_comb_45v" },
220  { 46, 9, 5, "sel_9h", "sel_comb_45h", "sel_9v", "sel_comb_45v" },
221  { 47, 8, 6, "sel_8h", "sel_comb_48h", "sel_8v", "sel_comb_48v" },
222  { 48, 8, 6, "sel_8h", "sel_comb_48h", "sel_8v", "sel_comb_48v" },
223  { 49, 7, 7, "sel_7h", "sel_comb_49h", "sel_7v", "sel_comb_49v" },
224  { 50, 10, 5, "sel_10h", "sel_comb_50h", "sel_10v", "sel_comb_50v" },
225  { 51, 10, 5, "sel_10h", "sel_comb_50h", "sel_10v", "sel_comb_50v" },
226  { 52, 13, 4, "sel_13h", "sel_comb_52h", "sel_13v", "sel_comb_52v" },
227  { 53, 9, 6, "sel_9h", "sel_comb_54h", "sel_9v", "sel_comb_54v" },
228  { 54, 9, 6, "sel_9h", "sel_comb_54h", "sel_9v", "sel_comb_54v" },
229  { 55, 11, 5, "sel_11h", "sel_comb_55h", "sel_11v", "sel_comb_55v" },
230  { 56, 8, 7, "sel_8h", "sel_comb_56h", "sel_8v", "sel_comb_56v" },
231  { 57, 8, 7, "sel_8h", "sel_comb_56h", "sel_8v", "sel_comb_56v" },
232  { 58, 8, 7, "sel_8h", "sel_comb_56h", "sel_8v", "sel_comb_56v" },
233  { 59, 10, 6, "sel_10h", "sel_comb_60h", "sel_10v", "sel_comb_60v" },
234  { 60, 10, 6, "sel_10h", "sel_comb_60h", "sel_10v", "sel_comb_60v" },
235  { 61, 10, 6, "sel_10h", "sel_comb_60h", "sel_10v", "sel_comb_60v" },
236  { 62, 9, 7, "sel_9h", "sel_comb_63h", "sel_9v", "sel_comb_63v" },
237  { 63, 9, 7, "sel_9h", "sel_comb_63h", "sel_9v", "sel_comb_63v" } };
238 
239 
240 
241 /*------------------------------------------------------------------------*
242  * Create / Destroy / Copy *
243  *------------------------------------------------------------------------*/
250 SELA *
251 selaCreate(l_int32 n)
252 {
253 SELA *sela;
254 
255  PROCNAME("selaCreate");
256 
257  if (n <= 0 || n > MaxPtrArraySize)
259 
260  /* Make array of sel ptrs */
261  sela = (SELA *)LEPT_CALLOC(1, sizeof(SELA));
262  sela->nalloc = n;
263  sela->n = 0;
264  sela->sel = (SEL **)LEPT_CALLOC(n, sizeof(SEL *));
265  return sela;
266 }
267 
268 
275 void
277 {
278 SELA *sela;
279 l_int32 i;
280 
281  if (!psela) return;
282  if ((sela = *psela) == NULL)
283  return;
284 
285  for (i = 0; i < sela->n; i++)
286  selDestroy(&sela->sel[i]);
287  LEPT_FREE(sela->sel);
288  LEPT_FREE(sela);
289  *psela = NULL;
290 }
291 
292 
309 SEL *
310 selCreate(l_int32 height,
311  l_int32 width,
312  const char *name)
313 {
314 SEL *sel;
315 
316  PROCNAME("selCreate");
317 
318  sel = (SEL *)LEPT_CALLOC(1, sizeof(SEL));
319  if (name)
320  sel->name = stringNew(name);
321  sel->sy = height;
322  sel->sx = width;
323  if ((sel->data = create2dIntArray(height, width)) == NULL) {
324  LEPT_FREE(sel->name);
325  LEPT_FREE(sel);
326  return (SEL *)ERROR_PTR("data not allocated", procName, NULL);
327  }
328 
329  return sel;
330 }
331 
332 
339 void
340 selDestroy(SEL **psel)
341 {
342 l_int32 i;
343 SEL *sel;
344 
345  PROCNAME("selDestroy");
346 
347  if (psel == NULL) {
348  L_WARNING("ptr address is NULL!\n", procName);
349  return;
350  }
351  if ((sel = *psel) == NULL)
352  return;
353 
354  for (i = 0; i < sel->sy; i++)
355  LEPT_FREE(sel->data[i]);
356  LEPT_FREE(sel->data);
357  if (sel->name)
358  LEPT_FREE(sel->name);
359  LEPT_FREE(sel);
360  *psel = NULL;
361 }
362 
363 
370 SEL *
371 selCopy(SEL *sel)
372 {
373 l_int32 sx, sy, cx, cy, i, j;
374 SEL *csel;
375 
376  PROCNAME("selCopy");
377 
378  if (!sel)
379  return (SEL *)ERROR_PTR("sel not defined", procName, NULL);
380 
381  csel = (SEL *)LEPT_CALLOC(1, sizeof(SEL));
382  selGetParameters(sel, &sy, &sx, &cy, &cx);
383  csel->sy = sy;
384  csel->sx = sx;
385  csel->cy = cy;
386  csel->cx = cx;
387 
388  if ((csel->data = create2dIntArray(sy, sx)) == NULL) {
389  LEPT_FREE(csel);
390  return (SEL *)ERROR_PTR("sel data not made", procName, NULL);
391  }
392 
393  for (i = 0; i < sy; i++)
394  for (j = 0; j < sx; j++)
395  csel->data[i][j] = sel->data[i][j];
396 
397  if (sel->name)
398  csel->name = stringNew(sel->name);
399 
400  return csel;
401 }
402 
403 
417 SEL *
418 selCreateBrick(l_int32 h,
419  l_int32 w,
420  l_int32 cy,
421  l_int32 cx,
422  l_int32 type)
423 {
424 l_int32 i, j;
425 SEL *sel;
426 
427  PROCNAME("selCreateBrick");
428 
429  if (h <= 0 || w <= 0)
430  return (SEL *)ERROR_PTR("h and w must both be > 0", procName, NULL);
431  if (type != SEL_HIT && type != SEL_MISS && type != SEL_DONT_CARE)
432  return (SEL *)ERROR_PTR("invalid sel element type", procName, NULL);
433 
434  if ((sel = selCreate(h, w, NULL)) == NULL)
435  return (SEL *)ERROR_PTR("sel not made", procName, NULL);
436  selSetOrigin(sel, cy, cx);
437  for (i = 0; i < h; i++)
438  for (j = 0; j < w; j++)
439  sel->data[i][j] = type;
440 
441  return sel;
442 }
443 
444 
461 SEL *
462 selCreateComb(l_int32 factor1,
463  l_int32 factor2,
464  l_int32 direction)
465 {
466 l_int32 i, size, z;
467 SEL *sel;
468 
469  PROCNAME("selCreateComb");
470 
471  if (factor1 < 1 || factor2 < 1)
472  return (SEL *)ERROR_PTR("factors must be >= 1", procName, NULL);
473  if (direction != L_HORIZ && direction != L_VERT)
474  return (SEL *)ERROR_PTR("invalid direction", procName, NULL);
475 
476  size = factor1 * factor2;
477  if (direction == L_HORIZ) {
478  if ((sel = selCreate(1, size, NULL)) == NULL)
479  return (SEL *)ERROR_PTR("horiz sel not made", procName, NULL);
480  selSetOrigin(sel, 0, size / 2);
481  } else {
482  if ((sel = selCreate(size, 1, NULL)) == NULL)
483  return (SEL *)ERROR_PTR("vert sel not made", procName, NULL);
484  selSetOrigin(sel, size / 2, 0);
485  }
486 
487  /* Lay down the elements of the comb */
488  for (i = 0; i < factor2; i++) {
489  z = factor1 / 2 + i * factor1;
490 /* lept_stderr("i = %d, factor1 = %d, factor2 = %d, z = %d\n",
491  i, factor1, factor2, z); */
492  if (direction == L_HORIZ)
493  selSetElement(sel, 0, z, SEL_HIT);
494  else
495  selSetElement(sel, z, 0, SEL_HIT);
496  }
497 
498  return sel;
499 }
500 
501 
516 l_int32 **
517 create2dIntArray(l_int32 sy,
518  l_int32 sx)
519 {
520 l_int32 i;
521 l_int32 **array;
522 
523  PROCNAME("create2dIntArray");
524 
525  if (sx <= 0 || sx > MaxKernelSize)
526  return (l_int32 **)ERROR_PTR("sx out of bounds", procName, NULL);
527  if (sy <= 0 || sy > MaxKernelSize)
528  return (l_int32 **)ERROR_PTR("sy out of bounds", procName, NULL);
529 
530  array = (l_int32 **)LEPT_CALLOC(sy, sizeof(l_int32 *));
531  for (i = 0; i < sy; i++)
532  array[i] = (l_int32 *)LEPT_CALLOC(sx, sizeof(l_int32));
533  return array;
534 }
535 
536 
537 /*------------------------------------------------------------------------*
538  * Extension of sela *
539  *------------------------------------------------------------------------*/
558 l_ok
560  SEL *sel,
561  const char *selname,
562  l_int32 copyflag)
563 {
564 l_int32 n;
565 SEL *csel;
566 
567  PROCNAME("selaAddSel");
568 
569  if (!sela)
570  return ERROR_INT("sela not defined", procName, 1);
571  if (!sel)
572  return ERROR_INT("sel not defined", procName, 1);
573  if (!sel->name && !selname)
574  return ERROR_INT("added sel must have name", procName, 1);
575  if (copyflag != L_INSERT && copyflag != L_COPY)
576  return ERROR_INT("invalid copyflag", procName, 1);
577 
578  if (copyflag == L_COPY) {
579  if ((csel = selCopy(sel)) == NULL)
580  return ERROR_INT("csel not made", procName, 1);
581  } else { /* copyflag == L_INSERT */
582  csel = sel;
583  }
584  if (!csel->name)
585  csel->name = stringNew(selname);
586 
587  n = selaGetCount(sela);
588  if (n >= sela->nalloc) {
589  if (selaExtendArray(sela)) {
590  if (copyflag != L_INSERT)
591  selDestroy(&csel);
592  return ERROR_INT("extension failed", procName, 1);
593  }
594  }
595 
596  sela->sel[n] = csel;
597  sela->n++;
598  return 0;
599 }
600 
601 
608 static l_int32
610 {
611  PROCNAME("selaExtendArray");
612 
613  if (!sela)
614  return ERROR_INT("sela not defined", procName, 1);
615 
616  if ((sela->sel = (SEL **)reallocNew((void **)&sela->sel,
617  sizeof(SEL *) * sela->nalloc,
618  2 * sizeof(SEL *) * sela->nalloc)) == NULL)
619  return ERROR_INT("new ptr array not returned", procName, 1);
620 
621  sela->nalloc = 2 * sela->nalloc;
622  return 0;
623 }
624 
625 
626 
627 /*----------------------------------------------------------------------*
628  * Accessors *
629  *----------------------------------------------------------------------*/
636 l_int32
638 {
639  PROCNAME("selaGetCount");
640 
641  if (!sela)
642  return ERROR_INT("sela not defined", procName, 0);
643 
644  return sela->n;
645 }
646 
647 
661 SEL *
663  l_int32 i)
664 {
665  PROCNAME("selaGetSel");
666 
667  if (!sela)
668  return (SEL *)ERROR_PTR("sela not defined", procName, NULL);
669 
670  if (i < 0 || i >= sela->n)
671  return (SEL *)ERROR_PTR("invalid index", procName, NULL);
672  return sela->sel[i];
673 }
674 
675 
682 char *
683 selGetName(SEL *sel)
684 {
685  PROCNAME("selGetName");
686 
687  if (!sel)
688  return (char *)ERROR_PTR("sel not defined", procName, NULL);
689 
690  return sel->name;
691 }
692 
693 
707 l_ok
708 selSetName(SEL *sel,
709  const char *name)
710 {
711  PROCNAME("selSetName");
712 
713  if (!sel)
714  return ERROR_INT("sel not defined", procName, 1);
715 
716  return stringReplace(&sel->name, name);
717 }
718 
719 
729 l_ok
731  const char *name,
732  l_int32 *pindex,
733  SEL **psel)
734 {
735 l_int32 i, n;
736 char *sname;
737 SEL *sel;
738 
739  PROCNAME("selaFindSelByName");
740 
741  if (pindex) *pindex = -1;
742  if (psel) *psel = NULL;
743 
744  if (!sela)
745  return ERROR_INT("sela not defined", procName, 1);
746 
747  n = selaGetCount(sela);
748  for (i = 0; i < n; i++)
749  {
750  if ((sel = selaGetSel(sela, i)) == NULL) {
751  L_WARNING("missing sel\n", procName);
752  continue;
753  }
754 
755  sname = selGetName(sel);
756  if (sname && (!strcmp(name, sname))) {
757  if (pindex)
758  *pindex = i;
759  if (psel)
760  *psel = sel;
761  return 0;
762  }
763  }
764 
765  return 1;
766 }
767 
768 
778 l_ok
779 selGetElement(SEL *sel,
780  l_int32 row,
781  l_int32 col,
782  l_int32 *ptype)
783 {
784  PROCNAME("selGetElement");
785 
786  if (!ptype)
787  return ERROR_INT("&type not defined", procName, 1);
788  *ptype = SEL_DONT_CARE;
789  if (!sel)
790  return ERROR_INT("sel not defined", procName, 1);
791  if (row < 0 || row >= sel->sy)
792  return ERROR_INT("sel row out of bounds", procName, 1);
793  if (col < 0 || col >= sel->sx)
794  return ERROR_INT("sel col out of bounds", procName, 1);
795 
796  *ptype = sel->data[row][col];
797  return 0;
798 }
799 
800 
818 l_ok
819 selSetElement(SEL *sel,
820  l_int32 row,
821  l_int32 col,
822  l_int32 type)
823 {
824  PROCNAME("selSetElement");
825 
826  if (!sel)
827  return ERROR_INT("sel not defined", procName, 1);
828  if (type != SEL_HIT && type != SEL_MISS && type != SEL_DONT_CARE)
829  return ERROR_INT("invalid sel element type", procName, 1);
830  if (row < 0 || row >= sel->sy)
831  return ERROR_INT("sel row out of bounds", procName, 1);
832  if (col < 0 || col >= sel->sx)
833  return ERROR_INT("sel col out of bounds", procName, 1);
834 
835  sel->data[row][col] = type;
836  return 0;
837 }
838 
839 
847 l_ok
849  l_int32 *psy,
850  l_int32 *psx,
851  l_int32 *pcy,
852  l_int32 *pcx)
853 {
854  PROCNAME("selGetParameters");
855 
856  if (psy) *psy = 0;
857  if (psx) *psx = 0;
858  if (pcy) *pcy = 0;
859  if (pcx) *pcx = 0;
860  if (!sel)
861  return ERROR_INT("sel not defined", procName, 1);
862  if (psy) *psy = sel->sy;
863  if (psx) *psx = sel->sx;
864  if (pcy) *pcy = sel->cy;
865  if (pcx) *pcx = sel->cx;
866  return 0;
867 }
868 
869 
877 l_ok
878 selSetOrigin(SEL *sel,
879  l_int32 cy,
880  l_int32 cx)
881 {
882  PROCNAME("selSetOrigin");
883 
884  if (!sel)
885  return ERROR_INT("sel not defined", procName, 1);
886  sel->cy = cy;
887  sel->cx = cx;
888  return 0;
889 }
890 
891 
899 l_ok
901  l_int32 *ptype)
902 {
903 l_int32 sx, sy, cx, cy, i, j;
904 
905  PROCNAME("selGetTypeAtOrigin");
906 
907  if (!ptype)
908  return ERROR_INT("&type not defined", procName, 1);
909  *ptype = SEL_DONT_CARE; /* init */
910  if (!sel)
911  return ERROR_INT("sel not defined", procName, 1);
912 
913  selGetParameters(sel, &sy, &sx, &cy, &cx);
914  for (i = 0; i < sy; i++) {
915  for (j = 0; j < sx; j++) {
916  if (i == cy && j == cx) {
917  selGetElement(sel, i, j, ptype);
918  return 0;
919  }
920  }
921  }
922 
923  return ERROR_INT("sel origin not found", procName, 1);
924 }
925 
926 
934 char *
936  l_int32 hsize,
937  l_int32 vsize)
938 {
939 l_int32 i, nsels, sx, sy;
940 SEL *sel;
941 
942  PROCNAME("selaGetBrickName");
943 
944  if (!sela)
945  return (char *)ERROR_PTR("sela not defined", procName, NULL);
946 
947  nsels = selaGetCount(sela);
948  for (i = 0; i < nsels; i++) {
949  sel = selaGetSel(sela, i);
950  selGetParameters(sel, &sy, &sx, NULL, NULL);
951  if (hsize == sx && vsize == sy)
952  return stringNew(selGetName(sel));
953  }
954 
955  return (char *)ERROR_PTR("sel not found", procName, NULL);
956 }
957 
958 
973 char *
975  l_int32 size,
976  l_int32 direction)
977 {
978 char *selname;
979 char combname[256];
980 l_int32 i, nsels, sx, sy, found;
981 SEL *sel;
982 
983  PROCNAME("selaGetCombName");
984 
985  if (!sela)
986  return (char *)ERROR_PTR("sela not defined", procName, NULL);
987  if (direction != L_HORIZ && direction != L_VERT)
988  return (char *)ERROR_PTR("invalid direction", procName, NULL);
989 
990  /* Derive the comb name we're looking for */
991  if (direction == L_HORIZ)
992  snprintf(combname, sizeof(combname), "sel_comb_%dh", size);
993  else /* direction == L_VERT */
994  snprintf(combname, sizeof(combname), "sel_comb_%dv", size);
995 
996  found = FALSE;
997  nsels = selaGetCount(sela);
998  for (i = 0; i < nsels; i++) {
999  sel = selaGetSel(sela, i);
1000  selGetParameters(sel, &sy, &sx, NULL, NULL);
1001  if (sy != 1 && sx != 1) /* 2-D; not a comb */
1002  continue;
1003  selname = selGetName(sel);
1004  if (!strcmp(selname, combname)) {
1005  found = TRUE;
1006  break;
1007  }
1008  }
1009 
1010  if (found)
1011  return stringNew(selname);
1012  else
1013  return (char *)ERROR_PTR("sel not found", procName, NULL);
1014 }
1015 
1016 
1017 /* --------- Function used to generate code in this file ---------- */
1018 #if 0
1019 static void selaComputeCompositeParameters(const char *fileout);
1020 
1038 static void
1039 selaComputeCompositeParameters(const char *fileout)
1040 {
1041 char *str, *nameh1, *nameh2, *namev1, *namev2;
1042 char buf[256];
1043 l_int32 size, size1, size2, len;
1044 SARRAY *sa;
1045 SELA *selabasic, *selacomb;
1046 
1047  selabasic = selaAddBasic(NULL);
1048  selacomb = selaAddDwaCombs(NULL);
1049  sa = sarrayCreate(64);
1050  for (size = 2; size < 64; size++) {
1051  selectComposableSizes(size, &size1, &size2);
1052  nameh1 = selaGetBrickName(selabasic, size1, 1);
1053  namev1 = selaGetBrickName(selabasic, 1, size1);
1054  if (size2 > 1) {
1055  nameh2 = selaGetCombName(selacomb, size1 * size2, L_HORIZ);
1056  namev2 = selaGetCombName(selacomb, size1 * size2, L_VERT);
1057  } else {
1058  nameh2 = stringNew("");
1059  namev2 = stringNew("");
1060  }
1061  snprintf(buf, sizeof(buf),
1062  " { %d, %d, %d, \"%s\", \"%s\", \"%s\", \"%s\" },",
1063  size, size1, size2, nameh1, nameh2, namev1, namev2);
1064  sarrayAddString(sa, buf, L_COPY);
1065  LEPT_FREE(nameh1);
1066  LEPT_FREE(nameh2);
1067  LEPT_FREE(namev1);
1068  LEPT_FREE(namev2);
1069  }
1070  str = sarrayToString(sa, 1);
1071  len = strlen(str);
1072  l_binaryWrite(fileout, "w", str, len + 1);
1073  LEPT_FREE(str);
1074  sarrayDestroy(&sa);
1075  selaDestroy(&selabasic);
1076  selaDestroy(&selacomb);
1077 }
1078 #endif
1079 /* -------------------------------------------------------------------- */
1080 
1081 
1100 l_ok
1102  l_int32 *psize1,
1103  l_int32 *psize2,
1104  char **pnameh1,
1105  char **pnameh2,
1106  char **pnamev1,
1107  char **pnamev2)
1108 {
1109 l_int32 index;
1110 
1111  PROCNAME("selaGetSelnames");
1112 
1113  if (psize1) *psize1 = 0;
1114  if (psize2) *psize2 = 0;
1115  if (pnameh1) *pnameh1 = NULL;
1116  if (pnameh2) *pnameh2 = NULL;
1117  if (pnamev1) *pnamev1 = NULL;
1118  if (pnamev2) *pnamev2 = NULL;
1119  if (size < 2 || size > 63)
1120  return ERROR_INT("valid size range is {2 ... 63}", procName, 1);
1121  index = size - 2;
1122  if (psize1)
1123  *psize1 = comp_parameter_map[index].size1;
1124  if (psize2)
1125  *psize2 = comp_parameter_map[index].size2;
1126  if (pnameh1)
1127  *pnameh1 = stringNew(comp_parameter_map[index].selnameh1);
1128  if (pnameh2)
1129  *pnameh2 = stringNew(comp_parameter_map[index].selnameh2);
1130  if (pnamev1)
1131  *pnamev1 = stringNew(comp_parameter_map[index].selnamev1);
1132  if (pnamev2)
1133  *pnamev2 = stringNew(comp_parameter_map[index].selnamev2);
1134  return 0;
1135 }
1136 
1137 
1144 SARRAY *
1146 {
1147 char *selname;
1148 l_int32 i, n;
1149 SEL *sel;
1150 SARRAY *sa;
1151 
1152  PROCNAME("selaGetSelnames");
1153 
1154  if (!sela)
1155  return (SARRAY *)ERROR_PTR("sela not defined", procName, NULL);
1156  if ((n = selaGetCount(sela)) == 0)
1157  return (SARRAY *)ERROR_PTR("no sels in sela", procName, NULL);
1158 
1159  if ((sa = sarrayCreate(n)) == NULL)
1160  return (SARRAY *)ERROR_PTR("sa not made", procName, NULL);
1161  for (i = 0; i < n; i++) {
1162  sel = selaGetSel(sela, i);
1163  selname = selGetName(sel);
1164  sarrayAddString(sa, selname, L_COPY);
1165  }
1166 
1167  return sa;
1168 }
1169 
1170 
1171 
1172 /*----------------------------------------------------------------------*
1173  * Max translations for erosion and hmt *
1174  *----------------------------------------------------------------------*/
1189 l_ok
1191  l_int32 *pxp,
1192  l_int32 *pyp,
1193  l_int32 *pxn,
1194  l_int32 *pyn)
1195 {
1196 l_int32 sx, sy, cx, cy, i, j;
1197 l_int32 maxxp, maxyp, maxxn, maxyn;
1198 
1199  PROCNAME("selaFindMaxTranslations");
1200 
1201  if (!pxp || !pyp || !pxn || !pyn)
1202  return ERROR_INT("&xp (etc) defined", procName, 1);
1203  *pxp = *pyp = *pxn = *pyn = 0;
1204  if (!sel)
1205  return ERROR_INT("sel not defined", procName, 1);
1206  selGetParameters(sel, &sy, &sx, &cy, &cx);
1207 
1208  maxxp = maxyp = maxxn = maxyn = 0;
1209  for (i = 0; i < sy; i++) {
1210  for (j = 0; j < sx; j++) {
1211  if (sel->data[i][j] == 1) {
1212  maxxp = L_MAX(maxxp, cx - j);
1213  maxyp = L_MAX(maxyp, cy - i);
1214  maxxn = L_MAX(maxxn, j - cx);
1215  maxyn = L_MAX(maxyn, i - cy);
1216  }
1217  }
1218  }
1219 
1220  *pxp = maxxp;
1221  *pyp = maxyp;
1222  *pxn = maxxn;
1223  *pyn = maxyn;
1224 
1225  return 0;
1226 }
1227 
1228 
1229 /*----------------------------------------------------------------------*
1230  * Rotation by multiples of 90 degrees *
1231  *----------------------------------------------------------------------*/
1239 SEL *
1240 selRotateOrth(SEL *sel,
1241  l_int32 quads)
1242 {
1243 l_int32 i, j, ni, nj, sx, sy, cx, cy, nsx, nsy, ncx, ncy, type;
1244 SEL *seld;
1245 
1246  PROCNAME("selRotateOrth");
1247 
1248  if (!sel)
1249  return (SEL *)ERROR_PTR("sel not defined", procName, NULL);
1250  if (quads < 0 || quads > 4)
1251  return (SEL *)ERROR_PTR("quads not in {0,1,2,3,4}", procName, NULL);
1252  if (quads == 0 || quads == 4)
1253  return selCopy(sel);
1254 
1255  selGetParameters(sel, &sy, &sx, &cy, &cx);
1256  if (quads == 1) { /* 90 degrees cw */
1257  nsx = sy;
1258  nsy = sx;
1259  ncx = sy - cy - 1;
1260  ncy = cx;
1261  } else if (quads == 2) { /* 180 degrees cw */
1262  nsx = sx;
1263  nsy = sy;
1264  ncx = sx - cx - 1;
1265  ncy = sy - cy - 1;
1266  } else { /* 270 degrees cw */
1267  nsx = sy;
1268  nsy = sx;
1269  ncx = cy;
1270  ncy = sx - cx - 1;
1271  }
1272  seld = selCreateBrick(nsy, nsx, ncy, ncx, SEL_DONT_CARE);
1273  if (sel->name)
1274  seld->name = stringNew(sel->name);
1275 
1276  for (i = 0; i < sy; i++) {
1277  for (j = 0; j < sx; j++) {
1278  selGetElement(sel, i, j, &type);
1279  if (quads == 1) {
1280  ni = j;
1281  nj = sy - i - 1;
1282  } else if (quads == 2) {
1283  ni = sy - i - 1;
1284  nj = sx - j - 1;
1285  } else { /* quads == 3 */
1286  ni = sx - j - 1;
1287  nj = i;
1288  }
1289  selSetElement(seld, ni, nj, type);
1290  }
1291  }
1292 
1293  return seld;
1294 }
1295 
1296 
1297 /*----------------------------------------------------------------------*
1298  * Sela and Sel serialized I/O *
1299  *----------------------------------------------------------------------*/
1306 SELA *
1307 selaRead(const char *fname)
1308 {
1309 FILE *fp;
1310 SELA *sela;
1311 
1312  PROCNAME("selaRead");
1313 
1314  if (!fname)
1315  return (SELA *)ERROR_PTR("fname not defined", procName, NULL);
1316 
1317  if ((fp = fopenReadStream(fname)) == NULL)
1318  return (SELA *)ERROR_PTR("stream not opened", procName, NULL);
1319  if ((sela = selaReadStream(fp)) == NULL) {
1320  fclose(fp);
1321  return (SELA *)ERROR_PTR("sela not returned", procName, NULL);
1322  }
1323  fclose(fp);
1324 
1325  return sela;
1326 }
1327 
1328 
1335 SELA *
1337 {
1338 l_int32 i, n, version;
1339 SEL *sel;
1340 SELA *sela;
1341 
1342  PROCNAME("selaReadStream");
1343 
1344  if (!fp)
1345  return (SELA *)ERROR_PTR("stream not defined", procName, NULL);
1346 
1347  if (fscanf(fp, "\nSela Version %d\n", &version) != 1)
1348  return (SELA *)ERROR_PTR("not a sela file", procName, NULL);
1349  if (version != SEL_VERSION_NUMBER)
1350  return (SELA *)ERROR_PTR("invalid sel version", procName, NULL);
1351  if (fscanf(fp, "Number of Sels = %d\n\n", &n) != 1)
1352  return (SELA *)ERROR_PTR("not a sela file", procName, NULL);
1353 
1354  if ((sela = selaCreate(n)) == NULL)
1355  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
1356  sela->nalloc = n;
1357 
1358  for (i = 0; i < n; i++) {
1359  if ((sel = selReadStream(fp)) == NULL) {
1360  selaDestroy(&sela);
1361  return (SELA *)ERROR_PTR("sel not read", procName, NULL);
1362  }
1363  selaAddSel(sela, sel, NULL, 0);
1364  }
1365 
1366  return sela;
1367 }
1368 
1369 
1376 SEL *
1377 selRead(const char *fname)
1378 {
1379 FILE *fp;
1380 SEL *sel;
1381 
1382  PROCNAME("selRead");
1383 
1384  if (!fname)
1385  return (SEL *)ERROR_PTR("fname not defined", procName, NULL);
1386 
1387  if ((fp = fopenReadStream(fname)) == NULL)
1388  return (SEL *)ERROR_PTR("stream not opened", procName, NULL);
1389  if ((sel = selReadStream(fp)) == NULL) {
1390  fclose(fp);
1391  return (SEL *)ERROR_PTR("sela not returned", procName, NULL);
1392  }
1393  fclose(fp);
1394 
1395  return sel;
1396 }
1397 
1398 
1405 SEL *
1406 selReadStream(FILE *fp)
1407 {
1408 char selname[256];
1409 char linebuf[256];
1410 l_int32 sy, sx, cy, cx, i, j, version, ignore;
1411 SEL *sel;
1412 
1413  PROCNAME("selReadStream");
1414 
1415  if (!fp)
1416  return (SEL *)ERROR_PTR("stream not defined", procName, NULL);
1417 
1418  if (fscanf(fp, " Sel Version %d\n", &version) != 1)
1419  return (SEL *)ERROR_PTR("not a sel file", procName, NULL);
1420  if (version != SEL_VERSION_NUMBER)
1421  return (SEL *)ERROR_PTR("invalid sel version", procName, NULL);
1422 
1423  if (fgets(linebuf, sizeof(linebuf), fp) == NULL)
1424  return (SEL *)ERROR_PTR("error reading into linebuf", procName, NULL);
1425  sscanf(linebuf, " ------ %200s ------", selname);
1426 
1427  if (fscanf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n",
1428  &sy, &sx, &cy, &cx) != 4)
1429  return (SEL *)ERROR_PTR("dimensions not read", procName, NULL);
1430 
1431  if ((sel = selCreate(sy, sx, selname)) == NULL)
1432  return (SEL *)ERROR_PTR("sel not made", procName, NULL);
1433  selSetOrigin(sel, cy, cx);
1434 
1435  for (i = 0; i < sy; i++) {
1436  ignore = fscanf(fp, " ");
1437  for (j = 0; j < sx; j++)
1438  ignore = fscanf(fp, "%1d", &sel->data[i][j]);
1439  ignore = fscanf(fp, "\n");
1440  }
1441  ignore = fscanf(fp, "\n");
1442 
1443  return sel;
1444 }
1445 
1446 
1454 l_ok
1455 selaWrite(const char *fname,
1456  SELA *sela)
1457 {
1458 FILE *fp;
1459 
1460  PROCNAME("selaWrite");
1461 
1462  if (!fname)
1463  return ERROR_INT("fname not defined", procName, 1);
1464  if (!sela)
1465  return ERROR_INT("sela not defined", procName, 1);
1466 
1467  if ((fp = fopenWriteStream(fname, "wb")) == NULL)
1468  return ERROR_INT("stream not opened", procName, 1);
1469  selaWriteStream(fp, sela);
1470  fclose(fp);
1471 
1472  return 0;
1473 }
1474 
1475 
1483 l_ok
1485  SELA *sela)
1486 {
1487 l_int32 i, n;
1488 SEL *sel;
1489 
1490  PROCNAME("selaWriteStream");
1491 
1492  if (!fp)
1493  return ERROR_INT("stream not defined", procName, 1);
1494  if (!sela)
1495  return ERROR_INT("sela not defined", procName, 1);
1496 
1497  n = selaGetCount(sela);
1498  fprintf(fp, "\nSela Version %d\n", SEL_VERSION_NUMBER);
1499  fprintf(fp, "Number of Sels = %d\n\n", n);
1500  for (i = 0; i < n; i++) {
1501  if ((sel = selaGetSel(sela, i)) == NULL)
1502  continue;
1503  selWriteStream(fp, sel);
1504  }
1505  return 0;
1506 }
1507 
1508 
1516 l_ok
1517 selWrite(const char *fname,
1518  SEL *sel)
1519 {
1520 FILE *fp;
1521 
1522  PROCNAME("selWrite");
1523 
1524  if (!fname)
1525  return ERROR_INT("fname not defined", procName, 1);
1526  if (!sel)
1527  return ERROR_INT("sel not defined", procName, 1);
1528 
1529  if ((fp = fopenWriteStream(fname, "wb")) == NULL)
1530  return ERROR_INT("stream not opened", procName, 1);
1531  selWriteStream(fp, sel);
1532  fclose(fp);
1533 
1534  return 0;
1535 }
1536 
1537 
1545 l_ok
1547  SEL *sel)
1548 {
1549 l_int32 sx, sy, cx, cy, i, j;
1550 
1551  PROCNAME("selWriteStream");
1552 
1553  if (!fp)
1554  return ERROR_INT("stream not defined", procName, 1);
1555  if (!sel)
1556  return ERROR_INT("sel not defined", procName, 1);
1557  selGetParameters(sel, &sy, &sx, &cy, &cx);
1558 
1559  fprintf(fp, " Sel Version %d\n", SEL_VERSION_NUMBER);
1560  fprintf(fp, " ------ %s ------\n", selGetName(sel));
1561  fprintf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n", sy, sx, cy, cx);
1562  for (i = 0; i < sy; i++) {
1563  fprintf(fp, " ");
1564  for (j = 0; j < sx; j++)
1565  fprintf(fp, "%d", sel->data[i][j]);
1566  fprintf(fp, "\n");
1567  }
1568  fprintf(fp, "\n");
1569 
1570  return 0;
1571 }
1572 
1573 
1574 /*----------------------------------------------------------------------*
1575  * Building custom hit-miss sels from compiled strings *
1576  *----------------------------------------------------------------------*/
1606 SEL *
1607 selCreateFromString(const char *text,
1608  l_int32 h,
1609  l_int32 w,
1610  const char *name)
1611 {
1612 SEL *sel;
1613 l_int32 y, x, norig;
1614 char ch;
1615 
1616  PROCNAME("selCreateFromString");
1617 
1618  if (!text || text[0] == '\0')
1619  return (SEL *)ERROR_PTR("text undefined or empty", procName, NULL);
1620  if (h < 1)
1621  return (SEL *)ERROR_PTR("height must be > 0", procName, NULL);
1622  if (w < 1)
1623  return (SEL *)ERROR_PTR("width must be > 0", procName, NULL);
1624  if (strlen(text) != (size_t)w * h)
1625  return (SEL *)ERROR_PTR("text size != w * h", procName, NULL);
1626 
1627  sel = selCreate(h, w, name);
1628  norig = 0;
1629  for (y = 0; y < h; ++y) {
1630  for (x = 0; x < w; ++x) {
1631  ch = *(text++);
1632  switch (ch)
1633  {
1634  case 'X':
1635  norig++;
1636  selSetOrigin(sel, y, x);
1637  /* fall through */
1638  case 'x':
1639  selSetElement(sel, y, x, SEL_HIT);
1640  break;
1641 
1642  case 'O':
1643  norig++;
1644  selSetOrigin(sel, y, x);
1645  /* fall through */
1646  case 'o':
1647  selSetElement(sel, y, x, SEL_MISS);
1648  break;
1649 
1650  case 'C':
1651  norig++;
1652  selSetOrigin(sel, y, x);
1653  /* fall through */
1654  case ' ':
1655  selSetElement(sel, y, x, SEL_DONT_CARE);
1656  break;
1657 
1658  case '\n':
1659  /* ignored */
1660  continue;
1661 
1662  default:
1663  selDestroy(&sel);
1664  return (SEL *)ERROR_PTR("unknown char", procName, NULL);
1665  }
1666  }
1667  }
1668  if (norig != 1) {
1669  L_ERROR("Exactly one origin must be specified; this string has %d\n",
1670  procName, norig);
1671  selDestroy(&sel);
1672  }
1673 
1674  return sel;
1675 }
1676 
1677 
1697 char *
1699 {
1700 char is_center;
1701 char *str, *strptr;
1702 l_int32 type;
1703 l_int32 sx, sy, cx, cy, x, y;
1704 
1705  PROCNAME("selPrintToString");
1706 
1707  if (!sel)
1708  return (char *)ERROR_PTR("sel not defined", procName, NULL);
1709 
1710  selGetParameters(sel, &sy, &sx, &cy, &cx);
1711  if ((str = (char *)LEPT_CALLOC(1, sy * (sx + 1) + 1)) == NULL)
1712  return (char *)ERROR_PTR("calloc fail for str", procName, NULL);
1713  strptr = str;
1714 
1715  for (y = 0; y < sy; ++y) {
1716  for (x = 0; x < sx; ++x) {
1717  selGetElement(sel, y, x, &type);
1718  is_center = (x == cx && y == cy);
1719  switch (type) {
1720  case SEL_HIT:
1721  *(strptr++) = is_center ? 'X' : 'x';
1722  break;
1723  case SEL_MISS:
1724  *(strptr++) = is_center ? 'O' : 'o';
1725  break;
1726  case SEL_DONT_CARE:
1727  *(strptr++) = is_center ? 'C' : ' ';
1728  break;
1729  }
1730  }
1731  *(strptr++) = '\n';
1732  }
1733 
1734  return str;
1735 }
1736 
1737 
1738 /*----------------------------------------------------------------------*
1739  * Building custom hit-miss sels from a simple file format *
1740  *----------------------------------------------------------------------*/
1772 SELA *
1773 selaCreateFromFile(const char *filename)
1774 {
1775 char *filestr, *line;
1776 l_int32 i, n, first, last, nsel, insel;
1777 size_t nbytes;
1778 NUMA *nafirst, *nalast;
1779 SARRAY *sa;
1780 SEL *sel;
1781 SELA *sela;
1782 
1783  PROCNAME("selaCreateFromFile");
1784 
1785  if (!filename)
1786  return (SELA *)ERROR_PTR("filename not defined", procName, NULL);
1787 
1788  filestr = (char *)l_binaryRead(filename, &nbytes);
1789  sa = sarrayCreateLinesFromString(filestr, 1);
1790  LEPT_FREE(filestr);
1791  n = sarrayGetCount(sa);
1792  sela = selaCreate(0);
1793 
1794  /* Find the start and end lines for each Sel.
1795  * We allow the "blank" lines to be null strings or
1796  * to have standard whitespace (' ','\t',\'n') or be '#'. */
1797  nafirst = numaCreate(0);
1798  nalast = numaCreate(0);
1799  insel = FALSE;
1800  for (i = 0; i < n; i++) {
1801  line = sarrayGetString(sa, i, L_NOCOPY);
1802  if (!insel &&
1803  (line[0] != '\0' && line[0] != ' ' &&
1804  line[0] != '\t' && line[0] != '\n' && line[0] != '#')) {
1805  numaAddNumber(nafirst, i);
1806  insel = TRUE;
1807  continue;
1808  }
1809  if (insel &&
1810  (line[0] == '\0' || line[0] == ' ' ||
1811  line[0] == '\t' || line[0] == '\n' || line[0] == '#')) {
1812  numaAddNumber(nalast, i - 1);
1813  insel = FALSE;
1814  continue;
1815  }
1816  }
1817  if (insel) /* fell off the end of the file */
1818  numaAddNumber(nalast, n - 1);
1819 
1820  /* Extract sels */
1821  nsel = numaGetCount(nafirst);
1822  for (i = 0; i < nsel; i++) {
1823  numaGetIValue(nafirst, i, &first);
1824  numaGetIValue(nalast, i, &last);
1825  if ((sel = selCreateFromSArray(sa, first, last)) == NULL) {
1826  lept_stderr("Error reading sel from %d to %d\n", first, last);
1827  selaDestroy(&sela);
1828  sarrayDestroy(&sa);
1829  numaDestroy(&nafirst);
1830  numaDestroy(&nalast);
1831  return (SELA *)ERROR_PTR("bad sela file", procName, NULL);
1832  }
1833  selaAddSel(sela, sel, NULL, 0);
1834  }
1835 
1836  numaDestroy(&nafirst);
1837  numaDestroy(&nalast);
1838  sarrayDestroy(&sa);
1839  return sela;
1840 }
1841 
1842 
1873 static SEL *
1875  l_int32 first,
1876  l_int32 last)
1877 {
1878 char ch;
1879 char *name, *line;
1880 l_int32 n, len, i, w, h, y, x;
1881 SEL *sel;
1882 
1883  PROCNAME("selCreateFromSArray");
1884 
1885  if (!sa)
1886  return (SEL *)ERROR_PTR("sa not defined", procName, NULL);
1887  n = sarrayGetCount(sa);
1888  if (first < 0 || first >= n || last <= first || last >= n)
1889  return (SEL *)ERROR_PTR("invalid range", procName, NULL);
1890 
1891  name = sarrayGetString(sa, first, L_NOCOPY);
1892  h = last - first;
1893  line = sarrayGetString(sa, first + 1, L_NOCOPY);
1894  len = strlen(line);
1895  if (line[0] != '"' || line[len - 1] != '"')
1896  return (SEL *)ERROR_PTR("invalid format", procName, NULL);
1897  w = len - 2;
1898  if ((sel = selCreate(h, w, name)) == NULL)
1899  return (SEL *)ERROR_PTR("sel not made", procName, NULL);
1900  for (i = first + 1; i <= last; i++) {
1901  line = sarrayGetString(sa, i, L_NOCOPY);
1902  y = i - first - 1;
1903  for (x = 0; x < w; ++x) {
1904  ch = line[x + 1]; /* skip the leading double-quote */
1905  switch (ch)
1906  {
1907  case 'X':
1908  selSetOrigin(sel, y, x); /* set origin and hit */
1909  /* fall through */
1910  case 'x':
1911  selSetElement(sel, y, x, SEL_HIT);
1912  break;
1913 
1914  case 'O':
1915  selSetOrigin(sel, y, x); /* set origin and miss */
1916  /* fall through */
1917  case 'o':
1918  selSetElement(sel, y, x, SEL_MISS);
1919  break;
1920 
1921  case 'C':
1922  selSetOrigin(sel, y, x); /* set origin and don't-care */
1923  /* fall through */
1924  case ' ':
1925  selSetElement(sel, y, x, SEL_DONT_CARE);
1926  break;
1927 
1928  default:
1929  selDestroy(&sel);
1930  return (SEL *)ERROR_PTR("unknown char", procName, NULL);
1931  }
1932  }
1933  }
1934 
1935  return sel;
1936 }
1937 
1938 
1939 /*----------------------------------------------------------------------*
1940  * Making hit-only SELs from Pta and Pix *
1941  *----------------------------------------------------------------------*/
1955 SEL *
1957  l_int32 cy,
1958  l_int32 cx,
1959  const char *name)
1960 {
1961 l_int32 i, n, x, y, w, h;
1962 BOX *box;
1963 SEL *sel;
1964 
1965  PROCNAME("selCreateFromPta");
1966 
1967  if (!pta)
1968  return (SEL *)ERROR_PTR("pta not defined", procName, NULL);
1969  if (cy < 0 || cx < 0)
1970  return (SEL *)ERROR_PTR("(cy, cx) not both >= 0", procName, NULL);
1971  n = ptaGetCount(pta);
1972  if (n == 0)
1973  return (SEL *)ERROR_PTR("no pts in pta", procName, NULL);
1974 
1975  box = ptaGetBoundingRegion(pta);
1976  boxGetGeometry(box, &x, &y, &w, &h);
1977  boxDestroy(&box);
1978  if (x < 0 || y < 0)
1979  return (SEL *)ERROR_PTR("not all x and y >= 0", procName, NULL);
1980 
1981  sel = selCreate(y + h, x + w, name);
1982  selSetOrigin(sel, cy, cx);
1983  for (i = 0; i < n; i++) {
1984  ptaGetIPt(pta, i, &x, &y);
1985  selSetElement(sel, y, x, SEL_HIT);
1986  }
1987 
1988  return sel;
1989 }
1990 
1991 
2007 SEL *
2009  l_int32 cy,
2010  l_int32 cx,
2011  const char *name)
2012 {
2013 SEL *sel;
2014 l_int32 i, j, w, h, d, nhits;
2015 l_uint32 val;
2016 
2017  PROCNAME("selCreateFromPix");
2018 
2019  if (!pix)
2020  return (SEL *)ERROR_PTR("pix not defined", procName, NULL);
2021  if (cy < 0 || cx < 0)
2022  return (SEL *)ERROR_PTR("(cy, cx) not both >= 0", procName, NULL);
2023  pixGetDimensions(pix, &w, &h, &d);
2024  if (d != 1)
2025  return (SEL *)ERROR_PTR("pix not 1 bpp", procName, NULL);
2026  if (w > MaxPixTemplateSize || h > MaxPixTemplateSize) {
2027  L_ERROR("pix template too large (w = %d, h = %d)\n", procName, w, h);
2028  return NULL;
2029  }
2030  pixCountPixels(pix, &nhits, NULL);
2031  if (nhits > MaxPixTemplateHits) {
2032  L_ERROR("too many hits (%d) in pix template\n", procName, nhits);
2033  return NULL;
2034  }
2035 
2036  sel = selCreate(h, w, name);
2037  selSetOrigin(sel, cy, cx);
2038  for (i = 0; i < h; i++) {
2039  for (j = 0; j < w; j++) {
2040  pixGetPixel(pix, j, i, &val);
2041  if (val)
2042  selSetElement(sel, i, j, SEL_HIT);
2043  }
2044  }
2045 
2046  return sel;
2047 }
2048 
2049 
2050 /*----------------------------------------------------------------------*
2051  * Making hit-miss sels from color Pix and image files *
2052  *----------------------------------------------------------------------*/
2067 SEL *
2068 selReadFromColorImage(const char *pathname)
2069 {
2070 PIX *pix;
2071 SEL *sel;
2072 char *basename, *selname;
2073 
2074  PROCNAME("selReadFromColorImage");
2075 
2076  splitPathAtExtension (pathname, &basename, NULL);
2077  splitPathAtDirectory (basename, NULL, &selname);
2078  LEPT_FREE(basename);
2079 
2080  if ((pix = pixRead(pathname)) == NULL) {
2081  LEPT_FREE(selname);
2082  return (SEL *)ERROR_PTR("pix not returned", procName, NULL);
2083  }
2084  if ((sel = selCreateFromColorPix(pix, selname)) == NULL)
2085  L_ERROR("sel not made\n", procName);
2086 
2087  LEPT_FREE(selname);
2088  pixDestroy(&pix);
2089  return sel;
2090 }
2091 
2092 
2116 SEL *
2118  const char *selname)
2119 {
2120 PIXCMAP *cmap;
2121 SEL *sel;
2122 l_int32 hascolor, num_origins, nohits;
2123 l_int32 w, h, d, i, j, red, green, blue;
2124 l_uint32 pixval;
2125 
2126  PROCNAME("selCreateFromColorPix");
2127 
2128  if (!pixs)
2129  return (SEL *)ERROR_PTR("pixs not defined", procName, NULL);
2130 
2131  hascolor = FALSE;
2132  cmap = pixGetColormap(pixs);
2133  if (cmap)
2134  pixcmapHasColor(cmap, &hascolor);
2135  pixGetDimensions(pixs, &w, &h, &d);
2136  if (hascolor == FALSE && d != 32)
2137  return (SEL *)ERROR_PTR("pixs has no color", procName, NULL);
2138 
2139  if ((sel = selCreate (h, w, NULL)) == NULL)
2140  return (SEL *)ERROR_PTR ("sel not made", procName, NULL);
2141  selSetOrigin (sel, h / 2, w / 2); /* default */
2142  selSetName(sel, selname);
2143 
2144  num_origins = 0;
2145  nohits = TRUE;
2146  for (i = 0; i < h; i++) {
2147  for (j = 0; j < w; j++) {
2148  pixGetPixel (pixs, j, i, &pixval);
2149 
2150  if (cmap) {
2151  pixcmapGetColor (cmap, pixval, &red, &green, &blue);
2152  } else {
2153  red = GET_DATA_BYTE (&pixval, COLOR_RED);
2154  green = GET_DATA_BYTE (&pixval, COLOR_GREEN);
2155  blue = GET_DATA_BYTE (&pixval, COLOR_BLUE);
2156  }
2157 
2158  if (red < 255 && green < 255 && blue < 255) {
2159  num_origins++;
2160  if (num_origins == 1) /* first one found */
2161  selSetOrigin (sel, i, j);
2162  if (num_origins == 2)
2163  L_WARNING("multiple origins in sel image\n", procName);
2164  }
2165  if (!red && green && !blue) {
2166  nohits = FALSE;
2167  selSetElement (sel, i, j, SEL_HIT);
2168  } else if (red && !green && !blue) {
2169  selSetElement (sel, i, j, SEL_MISS);
2170  } else if (red && green && blue) {
2171  selSetElement (sel, i, j, SEL_DONT_CARE);
2172  } else {
2173  selDestroy(&sel);
2174  return (SEL *)ERROR_PTR("invalid color", procName, NULL);
2175  }
2176  }
2177  }
2178 
2179  if (nohits) {
2180  selDestroy(&sel);
2181  return (SEL *)ERROR_PTR("no hits in sel", procName, NULL);
2182  }
2183  return sel;
2184 }
2185 
2186 
2202 SELA *
2204  SARRAY *sa)
2205 {
2206 char *str;
2207 l_int32 i, n;
2208 PIX *pix;
2209 SEL *sel;
2210 SELA *sela;
2211 
2212  PROCNAME("selaCreateFromColorPixa");
2213 
2214  if (!pixa)
2215  return (SELA *)ERROR_PTR("pixa not defined", procName, NULL);
2216  if (!sa)
2217  return (SELA *)ERROR_PTR("sa of sel names not defined", procName, NULL);
2218 
2219  n = pixaGetCount(pixa);
2220  if ((sela = selaCreate(n)) == NULL)
2221  return (SELA *)ERROR_PTR("sela not allocated", procName, NULL);
2222  for (i = 0; i < n; i++) {
2223  pix = pixaGetPix(pixa, i, L_CLONE);
2224  str = sarrayGetString(sa, i, L_NOCOPY);
2225  sel = selCreateFromColorPix(pix, str);
2226  selaAddSel(sela, sel, NULL, L_INSERT);
2227  pixDestroy(&pix);
2228  }
2229  return sela;
2230 }
2231 
2232 
2233 /*----------------------------------------------------------------------*
2234  * Printable display of sel *
2235  *----------------------------------------------------------------------*/
2254 PIX *
2256  l_int32 size,
2257  l_int32 gthick)
2258 {
2259 l_int32 i, j, w, h, sx, sy, cx, cy, type, width;
2260 l_int32 radius1, radius2, shift1, shift2, x0, y0;
2261 PIX *pixd, *pix2, *pixh, *pixm, *pixorig;
2262 PTA *pta1, *pta2, *pta1t, *pta2t;
2263 
2264  PROCNAME("selDisplayInPix");
2265 
2266  if (!sel)
2267  return (PIX *)ERROR_PTR("sel not defined", procName, NULL);
2268  if (size < 13) {
2269  L_WARNING("size < 13; setting to 13\n", procName);
2270  size = 13;
2271  }
2272  if (size % 2 == 0)
2273  size++;
2274  if (gthick < 2) {
2275  L_WARNING("grid thickness < 2; setting to 2\n", procName);
2276  gthick = 2;
2277  }
2278  selGetParameters(sel, &sy, &sx, &cy, &cx);
2279  w = size * sx + gthick * (sx + 1);
2280  h = size * sy + gthick * (sy + 1);
2281  pixd = pixCreate(w, h, 1);
2282 
2283  /* Generate grid lines */
2284  for (i = 0; i <= sy; i++)
2285  pixRenderLine(pixd, 0, gthick / 2 + i * (size + gthick),
2286  w - 1, gthick / 2 + i * (size + gthick),
2287  gthick, L_SET_PIXELS);
2288  for (j = 0; j <= sx; j++)
2289  pixRenderLine(pixd, gthick / 2 + j * (size + gthick), 0,
2290  gthick / 2 + j * (size + gthick), h - 1,
2291  gthick, L_SET_PIXELS);
2292 
2293  /* Generate hit and miss patterns */
2294  radius1 = (l_int32)(0.85 * ((size - 1) / 2.0) + 0.5); /* of hit */
2295  radius2 = (l_int32)(0.65 * ((size - 1) / 2.0) + 0.5); /* of inner miss */
2296  pta1 = generatePtaFilledCircle(radius1);
2297  pta2 = generatePtaFilledCircle(radius2);
2298  shift1 = (size - 1) / 2 - radius1; /* center circle in square */
2299  shift2 = (size - 1) / 2 - radius2;
2300  pta1t = ptaTransform(pta1, shift1, shift1, 1.0, 1.0);
2301  pta2t = ptaTransform(pta2, shift2, shift2, 1.0, 1.0);
2302  pixh = pixGenerateFromPta(pta1t, size, size); /* hits */
2303  pix2 = pixGenerateFromPta(pta2t, size, size);
2304  pixm = pixSubtract(NULL, pixh, pix2);
2305 
2306  /* Generate crossed lines for origin pattern */
2307  pixorig = pixCreate(size, size, 1);
2308  width = size / 8;
2309  pixRenderLine(pixorig, size / 2, (l_int32)(0.12 * size),
2310  size / 2, (l_int32)(0.88 * size),
2311  width, L_SET_PIXELS);
2312  pixRenderLine(pixorig, (l_int32)(0.15 * size), size / 2,
2313  (l_int32)(0.85 * size), size / 2,
2314  width, L_FLIP_PIXELS);
2315  pixRasterop(pixorig, size / 2 - width, size / 2 - width,
2316  2 * width, 2 * width, PIX_NOT(PIX_DST), NULL, 0, 0);
2317 
2318  /* Specialize origin pattern for this sel */
2319  selGetTypeAtOrigin(sel, &type);
2320  if (type == SEL_HIT)
2321  pixXor(pixorig, pixorig, pixh);
2322  else if (type == SEL_MISS)
2323  pixXor(pixorig, pixorig, pixm);
2324 
2325  /* Paste the patterns in */
2326  y0 = gthick;
2327  for (i = 0; i < sy; i++) {
2328  x0 = gthick;
2329  for (j = 0; j < sx; j++) {
2330  selGetElement(sel, i, j, &type);
2331  if (i == cy && j == cx) /* origin */
2332  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixorig, 0, 0);
2333  else if (type == SEL_HIT)
2334  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixh, 0, 0);
2335  else if (type == SEL_MISS)
2336  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixm, 0, 0);
2337  x0 += size + gthick;
2338  }
2339  y0 += size + gthick;
2340  }
2341 
2342  pixDestroy(&pix2);
2343  pixDestroy(&pixh);
2344  pixDestroy(&pixm);
2345  pixDestroy(&pixorig);
2346  ptaDestroy(&pta1);
2347  ptaDestroy(&pta1t);
2348  ptaDestroy(&pta2);
2349  ptaDestroy(&pta2t);
2350  return pixd;
2351 }
2352 
2353 
2372 PIX *
2374  l_int32 size,
2375  l_int32 gthick,
2376  l_int32 spacing,
2377  l_int32 ncols)
2378 {
2379 l_int32 nsels, i, w, width;
2380 PIX *pixt, *pixd;
2381 PIXA *pixa;
2382 SEL *sel;
2383 
2384  PROCNAME("selaDisplayInPix");
2385 
2386  if (!sela)
2387  return (PIX *)ERROR_PTR("sela not defined", procName, NULL);
2388  if (size < 13) {
2389  L_WARNING("size < 13; setting to 13\n", procName);
2390  size = 13;
2391  }
2392  if (size % 2 == 0)
2393  size++;
2394  if (gthick < 2) {
2395  L_WARNING("grid thickness < 2; setting to 2\n", procName);
2396  gthick = 2;
2397  }
2398  if (spacing < 5) {
2399  L_WARNING("spacing < 5; setting to 5\n", procName);
2400  spacing = 5;
2401  }
2402 
2403  /* Accumulate the pix of each sel */
2404  nsels = selaGetCount(sela);
2405  pixa = pixaCreate(nsels);
2406  for (i = 0; i < nsels; i++) {
2407  sel = selaGetSel(sela, i);
2408  pixt = selDisplayInPix(sel, size, gthick);
2409  pixaAddPix(pixa, pixt, L_INSERT);
2410  }
2411 
2412  /* Find the tiled output width, using just the first
2413  * ncols pix in the pixa. If all pix have the same width,
2414  * they will align properly in columns. */
2415  width = 0;
2416  ncols = L_MIN(nsels, ncols);
2417  for (i = 0; i < ncols; i++) {
2418  pixt = pixaGetPix(pixa, i, L_CLONE);
2419  pixGetDimensions(pixt, &w, NULL, NULL);
2420  width += w;
2421  pixDestroy(&pixt);
2422  }
2423  width += (ncols + 1) * spacing; /* add spacing all around as well */
2424 
2425  pixd = pixaDisplayTiledInRows(pixa, 1, width, 1.0, 0, spacing, 0);
2426  pixaDestroy(&pixa);
2427  return pixd;
2428 }
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1075
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
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 * generatePtaFilledCircle(l_int32 radius)
generatePtaFilledCircle()
Definition: graphics.c:833
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1132
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:190
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1937
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1688
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtract()
Definition: pix3.c:1753
#define PIX_DST
Definition: pix.h:331
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ COLOR_GREEN
Definition: pix.h:205
@ L_FLIP_PIXELS
Definition: pix.h:774
@ L_SET_PIXELS
Definition: pix.h:772
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_NOCOPY
Definition: pix.h:710
@ L_INSERT
Definition: pix.h:711
#define PIX_SRC
Definition: pix.h:330
#define PIX_NOT(op)
Definition: pix.h:332
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_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
PIX * pixaDisplayTiledInRows(PIXA *pixa, l_int32 outdepth, l_int32 maxwidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledInRows()
Definition: pixafunc2.c:746
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
BOX * ptaGetBoundingRegion(PTA *pta)
ptaGetBoundingRegion()
Definition: ptafunc1.c:444
PIX * pixGenerateFromPta(PTA *pta, l_int32 w, l_int32 h)
pixGenerateFromPta()
Definition: ptafunc1.c:2023
PTA * ptaTransform(PTA *ptas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
ptaTransform()
Definition: ptafunc1.c:740
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:193
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:204
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_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:643
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
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:785
static SEL * selCreateFromSArray(SARRAY *sa, l_int32 first, l_int32 last)
selCreateFromSArray()
Definition: sel1.c:1874
SEL * selCreateFromPta(PTA *pta, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPta()
Definition: sel1.c:1956
l_ok selWrite(const char *fname, SEL *sel)
selWrite()
Definition: sel1.c:1517
PIX * selDisplayInPix(SEL *sel, l_int32 size, l_int32 gthick)
selDisplayInPix()
Definition: sel1.c:2255
l_ok selWriteStream(FILE *fp, SEL *sel)
selWriteStream()
Definition: sel1.c:1546
static const l_int32 InitialPtrArraySize
Definition: sel1.c:151
SARRAY * selaGetSelnames(SELA *sela)
selaGetSelnames()
Definition: sel1.c:1145
SEL * selRead(const char *fname)
selRead()
Definition: sel1.c:1377
l_ok selGetParameters(SEL *sel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
selGetParameters()
Definition: sel1.c:848
SEL * selCreateFromPix(PIX *pix, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPix()
Definition: sel1.c:2008
l_ok getCompositeParameters(l_int32 size, l_int32 *psize1, l_int32 *psize2, char **pnameh1, char **pnameh2, char **pnamev1, char **pnamev2)
getCompositeParameters()
Definition: sel1.c:1101
l_ok selFindMaxTranslations(SEL *sel, l_int32 *pxp, l_int32 *pyp, l_int32 *pxn, l_int32 *pyn)
selFindMaxTranslations()
Definition: sel1.c:1190
SEL * selReadFromColorImage(const char *pathname)
Definition: sel1.c:2068
l_ok selSetName(SEL *sel, const char *name)
selSetName()
Definition: sel1.c:708
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
void selaDestroy(SELA **psela)
selaDestroy()
Definition: sel1.c:276
l_ok selaFindSelByName(SELA *sela, const char *name, l_int32 *pindex, SEL **psel)
selaFindSelByName()
Definition: sel1.c:730
SEL * selCopy(SEL *sel)
selCopy()
Definition: sel1.c:371
SEL * selCreateComb(l_int32 factor1, l_int32 factor2, l_int32 direction)
selCreateComb()
Definition: sel1.c:462
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
SEL * selRotateOrth(SEL *sel, l_int32 quads)
selRotateOrth()
Definition: sel1.c:1240
void selDestroy(SEL **psel)
selDestroy()
Definition: sel1.c:340
l_int32 ** create2dIntArray(l_int32 sy, l_int32 sx)
create2dIntArray()
Definition: sel1.c:517
SEL * selReadStream(FILE *fp)
selReadStream()
Definition: sel1.c:1406
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
char * selGetName(SEL *sel)
selGetName()
Definition: sel1.c:683
SELA * selaCreateFromColorPixa(PIXA *pixa, SARRAY *sa)
Definition: sel1.c:2203
l_ok selaWrite(const char *fname, SELA *sela)
selaWrite()
Definition: sel1.c:1455
SEL * selaGetSel(SELA *sela, l_int32 i)
selaGetSel()
Definition: sel1.c:662
char * selaGetCombName(SELA *sela, l_int32 size, l_int32 direction)
selaGetCombName()
Definition: sel1.c:974
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
static l_int32 selaExtendArray(SELA *sela)
selaExtendArray()
Definition: sel1.c:609
l_ok selGetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 *ptype)
selGetElement()
Definition: sel1.c:779
l_int32 selaGetCount(SELA *sela)
selaGetCount()
Definition: sel1.c:637
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
SELA * selaReadStream(FILE *fp)
selaReadStream()
Definition: sel1.c:1336
SELA * selaCreateFromFile(const char *filename)
selaCreateFromFile()
Definition: sel1.c:1773
char * selaGetBrickName(SELA *sela, l_int32 hsize, l_int32 vsize)
selaGetBrickName()
Definition: sel1.c:935
SELA * selaRead(const char *fname)
selaRead()
Definition: sel1.c:1307
l_ok selGetTypeAtOrigin(SEL *sel, l_int32 *ptype)
selGetTypeAtOrigin()
Definition: sel1.c:900
char * selPrintToString(SEL *sel)
selPrintToString()
Definition: sel1.c:1698
SEL * selCreateFromColorPix(PIX *pixs, const char *selname)
Definition: sel1.c:2117
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
SELA * selaAddDwaCombs(SELA *sela)
selaAddDwaCombs()
Definition: sel2.c:368
Definition: pix.h:481
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:517
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
char * name
Definition: morph.h:68
l_int32 sy
Definition: morph.h:63
Definition: morph.h:74
struct Sel ** sel
Definition: morph.h:77
l_int32 nalloc
Definition: morph.h:76
l_int32 n
Definition: morph.h:75
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition: utils2.c:345
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2894
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2824
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1302
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352