118 #include <config_auto.h>
122 #include "allheaders.h"
172 static const l_int32 CqNLevels = 5;
173 static const l_int32 CqReservedColors = 64;
175 static const l_int32 ExtraReservedColors = 25;
176 static const l_int32 TreeGenWidth = 350;
177 static const l_int32 MinDitherSize = 250;
196 l_int32 rcum, gcum, bcum;
197 l_int32 rval, gval, bval;
228 static const l_int32 FIXED_DIF_CAP = 0;
229 static const l_int32 POP_DIF_CAP = 40;
234 l_int32 *pindex, l_int32 *prval,
235 l_int32 *pgval, l_int32 *pbval);
239 l_int32 reservedcolors,
248 l_int32 *prval, l_int32 *pgval, l_int32 *pbval);
250 l_int32 *pbindex, l_int32 *psindex);
255 l_uint32 *gtab, l_uint32 *btab,
256 l_int32 *carray, l_int32 difcap);
260 l_int32 mindepth, l_int32 *cmaptab,
261 l_uint32 *rtab, l_uint32 *gtab,
264 #ifndef NO_CONSOLE_IO
265 #define DEBUG_COLORQUANT 0
266 #define DEBUG_OCTINDEX 0
267 #define DEBUG_OCTCUBE_CMAP 0
269 #define DEBUG_FEW_COLORS 0
270 #define PRINT_OCTCUBE_STATS 0
539 PROCNAME(
"pixOctreeColorQuant");
542 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
543 if (pixGetDepth(pixs) != 32)
544 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
545 if (colors < 128 || colors > 240)
546 return (
PIX *)ERROR_PTR(
"colors must be in [128, 240]", procName, NULL);
604 l_float32 validthresh,
605 l_float32 colorthresh)
607 l_int32 w, h, minside, factor, index, rval, gval, bval;
608 l_float32 scalefactor;
610 l_float32 colorfract;
615 PROCNAME(
"pixOctreeColorQuantGeneral");
618 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
619 if (pixGetDepth(pixs) != 32)
620 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
621 if (colors < 128 || colors > 240)
622 return (
PIX *)ERROR_PTR(
"colors must be in [128, 240]", procName, NULL);
631 if (validthresh > 0.0 && colorthresh > 0.0) {
632 minside = L_MIN(w, h);
633 factor = L_MAX(1, minside / 400);
635 if (pixfract * colorfract < validthresh * colorthresh) {
636 L_INFO(
"\n Pixel fraction neither white nor black = %6.3f"
637 "\n Color fraction of those pixels = %6.3f"
638 "\n Quantizing to 8 bpp gray\n",
639 procName, pixfract, colorfract);
643 L_INFO(
"\n Process in color by default\n", procName);
647 if (w > TreeGenWidth) {
648 scalefactor = (l_float32)TreeGenWidth / (l_float32)w;
655 if (w < MinDitherSize && h < MinDitherSize)
656 colors = L_MIN(colors, 220);
662 return (
PIX *)ERROR_PTR(
"tree not made", procName, NULL);
665 L_INFO(
" Colors requested = %d\n", procName, colors);
666 L_INFO(
" Actual colors = %d\n", procName, cmap->
n);
670 if (w < MinDitherSize && h < MinDitherSize && ditherflag == 1) {
671 L_INFO(
"Small image: dithering turned off\n", procName);
681 return (
PIX *)ERROR_PTR(
"pixd not made", procName, NULL);
686 pixCopyResolution(pixd, pixs);
687 pixCopyInputFormat(pixd, pixs);
692 if (rval < 5 && gval < 5 && bval < 5)
698 if (rval > 251 && gval > 251 && bval > 251)
726 l_int32 reservedcolors,
729 l_int32 rval, gval, bval, cindex;
730 l_int32 level, ncells, octindex;
737 l_float32 thresholdFactor[] = {0.01f, 0.01f, 1.0f, 1.0f, 1.0f, 1.0f};
739 l_uint32 *datas, *lines;
740 l_uint32 *rtab, *gtab, *btab;
748 PROCNAME(
"octreeGenerateAndPrune");
751 return (
CQCELL ***)ERROR_PTR(
"pixs not defined", procName, NULL);
752 if (pixGetDepth(pixs) != 32)
753 return (
CQCELL ***)ERROR_PTR(
"pixs must be 32 bpp", procName, NULL);
754 if (colors < 128 || colors > 256)
755 return (
CQCELL ***)ERROR_PTR(
"colors not in [128,256]", procName, NULL);
757 return (
CQCELL ***)ERROR_PTR(
"&cmap not defined", procName, NULL);
760 return (
CQCELL ***)ERROR_PTR(
"cqcaa not made", procName, NULL);
763 rtab = gtab = btab = NULL;
772 ncolor = colors - reservedcolors - ExtraReservedColors;
775 wpls = pixGetWpl(pixs);
778 ncells = 1 << (3 * CqNLevels);
779 cqca = cqcaa[CqNLevels];
780 for (i = 0; i < h; i++) {
781 lines = datas + i * wpls;
782 for (j = 0; j < w; j++) {
784 octindex = rtab[rval] | gtab[gval] | btab[bval];
785 cqc = cqca[octindex];
795 for (level = CqNLevels - 1; level >= 2; level--) {
796 thresh = thresholdFactor[level];
798 cqcasub = cqcaa[level + 1];
799 ncells = 1 << (3 * level);
800 for (i = 0; i < ncells; i++) {
802 for (j = 0; j < 8; j++) {
804 cqcsub = cqcasub[isub];
805 if (cqcsub->bleaf == 1) {
809 if (cqcsub->n >= thresh * ppc) {
812 cqcsub->index = cmap->
n;
822 L_ERROR(
"assigning pixels to wrong color\n", procName);
824 cqcsub->index = cindex;
835 else if (ncolor + reservedcolors > 0)
836 ppc = npix / (ncolor + reservedcolors);
841 #if DEBUG_OCTCUBE_CMAP
842 lept_stderr(
"Exceeds threshold: colors used = %d, colors remaining = %d\n",
843 cmap->
n, ncolor + reservedcolors);
844 lept_stderr(
" cell with %d pixels, npix = %d, ppc = %d\n",
845 cqcsub->n, npix, ppc);
846 lept_stderr(
" index = %d, level = %d, subindex = %d\n",
848 lept_stderr(
" rv = %d, gv = %d, bv = %d\n", rv, gv, bv);
853 if (cqc->nleaves > 0 || level == 2) {
855 if (cqc->nleaves < 8) {
857 for (j = 0; j < 8; j++) {
859 cqcsub = cqcasub[isub];
860 if (cqcsub->bleaf == 0)
864 cqc->index = cmap->
n;
873 L_WARNING(
"possibly assigned pixels to wrong color\n",
889 else if (ncolor + reservedcolors > 0)
890 ppc = npix / (ncolor + reservedcolors);
895 #if DEBUG_OCTCUBE_CMAP
896 lept_stderr(
"By remainder: colors used = %d, colors remaining = %d\n",
897 cmap->
n, ncolor + reservedcolors);
898 lept_stderr(
" cell with %d pixels, npix = %d, ppc = %d\n",
900 lept_stderr(
" index = %d, level = %d\n", i, level);
901 lept_stderr(
" rv = %d, gv = %d, bv = %d\n", rv, gv, bv);
906 for (j = 0; j < 8; j++) {
908 cqcsub = cqcasub[isub];
915 #if PRINT_OCTCUBE_STATS
917 l_int32 tc[] = {0, 0, 0, 0, 0, 0, 0};
918 l_int32 rc[] = {0, 0, 0, 0, 0, 0, 0};
919 l_int32 nt, nr, ival;
923 for (i = 0; i < nt; i++) {
927 for (i = 0; i < nr; i++) {
932 for (i = 1; i < CqNLevels + 1; i++)
935 for (i = 0; i < CqNLevels ; i++)
978 l_uint8 *bufu8r, *bufu8g, *bufu8b;
979 l_int32 rval, gval, bval;
980 l_int32 octindex, index;
981 l_int32 val1, val2, val3, dif;
982 l_int32 w, h, wpls, wpld, i, j, success;
984 l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
985 l_uint32 *rtab, *gtab, *btab;
986 l_uint32 *datas, *datad, *lines, *lined;
989 PROCNAME(
"pixOctreeQuantizePixels");
992 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
993 if (pixGetDepth(pixs) != 32)
994 return (
PIX *)ERROR_PTR(
"pixs must be 32 bpp", procName, NULL);
996 return (
PIX *)ERROR_PTR(
"cqcaa not defined", procName, NULL);
1001 wpls = pixGetWpl(pixs);
1002 if ((pixd =
pixCreate(w, h, 8)) == NULL)
1003 return (
PIX *)ERROR_PTR(
"pixd not made", procName, NULL);
1004 pixCopyResolution(pixd, pixs);
1005 pixCopyInputFormat(pixd, pixs);
1007 wpld = pixGetWpl(pixd);
1010 rtab = gtab = btab = NULL;
1018 if (ditherflag == 0) {
1019 for (i = 0; i < h; i++) {
1020 lines = datas + i * wpls;
1021 lined = datad + i * wpld;
1022 for (j = 0; j < w; j++) {
1024 octindex = rtab[rval] | gtab[gval] | btab[bval];
1031 bufu8r = bufu8g = bufu8b = NULL;
1032 buf1r = buf1g = buf1b = buf2r = buf2g = buf2b = NULL;
1033 bufu8r = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1034 bufu8g = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1035 bufu8b = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
1036 buf1r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1037 buf1g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1038 buf1b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1039 buf2r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1040 buf2g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1041 buf2b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
1042 if (!bufu8r || !bufu8g || !bufu8b || !buf1r || !buf1g ||
1043 !buf1b || !buf2r || !buf2g || !buf2b) {
1044 L_ERROR(
"buffer not made\n", procName);
1046 goto buffer_cleanup;
1051 for (j = 0; j < w; j++) {
1052 buf2r[j] = 64 * bufu8r[j];
1053 buf2g[j] = 64 * bufu8g[j];
1054 buf2b[j] = 64 * bufu8b[j];
1057 for (i = 0; i < h - 1; i++) {
1059 memcpy(buf1r, buf2r, 4 * w);
1060 memcpy(buf1g, buf2g, 4 * w);
1061 memcpy(buf1b, buf2b, 4 * w);
1063 for (j = 0; j < w; j++) {
1064 buf2r[j] = 64 * bufu8r[j];
1065 buf2g[j] = 64 * bufu8g[j];
1066 buf2b[j] = 64 * bufu8b[j];
1070 lined = datad + i * wpld;
1071 for (j = 0; j < w - 1; j++) {
1072 rval = buf1r[j] / 64;
1073 gval = buf1g[j] / 64;
1074 bval = buf1b[j] / 64;
1075 octindex = rtab[rval] | gtab[gval] | btab[bval];
1079 dif = buf1r[j] / 8 - 8 * rc;
1081 val1 = buf1r[j + 1] + 3 * dif;
1082 val2 = buf2r[j] + 3 * dif;
1083 val3 = buf2r[j + 1] + 2 * dif;
1085 buf1r[j + 1] = L_MIN(16383, val1);
1086 buf2r[j] = L_MIN(16383, val2);
1087 buf2r[j + 1] = L_MIN(16383, val3);
1089 buf1r[j + 1] = L_MAX(0, val1);
1090 buf2r[j] = L_MAX(0, val2);
1091 buf2r[j + 1] = L_MAX(0, val3);
1095 dif = buf1g[j] / 8 - 8 * gc;
1097 val1 = buf1g[j + 1] + 3 * dif;
1098 val2 = buf2g[j] + 3 * dif;
1099 val3 = buf2g[j + 1] + 2 * dif;
1101 buf1g[j + 1] = L_MIN(16383, val1);
1102 buf2g[j] = L_MIN(16383, val2);
1103 buf2g[j + 1] = L_MIN(16383, val3);
1105 buf1g[j + 1] = L_MAX(0, val1);
1106 buf2g[j] = L_MAX(0, val2);
1107 buf2g[j + 1] = L_MAX(0, val3);
1111 dif = buf1b[j] / 8 - 8 * bc;
1113 val1 = buf1b[j + 1] + 3 * dif;
1114 val2 = buf2b[j] + 3 * dif;
1115 val3 = buf2b[j + 1] + 2 * dif;
1117 buf1b[j + 1] = L_MIN(16383, val1);
1118 buf2b[j] = L_MIN(16383, val2);
1119 buf2b[j + 1] = L_MIN(16383, val3);
1121 buf1b[j + 1] = L_MAX(0, val1);
1122 buf2b[j] = L_MAX(0, val2);
1123 buf2b[j + 1] = L_MAX(0, val3);
1129 rval = buf1r[w - 1] / 64;
1130 gval = buf1g[w - 1] / 64;
1131 bval = buf1b[w - 1] / 64;
1132 octindex = rtab[rval] | gtab[gval] | btab[bval];
1138 lined = datad + (h - 1) * wpld;
1139 for (j = 0; j < w; j++) {
1140 rval = buf2r[j] / 64;
1141 gval = buf2g[j] / 64;
1142 bval = buf2b[j] / 64;
1143 octindex = rtab[rval] | gtab[gval] | btab[bval];
1198 l_int32 baseindex, subindex;
1202 for (level = 2; level < CqNLevels; level++) {
1204 cqc = cqcaa[level][baseindex];
1205 cqcsub = cqcaa[level + 1][subindex];
1206 if (cqcsub->bleaf == 0) {
1207 *pindex = cqc->index;
1212 }
else if (level == CqNLevels - 1) {
1213 *pindex = cqcsub->index;
1214 *prval = cqcsub->rc;
1215 *pgval = cqcsub->gc;
1216 *pbval = cqcsub->bc;
1223 for (level = 2; level < CqNLevels; level++) {
1226 cqc = cqcaa[level][baseindex];
1227 cqcsub = cqcaa[level + 1][subindex];
1228 if (cqcsub->bleaf == 0) {
1230 *pindex = cqc->index;
1235 }
else if (level == CqNLevels - 1) {
1237 *pindex = cqcsub->index;
1262 l_int32 level, ncells, i;
1266 PROCNAME(
"cqcellTreeCreate");
1269 cqcaa = (
CQCELL ***)LEPT_CALLOC(CqNLevels + 1,
sizeof(
CQCELL **));
1270 for (level = 0; level <= CqNLevels; level++) {
1271 ncells = 1 << (3 * level);
1272 cqca = (
CQCELL **)LEPT_CALLOC(ncells,
sizeof(
CQCELL *));
1273 cqcaa[level] = cqca;
1274 for (i = 0; i < ncells; i++) {
1291 l_int32 level, ncells, i;
1295 PROCNAME(
"cqcellTreeDestroy");
1297 if (pcqcaa == NULL) {
1298 L_WARNING(
"ptr address is NULL\n", procName);
1302 if ((cqcaa = *pcqcaa) == NULL)
1305 for (level = 0; level <= CqNLevels; level++) {
1306 cqca = cqcaa[level];
1307 ncells = 1 << (3 * level);
1308 for (i = 0; i < ncells; i++)
1359 l_uint32 *rtab, *gtab, *btab;
1361 PROCNAME(
"makeRGBToIndexTables");
1363 if (cqlevels < 1 || cqlevels > 6)
1364 return ERROR_INT(
"cqlevels must be in {1,...6}", procName, 1);
1365 if (!prtab || !pgtab || !pbtab)
1366 return ERROR_INT(
"not all &tabs defined", procName, 1);
1368 rtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1369 gtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1370 btab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1371 if (!rtab || !gtab || !btab)
1372 return ERROR_INT(
"calloc fail for tab", procName, 1);
1380 for (i = 0; i < 256; i++) {
1381 rtab[i] = (i >> 5) & 0x0004;
1382 gtab[i] = (i >> 6) & 0x0002;
1387 for (i = 0; i < 256; i++) {
1388 rtab[i] = ((i >> 2) & 0x0020) | ((i >> 4) & 0x0004);
1389 gtab[i] = ((i >> 3) & 0x0010) | ((i >> 5) & 0x0002);
1390 btab[i] = ((i >> 4) & 0x0008) | ((i >> 6) & 0x0001);
1394 for (i = 0; i < 256; i++) {
1395 rtab[i] = ((i << 1) & 0x0100) | ((i >> 1) & 0x0020) |
1396 ((i >> 3) & 0x0004);
1397 gtab[i] = (i & 0x0080) | ((i >> 2) & 0x0010) |
1398 ((i >> 4) & 0x0002);
1399 btab[i] = ((i >> 1) & 0x0040) | ((i >> 3) & 0x0008) |
1400 ((i >> 5) & 0x0001);
1404 for (i = 0; i < 256; i++) {
1405 rtab[i] = ((i << 4) & 0x0800) | ((i << 2) & 0x0100) |
1406 (i & 0x0020) | ((i >> 2) & 0x0004);
1407 gtab[i] = ((i << 3) & 0x0400) | ((i << 1) & 0x0080) |
1408 ((i >> 1) & 0x0010) | ((i >> 3) & 0x0002);
1409 btab[i] = ((i << 2) & 0x0200) | (i & 0x0040) |
1410 ((i >> 2) & 0x0008) | ((i >> 4) & 0x0001);
1414 for (i = 0; i < 256; i++) {
1415 rtab[i] = ((i << 7) & 0x4000) | ((i << 5) & 0x0800) |
1416 ((i << 3) & 0x0100) | ((i << 1) & 0x0020) |
1417 ((i >> 1) & 0x0004);
1418 gtab[i] = ((i << 6) & 0x2000) | ((i << 4) & 0x0400) |
1419 ((i << 2) & 0x0080) | (i & 0x0010) |
1420 ((i >> 2) & 0x0002);
1421 btab[i] = ((i << 5) & 0x1000) | ((i << 3) & 0x0200) |
1422 ((i << 1) & 0x0040) | ((i >> 1) & 0x0008) |
1423 ((i >> 3) & 0x0001);
1427 for (i = 0; i < 256; i++) {
1428 rtab[i] = ((i << 10) & 0x20000) | ((i << 8) & 0x4000) |
1429 ((i << 6) & 0x0800) | ((i << 4) & 0x0100) |
1430 ((i << 2) & 0x0020) | (i & 0x0004);
1431 gtab[i] = ((i << 9) & 0x10000) | ((i << 7) & 0x2000) |
1432 ((i << 5) & 0x0400) | ((i << 3) & 0x0080) |
1433 ((i << 1) & 0x0010) | ((i >> 1) & 0x0002);
1434 btab[i] = ((i << 8) & 0x8000) | ((i << 6) & 0x1000) |
1435 ((i << 4) & 0x0200) | ((i << 2) & 0x0040) |
1436 (i & 0x0008) | ((i >> 2) & 0x0001);
1440 ERROR_INT(
"cqlevels not in [1...6]", procName, 1);
1470 *pindex = rtab[rval] | gtab[gval] | btab[bval];
1518 rgbindex = cubeindex << (3 * (7 - level));
1519 rgbindex |= (0x7 << (3 * (6 - level)));
1522 *prval = ((rgbindex >> 13) & 0x80) |
1523 ((rgbindex >> 11) & 0x40) |
1524 ((rgbindex >> 9) & 0x20) |
1525 ((rgbindex >> 7) & 0x10) |
1526 ((rgbindex >> 5) & 0x08) |
1527 ((rgbindex >> 3) & 0x04) |
1528 ((rgbindex >> 1) & 0x02);
1529 *pgval = ((rgbindex >> 12) & 0x80) |
1530 ((rgbindex >> 10) & 0x40) |
1531 ((rgbindex >> 8) & 0x20) |
1532 ((rgbindex >> 6) & 0x10) |
1533 ((rgbindex >> 4) & 0x08) |
1534 ((rgbindex >> 2) & 0x04) |
1536 *pbval = ((rgbindex >> 11) & 0x80) |
1537 ((rgbindex >> 9) & 0x40) |
1538 ((rgbindex >> 7) & 0x20) |
1539 ((rgbindex >> 5) & 0x10) |
1540 ((rgbindex >> 3) & 0x08) |
1541 ((rgbindex >> 1) & 0x04) |
1542 ((rgbindex << 1) & 0x02);
1590 PROCNAME(
"getOctcubeIndex");
1592 if (level < 0 || level > CqNLevels - 1)
1593 return ERROR_INT(
"level must be in e.g., [0 ... 5]", procName, 1);
1595 return ERROR_INT(
"&bindex not defined", procName, 1);
1597 return ERROR_INT(
"&sindex not defined", procName, 1);
1599 *pbindex = rgbindex >> (3 * (CqNLevels - level));
1600 *psindex = rgbindex >> (3 * (CqNLevels - 1 - level));
1622 PROCNAME(
"octcubeGetCount");
1625 return ERROR_INT(
"&size not defined", procName, 1);
1626 if (level < 1 || level > 6)
1627 return ERROR_INT(
"invalid level", procName, 1);
1629 *psize = 1 << (3 * level);
1697 l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
1698 l_int32 rval, gval, bval;
1699 l_int32 *rarray, *garray, *barray, *narray, *iarray;
1700 l_uint32 octindex, octindex2;
1701 l_uint32 *rtab, *gtab, *btab, *rtab2, *gtab2, *btab2;
1702 l_uint32 *lines, *lined, *datas, *datad;
1708 PROCNAME(
"pixOctreeQuantByPopulation");
1711 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
1712 if (pixGetDepth(pixs) != 32)
1713 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
1714 if (level == 0) level = 4;
1715 if (level < 3 || level > 4)
1716 return (
PIX *)ERROR_PTR(
"level not in {3,4}", procName, NULL);
1720 if (w < MinDitherSize && h < MinDitherSize && ditherflag == 1) {
1721 L_INFO(
"Small image: dithering turned off\n", procName);
1726 return (
PIX *)ERROR_PTR(
"size not returned", procName, NULL);
1727 rtab = gtab = btab = NULL;
1731 narray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1732 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1733 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1734 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1735 if (!narray || !rarray || !garray || !barray)
1740 wpls = pixGetWpl(pixs);
1741 for (i = 0; i < h; i++) {
1742 lines = datas + i * wpls;
1743 for (j = 0; j < w; j++) {
1745 octindex = rtab[rval] | gtab[gval] | btab[bval];
1747 rarray[octindex] += rval;
1748 garray[octindex] += gval;
1749 barray[octindex] += bval;
1754 for (i = 0, ncolors = 0; i < size; i++) {
1760 else if (ncolors <= 16)
1766 wpld = pixGetWpl(pixd);
1767 pixCopyResolution(pixd, pixs);
1768 pixCopyInputFormat(pixd, pixs);
1773 for (i = 0; i < size; i++) {
1774 if (narray[i] > 0) {
1775 rarray[i] /= narray[i];
1776 garray[i] /= narray[i];
1777 barray[i] /= narray[i];
1783 if (ncolors <= 256) {
1784 for (i = 0, index = 0; i < size; i++) {
1785 if (narray[i] > 0) {
1787 narray[i] = index + 1;
1793 for (i = 0; i < h; i++) {
1794 lines = datas + i * wpls;
1795 lined = datad + i * wpld;
1796 for (j = 0; j < w; j++) {
1798 octindex = rtab[rval] | gtab[gval] | btab[bval];
1811 L_WARNING(
"shouldn't get here\n", procName);
1820 for (i = 0; i < size; i++) {
1821 if (narray[i] > 0) {
1823 opop->npix = (l_float32)narray[i];
1825 opop->rval = rarray[i];
1826 opop->gval = garray[i];
1827 opop->bval = barray[i];
1834 iarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1835 for (i = 0; i < 192; i++) {
1839 iarray[opop->index] = i + 1;
1842 lept_stderr(
"i = %d, n = %6.0f, (r,g,b) = (%d %d %d)\n",
1843 i, opop->npix, opop->rval, opop->gval, opop->bval);
1850 rtab2 = gtab2 = btab2 = NULL;
1852 for (i = 0; i < 64; i++) {
1863 for (i = 192; i < size; i++) {
1869 octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
1870 narray[octindex2] += (l_int32)opop->npix;
1871 rarray[octindex2] += (l_int32)opop->npix * rval;
1872 garray[octindex2] += (l_int32)opop->npix * gval;
1873 barray[octindex2] += (l_int32)opop->npix * bval;
1874 iarray[opop->index] = 192 + octindex2 + 1;
1885 for (i = 0; i < size; i++) {
1886 if (iarray[i] == 0) {
1888 octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
1889 iarray[i] = 192 + octindex2 + 1;
1899 for (i = 0; i < 64; i++) {
1900 if (narray[i] > 0) {
1901 rarray[i] /= narray[i];
1902 garray[i] /= narray[i];
1903 barray[i] /= narray[i];
1912 if (ditherflag == 0) {
1913 for (i = 0; i < h; i++) {
1914 lines = datas + i * wpls;
1915 lined = datad + i * wpld;
1916 for (j = 0; j < w; j++) {
1918 octindex = rtab[rval] | gtab[gval] | btab[bval];
1924 iarray, POP_DIF_CAP);
1928 for (i = 0; i < size / 16; i++) {
1930 for (j = 0; j < 16; j++)
1993 l_uint8 *bufu8r, *bufu8g, *bufu8b;
1994 l_int32 i, j, w, h, wpld, octindex, cmapindex, success;
1995 l_int32 rval, gval, bval, rc, gc, bc;
1996 l_int32 dif, val1, val2, val3;
1997 l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
1998 l_uint32 *datad, *lined;
2001 PROCNAME(
"pixDitherOctindexWithCmap");
2003 if (!pixs || pixGetDepth(pixs) != 32)
2004 return ERROR_INT(
"pixs undefined or not 32 bpp", procName, 1);
2005 if (!pixd || pixGetDepth(pixd) != 8)
2006 return ERROR_INT(
"pixd undefined or not 8 bpp", procName, 1);
2007 if ((cmap = pixGetColormap(pixd)) == NULL)
2008 return ERROR_INT(
"pixd not cmapped", procName, 1);
2009 if (!rtab || !gtab || !btab || !indexmap)
2010 return ERROR_INT(
"not all 4 tables defined", procName, 1);
2012 if (pixGetWidth(pixd) != w || pixGetHeight(pixd) != h)
2013 return ERROR_INT(
"pixs and pixd not same size", procName, 1);
2016 bufu8r = bufu8g = bufu8b = NULL;
2017 buf1r = buf1g = buf1b = buf2r = buf2g = buf2b = NULL;
2018 bufu8r = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
2019 bufu8g = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
2020 bufu8b = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
2021 buf1r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2022 buf1g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2023 buf1b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2024 buf2r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2025 buf2g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2026 buf2b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2027 if (!bufu8r || !bufu8g || !bufu8b || !buf1r || !buf1g ||
2028 !buf1b || !buf2r || !buf2g || !buf2b) {
2029 L_ERROR(
"buffer not made\n", procName);
2031 goto buffer_cleanup;
2036 for (j = 0; j < w; j++) {
2037 buf2r[j] = 64 * bufu8r[j];
2038 buf2g[j] = 64 * bufu8g[j];
2039 buf2b[j] = 64 * bufu8b[j];
2043 wpld = pixGetWpl(pixd);
2044 for (i = 0; i < h - 1; i++) {
2046 memcpy(buf1r, buf2r, 4 * w);
2047 memcpy(buf1g, buf2g, 4 * w);
2048 memcpy(buf1b, buf2b, 4 * w);
2050 for (j = 0; j < w; j++) {
2051 buf2r[j] = 64 * bufu8r[j];
2052 buf2g[j] = 64 * bufu8g[j];
2053 buf2b[j] = 64 * bufu8b[j];
2057 lined = datad + i * wpld;
2058 for (j = 0; j < w - 1; j++) {
2059 rval = buf1r[j] / 64;
2060 gval = buf1g[j] / 64;
2061 bval = buf1b[j] / 64;
2062 octindex = rtab[rval] | gtab[gval] | btab[bval];
2063 cmapindex = indexmap[octindex] - 1;
2067 dif = buf1r[j] / 8 - 8 * rc;
2069 if (dif > difcap) dif = difcap;
2070 if (dif < -difcap) dif = -difcap;
2073 val1 = buf1r[j + 1] + 3 * dif;
2074 val2 = buf2r[j] + 3 * dif;
2075 val3 = buf2r[j + 1] + 2 * dif;
2077 buf1r[j + 1] = L_MIN(16383, val1);
2078 buf2r[j] = L_MIN(16383, val2);
2079 buf2r[j + 1] = L_MIN(16383, val3);
2081 buf1r[j + 1] = L_MAX(0, val1);
2082 buf2r[j] = L_MAX(0, val2);
2083 buf2r[j + 1] = L_MAX(0, val3);
2087 dif = buf1g[j] / 8 - 8 * gc;
2089 if (dif > difcap) dif = difcap;
2090 if (dif < -difcap) dif = -difcap;
2093 val1 = buf1g[j + 1] + 3 * dif;
2094 val2 = buf2g[j] + 3 * dif;
2095 val3 = buf2g[j + 1] + 2 * dif;
2097 buf1g[j + 1] = L_MIN(16383, val1);
2098 buf2g[j] = L_MIN(16383, val2);
2099 buf2g[j + 1] = L_MIN(16383, val3);
2101 buf1g[j + 1] = L_MAX(0, val1);
2102 buf2g[j] = L_MAX(0, val2);
2103 buf2g[j + 1] = L_MAX(0, val3);
2107 dif = buf1b[j] / 8 - 8 * bc;
2109 if (dif > difcap) dif = difcap;
2110 if (dif < -difcap) dif = -difcap;
2113 val1 = buf1b[j + 1] + 3 * dif;
2114 val2 = buf2b[j] + 3 * dif;
2115 val3 = buf2b[j + 1] + 2 * dif;
2117 buf1b[j + 1] = L_MIN(16383, val1);
2118 buf2b[j] = L_MIN(16383, val2);
2119 buf2b[j + 1] = L_MIN(16383, val3);
2121 buf1b[j + 1] = L_MAX(0, val1);
2122 buf2b[j] = L_MAX(0, val2);
2123 buf2b[j + 1] = L_MAX(0, val3);
2129 rval = buf1r[w - 1] / 64;
2130 gval = buf1g[w - 1] / 64;
2131 bval = buf1b[w - 1] / 64;
2132 octindex = rtab[rval] | gtab[gval] | btab[bval];
2133 cmapindex = indexmap[octindex] - 1;
2138 lined = datad + (h - 1) * wpld;
2139 for (j = 0; j < w; j++) {
2140 rval = buf2r[j] / 64;
2141 gval = buf2g[j] / 64;
2142 bval = buf2b[j] / 64;
2143 octindex = rtab[rval] | gtab[gval] | btab[bval];
2144 cmapindex = indexmap[octindex] - 1;
2159 return (success) ? 0 : 1;
2260 l_int32 w, h, minside, bpp, wpls, wpld, i, j, actualcolors;
2261 l_int32 rval, gval, bval, nbase, nextra, maxlevel, ncubes, val;
2262 l_int32 *lut1, *lut2;
2264 l_uint32 *lines, *lined, *datas, *datad, *pspixel;
2265 l_uint32 *rtab, *gtab, *btab;
2272 PROCNAME(
"pixOctreeQuantNumColors");
2275 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2276 if (pixGetDepth(pixs) != 32)
2277 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2278 if (maxcolors < 8) {
2279 L_WARNING(
"max colors < 8; setting to 8\n", procName);
2282 if (maxcolors > 256) {
2283 L_WARNING(
"max colors > 256; setting to 256\n", procName);
2289 wpls = pixGetWpl(pixs);
2290 minside = L_MIN(w, h);
2291 if (subsample <= 0) {
2292 subsample = L_MAX(1, minside / 200);
2295 if (maxcolors <= 16) {
2301 nextra = maxcolors - nbase;
2302 }
else if (maxcolors <= 64) {
2308 nextra = maxcolors - nbase;
2315 nextra = maxcolors - nbase;
2318 pixCopyResolution(pixd, pixs);
2319 pixCopyInputFormat(pixd, pixs);
2328 if ((oqca = (
OQCELL **)LEPT_CALLOC(nbase,
sizeof(
OQCELL *))) == NULL) {
2330 return (
PIX *)ERROR_PTR(
"oqca not made", procName, NULL);
2332 for (i = 0; i < nbase; i++) {
2337 rtab = gtab = btab = NULL;
2343 wpld = pixGetWpl(pixd);
2344 for (i = 0; i < h; i++) {
2345 lines = datas + i * wpls;
2346 lined = datad + i * wpld;
2347 for (j = 0; j < w; j++) {
2348 pspixel = lines + j;
2351 rtab, gtab, btab, &index);
2358 oqca[index]->n += 1.0;
2359 oqca[index]->rcum += rval;
2360 oqca[index]->gcum += gval;
2361 oqca[index]->bcum += bval;
2369 for (i = 0; i < nbase; i++) {
2372 oqc->rval = (l_int32)(oqc->rcum / oqc->n);
2373 oqc->gval = (l_int32)(oqc->gcum / oqc->n);
2374 oqc->bval = (l_int32)(oqc->bcum / oqc->n);
2377 &oqc->gval, &oqc->bval);
2382 for (i = 0; i < nbase; i++)
2397 oqca = (
OQCELL **)LEPT_CALLOC(ncubes,
sizeof(
OQCELL *));
2398 for (i = 0; i < ncubes; i++) {
2405 rtab = gtab = btab = NULL;
2410 for (i = 0; i < h; i += subsample) {
2411 lines = datas + i * wpls;
2412 for (j = 0; j < w; j += subsample) {
2413 pspixel = lines + j;
2416 oqca[index]->n += 1.0;
2417 oqca[index]->octindex = index;
2418 oqca[index]->rcum += rval;
2419 oqca[index]->gcum += gval;
2420 oqca[index]->bcum += bval;
2426 for (i = 0; i < ncubes; i++)
2431 oqca = (
OQCELL **)LEPT_CALLOC(maxcolors,
sizeof(
OQCELL *));
2432 for (i = 0; i < nbase; i++) {
2438 for (i = 0; i < nextra; i++) {
2444 oqca[nbase + i] = oqc;
2452 lut1 = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
2453 for (i = 0; i < nextra; i++)
2454 lut1[oqca[nbase + i]->octindex] = nbase + i;
2455 for (index = 0; index < ncubes; index++) {
2456 if (lut1[index] == 0)
2457 lut1[index] = index >> 3;
2464 wpld = pixGetWpl(pixd);
2465 for (i = 0; i < h; i++) {
2466 lines = datas + i * wpls;
2467 lined = datad + i * wpld;
2468 for (j = 0; j < w; j++) {
2469 pspixel = lines + j;
2485 return (
PIX *)ERROR_PTR(
"bpp not 4 or 8!", procName, NULL);
2488 oqca[val]->n += 1.0;
2489 oqca[val]->rcum += rval;
2490 oqca[val]->gcum += gval;
2491 oqca[val]->bcum += bval;
2498 lut2 = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
2501 for (i = 0, index = 0; i < maxcolors; i++) {
2506 oqc->rval = (l_int32)(oqc->rcum / oqc->n);
2507 oqc->gval = (l_int32)(oqc->gcum / oqc->n);
2508 oqc->bval = (l_int32)(oqc->bcum / oqc->n);
2518 if (actualcolors < maxcolors) {
2519 for (i = 0; i < h; i++) {
2520 lined = datad + i * wpld;
2521 for (j = 0; j < w; j++) {
2537 for (i = 0; i < maxcolors; i++)
2588 l_int32 w, h, wpls, wpld, i, j, size, octlevels;
2589 l_int32 rval, gval, bval, del, val, midval;
2590 l_int32 *carray, *rarray, *garray, *barray;
2593 l_uint32 *rtab, *gtab, *btab;
2594 l_uint32 *lines, *lined, *datas, *datad;
2598 PROCNAME(
"pixOctcubeQuantMixedWithGray");
2601 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2602 if (pixGetDepth(pixs) != 32)
2603 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2605 return (
PIX *)ERROR_PTR(
"invalid graylevels", procName, NULL);
2610 return (
PIX *)ERROR_PTR(
"max 8 gray levels", procName, NULL);
2611 }
else if (depth == 8) {
2614 if (graylevels > 192)
2615 return (
PIX *)ERROR_PTR(
"max 192 gray levels", procName, NULL);
2617 return (
PIX *)ERROR_PTR(
"output depth not 4 or 8 bpp", procName, NULL);
2623 rtab = gtab = btab = NULL;
2627 carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2628 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2629 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2630 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2634 if (!rtab || !gtab || !btab ||
2635 !carray || !rarray || !garray || !barray || !tabval) {
2636 L_ERROR(
"calloc fail for an array\n", procName);
2642 if ((pixd =
pixCreate(w, h, depth)) == NULL) {
2643 L_ERROR(
"pixd not made\n", procName);
2646 pixCopyResolution(pixd, pixs);
2647 pixCopyInputFormat(pixd, pixs);
2649 for (j = 0; j < size; j++)
2651 for (j = 0; j < graylevels; j++) {
2652 val = (255 * j) / (graylevels - 1);
2656 wpld = pixGetWpl(pixd);
2662 wpls = pixGetWpl(pixs);
2663 for (i = 0; i < h; i++) {
2664 lines = datas + i * wpls;
2665 lined = datad + i * wpld;
2666 for (j = 0; j < w; j++) {
2672 }
else if (rval > bval) {
2683 }
else if (gval > bval) {
2692 octindex = rtab[rval] | gtab[gval] | btab[bval];
2694 rarray[octindex] += rval;
2695 garray[octindex] += gval;
2696 barray[octindex] += bval;
2702 val = size + tabval[midval];
2712 for (i = 0; i < size; i++) {
2713 if (carray[i] > 0) {
2714 rarray[i] /= carray[i];
2715 garray[i] /= carray[i];
2716 barray[i] /= carray[i];
2806 l_int32 rval, gval, bval;
2807 l_int32 w, h, wpls, wpld, i, j, cindex;
2808 l_uint32 *rtab, *gtab, *btab;
2810 l_uint32 *datas, *datad, *lines, *lined;
2814 PROCNAME(
"pixFixedOctcubeQuant256");
2817 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2818 if (pixGetDepth(pixs) != 32)
2819 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2823 if (w < MinDitherSize && h < MinDitherSize && ditherflag == 1) {
2824 L_INFO(
"Small image: dithering turned off\n", procName);
2837 for (cindex = 0; cindex < 256; cindex++) {
2838 rval = (cindex & 0xe0) | 0x10;
2839 gval = ((cindex << 3) & 0xe0) | 0x10;
2840 bval = ((cindex << 6) & 0xc0) | 0x20;
2846 wpls = pixGetWpl(pixs);
2847 if ((pixd =
pixCreate(w, h, 8)) == NULL) {
2849 return (
PIX *)ERROR_PTR(
"pixd not made", procName, NULL);
2852 pixCopyResolution(pixd, pixs);
2853 pixCopyInputFormat(pixd, pixs);
2855 wpld = pixGetWpl(pixd);
2858 if (ditherflag == 0) {
2859 for (i = 0; i < h; i++) {
2860 lines = datas + i * wpls;
2861 lined = datad + i * wpld;
2862 for (j = 0; j < w; j++) {
2864 index = (rval & 0xe0) | ((gval >> 3) & 0x1c) | (bval >> 6);
2876 rtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2877 gtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2878 btab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2879 itab = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
2880 if (!rtab || !gtab || !btab || !itab) {
2882 return (
PIX *)ERROR_PTR(
"calloc fail for table", procName, NULL);
2884 for (i = 0; i < 256; i++) {
2886 gtab[i] = (i >> 3) & 0x1c;
2939 l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
2940 l_int32 rval, gval, bval;
2941 l_int32 *carray, *rarray, *garray, *barray;
2943 l_uint32 *rtab, *gtab, *btab;
2944 l_uint32 *lines, *lined, *datas, *datad, *pspixel;
2948 PROCNAME(
"pixFewColorsOctcubeQuant1");
2951 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2952 if (pixGetDepth(pixs) != 32)
2953 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2954 if (level < 1 || level > 6)
2955 return (
PIX *)ERROR_PTR(
"invalid level", procName, NULL);
2960 return (
PIX *)ERROR_PTR(
"size not returned", procName, NULL);
2961 rtab = gtab = btab = NULL;
2964 carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2965 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2966 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2967 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2968 if (!carray || !rarray || !garray || !barray) {
2969 L_ERROR(
"calloc fail for an array\n", procName);
2976 wpls = pixGetWpl(pixs);
2977 for (i = 0; i < h; i++) {
2978 lines = datas + i * wpls;
2979 for (j = 0; j < w; j++) {
2980 pspixel = lines + j;
2982 octindex = rtab[rval] | gtab[gval] | btab[bval];
2984 rarray[octindex] += rval;
2985 garray[octindex] += gval;
2986 barray[octindex] += bval;
2991 for (i = 0, ncolors = 0; i < size; i++) {
2995 if (ncolors > 256) {
2996 L_WARNING(
"%d colors found; more than 256\n", procName, ncolors);
3001 else if (ncolors <= 16)
3009 for (i = 0, index = 0; i < size; i++) {
3010 if (carray[i] > 0) {
3011 rarray[i] /= carray[i];
3012 garray[i] /= carray[i];
3013 barray[i] /= carray[i];
3015 carray[i] = index + 1;
3022 pixCopyResolution(pixd, pixs);
3023 pixCopyInputFormat(pixd, pixs);
3025 wpld = pixGetWpl(pixd);
3026 for (i = 0; i < h; i++) {
3027 lines = datas + i * wpls;
3028 lined = datad + i * wpld;
3029 for (j = 0; j < w; j++) {
3030 pspixel = lines + j;
3032 octindex = rtab[rval] | gtab[gval] | btab[bval];
3045 L_WARNING(
"shouldn't get here\n", procName);
3112 l_int32 w, h, wpls, wpld, i, j, nerrors;
3113 l_int32 ncubes, depth, cindex, oval;
3114 l_int32 rval, gval, bval;
3117 l_uint32 *rtab, *gtab, *btab;
3118 l_uint32 *lines, *lined, *datas, *datad, *ppixel;
3119 l_uint32 *colorarray;
3123 PROCNAME(
"pixFewColorsOctcubeQuant2");
3126 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3127 if (pixGetDepth(pixs) != 32)
3128 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3129 if (level < 3 || level > 6)
3130 return (
PIX *)ERROR_PTR(
"level not in {4, 5, 6}", procName, NULL);
3132 return (
PIX *)ERROR_PTR(
"ncolors > 256", procName, NULL);
3140 rtab = gtab = btab = NULL;
3145 octarray = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
3150 colorarray = (l_uint32 *)LEPT_CALLOC(ncolors + 1,
sizeof(l_uint32));
3151 if (!octarray || !colorarray) {
3152 L_ERROR(
"octarray or colorarray not made\n", procName);
3153 goto cleanup_arrays;
3159 wpls = pixGetWpl(pixs);
3162 else if (ncolors <= 16)
3167 if ((pixd =
pixCreate(w, h, depth)) == NULL) {
3168 L_ERROR(
"pixd not made\n", procName);
3169 goto cleanup_arrays;
3171 pixCopyResolution(pixd, pixs);
3172 pixCopyInputFormat(pixd, pixs);
3174 wpld = pixGetWpl(pixd);
3186 for (i = 0; i < h; i++) {
3187 lines = datas + i * wpls;
3188 lined = datad + i * wpld;
3189 for (j = 0; j < w; j++) {
3192 octindex = rtab[rval] | gtab[gval] | btab[bval];
3193 oval = octarray[octindex];
3195 octarray[octindex] = cindex;
3196 colorarray[cindex] = *ppixel;
3201 if (colorarray[oval] != *ppixel)
3207 *pnerrors = nerrors;
3209 #if DEBUG_FEW_COLORS
3210 lept_stderr(
"ncubes = %d, ncolors = %d\n", ncubes, ncolors);
3211 for (i = 0; i < ncolors; i++)
3212 lept_stderr(
"color[%d] = %x\n", i, colorarray[i + 1]);
3217 for (i = 0; i < ncolors; i++) {
3218 ppixel = colorarray + i + 1;
3225 LEPT_FREE(octarray);
3226 LEPT_FREE(colorarray);
3298 l_int32 lightthresh,
3303 l_int32 i, j, w, h, wplc, wplm, wpld, ncolors, index;
3304 l_int32 rval, gval, bval, val, minval, maxval;
3306 l_uint32 *datac, *datam, *datad, *linec, *linem, *lined;
3307 PIX *pix1, *pixc, *pixm, *pixg, *pixd;
3310 PROCNAME(
"pixFewColorsOctcubeQuantMixed");
3312 if (!pixs || pixGetDepth(pixs) != 32)
3313 return (
PIX *)ERROR_PTR(
"pixs undefined or not 32 bpp", procName, NULL);
3314 if (level <= 0) level = 3;
3316 return (
PIX *)ERROR_PTR(
"invalid level", procName, NULL);
3317 if (darkthresh <= 0) darkthresh = 20;
3318 if (lightthresh <= 0) lightthresh = 244;
3319 if (diffthresh <= 0) diffthresh = 20;
3320 if (minfract <= 0.0) minfract = 0.05;
3321 if (maxspan <= 2) maxspan = 15;
3325 return (
PIX *)ERROR_PTR(
"too many colors", procName, NULL);
3331 cmap = pixGetColormap(pixc);
3334 lut = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
3335 for (i = 0; i < 256; i++)
3337 for (i = 0, index = 0; i < ncolors; i++) {
3339 minval = L_MIN(rval, gval);
3340 minval = L_MIN(minval, bval);
3341 if (minval > lightthresh)
3343 maxval = L_MAX(rval, gval);
3344 maxval = L_MAX(maxval, bval);
3345 if (maxval < darkthresh)
3349 if (maxval - minval >= diffthresh) {
3366 wplc = pixGetWpl(pixc);
3367 wplm = pixGetWpl(pixm);
3368 wpld = pixGetWpl(pixd);
3369 for (i = 0; i < h; i++) {
3370 linec = datac + i * wplc;
3371 linem = datam + i * wplm;
3372 lined = datad + i * wpld;
3373 for (j = 0; j < w; j++) {
3418 l_int32 w, h, wpls, wpld, i, j;
3419 l_int32 rval, gval, bval;
3421 l_uint32 *rtab, *gtab, *btab;
3422 l_uint32 *lines, *lined, *datas, *datad;
3425 PROCNAME(
"pixFixedOctcubeQuantGenRGB");
3428 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3429 if (pixGetDepth(pixs) != 32)
3430 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3431 if (level < 1 || level > 6)
3432 return (
PIX *)ERROR_PTR(
"level not in {1,...6}", procName, NULL);
3435 return (
PIX *)ERROR_PTR(
"tables not made", procName, NULL);
3439 pixCopyResolution(pixd, pixs);
3440 pixCopyInputFormat(pixd, pixs);
3442 wpld = pixGetWpl(pixd);
3444 wpls = pixGetWpl(pixs);
3445 for (i = 0; i < h; i++) {
3446 lines = datas + i * wpls;
3447 lined = datad + i * wpld;
3448 for (j = 0; j < w; j++) {
3450 octindex = rtab[rval] | gtab[gval] | btab[bval];
3496 PROCNAME(
"pixQuantFromCmap");
3499 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3500 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3501 return (
PIX *)ERROR_PTR(
"invalid mindepth", procName, NULL);
3502 d = pixGetDepth(pixs);
3509 return (
PIX *)ERROR_PTR(
"d not 8 or 32 bpp", procName, NULL);
3584 l_uint32 *rtab, *gtab, *btab;
3587 PROCNAME(
"pixOctcubeQuantFromCmap");
3590 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3591 if (pixGetDepth(pixs) != 32)
3592 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3594 return (
PIX *)ERROR_PTR(
"cmap not defined", procName, NULL);
3595 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3596 return (
PIX *)ERROR_PTR(
"invalid mindepth", procName, NULL);
3597 if (level < 1 || level > 6)
3598 return (
PIX *)ERROR_PTR(
"level not in {1...6}", procName, NULL);
3600 return (
PIX *)ERROR_PTR(
"invalid metric", procName, NULL);
3603 rtab = gtab = btab = NULL;
3608 cmaptab, rtab, gtab, btab);
3651 l_int32 i, j, w, h, depth, wpls, wpld;
3652 l_int32 rval, gval, bval, index;
3654 l_uint32 *lines, *lined, *datas, *datad;
3658 PROCNAME(
"pixOctcubeQuantFromCmapLUT");
3661 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3662 if (pixGetDepth(pixs) != 32)
3663 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3665 return (
PIX *)ERROR_PTR(
"cmap not defined", procName, NULL);
3666 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3667 return (
PIX *)ERROR_PTR(
"invalid mindepth", procName, NULL);
3668 if (!rtab || !gtab || !btab || !cmaptab)
3669 return (
PIX *)ERROR_PTR(
"tables not all defined", procName, NULL);
3673 depth = L_MAX(depth, mindepth);
3675 if ((pixd =
pixCreate(w, h, depth)) == NULL)
3676 return (
PIX *)ERROR_PTR(
"pixd not made", procName, NULL);
3679 pixCopyResolution(pixd, pixs);
3680 pixCopyInputFormat(pixd, pixs);
3685 wpls = pixGetWpl(pixs);
3686 wpld = pixGetWpl(pixd);
3687 for (i = 0; i < h; i++) {
3688 lines = datas + i * wpls;
3689 lined = datad + i * wpld;
3690 for (j = 0; j < w; j++) {
3696 index = cmaptab[octindex];
3699 else if (depth == 4)
3731 l_int32 size, i, j, w, h, wpl, ncolors, val;
3732 l_int32 rval, gval, bval;
3734 l_uint32 *rtab, *gtab, *btab;
3735 l_uint32 *data, *line;
3739 PROCNAME(
"pixOctcubeHistogram");
3741 if (pncolors) *pncolors = 0;
3743 return (
NUMA *)ERROR_PTR(
"pixs not defined", procName, NULL);
3744 if (pixGetDepth(pixs) != 32)
3745 return (
NUMA *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3748 wpl = pixGetWpl(pixs);
3752 return (
NUMA *)ERROR_PTR(
"size not returned", procName, NULL);
3753 rtab = gtab = btab = NULL;
3757 L_ERROR(
"na not made\n", procName);
3758 goto cleanup_arrays;
3763 for (i = 0; i < h; i++) {
3764 line = data + i * wpl;
3765 for (j = 0; j < w; j++) {
3767 octindex = rtab[rval] | gtab[gval] | btab[bval];
3769 if ((level == 1 && octindex > 7) ||
3770 (level == 2 && octindex > 63) ||
3771 (level == 3 && octindex > 511) ||
3772 (level == 4 && octindex > 4097) ||
3773 (level == 5 && octindex > 32783) ||
3774 (level == 6 && octindex > 262271)) {
3775 lept_stderr(
"level = %d, octindex = %d, index error!\n",
3780 array[octindex] += 1.0;
3785 for (i = 0, ncolors = 0; i < size; i++) {
3790 *pncolors = ncolors;
3854 l_int32 i, k, size, ncolors, mindist, dist, mincolor, index;
3855 l_int32 rval, gval, bval;
3856 l_int32 *rmap, *gmap, *bmap, *tab;
3858 PROCNAME(
"pixcmapToOctcubeLUT");
3861 return (l_int32 *)ERROR_PTR(
"cmap not defined", procName, NULL);
3862 if (level < 1 || level > 6)
3863 return (l_int32 *)ERROR_PTR(
"level not in {1...6}", procName, NULL);
3865 return (l_int32 *)ERROR_PTR(
"invalid metric", procName, NULL);
3868 return (l_int32 *)ERROR_PTR(
"size not returned", procName, NULL);
3869 if ((tab = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL)
3870 return (l_int32 *)ERROR_PTR(
"tab not allocated", procName, NULL);
3876 for (i = 0; i < size; i++) {
3880 for (k = 0; k < ncolors; k++) {
3882 dist = L_ABS(rval - rmap[k]) + L_ABS(gval - gmap[k]) +
3883 L_ABS(bval - bmap[k]);
3885 dist = (rval - rmap[k]) * (rval - rmap[k]) +
3886 (gval - gmap[k]) * (gval - gmap[k]) +
3887 (bval - bmap[k]) * (bval - bmap[k]);
3889 if (dist < mindist) {
3902 if (rval < 7 && gval < 7 && bval < 7) {
3907 if (rval > 248 && gval > 248 && bval > 248) {
3908 tab[(1 << (3 * level)) - 1] = index;
3938 l_int32 i, j, w, h, d, nc, wpls, val, newval, index, zerofound;
3939 l_int32 rval, gval, bval;
3940 l_uint32 *datas, *lines;
3941 l_int32 *histo, *map1, *map2;
3944 PROCNAME(
"pixRemoveUnusedColors");
3947 return ERROR_INT(
"pixs not defined", procName, 1);
3948 if ((cmap = pixGetColormap(pixs)) == NULL)
3951 d = pixGetDepth(pixs);
3952 if (d != 2 && d != 4 && d != 8)
3953 return ERROR_INT(
"d not in {2, 4, 8}", procName, 1);
3957 if ((histo = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32))) == NULL)
3958 return ERROR_INT(
"histo not made", procName, 1);
3960 wpls = pixGetWpl(pixs);
3962 for (i = 0; i < h; i++) {
3963 lines = datas + i * wpls;
3964 for (j = 0; j < w; j++) {
3978 return ERROR_INT(
"switch ran off end!", procName, 1);
3981 L_WARNING(
"cmap index out of bounds!\n", procName);
3990 for (i = 0; i < nc; i++) {
3991 if (histo[i] == 0) {
4002 map1 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
4003 map2 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
4005 for (i = 0; i < nc; i++) {
4006 if (histo[i] != 0) {
4015 for (i = 0; i < index; i++) {
4022 for (i = 0; i < h; i++) {
4023 lines = datas + i * wpls;
4024 for (j = 0; j < w; j++) {
4046 return ERROR_INT(
"switch ran off end!", procName, 1);
4088 l_int32 i, j, w, h, d, wpl, ncolors, size, octindex;
4089 l_int32 rval, gval, bval;
4091 l_uint32 *data, *line, *rtab, *gtab, *btab;
4093 PROCNAME(
"pixNumberOccupiedOctcubes");
4096 return ERROR_INT(
"&ncolors not defined", procName, 1);
4099 return ERROR_INT(
"pix not defined", procName, 1);
4102 return ERROR_INT(
"pix not 32 bpp", procName, 1);
4103 if (level < 1 || level > 6)
4104 return ERROR_INT(
"invalid level", procName, 1);
4105 if ((mincount < 0 && minfract < 0) || (mincount >= 0.0 && minfract >= 0.0))
4106 return ERROR_INT(
"invalid mincount/minfract", procName, 1);
4107 if (mincount == 0 || minfract == 0.0)
4109 else if (minfract > 0.0)
4110 mincount = L_MIN(1, (l_int32)(minfract * w * h));
4113 return ERROR_INT(
"size not returned", procName, 1);
4114 rtab = gtab = btab = NULL;
4116 if ((carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL) {
4117 L_ERROR(
"carray not made\n", procName);
4118 goto cleanup_arrays;
4123 wpl = pixGetWpl(pix);
4124 for (i = 0; i < h; i++) {
4125 line = data + i * wpl;
4126 for (j = 0; j < w; j++) {
4128 octindex = rtab[rval] | gtab[gval] | btab[bval];
4134 for (i = 0, ncolors = 0; i < size; i++) {
4135 if (carray[i] >= mincount)
4138 *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()