Leptonica  1.82.0
Image processing and image analysis suite
morph.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 
165 #ifdef HAVE_CONFIG_H
166 #include <config_auto.h>
167 #endif /* HAVE_CONFIG_H */
168 
169 #include <math.h>
170 #include "allheaders.h"
171 
172  /* Global constant; initialized here; must be declared extern
173  * in other files to access it directly. However, in most
174  * cases that is not necessary, because it can be reset
175  * using resetMorphBoundaryCondition(). */
176 LEPT_DLL l_int32 MORPH_BC = ASYMMETRIC_MORPH_BC;
177 
178  /* We accept this cost in extra rasterops for decomposing exactly. */
179 static const l_int32 ACCEPTABLE_COST = 5;
180 
181  /* Static helpers for arg processing */
182 static PIX * processMorphArgs1(PIX *pixd, PIX *pixs, SEL *sel, PIX **ppixt);
183 static PIX * processMorphArgs2(PIX *pixd, PIX *pixs, SEL *sel);
184 
185 
186 /*-----------------------------------------------------------------*
187  * Generic binary morphological ops implemented with rasterop *
188  *-----------------------------------------------------------------*/
212 PIX *
214  PIX *pixs,
215  SEL *sel)
216 {
217 l_int32 i, j, w, h, sx, sy, cx, cy, seldata;
218 PIX *pixt;
219 
220  PROCNAME("pixDilate");
221 
222  if ((pixd = processMorphArgs1(pixd, pixs, sel, &pixt)) == NULL)
223  return (PIX *)ERROR_PTR("processMorphArgs1 failed", procName, pixd);
224 
225  pixGetDimensions(pixs, &w, &h, NULL);
226  selGetParameters(sel, &sy, &sx, &cy, &cx);
227  pixClearAll(pixd);
228  for (i = 0; i < sy; i++) {
229  for (j = 0; j < sx; j++) {
230  seldata = sel->data[i][j];
231  if (seldata == 1) { /* src | dst */
232  pixRasterop(pixd, j - cx, i - cy, w, h, PIX_SRC | PIX_DST,
233  pixt, 0, 0);
234  }
235  }
236  }
237 
238  pixDestroy(&pixt);
239  return pixd;
240 }
241 
242 
266 PIX *
267 pixErode(PIX *pixd,
268  PIX *pixs,
269  SEL *sel)
270 {
271 l_int32 i, j, w, h, sx, sy, cx, cy, seldata;
272 l_int32 xp, yp, xn, yn;
273 PIX *pixt;
274 
275  PROCNAME("pixErode");
276 
277  if ((pixd = processMorphArgs1(pixd, pixs, sel, &pixt)) == NULL)
278  return (PIX *)ERROR_PTR("processMorphArgs1 failed", procName, pixd);
279 
280  pixGetDimensions(pixs, &w, &h, NULL);
281  selGetParameters(sel, &sy, &sx, &cy, &cx);
282  pixSetAll(pixd);
283  for (i = 0; i < sy; i++) {
284  for (j = 0; j < sx; j++) {
285  seldata = sel->data[i][j];
286  if (seldata == 1) { /* src & dst */
287  pixRasterop(pixd, cx - j, cy - i, w, h, PIX_SRC & PIX_DST,
288  pixt, 0, 0);
289  }
290  }
291  }
292 
293  /* Clear near edges. We do this for the asymmetric boundary
294  * condition convention that implements erosion assuming all
295  * pixels surrounding the image are OFF. If you use a
296  * use a symmetric b.c. convention, where the erosion is
297  * implemented assuming pixels surrounding the image
298  * are ON, these operations are omitted. */
299  if (MORPH_BC == ASYMMETRIC_MORPH_BC) {
300  selFindMaxTranslations(sel, &xp, &yp, &xn, &yn);
301  if (xp > 0)
302  pixRasterop(pixd, 0, 0, xp, h, PIX_CLR, NULL, 0, 0);
303  if (xn > 0)
304  pixRasterop(pixd, w - xn, 0, xn, h, PIX_CLR, NULL, 0, 0);
305  if (yp > 0)
306  pixRasterop(pixd, 0, 0, w, yp, PIX_CLR, NULL, 0, 0);
307  if (yn > 0)
308  pixRasterop(pixd, 0, h - yn, w, yn, PIX_CLR, NULL, 0, 0);
309  }
310 
311  pixDestroy(&pixt);
312  return pixd;
313 }
314 
315 
341 PIX *
342 pixHMT(PIX *pixd,
343  PIX *pixs,
344  SEL *sel)
345 {
346 l_int32 i, j, w, h, sx, sy, cx, cy, firstrasterop, seldata;
347 l_int32 xp, yp, xn, yn;
348 PIX *pixt;
349 
350  PROCNAME("pixHMT");
351 
352  if ((pixd = processMorphArgs1(pixd, pixs, sel, &pixt)) == NULL)
353  return (PIX *)ERROR_PTR("processMorphArgs1 failed", procName, pixd);
354 
355  pixGetDimensions(pixs, &w, &h, NULL);
356  selGetParameters(sel, &sy, &sx, &cy, &cx);
357  firstrasterop = TRUE;
358  for (i = 0; i < sy; i++) {
359  for (j = 0; j < sx; j++) {
360  seldata = sel->data[i][j];
361  if (seldata == 1) { /* hit */
362  if (firstrasterop == TRUE) { /* src only */
363  pixClearAll(pixd);
364  pixRasterop(pixd, cx - j, cy - i, w, h, PIX_SRC,
365  pixt, 0, 0);
366  firstrasterop = FALSE;
367  } else { /* src & dst */
368  pixRasterop(pixd, cx - j, cy - i, w, h, PIX_SRC & PIX_DST,
369  pixt, 0, 0);
370  }
371  } else if (seldata == 2) { /* miss */
372  if (firstrasterop == TRUE) { /* ~src only */
373  pixSetAll(pixd);
374  pixRasterop(pixd, cx - j, cy - i, w, h, PIX_NOT(PIX_SRC),
375  pixt, 0, 0);
376  firstrasterop = FALSE;
377  } else { /* ~src & dst */
378  pixRasterop(pixd, cx - j, cy - i, w, h,
380  pixt, 0, 0);
381  }
382  }
383  }
384  }
385 
386  /* Clear near edges */
387  selFindMaxTranslations(sel, &xp, &yp, &xn, &yn);
388  if (xp > 0)
389  pixRasterop(pixd, 0, 0, xp, h, PIX_CLR, NULL, 0, 0);
390  if (xn > 0)
391  pixRasterop(pixd, w - xn, 0, xn, h, PIX_CLR, NULL, 0, 0);
392  if (yp > 0)
393  pixRasterop(pixd, 0, 0, w, yp, PIX_CLR, NULL, 0, 0);
394  if (yn > 0)
395  pixRasterop(pixd, 0, h - yn, w, yn, PIX_CLR, NULL, 0, 0);
396 
397  pixDestroy(&pixt);
398  return pixd;
399 }
400 
401 
425 PIX *
426 pixOpen(PIX *pixd,
427  PIX *pixs,
428  SEL *sel)
429 {
430 PIX *pixt;
431 
432  PROCNAME("pixOpen");
433 
434  if ((pixd = processMorphArgs2(pixd, pixs, sel)) == NULL)
435  return (PIX *)ERROR_PTR("pixd not returned", procName, pixd);
436 
437  if ((pixt = pixErode(NULL, pixs, sel)) == NULL)
438  return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
439  pixDilate(pixd, pixt, sel);
440  pixDestroy(&pixt);
441 
442  return pixd;
443 }
444 
445 
472 PIX *
473 pixClose(PIX *pixd,
474  PIX *pixs,
475  SEL *sel)
476 {
477 PIX *pixt;
478 
479  PROCNAME("pixClose");
480 
481  if ((pixd = processMorphArgs2(pixd, pixs, sel)) == NULL)
482  return (PIX *)ERROR_PTR("pixd not returned", procName, pixd);
483 
484  if ((pixt = pixDilate(NULL, pixs, sel)) == NULL)
485  return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
486  pixErode(pixd, pixt, sel);
487  pixDestroy(&pixt);
488 
489  return pixd;
490 }
491 
492 
523 PIX *
525  PIX *pixs,
526  SEL *sel)
527 {
528 l_int32 xp, yp, xn, yn, xmax, xbord;
529 PIX *pixt1, *pixt2;
530 
531  PROCNAME("pixCloseSafe");
532 
533  if (!pixs)
534  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
535  if (!sel)
536  return (PIX *)ERROR_PTR("sel not defined", procName, pixd);
537  if (pixGetDepth(pixs) != 1)
538  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
539 
540  /* Symmetric b.c. handles correctly without added pixels */
541  if (MORPH_BC == SYMMETRIC_MORPH_BC)
542  return pixClose(pixd, pixs, sel);
543 
544  selFindMaxTranslations(sel, &xp, &yp, &xn, &yn);
545  xmax = L_MAX(xp, xn);
546  xbord = 32 * ((xmax + 31) / 32); /* full 32 bit words */
547 
548  if ((pixt1 = pixAddBorderGeneral(pixs, xbord, xbord, yp, yn, 0)) == NULL)
549  return (PIX *)ERROR_PTR("pixt1 not made", procName, pixd);
550  pixClose(pixt1, pixt1, sel);
551  if ((pixt2 = pixRemoveBorderGeneral(pixt1, xbord, xbord, yp, yn)) == NULL)
552  return (PIX *)ERROR_PTR("pixt2 not made", procName, pixd);
553  pixDestroy(&pixt1);
554 
555  if (!pixd)
556  return pixt2;
557 
558  pixCopy(pixd, pixt2);
559  pixDestroy(&pixt2);
560  return pixd;
561 }
562 
563 
590 PIX *
592  PIX *pixs,
593  SEL *sel)
594 {
595 PIX *pixt;
596 
597  PROCNAME("pixOpenGeneralized");
598 
599  if ((pixd = processMorphArgs2(pixd, pixs, sel)) == NULL)
600  return (PIX *)ERROR_PTR("pixd not returned", procName, pixd);
601 
602  if ((pixt = pixHMT(NULL, pixs, sel)) == NULL)
603  return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
604  pixDilate(pixd, pixt, sel);
605  pixDestroy(&pixt);
606  return pixd;
607 }
608 
609 
637 PIX *
639  PIX *pixs,
640  SEL *sel)
641 {
642 PIX *pixt;
643 
644  PROCNAME("pixCloseGeneralized");
645 
646  if ((pixd = processMorphArgs2(pixd, pixs, sel)) == NULL)
647  return (PIX *)ERROR_PTR("pixd not returned", procName, pixd);
648 
649  if ((pixt = pixDilate(NULL, pixs, sel)) == NULL)
650  return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
651  pixHMT(pixd, pixt, sel);
652  pixDestroy(&pixt);
653 
654  return pixd;
655 }
656 
657 
658 /*-----------------------------------------------------------------*
659  * Binary morphological (raster) ops with brick Sels *
660  *-----------------------------------------------------------------*/
687 PIX *
689  PIX *pixs,
690  l_int32 hsize,
691  l_int32 vsize)
692 {
693 PIX *pixt;
694 SEL *sel, *selh, *selv;
695 
696  PROCNAME("pixDilateBrick");
697 
698  if (!pixs)
699  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
700  if (pixGetDepth(pixs) != 1)
701  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
702  if (hsize < 1 || vsize < 1)
703  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
704 
705  if (hsize == 1 && vsize == 1)
706  return pixCopy(pixd, pixs);
707  if (hsize == 1 || vsize == 1) { /* no intermediate result */
708  sel = selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
709  if (!sel)
710  return (PIX *)ERROR_PTR("sel not made", procName, pixd);
711  pixd = pixDilate(pixd, pixs, sel);
712  selDestroy(&sel);
713  } else {
714  if ((selh = selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
715  return (PIX *)ERROR_PTR("selh not made", procName, pixd);
716  if ((selv = selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
717  selDestroy(&selh);
718  return (PIX *)ERROR_PTR("selv not made", procName, pixd);
719  }
720  pixt = pixDilate(NULL, pixs, selh);
721  pixd = pixDilate(pixd, pixt, selv);
722  pixDestroy(&pixt);
723  selDestroy(&selh);
724  selDestroy(&selv);
725  }
726 
727  return pixd;
728 }
729 
730 
757 PIX *
759  PIX *pixs,
760  l_int32 hsize,
761  l_int32 vsize)
762 {
763 PIX *pixt;
764 SEL *sel, *selh, *selv;
765 
766  PROCNAME("pixErodeBrick");
767 
768  if (!pixs)
769  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
770  if (pixGetDepth(pixs) != 1)
771  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
772  if (hsize < 1 || vsize < 1)
773  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
774 
775  if (hsize == 1 && vsize == 1)
776  return pixCopy(pixd, pixs);
777  if (hsize == 1 || vsize == 1) { /* no intermediate result */
778  sel = selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
779  if (!sel)
780  return (PIX *)ERROR_PTR("sel not made", procName, pixd);
781  pixd = pixErode(pixd, pixs, sel);
782  selDestroy(&sel);
783  } else {
784  if ((selh = selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
785  return (PIX *)ERROR_PTR("selh not made", procName, pixd);
786  if ((selv = selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
787  selDestroy(&selh);
788  return (PIX *)ERROR_PTR("selv not made", procName, pixd);
789  }
790  pixt = pixErode(NULL, pixs, selh);
791  pixd = pixErode(pixd, pixt, selv);
792  pixDestroy(&pixt);
793  selDestroy(&selh);
794  selDestroy(&selv);
795  }
796 
797  return pixd;
798 }
799 
800 
827 PIX *
829  PIX *pixs,
830  l_int32 hsize,
831  l_int32 vsize)
832 {
833 PIX *pixt;
834 SEL *sel, *selh, *selv;
835 
836  PROCNAME("pixOpenBrick");
837 
838  if (!pixs)
839  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
840  if (pixGetDepth(pixs) != 1)
841  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
842  if (hsize < 1 || vsize < 1)
843  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
844 
845  if (hsize == 1 && vsize == 1)
846  return pixCopy(pixd, pixs);
847  if (hsize == 1 || vsize == 1) { /* no intermediate result */
848  sel = selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
849  if (!sel)
850  return (PIX *)ERROR_PTR("sel not made", procName, pixd);
851  pixd = pixOpen(pixd, pixs, sel);
852  selDestroy(&sel);
853  } else { /* do separably */
854  if ((selh = selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
855  return (PIX *)ERROR_PTR("selh not made", procName, pixd);
856  if ((selv = selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
857  selDestroy(&selh);
858  return (PIX *)ERROR_PTR("selv not made", procName, pixd);
859  }
860  pixt = pixErode(NULL, pixs, selh);
861  pixd = pixErode(pixd, pixt, selv);
862  pixDilate(pixt, pixd, selh);
863  pixDilate(pixd, pixt, selv);
864  pixDestroy(&pixt);
865  selDestroy(&selh);
866  selDestroy(&selv);
867  }
868 
869  return pixd;
870 }
871 
872 
899 PIX *
901  PIX *pixs,
902  l_int32 hsize,
903  l_int32 vsize)
904 {
905 PIX *pixt;
906 SEL *sel, *selh, *selv;
907 
908  PROCNAME("pixCloseBrick");
909 
910  if (!pixs)
911  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
912  if (pixGetDepth(pixs) != 1)
913  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
914  if (hsize < 1 || vsize < 1)
915  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
916 
917  if (hsize == 1 && vsize == 1)
918  return pixCopy(pixd, pixs);
919  if (hsize == 1 || vsize == 1) { /* no intermediate result */
920  sel = selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
921  if (!sel)
922  return (PIX *)ERROR_PTR("sel not made", procName, pixd);
923  pixd = pixClose(pixd, pixs, sel);
924  selDestroy(&sel);
925  } else { /* do separably */
926  if ((selh = selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
927  return (PIX *)ERROR_PTR("selh not made", procName, pixd);
928  if ((selv = selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
929  selDestroy(&selh);
930  return (PIX *)ERROR_PTR("selv not made", procName, pixd);
931  }
932  pixt = pixDilate(NULL, pixs, selh);
933  pixd = pixDilate(pixd, pixt, selv);
934  pixErode(pixt, pixd, selh);
935  pixErode(pixd, pixt, selv);
936  pixDestroy(&pixt);
937  selDestroy(&selh);
938  selDestroy(&selv);
939  }
940 
941  return pixd;
942 }
943 
944 
976 PIX *
978  PIX *pixs,
979  l_int32 hsize,
980  l_int32 vsize)
981 {
982 l_int32 maxtrans, bordsize;
983 PIX *pixsb, *pixt, *pixdb;
984 SEL *sel, *selh, *selv;
985 
986  PROCNAME("pixCloseSafeBrick");
987 
988  if (!pixs)
989  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
990  if (pixGetDepth(pixs) != 1)
991  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
992  if (hsize < 1 || vsize < 1)
993  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
994 
995  if (hsize == 1 && vsize == 1)
996  return pixCopy(pixd, pixs);
997 
998  /* Symmetric b.c. handles correctly without added pixels */
999  if (MORPH_BC == SYMMETRIC_MORPH_BC)
1000  return pixCloseBrick(pixd, pixs, hsize, vsize);
1001 
1002  maxtrans = L_MAX(hsize / 2, vsize / 2);
1003  bordsize = 32 * ((maxtrans + 31) / 32); /* full 32 bit words */
1004  pixsb = pixAddBorder(pixs, bordsize, 0);
1005 
1006  if (hsize == 1 || vsize == 1) { /* no intermediate result */
1007  sel = selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
1008  if (!sel) {
1009  pixDestroy(&pixsb);
1010  return (PIX *)ERROR_PTR("sel not made", procName, pixd);
1011  }
1012  pixdb = pixClose(NULL, pixsb, sel);
1013  selDestroy(&sel);
1014  } else { /* do separably */
1015  selh = selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT);
1016  selv = selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT);
1017  if (!selh || !selv) {
1018  selDestroy(&selh);
1019  selDestroy(&selv);
1020  pixDestroy(&pixsb);
1021  return (PIX *)ERROR_PTR("selh and selv not both made",
1022  procName, pixd);
1023  }
1024  pixt = pixDilate(NULL, pixsb, selh);
1025  pixdb = pixDilate(NULL, pixt, selv);
1026  pixErode(pixt, pixdb, selh);
1027  pixErode(pixdb, pixt, selv);
1028  pixDestroy(&pixt);
1029  selDestroy(&selh);
1030  selDestroy(&selv);
1031  }
1032 
1033  pixt = pixRemoveBorder(pixdb, bordsize);
1034  pixDestroy(&pixsb);
1035  pixDestroy(&pixdb);
1036 
1037  if (!pixd) {
1038  pixd = pixt;
1039  } else {
1040  pixCopy(pixd, pixt);
1041  pixDestroy(&pixt);
1042  }
1043  return pixd;
1044 }
1045 
1046 
1047 /*-----------------------------------------------------------------*
1048  * Binary composed morphological (raster) ops with brick Sels *
1049  *-----------------------------------------------------------------*/
1050 /* \brief selectComposableSels()
1051  *
1052  * \param[in] size of composed sel
1053  * \param[in] direction L_HORIZ, L_VERT
1054  * \param[out] psel1 [optional] contiguous sel; can be null
1055  * \param[out] psel2 [optional] comb sel; can be null
1056  * \return 0 if OK, 1 on error
1057  *
1058  * <pre>
1059  * Notes:
1060  * (1) When using composable Sels, where the original Sel is
1061  * decomposed into two, the best you can do in terms
1062  * of reducing the computation is by a factor:
1063  *
1064  * 2 * sqrt(size) / size
1065  *
1066  * In practice, you get quite close to this. E.g.,
1067  *
1068  * Sel size | Optimum reduction factor
1069  * -------- ------------------------
1070  * 36 | 1/3
1071  * 64 | 1/4
1072  * 144 | 1/6
1073  * 256 | 1/8
1074  * </pre>
1075  */
1076 l_int32
1077 selectComposableSels(l_int32 size,
1078  l_int32 direction,
1079  SEL **psel1,
1080  SEL **psel2)
1081 {
1082 l_int32 factor1, factor2;
1083 
1084  PROCNAME("selectComposableSels");
1085 
1086  if (!psel1 && !psel2)
1087  return ERROR_INT("neither &sel1 nor &sel2 are defined", procName, 1);
1088  if (psel1) *psel1 = NULL;
1089  if (psel2) *psel2 = NULL;
1090  if (size < 1 || size > 10000)
1091  return ERROR_INT("size < 1 or size > 10000", procName, 1);
1092  if (direction != L_HORIZ && direction != L_VERT)
1093  return ERROR_INT("invalid direction", procName, 1);
1094 
1095  if (selectComposableSizes(size, &factor1, &factor2))
1096  return ERROR_INT("factors not found", procName, 1);
1097 
1098  if (psel1) {
1099  if (direction == L_HORIZ)
1100  *psel1 = selCreateBrick(1, factor1, 0, factor1 / 2, SEL_HIT);
1101  else
1102  *psel1 = selCreateBrick(factor1, 1, factor1 / 2 , 0, SEL_HIT);
1103  }
1104  if (psel2)
1105  *psel2 = selCreateComb(factor1, factor2, direction);
1106  return 0;
1107 }
1108 
1109 
1131 l_ok
1133  l_int32 *pfactor1,
1134  l_int32 *pfactor2)
1135 {
1136 l_int32 i, midval, val1, val2m, val2p;
1137 l_int32 index, prodm, prodp;
1138 l_int32 mincost, totcost, rastcostm, rastcostp, diffm, diffp;
1139 l_int32 lowval[256];
1140 l_int32 hival[256];
1141 l_int32 rastcost[256]; /* excess in sum of sizes (extra rasterops) */
1142 l_int32 diff[256]; /* diff between product (sel size) and input size */
1143 
1144  PROCNAME("selectComposableSizes");
1145 
1146  if (size < 1 || size > 10000)
1147  return ERROR_INT("size < 1 or size > 10000", procName, 1);
1148  if (!pfactor1 || !pfactor2)
1149  return ERROR_INT("&factor1 or &factor2 not defined", procName, 1);
1150 
1151  midval = (l_int32)(sqrt((l_float64)size) + 0.001);
1152  if (midval * midval == size) {
1153  *pfactor1 = *pfactor2 = midval;
1154  return 0;
1155  }
1156 
1157  /* Set up arrays. For each val1, optimize for lowest diff,
1158  * and save the rastcost, the diff, and the two factors. */
1159  for (val1 = midval + 1, i = 0; val1 > 0; val1--, i++) {
1160  val2m = size / val1;
1161  val2p = val2m + 1;
1162  prodm = val1 * val2m;
1163  prodp = val1 * val2p;
1164  rastcostm = val1 + val2m - 2 * midval;
1165  rastcostp = val1 + val2p - 2 * midval;
1166  diffm = L_ABS(size - prodm);
1167  diffp = L_ABS(size - prodp);
1168  if (diffm <= diffp) {
1169  lowval[i] = L_MIN(val1, val2m);
1170  hival[i] = L_MAX(val1, val2m);
1171  rastcost[i] = rastcostm;
1172  diff[i] = diffm;
1173  } else {
1174  lowval[i] = L_MIN(val1, val2p);
1175  hival[i] = L_MAX(val1, val2p);
1176  rastcost[i] = rastcostp;
1177  diff[i] = diffp;
1178  }
1179  }
1180 
1181  /* Choose the optimum factors; use cost ratio 4 on diff */
1182  mincost = 10000;
1183  index = 1; /* unimportant initial value */
1184  for (i = 0; i < midval + 1; i++) {
1185  if (diff[i] == 0 && rastcost[i] < ACCEPTABLE_COST) {
1186  *pfactor1 = hival[i];
1187  *pfactor2 = lowval[i];
1188  return 0;
1189  }
1190  totcost = 4 * diff[i] + rastcost[i];
1191  if (totcost < mincost) {
1192  mincost = totcost;
1193  index = i;
1194  }
1195  }
1196  *pfactor1 = hival[index];
1197  *pfactor2 = lowval[index];
1198 
1199  return 0;
1200 }
1201 
1202 
1243 PIX *
1245  PIX *pixs,
1246  l_int32 hsize,
1247  l_int32 vsize)
1248 {
1249 PIX *pix1, *pix2, *pix3;
1250 SEL *selh1 = NULL;
1251 SEL *selh2 = NULL;
1252 SEL *selv1 = NULL;
1253 SEL *selv2 = NULL;
1254 
1255  PROCNAME("pixDilateCompBrick");
1256 
1257  if (!pixs)
1258  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1259  if (pixGetDepth(pixs) != 1)
1260  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1261  if (hsize < 1 || vsize < 1)
1262  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1263 
1264  if (hsize == 1 && vsize == 1)
1265  return pixCopy(pixd, pixs);
1266  if (hsize > 1) {
1267  if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1268  selDestroy(&selh1);
1269  selDestroy(&selh2);
1270  return (PIX *)ERROR_PTR("horiz sels not made", procName, pixd);
1271  }
1272  }
1273  if (vsize > 1) {
1274  if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1275  selDestroy(&selh1);
1276  selDestroy(&selh2);
1277  selDestroy(&selv1);
1278  selDestroy(&selv2);
1279  return (PIX *)ERROR_PTR("vert sels not made", procName, pixd);
1280  }
1281  }
1282 
1283  pix1 = pixAddBorder(pixs, 32, 0);
1284  if (vsize == 1) {
1285  pix2 = pixDilate(NULL, pix1, selh1);
1286  pix3 = pixDilate(NULL, pix2, selh2);
1287  } else if (hsize == 1) {
1288  pix2 = pixDilate(NULL, pix1, selv1);
1289  pix3 = pixDilate(NULL, pix2, selv2);
1290  } else {
1291  pix2 = pixDilate(NULL, pix1, selh1);
1292  pix3 = pixDilate(NULL, pix2, selh2);
1293  pixDilate(pix2, pix3, selv1);
1294  pixDilate(pix3, pix2, selv2);
1295  }
1296  pixDestroy(&pix1);
1297  pixDestroy(&pix2);
1298 
1299  selDestroy(&selh1);
1300  selDestroy(&selh2);
1301  selDestroy(&selv1);
1302  selDestroy(&selv2);
1303 
1304  pix1 = pixRemoveBorder(pix3, 32);
1305  pixDestroy(&pix3);
1306  if (!pixd)
1307  return pix1;
1308  pixCopy(pixd, pix1);
1309  pixDestroy(&pix1);
1310  return pixd;
1311 }
1312 
1313 
1354 PIX *
1356  PIX *pixs,
1357  l_int32 hsize,
1358  l_int32 vsize)
1359 {
1360 PIX *pixt;
1361 SEL *selh1 = NULL;
1362 SEL *selh2 = NULL;
1363 SEL *selv1 = NULL;
1364 SEL *selv2 = NULL;
1365 
1366  PROCNAME("pixErodeCompBrick");
1367 
1368  if (!pixs)
1369  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1370  if (pixGetDepth(pixs) != 1)
1371  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1372  if (hsize < 1 || vsize < 1)
1373  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1374 
1375  if (hsize == 1 && vsize == 1)
1376  return pixCopy(pixd, pixs);
1377  if (hsize > 1) {
1378  if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1379  selDestroy(&selh1);
1380  selDestroy(&selh2);
1381  return (PIX *)ERROR_PTR("horiz sels not made", procName, pixd);
1382  }
1383  }
1384  if (vsize > 1) {
1385  if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1386  selDestroy(&selh1);
1387  selDestroy(&selh2);
1388  selDestroy(&selv1);
1389  selDestroy(&selv2);
1390  return (PIX *)ERROR_PTR("vert sels not made", procName, pixd);
1391  }
1392  }
1393 
1394  if (vsize == 1) {
1395  pixt = pixErode(NULL, pixs, selh1);
1396  pixd = pixErode(pixd, pixt, selh2);
1397  } else if (hsize == 1) {
1398  pixt = pixErode(NULL, pixs, selv1);
1399  pixd = pixErode(pixd, pixt, selv2);
1400  } else {
1401  pixt = pixErode(NULL, pixs, selh1);
1402  pixd = pixErode(pixd, pixt, selh2);
1403  pixErode(pixt, pixd, selv1);
1404  pixErode(pixd, pixt, selv2);
1405  }
1406  pixDestroy(&pixt);
1407 
1408  selDestroy(&selh1);
1409  selDestroy(&selh2);
1410  selDestroy(&selv1);
1411  selDestroy(&selv2);
1412  return pixd;
1413 }
1414 
1415 
1456 PIX *
1458  PIX *pixs,
1459  l_int32 hsize,
1460  l_int32 vsize)
1461 {
1462 PIX *pixt;
1463 SEL *selh1 = NULL;
1464 SEL *selh2 = NULL;
1465 SEL *selv1 = NULL;
1466 SEL *selv2 = NULL;
1467 
1468  PROCNAME("pixOpenCompBrick");
1469 
1470  if (!pixs)
1471  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1472  if (pixGetDepth(pixs) != 1)
1473  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1474  if (hsize < 1 || vsize < 1)
1475  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1476 
1477  if (hsize == 1 && vsize == 1)
1478  return pixCopy(pixd, pixs);
1479  if (hsize > 1) {
1480  if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1481  selDestroy(&selh1);
1482  selDestroy(&selh2);
1483  return (PIX *)ERROR_PTR("horiz sels not made", procName, pixd);
1484  }
1485  }
1486  if (vsize > 1) {
1487  if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1488  selDestroy(&selh1);
1489  selDestroy(&selh2);
1490  selDestroy(&selv1);
1491  selDestroy(&selv2);
1492  return (PIX *)ERROR_PTR("vert sels not made", procName, pixd);
1493  }
1494  }
1495 
1496  if (vsize == 1) {
1497  pixt = pixErode(NULL, pixs, selh1);
1498  pixd = pixErode(pixd, pixt, selh2);
1499  pixDilate(pixt, pixd, selh1);
1500  pixDilate(pixd, pixt, selh2);
1501  } else if (hsize == 1) {
1502  pixt = pixErode(NULL, pixs, selv1);
1503  pixd = pixErode(pixd, pixt, selv2);
1504  pixDilate(pixt, pixd, selv1);
1505  pixDilate(pixd, pixt, selv2);
1506  } else { /* do separably */
1507  pixt = pixErode(NULL, pixs, selh1);
1508  pixd = pixErode(pixd, pixt, selh2);
1509  pixErode(pixt, pixd, selv1);
1510  pixErode(pixd, pixt, selv2);
1511  pixDilate(pixt, pixd, selh1);
1512  pixDilate(pixd, pixt, selh2);
1513  pixDilate(pixt, pixd, selv1);
1514  pixDilate(pixd, pixt, selv2);
1515  }
1516  pixDestroy(&pixt);
1517 
1518  selDestroy(&selh1);
1519  selDestroy(&selh2);
1520  selDestroy(&selv1);
1521  selDestroy(&selv2);
1522  return pixd;
1523 }
1524 
1525 
1566 PIX *
1568  PIX *pixs,
1569  l_int32 hsize,
1570  l_int32 vsize)
1571 {
1572 PIX *pixt;
1573 SEL *selh1 = NULL;
1574 SEL *selh2 = NULL;
1575 SEL *selv1 = NULL;
1576 SEL *selv2 = NULL;
1577 
1578  PROCNAME("pixCloseCompBrick");
1579 
1580  if (!pixs)
1581  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1582  if (pixGetDepth(pixs) != 1)
1583  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1584  if (hsize < 1 || vsize < 1)
1585  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1586 
1587  if (hsize == 1 && vsize == 1)
1588  return pixCopy(pixd, pixs);
1589  if (hsize > 1) {
1590  if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1591  selDestroy(&selh1);
1592  selDestroy(&selh2);
1593  return (PIX *)ERROR_PTR("horiz sels not made", procName, pixd);
1594  }
1595  }
1596  if (vsize > 1) {
1597  if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1598  selDestroy(&selh1);
1599  selDestroy(&selh2);
1600  selDestroy(&selv1);
1601  selDestroy(&selv2);
1602  return (PIX *)ERROR_PTR("vert sels not made", procName, pixd);
1603  }
1604  }
1605 
1606  if (vsize == 1) {
1607  pixt = pixDilate(NULL, pixs, selh1);
1608  pixd = pixDilate(pixd, pixt, selh2);
1609  pixErode(pixt, pixd, selh1);
1610  pixErode(pixd, pixt, selh2);
1611  } else if (hsize == 1) {
1612  pixt = pixDilate(NULL, pixs, selv1);
1613  pixd = pixDilate(pixd, pixt, selv2);
1614  pixErode(pixt, pixd, selv1);
1615  pixErode(pixd, pixt, selv2);
1616  } else { /* do separably */
1617  pixt = pixDilate(NULL, pixs, selh1);
1618  pixd = pixDilate(pixd, pixt, selh2);
1619  pixDilate(pixt, pixd, selv1);
1620  pixDilate(pixd, pixt, selv2);
1621  pixErode(pixt, pixd, selh1);
1622  pixErode(pixd, pixt, selh2);
1623  pixErode(pixt, pixd, selv1);
1624  pixErode(pixd, pixt, selv2);
1625  }
1626  pixDestroy(&pixt);
1627 
1628  selDestroy(&selh1);
1629  selDestroy(&selh2);
1630  selDestroy(&selv1);
1631  selDestroy(&selv2);
1632  return pixd;
1633 }
1634 
1635 
1681 PIX *
1683  PIX *pixs,
1684  l_int32 hsize,
1685  l_int32 vsize)
1686 {
1687 l_int32 maxtrans, bordsize;
1688 PIX *pixsb, *pixt, *pixdb;
1689 SEL *selh1 = NULL;
1690 SEL *selh2 = NULL;
1691 SEL *selv1 = NULL;
1692 SEL *selv2 = NULL;
1693 
1694  PROCNAME("pixCloseSafeCompBrick");
1695 
1696  if (!pixs)
1697  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1698  if (pixGetDepth(pixs) != 1)
1699  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1700  if (hsize < 1 || vsize < 1)
1701  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1702 
1703  if (hsize == 1 && vsize == 1)
1704  return pixCopy(pixd, pixs);
1705 
1706  /* Symmetric b.c. handles correctly without added pixels */
1707  if (MORPH_BC == SYMMETRIC_MORPH_BC)
1708  return pixCloseCompBrick(pixd, pixs, hsize, vsize);
1709 
1710  if (hsize > 1) {
1711  if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1712  selDestroy(&selh1);
1713  selDestroy(&selh2);
1714  return (PIX *)ERROR_PTR("horiz sels not made", procName, pixd);
1715  }
1716  }
1717  if (vsize > 1) {
1718  if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1719  selDestroy(&selh1);
1720  selDestroy(&selh2);
1721  selDestroy(&selv1);
1722  selDestroy(&selv2);
1723  return (PIX *)ERROR_PTR("vert sels not made", procName, pixd);
1724  }
1725  }
1726 
1727  maxtrans = L_MAX(hsize / 2, vsize / 2);
1728  bordsize = 32 * ((maxtrans + 31) / 32); /* full 32 bit words */
1729  pixsb = pixAddBorder(pixs, bordsize, 0);
1730 
1731  if (vsize == 1) {
1732  pixt = pixDilate(NULL, pixsb, selh1);
1733  pixdb = pixDilate(NULL, pixt, selh2);
1734  pixErode(pixt, pixdb, selh1);
1735  pixErode(pixdb, pixt, selh2);
1736  } else if (hsize == 1) {
1737  pixt = pixDilate(NULL, pixsb, selv1);
1738  pixdb = pixDilate(NULL, pixt, selv2);
1739  pixErode(pixt, pixdb, selv1);
1740  pixErode(pixdb, pixt, selv2);
1741  } else { /* do separably */
1742  pixt = pixDilate(NULL, pixsb, selh1);
1743  pixdb = pixDilate(NULL, pixt, selh2);
1744  pixDilate(pixt, pixdb, selv1);
1745  pixDilate(pixdb, pixt, selv2);
1746  pixErode(pixt, pixdb, selh1);
1747  pixErode(pixdb, pixt, selh2);
1748  pixErode(pixt, pixdb, selv1);
1749  pixErode(pixdb, pixt, selv2);
1750  }
1751  pixDestroy(&pixt);
1752 
1753  pixt = pixRemoveBorder(pixdb, bordsize);
1754  pixDestroy(&pixsb);
1755  pixDestroy(&pixdb);
1756 
1757  if (!pixd) {
1758  pixd = pixt;
1759  } else {
1760  pixCopy(pixd, pixt);
1761  pixDestroy(&pixt);
1762  }
1763 
1764  selDestroy(&selh1);
1765  selDestroy(&selh2);
1766  selDestroy(&selv1);
1767  selDestroy(&selv2);
1768  return pixd;
1769 }
1770 
1771 
1772 /*-----------------------------------------------------------------*
1773  * Functions associated with boundary conditions *
1774  *-----------------------------------------------------------------*/
1781 void
1783 {
1784  PROCNAME("resetMorphBoundaryCondition");
1785 
1786  if (bc != SYMMETRIC_MORPH_BC && bc != ASYMMETRIC_MORPH_BC) {
1787  L_WARNING("invalid bc; using asymmetric\n", procName);
1788  bc = ASYMMETRIC_MORPH_BC;
1789  }
1790  MORPH_BC = bc;
1791  return;
1792 }
1793 
1794 
1802 l_uint32
1804  l_int32 depth)
1805 {
1806  PROCNAME("getMorphBorderPixelColor");
1807 
1808  if (type != L_MORPH_DILATE && type != L_MORPH_ERODE)
1809  return ERROR_INT("invalid type", procName, 0);
1810  if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
1811  depth != 16 && depth != 32)
1812  return ERROR_INT("invalid depth", procName, 0);
1813 
1814  if (MORPH_BC == ASYMMETRIC_MORPH_BC || type == L_MORPH_DILATE)
1815  return 0;
1816 
1817  /* Symmetric & erosion */
1818  if (depth < 32)
1819  return ((1 << depth) - 1);
1820  else /* depth == 32 */
1821  return 0xffffff00;
1822 }
1823 
1824 
1825 /*-----------------------------------------------------------------*
1826  * Static helpers for arg processing *
1827  *-----------------------------------------------------------------*/
1843 static PIX *
1845  PIX *pixs,
1846  SEL *sel,
1847  PIX **ppixt)
1848 {
1849 l_int32 sx, sy;
1850 
1851  PROCNAME("processMorphArgs1");
1852 
1853  if (!ppixt)
1854  return (PIX *)ERROR_PTR("&pixt not defined", procName, pixd);
1855  *ppixt = NULL;
1856  if (!pixs)
1857  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1858  if (!sel)
1859  return (PIX *)ERROR_PTR("sel not defined", procName, pixd);
1860  if (pixGetDepth(pixs) != 1)
1861  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1862 
1863  selGetParameters(sel, &sx, &sy, NULL, NULL);
1864  if (sx == 0 || sy == 0)
1865  return (PIX *)ERROR_PTR("sel of size 0", procName, pixd);
1866 
1867  /* We require pixd to exist and to be the same size as pixs.
1868  * Further, pixt must be a copy (or clone) of pixs. */
1869  if (!pixd) {
1870  if ((pixd = pixCreateTemplate(pixs)) == NULL)
1871  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1872  *ppixt = pixClone(pixs);
1873  } else {
1874  pixResizeImageData(pixd, pixs);
1875  if (pixd == pixs) { /* in-place; must make a copy of pixs */
1876  if ((*ppixt = pixCopy(NULL, pixs)) == NULL)
1877  return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
1878  } else {
1879  *ppixt = pixClone(pixs);
1880  }
1881  }
1882  return pixd;
1883 }
1884 
1885 
1891 static PIX *
1893  PIX *pixs,
1894  SEL *sel)
1895 {
1896 l_int32 sx, sy;
1897 
1898  PROCNAME("processMorphArgs2");
1899 
1900  if (!pixs)
1901  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1902  if (!sel)
1903  return (PIX *)ERROR_PTR("sel not defined", procName, pixd);
1904  if (pixGetDepth(pixs) != 1)
1905  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1906 
1907  selGetParameters(sel, &sx, &sy, NULL, NULL);
1908  if (sx == 0 || sy == 0)
1909  return (PIX *)ERROR_PTR("sel of size 0", procName, pixd);
1910 
1911  if (!pixd)
1912  return pixCreateTemplate(pixs);
1913  pixResizeImageData(pixd, pixs);
1914  return pixd;
1915 }
PIX * pixCloseGeneralized(PIX *pixd, PIX *pixs, SEL *sel)
pixCloseGeneralized()
Definition: morph.c:638
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1132
l_ok pixResizeImageData(PIX *pixd, const PIX *pixs)
pixResizeImageData()
Definition: pix1.c:768
#define PIX_CLR
Definition: pix.h:333
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1993
l_uint32 getMorphBorderPixelColor(l_int32 type, l_int32 depth)
getMorphBorderPixelColor()
Definition: morph.c:1803
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCloseBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseBrick()
Definition: morph.c:900
PIX * pixOpen(PIX *pixd, PIX *pixs, SEL *sel)
pixOpen()
Definition: morph.c:426
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
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixCloseSafeCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseSafeCompBrick()
Definition: morph.c:1682
PIX * pixDilateBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrick()
Definition: morph.c:688
l_ok selGetParameters(SEL *sel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
selGetParameters()
Definition: sel1.c:848
void resetMorphBoundaryCondition(l_int32 bc)
resetMorphBoundaryCondition()
Definition: morph.c:1782
static PIX * processMorphArgs2(PIX *pixd, PIX *pixs, SEL *sel)
processMorphArgs2()
Definition: morph.c:1892
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok selFindMaxTranslations(SEL *sel, l_int32 *pxp, l_int32 *pyp, l_int32 *pxn, l_int32 *pyn)
selFindMaxTranslations()
Definition: sel1.c:1190
l_int32 ** data
Definition: morph.h:67
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1823
PIX * pixErode(PIX *pixd, PIX *pixs, SEL *sel)
pixErode()
Definition: morph.c:267
PIX * pixRemoveBorder(PIX *pixs, l_int32 npix)
pixRemoveBorder()
Definition: pix2.c:1972
PIX * pixCloseSafeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseSafeBrick()
Definition: morph.c:977
l_ok pixClearAll(PIX *pix)
pixClearAll()
Definition: pix2.c:789
void selDestroy(SEL **psel)
selDestroy()
Definition: sel1.c:340
SEL * selCreateComb(l_int32 factor1, l_int32 factor2, l_int32 direction)
selCreateComb()
Definition: sel1.c:462
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()
Definition: sel1.c:418
PIX * pixCloseSafe(PIX *pixd, PIX *pixs, SEL *sel)
pixCloseSafe()
Definition: morph.c:524
PIX * pixDilateCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrick()
Definition: morph.c:1244
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixOpenGeneralized(PIX *pixd, PIX *pixs, SEL *sel)
pixOpenGeneralized()
Definition: morph.c:591
PIX * pixOpenBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenBrick()
Definition: morph.c:828
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixCloseCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrick()
Definition: morph.c:1567
PIX * pixHMT(PIX *pixd, PIX *pixs, SEL *sel)
pixHMT()
Definition: morph.c:342
#define PIX_NOT(op)
Definition: pix.h:332
PIX * pixClose(PIX *pixd, PIX *pixs, SEL *sel)
pixClose()
Definition: morph.c:473
PIX * pixErodeCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrick()
Definition: morph.c:1355
Definition: pix.h:138
static PIX * processMorphArgs1(PIX *pixd, PIX *pixs, SEL *sel, PIX **ppixt)
processMorphArgs1()
Definition: morph.c:1844
#define PIX_SRC
Definition: pix.h:330
PIX * pixDilate(PIX *pixd, PIX *pixs, SEL *sel)
pixDilate()
Definition: morph.c:213
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
Definition: morph.c:758
PIX * pixOpenCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrick()
Definition: morph.c:1457
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1917
#define PIX_DST
Definition: pix.h:331