Leptonica  1.83.1
Image processing and image analysis suite
morphdwa.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 
132 #ifdef HAVE_CONFIG_H
133 #include <config_auto.h>
134 #endif /* HAVE_CONFIG_H */
135 
136 #include "allheaders.h"
137 
138 #ifndef NO_CONSOLE_IO
139 #define DEBUG_SEL_LOOKUP 0
140 #endif /* ~NO_CONSOLE_IO */
141 
142 /*-----------------------------------------------------------------*
143  * Binary morphological (dwa) ops with brick Sels *
144  *-----------------------------------------------------------------*/
177 PIX *
179  PIX *pixs,
180  l_int32 hsize,
181  l_int32 vsize)
182 {
183 l_int32 found;
184 char *selnameh, *selnamev;
185 SELA *sela;
186 PIX *pixt1, *pixt2, *pixt3;
187 
188  if (!pixs)
189  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
190  if (pixGetDepth(pixs) != 1)
191  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
192  if (hsize < 1 || vsize < 1)
193  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
194 
195  if (hsize == 1 && vsize == 1)
196  return pixCopy(pixd, pixs);
197 
198  sela = selaAddBasic(NULL);
199  found = TRUE;
200  selnameh = selnamev = NULL;
201  if (hsize > 1) {
202  selnameh = selaGetBrickName(sela, hsize, 1);
203  if (!selnameh) found = FALSE;
204  }
205  if (vsize > 1) {
206  selnamev = selaGetBrickName(sela, 1, vsize);
207  if (!selnamev) found = FALSE;
208  }
209  selaDestroy(&sela);
210  if (!found) {
211  L_INFO("Calling the decomposable dwa function\n", __func__);
212  if (selnameh) LEPT_FREE(selnameh);
213  if (selnamev) LEPT_FREE(selnamev);
214  return pixDilateCompBrickDwa(pixd, pixs, hsize, vsize);
215  }
216 
217  if (vsize == 1) {
218  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh);
219  LEPT_FREE(selnameh);
220  } else if (hsize == 1) {
221  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnamev);
222  LEPT_FREE(selnamev);
223  } else {
224  pixt1 = pixAddBorder(pixs, 32, 0);
225  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh);
226  pixFMorphopGen_1(pixt1, pixt3, L_MORPH_DILATE, selnamev);
227  pixt2 = pixRemoveBorder(pixt1, 32);
228  pixDestroy(&pixt1);
229  pixDestroy(&pixt3);
230  LEPT_FREE(selnameh);
231  LEPT_FREE(selnamev);
232  }
233 
234  if (!pixd)
235  return pixt2;
236 
237  pixTransferAllData(pixd, &pixt2, 0, 0);
238  return pixd;
239 }
240 
241 
277 PIX *
279  PIX *pixs,
280  l_int32 hsize,
281  l_int32 vsize)
282 {
283 l_int32 found;
284 char *selnameh, *selnamev;
285 SELA *sela;
286 PIX *pixt1, *pixt2, *pixt3;
287 
288  if (!pixs)
289  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
290  if (pixGetDepth(pixs) != 1)
291  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
292  if (hsize < 1 || vsize < 1)
293  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
294 
295  if (hsize == 1 && vsize == 1)
296  return pixCopy(pixd, pixs);
297 
298  sela = selaAddBasic(NULL);
299  found = TRUE;
300  selnameh = selnamev = NULL;
301  if (hsize > 1) {
302  selnameh = selaGetBrickName(sela, hsize, 1);
303  if (!selnameh) found = FALSE;
304  }
305  if (vsize > 1) {
306  selnamev = selaGetBrickName(sela, 1, vsize);
307  if (!selnamev) found = FALSE;
308  }
309  selaDestroy(&sela);
310  if (!found) {
311  L_INFO("Calling the decomposable dwa function\n", __func__);
312  if (selnameh) LEPT_FREE(selnameh);
313  if (selnamev) LEPT_FREE(selnamev);
314  return pixErodeCompBrickDwa(pixd, pixs, hsize, vsize);
315  }
316 
317  if (vsize == 1) {
318  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnameh);
319  LEPT_FREE(selnameh);
320  } else if (hsize == 1) {
321  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnamev);
322  LEPT_FREE(selnamev);
323  } else {
324  pixt1 = pixAddBorder(pixs, 32, 0);
325  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh);
326  pixFMorphopGen_1(pixt1, pixt3, L_MORPH_ERODE, selnamev);
327  pixt2 = pixRemoveBorder(pixt1, 32);
328  pixDestroy(&pixt1);
329  pixDestroy(&pixt3);
330  LEPT_FREE(selnameh);
331  LEPT_FREE(selnamev);
332  }
333 
334  if (!pixd)
335  return pixt2;
336 
337  pixTransferAllData(pixd, &pixt2, 0, 0);
338  return pixd;
339 }
340 
341 
377 PIX *
379  PIX *pixs,
380  l_int32 hsize,
381  l_int32 vsize)
382 {
383 l_int32 found;
384 char *selnameh, *selnamev;
385 SELA *sela;
386 PIX *pixt1, *pixt2, *pixt3;
387 
388  if (!pixs)
389  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
390  if (pixGetDepth(pixs) != 1)
391  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
392  if (hsize < 1 || vsize < 1)
393  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
394 
395  if (hsize == 1 && vsize == 1)
396  return pixCopy(pixd, pixs);
397 
398  sela = selaAddBasic(NULL);
399  found = TRUE;
400  selnameh = selnamev = NULL;
401  if (hsize > 1) {
402  selnameh = selaGetBrickName(sela, hsize, 1);
403  if (!selnameh) found = FALSE;
404  }
405  if (vsize > 1) {
406  selnamev = selaGetBrickName(sela, 1, vsize);
407  if (!selnamev) found = FALSE;
408  }
409  selaDestroy(&sela);
410  if (!found) {
411  L_INFO("Calling the decomposable dwa function\n", __func__);
412  if (selnameh) LEPT_FREE(selnameh);
413  if (selnamev) LEPT_FREE(selnamev);
414  return pixOpenCompBrickDwa(pixd, pixs, hsize, vsize);
415  }
416 
417  pixt1 = pixAddBorder(pixs, 32, 0);
418  if (vsize == 1) { /* horizontal only */
419  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_OPEN, selnameh);
420  LEPT_FREE(selnameh);
421  } else if (hsize == 1) { /* vertical only */
422  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_OPEN, selnamev);
423  LEPT_FREE(selnamev);
424  } else { /* do separable */
425  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh);
426  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev);
427  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh);
428  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnamev);
429  LEPT_FREE(selnameh);
430  LEPT_FREE(selnamev);
431  pixDestroy(&pixt3);
432  }
433  pixt3 = pixRemoveBorder(pixt2, 32);
434  pixDestroy(&pixt1);
435  pixDestroy(&pixt2);
436 
437  if (!pixd)
438  return pixt3;
439 
440  pixTransferAllData(pixd, &pixt3, 0, 0);
441  return pixd;
442 }
443 
444 
482 PIX *
484  PIX *pixs,
485  l_int32 hsize,
486  l_int32 vsize)
487 {
488 l_int32 bordercolor, bordersize, found;
489 char *selnameh, *selnamev;
490 SELA *sela;
491 PIX *pixt1, *pixt2, *pixt3;
492 
493  if (!pixs)
494  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
495  if (pixGetDepth(pixs) != 1)
496  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
497  if (hsize < 1 || vsize < 1)
498  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
499 
500  if (hsize == 1 && vsize == 1)
501  return pixCopy(pixd, pixs);
502 
503  sela = selaAddBasic(NULL);
504  found = TRUE;
505  selnameh = selnamev = NULL;
506  if (hsize > 1) {
507  selnameh = selaGetBrickName(sela, hsize, 1);
508  if (!selnameh) found = FALSE;
509  }
510  if (vsize > 1) {
511  selnamev = selaGetBrickName(sela, 1, vsize);
512  if (!selnamev) found = FALSE;
513  }
514  selaDestroy(&sela);
515  if (!found) {
516  L_INFO("Calling the decomposable dwa function\n", __func__);
517  if (selnameh) LEPT_FREE(selnameh);
518  if (selnamev) LEPT_FREE(selnamev);
519  return pixCloseCompBrickDwa(pixd, pixs, hsize, vsize);
520  }
521 
522  /* For "safe closing" with ASYMMETRIC_MORPH_BC, we always need
523  * an extra 32 OFF pixels around the image (in addition to
524  * the 32 added pixels for all dwa operations), whereas with
525  * SYMMETRIC_MORPH_BC this is not necessary. */
526  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
527  if (bordercolor == 0) /* asymmetric b.c. */
528  bordersize = 64;
529  else /* symmetric b.c. */
530  bordersize = 32;
531  pixt1 = pixAddBorder(pixs, bordersize, 0);
532 
533  if (vsize == 1) { /* horizontal only */
534  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnameh);
535  LEPT_FREE(selnameh);
536  } else if (hsize == 1) { /* vertical only */
537  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnamev);
538  LEPT_FREE(selnamev);
539  } else { /* do separable */
540  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh);
541  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev);
542  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh);
543  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnamev);
544  LEPT_FREE(selnameh);
545  LEPT_FREE(selnamev);
546  pixDestroy(&pixt3);
547  }
548  pixt3 = pixRemoveBorder(pixt2, bordersize);
549  pixDestroy(&pixt1);
550  pixDestroy(&pixt2);
551 
552  if (!pixd)
553  return pixt3;
554 
555  pixTransferAllData(pixd, &pixt3, 0, 0);
556  return pixd;
557 }
558 
559 
560 /*-----------------------------------------------------------------*
561  * Binary composite morphological (dwa) ops with brick Sels *
562  *-----------------------------------------------------------------*/
607 PIX *
609  PIX *pixs,
610  l_int32 hsize,
611  l_int32 vsize)
612 {
613 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
614 l_int32 hsize1, hsize2, vsize1, vsize2;
615 PIX *pixt1, *pixt2, *pixt3;
616 
617  if (!pixs)
618  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
619  if (pixGetDepth(pixs) != 1)
620  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
621  if (hsize < 1 || vsize < 1)
622  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
623  if (hsize > 63 || vsize > 63)
624  return pixDilateCompBrickExtendDwa(pixd, pixs, hsize, vsize);
625 
626  if (hsize == 1 && vsize == 1)
627  return pixCopy(pixd, pixs);
628 
629  hsize1 = hsize2 = vsize1 = vsize2 = 1;
630  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
631  if (hsize > 1)
632  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
633  &selnameh2, NULL, NULL);
634  if (vsize > 1)
635  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
636  &selnamev1, &selnamev2);
637 
638 #if DEBUG_SEL_LOOKUP
639  lept_stderr("nameh1=%s, nameh2=%s, namev1=%s, namev2=%s\n",
640  selnameh1, selnameh2, selnamev1, selnamev2);
641  lept_stderr("hsize1=%d, hsize2=%d, vsize1=%d, vsize2=%d\n",
642  hsize1, hsize2, vsize1, vsize2);
643 #endif /* DEBUG_SEL_LOOKUP */
644 
645  pixt1 = pixAddBorder(pixs, 64, 0);
646  if (vsize == 1) {
647  if (hsize2 == 1) {
648  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
649  } else {
650  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
651  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
652  pixDestroy(&pixt3);
653  }
654  } else if (hsize == 1) {
655  if (vsize2 == 1) {
656  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnamev1);
657  } else {
658  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnamev1);
659  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnamev2);
660  pixDestroy(&pixt3);
661  }
662  } else { /* vsize and hsize both > 1 */
663  if (hsize2 == 1) {
664  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
665  } else {
666  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
667  pixt3 = pixFMorphopGen_2(NULL, pixt2, L_MORPH_DILATE, selnameh2);
668  pixDestroy(&pixt2);
669  }
670  if (vsize2 == 1) {
671  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
672  } else {
673  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
674  pixFMorphopGen_2(pixt2, pixt2, L_MORPH_DILATE, selnamev2);
675  }
676  pixDestroy(&pixt3);
677  }
678  pixDestroy(&pixt1);
679  pixt1 = pixRemoveBorder(pixt2, 64);
680  pixDestroy(&pixt2);
681  if (selnameh1) LEPT_FREE(selnameh1);
682  if (selnameh2) LEPT_FREE(selnameh2);
683  if (selnamev1) LEPT_FREE(selnamev1);
684  if (selnamev2) LEPT_FREE(selnamev2);
685 
686  if (!pixd)
687  return pixt1;
688 
689  pixTransferAllData(pixd, &pixt1, 0, 0);
690  return pixd;
691 }
692 
693 
738 PIX *
740  PIX *pixs,
741  l_int32 hsize,
742  l_int32 vsize)
743 {
744 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
745 l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
746 PIX *pixt1, *pixt2, *pixt3;
747 
748  if (!pixs)
749  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
750  if (pixGetDepth(pixs) != 1)
751  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
752  if (hsize < 1 || vsize < 1)
753  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
754  if (hsize > 63 || vsize > 63)
755  return pixErodeCompBrickExtendDwa(pixd, pixs, hsize, vsize);
756 
757  if (hsize == 1 && vsize == 1)
758  return pixCopy(pixd, pixs);
759 
760  hsize1 = hsize2 = vsize1 = vsize2 = 1;
761  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
762  if (hsize > 1)
763  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
764  &selnameh2, NULL, NULL);
765  if (vsize > 1)
766  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
767  &selnamev1, &selnamev2);
768 
769  /* For symmetric b.c., bordercolor == 1 for erosion */
770  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
771  pixt1 = pixAddBorder(pixs, 64, bordercolor);
772 
773  if (vsize == 1) {
774  if (hsize2 == 1) {
775  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
776  } else {
777  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
778  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
779  pixDestroy(&pixt3);
780  }
781  } else if (hsize == 1) {
782  if (vsize2 == 1) {
783  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
784  } else {
785  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
786  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnamev2);
787  pixDestroy(&pixt3);
788  }
789  } else { /* vsize and hsize both > 1 */
790  if (hsize2 == 1) {
791  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
792  } else {
793  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
794  pixt3 = pixFMorphopGen_2(NULL, pixt2, L_MORPH_ERODE, selnameh2);
795  pixDestroy(&pixt2);
796  }
797  if (vsize2 == 1) {
798  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
799  } else {
800  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
801  pixFMorphopGen_2(pixt2, pixt2, L_MORPH_ERODE, selnamev2);
802  }
803  pixDestroy(&pixt3);
804  }
805  pixDestroy(&pixt1);
806  pixt1 = pixRemoveBorder(pixt2, 64);
807  pixDestroy(&pixt2);
808  if (selnameh1) LEPT_FREE(selnameh1);
809  if (selnameh2) LEPT_FREE(selnameh2);
810  if (selnamev1) LEPT_FREE(selnamev1);
811  if (selnamev2) LEPT_FREE(selnamev2);
812 
813  if (!pixd)
814  return pixt1;
815 
816  pixTransferAllData(pixd, &pixt1, 0, 0);
817  return pixd;
818 }
819 
820 
865 PIX *
867  PIX *pixs,
868  l_int32 hsize,
869  l_int32 vsize)
870 {
871 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
872 l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
873 PIX *pixt1, *pixt2, *pixt3;
874 
875  if (!pixs)
876  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
877  if (pixGetDepth(pixs) != 1)
878  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
879  if (hsize < 1 || vsize < 1)
880  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
881  if (hsize > 63 || vsize > 63)
882  return pixOpenCompBrickExtendDwa(pixd, pixs, hsize, vsize);
883 
884  if (hsize == 1 && vsize == 1)
885  return pixCopy(pixd, pixs);
886 
887  hsize1 = hsize2 = vsize1 = vsize2 = 1;
888  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
889  if (hsize > 1)
890  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
891  &selnameh2, NULL, NULL);
892  if (vsize > 1)
893  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
894  &selnamev1, &selnamev2);
895 
896  /* For symmetric b.c., initialize erosion with bordercolor == 1 */
897  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
898  pixt1 = pixAddBorder(pixs, 64, bordercolor);
899 
900  if (vsize == 1) {
901  if (hsize2 == 1) {
902  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
903  if (bordercolor == 1)
904  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
905  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnameh1);
906  } else {
907  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
908  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
909  if (bordercolor == 1)
910  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
911  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh1);
912  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnameh2);
913  }
914  } else if (hsize == 1) {
915  if (vsize2 == 1) {
916  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
917  if (bordercolor == 1)
918  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
919  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
920  } else {
921  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
922  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnamev2);
923  if (bordercolor == 1)
924  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
925  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
926  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
927  }
928  } else { /* vsize and hsize both > 1 */
929  if (hsize2 == 1 && vsize2 == 1) {
930  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
931  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
932  if (bordercolor == 1)
933  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
934  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh1);
935  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnamev1);
936  } else if (vsize2 == 1) {
937  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
938  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
939  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
940  if (bordercolor == 1)
941  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
942  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnameh1);
943  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_DILATE, selnameh2);
944  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnamev1);
945  } else if (hsize2 == 1) {
946  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
947  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
948  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_ERODE, selnamev2);
949  if (bordercolor == 1)
950  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
951  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnameh1);
952  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
953  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
954  } else { /* both directions are combed */
955  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
956  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
957  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
958  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
959  if (bordercolor == 1)
960  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
961  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh1);
962  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnameh2);
963  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
964  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
965  }
966  }
967  pixDestroy(&pixt3);
968 
969  pixDestroy(&pixt1);
970  pixt1 = pixRemoveBorder(pixt2, 64);
971  pixDestroy(&pixt2);
972  if (selnameh1) LEPT_FREE(selnameh1);
973  if (selnameh2) LEPT_FREE(selnameh2);
974  if (selnamev1) LEPT_FREE(selnamev1);
975  if (selnamev2) LEPT_FREE(selnamev2);
976 
977  if (!pixd)
978  return pixt1;
979 
980  pixTransferAllData(pixd, &pixt1, 0, 0);
981  return pixd;
982 }
983 
984 
1030 PIX *
1032  PIX *pixs,
1033  l_int32 hsize,
1034  l_int32 vsize)
1035 {
1036 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
1037 l_int32 hsize1, hsize2, vsize1, vsize2, setborder;
1038 PIX *pixt1, *pixt2, *pixt3;
1039 
1040  if (!pixs)
1041  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
1042  if (pixGetDepth(pixs) != 1)
1043  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
1044  if (hsize < 1 || vsize < 1)
1045  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
1046  if (hsize > 63 || vsize > 63)
1047  return pixCloseCompBrickExtendDwa(pixd, pixs, hsize, vsize);
1048 
1049  if (hsize == 1 && vsize == 1)
1050  return pixCopy(pixd, pixs);
1051 
1052  hsize1 = hsize2 = vsize1 = vsize2 = 1;
1053  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
1054  if (hsize > 1)
1055  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
1056  &selnameh2, NULL, NULL);
1057  if (vsize > 1)
1058  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
1059  &selnamev1, &selnamev2);
1060 
1061  pixt3 = NULL;
1062  /* For symmetric b.c., PIX_SET border for erosions */
1063  setborder = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
1064  pixt1 = pixAddBorder(pixs, 64, 0);
1065 
1066  if (vsize == 1) {
1067  if (hsize2 == 1) {
1068  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnameh1);
1069  } else {
1070  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1071  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
1072  if (setborder == 1)
1073  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1074  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh1);
1075  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnameh2);
1076  }
1077  } else if (hsize == 1) {
1078  if (vsize2 == 1) {
1079  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnamev1);
1080  } else {
1081  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnamev1);
1082  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnamev2);
1083  if (setborder == 1)
1084  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1085  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
1086  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
1087  }
1088  } else { /* vsize and hsize both > 1 */
1089  if (hsize2 == 1 && vsize2 == 1) {
1090  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1091  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
1092  if (setborder == 1)
1093  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1094  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh1);
1095  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnamev1);
1096  } else if (vsize2 == 1) {
1097  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1098  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
1099  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
1100  if (setborder == 1)
1101  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_SET);
1102  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnameh1);
1103  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_ERODE, selnameh2);
1104  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnamev1);
1105  } else if (hsize2 == 1) {
1106  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1107  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
1108  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_DILATE, selnamev2);
1109  if (setborder == 1)
1110  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_SET);
1111  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnameh1);
1112  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
1113  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
1114  } else { /* both directions are combed */
1115  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1116  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
1117  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
1118  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
1119  if (setborder == 1)
1120  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1121  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh1);
1122  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnameh2);
1123  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
1124  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
1125  }
1126  }
1127  pixDestroy(&pixt3);
1128 
1129  pixDestroy(&pixt1);
1130  pixt1 = pixRemoveBorder(pixt2, 64);
1131  pixDestroy(&pixt2);
1132  if (selnameh1) LEPT_FREE(selnameh1);
1133  if (selnameh2) LEPT_FREE(selnameh2);
1134  if (selnamev1) LEPT_FREE(selnamev1);
1135  if (selnamev2) LEPT_FREE(selnamev2);
1136 
1137  if (!pixd)
1138  return pixt1;
1139 
1140  pixTransferAllData(pixd, &pixt1, 0, 0);
1141  return pixd;
1142 }
1143 
1144 
1145 /*--------------------------------------------------------------------------*
1146  * Binary expanded composite morphological (dwa) ops with brick Sels *
1147  *--------------------------------------------------------------------------*/
1178 PIX *
1180  PIX *pixs,
1181  l_int32 hsize,
1182  l_int32 vsize)
1183 {
1184 l_int32 i, nops, nh, extrah, nv, extrav;
1185 PIX *pixt1, *pixt2, *pixt3;
1186 
1187  if (!pixs)
1188  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
1189  if (pixGetDepth(pixs) != 1)
1190  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
1191  if (hsize < 1 || vsize < 1)
1192  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
1193 
1194  if (hsize < 64 && vsize < 64)
1195  return pixDilateCompBrickDwa(pixd, pixs, hsize, vsize);
1196 
1197  if (hsize > 63)
1198  getExtendedCompositeParameters(hsize, &nh, &extrah, NULL);
1199  if (vsize > 63)
1200  getExtendedCompositeParameters(vsize, &nv, &extrav, NULL);
1201 
1202  /* Horizontal dilation first: pixs --> pixt2. Do not alter pixs. */
1203  pixt1 = pixCreateTemplate(pixs); /* temp image */
1204  if (hsize == 1) {
1205  pixt2 = pixClone(pixs);
1206  } else if (hsize < 64) {
1207  pixt2 = pixDilateCompBrickDwa(NULL, pixs, hsize, 1);
1208  } else if (hsize == 64) { /* approximate */
1209  pixt2 = pixDilateCompBrickDwa(NULL, pixs, 63, 1);
1210  } else {
1211  nops = (extrah < 3) ? nh : nh + 1;
1212  if (nops & 1) { /* odd */
1213  if (extrah > 2)
1214  pixt2 = pixDilateCompBrickDwa(NULL, pixs, extrah, 1);
1215  else
1216  pixt2 = pixDilateCompBrickDwa(NULL, pixs, 63, 1);
1217  for (i = 0; i < nops / 2; i++) {
1218  pixDilateCompBrickDwa(pixt1, pixt2, 63, 1);
1219  pixDilateCompBrickDwa(pixt2, pixt1, 63, 1);
1220  }
1221  } else { /* nops even */
1222  if (extrah > 2) {
1223  pixDilateCompBrickDwa(pixt1, pixs, extrah, 1);
1224  pixt2 = pixDilateCompBrickDwa(NULL, pixt1, 63, 1);
1225  } else { /* they're all 63s */
1226  pixDilateCompBrickDwa(pixt1, pixs, 63, 1);
1227  pixt2 = pixDilateCompBrickDwa(NULL, pixt1, 63, 1);
1228  }
1229  for (i = 0; i < nops / 2 - 1; i++) {
1230  pixDilateCompBrickDwa(pixt1, pixt2, 63, 1);
1231  pixDilateCompBrickDwa(pixt2, pixt1, 63, 1);
1232  }
1233  }
1234  }
1235 
1236  /* Vertical dilation: pixt2 --> pixt3. */
1237  if (vsize == 1) {
1238  pixt3 = pixClone(pixt2);
1239  } else if (vsize < 64) {
1240  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, vsize);
1241  } else if (vsize == 64) { /* approximate */
1242  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, 63);
1243  } else {
1244  nops = (extrav < 3) ? nv : nv + 1;
1245  if (nops & 1) { /* odd */
1246  if (extrav > 2)
1247  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, extrav);
1248  else
1249  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, 63);
1250  for (i = 0; i < nops / 2; i++) {
1251  pixDilateCompBrickDwa(pixt1, pixt3, 1, 63);
1252  pixDilateCompBrickDwa(pixt3, pixt1, 1, 63);
1253  }
1254  } else { /* nops even */
1255  if (extrav > 2) {
1256  pixDilateCompBrickDwa(pixt1, pixt2, 1, extrav);
1257  pixt3 = pixDilateCompBrickDwa(NULL, pixt1, 1, 63);
1258  } else { /* they're all 63s */
1259  pixDilateCompBrickDwa(pixt1, pixt2, 1, 63);
1260  pixt3 = pixDilateCompBrickDwa(NULL, pixt1, 1, 63);
1261  }
1262  for (i = 0; i < nops / 2 - 1; i++) {
1263  pixDilateCompBrickDwa(pixt1, pixt3, 1, 63);
1264  pixDilateCompBrickDwa(pixt3, pixt1, 1, 63);
1265  }
1266  }
1267  }
1268  pixDestroy(&pixt1);
1269  pixDestroy(&pixt2);
1270 
1271  if (!pixd)
1272  return pixt3;
1273 
1274  pixTransferAllData(pixd, &pixt3, 0, 0);
1275  return pixd;
1276 }
1277 
1278 
1296 PIX *
1298  PIX *pixs,
1299  l_int32 hsize,
1300  l_int32 vsize)
1301 {
1302 l_int32 i, nops, nh, extrah, nv, extrav;
1303 PIX *pixt1, *pixt2, *pixt3;
1304 
1305  if (!pixs)
1306  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
1307  if (pixGetDepth(pixs) != 1)
1308  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
1309  if (hsize < 1 || vsize < 1)
1310  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
1311 
1312  if (hsize < 64 && vsize < 64)
1313  return pixErodeCompBrickDwa(pixd, pixs, hsize, vsize);
1314 
1315  if (hsize > 63)
1316  getExtendedCompositeParameters(hsize, &nh, &extrah, NULL);
1317  if (vsize > 63)
1318  getExtendedCompositeParameters(vsize, &nv, &extrav, NULL);
1319 
1320  /* Horizontal erosion first: pixs --> pixt2. Do not alter pixs. */
1321  pixt1 = pixCreateTemplate(pixs); /* temp image */
1322  if (hsize == 1) {
1323  pixt2 = pixClone(pixs);
1324  } else if (hsize < 64) {
1325  pixt2 = pixErodeCompBrickDwa(NULL, pixs, hsize, 1);
1326  } else if (hsize == 64) { /* approximate */
1327  pixt2 = pixErodeCompBrickDwa(NULL, pixs, 63, 1);
1328  } else {
1329  nops = (extrah < 3) ? nh : nh + 1;
1330  if (nops & 1) { /* odd */
1331  if (extrah > 2)
1332  pixt2 = pixErodeCompBrickDwa(NULL, pixs, extrah, 1);
1333  else
1334  pixt2 = pixErodeCompBrickDwa(NULL, pixs, 63, 1);
1335  for (i = 0; i < nops / 2; i++) {
1336  pixErodeCompBrickDwa(pixt1, pixt2, 63, 1);
1337  pixErodeCompBrickDwa(pixt2, pixt1, 63, 1);
1338  }
1339  } else { /* nops even */
1340  if (extrah > 2) {
1341  pixErodeCompBrickDwa(pixt1, pixs, extrah, 1);
1342  pixt2 = pixErodeCompBrickDwa(NULL, pixt1, 63, 1);
1343  } else { /* they're all 63s */
1344  pixErodeCompBrickDwa(pixt1, pixs, 63, 1);
1345  pixt2 = pixErodeCompBrickDwa(NULL, pixt1, 63, 1);
1346  }
1347  for (i = 0; i < nops / 2 - 1; i++) {
1348  pixErodeCompBrickDwa(pixt1, pixt2, 63, 1);
1349  pixErodeCompBrickDwa(pixt2, pixt1, 63, 1);
1350  }
1351  }
1352  }
1353 
1354  /* Vertical erosion: pixt2 --> pixt3. */
1355  if (vsize == 1) {
1356  pixt3 = pixClone(pixt2);
1357  } else if (vsize < 64) {
1358  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, vsize);
1359  } else if (vsize == 64) { /* approximate */
1360  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, 63);
1361  } else {
1362  nops = (extrav < 3) ? nv : nv + 1;
1363  if (nops & 1) { /* odd */
1364  if (extrav > 2)
1365  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, extrav);
1366  else
1367  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, 63);
1368  for (i = 0; i < nops / 2; i++) {
1369  pixErodeCompBrickDwa(pixt1, pixt3, 1, 63);
1370  pixErodeCompBrickDwa(pixt3, pixt1, 1, 63);
1371  }
1372  } else { /* nops even */
1373  if (extrav > 2) {
1374  pixErodeCompBrickDwa(pixt1, pixt2, 1, extrav);
1375  pixt3 = pixErodeCompBrickDwa(NULL, pixt1, 1, 63);
1376  } else { /* they're all 63s */
1377  pixErodeCompBrickDwa(pixt1, pixt2, 1, 63);
1378  pixt3 = pixErodeCompBrickDwa(NULL, pixt1, 1, 63);
1379  }
1380  for (i = 0; i < nops / 2 - 1; i++) {
1381  pixErodeCompBrickDwa(pixt1, pixt3, 1, 63);
1382  pixErodeCompBrickDwa(pixt3, pixt1, 1, 63);
1383  }
1384  }
1385  }
1386  pixDestroy(&pixt1);
1387  pixDestroy(&pixt2);
1388 
1389  if (!pixd)
1390  return pixt3;
1391 
1392  pixTransferAllData(pixd, &pixt3, 0, 0);
1393  return pixd;
1394 }
1395 
1396 
1417 PIX *
1419  PIX *pixs,
1420  l_int32 hsize,
1421  l_int32 vsize)
1422 {
1423 PIX *pixt;
1424 
1425  if (!pixs)
1426  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
1427  if (pixGetDepth(pixs) != 1)
1428  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
1429  if (hsize < 1 || vsize < 1)
1430  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
1431 
1432  pixt = pixErodeCompBrickExtendDwa(NULL, pixs, hsize, vsize);
1433  pixd = pixDilateCompBrickExtendDwa(pixd, pixt, hsize, vsize);
1434  pixDestroy(&pixt);
1435  return pixd;
1436 }
1437 
1438 
1459 PIX *
1461  PIX *pixs,
1462  l_int32 hsize,
1463  l_int32 vsize)
1464 {
1465 l_int32 bordercolor, borderx, bordery;
1466 PIX *pixt1, *pixt2, *pixt3;
1467 
1468  if (!pixs)
1469  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
1470  if (pixGetDepth(pixs) != 1)
1471  return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
1472  if (hsize < 1 || vsize < 1)
1473  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", __func__, pixd);
1474 
1475  /* For "safe closing" with ASYMMETRIC_MORPH_BC, we always need
1476  * an extra 32 OFF pixels around the image (in addition to
1477  * the 32 added pixels for all dwa operations), whereas with
1478  * SYMMETRIC_MORPH_BC this is not necessary. */
1479  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
1480  if (bordercolor == 0) { /* asymmetric b.c. */
1481  borderx = 32 + (hsize / 64) * 32;
1482  bordery = 32 + (vsize / 64) * 32;
1483  } else { /* symmetric b.c. */
1484  borderx = bordery = 32;
1485  }
1486  pixt1 = pixAddBorderGeneral(pixs, borderx, borderx, bordery, bordery, 0);
1487 
1488  pixt2 = pixDilateCompBrickExtendDwa(NULL, pixt1, hsize, vsize);
1489  pixErodeCompBrickExtendDwa(pixt1, pixt2, hsize, vsize);
1490 
1491  pixt3 = pixRemoveBorderGeneral(pixt1, borderx, borderx, bordery, bordery);
1492  pixDestroy(&pixt1);
1493  pixDestroy(&pixt2);
1494 
1495  if (!pixd)
1496  return pixt3;
1497 
1498  pixTransferAllData(pixd, &pixt3, 0, 0);
1499  return pixd;
1500 }
1501 
1502 
1546 l_ok
1548  l_int32 *pn,
1549  l_int32 *pextra,
1550  l_int32 *pactualsize)
1551 {
1552 l_int32 n, extra, fact1, fact2;
1553 
1554  if (!pn || !pextra)
1555  return ERROR_INT("&n and &extra not both defined", __func__, 1);
1556 
1557  if (size <= 63) {
1558  n = 0;
1559  extra = L_MIN(1, size);
1560  } else { /* size > 63 */
1561  n = 1 + (l_int32)((size - 63) / 62);
1562  extra = size - 63 - (n - 1) * 62 + 1;
1563  }
1564 
1565  if (pactualsize) {
1566  selectComposableSizes(extra, &fact1, &fact2);
1567  *pactualsize = 63 + (n - 1) * 62 + fact1 * fact2 - 1;
1568  }
1569 
1570  *pn = n;
1571  *pextra = extra;
1572  return 0;
1573 }
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1104
l_uint32 getMorphBorderPixelColor(l_int32 type, l_int32 depth)
getMorphBorderPixelColor()
Definition: morph.c:1761
PIX * pixCloseCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickExtendDwa()
Definition: morphdwa.c:1460
PIX * pixErodeCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrickDwa()
Definition: morphdwa.c:739
l_ok getExtendedCompositeParameters(l_int32 size, l_int32 *pn, l_int32 *pextra, l_int32 *pactualsize)
getExtendedCompositeParameters()
Definition: morphdwa.c:1547
PIX * pixOpenCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickDwa()
Definition: morphdwa.c:866
PIX * pixCloseCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickDwa()
Definition: morphdwa.c:1031
PIX * pixOpenBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenBrickDwa()
Definition: morphdwa.c:378
PIX * pixCloseBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseBrickDwa()
Definition: morphdwa.c:483
PIX * pixErodeBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrickDwa()
Definition: morphdwa.c:278
PIX * pixErodeCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrickExtendDwa()
Definition: morphdwa.c:1297
PIX * pixDilateCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrickDwa()
Definition: morphdwa.c:608
PIX * pixOpenCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickExtendDwa()
Definition: morphdwa.c:1418
PIX * pixDilateBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrickDwa()
Definition: morphdwa.c:178
PIX * pixDilateCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrickExtendDwa()
Definition: morphdwa.c:1179
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
l_ok pixTransferAllData(PIX *pixd, PIX **ppixs, l_int32 copytext, l_int32 copyformat)
pixTransferAllData()
Definition: pix1.c:879
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1996
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1773
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1863
PIX * pixRemoveBorder(PIX *pixs, l_int32 npix)
pixRemoveBorder()
Definition: pix2.c:1977
l_ok pixSetOrClearBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op)
pixSetOrClearBorder()
Definition: pix2.c:1474
#define PIX_CLR
Definition: pix.h:447
#define PIX_SET
Definition: pix.h:448
l_ok getCompositeParameters(l_int32 size, l_int32 *psize1, l_int32 *psize2, char **pnameh1, char **pnameh2, char **pnamev1, char **pnamev2)
getCompositeParameters()
Definition: sel1.c:1059
void selaDestroy(SELA **psela)
selaDestroy()
Definition: sel1.c:274
char * selaGetBrickName(SELA *sela, l_int32 hsize, l_int32 vsize)
selaGetBrickName()
Definition: sel1.c:897
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
Definition: morph.h:74
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306