Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
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 *-----------------------------------------------------------------*/
177PIX *
179 PIX *pixs,
180 l_int32 hsize,
181 l_int32 vsize)
182{
183l_int32 found;
184char *selnameh, *selnamev;
185SELA *sela;
186PIX *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
277PIX *
279 PIX *pixs,
280 l_int32 hsize,
281 l_int32 vsize)
282{
283l_int32 found;
284char *selnameh, *selnamev;
285SELA *sela;
286PIX *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
377PIX *
379 PIX *pixs,
380 l_int32 hsize,
381 l_int32 vsize)
382{
383l_int32 found;
384char *selnameh, *selnamev;
385SELA *sela;
386PIX *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
482PIX *
484 PIX *pixs,
485 l_int32 hsize,
486 l_int32 vsize)
487{
488l_int32 bordercolor, bordersize, found;
489char *selnameh, *selnamev;
490SELA *sela;
491PIX *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 *-----------------------------------------------------------------*/
607PIX *
609 PIX *pixs,
610 l_int32 hsize,
611 l_int32 vsize)
612{
613char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
614l_int32 hsize1, hsize2, vsize1, vsize2;
615PIX *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
738PIX *
740 PIX *pixs,
741 l_int32 hsize,
742 l_int32 vsize)
743{
744char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
745l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
746PIX *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
865PIX *
867 PIX *pixs,
868 l_int32 hsize,
869 l_int32 vsize)
870{
871char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
872l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
873PIX *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
1030PIX *
1032 PIX *pixs,
1033 l_int32 hsize,
1034 l_int32 vsize)
1035{
1036char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
1037l_int32 hsize1, hsize2, vsize1, vsize2, setborder;
1038PIX *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 *--------------------------------------------------------------------------*/
1178PIX *
1180 PIX *pixs,
1181 l_int32 hsize,
1182 l_int32 vsize)
1183{
1184l_int32 i, nops, nh, extrah, nv, extrav;
1185PIX *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
1296PIX *
1298 PIX *pixs,
1299 l_int32 hsize,
1300 l_int32 vsize)
1301{
1302l_int32 i, nops, nh, extrah, nv, extrav;
1303PIX *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
1417PIX *
1419 PIX *pixs,
1420 l_int32 hsize,
1421 l_int32 vsize)
1422{
1423PIX *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
1459PIX *
1461 PIX *pixs,
1462 l_int32 hsize,
1463 l_int32 vsize)
1464{
1465l_int32 bordercolor, borderx, bordery;
1466PIX *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
1546l_ok
1548 l_int32 *pn,
1549 l_int32 *pextra,
1550 l_int32 *pactualsize)
1551{
1552l_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}
PIX * pixCloseCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickExtendDwa()
Definition morphdwa.c:1460
l_ok getExtendedCompositeParameters(l_int32 size, l_int32 *pn, l_int32 *pextra, l_int32 *pactualsize)
getExtendedCompositeParameters()
Definition morphdwa.c:1547
PIX * pixDilateCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrickDwa()
Definition morphdwa.c:608
PIX * pixCloseBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseBrickDwa()
Definition morphdwa.c:483
PIX * pixDilateCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrickExtendDwa()
Definition morphdwa.c:1179
PIX * pixErodeCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrickExtendDwa()
Definition morphdwa.c:1297
PIX * pixDilateBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrickDwa()
Definition morphdwa.c:178
PIX * pixErodeBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrickDwa()
Definition morphdwa.c:278
PIX * pixErodeCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrickDwa()
Definition morphdwa.c:739
PIX * pixOpenBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenBrickDwa()
Definition morphdwa.c:378
PIX * pixCloseCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickDwa()
Definition morphdwa.c:1031
PIX * pixOpenCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickDwa()
Definition morphdwa.c:866
PIX * pixOpenCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickExtendDwa()
Definition morphdwa.c:1418
#define PIX_CLR
Definition pix.h:447
#define PIX_SET
Definition pix.h:448
Definition morph.h:74