325l_int32 i, subsample, histosize, smalln, ncolors, niters, popcolors;
326l_int32 w, h, minside, factor, index, rval, gval, bval;
328l_float32 maxprod, prod, norm, pixfract, colorfract;
334 if (!pixs || pixGetDepth(pixs) != 32)
335 return (
PIX *)ERROR_PTR(
"pixs undefined or not 32 bpp", __func__, NULL);
336 if (maxcolors < 2 || maxcolors > 256)
337 return (
PIX *)ERROR_PTR(
"maxcolors not in [2...256]", __func__, NULL);
338 if (outdepth != 0 && outdepth != 1 && outdepth != 2 && outdepth != 4 &&
340 return (
PIX *)ERROR_PTR(
"outdepth not in {0,1,2,4,8}", __func__, NULL);
341 if (outdepth > 0 && (maxcolors > (1 << outdepth)))
342 return (
PIX *)ERROR_PTR(
"maxcolors > 2^(outdepth)", __func__, NULL);
344 sigbits = DefaultSigBits;
345 else if (sigbits < 5 || sigbits > 6)
346 return (
PIX *)ERROR_PTR(
"sigbits not 5 or 6", __func__, NULL);
355 pixGetDimensions(pixs, &w, &h, NULL);
357 minside = L_MIN(w, h);
358 factor = L_MAX(1, minside / 400);
359 pixColorFraction(pixs, 20, 244, 20, factor, &pixfract, &colorfract);
360 if (pixfract * colorfract < 0.00025) {
361 L_INFO(
"\n Pixel fraction neither white nor black = %6.3f"
362 "\n Color fraction of those pixels = %6.3f"
363 "\n Quantizing in gray\n",
364 __func__, pixfract, colorfract);
365 return pixConvertTo8(pixs, 1);
374 subsample = (l_int32)(sqrt((l_float64)(w * h) / 100000.));
375 subsample = L_MAX(1, L_MIN(maxsub, subsample));
378 histosize = 1 << (3 * sigbits);
383 for (i = 0; i < histosize; i++) {
386 if (ncolors > maxcolors) {
395 else if (ncolors <= 4)
397 else if (ncolors <= 16)
403 histo, histosize, sigbits);
405 histo, histosize, sigbits);
411 if (ditherflag || subsample > 1)
413 0, (1 << sigbits) - 1,
414 0, (1 << sigbits) - 1);
427 popcolors = (l_int32)(FractByPopulation * maxcolors);
429 vbox = (
L_BOX3D *)lheapRemove(lh);
436 L_WARNING(
"vbox1 not defined; shouldn't happen!\n", __func__);
440 vbox1->sortparam = vbox1->npix;
445 vbox2->sortparam = vbox2->npix;
449 if (ncolors >= popcolors)
451 if (niters++ > MaxItersAllowed) {
452 L_WARNING(
"infinite loop; perhaps too few pixels!\n", __func__);
461 for (i = 0; i < lh->
n; i++) {
462 if ((vbox = (
L_BOX3D *)lheapGetElement(lh, i)) == NULL)
464 prod = (l_float32)vbox->npix * (l_float32)vbox->vol;
465 if (prod > maxprod) maxprod = prod;
467 norm = (maxprod == 0) ? 1.0 : 1000000.0 / maxprod;
469 while ((vbox = (
L_BOX3D *)lheapRemove(lh))) {
470 vbox->sortparam = norm * vbox->npix * vbox->vol;
473 lheapDestroy(&lh, TRUE);
478 vbox = (
L_BOX3D *)lheapRemove(lhs);
485 L_WARNING(
"vbox1 not defined; shouldn't happen!\n", __func__);
489 vbox1->sortparam = norm * vbox1->npix * vbox1->vol;
491 lheapAdd(lhs, vbox1);
494 vbox2->sortparam = norm * vbox2->npix * vbox2->vol;
495 lheapAdd(lhs, vbox2);
498 if (ncolors >= maxcolors)
500 if (niters++ > MaxItersAllowed) {
501 L_WARNING(
"infinite loop; perhaps too few pixels!\n", __func__);
509 while ((vbox = (
L_BOX3D *)lheapRemove(lhs))) {
510 vbox->sortparam = vbox->npix;
514 lheapDestroy(&lhs, TRUE);
519 ncolors = pixcmapGetCount(cmap);
522 else if (ncolors <= 4)
524 else if (ncolors <= 16)
530 histo, histosize, sigbits);
533 pixcmapGetRankIntensity(cmap, 0.0, &index);
534 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
535 if (rval < 5 && gval < 5 && bval < 5)
536 pixcmapResetColor(cmap, index, 0, 0, 0);
539 pixcmapGetRankIntensity(cmap, 1.0, &index);
540 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
541 if (rval > 251 && gval > 251 && bval > 251)
542 pixcmapResetColor(cmap, index, 255, 255, 255);
544 lheapDestroy(&lh, TRUE);
602l_int32 i, j, w, h, wplc, wplg, wpld, nc, unused, iscolor, factor, minside;
603l_int32 rval, gval, bval, minval, maxval, val, grayval;
604l_float32 pixfract, colorfract;
606l_uint32 *datac, *datag, *datad, *linec, *lineg, *lined;
607PIX *pixc, *pixg, *pixd;
610 if (!pixs || pixGetDepth(pixs) != 32)
611 return (
PIX *)ERROR_PTR(
"pixs undefined or not 32 bpp", __func__, NULL);
613 return (
PIX *)ERROR_PTR(
"ngray < 2", __func__, NULL);
614 if (ncolor + ngray > 255)
615 return (
PIX *)ERROR_PTR(
"ncolor + ngray > 255", __func__, NULL);
616 if (darkthresh <= 0) darkthresh = 20;
617 if (lightthresh <= 0) lightthresh = 244;
618 if (diffthresh <= 0) diffthresh = 20;
624 pixGetDimensions(pixs, &w, &h, NULL);
625 minside = L_MIN(w, h);
626 factor = L_MAX(1, minside / 400);
627 pixColorFraction(pixs, darkthresh, lightthresh, diffthresh, factor,
628 &pixfract, &colorfract);
629 if (pixfract * colorfract < 0.0001) {
630 L_INFO(
"\n Pixel fraction neither white nor black = %6.3f"
631 "\n Color fraction of those pixels = %6.3f"
632 "\n Quantizing in gray\n",
633 __func__, pixfract, colorfract);
634 pixg = pixConvertTo8(pixs, 0);
635 pixd = pixThresholdOn8bpp(pixg, ngray, 1);
643 pixc = pixCopy(NULL, pixs);
644 pixg = pixCreate(w, h, 8);
645 datac = pixGetData(pixc);
646 datag = pixGetData(pixg);
647 wplc = pixGetWpl(pixc);
648 wplg = pixGetWpl(pixg);
649 lut = (l_int32 *)LEPT_CALLOC(256,
sizeof(l_int32));
650 for (i = 0; i < 256; i++)
651 lut[i] = ncolor + 1 + (i * (ngray - 1) + 128) / 255;
652 for (i = 0; i < h; i++) {
653 linec = datac + i * wplc;
654 lineg = datag + i * wplg;
655 for (j = 0; j < w; j++) {
657 extractRGBValues(linec[j], &rval, &gval, &bval);
658 minval = L_MIN(rval, gval);
659 minval = L_MIN(minval, bval);
660 maxval = L_MAX(rval, gval);
661 maxval = L_MAX(maxval, bval);
662 if (maxval >= darkthresh &&
663 minval <= lightthresh &&
664 maxval - minval >= diffthresh) {
669 grayval = (maxval + minval) / 2;
677 DefaultSigBits, 1, 0);
681 cmap = pixGetColormap(pixd);
682 nc = pixcmapGetCount(cmap);
683 unused = ncolor + 1 - nc;
685 L_ERROR(
"Too many colors: extra = %d\n", __func__, -unused);
687 L_INFO(
"%d unused colors\n", __func__, unused);
688 for (i = 0; i < unused; i++)
689 pixcmapAddColor(cmap, 0, 0, 0);
691 for (i = 0; i < ngray; i++) {
692 grayval = (255 * i) / (ngray - 1);
693 pixcmapAddColor(cmap, grayval, grayval, grayval);
697 datad = pixGetData(pixd);
698 wpld = pixGetWpl(pixd);
699 for (i = 0; i < h; i++) {
700 lined = datad + i * wpld;
701 lineg = datag + i * wplg;
702 for (j = 0; j < w; j++) {
964l_uint8 *bufu8r, *bufu8g, *bufu8b;
965l_int32 i, j, w, h, wpls, wpld, rshift, index, cmapindex, success;
966l_int32 rval, gval, bval, rc, gc, bc;
967l_int32 dif, val1, val2, val3;
968l_int32 *buf1r, *buf1g, *buf1b, *buf2r, *buf2g, *buf2b;
969l_uint32 *datas, *datad, *lines, *lined;
973 if (!pixs || pixGetDepth(pixs) != 32)
974 return (
PIX *)ERROR_PTR(
"pixs not 32 bpp", __func__, NULL);
976 return (
PIX *)ERROR_PTR(
"cmap not defined", __func__, NULL);
978 return (
PIX *)ERROR_PTR(
"indexmap not defined", __func__, NULL);
982 pixGetDimensions(pixs, &w, &h, NULL);
983 pixd = pixCreate(w, h, outdepth);
984 pixSetColormap(pixd, cmap);
985 pixCopyResolution(pixd, pixs);
986 pixCopyInputFormat(pixd, pixs);
987 datas = pixGetData(pixs);
988 datad = pixGetData(pixd);
989 wpls = pixGetWpl(pixs);
990 wpld = pixGetWpl(pixd);
992 rshift = 8 - sigbits;
993 mask = 0xff >> rshift;
994 if (ditherflag == 0) {
995 for (i = 0; i < h; i++) {
996 lines = datas + i * wpls;
997 lined = datad + i * wpld;
999 for (j = 0; j < w; j++) {
1003 if (indexmap[index])
1006 }
else if (outdepth == 2) {
1007 for (j = 0; j < w; j++) {
1013 }
else if (outdepth == 4) {
1014 for (j = 0; j < w; j++) {
1021 for (j = 0; j < w; j++) {
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", __func__);
1046 goto buffer_cleanup;
1050 pixGetRGBLine(pixs, 0, bufu8r, bufu8g, bufu8b);
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);
1062 pixGetRGBLine(pixs, i + 1, bufu8r, bufu8g, bufu8b);
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 index = ((rval >> rshift) << (2 * sigbits)) +
1076 ((gval >> rshift) << sigbits) + (bval >> rshift);
1077 cmapindex = indexmap[index];
1079 pixcmapGetColor(cmap, cmapindex, &rc, &gc, &bc);
1081 dif = buf1r[j] / 8 - 8 * rc;
1082 if (dif > DifCap) dif = DifCap;
1083 if (dif < -DifCap) dif = -DifCap;
1085 val1 = buf1r[j + 1] + 3 * dif;
1086 val2 = buf2r[j] + 3 * dif;
1087 val3 = buf2r[j + 1] + 2 * dif;
1089 buf1r[j + 1] = L_MIN(16383, val1);
1090 buf2r[j] = L_MIN(16383, val2);
1091 buf2r[j + 1] = L_MIN(16383, val3);
1093 buf1r[j + 1] = L_MAX(0, val1);
1094 buf2r[j] = L_MAX(0, val2);
1095 buf2r[j + 1] = L_MAX(0, val3);
1099 dif = buf1g[j] / 8 - 8 * gc;
1100 if (dif > DifCap) dif = DifCap;
1101 if (dif < -DifCap) dif = -DifCap;
1103 val1 = buf1g[j + 1] + 3 * dif;
1104 val2 = buf2g[j] + 3 * dif;
1105 val3 = buf2g[j + 1] + 2 * dif;
1107 buf1g[j + 1] = L_MIN(16383, val1);
1108 buf2g[j] = L_MIN(16383, val2);
1109 buf2g[j + 1] = L_MIN(16383, val3);
1111 buf1g[j + 1] = L_MAX(0, val1);
1112 buf2g[j] = L_MAX(0, val2);
1113 buf2g[j + 1] = L_MAX(0, val3);
1117 dif = buf1b[j] / 8 - 8 * bc;
1118 if (dif > DifCap) dif = DifCap;
1119 if (dif < -DifCap) dif = -DifCap;
1121 val1 = buf1b[j + 1] + 3 * dif;
1122 val2 = buf2b[j] + 3 * dif;
1123 val3 = buf2b[j + 1] + 2 * dif;
1125 buf1b[j + 1] = L_MIN(16383, val1);
1126 buf2b[j] = L_MIN(16383, val2);
1127 buf2b[j + 1] = L_MIN(16383, val3);
1129 buf1b[j + 1] = L_MAX(0, val1);
1130 buf2b[j] = L_MAX(0, val2);
1131 buf2b[j + 1] = L_MAX(0, val3);
1137 rval = buf1r[w - 1] / 64;
1138 gval = buf1g[w - 1] / 64;
1139 bval = buf1b[w - 1] / 64;
1140 index = ((rval >> rshift) << (2 * sigbits)) +
1141 ((gval >> rshift) << sigbits) + (bval >> rshift);
1146 lined = datad + (h - 1) * wpld;
1147 for (j = 0; j < w; j++) {
1148 rval = buf2r[j] / 64;
1149 gval = buf2g[j] / 64;
1150 bval = buf2b[j] / 64;
1151 index = ((rval >> rshift) << (2 * sigbits)) +
1152 ((gval >> rshift) << sigbits) + (bval >> rshift);
1166 if (!success) pixDestroy(&pixd);
1283l_int32 i, j, k, sum, rw, gw, bw, maxw, index;
1284l_int32 total, left, right;
1285l_int32 partialsum[128];
1288 if (pvbox1) *pvbox1 = NULL;
1289 if (pvbox2) *pvbox2 = NULL;
1291 return ERROR_INT(
"histo not defined", __func__, 1);
1293 return ERROR_INT(
"vbox not defined", __func__, 1);
1294 if (!pvbox1 || !pvbox2)
1295 return ERROR_INT(
"&vbox1 and &vbox2 not both defined", __func__, 1);
1298 return ERROR_INT(
"no pixels in vbox", __func__, 1);
1305 rw = vbox->r2 - vbox->r1 + 1;
1306 gw = vbox->g2 - vbox->g1 + 1;
1307 bw = vbox->b2 - vbox->b1 + 1;
1308 if (rw == 1 && gw == 1 && bw == 1) {
1314 maxw = L_MAX(rw, gw);
1315 maxw = L_MAX(maxw, bw);
1318 lept_stderr(
"red split\n");
1319 else if (gw == maxw)
1320 lept_stderr(
"green split\n");
1322 lept_stderr(
"blue split\n");
1328 for (i = vbox->r1; i <= vbox->r2; i++) {
1330 for (j = vbox->g1; j <= vbox->g2; j++) {
1331 for (k = vbox->b1; k <= vbox->b2; k++) {
1332 index = (i << (2 * sigbits)) + (j << sigbits) + k;
1333 sum += histo[index];
1337 partialsum[i] = total;
1339 }
else if (maxw == gw) {
1340 for (i = vbox->g1; i <= vbox->g2; i++) {
1342 for (j = vbox->r1; j <= vbox->r2; j++) {
1343 for (k = vbox->b1; k <= vbox->b2; k++) {
1344 index = (i << sigbits) + (j << (2 * sigbits)) + k;
1345 sum += histo[index];
1349 partialsum[i] = total;
1352 for (i = vbox->b1; i <= vbox->b2; i++) {
1354 for (j = vbox->r1; j <= vbox->r2; j++) {
1355 for (k = vbox->g1; k <= vbox->g2; k++) {
1356 index = i + (j << (2 * sigbits)) + (k << sigbits);
1357 sum += histo[index];
1361 partialsum[i] = total;
1374 vbox1 = vbox2 = NULL;
1376 for (i = vbox->r1; i <= vbox->r2; i++) {
1377 if (partialsum[i] > total / 2) {
1380 left = i - vbox->r1;
1381 right = vbox->r2 - i;
1383 vbox1->r2 = L_MIN(vbox->r2 - 1, i + right / 2);
1385 vbox1->r2 = L_MAX(vbox->r1, i - 1 - left / 2);
1386 vbox2->r1 = vbox1->r2 + 1;
1390 }
else if (maxw == gw) {
1391 for (i = vbox->g1; i <= vbox->g2; i++) {
1392 if (partialsum[i] > total / 2) {
1395 left = i - vbox->g1;
1396 right = vbox->g2 - i;
1398 vbox1->g2 = L_MIN(vbox->g2 - 1, i + right / 2);
1400 vbox1->g2 = L_MAX(vbox->g1, i - 1 - left / 2);
1401 vbox2->g1 = vbox1->g2 + 1;
1406 for (i = vbox->b1; i <= vbox->b2; i++) {
1407 if (partialsum[i] > total / 2) {
1410 left = i - vbox->b1;
1411 right = vbox->b2 - i;
1413 vbox1->b2 = L_MIN(vbox->b2 - 1, i + right / 2);
1415 vbox1->b2 = L_MAX(vbox->b1, i - 1 - left / 2);
1416 vbox2->b1 = vbox1->b2 + 1;
1424 return ERROR_INT(
"vbox1 not made; shouldn't happen", __func__, 1);
1426 return ERROR_INT(
"vbox2 not made; shouldn't happen", __func__, 1);
1517l_int32 i, j, k, ntot, mult, histoindex, rsum, gsum, bsum;
1520 return ERROR_INT(
"vbox not defined", __func__, 1);
1522 return ERROR_INT(
"histo not defined", __func__, 1);
1523 if (!prval || !pgval || !pbval)
1524 return ERROR_INT(
"&p*val not all defined", __func__, 1);
1526 *prval = *pgval = *pbval = 0;
1528 mult = 1 << (8 - sigbits);
1529 rsum = gsum = bsum = 0;
1530 for (i = vbox->r1; i <= vbox->r2; i++) {
1531 for (j = vbox->g1; j <= vbox->g2; j++) {
1532 for (k = vbox->b1; k <= vbox->b2; k++) {
1533 histoindex = (i << (2 * sigbits)) + (j << sigbits) + k;
1534 ntot += histo[histoindex];
1535 rsum += (l_int32)(histo[histoindex] * (i + 0.5) * mult);
1536 gsum += (l_int32)(histo[histoindex] * (j + 0.5) * mult);
1537 bsum += (l_int32)(histo[histoindex] * (k + 0.5) * mult);
1539 histo[histoindex] = index;
1545 *prval = mult * (vbox->r1 + vbox->r2 + 1) / 2;
1546 *pgval = mult * (vbox->g1 + vbox->g2 + 1) / 2;
1547 *pbval = mult * (vbox->b1 + vbox->b2 + 1) / 2;
1549 *prval = rsum / ntot;
1550 *pgval = gsum / ntot;
1551 *pbval = bsum / ntot;
1555 lept_stderr(
"ntot[%d] = %d: [%d, %d, %d], (%d, %d, %d)\n",
1556 index, ntot, vbox->r2 - vbox->r1 + 1,
1557 vbox->g2 - vbox->g1 + 1, vbox->b2 - vbox->b1 + 1,
1558 *prval, *pgval, *pbval);