118 #include <config_auto.h>
122 #include "allheaders.h"
173 static const l_int32 CqNLevels = 5;
174 static const l_int32 CqReservedColors = 64;
176 static const l_int32 ExtraReservedColors = 25;
177 static const l_int32 TreeGenWidth = 350;
178 static const l_int32 MinDitherSize = 250;
197 l_int32 rcum, gcum, bcum;
198 l_int32 rval, gval, bval;
229 static const l_int32 FIXED_DIF_CAP = 0;
230 static const l_int32 POP_DIF_CAP = 40;
235 l_int32 *pindex, l_int32 *prval,
236 l_int32 *pgval, l_int32 *pbval);
240 l_int32 reservedcolors,
249 l_int32 *prval, l_int32 *pgval, l_int32 *pbval);
251 l_int32 *pbindex, l_int32 *psindex);
256 l_uint32 *gtab, l_uint32 *btab,
257 l_int32 *carray, l_int32 difcap);
261 l_int32 mindepth, l_int32 *cmaptab,
262 l_uint32 *rtab, l_uint32 *gtab,
265 #ifndef NO_CONSOLE_IO
266 #define DEBUG_COLORQUANT 0
267 #define DEBUG_OCTINDEX 0
268 #define DEBUG_OCTCUBE_CMAP 0
270 #define DEBUG_FEW_COLORS 0
271 #define PRINT_OCTCUBE_STATS 0
541 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
542 if (pixGetDepth(pixs) != 32)
543 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
544 if (colors < 128 || colors > 240)
545 return (
PIX *)ERROR_PTR(
"colors must be in [128, 240]", __func__, NULL);
603 l_float32 validthresh,
604 l_float32 colorthresh)
606 l_int32 w, h, minside, factor, index, rval, gval, bval;
607 l_float32 scalefactor;
609 l_float32 colorfract;
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);
628 if (validthresh > 0.0 && colorthresh > 0.0) {
629 minside = L_MIN(w, h);
630 factor = L_MAX(1, minside / 400);
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);
640 L_INFO(
"\n Process in color by default\n", __func__);
644 if (w > TreeGenWidth) {
645 scalefactor = (l_float32)TreeGenWidth / (l_float32)w;
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);
683 pixCopyResolution(pixd, pixs);
684 pixCopyInputFormat(pixd, pixs);
689 if (rval < 5 && gval < 5 && bval < 5)
695 if (rval > 251 && gval > 251 && bval > 251)
723 l_int32 reservedcolors,
726 l_int32 rval, gval, bval, cindex;
727 l_int32 level, ncells, octindex;
734 l_float32 thresholdFactor[] = {0.01f, 0.01f, 1.0f, 1.0f, 1.0f, 1.0f};
736 l_uint32 *datas, *lines;
737 l_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;
767 ncolor = colors - reservedcolors - ExtraReservedColors;
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++) {
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;
817 L_ERROR(
"assigning pixels to wrong color\n", __func__);
819 cqcsub->index = cindex;
830 else if (ncolor + reservedcolors > 0)
831 ppc = npix / (ncolor + reservedcolors);
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;
868 L_WARNING(
"possibly assigned pixels to wrong color\n",
884 else if (ncolor + reservedcolors > 0)
885 ppc = npix / (ncolor + reservedcolors);
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
912 l_int32 tc[] = {0, 0, 0, 0, 0, 0, 0};
913 l_int32 rc[] = {0, 0, 0, 0, 0, 0, 0};
914 l_int32 nt, nr, ival;
918 for (i = 0; i < nt; i++) {
922 for (i = 0; i < nr; i++) {
927 for (i = 1; i < CqNLevels + 1; i++)
930 for (i = 0; i < CqNLevels ; i++)
973 l_uint8 *bufu8r, *bufu8g, *bufu8b;
974 l_int32 rval, gval, bval;
975 l_int32 octindex, index;
976 l_int32 val1, val2, val3, dif;
977 l_int32 w, h, wpls, wpld, i, j, success;
979 l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
980 l_uint32 *rtab, *gtab, *btab;
981 l_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);
994 wpls = pixGetWpl(pixs);
996 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
997 pixCopyResolution(pixd, pixs);
998 pixCopyInputFormat(pixd, pixs);
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++) {
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;
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);
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];
1191 l_int32 baseindex, subindex;
1195 for (level = 2; level < CqNLevels; level++) {
1197 cqc = cqcaa[level][baseindex];
1198 cqcsub = cqcaa[level + 1][subindex];
1199 if (cqcsub->bleaf == 0) {
1200 *pindex = cqc->index;
1205 }
else if (level == CqNLevels - 1) {
1206 *pindex = cqcsub->index;
1207 *prval = cqcsub->rc;
1208 *pgval = cqcsub->gc;
1209 *pbval = cqcsub->bc;
1216 for (level = 2; level < CqNLevels; level++) {
1219 cqc = cqcaa[level][baseindex];
1220 cqcsub = cqcaa[level + 1][subindex];
1221 if (cqcsub->bleaf == 0) {
1223 *pindex = cqc->index;
1228 }
else if (level == CqNLevels - 1) {
1230 *pindex = cqcsub->index;
1255 l_int32 level, ncells, i;
1260 cqcaa = (
CQCELL ***)LEPT_CALLOC(CqNLevels + 1,
sizeof(
CQCELL **));
1261 for (level = 0; level <= CqNLevels; level++) {
1262 ncells = 1 << (3 * level);
1263 cqca = (
CQCELL **)LEPT_CALLOC(ncells,
sizeof(
CQCELL *));
1264 cqcaa[level] = cqca;
1265 for (i = 0; i < ncells; i++) {
1282 l_int32 level, ncells, i;
1286 if (pcqcaa == NULL) {
1287 L_WARNING(
"ptr address is NULL\n", __func__);
1291 if ((cqcaa = *pcqcaa) == NULL)
1294 for (level = 0; level <= CqNLevels; level++) {
1295 cqca = cqcaa[level];
1296 ncells = 1 << (3 * level);
1297 for (i = 0; i < ncells; i++)
1348 l_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);
1457 *pindex = rtab[rval] | gtab[gval] | btab[bval];
1505 rgbindex = cubeindex << (3 * (7 - level));
1506 rgbindex |= (0x7 << (3 * (6 - level)));
1509 *prval = ((rgbindex >> 13) & 0x80) |
1510 ((rgbindex >> 11) & 0x40) |
1511 ((rgbindex >> 9) & 0x20) |
1512 ((rgbindex >> 7) & 0x10) |
1513 ((rgbindex >> 5) & 0x08) |
1514 ((rgbindex >> 3) & 0x04) |
1515 ((rgbindex >> 1) & 0x02);
1516 *pgval = ((rgbindex >> 12) & 0x80) |
1517 ((rgbindex >> 10) & 0x40) |
1518 ((rgbindex >> 8) & 0x20) |
1519 ((rgbindex >> 6) & 0x10) |
1520 ((rgbindex >> 4) & 0x08) |
1521 ((rgbindex >> 2) & 0x04) |
1523 *pbval = ((rgbindex >> 11) & 0x80) |
1524 ((rgbindex >> 9) & 0x40) |
1525 ((rgbindex >> 7) & 0x20) |
1526 ((rgbindex >> 5) & 0x10) |
1527 ((rgbindex >> 3) & 0x08) |
1528 ((rgbindex >> 1) & 0x04) |
1529 ((rgbindex << 1) & 0x02);
1577 if (level < 0 || level > CqNLevels - 1)
1578 return ERROR_INT(
"level must be in e.g., [0 ... 5]", __func__, 1);
1580 return ERROR_INT(
"&bindex not defined", __func__, 1);
1582 return ERROR_INT(
"&sindex not defined", __func__, 1);
1584 *pbindex = rgbindex >> (3 * (CqNLevels - level));
1585 *psindex = rgbindex >> (3 * (CqNLevels - 1 - level));
1608 return ERROR_INT(
"&size not defined", __func__, 1);
1609 if (level < 1 || level > 6)
1610 return ERROR_INT(
"invalid level", __func__, 1);
1612 *psize = 1 << (3 * level);
1680 l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
1681 l_int32 rval, gval, bval;
1682 l_int32 *rarray, *garray, *barray, *narray, *iarray;
1683 l_uint32 octindex, octindex2;
1684 l_uint32 *rtab, *gtab, *btab, *rtab2, *gtab2, *btab2;
1685 l_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);
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)
1721 wpls = pixGetWpl(pixs);
1722 for (i = 0; i < h; i++) {
1723 lines = datas + i * wpls;
1724 for (j = 0; j < w; j++) {
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)
1747 wpld = pixGetWpl(pixd);
1748 pixCopyResolution(pixd, pixs);
1749 pixCopyInputFormat(pixd, pixs);
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) {
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++) {
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++) {
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;
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];
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++) {
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++)
1974 l_uint8 *bufu8r, *bufu8g, *bufu8b;
1975 l_int32 i, j, w, h, wpld, octindex, cmapindex, success;
1976 l_int32 rval, gval, bval, rc, gc, bc;
1977 l_int32 dif, val1, val2, val3;
1978 l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
1979 l_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);
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;
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];
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);
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;
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;
2239 l_int32 w, h, minside, bpp, wpls, wpld, i, j, actualcolors;
2240 l_int32 rval, gval, bval, nbase, nextra, maxlevel, ncubes, val;
2241 l_int32 *lut1, *lut2;
2243 l_uint32 *lines, *lined, *datas, *datad, *pspixel;
2244 l_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__);
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) {
2278 nextra = maxcolors - nbase;
2279 }
else if (maxcolors <= 64) {
2285 nextra = maxcolors - nbase;
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;
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;
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;
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);
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;
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++)
2408 oqca = (
OQCELL **)LEPT_CALLOC(maxcolors,
sizeof(
OQCELL *));
2409 for (i = 0; i < nbase; i++) {
2415 for (i = 0; i < nextra; i++) {
2421 oqca[nbase + i] = oqc;
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;
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;
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));
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);
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++)
2565 l_int32 w, h, wpls, wpld, i, j, size, octlevels;
2566 l_int32 rval, gval, bval, del, val, midval;
2567 l_int32 *carray, *rarray, *garray, *barray;
2570 l_uint32 *rtab, *gtab, *btab;
2571 l_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));
2609 if (!rtab || !gtab || !btab ||
2610 !carray || !rarray || !garray || !barray || !tabval) {
2611 L_ERROR(
"calloc fail for an array\n", __func__);
2617 if ((pixd =
pixCreate(w, h, depth)) == NULL) {
2618 L_ERROR(
"pixd not made\n", __func__);
2621 pixCopyResolution(pixd, pixs);
2622 pixCopyInputFormat(pixd, pixs);
2624 for (j = 0; j < size; j++)
2626 for (j = 0; j < graylevels; j++) {
2627 val = (255 * j) / (graylevels - 1);
2631 wpld = pixGetWpl(pixd);
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++) {
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];
2781 l_int32 rval, gval, bval;
2782 l_int32 w, h, wpls, wpld, i, j, cindex;
2783 l_uint32 *rtab, *gtab, *btab;
2785 l_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);
2796 if (w < MinDitherSize && h < MinDitherSize && ditherflag == 1) {
2797 L_INFO(
"Small image: dithering turned off\n", __func__);
2810 for (cindex = 0; cindex < 256; cindex++) {
2811 rval = (cindex & 0xe0) | 0x10;
2812 gval = ((cindex << 3) & 0xe0) | 0x10;
2813 bval = ((cindex << 6) & 0xc0) | 0x20;
2819 wpls = pixGetWpl(pixs);
2820 if ((pixd =
pixCreate(w, h, 8)) == NULL) {
2822 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
2825 pixCopyResolution(pixd, pixs);
2826 pixCopyInputFormat(pixd, pixs);
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++) {
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;
2912 l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
2913 l_int32 rval, gval, bval;
2914 l_int32 *carray, *rarray, *garray, *barray;
2916 l_uint32 *rtab, *gtab, *btab;
2917 l_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__);
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;
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)
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];
2986 carray[i] = index + 1;
2993 pixCopyResolution(pixd, pixs);
2994 pixCopyInputFormat(pixd, pixs);
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;
3003 octindex = rtab[rval] | gtab[gval] | btab[bval];
3016 L_WARNING(
"shouldn't get here\n", __func__);
3083 l_int32 w, h, wpls, wpld, i, j, nerrors;
3084 l_int32 ncubes, depth, cindex, oval;
3085 l_int32 rval, gval, bval;
3088 l_uint32 *rtab, *gtab, *btab;
3089 l_uint32 *lines, *lined, *datas, *datad, *ppixel;
3090 l_uint32 *colorarray;
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;
3114 octarray = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
3119 colorarray = (l_uint32 *)LEPT_CALLOC(ncolors + 1,
sizeof(l_uint32));
3120 if (!octarray || !colorarray) {
3121 L_ERROR(
"octarray or colorarray not made\n", __func__);
3122 goto cleanup_arrays;
3128 wpls = pixGetWpl(pixs);
3131 else if (ncolors <= 16)
3136 if ((pixd =
pixCreate(w, h, depth)) == NULL) {
3137 L_ERROR(
"pixd not made\n", __func__);
3138 goto cleanup_arrays;
3140 pixCopyResolution(pixd, pixs);
3141 pixCopyInputFormat(pixd, pixs);
3143 wpld = pixGetWpl(pixd);
3155 for (i = 0; i < h; i++) {
3156 lines = datas + i * wpls;
3157 lined = datad + i * wpld;
3158 for (j = 0; j < w; j++) {
3161 octindex = rtab[rval] | gtab[gval] | btab[bval];
3162 oval = octarray[octindex];
3164 octarray[octindex] = cindex;
3165 colorarray[cindex] = *ppixel;
3170 if (colorarray[oval] != *ppixel)
3176 *pnerrors = nerrors;
3178 #if DEBUG_FEW_COLORS
3179 lept_stderr(
"ncubes = %d, ncolors = %d\n", ncubes, ncolors);
3180 for (i = 0; i < ncolors; i++)
3181 lept_stderr(
"color[%d] = %x\n", i, colorarray[i + 1]);
3186 for (i = 0; i < ncolors; i++) {
3187 ppixel = colorarray + i + 1;
3194 LEPT_FREE(octarray);
3195 LEPT_FREE(colorarray);
3267 l_int32 lightthresh,
3272 l_int32 i, j, w, h, wplc, wplm, wpld, ncolors, index;
3273 l_int32 rval, gval, bval, val, minval, maxval;
3275 l_uint32 *datac, *datam, *datad, *linec, *linem, *lined;
3276 PIX *pix1, *pixc, *pixm, *pixg, *pixd;
3279 if (!pixs || pixGetDepth(pixs) != 32)
3280 return (
PIX *)ERROR_PTR(
"pixs undefined or not 32 bpp", __func__, NULL);
3281 if (level <= 0) level = 3;
3283 return (
PIX *)ERROR_PTR(
"invalid level", __func__, NULL);
3284 if (darkthresh <= 0) darkthresh = 20;
3285 if (lightthresh <= 0) lightthresh = 244;
3286 if (diffthresh <= 0) diffthresh = 20;
3287 if (minfract <= 0.0) minfract = 0.05;
3288 if (maxspan <= 2) maxspan = 15;
3292 return (
PIX *)ERROR_PTR(
"too many colors", __func__, NULL);
3298 cmap = pixGetColormap(pixc);
3301 lut = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
3302 for (i = 0; i < 256; i++)
3304 for (i = 0, index = 0; i < ncolors; i++) {
3306 minval = L_MIN(rval, gval);
3307 minval = L_MIN(minval, bval);
3308 if (minval > lightthresh)
3310 maxval = L_MAX(rval, gval);
3311 maxval = L_MAX(maxval, bval);
3312 if (maxval < darkthresh)
3316 if (maxval - minval >= diffthresh) {
3333 wplc = pixGetWpl(pixc);
3334 wplm = pixGetWpl(pixm);
3335 wpld = pixGetWpl(pixd);
3336 for (i = 0; i < h; i++) {
3337 linec = datac + i * wplc;
3338 linem = datam + i * wplm;
3339 lined = datad + i * wpld;
3340 for (j = 0; j < w; j++) {
3385 l_int32 w, h, wpls, wpld, i, j;
3386 l_int32 rval, gval, bval;
3388 l_uint32 *rtab, *gtab, *btab;
3389 l_uint32 *lines, *lined, *datas, *datad;
3393 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3394 if (pixGetDepth(pixs) != 32)
3395 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3396 if (level < 1 || level > 6)
3397 return (
PIX *)ERROR_PTR(
"level not in {1,...6}", __func__, NULL);
3400 return (
PIX *)ERROR_PTR(
"tables not made", __func__, NULL);
3404 pixCopyResolution(pixd, pixs);
3405 pixCopyInputFormat(pixd, pixs);
3407 wpld = pixGetWpl(pixd);
3409 wpls = pixGetWpl(pixs);
3410 for (i = 0; i < h; i++) {
3411 lines = datas + i * wpls;
3412 lined = datad + i * wpld;
3413 for (j = 0; j < w; j++) {
3415 octindex = rtab[rval] | gtab[gval] | btab[bval];
3462 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3463 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3464 return (
PIX *)ERROR_PTR(
"invalid mindepth", __func__, NULL);
3465 d = pixGetDepth(pixs);
3472 return (
PIX *)ERROR_PTR(
"d not 8 or 32 bpp", __func__, NULL);
3547 l_uint32 *rtab, *gtab, *btab;
3551 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3552 if (pixGetDepth(pixs) != 32)
3553 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3555 return (
PIX *)ERROR_PTR(
"cmap not defined", __func__, NULL);
3556 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3557 return (
PIX *)ERROR_PTR(
"invalid mindepth", __func__, NULL);
3558 if (level < 1 || level > 6)
3559 return (
PIX *)ERROR_PTR(
"level not in {1...6}", __func__, NULL);
3561 return (
PIX *)ERROR_PTR(
"invalid metric", __func__, NULL);
3564 rtab = gtab = btab = NULL;
3569 cmaptab, rtab, gtab, btab);
3612 l_int32 i, j, w, h, depth, wpls, wpld;
3613 l_int32 rval, gval, bval, index;
3615 l_uint32 *lines, *lined, *datas, *datad;
3620 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3621 if (pixGetDepth(pixs) != 32)
3622 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3624 return (
PIX *)ERROR_PTR(
"cmap not defined", __func__, NULL);
3625 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3626 return (
PIX *)ERROR_PTR(
"invalid mindepth", __func__, NULL);
3627 if (!rtab || !gtab || !btab || !cmaptab)
3628 return (
PIX *)ERROR_PTR(
"tables not all defined", __func__, NULL);
3632 depth = L_MAX(depth, mindepth);
3634 if ((pixd =
pixCreate(w, h, depth)) == NULL)
3635 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
3638 pixCopyResolution(pixd, pixs);
3639 pixCopyInputFormat(pixd, pixs);
3644 wpls = pixGetWpl(pixs);
3645 wpld = pixGetWpl(pixd);
3646 for (i = 0; i < h; i++) {
3647 lines = datas + i * wpls;
3648 lined = datad + i * wpld;
3649 for (j = 0; j < w; j++) {
3655 index = cmaptab[octindex];
3658 else if (depth == 4)
3690 l_int32 size, i, j, w, h, wpl, ncolors, val;
3691 l_int32 rval, gval, bval;
3693 l_uint32 *rtab, *gtab, *btab;
3694 l_uint32 *data, *line;
3698 if (pncolors) *pncolors = 0;
3700 return (
NUMA *)ERROR_PTR(
"pixs not defined", __func__, NULL);
3701 if (pixGetDepth(pixs) != 32)
3702 return (
NUMA *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
3705 wpl = pixGetWpl(pixs);
3709 return (
NUMA *)ERROR_PTR(
"size not returned", __func__, NULL);
3710 rtab = gtab = btab = NULL;
3714 L_ERROR(
"na not made\n", __func__);
3715 goto cleanup_arrays;
3720 for (i = 0; i < h; i++) {
3721 line = data + i * wpl;
3722 for (j = 0; j < w; j++) {
3724 octindex = rtab[rval] | gtab[gval] | btab[bval];
3726 if ((level == 1 && octindex > 7) ||
3727 (level == 2 && octindex > 63) ||
3728 (level == 3 && octindex > 511) ||
3729 (level == 4 && octindex > 4097) ||
3730 (level == 5 && octindex > 32783) ||
3731 (level == 6 && octindex > 262271)) {
3732 lept_stderr(
"level = %d, octindex = %d, index error!\n",
3737 array[octindex] += 1.0;
3742 for (i = 0, ncolors = 0; i < size; i++) {
3747 *pncolors = ncolors;
3811 l_int32 i, k, size, ncolors, mindist, dist, mincolor, index;
3812 l_int32 rval, gval, bval;
3813 l_int32 *rmap, *gmap, *bmap, *tab;
3816 return (l_int32 *)ERROR_PTR(
"cmap not defined", __func__, NULL);
3817 if (level < 1 || level > 6)
3818 return (l_int32 *)ERROR_PTR(
"level not in {1...6}", __func__, NULL);
3820 return (l_int32 *)ERROR_PTR(
"invalid metric", __func__, NULL);
3823 return (l_int32 *)ERROR_PTR(
"size not returned", __func__, NULL);
3824 if ((tab = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL)
3825 return (l_int32 *)ERROR_PTR(
"tab not allocated", __func__, NULL);
3831 for (i = 0; i < size; i++) {
3835 for (k = 0; k < ncolors; k++) {
3837 dist = L_ABS(rval - rmap[k]) + L_ABS(gval - gmap[k]) +
3838 L_ABS(bval - bmap[k]);
3840 dist = (rval - rmap[k]) * (rval - rmap[k]) +
3841 (gval - gmap[k]) * (gval - gmap[k]) +
3842 (bval - bmap[k]) * (bval - bmap[k]);
3844 if (dist < mindist) {
3857 if (rval < 7 && gval < 7 && bval < 7) {
3862 if (rval > 248 && gval > 248 && bval > 248) {
3863 tab[(1 << (3 * level)) - 1] = index;
3893 l_int32 i, j, w, h, d, nc, wpls, val, newval, index, zerofound;
3894 l_int32 rval, gval, bval;
3895 l_uint32 *datas, *lines;
3896 l_int32 *histo, *map1, *map2;
3900 return ERROR_INT(
"pixs not defined", __func__, 1);
3901 if ((cmap = pixGetColormap(pixs)) == NULL)
3904 d = pixGetDepth(pixs);
3905 if (d != 2 && d != 4 && d != 8)
3906 return ERROR_INT(
"d not in {2, 4, 8}", __func__, 1);
3910 if ((histo = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32))) == NULL)
3911 return ERROR_INT(
"histo not made", __func__, 1);
3913 wpls = pixGetWpl(pixs);
3915 for (i = 0; i < h; i++) {
3916 lines = datas + i * wpls;
3917 for (j = 0; j < w; j++) {
3931 return ERROR_INT(
"switch ran off end!", __func__, 1);
3934 L_WARNING(
"cmap index out of bounds!\n", __func__);
3943 for (i = 0; i < nc; i++) {
3944 if (histo[i] == 0) {
3955 map1 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
3956 map2 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
3958 for (i = 0; i < nc; i++) {
3959 if (histo[i] != 0) {
3968 for (i = 0; i < index; i++) {
3975 for (i = 0; i < h; i++) {
3976 lines = datas + i * wpls;
3977 for (j = 0; j < w; j++) {
3999 return ERROR_INT(
"switch ran off end!", __func__, 1);
4041 l_int32 i, j, w, h, d, wpl, ncolors, size, octindex;
4042 l_int32 rval, gval, bval;
4044 l_uint32 *data, *line, *rtab, *gtab, *btab;
4047 return ERROR_INT(
"&ncolors not defined", __func__, 1);
4050 return ERROR_INT(
"pix not defined", __func__, 1);
4053 return ERROR_INT(
"pix not 32 bpp", __func__, 1);
4054 if (level < 1 || level > 6)
4055 return ERROR_INT(
"invalid level", __func__, 1);
4056 if ((mincount < 0 && minfract < 0) || (mincount >= 0.0 && minfract >= 0.0))
4057 return ERROR_INT(
"invalid mincount/minfract", __func__, 1);
4058 if (mincount == 0 || minfract == 0.0)
4060 else if (minfract > 0.0)
4061 mincount = L_MIN(1, (l_int32)(minfract * w * h));
4064 return ERROR_INT(
"size not returned", __func__, 1);
4065 rtab = gtab = btab = NULL;
4067 if ((carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL) {
4068 L_ERROR(
"carray not made\n", __func__);
4069 goto cleanup_arrays;
4074 wpl = pixGetWpl(pix);
4075 for (i = 0; i < h; i++) {
4076 line = data + i * wpl;
4077 for (j = 0; j < w; j++) {
4079 octindex = rtab[rval] | gtab[gval] | btab[bval];
4085 for (i = 0, ncolors = 0; i < size; i++) {
4086 if (carray[i] >= mincount)
4089 *pncolors = ncolors;
#define GET_DATA_QBIT(pdata, n)
#define SET_DATA_BIT(pdata, n)
#define SET_DATA_DIBIT(pdata, n, val)
#define GET_DATA_BYTE(pdata, n)
#define GET_DATA_DIBIT(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
#define SET_DATA_QBIT(pdata, n, val)
l_ok pixColorFraction(PIX *pixs, l_int32 darkthresh, l_int32 lightthresh, l_int32 diffthresh, l_int32 factor, l_float32 *ppixfract, l_float32 *pcolorfract)
pixColorFraction()
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
l_ok pixcmapGetNearestIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetNearestIndex()
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
l_ok pixcmapGetMinDepth(PIXCMAP *cmap, l_int32 *pmindepth)
pixcmapGetMinDepth()
l_ok pixcmapGetRankIntensity(PIXCMAP *cmap, l_float32 rankval, l_int32 *pindex)
pixcmapGetRankIntensity()
l_ok pixcmapToArrays(const PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
PIXCMAP * pixcmapCopy(const PIXCMAP *cmaps)
pixcmapCopy()
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
static void getRGBFromOctcube(l_int32 cubeindex, l_int32 level, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
getRGBFromOctcube()
static l_int32 octreeFindColorCell(l_int32 octindex, CQCELL ***cqcaa, l_int32 *pindex, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
octreeFindColorCell()
PIX * pixFewColorsOctcubeQuant1(PIX *pixs, l_int32 level)
pixFewColorsOctcubeQuant1()
PIX * pixOctreeQuantByPopulation(PIX *pixs, l_int32 level, l_int32 ditherflag)
pixOctreeQuantByPopulation()
l_ok makeRGBToIndexTables(l_int32 cqlevels, l_uint32 **prtab, l_uint32 **pgtab, l_uint32 **pbtab)
makeRGBToIndexTables()
PIX * pixFixedOctcubeQuantGenRGB(PIX *pixs, l_int32 level)
pixFixedOctcubeQuantGenRGB()
NUMA * pixOctcubeHistogram(PIX *pixs, l_int32 level, l_int32 *pncolors)
pixOctcubeHistogram()
PIX * pixOctreeColorQuant(PIX *pixs, l_int32 colors, l_int32 ditherflag)
pixOctreeColorQuant()
l_int32 * pixcmapToOctcubeLUT(PIXCMAP *cmap, l_int32 level, l_int32 metric)
pixcmapToOctcubeLUT()
PIX * pixFewColorsOctcubeQuant2(PIX *pixs, l_int32 level, NUMA *na, l_int32 ncolors, l_int32 *pnerrors)
pixFewColorsOctcubeQuant2()
PIX * pixOctreeColorQuantGeneral(PIX *pixs, l_int32 colors, l_int32 ditherflag, l_float32 validthresh, l_float32 colorthresh)
pixOctreeColorQuantGeneral()
static void cqcellTreeDestroy(CQCELL ****pcqcaa)
cqcellTreeDestroy()
PIX * pixQuantFromCmap(PIX *pixs, PIXCMAP *cmap, l_int32 mindepth, l_int32 level, l_int32 metric)
pixQuantFromCmap()
l_ok pixRemoveUnusedColors(PIX *pixs)
pixRemoveUnusedColors()
static CQCELL *** cqcellTreeCreate(void)
cqcellTreeCreate()
PIX * pixOctcubeQuantFromCmap(PIX *pixs, PIXCMAP *cmap, l_int32 mindepth, l_int32 level, l_int32 metric)
pixOctcubeQuantFromCmap()
static l_int32 getOctcubeIndices(l_int32 rgbindex, l_int32 level, l_int32 *pbindex, l_int32 *psindex)
getOctcubeIndices()
PIX * pixFewColorsOctcubeQuantMixed(PIX *pixs, l_int32 level, l_int32 darkthresh, l_int32 lightthresh, l_int32 diffthresh, l_float32 minfract, l_int32 maxspan)
pixFewColorsOctcubeQuantMixed()
PIX * pixOctcubeQuantMixedWithGray(PIX *pixs, l_int32 depth, l_int32 graylevels, l_int32 delta)
pixOctcubeQuantMixedWithGray()
static CQCELL *** octreeGenerateAndPrune(PIX *pixs, l_int32 colors, l_int32 reservedcolors, PIXCMAP **pcmap)
octreeGenerateAndPrune()
static l_int32 pixDitherOctindexWithCmap(PIX *pixs, PIX *pixd, l_uint32 *rtab, l_uint32 *gtab, l_uint32 *btab, l_int32 *carray, l_int32 difcap)
pixDitherOctindexWithCmap()
PIX * pixFixedOctcubeQuant256(PIX *pixs, l_int32 ditherflag)
pixFixedOctcubeQuant256()
static PIX * pixOctcubeQuantFromCmapLUT(PIX *pixs, PIXCMAP *cmap, l_int32 mindepth, l_int32 *cmaptab, l_uint32 *rtab, l_uint32 *gtab, l_uint32 *btab)
pixOctcubeQuantFromCmapLUT()
l_ok pixNumberOccupiedOctcubes(PIX *pix, l_int32 level, l_int32 mincount, l_float32 minfract, l_int32 *pncolors)
pixNumberOccupiedOctcubes()
static l_int32 octcubeGetCount(l_int32 level, l_int32 *psize)
octcubeGetCount()
void getOctcubeIndexFromRGB(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *rtab, l_uint32 *gtab, l_uint32 *btab, l_uint32 *pindex)
getOctcubeIndexFromRGB()
PIX * pixOctreeQuantNumColors(PIX *pixs, l_int32 maxcolors, l_int32 subsample)
pixOctreeQuantNumColors()
static PIX * pixOctreeQuantizePixels(PIX *pixs, CQCELL ***cqcaa, l_int32 ditherflag)
pixOctreeQuantizePixels()
PIX * pixGrayQuantFromCmap(PIX *pixs, PIXCMAP *cmap, l_int32 mindepth)
pixGrayQuantFromCmap()
l_int32 * makeGrayQuantIndexTable(l_int32 nlevels)
makeGrayQuantIndexTable()
PIX * pixGrayQuantFromHisto(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 minfract, l_int32 maxsize)
pixGrayQuantFromHisto()
void lheapDestroy(L_HEAP **plh, l_int32 freeflag)
lheapDestroy()
L_HEAP * lheapCreate(l_int32 n, l_int32 direction)
lheapCreate()
l_ok lheapAdd(L_HEAP *lh, void *item)
lheapAdd()
void * lheapRemove(L_HEAP *lh)
lheapRemove()
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
NUMA * numaCreate(l_int32 n)
numaCreate()
l_ok numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
void numaDestroy(NUMA **pna)
numaDestroy()
l_int32 numaGetCount(NUMA *na)
numaGetCount()
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
PIX * pixClone(PIX *pixs)
pixClone()
l_ok pixGetRGBLine(PIX *pixs, l_int32 row, l_uint8 *bufr, l_uint8 *bufg, l_uint8 *bufb)
pixGetRGBLine()
void setPixelLow(l_uint32 *line, l_int32 x, l_int32 depth, l_uint32 val)
setPixelLow()
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
void lept_stderr(const char *fmt,...)
lept_stderr()