168#include <config_auto.h>
172#include "allheaders.h"
182 l_uint32 *datam, l_int32 hm, l_int32 wplm,
183 l_int32 connectivity);
185 l_int32 wpls, l_uint32 *datam, l_int32 wplm,
186 l_int32 connectivity);
188 l_int32 wpls, l_uint32 *datam, l_int32 wplm,
189 l_int32 connectivity);
191 l_int32 wpls, l_uint32 *datam, l_int32 wplm,
192 l_int32 connectivity);
194 l_int32 wpls, l_uint32 *datam,
195 l_int32 wplm, l_int32 connectivity);
197 l_int32 d, l_int32 wpld, l_int32 connectivity);
198static void seedspreadLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld,
199 l_uint32 *datat, l_int32 wplt, l_int32 connectivity);
205#define DEBUG_PRINT_ITERS 0
209static const l_int32 MaxIters = 40;
250 l_int32 connectivity)
253l_int32 hd, hm, wpld, wplm;
254l_uint32 *datad, *datam;
257 if (!pixs || pixGetDepth(pixs) != 1)
258 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, pixd);
259 if (!pixm || pixGetDepth(pixm) != 1)
260 return (
PIX *)ERROR_PTR(
"pixm undefined or not 1 bpp", __func__, pixd);
261 if (connectivity != 4 && connectivity != 8)
262 return (
PIX *)ERROR_PTR(
"connectivity not in {4,8}", __func__, pixd);
265 if ((pixd = pixCopy(pixd, pixs)) == NULL)
266 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
267 pixSetPadBits(pixd, 0);
268 pixSetPadBits(pixm, 0);
271 if ((pixt = pixCreateTemplate(pixs)) == NULL)
272 return (
PIX *)ERROR_PTR(
"pixt not made", __func__, pixd);
274 hd = pixGetHeight(pixd);
275 hm = pixGetHeight(pixm);
276 datad = pixGetData(pixd);
277 datam = pixGetData(pixm);
278 wpld = pixGetWpl(pixd);
279 wplm = pixGetWpl(pixm);
282 for (i = 0; i < MaxIters; i++) {
285 pixEqual(pixd, pixt, &boolval);
288 lept_stderr(
"Binary seed fill converged: %d iters\n", i + 1);
336 l_int32 connectivity,
343 if (!pixs || pixGetDepth(pixs) != 1)
344 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, pixd);
345 if (!pixm || pixGetDepth(pixm) != 1)
346 return (
PIX *)ERROR_PTR(
"pixm undefined or not 1 bpp", __func__, pixd);
347 if (connectivity != 4 && connectivity != 8)
348 return (
PIX *)ERROR_PTR(
"connectivity not in {4,8}", __func__, pixd);
349 if (xmax == 0 && ymax == 0)
350 return pixClone(pixs);
351 if (xmax < 0 || ymax < 0) {
352 L_ERROR(
"xmax and ymax must be non-negative", __func__);
353 return pixClone(pixs);
358 return (
PIX *)ERROR_PTR(
"pix1 not made", __func__, pixd);
363 pix2 = pixDilateCompBrick(NULL, pixs, 2 * xmax + 1, 2 * ymax + 1);
364 pixInvert(pix2, pix2);
371 pixGetDimensions(pixs, &w, &h, NULL);
405 l_int32 connectivity)
409l_uint32 wordabove, wordleft, wordbelow, wordright;
411l_uint32 *lines, *linem;
414 wpl = L_MIN(wpls, wplm);
416 switch (connectivity)
420 for (i = 0; i < h; i++) {
421 lines = datas + i * wpls;
422 linem = datam + i * wplm;
423 for (j = 0; j < wpl; j++) {
429 wordabove = *(lines - wpls + j);
433 wordleft = *(lines + j - 1);
434 word |= wordleft << 31;
439 if (!word || !(~word)) {
446 word = (word | (word >> 1) | (word << 1)) & mask;
447 if ((word ^ wordprev) == 0) {
456 for (i = h - 1; i >= 0; i--) {
457 lines = datas + i * wpls;
458 linem = datam + i * wplm;
459 for (j = wpl - 1; j >= 0; j--) {
465 wordbelow = *(lines + wpls + j);
469 wordright = *(lines + j + 1);
470 word |= wordright >> 31;
475 if (!word || !(~word)) {
482 word = (word | (word >> 1) | (word << 1)) & mask;
483 if ((word ^ wordprev) == 0) {
494 for (i = 0; i < h; i++) {
495 lines = datas + i * wpls;
496 linem = datam + i * wplm;
497 for (j = 0; j < wpl; j++) {
503 wordabove = *(lines - wpls + j);
504 word |= (wordabove | (wordabove << 1) | (wordabove >> 1));
506 word |= (*(lines - wpls + j - 1)) << 31;
508 word |= (*(lines - wpls + j + 1)) >> 31;
511 wordleft = *(lines + j - 1);
512 word |= wordleft << 31;
517 if (!word || !(~word)) {
524 word = (word | (word >> 1) | (word << 1)) & mask;
525 if ((word ^ wordprev) == 0) {
534 for (i = h - 1; i >= 0; i--) {
535 lines = datas + i * wpls;
536 linem = datam + i * wplm;
537 for (j = wpl - 1; j >= 0; j--) {
543 wordbelow = *(lines + wpls + j);
544 word |= (wordbelow | (wordbelow << 1) | (wordbelow >> 1));
546 word |= (*(lines + wpls + j - 1)) << 31;
548 word |= (*(lines + wpls + j + 1)) >> 31;
551 wordright = *(lines + j + 1);
552 word |= wordright >> 31;
557 if (!word || !(~word)) {
564 word = (word | (word >> 1) | (word << 1)) & mask;
565 if ((word ^ wordprev) == 0) {
575 L_ERROR(
"connectivity must be 4 or 8\n", __func__);
604 l_int32 connectivity)
608 if (!pixs || pixGetDepth(pixs) != 1)
609 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
610 if (connectivity != 4 && connectivity != 8)
611 return (
PIX *)ERROR_PTR(
"connectivity not 4 or 8", __func__, NULL);
613 if ((pixd = pixCreateTemplate(pixs)) == NULL)
614 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
615 if ((pixsi = pixInvert(NULL, pixs)) == NULL) {
617 return (
PIX *)ERROR_PTR(
"pixsi not made", __func__, NULL);
620 pixSetOrClearBorder(pixd, 1, 1, 1, 1,
PIX_SET);
622 pixOr(pixd, pixd, pixs);
623 pixInvert(pixd, pixd);
653 l_int32 connectivity)
657 if (!pixs || pixGetDepth(pixs) != 1)
658 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
659 if (connectivity != 4 && connectivity != 8)
660 return (
PIX *)ERROR_PTR(
"connectivity not 4 or 8", __func__, NULL);
662 if ((pixd = pixCreateTemplate(pixs)) == NULL)
663 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
664 pixSetOrClearBorder(pixd, 1, 1, 1, 1,
PIX_SET);
665 pixSubtract(pixd, pixd, pixs);
666 if ((pixsi = pixInvert(NULL, pixs)) == NULL) {
668 return (
PIX *)ERROR_PTR(
"pixsi not made", __func__, NULL);
672 pixInvert(pixd, pixd);
689 l_int32 connectivity)
693 if (!pixs || pixGetDepth(pixs) != 1)
694 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
695 if (connectivity != 4 && connectivity != 8)
696 return (
PIX *)ERROR_PTR(
"connectivity not 4 or 8", __func__, NULL);
699 if ((pixd = pixCreateTemplate(pixs)) == NULL)
700 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
701 pixSetOrClearBorder(pixd, 1, 1, 1, 1,
PIX_SET);
726 l_int32 connectivity)
730 if (!pixs || pixGetDepth(pixs) != 1)
731 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
732 if (connectivity != 4 && connectivity != 8)
733 return (
PIX *)ERROR_PTR(
"connectivity not 4 or 8", __func__, NULL);
740 pixXor(pixd, pixd, pixs);
774 l_int32 connectivity)
778 if (!pixs || pixGetDepth(pixs) != 1)
779 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
780 if (connectivity != 4 && connectivity != 8)
781 return (
PIX *)ERROR_PTR(
"connectivity not 4 or 8", __func__, NULL);
785 pixInvert(pixs, pixs);
787 pixInvert(pixs, pixs);
790 pixOr(pixd, pixd, pixs);
834 l_float32 minfgfract)
836l_int32 i, x, y, w, h, n, nfg, nh, ntot, area;
841PIX *pixd, *pixfg, *pixh;
844 if (!pixs || pixGetDepth(pixs) != 1)
845 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
846 maxhfract = L_MIN(L_MAX(maxhfract, 0.0), 1.0);
847 minfgfract = L_MIN(L_MAX(minfgfract, 0.0), 1.0);
849 pixd = pixCopy(NULL, pixs);
850 boxa = pixConnComp(pixd, &pixa, 8);
851 n = boxaGetCount(boxa);
852 tab = makePixelSumTab8();
853 for (i = 0; i < n; i++) {
854 boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
858 pixfg = pixaGetPix(pixa, i,
L_COPY);
860 pixCountPixels(pixfg, &nfg, tab);
861 pixCountPixels(pixh, &nh, tab);
862 hfract = (l_float32)nh / (l_float32)nfg;
864 if (hfract <= maxhfract)
866 fgfract = (l_float32)ntot / (l_float32)area;
867 if (fgfract >= minfgfract) {
869 pixRasterop(pixd, x, y, w, h,
PIX_SRC, pixfg, 0, 0);
870 }
else if (hfract <= maxhfract) {
913 l_int32 connectivity)
915l_int32 h, w, wpls, wplm;
916l_uint32 *datas, *datam;
918 if (!pixs || pixGetDepth(pixs) != 8)
919 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
920 if (!pixm || pixGetDepth(pixm) != 8)
921 return ERROR_INT(
"pixm not defined or not 8 bpp", __func__, 1);
922 if (connectivity != 4 && connectivity != 8)
923 return ERROR_INT(
"connectivity not in {4,8}", __func__, 1);
926 if (pixSizesEqual(pixs, pixm) == 0)
927 return ERROR_INT(
"pixs and pixm sizes differ", __func__, 1);
929 datas = pixGetData(pixs);
930 datam = pixGetData(pixm);
931 wpls = pixGetWpl(pixs);
932 wplm = pixGetWpl(pixm);
933 pixGetDimensions(pixs, &w, &h, NULL);
970 l_int32 connectivity)
972l_int32 h, w, wpls, wplm;
973l_uint32 *datas, *datam;
975 if (!pixs || pixGetDepth(pixs) != 8)
976 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
977 if (!pixm || pixGetDepth(pixm) != 8)
978 return ERROR_INT(
"pixm not defined or not 8 bpp", __func__, 1);
979 if (connectivity != 4 && connectivity != 8)
980 return ERROR_INT(
"connectivity not in {4,8}", __func__, 1);
983 if (pixSizesEqual(pixs, pixm) == 0)
984 return ERROR_INT(
"pixs and pixm sizes differ", __func__, 1);
986 datas = pixGetData(pixs);
987 datam = pixGetData(pixm);
988 wpls = pixGetWpl(pixs);
989 wplm = pixGetWpl(pixm);
990 pixGetDimensions(pixs, &w, &h, NULL);
1049 l_int32 connectivity)
1051l_uint8 val1, val2, val3, val4, val5, val6, val7, val8;
1052l_uint8 val, maxval, maskval, boolval;
1053l_int32 i, j, imax, jmax, queue_size;
1054l_uint32 *lines, *linem;
1058 if (connectivity != 4 && connectivity != 8) {
1059 L_ERROR(
"connectivity must be 4 or 8\n", __func__);
1070 lq_pixel = lqueueCreate(2 * (w + h));
1072 switch (connectivity)
1081 for (i = 0; i < h; i++) {
1082 lines = datas + i * wpls;
1083 linem = datam + i * wplm;
1084 for (j = 0; j < w; j++) {
1091 maxval = L_MAX(maxval, val4);
1094 maxval = L_MAX(maxval, val);
1095 val = L_MIN(maxval, maskval);
1105 for (i = imax; i >= 0; i--) {
1106 lines = datas + i * wpls;
1107 linem = datam + i * wplm;
1108 for (j = jmax; j >= 0; j--) {
1116 maxval = L_MAX(maxval, val5);
1119 maxval = L_MAX(maxval, val);
1120 val = L_MIN(maxval, maskval);
1137 if (!boolval && (val5 < val) &&
1146 lqueueAdd(lq_pixel, pixel);
1162 queue_size = lqueueGetCount(lq_pixel);
1163 while (queue_size) {
1164 pixel = (
L_PIXEL *)lqueueRemove(lq_pixel);
1168 lines = datas + i * wpls;
1169 linem = datam + i * wplm;
1175 if (val > val2 && val2 != maskval) {
1180 lqueueAdd(lq_pixel, pixel);
1187 if (val > val4 && val4 != maskval) {
1192 lqueueAdd(lq_pixel, pixel);
1198 if (val > val7 && val7 != maskval) {
1203 lqueueAdd(lq_pixel, pixel);
1209 if (val > val5 && val5 != maskval) {
1214 lqueueAdd(lq_pixel, pixel);
1219 queue_size = lqueueGetCount(lq_pixel);
1230 for (i = 0; i < h; i++) {
1231 lines = datas + i * wpls;
1232 linem = datam + i * wplm;
1233 for (j = 0; j < w; j++) {
1241 maxval = L_MAX(maxval, val3);
1244 maxval = L_MAX(maxval, val2);
1248 maxval = L_MAX(maxval, val4);
1251 maxval = L_MAX(maxval, val);
1252 val = L_MIN(maxval, maskval);
1262 for (i = imax; i >= 0; i--) {
1263 lines = datas + i * wpls;
1264 linem = datam + i * wplm;
1265 for (j = jmax; j >= 0; j--) {
1275 maxval = L_MAX(maxval, val8);
1278 maxval = L_MAX(maxval, val7);
1282 maxval = L_MAX(maxval, val5);
1285 maxval = L_MAX(maxval, val);
1286 val = L_MIN(maxval, maskval);
1303 if (!boolval && (val8 < val) &&
1309 if (!boolval && (val7 < val) &&
1316 if (!boolval && (val5 < val) &&
1325 lqueueAdd(lq_pixel, pixel);
1341 queue_size = lqueueGetCount(lq_pixel);
1342 while (queue_size) {
1343 pixel = (
L_PIXEL *)lqueueRemove(lq_pixel);
1347 lines = datas + i * wpls;
1348 linem = datam + i * wplm;
1355 if (val > val1 && val1 != maskval) {
1357 L_MIN(val, maskval));
1361 lqueueAdd(lq_pixel, pixel);
1367 if (val > val3 && val3 != maskval) {
1369 L_MIN(val, maskval));
1373 lqueueAdd(lq_pixel, pixel);
1378 if (val > val2 && val2 != maskval) {
1383 lqueueAdd(lq_pixel, pixel);
1390 if (val > val4 && val4 != maskval) {
1395 lqueueAdd(lq_pixel, pixel);
1402 if (val > val6 && val6 != maskval) {
1404 L_MIN(val, maskval));
1408 lqueueAdd(lq_pixel, pixel);
1414 if (val > val8 && val8 != maskval) {
1416 L_MIN(val, maskval));
1420 lqueueAdd(lq_pixel, pixel);
1425 if (val > val7 && val7 != maskval) {
1430 lqueueAdd(lq_pixel, pixel);
1436 if (val > val5 && val5 != maskval) {
1441 lqueueAdd(lq_pixel, pixel);
1446 queue_size = lqueueGetCount(lq_pixel);
1451 L_ERROR(
"shouldn't get here!\n", __func__);
1454 lqueueDestroy(&lq_pixel, TRUE);
1498 l_int32 connectivity)
1500l_uint8 val1, val2, val3, val4, val5, val6, val7, val8;
1501l_uint8 val, maxval, maskval, boolval;
1502l_int32 i, j, imax, jmax, queue_size;
1503l_uint32 *lines, *linem;
1507 if (connectivity != 4 && connectivity != 8) {
1508 L_ERROR(
"connectivity must be 4 or 8\n", __func__);
1519 lq_pixel = lqueueCreate(2 * (w + h));
1521 switch (connectivity)
1532 for (i = 0; i < h; i++) {
1533 lines = datas + i * wpls;
1534 linem = datam + i * wplm;
1535 for (j = 0; j < w; j++) {
1540 maxval = L_MAX(maxval, val2);
1544 maxval = L_MAX(maxval, val4);
1546 if (maxval > maskval)
1560 for (i = imax; i >= 0; i--) {
1561 lines = datas + i * wpls;
1562 linem = datam + i * wplm;
1563 for (j = jmax; j >= 0; j--) {
1569 maxval = L_MAX(maxval, val7);
1573 maxval = L_MAX(maxval, val5);
1575 if (maxval > maskval)
1593 if (!boolval && (val5 < val) &&
1602 lqueueAdd(lq_pixel, pixel);
1618 queue_size = lqueueGetCount(lq_pixel);
1619 while (queue_size) {
1620 pixel = (
L_PIXEL *)lqueueRemove(lq_pixel);
1624 lines = datas + i * wpls;
1625 linem = datam + i * wplm;
1631 if (val > val2 && val > maskval) {
1636 lqueueAdd(lq_pixel, pixel);
1643 if (val > val4 && val > maskval) {
1648 lqueueAdd(lq_pixel, pixel);
1654 if (val > val7 && val > maskval) {
1659 lqueueAdd(lq_pixel, pixel);
1665 if (val > val5 && val > maskval) {
1670 lqueueAdd(lq_pixel, pixel);
1675 queue_size = lqueueGetCount(lq_pixel);
1688 for (i = 0; i < h; i++) {
1689 lines = datas + i * wpls;
1690 linem = datam + i * wplm;
1691 for (j = 0; j < w; j++) {
1697 maxval = L_MAX(maxval, val1);
1701 maxval = L_MAX(maxval, val3);
1704 maxval = L_MAX(maxval, val2);
1708 maxval = L_MAX(maxval, val4);
1710 if (maxval > maskval)
1724 for (i = imax; i >= 0; i--) {
1725 lines = datas + i * wpls;
1726 linem = datam + i * wplm;
1727 for (j = jmax; j >= 0; j--) {
1734 maxval = L_MAX(maxval, val6);
1738 maxval = L_MAX(maxval, val8);
1741 maxval = L_MAX(maxval, val7);
1745 maxval = L_MAX(maxval, val5);
1747 if (maxval > maskval)
1766 if (!boolval && (val8 < val) &&
1772 if (!boolval && (val7 < val) &&
1779 if (!boolval && (val5 < val) &&
1788 lqueueAdd(lq_pixel, pixel);
1804 queue_size = lqueueGetCount(lq_pixel);
1805 while (queue_size) {
1806 pixel = (
L_PIXEL *)lqueueRemove(lq_pixel);
1810 lines = datas + i * wpls;
1811 linem = datam + i * wplm;
1818 if (val > val1 && val > maskval) {
1823 lqueueAdd(lq_pixel, pixel);
1829 if (val > val3 && val > maskval) {
1834 lqueueAdd(lq_pixel, pixel);
1839 if (val > val2 && val > maskval) {
1844 lqueueAdd(lq_pixel, pixel);
1851 if (val > val4 && val > maskval) {
1856 lqueueAdd(lq_pixel, pixel);
1863 if (val > val6 && val > maskval) {
1868 lqueueAdd(lq_pixel, pixel);
1874 if (val > val8 && val > maskval) {
1879 lqueueAdd(lq_pixel, pixel);
1884 if (val > val7 && val > maskval) {
1889 lqueueAdd(lq_pixel, pixel);
1895 if (val > val5 && val > maskval) {
1900 lqueueAdd(lq_pixel, pixel);
1905 queue_size = lqueueGetCount(lq_pixel);
1910 L_ERROR(
"shouldn't get here!\n", __func__);
1913 lqueueDestroy(&lq_pixel, TRUE);
1947 l_int32 connectivity)
1949l_int32 i, h, w, wpls, wplm, boolval;
1950l_uint32 *datas, *datam;
1953 if (!pixs || pixGetDepth(pixs) != 8)
1954 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
1955 if (!pixm || pixGetDepth(pixm) != 8)
1956 return ERROR_INT(
"pixm not defined or not 8 bpp", __func__, 1);
1957 if (connectivity != 4 && connectivity != 8)
1958 return ERROR_INT(
"connectivity not in {4,8}", __func__, 1);
1961 if (pixSizesEqual(pixs, pixm) == 0)
1962 return ERROR_INT(
"pixs and pixm sizes differ", __func__, 1);
1965 if ((pixt = pixCreateTemplate(pixs)) == NULL)
1966 return ERROR_INT(
"pixt not made", __func__, 1);
1968 datas = pixGetData(pixs);
1969 datam = pixGetData(pixm);
1970 wpls = pixGetWpl(pixs);
1971 wplm = pixGetWpl(pixm);
1972 pixGetDimensions(pixs, &w, &h, NULL);
1973 for (i = 0; i < MaxIters; i++) {
1974 pixCopy(pixt, pixs);
1976 pixEqual(pixs, pixt, &boolval);
1978#if DEBUG_PRINT_ITERS
1979 L_INFO(
"Gray seed fill converged: %d iters\n", __func__, i + 1);
2016 l_int32 connectivity)
2018l_int32 i, h, w, wpls, wplm, boolval;
2019l_uint32 *datas, *datam;
2022 if (!pixs || pixGetDepth(pixs) != 8)
2023 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
2024 if (!pixm || pixGetDepth(pixm) != 8)
2025 return ERROR_INT(
"pixm not defined or not 8 bpp", __func__, 1);
2026 if (connectivity != 4 && connectivity != 8)
2027 return ERROR_INT(
"connectivity not in {4,8}", __func__, 1);
2030 if (pixSizesEqual(pixs, pixm) == 0)
2031 return ERROR_INT(
"pixs and pixm sizes differ", __func__, 1);
2034 if ((pixt = pixCreateTemplate(pixs)) == NULL)
2035 return ERROR_INT(
"pixt not made", __func__, 1);
2037 datas = pixGetData(pixs);
2038 datam = pixGetData(pixm);
2039 wpls = pixGetWpl(pixs);
2040 wplm = pixGetWpl(pixm);
2041 pixGetDimensions(pixs, &w, &h, NULL);
2042 for (i = 0; i < MaxIters; i++) {
2043 pixCopy(pixt, pixs);
2045 pixEqual(pixs, pixt, &boolval);
2047#if DEBUG_PRINT_ITERS
2048 L_INFO(
"Gray seed fill converged: %d iters\n", __func__, i + 1);
2099 l_int32 connectivity)
2101l_uint8 val2, val3, val4, val5, val7, val8;
2102l_uint8 val, maxval, maskval;
2103l_int32 i, j, imax, jmax;
2104l_uint32 *lines, *linem;
2109 switch (connectivity)
2113 for (i = 0; i < h; i++) {
2114 lines = datas + i * wpls;
2115 linem = datam + i * wplm;
2116 for (j = 0; j < w; j++) {
2123 maxval = L_MAX(maxval, val4);
2126 maxval = L_MAX(maxval, val);
2127 val = L_MIN(maxval, maskval);
2134 for (i = imax; i >= 0; i--) {
2135 lines = datas + i * wpls;
2136 linem = datam + i * wplm;
2137 for (j = jmax; j >= 0; j--) {
2144 maxval = L_MAX(maxval, val5);
2147 maxval = L_MAX(maxval, val);
2148 val = L_MIN(maxval, maskval);
2157 for (i = 0; i < h; i++) {
2158 lines = datas + i * wpls;
2159 linem = datam + i * wplm;
2160 for (j = 0; j < w; j++) {
2168 maxval = L_MAX(maxval, val2);
2171 maxval = L_MAX(maxval, val3);
2175 maxval = L_MAX(maxval, val4);
2178 maxval = L_MAX(maxval, val);
2179 val = L_MIN(maxval, maskval);
2186 for (i = imax; i >= 0; i--) {
2187 lines = datas + i * wpls;
2188 linem = datam + i * wplm;
2189 for (j = jmax; j >= 0; j--) {
2197 maxval = L_MAX(maxval, val8);
2200 maxval = L_MAX(maxval, val7);
2204 maxval = L_MAX(maxval, val5);
2207 maxval = L_MAX(maxval, val);
2208 val = L_MIN(maxval, maskval);
2216 L_ERROR(
"connectivity must be 4 or 8\n", __func__);
2253 l_int32 connectivity)
2255l_uint8 val1, val2, val3, val4, val5, val6, val7, val8;
2256l_uint8 maxval, maskval;
2257l_int32 i, j, imax, jmax;
2258l_uint32 *lines, *linem;
2263 switch (connectivity)
2267 for (i = 0; i < h; i++) {
2268 lines = datas + i * wpls;
2269 linem = datam + i * wplm;
2270 for (j = 0; j < w; j++) {
2275 maxval = L_MAX(maxval, val2);
2279 maxval = L_MAX(maxval, val4);
2281 if (maxval > maskval)
2288 for (i = imax; i >= 0; i--) {
2289 lines = datas + i * wpls;
2290 linem = datam + i * wplm;
2291 for (j = jmax; j >= 0; j--) {
2296 maxval = L_MAX(maxval, val7);
2300 maxval = L_MAX(maxval, val5);
2302 if (maxval > maskval)
2311 for (i = 0; i < h; i++) {
2312 lines = datas + i * wpls;
2313 linem = datam + i * wplm;
2314 for (j = 0; j < w; j++) {
2320 maxval = L_MAX(maxval, val1);
2324 maxval = L_MAX(maxval, val2);
2327 maxval = L_MAX(maxval, val3);
2331 maxval = L_MAX(maxval, val4);
2333 if (maxval > maskval)
2340 for (i = imax; i >= 0; i--) {
2341 lines = datas + i * wpls;
2342 linem = datam + i * wplm;
2343 for (j = jmax; j >= 0; j--) {
2349 maxval = L_MAX(maxval, val6);
2353 maxval = L_MAX(maxval, val8);
2356 maxval = L_MAX(maxval, val7);
2360 maxval = L_MAX(maxval, val5);
2362 if (maxval > maskval)
2370 L_ERROR(
"connectivity must be 4 or 8\n", __func__);
2413 l_int32 connectivity)
2415PIX *pixbi, *pixmi, *pixsd;
2417 if (!pixb || pixGetDepth(pixb) != 1)
2418 return (
PIX *)ERROR_PTR(
"pixb undefined or not 1 bpp", __func__, NULL);
2419 if (!pixm || pixGetDepth(pixm) != 8)
2420 return (
PIX *)ERROR_PTR(
"pixm undefined or not 8 bpp", __func__, NULL);
2421 if (connectivity != 4 && connectivity != 8)
2422 return (
PIX *)ERROR_PTR(
"connectivity not in {4,8}", __func__, NULL);
2425 L_WARNING(
"delta <= 0; returning a copy of pixm\n", __func__);
2426 return pixCopy(NULL, pixm);
2430 pixsd = pixCopy(NULL, pixm);
2431 pixAddConstantGray(pixsd, delta);
2435 pixbi = pixInvert(NULL, pixb);
2436 pixSetMasked(pixsd, pixbi, 255);
2439 pixmi = pixInvert(NULL, pixm);
2440 pixInvert(pixsd, pixsd);
2444 pixInvert(pixsd, pixsd);
2500 l_int32 connectivity,
2508 if (!pixs || pixGetDepth(pixs) != 1)
2509 return (
PIX *)ERROR_PTR(
"!pixs or pixs not 1 bpp", __func__, NULL);
2510 if (connectivity != 4 && connectivity != 8)
2511 return (
PIX *)ERROR_PTR(
"connectivity not 4 or 8", __func__, NULL);
2512 if (outdepth != 8 && outdepth != 16)
2513 return (
PIX *)ERROR_PTR(
"outdepth not 8 or 16 bpp", __func__, NULL);
2514 if (boundcond != L_BOUNDARY_BG && boundcond != L_BOUNDARY_FG)
2515 return (
PIX *)ERROR_PTR(
"invalid boundcond", __func__, NULL);
2517 pixGetDimensions(pixs, &w, &h, NULL);
2518 if ((pixd = pixCreate(w, h, outdepth)) == NULL)
2519 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
2520 datad = pixGetData(pixd);
2521 wpld = pixGetWpl(pixd);
2524 pixSetMasked(pixd, pixs, 1);
2526 if (boundcond == L_BOUNDARY_BG) {
2529 pixRasterop(pixd, 0, 0, w, 1,
PIX_SET, NULL, 0, 0);
2530 pixRasterop(pixd, 0, h - 1, w, 1,
PIX_SET, NULL, 0, 0);
2531 pixRasterop(pixd, 0, 0, 1, h,
PIX_SET, NULL, 0, 0);
2532 pixRasterop(pixd, w - 1, 0, 1, h,
PIX_SET, NULL, 0, 0);
2537 pixSetMirroredBorder(pixd, 1, 1, 1, 1);
2553 l_int32 connectivity)
2555l_int32 val1, val2, val3, val4, val5, val6, val7, val8, minval, val;
2556l_int32 i, j, imax, jmax;
2564 switch (connectivity)
2569 for (i = 1; i < imax; i++) {
2570 lined = datad + i * wpld;
2571 for (j = 1; j < jmax; j++) {
2575 minval = L_MIN(val2, val4);
2576 minval = L_MIN(minval, 254);
2583 for (i = imax - 1; i > 0; i--) {
2584 lined = datad + i * wpld;
2585 for (j = jmax - 1; j > 0; j--) {
2589 minval = L_MIN(val5, val7);
2590 minval = L_MIN(minval + 1, val);
2597 for (i = 1; i < imax; i++) {
2598 lined = datad + i * wpld;
2599 for (j = 1; j < jmax; j++) {
2603 minval = L_MIN(val2, val4);
2604 minval = L_MIN(minval, 0xfffe);
2611 for (i = imax - 1; i > 0; i--) {
2612 lined = datad + i * wpld;
2613 for (j = jmax - 1; j > 0; j--) {
2617 minval = L_MIN(val5, val7);
2618 minval = L_MIN(minval + 1, val);
2629 for (i = 1; i < imax; i++) {
2630 lined = datad + i * wpld;
2631 for (j = 1; j < jmax; j++) {
2637 minval = L_MIN(val1, val2);
2638 minval = L_MIN(minval, val3);
2639 minval = L_MIN(minval, val4);
2640 minval = L_MIN(minval, 254);
2647 for (i = imax - 1; i > 0; i--) {
2648 lined = datad + i * wpld;
2649 for (j = jmax - 1; j > 0; j--) {
2655 minval = L_MIN(val8, val7);
2656 minval = L_MIN(minval, val6);
2657 minval = L_MIN(minval, val5);
2658 minval = L_MIN(minval + 1, val);
2665 for (i = 1; i < imax; i++) {
2666 lined = datad + i * wpld;
2667 for (j = 1; j < jmax; j++) {
2673 minval = L_MIN(val1, val2);
2674 minval = L_MIN(minval, val3);
2675 minval = L_MIN(minval, val4);
2676 minval = L_MIN(minval, 0xfffe);
2683 for (i = imax - 1; i > 0; i--) {
2684 lined = datad + i * wpld;
2685 for (j = jmax - 1; j > 0; j--) {
2691 minval = L_MIN(val8, val7);
2692 minval = L_MIN(minval, val6);
2693 minval = L_MIN(minval, val5);
2694 minval = L_MIN(minval + 1, val);
2703 L_ERROR(
"connectivity must be 4 or 8\n", __func__);
2753 l_int32 connectivity)
2755l_int32 w, h, wplt, wplg;
2756l_uint32 *datat, *datag;
2757PIX *pixm, *pixt, *pixg, *pixd;
2759 if (!pixs || pixGetDepth(pixs) != 8)
2760 return (
PIX *)ERROR_PTR(
"!pixs or pixs not 8 bpp", __func__, NULL);
2761 if (connectivity != 4 && connectivity != 8)
2762 return (
PIX *)ERROR_PTR(
"connectivity not 4 or 8", __func__, NULL);
2765 pixg = pixAddBorder(pixs, 4, 0);
2766 pixGetDimensions(pixg, &w, &h, NULL);
2775 pixm = pixThresholdToBinary(pixg, 1);
2776 pixt = pixCreate(w, h, 16);
2777 pixSetMasked(pixt, pixm, 1);
2778 pixRasterop(pixt, 0, 0, w, 1,
PIX_SET, NULL, 0, 0);
2779 pixRasterop(pixt, 0, h - 1, w, 1,
PIX_SET, NULL, 0, 0);
2780 pixRasterop(pixt, 0, 0, 1, h,
PIX_SET, NULL, 0, 0);
2781 pixRasterop(pixt, w - 1, 0, 1, h,
PIX_SET, NULL, 0, 0);
2782 datat = pixGetData(pixt);
2783 wplt = pixGetWpl(pixt);
2786 datag = pixGetData(pixg);
2787 wplg = pixGetWpl(pixg);
2788 seedspreadLow(datag, w, h, wplg, datat, wplt, connectivity);
2789 pixd = pixRemoveBorder(pixg, 4);
2810 l_int32 connectivity)
2812l_int32 val1t, val2t, val3t, val4t, val5t, val6t, val7t, val8t;
2813l_int32 i, j, imax, jmax, minval, valt, vald;
2814l_uint32 *linet, *lined;
2823 switch (connectivity)
2827 for (i = 1; i < h; i++) {
2828 linet = datat + i * wplt;
2829 lined = datad + i * wpld;
2830 for (j = 1; j < jmax; j++) {
2834 minval = L_MIN(val2t, val4t);
2835 minval = L_MIN(minval, 0xfffe);
2847 for (i = imax - 1; i > 0; i--) {
2848 linet = datat + i * wplt;
2849 lined = datad + i * wpld;
2850 for (j = jmax - 1; j > 0; j--) {
2854 minval = L_MIN(val5t, val7t);
2855 minval = L_MIN(minval + 1, valt);
2856 if (valt > minval) {
2870 for (i = 1; i < h; i++) {
2871 linet = datat + i * wplt;
2872 lined = datad + i * wpld;
2873 for (j = 1; j < jmax; j++) {
2879 minval = L_MIN(val1t, val2t);
2880 minval = L_MIN(minval, val3t);
2881 minval = L_MIN(minval, val4t);
2882 minval = L_MIN(minval, 0xfffe);
2884 if (minval == val1t)
2886 else if (minval == val2t)
2888 else if (minval == val3t)
2898 for (i = imax - 1; i > 0; i--) {
2899 linet = datat + i * wplt;
2900 lined = datad + i * wpld;
2901 for (j = jmax - 1; j > 0; j--) {
2907 minval = L_MIN(val8t, val7t);
2908 minval = L_MIN(minval, val6t);
2909 minval = L_MIN(minval, val5t);
2910 minval = L_MIN(minval + 1, valt);
2911 if (valt > minval) {
2913 if (minval == val5t + 1)
2915 else if (minval == val6t + 1)
2917 else if (minval == val7t + 1)
2928 L_ERROR(
"connectivity must be 4 or 8\n", __func__);
2981PIX *pixmin, *pixmax, *pixt1, *pixt2;
2983 if (!pixs || pixGetDepth(pixs) != 8)
2984 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
2985 if (!ppixmin && !ppixmax)
2986 return ERROR_INT(
"neither &pixmin, &pixmax are defined", __func__, 1);
2987 if (maxmin <= 0) maxmin = 254;
2988 if (minmax <= 0) minmax = 1;
2991 pixt1 = pixErodeGray(pixs, 3, 3);
2999 pixt1 = pixInvert(NULL, pixs);
3000 pixt2 = pixErodeGray(pixt1, 3, 3);
3041l_int32 n, i, j, k, x, y, w, h, xc, yc, wc, hc, xon, yon;
3042l_int32 vals, wpls, wplc, ismin;
3044l_uint32 *datas, *datac, *lines, *linec;
3046PIX *pix1, *pix2, *pix3;
3049 if (!pixs || pixGetDepth(pixs) != 8)
3050 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
3051 if (!pixm || pixGetDepth(pixm) != 1)
3052 return ERROR_INT(
"pixm not defined or not 1 bpp", __func__, 1);
3053 if (maxval <= 0) maxval = 254;
3055 pixGetDimensions(pixs, &w, &h, NULL);
3056 datas = pixGetData(pixs);
3057 wpls = pixGetWpl(pixs);
3058 boxa = pixConnComp(pixm, &pixa, 8);
3059 n = pixaGetCount(pixa);
3060 for (k = 0; k < n; k++) {
3061 boxaGetBoxGeometry(boxa, k, &xc, &yc, &wc, &hc);
3062 pix1 = pixaGetPix(pixa, k,
L_COPY);
3063 pix2 = pixAddBorder(pix1, 1, 0);
3064 pix3 = pixDilateBrick(NULL, pix2, 3, 3);
3065 pixXor(pix3, pix3, pix2);
3066 datac = pixGetData(pix3);
3067 wplc = pixGetWpl(pix3);
3068 nextOnPixelInRaster(pix1, 0, 0, &xon, &yon);
3069 pixGetPixel(pixs, xc + xon, yc + yon, &val);
3071 pixRasterop(pixm, xc, yc, wc, hc,
PIX_XOR, pix1, 0, 0);
3082 for (i = 0, y = yc - 1; i < hc + 2 && y >= 0 && y < h; i++, y++) {
3083 lines = datas + y * wpls;
3084 linec = datac + i * wplc;
3085 for (j = 0, x = xc - 1; j < wc + 2 && x >= 0 && x < w; j++, x++) {
3098 pixRasterop(pixm, xc, yc, wc, hc,
PIX_XOR, pix1, 0, 0);
3148PIX *pixmin, *pixmax, *pixt, *pixtmin, *pixtmax;
3150 if (!pixs || pixGetDepth(pixs) != 8)
3151 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
3152 if (!ppixmin || !ppixmax)
3153 return ERROR_INT(
"&pixmin and &pixmax not both defined", __func__, 1);
3155 pixt = pixErodeGray(pixs, 3, 3);
3158 pixt = pixDilateGray(pixs, 3, 3);
3167 }
else if (mindist == 0) {
3168 pixt = pixAnd(NULL, pixmin, pixmax);
3169 *ppixmin = pixSubtract(pixmin, pixmin, pixt);
3170 *ppixmax = pixSubtract(pixmax, pixmax, pixt);
3173 pixtmin = pixDilateBrick(NULL, pixmin,
3174 2 * mindist + 1, 2 * mindist + 1);
3175 pixtmax = pixDilateBrick(NULL, pixmax,
3176 2 * mindist + 1, 2 * mindist + 1);
3177 *ppixmin = pixSubtract(pixmin, pixmin, pixtmax);
3178 *ppixmax = pixSubtract(pixmax, pixmax, pixtmin);
3179 pixDestroy(&pixtmin);
3180 pixDestroy(&pixtmax);
3204l_int32 w1, h1, w2, h2, w, h;
3205l_int32 i, j, val1, val2, wpls1, wpls2, wpld;
3206l_uint32 *datas1, *datas2, *datad, *lines1, *lines2, *lined;
3209 if (!pixs1 || pixGetDepth(pixs1) != 8)
3210 return (
PIX *)ERROR_PTR(
"pixs1 undefined or not 8 bpp", __func__, NULL);
3211 if (!pixs2 || pixGetDepth(pixs2) != 8)
3212 return (
PIX *)ERROR_PTR(
"pixs2 undefined or not 8 bpp", __func__, NULL);
3213 pixGetDimensions(pixs1, &w1, &h1, NULL);
3214 pixGetDimensions(pixs2, &w2, &h2, NULL);
3217 pixd = pixCreate(w, h, 1);
3218 datas1 = pixGetData(pixs1);
3219 datas2 = pixGetData(pixs2);
3220 datad = pixGetData(pixd);
3221 wpls1 = pixGetWpl(pixs1);
3222 wpls2 = pixGetWpl(pixs2);
3223 wpld = pixGetWpl(pixd);
3225 for (i = 0; i < h; i++) {
3226 lines1 = datas1 + i * wpls1;
3227 lines2 = datas2 + i * wpls2;
3228 lined = datad + i * wpld;
3229 for (j = 0; j < w; j++) {
3271l_int32 bx, by, bw, bh, i, j, c, n;
3272l_int32 xs, ys, minx, miny, wpls, wplt, val, minval;
3273l_uint32 *datas, *datat, *lines, *linet;
3276PIX *pixt, *pixs2, *pixm2;
3281 return ERROR_INT(
"&pta not defined", __func__, 1);
3283 if (pnav) *pnav = NULL;
3284 if (!pixs || pixGetDepth(pixs) != 8)
3285 return ERROR_INT(
"pixs undefined or not 8 bpp", __func__, 1);
3286 if (!pixm || pixGetDepth(pixm) != 1)
3287 return ERROR_INT(
"pixm undefined or not 1 bpp", __func__, 1);
3290 if (pixCropToMatch(pixs, pixm, &pixs2, &pixm2)) {
3293 return ERROR_INT(
"cropping failure", __func__, 1);
3297 boxa = pixConnComp(pixm2, &pixa, 8);
3298 n = boxaGetCount(boxa);
3301 nav = numaCreate(n);
3302 datas = pixGetData(pixs2);
3303 wpls = pixGetWpl(pixs2);
3304 for (c = 0; c < n; c++) {
3305 pixt = pixaGetPix(pixa, c,
L_CLONE);
3306 boxaGetBoxGeometry(boxa, c, &bx, &by, &bw, &bh);
3307 if (bw == 1 && bh == 1) {
3308 ptaAddPt(pta, bx, by);
3313 datat = pixGetData(pixt);
3314 wplt = pixGetWpl(pixt);
3315 minx = miny = 1000000;
3317 for (i = 0; i < bh; i++) {
3319 lines = datas + ys * wpls;
3320 linet = datat + i * wplt;
3321 for (j = 0; j < bw; j++) {
3333 ptaAddPt(pta, minx, miny);
3334 numaAddNumber(nav,
GET_DATA_BYTE(datas + miny * wpls, minx));
3380 l_int32 connectivity,
3385 if (!pixs || pixGetDepth(pixs) != 1)
3386 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, pixd);
3387 if (!pixm || pixGetDepth(pixm) != 1)
3388 return (
PIX *)ERROR_PTR(
"pixm undefined or not 1 bpp", __func__, pixd);
3389 if (pixd && pixd != pixm)
3390 return (
PIX *)ERROR_PTR(
"operation not inplace", __func__, pixd);
3392 pixt = pixCopy(NULL, pixs);
3394 pixd = pixXor(pixd, pixm, pixt);
3396 pixSetOrClearBorder(pixd, bordersize, bordersize, bordersize,
#define GET_DATA_TWO_BYTES(pdata, n)
#define SET_DATA_BIT(pdata, n)
#define SET_DATA_TWO_BYTES(pdata, n, val)
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
#define GET_DATA_BIT(pdata, n)
l_ok pixSeedfillGrayInvSimple(PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillGrayInvSimple()
PIX * pixSeedspread(PIX *pixs, l_int32 connectivity)
pixSeedspread()
static void distanceFunctionLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 d, l_int32 wpld, l_int32 connectivity)
distanceFunctionLow()
static l_int32 pixQualifyLocalMinima(PIX *pixs, PIX *pixm, l_int32 maxval)
pixQualifyLocalMinima()
static void seedfillBinaryLow(l_uint32 *datas, l_int32 hs, l_int32 wpls, l_uint32 *datam, l_int32 hm, l_int32 wplm, l_int32 connectivity)
seedfillBinaryLow()
static void seedfillGrayInvLowSimple(l_uint32 *datas, l_int32 w, l_int32 h, l_int32 wpls, l_uint32 *datam, l_int32 wplm, l_int32 connectivity)
seedfillGrayInvLowSimple()
static void seedspreadLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datat, l_int32 wplt, l_int32 connectivity)
seedspreadLow()
PIX * pixExtractBorderConnComps(PIX *pixs, l_int32 connectivity)
pixExtractBorderConnComps()
static void seedfillGrayLow(l_uint32 *datas, l_int32 w, l_int32 h, l_int32 wpls, l_uint32 *datam, l_int32 wplm, l_int32 connectivity)
seedfillGrayLow()
PIX * pixRemoveSeededComponents(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 connectivity, l_int32 bordersize)
pixRemoveSeededComponents()
PIX * pixDistanceFunction(PIX *pixs, l_int32 connectivity, l_int32 outdepth, l_int32 boundcond)
pixDistanceFunction()
static void seedfillGrayLowSimple(l_uint32 *datas, l_int32 w, l_int32 h, l_int32 wpls, l_uint32 *datam, l_int32 wplm, l_int32 connectivity)
seedfillGrayLowSimple()
l_ok pixSelectedLocalExtrema(PIX *pixs, l_int32 mindist, PIX **ppixmin, PIX **ppixmax)
pixSelectedLocalExtrema()
PIX * pixSeedfillGrayBasin(PIX *pixb, PIX *pixm, l_int32 delta, l_int32 connectivity)
pixSeedfillGrayBasin()
l_ok pixSeedfillGrayInv(PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillGrayInv()
PIX * pixSeedfillBinary(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillBinary()
l_ok pixSelectMinInConnComp(PIX *pixs, PIX *pixm, PTA **ppta, NUMA **pnav)
pixSelectMinInConnComp()
PIX * pixFillHolesToBoundingRect(PIX *pixs, l_int32 minsize, l_float32 maxhfract, l_float32 minfgfract)
pixFillHolesToBoundingRect()
l_ok pixLocalExtrema(PIX *pixs, l_int32 maxmin, l_int32 minmax, PIX **ppixmin, PIX **ppixmax)
pixLocalExtrema()
PIX * pixFillBgFromBorder(PIX *pixs, l_int32 connectivity)
pixFillBgFromBorder()
PIX * pixFindEqualValues(PIX *pixs1, PIX *pixs2)
pixFindEqualValues()
PIX * pixSeedfillBinaryRestricted(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 connectivity, l_int32 xmax, l_int32 ymax)
pixSeedfillBinaryRestricted()
PIX * pixFillClosedBorders(PIX *pixs, l_int32 connectivity)
pixFillClosedBorders()
PIX * pixHolesByFilling(PIX *pixs, l_int32 connectivity)
pixHolesByFilling()
static void seedfillGrayInvLow(l_uint32 *datas, l_int32 w, l_int32 h, l_int32 wpls, l_uint32 *datam, l_int32 wplm, l_int32 connectivity)
seedfillGrayInvLow()
l_ok pixSeedfillGray(PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillGray()
l_ok pixSeedfillGraySimple(PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillGraySimple()
PIX * pixRemoveBorderConnComps(PIX *pixs, l_int32 connectivity)
pixRemoveBorderConnComps()