Leptonica  1.77.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 
141 #include <string.h>
142 #include "allheaders.h"
143 
144 static const l_int32 L_BUFSIZE = 256; /* hardcoded below in sscanf */
145 static const l_int32 INITIAL_PTR_ARRAYSIZE = 50; /* n'import quoi */
146 static const l_int32 MANY_SELS = 1000;
147 
148  /* Static functions */
149 static l_int32 selaExtendArray(SELA *sela);
150 static SEL *selCreateFromSArray(SARRAY *sa, l_int32 first, l_int32 last);
151 
153 {
154  l_int32 size;
155  l_int32 size1;
156  l_int32 size2;
157  char selnameh1[20];
158  char selnameh2[20];
159  char selnamev1[20];
160  char selnamev2[20];
161 };
162 
163 static const struct CompParameterMap comp_parameter_map[] =
164  { { 2, 2, 1, "sel_2h", "", "sel_2v", "" },
165  { 3, 3, 1, "sel_3h", "", "sel_3v", "" },
166  { 4, 2, 2, "sel_2h", "sel_comb_4h", "sel_2v", "sel_comb_4v" },
167  { 5, 5, 1, "sel_5h", "", "sel_5v", "" },
168  { 6, 3, 2, "sel_3h", "sel_comb_6h", "sel_3v", "sel_comb_6v" },
169  { 7, 7, 1, "sel_7h", "", "sel_7v", "" },
170  { 8, 4, 2, "sel_4h", "sel_comb_8h", "sel_4v", "sel_comb_8v" },
171  { 9, 3, 3, "sel_3h", "sel_comb_9h", "sel_3v", "sel_comb_9v" },
172  { 10, 5, 2, "sel_5h", "sel_comb_10h", "sel_5v", "sel_comb_10v" },
173  { 11, 4, 3, "sel_4h", "sel_comb_12h", "sel_4v", "sel_comb_12v" },
174  { 12, 4, 3, "sel_4h", "sel_comb_12h", "sel_4v", "sel_comb_12v" },
175  { 13, 4, 3, "sel_4h", "sel_comb_12h", "sel_4v", "sel_comb_12v" },
176  { 14, 7, 2, "sel_7h", "sel_comb_14h", "sel_7v", "sel_comb_14v" },
177  { 15, 5, 3, "sel_5h", "sel_comb_15h", "sel_5v", "sel_comb_15v" },
178  { 16, 4, 4, "sel_4h", "sel_comb_16h", "sel_4v", "sel_comb_16v" },
179  { 17, 4, 4, "sel_4h", "sel_comb_16h", "sel_4v", "sel_comb_16v" },
180  { 18, 6, 3, "sel_6h", "sel_comb_18h", "sel_6v", "sel_comb_18v" },
181  { 19, 5, 4, "sel_5h", "sel_comb_20h", "sel_5v", "sel_comb_20v" },
182  { 20, 5, 4, "sel_5h", "sel_comb_20h", "sel_5v", "sel_comb_20v" },
183  { 21, 7, 3, "sel_7h", "sel_comb_21h", "sel_7v", "sel_comb_21v" },
184  { 22, 11, 2, "sel_11h", "sel_comb_22h", "sel_11v", "sel_comb_22v" },
185  { 23, 6, 4, "sel_6h", "sel_comb_24h", "sel_6v", "sel_comb_24v" },
186  { 24, 6, 4, "sel_6h", "sel_comb_24h", "sel_6v", "sel_comb_24v" },
187  { 25, 5, 5, "sel_5h", "sel_comb_25h", "sel_5v", "sel_comb_25v" },
188  { 26, 5, 5, "sel_5h", "sel_comb_25h", "sel_5v", "sel_comb_25v" },
189  { 27, 9, 3, "sel_9h", "sel_comb_27h", "sel_9v", "sel_comb_27v" },
190  { 28, 7, 4, "sel_7h", "sel_comb_28h", "sel_7v", "sel_comb_28v" },
191  { 29, 6, 5, "sel_6h", "sel_comb_30h", "sel_6v", "sel_comb_30v" },
192  { 30, 6, 5, "sel_6h", "sel_comb_30h", "sel_6v", "sel_comb_30v" },
193  { 31, 6, 5, "sel_6h", "sel_comb_30h", "sel_6v", "sel_comb_30v" },
194  { 32, 8, 4, "sel_8h", "sel_comb_32h", "sel_8v", "sel_comb_32v" },
195  { 33, 11, 3, "sel_11h", "sel_comb_33h", "sel_11v", "sel_comb_33v" },
196  { 34, 7, 5, "sel_7h", "sel_comb_35h", "sel_7v", "sel_comb_35v" },
197  { 35, 7, 5, "sel_7h", "sel_comb_35h", "sel_7v", "sel_comb_35v" },
198  { 36, 6, 6, "sel_6h", "sel_comb_36h", "sel_6v", "sel_comb_36v" },
199  { 37, 6, 6, "sel_6h", "sel_comb_36h", "sel_6v", "sel_comb_36v" },
200  { 38, 6, 6, "sel_6h", "sel_comb_36h", "sel_6v", "sel_comb_36v" },
201  { 39, 13, 3, "sel_13h", "sel_comb_39h", "sel_13v", "sel_comb_39v" },
202  { 40, 8, 5, "sel_8h", "sel_comb_40h", "sel_8v", "sel_comb_40v" },
203  { 41, 7, 6, "sel_7h", "sel_comb_42h", "sel_7v", "sel_comb_42v" },
204  { 42, 7, 6, "sel_7h", "sel_comb_42h", "sel_7v", "sel_comb_42v" },
205  { 43, 7, 6, "sel_7h", "sel_comb_42h", "sel_7v", "sel_comb_42v" },
206  { 44, 11, 4, "sel_11h", "sel_comb_44h", "sel_11v", "sel_comb_44v" },
207  { 45, 9, 5, "sel_9h", "sel_comb_45h", "sel_9v", "sel_comb_45v" },
208  { 46, 9, 5, "sel_9h", "sel_comb_45h", "sel_9v", "sel_comb_45v" },
209  { 47, 8, 6, "sel_8h", "sel_comb_48h", "sel_8v", "sel_comb_48v" },
210  { 48, 8, 6, "sel_8h", "sel_comb_48h", "sel_8v", "sel_comb_48v" },
211  { 49, 7, 7, "sel_7h", "sel_comb_49h", "sel_7v", "sel_comb_49v" },
212  { 50, 10, 5, "sel_10h", "sel_comb_50h", "sel_10v", "sel_comb_50v" },
213  { 51, 10, 5, "sel_10h", "sel_comb_50h", "sel_10v", "sel_comb_50v" },
214  { 52, 13, 4, "sel_13h", "sel_comb_52h", "sel_13v", "sel_comb_52v" },
215  { 53, 9, 6, "sel_9h", "sel_comb_54h", "sel_9v", "sel_comb_54v" },
216  { 54, 9, 6, "sel_9h", "sel_comb_54h", "sel_9v", "sel_comb_54v" },
217  { 55, 11, 5, "sel_11h", "sel_comb_55h", "sel_11v", "sel_comb_55v" },
218  { 56, 8, 7, "sel_8h", "sel_comb_56h", "sel_8v", "sel_comb_56v" },
219  { 57, 8, 7, "sel_8h", "sel_comb_56h", "sel_8v", "sel_comb_56v" },
220  { 58, 8, 7, "sel_8h", "sel_comb_56h", "sel_8v", "sel_comb_56v" },
221  { 59, 10, 6, "sel_10h", "sel_comb_60h", "sel_10v", "sel_comb_60v" },
222  { 60, 10, 6, "sel_10h", "sel_comb_60h", "sel_10v", "sel_comb_60v" },
223  { 61, 10, 6, "sel_10h", "sel_comb_60h", "sel_10v", "sel_comb_60v" },
224  { 62, 9, 7, "sel_9h", "sel_comb_63h", "sel_9v", "sel_comb_63v" },
225  { 63, 9, 7, "sel_9h", "sel_comb_63h", "sel_9v", "sel_comb_63v" } };
226 
227 
228 
229 /*------------------------------------------------------------------------*
230  * Create / Destroy / Copy *
231  *------------------------------------------------------------------------*/
238 SELA *
239 selaCreate(l_int32 n)
240 {
241 SELA *sela;
242 
243  PROCNAME("selaCreate");
244 
245  if (n <= 0)
246  n = INITIAL_PTR_ARRAYSIZE;
247  if (n > MANY_SELS)
248  L_WARNING("%d sels\n", procName, n);
249 
250  if ((sela = (SELA *)LEPT_CALLOC(1, sizeof(SELA))) == NULL)
251  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
252 
253  sela->nalloc = n;
254  sela->n = 0;
255 
256  /* make array of se ptrs */
257  if ((sela->sel = (SEL **)LEPT_CALLOC(n, sizeof(SEL *))) == NULL) {
258  LEPT_FREE(sela);
259  return (SELA *)ERROR_PTR("sel ptrs not made", procName, NULL);
260  }
261  return sela;
262 }
263 
264 
271 void
273 {
274 SELA *sela;
275 l_int32 i;
276 
277  if (!psela) return;
278  if ((sela = *psela) == NULL)
279  return;
280 
281  for (i = 0; i < sela->n; i++)
282  selDestroy(&sela->sel[i]);
283  LEPT_FREE(sela->sel);
284  LEPT_FREE(sela);
285  *psela = NULL;
286  return;
287 }
288 
289 
305 SEL *
306 selCreate(l_int32 height,
307  l_int32 width,
308  const char *name)
309 {
310 SEL *sel;
311 
312  PROCNAME("selCreate");
313 
314  if ((sel = (SEL *)LEPT_CALLOC(1, sizeof(SEL))) == NULL)
315  return (SEL *)ERROR_PTR("sel not made", procName, NULL);
316  if (name)
317  sel->name = stringNew(name);
318  sel->sy = height;
319  sel->sx = width;
320  if ((sel->data = create2dIntArray(height, width)) == NULL) {
321  LEPT_FREE(sel->name);
322  LEPT_FREE(sel);
323  return (SEL *)ERROR_PTR("data not allocated", procName, NULL);
324  }
325 
326  return sel;
327 }
328 
329 
336 void
337 selDestroy(SEL **psel)
338 {
339 l_int32 i;
340 SEL *sel;
341 
342  PROCNAME("selDestroy");
343 
344  if (psel == NULL) {
345  L_WARNING("ptr address is NULL!\n", procName);
346  return;
347  }
348  if ((sel = *psel) == NULL)
349  return;
350 
351  for (i = 0; i < sel->sy; i++)
352  LEPT_FREE(sel->data[i]);
353  LEPT_FREE(sel->data);
354  if (sel->name)
355  LEPT_FREE(sel->name);
356  LEPT_FREE(sel);
357 
358  *psel = NULL;
359  return;
360 }
361 
362 
369 SEL *
370 selCopy(SEL *sel)
371 {
372 l_int32 sx, sy, cx, cy, i, j;
373 SEL *csel;
374 
375  PROCNAME("selCopy");
376 
377  if (!sel)
378  return (SEL *)ERROR_PTR("sel not defined", procName, NULL);
379 
380  if ((csel = (SEL *)LEPT_CALLOC(1, sizeof(SEL))) == NULL)
381  return (SEL *)ERROR_PTR("csel not made", procName, NULL);
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  sel = selCreate(1, size, NULL);
479  selSetOrigin(sel, 0, size / 2);
480  } else {
481  sel = selCreate(size, 1, NULL);
482  selSetOrigin(sel, size / 2, 0);
483  }
484 
485  /* Lay down the elements of the comb */
486  for (i = 0; i < factor2; i++) {
487  z = factor1 / 2 + i * factor1;
488 /* fprintf(stderr, "i = %d, factor1 = %d, factor2 = %d, z = %d\n",
489  i, factor1, factor2, z); */
490  if (direction == L_HORIZ)
491  selSetElement(sel, 0, z, SEL_HIT);
492  else
493  selSetElement(sel, z, 0, SEL_HIT);
494  }
495 
496  return sel;
497 }
498 
499 
514 l_int32 **
515 create2dIntArray(l_int32 sy,
516  l_int32 sx)
517 {
518 l_int32 i, j, success;
519 l_int32 **array;
520 
521  PROCNAME("create2dIntArray");
522 
523  if ((array = (l_int32 **)LEPT_CALLOC(sy, sizeof(l_int32 *))) == NULL)
524  return (l_int32 **)ERROR_PTR("ptr array not made", procName, NULL);
525 
526  success = TRUE;
527  for (i = 0; i < sy; i++) {
528  if ((array[i] = (l_int32 *)LEPT_CALLOC(sx, sizeof(l_int32))) == NULL) {
529  success = FALSE;
530  break;
531  }
532  }
533  if (success) return array;
534 
535  /* Cleanup after error */
536  for (j = 0; j < i; j++)
537  LEPT_FREE(array[j]);
538  LEPT_FREE(array);
539  return (l_int32 **)ERROR_PTR("array not made", procName, NULL);
540 }
541 
542 
543 
544 /*------------------------------------------------------------------------*
545  * Extension of sela *
546  *------------------------------------------------------------------------*/
565 l_ok
567  SEL *sel,
568  const char *selname,
569  l_int32 copyflag)
570 {
571 l_int32 n;
572 SEL *csel;
573 
574  PROCNAME("selaAddSel");
575 
576  if (!sela)
577  return ERROR_INT("sela not defined", procName, 1);
578  if (!sel)
579  return ERROR_INT("sel not defined", procName, 1);
580  if (!sel->name && !selname)
581  return ERROR_INT("added sel must have name", procName, 1);
582  if (copyflag != L_INSERT && copyflag != L_COPY)
583  return ERROR_INT("invalid copyflag", procName, 1);
584 
585  if (copyflag == L_COPY) {
586  if ((csel = selCopy(sel)) == NULL)
587  return ERROR_INT("csel not made", procName, 1);
588  } else { /* copyflag == L_INSERT */
589  csel = sel;
590  }
591  if (!csel->name)
592  csel->name = stringNew(selname);
593 
594  n = selaGetCount(sela);
595  if (n >= sela->nalloc)
596  selaExtendArray(sela);
597  sela->sel[n] = csel;
598  sela->n++;
599 
600  return 0;
601 }
602 
603 
610 static l_int32
612 {
613  PROCNAME("selaExtendArray");
614 
615  if (!sela)
616  return ERROR_INT("sela not defined", procName, 1);
617 
618  if ((sela->sel = (SEL **)reallocNew((void **)&sela->sel,
619  sizeof(SEL *) * sela->nalloc,
620  2 * sizeof(SEL *) * sela->nalloc)) == NULL)
621  return ERROR_INT("new ptr array not returned", procName, 1);
622 
623  sela->nalloc = 2 * sela->nalloc;
624  return 0;
625 }
626 
627 
628 
629 /*----------------------------------------------------------------------*
630  * Accessors *
631  *----------------------------------------------------------------------*/
638 l_int32
640 {
641  PROCNAME("selaGetCount");
642 
643  if (!sela)
644  return ERROR_INT("sela not defined", procName, 0);
645 
646  return sela->n;
647 }
648 
649 
663 SEL *
665  l_int32 i)
666 {
667  PROCNAME("selaGetSel");
668 
669  if (!sela)
670  return (SEL *)ERROR_PTR("sela not defined", procName, NULL);
671 
672  if (i < 0 || i >= sela->n)
673  return (SEL *)ERROR_PTR("invalid index", procName, NULL);
674  return sela->sel[i];
675 }
676 
677 
684 char *
685 selGetName(SEL *sel)
686 {
687  PROCNAME("selGetName");
688 
689  if (!sel)
690  return (char *)ERROR_PTR("sel not defined", procName, NULL);
691 
692  return sel->name;
693 }
694 
695 
709 l_ok
710 selSetName(SEL *sel,
711  const char *name)
712 {
713  PROCNAME("selSetName");
714 
715  if (!sel)
716  return ERROR_INT("sel not defined", procName, 1);
717 
718  return stringReplace(&sel->name, name);
719 }
720 
721 
731 l_ok
733  const char *name,
734  l_int32 *pindex,
735  SEL **psel)
736 {
737 l_int32 i, n;
738 char *sname;
739 SEL *sel;
740 
741  PROCNAME("selaFindSelByName");
742 
743  if (pindex) *pindex = -1;
744  if (psel) *psel = NULL;
745 
746  if (!sela)
747  return ERROR_INT("sela not defined", procName, 1);
748 
749  n = selaGetCount(sela);
750  for (i = 0; i < n; i++)
751  {
752  if ((sel = selaGetSel(sela, i)) == NULL) {
753  L_WARNING("missing sel\n", procName);
754  continue;
755  }
756 
757  sname = selGetName(sel);
758  if (sname && (!strcmp(name, sname))) {
759  if (pindex)
760  *pindex = i;
761  if (psel)
762  *psel = sel;
763  return 0;
764  }
765  }
766 
767  return 1;
768 }
769 
770 
780 l_ok
781 selGetElement(SEL *sel,
782  l_int32 row,
783  l_int32 col,
784  l_int32 *ptype)
785 {
786  PROCNAME("selGetElement");
787 
788  if (!ptype)
789  return ERROR_INT("&type not defined", procName, 1);
790  *ptype = SEL_DONT_CARE;
791  if (!sel)
792  return ERROR_INT("sel not defined", procName, 1);
793  if (row < 0 || row >= sel->sy)
794  return ERROR_INT("sel row out of bounds", procName, 1);
795  if (col < 0 || col >= sel->sx)
796  return ERROR_INT("sel col out of bounds", procName, 1);
797 
798  *ptype = sel->data[row][col];
799  return 0;
800 }
801 
802 
820 l_ok
821 selSetElement(SEL *sel,
822  l_int32 row,
823  l_int32 col,
824  l_int32 type)
825 {
826  PROCNAME("selSetElement");
827 
828  if (!sel)
829  return ERROR_INT("sel not defined", procName, 1);
830  if (type != SEL_HIT && type != SEL_MISS && type != SEL_DONT_CARE)
831  return ERROR_INT("invalid sel element type", procName, 1);
832  if (row < 0 || row >= sel->sy)
833  return ERROR_INT("sel row out of bounds", procName, 1);
834  if (col < 0 || col >= sel->sx)
835  return ERROR_INT("sel col out of bounds", procName, 1);
836 
837  sel->data[row][col] = type;
838  return 0;
839 }
840 
841 
849 l_ok
851  l_int32 *psy,
852  l_int32 *psx,
853  l_int32 *pcy,
854  l_int32 *pcx)
855 {
856  PROCNAME("selGetParameters");
857 
858  if (psy) *psy = 0;
859  if (psx) *psx = 0;
860  if (pcy) *pcy = 0;
861  if (pcx) *pcx = 0;
862  if (!sel)
863  return ERROR_INT("sel not defined", procName, 1);
864  if (psy) *psy = sel->sy;
865  if (psx) *psx = sel->sx;
866  if (pcy) *pcy = sel->cy;
867  if (pcx) *pcx = sel->cx;
868  return 0;
869 }
870 
871 
879 l_ok
880 selSetOrigin(SEL *sel,
881  l_int32 cy,
882  l_int32 cx)
883 {
884  PROCNAME("selSetOrigin");
885 
886  if (!sel)
887  return ERROR_INT("sel not defined", procName, 1);
888  sel->cy = cy;
889  sel->cx = cx;
890  return 0;
891 }
892 
893 
901 l_ok
903  l_int32 *ptype)
904 {
905 l_int32 sx, sy, cx, cy, i, j;
906 
907  PROCNAME("selGetTypeAtOrigin");
908 
909  if (!ptype)
910  return ERROR_INT("&type not defined", procName, 1);
911  *ptype = SEL_DONT_CARE; /* init */
912  if (!sel)
913  return ERROR_INT("sel not defined", procName, 1);
914 
915  selGetParameters(sel, &sy, &sx, &cy, &cx);
916  for (i = 0; i < sy; i++) {
917  for (j = 0; j < sx; j++) {
918  if (i == cy && j == cx) {
919  selGetElement(sel, i, j, ptype);
920  return 0;
921  }
922  }
923  }
924 
925  return ERROR_INT("sel origin not found", procName, 1);
926 }
927 
928 
936 char *
938  l_int32 hsize,
939  l_int32 vsize)
940 {
941 l_int32 i, nsels, sx, sy;
942 SEL *sel;
943 
944  PROCNAME("selaGetBrickName");
945 
946  if (!sela)
947  return (char *)ERROR_PTR("sela not defined", procName, NULL);
948 
949  nsels = selaGetCount(sela);
950  for (i = 0; i < nsels; i++) {
951  sel = selaGetSel(sela, i);
952  selGetParameters(sel, &sy, &sx, NULL, NULL);
953  if (hsize == sx && vsize == sy)
954  return stringNew(selGetName(sel));
955  }
956 
957  return (char *)ERROR_PTR("sel not found", procName, NULL);
958 }
959 
960 
975 char *
977  l_int32 size,
978  l_int32 direction)
979 {
980 char *selname;
981 char combname[L_BUFSIZE];
982 l_int32 i, nsels, sx, sy, found;
983 SEL *sel;
984 
985  PROCNAME("selaGetCombName");
986 
987  if (!sela)
988  return (char *)ERROR_PTR("sela not defined", procName, NULL);
989  if (direction != L_HORIZ && direction != L_VERT)
990  return (char *)ERROR_PTR("invalid direction", procName, NULL);
991 
992  /* Derive the comb name we're looking for */
993  if (direction == L_HORIZ)
994  snprintf(combname, L_BUFSIZE, "sel_comb_%dh", size);
995  else /* direction == L_VERT */
996  snprintf(combname, L_BUFSIZE, "sel_comb_%dv", size);
997 
998  found = FALSE;
999  nsels = selaGetCount(sela);
1000  for (i = 0; i < nsels; i++) {
1001  sel = selaGetSel(sela, i);
1002  selGetParameters(sel, &sy, &sx, NULL, NULL);
1003  if (sy != 1 && sx != 1) /* 2-D; not a comb */
1004  continue;
1005  selname = selGetName(sel);
1006  if (!strcmp(selname, combname)) {
1007  found = TRUE;
1008  break;
1009  }
1010  }
1011 
1012  if (found)
1013  return stringNew(selname);
1014  else
1015  return (char *)ERROR_PTR("sel not found", procName, NULL);
1016 }
1017 
1018 
1019 /* --------- Function used to generate code in this file ---------- */
1020 #if 0
1021 static void selaComputeCompositeParameters(const char *fileout);
1022 
1040 static void
1041 selaComputeCompositeParameters(const char *fileout)
1042 {
1043 char *str, *nameh1, *nameh2, *namev1, *namev2;
1044 char buf[L_BUFSIZE];
1045 l_int32 size, size1, size2, len;
1046 SARRAY *sa;
1047 SELA *selabasic, *selacomb;
1048 
1049  selabasic = selaAddBasic(NULL);
1050  selacomb = selaAddDwaCombs(NULL);
1051  sa = sarrayCreate(64);
1052  for (size = 2; size < 64; size++) {
1053  selectComposableSizes(size, &size1, &size2);
1054  nameh1 = selaGetBrickName(selabasic, size1, 1);
1055  namev1 = selaGetBrickName(selabasic, 1, size1);
1056  if (size2 > 1) {
1057  nameh2 = selaGetCombName(selacomb, size1 * size2, L_HORIZ);
1058  namev2 = selaGetCombName(selacomb, size1 * size2, L_VERT);
1059  } else {
1060  nameh2 = stringNew("");
1061  namev2 = stringNew("");
1062  }
1063  snprintf(buf, L_BUFSIZE,
1064  " { %d, %d, %d, \"%s\", \"%s\", \"%s\", \"%s\" },",
1065  size, size1, size2, nameh1, nameh2, namev1, namev2);
1066  sarrayAddString(sa, buf, L_COPY);
1067  LEPT_FREE(nameh1);
1068  LEPT_FREE(nameh2);
1069  LEPT_FREE(namev1);
1070  LEPT_FREE(namev2);
1071  }
1072  str = sarrayToString(sa, 1);
1073  len = strlen(str);
1074  l_binaryWrite(fileout, "w", str, len + 1);
1075  LEPT_FREE(str);
1076  sarrayDestroy(&sa);
1077  selaDestroy(&selabasic);
1078  selaDestroy(&selacomb);
1079  return;
1080 }
1081 #endif
1082 /* -------------------------------------------------------------------- */
1083 
1084 
1103 l_ok
1105  l_int32 *psize1,
1106  l_int32 *psize2,
1107  char **pnameh1,
1108  char **pnameh2,
1109  char **pnamev1,
1110  char **pnamev2)
1111 {
1112 l_int32 index;
1113 
1114  PROCNAME("selaGetSelnames");
1115 
1116  if (psize1) *psize1 = 0;
1117  if (psize2) *psize2 = 0;
1118  if (pnameh1) *pnameh1 = NULL;
1119  if (pnameh2) *pnameh2 = NULL;
1120  if (pnamev1) *pnamev1 = NULL;
1121  if (pnamev2) *pnamev2 = NULL;
1122  if (size < 2 || size > 63)
1123  return ERROR_INT("valid size range is {2 ... 63}", procName, 1);
1124  index = size - 2;
1125  if (psize1)
1126  *psize1 = comp_parameter_map[index].size1;
1127  if (psize2)
1128  *psize2 = comp_parameter_map[index].size2;
1129  if (pnameh1)
1130  *pnameh1 = stringNew(comp_parameter_map[index].selnameh1);
1131  if (pnameh2)
1132  *pnameh2 = stringNew(comp_parameter_map[index].selnameh2);
1133  if (pnamev1)
1134  *pnamev1 = stringNew(comp_parameter_map[index].selnamev1);
1135  if (pnamev2)
1136  *pnamev2 = stringNew(comp_parameter_map[index].selnamev2);
1137  return 0;
1138 }
1139 
1140 
1147 SARRAY *
1149 {
1150 char *selname;
1151 l_int32 i, n;
1152 SEL *sel;
1153 SARRAY *sa;
1154 
1155  PROCNAME("selaGetSelnames");
1156 
1157  if (!sela)
1158  return (SARRAY *)ERROR_PTR("sela not defined", procName, NULL);
1159  if ((n = selaGetCount(sela)) == 0)
1160  return (SARRAY *)ERROR_PTR("no sels in sela", procName, NULL);
1161 
1162  if ((sa = sarrayCreate(n)) == NULL)
1163  return (SARRAY *)ERROR_PTR("sa not made", procName, NULL);
1164  for (i = 0; i < n; i++) {
1165  sel = selaGetSel(sela, i);
1166  selname = selGetName(sel);
1167  sarrayAddString(sa, selname, L_COPY);
1168  }
1169 
1170  return sa;
1171 }
1172 
1173 
1174 
1175 /*----------------------------------------------------------------------*
1176  * Max translations for erosion and hmt *
1177  *----------------------------------------------------------------------*/
1192 l_ok
1194  l_int32 *pxp,
1195  l_int32 *pyp,
1196  l_int32 *pxn,
1197  l_int32 *pyn)
1198 {
1199 l_int32 sx, sy, cx, cy, i, j;
1200 l_int32 maxxp, maxyp, maxxn, maxyn;
1201 
1202  PROCNAME("selaFindMaxTranslations");
1203 
1204  if (!pxp || !pyp || !pxn || !pyn)
1205  return ERROR_INT("&xp (etc) defined", procName, 1);
1206  *pxp = *pyp = *pxn = *pyn = 0;
1207  if (!sel)
1208  return ERROR_INT("sel not defined", procName, 1);
1209  selGetParameters(sel, &sy, &sx, &cy, &cx);
1210 
1211  maxxp = maxyp = maxxn = maxyn = 0;
1212  for (i = 0; i < sy; i++) {
1213  for (j = 0; j < sx; j++) {
1214  if (sel->data[i][j] == 1) {
1215  maxxp = L_MAX(maxxp, cx - j);
1216  maxyp = L_MAX(maxyp, cy - i);
1217  maxxn = L_MAX(maxxn, j - cx);
1218  maxyn = L_MAX(maxyn, i - cy);
1219  }
1220  }
1221  }
1222 
1223  *pxp = maxxp;
1224  *pyp = maxyp;
1225  *pxn = maxxn;
1226  *pyn = maxyn;
1227 
1228  return 0;
1229 }
1230 
1231 
1232 /*----------------------------------------------------------------------*
1233  * Rotation by multiples of 90 degrees *
1234  *----------------------------------------------------------------------*/
1242 SEL *
1243 selRotateOrth(SEL *sel,
1244  l_int32 quads)
1245 {
1246 l_int32 i, j, ni, nj, sx, sy, cx, cy, nsx, nsy, ncx, ncy, type;
1247 SEL *seld;
1248 
1249  PROCNAME("selRotateOrth");
1250 
1251  if (!sel)
1252  return (SEL *)ERROR_PTR("sel not defined", procName, NULL);
1253  if (quads < 0 || quads > 4)
1254  return (SEL *)ERROR_PTR("quads not in {0,1,2,3,4}", procName, NULL);
1255  if (quads == 0 || quads == 4)
1256  return selCopy(sel);
1257 
1258  selGetParameters(sel, &sy, &sx, &cy, &cx);
1259  if (quads == 1) { /* 90 degrees cw */
1260  nsx = sy;
1261  nsy = sx;
1262  ncx = sy - cy - 1;
1263  ncy = cx;
1264  } else if (quads == 2) { /* 180 degrees cw */
1265  nsx = sx;
1266  nsy = sy;
1267  ncx = sx - cx - 1;
1268  ncy = sy - cy - 1;
1269  } else { /* 270 degrees cw */
1270  nsx = sy;
1271  nsy = sx;
1272  ncx = cy;
1273  ncy = sx - cx - 1;
1274  }
1275  seld = selCreateBrick(nsy, nsx, ncy, ncx, SEL_DONT_CARE);
1276  if (sel->name)
1277  seld->name = stringNew(sel->name);
1278 
1279  for (i = 0; i < sy; i++) {
1280  for (j = 0; j < sx; j++) {
1281  selGetElement(sel, i, j, &type);
1282  if (quads == 1) {
1283  ni = j;
1284  nj = sy - i - 1;
1285  } else if (quads == 2) {
1286  ni = sy - i - 1;
1287  nj = sx - j - 1;
1288  } else { /* quads == 3 */
1289  ni = sx - j - 1;
1290  nj = i;
1291  }
1292  selSetElement(seld, ni, nj, type);
1293  }
1294  }
1295 
1296  return seld;
1297 }
1298 
1299 
1300 /*----------------------------------------------------------------------*
1301  * Sela and Sel serialized I/O *
1302  *----------------------------------------------------------------------*/
1309 SELA *
1310 selaRead(const char *fname)
1311 {
1312 FILE *fp;
1313 SELA *sela;
1314 
1315  PROCNAME("selaRead");
1316 
1317  if (!fname)
1318  return (SELA *)ERROR_PTR("fname not defined", procName, NULL);
1319 
1320  if ((fp = fopenReadStream(fname)) == NULL)
1321  return (SELA *)ERROR_PTR("stream not opened", procName, NULL);
1322  if ((sela = selaReadStream(fp)) == NULL) {
1323  fclose(fp);
1324  return (SELA *)ERROR_PTR("sela not returned", procName, NULL);
1325  }
1326  fclose(fp);
1327 
1328  return sela;
1329 }
1330 
1331 
1338 SELA *
1340 {
1341 l_int32 i, n, version;
1342 SEL *sel;
1343 SELA *sela;
1344 
1345  PROCNAME("selaReadStream");
1346 
1347  if (!fp)
1348  return (SELA *)ERROR_PTR("stream not defined", procName, NULL);
1349 
1350  if (fscanf(fp, "\nSela Version %d\n", &version) != 1)
1351  return (SELA *)ERROR_PTR("not a sela file", procName, NULL);
1352  if (version != SEL_VERSION_NUMBER)
1353  return (SELA *)ERROR_PTR("invalid sel version", procName, NULL);
1354  if (fscanf(fp, "Number of Sels = %d\n\n", &n) != 1)
1355  return (SELA *)ERROR_PTR("not a sela file", procName, NULL);
1356 
1357  if ((sela = selaCreate(n)) == NULL)
1358  return (SELA *)ERROR_PTR("sela not made", procName, NULL);
1359  sela->nalloc = n;
1360 
1361  for (i = 0; i < n; i++) {
1362  if ((sel = selReadStream(fp)) == NULL) {
1363  selaDestroy(&sela);
1364  return (SELA *)ERROR_PTR("sel not read", procName, NULL);
1365  }
1366  selaAddSel(sela, sel, NULL, 0);
1367  }
1368 
1369  return sela;
1370 }
1371 
1372 
1379 SEL *
1380 selRead(const char *fname)
1381 {
1382 FILE *fp;
1383 SEL *sel;
1384 
1385  PROCNAME("selRead");
1386 
1387  if (!fname)
1388  return (SEL *)ERROR_PTR("fname not defined", procName, NULL);
1389 
1390  if ((fp = fopenReadStream(fname)) == NULL)
1391  return (SEL *)ERROR_PTR("stream not opened", procName, NULL);
1392  if ((sel = selReadStream(fp)) == NULL) {
1393  fclose(fp);
1394  return (SEL *)ERROR_PTR("sela not returned", procName, NULL);
1395  }
1396  fclose(fp);
1397 
1398  return sel;
1399 }
1400 
1401 
1408 SEL *
1409 selReadStream(FILE *fp)
1410 {
1411 char *selname;
1412 char linebuf[L_BUFSIZE];
1413 l_int32 sy, sx, cy, cx, i, j, version, ignore;
1414 SEL *sel;
1415 
1416  PROCNAME("selReadStream");
1417 
1418  if (!fp)
1419  return (SEL *)ERROR_PTR("stream not defined", procName, NULL);
1420 
1421  if (fscanf(fp, " Sel Version %d\n", &version) != 1)
1422  return (SEL *)ERROR_PTR("not a sel file", procName, NULL);
1423  if (version != SEL_VERSION_NUMBER)
1424  return (SEL *)ERROR_PTR("invalid sel version", procName, NULL);
1425 
1426  if (fgets(linebuf, L_BUFSIZE, fp) == NULL)
1427  return (SEL *)ERROR_PTR("error reading into linebuf", procName, NULL);
1428  selname = stringNew(linebuf);
1429  sscanf(linebuf, " ------ %200s ------", selname);
1430 
1431  if (fscanf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n",
1432  &sy, &sx, &cy, &cx) != 4) {
1433  LEPT_FREE(selname);
1434  return (SEL *)ERROR_PTR("dimensions not read", procName, NULL);
1435  }
1436 
1437  if ((sel = selCreate(sy, sx, selname)) == NULL) {
1438  LEPT_FREE(selname);
1439  return (SEL *)ERROR_PTR("sel not made", procName, NULL);
1440  }
1441  selSetOrigin(sel, cy, cx);
1442 
1443  for (i = 0; i < sy; i++) {
1444  ignore = fscanf(fp, " ");
1445  for (j = 0; j < sx; j++)
1446  ignore = fscanf(fp, "%1d", &sel->data[i][j]);
1447  ignore = fscanf(fp, "\n");
1448  }
1449  ignore = fscanf(fp, "\n");
1450 
1451  LEPT_FREE(selname);
1452  return sel;
1453 }
1454 
1455 
1463 l_ok
1464 selaWrite(const char *fname,
1465  SELA *sela)
1466 {
1467 FILE *fp;
1468 
1469  PROCNAME("selaWrite");
1470 
1471  if (!fname)
1472  return ERROR_INT("fname not defined", procName, 1);
1473  if (!sela)
1474  return ERROR_INT("sela not defined", procName, 1);
1475 
1476  if ((fp = fopenWriteStream(fname, "wb")) == NULL)
1477  return ERROR_INT("stream not opened", procName, 1);
1478  selaWriteStream(fp, sela);
1479  fclose(fp);
1480 
1481  return 0;
1482 }
1483 
1484 
1492 l_ok
1494  SELA *sela)
1495 {
1496 l_int32 i, n;
1497 SEL *sel;
1498 
1499  PROCNAME("selaWriteStream");
1500 
1501  if (!fp)
1502  return ERROR_INT("stream not defined", procName, 1);
1503  if (!sela)
1504  return ERROR_INT("sela not defined", procName, 1);
1505 
1506  n = selaGetCount(sela);
1507  fprintf(fp, "\nSela Version %d\n", SEL_VERSION_NUMBER);
1508  fprintf(fp, "Number of Sels = %d\n\n", n);
1509  for (i = 0; i < n; i++) {
1510  if ((sel = selaGetSel(sela, i)) == NULL)
1511  continue;
1512  selWriteStream(fp, sel);
1513  }
1514  return 0;
1515 }
1516 
1517 
1525 l_ok
1526 selWrite(const char *fname,
1527  SEL *sel)
1528 {
1529 FILE *fp;
1530 
1531  PROCNAME("selWrite");
1532 
1533  if (!fname)
1534  return ERROR_INT("fname not defined", procName, 1);
1535  if (!sel)
1536  return ERROR_INT("sel not defined", procName, 1);
1537 
1538  if ((fp = fopenWriteStream(fname, "wb")) == NULL)
1539  return ERROR_INT("stream not opened", procName, 1);
1540  selWriteStream(fp, sel);
1541  fclose(fp);
1542 
1543  return 0;
1544 }
1545 
1546 
1554 l_ok
1556  SEL *sel)
1557 {
1558 l_int32 sx, sy, cx, cy, i, j;
1559 
1560  PROCNAME("selWriteStream");
1561 
1562  if (!fp)
1563  return ERROR_INT("stream not defined", procName, 1);
1564  if (!sel)
1565  return ERROR_INT("sel not defined", procName, 1);
1566  selGetParameters(sel, &sy, &sx, &cy, &cx);
1567 
1568  fprintf(fp, " Sel Version %d\n", SEL_VERSION_NUMBER);
1569  fprintf(fp, " ------ %s ------\n", selGetName(sel));
1570  fprintf(fp, " sy = %d, sx = %d, cy = %d, cx = %d\n", sy, sx, cy, cx);
1571  for (i = 0; i < sy; i++) {
1572  fprintf(fp, " ");
1573  for (j = 0; j < sx; j++)
1574  fprintf(fp, "%d", sel->data[i][j]);
1575  fprintf(fp, "\n");
1576  }
1577  fprintf(fp, "\n");
1578 
1579  return 0;
1580 }
1581 
1582 
1583 /*----------------------------------------------------------------------*
1584  * Building custom hit-miss sels from compiled strings *
1585  *----------------------------------------------------------------------*/
1615 SEL *
1616 selCreateFromString(const char *text,
1617  l_int32 h,
1618  l_int32 w,
1619  const char *name)
1620 {
1621 SEL *sel;
1622 l_int32 y, x, norig;
1623 char ch;
1624 
1625  PROCNAME("selCreateFromString");
1626 
1627  if (!text || text[0] == '\0')
1628  return (SEL *)ERROR_PTR("text undefined or empty", procName, NULL);
1629  if (h < 1)
1630  return (SEL *)ERROR_PTR("height must be > 0", procName, NULL);
1631  if (w < 1)
1632  return (SEL *)ERROR_PTR("width must be > 0", procName, NULL);
1633  if (strlen(text) != (size_t)w * h)
1634  return (SEL *)ERROR_PTR("text size != w * h", procName, NULL);
1635 
1636  sel = selCreate(h, w, name);
1637  norig = 0;
1638  for (y = 0; y < h; ++y) {
1639  for (x = 0; x < w; ++x) {
1640  ch = *(text++);
1641  switch (ch)
1642  {
1643  case 'X':
1644  norig++;
1645  selSetOrigin(sel, y, x);
1646  case 'x':
1647  selSetElement(sel, y, x, SEL_HIT);
1648  break;
1649 
1650  case 'O':
1651  norig++;
1652  selSetOrigin(sel, y, x);
1653  case 'o':
1654  selSetElement(sel, y, x, SEL_MISS);
1655  break;
1656 
1657  case 'C':
1658  norig++;
1659  selSetOrigin(sel, y, x);
1660  case ' ':
1661  selSetElement(sel, y, x, SEL_DONT_CARE);
1662  break;
1663 
1664  case '\n':
1665  /* ignored */
1666  continue;
1667 
1668  default:
1669  selDestroy(&sel);
1670  return (SEL *)ERROR_PTR("unknown char", procName, NULL);
1671  }
1672  }
1673  }
1674  if (norig != 1) {
1675  L_ERROR("Exactly one origin must be specified; this string has %d\n",
1676  procName, norig);
1677  selDestroy(&sel);
1678  }
1679 
1680  return sel;
1681 }
1682 
1683 
1703 char *
1705 {
1706 char is_center;
1707 char *str, *strptr;
1708 l_int32 type;
1709 l_int32 sx, sy, cx, cy, x, y;
1710 
1711  PROCNAME("selPrintToString");
1712 
1713  if (!sel)
1714  return (char *)ERROR_PTR("sel not defined", procName, NULL);
1715 
1716  selGetParameters(sel, &sy, &sx, &cy, &cx);
1717  if ((str = (char *)LEPT_CALLOC(1, sy * (sx + 1) + 1)) == NULL)
1718  return (char *)ERROR_PTR("calloc fail for str", procName, NULL);
1719  strptr = str;
1720 
1721  for (y = 0; y < sy; ++y) {
1722  for (x = 0; x < sx; ++x) {
1723  selGetElement(sel, y, x, &type);
1724  is_center = (x == cx && y == cy);
1725  switch (type) {
1726  case SEL_HIT:
1727  *(strptr++) = is_center ? 'X' : 'x';
1728  break;
1729  case SEL_MISS:
1730  *(strptr++) = is_center ? 'O' : 'o';
1731  break;
1732  case SEL_DONT_CARE:
1733  *(strptr++) = is_center ? 'C' : ' ';
1734  break;
1735  }
1736  }
1737  *(strptr++) = '\n';
1738  }
1739 
1740  return str;
1741 }
1742 
1743 
1744 /*----------------------------------------------------------------------*
1745  * Building custom hit-miss sels from a simple file format *
1746  *----------------------------------------------------------------------*/
1778 SELA *
1779 selaCreateFromFile(const char *filename)
1780 {
1781 char *filestr, *line;
1782 l_int32 i, n, first, last, nsel, insel;
1783 size_t nbytes;
1784 NUMA *nafirst, *nalast;
1785 SARRAY *sa;
1786 SEL *sel;
1787 SELA *sela;
1788 
1789  PROCNAME("selaCreateFromFile");
1790 
1791  if (!filename)
1792  return (SELA *)ERROR_PTR("filename not defined", procName, NULL);
1793 
1794  filestr = (char *)l_binaryRead(filename, &nbytes);
1795  sa = sarrayCreateLinesFromString(filestr, 1);
1796  LEPT_FREE(filestr);
1797  n = sarrayGetCount(sa);
1798  sela = selaCreate(0);
1799 
1800  /* Find the start and end lines for each Sel.
1801  * We allow the "blank" lines to be null strings or
1802  * to have standard whitespace (' ','\t',\'n') or be '#'. */
1803  nafirst = numaCreate(0);
1804  nalast = numaCreate(0);
1805  insel = FALSE;
1806  for (i = 0; i < n; i++) {
1807  line = sarrayGetString(sa, i, L_NOCOPY);
1808  if (!insel &&
1809  (line[0] != '\0' && line[0] != ' ' &&
1810  line[0] != '\t' && line[0] != '\n' && line[0] != '#')) {
1811  numaAddNumber(nafirst, i);
1812  insel = TRUE;
1813  continue;
1814  }
1815  if (insel &&
1816  (line[0] == '\0' || line[0] == ' ' ||
1817  line[0] == '\t' || line[0] == '\n' || line[0] == '#')) {
1818  numaAddNumber(nalast, i - 1);
1819  insel = FALSE;
1820  continue;
1821  }
1822  }
1823  if (insel) /* fell off the end of the file */
1824  numaAddNumber(nalast, n - 1);
1825 
1826  /* Extract sels */
1827  nsel = numaGetCount(nafirst);
1828  for (i = 0; i < nsel; i++) {
1829  numaGetIValue(nafirst, i, &first);
1830  numaGetIValue(nalast, i, &last);
1831  if ((sel = selCreateFromSArray(sa, first, last)) == NULL) {
1832  fprintf(stderr, "Error reading sel from %d to %d\n", first, last);
1833  selaDestroy(&sela);
1834  sarrayDestroy(&sa);
1835  numaDestroy(&nafirst);
1836  numaDestroy(&nalast);
1837  return (SELA *)ERROR_PTR("bad sela file", procName, NULL);
1838  }
1839  selaAddSel(sela, sel, NULL, 0);
1840  }
1841 
1842  numaDestroy(&nafirst);
1843  numaDestroy(&nalast);
1844  sarrayDestroy(&sa);
1845  return sela;
1846 }
1847 
1848 
1879 static SEL *
1881  l_int32 first,
1882  l_int32 last)
1883 {
1884 char ch;
1885 char *name, *line;
1886 l_int32 n, len, i, w, h, y, x;
1887 SEL *sel;
1888 
1889  PROCNAME("selCreateFromSArray");
1890 
1891  if (!sa)
1892  return (SEL *)ERROR_PTR("sa not defined", procName, NULL);
1893  n = sarrayGetCount(sa);
1894  if (first < 0 || first >= n || last <= first || last >= n)
1895  return (SEL *)ERROR_PTR("invalid range", procName, NULL);
1896 
1897  name = sarrayGetString(sa, first, L_NOCOPY);
1898  h = last - first;
1899  line = sarrayGetString(sa, first + 1, L_NOCOPY);
1900  len = strlen(line);
1901  if (line[0] != '"' || line[len - 1] != '"')
1902  return (SEL *)ERROR_PTR("invalid format", procName, NULL);
1903  w = len - 2;
1904  if ((sel = selCreate(h, w, name)) == NULL)
1905  return (SEL *)ERROR_PTR("sel not made", procName, NULL);
1906  for (i = first + 1; i <= last; i++) {
1907  line = sarrayGetString(sa, i, L_NOCOPY);
1908  y = i - first - 1;
1909  for (x = 0; x < w; ++x) {
1910  ch = line[x + 1]; /* skip the leading double-quote */
1911  switch (ch)
1912  {
1913  case 'X':
1914  selSetOrigin(sel, y, x); /* set origin and hit */
1915  case 'x':
1916  selSetElement(sel, y, x, SEL_HIT);
1917  break;
1918 
1919  case 'O':
1920  selSetOrigin(sel, y, x); /* set origin and miss */
1921  case 'o':
1922  selSetElement(sel, y, x, SEL_MISS);
1923  break;
1924 
1925  case 'C':
1926  selSetOrigin(sel, y, x); /* set origin and don't-care */
1927  case ' ':
1928  selSetElement(sel, y, x, SEL_DONT_CARE);
1929  break;
1930 
1931  default:
1932  selDestroy(&sel);
1933  return (SEL *)ERROR_PTR("unknown char", procName, NULL);
1934  }
1935  }
1936  }
1937 
1938  return sel;
1939 }
1940 
1941 
1942 /*----------------------------------------------------------------------*
1943  * Making hit-only SELs from Pta and Pix *
1944  *----------------------------------------------------------------------*/
1958 SEL *
1960  l_int32 cy,
1961  l_int32 cx,
1962  const char *name)
1963 {
1964 l_int32 i, n, x, y, w, h;
1965 BOX *box;
1966 SEL *sel;
1967 
1968  PROCNAME("selCreateFromPta");
1969 
1970  if (!pta)
1971  return (SEL *)ERROR_PTR("pta not defined", procName, NULL);
1972  if (cy < 0 || cx < 0)
1973  return (SEL *)ERROR_PTR("(cy, cx) not both >= 0", procName, NULL);
1974  n = ptaGetCount(pta);
1975  if (n == 0)
1976  return (SEL *)ERROR_PTR("no pts in pta", procName, NULL);
1977 
1978  box = ptaGetBoundingRegion(pta);
1979  boxGetGeometry(box, &x, &y, &w, &h);
1980  boxDestroy(&box);
1981  if (x < 0 || y < 0)
1982  return (SEL *)ERROR_PTR("not all x and y >= 0", procName, NULL);
1983 
1984  sel = selCreate(y + h, x + w, name);
1985  selSetOrigin(sel, cy, cx);
1986  for (i = 0; i < n; i++) {
1987  ptaGetIPt(pta, i, &x, &y);
1988  selSetElement(sel, y, x, SEL_HIT);
1989  }
1990 
1991  return sel;
1992 }
1993 
1994 
2008 SEL *
2010  l_int32 cy,
2011  l_int32 cx,
2012  const char *name)
2013 {
2014 SEL *sel;
2015 l_int32 i, j, w, h, d;
2016 l_uint32 val;
2017 
2018  PROCNAME("selCreateFromPix");
2019 
2020  if (!pix)
2021  return (SEL *)ERROR_PTR("pix not defined", procName, NULL);
2022  if (cy < 0 || cx < 0)
2023  return (SEL *)ERROR_PTR("(cy, cx) not both >= 0", procName, NULL);
2024  pixGetDimensions(pix, &w, &h, &d);
2025  if (d != 1)
2026  return (SEL *)ERROR_PTR("pix not 1 bpp", procName, NULL);
2027 
2028  sel = selCreate(h, w, name);
2029  selSetOrigin(sel, cy, cx);
2030  for (i = 0; i < h; i++) {
2031  for (j = 0; j < w; j++) {
2032  pixGetPixel(pix, j, i, &val);
2033  if (val)
2034  selSetElement(sel, i, j, SEL_HIT);
2035  }
2036  }
2037 
2038  return sel;
2039 }
2040 
2041 
2042 /*----------------------------------------------------------------------*
2043  * Making hit-miss sels from color Pix and image files *
2044  *----------------------------------------------------------------------*/
2059 SEL *
2060 selReadFromColorImage(const char *pathname)
2061 {
2062 PIX *pix;
2063 SEL *sel;
2064 char *basename, *selname;
2065 
2066  PROCNAME("selReadFromColorImage");
2067 
2068  splitPathAtExtension (pathname, &basename, NULL);
2069  splitPathAtDirectory (basename, NULL, &selname);
2070  LEPT_FREE(basename);
2071 
2072  if ((pix = pixRead(pathname)) == NULL) {
2073  LEPT_FREE(selname);
2074  return (SEL *)ERROR_PTR("pix not returned", procName, NULL);
2075  }
2076  if ((sel = selCreateFromColorPix(pix, selname)) == NULL)
2077  L_ERROR("sel not made\n", procName);
2078 
2079  LEPT_FREE(selname);
2080  pixDestroy(&pix);
2081  return sel;
2082 }
2083 
2084 
2108 SEL *
2110  const char *selname)
2111 {
2112 PIXCMAP *cmap;
2113 SEL *sel;
2114 l_int32 hascolor, hasorigin, nohits;
2115 l_int32 w, h, d, i, j, red, green, blue;
2116 l_uint32 pixval;
2117 
2118  PROCNAME("selCreateFromColorPix");
2119 
2120  if (!pixs)
2121  return (SEL *)ERROR_PTR("pixs not defined", procName, NULL);
2122 
2123  hascolor = FALSE;
2124  cmap = pixGetColormap(pixs);
2125  if (cmap)
2126  pixcmapHasColor(cmap, &hascolor);
2127  pixGetDimensions(pixs, &w, &h, &d);
2128  if (hascolor == FALSE && d != 32)
2129  return (SEL *)ERROR_PTR("pixs has no color", procName, NULL);
2130 
2131  if ((sel = selCreate (h, w, NULL)) == NULL)
2132  return (SEL *)ERROR_PTR ("sel not made", procName, NULL);
2133  selSetOrigin (sel, h / 2, w / 2);
2134  selSetName(sel, selname);
2135 
2136  hasorigin = FALSE;
2137  nohits = TRUE;
2138  for (i = 0; i < h; i++) {
2139  for (j = 0; j < w; j++) {
2140  pixGetPixel (pixs, j, i, &pixval);
2141 
2142  if (cmap) {
2143  pixcmapGetColor (cmap, pixval, &red, &green, &blue);
2144  } else {
2145  red = GET_DATA_BYTE (&pixval, COLOR_RED);
2146  green = GET_DATA_BYTE (&pixval, COLOR_GREEN);
2147  blue = GET_DATA_BYTE (&pixval, COLOR_BLUE);
2148  }
2149 
2150  if (red < 255 && green < 255 && blue < 255) {
2151  if (hasorigin)
2152  L_WARNING("multiple origins in sel image\n", procName);
2153  selSetOrigin (sel, i, j);
2154  hasorigin = TRUE;
2155  }
2156  if (!red && green && !blue) {
2157  nohits = FALSE;
2158  selSetElement (sel, i, j, SEL_HIT);
2159  } else if (red && !green && !blue) {
2160  selSetElement (sel, i, j, SEL_MISS);
2161  } else if (red && green && blue) {
2162  selSetElement (sel, i, j, SEL_DONT_CARE);
2163  } else {
2164  selDestroy(&sel);
2165  return (SEL *)ERROR_PTR("invalid color", procName, NULL);
2166  }
2167  }
2168  }
2169 
2170  if (nohits) {
2171  selDestroy(&sel);
2172  return (SEL *)ERROR_PTR("no hits in sel", procName, NULL);
2173  }
2174  return sel;
2175 }
2176 
2177 
2178 /*----------------------------------------------------------------------*
2179  * Printable display of sel *
2180  *----------------------------------------------------------------------*/
2199 PIX *
2201  l_int32 size,
2202  l_int32 gthick)
2203 {
2204 l_int32 i, j, w, h, sx, sy, cx, cy, type, width;
2205 l_int32 radius1, radius2, shift1, shift2, x0, y0;
2206 PIX *pixd, *pix2, *pixh, *pixm, *pixorig;
2207 PTA *pta1, *pta2, *pta1t, *pta2t;
2208 
2209  PROCNAME("selDisplayInPix");
2210 
2211  if (!sel)
2212  return (PIX *)ERROR_PTR("sel not defined", procName, NULL);
2213  if (size < 13) {
2214  L_WARNING("size < 13; setting to 13\n", procName);
2215  size = 13;
2216  }
2217  if (size % 2 == 0)
2218  size++;
2219  if (gthick < 2) {
2220  L_WARNING("grid thickness < 2; setting to 2\n", procName);
2221  gthick = 2;
2222  }
2223  selGetParameters(sel, &sy, &sx, &cy, &cx);
2224  w = size * sx + gthick * (sx + 1);
2225  h = size * sy + gthick * (sy + 1);
2226  pixd = pixCreate(w, h, 1);
2227 
2228  /* Generate grid lines */
2229  for (i = 0; i <= sy; i++)
2230  pixRenderLine(pixd, 0, gthick / 2 + i * (size + gthick),
2231  w - 1, gthick / 2 + i * (size + gthick),
2232  gthick, L_SET_PIXELS);
2233  for (j = 0; j <= sx; j++)
2234  pixRenderLine(pixd, gthick / 2 + j * (size + gthick), 0,
2235  gthick / 2 + j * (size + gthick), h - 1,
2236  gthick, L_SET_PIXELS);
2237 
2238  /* Generate hit and miss patterns */
2239  radius1 = (l_int32)(0.85 * ((size - 1) / 2.0) + 0.5); /* of hit */
2240  radius2 = (l_int32)(0.65 * ((size - 1) / 2.0) + 0.5); /* of inner miss */
2241  pta1 = generatePtaFilledCircle(radius1);
2242  pta2 = generatePtaFilledCircle(radius2);
2243  shift1 = (size - 1) / 2 - radius1; /* center circle in square */
2244  shift2 = (size - 1) / 2 - radius2;
2245  pta1t = ptaTransform(pta1, shift1, shift1, 1.0, 1.0);
2246  pta2t = ptaTransform(pta2, shift2, shift2, 1.0, 1.0);
2247  pixh = pixGenerateFromPta(pta1t, size, size); /* hits */
2248  pix2 = pixGenerateFromPta(pta2t, size, size);
2249  pixm = pixSubtract(NULL, pixh, pix2);
2250 
2251  /* Generate crossed lines for origin pattern */
2252  pixorig = pixCreate(size, size, 1);
2253  width = size / 8;
2254  pixRenderLine(pixorig, size / 2, (l_int32)(0.12 * size),
2255  size / 2, (l_int32)(0.88 * size),
2256  width, L_SET_PIXELS);
2257  pixRenderLine(pixorig, (l_int32)(0.15 * size), size / 2,
2258  (l_int32)(0.85 * size), size / 2,
2259  width, L_FLIP_PIXELS);
2260  pixRasterop(pixorig, size / 2 - width, size / 2 - width,
2261  2 * width, 2 * width, PIX_NOT(PIX_DST), NULL, 0, 0);
2262 
2263  /* Specialize origin pattern for this sel */
2264  selGetTypeAtOrigin(sel, &type);
2265  if (type == SEL_HIT)
2266  pixXor(pixorig, pixorig, pixh);
2267  else if (type == SEL_MISS)
2268  pixXor(pixorig, pixorig, pixm);
2269 
2270  /* Paste the patterns in */
2271  y0 = gthick;
2272  for (i = 0; i < sy; i++) {
2273  x0 = gthick;
2274  for (j = 0; j < sx; j++) {
2275  selGetElement(sel, i, j, &type);
2276  if (i == cy && j == cx) /* origin */
2277  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixorig, 0, 0);
2278  else if (type == SEL_HIT)
2279  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixh, 0, 0);
2280  else if (type == SEL_MISS)
2281  pixRasterop(pixd, x0, y0, size, size, PIX_SRC, pixm, 0, 0);
2282  x0 += size + gthick;
2283  }
2284  y0 += size + gthick;
2285  }
2286 
2287  pixDestroy(&pix2);
2288  pixDestroy(&pixh);
2289  pixDestroy(&pixm);
2290  pixDestroy(&pixorig);
2291  ptaDestroy(&pta1);
2292  ptaDestroy(&pta1t);
2293  ptaDestroy(&pta2);
2294  ptaDestroy(&pta2t);
2295  return pixd;
2296 }
2297 
2298 
2317 PIX *
2319  l_int32 size,
2320  l_int32 gthick,
2321  l_int32 spacing,
2322  l_int32 ncols)
2323 {
2324 l_int32 nsels, i, w, width;
2325 PIX *pixt, *pixd;
2326 PIXA *pixa;
2327 SEL *sel;
2328 
2329  PROCNAME("selaDisplayInPix");
2330 
2331  if (!sela)
2332  return (PIX *)ERROR_PTR("sela not defined", procName, NULL);
2333  if (size < 13) {
2334  L_WARNING("size < 13; setting to 13\n", procName);
2335  size = 13;
2336  }
2337  if (size % 2 == 0)
2338  size++;
2339  if (gthick < 2) {
2340  L_WARNING("grid thickness < 2; setting to 2\n", procName);
2341  gthick = 2;
2342  }
2343  if (spacing < 5) {
2344  L_WARNING("spacing < 5; setting to 5\n", procName);
2345  spacing = 5;
2346  }
2347 
2348  /* Accumulate the pix of each sel */
2349  nsels = selaGetCount(sela);
2350  pixa = pixaCreate(nsels);
2351  for (i = 0; i < nsels; i++) {
2352  sel = selaGetSel(sela, i);
2353  pixt = selDisplayInPix(sel, size, gthick);
2354  pixaAddPix(pixa, pixt, L_INSERT);
2355  }
2356 
2357  /* Find the tiled output width, using just the first
2358  * ncols pix in the pixa. If all pix have the same width,
2359  * they will align properly in columns. */
2360  width = 0;
2361  ncols = L_MIN(nsels, ncols);
2362  for (i = 0; i < ncols; i++) {
2363  pixt = pixaGetPix(pixa, i, L_CLONE);
2364  pixGetDimensions(pixt, &w, NULL, NULL);
2365  width += w;
2366  pixDestroy(&pixt);
2367  }
2368  width += (ncols + 1) * spacing; /* add spacing all around as well */
2369 
2370  pixd = pixaDisplayTiledInRows(pixa, 1, width, 1.0, 0, spacing, 0);
2371  pixaDestroy(&pixa);
2372  return pixd;
2373 }
l_ok selSetOrigin(SEL *sel, l_int32 cy, l_int32 cx)
selSetOrigin()
Definition: sel1.c:880
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1092
l_ok selWriteStream(FILE *fp, SEL *sel)
selWriteStream()
Definition: sel1.c:1555
char * sarrayToString(SARRAY *sa, l_int32 addnlflag)
sarrayToString()
Definition: sarray1.c:763
Definition: pix.h:717
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2607
char * selaGetBrickName(SELA *sela, l_int32 hsize, l_int32 vsize)
selaGetBrickName()
Definition: sel1.c:937
PIX * pixGenerateFromPta(PTA *pta, l_int32 w, l_int32 h)
pixGenerateFromPta()
Definition: ptafunc1.c:1961
SEL * selCopy(SEL *sel)
selCopy()
Definition: sel1.c:370
SEL * selCreateFromColorPix(PIX *pixs, const char *selname)
Definition: sel1.c:2109
char * selaGetCombName(SELA *sela, l_int32 size, l_int32 direction)
selaGetCombName()
Definition: sel1.c:976
l_ok selSetName(SEL *sel, const char *name)
selSetName()
Definition: sel1.c:710
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
l_ok selaWrite(const char *fname, SELA *sela)
selaWrite()
Definition: sel1.c:1464
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
SEL * selRead(const char *fname)
selRead()
Definition: sel1.c:1380
Definition: pix.h:716
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:215
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:193
SEL * selReadStream(FILE *fp)
selReadStream()
Definition: sel1.c:1409
l_int32 nalloc
Definition: morph.h:77
l_int32 selaGetCount(SELA *sela)
selaGetCount()
Definition: sel1.c:639
l_ok selGetParameters(SEL *sel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
selGetParameters()
Definition: sel1.c:850
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:163
l_ok selaWriteStream(FILE *fp, SELA *sela)
selaWriteStream()
Definition: sel1.c:1493
SELA * selaCreateFromFile(const char *filename)
selaCreateFromFile()
Definition: sel1.c:1779
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:504
l_ok selFindMaxTranslations(SEL *sel, l_int32 *pxp, l_int32 *pyp, l_int32 *pxn, l_int32 *pyn)
selFindMaxTranslations()
Definition: sel1.c:1193
l_int32 sy
Definition: morph.h:64
l_int32 ** data
Definition: morph.h:68
void * reallocNew(void **pindata, l_int32 oldsize, l_int32 newsize)
reallocNew()
Definition: utils2.c:1161
SARRAY * selaGetSelnames(SELA *sela)
selaGetSelnames()
Definition: sel1.c:1148
void selaDestroy(SELA **psela)
selaDestroy()
Definition: sel1.c:272
Definition: array.h:116
SEL * selCreateFromPta(PTA *pta, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPta()
Definition: sel1.c:1959
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1429
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1212
l_ok selGetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 *ptype)
selGetElement()
Definition: sel1.c:781
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
PIX * selDisplayInPix(SEL *sel, l_int32 size, l_int32 gthick)
selDisplayInPix()
Definition: sel1.c:2200
Definition: array.h:59
l_int32 ** create2dIntArray(l_int32 sy, l_int32 sx)
create2dIntArray()
Definition: sel1.c:515
char * selPrintToString(SEL *sel)
selPrintToString()
Definition: sel1.c:1704
char * name
Definition: morph.h:69
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1574
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:631
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:446
l_int32 sx
Definition: morph.h:65
SELA * selaAddDwaCombs(SELA *sela)
selaAddDwaCombs()
Definition: sel2.c:361
void selDestroy(SEL **psel)
selDestroy()
Definition: sel1.c:337
l_ok selaFindSelByName(SELA *sela, const char *name, l_int32 *pindex, SEL **psel)
selaFindSelByName()
Definition: sel1.c:732
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:836
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:751
SEL * selCreateComb(l_int32 factor1, l_int32 factor2, l_int32 direction)
selCreateComb()
Definition: sel1.c:462
SEL * selCreate(l_int32 height, l_int32 width, const char *name)
selCreate()
Definition: sel1.c:306
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:681
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtract()
Definition: pix3.c:1639
l_ok stringReplace(char **pdest, const char *src)
stringReplace()
Definition: utils2.c:337
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
static l_int32 selaExtendArray(SELA *sela)
selaExtendArray()
Definition: sel1.c:611
l_int32 cx
Definition: morph.h:67
l_ok selWrite(const char *fname, SEL *sel)
selWrite()
Definition: sel1.c:1526
l_int32 cy
Definition: morph.h:66
SELA * selaRead(const char *fname)
selaRead()
Definition: sel1.c:1310
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1002
BOX * ptaGetBoundingRegion(PTA *pta)
ptaGetBoundingRegion()
Definition: ptafunc1.c:439
SARRAY * sarrayCreateLinesFromString(const char *string, l_int32 blankflag)
sarrayCreateLinesFromString()
Definition: sarray1.c:276
Definition: pix.h:454
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:1483
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2540
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:180
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1700
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1657
l_int32 n
Definition: morph.h:76
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:621
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:190
l_ok getCompositeParameters(l_int32 size, l_int32 *psize1, l_int32 *psize2, char **pnameh1, char **pnameh2, char **pnamev1, char **pnamev2)
getCompositeParameters()
Definition: sel1.c:1104
char * selGetName(SEL *sel)
selGetName()
Definition: sel1.c:685
SELA * selaCreate(l_int32 n)
selaCreate()
Definition: sel1.c:239
l_ok selaAddSel(SELA *sela, SEL *sel, const char *selname, l_int32 copyflag)
selaAddSel()
Definition: sel1.c:566
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:672
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:92
Definition: pix.h:718
#define PIX_NOT(op)
Definition: pix.h:329
Definition: pix.h:134
Definition: pix.h:719
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:192
struct Sel ** sel
Definition: morph.h:78
#define PIX_SRC
Definition: pix.h:327
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
Definition: pix.h:201
SEL * selRotateOrth(SEL *sel, l_int32 quads)
selRotateOrth()
Definition: sel1.c:1243
PTA * ptaTransform(PTA *ptas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley)
ptaTransform()
Definition: ptafunc1.c:735
l_ok selGetTypeAtOrigin(SEL *sel, l_int32 *ptype)
selGetTypeAtOrigin()
Definition: sel1.c:902
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:555
SEL * selaGetSel(SELA *sela, l_int32 i)
selaGetSel()
Definition: sel1.c:664
Definition: morph.h:74
PTA * generatePtaFilledCircle(l_int32 radius)
generatePtaFilledCircle()
Definition: graphics.c:823
SEL * selCreateFromPix(PIX *pix, l_int32 cy, l_int32 cx, const char *name)
selCreateFromPix()
Definition: sel1.c:2009
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:310
Definition: pix.h:480
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
static SEL * selCreateFromSArray(SARRAY *sa, l_int32 first, l_int32 last)
selCreateFromSArray()
Definition: sel1.c:1880
SELA * selaReadStream(FILE *fp)
selaReadStream()
Definition: sel1.c:1339
PIX * selaDisplayInPix(SELA *sela, l_int32 size, l_int32 gthick, l_int32 spacing, l_int32 ncols)
selaDisplayInPix()
Definition: sel1.c:2318
Definition: pix.h:517
l_ok selSetElement(SEL *sel, l_int32 row, l_int32 col, l_int32 type)
selSetElement()
Definition: sel1.c:821
#define PIX_DST
Definition: pix.h:328
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:355
SEL * selCreateFromString(const char *text, l_int32 h, l_int32 w, const char *name)
selCreateFromString()
Definition: sel1.c:1616
SEL * selReadFromColorImage(const char *pathname)
Definition: sel1.c:2060