166 #include <config_auto.h>
170 #include "allheaders.h"
176 LEPT_DLL l_int32 MORPH_BC = ASYMMETRIC_MORPH_BC;
179 static const l_int32 ACCEPTABLE_COST = 5;
217 l_int32 i, j, w, h, sx, sy, cx, cy, seldata;
221 return (
PIX *)ERROR_PTR(
"processMorphArgs1 failed", __func__, pixd);
226 for (i = 0; i < sy; i++) {
227 for (j = 0; j < sx; j++) {
228 seldata = sel->
data[i][j];
269 l_int32 i, j, w, h, sx, sy, cx, cy, seldata;
270 l_int32 xp, yp, xn, yn;
274 return (
PIX *)ERROR_PTR(
"processMorphArgs1 failed", __func__, pixd);
279 for (i = 0; i < sy; i++) {
280 for (j = 0; j < sx; j++) {
281 seldata = sel->
data[i][j];
295 if (MORPH_BC == ASYMMETRIC_MORPH_BC) {
342 l_int32 i, j, w, h, sx, sy, cx, cy, firstrasterop, seldata;
343 l_int32 xp, yp, xn, yn;
347 return (
PIX *)ERROR_PTR(
"processMorphArgs1 failed", __func__, pixd);
351 firstrasterop = TRUE;
352 for (i = 0; i < sy; i++) {
353 for (j = 0; j < sx; j++) {
354 seldata = sel->
data[i][j];
356 if (firstrasterop == TRUE) {
360 firstrasterop = FALSE;
365 }
else if (seldata == 2) {
366 if (firstrasterop == TRUE) {
370 firstrasterop = FALSE;
427 return (
PIX *)ERROR_PTR(
"pixd not returned", __func__, pixd);
429 if ((pixt =
pixErode(NULL, pixs, sel)) == NULL)
430 return (
PIX *)ERROR_PTR(
"pixt not made", __func__, pixd);
472 return (
PIX *)ERROR_PTR(
"pixd not returned", __func__, pixd);
474 if ((pixt =
pixDilate(NULL, pixs, sel)) == NULL)
475 return (
PIX *)ERROR_PTR(
"pixt not made", __func__, pixd);
518 l_int32 xp, yp, xn, yn, xmax, xbord;
522 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
524 return (
PIX *)ERROR_PTR(
"sel not defined", __func__, pixd);
525 if (pixGetDepth(pixs) != 1)
526 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
529 if (MORPH_BC == SYMMETRIC_MORPH_BC)
533 xmax = L_MAX(xp, xn);
534 xbord = 32 * ((xmax + 31) / 32);
537 return (
PIX *)ERROR_PTR(
"pixt1 not made", __func__, pixd);
540 return (
PIX *)ERROR_PTR(
"pixt2 not made", __func__, pixd);
586 return (
PIX *)ERROR_PTR(
"pixd not returned", __func__, pixd);
588 if ((pixt =
pixHMT(NULL, pixs, sel)) == NULL)
589 return (
PIX *)ERROR_PTR(
"pixt not made", __func__, pixd);
631 return (
PIX *)ERROR_PTR(
"pixd not returned", __func__, pixd);
633 if ((pixt =
pixDilate(NULL, pixs, sel)) == NULL)
634 return (
PIX *)ERROR_PTR(
"pixt not made", __func__, pixd);
678 SEL *sel, *selh, *selv;
681 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
682 if (pixGetDepth(pixs) != 1)
683 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
684 if (hsize < 1 || vsize < 1)
685 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
687 if (hsize == 1 && vsize == 1)
689 if (hsize == 1 || vsize == 1) {
690 sel =
selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
692 return (
PIX *)ERROR_PTR(
"sel not made", __func__, pixd);
696 if ((selh =
selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
697 return (
PIX *)ERROR_PTR(
"selh not made", __func__, pixd);
698 if ((selv =
selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
700 return (
PIX *)ERROR_PTR(
"selv not made", __func__, pixd);
746 SEL *sel, *selh, *selv;
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);
755 if (hsize == 1 && vsize == 1)
757 if (hsize == 1 || vsize == 1) {
758 sel =
selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
760 return (
PIX *)ERROR_PTR(
"sel not made", __func__, pixd);
764 if ((selh =
selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
765 return (
PIX *)ERROR_PTR(
"selh not made", __func__, pixd);
766 if ((selv =
selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
768 return (
PIX *)ERROR_PTR(
"selv not made", __func__, pixd);
814 SEL *sel, *selh, *selv;
817 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
818 if (pixGetDepth(pixs) != 1)
819 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
820 if (hsize < 1 || vsize < 1)
821 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
823 if (hsize == 1 && vsize == 1)
825 if (hsize == 1 || vsize == 1) {
826 sel =
selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
828 return (
PIX *)ERROR_PTR(
"sel not made", __func__, pixd);
829 pixd =
pixOpen(pixd, pixs, sel);
832 if ((selh =
selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
833 return (
PIX *)ERROR_PTR(
"selh not made", __func__, pixd);
834 if ((selv =
selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
836 return (
PIX *)ERROR_PTR(
"selv not made", __func__, pixd);
884 SEL *sel, *selh, *selv;
887 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
888 if (pixGetDepth(pixs) != 1)
889 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
890 if (hsize < 1 || vsize < 1)
891 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
893 if (hsize == 1 && vsize == 1)
895 if (hsize == 1 || vsize == 1) {
896 sel =
selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
898 return (
PIX *)ERROR_PTR(
"sel not made", __func__, pixd);
902 if ((selh =
selCreateBrick(1, hsize, 0, hsize / 2, SEL_HIT)) == NULL)
903 return (
PIX *)ERROR_PTR(
"selh not made", __func__, pixd);
904 if ((selv =
selCreateBrick(vsize, 1, vsize / 2, 0, SEL_HIT)) == NULL) {
906 return (
PIX *)ERROR_PTR(
"selv not made", __func__, pixd);
958 l_int32 maxtrans, bordsize;
959 PIX *pixsb, *pixt, *pixdb;
960 SEL *sel, *selh, *selv;
963 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
964 if (pixGetDepth(pixs) != 1)
965 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
966 if (hsize < 1 || vsize < 1)
967 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
969 if (hsize == 1 && vsize == 1)
973 if (MORPH_BC == SYMMETRIC_MORPH_BC)
976 maxtrans = L_MAX(hsize / 2, vsize / 2);
977 bordsize = 32 * ((maxtrans + 31) / 32);
980 if (hsize == 1 || vsize == 1) {
981 sel =
selCreateBrick(vsize, hsize, vsize / 2, hsize / 2, SEL_HIT);
984 return (
PIX *)ERROR_PTR(
"sel not made", __func__, pixd);
991 if (!selh || !selv) {
995 return (
PIX *)ERROR_PTR(
"selh and selv not both made",
1051 selectComposableSels(l_int32 size,
1056 l_int32 factor1, factor2;
1058 if (!psel1 && !psel2)
1059 return ERROR_INT(
"neither &sel1 nor &sel2 are defined", __func__, 1);
1060 if (psel1) *psel1 = NULL;
1061 if (psel2) *psel2 = NULL;
1062 if (size < 1 || size > 10000)
1063 return ERROR_INT(
"size < 1 or size > 10000", __func__, 1);
1064 if (direction != L_HORIZ && direction != L_VERT)
1065 return ERROR_INT(
"invalid direction", __func__, 1);
1068 return ERROR_INT(
"factors not found", __func__, 1);
1071 if (direction == L_HORIZ)
1108 l_int32 i, midval, val1, val2m, val2p;
1109 l_int32 index, prodm, prodp;
1110 l_int32 mincost, totcost, rastcostm, rastcostp, diffm, diffp;
1111 l_int32 lowval[256];
1113 l_int32 rastcost[256];
1116 if (size < 1 || size > 10000)
1117 return ERROR_INT(
"size < 1 or size > 10000", __func__, 1);
1118 if (!pfactor1 || !pfactor2)
1119 return ERROR_INT(
"&factor1 or &factor2 not defined", __func__, 1);
1121 midval = (l_int32)(sqrt((l_float64)size) + 0.001);
1122 if (midval * midval == size) {
1123 *pfactor1 = *pfactor2 = midval;
1129 for (val1 = midval + 1, i = 0; val1 > 0; val1--, i++) {
1130 val2m = size / val1;
1132 prodm = val1 * val2m;
1133 prodp = val1 * val2p;
1134 rastcostm = val1 + val2m - 2 * midval;
1135 rastcostp = val1 + val2p - 2 * midval;
1136 diffm = L_ABS(size - prodm);
1137 diffp = L_ABS(size - prodp);
1138 if (diffm <= diffp) {
1139 lowval[i] = L_MIN(val1, val2m);
1140 hival[i] = L_MAX(val1, val2m);
1141 rastcost[i] = rastcostm;
1144 lowval[i] = L_MIN(val1, val2p);
1145 hival[i] = L_MAX(val1, val2p);
1146 rastcost[i] = rastcostp;
1154 for (i = 0; i < midval + 1; i++) {
1155 if (diff[i] == 0 && rastcost[i] < ACCEPTABLE_COST) {
1156 *pfactor1 = hival[i];
1157 *pfactor2 = lowval[i];
1160 totcost = 4 * diff[i] + rastcost[i];
1161 if (totcost < mincost) {
1166 *pfactor1 = hival[index];
1167 *pfactor2 = lowval[index];
1219 PIX *pix1, *pix2, *pix3;
1226 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
1227 if (pixGetDepth(pixs) != 1)
1228 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
1229 if (hsize < 1 || vsize < 1)
1230 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
1232 if (hsize == 1 && vsize == 1)
1235 if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1238 return (
PIX *)ERROR_PTR(
"horiz sels not made", __func__, pixd);
1242 if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1247 return (
PIX *)ERROR_PTR(
"vert sels not made", __func__, pixd);
1255 }
else if (hsize == 1) {
1335 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
1336 if (pixGetDepth(pixs) != 1)
1337 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
1338 if (hsize < 1 || vsize < 1)
1339 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
1341 if (hsize == 1 && vsize == 1)
1344 if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1347 return (
PIX *)ERROR_PTR(
"horiz sels not made", __func__, pixd);
1351 if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1356 return (
PIX *)ERROR_PTR(
"vert sels not made", __func__, pixd);
1361 pixt =
pixErode(NULL, pixs, selh1);
1362 pixd =
pixErode(pixd, pixt, selh2);
1363 }
else if (hsize == 1) {
1364 pixt =
pixErode(NULL, pixs, selv1);
1365 pixd =
pixErode(pixd, pixt, selv2);
1367 pixt =
pixErode(NULL, pixs, selh1);
1368 pixd =
pixErode(pixd, pixt, selh2);
1435 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
1436 if (pixGetDepth(pixs) != 1)
1437 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
1438 if (hsize < 1 || vsize < 1)
1439 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
1441 if (hsize == 1 && vsize == 1)
1444 if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1447 return (
PIX *)ERROR_PTR(
"horiz sels not made", __func__, pixd);
1451 if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1456 return (
PIX *)ERROR_PTR(
"vert sels not made", __func__, pixd);
1461 pixt =
pixErode(NULL, pixs, selh1);
1462 pixd =
pixErode(pixd, pixt, selh2);
1465 }
else if (hsize == 1) {
1466 pixt =
pixErode(NULL, pixs, selv1);
1467 pixd =
pixErode(pixd, pixt, selv2);
1471 pixt =
pixErode(NULL, pixs, selh1);
1472 pixd =
pixErode(pixd, pixt, selh2);
1543 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
1544 if (pixGetDepth(pixs) != 1)
1545 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
1546 if (hsize < 1 || vsize < 1)
1547 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
1549 if (hsize == 1 && vsize == 1)
1552 if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1555 return (
PIX *)ERROR_PTR(
"horiz sels not made", __func__, pixd);
1559 if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1564 return (
PIX *)ERROR_PTR(
"vert sels not made", __func__, pixd);
1573 }
else if (hsize == 1) {
1649 l_int32 maxtrans, bordsize;
1650 PIX *pixsb, *pixt, *pixdb;
1657 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
1658 if (pixGetDepth(pixs) != 1)
1659 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
1660 if (hsize < 1 || vsize < 1)
1661 return (
PIX *)ERROR_PTR(
"hsize and vsize not >= 1", __func__, pixd);
1663 if (hsize == 1 && vsize == 1)
1667 if (MORPH_BC == SYMMETRIC_MORPH_BC)
1671 if (selectComposableSels(hsize, L_HORIZ, &selh1, &selh2)) {
1674 return (
PIX *)ERROR_PTR(
"horiz sels not made", __func__, pixd);
1678 if (selectComposableSels(vsize, L_VERT, &selv1, &selv2)) {
1683 return (
PIX *)ERROR_PTR(
"vert sels not made", __func__, pixd);
1687 maxtrans = L_MAX(hsize / 2, vsize / 2);
1688 bordsize = 32 * ((maxtrans + 31) / 32);
1696 }
else if (hsize == 1) {
1744 if (bc != SYMMETRIC_MORPH_BC && bc != ASYMMETRIC_MORPH_BC) {
1745 L_WARNING(
"invalid bc; using asymmetric\n", __func__);
1746 bc = ASYMMETRIC_MORPH_BC;
1764 if (type != L_MORPH_DILATE && type != L_MORPH_ERODE)
1765 return ERROR_INT(
"invalid type", __func__, 0);
1766 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
1767 depth != 16 && depth != 32)
1768 return ERROR_INT(
"invalid depth", __func__, 0);
1770 if (MORPH_BC == ASYMMETRIC_MORPH_BC || type == L_MORPH_DILATE)
1775 return ((1 << depth) - 1);
1808 return (
PIX *)ERROR_PTR(
"&pixt not defined", __func__, pixd);
1811 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
1813 return (
PIX *)ERROR_PTR(
"sel not defined", __func__, pixd);
1814 if (pixGetDepth(pixs) != 1)
1815 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
1818 if (sx == 0 || sy == 0)
1819 return (
PIX *)ERROR_PTR(
"sel of size 0", __func__, pixd);
1825 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
1830 if ((*ppixt =
pixCopy(NULL, pixs)) == NULL)
1831 return (
PIX *)ERROR_PTR(
"pixt not made", __func__, pixd);
1853 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, pixd);
1855 return (
PIX *)ERROR_PTR(
"sel not defined", __func__, pixd);
1856 if (pixGetDepth(pixs) != 1)
1857 return (
PIX *)ERROR_PTR(
"pixs not 1 bpp", __func__, pixd);
1860 if (sx == 0 || sy == 0)
1861 return (
PIX *)ERROR_PTR(
"sel of size 0", __func__, pixd);
PIX * pixCloseSafe(PIX *pixd, PIX *pixs, SEL *sel)
pixCloseSafe()
PIX * pixOpenBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenBrick()
void resetMorphBoundaryCondition(l_int32 bc)
resetMorphBoundaryCondition()
PIX * pixOpen(PIX *pixd, PIX *pixs, SEL *sel)
pixOpen()
PIX * pixErode(PIX *pixd, PIX *pixs, SEL *sel)
pixErode()
l_ok selectComposableSizes(l_int32 size, l_int32 *pfactor1, l_int32 *pfactor2)
selectComposableSizes()
PIX * pixOpenCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenCompBrick()
PIX * pixOpenGeneralized(PIX *pixd, PIX *pixs, SEL *sel)
pixOpenGeneralized()
PIX * pixClose(PIX *pixd, PIX *pixs, SEL *sel)
pixClose()
static PIX * processMorphArgs1(PIX *pixd, PIX *pixs, SEL *sel, PIX **ppixt)
processMorphArgs1()
PIX * pixCloseSafeCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseSafeCompBrick()
PIX * pixCloseSafeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseSafeBrick()
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
PIX * pixCloseCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseCompBrick()
PIX * pixDilate(PIX *pixd, PIX *pixs, SEL *sel)
pixDilate()
PIX * pixHMT(PIX *pixd, PIX *pixs, SEL *sel)
pixHMT()
static PIX * processMorphArgs2(PIX *pixd, PIX *pixs, SEL *sel)
processMorphArgs2()
l_uint32 getMorphBorderPixelColor(l_int32 type, l_int32 depth)
getMorphBorderPixelColor()
PIX * pixDilateBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrick()
PIX * pixCloseBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseBrick()
PIX * pixCloseGeneralized(PIX *pixd, PIX *pixs, SEL *sel)
pixCloseGeneralized()
PIX * pixDilateCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateCompBrick()
PIX * pixErodeCompBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeCompBrick()
l_ok pixResizeImageData(PIX *pixd, const PIX *pixs)
pixResizeImageData()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
PIX * pixClone(PIX *pixs)
pixClone()
l_ok pixClearAll(PIX *pix)
pixClearAll()
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
pixAddBorder()
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
PIX * pixRemoveBorder(PIX *pixs, l_int32 npix)
pixRemoveBorder()
l_ok pixSetAll(PIX *pix)
pixSetAll()
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
l_ok selGetParameters(SEL *sel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
selGetParameters()
l_ok selFindMaxTranslations(SEL *sel, l_int32 *pxp, l_int32 *pyp, l_int32 *pxn, l_int32 *pyn)
selFindMaxTranslations()
SEL * selCreateComb(l_int32 factor1, l_int32 factor2, l_int32 direction)
selCreateComb()
void selDestroy(SEL **psel)
selDestroy()
SEL * selCreateBrick(l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type)
selCreateBrick()