Leptonica 1.82.0
Image processing and image analysis suite
pixconv.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
157#ifdef HAVE_CONFIG_H
158#include <config_auto.h>
159#endif /* HAVE_CONFIG_H */
160
161#include <string.h>
162#include <math.h>
163#include "allheaders.h"
164
165/* ------- Set neutral point for min/max boost conversion to gray ------ */
166 /* Call l_setNeutralBoostVal() to change this */
167static l_int32 var_NEUTRAL_BOOST_VAL = 180;
168
169
170#ifndef NO_CONSOLE_IO
171#define DEBUG_CONVERT_TO_COLORMAP 0
172#define DEBUG_UNROLLING 0
173#endif /* ~NO_CONSOLE_IO */
174
175
176/*-------------------------------------------------------------*
177 * Conversion from 8 bpp grayscale to 1, 2 4 and 8 bpp *
178 *-------------------------------------------------------------*/
209PIX *
211 l_int32 d,
212 l_int32 nlevels,
213 l_int32 cmapflag)
214{
215PIX *pixd;
216PIXCMAP *cmap;
217
218 PROCNAME("pixThreshold8");
219
220 if (!pixs)
221 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
222 if (pixGetDepth(pixs) != 8)
223 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
224 if (cmapflag && nlevels < 2)
225 return (PIX *)ERROR_PTR("nlevels must be at least 2", procName, NULL);
226
227 switch (d) {
228 case 1:
229 pixd = pixThresholdToBinary(pixs, 128);
230 if (cmapflag) {
231 cmap = pixcmapCreateLinear(1, 2);
232 pixSetColormap(pixd, cmap);
233 }
234 break;
235 case 2:
236 pixd = pixThresholdTo2bpp(pixs, nlevels, cmapflag);
237 break;
238 case 4:
239 pixd = pixThresholdTo4bpp(pixs, nlevels, cmapflag);
240 break;
241 case 8:
242 pixd = pixThresholdOn8bpp(pixs, nlevels, cmapflag);
243 break;
244 default:
245 return (PIX *)ERROR_PTR("d must be in {1,2,4,8}", procName, NULL);
246 }
247
248 if (!pixd)
249 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
250 pixCopyInputFormat(pixd, pixs);
251 return pixd;
252}
253
254
255/*-------------------------------------------------------------*
256 * Conversion from colormapped pix *
257 *-------------------------------------------------------------*/
277PIX *
279 l_int32 type,
280 l_int32 ifnocmap)
281{
282 PROCNAME("pixRemoveColormapGeneral");
283
284 if (!pixs)
285 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
286 if (ifnocmap != L_CLONE && ifnocmap != L_COPY)
287 return (PIX *)ERROR_PTR("invalid value for ifnocmap", procName, NULL);
288
289 if (pixGetColormap(pixs))
290 return pixRemoveColormap(pixs, type);
291
292 if (ifnocmap == L_CLONE)
293 return pixClone(pixs);
294 else
295 return pixCopy(NULL, pixs);
296}
297
298
327PIX *
329 l_int32 type)
330{
331l_int32 sval, rval, gval, bval, val0, val1;
332l_int32 i, j, k, w, h, d, wpls, wpld, ncolors, nalloc, count;
333l_int32 opaque, colorfound, blackwhite;
334l_int32 *rmap, *gmap, *bmap, *amap;
335l_uint32 *datas, *lines, *datad, *lined, *lut, *graymap;
336l_uint32 sword, dword;
337PIXCMAP *cmap;
338PIX *pixd;
339
340 PROCNAME("pixRemoveColormap");
341
342 if (!pixs)
343 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
344 if ((cmap = pixGetColormap(pixs)) == NULL)
345 return pixClone(pixs);
346 if (type != REMOVE_CMAP_TO_BINARY &&
347 type != REMOVE_CMAP_TO_GRAYSCALE &&
349 type != REMOVE_CMAP_WITH_ALPHA &&
350 type != REMOVE_CMAP_BASED_ON_SRC) {
351 L_WARNING("Invalid type; converting based on src\n", procName);
353 }
354 pixGetDimensions(pixs, &w, &h, &d);
355 if (d != 1 && d != 2 && d != 4 && d != 8)
356 return (PIX *)ERROR_PTR("pixs must be {1,2,4,8} bpp", procName, NULL);
357
358 ncolors = pixcmapGetCount(cmap);
359 nalloc = 1 << d; /* allocate for max size in case of pixel corruption */
360 if (ncolors > nalloc)
361 return (PIX *)ERROR_PTR("too many colors for pixel depth",
362 procName, NULL);
363
364 if (pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap))
365 return (PIX *)ERROR_PTR("colormap arrays not made", procName, NULL);
366
367 if (d != 1 && type == REMOVE_CMAP_TO_BINARY) {
368 L_WARNING("not 1 bpp; can't remove cmap to binary\n", procName);
370 }
371
372 /* Select output type depending on colormap content */
373 if (type == REMOVE_CMAP_BASED_ON_SRC) {
374 pixcmapIsOpaque(cmap, &opaque);
375 pixcmapHasColor(cmap, &colorfound);
376 pixcmapIsBlackAndWhite(cmap, &blackwhite);
377 if (!opaque) { /* save the alpha */
379 } else if (colorfound) {
381 } else { /* opaque and no color */
382 if (d == 1 && blackwhite) /* can binarize without loss */
384 else
386 }
387 }
388
389 datas = pixGetData(pixs);
390 wpls = pixGetWpl(pixs);
391 if (type == REMOVE_CMAP_TO_BINARY) {
392 if ((pixd = pixCopy(NULL, pixs)) == NULL) {
393 L_ERROR("pixd not made\n", procName);
394 goto cleanup_arrays;
395 }
396 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
397 val0 = rval + gval + bval;
398 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
399 val1 = rval + gval + bval;
400 if (val0 < val1) /* photometrically inverted from standard */
401 pixInvert(pixd, pixd);
402 pixDestroyColormap(pixd);
403 } else if (type == REMOVE_CMAP_TO_GRAYSCALE) {
404 if ((pixd = pixCreate(w, h, 8)) == NULL) {
405 L_ERROR("pixd not made\n", procName);
406 goto cleanup_arrays;
407 }
408 pixCopyResolution(pixd, pixs);
409 pixCopyInputFormat(pixd, pixs);
410 datad = pixGetData(pixd);
411 wpld = pixGetWpl(pixd);
412 graymap = (l_uint32 *)LEPT_CALLOC(nalloc, sizeof(l_uint32));
413 for (i = 0; i < ncolors; i++) {
414 graymap[i] = (l_uint32)(L_RED_WEIGHT * rmap[i] +
415 L_GREEN_WEIGHT * gmap[i] +
416 L_BLUE_WEIGHT * bmap[i] + 0.5);
417 }
418 for (i = 0; i < h; i++) {
419 lines = datas + i * wpls;
420 lined = datad + i * wpld;
421 switch (d) /* depth test above; no default permitted */
422 {
423 case 8:
424 /* Unrolled 4x */
425 for (j = 0, count = 0; j + 3 < w; j += 4, count++) {
426 sword = lines[count];
427 dword = (graymap[(sword >> 24) & 0xff] << 24) |
428 (graymap[(sword >> 16) & 0xff] << 16) |
429 (graymap[(sword >> 8) & 0xff] << 8) |
430 graymap[sword & 0xff];
431 lined[count] = dword;
432 }
433 /* Cleanup partial word */
434 for (; j < w; j++) {
435 sval = GET_DATA_BYTE(lines, j);
436 gval = graymap[sval];
437 SET_DATA_BYTE(lined, j, gval);
438 }
439#if DEBUG_UNROLLING
440#define CHECK_VALUE(a, b, c) if (GET_DATA_BYTE(a, b) != c) { \
441 lept_stderr("Error: mismatch at %d, %d vs %d\n", \
442 j, GET_DATA_BYTE(a, b), c); }
443 for (j = 0; j < w; j++) {
444 sval = GET_DATA_BYTE(lines, j);
445 gval = graymap[sval];
446 CHECK_VALUE(lined, j, gval);
447 }
448#endif
449 break;
450 case 4:
451 /* Unrolled 8x */
452 for (j = 0, count = 0; j + 7 < w; j += 8, count++) {
453 sword = lines[count];
454 dword = (graymap[(sword >> 28) & 0xf] << 24) |
455 (graymap[(sword >> 24) & 0xf] << 16) |
456 (graymap[(sword >> 20) & 0xf] << 8) |
457 graymap[(sword >> 16) & 0xf];
458 lined[2 * count] = dword;
459 dword = (graymap[(sword >> 12) & 0xf] << 24) |
460 (graymap[(sword >> 8) & 0xf] << 16) |
461 (graymap[(sword >> 4) & 0xf] << 8) |
462 graymap[sword & 0xf];
463 lined[2 * count + 1] = dword;
464 }
465 /* Cleanup partial word */
466 for (; j < w; j++) {
467 sval = GET_DATA_QBIT(lines, j);
468 gval = graymap[sval];
469 SET_DATA_BYTE(lined, j, gval);
470 }
471#if DEBUG_UNROLLING
472 for (j = 0; j < w; j++) {
473 sval = GET_DATA_QBIT(lines, j);
474 gval = graymap[sval];
475 CHECK_VALUE(lined, j, gval);
476 }
477#endif
478 break;
479 case 2:
480 /* Unrolled 16x */
481 for (j = 0, count = 0; j + 15 < w; j += 16, count++) {
482 sword = lines[count];
483 dword = (graymap[(sword >> 30) & 0x3] << 24) |
484 (graymap[(sword >> 28) & 0x3] << 16) |
485 (graymap[(sword >> 26) & 0x3] << 8) |
486 graymap[(sword >> 24) & 0x3];
487 lined[4 * count] = dword;
488 dword = (graymap[(sword >> 22) & 0x3] << 24) |
489 (graymap[(sword >> 20) & 0x3] << 16) |
490 (graymap[(sword >> 18) & 0x3] << 8) |
491 graymap[(sword >> 16) & 0x3];
492 lined[4 * count + 1] = dword;
493 dword = (graymap[(sword >> 14) & 0x3] << 24) |
494 (graymap[(sword >> 12) & 0x3] << 16) |
495 (graymap[(sword >> 10) & 0x3] << 8) |
496 graymap[(sword >> 8) & 0x3];
497 lined[4 * count + 2] = dword;
498 dword = (graymap[(sword >> 6) & 0x3] << 24) |
499 (graymap[(sword >> 4) & 0x3] << 16) |
500 (graymap[(sword >> 2) & 0x3] << 8) |
501 graymap[sword & 0x3];
502 lined[4 * count + 3] = dword;
503 }
504 /* Cleanup partial word */
505 for (; j < w; j++) {
506 sval = GET_DATA_DIBIT(lines, j);
507 gval = graymap[sval];
508 SET_DATA_BYTE(lined, j, gval);
509 }
510#if DEBUG_UNROLLING
511 for (j = 0; j < w; j++) {
512 sval = GET_DATA_DIBIT(lines, j);
513 gval = graymap[sval];
514 CHECK_VALUE(lined, j, gval);
515 }
516#endif
517 break;
518 case 1:
519 /* Unrolled 8x */
520 for (j = 0, count = 0; j + 31 < w; j += 32, count++) {
521 sword = lines[count];
522 for (k = 0; k < 4; k++) {
523 /* The top byte is always the relevant one */
524 dword = (graymap[(sword >> 31) & 0x1] << 24) |
525 (graymap[(sword >> 30) & 0x1] << 16) |
526 (graymap[(sword >> 29) & 0x1] << 8) |
527 graymap[(sword >> 28) & 0x1];
528 lined[8 * count + 2 * k] = dword;
529 dword = (graymap[(sword >> 27) & 0x1] << 24) |
530 (graymap[(sword >> 26) & 0x1] << 16) |
531 (graymap[(sword >> 25) & 0x1] << 8) |
532 graymap[(sword >> 24) & 0x1];
533 lined[8 * count + 2 * k + 1] = dword;
534 sword <<= 8; /* Move up the next byte */
535 }
536 }
537 /* Cleanup partial word */
538 for (; j < w; j++) {
539 sval = GET_DATA_BIT(lines, j);
540 gval = graymap[sval];
541 SET_DATA_BYTE(lined, j, gval);
542 }
543#if DEBUG_UNROLLING
544 for (j = 0; j < w; j++) {
545 sval = GET_DATA_BIT(lines, j);
546 gval = graymap[sval];
547 CHECK_VALUE(lined, j, gval);
548 }
549#undef CHECK_VALUE
550#endif
551 break;
552 default:
553 return NULL;
554 }
555 }
556 if (graymap)
557 LEPT_FREE(graymap);
558 } else { /* type == REMOVE_CMAP_TO_FULL_COLOR or REMOVE_CMAP_WITH_ALPHA */
559 if ((pixd = pixCreate(w, h, 32)) == NULL) {
560 L_ERROR("pixd not made\n", procName);
561 goto cleanup_arrays;
562 }
563 pixCopyInputFormat(pixd, pixs);
564 pixCopyResolution(pixd, pixs);
565 if (type == REMOVE_CMAP_WITH_ALPHA)
566 pixSetSpp(pixd, 4);
567 datad = pixGetData(pixd);
568 wpld = pixGetWpl(pixd);
569 lut = (l_uint32 *)LEPT_CALLOC(nalloc, sizeof(l_uint32));
570 for (i = 0; i < ncolors; i++) {
571 if (type == REMOVE_CMAP_TO_FULL_COLOR)
572 composeRGBPixel(rmap[i], gmap[i], bmap[i], lut + i);
573 else /* full color plus alpha */
574 composeRGBAPixel(rmap[i], gmap[i], bmap[i], amap[i], lut + i);
575 }
576
577 for (i = 0; i < h; i++) {
578 lines = datas + i * wpls;
579 lined = datad + i * wpld;
580 for (j = 0; j < w; j++) {
581 if (d == 8)
582 sval = GET_DATA_BYTE(lines, j);
583 else if (d == 4)
584 sval = GET_DATA_QBIT(lines, j);
585 else if (d == 2)
586 sval = GET_DATA_DIBIT(lines, j);
587 else /* (d == 1) */
588 sval = GET_DATA_BIT(lines, j);
589 if (sval >= ncolors)
590 L_WARNING("pixel value out of bounds\n", procName);
591 else
592 lined[j] = lut[sval];
593 }
594 }
595 LEPT_FREE(lut);
596 }
597
598cleanup_arrays:
599 LEPT_FREE(rmap);
600 LEPT_FREE(gmap);
601 LEPT_FREE(bmap);
602 LEPT_FREE(amap);
603 return pixd;
604}
605
606
607/*-------------------------------------------------------------*
608 * Add colormap losslessly (8 to 8) *
609 *-------------------------------------------------------------*/
621l_ok
623{
624PIXCMAP *cmap;
625
626 PROCNAME("pixAddGrayColormap8");
627
628 if (!pixs || pixGetDepth(pixs) != 8)
629 return ERROR_INT("pixs not defined or not 8 bpp", procName, 1);
630 if (pixGetColormap(pixs))
631 return 0;
632
633 cmap = pixcmapCreateLinear(8, 256);
634 pixSetColormap(pixs, cmap);
635 return 0;
636}
637
638
652PIX *
654{
655l_int32 ncolors, w, h, i, j, wpl1, wpld, index, val;
656l_int32 *inta, *revmap;
657l_uint32 *data1, *datad, *line1, *lined;
658PIX *pix1, *pixd;
659PIXCMAP *cmap;
660
661 PROCNAME("pixAddMinimalGrayColormap8");
662
663 if (!pixs || pixGetDepth(pixs) != 8)
664 return (PIX *)ERROR_PTR("pixs undefined or not 8 bpp", procName, NULL);
665
666 /* Eliminate the easy cases */
667 pixNumColors(pixs, 1, &ncolors);
668 cmap = pixGetColormap(pixs);
669 if (cmap) {
670 if (pixcmapGetCount(cmap) == ncolors) /* irreducible */
671 return pixCopy(NULL, pixs);
672 else
674 } else {
675 if (ncolors == 256) {
676 pix1 = pixCopy(NULL, pixs);
678 return pix1;
679 }
680 pix1 = pixClone(pixs);
681 }
682
683 /* Find the gray levels and make a reverse map */
684 pixGetDimensions(pix1, &w, &h, NULL);
685 data1 = pixGetData(pix1);
686 wpl1 = pixGetWpl(pix1);
687 inta = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
688 for (i = 0; i < h; i++) {
689 line1 = data1 + i * wpl1;
690 for (j = 0; j < w; j++) {
691 val = GET_DATA_BYTE(line1, j);
692 inta[val] = 1;
693 }
694 }
695 cmap = pixcmapCreate(8);
696 revmap = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
697 for (i = 0, index = 0; i < 256; i++) {
698 if (inta[i]) {
699 pixcmapAddColor(cmap, i, i, i);
700 revmap[i] = index++;
701 }
702 }
703
704 /* Set all pixels in pixd to the colormap index */
705 pixd = pixCreateTemplate(pix1);
706 pixSetColormap(pixd, cmap);
707 pixCopyInputFormat(pixd, pixs);
708 pixCopyResolution(pixd, pixs);
709 datad = pixGetData(pixd);
710 wpld = pixGetWpl(pixd);
711 for (i = 0; i < h; i++) {
712 line1 = data1 + i * wpl1;
713 lined = datad + i * wpld;
714 for (j = 0; j < w; j++) {
715 val = GET_DATA_BYTE(line1, j);
716 SET_DATA_BYTE(lined, j, revmap[val]);
717 }
718 }
719
720 pixDestroy(&pix1);
721 LEPT_FREE(inta);
722 LEPT_FREE(revmap);
723 return pixd;
724}
725
726
727/*-------------------------------------------------------------*
728 * Conversion from RGB color to grayscale *
729 *-------------------------------------------------------------*/
741PIX *
743{
744 return pixConvertRGBToGray(pixs, 0.0, 0.0, 0.0);
745}
746
747
765PIX *
767 l_int32 type,
768 l_float32 rwt,
769 l_float32 gwt,
770 l_float32 bwt)
771{
772PIX *pix1;
773
774 PROCNAME("pixConvertRGBToGrayGeneral");
775
776 if (!pixs || pixGetDepth(pixs) != 32)
777 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
778 if (type != L_SELECT_RED && type != L_SELECT_GREEN &&
779 type != L_SELECT_BLUE && type != L_SELECT_MIN &&
780 type != L_SELECT_MAX && type != L_SELECT_AVERAGE &&
781 type != L_SELECT_HUE && type != L_SELECT_SATURATION &&
782 type != L_SELECT_WEIGHTED)
783 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
784
785 if (type == L_SELECT_RED) {
786 pix1 = pixGetRGBComponent(pixs, COLOR_RED);
787 } else if (type == L_SELECT_GREEN) {
788 pix1 = pixGetRGBComponent(pixs, COLOR_GREEN);
789 } else if (type == L_SELECT_BLUE) {
790 pix1 = pixGetRGBComponent(pixs, COLOR_BLUE);
791 } else if (type == L_SELECT_MIN) {
792 pix1 = pixConvertRGBToGrayMinMax(pixs, L_CHOOSE_MIN);
793 } else if (type == L_SELECT_MAX) {
794 pix1 = pixConvertRGBToGrayMinMax(pixs, L_CHOOSE_MAX);
795 } else if (type == L_SELECT_AVERAGE) {
796 pix1 = pixConvertRGBToGray(pixs, 0.34, 0.33, 0.33);
797 } else if (type == L_SELECT_HUE) {
798 pix1 = pixConvertRGBToHue(pixs);
799 } else if (type == L_SELECT_SATURATION) {
800 pix1 = pixConvertRGBToSaturation(pixs);
801 } else { /* L_SELECT_WEIGHTED */
802 if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0)
803 return (PIX *)ERROR_PTR("weights not all >= 0.0", procName, NULL);
804 if (rwt + gwt + bwt != 1.0)
805 return (PIX *)ERROR_PTR("weights don't sum to 1.0", procName, NULL);
806 pix1 = pixConvertRGBToGray(pixs, rwt, gwt, bwt);
807 }
808
809 return pix1;
810}
811
812
826PIX *
828 l_float32 rwt,
829 l_float32 gwt,
830 l_float32 bwt)
831{
832l_int32 i, j, w, h, wpls, wpld, val;
833l_uint32 word;
834l_uint32 *datas, *lines, *datad, *lined;
835l_float32 sum;
836PIX *pixd;
837
838 PROCNAME("pixConvertRGBToGray");
839
840 if (!pixs)
841 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
842 if (pixGetDepth(pixs) != 32)
843 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
844 if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0)
845 return (PIX *)ERROR_PTR("weights not all >= 0.0", procName, NULL);
846
847 /* Make sure the sum of weights is 1.0; otherwise, you can get
848 * overflow in the gray value. */
849 if (rwt == 0.0 && gwt == 0.0 && bwt == 0.0) {
850 rwt = L_RED_WEIGHT;
851 gwt = L_GREEN_WEIGHT;
852 bwt = L_BLUE_WEIGHT;
853 }
854 sum = rwt + gwt + bwt;
855 if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
856 L_WARNING("weights don't sum to 1; maintaining ratios\n", procName);
857 rwt = rwt / sum;
858 gwt = gwt / sum;
859 bwt = bwt / sum;
860 }
861
862 pixGetDimensions(pixs, &w, &h, NULL);
863 datas = pixGetData(pixs);
864 wpls = pixGetWpl(pixs);
865 if ((pixd = pixCreate(w, h, 8)) == NULL)
866 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
867 pixCopyResolution(pixd, pixs);
868 pixCopyInputFormat(pixd, pixs);
869 datad = pixGetData(pixd);
870 wpld = pixGetWpl(pixd);
871
872 for (i = 0; i < h; i++) {
873 lines = datas + i * wpls;
874 lined = datad + i * wpld;
875 for (j = 0; j < w; j++) {
876 word = *(lines + j);
877 val = (l_int32)(rwt * ((word >> L_RED_SHIFT) & 0xff) +
878 gwt * ((word >> L_GREEN_SHIFT) & 0xff) +
879 bwt * ((word >> L_BLUE_SHIFT) & 0xff) + 0.5);
880 SET_DATA_BYTE(lined, j, val);
881 }
882 }
883
884 return pixd;
885}
886
887
904PIX *
906{
907l_int32 i, j, w, h, wpls, wpld, val;
908l_uint32 *datas, *lines, *datad, *lined;
909PIX *pixd;
910
911 PROCNAME("pixConvertRGBToGrayFast");
912
913 if (!pixs)
914 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
915 if (pixGetDepth(pixs) != 32)
916 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
917
918 pixGetDimensions(pixs, &w, &h, NULL);
919 datas = pixGetData(pixs);
920 wpls = pixGetWpl(pixs);
921 if ((pixd = pixCreate(w, h, 8)) == NULL)
922 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
923 pixCopyResolution(pixd, pixs);
924 pixCopyInputFormat(pixd, pixs);
925 datad = pixGetData(pixd);
926 wpld = pixGetWpl(pixd);
927
928 for (i = 0; i < h; i++) {
929 lines = datas + i * wpls;
930 lined = datad + i * wpld;
931 for (j = 0; j < w; j++, lines++) {
932 val = ((*lines) >> L_GREEN_SHIFT) & 0xff;
933 SET_DATA_BYTE(lined, j, val);
934 }
935 }
936
937 return pixd;
938}
939
940
962PIX *
964 l_int32 type)
965{
966l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val, minval, maxval;
967l_uint32 *datas, *lines, *datad, *lined;
968PIX *pixd;
969
970 PROCNAME("pixConvertRGBToGrayMinMax");
971
972 if (!pixs)
973 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
974 if (pixGetDepth(pixs) != 32)
975 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
976 if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX &&
977 type != L_CHOOSE_MAXDIFF && type != L_CHOOSE_MIN_BOOST &&
978 type != L_CHOOSE_MAX_BOOST)
979 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
980
981 pixGetDimensions(pixs, &w, &h, NULL);
982 datas = pixGetData(pixs);
983 wpls = pixGetWpl(pixs);
984 if ((pixd = pixCreate(w, h, 8)) == NULL)
985 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
986 pixCopyResolution(pixd, pixs);
987 pixCopyInputFormat(pixd, pixs);
988 datad = pixGetData(pixd);
989 wpld = pixGetWpl(pixd);
990
991 for (i = 0; i < h; i++) {
992 lines = datas + i * wpls;
993 lined = datad + i * wpld;
994 for (j = 0; j < w; j++) {
995 extractRGBValues(lines[j], &rval, &gval, &bval);
996 if (type == L_CHOOSE_MIN || type == L_CHOOSE_MIN_BOOST) {
997 val = L_MIN(rval, gval);
998 val = L_MIN(val, bval);
999 if (type == L_CHOOSE_MIN_BOOST)
1000 val = L_MIN(255, (val * val) / var_NEUTRAL_BOOST_VAL);
1001 } else if (type == L_CHOOSE_MAX || type == L_CHOOSE_MAX_BOOST) {
1002 val = L_MAX(rval, gval);
1003 val = L_MAX(val, bval);
1004 if (type == L_CHOOSE_MAX_BOOST)
1005 val = L_MIN(255, (val * val) / var_NEUTRAL_BOOST_VAL);
1006 } else { /* L_CHOOSE_MAXDIFF */
1007 minval = L_MIN(rval, gval);
1008 minval = L_MIN(minval, bval);
1009 maxval = L_MAX(rval, gval);
1010 maxval = L_MAX(maxval, bval);
1011 val = maxval - minval;
1012 }
1013 SET_DATA_BYTE(lined, j, val);
1014 }
1015 }
1016
1017 return pixd;
1018}
1019
1020
1049PIX *
1051 l_int32 refval)
1052{
1053l_int32 w, h, d, i, j, wplt, wpld;
1054l_int32 rval, gval, bval, sval, minrg, maxrg, min, max, delta;
1055l_int32 fullsat, newval;
1056l_float32 *invmax, *ratio;
1057l_uint32 *linet, *lined, *datat, *datad;
1058PIX *pixt, *pixd;
1059
1060 PROCNAME("pixConvertRGBToGraySatBoost");
1061
1062 if (!pixs)
1063 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1064 pixGetDimensions(pixs, &w, &h, &d);
1065 if (d != 32 && !pixGetColormap(pixs))
1066 return (PIX *)ERROR_PTR("pixs not cmapped or rgb", procName, NULL);
1067 if (refval < 1 || refval > 255)
1068 return (PIX *)ERROR_PTR("refval not in [1 ... 255]", procName, NULL);
1069
1071 pixd = pixCreate(w, h, 8);
1072 pixCopyResolution(pixd, pixs);
1073 pixCopyInputFormat(pixd, pixs);
1074 wplt = pixGetWpl(pixt);
1075 datat = pixGetData(pixt);
1076 wpld = pixGetWpl(pixd);
1077 datad = pixGetData(pixd);
1078 invmax = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
1079 ratio = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
1080 for (i = 1; i < 256; i++) { /* i == 0 --> delta = sval = newval = 0 */
1081 invmax[i] = 1.0 / (l_float32)i;
1082 ratio[i] = (l_float32)i / (l_float32)refval;
1083 }
1084 for (i = 0; i < h; i++) {
1085 linet = datat + i * wplt;
1086 lined = datad + i * wpld;
1087 for (j = 0; j < w; j++) {
1088 extractRGBValues(linet[j], &rval, &gval, &bval);
1089 minrg = L_MIN(rval, gval);
1090 min = L_MIN(minrg, bval);
1091 maxrg = L_MAX(rval, gval);
1092 max = L_MAX(maxrg, bval);
1093 delta = max - min;
1094 if (delta == 0) /* gray; no chroma */
1095 sval = 0;
1096 else
1097 sval = (l_int32)(255. * (l_float32)delta * invmax[max] + 0.5);
1098
1099 fullsat = L_MIN(255, 255 * ratio[max]);
1100 newval = (sval * fullsat + (255 - sval) * max) / 255;
1101 SET_DATA_BYTE(lined, j, newval);
1102 }
1103 }
1104
1105 pixDestroy(&pixt);
1106 LEPT_FREE(invmax);
1107 LEPT_FREE(ratio);
1108 return pixd;
1109}
1110
1111
1127PIX *
1129 l_float32 rc,
1130 l_float32 gc,
1131 l_float32 bc)
1132{
1133l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val;
1134l_uint32 *datas, *lines, *datad, *lined;
1135PIX *pixd;
1136
1137 PROCNAME("pixConvertRGBToGrayArb");
1138
1139 if (!pixs)
1140 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1141 if (pixGetDepth(pixs) != 32)
1142 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1143 if (rc <= 0 && gc <= 0 && bc <= 0)
1144 return (PIX *)ERROR_PTR("all coefficients <= 0", procName, NULL);
1145
1146 pixGetDimensions(pixs, &w, &h, NULL);
1147 datas = pixGetData(pixs);
1148 wpls = pixGetWpl(pixs);
1149 if ((pixd = pixCreate(w, h, 8)) == NULL)
1150 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1151 pixCopyResolution(pixd, pixs);
1152 pixCopyInputFormat(pixd, pixs);
1153 datad = pixGetData(pixd);
1154 wpld = pixGetWpl(pixd);
1155
1156 for (i = 0; i < h; i++) {
1157 lines = datas + i * wpls;
1158 lined = datad + i * wpld;
1159 for (j = 0; j < w; j++) {
1160 extractRGBValues(lines[j], &rval, &gval, &bval);
1161 val = (l_int32)(rc * rval + gc * gval + bc * bval);
1162 val = L_MIN(255, L_MAX(0, val));
1163 SET_DATA_BYTE(lined, j, val);
1164 }
1165 }
1166
1167 return pixd;
1168}
1169
1170
1189PIX *
1191 l_float32 rc,
1192 l_float32 gc,
1193 l_float32 bc,
1194 l_int32 thresh,
1195 l_int32 relation)
1196{
1197l_int32 threshold;
1198PIX *pix1, *pix2;
1199
1200 PROCNAME("pixConvertRGBToBinaryArb");
1201
1202 if (!pixs || pixGetDepth(pixs) != 32)
1203 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1204 if (rc <= 0 && gc <= 0 && bc <= 0)
1205 return (PIX *)ERROR_PTR("all coefficients <= 0", procName, NULL);
1206 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
1207 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
1208 return (PIX *)ERROR_PTR("invalid relation", procName, NULL);
1209
1210 pix1 = pixConvertRGBToGrayArb(pixs, rc, gc, bc);
1211 threshold = (relation == L_SELECT_IF_LTE || relation == L_SELECT_IF_GT) ?
1212 thresh : thresh + 1;
1213 pix2 = pixThresholdToBinary(pix1, threshold);
1214 if (relation == L_SELECT_IF_GT || relation == L_SELECT_IF_GTE)
1215 pixInvert(pix2, pix2);
1216 pixDestroy(&pix1);
1217 return pix2;
1218}
1219
1220
1221/*---------------------------------------------------------------------------*
1222 * Conversion from grayscale to colormap *
1223 *---------------------------------------------------------------------------*/
1246PIX *
1248{
1249l_int32 d;
1250PIX *pixd;
1251PIXCMAP *cmap;
1252
1253 PROCNAME("pixConvertGrayToColormap");
1254
1255 if (!pixs)
1256 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1257 d = pixGetDepth(pixs);
1258 if (d != 2 && d != 4 && d != 8)
1259 return (PIX *)ERROR_PTR("pixs not 2, 4 or 8 bpp", procName, NULL);
1260
1261 if (pixGetColormap(pixs)) {
1262 L_INFO("pixs already has a colormap\n", procName);
1263 return pixCopy(NULL, pixs);
1264 }
1265
1266 if (d == 8) /* lossless conversion */
1267 return pixConvertGrayToColormap8(pixs, 2);
1268
1269 /* Build a cmap with equally spaced target values over the
1270 * full 8 bpp range. */
1271 pixd = pixCopy(NULL, pixs);
1272 cmap = pixcmapCreateLinear(d, 1 << d);
1273 pixSetColormap(pixd, cmap);
1274 pixCopyInputFormat(pixd, pixs);
1275 return pixd;
1276}
1277
1278
1301PIX *
1303 l_int32 mindepth)
1304{
1305l_int32 ncolors, w, h, depth, i, j, wpls, wpld;
1306l_int32 index, num, val, newval;
1307l_int32 array[256];
1308l_uint32 *lines, *lined, *datas, *datad;
1309NUMA *na;
1310PIX *pixd;
1311PIXCMAP *cmap;
1312
1313 PROCNAME("pixConvertGrayToColormap8");
1314
1315 if (!pixs)
1316 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1317 if (pixGetDepth(pixs) != 8)
1318 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1319 if (mindepth != 2 && mindepth != 4 && mindepth != 8) {
1320 L_WARNING("invalid value of mindepth; setting to 8\n", procName);
1321 mindepth = 8;
1322 }
1323
1324 if (pixGetColormap(pixs)) {
1325 L_INFO("pixs already has a colormap\n", procName);
1326 return pixCopy(NULL, pixs);
1327 }
1328
1329 na = pixGetGrayHistogram(pixs, 1);
1331 if (mindepth == 8 || ncolors > 16)
1332 depth = 8;
1333 else if (mindepth == 4 || ncolors > 4)
1334 depth = 4;
1335 else
1336 depth = 2;
1337
1338 pixGetDimensions(pixs, &w, &h, NULL);
1339 pixd = pixCreate(w, h, depth);
1340 cmap = pixcmapCreate(depth);
1341 pixSetColormap(pixd, cmap);
1342 pixCopyInputFormat(pixd, pixs);
1343 pixCopyResolution(pixd, pixs);
1344
1345 index = 0;
1346 for (i = 0; i < 256; i++) {
1347 array[i] = 0; /* only to quiet the static checker */
1348 numaGetIValue(na, i, &num);
1349 if (num > 0) {
1350 pixcmapAddColor(cmap, i, i, i);
1351 array[i] = index;
1352 index++;
1353 }
1354 }
1355
1356 datas = pixGetData(pixs);
1357 wpls = pixGetWpl(pixs);
1358 datad = pixGetData(pixd);
1359 wpld = pixGetWpl(pixd);
1360 for (i = 0; i < h; i++) {
1361 lines = datas + i * wpls;
1362 lined = datad + i * wpld;
1363 for (j = 0; j < w; j++) {
1364 val = GET_DATA_BYTE(lines, j);
1365 newval = array[val];
1366 if (depth == 2)
1367 SET_DATA_DIBIT(lined, j, newval);
1368 else if (depth == 4)
1369 SET_DATA_QBIT(lined, j, newval);
1370 else /* depth == 8 */
1371 SET_DATA_BYTE(lined, j, newval);
1372 }
1373 }
1374
1375 numaDestroy(&na);
1376 return pixd;
1377}
1378
1379
1380/*---------------------------------------------------------------------------*
1381 * Colorizing conversion from grayscale to color *
1382 *---------------------------------------------------------------------------*/
1398PIX *
1400 l_uint32 color,
1401 l_int32 cmapflag)
1402{
1403l_int32 i, j, w, h, wplt, wpld, val8;
1404l_uint32 *datad, *datat, *lined, *linet, *tab;
1405PIX *pixt, *pixd;
1406PIXCMAP *cmap;
1407
1408 PROCNAME("pixColorizeGray");
1409
1410 if (!pixs)
1411 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1412 if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
1413 return (PIX *)ERROR_PTR("pixs not 8 bpp or cmapped", procName, NULL);
1414
1415 if (pixGetColormap(pixs))
1417 else
1418 pixt = pixClone(pixs);
1419
1420 cmap = pixcmapGrayToColor(color);
1421 if (cmapflag) {
1422 pixd = pixCopy(NULL, pixt);
1423 pixSetColormap(pixd, cmap);
1424 pixDestroy(&pixt);
1425 return pixd;
1426 }
1427
1428 /* Make an RGB pix */
1429 pixcmapToRGBTable(cmap, &tab, NULL);
1430 pixGetDimensions(pixt, &w, &h, NULL);
1431 pixd = pixCreate(w, h, 32);
1432 pixCopyResolution(pixd, pixs);
1433 pixCopyInputFormat(pixd, pixs);
1434 datad = pixGetData(pixd);
1435 wpld = pixGetWpl(pixd);
1436 datat = pixGetData(pixt);
1437 wplt = pixGetWpl(pixt);
1438 for (i = 0; i < h; i++) {
1439 lined = datad + i * wpld;
1440 linet = datat + i * wplt;
1441 for (j = 0; j < w; j++) {
1442 val8 = GET_DATA_BYTE(linet, j);
1443 lined[j] = tab[val8];
1444 }
1445 }
1446
1447 pixDestroy(&pixt);
1448 pixcmapDestroy(&cmap);
1449 LEPT_FREE(tab);
1450 return pixd;
1451}
1452
1453
1454/*---------------------------------------------------------------------------*
1455 * Conversion from RGB color to colormap *
1456 *---------------------------------------------------------------------------*/
1485PIX *
1487 l_int32 ditherflag)
1488{
1489l_int32 ncolors;
1490NUMA *na;
1491PIX *pixd;
1492
1493 PROCNAME("pixConvertRGBToColormap");
1494
1495 if (!pixs)
1496 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1497 if (pixGetDepth(pixs) != 32)
1498 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1499 if (pixGetSpp(pixs) == 4)
1500 L_WARNING("pixs has alpha; removing\n", procName);
1501
1502 /* Get the histogram and count the number of occupied level 4
1503 * leaf octcubes. We don't yet know if this is the number of
1504 * actual colors, but if it's not, all pixels falling into
1505 * the same leaf octcube will be assigned to the color of the
1506 * first pixel that lands there. */
1507 na = pixOctcubeHistogram(pixs, 4, &ncolors);
1508
1509 /* If 256 or fewer occupied leaf octcubes, quantize to those octcubes */
1510 if (ncolors <= 256) {
1511 pixd = pixFewColorsOctcubeQuant2(pixs, 4, na, ncolors, NULL);
1512 pixCopyInputFormat(pixd, pixs);
1513 numaDestroy(&na);
1514 return pixd;
1515 }
1516
1517 /* There are too many occupied leaf octcubes to be represented
1518 * directly in a colormap. Fall back to octree quantization,
1519 * optionally with dithering. */
1520 numaDestroy(&na);
1521 if (ditherflag)
1522 L_INFO("More than 256 colors; using octree quant with dithering\n",
1523 procName);
1524 else
1525 L_INFO("More than 256 colors; using octree quant; no dithering\n",
1526 procName);
1527 return pixOctreeColorQuant(pixs, 240, ditherflag);
1528}
1529
1530
1531/*---------------------------------------------------------------------------*
1532 * Conversion from colormap to 1 bpp *
1533 *---------------------------------------------------------------------------*/
1549PIX *
1551{
1552l_int32 i, j, nc, w, h, imin, imax, factor, wpl1, wpld;
1553l_int32 index, rmin, gmin, bmin, rmax, gmax, bmax, dmin, dmax;
1554l_float32 minfract, ifract;
1555l_int32 *lut;
1556l_uint32 *line1, *lined, *data1, *datad;
1557NUMA *na1, *na2; /* histograms */
1558PIX *pix1, *pixd;
1559PIXCMAP *cmap;
1560
1561 PROCNAME("pixConvertCmapTo1");
1562
1563 if (!pixs)
1564 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1565 if ((cmap = pixGetColormap(pixs)) == NULL)
1566 return (PIX *)ERROR_PTR("no colormap", procName, NULL);
1567
1568 /* Select target colors for the two classes. Find the
1569 * colors with smallest and largest average component values.
1570 * The smallest is class 0 and the largest is class 1. */
1571 pixcmapGetRangeValues(cmap, L_SELECT_AVERAGE, NULL, NULL, &imin, &imax);
1572 pixcmapGetColor(cmap, imin, &rmin, &gmin, &bmin);
1573 pixcmapGetColor(cmap, imax, &rmax, &gmax, &bmax);
1574 nc = pixcmapGetCount(cmap);
1575
1576 /* Assign colors to the two classes. The histogram is
1577 * initialized to 0, so any colors not found when computing
1578 * the sampled histogram will get zero weight in minfract. */
1579 if ((lut = (l_int32 *)LEPT_CALLOC(nc, sizeof(l_int32))) == NULL)
1580 return (PIX *)ERROR_PTR("calloc fail for lut", procName, NULL);
1581 pixGetDimensions(pixs, &w, &h, NULL);
1582 factor = L_MAX(1, (l_int32)sqrt((l_float64)(w * h) / 50000. + 0.5));
1583 na1 = pixGetCmapHistogram(pixs, factor);
1584 na2 = numaNormalizeHistogram(na1, 1.0);
1585 minfract = 0.0;
1586 for (i = 0; i < nc; i++) {
1587 numaGetFValue(na2, i, &ifract);
1588 pixcmapGetDistanceToColor(cmap, i, rmin, gmin, bmin, &dmin);
1589 pixcmapGetDistanceToColor(cmap, i, rmax, gmax, bmax, &dmax);
1590 if (dmin < dmax) { /* closer to dark extreme value */
1591 lut[i] = 1; /* black pixel in 1 bpp image */
1592 minfract += ifract;
1593 }
1594 }
1595 numaDestroy(&na1);
1596 numaDestroy(&na2);
1597
1598 /* Generate the output binarized image */
1599 pix1 = pixConvertTo8(pixs, 1);
1600 pixd = pixCreate(w, h, 1);
1601 data1 = pixGetData(pix1);
1602 datad = pixGetData(pixd);
1603 wpl1 = pixGetWpl(pix1);
1604 wpld = pixGetWpl(pixd);
1605 for (i = 0; i < h; i++) {
1606 line1 = data1 + i * wpl1;
1607 lined = datad + i * wpld;
1608 for (j = 0; j < w; j++) {
1609 index = GET_DATA_BYTE(line1, j);
1610 if (lut[index] == 1) SET_DATA_BIT(lined, j);
1611 }
1612 }
1613 pixDestroy(&pix1);
1614 LEPT_FREE(lut);
1615
1616 /* We expect minfract (the dark colors) to be less than 0.5.
1617 * If that is not the case, invert pixd. */
1618 if (minfract > 0.5) {
1619 L_INFO("minfract = %5.3f; inverting\n", procName, minfract);
1620 pixInvert(pixd, pixd);
1621 }
1622
1623 return pixd;
1624}
1625
1626
1627/*---------------------------------------------------------------------------*
1628 * Quantization for relatively small number of colors in source *
1629 *---------------------------------------------------------------------------*/
1660l_ok
1662 l_int32 maxcolors,
1663 l_int32 mingraycolors,
1664 l_int32 octlevel,
1665 PIX **ppixd)
1666{
1667l_int32 d, ncolors, iscolor, graycolors;
1668PIX *pixg, *pixd;
1669
1670 PROCNAME("pixQuantizeIfFewColors");
1671
1672 if (!ppixd)
1673 return ERROR_INT("&pixd not defined", procName, 1);
1674 *ppixd = NULL;
1675 if (!pixs)
1676 return ERROR_INT("pixs not defined", procName, 1);
1677 d = pixGetDepth(pixs);
1678 if (d != 8 && d != 32)
1679 return ERROR_INT("pixs not defined", procName, 1);
1680 if (pixGetColormap(pixs) != NULL) {
1681 *ppixd = pixClone(pixs);
1682 return 0;
1683 }
1684 if (maxcolors <= 0)
1685 maxcolors = 15; /* default */
1686 if (maxcolors > 50)
1687 L_WARNING("maxcolors > 50; very large!\n", procName);
1688 if (mingraycolors <= 0)
1689 mingraycolors = 10; /* default */
1690 if (mingraycolors > 30)
1691 L_WARNING("mingraycolors > 30; very large!\n", procName);
1692 if (octlevel != 3 && octlevel != 4) {
1693 L_WARNING("invalid octlevel; setting to 3\n", procName);
1694 octlevel = 3;
1695 }
1696
1697 /* Test the number of colors. For color, the octcube leaves
1698 * are at level 4. */
1699 pixColorsForQuantization(pixs, 0, &ncolors, &iscolor, 0);
1700 if (ncolors > maxcolors)
1701 return ERROR_INT("too many colors", procName, 1);
1702
1703 /* Quantize!
1704 * (1) For color:
1705 * If octlevel == 4, try to quantize to an octree where
1706 * the octcube leaves are at level 4. If that fails,
1707 * back off to level 3.
1708 * If octlevel == 3, quantize to level 3 directly.
1709 * For level 3, the quality is usually good enough and there
1710 * is negligible chance of getting more than 256 colors.
1711 * (2) For grayscale, multiply ncolors by 1.5 for extra quality,
1712 * but use at least mingraycolors and not more than 256. */
1713 if (iscolor) {
1714 pixd = pixFewColorsOctcubeQuant1(pixs, octlevel);
1715 if (!pixd) { /* backoff */
1716 pixd = pixFewColorsOctcubeQuant1(pixs, octlevel - 1);
1717 if (octlevel == 3) /* shouldn't happen */
1718 L_WARNING("quantized at level 2; low quality\n", procName);
1719 }
1720 } else { /* image is really grayscale */
1721 if (d == 32)
1722 pixg = pixConvertRGBToLuminance(pixs);
1723 else
1724 pixg = pixClone(pixs);
1725 graycolors = L_MAX(mingraycolors, (l_int32)(1.5 * ncolors));
1726 graycolors = L_MIN(graycolors, 256);
1727 if (graycolors < 16)
1728 pixd = pixThresholdTo4bpp(pixg, graycolors, 1);
1729 else
1730 pixd = pixThresholdOn8bpp(pixg, graycolors, 1);
1731 pixDestroy(&pixg);
1732 }
1733 *ppixd = pixd;
1734
1735 if (!pixd)
1736 return ERROR_INT("pixd not made", procName, 1);
1737 pixCopyInputFormat(pixd, pixs);
1738 return 0;
1739}
1740
1741
1742
1743/*---------------------------------------------------------------------------*
1744 * Conversion from 16 bpp to 8 bpp *
1745 *---------------------------------------------------------------------------*/
1761PIX *
1763 l_int32 type)
1764{
1765l_uint16 dword;
1766l_int32 w, h, wpls, wpld, i, j, val, use_lsb;
1767l_uint32 sword, first, second;
1768l_uint32 *datas, *datad, *lines, *lined;
1769PIX *pixd;
1770
1771 PROCNAME("pixConvert16To8");
1772
1773 if (!pixs)
1774 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1775 if (pixGetDepth(pixs) != 16)
1776 return (PIX *)ERROR_PTR("pixs not 16 bpp", procName, NULL);
1777 if (type != L_LS_BYTE && type != L_MS_BYTE &&
1778 type != L_AUTO_BYTE && type != L_CLIP_TO_FF)
1779 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1780
1781 pixGetDimensions(pixs, &w, &h, NULL);
1782 if ((pixd = pixCreate(w, h, 8)) == NULL)
1783 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1784 pixCopyInputFormat(pixd, pixs);
1785 pixCopyResolution(pixd, pixs);
1786 wpls = pixGetWpl(pixs);
1787 datas = pixGetData(pixs);
1788 wpld = pixGetWpl(pixd);
1789 datad = pixGetData(pixd);
1790
1791 if (type == L_AUTO_BYTE) {
1792 use_lsb = TRUE;
1793 for (i = 0; i < h; i++) {
1794 lines = datas + i * wpls;
1795 for (j = 0; j < wpls; j++) {
1796 val = GET_DATA_TWO_BYTES(lines, j);
1797 if (val > 255) {
1798 use_lsb = FALSE;
1799 break;
1800 }
1801 }
1802 if (!use_lsb) break;
1803 }
1804 type = (use_lsb) ? L_LS_BYTE : L_MS_BYTE;
1805 }
1806
1807 /* Convert 2 pixels at a time */
1808 for (i = 0; i < h; i++) {
1809 lines = datas + i * wpls;
1810 lined = datad + i * wpld;
1811 if (type == L_LS_BYTE) {
1812 for (j = 0; j < wpls; j++) {
1813 sword = *(lines + j);
1814 dword = ((sword >> 8) & 0xff00) | (sword & 0xff);
1815 SET_DATA_TWO_BYTES(lined, j, dword);
1816 }
1817 } else if (type == L_MS_BYTE) {
1818 for (j = 0; j < wpls; j++) {
1819 sword = *(lines + j);
1820 dword = ((sword >> 16) & 0xff00) | ((sword >> 8) & 0xff);
1821 SET_DATA_TWO_BYTES(lined, j, dword);
1822 }
1823 } else { /* type == L_CLIP_TO_FF */
1824 for (j = 0; j < wpls; j++) {
1825 sword = *(lines + j);
1826 first = (sword >> 24) ? 255 : ((sword >> 16) & 0xff);
1827 second = ((sword >> 8) & 0xff) ? 255 : (sword & 0xff);
1828 dword = (first << 8) | second;
1829 SET_DATA_TWO_BYTES(lined, j, dword);
1830 }
1831 }
1832 }
1833
1834 return pixd;
1835}
1836
1837
1838/*---------------------------------------------------------------------------*
1839 * Conversion from grayscale to false color
1840 *---------------------------------------------------------------------------*/
1857PIX *
1859 l_float32 gamma)
1860{
1861l_int32 d;
1862PIX *pixd;
1863PIXCMAP *cmap;
1864
1865 PROCNAME("pixConvertGrayToFalseColor");
1866
1867 if (!pixs)
1868 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1869 d = pixGetDepth(pixs);
1870 if (d != 8 && d != 16)
1871 return (PIX *)ERROR_PTR("pixs not 8 or 16 bpp", procName, NULL);
1872
1873 if (d == 16) {
1874 pixd = pixConvert16To8(pixs, L_MS_BYTE);
1875 } else { /* d == 8 */
1876 if (pixGetColormap(pixs))
1878 else
1879 pixd = pixCopy(NULL, pixs);
1880 }
1881 if (!pixd)
1882 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1883
1884 cmap = pixcmapGrayToFalseColor(gamma);
1885 pixSetColormap(pixd, cmap);
1886 pixCopyResolution(pixd, pixs);
1887 pixCopyInputFormat(pixd, pixs);
1888 return pixd;
1889}
1890
1891
1892/*---------------------------------------------------------------------------*
1893 * Unpacking conversion from 1 bpp to 2, 4, 8, 16 and 32 bpp *
1894 *---------------------------------------------------------------------------*/
1912PIX *
1914 l_int32 depth,
1915 l_int32 invert)
1916{
1917PIX *pixd;
1918
1919 PROCNAME("pixUnpackBinary");
1920
1921 if (!pixs)
1922 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1923 if (pixGetDepth(pixs) != 1)
1924 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
1925 if (depth != 2 && depth != 4 && depth != 8 && depth != 16 && depth != 32)
1926 return (PIX *)ERROR_PTR("depth not 2, 4, 8, 16 or 32 bpp",
1927 procName, NULL);
1928
1929 if (depth == 2) {
1930 if (invert == 0)
1931 pixd = pixConvert1To2(NULL, pixs, 0, 3);
1932 else /* invert bits */
1933 pixd = pixConvert1To2(NULL, pixs, 3, 0);
1934 } else if (depth == 4) {
1935 if (invert == 0)
1936 pixd = pixConvert1To4(NULL, pixs, 0, 15);
1937 else /* invert bits */
1938 pixd = pixConvert1To4(NULL, pixs, 15, 0);
1939 } else if (depth == 8) {
1940 if (invert == 0)
1941 pixd = pixConvert1To8(NULL, pixs, 0, 255);
1942 else /* invert bits */
1943 pixd = pixConvert1To8(NULL, pixs, 255, 0);
1944 } else if (depth == 16) {
1945 if (invert == 0)
1946 pixd = pixConvert1To16(NULL, pixs, 0, 0xffff);
1947 else /* invert bits */
1948 pixd = pixConvert1To16(NULL, pixs, 0xffff, 0);
1949 } else {
1950 if (invert == 0)
1951 pixd = pixConvert1To32(NULL, pixs, 0, 0xffffffff);
1952 else /* invert bits */
1953 pixd = pixConvert1To32(NULL, pixs, 0xffffffff, 0);
1954 }
1955
1956 pixCopyInputFormat(pixd, pixs);
1957 return pixd;
1958}
1959
1960
1977PIX *
1979 PIX *pixs,
1980 l_uint16 val0,
1981 l_uint16 val1)
1982{
1983l_int32 w, h, i, j, dibit, ndibits, wpls, wpld;
1984l_uint16 val[2];
1985l_uint32 index;
1986l_uint32 *tab, *datas, *datad, *lines, *lined;
1987
1988 PROCNAME("pixConvert1To16");
1989
1990 if (!pixs)
1991 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1992 if (pixGetDepth(pixs) != 1)
1993 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
1994
1995 pixGetDimensions(pixs, &w, &h, NULL);
1996 if (pixd) {
1997 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
1998 return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
1999 if (pixGetDepth(pixd) != 16)
2000 return (PIX *)ERROR_PTR("pixd not 16 bpp", procName, pixd);
2001 } else {
2002 if ((pixd = pixCreate(w, h, 16)) == NULL)
2003 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2004 }
2005 pixCopyResolution(pixd, pixs);
2006 pixCopyInputFormat(pixd, pixs);
2007
2008 /* Use a table to convert 2 src bits at a time */
2009 tab = (l_uint32 *)LEPT_CALLOC(4, sizeof(l_uint32));
2010 val[0] = val0;
2011 val[1] = val1;
2012 for (index = 0; index < 4; index++) {
2013 tab[index] = (val[(index >> 1) & 1] << 16) | val[index & 1];
2014 }
2015
2016 datas = pixGetData(pixs);
2017 wpls = pixGetWpl(pixs);
2018 datad = pixGetData(pixd);
2019 wpld = pixGetWpl(pixd);
2020 ndibits = (w + 1) / 2;
2021 for (i = 0; i < h; i++) {
2022 lines = datas + i * wpls;
2023 lined = datad + i * wpld;
2024 for (j = 0; j < ndibits; j++) {
2025 dibit = GET_DATA_DIBIT(lines, j);
2026 lined[j] = tab[dibit];
2027 }
2028 }
2029
2030 LEPT_FREE(tab);
2031 return pixd;
2032}
2033
2034
2051PIX *
2053 PIX *pixs,
2054 l_uint32 val0,
2055 l_uint32 val1)
2056{
2057l_int32 w, h, i, j, wpls, wpld, bit;
2058l_uint32 val[2];
2059l_uint32 *datas, *datad, *lines, *lined;
2060
2061 PROCNAME("pixConvert1To32");
2062
2063 if (!pixs)
2064 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2065 if (pixGetDepth(pixs) != 1)
2066 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2067
2068 pixGetDimensions(pixs, &w, &h, NULL);
2069 if (pixd) {
2070 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2071 return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2072 if (pixGetDepth(pixd) != 32)
2073 return (PIX *)ERROR_PTR("pixd not 32 bpp", procName, pixd);
2074 } else {
2075 if ((pixd = pixCreate(w, h, 32)) == NULL)
2076 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2077 }
2078 pixCopyResolution(pixd, pixs);
2079 pixCopyInputFormat(pixd, pixs);
2080
2081 val[0] = val0;
2082 val[1] = val1;
2083 datas = pixGetData(pixs);
2084 wpls = pixGetWpl(pixs);
2085 datad = pixGetData(pixd);
2086 wpld = pixGetWpl(pixd);
2087 for (i = 0; i < h; i++) {
2088 lines = datas + i * wpls;
2089 lined = datad + i * wpld;
2090 for (j = 0; j <w; j++) {
2091 bit = GET_DATA_BIT(lines, j);
2092 lined[j] = val[bit];
2093 }
2094 }
2095
2096 return pixd;
2097}
2098
2099
2100/*---------------------------------------------------------------------------*
2101 * Conversion from 1 bpp to 2 bpp *
2102 *---------------------------------------------------------------------------*/
2114PIX *
2116{
2117PIX *pixd;
2118PIXCMAP *cmap;
2119
2120 PROCNAME("pixConvert1To2Cmap");
2121
2122 if (!pixs)
2123 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2124 if (pixGetDepth(pixs) != 1)
2125 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2126
2127 if ((pixd = pixConvert1To2(NULL, pixs, 0, 1)) == NULL)
2128 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2129 cmap = pixcmapCreate(2);
2130 pixcmapAddColor(cmap, 255, 255, 255);
2131 pixcmapAddColor(cmap, 0, 0, 0);
2132 pixSetColormap(pixd, cmap);
2133 pixCopyInputFormat(pixd, pixs);
2134
2135 return pixd;
2136}
2137
2138
2157PIX *
2159 PIX *pixs,
2160 l_int32 val0,
2161 l_int32 val1)
2162{
2163l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2164l_uint8 val[2];
2165l_uint32 index;
2166l_uint16 *tab;
2167l_uint32 *datas, *datad, *lines, *lined;
2168
2169 PROCNAME("pixConvert1To2");
2170
2171 if (!pixs)
2172 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
2173 if (pixGetDepth(pixs) != 1)
2174 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
2175
2176 pixGetDimensions(pixs, &w, &h, NULL);
2177 if (pixd) {
2178 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2179 return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2180 if (pixGetDepth(pixd) != 2)
2181 return (PIX *)ERROR_PTR("pixd not 2 bpp", procName, pixd);
2182 } else {
2183 if ((pixd = pixCreate(w, h, 2)) == NULL)
2184 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2185 }
2186 pixCopyResolution(pixd, pixs);
2187 pixCopyInputFormat(pixd, pixs);
2188
2189 /* Use a table to convert 8 src bits to 16 dest bits */
2190 tab = (l_uint16 *)LEPT_CALLOC(256, sizeof(l_uint16));
2191 val[0] = val0;
2192 val[1] = val1;
2193 for (index = 0; index < 256; index++) {
2194 tab[index] = (val[(index >> 7) & 1] << 14) |
2195 (val[(index >> 6) & 1] << 12) |
2196 (val[(index >> 5) & 1] << 10) |
2197 (val[(index >> 4) & 1] << 8) |
2198 (val[(index >> 3) & 1] << 6) |
2199 (val[(index >> 2) & 1] << 4) |
2200 (val[(index >> 1) & 1] << 2) | val[index & 1];
2201 }
2202
2203 datas = pixGetData(pixs);
2204 wpls = pixGetWpl(pixs);
2205 datad = pixGetData(pixd);
2206 wpld = pixGetWpl(pixd);
2207 nbytes = (w + 7) / 8;
2208 for (i = 0; i < h; i++) {
2209 lines = datas + i * wpls;
2210 lined = datad + i * wpld;
2211 for (j = 0; j < nbytes; j++) {
2212 byteval = GET_DATA_BYTE(lines, j);
2213 SET_DATA_TWO_BYTES(lined, j, tab[byteval]);
2214 }
2215 }
2216
2217 LEPT_FREE(tab);
2218 return pixd;
2219}
2220
2221
2222/*---------------------------------------------------------------------------*
2223 * Conversion from 1 bpp to 4 bpp *
2224 *---------------------------------------------------------------------------*/
2236PIX *
2238{
2239PIX *pixd;
2240PIXCMAP *cmap;
2241
2242 PROCNAME("pixConvert1To4Cmap");
2243
2244 if (!pixs)
2245 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2246 if (pixGetDepth(pixs) != 1)
2247 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2248
2249 if ((pixd = pixConvert1To4(NULL, pixs, 0, 1)) == NULL)
2250 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2251 cmap = pixcmapCreate(4);
2252 pixcmapAddColor(cmap, 255, 255, 255);
2253 pixcmapAddColor(cmap, 0, 0, 0);
2254 pixSetColormap(pixd, cmap);
2255 pixCopyInputFormat(pixd, pixs);
2256
2257 return pixd;
2258}
2259
2260
2279PIX *
2281 PIX *pixs,
2282 l_int32 val0,
2283 l_int32 val1)
2284{
2285l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2286l_uint8 val[2];
2287l_uint32 index;
2288l_uint32 *tab, *datas, *datad, *lines, *lined;
2289
2290 PROCNAME("pixConvert1To4");
2291
2292 if (!pixs)
2293 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
2294 if (pixGetDepth(pixs) != 1)
2295 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
2296
2297 pixGetDimensions(pixs, &w, &h, NULL);
2298 if (pixd) {
2299 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2300 return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2301 if (pixGetDepth(pixd) != 4)
2302 return (PIX *)ERROR_PTR("pixd not 4 bpp", procName, pixd);
2303 } else {
2304 if ((pixd = pixCreate(w, h, 4)) == NULL)
2305 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2306 }
2307 pixCopyResolution(pixd, pixs);
2308 pixCopyInputFormat(pixd, pixs);
2309
2310 /* Use a table to convert 8 src bits to 32 bit dest word */
2311 tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
2312 val[0] = val0;
2313 val[1] = val1;
2314 for (index = 0; index < 256; index++) {
2315 tab[index] = (val[(index >> 7) & 1] << 28) |
2316 (val[(index >> 6) & 1] << 24) |
2317 (val[(index >> 5) & 1] << 20) |
2318 (val[(index >> 4) & 1] << 16) |
2319 (val[(index >> 3) & 1] << 12) |
2320 (val[(index >> 2) & 1] << 8) |
2321 (val[(index >> 1) & 1] << 4) | val[index & 1];
2322 }
2323
2324 datas = pixGetData(pixs);
2325 wpls = pixGetWpl(pixs);
2326 datad = pixGetData(pixd);
2327 wpld = pixGetWpl(pixd);
2328 nbytes = (w + 7) / 8;
2329 for (i = 0; i < h; i++) {
2330 lines = datas + i * wpls;
2331 lined = datad + i * wpld;
2332 for (j = 0; j < nbytes; j++) {
2333 byteval = GET_DATA_BYTE(lines, j);
2334 lined[j] = tab[byteval];
2335 }
2336 }
2337
2338 LEPT_FREE(tab);
2339 return pixd;
2340}
2341
2342
2343/*---------------------------------------------------------------------------*
2344 * Conversion from 1, 2 and 4 bpp to 8 bpp *
2345 *---------------------------------------------------------------------------*/
2357PIX *
2359{
2360PIX *pixd;
2361PIXCMAP *cmap;
2362
2363 PROCNAME("pixConvert1To8Cmap");
2364
2365 if (!pixs)
2366 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2367 if (pixGetDepth(pixs) != 1)
2368 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2369
2370 if ((pixd = pixConvert1To8(NULL, pixs, 0, 1)) == NULL)
2371 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2372 cmap = pixcmapCreate(8);
2373 pixcmapAddColor(cmap, 255, 255, 255);
2374 pixcmapAddColor(cmap, 0, 0, 0);
2375 pixSetColormap(pixd, cmap);
2376 pixCopyInputFormat(pixd, pixs);
2377 return pixd;
2378}
2379
2380
2400PIX *
2402 PIX *pixs,
2403 l_uint8 val0,
2404 l_uint8 val1)
2405{
2406l_int32 w, h, i, j, qbit, nqbits, wpls, wpld;
2407l_uint8 val[2];
2408l_uint32 index;
2409l_uint32 *tab, *datas, *datad, *lines, *lined;
2410
2411 PROCNAME("pixConvert1To8");
2412
2413 if (!pixs)
2414 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
2415 if (pixGetDepth(pixs) != 1)
2416 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
2417
2418 pixGetDimensions(pixs, &w, &h, NULL);
2419 if (pixd) {
2420 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2421 return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2422 if (pixGetDepth(pixd) != 8)
2423 return (PIX *)ERROR_PTR("pixd not 8 bpp", procName, pixd);
2424 } else {
2425 if ((pixd = pixCreate(w, h, 8)) == NULL)
2426 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2427 }
2428 pixCopyResolution(pixd, pixs);
2429 pixCopyInputFormat(pixd, pixs);
2430 pixSetPadBits(pixs, 0);
2431
2432 /* Use a table to convert 4 src bits at a time */
2433 tab = (l_uint32 *)LEPT_CALLOC(16, sizeof(l_uint32));
2434 val[0] = val0;
2435 val[1] = val1;
2436 for (index = 0; index < 16; index++) {
2437 tab[index] = ((l_uint32)val[(index >> 3) & 1] << 24) |
2438 (val[(index >> 2) & 1] << 16) |
2439 (val[(index >> 1) & 1] << 8) | val[index & 1];
2440 }
2441
2442 datas = pixGetData(pixs);
2443 wpls = pixGetWpl(pixs);
2444 datad = pixGetData(pixd);
2445 wpld = pixGetWpl(pixd);
2446 nqbits = (w + 3) / 4;
2447 for (i = 0; i < h; i++) {
2448 lines = datas + i * wpls;
2449 lined = datad + i * wpld;
2450 for (j = 0; j < nqbits; j++) {
2451 qbit = GET_DATA_QBIT(lines, j);
2452 lined[j] = tab[qbit];
2453 }
2454 }
2455
2456 LEPT_FREE(tab);
2457 return pixd;
2458}
2459
2460
2491PIX *
2493 l_uint8 val0,
2494 l_uint8 val1,
2495 l_uint8 val2,
2496 l_uint8 val3,
2497 l_int32 cmapflag)
2498{
2499l_int32 w, h, i, j, nbytes, wpls, wpld, dibit, byte;
2500l_uint32 val[4];
2501l_uint32 index;
2502l_uint32 *tab, *datas, *datad, *lines, *lined;
2503PIX *pixd;
2504PIXCMAP *cmaps, *cmapd;
2505
2506 PROCNAME("pixConvert2To8");
2507
2508 if (!pixs)
2509 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2510 if (pixGetDepth(pixs) != 2)
2511 return (PIX *)ERROR_PTR("pixs not 2 bpp", procName, NULL);
2512
2513 cmaps = pixGetColormap(pixs);
2514 if (cmaps && cmapflag == FALSE)
2516
2517 pixGetDimensions(pixs, &w, &h, NULL);
2518 if ((pixd = pixCreate(w, h, 8)) == NULL)
2519 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2520 pixSetPadBits(pixs, 0);
2521 pixCopyResolution(pixd, pixs);
2522 pixCopyInputFormat(pixd, pixs);
2523 datas = pixGetData(pixs);
2524 wpls = pixGetWpl(pixs);
2525 datad = pixGetData(pixd);
2526 wpld = pixGetWpl(pixd);
2527
2528 if (cmapflag == TRUE) { /* pixd will have a colormap */
2529 if (cmaps) { /* use the existing colormap from pixs */
2530 cmapd = pixcmapConvertTo8(cmaps);
2531 } else { /* make a colormap from the input values */
2532 cmapd = pixcmapCreate(8);
2533 pixcmapAddColor(cmapd, val0, val0, val0);
2534 pixcmapAddColor(cmapd, val1, val1, val1);
2535 pixcmapAddColor(cmapd, val2, val2, val2);
2536 pixcmapAddColor(cmapd, val3, val3, val3);
2537 }
2538 pixSetColormap(pixd, cmapd);
2539 for (i = 0; i < h; i++) {
2540 lines = datas + i * wpls;
2541 lined = datad + i * wpld;
2542 for (j = 0; j < w; j++) {
2543 dibit = GET_DATA_DIBIT(lines, j);
2544 SET_DATA_BYTE(lined, j, dibit);
2545 }
2546 }
2547 return pixd;
2548 }
2549
2550 /* Last case: no colormap in either pixs or pixd.
2551 * Use input values and build a table to convert 1 src byte
2552 * (4 src pixels) at a time */
2553 tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
2554 val[0] = val0;
2555 val[1] = val1;
2556 val[2] = val2;
2557 val[3] = val3;
2558 for (index = 0; index < 256; index++) {
2559 tab[index] = (val[(index >> 6) & 3] << 24) |
2560 (val[(index >> 4) & 3] << 16) |
2561 (val[(index >> 2) & 3] << 8) | val[index & 3];
2562 }
2563
2564 nbytes = (w + 3) / 4;
2565 for (i = 0; i < h; i++) {
2566 lines = datas + i * wpls;
2567 lined = datad + i * wpld;
2568 for (j = 0; j < nbytes; j++) {
2569 byte = GET_DATA_BYTE(lines, j);
2570 lined[j] = tab[byte];
2571 }
2572 }
2573
2574 LEPT_FREE(tab);
2575 return pixd;
2576}
2577
2578
2603PIX *
2605 l_int32 cmapflag)
2606{
2607l_int32 w, h, i, j, wpls, wpld, byte, qbit;
2608l_uint32 *datas, *datad, *lines, *lined;
2609PIX *pixd;
2610PIXCMAP *cmaps, *cmapd;
2611
2612 PROCNAME("pixConvert4To8");
2613
2614 if (!pixs)
2615 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2616 if (pixGetDepth(pixs) != 4)
2617 return (PIX *)ERROR_PTR("pixs not 4 bpp", procName, NULL);
2618
2619 cmaps = pixGetColormap(pixs);
2620 if (cmaps && cmapflag == FALSE)
2622
2623 pixGetDimensions(pixs, &w, &h, NULL);
2624 if ((pixd = pixCreate(w, h, 8)) == NULL)
2625 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2626 pixCopyResolution(pixd, pixs);
2627 pixCopyInputFormat(pixd, pixs);
2628 datas = pixGetData(pixs);
2629 wpls = pixGetWpl(pixs);
2630 datad = pixGetData(pixd);
2631 wpld = pixGetWpl(pixd);
2632
2633 if (cmapflag == TRUE) { /* pixd will have a colormap */
2634 if (cmaps) { /* use the existing colormap from pixs */
2635 cmapd = pixcmapConvertTo8(cmaps);
2636 } else { /* make a colormap with a linear trc */
2637 cmapd = pixcmapCreate(8);
2638 for (i = 0; i < 16; i++)
2639 pixcmapAddColor(cmapd, 17 * i, 17 * i, 17 * i);
2640 }
2641 pixSetColormap(pixd, cmapd);
2642 for (i = 0; i < h; i++) {
2643 lines = datas + i * wpls;
2644 lined = datad + i * wpld;
2645 for (j = 0; j < w; j++) {
2646 qbit = GET_DATA_QBIT(lines, j);
2647 SET_DATA_BYTE(lined, j, qbit);
2648 }
2649 }
2650 return pixd;
2651 }
2652
2653 /* Last case: no colormap in either pixs or pixd.
2654 * Replicate the qbit value into 8 bits. */
2655 for (i = 0; i < h; i++) {
2656 lines = datas + i * wpls;
2657 lined = datad + i * wpld;
2658 for (j = 0; j < w; j++) {
2659 qbit = GET_DATA_QBIT(lines, j);
2660 byte = (qbit << 4) | qbit;
2661 SET_DATA_BYTE(lined, j, byte);
2662 }
2663 }
2664 return pixd;
2665}
2666
2667
2668
2669/*---------------------------------------------------------------------------*
2670 * Unpacking conversion from 8 bpp to 16 bpp *
2671 *---------------------------------------------------------------------------*/
2688PIX *
2690 l_int32 leftshift)
2691{
2692l_int32 i, j, w, h, d, wplt, wpld, val;
2693l_uint32 *datat, *datad, *linet, *lined;
2694PIX *pixt, *pixd;
2695
2696 PROCNAME("pixConvert8To16");
2697
2698 if (!pixs)
2699 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2700 pixGetDimensions(pixs, &w, &h, &d);
2701 if (d != 8)
2702 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
2703 if (leftshift < 0 || leftshift > 8)
2704 return (PIX *)ERROR_PTR("leftshift not in [0 ... 8]", procName, NULL);
2705
2706 if (pixGetColormap(pixs) != NULL)
2708 else
2709 pixt = pixClone(pixs);
2710
2711 pixd = pixCreate(w, h, 16);
2712 pixCopyResolution(pixd, pixs);
2713 pixCopyInputFormat(pixd, pixs);
2714 datat = pixGetData(pixt);
2715 datad = pixGetData(pixd);
2716 wplt = pixGetWpl(pixt);
2717 wpld = pixGetWpl(pixd);
2718 for (i = 0; i < h; i++) {
2719 linet = datat + i * wplt;
2720 lined = datad + i * wpld;
2721 for (j = 0; j < w; j++) {
2722 val = GET_DATA_BYTE(linet, j);
2723 if (leftshift == 8)
2724 val = val | (val << leftshift);
2725 else
2726 val <<= leftshift;
2727 SET_DATA_TWO_BYTES(lined, j, val);
2728 }
2729 }
2730
2731 pixDestroy(&pixt);
2732 return pixd;
2733}
2734
2735
2736/*---------------------------------------------------------------------------*
2737 * Top-level conversion to 2 bpp *
2738 *---------------------------------------------------------------------------*/
2754PIX *
2756{
2757l_int32 d;
2758PIX *pix1, *pix2, *pix3, *pixd;
2759
2760 PROCNAME("pixConvertTo2");
2761
2762 if (!pixs)
2763 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2764 d = pixGetDepth(pixs);
2765 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 24 && d != 32)
2766 return (PIX *)ERROR_PTR("depth not {1,2,4,8,24,32}", procName, NULL);
2767
2768 if (pixGetColormap(pixs) != NULL) {
2770 d = pixGetDepth(pix1);
2771 } else {
2772 pix1 = pixCopy(NULL, pixs);
2773 }
2774 if (d == 24 || d == 32)
2775 pix2 = pixConvertTo8(pix1, FALSE);
2776 else
2777 pix2 = pixClone(pix1);
2778 pixDestroy(&pix1);
2779 if (d == 1) {
2780 pixd = pixConvert1To2(NULL, pix2, 3, 0);
2781 } else if (d == 2) {
2782 pixd = pixClone(pix2);
2783 } else if (d == 4) {
2784 pix3 = pixConvert4To8(pix2, FALSE); /* unpack to 8 */
2785 pixd = pixConvert8To2(pix3);
2786 pixDestroy(&pix3);
2787 } else { /* d == 8 */
2788 pixd = pixConvert8To2(pix2);
2789 }
2790 pixDestroy(&pix2);
2791 return pixd;
2792}
2793
2794
2806PIX *
2808{
2809l_int32 i, j, w, h, wpls, wpld;
2810l_uint32 word;
2811l_uint32 *datas, *lines, *datad, *lined;
2812PIX *pixs, *pixd;
2813
2814 PROCNAME("pixConvert8To2");
2815
2816 if (!pix || pixGetDepth(pix) != 8)
2817 return (PIX *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2818
2819 if (pixGetColormap(pix) != NULL)
2821 else
2822 pixs = pixClone(pix);
2823 pixGetDimensions(pixs, &w, &h, NULL);
2824 datas = pixGetData(pixs);
2825 wpls = pixGetWpl(pixs);
2826 pixd = pixCreate(w, h, 2);
2827 datad = pixGetData(pixd);
2828 wpld = pixGetWpl(pixd);
2829 for (i = 0; i < h; i++) {
2830 lines = datas + i * wpls;
2831 lined = datad + i * wpld;
2832 for (j = 0; j < wpls; j++) { /* march through 4 pixels at a time */
2833 word = lines[j] & 0xc0c0c0c0; /* top 2 bits of each byte */
2834 word = (word >> 24) | ((word & 0xff0000) >> 18) |
2835 ((word & 0xff00) >> 12) | ((word & 0xff) >> 6);
2836 SET_DATA_BYTE(lined, j, word); /* only LS byte is filled */
2837 }
2838 }
2839 pixDestroy(&pixs);
2840 return pixd;
2841}
2842
2843
2844/*---------------------------------------------------------------------------*
2845 * Top-level conversion to 4 bpp *
2846 *---------------------------------------------------------------------------*/
2862PIX *
2864{
2865l_int32 d;
2866PIX *pix1, *pix2, *pix3, *pixd;
2867
2868 PROCNAME("pixConvertTo4");
2869
2870 if (!pixs)
2871 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2872 d = pixGetDepth(pixs);
2873 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 24 && d != 32)
2874 return (PIX *)ERROR_PTR("depth not {1,2,4,8,24,32}", procName, NULL);
2875
2876 if (pixGetColormap(pixs) != NULL) {
2878 d = pixGetDepth(pix1);
2879 } else {
2880 pix1 = pixCopy(NULL, pixs);
2881 }
2882 if (d == 24 || d == 32)
2883 pix2 = pixConvertTo8(pix1, FALSE);
2884 else
2885 pix2 = pixClone(pix1);
2886 pixDestroy(&pix1);
2887 if (d == 1) {
2888 pixd = pixConvert1To4(NULL, pix2, 15, 0);
2889 } else if (d == 2) {
2890 pix3 = pixConvert2To8(pix2, 0, 0x55, 0xaa, 0xff, FALSE);
2891 pixd = pixConvert8To4(pix3);
2892 pixDestroy(&pix3);
2893 } else if (d == 4) {
2894 pixd = pixClone(pix2);
2895 } else { /* d == 8 */
2896 pixd = pixConvert8To4(pix2);
2897 }
2898 pixDestroy(&pix2);
2899 return pixd;
2900}
2901
2902
2914PIX *
2916{
2917l_int32 i, j, w, h, wpls, wpld, val;
2918l_uint32 *datas, *lines, *datad, *lined;
2919PIX *pixs, *pixd;
2920
2921 PROCNAME("pixConvert8To4");
2922
2923 if (!pix || pixGetDepth(pix) != 8)
2924 return (PIX *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2925
2926 if (pixGetColormap(pix) != NULL)
2928 else
2929 pixs = pixClone(pix);
2930 pixGetDimensions(pixs, &w, &h, NULL);
2931 datas = pixGetData(pixs);
2932 wpls = pixGetWpl(pixs);
2933 pixd = pixCreate(w, h, 4);
2934 datad = pixGetData(pixd);
2935 wpld = pixGetWpl(pixd);
2936 for (i = 0; i < h; i++) {
2937 lines = datas + i * wpls;
2938 lined = datad + i * wpld;
2939 for (j = 0; j < w; j++) {
2940 val = GET_DATA_BYTE(lines, j);
2941 val = val >> 4; /* take top 4 bits */
2942 SET_DATA_QBIT(lined, j, val);
2943 }
2944 }
2945 pixDestroy(&pixs);
2946 return pixd;
2947}
2948
2949
2950/*---------------------------------------------------------------------------*
2951 * Top-level conversion to 1 bpp *
2952 *---------------------------------------------------------------------------*/
2966PIX *
2968{
2969l_int32 d, color0, color1, rval, gval, bval;
2970PIX *pix1, *pix2, *pixd;
2971PIXCMAP *cmap;
2972
2973 PROCNAME("pixConvertTo1Adaptive");
2974
2975 if (!pixs)
2976 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2977 d = pixGetDepth(pixs);
2978 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
2979 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", procName, NULL);
2980
2981 cmap = pixGetColormap(pixs);
2982 if (d == 1) {
2983 if (!cmap) {
2984 return pixCopy(NULL, pixs);
2985 } else { /* strip the colormap off, and invert if reasonable
2986 for standard binary photometry. */
2987 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
2988 color0 = rval + gval + bval;
2989 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
2990 color1 = rval + gval + bval;
2991 pixd = pixCopy(NULL, pixs);
2992 pixDestroyColormap(pixd);
2993 if (color1 > color0)
2994 pixInvert(pixd, pixd);
2995 return pixd;
2996 }
2997 }
2998
2999 /* For all other depths, use 8 bpp as an intermediary */
3000 pix1 = pixConvertTo8(pixs, FALSE);
3001 pix2 = pixBackgroundNormSimple(pix1, NULL, NULL);
3002 pixd = pixThresholdToBinary(pix2, 180);
3003 pixDestroy(&pix1);
3004 pixDestroy(&pix2);
3005 return pixd;
3006}
3007
3008
3025PIX *
3027 l_int32 threshold)
3028{
3029l_int32 d, color0, color1, rval, gval, bval;
3030PIX *pixg, *pixd;
3031PIXCMAP *cmap;
3032
3033 PROCNAME("pixConvertTo1");
3034
3035 if (!pixs)
3036 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3037 d = pixGetDepth(pixs);
3038 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
3039 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", procName, NULL);
3040
3041 cmap = pixGetColormap(pixs);
3042 if (d == 1) {
3043 if (!cmap) {
3044 return pixCopy(NULL, pixs);
3045 } else { /* strip the colormap off, and invert if reasonable
3046 for standard binary photometry. */
3047 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
3048 color0 = rval + gval + bval;
3049 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
3050 color1 = rval + gval + bval;
3051 pixd = pixCopy(NULL, pixs);
3052 pixDestroyColormap(pixd);
3053 if (color1 > color0)
3054 pixInvert(pixd, pixd);
3055 return pixd;
3056 }
3057 }
3058
3059 /* For all other depths, use 8 bpp as an intermediary */
3060 pixg = pixConvertTo8(pixs, FALSE);
3061 pixd = pixThresholdToBinary(pixg, threshold);
3062 pixDestroy(&pixg);
3063 return pixd;
3064}
3065
3066
3081PIX *
3083 l_int32 factor,
3084 l_int32 threshold)
3085{
3086l_float32 scalefactor;
3087PIX *pixt, *pixd;
3088
3089 PROCNAME("pixConvertTo1BySampling");
3090
3091 if (!pixs)
3092 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3093 if (factor < 1)
3094 return (PIX *)ERROR_PTR("factor must be >= 1", procName, NULL);
3095
3096 scalefactor = 1. / (l_float32)factor;
3097 pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3098 pixd = pixConvertTo1(pixt, threshold);
3099 pixDestroy(&pixt);
3100 return pixd;
3101}
3102
3103
3104/*---------------------------------------------------------------------------*
3105 * Top-level conversion to 8 bpp *
3106 *---------------------------------------------------------------------------*/
3132PIX *
3134 l_int32 cmapflag)
3135{
3136l_int32 d;
3137PIX *pix1, *pixd;
3138PIXCMAP *cmap;
3139
3140 PROCNAME("pixConvertTo8");
3141
3142 if (!pixs)
3143 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3144 d = pixGetDepth(pixs);
3145 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
3146 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", procName, NULL);
3147
3148 if (d == 1) {
3149 if (cmapflag)
3150 return pixConvert1To8Cmap(pixs);
3151 else
3152 return pixConvert1To8(NULL, pixs, 255, 0);
3153 } else if (d == 2) {
3154 return pixConvert2To8(pixs, 0, 85, 170, 255, cmapflag);
3155 } else if (d == 4) {
3156 return pixConvert4To8(pixs, cmapflag);
3157 } else if (d == 8) {
3158 cmap = pixGetColormap(pixs);
3159 if ((cmap && cmapflag) || (!cmap && !cmapflag)) {
3160 return pixCopy(NULL, pixs);
3161 } else if (cmap) { /* !cmapflag */
3163 } else { /* !cmap && cmapflag; add colormap to pixd */
3164 pixd = pixCopy(NULL, pixs);
3165 pixAddGrayColormap8(pixd);
3166 return pixd;
3167 }
3168 } else if (d == 16) {
3169 pixd = pixConvert16To8(pixs, L_MS_BYTE);
3170 if (cmapflag)
3171 pixAddGrayColormap8(pixd);
3172 return pixd;
3173 } else if (d == 24) {
3174 pix1 = pixConvert24To32(pixs);
3175 pixd = pixConvertRGBToLuminance(pix1);
3176 if (cmapflag)
3177 pixAddGrayColormap8(pixd);
3178 pixDestroy(&pix1);
3179 return pixd;
3180 } else { /* d == 32 */
3181 pixd = pixConvertRGBToLuminance(pixs);
3182 if (cmapflag)
3183 pixAddGrayColormap8(pixd);
3184 return pixd;
3185 }
3186}
3187
3188
3203PIX *
3205 l_int32 factor,
3206 l_int32 cmapflag)
3207{
3208l_float32 scalefactor;
3209PIX *pixt, *pixd;
3210
3211 PROCNAME("pixConvertTo8BySampling");
3212
3213 if (!pixs)
3214 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3215 if (factor < 1)
3216 return (PIX *)ERROR_PTR("factor must be >= 1", procName, NULL);
3217
3218 scalefactor = 1. / (l_float32)factor;
3219 pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3220 pixd = pixConvertTo8(pixt, cmapflag);
3221
3222 pixDestroy(&pixt);
3223 return pixd;
3224}
3225
3226
3247PIX *
3249 l_int32 dither)
3250{
3251l_int32 d;
3252
3253 PROCNAME("pixConvertTo8Colormap");
3254
3255 if (!pixs)
3256 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3257 d = pixGetDepth(pixs);
3258 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
3259 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,32}", procName, NULL);
3260
3261 if (d != 32)
3262 return pixConvertTo8(pixs, 1);
3263
3264 return pixConvertRGBToColormap(pixs, dither);
3265}
3266
3267
3268/*---------------------------------------------------------------------------*
3269 * Top-level conversion to 16 bpp *
3270 *---------------------------------------------------------------------------*/
3282PIX *
3284{
3285l_int32 d;
3286
3287 PROCNAME("pixConvertTo16");
3288
3289 if (!pixs)
3290 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3291
3292 d = pixGetDepth(pixs);
3293 if (d == 1)
3294 return pixConvert1To16(NULL, pixs, 0xffff, 0);
3295 else if (d == 8)
3296 return pixConvert8To16(pixs, 8);
3297 else
3298 return (PIX *)ERROR_PTR("src depth not 1 or 8 bpp", procName, NULL);
3299}
3300
3301
3302
3303/*---------------------------------------------------------------------------*
3304 * Top-level conversion to 32 bpp *
3305 *---------------------------------------------------------------------------*/
3331PIX *
3333{
3334l_int32 d;
3335PIX *pix1, *pixd;
3336
3337 PROCNAME("pixConvertTo32");
3338
3339 if (!pixs)
3340 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3341
3342 d = pixGetDepth(pixs);
3343 if (d == 1) {
3344 return pixConvert1To32(NULL, pixs, 0xffffffff, 0);
3345 } else if (d == 2) {
3346 pix1 = pixConvert2To8(pixs, 0, 85, 170, 255, TRUE);
3347 pixd = pixConvert8To32(pix1);
3348 pixDestroy(&pix1);
3349 return pixd;
3350 } else if (d == 4) {
3351 pix1 = pixConvert4To8(pixs, TRUE);
3352 pixd = pixConvert8To32(pix1);
3353 pixDestroy(&pix1);
3354 return pixd;
3355 } else if (d == 8) {
3356 return pixConvert8To32(pixs);
3357 } else if (d == 16) {
3358 pix1 = pixConvert16To8(pixs, L_MS_BYTE);
3359 pixd = pixConvert8To32(pix1);
3360 pixDestroy(&pix1);
3361 return pixd;
3362 } else if (d == 24) {
3363 return pixConvert24To32(pixs);
3364 } else if (d == 32) {
3365 return pixCopy(NULL, pixs);
3366 } else {
3367 return (PIX *)ERROR_PTR("depth not 1, 2, 4, 8, 16, 32 bpp",
3368 procName, NULL);
3369 }
3370}
3371
3372
3386PIX *
3388 l_int32 factor)
3389{
3390l_float32 scalefactor;
3391PIX *pix1, *pixd;
3392
3393 PROCNAME("pixConvertTo32BySampling");
3394
3395 if (!pixs)
3396 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3397 if (factor < 1)
3398 return (PIX *)ERROR_PTR("factor must be >= 1", procName, NULL);
3399
3400 scalefactor = 1. / (l_float32)factor;
3401 pix1 = pixScaleBySampling(pixs, scalefactor, scalefactor);
3402 pixd = pixConvertTo32(pix1);
3403
3404 pixDestroy(&pix1);
3405 return pixd;
3406}
3407
3408
3421PIX *
3423{
3424l_int32 i, j, w, h, wpls, wpld, val;
3425l_uint32 *datas, *datad, *lines, *lined;
3426l_uint32 *tab;
3427PIX *pixd;
3428
3429 PROCNAME("pixConvert8To32");
3430
3431 if (!pixs)
3432 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3433 if (pixGetDepth(pixs) != 8)
3434 return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
3435
3436 if (pixGetColormap(pixs))
3438
3439 pixGetDimensions(pixs, &w, &h, NULL);
3440 datas = pixGetData(pixs);
3441 wpls = pixGetWpl(pixs);
3442 if ((pixd = pixCreate(w, h, 32)) == NULL)
3443 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3444 pixCopyResolution(pixd, pixs);
3445 pixCopyInputFormat(pixd, pixs);
3446 datad = pixGetData(pixd);
3447 wpld = pixGetWpl(pixd);
3448
3449 /* Replication table gray --> rgb */
3450 tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
3451 for (i = 0; i < 256; i++)
3452 tab[i] = ((l_uint32)i << 24) | (i << 16) | (i << 8);
3453
3454 /* Replicate 1 --> 4 bytes (alpha byte not set) */
3455 for (i = 0; i < h; i++) {
3456 lines = datas + i * wpls;
3457 lined = datad + i * wpld;
3458 for (j = 0; j < w; j++) {
3459 val = GET_DATA_BYTE(lines, j);
3460 lined[j] = tab[val];
3461 }
3462 }
3463
3464 LEPT_FREE(tab);
3465 return pixd;
3466}
3467
3468
3469/*---------------------------------------------------------------------------*
3470 * Top-level conversion to 8 or 32 bpp, without colormap *
3471 *---------------------------------------------------------------------------*/
3491PIX *
3493 l_int32 copyflag,
3494 l_int32 warnflag)
3495{
3496l_int32 d;
3497PIX *pixd;
3498
3499 PROCNAME("pixConvertTo8Or32");
3500
3501 if (!pixs)
3502 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3503 if (copyflag != L_CLONE && copyflag != L_COPY)
3504 return (PIX *)ERROR_PTR("invalid copyflag", procName, NULL);
3505
3506 d = pixGetDepth(pixs);
3507 if (pixGetColormap(pixs)) {
3508 if (warnflag) L_WARNING("pix has colormap; removing\n", procName);
3510 } else if (d == 8 || d == 32) {
3511 if (copyflag == L_CLONE)
3512 pixd = pixClone(pixs);
3513 else /* copyflag == L_COPY */
3514 pixd = pixCopy(NULL, pixs);
3515 } else {
3516 pixd = pixConvertTo8(pixs, 0);
3517 }
3518
3519 /* Sanity check on result */
3520 d = pixGetDepth(pixd);
3521 if (d != 8 && d != 32) {
3522 pixDestroy(&pixd);
3523 return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, NULL);
3524 }
3525
3526 return pixd;
3527}
3528
3529
3530/*---------------------------------------------------------------------------*
3531 * Conversion between 24 bpp and 32 bpp rgb *
3532 *---------------------------------------------------------------------------*/
3554PIX *
3556{
3557l_uint8 *lines;
3558l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3559l_uint32 pixel;
3560l_uint32 *datas, *datad, *lined;
3561PIX *pixd;
3562
3563 PROCNAME("pixConvert24to32");
3564
3565 if (!pixs)
3566 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3567 pixGetDimensions(pixs, &w, &h, &d);
3568 if (d != 24)
3569 return (PIX *)ERROR_PTR("pixs not 24 bpp", procName, NULL);
3570
3571 pixd = pixCreate(w, h, 32);
3572 datas = pixGetData(pixs);
3573 datad = pixGetData(pixd);
3574 wpls = pixGetWpl(pixs);
3575 wpld = pixGetWpl(pixd);
3576 for (i = 0; i < h; i++) {
3577 lines = (l_uint8 *)(datas + i * wpls);
3578 lined = datad + i * wpld;
3579 for (j = 0; j < w; j++) {
3580 rval = *lines++;
3581 gval = *lines++;
3582 bval = *lines++;
3583 composeRGBPixel(rval, gval, bval, &pixel);
3584 lined[j] = pixel;
3585 }
3586 }
3587 pixCopyResolution(pixd, pixs);
3588 pixCopyInputFormat(pixd, pixs);
3589 return pixd;
3590}
3591
3592
3604PIX *
3606{
3607l_uint8 *rgbdata8;
3608l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3609l_uint32 *datas, *lines, *rgbdata;
3610PIX *pixd;
3611
3612 PROCNAME("pixConvert32to24");
3613
3614 if (!pixs)
3615 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3616 pixGetDimensions(pixs, &w, &h, &d);
3617 if (d != 32)
3618 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
3619
3620 datas = pixGetData(pixs);
3621 wpls = pixGetWpl(pixs);
3622 pixd = pixCreate(w, h, 24);
3623 rgbdata = pixGetData(pixd);
3624 wpld = pixGetWpl(pixd);
3625 for (i = 0; i < h; i++) {
3626 lines = datas + i * wpls;
3627 rgbdata8 = (l_uint8 *)(rgbdata + i * wpld);
3628 for (j = 0; j < w; j++) {
3629 extractRGBValues(lines[j], &rval, &gval, &bval);
3630 *rgbdata8++ = rval;
3631 *rgbdata8++ = gval;
3632 *rgbdata8++ = bval;
3633 }
3634 }
3635 pixCopyResolution(pixd, pixs);
3636 pixCopyInputFormat(pixd, pixs);
3637 return pixd;
3638}
3639
3640
3641/*---------------------------------------------------------------------------*
3642 * Conversion between 32 bpp (1 spp) and 16 or 8 bpp *
3643 *---------------------------------------------------------------------------*/
3657PIX *
3659 l_int32 type)
3660{
3661l_uint16 dword;
3662l_int32 w, h, i, j, wpls, wpld;
3663l_uint32 sword;
3664l_uint32 *datas, *lines, *datad, *lined;
3665PIX *pixd;
3666
3667 PROCNAME("pixConvert32to16");
3668
3669 if (!pixs || pixGetDepth(pixs) != 32)
3670 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
3671 if (type != L_LS_TWO_BYTES && type != L_MS_TWO_BYTES &&
3672 type != L_CLIP_TO_FFFF)
3673 return (PIX *)ERROR_PTR("invalid type", procName, NULL);
3674
3675 pixGetDimensions(pixs, &w, &h, NULL);
3676 if ((pixd = pixCreate(w, h, 16)) == NULL)
3677 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3678 pixCopyResolution(pixd, pixs);
3679 pixCopyInputFormat(pixd, pixs);
3680 wpls = pixGetWpl(pixs);
3681 datas = pixGetData(pixs);
3682 wpld = pixGetWpl(pixd);
3683 datad = pixGetData(pixd);
3684
3685 for (i = 0; i < h; i++) {
3686 lines = datas + i * wpls;
3687 lined = datad + i * wpld;
3688 if (type == L_LS_TWO_BYTES) {
3689 for (j = 0; j < wpls; j++) {
3690 sword = *(lines + j);
3691 dword = sword & 0xffff;
3692 SET_DATA_TWO_BYTES(lined, j, dword);
3693 }
3694 } else if (type == L_MS_TWO_BYTES) {
3695 for (j = 0; j < wpls; j++) {
3696 sword = *(lines + j);
3697 dword = sword >> 16;
3698 SET_DATA_TWO_BYTES(lined, j, dword);
3699 }
3700 } else { /* type == L_CLIP_TO_FFFF */
3701 for (j = 0; j < wpls; j++) {
3702 sword = *(lines + j);
3703 dword = (sword >> 16) ? 0xffff : (sword & 0xffff);
3704 SET_DATA_TWO_BYTES(lined, j, dword);
3705 }
3706 }
3707 }
3708
3709 return pixd;
3710}
3711
3712
3721PIX *
3723 l_int32 type16,
3724 l_int32 type8)
3725{
3726PIX *pix1, *pixd;
3727
3728 PROCNAME("pixConvert32to8");
3729
3730 if (!pixs || pixGetDepth(pixs) != 32)
3731 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
3732 if (type16 != L_LS_TWO_BYTES && type16 != L_MS_TWO_BYTES &&
3733 type16 != L_CLIP_TO_FFFF)
3734 return (PIX *)ERROR_PTR("invalid type16", procName, NULL);
3735 if (type8 != L_LS_BYTE && type8 != L_MS_BYTE && type8 != L_CLIP_TO_FF)
3736 return (PIX *)ERROR_PTR("invalid type8", procName, NULL);
3737
3738 pix1 = pixConvert32To16(pixs, type16);
3739 pixd = pixConvert16To8(pix1, type8);
3740 pixDestroy(&pix1);
3741 return pixd;
3742}
3743
3744
3745/*---------------------------------------------------------------------------*
3746 * Removal of alpha component by blending with white background *
3747 *---------------------------------------------------------------------------*/
3760PIX *
3762{
3763 PROCNAME("pixRemoveAlpha");
3764
3765 if (!pixs)
3766 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3767
3768 if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4)
3769 return pixAlphaBlendUniform(pixs, 0xffffff00);
3770 else
3771 return pixClone(pixs);
3772}
3773
3774
3775/*---------------------------------------------------------------------------*
3776 * Addition of alpha component to 1 bpp *
3777 *---------------------------------------------------------------------------*/
3797PIX *
3799 PIX *pixs)
3800{
3801PIXCMAP *cmap;
3802
3803 PROCNAME("pixAddAlphaTo1bpp");
3804
3805 if (!pixs || (pixGetDepth(pixs) != 1))
3806 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
3807 if (pixd && (pixd != pixs))
3808 return (PIX *)ERROR_PTR("pixd defined but != pixs", procName, NULL);
3809
3810 pixd = pixCopy(pixd, pixs);
3811 cmap = pixcmapCreate(1);
3812 pixSetColormap(pixd, cmap);
3813 pixcmapAddRGBA(cmap, 255, 255, 255, 0); /* 0 ==> white + transparent */
3814 pixcmapAddRGBA(cmap, 0, 0, 0, 255); /* 1 ==> black + opaque */
3815 return pixd;
3816}
3817
3818
3819/*---------------------------------------------------------------------------*
3820 * Lossless depth conversion (unpacking) *
3821 *---------------------------------------------------------------------------*/
3839PIX *
3841 l_int32 d)
3842{
3843l_int32 w, h, ds, wpls, wpld, i, j, val;
3844l_uint32 *datas, *datad, *lines, *lined;
3845PIX *pixd;
3846
3847 PROCNAME("pixConvertLossless");
3848
3849 if (!pixs)
3850 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3851 if (pixGetColormap(pixs))
3852 return (PIX *)ERROR_PTR("pixs has colormap", procName, NULL);
3853 if (d != 2 && d != 4 && d != 8)
3854 return (PIX *)ERROR_PTR("invalid dest depth", procName, NULL);
3855
3856 pixGetDimensions(pixs, &w, &h, &ds);
3857 if (d < ds)
3858 return (PIX *)ERROR_PTR("depth > d", procName, NULL);
3859 else if (d == ds)
3860 return pixCopy(NULL, pixs);
3861
3862 if ((pixd = pixCreate(w, h, d)) == NULL)
3863 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3864 pixCopyResolution(pixd, pixs);
3865 pixCopyInputFormat(pixd, pixs);
3866
3867 /* Unpack the bits */
3868 datas = pixGetData(pixs);
3869 wpls = pixGetWpl(pixs);
3870 datad = pixGetData(pixd);
3871 wpld = pixGetWpl(pixd);
3872 for (i = 0; i < h; i++) {
3873 lines = datas + i * wpls;
3874 lined = datad + i * wpld;
3875 switch (ds)
3876 {
3877 case 1:
3878 for (j = 0; j < w; j++) {
3879 val = GET_DATA_BIT(lines, j);
3880 if (d == 8)
3881 SET_DATA_BYTE(lined, j, val);
3882 else if (d == 4)
3883 SET_DATA_QBIT(lined, j, val);
3884 else /* d == 2 */
3885 SET_DATA_DIBIT(lined, j, val);
3886 }
3887 break;
3888 case 2:
3889 for (j = 0; j < w; j++) {
3890 val = GET_DATA_DIBIT(lines, j);
3891 if (d == 8)
3892 SET_DATA_BYTE(lined, j, val);
3893 else /* d == 4 */
3894 SET_DATA_QBIT(lined, j, val);
3895 }
3896 break;
3897 case 4:
3898 for (j = 0; j < w; j++) {
3899 val = GET_DATA_DIBIT(lines, j);
3900 SET_DATA_BYTE(lined, j, val);
3901 }
3902 break;
3903 }
3904 }
3905
3906 return pixd;
3907}
3908
3909
3910/*---------------------------------------------------------------------------*
3911 * Conversion for printing in PostScript *
3912 *---------------------------------------------------------------------------*/
3930PIX *
3932{
3933l_int32 d;
3934PIX *pixd;
3935PIXCMAP *cmap;
3936
3937 PROCNAME("pixConvertForPSWrap");
3938
3939 if (!pixs)
3940 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3941
3942 cmap = pixGetColormap(pixs);
3943 d = pixGetDepth(pixs);
3944 switch (d)
3945 {
3946 case 1:
3947 case 32:
3948 pixd = pixClone(pixs);
3949 break;
3950 case 2:
3951 if (cmap)
3953 else
3954 pixd = pixConvert2To8(pixs, 0, 0x55, 0xaa, 0xff, FALSE);
3955 break;
3956 case 4:
3957 if (cmap)
3959 else
3960 pixd = pixConvert4To8(pixs, FALSE);
3961 break;
3962 case 8:
3964 break;
3965 case 16:
3966 pixd = pixConvert16To8(pixs, L_MS_BYTE);
3967 break;
3968 default:
3969 lept_stderr("depth not in {1, 2, 4, 8, 16, 32}");
3970 return NULL;
3971 }
3972
3973 return pixd;
3974}
3975
3976
3977/*---------------------------------------------------------------------------*
3978 * Scaling conversion to subpixel RGB *
3979 *---------------------------------------------------------------------------*/
4009PIX *
4011 l_float32 scalex,
4012 l_float32 scaley,
4013 l_int32 order)
4014{
4015l_int32 d;
4016PIX *pix1, *pixd;
4017PIXCMAP *cmap;
4018
4019 PROCNAME("pixConvertToSubpixelRGB");
4020
4021 if (!pixs)
4022 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
4023 d = pixGetDepth(pixs);
4024 cmap = pixGetColormap(pixs);
4025 if (d != 8 && d != 32 && !cmap)
4026 return (PIX *)ERROR_PTR("pix not 8 or 32 bpp and not cmapped",
4027 procName, NULL);
4028 if (scalex <= 0.0 || scaley <= 0.0)
4029 return (PIX *)ERROR_PTR("scale factors must be > 0", procName, NULL);
4030 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
4031 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
4032 return (PIX *)ERROR_PTR("invalid subpixel order", procName, NULL);
4033 if ((pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC)) == NULL)
4034 return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
4035
4036 d = pixGetDepth(pix1);
4037 pixd = NULL;
4038 if (d == 8)
4039 pixd = pixConvertGrayToSubpixelRGB(pix1, scalex, scaley, order);
4040 else if (d == 32)
4041 pixd = pixConvertColorToSubpixelRGB(pix1, scalex, scaley, order);
4042 else
4043 L_ERROR("invalid depth %d\n", procName, d);
4044
4045 pixDestroy(&pix1);
4046 return pixd;
4047}
4048
4049
4079PIX *
4081 l_float32 scalex,
4082 l_float32 scaley,
4083 l_int32 order)
4084{
4085l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
4086l_uint32 *datat, *datad, *linet, *lined;
4087PIX *pix1, *pix2, *pixd;
4088PIXCMAP *cmap;
4089
4090 PROCNAME("pixConvertGrayToSubpixelRGB");
4091
4092 if (!pixs)
4093 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
4094 d = pixGetDepth(pixs);
4095 cmap = pixGetColormap(pixs);
4096 if (d != 8 && !cmap)
4097 return (PIX *)ERROR_PTR("pix not 8 bpp & not cmapped", procName, NULL);
4098 if (scalex <= 0.0 || scaley <= 0.0)
4099 return (PIX *)ERROR_PTR("scale factors must be > 0", procName, NULL);
4100 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
4101 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
4102 return (PIX *)ERROR_PTR("invalid subpixel order", procName, NULL);
4103
4104 direction =
4105 (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
4106 ? L_HORIZ : L_VERT;
4108 if (direction == L_HORIZ)
4109 pix2 = pixScale(pix1, 3.0 * scalex, scaley);
4110 else /* L_VERT */
4111 pix2 = pixScale(pix1, scalex, 3.0 * scaley);
4112
4113 pixGetDimensions(pix2, &w, &h, NULL);
4114 wd = (direction == L_HORIZ) ? w / 3 : w;
4115 hd = (direction == L_VERT) ? h / 3 : h;
4116 pixd = pixCreate(wd, hd, 32);
4117 datad = pixGetData(pixd);
4118 wpld = pixGetWpl(pixd);
4119 datat = pixGetData(pix2);
4120 wplt = pixGetWpl(pix2);
4121 if (direction == L_HORIZ) {
4122 for (i = 0; i < hd; i++) {
4123 linet = datat + i * wplt;
4124 lined = datad + i * wpld;
4125 for (j = 0; j < wd; j++) {
4126 rval = GET_DATA_BYTE(linet, 3 * j);
4127 gval = GET_DATA_BYTE(linet, 3 * j + 1);
4128 bval = GET_DATA_BYTE(linet, 3 * j + 2);
4129 if (order == L_SUBPIXEL_ORDER_RGB)
4130 composeRGBPixel(rval, gval, bval, &lined[j]);
4131 else /* order BGR */
4132 composeRGBPixel(bval, gval, rval, &lined[j]);
4133 }
4134 }
4135 } else { /* L_VERT */
4136 for (i = 0; i < hd; i++) {
4137 linet = datat + 3 * i * wplt;
4138 lined = datad + i * wpld;
4139 for (j = 0; j < wd; j++) {
4140 rval = GET_DATA_BYTE(linet, j);
4141 gval = GET_DATA_BYTE(linet + wplt, j);
4142 bval = GET_DATA_BYTE(linet + 2 * wplt, j);
4143 if (order == L_SUBPIXEL_ORDER_VRGB)
4144 composeRGBPixel(rval, gval, bval, &lined[j]);
4145 else /* order VBGR */
4146 composeRGBPixel(bval, gval, rval, &lined[j]);
4147 }
4148 }
4149 }
4150
4151 pixDestroy(&pix1);
4152 pixDestroy(&pix2);
4153 return pixd;
4154}
4155
4156
4184PIX *
4186 l_float32 scalex,
4187 l_float32 scaley,
4188 l_int32 order)
4189{
4190l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
4191l_uint32 *datat, *datad, *linet, *lined;
4192PIX *pix1, *pix2, *pixd;
4193PIXCMAP *cmap;
4194
4195 PROCNAME("pixConvertColorToSubpixelRGB");
4196
4197 if (!pixs)
4198 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
4199 d = pixGetDepth(pixs);
4200 cmap = pixGetColormap(pixs);
4201 if (d != 32 && !cmap)
4202 return (PIX *)ERROR_PTR("pix not 32 bpp & not cmapped", procName, NULL);
4203 if (scalex <= 0.0 || scaley <= 0.0)
4204 return (PIX *)ERROR_PTR("scale factors must be > 0", procName, NULL);
4205 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
4206 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
4207 return (PIX *)ERROR_PTR("invalid subpixel order", procName, NULL);
4208
4209 direction =
4210 (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
4211 ? L_HORIZ : L_VERT;
4213 if (direction == L_HORIZ)
4214 pix2 = pixScale(pix1, 3.0 * scalex, scaley);
4215 else /* L_VERT */
4216 pix2 = pixScale(pix1, scalex, 3.0 * scaley);
4217
4218 pixGetDimensions(pix2, &w, &h, NULL);
4219 wd = (direction == L_HORIZ) ? w / 3 : w;
4220 hd = (direction == L_VERT) ? h / 3 : h;
4221 pixd = pixCreate(wd, hd, 32);
4222 pixCopyInputFormat(pixd, pixs);
4223 datad = pixGetData(pixd);
4224 wpld = pixGetWpl(pixd);
4225 datat = pixGetData(pix2);
4226 wplt = pixGetWpl(pix2);
4227 if (direction == L_HORIZ) {
4228 for (i = 0; i < hd; i++) {
4229 linet = datat + i * wplt;
4230 lined = datad + i * wpld;
4231 for (j = 0; j < wd; j++) {
4232 if (order == L_SUBPIXEL_ORDER_RGB) {
4233 extractRGBValues(linet[3 * j], &rval, NULL, NULL);
4234 extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4235 extractRGBValues(linet[3 * j + 2], NULL, NULL, &bval);
4236 } else { /* order BGR */
4237 extractRGBValues(linet[3 * j], NULL, NULL, &bval);
4238 extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4239 extractRGBValues(linet[3 * j + 2], &rval, NULL, NULL);
4240 }
4241 composeRGBPixel(rval, gval, bval, &lined[j]);
4242 }
4243 }
4244 } else { /* L_VERT */
4245 for (i = 0; i < hd; i++) {
4246 linet = datat + 3 * i * wplt;
4247 lined = datad + i * wpld;
4248 for (j = 0; j < wd; j++) {
4249 if (order == L_SUBPIXEL_ORDER_VRGB) {
4250 extractRGBValues(linet[j], &rval, NULL, NULL);
4251 extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4252 extractRGBValues((linet + 2 * wplt)[j], NULL, NULL, &bval);
4253 } else { /* order VBGR */
4254 extractRGBValues(linet[j], NULL, NULL, &bval);
4255 extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4256 extractRGBValues((linet + 2 * wplt)[j], &rval, NULL, NULL);
4257 }
4258 composeRGBPixel(rval, gval, bval, &lined[j]);
4259 }
4260 }
4261 }
4262
4263 if (pixGetSpp(pixs) == 4)
4264 pixScaleAndTransferAlpha(pixd, pixs, scalex, scaley);
4265
4266 pixDestroy(&pix1);
4267 pixDestroy(&pix2);
4268 return pixd;
4269}
4270
4271
4272/*---------------------------------------------------------------------*
4273 * Setting neutral point for min/max boost conversion to gray *
4274 *---------------------------------------------------------------------*/
4287void
4289{
4290 PROCNAME("l_setNeutralBoostVal");
4291
4292 if (val <= 0) {
4293 L_ERROR("invalid reference value for neutral boost\n", procName);
4294 return;
4295 }
4296 var_NEUTRAL_BOOST_VAL = val;
4297}
PIX * pixBackgroundNormSimple(PIX *pixs, PIX *pixim, PIX *pixg)
pixBackgroundNormSimple()
Definition: adaptmap.c:247
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
PIX * pixAlphaBlendUniform(PIX *pixs, l_uint32 color)
pixAlphaBlendUniform()
Definition: blend.c:2024
l_ok pixColorsForQuantization(PIX *pixs, l_int32 thresh, l_int32 *pncolors, l_int32 *piscolor, l_int32 debug)
pixColorsForQuantization()
l_ok pixNumColors(PIX *pixs, l_int32 factor, l_int32 *pncolors)
pixNumColors()
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:279
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1075
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:708
l_ok pixcmapGetDistanceToColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pdist)
pixcmapGetDistanceToColor()
Definition: colormap.c:1464
PIXCMAP * pixcmapGrayToColor(l_uint32 color)
pixcmapGrayToColor()
Definition: colormap.c:1678
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
l_ok pixcmapAddRGBA(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval)
pixcmapAddRGBA()
Definition: colormap.c:452
PIXCMAP * pixcmapCreateLinear(l_int32 d, l_int32 nlevels)
pixcmapCreateLinear()
Definition: colormap.c:218
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
Definition: colormap.c:1114
PIXCMAP * pixcmapGrayToFalseColor(l_float32 gamma)
pixcmapGrayToFalseColor()
Definition: colormap.c:1614
l_ok pixcmapGetRangeValues(PIXCMAP *cmap, l_int32 select, l_int32 *pminval, l_int32 *pmaxval, l_int32 *pminindex, l_int32 *pmaxindex)
pixcmapGetRangeValues()
Definition: colormap.c:1520
PIXCMAP * pixcmapConvertTo8(PIXCMAP *cmaps)
pixcmapConvertTo8()
Definition: colormap.c:1802
l_ok pixcmapToArrays(const PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
Definition: colormap.c:2068
l_ok pixcmapIsBlackAndWhite(PIXCMAP *cmap, l_int32 *pblackwhite)
pixcmapIsBlackAndWhite()
Definition: colormap.c:1220
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:414
l_ok pixcmapToRGBTable(PIXCMAP *cmap, l_uint32 **ptab, l_int32 *pncolors)
pixcmapToRGBTable()
Definition: colormap.c:2121
NUMA * pixOctcubeHistogram(PIX *pixs, l_int32 level, l_int32 *pncolors)
pixOctcubeHistogram()
Definition: colorquant1.c:3727
PIX * pixFewColorsOctcubeQuant2(PIX *pixs, l_int32 level, NUMA *na, l_int32 ncolors, l_int32 *pnerrors)
pixFewColorsOctcubeQuant2()
Definition: colorquant1.c:3106
PIX * pixFewColorsOctcubeQuant1(PIX *pixs, l_int32 level)
pixFewColorsOctcubeQuant1()
Definition: colorquant1.c:2936
PIX * pixOctreeColorQuant(PIX *pixs, l_int32 colors, l_int32 ditherflag)
pixOctreeColorQuant()
Definition: colorquant1.c:535
PIX * pixConvertRGBToSaturation(PIX *pixs)
pixConvertRGBToSaturation()
Definition: colorspace.c:576
PIX * pixConvertRGBToHue(PIX *pixs)
pixConvertRGBToHue()
Definition: colorspace.c:500
PIX * pixThresholdTo4bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo4bpp()
Definition: grayquant.c:1520
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:447
PIX * pixThresholdOn8bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdOn8bpp()
Definition: grayquant.c:1637
PIX * pixThresholdTo2bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo2bpp()
Definition: grayquant.c:1378
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
l_ok numaGetCountRelativeToZero(NUMA *na, l_int32 type, l_int32 *pcount)
numaGetCountRelativeToZero()
Definition: numafunc1.c:1131
NUMA * numaNormalizeHistogram(NUMA *nas, l_float32 tsum)
numaNormalizeHistogram()
Definition: numafunc2.c:1179
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
l_ok pixDestroyColormap(PIX *pix)
pixDestroyColormap()
Definition: pix1.c:1728
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1382
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2783
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
NUMA * pixGetGrayHistogram(PIX *pixs, l_int32 factor)
pixGetGrayHistogram()
Definition: pix4.c:115
NUMA * pixGetCmapHistogram(PIX *pixs, l_int32 factor)
pixGetCmapHistogram()
Definition: pix4.c:633
static const l_float32 L_BLUE_WEIGHT
Definition: pix.h:248
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ COLOR_GREEN
Definition: pix.h:205
@ L_SELECT_MAX
Definition: pix.h:826
@ L_SELECT_GREEN
Definition: pix.h:823
@ L_SELECT_SATURATION
Definition: pix.h:829
@ L_SELECT_BLUE
Definition: pix.h:824
@ L_SELECT_AVERAGE
Definition: pix.h:827
@ L_SELECT_MIN
Definition: pix.h:825
@ L_SELECT_HUE
Definition: pix.h:828
@ L_SELECT_WEIGHTED
Definition: pix.h:830
@ L_SELECT_RED
Definition: pix.h:822
@ L_SELECT_IF_LTE
Definition: pix.h:784
@ L_SELECT_IF_LT
Definition: pix.h:782
@ L_SELECT_IF_GT
Definition: pix.h:783
@ L_SELECT_IF_GTE
Definition: pix.h:785
static const l_float32 L_RED_WEIGHT
Definition: pix.h:246
@ REMOVE_CMAP_TO_FULL_COLOR
Definition: pix.h:258
@ REMOVE_CMAP_TO_GRAYSCALE
Definition: pix.h:257
@ REMOVE_CMAP_WITH_ALPHA
Definition: pix.h:259
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:260
@ REMOVE_CMAP_TO_BINARY
Definition: pix.h:256
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_CLIP_TO_FFFF
Definition: pix.h:854
@ L_MS_TWO_BYTES
Definition: pix.h:853
@ L_CLIP_TO_FF
Definition: pix.h:851
@ L_LS_TWO_BYTES
Definition: pix.h:852
@ L_MS_BYTE
Definition: pix.h:849
@ L_AUTO_BYTE
Definition: pix.h:850
@ L_LS_BYTE
Definition: pix.h:848
@ L_SUBPIXEL_ORDER_VRGB
Definition: pix.h:1181
@ L_SUBPIXEL_ORDER_BGR
Definition: pix.h:1180
@ L_SUBPIXEL_ORDER_RGB
Definition: pix.h:1179
@ L_SUBPIXEL_ORDER_VBGR
Definition: pix.h:1182
@ L_GREATER_THAN_ZERO
Definition: pix.h:1280
static const l_float32 L_GREEN_WEIGHT
Definition: pix.h:247
PIX * pixConvertGrayToColormap8(PIX *pixs, l_int32 mindepth)
pixConvertGrayToColormap8()
Definition: pixconv.c:1302
PIX * pixConvert1To16(PIX *pixd, PIX *pixs, l_uint16 val0, l_uint16 val1)
pixConvert1To16()
Definition: pixconv.c:1978
PIX * pixConvert32To16(PIX *pixs, l_int32 type)
pixConvert32To16()
Definition: pixconv.c:3658
l_ok pixQuantizeIfFewColors(PIX *pixs, l_int32 maxcolors, l_int32 mingraycolors, l_int32 octlevel, PIX **ppixd)
pixQuantizeIfFewColors()
Definition: pixconv.c:1661
PIX * pixConvertRGBToBinaryArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc, l_int32 thresh, l_int32 relation)
pixConvertRGBToBinaryArb()
Definition: pixconv.c:1190
PIX * pixConvert8To4(PIX *pix)
pixConvert8To4()
Definition: pixconv.c:2915
PIX * pixConvert8To16(PIX *pixs, l_int32 leftshift)
pixConvert8To16()
Definition: pixconv.c:2689
PIX * pixThreshold8(PIX *pixs, l_int32 d, l_int32 nlevels, l_int32 cmapflag)
pixThreshold8()
Definition: pixconv.c:210
PIX * pixConvert32To24(PIX *pixs)
pixConvert32To24()
Definition: pixconv.c:3605
PIX * pixConvertTo4(PIX *pixs)
pixConvertTo4()
Definition: pixconv.c:2863
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition: pixconv.c:742
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
PIX * pixConvertRGBToGrayMinMax(PIX *pixs, l_int32 type)
pixConvertRGBToGrayMinMax()
Definition: pixconv.c:963
PIX * pixConvert8To32(PIX *pixs)
pixConvert8To32()
Definition: pixconv.c:3422
PIX * pixConvertTo2(PIX *pixs)
pixConvertTo2()
Definition: pixconv.c:2755
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition: pixconv.c:3492
PIX * pixConvertGrayToFalseColor(PIX *pixs, l_float32 gamma)
pixConvertGrayToFalseColor()
Definition: pixconv.c:1858
PIX * pixConvertTo8BySampling(PIX *pixs, l_int32 factor, l_int32 cmapflag)
pixConvertTo8BySampling()
Definition: pixconv.c:3204
l_ok pixAddGrayColormap8(PIX *pixs)
pixAddGrayColormap8()
Definition: pixconv.c:622
PIX * pixConvertRGBToGrayFast(PIX *pixs)
pixConvertRGBToGrayFast()
Definition: pixconv.c:905
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixConvert2To8(PIX *pixs, l_uint8 val0, l_uint8 val1, l_uint8 val2, l_uint8 val3, l_int32 cmapflag)
pixConvert2To8()
Definition: pixconv.c:2492
PIX * pixConvertTo1Adaptive(PIX *pixs)
pixConvertTo1Adaptive()
Definition: pixconv.c:2967
PIX * pixConvertLossless(PIX *pixs, l_int32 d)
pixConvertLossless()
Definition: pixconv.c:3840
PIX * pixAddMinimalGrayColormap8(PIX *pixs)
pixAddMinimalGrayColormap8()
Definition: pixconv.c:653
PIX * pixConvert1To8Cmap(PIX *pixs)
pixConvert1To8Cmap()
Definition: pixconv.c:2358
PIX * pixConvert1To32(PIX *pixd, PIX *pixs, l_uint32 val0, l_uint32 val1)
pixConvert1To32()
Definition: pixconv.c:2052
PIX * pixConvertGrayToColormap(PIX *pixs)
pixConvertGrayToColormap()
Definition: pixconv.c:1247
PIX * pixConvert1To2Cmap(PIX *pixs)
pixConvert1To2Cmap()
Definition: pixconv.c:2115
PIX * pixConvert16To8(PIX *pixs, l_int32 type)
pixConvert16To8()
Definition: pixconv.c:1762
PIX * pixConvertRGBToColormap(PIX *pixs, l_int32 ditherflag)
pixConvertRGBToColormap()
Definition: pixconv.c:1486
PIX * pixConvertToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertToSubpixelRGB()
Definition: pixconv.c:4010
PIX * pixConvertTo8Colormap(PIX *pixs, l_int32 dither)
pixConvertTo8Colormap()
Definition: pixconv.c:3248
PIX * pixConvert1To4Cmap(PIX *pixs)
pixConvert1To4Cmap()
Definition: pixconv.c:2237
PIX * pixConvertRGBToGrayGeneral(PIX *pixs, l_int32 type, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGrayGeneral()
Definition: pixconv.c:766
PIX * pixConvertTo32BySampling(PIX *pixs, l_int32 factor)
pixConvertTo32BySampling()
Definition: pixconv.c:3387
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
Definition: pixconv.c:3555
PIX * pixConvert1To4(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To4()
Definition: pixconv.c:2280
PIX * pixConvertTo16(PIX *pixs)
pixConvertTo16()
Definition: pixconv.c:3283
PIX * pixConvertRGBToGrayArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc)
pixConvertRGBToGrayArb()
Definition: pixconv.c:1128
PIX * pixConvertGrayToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertGrayToSubpixelRGB()
Definition: pixconv.c:4080
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition: pixconv.c:3931
PIX * pixConvert1To2(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To2()
Definition: pixconv.c:2158
PIX * pixConvertRGBToGraySatBoost(PIX *pixs, l_int32 refval)
pixConvertRGBToGraySatBoost()
Definition: pixconv.c:1050
PIX * pixConvertRGBToGray(PIX *pixs, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGray()
Definition: pixconv.c:827
PIX * pixConvert4To8(PIX *pixs, l_int32 cmapflag)
pixConvert4To8()
Definition: pixconv.c:2604
PIX * pixConvertCmapTo1(PIX *pixs)
pixConvertCmapTo1()
Definition: pixconv.c:1550
PIX * pixAddAlphaTo1bpp(PIX *pixd, PIX *pixs)
pixAddAlphaTo1bpp()
Definition: pixconv.c:3798
PIX * pixConvert8To2(PIX *pix)
pixConvert8To2()
Definition: pixconv.c:2807
PIX * pixRemoveAlpha(PIX *pixs)
pixRemoveAlpha()
Definition: pixconv.c:3761
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition: pixconv.c:1399
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition: pixconv.c:3026
PIX * pixConvertTo1BySampling(PIX *pixs, l_int32 factor, l_int32 threshold)
pixConvertTo1BySampling()
Definition: pixconv.c:3082
PIX * pixConvertColorToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertColorToSubpixelRGB()
Definition: pixconv.c:4185
PIX * pixRemoveColormapGeneral(PIX *pixs, l_int32 type, l_int32 ifnocmap)
pixRemoveColormapGeneral()
Definition: pixconv.c:278
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2401
void l_setNeutralBoostVal(l_int32 val)
l_setNeutralBoostVal()
Definition: pixconv.c:4288
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
pixUnpackBinary()
Definition: pixconv.c:1913
PIX * pixConvert32To8(PIX *pixs, l_int32 type16, l_int32 type8)
pixConvert32To8()
Definition: pixconv.c:3722
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
l_ok pixScaleAndTransferAlpha(PIX *pixd, PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleAndTransferAlpha()
Definition: scale2.c:1364
Definition: array.h:71
Definition: pix.h:139
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306