603 l_float32 validthresh,
604 l_float32 colorthresh)
606l_int32 w, h, minside, factor, index, rval, gval, bval;
607l_float32 scalefactor;
615 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
616 if (pixGetDepth(pixs) != 32)
617 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
618 if (colors < 128 || colors > 240)
619 return (
PIX *)ERROR_PTR(
"colors must be in [128, 240]", __func__, NULL);
627 pixGetDimensions(pixs, &w, &h, NULL);
628 if (validthresh > 0.0 && colorthresh > 0.0) {
629 minside = L_MIN(w, h);
630 factor = L_MAX(1, minside / 400);
631 pixColorFraction(pixs, 20, 244, 20, factor, &pixfract, &colorfract);
632 if (pixfract * colorfract < validthresh * colorthresh) {
633 L_INFO(
"\n Pixel fraction neither white nor black = %6.3f"
634 "\n Color fraction of those pixels = %6.3f"
635 "\n Quantizing to 8 bpp gray\n",
636 __func__, pixfract, colorfract);
637 return pixConvertTo8(pixs, 1);
640 L_INFO(
"\n Process in color by default\n", __func__);
644 if (w > TreeGenWidth) {
645 scalefactor = (l_float32)TreeGenWidth / (l_float32)w;
646 pixsub = pixScaleBySampling(pixs, scalefactor, scalefactor);
648 pixsub = pixClone(pixs);
652 if (w < MinDitherSize && h < MinDitherSize)
653 colors = L_MIN(colors, 220);
659 return (
PIX *)ERROR_PTR(
"tree not made", __func__, NULL);
662 L_INFO(
" Colors requested = %d\n", __func__, colors);
663 L_INFO(
" Actual colors = %d\n", __func__, cmap->
n);
667 if (w < MinDitherSize && h < MinDitherSize && ditherflag == 1) {
668 L_INFO(
"Small image: dithering turned off\n", __func__);
678 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
682 pixSetColormap(pixd, cmap);
683 pixCopyResolution(pixd, pixs);
684 pixCopyInputFormat(pixd, pixs);
687 pixcmapGetRankIntensity(cmap, 0.0, &index);
688 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
689 if (rval < 5 && gval < 5 && bval < 5)
690 pixcmapResetColor(cmap, index, 0, 0, 0);
693 pixcmapGetRankIntensity(cmap, 1.0, &index);
694 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
695 if (rval > 251 && gval > 251 && bval > 251)
696 pixcmapResetColor(cmap, index, 255, 255, 255);
723 l_int32 reservedcolors,
726l_int32 rval, gval, bval, cindex;
727l_int32 level, ncells, octindex;
734l_float32 thresholdFactor[] = {0.01f, 0.01f, 1.0f, 1.0f, 1.0f, 1.0f};
736l_uint32 *datas, *lines;
737l_uint32 *rtab, *gtab, *btab;
746 return (
CQCELL ***)ERROR_PTR(
"pixs not defined", __func__, NULL);
747 if (pixGetDepth(pixs) != 32)
748 return (
CQCELL ***)ERROR_PTR(
"pixs must be 32 bpp", __func__, NULL);
749 if (colors < 128 || colors > 256)
750 return (
CQCELL ***)ERROR_PTR(
"colors not in [128,256]", __func__, NULL);
752 return (
CQCELL ***)ERROR_PTR(
"&cmap not defined", __func__, NULL);
755 return (
CQCELL ***)ERROR_PTR(
"cqcaa not made", __func__, NULL);
758 rtab = gtab = btab = NULL;
762 cmap = pixcmapCreate(8);
765 pixGetDimensions(pixs, &w, &h, NULL);
767 ncolor = colors - reservedcolors - ExtraReservedColors;
769 datas = pixGetData(pixs);
770 wpls = pixGetWpl(pixs);
773 ncells = 1 << (3 * CqNLevels);
774 cqca = cqcaa[CqNLevels];
775 for (i = 0; i < h; i++) {
776 lines = datas + i * wpls;
777 for (j = 0; j < w; j++) {
778 extractRGBValues(lines[j], &rval, &gval, &bval);
779 octindex = rtab[rval] | gtab[gval] | btab[bval];
780 cqc = cqca[octindex];
790 for (level = CqNLevels - 1; level >= 2; level--) {
791 thresh = thresholdFactor[level];
793 cqcasub = cqcaa[level + 1];
794 ncells = 1 << (3 * level);
795 for (i = 0; i < ncells; i++) {
797 for (j = 0; j < 8; j++) {
799 cqcsub = cqcasub[isub];
800 if (cqcsub->bleaf == 1) {
804 if (cqcsub->n >= thresh * ppc) {
807 cqcsub->index = cmap->
n;
809 pixcmapAddColor(cmap, rv, gv, bv);
817 L_ERROR(
"assigning pixels to wrong color\n", __func__);
818 pixcmapGetNearestIndex(cmap, 128, 128, 128, &cindex);
819 cqcsub->index = cindex;
820 pixcmapGetColor(cmap, cindex, &rval, &gval, &bval);
830 else if (ncolor + reservedcolors > 0)
831 ppc = npix / (ncolor + reservedcolors);
834 numaAddNumber(nat, level + 1);
836#if DEBUG_OCTCUBE_CMAP
837 lept_stderr(
"Exceeds threshold: colors used = %d, colors remaining = %d\n",
838 cmap->
n, ncolor + reservedcolors);
839 lept_stderr(
" cell with %d pixels, npix = %d, ppc = %d\n",
840 cqcsub->n, npix, ppc);
841 lept_stderr(
" index = %d, level = %d, subindex = %d\n",
843 lept_stderr(
" rv = %d, gv = %d, bv = %d\n", rv, gv, bv);
848 if (cqc->nleaves > 0 || level == 2) {
850 if (cqc->nleaves < 8) {
852 for (j = 0; j < 8; j++) {
854 cqcsub = cqcasub[isub];
855 if (cqcsub->bleaf == 0)
859 cqc->index = cmap->
n;
861 pixcmapAddColor(cmap, rv, gv, bv);
868 L_WARNING(
"possibly assigned pixels to wrong color\n",
873 pixcmapGetNearestIndex(cmap, rv, gv, bv, &cindex);
875 pixcmapGetColor(cmap, cindex, &rval, &gval, &bval);
884 else if (ncolor + reservedcolors > 0)
885 ppc = npix / (ncolor + reservedcolors);
888 numaAddNumber(nar, level);
890#if DEBUG_OCTCUBE_CMAP
891 lept_stderr(
"By remainder: colors used = %d, colors remaining = %d\n",
892 cmap->
n, ncolor + reservedcolors);
893 lept_stderr(
" cell with %d pixels, npix = %d, ppc = %d\n",
895 lept_stderr(
" index = %d, level = %d\n", i, level);
896 lept_stderr(
" rv = %d, gv = %d, bv = %d\n", rv, gv, bv);
901 for (j = 0; j < 8; j++) {
903 cqcsub = cqcasub[isub];
910#if PRINT_OCTCUBE_STATS
912l_int32 tc[] = {0, 0, 0, 0, 0, 0, 0};
913l_int32 rc[] = {0, 0, 0, 0, 0, 0, 0};
916 nt = numaGetCount(nat);
917 nr = numaGetCount(nar);
918 for (i = 0; i < nt; i++) {
919 numaGetIValue(nat, i, &ival);
922 for (i = 0; i < nr; i++) {
923 numaGetIValue(nar, i, &ival);
926 lept_stderr(
" Threshold cells formed: %d\n", nt);
927 for (i = 1; i < CqNLevels + 1; i++)
928 lept_stderr(
" level %d: %d\n", i, tc[i]);
929 lept_stderr(
"\n Residual cells formed: %d\n", nr);
930 for (i = 0; i < CqNLevels ; i++)
931 lept_stderr(
" level %d: %d\n", i, rc[i]);
973l_uint8 *bufu8r, *bufu8g, *bufu8b;
974l_int32 rval, gval, bval;
975l_int32 octindex, index;
976l_int32 val1, val2, val3, dif;
977l_int32 w, h, wpls, wpld, i, j, success;
979l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
980l_uint32 *rtab, *gtab, *btab;
981l_uint32 *datas, *datad, *lines, *lined;
985 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
986 if (pixGetDepth(pixs) != 32)
987 return (
PIX *)ERROR_PTR(
"pixs must be 32 bpp", __func__, NULL);
989 return (
PIX *)ERROR_PTR(
"cqcaa not defined", __func__, NULL);
992 pixGetDimensions(pixs, &w, &h, NULL);
993 datas = pixGetData(pixs);
994 wpls = pixGetWpl(pixs);
995 if ((pixd = pixCreate(w, h, 8)) == NULL)
996 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
997 pixCopyResolution(pixd, pixs);
998 pixCopyInputFormat(pixd, pixs);
999 datad = pixGetData(pixd);
1000 wpld = pixGetWpl(pixd);
1003 rtab = gtab = btab = NULL;
1011 if (ditherflag == 0) {
1012 for (i = 0; i < h; i++) {
1013 lines = datas + i * wpls;
1014 lined = datad + i * wpld;
1015 for (j = 0; j < w; j++) {
1016 extractRGBValues(lines[j], &rval, &gval, &bval);
1017 octindex = rtab[rval] | gtab[gval] | btab[bval];
1024 bufu8r = bufu8g = bufu8b = NULL;
1025 buf1r = buf1g = buf1b = buf2r = buf2g = buf2b = NULL;
1026 bufu8r = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1027 bufu8g = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1028 bufu8b = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1029 buf1r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1030 buf1g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1031 buf1b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1032 buf2r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1033 buf2g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1034 buf2b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1035 if (!bufu8r || !bufu8g || !bufu8b || !buf1r || !buf1g ||
1036 !buf1b || !buf2r || !buf2g || !buf2b) {
1037 L_ERROR(
"buffer not made\n", __func__);
1039 goto buffer_cleanup;
1043 pixGetRGBLine(pixs, 0, bufu8r, bufu8g, bufu8b);
1044 for (j = 0; j < w; j++) {
1045 buf2r[j] = 64 * bufu8r[j];
1046 buf2g[j] = 64 * bufu8g[j];
1047 buf2b[j] = 64 * bufu8b[j];
1050 for (i = 0; i < h - 1; i++) {
1052 memcpy(buf1r, buf2r, 4 * w);
1053 memcpy(buf1g, buf2g, 4 * w);
1054 memcpy(buf1b, buf2b, 4 * w);
1055 pixGetRGBLine(pixs, i + 1, bufu8r, bufu8g, bufu8b);
1056 for (j = 0; j < w; j++) {
1057 buf2r[j] = 64 * bufu8r[j];
1058 buf2g[j] = 64 * bufu8g[j];
1059 buf2b[j] = 64 * bufu8b[j];
1063 lined = datad + i * wpld;
1064 for (j = 0; j < w - 1; j++) {
1065 rval = buf1r[j] / 64;
1066 gval = buf1g[j] / 64;
1067 bval = buf1b[j] / 64;
1068 octindex = rtab[rval] | gtab[gval] | btab[bval];
1072 dif = buf1r[j] / 8 - 8 * rc;
1074 val1 = buf1r[j + 1] + 3 * dif;
1075 val2 = buf2r[j] + 3 * dif;
1076 val3 = buf2r[j + 1] + 2 * dif;
1078 buf1r[j + 1] = L_MIN(16383, val1);
1079 buf2r[j] = L_MIN(16383, val2);
1080 buf2r[j + 1] = L_MIN(16383, val3);
1082 buf1r[j + 1] = L_MAX(0, val1);
1083 buf2r[j] = L_MAX(0, val2);
1084 buf2r[j + 1] = L_MAX(0, val3);
1088 dif = buf1g[j] / 8 - 8 * gc;
1090 val1 = buf1g[j + 1] + 3 * dif;
1091 val2 = buf2g[j] + 3 * dif;
1092 val3 = buf2g[j + 1] + 2 * dif;
1094 buf1g[j + 1] = L_MIN(16383, val1);
1095 buf2g[j] = L_MIN(16383, val2);
1096 buf2g[j + 1] = L_MIN(16383, val3);
1098 buf1g[j + 1] = L_MAX(0, val1);
1099 buf2g[j] = L_MAX(0, val2);
1100 buf2g[j + 1] = L_MAX(0, val3);
1104 dif = buf1b[j] / 8 - 8 * bc;
1106 val1 = buf1b[j + 1] + 3 * dif;
1107 val2 = buf2b[j] + 3 * dif;
1108 val3 = buf2b[j + 1] + 2 * dif;
1110 buf1b[j + 1] = L_MIN(16383, val1);
1111 buf2b[j] = L_MIN(16383, val2);
1112 buf2b[j + 1] = L_MIN(16383, val3);
1114 buf1b[j + 1] = L_MAX(0, val1);
1115 buf2b[j] = L_MAX(0, val2);
1116 buf2b[j + 1] = L_MAX(0, val3);
1122 rval = buf1r[w - 1] / 64;
1123 gval = buf1g[w - 1] / 64;
1124 bval = buf1b[w - 1] / 64;
1125 octindex = rtab[rval] | gtab[gval] | btab[bval];
1131 lined = datad + (h - 1) * wpld;
1132 for (j = 0; j < w; j++) {
1133 rval = buf2r[j] / 64;
1134 gval = buf2g[j] / 64;
1135 bval = buf2b[j] / 64;
1136 octindex = rtab[rval] | gtab[gval] | btab[bval];
1151 if (!success) pixDestroy(&pixd);
1348l_uint32 *rtab, *gtab, *btab;
1350 if (cqlevels < 1 || cqlevels > 6)
1351 return ERROR_INT(
"cqlevels must be in {1,...6}", __func__, 1);
1352 if (!prtab || !pgtab || !pbtab)
1353 return ERROR_INT(
"not all &tabs defined", __func__, 1);
1355 rtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1356 gtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1357 btab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1358 if (!rtab || !gtab || !btab)
1359 return ERROR_INT(
"calloc fail for tab", __func__, 1);
1367 for (i = 0; i < 256; i++) {
1368 rtab[i] = (i >> 5) & 0x0004;
1369 gtab[i] = (i >> 6) & 0x0002;
1374 for (i = 0; i < 256; i++) {
1375 rtab[i] = ((i >> 2) & 0x0020) | ((i >> 4) & 0x0004);
1376 gtab[i] = ((i >> 3) & 0x0010) | ((i >> 5) & 0x0002);
1377 btab[i] = ((i >> 4) & 0x0008) | ((i >> 6) & 0x0001);
1381 for (i = 0; i < 256; i++) {
1382 rtab[i] = ((i << 1) & 0x0100) | ((i >> 1) & 0x0020) |
1383 ((i >> 3) & 0x0004);
1384 gtab[i] = (i & 0x0080) | ((i >> 2) & 0x0010) |
1385 ((i >> 4) & 0x0002);
1386 btab[i] = ((i >> 1) & 0x0040) | ((i >> 3) & 0x0008) |
1387 ((i >> 5) & 0x0001);
1391 for (i = 0; i < 256; i++) {
1392 rtab[i] = ((i << 4) & 0x0800) | ((i << 2) & 0x0100) |
1393 (i & 0x0020) | ((i >> 2) & 0x0004);
1394 gtab[i] = ((i << 3) & 0x0400) | ((i << 1) & 0x0080) |
1395 ((i >> 1) & 0x0010) | ((i >> 3) & 0x0002);
1396 btab[i] = ((i << 2) & 0x0200) | (i & 0x0040) |
1397 ((i >> 2) & 0x0008) | ((i >> 4) & 0x0001);
1401 for (i = 0; i < 256; i++) {
1402 rtab[i] = ((i << 7) & 0x4000) | ((i << 5) & 0x0800) |
1403 ((i << 3) & 0x0100) | ((i << 1) & 0x0020) |
1404 ((i >> 1) & 0x0004);
1405 gtab[i] = ((i << 6) & 0x2000) | ((i << 4) & 0x0400) |
1406 ((i << 2) & 0x0080) | (i & 0x0010) |
1407 ((i >> 2) & 0x0002);
1408 btab[i] = ((i << 5) & 0x1000) | ((i << 3) & 0x0200) |
1409 ((i << 1) & 0x0040) | ((i >> 1) & 0x0008) |
1410 ((i >> 3) & 0x0001);
1414 for (i = 0; i < 256; i++) {
1415 rtab[i] = ((i << 10) & 0x20000) | ((i << 8) & 0x4000) |
1416 ((i << 6) & 0x0800) | ((i << 4) & 0x0100) |
1417 ((i << 2) & 0x0020) | (i & 0x0004);
1418 gtab[i] = ((i << 9) & 0x10000) | ((i << 7) & 0x2000) |
1419 ((i << 5) & 0x0400) | ((i << 3) & 0x0080) |
1420 ((i << 1) & 0x0010) | ((i >> 1) & 0x0002);
1421 btab[i] = ((i << 8) & 0x8000) | ((i << 6) & 0x1000) |
1422 ((i << 4) & 0x0200) | ((i << 2) & 0x0040) |
1423 (i & 0x0008) | ((i >> 2) & 0x0001);
1427 ERROR_INT(
"cqlevels not in [1...6]", __func__, 1);
1680l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
1681l_int32 rval, gval, bval;
1682l_int32 *rarray, *garray, *barray, *narray, *iarray;
1683l_uint32 octindex, octindex2;
1684l_uint32 *rtab, *gtab, *btab, *rtab2, *gtab2, *btab2;
1685l_uint32 *lines, *lined, *datas, *datad;
1692 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
1693 if (pixGetDepth(pixs) != 32)
1694 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
1695 if (level == 0) level = 4;
1696 if (level < 3 || level > 4)
1697 return (
PIX *)ERROR_PTR(
"level not in {3,4}", __func__, NULL);
1700 pixGetDimensions(pixs, &w, &h, NULL);
1701 if (w < MinDitherSize && h < MinDitherSize && ditherflag == 1) {
1702 L_INFO(
"Small image: dithering turned off\n", __func__);
1707 return (
PIX *)ERROR_PTR(
"size not returned", __func__, NULL);
1708 rtab = gtab = btab = NULL;
1712 narray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1713 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1714 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1715 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1716 if (!narray || !rarray || !garray || !barray)
1720 datas = pixGetData(pixs);
1721 wpls = pixGetWpl(pixs);
1722 for (i = 0; i < h; i++) {
1723 lines = datas + i * wpls;
1724 for (j = 0; j < w; j++) {
1725 extractRGBValues(lines[j], &rval, &gval, &bval);
1726 octindex = rtab[rval] | gtab[gval] | btab[bval];
1728 rarray[octindex] += rval;
1729 garray[octindex] += gval;
1730 barray[octindex] += bval;
1735 for (i = 0, ncolors = 0; i < size; i++) {
1741 else if (ncolors <= 16)
1745 pixd = pixCreate(w, h, depth);
1746 datad = pixGetData(pixd);
1747 wpld = pixGetWpl(pixd);
1748 pixCopyResolution(pixd, pixs);
1749 pixCopyInputFormat(pixd, pixs);
1750 cmap = pixcmapCreate(depth);
1751 pixSetColormap(pixd, cmap);
1754 for (i = 0; i < size; i++) {
1755 if (narray[i] > 0) {
1756 rarray[i] /= narray[i];
1757 garray[i] /= narray[i];
1758 barray[i] /= narray[i];
1764 if (ncolors <= 256) {
1765 for (i = 0, index = 0; i < size; i++) {
1766 if (narray[i] > 0) {
1767 pixcmapAddColor(cmap, rarray[i], garray[i], barray[i]);
1768 narray[i] = index + 1;
1774 for (i = 0; i < h; i++) {
1775 lines = datas + i * wpls;
1776 lined = datad + i * wpld;
1777 for (j = 0; j < w; j++) {
1778 extractRGBValues(lines[j], &rval, &gval, &bval);
1779 octindex = rtab[rval] | gtab[gval] | btab[bval];
1792 L_WARNING(
"shouldn't get here\n", __func__);
1801 for (i = 0; i < size; i++) {
1802 if (narray[i] > 0) {
1804 opop->npix = (l_float32)narray[i];
1806 opop->rval = rarray[i];
1807 opop->gval = garray[i];
1808 opop->bval = barray[i];
1815 iarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1816 for (i = 0; i < 192; i++) {
1819 pixcmapAddColor(cmap, opop->rval, opop->gval, opop->bval);
1820 iarray[opop->index] = i + 1;
1823 lept_stderr(
"i = %d, n = %6.0f, (r,g,b) = (%d %d %d)\n",
1824 i, opop->npix, opop->rval, opop->gval, opop->bval);
1831 rtab2 = gtab2 = btab2 = NULL;
1833 for (i = 0; i < 64; i++) {
1844 for (i = 192; i < size; i++) {
1850 octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
1851 narray[octindex2] += (l_int32)opop->npix;
1852 rarray[octindex2] += (l_int32)opop->npix * rval;
1853 garray[octindex2] += (l_int32)opop->npix * gval;
1854 barray[octindex2] += (l_int32)opop->npix * bval;
1855 iarray[opop->index] = 192 + octindex2 + 1;
1858 lheapDestroy(&lh, TRUE);
1866 for (i = 0; i < size; i++) {
1867 if (iarray[i] == 0) {
1869 octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
1870 iarray[i] = 192 + octindex2 + 1;
1880 for (i = 0; i < 64; i++) {
1881 if (narray[i] > 0) {
1882 rarray[i] /= narray[i];
1883 garray[i] /= narray[i];
1884 barray[i] /= narray[i];
1888 pixcmapAddColor(cmap, rarray[i], garray[i], barray[i]);
1893 if (ditherflag == 0) {
1894 for (i = 0; i < h; i++) {
1895 lines = datas + i * wpls;
1896 lined = datad + i * wpld;
1897 for (j = 0; j < w; j++) {
1898 extractRGBValues(lines[j], &rval, &gval, &bval);
1899 octindex = rtab[rval] | gtab[gval] | btab[bval];
1905 iarray, POP_DIF_CAP);
1909 for (i = 0; i < size / 16; i++) {
1911 for (j = 0; j < 16; j++)
1912 lept_stderr(
"%d ", iarray[16 * i + j]);
1974l_uint8 *bufu8r, *bufu8g, *bufu8b;
1975l_int32 i, j, w, h, wpld, octindex, cmapindex, success;
1976l_int32 rval, gval, bval, rc, gc, bc;
1977l_int32 dif, val1, val2, val3;
1978l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
1979l_uint32 *datad, *lined;
1982 if (!pixs || pixGetDepth(pixs) != 32)
1983 return ERROR_INT(
"pixs undefined or not 32 bpp", __func__, 1);
1984 if (!pixd || pixGetDepth(pixd) != 8)
1985 return ERROR_INT(
"pixd undefined or not 8 bpp", __func__, 1);
1986 if ((cmap = pixGetColormap(pixd)) == NULL)
1987 return ERROR_INT(
"pixd not cmapped", __func__, 1);
1988 if (!rtab || !gtab || !btab || !indexmap)
1989 return ERROR_INT(
"not all 4 tables defined", __func__, 1);
1990 pixGetDimensions(pixs, &w, &h, NULL);
1991 if (pixGetWidth(pixd) != w || pixGetHeight(pixd) != h)
1992 return ERROR_INT(
"pixs and pixd not same size", __func__, 1);
1995 bufu8r = bufu8g = bufu8b = NULL;
1996 buf1r = buf1g = buf1b = buf2r = buf2g = buf2b = NULL;
1997 bufu8r = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1998 bufu8g = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1999 bufu8b = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
2000 buf1r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2001 buf1g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2002 buf1b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2003 buf2r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2004 buf2g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2005 buf2b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2006 if (!bufu8r || !bufu8g || !bufu8b || !buf1r || !buf1g ||
2007 !buf1b || !buf2r || !buf2g || !buf2b) {
2008 L_ERROR(
"buffer not made\n", __func__);
2010 goto buffer_cleanup;
2014 pixGetRGBLine(pixs, 0, bufu8r, bufu8g, bufu8b);
2015 for (j = 0; j < w; j++) {
2016 buf2r[j] = 64 * bufu8r[j];
2017 buf2g[j] = 64 * bufu8g[j];
2018 buf2b[j] = 64 * bufu8b[j];
2021 datad = pixGetData(pixd);
2022 wpld = pixGetWpl(pixd);
2023 for (i = 0; i < h - 1; i++) {
2025 memcpy(buf1r, buf2r, 4 * w);
2026 memcpy(buf1g, buf2g, 4 * w);
2027 memcpy(buf1b, buf2b, 4 * w);
2028 pixGetRGBLine(pixs, i + 1, bufu8r, bufu8g, bufu8b);
2029 for (j = 0; j < w; j++) {
2030 buf2r[j] = 64 * bufu8r[j];
2031 buf2g[j] = 64 * bufu8g[j];
2032 buf2b[j] = 64 * bufu8b[j];
2036 lined = datad + i * wpld;
2037 for (j = 0; j < w - 1; j++) {
2038 rval = buf1r[j] / 64;
2039 gval = buf1g[j] / 64;
2040 bval = buf1b[j] / 64;
2041 octindex = rtab[rval] | gtab[gval] | btab[bval];
2042 cmapindex = indexmap[octindex] - 1;
2044 pixcmapGetColor(cmap, cmapindex, &rc, &gc, &bc);
2046 dif = buf1r[j] / 8 - 8 * rc;
2048 if (dif > difcap) dif = difcap;
2049 if (dif < -difcap) dif = -difcap;
2052 val1 = buf1r[j + 1] + 3 * dif;
2053 val2 = buf2r[j] + 3 * dif;
2054 val3 = buf2r[j + 1] + 2 * dif;
2056 buf1r[j + 1] = L_MIN(16383, val1);
2057 buf2r[j] = L_MIN(16383, val2);
2058 buf2r[j + 1] = L_MIN(16383, val3);
2060 buf1r[j + 1] = L_MAX(0, val1);
2061 buf2r[j] = L_MAX(0, val2);
2062 buf2r[j + 1] = L_MAX(0, val3);
2066 dif = buf1g[j] / 8 - 8 * gc;
2068 if (dif > difcap) dif = difcap;
2069 if (dif < -difcap) dif = -difcap;
2072 val1 = buf1g[j + 1] + 3 * dif;
2073 val2 = buf2g[j] + 3 * dif;
2074 val3 = buf2g[j + 1] + 2 * dif;
2076 buf1g[j + 1] = L_MIN(16383, val1);
2077 buf2g[j] = L_MIN(16383, val2);
2078 buf2g[j + 1] = L_MIN(16383, val3);
2080 buf1g[j + 1] = L_MAX(0, val1);
2081 buf2g[j] = L_MAX(0, val2);
2082 buf2g[j + 1] = L_MAX(0, val3);
2086 dif = buf1b[j] / 8 - 8 * bc;
2088 if (dif > difcap) dif = difcap;
2089 if (dif < -difcap) dif = -difcap;
2092 val1 = buf1b[j + 1] + 3 * dif;
2093 val2 = buf2b[j] + 3 * dif;
2094 val3 = buf2b[j + 1] + 2 * dif;
2096 buf1b[j + 1] = L_MIN(16383, val1);
2097 buf2b[j] = L_MIN(16383, val2);
2098 buf2b[j + 1] = L_MIN(16383, val3);
2100 buf1b[j + 1] = L_MAX(0, val1);
2101 buf2b[j] = L_MAX(0, val2);
2102 buf2b[j + 1] = L_MAX(0, val3);
2108 rval = buf1r[w - 1] / 64;
2109 gval = buf1g[w - 1] / 64;
2110 bval = buf1b[w - 1] / 64;
2111 octindex = rtab[rval] | gtab[gval] | btab[bval];
2112 cmapindex = indexmap[octindex] - 1;
2117 lined = datad + (h - 1) * wpld;
2118 for (j = 0; j < w; j++) {
2119 rval = buf2r[j] / 64;
2120 gval = buf2g[j] / 64;
2121 bval = buf2b[j] / 64;
2122 octindex = rtab[rval] | gtab[gval] | btab[bval];
2123 cmapindex = indexmap[octindex] - 1;
2138 return (success) ? 0 : 1;
2239l_int32 w, h, minside, bpp, wpls, wpld, i, j, actualcolors;
2240l_int32 rval, gval, bval, nbase, nextra, maxlevel, ncubes, val;
2241l_int32 *lut1, *lut2;
2243l_uint32 *lines, *lined, *datas, *datad, *pspixel;
2244l_uint32 *rtab, *gtab, *btab;
2252 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
2253 if (pixGetDepth(pixs) != 32)
2254 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
2255 if (maxcolors < 8) {
2256 L_WARNING(
"max colors < 8; setting to 8\n", __func__);
2259 if (maxcolors > 256) {
2260 L_WARNING(
"max colors > 256; setting to 256\n", __func__);
2264 pixGetDimensions(pixs, &w, &h, NULL);
2265 datas = pixGetData(pixs);
2266 wpls = pixGetWpl(pixs);
2267 minside = L_MIN(w, h);
2268 if (subsample <= 0) {
2269 subsample = L_MAX(1, minside / 200);
2272 if (maxcolors <= 16) {
2274 pixd = pixCreate(w, h, bpp);
2278 nextra = maxcolors - nbase;
2279 }
else if (maxcolors <= 64) {
2281 pixd = pixCreate(w, h, bpp);
2285 nextra = maxcolors - nbase;
2288 pixd = pixCreate(w, h, bpp);
2292 nextra = maxcolors - nbase;
2295 pixCopyResolution(pixd, pixs);
2296 pixCopyInputFormat(pixd, pixs);
2305 if ((oqca = (
OQCELL **)LEPT_CALLOC(nbase,
sizeof(
OQCELL *))) == NULL) {
2307 return (
PIX *)ERROR_PTR(
"oqca not made", __func__, NULL);
2309 for (i = 0; i < nbase; i++) {
2314 rtab = gtab = btab = NULL;
2319 datad = pixGetData(pixd);
2320 wpld = pixGetWpl(pixd);
2321 for (i = 0; i < h; i++) {
2322 lines = datas + i * wpls;
2323 lined = datad + i * wpld;
2324 for (j = 0; j < w; j++) {
2325 pspixel = lines + j;
2326 extractRGBValues(*pspixel, &rval, &gval, &bval);
2328 rtab, gtab, btab, &index);
2335 oqca[index]->n += 1.0;
2336 oqca[index]->rcum += rval;
2337 oqca[index]->gcum += gval;
2338 oqca[index]->bcum += bval;
2344 cmap = pixcmapCreate(bpp);
2345 pixSetColormap(pixd, cmap);
2346 for (i = 0; i < nbase; i++) {
2349 oqc->rval = (l_int32)(oqc->rcum / oqc->n);
2350 oqc->gval = (l_int32)(oqc->gcum / oqc->n);
2351 oqc->bval = (l_int32)(oqc->bcum / oqc->n);
2354 &oqc->gval, &oqc->bval);
2356 pixcmapAddColor(cmap, oqc->rval, oqc->gval, oqc->bval);
2359 for (i = 0; i < nbase; i++)
2374 oqca = (
OQCELL **)LEPT_CALLOC(ncubes,
sizeof(
OQCELL *));
2375 for (i = 0; i < ncubes; i++) {
2382 rtab = gtab = btab = NULL;
2387 for (i = 0; i < h; i += subsample) {
2388 lines = datas + i * wpls;
2389 for (j = 0; j < w; j += subsample) {
2390 pspixel = lines + j;
2391 extractRGBValues(*pspixel, &rval, &gval, &bval);
2393 oqca[index]->n += 1.0;
2394 oqca[index]->octindex = index;
2395 oqca[index]->rcum += rval;
2396 oqca[index]->gcum += gval;
2397 oqca[index]->bcum += bval;
2403 for (i = 0; i < ncubes; i++)
2404 lheapAdd(lh, oqca[i]);
2408 oqca = (
OQCELL **)LEPT_CALLOC(maxcolors,
sizeof(
OQCELL *));
2409 for (i = 0; i < nbase; i++) {
2415 for (i = 0; i < nextra; i++) {
2416 oqc = (
OQCELL *)lheapRemove(lh);
2421 oqca[nbase + i] = oqc;
2425 lheapDestroy(&lh, TRUE);
2429 lut1 = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
2430 for (i = 0; i < nextra; i++)
2431 lut1[oqca[nbase + i]->octindex] = nbase + i;
2432 for (index = 0; index < ncubes; index++) {
2433 if (lut1[index] == 0)
2434 lut1[index] = index >> 3;
2440 datad = pixGetData(pixd);
2441 wpld = pixGetWpl(pixd);
2442 for (i = 0; i < h; i++) {
2443 lines = datas + i * wpls;
2444 lined = datad + i * wpld;
2445 for (j = 0; j < w; j++) {
2446 pspixel = lines + j;
2447 extractRGBValues(*pspixel, &rval, &gval, &bval);
2462 return (
PIX *)ERROR_PTR(
"bpp not 4 or 8!", __func__, NULL);
2465 oqca[val]->n += 1.0;
2466 oqca[val]->rcum += rval;
2467 oqca[val]->gcum += gval;
2468 oqca[val]->bcum += bval;
2475 lut2 = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
2476 cmap = pixcmapCreate(bpp);
2477 pixSetColormap(pixd, cmap);
2478 for (i = 0, index = 0; i < maxcolors; i++) {
2483 oqc->rval = (l_int32)(oqc->rcum / oqc->n);
2484 oqc->gval = (l_int32)(oqc->gcum / oqc->n);
2485 oqc->bval = (l_int32)(oqc->bcum / oqc->n);
2486 pixcmapAddColor(cmap, oqc->rval, oqc->gval, oqc->bval);
2490 actualcolors = pixcmapGetCount(cmap);
2495 if (actualcolors < maxcolors) {
2496 for (i = 0; i < h; i++) {
2497 lined = datad + i * wpld;
2498 for (j = 0; j < w; j++) {
2514 for (i = 0; i < maxcolors; i++)
2565l_int32 w, h, wpls, wpld, i, j, size, octlevels;
2566l_int32 rval, gval, bval, del, val, midval;
2567l_int32 *carray, *rarray, *garray, *barray;
2570l_uint32 *rtab, *gtab, *btab;
2571l_uint32 *lines, *lined, *datas, *datad;
2576 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
2577 if (pixGetDepth(pixs) != 32)
2578 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
2580 return (
PIX *)ERROR_PTR(
"invalid graylevels", __func__, NULL);
2585 return (
PIX *)ERROR_PTR(
"max 8 gray levels", __func__, NULL);
2586 }
else if (depth == 8) {
2589 if (graylevels > 192)
2590 return (
PIX *)ERROR_PTR(
"max 192 gray levels", __func__, NULL);
2592 return (
PIX *)ERROR_PTR(
"output depth not 4 or 8 bpp", __func__, NULL);
2598 rtab = gtab = btab = NULL;
2602 carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2603 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2604 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2605 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2608 tabval = makeGrayQuantIndexTable(graylevels);
2609 if (!rtab || !gtab || !btab ||
2610 !carray || !rarray || !garray || !barray || !tabval) {
2611 L_ERROR(
"calloc fail for an array\n", __func__);
2616 pixGetDimensions(pixs, &w, &h, NULL);
2617 if ((pixd = pixCreate(w, h, depth)) == NULL) {
2618 L_ERROR(
"pixd not made\n", __func__);
2621 pixCopyResolution(pixd, pixs);
2622 pixCopyInputFormat(pixd, pixs);
2623 cmap = pixcmapCreate(depth);
2624 for (j = 0; j < size; j++)
2625 pixcmapAddColor(cmap, 1, 1, 1);
2626 for (j = 0; j < graylevels; j++) {
2627 val = (255 * j) / (graylevels - 1);
2628 pixcmapAddColor(cmap, val, val, val);
2630 pixSetColormap(pixd, cmap);
2631 wpld = pixGetWpl(pixd);
2632 datad = pixGetData(pixd);
2636 datas = pixGetData(pixs);
2637 wpls = pixGetWpl(pixs);
2638 for (i = 0; i < h; i++) {
2639 lines = datas + i * wpls;
2640 lined = datad + i * wpld;
2641 for (j = 0; j < w; j++) {
2642 extractRGBValues(lines[j], &rval, &gval, &bval);
2647 }
else if (rval > bval) {
2658 }
else if (gval > bval) {
2667 octindex = rtab[rval] | gtab[gval] | btab[bval];
2669 rarray[octindex] += rval;
2670 garray[octindex] += gval;
2671 barray[octindex] += bval;
2677 val = size + tabval[midval];
2687 for (i = 0; i < size; i++) {
2688 if (carray[i] > 0) {
2689 rarray[i] /= carray[i];
2690 garray[i] /= carray[i];
2691 barray[i] /= carray[i];
2692 pixcmapResetColor(cmap, i, rarray[i], garray[i], barray[i]);
2781l_int32 rval, gval, bval;
2782l_int32 w, h, wpls, wpld, i, j, cindex;
2783l_uint32 *rtab, *gtab, *btab;
2785l_uint32 *datas, *datad, *lines, *lined;
2790 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
2791 if (pixGetDepth(pixs) != 32)
2792 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
2795 pixGetDimensions(pixs, &w, &h, NULL);
2796 if (w < MinDitherSize && h < MinDitherSize && ditherflag == 1) {
2797 L_INFO(
"Small image: dithering turned off\n", __func__);
2809 cmap = pixcmapCreate(8);
2810 for (cindex = 0; cindex < 256; cindex++) {
2811 rval = (cindex & 0xe0) | 0x10;
2812 gval = ((cindex << 3) & 0xe0) | 0x10;
2813 bval = ((cindex << 6) & 0xc0) | 0x20;
2814 pixcmapAddColor(cmap, rval, gval, bval);
2818 datas = pixGetData(pixs);
2819 wpls = pixGetWpl(pixs);
2820 if ((pixd = pixCreate(w, h, 8)) == NULL) {
2821 pixcmapDestroy(&cmap);
2822 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
2824 pixSetColormap(pixd, cmap);
2825 pixCopyResolution(pixd, pixs);
2826 pixCopyInputFormat(pixd, pixs);
2827 datad = pixGetData(pixd);
2828 wpld = pixGetWpl(pixd);
2831 if (ditherflag == 0) {
2832 for (i = 0; i < h; i++) {
2833 lines = datas + i * wpls;
2834 lined = datad + i * wpld;
2835 for (j = 0; j < w; j++) {
2836 extractRGBValues(lines[j], &rval, &gval, &bval);
2837 index = (rval & 0xe0) | ((gval >> 3) & 0x1c) | (bval >> 6);
2849 rtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2850 gtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2851 btab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2852 itab = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
2853 if (!rtab || !gtab || !btab || !itab) {
2855 return (
PIX *)ERROR_PTR(
"calloc fail for table", __func__, NULL);
2857 for (i = 0; i < 256; i++) {
2859 gtab[i] = (i >> 3) & 0x1c;
2912l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
2913l_int32 rval, gval, bval;
2914l_int32 *carray, *rarray, *garray, *barray;
2916l_uint32 *rtab, *gtab, *btab;
2917l_uint32 *lines, *lined, *datas, *datad, *pspixel;
2922 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
2923 if (pixGetDepth(pixs) != 32)
2924 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
2925 if (level < 1 || level > 6)
2926 return (
PIX *)ERROR_PTR(
"invalid level", __func__, NULL);
2931 return (
PIX *)ERROR_PTR(
"size not returned", __func__, NULL);
2932 rtab = gtab = btab = NULL;
2935 carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2936 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2937 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2938 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2939 if (!carray || !rarray || !garray || !barray) {
2940 L_ERROR(
"calloc fail for an array\n", __func__);
2945 pixGetDimensions(pixs, &w, &h, NULL);
2946 datas = pixGetData(pixs);
2947 wpls = pixGetWpl(pixs);
2948 for (i = 0; i < h; i++) {
2949 lines = datas + i * wpls;
2950 for (j = 0; j < w; j++) {
2951 pspixel = lines + j;
2952 extractRGBValues(*pspixel, &rval, &gval, &bval);
2953 octindex = rtab[rval] | gtab[gval] | btab[bval];
2955 rarray[octindex] += rval;
2956 garray[octindex] += gval;
2957 barray[octindex] += bval;
2962 for (i = 0, ncolors = 0; i < size; i++) {
2966 if (ncolors > 256) {
2967 L_WARNING(
"%d colors found; more than 256\n", __func__, ncolors);
2972 else if (ncolors <= 16)
2979 cmap = pixcmapCreate(depth);
2980 for (i = 0, index = 0; i < size; i++) {
2981 if (carray[i] > 0) {
2982 rarray[i] /= carray[i];
2983 garray[i] /= carray[i];
2984 barray[i] /= carray[i];
2985 pixcmapAddColor(cmap, rarray[i], garray[i], barray[i]);
2986 carray[i] = index + 1;
2991 pixd = pixCreate(w, h, depth);
2992 pixSetColormap(pixd, cmap);
2993 pixCopyResolution(pixd, pixs);
2994 pixCopyInputFormat(pixd, pixs);
2995 datad = pixGetData(pixd);
2996 wpld = pixGetWpl(pixd);
2997 for (i = 0; i < h; i++) {
2998 lines = datas + i * wpls;
2999 lined = datad + i * wpld;
3000 for (j = 0; j < w; j++) {
3001 pspixel = lines + j;
3002 extractRGBValues(*pspixel, &rval, &gval, &bval);
3003 octindex = rtab[rval] | gtab[gval] | btab[bval];
3016 L_WARNING(
"shouldn't get here\n", __func__);
3083l_int32 w, h, wpls, wpld, i, j, nerrors;
3084l_int32 ncubes, depth, cindex, oval;
3085l_int32 rval, gval, bval;
3086l_int32 *octarray = NULL;
3088l_uint32 *rtab, *gtab, *btab;
3089l_uint32 *lines, *lined, *datas, *datad, *ppixel;
3090l_uint32 *colorarray = NULL;
3095 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3096 if (pixGetDepth(pixs) != 32)
3097 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3098 if (level < 3 || level > 6)
3099 return (
PIX *)ERROR_PTR(
"level not in {4, 5, 6}", __func__, NULL);
3101 return (
PIX *)ERROR_PTR(
"ncolors > 256", __func__, NULL);
3109 rtab = gtab = btab = NULL;
3113 if ((ncubes = numaGetCount(na)) == 0) {
3114 L_ERROR(
"no slots in pixel occupation histogram", __func__);
3115 goto cleanup_arrays;
3117 octarray = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
3122 colorarray = (l_uint32 *)LEPT_CALLOC(ncolors + 1,
sizeof(l_uint32));
3123 if (!octarray || !colorarray) {
3124 L_ERROR(
"octarray or colorarray not made\n", __func__);
3125 goto cleanup_arrays;
3129 pixGetDimensions(pixs, &w, &h, NULL);
3130 datas = pixGetData(pixs);
3131 wpls = pixGetWpl(pixs);
3134 else if (ncolors <= 16)
3139 if ((pixd = pixCreate(w, h, depth)) == NULL) {
3140 L_ERROR(
"pixd not made\n", __func__);
3141 goto cleanup_arrays;
3143 pixCopyResolution(pixd, pixs);
3144 pixCopyInputFormat(pixd, pixs);
3145 datad = pixGetData(pixd);
3146 wpld = pixGetWpl(pixd);
3158 for (i = 0; i < h; i++) {
3159 lines = datas + i * wpls;
3160 lined = datad + i * wpld;
3161 for (j = 0; j < w; j++) {
3163 extractRGBValues(*ppixel, &rval, &gval, &bval);
3164 octindex = rtab[rval] | gtab[gval] | btab[bval];
3165 oval = octarray[octindex];
3167 octarray[octindex] = cindex;
3168 colorarray[cindex] = *ppixel;
3169 setPixelLow(lined, j, depth, cindex - 1);
3172 setPixelLow(lined, j, depth, oval - 1);
3173 if (colorarray[oval] != *ppixel)
3179 *pnerrors = nerrors;
3182 lept_stderr(
"ncubes = %d, ncolors = %d\n", ncubes, ncolors);
3183 for (i = 0; i < ncolors; i++)
3184 lept_stderr(
"color[%d] = %x\n", i, colorarray[i + 1]);
3188 cmap = pixcmapCreate(depth);
3189 for (i = 0; i < ncolors; i++) {
3190 ppixel = colorarray + i + 1;
3191 extractRGBValues(*ppixel, &rval, &gval, &bval);
3192 pixcmapAddColor(cmap, rval, gval, bval);
3194 pixSetColormap(pixd, cmap);
3197 LEPT_FREE(octarray);
3198 LEPT_FREE(colorarray);
3270 l_int32 lightthresh,
3275l_int32 i, j, w, h, wplc, wplm, wpld, ncolors, index;
3276l_int32 rval, gval, bval, val, minval, maxval;
3278l_uint32 *datac, *datam, *datad, *linec, *linem, *lined;
3279PIX *pix1, *pixc, *pixm, *pixg, *pixd;
3282 if (!pixs || pixGetDepth(pixs) != 32)
3283 return (
PIX *)ERROR_PTR(
"pixs undefined or not 32 bpp", __func__, NULL);
3284 if (level <= 0) level = 3;
3286 return (
PIX *)ERROR_PTR(
"invalid level", __func__, NULL);
3287 if (darkthresh <= 0) darkthresh = 20;
3288 if (lightthresh <= 0) lightthresh = 244;
3289 if (diffthresh <= 0) diffthresh = 20;
3290 if (minfract <= 0.0) minfract = 0.05f;
3291 if (maxspan <= 2) maxspan = 15;
3295 return (
PIX *)ERROR_PTR(
"too many colors", __func__, NULL);
3296 pixc = pixConvertTo8(pix1, 1);
3301 cmap = pixGetColormap(pixc);
3302 ncolors = pixcmapGetCount(cmap);
3303 cmapd = pixcmapCreate(8);
3304 lut = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
3305 for (i = 0; i < 256; i++)
3307 for (i = 0, index = 0; i < ncolors; i++) {
3308 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
3309 minval = L_MIN(rval, gval);
3310 minval = L_MIN(minval, bval);
3311 if (minval > lightthresh)
3313 maxval = L_MAX(rval, gval);
3314 maxval = L_MAX(maxval, bval);
3315 if (maxval < darkthresh)
3319 if (maxval - minval >= diffthresh) {
3320 pixcmapAddColor(cmapd, rval, gval, bval);
3329 pixGetDimensions(pixs, &w, &h, NULL);
3330 pixd = pixCreate(w, h, 8);
3331 pixSetColormap(pixd, cmapd);
3332 pixm = pixCreate(w, h, 1);
3333 datac = pixGetData(pixc);
3334 datam = pixGetData(pixm);
3335 datad = pixGetData(pixd);
3336 wplc = pixGetWpl(pixc);
3337 wplm = pixGetWpl(pixm);
3338 wpld = pixGetWpl(pixd);
3339 for (i = 0; i < h; i++) {
3340 linec = datac + i * wplc;
3341 linem = datam + i * wplm;
3342 lined = datad + i * wpld;
3343 for (j = 0; j < w; j++) {
3354 pixg = pixConvertTo8(pixs, 0);
3355 pixGrayQuantFromHisto(pixd, pixg, pixm, minfract, maxspan);
3388l_int32 w, h, wpls, wpld, i, j;
3389l_int32 rval, gval, bval;
3391l_uint32 *rtab, *gtab, *btab;
3392l_uint32 *lines, *lined, *datas, *datad;
3396 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3397 if (pixGetDepth(pixs) != 32)
3398 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3399 if (level < 1 || level > 6)
3400 return (
PIX *)ERROR_PTR(
"level not in {1,...6}", __func__, NULL);
3403 return (
PIX *)ERROR_PTR(
"tables not made", __func__, NULL);
3405 pixGetDimensions(pixs, &w, &h, NULL);
3406 pixd = pixCreate(w, h, 32);
3407 pixCopyResolution(pixd, pixs);
3408 pixCopyInputFormat(pixd, pixs);
3409 datad = pixGetData(pixd);
3410 wpld = pixGetWpl(pixd);
3411 datas = pixGetData(pixs);
3412 wpls = pixGetWpl(pixs);
3413 for (i = 0; i < h; i++) {
3414 lines = datas + i * wpls;
3415 lined = datad + i * wpld;
3416 for (j = 0; j < w; j++) {
3417 extractRGBValues(lines[j], &rval, &gval, &bval);
3418 octindex = rtab[rval] | gtab[gval] | btab[bval];
3420 composeRGBPixel(rval, gval, bval, lined + j);
3615l_int32 i, j, w, h, depth, wpls, wpld;
3616l_int32 rval, gval, bval, index;
3618l_uint32 *lines, *lined, *datas, *datad;
3623 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3624 if (pixGetDepth(pixs) != 32)
3625 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3627 return (
PIX *)ERROR_PTR(
"cmap not defined", __func__, NULL);
3628 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3629 return (
PIX *)ERROR_PTR(
"invalid mindepth", __func__, NULL);
3630 if (!rtab || !gtab || !btab || !cmaptab)
3631 return (
PIX *)ERROR_PTR(
"tables not all defined", __func__, NULL);
3634 pixcmapGetMinDepth(cmap, &depth);
3635 depth = L_MAX(depth, mindepth);
3636 pixGetDimensions(pixs, &w, &h, NULL);
3637 if ((pixd = pixCreate(w, h, depth)) == NULL)
3638 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
3639 cmapc = pixcmapCopy(cmap);
3640 pixSetColormap(pixd, cmapc);
3641 pixCopyResolution(pixd, pixs);
3642 pixCopyInputFormat(pixd, pixs);
3645 datas = pixGetData(pixs);
3646 datad = pixGetData(pixd);
3647 wpls = pixGetWpl(pixs);
3648 wpld = pixGetWpl(pixd);
3649 for (i = 0; i < h; i++) {
3650 lines = datas + i * wpls;
3651 lined = datad + i * wpld;
3652 for (j = 0; j < w; j++) {
3653 extractRGBValues(lines[j], &rval, &gval, &bval);
3658 index = cmaptab[octindex];
3661 else if (depth == 4)
3693l_int32 size, i, j, w, h, wpl, ncolors, val;
3694l_int32 rval, gval, bval;
3696l_uint32 *rtab, *gtab, *btab;
3697l_uint32 *data, *line;
3701 if (pncolors) *pncolors = 0;
3703 return (
NUMA *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3704 if (pixGetDepth(pixs) != 32)
3705 return (
NUMA *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3707 pixGetDimensions(pixs, &w, &h, NULL);
3708 wpl = pixGetWpl(pixs);
3709 data = pixGetData(pixs);
3712 return (
NUMA *)ERROR_PTR(
"size not returned", __func__, NULL);
3713 rtab = gtab = btab = NULL;
3716 if ((na = numaCreate(size)) == NULL) {
3717 L_ERROR(
"na not made\n", __func__);
3718 goto cleanup_arrays;
3720 numaSetCount(na, size);
3721 array = numaGetFArray(na,
L_NOCOPY);
3723 for (i = 0; i < h; i++) {
3724 line = data + i * wpl;
3725 for (j = 0; j < w; j++) {
3726 extractRGBValues(line[j], &rval, &gval, &bval);
3727 octindex = rtab[rval] | gtab[gval] | btab[bval];
3729 if ((level == 1 && octindex > 7) ||
3730 (level == 2 && octindex > 63) ||
3731 (level == 3 && octindex > 511) ||
3732 (level == 4 && octindex > 4097) ||
3733 (level == 5 && octindex > 32783) ||
3734 (level == 6 && octindex > 262271)) {
3735 lept_stderr(
"level = %d, octindex = %d, index error!\n",
3740 array[octindex] += 1.0;
3745 for (i = 0, ncolors = 0; i < size; i++) {
3746 numaGetIValue(na, i, &val);
3750 *pncolors = ncolors;
3814l_int32 i, k, size, ncolors, mindist, dist, mincolor, index;
3815l_int32 rval, gval, bval;
3816l_int32 *rmap, *gmap, *bmap, *tab;
3819 return (l_int32 *)ERROR_PTR(
"cmap not defined", __func__, NULL);
3820 if (level < 1 || level > 6)
3821 return (l_int32 *)ERROR_PTR(
"level not in {1...6}", __func__, NULL);
3823 return (l_int32 *)ERROR_PTR(
"invalid metric", __func__, NULL);
3826 return (l_int32 *)ERROR_PTR(
"size not returned", __func__, NULL);
3827 if ((tab = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL)
3828 return (l_int32 *)ERROR_PTR(
"tab not allocated", __func__, NULL);
3830 ncolors = pixcmapGetCount(cmap);
3831 pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL);
3834 for (i = 0; i < size; i++) {
3838 for (k = 0; k < ncolors; k++) {
3840 dist = L_ABS(rval - rmap[k]) + L_ABS(gval - gmap[k]) +
3841 L_ABS(bval - bmap[k]);
3843 dist = (rval - rmap[k]) * (rval - rmap[k]) +
3844 (gval - gmap[k]) * (gval - gmap[k]) +
3845 (bval - bmap[k]) * (bval - bmap[k]);
3847 if (dist < mindist) {
3858 pixcmapGetNearestIndex(cmap, 0, 0, 0, &index);
3859 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
3860 if (rval < 7 && gval < 7 && bval < 7) {
3863 pixcmapGetNearestIndex(cmap, 255, 255, 255, &index);
3864 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
3865 if (rval > 248 && gval > 248 && bval > 248) {
3866 tab[(1 << (3 * level)) - 1] = index;
3896l_int32 i, j, w, h, d, nc, wpls, val, newval, index, zerofound;
3897l_int32 rval, gval, bval;
3898l_uint32 *datas, *lines;
3899l_int32 *histo, *map1, *map2;
3903 return ERROR_INT(
"pixs not defined", __func__, 1);
3904 if ((cmap = pixGetColormap(pixs)) == NULL)
3907 d = pixGetDepth(pixs);
3908 if (d != 2 && d != 4 && d != 8)
3909 return ERROR_INT(
"d not in {2, 4, 8}", __func__, 1);
3912 nc = pixcmapGetCount(cmap);
3913 if ((histo = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32))) == NULL)
3914 return ERROR_INT(
"histo not made", __func__, 1);
3915 pixGetDimensions(pixs, &w, &h, NULL);
3916 wpls = pixGetWpl(pixs);
3917 datas = pixGetData(pixs);
3918 for (i = 0; i < h; i++) {
3919 lines = datas + i * wpls;
3920 for (j = 0; j < w; j++) {
3934 return ERROR_INT(
"switch ran off end!", __func__, 1);
3937 L_WARNING(
"cmap index out of bounds!\n", __func__);
3946 for (i = 0; i < nc; i++) {
3947 if (histo[i] == 0) {
3958 map1 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
3959 map2 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
3961 for (i = 0; i < nc; i++) {
3962 if (histo[i] != 0) {
3970 cmapd = pixcmapCreate(d);
3971 for (i = 0; i < index; i++) {
3972 pixcmapGetColor(cmap, map1[i], &rval, &gval, &bval);
3973 pixcmapAddColor(cmapd, rval, gval, bval);
3975 pixSetColormap(pixs, cmapd);
3978 for (i = 0; i < h; i++) {
3979 lines = datas + i * wpls;
3980 for (j = 0; j < w; j++) {
4002 return ERROR_INT(
"switch ran off end!", __func__, 1);
4044l_int32 i, j, w, h, d, wpl, ncolors, size, octindex;
4045l_int32 rval, gval, bval;
4047l_uint32 *data, *line, *rtab, *gtab, *btab;
4050 return ERROR_INT(
"&ncolors not defined", __func__, 1);
4053 return ERROR_INT(
"pix not defined", __func__, 1);
4054 pixGetDimensions(pix, &w, &h, &d);
4056 return ERROR_INT(
"pix not 32 bpp", __func__, 1);
4057 if (level < 1 || level > 6)
4058 return ERROR_INT(
"invalid level", __func__, 1);
4059 if ((mincount < 0 && minfract < 0) || (mincount >= 0.0 && minfract >= 0.0))
4060 return ERROR_INT(
"invalid mincount/minfract", __func__, 1);
4061 if (mincount == 0 || minfract == 0.0)
4063 else if (minfract > 0.0)
4064 mincount = L_MIN(1, (l_int32)(minfract * w * h));
4067 return ERROR_INT(
"size not returned", __func__, 1);
4068 rtab = gtab = btab = NULL;
4070 if ((carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL) {
4071 L_ERROR(
"carray not made\n", __func__);
4072 goto cleanup_arrays;
4076 data = pixGetData(pix);
4077 wpl = pixGetWpl(pix);
4078 for (i = 0; i < h; i++) {
4079 line = data + i * wpl;
4080 for (j = 0; j < w; j++) {
4081 extractRGBValues(line[j], &rval, &gval, &bval);
4082 octindex = rtab[rval] | gtab[gval] | btab[bval];
4088 for (i = 0, ncolors = 0; i < size; i++) {
4089 if (carray[i] >= mincount)
4092 *pncolors = ncolors;