Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
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 if (!pixs)
219 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
220 if (pixGetDepth(pixs) != 8)
221 return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
222 if (cmapflag && nlevels < 2)
223 return (PIX *)ERROR_PTR("nlevels must be at least 2", __func__, NULL);
224
225 switch (d) {
226 case 1:
227 pixd = pixThresholdToBinary(pixs, 128);
228 if (cmapflag) {
229 cmap = pixcmapCreateLinear(1, 2);
230 pixSetColormap(pixd, cmap);
231 }
232 break;
233 case 2:
234 pixd = pixThresholdTo2bpp(pixs, nlevels, cmapflag);
235 break;
236 case 4:
237 pixd = pixThresholdTo4bpp(pixs, nlevels, cmapflag);
238 break;
239 case 8:
240 pixd = pixThresholdOn8bpp(pixs, nlevels, cmapflag);
241 break;
242 default:
243 return (PIX *)ERROR_PTR("d must be in {1,2,4,8}", __func__, NULL);
244 }
245
246 if (!pixd)
247 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
248 pixCopyInputFormat(pixd, pixs);
249 return pixd;
250}
251
252
253/*-------------------------------------------------------------*
254 * Conversion from colormapped pix *
255 *-------------------------------------------------------------*/
275PIX *
277 l_int32 type,
278 l_int32 ifnocmap)
279{
280 if (!pixs)
281 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
282 if (ifnocmap != L_CLONE && ifnocmap != L_COPY)
283 return (PIX *)ERROR_PTR("invalid value for ifnocmap", __func__, NULL);
284
285 if (pixGetColormap(pixs))
286 return pixRemoveColormap(pixs, type);
287
288 if (ifnocmap == L_CLONE)
289 return pixClone(pixs);
290 else
291 return pixCopy(NULL, pixs);
292}
293
294
323PIX *
325 l_int32 type)
326{
327l_int32 sval, rval, gval, bval, val0, val1;
328l_int32 i, j, k, w, h, d, wpls, wpld, ncolors, nalloc, count;
329l_int32 opaque, colorfound, blackwhite;
330l_int32 *rmap, *gmap, *bmap, *amap;
331l_uint32 *datas, *lines, *datad, *lined, *lut, *graymap;
332l_uint32 sword, dword;
333PIXCMAP *cmap;
334PIX *pixd;
335
336 if (!pixs)
337 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
338 if ((cmap = pixGetColormap(pixs)) == NULL)
339 return pixClone(pixs);
340 if (type != REMOVE_CMAP_TO_BINARY &&
341 type != REMOVE_CMAP_TO_GRAYSCALE &&
343 type != REMOVE_CMAP_WITH_ALPHA &&
344 type != REMOVE_CMAP_BASED_ON_SRC) {
345 L_WARNING("Invalid type; converting based on src\n", __func__);
347 }
348 pixGetDimensions(pixs, &w, &h, &d);
349 if (d != 1 && d != 2 && d != 4 && d != 8)
350 return (PIX *)ERROR_PTR("pixs must be {1,2,4,8} bpp", __func__, NULL);
351
352 ncolors = pixcmapGetCount(cmap);
353 nalloc = 1 << d; /* allocate for max size in case of pixel corruption */
354 if (ncolors > nalloc)
355 return (PIX *)ERROR_PTR("too many colors for pixel depth",
356 __func__, NULL);
357
358 if (pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap))
359 return (PIX *)ERROR_PTR("colormap arrays not made", __func__, NULL);
360
361 if (d != 1 && type == REMOVE_CMAP_TO_BINARY) {
362 L_WARNING("not 1 bpp; can't remove cmap to binary\n", __func__);
364 }
365
366 /* Select output type depending on colormap content */
367 if (type == REMOVE_CMAP_BASED_ON_SRC) {
368 pixcmapIsOpaque(cmap, &opaque);
369 pixcmapHasColor(cmap, &colorfound);
370 pixcmapIsBlackAndWhite(cmap, &blackwhite);
371 if (!opaque) { /* save the alpha */
373 } else if (colorfound) {
375 } else { /* opaque and no color */
376 if (d == 1 && blackwhite) /* can binarize without loss */
378 else
380 }
381 }
382
383 datas = pixGetData(pixs);
384 wpls = pixGetWpl(pixs);
385 if (type == REMOVE_CMAP_TO_BINARY) {
386 if ((pixd = pixCopy(NULL, pixs)) == NULL) {
387 L_ERROR("pixd not made\n", __func__);
388 goto cleanup_arrays;
389 }
390 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
391 val0 = rval + gval + bval;
392 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
393 val1 = rval + gval + bval;
394 if (val0 < val1) /* photometrically inverted from standard */
395 pixInvert(pixd, pixd);
396 pixDestroyColormap(pixd);
397 } else if (type == REMOVE_CMAP_TO_GRAYSCALE) {
398 if ((pixd = pixCreate(w, h, 8)) == NULL) {
399 L_ERROR("pixd not made\n", __func__);
400 goto cleanup_arrays;
401 }
402 pixCopyResolution(pixd, pixs);
403 pixCopyInputFormat(pixd, pixs);
404 datad = pixGetData(pixd);
405 wpld = pixGetWpl(pixd);
406 graymap = (l_uint32 *)LEPT_CALLOC(nalloc, sizeof(l_uint32));
407 for (i = 0; i < ncolors; i++) {
408 graymap[i] = (l_uint32)(L_RED_WEIGHT * rmap[i] +
409 L_GREEN_WEIGHT * gmap[i] +
410 L_BLUE_WEIGHT * bmap[i] + 0.5);
411 }
412 for (i = 0; i < h; i++) {
413 lines = datas + i * wpls;
414 lined = datad + i * wpld;
415 switch (d) /* depth test above; no default permitted */
416 {
417 case 8:
418 /* Unrolled 4x */
419 for (j = 0, count = 0; j + 3 < w; j += 4, count++) {
420 sword = lines[count];
421 dword = (graymap[(sword >> 24) & 0xff] << 24) |
422 (graymap[(sword >> 16) & 0xff] << 16) |
423 (graymap[(sword >> 8) & 0xff] << 8) |
424 graymap[sword & 0xff];
425 lined[count] = dword;
426 }
427 /* Cleanup partial word */
428 for (; j < w; j++) {
429 sval = GET_DATA_BYTE(lines, j);
430 gval = graymap[sval];
431 SET_DATA_BYTE(lined, j, gval);
432 }
433#if DEBUG_UNROLLING
434#define CHECK_VALUE(a, b, c) if (GET_DATA_BYTE(a, b) != c) { \
435 lept_stderr("Error: mismatch at %d, %d vs %d\n", \
436 j, GET_DATA_BYTE(a, b), c); }
437 for (j = 0; j < w; j++) {
438 sval = GET_DATA_BYTE(lines, j);
439 gval = graymap[sval];
440 CHECK_VALUE(lined, j, gval);
441 }
442#endif
443 break;
444 case 4:
445 /* Unrolled 8x */
446 for (j = 0, count = 0; j + 7 < w; j += 8, count++) {
447 sword = lines[count];
448 dword = (graymap[(sword >> 28) & 0xf] << 24) |
449 (graymap[(sword >> 24) & 0xf] << 16) |
450 (graymap[(sword >> 20) & 0xf] << 8) |
451 graymap[(sword >> 16) & 0xf];
452 lined[2 * count] = dword;
453 dword = (graymap[(sword >> 12) & 0xf] << 24) |
454 (graymap[(sword >> 8) & 0xf] << 16) |
455 (graymap[(sword >> 4) & 0xf] << 8) |
456 graymap[sword & 0xf];
457 lined[2 * count + 1] = dword;
458 }
459 /* Cleanup partial word */
460 for (; j < w; j++) {
461 sval = GET_DATA_QBIT(lines, j);
462 gval = graymap[sval];
463 SET_DATA_BYTE(lined, j, gval);
464 }
465#if DEBUG_UNROLLING
466 for (j = 0; j < w; j++) {
467 sval = GET_DATA_QBIT(lines, j);
468 gval = graymap[sval];
469 CHECK_VALUE(lined, j, gval);
470 }
471#endif
472 break;
473 case 2:
474 /* Unrolled 16x */
475 for (j = 0, count = 0; j + 15 < w; j += 16, count++) {
476 sword = lines[count];
477 dword = (graymap[(sword >> 30) & 0x3] << 24) |
478 (graymap[(sword >> 28) & 0x3] << 16) |
479 (graymap[(sword >> 26) & 0x3] << 8) |
480 graymap[(sword >> 24) & 0x3];
481 lined[4 * count] = dword;
482 dword = (graymap[(sword >> 22) & 0x3] << 24) |
483 (graymap[(sword >> 20) & 0x3] << 16) |
484 (graymap[(sword >> 18) & 0x3] << 8) |
485 graymap[(sword >> 16) & 0x3];
486 lined[4 * count + 1] = dword;
487 dword = (graymap[(sword >> 14) & 0x3] << 24) |
488 (graymap[(sword >> 12) & 0x3] << 16) |
489 (graymap[(sword >> 10) & 0x3] << 8) |
490 graymap[(sword >> 8) & 0x3];
491 lined[4 * count + 2] = dword;
492 dword = (graymap[(sword >> 6) & 0x3] << 24) |
493 (graymap[(sword >> 4) & 0x3] << 16) |
494 (graymap[(sword >> 2) & 0x3] << 8) |
495 graymap[sword & 0x3];
496 lined[4 * count + 3] = dword;
497 }
498 /* Cleanup partial word */
499 for (; j < w; j++) {
500 sval = GET_DATA_DIBIT(lines, j);
501 gval = graymap[sval];
502 SET_DATA_BYTE(lined, j, gval);
503 }
504#if DEBUG_UNROLLING
505 for (j = 0; j < w; j++) {
506 sval = GET_DATA_DIBIT(lines, j);
507 gval = graymap[sval];
508 CHECK_VALUE(lined, j, gval);
509 }
510#endif
511 break;
512 case 1:
513 /* Unrolled 8x */
514 for (j = 0, count = 0; j + 31 < w; j += 32, count++) {
515 sword = lines[count];
516 for (k = 0; k < 4; k++) {
517 /* The top byte is always the relevant one */
518 dword = (graymap[(sword >> 31) & 0x1] << 24) |
519 (graymap[(sword >> 30) & 0x1] << 16) |
520 (graymap[(sword >> 29) & 0x1] << 8) |
521 graymap[(sword >> 28) & 0x1];
522 lined[8 * count + 2 * k] = dword;
523 dword = (graymap[(sword >> 27) & 0x1] << 24) |
524 (graymap[(sword >> 26) & 0x1] << 16) |
525 (graymap[(sword >> 25) & 0x1] << 8) |
526 graymap[(sword >> 24) & 0x1];
527 lined[8 * count + 2 * k + 1] = dword;
528 sword <<= 8; /* Move up the next byte */
529 }
530 }
531 /* Cleanup partial word */
532 for (; j < w; j++) {
533 sval = GET_DATA_BIT(lines, j);
534 gval = graymap[sval];
535 SET_DATA_BYTE(lined, j, gval);
536 }
537#if DEBUG_UNROLLING
538 for (j = 0; j < w; j++) {
539 sval = GET_DATA_BIT(lines, j);
540 gval = graymap[sval];
541 CHECK_VALUE(lined, j, gval);
542 }
543#undef CHECK_VALUE
544#endif
545 break;
546 default:
547 return NULL;
548 }
549 }
550 if (graymap)
551 LEPT_FREE(graymap);
552 } else { /* type == REMOVE_CMAP_TO_FULL_COLOR or REMOVE_CMAP_WITH_ALPHA */
553 if ((pixd = pixCreate(w, h, 32)) == NULL) {
554 L_ERROR("pixd not made\n", __func__);
555 goto cleanup_arrays;
556 }
557 pixCopyInputFormat(pixd, pixs);
558 pixCopyResolution(pixd, pixs);
559 if (type == REMOVE_CMAP_WITH_ALPHA)
560 pixSetSpp(pixd, 4);
561 datad = pixGetData(pixd);
562 wpld = pixGetWpl(pixd);
563 lut = (l_uint32 *)LEPT_CALLOC(nalloc, sizeof(l_uint32));
564 for (i = 0; i < ncolors; i++) {
565 if (type == REMOVE_CMAP_TO_FULL_COLOR)
566 composeRGBPixel(rmap[i], gmap[i], bmap[i], lut + i);
567 else /* full color plus alpha */
568 composeRGBAPixel(rmap[i], gmap[i], bmap[i], amap[i], lut + i);
569 }
570
571 for (i = 0; i < h; i++) {
572 lines = datas + i * wpls;
573 lined = datad + i * wpld;
574 for (j = 0; j < w; j++) {
575 if (d == 8)
576 sval = GET_DATA_BYTE(lines, j);
577 else if (d == 4)
578 sval = GET_DATA_QBIT(lines, j);
579 else if (d == 2)
580 sval = GET_DATA_DIBIT(lines, j);
581 else /* (d == 1) */
582 sval = GET_DATA_BIT(lines, j);
583 if (sval >= ncolors)
584 L_WARNING("pixel value out of bounds\n", __func__);
585 else
586 lined[j] = lut[sval];
587 }
588 }
589 LEPT_FREE(lut);
590 }
591
592cleanup_arrays:
593 LEPT_FREE(rmap);
594 LEPT_FREE(gmap);
595 LEPT_FREE(bmap);
596 LEPT_FREE(amap);
597 return pixd;
598}
599
600
601/*-------------------------------------------------------------*
602 * Add colormap losslessly (8 to 8) *
603 *-------------------------------------------------------------*/
615l_ok
617{
618PIXCMAP *cmap;
619
620 if (!pixs || pixGetDepth(pixs) != 8)
621 return ERROR_INT("pixs not defined or not 8 bpp", __func__, 1);
622 if (pixGetColormap(pixs))
623 return 0;
624
625 cmap = pixcmapCreateLinear(8, 256);
626 pixSetColormap(pixs, cmap);
627 return 0;
628}
629
630
644PIX *
646{
647l_int32 ncolors, w, h, i, j, wpl1, wpld, index, val;
648l_int32 *inta, *revmap;
649l_uint32 *data1, *datad, *line1, *lined;
650PIX *pix1, *pixd;
651PIXCMAP *cmap;
652
653 if (!pixs || pixGetDepth(pixs) != 8)
654 return (PIX *)ERROR_PTR("pixs undefined or not 8 bpp", __func__, NULL);
655
656 /* Eliminate the easy cases */
657 pixNumColors(pixs, 1, &ncolors);
658 cmap = pixGetColormap(pixs);
659 if (cmap) {
660 if (pixcmapGetCount(cmap) == ncolors) /* irreducible */
661 return pixCopy(NULL, pixs);
662 else
664 } else {
665 if (ncolors == 256) {
666 pix1 = pixCopy(NULL, pixs);
668 return pix1;
669 }
670 pix1 = pixClone(pixs);
671 }
672
673 /* Find the gray levels and make a reverse map */
674 pixGetDimensions(pix1, &w, &h, NULL);
675 data1 = pixGetData(pix1);
676 wpl1 = pixGetWpl(pix1);
677 inta = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
678 for (i = 0; i < h; i++) {
679 line1 = data1 + i * wpl1;
680 for (j = 0; j < w; j++) {
681 val = GET_DATA_BYTE(line1, j);
682 inta[val] = 1;
683 }
684 }
685 cmap = pixcmapCreate(8);
686 revmap = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
687 for (i = 0, index = 0; i < 256; i++) {
688 if (inta[i]) {
689 pixcmapAddColor(cmap, i, i, i);
690 revmap[i] = index++;
691 }
692 }
693
694 /* Set all pixels in pixd to the colormap index */
695 pixd = pixCreateTemplate(pix1);
696 pixSetColormap(pixd, cmap);
697 pixCopyInputFormat(pixd, pixs);
698 pixCopyResolution(pixd, pixs);
699 datad = pixGetData(pixd);
700 wpld = pixGetWpl(pixd);
701 for (i = 0; i < h; i++) {
702 line1 = data1 + i * wpl1;
703 lined = datad + i * wpld;
704 for (j = 0; j < w; j++) {
705 val = GET_DATA_BYTE(line1, j);
706 SET_DATA_BYTE(lined, j, revmap[val]);
707 }
708 }
709
710 pixDestroy(&pix1);
711 LEPT_FREE(inta);
712 LEPT_FREE(revmap);
713 return pixd;
714}
715
716
717/*-------------------------------------------------------------*
718 * Conversion from RGB color to grayscale *
719 *-------------------------------------------------------------*/
731PIX *
733{
734 return pixConvertRGBToGray(pixs, 0.0, 0.0, 0.0);
735}
736
737
755PIX *
757 l_int32 type,
758 l_float32 rwt,
759 l_float32 gwt,
760 l_float32 bwt)
761{
762PIX *pix1;
763
764 if (!pixs || pixGetDepth(pixs) != 32)
765 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
766 if (type != L_SELECT_RED && type != L_SELECT_GREEN &&
767 type != L_SELECT_BLUE && type != L_SELECT_MIN &&
768 type != L_SELECT_MAX && type != L_SELECT_AVERAGE &&
769 type != L_SELECT_HUE && type != L_SELECT_SATURATION &&
770 type != L_SELECT_WEIGHTED)
771 return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
772
773 if (type == L_SELECT_RED) {
774 pix1 = pixGetRGBComponent(pixs, COLOR_RED);
775 } else if (type == L_SELECT_GREEN) {
776 pix1 = pixGetRGBComponent(pixs, COLOR_GREEN);
777 } else if (type == L_SELECT_BLUE) {
778 pix1 = pixGetRGBComponent(pixs, COLOR_BLUE);
779 } else if (type == L_SELECT_MIN) {
780 pix1 = pixConvertRGBToGrayMinMax(pixs, L_CHOOSE_MIN);
781 } else if (type == L_SELECT_MAX) {
782 pix1 = pixConvertRGBToGrayMinMax(pixs, L_CHOOSE_MAX);
783 } else if (type == L_SELECT_AVERAGE) {
784 pix1 = pixConvertRGBToGray(pixs, 0.34f, 0.33f, 0.33f);
785 } else if (type == L_SELECT_HUE) {
786 pix1 = pixConvertRGBToHue(pixs);
787 } else if (type == L_SELECT_SATURATION) {
788 pix1 = pixConvertRGBToSaturation(pixs);
789 } else { /* L_SELECT_WEIGHTED */
790 if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0)
791 return (PIX *)ERROR_PTR("weights not all >= 0.0", __func__, NULL);
792 if (rwt + gwt + bwt != 1.0)
793 return (PIX *)ERROR_PTR("weights don't sum to 1.0", __func__, NULL);
794 pix1 = pixConvertRGBToGray(pixs, rwt, gwt, bwt);
795 }
796
797 return pix1;
798}
799
800
814PIX *
816 l_float32 rwt,
817 l_float32 gwt,
818 l_float32 bwt)
819{
820l_int32 i, j, w, h, wpls, wpld, val;
821l_uint32 word;
822l_uint32 *datas, *lines, *datad, *lined;
823l_float32 sum;
824PIX *pixd;
825
826 if (!pixs)
827 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
828 if (pixGetDepth(pixs) != 32)
829 return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
830 if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0)
831 return (PIX *)ERROR_PTR("weights not all >= 0.0", __func__, NULL);
832
833 /* Make sure the sum of weights is 1.0; otherwise, you can get
834 * overflow in the gray value. */
835 if (rwt == 0.0 && gwt == 0.0 && bwt == 0.0) {
836 rwt = L_RED_WEIGHT;
837 gwt = L_GREEN_WEIGHT;
838 bwt = L_BLUE_WEIGHT;
839 }
840 sum = rwt + gwt + bwt;
841 if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
842 L_WARNING("weights don't sum to 1; maintaining ratios\n", __func__);
843 rwt = rwt / sum;
844 gwt = gwt / sum;
845 bwt = bwt / sum;
846 }
847
848 pixGetDimensions(pixs, &w, &h, NULL);
849 datas = pixGetData(pixs);
850 wpls = pixGetWpl(pixs);
851 if ((pixd = pixCreate(w, h, 8)) == NULL)
852 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
853 pixCopyResolution(pixd, pixs);
854 pixCopyInputFormat(pixd, pixs);
855 datad = pixGetData(pixd);
856 wpld = pixGetWpl(pixd);
857
858 for (i = 0; i < h; i++) {
859 lines = datas + i * wpls;
860 lined = datad + i * wpld;
861 for (j = 0; j < w; j++) {
862 word = *(lines + j);
863 val = (l_int32)(rwt * ((word >> L_RED_SHIFT) & 0xff) +
864 gwt * ((word >> L_GREEN_SHIFT) & 0xff) +
865 bwt * ((word >> L_BLUE_SHIFT) & 0xff) + 0.5);
866 SET_DATA_BYTE(lined, j, val);
867 }
868 }
869
870 return pixd;
871}
872
873
890PIX *
892{
893l_int32 i, j, w, h, wpls, wpld, val;
894l_uint32 *datas, *lines, *datad, *lined;
895PIX *pixd;
896
897 if (!pixs)
898 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
899 if (pixGetDepth(pixs) != 32)
900 return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
901
902 pixGetDimensions(pixs, &w, &h, NULL);
903 datas = pixGetData(pixs);
904 wpls = pixGetWpl(pixs);
905 if ((pixd = pixCreate(w, h, 8)) == NULL)
906 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
907 pixCopyResolution(pixd, pixs);
908 pixCopyInputFormat(pixd, pixs);
909 datad = pixGetData(pixd);
910 wpld = pixGetWpl(pixd);
911
912 for (i = 0; i < h; i++) {
913 lines = datas + i * wpls;
914 lined = datad + i * wpld;
915 for (j = 0; j < w; j++, lines++) {
916 val = ((*lines) >> L_GREEN_SHIFT) & 0xff;
917 SET_DATA_BYTE(lined, j, val);
918 }
919 }
920
921 return pixd;
922}
923
924
946PIX *
948 l_int32 type)
949{
950l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val, minval, maxval;
951l_uint32 *datas, *lines, *datad, *lined;
952PIX *pixd;
953
954 if (!pixs)
955 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
956 if (pixGetDepth(pixs) != 32)
957 return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
958 if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX &&
959 type != L_CHOOSE_MAXDIFF && type != L_CHOOSE_MIN_BOOST &&
960 type != L_CHOOSE_MAX_BOOST)
961 return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
962
963 pixGetDimensions(pixs, &w, &h, NULL);
964 datas = pixGetData(pixs);
965 wpls = pixGetWpl(pixs);
966 if ((pixd = pixCreate(w, h, 8)) == NULL)
967 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
968 pixCopyResolution(pixd, pixs);
969 pixCopyInputFormat(pixd, pixs);
970 datad = pixGetData(pixd);
971 wpld = pixGetWpl(pixd);
972
973 for (i = 0; i < h; i++) {
974 lines = datas + i * wpls;
975 lined = datad + i * wpld;
976 for (j = 0; j < w; j++) {
977 extractRGBValues(lines[j], &rval, &gval, &bval);
978 if (type == L_CHOOSE_MIN || type == L_CHOOSE_MIN_BOOST) {
979 val = L_MIN(rval, gval);
980 val = L_MIN(val, bval);
981 if (type == L_CHOOSE_MIN_BOOST)
982 val = L_MIN(255, (val * val) / var_NEUTRAL_BOOST_VAL);
983 } else if (type == L_CHOOSE_MAX || type == L_CHOOSE_MAX_BOOST) {
984 val = L_MAX(rval, gval);
985 val = L_MAX(val, bval);
986 if (type == L_CHOOSE_MAX_BOOST)
987 val = L_MIN(255, (val * val) / var_NEUTRAL_BOOST_VAL);
988 } else { /* L_CHOOSE_MAXDIFF */
989 minval = L_MIN(rval, gval);
990 minval = L_MIN(minval, bval);
991 maxval = L_MAX(rval, gval);
992 maxval = L_MAX(maxval, bval);
993 val = maxval - minval;
994 }
995 SET_DATA_BYTE(lined, j, val);
996 }
997 }
998
999 return pixd;
1000}
1001
1002
1031PIX *
1033 l_int32 refval)
1034{
1035l_int32 w, h, d, i, j, wplt, wpld;
1036l_int32 rval, gval, bval, sval, minrg, maxrg, min, max, delta;
1037l_int32 fullsat, newval;
1038l_float32 *invmax, *ratio;
1039l_uint32 *linet, *lined, *datat, *datad;
1040PIX *pixt, *pixd;
1041
1042 if (!pixs)
1043 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1044 pixGetDimensions(pixs, &w, &h, &d);
1045 if (d != 32 && !pixGetColormap(pixs))
1046 return (PIX *)ERROR_PTR("pixs not cmapped or rgb", __func__, NULL);
1047 if (refval < 1 || refval > 255)
1048 return (PIX *)ERROR_PTR("refval not in [1 ... 255]", __func__, NULL);
1049
1051 pixd = pixCreate(w, h, 8);
1052 pixCopyResolution(pixd, pixs);
1053 pixCopyInputFormat(pixd, pixs);
1054 wplt = pixGetWpl(pixt);
1055 datat = pixGetData(pixt);
1056 wpld = pixGetWpl(pixd);
1057 datad = pixGetData(pixd);
1058 invmax = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
1059 ratio = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
1060 for (i = 1; i < 256; i++) { /* i == 0 --> delta = sval = newval = 0 */
1061 invmax[i] = 1.0f / (l_float32)i;
1062 ratio[i] = (l_float32)i / (l_float32)refval;
1063 }
1064 for (i = 0; i < h; i++) {
1065 linet = datat + i * wplt;
1066 lined = datad + i * wpld;
1067 for (j = 0; j < w; j++) {
1068 extractRGBValues(linet[j], &rval, &gval, &bval);
1069 minrg = L_MIN(rval, gval);
1070 min = L_MIN(minrg, bval);
1071 maxrg = L_MAX(rval, gval);
1072 max = L_MAX(maxrg, bval);
1073 delta = max - min;
1074 if (delta == 0) /* gray; no chroma */
1075 sval = 0;
1076 else
1077 sval = (l_int32)(255. * (l_float32)delta * invmax[max] + 0.5);
1078
1079 fullsat = L_MIN(255, 255 * ratio[max]);
1080 newval = (sval * fullsat + (255 - sval) * max) / 255;
1081 SET_DATA_BYTE(lined, j, newval);
1082 }
1083 }
1084
1085 pixDestroy(&pixt);
1086 LEPT_FREE(invmax);
1087 LEPT_FREE(ratio);
1088 return pixd;
1089}
1090
1091
1107PIX *
1109 l_float32 rc,
1110 l_float32 gc,
1111 l_float32 bc)
1112{
1113l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val;
1114l_uint32 *datas, *lines, *datad, *lined;
1115PIX *pixd;
1116
1117 if (!pixs)
1118 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1119 if (pixGetDepth(pixs) != 32)
1120 return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
1121 if (rc <= 0 && gc <= 0 && bc <= 0)
1122 return (PIX *)ERROR_PTR("all coefficients <= 0", __func__, NULL);
1123
1124 pixGetDimensions(pixs, &w, &h, NULL);
1125 datas = pixGetData(pixs);
1126 wpls = pixGetWpl(pixs);
1127 if ((pixd = pixCreate(w, h, 8)) == NULL)
1128 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1129 pixCopyResolution(pixd, pixs);
1130 pixCopyInputFormat(pixd, pixs);
1131 datad = pixGetData(pixd);
1132 wpld = pixGetWpl(pixd);
1133
1134 for (i = 0; i < h; i++) {
1135 lines = datas + i * wpls;
1136 lined = datad + i * wpld;
1137 for (j = 0; j < w; j++) {
1138 extractRGBValues(lines[j], &rval, &gval, &bval);
1139 val = (l_int32)(rc * rval + gc * gval + bc * bval);
1140 val = L_MIN(255, L_MAX(0, val));
1141 SET_DATA_BYTE(lined, j, val);
1142 }
1143 }
1144
1145 return pixd;
1146}
1147
1148
1167PIX *
1169 l_float32 rc,
1170 l_float32 gc,
1171 l_float32 bc,
1172 l_int32 thresh,
1173 l_int32 relation)
1174{
1175l_int32 threshold;
1176PIX *pix1, *pix2;
1177
1178 if (!pixs || pixGetDepth(pixs) != 32)
1179 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
1180 if (rc <= 0 && gc <= 0 && bc <= 0)
1181 return (PIX *)ERROR_PTR("all coefficients <= 0", __func__, NULL);
1182 if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
1183 relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
1184 return (PIX *)ERROR_PTR("invalid relation", __func__, NULL);
1185
1186 pix1 = pixConvertRGBToGrayArb(pixs, rc, gc, bc);
1187 threshold = (relation == L_SELECT_IF_LTE || relation == L_SELECT_IF_GT) ?
1188 thresh : thresh + 1;
1189 pix2 = pixThresholdToBinary(pix1, threshold);
1190 if (relation == L_SELECT_IF_GT || relation == L_SELECT_IF_GTE)
1191 pixInvert(pix2, pix2);
1192 pixDestroy(&pix1);
1193 return pix2;
1194}
1195
1196
1197/*---------------------------------------------------------------------------*
1198 * Conversion from grayscale to colormap *
1199 *---------------------------------------------------------------------------*/
1222PIX *
1224{
1225l_int32 d;
1226PIX *pixd;
1227PIXCMAP *cmap;
1228
1229 if (!pixs)
1230 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1231 d = pixGetDepth(pixs);
1232 if (d != 2 && d != 4 && d != 8)
1233 return (PIX *)ERROR_PTR("pixs not 2, 4 or 8 bpp", __func__, NULL);
1234
1235 if (pixGetColormap(pixs)) {
1236 L_INFO("pixs already has a colormap\n", __func__);
1237 return pixCopy(NULL, pixs);
1238 }
1239
1240 if (d == 8) /* lossless conversion */
1241 return pixConvertGrayToColormap8(pixs, 2);
1242
1243 /* Build a cmap with equally spaced target values over the
1244 * full 8 bpp range. */
1245 pixd = pixCopy(NULL, pixs);
1246 cmap = pixcmapCreateLinear(d, 1 << d);
1247 pixSetColormap(pixd, cmap);
1248 pixCopyInputFormat(pixd, pixs);
1249 return pixd;
1250}
1251
1252
1275PIX *
1277 l_int32 mindepth)
1278{
1279l_int32 ncolors, w, h, depth, i, j, wpls, wpld;
1280l_int32 index, num, val, newval;
1281l_int32 array[256];
1282l_uint32 *lines, *lined, *datas, *datad;
1283NUMA *na;
1284PIX *pixd;
1285PIXCMAP *cmap;
1286
1287 if (!pixs)
1288 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1289 if (pixGetDepth(pixs) != 8)
1290 return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
1291 if (mindepth != 2 && mindepth != 4 && mindepth != 8) {
1292 L_WARNING("invalid value of mindepth; setting to 8\n", __func__);
1293 mindepth = 8;
1294 }
1295
1296 if (pixGetColormap(pixs)) {
1297 L_INFO("pixs already has a colormap\n", __func__);
1298 return pixCopy(NULL, pixs);
1299 }
1300
1301 na = pixGetGrayHistogram(pixs, 1);
1302 numaGetCountRelativeToZero(na, L_GREATER_THAN_ZERO, &ncolors);
1303 if (mindepth == 8 || ncolors > 16)
1304 depth = 8;
1305 else if (mindepth == 4 || ncolors > 4)
1306 depth = 4;
1307 else
1308 depth = 2;
1309
1310 pixGetDimensions(pixs, &w, &h, NULL);
1311 pixd = pixCreate(w, h, depth);
1312 cmap = pixcmapCreate(depth);
1313 pixSetColormap(pixd, cmap);
1314 pixCopyInputFormat(pixd, pixs);
1315 pixCopyResolution(pixd, pixs);
1316
1317 index = 0;
1318 for (i = 0; i < 256; i++) {
1319 array[i] = 0; /* only to quiet the static checker */
1320 numaGetIValue(na, i, &num);
1321 if (num > 0) {
1322 pixcmapAddColor(cmap, i, i, i);
1323 array[i] = index;
1324 index++;
1325 }
1326 }
1327
1328 datas = pixGetData(pixs);
1329 wpls = pixGetWpl(pixs);
1330 datad = pixGetData(pixd);
1331 wpld = pixGetWpl(pixd);
1332 for (i = 0; i < h; i++) {
1333 lines = datas + i * wpls;
1334 lined = datad + i * wpld;
1335 for (j = 0; j < w; j++) {
1336 val = GET_DATA_BYTE(lines, j);
1337 newval = array[val];
1338 if (depth == 2)
1339 SET_DATA_DIBIT(lined, j, newval);
1340 else if (depth == 4)
1341 SET_DATA_QBIT(lined, j, newval);
1342 else /* depth == 8 */
1343 SET_DATA_BYTE(lined, j, newval);
1344 }
1345 }
1346
1347 numaDestroy(&na);
1348 return pixd;
1349}
1350
1351
1352/*---------------------------------------------------------------------------*
1353 * Colorizing conversion from grayscale to color *
1354 *---------------------------------------------------------------------------*/
1370PIX *
1372 l_uint32 color,
1373 l_int32 cmapflag)
1374{
1375l_int32 i, j, w, h, wplt, wpld, val8;
1376l_uint32 *datad, *datat, *lined, *linet, *tab;
1377PIX *pixt, *pixd;
1378PIXCMAP *cmap;
1379
1380 if (!pixs)
1381 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1382 if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
1383 return (PIX *)ERROR_PTR("pixs not 8 bpp or cmapped", __func__, NULL);
1384
1385 if (pixGetColormap(pixs))
1387 else
1388 pixt = pixClone(pixs);
1389
1390 cmap = pixcmapGrayToColor(color);
1391 if (cmapflag) {
1392 pixd = pixCopy(NULL, pixt);
1393 pixSetColormap(pixd, cmap);
1394 pixDestroy(&pixt);
1395 return pixd;
1396 }
1397
1398 /* Make an RGB pix */
1399 pixcmapToRGBTable(cmap, &tab, NULL);
1400 pixGetDimensions(pixt, &w, &h, NULL);
1401 pixd = pixCreate(w, h, 32);
1402 pixCopyResolution(pixd, pixs);
1403 pixCopyInputFormat(pixd, pixs);
1404 datad = pixGetData(pixd);
1405 wpld = pixGetWpl(pixd);
1406 datat = pixGetData(pixt);
1407 wplt = pixGetWpl(pixt);
1408 for (i = 0; i < h; i++) {
1409 lined = datad + i * wpld;
1410 linet = datat + i * wplt;
1411 for (j = 0; j < w; j++) {
1412 val8 = GET_DATA_BYTE(linet, j);
1413 lined[j] = tab[val8];
1414 }
1415 }
1416
1417 pixDestroy(&pixt);
1418 pixcmapDestroy(&cmap);
1419 LEPT_FREE(tab);
1420 return pixd;
1421}
1422
1423
1424/*---------------------------------------------------------------------------*
1425 * Conversion from RGB color to colormap *
1426 *---------------------------------------------------------------------------*/
1455PIX *
1457 l_int32 ditherflag)
1458{
1459l_int32 ncolors;
1460NUMA *na;
1461PIX *pixd;
1462
1463 if (!pixs)
1464 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1465 if (pixGetDepth(pixs) != 32)
1466 return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
1467 if (pixGetSpp(pixs) == 4)
1468 L_WARNING("pixs has alpha; removing\n", __func__);
1469
1470 /* Get the histogram and count the number of occupied level 4
1471 * leaf octcubes. We don't yet know if this is the number of
1472 * actual colors, but if it's not, all pixels falling into
1473 * the same leaf octcube will be assigned to the color of the
1474 * first pixel that lands there. */
1475 na = pixOctcubeHistogram(pixs, 4, &ncolors);
1476
1477 /* If 256 or fewer occupied leaf octcubes, quantize to those octcubes */
1478 if (ncolors <= 256) {
1479 pixd = pixFewColorsOctcubeQuant2(pixs, 4, na, ncolors, NULL);
1480 pixCopyInputFormat(pixd, pixs);
1481 numaDestroy(&na);
1482 return pixd;
1483 }
1484
1485 /* There are too many occupied leaf octcubes to be represented
1486 * directly in a colormap. Fall back to octree quantization,
1487 * optionally with dithering. */
1488 numaDestroy(&na);
1489 if (ditherflag)
1490 L_INFO("More than 256 colors; using octree quant with dithering\n",
1491 __func__);
1492 else
1493 L_INFO("More than 256 colors; using octree quant; no dithering\n",
1494 __func__);
1495 return pixOctreeColorQuant(pixs, 240, ditherflag);
1496}
1497
1498
1499/*---------------------------------------------------------------------------*
1500 * Conversion from colormap to 1 bpp *
1501 *---------------------------------------------------------------------------*/
1517PIX *
1519{
1520l_int32 i, j, nc, w, h, imin, imax, factor, wpl1, wpld;
1521l_int32 index, rmin, gmin, bmin, rmax, gmax, bmax, dmin, dmax;
1522l_float32 minfract, ifract;
1523l_int32 *lut;
1524l_uint32 *line1, *lined, *data1, *datad;
1525NUMA *na1, *na2; /* histograms */
1526PIX *pix1, *pixd;
1527PIXCMAP *cmap;
1528
1529 if (!pixs)
1530 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1531 if ((cmap = pixGetColormap(pixs)) == NULL)
1532 return (PIX *)ERROR_PTR("no colormap", __func__, NULL);
1533
1534 /* Select target colors for the two classes. Find the
1535 * colors with smallest and largest average component values.
1536 * The smallest is class 0 and the largest is class 1. */
1537 pixcmapGetRangeValues(cmap, L_SELECT_AVERAGE, NULL, NULL, &imin, &imax);
1538 pixcmapGetColor(cmap, imin, &rmin, &gmin, &bmin);
1539 pixcmapGetColor(cmap, imax, &rmax, &gmax, &bmax);
1540 nc = pixcmapGetCount(cmap);
1541
1542 /* Assign colors to the two classes. The histogram is
1543 * initialized to 0, so any colors not found when computing
1544 * the sampled histogram will get zero weight in minfract. */
1545 if ((lut = (l_int32 *)LEPT_CALLOC(nc, sizeof(l_int32))) == NULL)
1546 return (PIX *)ERROR_PTR("calloc fail for lut", __func__, NULL);
1547 pixGetDimensions(pixs, &w, &h, NULL);
1548 factor = L_MAX(1, (l_int32)sqrt((l_float64)(w * h) / 50000. + 0.5));
1549 na1 = pixGetCmapHistogram(pixs, factor);
1550 na2 = numaNormalizeHistogram(na1, 1.0);
1551 minfract = 0.0;
1552 for (i = 0; i < nc; i++) {
1553 numaGetFValue(na2, i, &ifract);
1554 pixcmapGetDistanceToColor(cmap, i, rmin, gmin, bmin, &dmin);
1555 pixcmapGetDistanceToColor(cmap, i, rmax, gmax, bmax, &dmax);
1556 if (dmin < dmax) { /* closer to dark extreme value */
1557 lut[i] = 1; /* black pixel in 1 bpp image */
1558 minfract += ifract;
1559 }
1560 }
1561 numaDestroy(&na1);
1562 numaDestroy(&na2);
1563
1564 /* Generate the output binarized image */
1565 pix1 = pixConvertTo8(pixs, 1);
1566 pixd = pixCreate(w, h, 1);
1567 data1 = pixGetData(pix1);
1568 datad = pixGetData(pixd);
1569 wpl1 = pixGetWpl(pix1);
1570 wpld = pixGetWpl(pixd);
1571 for (i = 0; i < h; i++) {
1572 line1 = data1 + i * wpl1;
1573 lined = datad + i * wpld;
1574 for (j = 0; j < w; j++) {
1575 index = GET_DATA_BYTE(line1, j);
1576 if (lut[index] == 1) SET_DATA_BIT(lined, j);
1577 }
1578 }
1579 pixDestroy(&pix1);
1580 LEPT_FREE(lut);
1581
1582 /* We expect minfract (the dark colors) to be less than 0.5.
1583 * If that is not the case, invert pixd. */
1584 if (minfract > 0.5) {
1585 L_INFO("minfract = %5.3f; inverting\n", __func__, minfract);
1586 pixInvert(pixd, pixd);
1587 }
1588
1589 return pixd;
1590}
1591
1592
1593/*---------------------------------------------------------------------------*
1594 * Quantization for relatively small number of colors in source *
1595 *---------------------------------------------------------------------------*/
1626l_ok
1628 l_int32 maxcolors,
1629 l_int32 mingraycolors,
1630 l_int32 octlevel,
1631 PIX **ppixd)
1632{
1633l_int32 d, ncolors, iscolor, graycolors;
1634PIX *pixg, *pixd;
1635
1636 if (!ppixd)
1637 return ERROR_INT("&pixd not defined", __func__, 1);
1638 *ppixd = NULL;
1639 if (!pixs)
1640 return ERROR_INT("pixs not defined", __func__, 1);
1641 d = pixGetDepth(pixs);
1642 if (d != 8 && d != 32)
1643 return ERROR_INT("pixs not defined", __func__, 1);
1644 if (pixGetColormap(pixs) != NULL) {
1645 *ppixd = pixClone(pixs);
1646 return 0;
1647 }
1648 if (maxcolors <= 0)
1649 maxcolors = 15; /* default */
1650 if (maxcolors > 50)
1651 L_WARNING("maxcolors > 50; very large!\n", __func__);
1652 if (mingraycolors <= 0)
1653 mingraycolors = 10; /* default */
1654 if (mingraycolors > 30)
1655 L_WARNING("mingraycolors > 30; very large!\n", __func__);
1656 if (octlevel != 3 && octlevel != 4) {
1657 L_WARNING("invalid octlevel; setting to 3\n", __func__);
1658 octlevel = 3;
1659 }
1660
1661 /* Test the number of colors. For color, the octcube leaves
1662 * are at level 4. */
1663 pixColorsForQuantization(pixs, 0, &ncolors, &iscolor, 0);
1664 if (ncolors > maxcolors)
1665 return ERROR_INT("too many colors", __func__, 1);
1666
1667 /* Quantize!
1668 * (1) For color:
1669 * If octlevel == 4, try to quantize to an octree where
1670 * the octcube leaves are at level 4. If that fails,
1671 * back off to level 3.
1672 * If octlevel == 3, quantize to level 3 directly.
1673 * For level 3, the quality is usually good enough and there
1674 * is negligible chance of getting more than 256 colors.
1675 * (2) For grayscale, multiply ncolors by 1.5 for extra quality,
1676 * but use at least mingraycolors and not more than 256. */
1677 if (iscolor) {
1678 pixd = pixFewColorsOctcubeQuant1(pixs, octlevel);
1679 if (!pixd) { /* backoff */
1680 pixd = pixFewColorsOctcubeQuant1(pixs, octlevel - 1);
1681 if (octlevel == 3) /* shouldn't happen */
1682 L_WARNING("quantized at level 2; low quality\n", __func__);
1683 }
1684 } else { /* image is really grayscale */
1685 if (d == 32)
1686 pixg = pixConvertRGBToLuminance(pixs);
1687 else
1688 pixg = pixClone(pixs);
1689 graycolors = L_MAX(mingraycolors, (l_int32)(1.5 * ncolors));
1690 graycolors = L_MIN(graycolors, 256);
1691 if (graycolors < 16)
1692 pixd = pixThresholdTo4bpp(pixg, graycolors, 1);
1693 else
1694 pixd = pixThresholdOn8bpp(pixg, graycolors, 1);
1695 pixDestroy(&pixg);
1696 }
1697 *ppixd = pixd;
1698
1699 if (!pixd)
1700 return ERROR_INT("pixd not made", __func__, 1);
1701 pixCopyInputFormat(pixd, pixs);
1702 return 0;
1703}
1704
1705
1706
1707/*---------------------------------------------------------------------------*
1708 * Conversion from 16 bpp to 8 bpp *
1709 *---------------------------------------------------------------------------*/
1725PIX *
1727 l_int32 type)
1728{
1729l_uint16 dword;
1730l_int32 w, h, wpls, wpld, i, j, val, use_lsb;
1731l_uint32 sword, first, second;
1732l_uint32 *datas, *datad, *lines, *lined;
1733PIX *pixd;
1734
1735 if (!pixs)
1736 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1737 if (pixGetDepth(pixs) != 16)
1738 return (PIX *)ERROR_PTR("pixs not 16 bpp", __func__, NULL);
1739 if (type != L_LS_BYTE && type != L_MS_BYTE &&
1740 type != L_AUTO_BYTE && type != L_CLIP_TO_FF)
1741 return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
1742
1743 pixGetDimensions(pixs, &w, &h, NULL);
1744 if ((pixd = pixCreate(w, h, 8)) == NULL)
1745 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1746 pixCopyInputFormat(pixd, pixs);
1747 pixCopyResolution(pixd, pixs);
1748 wpls = pixGetWpl(pixs);
1749 datas = pixGetData(pixs);
1750 wpld = pixGetWpl(pixd);
1751 datad = pixGetData(pixd);
1752
1753 if (type == L_AUTO_BYTE) {
1754 use_lsb = TRUE;
1755 for (i = 0; i < h; i++) {
1756 lines = datas + i * wpls;
1757 for (j = 0; j < wpls; j++) {
1758 val = GET_DATA_TWO_BYTES(lines, j);
1759 if (val > 255) {
1760 use_lsb = FALSE;
1761 break;
1762 }
1763 }
1764 if (!use_lsb) break;
1765 }
1766 type = (use_lsb) ? L_LS_BYTE : L_MS_BYTE;
1767 }
1768
1769 /* Convert 2 pixels at a time */
1770 for (i = 0; i < h; i++) {
1771 lines = datas + i * wpls;
1772 lined = datad + i * wpld;
1773 if (type == L_LS_BYTE) {
1774 for (j = 0; j < wpls; j++) {
1775 sword = *(lines + j);
1776 dword = ((sword >> 8) & 0xff00) | (sword & 0xff);
1777 SET_DATA_TWO_BYTES(lined, j, dword);
1778 }
1779 } else if (type == L_MS_BYTE) {
1780 for (j = 0; j < wpls; j++) {
1781 sword = *(lines + j);
1782 dword = ((sword >> 16) & 0xff00) | ((sword >> 8) & 0xff);
1783 SET_DATA_TWO_BYTES(lined, j, dword);
1784 }
1785 } else { /* type == L_CLIP_TO_FF */
1786 for (j = 0; j < wpls; j++) {
1787 sword = *(lines + j);
1788 first = (sword >> 24) ? 255 : ((sword >> 16) & 0xff);
1789 second = ((sword >> 8) & 0xff) ? 255 : (sword & 0xff);
1790 dword = (first << 8) | second;
1791 SET_DATA_TWO_BYTES(lined, j, dword);
1792 }
1793 }
1794 }
1795
1796 return pixd;
1797}
1798
1799
1800/*---------------------------------------------------------------------------*
1801 * Conversion from grayscale to false color
1802 *---------------------------------------------------------------------------*/
1819PIX *
1821 l_float32 gamma)
1822{
1823l_int32 d;
1824PIX *pixd;
1825PIXCMAP *cmap;
1826
1827 if (!pixs)
1828 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1829 d = pixGetDepth(pixs);
1830 if (d != 8 && d != 16)
1831 return (PIX *)ERROR_PTR("pixs not 8 or 16 bpp", __func__, NULL);
1832
1833 if (d == 16) {
1834 pixd = pixConvert16To8(pixs, L_MS_BYTE);
1835 } else { /* d == 8 */
1836 if (pixGetColormap(pixs))
1838 else
1839 pixd = pixCopy(NULL, pixs);
1840 }
1841 if (!pixd)
1842 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1843
1844 cmap = pixcmapGrayToFalseColor(gamma);
1845 pixSetColormap(pixd, cmap);
1846 pixCopyResolution(pixd, pixs);
1847 pixCopyInputFormat(pixd, pixs);
1848 return pixd;
1849}
1850
1851
1852/*---------------------------------------------------------------------------*
1853 * Unpacking conversion from 1 bpp to 2, 4, 8, 16 and 32 bpp *
1854 *---------------------------------------------------------------------------*/
1872PIX *
1874 l_int32 depth,
1875 l_int32 invert)
1876{
1877PIX *pixd;
1878
1879 if (!pixs)
1880 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1881 if (pixGetDepth(pixs) != 1)
1882 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
1883 if (depth != 2 && depth != 4 && depth != 8 && depth != 16 && depth != 32)
1884 return (PIX *)ERROR_PTR("depth not 2, 4, 8, 16 or 32 bpp",
1885 __func__, NULL);
1886
1887 if (depth == 2) {
1888 if (invert == 0)
1889 pixd = pixConvert1To2(NULL, pixs, 0, 3);
1890 else /* invert bits */
1891 pixd = pixConvert1To2(NULL, pixs, 3, 0);
1892 } else if (depth == 4) {
1893 if (invert == 0)
1894 pixd = pixConvert1To4(NULL, pixs, 0, 15);
1895 else /* invert bits */
1896 pixd = pixConvert1To4(NULL, pixs, 15, 0);
1897 } else if (depth == 8) {
1898 if (invert == 0)
1899 pixd = pixConvert1To8(NULL, pixs, 0, 255);
1900 else /* invert bits */
1901 pixd = pixConvert1To8(NULL, pixs, 255, 0);
1902 } else if (depth == 16) {
1903 if (invert == 0)
1904 pixd = pixConvert1To16(NULL, pixs, 0, 0xffff);
1905 else /* invert bits */
1906 pixd = pixConvert1To16(NULL, pixs, 0xffff, 0);
1907 } else {
1908 if (invert == 0)
1909 pixd = pixConvert1To32(NULL, pixs, 0, 0xffffffff);
1910 else /* invert bits */
1911 pixd = pixConvert1To32(NULL, pixs, 0xffffffff, 0);
1912 }
1913
1914 pixCopyInputFormat(pixd, pixs);
1915 return pixd;
1916}
1917
1918
1935PIX *
1937 PIX *pixs,
1938 l_uint16 val0,
1939 l_uint16 val1)
1940{
1941l_int32 w, h, i, j, dibit, ndibits, wpls, wpld;
1942l_uint16 val[2];
1943l_uint32 index;
1944l_uint32 *tab, *datas, *datad, *lines, *lined;
1945
1946 if (!pixs)
1947 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1948 if (pixGetDepth(pixs) != 1)
1949 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
1950
1951 pixGetDimensions(pixs, &w, &h, NULL);
1952 if (pixd) {
1953 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
1954 return (PIX *)ERROR_PTR("pix sizes unequal", __func__, pixd);
1955 if (pixGetDepth(pixd) != 16)
1956 return (PIX *)ERROR_PTR("pixd not 16 bpp", __func__, pixd);
1957 } else {
1958 if ((pixd = pixCreate(w, h, 16)) == NULL)
1959 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
1960 }
1961 pixCopyResolution(pixd, pixs);
1962 pixCopyInputFormat(pixd, pixs);
1963
1964 /* Use a table to convert 2 src bits at a time */
1965 tab = (l_uint32 *)LEPT_CALLOC(4, sizeof(l_uint32));
1966 val[0] = val0;
1967 val[1] = val1;
1968 for (index = 0; index < 4; index++) {
1969 tab[index] = (val[(index >> 1) & 1] << 16) | val[index & 1];
1970 }
1971
1972 datas = pixGetData(pixs);
1973 wpls = pixGetWpl(pixs);
1974 datad = pixGetData(pixd);
1975 wpld = pixGetWpl(pixd);
1976 ndibits = (w + 1) / 2;
1977 for (i = 0; i < h; i++) {
1978 lines = datas + i * wpls;
1979 lined = datad + i * wpld;
1980 for (j = 0; j < ndibits; j++) {
1981 dibit = GET_DATA_DIBIT(lines, j);
1982 lined[j] = tab[dibit];
1983 }
1984 }
1985
1986 LEPT_FREE(tab);
1987 return pixd;
1988}
1989
1990
2007PIX *
2009 PIX *pixs,
2010 l_uint32 val0,
2011 l_uint32 val1)
2012{
2013l_int32 w, h, i, j, wpls, wpld, bit;
2014l_uint32 val[2];
2015l_uint32 *datas, *datad, *lines, *lined;
2016
2017 if (!pixs)
2018 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2019 if (pixGetDepth(pixs) != 1)
2020 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
2021
2022 pixGetDimensions(pixs, &w, &h, NULL);
2023 if (pixd) {
2024 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2025 return (PIX *)ERROR_PTR("pix sizes unequal", __func__, pixd);
2026 if (pixGetDepth(pixd) != 32)
2027 return (PIX *)ERROR_PTR("pixd not 32 bpp", __func__, pixd);
2028 } else {
2029 if ((pixd = pixCreate(w, h, 32)) == NULL)
2030 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2031 }
2032 pixCopyResolution(pixd, pixs);
2033 pixCopyInputFormat(pixd, pixs);
2034
2035 val[0] = val0;
2036 val[1] = val1;
2037 datas = pixGetData(pixs);
2038 wpls = pixGetWpl(pixs);
2039 datad = pixGetData(pixd);
2040 wpld = pixGetWpl(pixd);
2041 for (i = 0; i < h; i++) {
2042 lines = datas + i * wpls;
2043 lined = datad + i * wpld;
2044 for (j = 0; j <w; j++) {
2045 bit = GET_DATA_BIT(lines, j);
2046 lined[j] = val[bit];
2047 }
2048 }
2049
2050 return pixd;
2051}
2052
2053
2054/*---------------------------------------------------------------------------*
2055 * Conversion from 1 bpp to 2 bpp *
2056 *---------------------------------------------------------------------------*/
2068PIX *
2070{
2071PIX *pixd;
2072PIXCMAP *cmap;
2073
2074 if (!pixs)
2075 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2076 if (pixGetDepth(pixs) != 1)
2077 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
2078
2079 if ((pixd = pixConvert1To2(NULL, pixs, 0, 1)) == NULL)
2080 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2081 cmap = pixcmapCreate(2);
2082 pixcmapAddColor(cmap, 255, 255, 255);
2083 pixcmapAddColor(cmap, 0, 0, 0);
2084 pixSetColormap(pixd, cmap);
2085 pixCopyInputFormat(pixd, pixs);
2086
2087 return pixd;
2088}
2089
2090
2109PIX *
2111 PIX *pixs,
2112 l_int32 val0,
2113 l_int32 val1)
2114{
2115l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2116l_uint8 val[2];
2117l_uint32 index;
2118l_uint16 *tab;
2119l_uint32 *datas, *datad, *lines, *lined;
2120
2121 if (!pixs)
2122 return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
2123 if (pixGetDepth(pixs) != 1)
2124 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
2125
2126 pixGetDimensions(pixs, &w, &h, NULL);
2127 if (pixd) {
2128 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2129 return (PIX *)ERROR_PTR("pix sizes unequal", __func__, pixd);
2130 if (pixGetDepth(pixd) != 2)
2131 return (PIX *)ERROR_PTR("pixd not 2 bpp", __func__, pixd);
2132 } else {
2133 if ((pixd = pixCreate(w, h, 2)) == NULL)
2134 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2135 }
2136 pixCopyResolution(pixd, pixs);
2137 pixCopyInputFormat(pixd, pixs);
2138
2139 /* Use a table to convert 8 src bits to 16 dest bits */
2140 tab = (l_uint16 *)LEPT_CALLOC(256, sizeof(l_uint16));
2141 val[0] = val0;
2142 val[1] = val1;
2143 for (index = 0; index < 256; index++) {
2144 tab[index] = (val[(index >> 7) & 1] << 14) |
2145 (val[(index >> 6) & 1] << 12) |
2146 (val[(index >> 5) & 1] << 10) |
2147 (val[(index >> 4) & 1] << 8) |
2148 (val[(index >> 3) & 1] << 6) |
2149 (val[(index >> 2) & 1] << 4) |
2150 (val[(index >> 1) & 1] << 2) | val[index & 1];
2151 }
2152
2153 datas = pixGetData(pixs);
2154 wpls = pixGetWpl(pixs);
2155 datad = pixGetData(pixd);
2156 wpld = pixGetWpl(pixd);
2157 nbytes = (w + 7) / 8;
2158 for (i = 0; i < h; i++) {
2159 lines = datas + i * wpls;
2160 lined = datad + i * wpld;
2161 for (j = 0; j < nbytes; j++) {
2162 byteval = GET_DATA_BYTE(lines, j);
2163 SET_DATA_TWO_BYTES(lined, j, tab[byteval]);
2164 }
2165 }
2166
2167 LEPT_FREE(tab);
2168 return pixd;
2169}
2170
2171
2172/*---------------------------------------------------------------------------*
2173 * Conversion from 1 bpp to 4 bpp *
2174 *---------------------------------------------------------------------------*/
2186PIX *
2188{
2189PIX *pixd;
2190PIXCMAP *cmap;
2191
2192 if (!pixs)
2193 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2194 if (pixGetDepth(pixs) != 1)
2195 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
2196
2197 if ((pixd = pixConvert1To4(NULL, pixs, 0, 1)) == NULL)
2198 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2199 cmap = pixcmapCreate(4);
2200 pixcmapAddColor(cmap, 255, 255, 255);
2201 pixcmapAddColor(cmap, 0, 0, 0);
2202 pixSetColormap(pixd, cmap);
2203 pixCopyInputFormat(pixd, pixs);
2204
2205 return pixd;
2206}
2207
2208
2227PIX *
2229 PIX *pixs,
2230 l_int32 val0,
2231 l_int32 val1)
2232{
2233l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2234l_uint8 val[2];
2235l_uint32 index;
2236l_uint32 *tab, *datas, *datad, *lines, *lined;
2237
2238 if (!pixs)
2239 return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
2240 if (pixGetDepth(pixs) != 1)
2241 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
2242
2243 pixGetDimensions(pixs, &w, &h, NULL);
2244 if (pixd) {
2245 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2246 return (PIX *)ERROR_PTR("pix sizes unequal", __func__, pixd);
2247 if (pixGetDepth(pixd) != 4)
2248 return (PIX *)ERROR_PTR("pixd not 4 bpp", __func__, pixd);
2249 } else {
2250 if ((pixd = pixCreate(w, h, 4)) == NULL)
2251 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2252 }
2253 pixCopyResolution(pixd, pixs);
2254 pixCopyInputFormat(pixd, pixs);
2255
2256 /* Use a table to convert 8 src bits to 32 bit dest word */
2257 tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
2258 val[0] = val0;
2259 val[1] = val1;
2260 for (index = 0; index < 256; index++) {
2261 tab[index] = (val[(index >> 7) & 1] << 28) |
2262 (val[(index >> 6) & 1] << 24) |
2263 (val[(index >> 5) & 1] << 20) |
2264 (val[(index >> 4) & 1] << 16) |
2265 (val[(index >> 3) & 1] << 12) |
2266 (val[(index >> 2) & 1] << 8) |
2267 (val[(index >> 1) & 1] << 4) | val[index & 1];
2268 }
2269
2270 datas = pixGetData(pixs);
2271 wpls = pixGetWpl(pixs);
2272 datad = pixGetData(pixd);
2273 wpld = pixGetWpl(pixd);
2274 nbytes = (w + 7) / 8;
2275 for (i = 0; i < h; i++) {
2276 lines = datas + i * wpls;
2277 lined = datad + i * wpld;
2278 for (j = 0; j < nbytes; j++) {
2279 byteval = GET_DATA_BYTE(lines, j);
2280 lined[j] = tab[byteval];
2281 }
2282 }
2283
2284 LEPT_FREE(tab);
2285 return pixd;
2286}
2287
2288
2289/*---------------------------------------------------------------------------*
2290 * Conversion from 1, 2 and 4 bpp to 8 bpp *
2291 *---------------------------------------------------------------------------*/
2303PIX *
2305{
2306PIX *pixd;
2307PIXCMAP *cmap;
2308
2309 if (!pixs)
2310 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2311 if (pixGetDepth(pixs) != 1)
2312 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
2313
2314 if ((pixd = pixConvert1To8(NULL, pixs, 0, 1)) == NULL)
2315 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2316 cmap = pixcmapCreate(8);
2317 pixcmapAddColor(cmap, 255, 255, 255);
2318 pixcmapAddColor(cmap, 0, 0, 0);
2319 pixSetColormap(pixd, cmap);
2320 pixCopyInputFormat(pixd, pixs);
2321 return pixd;
2322}
2323
2324
2344PIX *
2346 PIX *pixs,
2347 l_uint8 val0,
2348 l_uint8 val1)
2349{
2350l_int32 w, h, i, j, qbit, nqbits, wpls, wpld;
2351l_uint8 val[2];
2352l_uint32 index;
2353l_uint32 *tab, *datas, *datad, *lines, *lined;
2354
2355 if (!pixs)
2356 return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
2357 if (pixGetDepth(pixs) != 1)
2358 return (PIX *)ERROR_PTR("pixs not 1 bpp", __func__, pixd);
2359
2360 pixGetDimensions(pixs, &w, &h, NULL);
2361 if (pixd) {
2362 if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2363 return (PIX *)ERROR_PTR("pix sizes unequal", __func__, pixd);
2364 if (pixGetDepth(pixd) != 8)
2365 return (PIX *)ERROR_PTR("pixd not 8 bpp", __func__, pixd);
2366 } else {
2367 if ((pixd = pixCreate(w, h, 8)) == NULL)
2368 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2369 }
2370 pixCopyResolution(pixd, pixs);
2371 pixCopyInputFormat(pixd, pixs);
2372 pixSetPadBits(pixs, 0);
2373
2374 /* Use a table to convert 4 src bits at a time */
2375 tab = (l_uint32 *)LEPT_CALLOC(16, sizeof(l_uint32));
2376 val[0] = val0;
2377 val[1] = val1;
2378 for (index = 0; index < 16; index++) {
2379 tab[index] = ((l_uint32)val[(index >> 3) & 1] << 24) |
2380 (val[(index >> 2) & 1] << 16) |
2381 (val[(index >> 1) & 1] << 8) | val[index & 1];
2382 }
2383
2384 datas = pixGetData(pixs);
2385 wpls = pixGetWpl(pixs);
2386 datad = pixGetData(pixd);
2387 wpld = pixGetWpl(pixd);
2388 nqbits = (w + 3) / 4;
2389 for (i = 0; i < h; i++) {
2390 lines = datas + i * wpls;
2391 lined = datad + i * wpld;
2392 for (j = 0; j < nqbits; j++) {
2393 qbit = GET_DATA_QBIT(lines, j);
2394 lined[j] = tab[qbit];
2395 }
2396 }
2397
2398 LEPT_FREE(tab);
2399 return pixd;
2400}
2401
2402
2433PIX *
2435 l_uint8 val0,
2436 l_uint8 val1,
2437 l_uint8 val2,
2438 l_uint8 val3,
2439 l_int32 cmapflag)
2440{
2441l_int32 w, h, i, j, nbytes, wpls, wpld, dibit, byte;
2442l_uint32 val[4];
2443l_uint32 index;
2444l_uint32 *tab, *datas, *datad, *lines, *lined;
2445PIX *pixd;
2446PIXCMAP *cmaps, *cmapd;
2447
2448 if (!pixs)
2449 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2450 if (pixGetDepth(pixs) != 2)
2451 return (PIX *)ERROR_PTR("pixs not 2 bpp", __func__, NULL);
2452
2453 cmaps = pixGetColormap(pixs);
2454 if (cmaps && cmapflag == FALSE)
2456
2457 pixGetDimensions(pixs, &w, &h, NULL);
2458 if ((pixd = pixCreate(w, h, 8)) == NULL)
2459 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2460 pixSetPadBits(pixs, 0);
2461 pixCopyResolution(pixd, pixs);
2462 pixCopyInputFormat(pixd, pixs);
2463 datas = pixGetData(pixs);
2464 wpls = pixGetWpl(pixs);
2465 datad = pixGetData(pixd);
2466 wpld = pixGetWpl(pixd);
2467
2468 if (cmapflag == TRUE) { /* pixd will have a colormap */
2469 if (cmaps) { /* use the existing colormap from pixs */
2470 cmapd = pixcmapConvertTo8(cmaps);
2471 } else { /* make a colormap from the input values */
2472 cmapd = pixcmapCreate(8);
2473 pixcmapAddColor(cmapd, val0, val0, val0);
2474 pixcmapAddColor(cmapd, val1, val1, val1);
2475 pixcmapAddColor(cmapd, val2, val2, val2);
2476 pixcmapAddColor(cmapd, val3, val3, val3);
2477 }
2478 pixSetColormap(pixd, cmapd);
2479 for (i = 0; i < h; i++) {
2480 lines = datas + i * wpls;
2481 lined = datad + i * wpld;
2482 for (j = 0; j < w; j++) {
2483 dibit = GET_DATA_DIBIT(lines, j);
2484 SET_DATA_BYTE(lined, j, dibit);
2485 }
2486 }
2487 return pixd;
2488 }
2489
2490 /* Last case: no colormap in either pixs or pixd.
2491 * Use input values and build a table to convert 1 src byte
2492 * (4 src pixels) at a time */
2493 tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
2494 val[0] = val0;
2495 val[1] = val1;
2496 val[2] = val2;
2497 val[3] = val3;
2498 for (index = 0; index < 256; index++) {
2499 tab[index] = (val[(index >> 6) & 3] << 24) |
2500 (val[(index >> 4) & 3] << 16) |
2501 (val[(index >> 2) & 3] << 8) | val[index & 3];
2502 }
2503
2504 nbytes = (w + 3) / 4;
2505 for (i = 0; i < h; i++) {
2506 lines = datas + i * wpls;
2507 lined = datad + i * wpld;
2508 for (j = 0; j < nbytes; j++) {
2509 byte = GET_DATA_BYTE(lines, j);
2510 lined[j] = tab[byte];
2511 }
2512 }
2513
2514 LEPT_FREE(tab);
2515 return pixd;
2516}
2517
2518
2543PIX *
2545 l_int32 cmapflag)
2546{
2547l_int32 w, h, i, j, wpls, wpld, byte, qbit;
2548l_uint32 *datas, *datad, *lines, *lined;
2549PIX *pixd;
2550PIXCMAP *cmaps, *cmapd;
2551
2552 if (!pixs)
2553 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2554 if (pixGetDepth(pixs) != 4)
2555 return (PIX *)ERROR_PTR("pixs not 4 bpp", __func__, NULL);
2556
2557 cmaps = pixGetColormap(pixs);
2558 if (cmaps && cmapflag == FALSE)
2560
2561 pixGetDimensions(pixs, &w, &h, NULL);
2562 if ((pixd = pixCreate(w, h, 8)) == NULL)
2563 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
2564 pixCopyResolution(pixd, pixs);
2565 pixCopyInputFormat(pixd, pixs);
2566 datas = pixGetData(pixs);
2567 wpls = pixGetWpl(pixs);
2568 datad = pixGetData(pixd);
2569 wpld = pixGetWpl(pixd);
2570
2571 if (cmapflag == TRUE) { /* pixd will have a colormap */
2572 if (cmaps) { /* use the existing colormap from pixs */
2573 cmapd = pixcmapConvertTo8(cmaps);
2574 } else { /* make a colormap with a linear trc */
2575 cmapd = pixcmapCreate(8);
2576 for (i = 0; i < 16; i++)
2577 pixcmapAddColor(cmapd, 17 * i, 17 * i, 17 * i);
2578 }
2579 pixSetColormap(pixd, cmapd);
2580 for (i = 0; i < h; i++) {
2581 lines = datas + i * wpls;
2582 lined = datad + i * wpld;
2583 for (j = 0; j < w; j++) {
2584 qbit = GET_DATA_QBIT(lines, j);
2585 SET_DATA_BYTE(lined, j, qbit);
2586 }
2587 }
2588 return pixd;
2589 }
2590
2591 /* Last case: no colormap in either pixs or pixd.
2592 * Replicate the qbit value into 8 bits. */
2593 for (i = 0; i < h; i++) {
2594 lines = datas + i * wpls;
2595 lined = datad + i * wpld;
2596 for (j = 0; j < w; j++) {
2597 qbit = GET_DATA_QBIT(lines, j);
2598 byte = (qbit << 4) | qbit;
2599 SET_DATA_BYTE(lined, j, byte);
2600 }
2601 }
2602 return pixd;
2603}
2604
2605
2606
2607/*---------------------------------------------------------------------------*
2608 * Unpacking conversion from 8 bpp to 16 bpp *
2609 *---------------------------------------------------------------------------*/
2626PIX *
2628 l_int32 leftshift)
2629{
2630l_int32 i, j, w, h, d, wplt, wpld, val;
2631l_uint32 *datat, *datad, *linet, *lined;
2632PIX *pixt, *pixd;
2633
2634 if (!pixs)
2635 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2636 pixGetDimensions(pixs, &w, &h, &d);
2637 if (d != 8)
2638 return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
2639 if (leftshift < 0 || leftshift > 8)
2640 return (PIX *)ERROR_PTR("leftshift not in [0 ... 8]", __func__, NULL);
2641
2642 if (pixGetColormap(pixs) != NULL)
2644 else
2645 pixt = pixClone(pixs);
2646
2647 pixd = pixCreate(w, h, 16);
2648 pixCopyResolution(pixd, pixs);
2649 pixCopyInputFormat(pixd, pixs);
2650 datat = pixGetData(pixt);
2651 datad = pixGetData(pixd);
2652 wplt = pixGetWpl(pixt);
2653 wpld = pixGetWpl(pixd);
2654 for (i = 0; i < h; i++) {
2655 linet = datat + i * wplt;
2656 lined = datad + i * wpld;
2657 for (j = 0; j < w; j++) {
2658 val = GET_DATA_BYTE(linet, j);
2659 if (leftshift == 8)
2660 val = val | (val << leftshift);
2661 else
2662 val <<= leftshift;
2663 SET_DATA_TWO_BYTES(lined, j, val);
2664 }
2665 }
2666
2667 pixDestroy(&pixt);
2668 return pixd;
2669}
2670
2671
2672/*---------------------------------------------------------------------------*
2673 * Top-level conversion to 2 bpp *
2674 *---------------------------------------------------------------------------*/
2690PIX *
2692{
2693l_int32 d;
2694PIX *pix1, *pix2, *pix3, *pixd;
2695
2696 if (!pixs)
2697 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2698 d = pixGetDepth(pixs);
2699 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 24 && d != 32)
2700 return (PIX *)ERROR_PTR("depth not {1,2,4,8,24,32}", __func__, NULL);
2701
2702 if (pixGetColormap(pixs) != NULL) {
2704 d = pixGetDepth(pix1);
2705 } else {
2706 pix1 = pixCopy(NULL, pixs);
2707 }
2708 if (d == 24 || d == 32)
2709 pix2 = pixConvertTo8(pix1, FALSE);
2710 else
2711 pix2 = pixClone(pix1);
2712 pixDestroy(&pix1);
2713 if (d == 1) {
2714 pixd = pixConvert1To2(NULL, pix2, 3, 0);
2715 } else if (d == 2) {
2716 pixd = pixClone(pix2);
2717 } else if (d == 4) {
2718 pix3 = pixConvert4To8(pix2, FALSE); /* unpack to 8 */
2719 pixd = pixConvert8To2(pix3);
2720 pixDestroy(&pix3);
2721 } else { /* d == 8 */
2722 pixd = pixConvert8To2(pix2);
2723 }
2724 pixDestroy(&pix2);
2725 return pixd;
2726}
2727
2728
2740PIX *
2742{
2743l_int32 i, j, w, h, wpls, wpld;
2744l_uint32 word;
2745l_uint32 *datas, *lines, *datad, *lined;
2746PIX *pixs, *pixd;
2747
2748 if (!pix || pixGetDepth(pix) != 8)
2749 return (PIX *)ERROR_PTR("pix undefined or not 8 bpp", __func__, NULL);
2750
2751 if (pixGetColormap(pix) != NULL)
2753 else
2754 pixs = pixClone(pix);
2755 pixGetDimensions(pixs, &w, &h, NULL);
2756 datas = pixGetData(pixs);
2757 wpls = pixGetWpl(pixs);
2758 pixd = pixCreate(w, h, 2);
2759 datad = pixGetData(pixd);
2760 wpld = pixGetWpl(pixd);
2761 for (i = 0; i < h; i++) {
2762 lines = datas + i * wpls;
2763 lined = datad + i * wpld;
2764 for (j = 0; j < wpls; j++) { /* march through 4 pixels at a time */
2765 word = lines[j] & 0xc0c0c0c0; /* top 2 bits of each byte */
2766 word = (word >> 24) | ((word & 0xff0000) >> 18) |
2767 ((word & 0xff00) >> 12) | ((word & 0xff) >> 6);
2768 SET_DATA_BYTE(lined, j, word); /* only LS byte is filled */
2769 }
2770 }
2771 pixDestroy(&pixs);
2772 return pixd;
2773}
2774
2775
2776/*---------------------------------------------------------------------------*
2777 * Top-level conversion to 4 bpp *
2778 *---------------------------------------------------------------------------*/
2794PIX *
2796{
2797l_int32 d;
2798PIX *pix1, *pix2, *pix3, *pixd;
2799
2800 if (!pixs)
2801 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2802 d = pixGetDepth(pixs);
2803 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 24 && d != 32)
2804 return (PIX *)ERROR_PTR("depth not {1,2,4,8,24,32}", __func__, NULL);
2805
2806 if (pixGetColormap(pixs) != NULL) {
2808 d = pixGetDepth(pix1);
2809 } else {
2810 pix1 = pixCopy(NULL, pixs);
2811 }
2812 if (d == 24 || d == 32)
2813 pix2 = pixConvertTo8(pix1, FALSE);
2814 else
2815 pix2 = pixClone(pix1);
2816 pixDestroy(&pix1);
2817 if (d == 1) {
2818 pixd = pixConvert1To4(NULL, pix2, 15, 0);
2819 } else if (d == 2) {
2820 pix3 = pixConvert2To8(pix2, 0, 0x55, 0xaa, 0xff, FALSE);
2821 pixd = pixConvert8To4(pix3);
2822 pixDestroy(&pix3);
2823 } else if (d == 4) {
2824 pixd = pixClone(pix2);
2825 } else { /* d == 8 */
2826 pixd = pixConvert8To4(pix2);
2827 }
2828 pixDestroy(&pix2);
2829 return pixd;
2830}
2831
2832
2844PIX *
2846{
2847l_int32 i, j, w, h, wpls, wpld, val;
2848l_uint32 *datas, *lines, *datad, *lined;
2849PIX *pixs, *pixd;
2850
2851 if (!pix || pixGetDepth(pix) != 8)
2852 return (PIX *)ERROR_PTR("pix undefined or not 8 bpp", __func__, NULL);
2853
2854 if (pixGetColormap(pix) != NULL)
2856 else
2857 pixs = pixClone(pix);
2858 pixGetDimensions(pixs, &w, &h, NULL);
2859 datas = pixGetData(pixs);
2860 wpls = pixGetWpl(pixs);
2861 pixd = pixCreate(w, h, 4);
2862 datad = pixGetData(pixd);
2863 wpld = pixGetWpl(pixd);
2864 for (i = 0; i < h; i++) {
2865 lines = datas + i * wpls;
2866 lined = datad + i * wpld;
2867 for (j = 0; j < w; j++) {
2868 val = GET_DATA_BYTE(lines, j);
2869 val = val >> 4; /* take top 4 bits */
2870 SET_DATA_QBIT(lined, j, val);
2871 }
2872 }
2873 pixDestroy(&pixs);
2874 return pixd;
2875}
2876
2877
2878/*---------------------------------------------------------------------------*
2879 * Top-level conversion to 1 bpp *
2880 *---------------------------------------------------------------------------*/
2896PIX *
2898{
2899l_int32 d, color0, color1, rval, gval, bval;
2900PIX *pix1, *pix2, *pixd;
2901PIXCMAP *cmap;
2902
2903 if (!pixs)
2904 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2905 d = pixGetDepth(pixs);
2906 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
2907 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", __func__, NULL);
2908
2909 cmap = pixGetColormap(pixs);
2910 if (d == 1) {
2911 if (!cmap) {
2912 return pixCopy(NULL, pixs);
2913 } else { /* strip the colormap off, and invert if reasonable
2914 for standard binary photometry. */
2915 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
2916 color0 = rval + gval + bval;
2917 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
2918 color1 = rval + gval + bval;
2919 pixd = pixCopy(NULL, pixs);
2920 pixDestroyColormap(pixd);
2921 if (color1 > color0)
2922 pixInvert(pixd, pixd);
2923 return pixd;
2924 }
2925 }
2926
2927 /* For all other depths, use 8 bpp as an intermediary */
2928 pix1 = pixConvertTo8(pixs, FALSE);
2929 pix2 = pixBackgroundNormSimple(pix1, NULL, NULL);
2930 pixd = pixThresholdToBinary(pix2, 180);
2931 pixDestroy(&pix1);
2932 pixDestroy(&pix2);
2933 return pixd;
2934}
2935
2936
2953PIX *
2955 l_int32 threshold)
2956{
2957l_int32 d, color0, color1, rval, gval, bval;
2958PIX *pixg, *pixd;
2959PIXCMAP *cmap;
2960
2961 if (!pixs)
2962 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2963 d = pixGetDepth(pixs);
2964 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
2965 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", __func__, NULL);
2966
2967 cmap = pixGetColormap(pixs);
2968 if (d == 1) {
2969 if (!cmap) {
2970 return pixCopy(NULL, pixs);
2971 } else { /* strip the colormap off, and invert if reasonable
2972 for standard binary photometry. */
2973 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
2974 color0 = rval + gval + bval;
2975 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
2976 color1 = rval + gval + bval;
2977 pixd = pixCopy(NULL, pixs);
2978 pixDestroyColormap(pixd);
2979 if (color1 > color0)
2980 pixInvert(pixd, pixd);
2981 return pixd;
2982 }
2983 }
2984
2985 /* For all other depths, use 8 bpp as an intermediary */
2986 pixg = pixConvertTo8(pixs, FALSE);
2987 pixd = pixThresholdToBinary(pixg, threshold);
2988 pixDestroy(&pixg);
2989 return pixd;
2990}
2991
2992
3007PIX *
3009 l_int32 factor,
3010 l_int32 threshold)
3011{
3012l_float32 scalefactor;
3013PIX *pixt, *pixd;
3014
3015 if (!pixs)
3016 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3017 if (factor < 1)
3018 return (PIX *)ERROR_PTR("factor must be >= 1", __func__, NULL);
3019
3020 scalefactor = 1.f / (l_float32)factor;
3021 pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3022 pixd = pixConvertTo1(pixt, threshold);
3023 pixDestroy(&pixt);
3024 return pixd;
3025}
3026
3027
3028/*---------------------------------------------------------------------------*
3029 * Top-level conversion to 8 bpp *
3030 *---------------------------------------------------------------------------*/
3056PIX *
3058 l_int32 cmapflag)
3059{
3060l_int32 d;
3061PIX *pix1, *pixd;
3062PIXCMAP *cmap;
3063
3064 if (!pixs)
3065 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3066 d = pixGetDepth(pixs);
3067 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
3068 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", __func__, NULL);
3069
3070 if (d == 1) {
3071 if (cmapflag)
3072 return pixConvert1To8Cmap(pixs);
3073 else
3074 return pixConvert1To8(NULL, pixs, 255, 0);
3075 } else if (d == 2) {
3076 return pixConvert2To8(pixs, 0, 85, 170, 255, cmapflag);
3077 } else if (d == 4) {
3078 return pixConvert4To8(pixs, cmapflag);
3079 } else if (d == 8) {
3080 cmap = pixGetColormap(pixs);
3081 if ((cmap && cmapflag) || (!cmap && !cmapflag)) {
3082 return pixCopy(NULL, pixs);
3083 } else if (cmap) { /* !cmapflag */
3085 } else { /* !cmap && cmapflag; add colormap to pixd */
3086 pixd = pixCopy(NULL, pixs);
3087 pixAddGrayColormap8(pixd);
3088 return pixd;
3089 }
3090 } else if (d == 16) {
3091 pixd = pixConvert16To8(pixs, L_MS_BYTE);
3092 if (cmapflag)
3093 pixAddGrayColormap8(pixd);
3094 return pixd;
3095 } else if (d == 24) {
3096 pix1 = pixConvert24To32(pixs);
3097 pixd = pixConvertRGBToLuminance(pix1);
3098 if (cmapflag)
3099 pixAddGrayColormap8(pixd);
3100 pixDestroy(&pix1);
3101 return pixd;
3102 } else { /* d == 32 */
3103 pixd = pixConvertRGBToLuminance(pixs);
3104 if (cmapflag)
3105 pixAddGrayColormap8(pixd);
3106 return pixd;
3107 }
3108}
3109
3110
3125PIX *
3127 l_int32 factor,
3128 l_int32 cmapflag)
3129{
3130l_float32 scalefactor;
3131PIX *pixt, *pixd;
3132
3133 if (!pixs)
3134 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3135 if (factor < 1)
3136 return (PIX *)ERROR_PTR("factor must be >= 1", __func__, NULL);
3137
3138 scalefactor = 1.f / (l_float32)factor;
3139 pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3140 pixd = pixConvertTo8(pixt, cmapflag);
3141
3142 pixDestroy(&pixt);
3143 return pixd;
3144}
3145
3146
3167PIX *
3169 l_int32 dither)
3170{
3171l_int32 d;
3172
3173 if (!pixs)
3174 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3175 d = pixGetDepth(pixs);
3176 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
3177 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,32}", __func__, NULL);
3178
3179 if (d != 32)
3180 return pixConvertTo8(pixs, 1);
3181
3182 return pixConvertRGBToColormap(pixs, dither);
3183}
3184
3185
3186/*---------------------------------------------------------------------------*
3187 * Top-level conversion to 16 bpp *
3188 *---------------------------------------------------------------------------*/
3200PIX *
3202{
3203l_int32 d;
3204
3205 if (!pixs)
3206 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3207
3208 d = pixGetDepth(pixs);
3209 if (d == 1)
3210 return pixConvert1To16(NULL, pixs, 0xffff, 0);
3211 else if (d == 8)
3212 return pixConvert8To16(pixs, 8);
3213 else
3214 return (PIX *)ERROR_PTR("src depth not 1 or 8 bpp", __func__, NULL);
3215}
3216
3217
3218
3219/*---------------------------------------------------------------------------*
3220 * Top-level conversion to 32 bpp *
3221 *---------------------------------------------------------------------------*/
3247PIX *
3249{
3250l_int32 d;
3251PIX *pix1, *pixd;
3252
3253 if (!pixs)
3254 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3255
3256 d = pixGetDepth(pixs);
3257 if (d == 1) {
3258 return pixConvert1To32(NULL, pixs, 0xffffffff, 0);
3259 } else if (d == 2) {
3260 pix1 = pixConvert2To8(pixs, 0, 85, 170, 255, TRUE);
3261 pixd = pixConvert8To32(pix1);
3262 pixDestroy(&pix1);
3263 return pixd;
3264 } else if (d == 4) {
3265 pix1 = pixConvert4To8(pixs, TRUE);
3266 pixd = pixConvert8To32(pix1);
3267 pixDestroy(&pix1);
3268 return pixd;
3269 } else if (d == 8) {
3270 return pixConvert8To32(pixs);
3271 } else if (d == 16) {
3272 pix1 = pixConvert16To8(pixs, L_MS_BYTE);
3273 pixd = pixConvert8To32(pix1);
3274 pixDestroy(&pix1);
3275 return pixd;
3276 } else if (d == 24) {
3277 return pixConvert24To32(pixs);
3278 } else if (d == 32) {
3279 return pixCopy(NULL, pixs);
3280 } else {
3281 return (PIX *)ERROR_PTR("depth not 1, 2, 4, 8, 16, 32 bpp",
3282 __func__, NULL);
3283 }
3284}
3285
3286
3300PIX *
3302 l_int32 factor)
3303{
3304l_float32 scalefactor;
3305PIX *pix1, *pixd;
3306
3307 if (!pixs)
3308 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3309 if (factor < 1)
3310 return (PIX *)ERROR_PTR("factor must be >= 1", __func__, NULL);
3311
3312 scalefactor = 1.f / (l_float32)factor;
3313 pix1 = pixScaleBySampling(pixs, scalefactor, scalefactor);
3314 pixd = pixConvertTo32(pix1);
3315
3316 pixDestroy(&pix1);
3317 return pixd;
3318}
3319
3320
3333PIX *
3335{
3336l_int32 i, j, w, h, wpls, wpld, val;
3337l_uint32 *datas, *datad, *lines, *lined;
3338l_uint32 *tab;
3339PIX *pixd;
3340
3341 if (!pixs)
3342 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3343 if (pixGetDepth(pixs) != 8)
3344 return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
3345
3346 if (pixGetColormap(pixs))
3348
3349 pixGetDimensions(pixs, &w, &h, NULL);
3350 datas = pixGetData(pixs);
3351 wpls = pixGetWpl(pixs);
3352 if ((pixd = pixCreate(w, h, 32)) == NULL)
3353 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
3354 pixCopyResolution(pixd, pixs);
3355 pixCopyInputFormat(pixd, pixs);
3356 datad = pixGetData(pixd);
3357 wpld = pixGetWpl(pixd);
3358
3359 /* Replication table gray --> rgb */
3360 tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
3361 for (i = 0; i < 256; i++)
3362 tab[i] = ((l_uint32)i << 24) | (i << 16) | (i << 8);
3363
3364 /* Replicate 1 --> 4 bytes (alpha byte not set) */
3365 for (i = 0; i < h; i++) {
3366 lines = datas + i * wpls;
3367 lined = datad + i * wpld;
3368 for (j = 0; j < w; j++) {
3369 val = GET_DATA_BYTE(lines, j);
3370 lined[j] = tab[val];
3371 }
3372 }
3373
3374 LEPT_FREE(tab);
3375 return pixd;
3376}
3377
3378
3379/*---------------------------------------------------------------------------*
3380 * Top-level conversion to 8 or 32 bpp, without colormap *
3381 *---------------------------------------------------------------------------*/
3401PIX *
3403 l_int32 copyflag,
3404 l_int32 warnflag)
3405{
3406l_int32 d;
3407PIX *pixd;
3408
3409 if (!pixs)
3410 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3411 if (copyflag != L_CLONE && copyflag != L_COPY)
3412 return (PIX *)ERROR_PTR("invalid copyflag", __func__, NULL);
3413
3414 d = pixGetDepth(pixs);
3415 if (pixGetColormap(pixs)) {
3416 if (warnflag) L_WARNING("pix has colormap; removing\n", __func__);
3418 } else if (d == 8 || d == 32) {
3419 if (copyflag == L_CLONE)
3420 pixd = pixClone(pixs);
3421 else /* copyflag == L_COPY */
3422 pixd = pixCopy(NULL, pixs);
3423 } else {
3424 pixd = pixConvertTo8(pixs, 0);
3425 }
3426
3427 /* Sanity check on result */
3428 d = pixGetDepth(pixd);
3429 if (d != 8 && d != 32) {
3430 pixDestroy(&pixd);
3431 return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", __func__, NULL);
3432 }
3433
3434 return pixd;
3435}
3436
3437
3438/*---------------------------------------------------------------------------*
3439 * Conversion between 24 bpp and 32 bpp rgb *
3440 *---------------------------------------------------------------------------*/
3462PIX *
3464{
3465l_uint8 *lines;
3466l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3467l_uint32 pixel;
3468l_uint32 *datas, *datad, *lined;
3469PIX *pixd;
3470
3471 if (!pixs)
3472 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3473 pixGetDimensions(pixs, &w, &h, &d);
3474 if (d != 24)
3475 return (PIX *)ERROR_PTR("pixs not 24 bpp", __func__, NULL);
3476
3477 pixd = pixCreate(w, h, 32);
3478 datas = pixGetData(pixs);
3479 datad = pixGetData(pixd);
3480 wpls = pixGetWpl(pixs);
3481 wpld = pixGetWpl(pixd);
3482 for (i = 0; i < h; i++) {
3483 lines = (l_uint8 *)(datas + i * wpls);
3484 lined = datad + i * wpld;
3485 for (j = 0; j < w; j++) {
3486 rval = *lines++;
3487 gval = *lines++;
3488 bval = *lines++;
3489 composeRGBPixel(rval, gval, bval, &pixel);
3490 lined[j] = pixel;
3491 }
3492 }
3493 pixCopyResolution(pixd, pixs);
3494 pixCopyInputFormat(pixd, pixs);
3495 return pixd;
3496}
3497
3498
3510PIX *
3512{
3513l_uint8 *rgbdata8;
3514l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3515l_uint32 *datas, *lines, *rgbdata;
3516PIX *pixd;
3517
3518 if (!pixs)
3519 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3520 pixGetDimensions(pixs, &w, &h, &d);
3521 if (d != 32)
3522 return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
3523
3524 datas = pixGetData(pixs);
3525 wpls = pixGetWpl(pixs);
3526 pixd = pixCreate(w, h, 24);
3527 rgbdata = pixGetData(pixd);
3528 wpld = pixGetWpl(pixd);
3529 for (i = 0; i < h; i++) {
3530 lines = datas + i * wpls;
3531 rgbdata8 = (l_uint8 *)(rgbdata + i * wpld);
3532 for (j = 0; j < w; j++) {
3533 extractRGBValues(lines[j], &rval, &gval, &bval);
3534 *rgbdata8++ = rval;
3535 *rgbdata8++ = gval;
3536 *rgbdata8++ = bval;
3537 }
3538 }
3539 pixCopyResolution(pixd, pixs);
3540 pixCopyInputFormat(pixd, pixs);
3541 return pixd;
3542}
3543
3544
3545/*---------------------------------------------------------------------------*
3546 * Conversion between 32 bpp (1 spp) and 16 or 8 bpp *
3547 *---------------------------------------------------------------------------*/
3561PIX *
3563 l_int32 type)
3564{
3565l_uint16 dword;
3566l_int32 w, h, i, j, wpls, wpld;
3567l_uint32 sword;
3568l_uint32 *datas, *lines, *datad, *lined;
3569PIX *pixd;
3570
3571 if (!pixs || pixGetDepth(pixs) != 32)
3572 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
3573 if (type != L_LS_TWO_BYTES && type != L_MS_TWO_BYTES &&
3574 type != L_CLIP_TO_FFFF)
3575 return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
3576
3577 pixGetDimensions(pixs, &w, &h, NULL);
3578 if ((pixd = pixCreate(w, h, 16)) == NULL)
3579 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
3580 pixCopyResolution(pixd, pixs);
3581 pixCopyInputFormat(pixd, pixs);
3582 wpls = pixGetWpl(pixs);
3583 datas = pixGetData(pixs);
3584 wpld = pixGetWpl(pixd);
3585 datad = pixGetData(pixd);
3586
3587 for (i = 0; i < h; i++) {
3588 lines = datas + i * wpls;
3589 lined = datad + i * wpld;
3590 if (type == L_LS_TWO_BYTES) {
3591 for (j = 0; j < wpls; j++) {
3592 sword = *(lines + j);
3593 dword = sword & 0xffff;
3594 SET_DATA_TWO_BYTES(lined, j, dword);
3595 }
3596 } else if (type == L_MS_TWO_BYTES) {
3597 for (j = 0; j < wpls; j++) {
3598 sword = *(lines + j);
3599 dword = sword >> 16;
3600 SET_DATA_TWO_BYTES(lined, j, dword);
3601 }
3602 } else { /* type == L_CLIP_TO_FFFF */
3603 for (j = 0; j < wpls; j++) {
3604 sword = *(lines + j);
3605 dword = (sword >> 16) ? 0xffff : (sword & 0xffff);
3606 SET_DATA_TWO_BYTES(lined, j, dword);
3607 }
3608 }
3609 }
3610
3611 return pixd;
3612}
3613
3614
3623PIX *
3625 l_int32 type16,
3626 l_int32 type8)
3627{
3628PIX *pix1, *pixd;
3629
3630 if (!pixs || pixGetDepth(pixs) != 32)
3631 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
3632 if (type16 != L_LS_TWO_BYTES && type16 != L_MS_TWO_BYTES &&
3633 type16 != L_CLIP_TO_FFFF)
3634 return (PIX *)ERROR_PTR("invalid type16", __func__, NULL);
3635 if (type8 != L_LS_BYTE && type8 != L_MS_BYTE && type8 != L_CLIP_TO_FF)
3636 return (PIX *)ERROR_PTR("invalid type8", __func__, NULL);
3637
3638 pix1 = pixConvert32To16(pixs, type16);
3639 pixd = pixConvert16To8(pix1, type8);
3640 pixDestroy(&pix1);
3641 return pixd;
3642}
3643
3644
3645/*---------------------------------------------------------------------------*
3646 * Removal of alpha component by blending with white background *
3647 *---------------------------------------------------------------------------*/
3660PIX *
3662{
3663 if (!pixs)
3664 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3665
3666 if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4)
3667 return pixAlphaBlendUniform(pixs, 0xffffff00);
3668 else
3669 return pixClone(pixs);
3670}
3671
3672
3673/*---------------------------------------------------------------------------*
3674 * Addition of alpha component to 1 bpp *
3675 *---------------------------------------------------------------------------*/
3695PIX *
3697 PIX *pixs)
3698{
3699PIXCMAP *cmap;
3700
3701 if (!pixs || (pixGetDepth(pixs) != 1))
3702 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", __func__, NULL);
3703 if (pixd && (pixd != pixs))
3704 return (PIX *)ERROR_PTR("pixd defined but != pixs", __func__, NULL);
3705
3706 pixd = pixCopy(pixd, pixs);
3707 cmap = pixcmapCreate(1);
3708 pixSetColormap(pixd, cmap);
3709 pixcmapAddRGBA(cmap, 255, 255, 255, 0); /* 0 ==> white + transparent */
3710 pixcmapAddRGBA(cmap, 0, 0, 0, 255); /* 1 ==> black + opaque */
3711 return pixd;
3712}
3713
3714
3715/*---------------------------------------------------------------------------*
3716 * Lossless depth conversion (unpacking) *
3717 *---------------------------------------------------------------------------*/
3735PIX *
3737 l_int32 d)
3738{
3739l_int32 w, h, ds, wpls, wpld, i, j, val;
3740l_uint32 *datas, *datad, *lines, *lined;
3741PIX *pixd;
3742
3743 if (!pixs)
3744 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3745 if (pixGetColormap(pixs))
3746 return (PIX *)ERROR_PTR("pixs has colormap", __func__, NULL);
3747 if (d != 2 && d != 4 && d != 8)
3748 return (PIX *)ERROR_PTR("invalid dest depth", __func__, NULL);
3749
3750 pixGetDimensions(pixs, &w, &h, &ds);
3751 if (d < ds)
3752 return (PIX *)ERROR_PTR("depth > d", __func__, NULL);
3753 else if (d == ds)
3754 return pixCopy(NULL, pixs);
3755
3756 if ((pixd = pixCreate(w, h, d)) == NULL)
3757 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
3758 pixCopyResolution(pixd, pixs);
3759 pixCopyInputFormat(pixd, pixs);
3760
3761 /* Unpack the bits */
3762 datas = pixGetData(pixs);
3763 wpls = pixGetWpl(pixs);
3764 datad = pixGetData(pixd);
3765 wpld = pixGetWpl(pixd);
3766 for (i = 0; i < h; i++) {
3767 lines = datas + i * wpls;
3768 lined = datad + i * wpld;
3769 switch (ds)
3770 {
3771 case 1:
3772 for (j = 0; j < w; j++) {
3773 val = GET_DATA_BIT(lines, j);
3774 if (d == 8)
3775 SET_DATA_BYTE(lined, j, val);
3776 else if (d == 4)
3777 SET_DATA_QBIT(lined, j, val);
3778 else /* d == 2 */
3779 SET_DATA_DIBIT(lined, j, val);
3780 }
3781 break;
3782 case 2:
3783 for (j = 0; j < w; j++) {
3784 val = GET_DATA_DIBIT(lines, j);
3785 if (d == 8)
3786 SET_DATA_BYTE(lined, j, val);
3787 else /* d == 4 */
3788 SET_DATA_QBIT(lined, j, val);
3789 }
3790 break;
3791 case 4:
3792 for (j = 0; j < w; j++) {
3793 val = GET_DATA_DIBIT(lines, j);
3794 SET_DATA_BYTE(lined, j, val);
3795 }
3796 break;
3797 }
3798 }
3799
3800 return pixd;
3801}
3802
3803
3804/*---------------------------------------------------------------------------*
3805 * Conversion for printing in PostScript *
3806 *---------------------------------------------------------------------------*/
3824PIX *
3826{
3827l_int32 d;
3828PIX *pixd;
3829PIXCMAP *cmap;
3830
3831 if (!pixs)
3832 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3833
3834 cmap = pixGetColormap(pixs);
3835 d = pixGetDepth(pixs);
3836 switch (d)
3837 {
3838 case 1:
3839 case 32:
3840 pixd = pixClone(pixs);
3841 break;
3842 case 2:
3843 if (cmap)
3845 else
3846 pixd = pixConvert2To8(pixs, 0, 0x55, 0xaa, 0xff, FALSE);
3847 break;
3848 case 4:
3849 if (cmap)
3851 else
3852 pixd = pixConvert4To8(pixs, FALSE);
3853 break;
3854 case 8:
3856 break;
3857 case 16:
3858 pixd = pixConvert16To8(pixs, L_MS_BYTE);
3859 break;
3860 default:
3861 lept_stderr("depth not in {1, 2, 4, 8, 16, 32}");
3862 return NULL;
3863 }
3864
3865 return pixd;
3866}
3867
3868
3869/*---------------------------------------------------------------------------*
3870 * Scaling conversion to subpixel RGB *
3871 *---------------------------------------------------------------------------*/
3901PIX *
3903 l_float32 scalex,
3904 l_float32 scaley,
3905 l_int32 order)
3906{
3907l_int32 d;
3908PIX *pix1, *pixd;
3909PIXCMAP *cmap;
3910
3911 if (!pixs)
3912 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3913 d = pixGetDepth(pixs);
3914 cmap = pixGetColormap(pixs);
3915 if (d != 8 && d != 32 && !cmap)
3916 return (PIX *)ERROR_PTR("pix not 8 or 32 bpp and not cmapped",
3917 __func__, NULL);
3918 if (scalex <= 0.0 || scaley <= 0.0)
3919 return (PIX *)ERROR_PTR("scale factors must be > 0", __func__, NULL);
3920 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
3921 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
3922 return (PIX *)ERROR_PTR("invalid subpixel order", __func__, NULL);
3923 if ((pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC)) == NULL)
3924 return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
3925
3926 d = pixGetDepth(pix1);
3927 pixd = NULL;
3928 if (d == 8)
3929 pixd = pixConvertGrayToSubpixelRGB(pix1, scalex, scaley, order);
3930 else if (d == 32)
3931 pixd = pixConvertColorToSubpixelRGB(pix1, scalex, scaley, order);
3932 else
3933 L_ERROR("invalid depth %d\n", __func__, d);
3934
3935 pixDestroy(&pix1);
3936 return pixd;
3937}
3938
3939
3969PIX *
3971 l_float32 scalex,
3972 l_float32 scaley,
3973 l_int32 order)
3974{
3975l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
3976l_uint32 *datat, *datad, *linet, *lined;
3977PIX *pix1, *pix2, *pixd;
3978PIXCMAP *cmap;
3979
3980 if (!pixs)
3981 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3982 d = pixGetDepth(pixs);
3983 cmap = pixGetColormap(pixs);
3984 if (d != 8 && !cmap)
3985 return (PIX *)ERROR_PTR("pix not 8 bpp & not cmapped", __func__, NULL);
3986 if (scalex <= 0.0 || scaley <= 0.0)
3987 return (PIX *)ERROR_PTR("scale factors must be > 0", __func__, NULL);
3988 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
3989 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
3990 return (PIX *)ERROR_PTR("invalid subpixel order", __func__, NULL);
3991
3992 direction =
3993 (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
3994 ? L_HORIZ : L_VERT;
3996 if (direction == L_HORIZ)
3997 pix2 = pixScale(pix1, 3.0f * scalex, scaley);
3998 else /* L_VERT */
3999 pix2 = pixScale(pix1, scalex, 3.0f * scaley);
4000
4001 pixGetDimensions(pix2, &w, &h, NULL);
4002 wd = (direction == L_HORIZ) ? w / 3 : w;
4003 hd = (direction == L_VERT) ? h / 3 : h;
4004 pixd = pixCreate(wd, hd, 32);
4005 datad = pixGetData(pixd);
4006 wpld = pixGetWpl(pixd);
4007 datat = pixGetData(pix2);
4008 wplt = pixGetWpl(pix2);
4009 if (direction == L_HORIZ) {
4010 for (i = 0; i < hd; i++) {
4011 linet = datat + i * wplt;
4012 lined = datad + i * wpld;
4013 for (j = 0; j < wd; j++) {
4014 rval = GET_DATA_BYTE(linet, 3 * j);
4015 gval = GET_DATA_BYTE(linet, 3 * j + 1);
4016 bval = GET_DATA_BYTE(linet, 3 * j + 2);
4017 if (order == L_SUBPIXEL_ORDER_RGB)
4018 composeRGBPixel(rval, gval, bval, &lined[j]);
4019 else /* order BGR */
4020 composeRGBPixel(bval, gval, rval, &lined[j]);
4021 }
4022 }
4023 } else { /* L_VERT */
4024 for (i = 0; i < hd; i++) {
4025 linet = datat + 3 * i * wplt;
4026 lined = datad + i * wpld;
4027 for (j = 0; j < wd; j++) {
4028 rval = GET_DATA_BYTE(linet, j);
4029 gval = GET_DATA_BYTE(linet + wplt, j);
4030 bval = GET_DATA_BYTE(linet + 2 * wplt, j);
4031 if (order == L_SUBPIXEL_ORDER_VRGB)
4032 composeRGBPixel(rval, gval, bval, &lined[j]);
4033 else /* order VBGR */
4034 composeRGBPixel(bval, gval, rval, &lined[j]);
4035 }
4036 }
4037 }
4038
4039 pixDestroy(&pix1);
4040 pixDestroy(&pix2);
4041 return pixd;
4042}
4043
4044
4072PIX *
4074 l_float32 scalex,
4075 l_float32 scaley,
4076 l_int32 order)
4077{
4078l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
4079l_uint32 *datat, *datad, *linet, *lined;
4080PIX *pix1, *pix2, *pixd;
4081PIXCMAP *cmap;
4082
4083 if (!pixs)
4084 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
4085 d = pixGetDepth(pixs);
4086 cmap = pixGetColormap(pixs);
4087 if (d != 32 && !cmap)
4088 return (PIX *)ERROR_PTR("pix not 32 bpp & not cmapped", __func__, NULL);
4089 if (scalex <= 0.0 || scaley <= 0.0)
4090 return (PIX *)ERROR_PTR("scale factors must be > 0", __func__, NULL);
4091 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
4092 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
4093 return (PIX *)ERROR_PTR("invalid subpixel order", __func__, NULL);
4094
4095 direction =
4096 (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
4097 ? L_HORIZ : L_VERT;
4099 if (direction == L_HORIZ)
4100 pix2 = pixScale(pix1, 3.0f * scalex, scaley);
4101 else /* L_VERT */
4102 pix2 = pixScale(pix1, scalex, 3.0f * scaley);
4103
4104 pixGetDimensions(pix2, &w, &h, NULL);
4105 wd = (direction == L_HORIZ) ? w / 3 : w;
4106 hd = (direction == L_VERT) ? h / 3 : h;
4107 pixd = pixCreate(wd, hd, 32);
4108 pixCopyInputFormat(pixd, pixs);
4109 datad = pixGetData(pixd);
4110 wpld = pixGetWpl(pixd);
4111 datat = pixGetData(pix2);
4112 wplt = pixGetWpl(pix2);
4113 if (direction == L_HORIZ) {
4114 for (i = 0; i < hd; i++) {
4115 linet = datat + i * wplt;
4116 lined = datad + i * wpld;
4117 for (j = 0; j < wd; j++) {
4118 if (order == L_SUBPIXEL_ORDER_RGB) {
4119 extractRGBValues(linet[3 * j], &rval, NULL, NULL);
4120 extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4121 extractRGBValues(linet[3 * j + 2], NULL, NULL, &bval);
4122 } else { /* order BGR */
4123 extractRGBValues(linet[3 * j], NULL, NULL, &bval);
4124 extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4125 extractRGBValues(linet[3 * j + 2], &rval, NULL, NULL);
4126 }
4127 composeRGBPixel(rval, gval, bval, &lined[j]);
4128 }
4129 }
4130 } else { /* L_VERT */
4131 for (i = 0; i < hd; i++) {
4132 linet = datat + 3 * i * wplt;
4133 lined = datad + i * wpld;
4134 for (j = 0; j < wd; j++) {
4135 if (order == L_SUBPIXEL_ORDER_VRGB) {
4136 extractRGBValues(linet[j], &rval, NULL, NULL);
4137 extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4138 extractRGBValues((linet + 2 * wplt)[j], NULL, NULL, &bval);
4139 } else { /* order VBGR */
4140 extractRGBValues(linet[j], NULL, NULL, &bval);
4141 extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4142 extractRGBValues((linet + 2 * wplt)[j], &rval, NULL, NULL);
4143 }
4144 composeRGBPixel(rval, gval, bval, &lined[j]);
4145 }
4146 }
4147 }
4148
4149 if (pixGetSpp(pixs) == 4)
4150 pixScaleAndTransferAlpha(pixd, pixs, scalex, scaley);
4151
4152 pixDestroy(&pix1);
4153 pixDestroy(&pix2);
4154 return pixd;
4155}
4156
4157
4158/*---------------------------------------------------------------------*
4159 * Setting neutral point for min/max boost conversion to gray *
4160 *---------------------------------------------------------------------*/
4173void
4175{
4176 if (val <= 0) {
4177 L_ERROR("invalid reference value for neutral boost\n", __func__);
4178 return;
4179 }
4180 var_NEUTRAL_BOOST_VAL = val;
4181}
PIX * pixBackgroundNormSimple(PIX *pixs, PIX *pixim, PIX *pixg)
pixBackgroundNormSimple()
Definition adaptmap.c:263
#define GET_DATA_QBIT(pdata, n)
#define GET_DATA_TWO_BYTES(pdata, n)
#define SET_DATA_BIT(pdata, n)
#define SET_DATA_DIBIT(pdata, n, val)
#define SET_DATA_TWO_BYTES(pdata, n, val)
#define GET_DATA_BYTE(pdata, n)
#define GET_DATA_DIBIT(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
#define GET_DATA_BIT(pdata, n)
#define SET_DATA_QBIT(pdata, n, val)
static const l_float32 L_BLUE_WEIGHT
Definition pix.h:372
@ COLOR_BLUE
Definition pix.h:330
@ COLOR_RED
Definition pix.h:328
@ COLOR_GREEN
Definition pix.h:329
@ L_SELECT_MAX
Definition pix.h:619
@ L_SELECT_GREEN
Definition pix.h:616
@ L_SELECT_SATURATION
Definition pix.h:622
@ L_SELECT_BLUE
Definition pix.h:617
@ L_SELECT_AVERAGE
Definition pix.h:620
@ L_SELECT_MIN
Definition pix.h:618
@ L_SELECT_HUE
Definition pix.h:621
@ L_SELECT_WEIGHTED
Definition pix.h:623
@ L_SELECT_RED
Definition pix.h:615
@ L_SELECT_IF_LTE
Definition pix.h:577
@ L_SELECT_IF_LT
Definition pix.h:575
@ L_SELECT_IF_GT
Definition pix.h:576
@ L_SELECT_IF_GTE
Definition pix.h:578
static const l_float32 L_RED_WEIGHT
Definition pix.h:370
@ REMOVE_CMAP_TO_FULL_COLOR
Definition pix.h:382
@ REMOVE_CMAP_TO_GRAYSCALE
Definition pix.h:381
@ REMOVE_CMAP_WITH_ALPHA
Definition pix.h:383
@ REMOVE_CMAP_BASED_ON_SRC
Definition pix.h:384
@ REMOVE_CMAP_TO_BINARY
Definition pix.h:380
@ L_COPY
Definition pix.h:505
@ L_CLONE
Definition pix.h:506
@ L_CLIP_TO_FFFF
Definition pix.h:647
@ L_MS_TWO_BYTES
Definition pix.h:646
@ L_CLIP_TO_FF
Definition pix.h:644
@ L_LS_TWO_BYTES
Definition pix.h:645
@ L_MS_BYTE
Definition pix.h:642
@ L_AUTO_BYTE
Definition pix.h:643
@ L_LS_BYTE
Definition pix.h:641
@ L_SUBPIXEL_ORDER_VRGB
Definition pix.h:974
@ L_SUBPIXEL_ORDER_BGR
Definition pix.h:973
@ L_SUBPIXEL_ORDER_RGB
Definition pix.h:972
@ L_SUBPIXEL_ORDER_VBGR
Definition pix.h:975
@ L_GREATER_THAN_ZERO
Definition pix.h:1074
static const l_float32 L_GREEN_WEIGHT
Definition pix.h:371
PIX * pixConvertGrayToColormap8(PIX *pixs, l_int32 mindepth)
pixConvertGrayToColormap8()
Definition pixconv.c:1276
PIX * pixConvert1To16(PIX *pixd, PIX *pixs, l_uint16 val0, l_uint16 val1)
pixConvert1To16()
Definition pixconv.c:1936
PIX * pixConvert32To16(PIX *pixs, l_int32 type)
pixConvert32To16()
Definition pixconv.c:3562
l_ok pixQuantizeIfFewColors(PIX *pixs, l_int32 maxcolors, l_int32 mingraycolors, l_int32 octlevel, PIX **ppixd)
pixQuantizeIfFewColors()
Definition pixconv.c:1627
PIX * pixConvertRGBToBinaryArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc, l_int32 thresh, l_int32 relation)
pixConvertRGBToBinaryArb()
Definition pixconv.c:1168
PIX * pixConvert8To4(PIX *pix)
pixConvert8To4()
Definition pixconv.c:2845
PIX * pixConvert8To16(PIX *pixs, l_int32 leftshift)
pixConvert8To16()
Definition pixconv.c:2627
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:3511
PIX * pixConvertTo4(PIX *pixs)
pixConvertTo4()
Definition pixconv.c:2795
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition pixconv.c:732
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition pixconv.c:3057
PIX * pixConvertRGBToGrayMinMax(PIX *pixs, l_int32 type)
pixConvertRGBToGrayMinMax()
Definition pixconv.c:947
PIX * pixConvert8To32(PIX *pixs)
pixConvert8To32()
Definition pixconv.c:3334
PIX * pixConvertTo2(PIX *pixs)
pixConvertTo2()
Definition pixconv.c:2691
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition pixconv.c:3402
PIX * pixConvertGrayToFalseColor(PIX *pixs, l_float32 gamma)
pixConvertGrayToFalseColor()
Definition pixconv.c:1820
PIX * pixConvertTo8BySampling(PIX *pixs, l_int32 factor, l_int32 cmapflag)
pixConvertTo8BySampling()
Definition pixconv.c:3126
l_ok pixAddGrayColormap8(PIX *pixs)
pixAddGrayColormap8()
Definition pixconv.c:616
PIX * pixConvertRGBToGrayFast(PIX *pixs)
pixConvertRGBToGrayFast()
Definition pixconv.c:891
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition pixconv.c:324
PIX * pixConvert2To8(PIX *pixs, l_uint8 val0, l_uint8 val1, l_uint8 val2, l_uint8 val3, l_int32 cmapflag)
pixConvert2To8()
Definition pixconv.c:2434
PIX * pixConvertTo1Adaptive(PIX *pixs)
pixConvertTo1Adaptive()
Definition pixconv.c:2897
PIX * pixConvertLossless(PIX *pixs, l_int32 d)
pixConvertLossless()
Definition pixconv.c:3736
PIX * pixAddMinimalGrayColormap8(PIX *pixs)
pixAddMinimalGrayColormap8()
Definition pixconv.c:645
PIX * pixConvert1To8Cmap(PIX *pixs)
pixConvert1To8Cmap()
Definition pixconv.c:2304
PIX * pixConvert1To32(PIX *pixd, PIX *pixs, l_uint32 val0, l_uint32 val1)
pixConvert1To32()
Definition pixconv.c:2008
PIX * pixConvertGrayToColormap(PIX *pixs)
pixConvertGrayToColormap()
Definition pixconv.c:1223
PIX * pixConvert1To2Cmap(PIX *pixs)
pixConvert1To2Cmap()
Definition pixconv.c:2069
PIX * pixConvert16To8(PIX *pixs, l_int32 type)
pixConvert16To8()
Definition pixconv.c:1726
PIX * pixConvertRGBToColormap(PIX *pixs, l_int32 ditherflag)
pixConvertRGBToColormap()
Definition pixconv.c:1456
PIX * pixConvertToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertToSubpixelRGB()
Definition pixconv.c:3902
PIX * pixConvertTo8Colormap(PIX *pixs, l_int32 dither)
pixConvertTo8Colormap()
Definition pixconv.c:3168
PIX * pixConvert1To4Cmap(PIX *pixs)
pixConvert1To4Cmap()
Definition pixconv.c:2187
PIX * pixConvertRGBToGrayGeneral(PIX *pixs, l_int32 type, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGrayGeneral()
Definition pixconv.c:756
PIX * pixConvertTo32BySampling(PIX *pixs, l_int32 factor)
pixConvertTo32BySampling()
Definition pixconv.c:3301
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
Definition pixconv.c:3463
PIX * pixConvert1To4(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To4()
Definition pixconv.c:2228
PIX * pixConvertTo16(PIX *pixs)
pixConvertTo16()
Definition pixconv.c:3201
PIX * pixConvertRGBToGrayArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc)
pixConvertRGBToGrayArb()
Definition pixconv.c:1108
PIX * pixConvertGrayToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertGrayToSubpixelRGB()
Definition pixconv.c:3970
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition pixconv.c:3825
PIX * pixConvert1To2(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To2()
Definition pixconv.c:2110
PIX * pixConvertRGBToGraySatBoost(PIX *pixs, l_int32 refval)
pixConvertRGBToGraySatBoost()
Definition pixconv.c:1032
PIX * pixConvertRGBToGray(PIX *pixs, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGray()
Definition pixconv.c:815
PIX * pixConvert4To8(PIX *pixs, l_int32 cmapflag)
pixConvert4To8()
Definition pixconv.c:2544
PIX * pixConvertCmapTo1(PIX *pixs)
pixConvertCmapTo1()
Definition pixconv.c:1518
PIX * pixAddAlphaTo1bpp(PIX *pixd, PIX *pixs)
pixAddAlphaTo1bpp()
Definition pixconv.c:3696
PIX * pixConvert8To2(PIX *pix)
pixConvert8To2()
Definition pixconv.c:2741
PIX * pixRemoveAlpha(PIX *pixs)
pixRemoveAlpha()
Definition pixconv.c:3661
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition pixconv.c:3248
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition pixconv.c:1371
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition pixconv.c:2954
PIX * pixConvertTo1BySampling(PIX *pixs, l_int32 factor, l_int32 threshold)
pixConvertTo1BySampling()
Definition pixconv.c:3008
PIX * pixConvertColorToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertColorToSubpixelRGB()
Definition pixconv.c:4073
PIX * pixRemoveColormapGeneral(PIX *pixs, l_int32 type, l_int32 ifnocmap)
pixRemoveColormapGeneral()
Definition pixconv.c:276
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition pixconv.c:2345
void l_setNeutralBoostVal(l_int32 val)
l_setNeutralBoostVal()
Definition pixconv.c:4174
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
pixUnpackBinary()
Definition pixconv.c:1873
PIX * pixConvert32To8(PIX *pixs, l_int32 type16, l_int32 type8)
pixConvert32To8()
Definition pixconv.c:3624