Leptonica  1.83.1
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  if (n <= 0 || n > MaxPtrArraySize)
257 
258  /* Make array of sel ptrs */
259  sela = (SELA *)LEPT_CALLOC(1, sizeof(SELA));
260  sela->nalloc = n;
261  sela->n = 0;
262  sela->sel = (SEL **)LEPT_CALLOC(n, sizeof(SEL *));
263  return sela;
264 }
265 
266 
273 void
275 {
276 SELA *sela;
277 l_int32 i;
278 
279  if (!psela) return;
280  if ((sela = *psela) == NULL)
281  return;
282 
283  for (i = 0; i < sela->n; i++)
284  selDestroy(&sela->sel[i]);
285  LEPT_FREE(sela->sel);
286  LEPT_FREE(sela);
287  *psela = NULL;
288 }
289 
290 
307 SEL *
308 selCreate(l_int32 height,
309  l_int32 width,
310  const char *name)
311 {
312 SEL *sel;
313 
314  sel = (SEL *)LEPT_CALLOC(1, sizeof(SEL));
315  if (name)
316  sel->name = stringNew(name);
317  sel->sy = height;
318  sel->sx = width;
319  if ((sel->data = create2dIntArray(height, width)) == NULL) {
320  LEPT_FREE(sel->name);
321  LEPT_FREE(sel);
322  return (SEL *)ERROR_PTR("data not allocated", __func__, NULL);
323  }
324 
325  return sel;
326 }
327 
328 
335 void
336 selDestroy(SEL **psel)
337 {
338 l_int32 i;
339 SEL *sel;
340 
341  if (psel == NULL) {
342  L_WARNING("ptr address is NULL!\n", __func__);
343  return;
344  }
345  if ((sel = *psel) == NULL)
346  return;
347 
348  for (i = 0; i < sel->sy; i++)
349  LEPT_FREE(sel->data[i]);
350  LEPT_FREE(sel->data);
351  if (sel->name)
352  LEPT_FREE(sel->name);
353  LEPT_FREE(sel);
354  *psel = NULL;
355 }
356 
357 
364 SEL *
365 selCopy(SEL *sel)
366 {
367 l_int32 sx, sy, cx, cy, i, j;
368 SEL *csel;
369 
370  if (!sel)
371  return (SEL *)ERROR_PTR("sel not defined", __func__, NULL);
372 
373  csel = (SEL *)LEPT_CALLOC(1, sizeof(SEL));
374  selGetParameters(sel, &sy, &sx, &cy, &cx);
375  csel->sy = sy;
376  csel->sx = sx;
377  csel->cy = cy;
378  csel->cx = cx;
379 
380  if ((csel->data = create2dIntArray(sy, sx)) == NULL) {
381  LEPT_FREE(csel);
382  return (SEL *)ERROR_PTR("sel data not made", __func__, NULL);
383  }
384 
385  for (i = 0; i < sy; i++)
386  for (j = 0; j < sx; j++)
387  csel->data[i][j] = sel->data[i][j];
388 
389  if (sel->name)
390  csel->name = stringNew(sel->name);
391 
392  return csel;
393 }
394 
395 
409 SEL *
410 selCreateBrick(l_int32 h,
411  l_int32 w,
412  l_int32 cy,
413  l_int32 cx,
414  l_int32 type)
415 {
416 l_int32 i, j;
417 SEL *sel;
418 
419  if (h <= 0 || w <= 0)
420  return (SEL *)ERROR_PTR("h and w must both be > 0", __func__, NULL);
421  if (type != SEL_HIT && type != SEL_MISS && type != SEL_DONT_CARE)
422  return (SEL *)ERROR_PTR("invalid sel element type", __func__, NULL);
423 
424  if ((sel = selCreate(h, w, NULL)) == NULL)
425  return (SEL *)ERROR_PTR("sel not made", __func__, NULL);
426  selSetOrigin(sel, cy, cx);
427  for (i = 0; i < h; i++)
428  for (j = 0; j < w; j++)
429  sel->data[i][j] = type;
430 
431  return sel;
432 }
433 
434 
451 SEL *
452 selCreateComb(l_int32 factor1,
453  l_int32 factor2,
454  l_int32 direction)
455 {
456 l_int32 i, size, z;
457 SEL *sel;
458 
459  if (factor1 < 1 || factor2 < 1)
460  return (SEL *)ERROR_PTR("factors must be >= 1", __func__, NULL);
461  if (direction != L_HORIZ && direction != L_VERT)
462  return (SEL *)ERROR_PTR("invalid direction", __func__, NULL);
463 
464  size = factor1 * factor2;
465  if (direction == L_HORIZ) {
466  if ((sel = selCreate(1, size, NULL)) == NULL)
467  return (SEL *)ERROR_PTR("horiz sel not made", __func__, NULL);
468  selSetOrigin(sel, 0, size / 2);
469  } else {
470  if ((sel = selCreate(size, 1, NULL)) == NULL)
471  return (SEL *)ERROR_PTR("vert sel not made", __func__, NULL);
472  selSetOrigin(sel, size / 2, 0);
473  }
474 
475  /* Lay down the elements of the comb */
476  for (i = 0; i < factor2; i++) {
477  z = factor1 / 2 + i * factor1;
478 /* lept_stderr("i = %d, factor1 = %d, factor2 = %d, z = %d\n",
479  i, factor1, factor2, z); */
480  if (direction == L_HORIZ)
481  selSetElement(sel, 0, z, SEL_HIT);
482  else
483  selSetElement(sel, z, 0, SEL_HIT);
484  }
485 
486  return sel;
487 }
488 
489 
504 l_int32 **
505 create2dIntArray(l_int32 sy,
506  l_int32 sx)
507 {
508 l_int32 i;
509 l_int32 **array;
510 
511  if (sx <= 0 || sx > MaxKernelSize)
512  return (l_int32 **)ERROR_PTR("sx out of bounds", __func__, NULL);
513  if (sy <= 0 || sy > MaxKernelSize)
514  return (l_int32 **)ERROR_PTR("sy out of bounds", __func__, NULL);
515 
516  array = (l_int32 **)LEPT_CALLOC(sy, sizeof(l_int32 *));
517  for (i = 0; i < sy; i++)
518  array[i] = (l_int32 *)LEPT_CALLOC(sx, sizeof(l_int32));
519  return array;
520 }
521 
522 
523 /*------------------------------------------------------------------------*
524  * Extension of sela *
525  *------------------------------------------------------------------------*/
544 l_ok
546  SEL *sel,
547  const char *selname,
548  l_int32 copyflag)
549 {
550 l_int32 n;
551 SEL *csel;
552 
553  if (!sela)
554  return ERROR_INT("sela not defined", __func__, 1);
555  if (!sel)
556  return ERROR_INT("sel not defined", __func__, 1);
557  if (!sel->name && !selname)
558  return ERROR_INT("added sel must have name", __func__, 1);
559  if (copyflag != L_INSERT && copyflag != L_COPY)
560  return ERROR_INT("invalid copyflag", __func__, 1);
561 
562  if (copyflag == L_COPY) {
563  if ((csel = selCopy(sel)) == NULL)
564  return ERROR_INT("csel not made", __func__, 1);
565  } else { /* copyflag == L_INSERT */
566  csel = sel;
567  }
568  if (!csel->name)
569  csel->name = stringNew(selname);
570 
571  n = selaGetCount(sela);
572  if (n >= sela->nalloc) {
573  if (selaExtendArray(sela)) {
574  if (copyflag != L_INSERT)
575  selDestroy(&csel);
576  return ERROR_INT("extension failed", __func__, 1);
577  }
578  }
579 
580  sela->sel[n] = csel;
581  sela->n++;
582  return 0;
583 }
584 
585 
592 static l_int32
594 {
595  if (!sela)
596  return ERROR_INT("sela not defined", __func__, 1);
597 
598  if ((sela->sel = (SEL **)reallocNew((void **)&sela->sel,
599  sizeof(SEL *) * sela->nalloc,
600  2 * sizeof(SEL *) * sela->nalloc)) == NULL)
601  return ERROR_INT("new ptr array not returned", __func__, 1);
602 
603  sela->nalloc = 2 * sela->nalloc;
604  return 0;
605 }
606 
607 
608 
609 /*----------------------------------------------------------------------*
610  * Accessors *
611  *----------------------------------------------------------------------*/
618 l_int32
620 {
621  if (!sela)
622  return ERROR_INT("sela not defined", __func__, 0);
623 
624  return sela->n;
625 }
626 
627 
641 SEL *
643  l_int32 i)
644 {
645  if (!sela)
646  return (SEL *)ERROR_PTR("sela not defined", __func__, NULL);
647 
648  if (i < 0 || i >= sela->n)
649  return (SEL *)ERROR_PTR("invalid index", __func__, NULL);
650  return sela->sel[i];
651 }
652 
653 
660 char *
661 selGetName(SEL *sel)
662 {
663  if (!sel)
664  return (char *)ERROR_PTR("sel not defined", __func__, NULL);
665 
666  return sel->name;
667 }
668 
669 
683 l_ok
684 selSetName(SEL *sel,
685  const char *name)
686 {
687  if (!sel)
688  return ERROR_INT("sel not defined", __func__, 1);
689 
690  return stringReplace(&sel->name, name);
691 }
692 
693 
703 l_ok
705  const char *name,
706  l_int32 *pindex,
707  SEL **psel)
708 {
709 l_int32 i, n;
710 char *sname;
711 SEL *sel;
712 
713  if (pindex) *pindex = -1;
714  if (psel) *psel = NULL;
715 
716  if (!sela)
717  return ERROR_INT("sela not defined", __func__, 1);
718 
719  n = selaGetCount(sela);
720  for (i = 0; i < n; i++)
721  {
722  if ((sel = selaGetSel(sela, i)) == NULL) {
723  L_WARNING("missing sel\n", __func__);
724  continue;
725  }
726 
727  sname = selGetName(sel);
728  if (sname && (!strcmp(name, sname))) {
729  if (pindex)
730  *pindex = i;
731  if (psel)
732  *psel = sel;
733  return 0;
734  }
735  }
736 
737  return 1;
738 }
739 
740 
750 l_ok
751 selGetElement(SEL *sel,
752  l_int32 row,
753  l_int32 col,
754  l_int32 *ptype)
755 {
756  if (!ptype)
757  return ERROR_INT("&type not defined", __func__, 1);
758  *ptype = SEL_DONT_CARE;
759  if (!sel)
760  return ERROR_INT("sel not defined", __func__, 1);
761  if (row < 0 || row >= sel->sy)
762  return ERROR_INT("sel row out of bounds", __func__, 1);
763  if (col < 0 || col >= sel->sx)
764  return ERROR_INT("sel col out of bounds", __func__, 1);
765 
766  *ptype = sel->data[row][col];
767  return 0;
768 }
769 
770 
788 l_ok
789 selSetElement(SEL *sel,
790  l_int32 row,
791  l_int32 col,
792  l_int32 type)
793 {
794  if (!sel)
795  return ERROR_INT("sel not defined", __func__, 1);
796  if (type != SEL_HIT && type != SEL_MISS && type != SEL_DONT_CARE)
797  return ERROR_INT("invalid sel element type", __func__, 1);
798  if (row < 0 || row >= sel->sy)
799  return ERROR_INT("sel row out of bounds", __func__, 1);
800  if (col < 0 || col >= sel->sx)
801  return ERROR_INT("sel col out of bounds", __func__, 1);
802 
803  sel->data[row][col] = type;
804  return 0;
805 }
806 
807 
815 l_ok
817  l_int32 *psy,
818  l_int32 *psx,
819  l_int32 *pcy,
820  l_int32 *pcx)
821 {
822  if (psy) *psy = 0;
823  if (psx) *psx = 0;
824  if (pcy) *pcy = 0;
825  if (pcx) *pcx = 0;
826  if (!sel)
827  return ERROR_INT("sel not defined", __func__, 1);
828  if (psy) *psy = sel->sy;
829  if (psx) *psx = sel->sx;
830  if (pcy) *pcy = sel->cy;
831  if (pcx) *pcx = sel->cx;
832  return 0;
833 }
834 
835 
843 l_ok
844 selSetOrigin(SEL *sel,
845  l_int32 cy,
846  l_int32 cx)
847 {
848  if (!sel)
849  return ERROR_INT("sel not defined", __func__, 1);
850  sel->cy = cy;
851  sel->cx = cx;
852  return 0;
853 }
854 
855 
863 l_ok
865  l_int32 *ptype)
866 {
867 l_int32 sx, sy, cx, cy, i, j;
868 
869  if (!ptype)
870  return ERROR_INT("&type not defined", __func__, 1);
871  *ptype = SEL_DONT_CARE; /* init */
872  if (!sel)
873  return ERROR_INT("sel not defined", __func__, 1);
874 
875  selGetParameters(sel, &sy, &sx, &cy, &cx);
876  for (i = 0; i < sy; i++) {
877  for (j = 0; j < sx; j++) {
878  if (i == cy && j == cx) {
879  selGetElement(sel, i, j, ptype);
880  return 0;
881  }
882  }
883  }
884 
885  return ERROR_INT("sel origin not found", __func__, 1);
886 }
887 
888 
896 char *
898  l_int32 hsize,
899  l_int32 vsize)
900 {
901 l_int32 i, nsels, sx, sy;
902 SEL *sel;
903 
904  if (!sela)
905  return (char *)ERROR_PTR("sela not defined", __func__, NULL);
906 
907  nsels = selaGetCount(sela);
908  for (i = 0; i < nsels; i++) {
909  sel = selaGetSel(sela, i);
910  selGetParameters(sel, &sy, &sx, NULL, NULL);
911  if (hsize == sx && vsize == sy)
912  return stringNew(selGetName(sel));
913  }
914 
915  return (char *)ERROR_PTR("sel not found", __func__, NULL);
916 }
917 
918 
933 char *
935  l_int32 size,
936  l_int32 direction)
937 {
938 char *selname;
939 char combname[256];
940 l_int32 i, nsels, sx, sy, found;
941 SEL *sel;
942 
943  if (!sela)
944  return (char *)ERROR_PTR("sela not defined", __func__, NULL);
945  if (direction != L_HORIZ && direction != L_VERT)
946  return (char *)ERROR_PTR("invalid direction", __func__, NULL);
947 
948  /* Derive the comb name we're looking for */
949  if (direction == L_HORIZ)
950  snprintf(combname, sizeof(combname), "sel_comb_%dh", size);
951  else /* direction == L_VERT */
952  snprintf(combname, sizeof(combname), "sel_comb_%dv", size);
953 
954  found = FALSE;
955  nsels = selaGetCount(sela);
956  for (i = 0; i < nsels; i++) {
957  sel = selaGetSel(sela, i);
958  selGetParameters(sel, &sy, &sx, NULL, NULL);
959  if (sy != 1 && sx != 1) /* 2-D; not a comb */
960  continue;
961  selname = selGetName(sel);
962  if (!strcmp(selname, combname)) {
963  found = TRUE;
964  break;
965  }
966  }
967 
968  if (found)
969  return stringNew(selname);
970  else
971  return (char *)ERROR_PTR("sel not found", __func__, NULL);
972 }
973 
974 
975 /* --------- Function used to generate code in this file ---------- */
976 #if 0
977 static void selaComputeCompositeParameters(const char *fileout);
978 
996 static void
997 selaComputeCompositeParameters(const char *fileout)
998 {
999 char *str, *nameh1, *nameh2, *namev1, *namev2;
1000 char buf[256];
1001 l_int32 size, size1, size2, len;
1002 SARRAY *sa;
1003 SELA *selabasic, *selacomb;
1004 
1005  selabasic = selaAddBasic(NULL);
1006  selacomb = selaAddDwaCombs(NULL);
1007  sa = sarrayCreate(64);
1008  for (size = 2; size < 64; size++) {
1009  selectComposableSizes(size, &size1, &size2);
1010  nameh1 = selaGetBrickName(selabasic, size1, 1);
1011  namev1 = selaGetBrickName(selabasic, 1, size1);
1012  if (size2 > 1) {
1013  nameh2 = selaGetCombName(selacomb, size1 * size2, L_HORIZ);
1014  namev2 = selaGetCombName(selacomb, size1 * size2, L_VERT);
1015  } else {
1016  nameh2 = stringNew("");
1017  namev2 = stringNew("");
1018  }
1019  snprintf(buf, sizeof(buf),
1020  " { %d, %d, %d, \"%s\", \"%s\", \"%s\", \"%s\" },",
1021  size, size1, size2, nameh1, nameh2, namev1, namev2);
1022  sarrayAddString(sa, buf, L_COPY);
1023  LEPT_FREE(nameh1);
1024  LEPT_FREE(nameh2);
1025  LEPT_FREE(namev1);
1026  LEPT_FREE(namev2);
1027  }
1028  str = sarrayToString(sa, 1);
1029  len = strlen(str);
1030  l_binaryWrite(fileout, "w", str, len + 1);
1031  LEPT_FREE(str);
1032  sarrayDestroy(&sa);
1033  selaDestroy(&selabasic);
1034  selaDestroy(&selacomb);
1035 }
1036 #endif
1037 /* -------------------------------------------------------------------- */
1038 
1039 
1058 l_ok
1060  l_int32 *psize1,
1061  l_int32 *psize2,
1062  char **pnameh1,
1063  char **pnameh2,
1064  char **pnamev1,
1065  char **pnamev2)
1066 {
1067 l_int32 index;
1068 
1069  if (psize1) *psize1 = 0;
1070  if (psize2) *psize2 = 0;
1071  if (pnameh1) *pnameh1 = NULL;
1072  if (pnameh2) *pnameh2 = NULL;
1073  if (pnamev1) *pnamev1 = NULL;
1074  if (pnamev2) *pnamev2 = NULL;
1075  if (size < 2 || size > 63)
1076  return ERROR_INT("valid size range is {2 ... 63}", __func__, 1);
1077  index = size - 2;
1078  if (psize1)
1079  *psize1 = comp_parameter_map[index].size1;
1080  if (psize2)
1081  *psize2 = comp_parameter_map[index].size2;
1082  if (pnameh1)
1083  *pnameh1 = stringNew(comp_parameter_map[index].selnameh1);
1084  if (pnameh2)
1085  *pnameh2 = stringNew(comp_parameter_map[index].selnameh2);
1086  if (pnamev1)
1087  *pnamev1 = stringNew(comp_parameter_map[index].selnamev1);
1088  if (pnamev2)
1089  *pnamev2 = stringNew(comp_parameter_map[index].selnamev2);
1090  return 0;
1091 }
1092 
1093 
1100 SARRAY *
1102 {
1103 char *selname;
1104 l_int32 i, n;
1105 SEL *sel;
1106 SARRAY *sa;
1107 
1108  if (!sela)
1109  return (SARRAY *)ERROR_PTR("sela not defined", __func__, NULL);
1110  if ((n = selaGetCount(sela)) == 0)
1111  return (SARRAY *)ERROR_PTR("no sels in sela", __func__, NULL);
1112 
1113  if ((sa = sarrayCreate(n)) == NULL)
1114  return (SARRAY *)ERROR_PTR("sa not made", __func__, NULL);
1115  for (i = 0; i < n; i++) {
1116  sel = selaGetSel(sela, i);
1117  selname = selGetName(sel);
1118  sarrayAddString(sa, selname, L_COPY);
1119  }
1120 
1121  return sa;
1122 }
1123 
1124 
1125 
1126 /*----------------------------------------------------------------------*
1127  * Max translations for erosion and hmt *
1128  *----------------------------------------------------------------------*/
1143 l_ok
1145  l_int32 *pxp,
1146  l_int32 *pyp,
1147  l_int32 *pxn,
1148  l_int32 *pyn)
1149 {
1150 l_int32 sx, sy, cx, cy, i, j;
1151 l_int32 maxxp, maxyp, maxxn, maxyn;
1152 
1153  if (!pxp || !pyp || !pxn || !pyn)
1154  return ERROR_INT("&xp (etc) defined", __func__, 1);
1155  *pxp = *pyp = *pxn = *pyn = 0;
1156  if (!sel)
1157  return ERROR_INT("sel not defined", __func__, 1);
1158  selGetParameters(sel, &sy, &sx, &cy, &cx);
1159 
1160  maxxp = maxyp = maxxn = maxyn = 0;
1161  for (i = 0; i < sy; i++) {
1162  for (j = 0; j < sx; j++) {
1163  if (sel->data[i][j] == 1) {
1164  maxxp = L_MAX(maxxp, cx - j);
1165  maxyp = L_MAX(maxyp, cy - i);
1166  maxxn = L_MAX(maxxn, j - cx);
1167  maxyn = L_MAX(maxyn, i - cy);
1168  }
1169  }
1170  }
1171 
1172  *pxp = maxxp;
1173  *pyp = maxyp;
1174  *pxn = maxxn;
1175  *pyn = maxyn;
1176 
1177  return 0;
1178 }
1179 
1180 
1181 /*----------------------------------------------------------------------*
1182  * Rotation by multiples of 90 degrees *
1183  *----------------------------------------------------------------------*/
1191 SEL *
1192 selRotateOrth(SEL *sel,
1193  l_int32 quads)
1194 {
1195 l_int32 i, j, ni, nj, sx, sy, cx, cy, nsx, nsy, ncx, ncy, type;
1196 SEL *seld;
1197 
1198  if (!sel)
1199  return (SEL *)ERROR_PTR("sel not defined", __func__, NULL);
1200  if (quads < 0 || quads > 4)
1201  return (SEL *)ERROR_PTR("quads not in {0,1,2,3,4}", __func__, NULL);
1202  if (quads == 0 || quads == 4)
1203  return selCopy(sel);
1204 
1205  selGetParameters(sel, &sy, &sx, &cy, &cx);
1206  if (quads == 1) { /* 90 degrees cw */
1207  nsx = sy;
1208  nsy = sx;
1209  ncx = sy - cy - 1;
1210  ncy = cx;
1211  } else if (quads == 2) { /* 180 degrees cw */
1212  nsx = sx;
1213  nsy = sy;
1214  ncx = sx - cx - 1;
1215  ncy = sy - cy - 1;
1216  } else { /* 270 degrees cw */
1217  nsx = sy;
1218  nsy = sx;
1219  ncx = cy;
1220  ncy = sx - cx - 1;
1221  }
1222  seld = selCreateBrick(nsy, nsx, ncy, ncx, SEL_DONT_CARE);
1223  if (sel->name)
1224  seld->name = stringNew(sel->name);
1225 
1226  for (i = 0; i < sy; i++) {
1227  for (j = 0; j < sx; j++) {
1228  selGetElement(sel, i, j, &type);
1229  if (quads == 1) {
1230  ni = j;
1231  nj = sy - i - 1;
1232  } else if (quads == 2) {
1233  ni = sy - i - 1;
1234  nj = sx - j - 1;
1235  } else { /* quads == 3 */
1236  ni = sx - j - 1;
1237  nj = i;
1238  }
1239  selSetElement(seld, ni, nj, type);
1240  }
1241  }
1242 
1243  return seld;
1244 }
1245 
1246 
1247 /*----------------------------------------------------------------------*
1248  * Sela and Sel serialized I/O *
1249  *----------------------------------------------------------------------*/
1256 SELA *
1257 selaRead(const char *fname)
1258 {
1259 FILE *fp;
1260 SELA *sela;
1261 
1262  if (!fname)
1263  return (SELA *)ERROR_PTR("fname not defined", __func__, NULL);
1264 
1265  if ((fp = fopenReadStream(fname)) == NULL)
1266  return (SELA *)ERROR_PTR("stream not opened", __func__, NULL);
1267  if ((sela = selaReadStream(fp)) == NULL) {
1268  fclose(fp);
1269  return (SELA *)ERROR_PTR("sela not returned", __func__, NULL);
1270  }
1271  fclose(fp);
1272 
1273  return sela;
1274 }
1275 
1276 
1283 SELA *
1285 {
1286 l_int32 i, n, version;
1287 SEL *sel;
1288 SELA *sela;
1289 
1290  if (!fp)
1291  return (SELA *)ERROR_PTR("stream not defined", __func__, NULL);
1292 
1293  if (fscanf(fp, "\nSela Version %d\n", &version) != 1)
1294  return (SELA *)ERROR_PTR("not a sela file", __func__, NULL);
1295  if (version != SEL_VERSION_NUMBER)
1296  return (SELA *)ERROR_PTR("invalid sel version", __func__, NULL);
1297  if (fscanf(fp, "Number of Sels = %d\n\n", &n) != 1)
1298  return (SELA *)ERROR_PTR("not a sela file", __func__, NULL);
1299 
1300  if ((sela = selaCreate(n)) == NULL)
1301  return (SELA *)ERROR_PTR("sela not made", __func__, NULL);
1302  sela->nalloc = n;
1303 
1304  for (i = 0; i < n; i++) {
1305  if ((sel = selReadStream(fp)) == NULL) {
1306  selaDestroy(&sela);
1307  return (SELA *)ERROR_PTR("sel not read", __func__, NULL);
1308  }
1309  selaAddSel(sela, sel, NULL, 0);
1310  }
1311 
1312  return sela;
1313 }
1314 
1315 
1322 SEL *
1323 selRead(const char *fname)
1324 {
1325 FILE *fp;
1326 SEL *sel;
1327 
1328  if (!fname)
1329  return (SEL *)ERROR_PTR("fname not defined", __func__, NULL);
1330 
1331  if ((fp = fopenReadStream(fname)) == NULL)
1332  return (SEL *)ERROR_PTR("stream not opened", __func__, NULL);
1333  if ((sel = selReadStream(fp)) == NULL) {
1334  fclose(fp);
1335  return (SEL *)ERROR_PTR("sela not returned", __func__, NULL);
1336  }
1337  fclose(fp);
1338 
1339  return sel;
1340 }
1341 
1342 
1349 SEL *
1350 selReadStream(FILE *fp)
1351 {
1352 char selname[256];
1353 char linebuf[256];
1354 l_int32 sy, sx, cy, cx, i, j, version, ignore;
1355 SEL *sel;
1356 
1357  if (!fp)
1358  return (SEL *)ERROR_PTR("stream not defined", __func__, NULL);
1359 
1360  if (fscanf(fp, " Sel Version %d\n", &version) != 1)
1361  return (SEL *)ERROR_PTR("not a sel file", __func__, NULL);
1362  if (version != SEL_VERSION_NUMBER)
1363  return (SEL *)ERROR_PTR("invalid sel version", __func__, NULL);
1364 
1365  if (fgets(linebuf, sizeof(linebuf), fp) == NULL)
1366  return (SEL *)ERROR_PTR("error reading into linebuf", __func__, NULL);
1367  sscanf(linebuf, " ------ %200s ------", selname);
1368 
1369  if (fscanf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n",
1370  &sy, &sx, &cy, &cx) != 4)
1371  return (SEL *)ERROR_PTR("dimensions not read", __func__, NULL);
1372 
1373  if ((sel = selCreate(sy, sx, selname)) == NULL)
1374  return (SEL *)ERROR_PTR("sel not made", __func__, NULL);
1375  selSetOrigin(sel, cy, cx);
1376 
1377  for (i = 0; i < sy; i++) {
1378  ignore = fscanf(fp, " ");
1379  for (j = 0; j < sx; j++)
1380  ignore = fscanf(fp, "%1d", &sel->data[i][j]);
1381  ignore = fscanf(fp, "\n");
1382  }
1383  ignore = fscanf(fp, "\n");
1384 
1385  return sel;
1386 }
1387 
1388 
1396 l_ok
1397 selaWrite(const char *fname,
1398  SELA *sela)
1399 {
1400 FILE *fp;
1401 
1402  if (!fname)
1403  return ERROR_INT("fname not defined", __func__, 1);
1404  if (!sela)
1405  return ERROR_INT("sela not defined", __func__, 1);
1406 
1407  if ((fp = fopenWriteStream(fname, "wb")) == NULL)
1408  return ERROR_INT("stream not opened", __func__, 1);
1409  selaWriteStream(fp, sela);
1410  fclose(fp);
1411 
1412  return 0;
1413 }
1414 
1415 
1423 l_ok
1425  SELA *sela)
1426 {
1427 l_int32 i, n;
1428 SEL *sel;
1429 
1430  if (!fp)
1431  return ERROR_INT("stream not defined", __func__, 1);
1432  if (!sela)
1433  return ERROR_INT("sela not defined", __func__, 1);
1434 
1435  n = selaGetCount(sela);
1436  fprintf(fp, "\nSela Version %d\n", SEL_VERSION_NUMBER);
1437  fprintf(fp, "Number of Sels = %d\n\n", n);
1438  for (i = 0; i < n; i++) {
1439  if ((sel = selaGetSel(sela, i)) == NULL)
1440  continue;
1441  selWriteStream(fp, sel);
1442  }
1443  return 0;
1444 }
1445 
1446 
1454 l_ok
1455 selWrite(const char *fname,
1456  SEL *sel)
1457 {
1458 FILE *fp;
1459 
1460  if (!fname)
1461  return ERROR_INT("fname not defined", __func__, 1);
1462  if (!sel)
1463  return ERROR_INT("sel not defined", __func__, 1);
1464 
1465  if ((fp = fopenWriteStream(fname, "wb")) == NULL)
1466  return ERROR_INT("stream not opened", __func__, 1);
1467  selWriteStream(fp, sel);
1468  fclose(fp);
1469 
1470  return 0;
1471 }
1472 
1473 
1481 l_ok
1483  SEL *sel)
1484 {
1485 l_int32 sx, sy, cx, cy, i, j;
1486 
1487  if (!fp)
1488  return ERROR_INT("stream not defined", __func__, 1);
1489  if (!sel)
1490  return ERROR_INT("sel not defined", __func__, 1);
1491  selGetParameters(sel, &sy, &sx, &cy, &cx);
1492 
1493  fprintf(fp, " Sel Version %d\n", SEL_VERSION_NUMBER);
1494  fprintf(fp, " ------ %s ------\n", selGetName(sel));
1495  fprintf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n", sy, sx, cy, cx);
1496  for (i = 0; i < sy; i++) {
1497  fprintf(fp, " ");
1498  for (j = 0; j < sx; j++)
1499  fprintf(fp, "%d", sel->data[i][j]);
1500  fprintf(fp, "\n");
1501  }
1502  fprintf(fp, "\n");
1503 
1504  return 0;
1505 }
1506 
1507 
1508 /*----------------------------------------------------------------------*
1509  * Building custom hit-miss sels from compiled strings *
1510  *----------------------------------------------------------------------*/
1540 SEL *
1541 selCreateFromString(const char *text,
1542  l_int32 h,
1543  l_int32 w,
1544  const char *name)
1545 {
1546 SEL *sel;
1547 l_int32 y, x, norig;
1548 char ch;
1549 
1550  if (!text || text[0] == '\0')
1551  return (SEL *)ERROR_PTR("text undefined or empty", __func__, NULL);
1552  if (h < 1)
1553  return (SEL *)ERROR_PTR("height must be > 0", __func__, NULL);
1554  if (w < 1)
1555  return (SEL *)ERROR_PTR("width must be > 0", __func__, NULL);
1556  if (strlen(text) != (size_t)w * h)
1557  return (SEL *)ERROR_PTR("text size != w * h", __func__, NULL);
1558 
1559  sel = selCreate(h, w, name);
1560  norig = 0;
1561  for (y = 0; y < h; ++y) {
1562  for (x = 0; x < w; ++x) {
1563  ch = *(text++);
1564  switch (ch)
1565  {
1566  case 'X':
1567  norig++;
1568  selSetOrigin(sel, y, x);
1569  /* fall through */
1570  case 'x':
1571  selSetElement(sel, y, x, SEL_HIT);
1572  break;
1573 
1574  case 'O':
1575  norig++;
1576  selSetOrigin(sel, y, x);
1577  /* fall through */
1578  case 'o':
1579  selSetElement(sel, y, x, SEL_MISS);
1580  break;
1581 
1582  case 'C':
1583  norig++;
1584  selSetOrigin(sel, y, x);
1585  /* fall through */
1586  case ' ':
1587  selSetElement(sel, y, x, SEL_DONT_CARE);
1588  break;
1589 
1590  case '\n':
1591  /* ignored */
1592  continue;
1593 
1594  default:
1595  selDestroy(&sel);
1596  return (SEL *)ERROR_PTR("unknown char", __func__, NULL);
1597  }
1598  }
1599  }
1600  if (norig != 1) {
1601  L_ERROR("Exactly one origin must be specified; this string has %d\n",
1602  __func__, norig);
1603  selDestroy(&sel);
1604  }
1605 
1606  return sel;
1607 }
1608 
1609 
1629 char *
1631 {
1632 char is_center;
1633 char *str, *strptr;
1634 l_int32 type;
1635 l_int32 sx, sy, cx, cy, x, y;
1636 
1637  if (!sel)
1638  return (char *)ERROR_PTR("sel not defined", __func__, NULL);
1639 
1640  selGetParameters(sel, &sy, &sx, &cy, &cx);
1641  if ((str = (char *)LEPT_CALLOC(1, sy * (sx + 1) + 1)) == NULL)
1642  return (char *)ERROR_PTR("calloc fail for str", __func__, NULL);
1643  strptr = str;
1644 
1645  for (y = 0; y < sy; ++y) {
1646  for (x = 0; x < sx; ++x) {
1647  selGetElement(sel, y, x, &type);
1648  is_center = (x == cx && y == cy);
1649  switch (type) {
1650  case SEL_HIT:
1651  *(strptr++) = is_center ? 'X' : 'x';
1652  break;
1653  case SEL_MISS:
1654  *(strptr++) = is_center ? 'O' : 'o';
1655  break;
1656  case SEL_DONT_CARE:
1657  *(strptr++) = is_center ? 'C' : ' ';
1658  break;
1659  }
1660  }
1661  *(strptr++) = '\n';
1662  }
1663 
1664  return str;
1665 }
1666 
1667 
1668 /*----------------------------------------------------------------------*
1669  * Building custom hit-miss sels from a simple file format *
1670  *----------------------------------------------------------------------*/
1702 SELA *
1703 selaCreateFromFile(const char *filename)
1704 {
1705 char *filestr, *line;
1706 l_int32 i, n, first, last, nsel, insel;
1707 size_t nbytes;
1708 NUMA *nafirst, *nalast;
1709 SARRAY *sa;
1710 SEL *sel;
1711 SELA *sela;
1712 
1713  if (!filename)
1714  return (SELA *)ERROR_PTR("filename not defined", __func__, NULL);
1715 
1716  filestr = (char *)l_binaryRead(filename, &nbytes);
1717  sa = sarrayCreateLinesFromString(filestr, 1);
1718  LEPT_FREE(filestr);
1719  n = sarrayGetCount(sa);
1720  sela = selaCreate(0);
1721 
1722  /* Find the start and end lines for each Sel.
1723  * We allow the "blank" lines to be null strings or
1724  * to have standard whitespace (' ','\t',\'n') or be '#'. */
1725  nafirst = numaCreate(0);
1726  nalast = numaCreate(0);
1727  insel = FALSE;
1728  for (i = 0; i < n; i++) {
1729  line = sarrayGetString(sa, i, L_NOCOPY);
1730  if (!insel &&
1731  (line[0] != '\0' && line[0] != ' ' &&
1732  line[0] != '\t' && line[0] != '\n' && line[0] != '#')) {
1733  numaAddNumber(nafirst, i);
1734  insel = TRUE;
1735  continue;
1736  }
1737  if (insel &&
1738  (line[0] == '\0' || line[0] == ' ' ||
1739  line[0] == '\t' || line[0] == '\n' || line[0] == '#')) {
1740  numaAddNumber(nalast, i - 1);
1741  insel = FALSE;
1742  continue;
1743  }
1744  }
1745  if (insel) /* fell off the end of the file */
1746  numaAddNumber(nalast, n - 1);
1747 
1748  /* Extract sels */
1749  nsel = numaGetCount(nafirst);
1750  for (i = 0; i < nsel; i++) {
1751  numaGetIValue(nafirst, i, &first);
1752  numaGetIValue(nalast, i, &last);
1753  if ((sel = selCreateFromSArray(sa, first, last)) == NULL) {
1754  lept_stderr("Error reading sel from %d to %d\n", first, last);
1755  selaDestroy(&sela);
1756  sarrayDestroy(&sa);
1757  numaDestroy(&nafirst);
1758  numaDestroy(&nalast);
1759  return (SELA *)ERROR_PTR("bad sela file", __func__, NULL);
1760  }
1761  selaAddSel(sela, sel, NULL, 0);
1762  }
1763 
1764  numaDestroy(&nafirst);
1765  numaDestroy(&nalast);
1766  sarrayDestroy(&sa);
1767  return sela;
1768 }
1769 
1770 
1801 static SEL *
1803  l_int32 first,
1804  l_int32 last)
1805 {
1806 char ch;
1807 char *name, *line;
1808 l_int32 n, len, i, w, h, y, x;
1809 SEL *sel;
1810 
1811  if (!sa)
1812  return (SEL *)ERROR_PTR("sa not defined", __func__, NULL);
1813  n = sarrayGetCount(sa);
1814  if (first < 0 || first >= n || last <= first || last >= n)
1815  return (SEL *)ERROR_PTR("invalid range", __func__, NULL);
1816 
1817  name = sarrayGetString(sa, first, L_NOCOPY);
1818  h = last - first;
1819  line = sarrayGetString(sa, first + 1, L_NOCOPY);
1820  len = strlen(line);
1821  if (line[0] != '"' || line[len - 1] != '"')
1822  return (SEL *)ERROR_PTR("invalid format", __func__, NULL);
1823  w = len - 2;
1824  if ((sel = selCreate(h, w, name)) == NULL)
1825  return (SEL *)ERROR_PTR("sel not made", __func__, NULL);
1826  for (i = first + 1; i <= last; i++) {
1827  line = sarrayGetString(sa, i, L_NOCOPY);
1828  y = i - first - 1;
1829  for (x = 0; x < w; ++x) {
1830  ch = line[x + 1]; /* skip the leading double-quote */
1831  switch (ch)
1832  {
1833  case 'X':
1834  selSetOrigin(sel, y, x); /* set origin and hit */
1835  /* fall through */
1836  case 'x':
1837  selSetElement(sel, y, x, SEL_HIT);
1838  break;
1839 
1840  case 'O':
1841  selSetOrigin(sel, y, x); /* set origin and miss */
1842  /* fall through */
1843  case 'o':
1844  selSetElement(sel, y, x, SEL_MISS);
1845  break;
1846 
1847  case 'C':
1848  selSetOrigin(sel, y, x); /* set origin and don't-care */
1849  /* fall through */
1850  case ' ':
1851  selSetElement(sel, y, x, SEL_DONT_CARE);
1852  break;
1853 
1854  default:
1855  selDestroy(&sel);
1856  return (SEL *)ERROR_PTR("unknown char", __func__, NULL);
1857  }
1858  }
1859  }
1860 
1861  return sel;
1862 }
1863 
1864 
1865 /*----------------------------------------------------------------------*
1866  * Making hit-only SELs from Pta and Pix *
1867  *----------------------------------------------------------------------*/
1881 SEL *
1883  l_int32 cy,
1884  l_int32 cx,
1885  const char *name)
1886 {
1887 l_int32 i, n, x, y, w, h;
1888 BOX *box;
1889 SEL *sel;
1890 
1891  if (!pta)
1892  return (SEL *)ERROR_PTR("pta not defined", __func__, NULL);
1893  if (cy < 0 || cx < 0)
1894  return (SEL *)ERROR_PTR("(cy, cx) not both >= 0", __func__, NULL);
1895  n = ptaGetCount(pta);
1896  if (n == 0)
1897  return (SEL *)ERROR_PTR("no pts in pta", __func__, NULL);
1898 
1899  box = ptaGetBoundingRegion(pta);
1900  boxGetGeometry(box, &x, &y, &w, &h);
1901  boxDestroy(&box);
1902  if (x < 0 || y < 0)
1903  return (SEL *)ERROR_PTR("not all x and y >= 0", __func__, NULL);
1904 
1905  sel = selCreate(y + h, x + w, name);
1906  selSetOrigin(sel, cy, cx);
1907  for (i = 0; i < n; i++) {
1908  ptaGetIPt(pta, i, &x, &y);
1909  selSetElement(sel, y, x, SEL_HIT);
1910  }
1911 
1912  return sel;
1913 }
1914 
1915 
1931 SEL *
1933  l_int32 cy,
1934  l_int32 cx,
1935  const char *name)
1936 {
1937 SEL *sel;
1938 l_int32 i, j, w, h, d, nhits;
1939 l_uint32 val;
1940 
1941  if (!pix)
1942  return (SEL *)ERROR_PTR("pix not defined", __func__, NULL);
1943  if (cy < 0 || cx < 0)
1944  return (SEL *)ERROR_PTR("(cy, cx) not both >= 0", __func__, NULL);
1945  pixGetDimensions(pix, &w, &h, &d);
1946  if (d != 1)
1947  return (SEL *)ERROR_PTR("pix not 1 bpp", __func__, NULL);
1948  if (w > MaxPixTemplateSize || h > MaxPixTemplateSize) {
1949  L_ERROR("pix template too large (w = %d, h = %d)\n", __func__, w, h);
1950  return NULL;
1951  }
1952  pixCountPixels(pix, &nhits, NULL);
1953  if (nhits > MaxPixTemplateHits) {
1954  L_ERROR("too many hits (%d) in pix template\n", __func__, nhits);
1955  return NULL;
1956  }
1957 
1958  sel = selCreate(h, w, name);
1959  selSetOrigin(sel, cy, cx);
1960  for (i = 0; i < h; i++) {
1961  for (j = 0; j < w; j++) {
1962  pixGetPixel(pix, j, i, &val);
1963  if (val)
1964  selSetElement(sel, i, j, SEL_HIT);
1965  }
1966  }
1967 
1968  return sel;
1969 }
1970 
1971 
1972 /*----------------------------------------------------------------------*
1973  * Making hit-miss sels from color Pix and image files *
1974  *----------------------------------------------------------------------*/
1989 SEL *
1990 selReadFromColorImage(const char *pathname)
1991 {
1992 PIX *pix;
1993 SEL *sel;
1994 char *basename, *selname;
1995 
1996  splitPathAtExtension (pathname, &basename, NULL);
1997  splitPathAtDirectory (basename, NULL, &selname);
1998  LEPT_FREE(basename);
1999 
2000  if ((pix = pixRead(pathname)) == NULL) {
2001  LEPT_FREE(selname);
2002  return (SEL *)ERROR_PTR("pix not returned", __func__, NULL);
2003  }
2004  if ((sel = selCreateFromColorPix(pix, selname)) == NULL)
2005  L_ERROR("sel not made\n", __func__);
2006 
2007  LEPT_FREE(selname);
2008  pixDestroy(&pix);
2009  return sel;
2010 }
2011 
2012 
2036 SEL *
2038  const char *selname)
2039 {
2040 PIXCMAP *cmap;
2041 SEL *sel;
2042 l_int32 hascolor, num_origins, nohits;
2043 l_int32 w, h, d, i, j, red, green, blue;
2044 l_uint32 pixval;
2045 
2046  if (!pixs)
2047  return (SEL *)ERROR_PTR("pixs not defined", __func__, NULL);
2048 
2049  hascolor = FALSE;
2050  cmap = pixGetColormap(pixs);
2051  if (cmap)
2052  pixcmapHasColor(cmap, &hascolor);
2053  pixGetDimensions(pixs, &w, &h, &d);
2054  if (hascolor == FALSE && d != 32)
2055  return (SEL *)ERROR_PTR("pixs has no color", __func__, NULL);
2056 
2057  if ((sel = selCreate (h, w, NULL)) == NULL)
2058  return (SEL *)ERROR_PTR ("sel not made", __func__, NULL);
2059  selSetOrigin (sel, h / 2, w / 2); /* default */
2060  selSetName(sel, selname);
2061 
2062  num_origins = 0;
2063  nohits = TRUE;
2064  for (i = 0; i < h; i++) {
2065  for (j = 0; j < w; j++) {
2066  pixGetPixel (pixs, j, i, &pixval);
2067 
2068  if (cmap) {
2069  pixcmapGetColor (cmap, pixval, &red, &green, &blue);
2070  } else {
2071  red = GET_DATA_BYTE (&pixval, COLOR_RED);
2072  green = GET_DATA_BYTE (&pixval, COLOR_GREEN);
2073  blue = GET_DATA_BYTE (&pixval, COLOR_BLUE);
2074  }
2075 
2076  if (red < 255 && green < 255 && blue < 255) {
2077  num_origins++;
2078  if (num_origins == 1) /* first one found */
2079  selSetOrigin (sel, i, j);
2080  if (num_origins == 2)
2081  L_WARNING("multiple origins in sel image\n", __func__);
2082  }
2083  if (!red && green && !blue) {
2084  nohits = FALSE;
2085  selSetElement (sel, i, j, SEL_HIT);
2086  } else if (red && !green && !blue) {
2087  selSetElement (sel, i, j, SEL_MISS);
2088  } else if (red && green && blue) {
2089  selSetElement (sel, i, j, SEL_DONT_CARE);
2090  } else {
2091  selDestroy(&sel);
2092  return (SEL *)ERROR_PTR("invalid color", __func__, NULL);
2093  }
2094  }
2095  }
2096 
2097  if (nohits) {
2098  selDestroy(&sel);
2099  return (SEL *)ERROR_PTR("no hits in sel", __func__, NULL);
2100  }
2101  return sel;
2102 }
2103 
2104 
2120 SELA *
2122  SARRAY *sa)
2123 {
2124 char *str;
2125 l_int32 i, n;
2126 PIX *pix;
2127 SEL *sel;
2128 SELA *sela;
2129 
2130  if (!pixa)
2131  return (SELA *)ERROR_PTR("pixa not defined", __func__, NULL);
2132  if (!sa)
2133  return (SELA *)ERROR_PTR("sa of sel names not defined", __func__, NULL);
2134 
2135  n = pixaGetCount(pixa);
2136  if ((sela = selaCreate(n)) == NULL)
2137  return (SELA *)ERROR_PTR("sela not allocated", __func__, NULL);
2138  for (i = 0; i < n; i++) {
2139  pix = pixaGetPix(pixa, i, L_CLONE);
2140  str = sarrayGetString(sa, i, L_NOCOPY);
2141  sel = selCreateFromColorPix(pix, str);
2142  selaAddSel(sela, sel, NULL, L_INSERT);
2143  pixDestroy(&pix);
2144  }
2145  return sela;
2146 }
2147 
2148 
2149 /*----------------------------------------------------------------------*
2150  * Printable display of sel *
2151  *----------------------------------------------------------------------*/
2170 PIX *
2172  l_int32 size,
2173  l_int32 gthick)
2174 {
2175 l_int32 i, j, w, h, sx, sy, cx, cy, type, width;
2176 l_int32 radius1, radius2, shift1, shift2, x0, y0;
2177 PIX *pixd, *pix2, *pixh, *pixm, *pixorig;
2178 PTA *pta1, *pta2, *pta1t, *pta2t;
2179 
2180  if (!sel)
2181  return (PIX *)ERROR_PTR("sel not defined", __func__, NULL);
2182  if (size < 13) {
2183  L_WARNING("size < 13; setting to 13\n", __func__);
2184  size = 13;
2185  }
2186  if (size % 2 == 0)
2187  size++;
2188  if (gthick < 2) {
2189  L_WARNING("grid thickness < 2; setting to 2\n", __func__);
2190  gthick = 2;
2191  }
2192  selGetParameters(sel, &sy, &sx, &cy, &cx);
2193  w = size * sx + gthick * (sx + 1);
2194  h = size * sy + gthick * (sy + 1);
2195  pixd = pixCreate(w, h, 1);
2196 
2197  /* Generate grid lines */
2198  for (i = 0; i <= sy; i++)
2199  pixRenderLine(pixd, 0, gthick / 2 + i * (size + gthick),
2200  w - 1, gthick / 2 + i * (size + gthick),
2201  gthick, L_SET_PIXELS);
2202  for (j = 0; j <= sx; j++)
2203  pixRenderLine(pixd, gthick / 2 + j * (size + gthick), 0,
2204  gthick / 2 + j * (size + gthick), h - 1,
2205  gthick, L_SET_PIXELS);
2206 
2207  /* Generate hit and miss patterns */
2208  radius1 = (l_int32)(0.85 * ((size - 1) / 2.0) + 0.5); /* of hit */
2209  radius2 = (l_int32)(0.65 * ((size - 1) / 2.0) + 0.5); /* of inner miss */
2210  pta1 = generatePtaFilledCircle(radius1);
2211  pta2 = generatePtaFilledCircle(radius2);
2212  shift1 = (size - 1) / 2 - radius1; /* center circle in square */
2213  shift2 = (size - 1) / 2 - radius2;
2214  pta1t = ptaTransform(pta1, shift1, shift1, 1.0, 1.0);
2215  pta2t = ptaTransform(pta2, shift2, shift2, 1.0, 1.0);
2216  pixh = pixGenerateFromPta(pta1t, size, size); /* hits */
2217  pix2 = pixGenerateFromPta(pta2t, size, size);
2218  pixm = pixSubtract(NULL, pixh, pix2);
2219 
2220  /* Generate crossed lines for origin pattern */
2221  pixorig = pixCreate(size, size, 1);
2222  width = size / 8;
2223  pixRenderLine(pixorig, size / 2, (l_int32)(0.12 * size),
2224  size / 2, (l_int32)(0.88 * size),
2225  width, L_SET_PIXELS);
2226  pixRenderLine(pixorig, (l_int32)(0.15 * size), size / 2,
2227  (l_int32)(0.85 * size), size / 2,
2228  width, L_FLIP_PIXELS);
2229  pixRasterop(pixorig, size / 2 - width, size / 2 - width,
2230  2 * width, 2 * width, PIX_NOT(PIX_DST), NULL, 0, 0);
2231 
2232  /* Specialize origin pattern for this sel */
2233  selGetTypeAtOrigin(sel, &type);
2234  if (type == SEL_HIT)
2235  pixXor(pixorig, pixorig, pixh);
2236  else if (type == SEL_MISS)
2237  pixXor(pixorig, pixorig, pixm);
2238 
2239  /* Paste the patterns in */
2240  y0 = gthick;
2241  for (i = 0; i < sy; i++) {
2242  x0 = gthick;
2243  for (j = 0; j < sx; j++) {
2244  selGetElement(sel, i, j, &type);
2245  if (i == cy && j == cx) /* origin */
2246  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixorig, 0, 0);
2247  else if (type == SEL_HIT)
2248  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixh, 0, 0);
2249  else if (type == SEL_MISS)
2250  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixm, 0, 0);
2251  x0 += size + gthick;
2252  }
2253  y0 += size + gthick;
2254  }
2255 
2256  pixDestroy(&pix2);
2257  pixDestroy(&pixh);
2258  pixDestroy(&pixm);
2259  pixDestroy(&pixorig);
2260  ptaDestroy(&pta1);
2261  ptaDestroy(&pta1t);
2262  ptaDestroy(&pta2);
2263  ptaDestroy(&pta2t);
2264  return pixd;
2265 }
2266 
2267 
2286 PIX *
2288  l_int32 size,
2289  l_int32 gthick,
2290  l_int32 spacing,
2291  l_int32 ncols)
2292 {
2293 l_int32 nsels, i, w, width;
2294 PIX *pixt, *pixd;
2295 PIXA *pixa;
2296 SEL *sel;
2297 
2298  if (!sela)
2299  return (PIX *)ERROR_PTR("sela not defined", __func__, NULL);
2300  if (size < 13) {
2301  L_WARNING("size < 13; setting to 13\n", __func__);
2302  size = 13;
2303  }
2304  if (size % 2 == 0)
2305  size++;
2306  if (gthick < 2) {
2307  L_WARNING("grid thickness < 2; setting to 2\n", __func__);
2308  gthick = 2;
2309  }
2310  if (spacing < 5) {
2311  L_WARNING("spacing < 5; setting to 5\n", __func__);
2312  spacing = 5;
2313  }
2314 
2315  /* Accumulate the pix of each sel */
2316  nsels = selaGetCount(sela);
2317  pixa = pixaCreate(nsels);
2318  for (i = 0; i < nsels; i++) {
2319  sel = selaGetSel(sela, i);
2320  pixt = selDisplayInPix(sel, size, gthick);
2321  pixaAddPix(pixa, pixt, L_INSERT);
2322  }
2323 
2324  /* Find the tiled output width, using just the first
2325  * ncols pix in the pixa. If all pix have the same width,
2326  * they will align properly in columns. */
2327  width = 0;
2328  ncols = L_MIN(nsels, ncols);
2329  for (i = 0; i < ncols; i++) {
2330  pixt = pixaGetPix(pixa, i, L_CLONE);
2331  pixGetDimensions(pixt, &w, NULL, NULL);
2332  width += w;
2333  pixDestroy(&pixt);
2334  }
2335  width += (ncols + 1) * spacing; /* add spacing all around as well */
2336 
2337  pixd = pixaDisplayTiledInRows(pixa, 1, width, 1.0, 0, spacing, 0);
2338  pixaDestroy(&pixa);
2339  return pixd;
2340 }
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
l_ok boxGetGeometry(const BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:301
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:273
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1026
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:789
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 * generatePtaFilledCircle(l_int32 radius)
generatePtaFilledCircle()
Definition: graphics.c:811
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1104
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:720
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
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:192
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1893
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1654
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtract()
Definition: pix3.c:1717
#define PIX_DST
Definition: pix.h:445
@ COLOR_BLUE
Definition: pix.h:330
@ COLOR_RED
Definition: pix.h:328
@ COLOR_GREEN
Definition: pix.h:329
@ L_FLIP_PIXELS
Definition: pix.h:567
@ L_SET_PIXELS
Definition: pix.h:565
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_NOCOPY
Definition: pix.h:503
@ L_INSERT
Definition: pix.h:504
#define PIX_SRC
Definition: pix.h:444
#define PIX_NOT(op)
Definition: pix.h:446
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_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:629
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:647
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:730
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:527
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:480
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
BOX * ptaGetBoundingRegion(PTA *pta)
ptaGetBoundingRegion()
Definition: ptafunc1.c:431
PIX * pixGenerateFromPta(PTA *pta, l_int32 w, l_int32 h)
pixGenerateFromPta()
Definition: ptafunc1.c:1962
PTA * ptaTransform(PTA *ptas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
ptaTransform()
Definition: ptafunc1.c:715
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:189
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:169
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:673
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:617
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:353
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:276
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:435
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:716
static SEL * selCreateFromSArray(SARRAY *sa, l_int32 first, l_int32 last)
selCreateFromSArray()
Definition: sel1.c:1802
SEL * selCreateFromPta(PTA *pta, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPta()
Definition: sel1.c:1882
l_ok selWrite(const char *fname, SEL *sel)
selWrite()
Definition: sel1.c:1455
PIX * selDisplayInPix(SEL *sel, l_int32 size, l_int32 gthick)
selDisplayInPix()
Definition: sel1.c:2171
l_ok selWriteStream(FILE *fp, SEL *sel)
selWriteStream()
Definition: sel1.c:1482
static const l_int32 InitialPtrArraySize
Definition: sel1.c:151
SARRAY * selaGetSelnames(SELA *sela)
selaGetSelnames()
Definition: sel1.c:1101
SEL * selRead(const char *fname)
selRead()
Definition: sel1.c:1323
l_ok selGetParameters(SEL *sel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
selGetParameters()
Definition: sel1.c:816
SEL * selCreateFromPix(PIX *pix, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPix()
Definition: sel1.c:1932
l_ok getCompositeParameters(l_int32 size, l_int32 *psize1, l_int32 *psize2, char **pnameh1, char **pnameh2, char **pnamev1, char **pnamev2)
getCompositeParameters()
Definition: sel1.c:1059
l_ok selFindMaxTranslations(SEL *sel, l_int32 *pxp, l_int32 *pyp, l_int32 *pxn, l_int32 *pyn)
selFindMaxTranslations()
Definition: sel1.c:1144
SEL * selReadFromColorImage(const char *pathname)
Definition: sel1.c:1990
l_ok selSetName(SEL *sel, const char *name)
selSetName()
Definition: sel1.c:684
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
void selaDestroy(SELA **psela)
selaDestroy()
Definition: sel1.c:274
l_ok selaFindSelByName(SELA *sela, const char *name, l_int32 *pindex, SEL **psel)
selaFindSelByName()
Definition: sel1.c:704
SEL * selCopy(SEL *sel)
selCopy()
Definition: sel1.c:365
SEL * selCreateComb(l_int32 factor1, l_int32 factor2, l_int32 direction)
selCreateComb()
Definition: sel1.c:452
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
SEL * selRotateOrth(SEL *sel, l_int32 quads)
selRotateOrth()
Definition: sel1.c:1192
void selDestroy(SEL **psel)
selDestroy()
Definition: sel1.c:336
l_int32 ** create2dIntArray(l_int32 sy, l_int32 sx)
create2dIntArray()
Definition: sel1.c:505
SEL * selReadStream(FILE *fp)
selReadStream()
Definition: sel1.c:1350
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
char * selGetName(SEL *sel)
selGetName()
Definition: sel1.c:661
SELA * selaCreateFromColorPixa(PIXA *pixa, SARRAY *sa)
Definition: sel1.c:2121
l_ok selaWrite(const char *fname, SELA *sela)
selaWrite()
Definition: sel1.c:1397
SEL * selaGetSel(SELA *sela, l_int32 i)
selaGetSel()
Definition: sel1.c:642
char * selaGetCombName(SELA *sela, l_int32 size, l_int32 direction)
selaGetCombName()
Definition: sel1.c:934
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
static l_int32 selaExtendArray(SELA *sela)
selaExtendArray()
Definition: sel1.c:593
l_ok selGetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 *ptype)
selGetElement()
Definition: sel1.c:751
l_int32 selaGetCount(SELA *sela)
selaGetCount()
Definition: sel1.c:619
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:410
SELA * selaReadStream(FILE *fp)
selaReadStream()
Definition: sel1.c:1284
SELA * selaCreateFromFile(const char *filename)
selaCreateFromFile()
Definition: sel1.c:1703
char * selaGetBrickName(SELA *sela, l_int32 hsize, l_int32 vsize)
selaGetBrickName()
Definition: sel1.c:897
SELA * selaRead(const char *fname)
selaRead()
Definition: sel1.c:1257
l_ok selGetTypeAtOrigin(SEL *sel, l_int32 *ptype)
selGetTypeAtOrigin()
Definition: sel1.c:864
char * selPrintToString(SEL *sel)
selPrintToString()
Definition: sel1.c:1630
SEL * selCreateFromColorPix(PIX *pixs, const char *selname)
Definition: sel1.c:2037
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
SELA * selaAddDwaCombs(SELA *sela)
selaAddDwaCombs()
Definition: sel2.c:362
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:339
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2796
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2728
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1905
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1519
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1262
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1864
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1310