Leptonica  1.82.0
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  PROCNAME("pixDilateBrickDwa");
189 
190  if (!pixs)
191  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
192  if (pixGetDepth(pixs) != 1)
193  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
194  if (hsize < 1 || vsize < 1)
195  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
196 
197  if (hsize == 1 && vsize == 1)
198  return pixCopy(pixd, pixs);
199 
200  sela = selaAddBasic(NULL);
201  found = TRUE;
202  selnameh = selnamev = NULL;
203  if (hsize > 1) {
204  selnameh = selaGetBrickName(sela, hsize, 1);
205  if (!selnameh) found = FALSE;
206  }
207  if (vsize > 1) {
208  selnamev = selaGetBrickName(sela, 1, vsize);
209  if (!selnamev) found = FALSE;
210  }
211  selaDestroy(&sela);
212  if (!found) {
213  L_INFO("Calling the decomposable dwa function\n", procName);
214  if (selnameh) LEPT_FREE(selnameh);
215  if (selnamev) LEPT_FREE(selnamev);
216  return pixDilateCompBrickDwa(pixd, pixs, hsize, vsize);
217  }
218 
219  if (vsize == 1) {
220  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh);
221  LEPT_FREE(selnameh);
222  } else if (hsize == 1) {
223  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnamev);
224  LEPT_FREE(selnamev);
225  } else {
226  pixt1 = pixAddBorder(pixs, 32, 0);
227  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh);
228  pixFMorphopGen_1(pixt1, pixt3, L_MORPH_DILATE, selnamev);
229  pixt2 = pixRemoveBorder(pixt1, 32);
230  pixDestroy(&pixt1);
231  pixDestroy(&pixt3);
232  LEPT_FREE(selnameh);
233  LEPT_FREE(selnamev);
234  }
235 
236  if (!pixd)
237  return pixt2;
238 
239  pixTransferAllData(pixd, &pixt2, 0, 0);
240  return pixd;
241 }
242 
243 
279 PIX *
281  PIX *pixs,
282  l_int32 hsize,
283  l_int32 vsize)
284 {
285 l_int32 found;
286 char *selnameh, *selnamev;
287 SELA *sela;
288 PIX *pixt1, *pixt2, *pixt3;
289 
290  PROCNAME("pixErodeBrickDwa");
291 
292  if (!pixs)
293  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
294  if (pixGetDepth(pixs) != 1)
295  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
296  if (hsize < 1 || vsize < 1)
297  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
298 
299  if (hsize == 1 && vsize == 1)
300  return pixCopy(pixd, pixs);
301 
302  sela = selaAddBasic(NULL);
303  found = TRUE;
304  selnameh = selnamev = NULL;
305  if (hsize > 1) {
306  selnameh = selaGetBrickName(sela, hsize, 1);
307  if (!selnameh) found = FALSE;
308  }
309  if (vsize > 1) {
310  selnamev = selaGetBrickName(sela, 1, vsize);
311  if (!selnamev) found = FALSE;
312  }
313  selaDestroy(&sela);
314  if (!found) {
315  L_INFO("Calling the decomposable dwa function\n", procName);
316  if (selnameh) LEPT_FREE(selnameh);
317  if (selnamev) LEPT_FREE(selnamev);
318  return pixErodeCompBrickDwa(pixd, pixs, hsize, vsize);
319  }
320 
321  if (vsize == 1) {
322  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnameh);
323  LEPT_FREE(selnameh);
324  } else if (hsize == 1) {
325  pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnamev);
326  LEPT_FREE(selnamev);
327  } else {
328  pixt1 = pixAddBorder(pixs, 32, 0);
329  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh);
330  pixFMorphopGen_1(pixt1, pixt3, L_MORPH_ERODE, selnamev);
331  pixt2 = pixRemoveBorder(pixt1, 32);
332  pixDestroy(&pixt1);
333  pixDestroy(&pixt3);
334  LEPT_FREE(selnameh);
335  LEPT_FREE(selnamev);
336  }
337 
338  if (!pixd)
339  return pixt2;
340 
341  pixTransferAllData(pixd, &pixt2, 0, 0);
342  return pixd;
343 }
344 
345 
381 PIX *
383  PIX *pixs,
384  l_int32 hsize,
385  l_int32 vsize)
386 {
387 l_int32 found;
388 char *selnameh, *selnamev;
389 SELA *sela;
390 PIX *pixt1, *pixt2, *pixt3;
391 
392  PROCNAME("pixOpenBrickDwa");
393 
394  if (!pixs)
395  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
396  if (pixGetDepth(pixs) != 1)
397  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
398  if (hsize < 1 || vsize < 1)
399  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
400 
401  if (hsize == 1 && vsize == 1)
402  return pixCopy(pixd, pixs);
403 
404  sela = selaAddBasic(NULL);
405  found = TRUE;
406  selnameh = selnamev = NULL;
407  if (hsize > 1) {
408  selnameh = selaGetBrickName(sela, hsize, 1);
409  if (!selnameh) found = FALSE;
410  }
411  if (vsize > 1) {
412  selnamev = selaGetBrickName(sela, 1, vsize);
413  if (!selnamev) found = FALSE;
414  }
415  selaDestroy(&sela);
416  if (!found) {
417  L_INFO("Calling the decomposable dwa function\n", procName);
418  if (selnameh) LEPT_FREE(selnameh);
419  if (selnamev) LEPT_FREE(selnamev);
420  return pixOpenCompBrickDwa(pixd, pixs, hsize, vsize);
421  }
422 
423  pixt1 = pixAddBorder(pixs, 32, 0);
424  if (vsize == 1) { /* horizontal only */
425  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_OPEN, selnameh);
426  LEPT_FREE(selnameh);
427  } else if (hsize == 1) { /* vertical only */
428  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_OPEN, selnamev);
429  LEPT_FREE(selnamev);
430  } else { /* do separable */
431  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh);
432  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev);
433  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh);
434  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnamev);
435  LEPT_FREE(selnameh);
436  LEPT_FREE(selnamev);
437  pixDestroy(&pixt3);
438  }
439  pixt3 = pixRemoveBorder(pixt2, 32);
440  pixDestroy(&pixt1);
441  pixDestroy(&pixt2);
442 
443  if (!pixd)
444  return pixt3;
445 
446  pixTransferAllData(pixd, &pixt3, 0, 0);
447  return pixd;
448 }
449 
450 
488 PIX *
490  PIX *pixs,
491  l_int32 hsize,
492  l_int32 vsize)
493 {
494 l_int32 bordercolor, bordersize, found;
495 char *selnameh, *selnamev;
496 SELA *sela;
497 PIX *pixt1, *pixt2, *pixt3;
498 
499  PROCNAME("pixCloseBrickDwa");
500 
501  if (!pixs)
502  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
503  if (pixGetDepth(pixs) != 1)
504  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
505  if (hsize < 1 || vsize < 1)
506  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
507 
508  if (hsize == 1 && vsize == 1)
509  return pixCopy(pixd, pixs);
510 
511  sela = selaAddBasic(NULL);
512  found = TRUE;
513  selnameh = selnamev = NULL;
514  if (hsize > 1) {
515  selnameh = selaGetBrickName(sela, hsize, 1);
516  if (!selnameh) found = FALSE;
517  }
518  if (vsize > 1) {
519  selnamev = selaGetBrickName(sela, 1, vsize);
520  if (!selnamev) found = FALSE;
521  }
522  selaDestroy(&sela);
523  if (!found) {
524  L_INFO("Calling the decomposable dwa function\n", procName);
525  if (selnameh) LEPT_FREE(selnameh);
526  if (selnamev) LEPT_FREE(selnamev);
527  return pixCloseCompBrickDwa(pixd, pixs, hsize, vsize);
528  }
529 
530  /* For "safe closing" with ASYMMETRIC_MORPH_BC, we always need
531  * an extra 32 OFF pixels around the image (in addition to
532  * the 32 added pixels for all dwa operations), whereas with
533  * SYMMETRIC_MORPH_BC this is not necessary. */
534  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
535  if (bordercolor == 0) /* asymmetric b.c. */
536  bordersize = 64;
537  else /* symmetric b.c. */
538  bordersize = 32;
539  pixt1 = pixAddBorder(pixs, bordersize, 0);
540 
541  if (vsize == 1) { /* horizontal only */
542  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnameh);
543  LEPT_FREE(selnameh);
544  } else if (hsize == 1) { /* vertical only */
545  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnamev);
546  LEPT_FREE(selnamev);
547  } else { /* do separable */
548  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh);
549  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev);
550  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh);
551  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnamev);
552  LEPT_FREE(selnameh);
553  LEPT_FREE(selnamev);
554  pixDestroy(&pixt3);
555  }
556  pixt3 = pixRemoveBorder(pixt2, bordersize);
557  pixDestroy(&pixt1);
558  pixDestroy(&pixt2);
559 
560  if (!pixd)
561  return pixt3;
562 
563  pixTransferAllData(pixd, &pixt3, 0, 0);
564  return pixd;
565 }
566 
567 
568 /*-----------------------------------------------------------------*
569  * Binary composite morphological (dwa) ops with brick Sels *
570  *-----------------------------------------------------------------*/
615 PIX *
617  PIX *pixs,
618  l_int32 hsize,
619  l_int32 vsize)
620 {
621 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
622 l_int32 hsize1, hsize2, vsize1, vsize2;
623 PIX *pixt1, *pixt2, *pixt3;
624 
625  PROCNAME("pixDilateCompBrickDwa");
626 
627  if (!pixs)
628  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
629  if (pixGetDepth(pixs) != 1)
630  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
631  if (hsize < 1 || vsize < 1)
632  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
633  if (hsize > 63 || vsize > 63)
634  return pixDilateCompBrickExtendDwa(pixd, pixs, hsize, vsize);
635 
636  if (hsize == 1 && vsize == 1)
637  return pixCopy(pixd, pixs);
638 
639  hsize1 = hsize2 = vsize1 = vsize2 = 1;
640  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
641  if (hsize > 1)
642  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
643  &selnameh2, NULL, NULL);
644  if (vsize > 1)
645  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
646  &selnamev1, &selnamev2);
647 
648 #if DEBUG_SEL_LOOKUP
649  lept_stderr("nameh1=%s, nameh2=%s, namev1=%s, namev2=%s\n",
650  selnameh1, selnameh2, selnamev1, selnamev2);
651  lept_stderr("hsize1=%d, hsize2=%d, vsize1=%d, vsize2=%d\n",
652  hsize1, hsize2, vsize1, vsize2);
653 #endif /* DEBUG_SEL_LOOKUP */
654 
655  pixt1 = pixAddBorder(pixs, 64, 0);
656  if (vsize == 1) {
657  if (hsize2 == 1) {
658  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
659  } else {
660  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
661  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
662  pixDestroy(&pixt3);
663  }
664  } else if (hsize == 1) {
665  if (vsize2 == 1) {
666  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnamev1);
667  } else {
668  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnamev1);
669  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnamev2);
670  pixDestroy(&pixt3);
671  }
672  } else { /* vsize and hsize both > 1 */
673  if (hsize2 == 1) {
674  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
675  } else {
676  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
677  pixt3 = pixFMorphopGen_2(NULL, pixt2, L_MORPH_DILATE, selnameh2);
678  pixDestroy(&pixt2);
679  }
680  if (vsize2 == 1) {
681  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
682  } else {
683  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
684  pixFMorphopGen_2(pixt2, pixt2, L_MORPH_DILATE, selnamev2);
685  }
686  pixDestroy(&pixt3);
687  }
688  pixDestroy(&pixt1);
689  pixt1 = pixRemoveBorder(pixt2, 64);
690  pixDestroy(&pixt2);
691  if (selnameh1) LEPT_FREE(selnameh1);
692  if (selnameh2) LEPT_FREE(selnameh2);
693  if (selnamev1) LEPT_FREE(selnamev1);
694  if (selnamev2) LEPT_FREE(selnamev2);
695 
696  if (!pixd)
697  return pixt1;
698 
699  pixTransferAllData(pixd, &pixt1, 0, 0);
700  return pixd;
701 }
702 
703 
748 PIX *
750  PIX *pixs,
751  l_int32 hsize,
752  l_int32 vsize)
753 {
754 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
755 l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
756 PIX *pixt1, *pixt2, *pixt3;
757 
758  PROCNAME("pixErodeCompBrickDwa");
759 
760  if (!pixs)
761  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
762  if (pixGetDepth(pixs) != 1)
763  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
764  if (hsize < 1 || vsize < 1)
765  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
766  if (hsize > 63 || vsize > 63)
767  return pixErodeCompBrickExtendDwa(pixd, pixs, hsize, vsize);
768 
769  if (hsize == 1 && vsize == 1)
770  return pixCopy(pixd, pixs);
771 
772  hsize1 = hsize2 = vsize1 = vsize2 = 1;
773  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
774  if (hsize > 1)
775  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
776  &selnameh2, NULL, NULL);
777  if (vsize > 1)
778  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
779  &selnamev1, &selnamev2);
780 
781  /* For symmetric b.c., bordercolor == 1 for erosion */
782  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
783  pixt1 = pixAddBorder(pixs, 64, bordercolor);
784 
785  if (vsize == 1) {
786  if (hsize2 == 1) {
787  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
788  } else {
789  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
790  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
791  pixDestroy(&pixt3);
792  }
793  } else if (hsize == 1) {
794  if (vsize2 == 1) {
795  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
796  } else {
797  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
798  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnamev2);
799  pixDestroy(&pixt3);
800  }
801  } else { /* vsize and hsize both > 1 */
802  if (hsize2 == 1) {
803  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
804  } else {
805  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
806  pixt3 = pixFMorphopGen_2(NULL, pixt2, L_MORPH_ERODE, selnameh2);
807  pixDestroy(&pixt2);
808  }
809  if (vsize2 == 1) {
810  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
811  } else {
812  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
813  pixFMorphopGen_2(pixt2, pixt2, L_MORPH_ERODE, selnamev2);
814  }
815  pixDestroy(&pixt3);
816  }
817  pixDestroy(&pixt1);
818  pixt1 = pixRemoveBorder(pixt2, 64);
819  pixDestroy(&pixt2);
820  if (selnameh1) LEPT_FREE(selnameh1);
821  if (selnameh2) LEPT_FREE(selnameh2);
822  if (selnamev1) LEPT_FREE(selnamev1);
823  if (selnamev2) LEPT_FREE(selnamev2);
824 
825  if (!pixd)
826  return pixt1;
827 
828  pixTransferAllData(pixd, &pixt1, 0, 0);
829  return pixd;
830 }
831 
832 
877 PIX *
879  PIX *pixs,
880  l_int32 hsize,
881  l_int32 vsize)
882 {
883 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
884 l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
885 PIX *pixt1, *pixt2, *pixt3;
886 
887  PROCNAME("pixOpenCompBrickDwa");
888 
889  if (!pixs)
890  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
891  if (pixGetDepth(pixs) != 1)
892  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
893  if (hsize < 1 || vsize < 1)
894  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
895  if (hsize > 63 || vsize > 63)
896  return pixOpenCompBrickExtendDwa(pixd, pixs, hsize, vsize);
897 
898  if (hsize == 1 && vsize == 1)
899  return pixCopy(pixd, pixs);
900 
901  hsize1 = hsize2 = vsize1 = vsize2 = 1;
902  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
903  if (hsize > 1)
904  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
905  &selnameh2, NULL, NULL);
906  if (vsize > 1)
907  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
908  &selnamev1, &selnamev2);
909 
910  /* For symmetric b.c., initialize erosion with bordercolor == 1 */
911  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
912  pixt1 = pixAddBorder(pixs, 64, bordercolor);
913 
914  if (vsize == 1) {
915  if (hsize2 == 1) {
916  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
917  if (bordercolor == 1)
918  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
919  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnameh1);
920  } else {
921  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
922  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
923  if (bordercolor == 1)
924  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
925  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh1);
926  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnameh2);
927  }
928  } else if (hsize == 1) {
929  if (vsize2 == 1) {
930  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
931  if (bordercolor == 1)
932  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
933  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
934  } else {
935  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnamev1);
936  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnamev2);
937  if (bordercolor == 1)
938  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
939  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
940  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
941  }
942  } else { /* vsize and hsize both > 1 */
943  if (hsize2 == 1 && vsize2 == 1) {
944  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
945  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
946  if (bordercolor == 1)
947  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
948  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh1);
949  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnamev1);
950  } else if (vsize2 == 1) {
951  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
952  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
953  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
954  if (bordercolor == 1)
955  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
956  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnameh1);
957  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_DILATE, selnameh2);
958  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnamev1);
959  } else if (hsize2 == 1) {
960  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
961  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_ERODE, selnamev1);
962  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_ERODE, selnamev2);
963  if (bordercolor == 1)
964  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_CLR);
965  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnameh1);
966  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
967  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
968  } else { /* both directions are combed */
969  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh1);
970  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_ERODE, selnameh2);
971  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
972  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
973  if (bordercolor == 1)
974  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_CLR);
975  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnameh1);
976  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnameh2);
977  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
978  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
979  }
980  }
981  pixDestroy(&pixt3);
982 
983  pixDestroy(&pixt1);
984  pixt1 = pixRemoveBorder(pixt2, 64);
985  pixDestroy(&pixt2);
986  if (selnameh1) LEPT_FREE(selnameh1);
987  if (selnameh2) LEPT_FREE(selnameh2);
988  if (selnamev1) LEPT_FREE(selnamev1);
989  if (selnamev2) LEPT_FREE(selnamev2);
990 
991  if (!pixd)
992  return pixt1;
993 
994  pixTransferAllData(pixd, &pixt1, 0, 0);
995  return pixd;
996 }
997 
998 
1044 PIX *
1046  PIX *pixs,
1047  l_int32 hsize,
1048  l_int32 vsize)
1049 {
1050 char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
1051 l_int32 hsize1, hsize2, vsize1, vsize2, setborder;
1052 PIX *pixt1, *pixt2, *pixt3;
1053 
1054  PROCNAME("pixCloseCompBrickDwa");
1055 
1056  if (!pixs)
1057  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1058  if (pixGetDepth(pixs) != 1)
1059  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1060  if (hsize < 1 || vsize < 1)
1061  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1062  if (hsize > 63 || vsize > 63)
1063  return pixCloseCompBrickExtendDwa(pixd, pixs, hsize, vsize);
1064 
1065  if (hsize == 1 && vsize == 1)
1066  return pixCopy(pixd, pixs);
1067 
1068  hsize1 = hsize2 = vsize1 = vsize2 = 1;
1069  selnameh1 = selnameh2 = selnamev1 = selnamev2 = NULL;
1070  if (hsize > 1)
1071  getCompositeParameters(hsize, &hsize1, &hsize2, &selnameh1,
1072  &selnameh2, NULL, NULL);
1073  if (vsize > 1)
1074  getCompositeParameters(vsize, &vsize1, &vsize2, NULL, NULL,
1075  &selnamev1, &selnamev2);
1076 
1077  pixt3 = NULL;
1078  /* For symmetric b.c., PIX_SET border for erosions */
1079  setborder = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
1080  pixt1 = pixAddBorder(pixs, 64, 0);
1081 
1082  if (vsize == 1) {
1083  if (hsize2 == 1) {
1084  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnameh1);
1085  } else {
1086  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1087  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
1088  if (setborder == 1)
1089  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1090  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh1);
1091  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnameh2);
1092  }
1093  } else if (hsize == 1) {
1094  if (vsize2 == 1) {
1095  pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnamev1);
1096  } else {
1097  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnamev1);
1098  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnamev2);
1099  if (setborder == 1)
1100  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1101  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
1102  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
1103  }
1104  } else { /* vsize and hsize both > 1 */
1105  if (hsize2 == 1 && vsize2 == 1) {
1106  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1107  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
1108  if (setborder == 1)
1109  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1110  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh1);
1111  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnamev1);
1112  } else if (vsize2 == 1) {
1113  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1114  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
1115  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
1116  if (setborder == 1)
1117  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_SET);
1118  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnameh1);
1119  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_ERODE, selnameh2);
1120  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnamev1);
1121  } else if (hsize2 == 1) {
1122  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1123  pixt2 = pixFMorphopGen_1(NULL, pixt3, L_MORPH_DILATE, selnamev1);
1124  pixFMorphopGen_2(pixt3, pixt2, L_MORPH_DILATE, selnamev2);
1125  if (setborder == 1)
1126  pixSetOrClearBorder(pixt3, 64, 64, 64, 64, PIX_SET);
1127  pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnameh1);
1128  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
1129  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
1130  } else { /* both directions are combed */
1131  pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh1);
1132  pixt2 = pixFMorphopGen_2(NULL, pixt3, L_MORPH_DILATE, selnameh2);
1133  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev1);
1134  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_DILATE, selnamev2);
1135  if (setborder == 1)
1136  pixSetOrClearBorder(pixt2, 64, 64, 64, 64, PIX_SET);
1137  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnameh1);
1138  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnameh2);
1139  pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev1);
1140  pixFMorphopGen_2(pixt2, pixt3, L_MORPH_ERODE, selnamev2);
1141  }
1142  }
1143  pixDestroy(&pixt3);
1144 
1145  pixDestroy(&pixt1);
1146  pixt1 = pixRemoveBorder(pixt2, 64);
1147  pixDestroy(&pixt2);
1148  if (selnameh1) LEPT_FREE(selnameh1);
1149  if (selnameh2) LEPT_FREE(selnameh2);
1150  if (selnamev1) LEPT_FREE(selnamev1);
1151  if (selnamev2) LEPT_FREE(selnamev2);
1152 
1153  if (!pixd)
1154  return pixt1;
1155 
1156  pixTransferAllData(pixd, &pixt1, 0, 0);
1157  return pixd;
1158 }
1159 
1160 
1161 /*--------------------------------------------------------------------------*
1162  * Binary expanded composite morphological (dwa) ops with brick Sels *
1163  *--------------------------------------------------------------------------*/
1194 PIX *
1196  PIX *pixs,
1197  l_int32 hsize,
1198  l_int32 vsize)
1199 {
1200 l_int32 i, nops, nh, extrah, nv, extrav;
1201 PIX *pixt1, *pixt2, *pixt3;
1202 
1203  PROCNAME("pixDilateCompBrickExtendDwa");
1204 
1205  if (!pixs)
1206  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1207  if (pixGetDepth(pixs) != 1)
1208  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1209  if (hsize < 1 || vsize < 1)
1210  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1211 
1212  if (hsize < 64 && vsize < 64)
1213  return pixDilateCompBrickDwa(pixd, pixs, hsize, vsize);
1214 
1215  if (hsize > 63)
1216  getExtendedCompositeParameters(hsize, &nh, &extrah, NULL);
1217  if (vsize > 63)
1218  getExtendedCompositeParameters(vsize, &nv, &extrav, NULL);
1219 
1220  /* Horizontal dilation first: pixs --> pixt2. Do not alter pixs. */
1221  pixt1 = pixCreateTemplate(pixs); /* temp image */
1222  if (hsize == 1) {
1223  pixt2 = pixClone(pixs);
1224  } else if (hsize < 64) {
1225  pixt2 = pixDilateCompBrickDwa(NULL, pixs, hsize, 1);
1226  } else if (hsize == 64) { /* approximate */
1227  pixt2 = pixDilateCompBrickDwa(NULL, pixs, 63, 1);
1228  } else {
1229  nops = (extrah < 3) ? nh : nh + 1;
1230  if (nops & 1) { /* odd */
1231  if (extrah > 2)
1232  pixt2 = pixDilateCompBrickDwa(NULL, pixs, extrah, 1);
1233  else
1234  pixt2 = pixDilateCompBrickDwa(NULL, pixs, 63, 1);
1235  for (i = 0; i < nops / 2; i++) {
1236  pixDilateCompBrickDwa(pixt1, pixt2, 63, 1);
1237  pixDilateCompBrickDwa(pixt2, pixt1, 63, 1);
1238  }
1239  } else { /* nops even */
1240  if (extrah > 2) {
1241  pixDilateCompBrickDwa(pixt1, pixs, extrah, 1);
1242  pixt2 = pixDilateCompBrickDwa(NULL, pixt1, 63, 1);
1243  } else { /* they're all 63s */
1244  pixDilateCompBrickDwa(pixt1, pixs, 63, 1);
1245  pixt2 = pixDilateCompBrickDwa(NULL, pixt1, 63, 1);
1246  }
1247  for (i = 0; i < nops / 2 - 1; i++) {
1248  pixDilateCompBrickDwa(pixt1, pixt2, 63, 1);
1249  pixDilateCompBrickDwa(pixt2, pixt1, 63, 1);
1250  }
1251  }
1252  }
1253 
1254  /* Vertical dilation: pixt2 --> pixt3. */
1255  if (vsize == 1) {
1256  pixt3 = pixClone(pixt2);
1257  } else if (vsize < 64) {
1258  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, vsize);
1259  } else if (vsize == 64) { /* approximate */
1260  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, 63);
1261  } else {
1262  nops = (extrav < 3) ? nv : nv + 1;
1263  if (nops & 1) { /* odd */
1264  if (extrav > 2)
1265  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, extrav);
1266  else
1267  pixt3 = pixDilateCompBrickDwa(NULL, pixt2, 1, 63);
1268  for (i = 0; i < nops / 2; i++) {
1269  pixDilateCompBrickDwa(pixt1, pixt3, 1, 63);
1270  pixDilateCompBrickDwa(pixt3, pixt1, 1, 63);
1271  }
1272  } else { /* nops even */
1273  if (extrav > 2) {
1274  pixDilateCompBrickDwa(pixt1, pixt2, 1, extrav);
1275  pixt3 = pixDilateCompBrickDwa(NULL, pixt1, 1, 63);
1276  } else { /* they're all 63s */
1277  pixDilateCompBrickDwa(pixt1, pixt2, 1, 63);
1278  pixt3 = pixDilateCompBrickDwa(NULL, pixt1, 1, 63);
1279  }
1280  for (i = 0; i < nops / 2 - 1; i++) {
1281  pixDilateCompBrickDwa(pixt1, pixt3, 1, 63);
1282  pixDilateCompBrickDwa(pixt3, pixt1, 1, 63);
1283  }
1284  }
1285  }
1286  pixDestroy(&pixt1);
1287  pixDestroy(&pixt2);
1288 
1289  if (!pixd)
1290  return pixt3;
1291 
1292  pixTransferAllData(pixd, &pixt3, 0, 0);
1293  return pixd;
1294 }
1295 
1296 
1314 PIX *
1316  PIX *pixs,
1317  l_int32 hsize,
1318  l_int32 vsize)
1319 {
1320 l_int32 i, nops, nh, extrah, nv, extrav;
1321 PIX *pixt1, *pixt2, *pixt3;
1322 
1323  PROCNAME("pixErodeCompBrickExtendDwa");
1324 
1325  if (!pixs)
1326  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1327  if (pixGetDepth(pixs) != 1)
1328  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1329  if (hsize < 1 || vsize < 1)
1330  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1331 
1332  if (hsize < 64 && vsize < 64)
1333  return pixErodeCompBrickDwa(pixd, pixs, hsize, vsize);
1334 
1335  if (hsize > 63)
1336  getExtendedCompositeParameters(hsize, &nh, &extrah, NULL);
1337  if (vsize > 63)
1338  getExtendedCompositeParameters(vsize, &nv, &extrav, NULL);
1339 
1340  /* Horizontal erosion first: pixs --> pixt2. Do not alter pixs. */
1341  pixt1 = pixCreateTemplate(pixs); /* temp image */
1342  if (hsize == 1) {
1343  pixt2 = pixClone(pixs);
1344  } else if (hsize < 64) {
1345  pixt2 = pixErodeCompBrickDwa(NULL, pixs, hsize, 1);
1346  } else if (hsize == 64) { /* approximate */
1347  pixt2 = pixErodeCompBrickDwa(NULL, pixs, 63, 1);
1348  } else {
1349  nops = (extrah < 3) ? nh : nh + 1;
1350  if (nops & 1) { /* odd */
1351  if (extrah > 2)
1352  pixt2 = pixErodeCompBrickDwa(NULL, pixs, extrah, 1);
1353  else
1354  pixt2 = pixErodeCompBrickDwa(NULL, pixs, 63, 1);
1355  for (i = 0; i < nops / 2; i++) {
1356  pixErodeCompBrickDwa(pixt1, pixt2, 63, 1);
1357  pixErodeCompBrickDwa(pixt2, pixt1, 63, 1);
1358  }
1359  } else { /* nops even */
1360  if (extrah > 2) {
1361  pixErodeCompBrickDwa(pixt1, pixs, extrah, 1);
1362  pixt2 = pixErodeCompBrickDwa(NULL, pixt1, 63, 1);
1363  } else { /* they're all 63s */
1364  pixErodeCompBrickDwa(pixt1, pixs, 63, 1);
1365  pixt2 = pixErodeCompBrickDwa(NULL, pixt1, 63, 1);
1366  }
1367  for (i = 0; i < nops / 2 - 1; i++) {
1368  pixErodeCompBrickDwa(pixt1, pixt2, 63, 1);
1369  pixErodeCompBrickDwa(pixt2, pixt1, 63, 1);
1370  }
1371  }
1372  }
1373 
1374  /* Vertical erosion: pixt2 --> pixt3. */
1375  if (vsize == 1) {
1376  pixt3 = pixClone(pixt2);
1377  } else if (vsize < 64) {
1378  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, vsize);
1379  } else if (vsize == 64) { /* approximate */
1380  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, 63);
1381  } else {
1382  nops = (extrav < 3) ? nv : nv + 1;
1383  if (nops & 1) { /* odd */
1384  if (extrav > 2)
1385  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, extrav);
1386  else
1387  pixt3 = pixErodeCompBrickDwa(NULL, pixt2, 1, 63);
1388  for (i = 0; i < nops / 2; i++) {
1389  pixErodeCompBrickDwa(pixt1, pixt3, 1, 63);
1390  pixErodeCompBrickDwa(pixt3, pixt1, 1, 63);
1391  }
1392  } else { /* nops even */
1393  if (extrav > 2) {
1394  pixErodeCompBrickDwa(pixt1, pixt2, 1, extrav);
1395  pixt3 = pixErodeCompBrickDwa(NULL, pixt1, 1, 63);
1396  } else { /* they're all 63s */
1397  pixErodeCompBrickDwa(pixt1, pixt2, 1, 63);
1398  pixt3 = pixErodeCompBrickDwa(NULL, pixt1, 1, 63);
1399  }
1400  for (i = 0; i < nops / 2 - 1; i++) {
1401  pixErodeCompBrickDwa(pixt1, pixt3, 1, 63);
1402  pixErodeCompBrickDwa(pixt3, pixt1, 1, 63);
1403  }
1404  }
1405  }
1406  pixDestroy(&pixt1);
1407  pixDestroy(&pixt2);
1408 
1409  if (!pixd)
1410  return pixt3;
1411 
1412  pixTransferAllData(pixd, &pixt3, 0, 0);
1413  return pixd;
1414 }
1415 
1416 
1437 PIX *
1439  PIX *pixs,
1440  l_int32 hsize,
1441  l_int32 vsize)
1442 {
1443 PIX *pixt;
1444 
1445  PROCNAME("pixOpenCompBrickExtendDwa");
1446 
1447  if (!pixs)
1448  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1449  if (pixGetDepth(pixs) != 1)
1450  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1451  if (hsize < 1 || vsize < 1)
1452  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1453 
1454  pixt = pixErodeCompBrickExtendDwa(NULL, pixs, hsize, vsize);
1455  pixd = pixDilateCompBrickExtendDwa(pixd, pixt, hsize, vsize);
1456  pixDestroy(&pixt);
1457  return pixd;
1458 }
1459 
1460 
1481 PIX *
1483  PIX *pixs,
1484  l_int32 hsize,
1485  l_int32 vsize)
1486 {
1487 l_int32 bordercolor, borderx, bordery;
1488 PIX *pixt1, *pixt2, *pixt3;
1489 
1490  PROCNAME("pixCloseCompBrickExtendDwa");
1491 
1492  if (!pixs)
1493  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1494  if (pixGetDepth(pixs) != 1)
1495  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
1496  if (hsize < 1 || vsize < 1)
1497  return (PIX *)ERROR_PTR("hsize and vsize not >= 1", procName, pixd);
1498 
1499  /* For "safe closing" with ASYMMETRIC_MORPH_BC, we always need
1500  * an extra 32 OFF pixels around the image (in addition to
1501  * the 32 added pixels for all dwa operations), whereas with
1502  * SYMMETRIC_MORPH_BC this is not necessary. */
1503  bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
1504  if (bordercolor == 0) { /* asymmetric b.c. */
1505  borderx = 32 + (hsize / 64) * 32;
1506  bordery = 32 + (vsize / 64) * 32;
1507  } else { /* symmetric b.c. */
1508  borderx = bordery = 32;
1509  }
1510  pixt1 = pixAddBorderGeneral(pixs, borderx, borderx, bordery, bordery, 0);
1511 
1512  pixt2 = pixDilateCompBrickExtendDwa(NULL, pixt1, hsize, vsize);
1513  pixErodeCompBrickExtendDwa(pixt1, pixt2, hsize, vsize);
1514 
1515  pixt3 = pixRemoveBorderGeneral(pixt1, borderx, borderx, bordery, bordery);
1516  pixDestroy(&pixt1);
1517  pixDestroy(&pixt2);
1518 
1519  if (!pixd)
1520  return pixt3;
1521 
1522  pixTransferAllData(pixd, &pixt3, 0, 0);
1523  return pixd;
1524 }
1525 
1526 
1570 l_ok
1572  l_int32 *pn,
1573  l_int32 *pextra,
1574  l_int32 *pactualsize)
1575 {
1576 l_int32 n, extra, fact1, fact2;
1577 
1578  PROCNAME("getExtendedCompositeParameters");
1579 
1580  if (!pn || !pextra)
1581  return ERROR_INT("&n and &extra not both defined", procName, 1);
1582 
1583  if (size <= 63) {
1584  n = 0;
1585  extra = L_MIN(1, size);
1586  } else { /* size > 63 */
1587  n = 1 + (l_int32)((size - 63) / 62);
1588  extra = size - 63 - (n - 1) * 62 + 1;
1589  }
1590 
1591  if (pactualsize) {
1592  selectComposableSizes(extra, &fact1, &fact2);
1593  *pactualsize = 63 + (n - 1) * 62 + fact1 * fact2 - 1;
1594  }
1595 
1596  *pn = n;
1597  *pextra = extra;
1598  return 0;
1599 }
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
Definition: morph.c:1132
PIX * pixCloseCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickDwa()
Definition: morphdwa.c:1045
#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
char * selaGetBrickName(SELA *sela, l_int32 hsize, l_int32 vsize)
selaGetBrickName()
Definition: sel1.c:935
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
PIX * pixDilateCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrickExtendDwa()
Definition: morphdwa.c:1195
PIX * pixErodeCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrickExtendDwa()
Definition: morphdwa.c:1315
PIX * pixDilateBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrickDwa()
Definition: morphdwa.c:178
void selaDestroy(SELA **psela)
selaDestroy()
Definition: sel1.c:276
l_ok pixSetOrClearBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op)
pixSetOrClearBorder()
Definition: pix2.c:1514
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
Definition: pix2.c:1823
PIX * pixRemoveBorder(PIX *pixs, l_int32 npix)
pixRemoveBorder()
Definition: pix2.c:1972
l_ok getExtendedCompositeParameters(l_int32 size, l_int32 *pn, l_int32 *pextra, l_int32 *pactualsize)
getExtendedCompositeParameters()
Definition: morphdwa.c:1571
PIX * pixOpenCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickExtendDwa()
Definition: morphdwa.c:1438
#define PIX_SET
Definition: pix.h:334
PIX * pixCloseBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseBrickDwa()
Definition: morphdwa.c:489
PIX * pixErodeBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrickDwa()
Definition: morphdwa.c:280
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixOpenCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickDwa()
Definition: morphdwa.c:878
l_ok getCompositeParameters(l_int32 size, l_int32 *psize1, l_int32 *psize2, char **pnameh1, char **pnameh2, char **pnamev1, char **pnamev2)
getCompositeParameters()
Definition: sel1.c:1101
PIX * pixOpenBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenBrickDwa()
Definition: morphdwa.c:382
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
Definition: pix.h:138
Definition: morph.h:73
PIX * pixDilateCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrickDwa()
Definition: morphdwa.c:616
l_ok pixTransferAllData(PIX *pixd, PIX **ppixs, l_int32 copytext, l_int32 copyformat)
pixTransferAllData()
Definition: pix1.c:902
PIX * pixErodeCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrickDwa()
Definition: morphdwa.c:749
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1917
PIX * pixCloseCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickExtendDwa()
Definition: morphdwa.c:1482