118 #include "allheaders.h" 169 static const l_int32 CQ_NLEVELS = 5;
170 static const l_int32 CQ_RESERVED_COLORS = 64;
172 static const l_int32 EXTRA_RESERVED_COLORS = 25;
173 static const l_int32 TREE_GEN_WIDTH = 350;
174 static const l_int32 MIN_DITHER_SIZE = 250;
194 l_int32 rcum, gcum, bcum;
195 l_int32 rval, gval, bval;
227 static const l_int32 FIXED_DIF_CAP = 0;
228 static const l_int32 POP_DIF_CAP = 40;
233 l_int32 *pindex, l_int32 *prval,
234 l_int32 *pgval, l_int32 *pbval);
238 l_int32 reservedcolors,
247 l_int32 *prval, l_int32 *pgval, l_int32 *pbval);
249 l_int32 *pbindex, l_int32 *psindex);
254 l_uint32 *gtab, l_uint32 *btab,
255 l_int32 *carray, l_int32 difcap);
259 l_int32 mindepth, l_int32 *cmaptab,
260 l_uint32 *rtab, l_uint32 *gtab,
263 #ifndef NO_CONSOLE_IO 264 #define DEBUG_COLORQUANT 0 265 #define DEBUG_OCTINDEX 0 266 #define DEBUG_OCTCUBE_CMAP 0 268 #define DEBUG_FEW_COLORS 0 269 #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 > TREE_GEN_WIDTH) {
648 scalefactor = (l_float32)TREE_GEN_WIDTH / (l_float32)w;
655 if (w < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE)
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 < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE && 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 - EXTRA_RESERVED_COLORS;
775 wpls = pixGetWpl(pixs);
778 ncells = 1 << (3 * CQ_NLEVELS);
779 cqca = cqcaa[CQ_NLEVELS];
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 = CQ_NLEVELS - 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 fprintf(stderr,
"Exceeds threshold: colors used = %d, colors remaining = %d\n",
843 cmap->
n, ncolor + reservedcolors);
844 fprintf(stderr,
" cell with %d pixels, npix = %d, ppc = %d\n",
845 cqcsub->n, npix, ppc);
846 fprintf(stderr,
" index = %d, level = %d, subindex = %d\n",
848 fprintf(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 fprintf(stderr,
"By remainder: colors used = %d, colors remaining = %d\n",
897 cmap->
n, ncolor + reservedcolors);
898 fprintf(stderr,
" cell with %d pixels, npix = %d, ppc = %d\n",
900 fprintf(stderr,
" index = %d, level = %d\n", i, level);
901 fprintf(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++) {
931 fprintf(stderr,
" Threshold cells formed: %d\n", nt);
932 for (i = 1; i < CQ_NLEVELS + 1; i++)
933 fprintf(stderr,
" level %d: %d\n", i, tc[i]);
934 fprintf(stderr,
"\n Residual cells formed: %d\n", nr);
935 for (i = 0; i < CQ_NLEVELS ; i++)
936 fprintf(stderr,
" level %d: %d\n", i, rc[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 < CQ_NLEVELS; 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 == CQ_NLEVELS - 1) {
1213 *pindex = cqcsub->index;
1214 *prval = cqcsub->rc;
1215 *pgval = cqcsub->gc;
1216 *pbval = cqcsub->bc;
1223 for (level = 2; level < CQ_NLEVELS; 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 == CQ_NLEVELS - 1) {
1237 *pindex = cqcsub->index;
1262 l_int32 level, ncells, i;
1266 PROCNAME(
"cqcellTreeCreate");
1269 if ((cqcaa = (
CQCELL ***)LEPT_CALLOC(CQ_NLEVELS + 1,
sizeof(
CQCELL **)))
1271 return (
CQCELL ***)ERROR_PTR(
"cqcaa not made", procName, NULL);
1272 for (level = 0; level <= CQ_NLEVELS; level++) {
1273 ncells = 1 << (3 * level);
1274 if ((cqca = (
CQCELL **)LEPT_CALLOC(ncells,
sizeof(
CQCELL *))) == NULL) {
1276 return (
CQCELL ***)ERROR_PTR(
"cqca not made", procName, NULL);
1278 cqcaa[level] = cqca;
1279 for (i = 0; i < ncells; i++) {
1280 if ((cqca[i] = (
CQCELL *)LEPT_CALLOC(1,
sizeof(
CQCELL))) == NULL) {
1282 return (
CQCELL ***)ERROR_PTR(
"cqc not made", procName, NULL);
1299 l_int32 level, ncells, i;
1303 PROCNAME(
"cqcellTreeDestroy");
1305 if (pcqcaa == NULL) {
1306 L_WARNING(
"ptr address is NULL\n", procName);
1310 if ((cqcaa = *pcqcaa) == NULL)
1313 for (level = 0; level <= CQ_NLEVELS; level++) {
1314 cqca = cqcaa[level];
1315 ncells = 1 << (3 * level);
1316 for (i = 0; i < ncells; i++)
1367 l_uint32 *rtab, *gtab, *btab;
1369 PROCNAME(
"makeRGBToIndexTables");
1371 if (cqlevels < 1 || cqlevels > 6)
1372 return ERROR_INT(
"cqlevels must be in {1,...6}", procName, 1);
1374 if (!prtab || !pgtab || !pbtab)
1375 return ERROR_INT(
"not all &tabs defined", procName, 1);
1376 rtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1377 gtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1378 btab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
1379 if (!rtab || !gtab || !btab)
1380 return ERROR_INT(
"calloc fail for tab", procName, 1);
1388 for (i = 0; i < 256; i++) {
1389 rtab[i] = (i >> 5) & 0x0004;
1390 gtab[i] = (i >> 6) & 0x0002;
1395 for (i = 0; i < 256; i++) {
1396 rtab[i] = ((i >> 2) & 0x0020) | ((i >> 4) & 0x0004);
1397 gtab[i] = ((i >> 3) & 0x0010) | ((i >> 5) & 0x0002);
1398 btab[i] = ((i >> 4) & 0x0008) | ((i >> 6) & 0x0001);
1402 for (i = 0; i < 256; i++) {
1403 rtab[i] = ((i << 1) & 0x0100) | ((i >> 1) & 0x0020) |
1404 ((i >> 3) & 0x0004);
1405 gtab[i] = (i & 0x0080) | ((i >> 2) & 0x0010) |
1406 ((i >> 4) & 0x0002);
1407 btab[i] = ((i >> 1) & 0x0040) | ((i >> 3) & 0x0008) |
1408 ((i >> 5) & 0x0001);
1412 for (i = 0; i < 256; i++) {
1413 rtab[i] = ((i << 4) & 0x0800) | ((i << 2) & 0x0100) |
1414 (i & 0x0020) | ((i >> 2) & 0x0004);
1415 gtab[i] = ((i << 3) & 0x0400) | ((i << 1) & 0x0080) |
1416 ((i >> 1) & 0x0010) | ((i >> 3) & 0x0002);
1417 btab[i] = ((i << 2) & 0x0200) | (i & 0x0040) |
1418 ((i >> 2) & 0x0008) | ((i >> 4) & 0x0001);
1422 for (i = 0; i < 256; i++) {
1423 rtab[i] = ((i << 7) & 0x4000) | ((i << 5) & 0x0800) |
1424 ((i << 3) & 0x0100) | ((i << 1) & 0x0020) |
1425 ((i >> 1) & 0x0004);
1426 gtab[i] = ((i << 6) & 0x2000) | ((i << 4) & 0x0400) |
1427 ((i << 2) & 0x0080) | (i & 0x0010) |
1428 ((i >> 2) & 0x0002);
1429 btab[i] = ((i << 5) & 0x1000) | ((i << 3) & 0x0200) |
1430 ((i << 1) & 0x0040) | ((i >> 1) & 0x0008) |
1431 ((i >> 3) & 0x0001);
1435 for (i = 0; i < 256; i++) {
1436 rtab[i] = ((i << 10) & 0x20000) | ((i << 8) & 0x4000) |
1437 ((i << 6) & 0x0800) | ((i << 4) & 0x0100) |
1438 ((i << 2) & 0x0020) | (i & 0x0004);
1439 gtab[i] = ((i << 9) & 0x10000) | ((i << 7) & 0x2000) |
1440 ((i << 5) & 0x0400) | ((i << 3) & 0x0080) |
1441 ((i << 1) & 0x0010) | ((i >> 1) & 0x0002);
1442 btab[i] = ((i << 8) & 0x8000) | ((i << 6) & 0x1000) |
1443 ((i << 4) & 0x0200) | ((i << 2) & 0x0040) |
1444 (i & 0x0008) | ((i >> 2) & 0x0001);
1448 ERROR_INT(
"cqlevels not in [1...6]", procName, 1);
1478 *pindex = rtab[rval] | gtab[gval] | btab[bval];
1526 rgbindex = cubeindex << (3 * (7 - level));
1527 rgbindex |= (0x7 << (3 * (6 - level)));
1530 *prval = ((rgbindex >> 13) & 0x80) |
1531 ((rgbindex >> 11) & 0x40) |
1532 ((rgbindex >> 9) & 0x20) |
1533 ((rgbindex >> 7) & 0x10) |
1534 ((rgbindex >> 5) & 0x08) |
1535 ((rgbindex >> 3) & 0x04) |
1536 ((rgbindex >> 1) & 0x02);
1537 *pgval = ((rgbindex >> 12) & 0x80) |
1538 ((rgbindex >> 10) & 0x40) |
1539 ((rgbindex >> 8) & 0x20) |
1540 ((rgbindex >> 6) & 0x10) |
1541 ((rgbindex >> 4) & 0x08) |
1542 ((rgbindex >> 2) & 0x04) |
1544 *pbval = ((rgbindex >> 11) & 0x80) |
1545 ((rgbindex >> 9) & 0x40) |
1546 ((rgbindex >> 7) & 0x20) |
1547 ((rgbindex >> 5) & 0x10) |
1548 ((rgbindex >> 3) & 0x08) |
1549 ((rgbindex >> 1) & 0x04) |
1550 ((rgbindex << 1) & 0x02);
1598 PROCNAME(
"getOctcubeIndex");
1600 if (level < 0 || level > CQ_NLEVELS - 1)
1601 return ERROR_INT(
"level must be in e.g., [0 ... 5]", procName, 1);
1603 return ERROR_INT(
"&bindex not defined", procName, 1);
1605 return ERROR_INT(
"&sindex not defined", procName, 1);
1607 *pbindex = rgbindex >> (3 * (CQ_NLEVELS - level));
1608 *psindex = rgbindex >> (3 * (CQ_NLEVELS - 1 - level));
1630 PROCNAME(
"octcubeGetCount");
1633 return ERROR_INT(
"&size not defined", procName, 1);
1634 if (level < 1 || level > 6)
1635 return ERROR_INT(
"invalid level", procName, 1);
1637 *psize = 1 << (3 * level);
1705 l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
1706 l_int32 rval, gval, bval;
1707 l_int32 *rarray, *garray, *barray, *narray, *iarray;
1708 l_uint32 octindex, octindex2;
1709 l_uint32 *rtab, *gtab, *btab, *rtab2, *gtab2, *btab2;
1710 l_uint32 *lines, *lined, *datas, *datad;
1716 PROCNAME(
"pixOctreeQuantByPopulation");
1719 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
1720 if (pixGetDepth(pixs) != 32)
1721 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
1722 if (level == 0) level = 4;
1723 if (level < 3 || level > 4)
1724 return (
PIX *)ERROR_PTR(
"level not in {3,4}", procName, NULL);
1728 if (w < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE && ditherflag == 1) {
1729 L_INFO(
"Small image: dithering turned off\n", procName);
1734 return (
PIX *)ERROR_PTR(
"size not returned", procName, NULL);
1735 rtab = gtab = btab = NULL;
1739 narray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1740 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1741 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1742 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1743 if (!narray || !rarray || !garray || !barray)
1748 wpls = pixGetWpl(pixs);
1749 for (i = 0; i < h; i++) {
1750 lines = datas + i * wpls;
1751 for (j = 0; j < w; j++) {
1753 octindex = rtab[rval] | gtab[gval] | btab[bval];
1755 rarray[octindex] += rval;
1756 garray[octindex] += gval;
1757 barray[octindex] += bval;
1762 for (i = 0, ncolors = 0; i < size; i++) {
1768 else if (ncolors <= 16)
1774 wpld = pixGetWpl(pixd);
1775 pixCopyResolution(pixd, pixs);
1776 pixCopyInputFormat(pixd, pixs);
1781 for (i = 0; i < size; i++) {
1782 if (narray[i] > 0) {
1783 rarray[i] /= narray[i];
1784 garray[i] /= narray[i];
1785 barray[i] /= narray[i];
1791 if (ncolors <= 256) {
1792 for (i = 0, index = 0; i < size; i++) {
1793 if (narray[i] > 0) {
1795 narray[i] = index + 1;
1801 for (i = 0; i < h; i++) {
1802 lines = datas + i * wpls;
1803 lined = datad + i * wpld;
1804 for (j = 0; j < w; j++) {
1806 octindex = rtab[rval] | gtab[gval] | btab[bval];
1819 L_WARNING(
"shouldn't get here\n", procName);
1828 for (i = 0; i < size; i++) {
1829 if (narray[i] > 0) {
1831 opop->npix = (l_float32)narray[i];
1833 opop->rval = rarray[i];
1834 opop->gval = garray[i];
1835 opop->bval = barray[i];
1842 iarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
1843 for (i = 0; i < 192; i++) {
1847 iarray[opop->index] = i + 1;
1850 fprintf(stderr,
"i = %d, n = %6.0f, (r,g,b) = (%d %d %d)\n",
1851 i, opop->npix, opop->rval, opop->gval, opop->bval);
1858 rtab2 = gtab2 = btab2 = NULL;
1860 for (i = 0; i < 64; i++) {
1871 for (i = 192; i < size; i++) {
1877 octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
1878 narray[octindex2] += (l_int32)opop->npix;
1879 rarray[octindex2] += (l_int32)opop->npix * rval;
1880 garray[octindex2] += (l_int32)opop->npix * gval;
1881 barray[octindex2] += (l_int32)opop->npix * bval;
1882 iarray[opop->index] = 192 + octindex2 + 1;
1893 for (i = 0; i < size; i++) {
1894 if (iarray[i] == 0) {
1896 octindex2 = rtab2[rval] | gtab2[gval] | btab2[bval];
1897 iarray[i] = 192 + octindex2 + 1;
1907 for (i = 0; i < 64; i++) {
1908 if (narray[i] > 0) {
1909 rarray[i] /= narray[i];
1910 garray[i] /= narray[i];
1911 barray[i] /= narray[i];
1920 if (ditherflag == 0) {
1921 for (i = 0; i < h; i++) {
1922 lines = datas + i * wpls;
1923 lined = datad + i * wpld;
1924 for (j = 0; j < w; j++) {
1926 octindex = rtab[rval] | gtab[gval] | btab[bval];
1932 iarray, POP_DIF_CAP);
1936 for (i = 0; i < size / 16; i++) {
1938 for (j = 0; j < 16; j++)
1939 fprintf(stderr,
"%d ", iarray[16 * i + j]);
1940 fprintf(stderr,
"\n");
2000 l_uint8 *bufu8r, *bufu8g, *bufu8b;
2001 l_int32 i, j, w, h, wpld, octindex, cmapindex, success;
2002 l_int32 rval, gval, bval, rc, gc, bc;
2003 l_int32 dif, val1, val2, val3;
2004 l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
2005 l_uint32 *datad, *lined;
2008 PROCNAME(
"pixDitherOctindexWithCmap");
2010 if (!pixs || pixGetDepth(pixs) != 32)
2011 return ERROR_INT(
"pixs undefined or not 32 bpp", procName, 1);
2012 if (!pixd || pixGetDepth(pixd) != 8)
2013 return ERROR_INT(
"pixd undefined or not 8 bpp", procName, 1);
2014 if ((cmap = pixGetColormap(pixd)) == NULL)
2015 return ERROR_INT(
"pixd not cmapped", procName, 1);
2016 if (!rtab || !gtab || !btab || !indexmap)
2017 return ERROR_INT(
"not all 4 tables defined", procName, 1);
2019 if (pixGetWidth(pixd) != w || pixGetHeight(pixd) != h)
2020 return ERROR_INT(
"pixs and pixd not same size", procName, 1);
2023 bufu8r = bufu8g = bufu8b = NULL;
2024 buf1r = buf1g = buf1b = buf2r = buf2g = buf2b = NULL;
2025 bufu8r = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
2026 bufu8g = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
2027 bufu8b = (l_uint8 *)LEPT_CALLOC(w,
sizeof(l_uint8));
2028 buf1r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2029 buf1g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2030 buf1b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2031 buf2r = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2032 buf2g = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2033 buf2b = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2034 if (!bufu8r || !bufu8g || !bufu8b || !buf1r || !buf1g ||
2035 !buf1b || !buf2r || !buf2g || !buf2b) {
2036 L_ERROR(
"buffer not made\n", procName);
2038 goto buffer_cleanup;
2043 for (j = 0; j < w; j++) {
2044 buf2r[j] = 64 * bufu8r[j];
2045 buf2g[j] = 64 * bufu8g[j];
2046 buf2b[j] = 64 * bufu8b[j];
2050 wpld = pixGetWpl(pixd);
2051 for (i = 0; i < h - 1; i++) {
2053 memcpy(buf1r, buf2r, 4 * w);
2054 memcpy(buf1g, buf2g, 4 * w);
2055 memcpy(buf1b, buf2b, 4 * w);
2057 for (j = 0; j < w; j++) {
2058 buf2r[j] = 64 * bufu8r[j];
2059 buf2g[j] = 64 * bufu8g[j];
2060 buf2b[j] = 64 * bufu8b[j];
2064 lined = datad + i * wpld;
2065 for (j = 0; j < w - 1; j++) {
2066 rval = buf1r[j] / 64;
2067 gval = buf1g[j] / 64;
2068 bval = buf1b[j] / 64;
2069 octindex = rtab[rval] | gtab[gval] | btab[bval];
2070 cmapindex = indexmap[octindex] - 1;
2074 dif = buf1r[j] / 8 - 8 * rc;
2076 if (dif > difcap) dif = difcap;
2077 if (dif < -difcap) dif = -difcap;
2080 val1 = buf1r[j + 1] + 3 * dif;
2081 val2 = buf2r[j] + 3 * dif;
2082 val3 = buf2r[j + 1] + 2 * dif;
2084 buf1r[j + 1] = L_MIN(16383, val1);
2085 buf2r[j] = L_MIN(16383, val2);
2086 buf2r[j + 1] = L_MIN(16383, val3);
2088 buf1r[j + 1] = L_MAX(0, val1);
2089 buf2r[j] = L_MAX(0, val2);
2090 buf2r[j + 1] = L_MAX(0, val3);
2094 dif = buf1g[j] / 8 - 8 * gc;
2096 if (dif > difcap) dif = difcap;
2097 if (dif < -difcap) dif = -difcap;
2100 val1 = buf1g[j + 1] + 3 * dif;
2101 val2 = buf2g[j] + 3 * dif;
2102 val3 = buf2g[j + 1] + 2 * dif;
2104 buf1g[j + 1] = L_MIN(16383, val1);
2105 buf2g[j] = L_MIN(16383, val2);
2106 buf2g[j + 1] = L_MIN(16383, val3);
2108 buf1g[j + 1] = L_MAX(0, val1);
2109 buf2g[j] = L_MAX(0, val2);
2110 buf2g[j + 1] = L_MAX(0, val3);
2114 dif = buf1b[j] / 8 - 8 * bc;
2116 if (dif > difcap) dif = difcap;
2117 if (dif < -difcap) dif = -difcap;
2120 val1 = buf1b[j + 1] + 3 * dif;
2121 val2 = buf2b[j] + 3 * dif;
2122 val3 = buf2b[j + 1] + 2 * dif;
2124 buf1b[j + 1] = L_MIN(16383, val1);
2125 buf2b[j] = L_MIN(16383, val2);
2126 buf2b[j + 1] = L_MIN(16383, val3);
2128 buf1b[j + 1] = L_MAX(0, val1);
2129 buf2b[j] = L_MAX(0, val2);
2130 buf2b[j + 1] = L_MAX(0, val3);
2136 rval = buf1r[w - 1] / 64;
2137 gval = buf1g[w - 1] / 64;
2138 bval = buf1b[w - 1] / 64;
2139 octindex = rtab[rval] | gtab[gval] | btab[bval];
2140 cmapindex = indexmap[octindex] - 1;
2145 lined = datad + (h - 1) * wpld;
2146 for (j = 0; j < w; j++) {
2147 rval = buf2r[j] / 64;
2148 gval = buf2g[j] / 64;
2149 bval = buf2b[j] / 64;
2150 octindex = rtab[rval] | gtab[gval] | btab[bval];
2151 cmapindex = indexmap[octindex] - 1;
2166 return (success) ? 0 : 1;
2267 l_int32 w, h, minside, bpp, wpls, wpld, i, j, actualcolors;
2268 l_int32 rval, gval, bval, nbase, nextra, maxlevel, ncubes, val;
2269 l_int32 *lut1, *lut2;
2271 l_uint32 *lines, *lined, *datas, *datad, *pspixel;
2272 l_uint32 *rtab, *gtab, *btab;
2279 PROCNAME(
"pixOctreeQuantNumColors");
2282 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2283 if (pixGetDepth(pixs) != 32)
2284 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2285 if (maxcolors < 8) {
2286 L_WARNING(
"max colors < 8; setting to 8\n", procName);
2289 if (maxcolors > 256) {
2290 L_WARNING(
"max colors > 256; setting to 256\n", procName);
2296 wpls = pixGetWpl(pixs);
2297 minside = L_MIN(w, h);
2298 if (subsample <= 0) {
2299 subsample = L_MAX(1, minside / 200);
2302 if (maxcolors <= 16) {
2308 nextra = maxcolors - nbase;
2309 }
else if (maxcolors <= 64) {
2315 nextra = maxcolors - nbase;
2322 nextra = maxcolors - nbase;
2325 pixCopyResolution(pixd, pixs);
2326 pixCopyInputFormat(pixd, pixs);
2335 if ((oqca = (
OQCELL **)LEPT_CALLOC(nbase,
sizeof(
OQCELL *))) == NULL) {
2337 return (
PIX *)ERROR_PTR(
"oqca not made", procName, NULL);
2339 for (i = 0; i < nbase; i++) {
2344 rtab = gtab = btab = NULL;
2350 wpld = pixGetWpl(pixd);
2351 for (i = 0; i < h; i++) {
2352 lines = datas + i * wpls;
2353 lined = datad + i * wpld;
2354 for (j = 0; j < w; j++) {
2355 pspixel = lines + j;
2358 rtab, gtab, btab, &index);
2365 oqca[index]->n += 1.0;
2366 oqca[index]->rcum += rval;
2367 oqca[index]->gcum += gval;
2368 oqca[index]->bcum += bval;
2376 for (i = 0; i < nbase; i++) {
2379 oqc->rval = (l_int32)(oqc->rcum / oqc->n);
2380 oqc->gval = (l_int32)(oqc->gcum / oqc->n);
2381 oqc->bval = (l_int32)(oqc->bcum / oqc->n);
2384 &oqc->gval, &oqc->bval);
2389 for (i = 0; i < nbase; i++)
2404 if ((oqca = (
OQCELL **)LEPT_CALLOC(ncubes,
sizeof(
OQCELL *))) == NULL) {
2406 return (
PIX *)ERROR_PTR(
"oqca not made", procName, NULL);
2408 for (i = 0; i < ncubes; i++) {
2415 rtab = gtab = btab = NULL;
2420 for (i = 0; i < h; i += subsample) {
2421 lines = datas + i * wpls;
2422 for (j = 0; j < w; j += subsample) {
2423 pspixel = lines + j;
2426 oqca[index]->n += 1.0;
2427 oqca[index]->octindex = index;
2428 oqca[index]->rcum += rval;
2429 oqca[index]->gcum += gval;
2430 oqca[index]->bcum += bval;
2436 for (i = 0; i < ncubes; i++)
2441 oqca = (
OQCELL **)LEPT_CALLOC(maxcolors,
sizeof(
OQCELL *));
2442 for (i = 0; i < nbase; i++) {
2448 for (i = 0; i < nextra; i++) {
2454 oqca[nbase + i] = oqc;
2462 lut1 = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
2463 for (i = 0; i < nextra; i++)
2464 lut1[oqca[nbase + i]->octindex] = nbase + i;
2465 for (index = 0; index < ncubes; index++) {
2466 if (lut1[index] == 0)
2467 lut1[index] = index >> 3;
2474 wpld = pixGetWpl(pixd);
2475 for (i = 0; i < h; i++) {
2476 lines = datas + i * wpls;
2477 lined = datad + i * wpld;
2478 for (j = 0; j < w; j++) {
2479 pspixel = lines + j;
2495 return (
PIX *)ERROR_PTR(
"bpp not 4 or 8!", procName, NULL);
2498 oqca[val]->n += 1.0;
2499 oqca[val]->rcum += rval;
2500 oqca[val]->gcum += gval;
2501 oqca[val]->bcum += bval;
2508 lut2 = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
2511 for (i = 0, index = 0; i < maxcolors; i++) {
2516 oqc->rval = (l_int32)(oqc->rcum / oqc->n);
2517 oqc->gval = (l_int32)(oqc->gcum / oqc->n);
2518 oqc->bval = (l_int32)(oqc->bcum / oqc->n);
2528 if (actualcolors < maxcolors) {
2529 for (i = 0; i < h; i++) {
2530 lined = datad + i * wpld;
2531 for (j = 0; j < w; j++) {
2547 for (i = 0; i < maxcolors; i++)
2598 l_int32 w, h, wpls, wpld, i, j, size, octlevels;
2599 l_int32 rval, gval, bval, del, val, midval;
2600 l_int32 *carray, *rarray, *garray, *barray;
2603 l_uint32 *rtab, *gtab, *btab;
2604 l_uint32 *lines, *lined, *datas, *datad;
2608 PROCNAME(
"pixOctcubeQuantMixedWithGray");
2611 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2612 if (pixGetDepth(pixs) != 32)
2613 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2615 return (
PIX *)ERROR_PTR(
"invalid graylevels", procName, NULL);
2620 return (
PIX *)ERROR_PTR(
"max 8 gray levels", procName, NULL);
2621 }
else if (depth == 8) {
2624 if (graylevels > 192)
2625 return (
PIX *)ERROR_PTR(
"max 192 gray levels", procName, NULL);
2627 return (
PIX *)ERROR_PTR(
"output depth not 4 or 8 bpp", procName, NULL);
2633 rtab = gtab = btab = NULL;
2637 carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2638 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2639 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2640 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2644 if (!rtab || !gtab || !btab ||
2645 !carray || !rarray || !garray || !barray || !tabval) {
2646 L_ERROR(
"calloc fail for an array\n", procName);
2652 if ((pixd =
pixCreate(w, h, depth)) == NULL) {
2653 L_ERROR(
"pixd not made\n", procName);
2656 pixCopyResolution(pixd, pixs);
2657 pixCopyInputFormat(pixd, pixs);
2659 for (j = 0; j < size; j++)
2661 for (j = 0; j < graylevels; j++) {
2662 val = (255 * j) / (graylevels - 1);
2666 wpld = pixGetWpl(pixd);
2672 wpls = pixGetWpl(pixs);
2673 for (i = 0; i < h; i++) {
2674 lines = datas + i * wpls;
2675 lined = datad + i * wpld;
2676 for (j = 0; j < w; j++) {
2682 }
else if (rval > bval) {
2693 }
else if (gval > bval) {
2702 octindex = rtab[rval] | gtab[gval] | btab[bval];
2704 rarray[octindex] += rval;
2705 garray[octindex] += gval;
2706 barray[octindex] += bval;
2712 val = size + tabval[midval];
2722 for (i = 0; i < size; i++) {
2723 if (carray[i] > 0) {
2724 rarray[i] /= carray[i];
2725 garray[i] /= carray[i];
2726 barray[i] /= carray[i];
2816 l_int32 rval, gval, bval;
2817 l_int32 w, h, wpls, wpld, i, j, cindex;
2818 l_uint32 *rtab, *gtab, *btab;
2820 l_uint32 *datas, *datad, *lines, *lined;
2824 PROCNAME(
"pixFixedOctcubeQuant256");
2827 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2828 if (pixGetDepth(pixs) != 32)
2829 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2833 if (w < MIN_DITHER_SIZE && h < MIN_DITHER_SIZE && ditherflag == 1) {
2834 L_INFO(
"Small image: dithering turned off\n", procName);
2847 for (cindex = 0; cindex < 256; cindex++) {
2848 rval = (cindex & 0xe0) | 0x10;
2849 gval = ((cindex << 3) & 0xe0) | 0x10;
2850 bval = ((cindex << 6) & 0xc0) | 0x20;
2856 wpls = pixGetWpl(pixs);
2857 if ((pixd =
pixCreate(w, h, 8)) == NULL) {
2859 return (
PIX *)ERROR_PTR(
"pixd not made", procName, NULL);
2862 pixCopyResolution(pixd, pixs);
2863 pixCopyInputFormat(pixd, pixs);
2865 wpld = pixGetWpl(pixd);
2868 if (ditherflag == 0) {
2869 for (i = 0; i < h; i++) {
2870 lines = datas + i * wpls;
2871 lined = datad + i * wpld;
2872 for (j = 0; j < w; j++) {
2874 index = (rval & 0xe0) | ((gval >> 3) & 0x1c) | (bval >> 6);
2886 rtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2887 gtab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2888 btab = (l_uint32 *)LEPT_CALLOC(256,
sizeof(l_uint32));
2889 itab = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
2890 if (!rtab || !gtab || !btab || !itab) {
2892 return (
PIX *)ERROR_PTR(
"calloc fail for table", procName, NULL);
2894 for (i = 0; i < 256; i++) {
2896 gtab[i] = (i >> 3) & 0x1c;
2949 l_int32 w, h, wpls, wpld, i, j, depth, size, ncolors, index;
2950 l_int32 rval, gval, bval;
2951 l_int32 *carray, *rarray, *garray, *barray;
2953 l_uint32 *rtab, *gtab, *btab;
2954 l_uint32 *lines, *lined, *datas, *datad, *pspixel;
2958 PROCNAME(
"pixFewColorsOctcubeQuant1");
2961 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
2962 if (pixGetDepth(pixs) != 32)
2963 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
2964 if (level < 1 || level > 6)
2965 return (
PIX *)ERROR_PTR(
"invalid level", procName, NULL);
2970 return (
PIX *)ERROR_PTR(
"size not returned", procName, NULL);
2971 rtab = gtab = btab = NULL;
2974 carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2975 rarray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2976 garray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2977 barray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32));
2978 if (!carray || !rarray || !garray || !barray) {
2979 L_ERROR(
"calloc fail for an array\n", procName);
2986 wpls = pixGetWpl(pixs);
2987 for (i = 0; i < h; i++) {
2988 lines = datas + i * wpls;
2989 for (j = 0; j < w; j++) {
2990 pspixel = lines + j;
2992 octindex = rtab[rval] | gtab[gval] | btab[bval];
2994 rarray[octindex] += rval;
2995 garray[octindex] += gval;
2996 barray[octindex] += bval;
3001 for (i = 0, ncolors = 0; i < size; i++) {
3005 if (ncolors > 256) {
3006 L_WARNING(
"%d colors found; more than 256\n", procName, ncolors);
3011 else if (ncolors <= 16)
3019 for (i = 0, index = 0; i < size; i++) {
3020 if (carray[i] > 0) {
3021 rarray[i] /= carray[i];
3022 garray[i] /= carray[i];
3023 barray[i] /= carray[i];
3025 carray[i] = index + 1;
3032 pixCopyResolution(pixd, pixs);
3033 pixCopyInputFormat(pixd, pixs);
3035 wpld = pixGetWpl(pixd);
3036 for (i = 0; i < h; i++) {
3037 lines = datas + i * wpls;
3038 lined = datad + i * wpld;
3039 for (j = 0; j < w; j++) {
3040 pspixel = lines + j;
3042 octindex = rtab[rval] | gtab[gval] | btab[bval];
3055 L_WARNING(
"shouldn't get here\n", procName);
3122 l_int32 w, h, wpls, wpld, i, j, nerrors;
3123 l_int32 ncubes, depth, cindex, oval;
3124 l_int32 rval, gval, bval;
3127 l_uint32 *rtab, *gtab, *btab;
3128 l_uint32 *lines, *lined, *datas, *datad, *ppixel;
3129 l_uint32 *colorarray;
3133 PROCNAME(
"pixFewColorsOctcubeQuant2");
3136 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3137 if (pixGetDepth(pixs) != 32)
3138 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3139 if (level < 3 || level > 6)
3140 return (
PIX *)ERROR_PTR(
"level not in {4, 5, 6}", procName, NULL);
3142 return (
PIX *)ERROR_PTR(
"ncolors > 256", procName, NULL);
3150 rtab = gtab = btab = NULL;
3155 octarray = (l_int32 *)LEPT_CALLOC(ncubes,
sizeof(l_int32));
3160 colorarray = (l_uint32 *)LEPT_CALLOC(ncolors + 1,
sizeof(l_uint32));
3161 if (!octarray || !colorarray) {
3162 L_ERROR(
"octarray or colorarray not made\n", procName);
3163 goto cleanup_arrays;
3169 wpls = pixGetWpl(pixs);
3172 else if (ncolors <= 16)
3177 if ((pixd =
pixCreate(w, h, depth)) == NULL) {
3178 L_ERROR(
"pixd not made\n", procName);
3179 goto cleanup_arrays;
3181 pixCopyResolution(pixd, pixs);
3182 pixCopyInputFormat(pixd, pixs);
3184 wpld = pixGetWpl(pixd);
3196 for (i = 0; i < h; i++) {
3197 lines = datas + i * wpls;
3198 lined = datad + i * wpld;
3199 for (j = 0; j < w; j++) {
3202 octindex = rtab[rval] | gtab[gval] | btab[bval];
3203 oval = octarray[octindex];
3205 octarray[octindex] = cindex;
3206 colorarray[cindex] = *ppixel;
3211 if (colorarray[oval] != *ppixel)
3217 *pnerrors = nerrors;
3219 #if DEBUG_FEW_COLORS 3220 fprintf(stderr,
"ncubes = %d, ncolors = %d\n", ncubes, ncolors);
3221 for (i = 0; i < ncolors; i++)
3222 fprintf(stderr,
"color[%d] = %x\n", i, colorarray[i + 1]);
3227 for (i = 0; i < ncolors; i++) {
3228 ppixel = colorarray + i + 1;
3235 LEPT_FREE(octarray);
3236 LEPT_FREE(colorarray);
3308 l_int32 lightthresh,
3313 l_int32 i, j, w, h, wplc, wplm, wpld, ncolors, index;
3314 l_int32 rval, gval, bval, val, minval, maxval;
3316 l_uint32 *datac, *datam, *datad, *linec, *linem, *lined;
3317 PIX *pixc, *pixm, *pixg, *pixd;
3320 PROCNAME(
"pixFewColorsOctcubeQuantMixed");
3322 if (!pixs || pixGetDepth(pixs) != 32)
3323 return (
PIX *)ERROR_PTR(
"pixs undefined or not 32 bpp", procName, NULL);
3324 if (level <= 0) level = 3;
3326 return (
PIX *)ERROR_PTR(
"invalid level", procName, NULL);
3327 if (darkthresh <= 0) darkthresh = 20;
3328 if (lightthresh <= 0) lightthresh = 244;
3329 if (diffthresh <= 0) diffthresh = 20;
3330 if (minfract <= 0.0) minfract = 0.05;
3331 if (maxspan <= 2) maxspan = 15;
3335 return (
PIX *)ERROR_PTR(
"too many colors", procName, NULL);
3339 cmap = pixGetColormap(pixc);
3342 lut = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
3343 for (i = 0; i < 256; i++)
3345 for (i = 0, index = 0; i < ncolors; i++) {
3347 minval = L_MIN(rval, gval);
3348 minval = L_MIN(minval, bval);
3349 if (minval > lightthresh)
3351 maxval = L_MAX(rval, gval);
3352 maxval = L_MAX(maxval, bval);
3353 if (maxval < darkthresh)
3357 if (maxval - minval >= diffthresh) {
3374 wplc = pixGetWpl(pixc);
3375 wplm = pixGetWpl(pixm);
3376 wpld = pixGetWpl(pixd);
3377 for (i = 0; i < h; i++) {
3378 linec = datac + i * wplc;
3379 linem = datam + i * wplm;
3380 lined = datad + i * wpld;
3381 for (j = 0; j < w; j++) {
3426 l_int32 w, h, wpls, wpld, i, j;
3427 l_int32 rval, gval, bval;
3429 l_uint32 *rtab, *gtab, *btab;
3430 l_uint32 *lines, *lined, *datas, *datad;
3433 PROCNAME(
"pixFixedOctcubeQuantGenRGB");
3436 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3437 if (pixGetDepth(pixs) != 32)
3438 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3439 if (level < 1 || level > 6)
3440 return (
PIX *)ERROR_PTR(
"level not in {1,...6}", procName, NULL);
3443 return (
PIX *)ERROR_PTR(
"tables not made", procName, NULL);
3447 pixCopyResolution(pixd, pixs);
3448 pixCopyInputFormat(pixd, pixs);
3450 wpld = pixGetWpl(pixd);
3452 wpls = pixGetWpl(pixs);
3453 for (i = 0; i < h; i++) {
3454 lines = datas + i * wpls;
3455 lined = datad + i * wpld;
3456 for (j = 0; j < w; j++) {
3458 octindex = rtab[rval] | gtab[gval] | btab[bval];
3504 PROCNAME(
"pixQuantFromCmap");
3507 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3508 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3509 return (
PIX *)ERROR_PTR(
"invalid mindepth", procName, NULL);
3510 d = pixGetDepth(pixs);
3517 return (
PIX *)ERROR_PTR(
"d not 8 or 32 bpp", procName, NULL);
3592 l_uint32 *rtab, *gtab, *btab;
3595 PROCNAME(
"pixOctcubeQuantFromCmap");
3598 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3599 if (pixGetDepth(pixs) != 32)
3600 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3602 return (
PIX *)ERROR_PTR(
"cmap not defined", procName, NULL);
3603 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3604 return (
PIX *)ERROR_PTR(
"invalid mindepth", procName, NULL);
3605 if (level < 1 || level > 6)
3606 return (
PIX *)ERROR_PTR(
"level not in {1...6}", procName, NULL);
3608 return (
PIX *)ERROR_PTR(
"invalid metric", procName, NULL);
3611 rtab = gtab = btab = NULL;
3616 cmaptab, rtab, gtab, btab);
3659 l_int32 i, j, w, h, depth, wpls, wpld;
3660 l_int32 rval, gval, bval, index;
3662 l_uint32 *lines, *lined, *datas, *datad;
3666 PROCNAME(
"pixOctcubeQuantFromCmapLUT");
3669 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
3670 if (pixGetDepth(pixs) != 32)
3671 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3673 return (
PIX *)ERROR_PTR(
"cmap not defined", procName, NULL);
3674 if (mindepth != 2 && mindepth != 4 && mindepth != 8)
3675 return (
PIX *)ERROR_PTR(
"invalid mindepth", procName, NULL);
3676 if (!rtab || !gtab || !btab || !cmaptab)
3677 return (
PIX *)ERROR_PTR(
"tables not all defined", procName, NULL);
3681 depth = L_MAX(depth, mindepth);
3683 if ((pixd =
pixCreate(w, h, depth)) == NULL)
3684 return (
PIX *)ERROR_PTR(
"pixd not made", procName, NULL);
3687 pixCopyResolution(pixd, pixs);
3688 pixCopyInputFormat(pixd, pixs);
3693 wpls = pixGetWpl(pixs);
3694 wpld = pixGetWpl(pixd);
3695 for (i = 0; i < h; i++) {
3696 lines = datas + i * wpls;
3697 lined = datad + i * wpld;
3698 for (j = 0; j < w; j++) {
3704 index = cmaptab[octindex];
3707 else if (depth == 4)
3739 l_int32 size, i, j, w, h, wpl, ncolors, val;
3740 l_int32 rval, gval, bval;
3742 l_uint32 *rtab, *gtab, *btab;
3743 l_uint32 *data, *line;
3747 PROCNAME(
"pixOctcubeHistogram");
3749 if (pncolors) *pncolors = 0;
3751 return (
NUMA *)ERROR_PTR(
"pixs not defined", procName, NULL);
3752 if (pixGetDepth(pixs) != 32)
3753 return (
NUMA *)ERROR_PTR(
"pixs not 32 bpp", procName, NULL);
3756 wpl = pixGetWpl(pixs);
3760 return (
NUMA *)ERROR_PTR(
"size not returned", procName, NULL);
3761 rtab = gtab = btab = NULL;
3765 L_ERROR(
"na not made\n", procName);
3766 goto cleanup_arrays;
3771 for (i = 0; i < h; i++) {
3772 line = data + i * wpl;
3773 for (j = 0; j < w; j++) {
3775 octindex = rtab[rval] | gtab[gval] | btab[bval];
3777 if ((level == 1 && octindex > 7) ||
3778 (level == 2 && octindex > 63) ||
3779 (level == 3 && octindex > 511) ||
3780 (level == 4 && octindex > 4097) ||
3781 (level == 5 && octindex > 32783) ||
3782 (level == 6 && octindex > 262271)) {
3783 fprintf(stderr,
"level = %d, octindex = %d, index error!\n",
3788 array[octindex] += 1.0;
3793 for (i = 0, ncolors = 0; i < size; i++) {
3798 *pncolors = ncolors;
3862 l_int32 i, k, size, ncolors, mindist, dist, mincolor, index;
3863 l_int32 rval, gval, bval;
3864 l_int32 *rmap, *gmap, *bmap, *tab;
3866 PROCNAME(
"pixcmapToOctcubeLUT");
3869 return (l_int32 *)ERROR_PTR(
"cmap not defined", procName, NULL);
3870 if (level < 1 || level > 6)
3871 return (l_int32 *)ERROR_PTR(
"level not in {1...6}", procName, NULL);
3873 return (l_int32 *)ERROR_PTR(
"invalid metric", procName, NULL);
3876 return (l_int32 *)ERROR_PTR(
"size not returned", procName, NULL);
3877 if ((tab = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL)
3878 return (l_int32 *)ERROR_PTR(
"tab not allocated", procName, NULL);
3884 for (i = 0; i < size; i++) {
3888 for (k = 0; k < ncolors; k++) {
3890 dist = L_ABS(rval - rmap[k]) + L_ABS(gval - gmap[k]) +
3891 L_ABS(bval - bmap[k]);
3893 dist = (rval - rmap[k]) * (rval - rmap[k]) +
3894 (gval - gmap[k]) * (gval - gmap[k]) +
3895 (bval - bmap[k]) * (bval - bmap[k]);
3897 if (dist < mindist) {
3910 if (rval < 7 && gval < 7 && bval < 7) {
3915 if (rval > 248 && gval > 248 && bval > 248) {
3916 tab[(1 << (3 * level)) - 1] = index;
3946 l_int32 i, j, w, h, d, nc, wpls, val, newval, index, zerofound;
3947 l_int32 rval, gval, bval;
3948 l_uint32 *datas, *lines;
3949 l_int32 *histo, *map1, *map2;
3952 PROCNAME(
"pixRemoveUnusedColors");
3955 return ERROR_INT(
"pixs not defined", procName, 1);
3956 if ((cmap = pixGetColormap(pixs)) == NULL)
3959 d = pixGetDepth(pixs);
3960 if (d != 2 && d != 4 && d != 8)
3961 return ERROR_INT(
"d not in {2, 4, 8}", procName, 1);
3965 if ((histo = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32))) == NULL)
3966 return ERROR_INT(
"histo not made", procName, 1);
3968 wpls = pixGetWpl(pixs);
3970 for (i = 0; i < h; i++) {
3971 lines = datas + i * wpls;
3972 for (j = 0; j < w; j++) {
3986 return ERROR_INT(
"switch ran off end!", procName, 1);
3989 L_WARNING(
"cmap index out of bounds!\n", procName);
3998 for (i = 0; i < nc; i++) {
3999 if (histo[i] == 0) {
4010 map1 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
4011 map2 = (l_int32 *)LEPT_CALLOC(nc,
sizeof(l_int32));
4013 for (i = 0; i < nc; i++) {
4014 if (histo[i] != 0) {
4023 for (i = 0; i < index; i++) {
4030 for (i = 0; i < h; i++) {
4031 lines = datas + i * wpls;
4032 for (j = 0; j < w; j++) {
4054 return ERROR_INT(
"switch ran off end!", procName, 1);
4096 l_int32 i, j, w, h, d, wpl, ncolors, size, octindex;
4097 l_int32 rval, gval, bval;
4099 l_uint32 *data, *line, *rtab, *gtab, *btab;
4101 PROCNAME(
"pixNumberOccupiedOctcubes");
4104 return ERROR_INT(
"&ncolors not defined", procName, 1);
4107 return ERROR_INT(
"pix not defined", procName, 1);
4110 return ERROR_INT(
"pix not 32 bpp", procName, 1);
4111 if (level < 1 || level > 6)
4112 return ERROR_INT(
"invalid level", procName, 1);
4113 if ((mincount < 0 && minfract < 0) || (mincount >= 0.0 && minfract >= 0.0))
4114 return ERROR_INT(
"invalid mincount/minfract", procName, 1);
4115 if (mincount == 0 || minfract == 0.0)
4117 else if (minfract > 0.0)
4118 mincount = L_MIN(1, (l_int32)(minfract * w * h));
4121 return ERROR_INT(
"size not returned", procName, 1);
4122 rtab = gtab = btab = NULL;
4124 if ((carray = (l_int32 *)LEPT_CALLOC(size,
sizeof(l_int32))) == NULL) {
4125 L_ERROR(
"carray not made\n", procName);
4126 goto cleanup_arrays;
4131 wpl = pixGetWpl(pix);
4132 for (i = 0; i < h; i++) {
4133 line = data + i * wpl;
4134 for (j = 0; j < w; j++) {
4136 octindex = rtab[rval] | gtab[gval] | btab[bval];
4142 for (i = 0, ncolors = 0; i < size; i++) {
4143 if (carray[i] >= mincount)
4146 *pncolors = ncolors;
PIX * pixOctreeColorQuant(PIX *pixs, l_int32 colors, l_int32 ditherflag)
pixOctreeColorQuant()
PIX * pixFewColorsOctcubeQuantMixed(PIX *pixs, l_int32 level, l_int32 darkthresh, l_int32 lightthresh, l_int32 diffthresh, l_float32 minfract, l_int32 maxspan)
pixFewColorsOctcubeQuantMixed()
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 lheapAdd(L_HEAP *lh, void *item)
lheapAdd()
l_int32 * pixcmapToOctcubeLUT(PIXCMAP *cmap, l_int32 level, l_int32 metric)
pixcmapToOctcubeLUT()
l_ok pixcmapGetMinDepth(PIXCMAP *cmap, l_int32 *pmindepth)
pixcmapGetMinDepth()
NUMA * pixOctcubeHistogram(PIX *pixs, l_int32 level, l_int32 *pncolors)
pixOctcubeHistogram()
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
PIX * pixGrayQuantFromHisto(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 minfract, l_int32 maxsize)
pixGrayQuantFromHisto()
void setPixelLow(l_uint32 *line, l_int32 x, l_int32 depth, l_uint32 val)
setPixelLow()
l_ok pixcmapGetNearestIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetNearestIndex()
static PIX * pixOctreeQuantizePixels(PIX *pixs, CQCELL ***cqcaa, l_int32 ditherflag)
pixOctreeQuantizePixels()
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
PIX * pixFixedOctcubeQuant256(PIX *pixs, l_int32 ditherflag)
pixFixedOctcubeQuant256()
l_ok makeRGBToIndexTables(l_uint32 **prtab, l_uint32 **pgtab, l_uint32 **pbtab, l_int32 cqlevels)
makeRGBToIndexTables()
static void cqcellTreeDestroy(CQCELL ****pcqcaa)
cqcellTreeDestroy()
static l_int32 octcubeGetCount(l_int32 level, l_int32 *psize)
octcubeGetCount()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
l_ok pixNumberOccupiedOctcubes(PIX *pix, l_int32 level, l_int32 mincount, l_float32 minfract, l_int32 *pncolors)
pixNumberOccupiedOctcubes()
#define SET_DATA_QBIT(pdata, n, val)
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
NUMA * numaCreate(l_int32 n)
numaCreate()
l_int32 * makeGrayQuantIndexTable(l_int32 nlevels)
makeGrayQuantIndexTable()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_ok numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
void lheapDestroy(L_HEAP **plh, l_int32 freeflag)
lheapDestroy()
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
PIX * pixFewColorsOctcubeQuant2(PIX *pixs, l_int32 level, NUMA *na, l_int32 ncolors, l_int32 *pnerrors)
pixFewColorsOctcubeQuant2()
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
static l_int32 pixDitherOctindexWithCmap(PIX *pixs, PIX *pixd, l_uint32 *rtab, l_uint32 *gtab, l_uint32 *btab, l_int32 *carray, l_int32 difcap)
pixDitherOctindexWithCmap()
#define SET_DATA_DIBIT(pdata, n, val)
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
static CQCELL *** cqcellTreeCreate(void)
cqcellTreeCreate()
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
PIX * pixOctcubeQuantFromCmap(PIX *pixs, PIXCMAP *cmap, l_int32 mindepth, l_int32 level, l_int32 metric)
pixOctcubeQuantFromCmap()
l_int32 numaGetCount(NUMA *na)
numaGetCount()
l_ok pixcmapToArrays(PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
void getOctcubeIndexFromRGB(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *rtab, l_uint32 *gtab, l_uint32 *btab, l_uint32 *pindex)
getOctcubeIndexFromRGB()
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
#define SET_DATA_BYTE(pdata, n, val)
#define GET_DATA_QBIT(pdata, n)
L_HEAP * lheapCreate(l_int32 nalloc, l_int32 direction)
lheapCreate()
#define GET_DATA_BYTE(pdata, n)
void * lheapRemove(L_HEAP *lh)
lheapRemove()
PIX * pixClone(PIX *pixs)
pixClone()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok pixGetRGBLine(PIX *pixs, l_int32 row, l_uint8 *bufr, l_uint8 *bufg, l_uint8 *bufb)
pixGetRGBLine()
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
PIX * pixFewColorsOctcubeQuant1(PIX *pixs, l_int32 level)
pixFewColorsOctcubeQuant1()
PIX * pixGrayQuantFromCmap(PIX *pixs, PIXCMAP *cmap, l_int32 mindepth)
pixGrayQuantFromCmap()
void numaDestroy(NUMA **pna)
numaDestroy()
static void getRGBFromOctcube(l_int32 cubeindex, l_int32 level, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
getRGBFromOctcube()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
PIX * pixFixedOctcubeQuantGenRGB(PIX *pixs, l_int32 level)
pixFixedOctcubeQuantGenRGB()
PIX * pixOctreeColorQuantGeneral(PIX *pixs, l_int32 colors, l_int32 ditherflag, l_float32 validthresh, l_float32 colorthresh)
pixOctreeColorQuantGeneral()
PIX * pixOctreeQuantNumColors(PIX *pixs, l_int32 maxcolors, l_int32 subsample)
pixOctreeQuantNumColors()
l_ok pixColorFraction(PIX *pixs, l_int32 darkthresh, l_int32 lightthresh, l_int32 diffthresh, l_int32 factor, l_float32 *ppixfract, l_float32 *pcolorfract)
pixColorFraction()
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
#define GET_DATA_DIBIT(pdata, n)
static l_int32 octreeFindColorCell(l_int32 octindex, CQCELL ***cqcaa, l_int32 *pindex, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
octreeFindColorCell()
l_ok pixRemoveUnusedColors(PIX *pixs)
pixRemoveUnusedColors()
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
static l_int32 getOctcubeIndices(l_int32 rgbindex, l_int32 level, l_int32 *pbindex, l_int32 *psindex)
getOctcubeIndices()
PIX * pixOctreeQuantByPopulation(PIX *pixs, l_int32 level, l_int32 ditherflag)
pixOctreeQuantByPopulation()
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()
PIXCMAP * pixcmapCopy(PIXCMAP *cmaps)
pixcmapCopy()
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
PIX * pixQuantFromCmap(PIX *pixs, PIXCMAP *cmap, l_int32 mindepth, l_int32 level, l_int32 metric)
pixQuantFromCmap()
#define SET_DATA_BIT(pdata, n)
l_ok pixcmapGetRankIntensity(PIXCMAP *cmap, l_float32 rankval, l_int32 *pindex)
pixcmapGetRankIntensity()