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