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 *-----------------------------------------------------------------*/
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 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
279PIX *
281 PIX *pixs,
282 l_int32 hsize,
283 l_int32 vsize)
284{
285l_int32 found;
286char *selnameh, *selnamev;
287SELA *sela;
288PIX *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
381PIX *
383 PIX *pixs,
384 l_int32 hsize,
385 l_int32 vsize)
386{
387l_int32 found;
388char *selnameh, *selnamev;
389SELA *sela;
390PIX *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
488PIX *
490 PIX *pixs,
491 l_int32 hsize,
492 l_int32 vsize)
493{
494l_int32 bordercolor, bordersize, found;
495char *selnameh, *selnamev;
496SELA *sela;
497PIX *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 *-----------------------------------------------------------------*/
615PIX *
617 PIX *pixs,
618 l_int32 hsize,
619 l_int32 vsize)
620{
621char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
622l_int32 hsize1, hsize2, vsize1, vsize2;
623PIX *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
748PIX *
750 PIX *pixs,
751 l_int32 hsize,
752 l_int32 vsize)
753{
754char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
755l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
756PIX *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
877PIX *
879 PIX *pixs,
880 l_int32 hsize,
881 l_int32 vsize)
882{
883char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
884l_int32 hsize1, hsize2, vsize1, vsize2, bordercolor;
885PIX *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
1044PIX *
1046 PIX *pixs,
1047 l_int32 hsize,
1048 l_int32 vsize)
1049{
1050char *selnameh1, *selnameh2, *selnamev1, *selnamev2;
1051l_int32 hsize1, hsize2, vsize1, vsize2, setborder;
1052PIX *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 *--------------------------------------------------------------------------*/
1194PIX *
1196 PIX *pixs,
1197 l_int32 hsize,
1198 l_int32 vsize)
1199{
1200l_int32 i, nops, nh, extrah, nv, extrav;
1201PIX *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
1314PIX *
1316 PIX *pixs,
1317 l_int32 hsize,
1318 l_int32 vsize)
1319{
1320l_int32 i, nops, nh, extrah, nv, extrav;
1321PIX *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
1437PIX *
1439 PIX *pixs,
1440 l_int32 hsize,
1441 l_int32 vsize)
1442{
1443PIX *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
1481PIX *
1483 PIX *pixs,
1484 l_int32 hsize,
1485 l_int32 vsize)
1486{
1487l_int32 bordercolor, borderx, bordery;
1488PIX *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
1570l_ok
1572 l_int32 *pn,
1573 l_int32 *pextra,
1574 l_int32 *pactualsize)
1575{
1576l_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
l_uint32 getMorphBorderPixelColor(l_int32 type, l_int32 depth)
getMorphBorderPixelColor()
Definition: morph.c:1803
PIX * pixCloseCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickExtendDwa()
Definition: morphdwa.c:1482
l_ok getExtendedCompositeParameters(l_int32 size, l_int32 *pn, l_int32 *pextra, l_int32 *pactualsize)
getExtendedCompositeParameters()
Definition: morphdwa.c:1571
PIX * pixDilateCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrickDwa()
Definition: morphdwa.c:616
PIX * pixCloseBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseBrickDwa()
Definition: morphdwa.c:489
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
PIX * pixErodeBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrickDwa()
Definition: morphdwa.c:280
PIX * pixErodeCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrickDwa()
Definition: morphdwa.c:749
PIX * pixOpenBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenBrickDwa()
Definition: morphdwa.c:382
PIX * pixCloseCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrickDwa()
Definition: morphdwa.c:1045
PIX * pixOpenCompBrickDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickDwa()
Definition: morphdwa.c:878
PIX * pixOpenCompBrickExtendDwa(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrickExtendDwa()
Definition: morphdwa.c:1438
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_ok pixTransferAllData(PIX *pixd, PIX **ppixs, l_int32 copytext, l_int32 copyformat)
pixTransferAllData()
Definition: pix1.c:902
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixRemoveBorder(PIX *pixs, l_int32 npix)
pixRemoveBorder()
Definition: pix2.c:1972
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1993
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 * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1917
#define PIX_CLR
Definition: pix.h:333
#define PIX_SET
Definition: pix.h:334
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
void selaDestroy(SELA **psela)
selaDestroy()
Definition: sel1.c:276
char * selaGetBrickName(SELA *sela, l_int32 hsize, l_int32 vsize)
selaGetBrickName()
Definition: sel1.c:935
SELA * selaAddBasic(SELA *sela)
selaAddBasic()
Definition: sel2.c:99
Definition: pix.h:139
Definition: morph.h:74
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306