Leptonica 1.84.1
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 *---------------------------------------------------------------------------*/
2894PIX *
2896{
2897l_int32 d, color0, color1, rval, gval, bval;
2898PIX *pix1, *pix2, *pixd;
2899PIXCMAP *cmap;
2900
2901 if (!pixs)
2902 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2903 d = pixGetDepth(pixs);
2904 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
2905 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", __func__, NULL);
2906
2907 cmap = pixGetColormap(pixs);
2908 if (d == 1) {
2909 if (!cmap) {
2910 return pixCopy(NULL, pixs);
2911 } else { /* strip the colormap off, and invert if reasonable
2912 for standard binary photometry. */
2913 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
2914 color0 = rval + gval + bval;
2915 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
2916 color1 = rval + gval + bval;
2917 pixd = pixCopy(NULL, pixs);
2918 pixDestroyColormap(pixd);
2919 if (color1 > color0)
2920 pixInvert(pixd, pixd);
2921 return pixd;
2922 }
2923 }
2924
2925 /* For all other depths, use 8 bpp as an intermediary */
2926 pix1 = pixConvertTo8(pixs, FALSE);
2927 pix2 = pixBackgroundNormSimple(pix1, NULL, NULL);
2928 pixd = pixThresholdToBinary(pix2, 180);
2929 pixDestroy(&pix1);
2930 pixDestroy(&pix2);
2931 return pixd;
2932}
2933
2934
2951PIX *
2953 l_int32 threshold)
2954{
2955l_int32 d, color0, color1, rval, gval, bval;
2956PIX *pixg, *pixd;
2957PIXCMAP *cmap;
2958
2959 if (!pixs)
2960 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2961 d = pixGetDepth(pixs);
2962 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
2963 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", __func__, NULL);
2964
2965 cmap = pixGetColormap(pixs);
2966 if (d == 1) {
2967 if (!cmap) {
2968 return pixCopy(NULL, pixs);
2969 } else { /* strip the colormap off, and invert if reasonable
2970 for standard binary photometry. */
2971 pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
2972 color0 = rval + gval + bval;
2973 pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
2974 color1 = rval + gval + bval;
2975 pixd = pixCopy(NULL, pixs);
2976 pixDestroyColormap(pixd);
2977 if (color1 > color0)
2978 pixInvert(pixd, pixd);
2979 return pixd;
2980 }
2981 }
2982
2983 /* For all other depths, use 8 bpp as an intermediary */
2984 pixg = pixConvertTo8(pixs, FALSE);
2985 pixd = pixThresholdToBinary(pixg, threshold);
2986 pixDestroy(&pixg);
2987 return pixd;
2988}
2989
2990
3005PIX *
3007 l_int32 factor,
3008 l_int32 threshold)
3009{
3010l_float32 scalefactor;
3011PIX *pixt, *pixd;
3012
3013 if (!pixs)
3014 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3015 if (factor < 1)
3016 return (PIX *)ERROR_PTR("factor must be >= 1", __func__, NULL);
3017
3018 scalefactor = 1.f / (l_float32)factor;
3019 pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3020 pixd = pixConvertTo1(pixt, threshold);
3021 pixDestroy(&pixt);
3022 return pixd;
3023}
3024
3025
3026/*---------------------------------------------------------------------------*
3027 * Top-level conversion to 8 bpp *
3028 *---------------------------------------------------------------------------*/
3054PIX *
3056 l_int32 cmapflag)
3057{
3058l_int32 d;
3059PIX *pix1, *pixd;
3060PIXCMAP *cmap;
3061
3062 if (!pixs)
3063 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3064 d = pixGetDepth(pixs);
3065 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32)
3066 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,24,32}", __func__, NULL);
3067
3068 if (d == 1) {
3069 if (cmapflag)
3070 return pixConvert1To8Cmap(pixs);
3071 else
3072 return pixConvert1To8(NULL, pixs, 255, 0);
3073 } else if (d == 2) {
3074 return pixConvert2To8(pixs, 0, 85, 170, 255, cmapflag);
3075 } else if (d == 4) {
3076 return pixConvert4To8(pixs, cmapflag);
3077 } else if (d == 8) {
3078 cmap = pixGetColormap(pixs);
3079 if ((cmap && cmapflag) || (!cmap && !cmapflag)) {
3080 return pixCopy(NULL, pixs);
3081 } else if (cmap) { /* !cmapflag */
3083 } else { /* !cmap && cmapflag; add colormap to pixd */
3084 pixd = pixCopy(NULL, pixs);
3085 pixAddGrayColormap8(pixd);
3086 return pixd;
3087 }
3088 } else if (d == 16) {
3089 pixd = pixConvert16To8(pixs, L_MS_BYTE);
3090 if (cmapflag)
3091 pixAddGrayColormap8(pixd);
3092 return pixd;
3093 } else if (d == 24) {
3094 pix1 = pixConvert24To32(pixs);
3095 pixd = pixConvertRGBToLuminance(pix1);
3096 if (cmapflag)
3097 pixAddGrayColormap8(pixd);
3098 pixDestroy(&pix1);
3099 return pixd;
3100 } else { /* d == 32 */
3101 pixd = pixConvertRGBToLuminance(pixs);
3102 if (cmapflag)
3103 pixAddGrayColormap8(pixd);
3104 return pixd;
3105 }
3106}
3107
3108
3123PIX *
3125 l_int32 factor,
3126 l_int32 cmapflag)
3127{
3128l_float32 scalefactor;
3129PIX *pixt, *pixd;
3130
3131 if (!pixs)
3132 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3133 if (factor < 1)
3134 return (PIX *)ERROR_PTR("factor must be >= 1", __func__, NULL);
3135
3136 scalefactor = 1.f / (l_float32)factor;
3137 pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3138 pixd = pixConvertTo8(pixt, cmapflag);
3139
3140 pixDestroy(&pixt);
3141 return pixd;
3142}
3143
3144
3165PIX *
3167 l_int32 dither)
3168{
3169l_int32 d;
3170
3171 if (!pixs)
3172 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3173 d = pixGetDepth(pixs);
3174 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
3175 return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,32}", __func__, NULL);
3176
3177 if (d != 32)
3178 return pixConvertTo8(pixs, 1);
3179
3180 return pixConvertRGBToColormap(pixs, dither);
3181}
3182
3183
3184/*---------------------------------------------------------------------------*
3185 * Top-level conversion to 16 bpp *
3186 *---------------------------------------------------------------------------*/
3198PIX *
3200{
3201l_int32 d;
3202
3203 if (!pixs)
3204 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3205
3206 d = pixGetDepth(pixs);
3207 if (d == 1)
3208 return pixConvert1To16(NULL, pixs, 0xffff, 0);
3209 else if (d == 8)
3210 return pixConvert8To16(pixs, 8);
3211 else
3212 return (PIX *)ERROR_PTR("src depth not 1 or 8 bpp", __func__, NULL);
3213}
3214
3215
3216
3217/*---------------------------------------------------------------------------*
3218 * Top-level conversion to 32 bpp *
3219 *---------------------------------------------------------------------------*/
3245PIX *
3247{
3248l_int32 d;
3249PIX *pix1, *pixd;
3250
3251 if (!pixs)
3252 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3253
3254 d = pixGetDepth(pixs);
3255 if (d == 1) {
3256 return pixConvert1To32(NULL, pixs, 0xffffffff, 0);
3257 } else if (d == 2) {
3258 pix1 = pixConvert2To8(pixs, 0, 85, 170, 255, TRUE);
3259 pixd = pixConvert8To32(pix1);
3260 pixDestroy(&pix1);
3261 return pixd;
3262 } else if (d == 4) {
3263 pix1 = pixConvert4To8(pixs, TRUE);
3264 pixd = pixConvert8To32(pix1);
3265 pixDestroy(&pix1);
3266 return pixd;
3267 } else if (d == 8) {
3268 return pixConvert8To32(pixs);
3269 } else if (d == 16) {
3270 pix1 = pixConvert16To8(pixs, L_MS_BYTE);
3271 pixd = pixConvert8To32(pix1);
3272 pixDestroy(&pix1);
3273 return pixd;
3274 } else if (d == 24) {
3275 return pixConvert24To32(pixs);
3276 } else if (d == 32) {
3277 return pixCopy(NULL, pixs);
3278 } else {
3279 return (PIX *)ERROR_PTR("depth not 1, 2, 4, 8, 16, 32 bpp",
3280 __func__, NULL);
3281 }
3282}
3283
3284
3298PIX *
3300 l_int32 factor)
3301{
3302l_float32 scalefactor;
3303PIX *pix1, *pixd;
3304
3305 if (!pixs)
3306 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3307 if (factor < 1)
3308 return (PIX *)ERROR_PTR("factor must be >= 1", __func__, NULL);
3309
3310 scalefactor = 1.f / (l_float32)factor;
3311 pix1 = pixScaleBySampling(pixs, scalefactor, scalefactor);
3312 pixd = pixConvertTo32(pix1);
3313
3314 pixDestroy(&pix1);
3315 return pixd;
3316}
3317
3318
3331PIX *
3333{
3334l_int32 i, j, w, h, wpls, wpld, val;
3335l_uint32 *datas, *datad, *lines, *lined;
3336l_uint32 *tab;
3337PIX *pixd;
3338
3339 if (!pixs)
3340 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3341 if (pixGetDepth(pixs) != 8)
3342 return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
3343
3344 if (pixGetColormap(pixs))
3346
3347 pixGetDimensions(pixs, &w, &h, NULL);
3348 datas = pixGetData(pixs);
3349 wpls = pixGetWpl(pixs);
3350 if ((pixd = pixCreate(w, h, 32)) == NULL)
3351 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
3352 pixCopyResolution(pixd, pixs);
3353 pixCopyInputFormat(pixd, pixs);
3354 datad = pixGetData(pixd);
3355 wpld = pixGetWpl(pixd);
3356
3357 /* Replication table gray --> rgb */
3358 tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
3359 for (i = 0; i < 256; i++)
3360 tab[i] = ((l_uint32)i << 24) | (i << 16) | (i << 8);
3361
3362 /* Replicate 1 --> 4 bytes (alpha byte not set) */
3363 for (i = 0; i < h; i++) {
3364 lines = datas + i * wpls;
3365 lined = datad + i * wpld;
3366 for (j = 0; j < w; j++) {
3367 val = GET_DATA_BYTE(lines, j);
3368 lined[j] = tab[val];
3369 }
3370 }
3371
3372 LEPT_FREE(tab);
3373 return pixd;
3374}
3375
3376
3377/*---------------------------------------------------------------------------*
3378 * Top-level conversion to 8 or 32 bpp, without colormap *
3379 *---------------------------------------------------------------------------*/
3399PIX *
3401 l_int32 copyflag,
3402 l_int32 warnflag)
3403{
3404l_int32 d;
3405PIX *pixd;
3406
3407 if (!pixs)
3408 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3409 if (copyflag != L_CLONE && copyflag != L_COPY)
3410 return (PIX *)ERROR_PTR("invalid copyflag", __func__, NULL);
3411
3412 d = pixGetDepth(pixs);
3413 if (pixGetColormap(pixs)) {
3414 if (warnflag) L_WARNING("pix has colormap; removing\n", __func__);
3416 } else if (d == 8 || d == 32) {
3417 if (copyflag == L_CLONE)
3418 pixd = pixClone(pixs);
3419 else /* copyflag == L_COPY */
3420 pixd = pixCopy(NULL, pixs);
3421 } else {
3422 pixd = pixConvertTo8(pixs, 0);
3423 }
3424
3425 /* Sanity check on result */
3426 d = pixGetDepth(pixd);
3427 if (d != 8 && d != 32) {
3428 pixDestroy(&pixd);
3429 return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", __func__, NULL);
3430 }
3431
3432 return pixd;
3433}
3434
3435
3436/*---------------------------------------------------------------------------*
3437 * Conversion between 24 bpp and 32 bpp rgb *
3438 *---------------------------------------------------------------------------*/
3460PIX *
3462{
3463l_uint8 *lines;
3464l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3465l_uint32 pixel;
3466l_uint32 *datas, *datad, *lined;
3467PIX *pixd;
3468
3469 if (!pixs)
3470 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3471 pixGetDimensions(pixs, &w, &h, &d);
3472 if (d != 24)
3473 return (PIX *)ERROR_PTR("pixs not 24 bpp", __func__, NULL);
3474
3475 pixd = pixCreate(w, h, 32);
3476 datas = pixGetData(pixs);
3477 datad = pixGetData(pixd);
3478 wpls = pixGetWpl(pixs);
3479 wpld = pixGetWpl(pixd);
3480 for (i = 0; i < h; i++) {
3481 lines = (l_uint8 *)(datas + i * wpls);
3482 lined = datad + i * wpld;
3483 for (j = 0; j < w; j++) {
3484 rval = *lines++;
3485 gval = *lines++;
3486 bval = *lines++;
3487 composeRGBPixel(rval, gval, bval, &pixel);
3488 lined[j] = pixel;
3489 }
3490 }
3491 pixCopyResolution(pixd, pixs);
3492 pixCopyInputFormat(pixd, pixs);
3493 return pixd;
3494}
3495
3496
3508PIX *
3510{
3511l_uint8 *rgbdata8;
3512l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3513l_uint32 *datas, *lines, *rgbdata;
3514PIX *pixd;
3515
3516 if (!pixs)
3517 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3518 pixGetDimensions(pixs, &w, &h, &d);
3519 if (d != 32)
3520 return (PIX *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
3521
3522 datas = pixGetData(pixs);
3523 wpls = pixGetWpl(pixs);
3524 pixd = pixCreate(w, h, 24);
3525 rgbdata = pixGetData(pixd);
3526 wpld = pixGetWpl(pixd);
3527 for (i = 0; i < h; i++) {
3528 lines = datas + i * wpls;
3529 rgbdata8 = (l_uint8 *)(rgbdata + i * wpld);
3530 for (j = 0; j < w; j++) {
3531 extractRGBValues(lines[j], &rval, &gval, &bval);
3532 *rgbdata8++ = rval;
3533 *rgbdata8++ = gval;
3534 *rgbdata8++ = bval;
3535 }
3536 }
3537 pixCopyResolution(pixd, pixs);
3538 pixCopyInputFormat(pixd, pixs);
3539 return pixd;
3540}
3541
3542
3543/*---------------------------------------------------------------------------*
3544 * Conversion between 32 bpp (1 spp) and 16 or 8 bpp *
3545 *---------------------------------------------------------------------------*/
3559PIX *
3561 l_int32 type)
3562{
3563l_uint16 dword;
3564l_int32 w, h, i, j, wpls, wpld;
3565l_uint32 sword;
3566l_uint32 *datas, *lines, *datad, *lined;
3567PIX *pixd;
3568
3569 if (!pixs || pixGetDepth(pixs) != 32)
3570 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
3571 if (type != L_LS_TWO_BYTES && type != L_MS_TWO_BYTES &&
3572 type != L_CLIP_TO_FFFF)
3573 return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
3574
3575 pixGetDimensions(pixs, &w, &h, NULL);
3576 if ((pixd = pixCreate(w, h, 16)) == NULL)
3577 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
3578 pixCopyResolution(pixd, pixs);
3579 pixCopyInputFormat(pixd, pixs);
3580 wpls = pixGetWpl(pixs);
3581 datas = pixGetData(pixs);
3582 wpld = pixGetWpl(pixd);
3583 datad = pixGetData(pixd);
3584
3585 for (i = 0; i < h; i++) {
3586 lines = datas + i * wpls;
3587 lined = datad + i * wpld;
3588 if (type == L_LS_TWO_BYTES) {
3589 for (j = 0; j < wpls; j++) {
3590 sword = *(lines + j);
3591 dword = sword & 0xffff;
3592 SET_DATA_TWO_BYTES(lined, j, dword);
3593 }
3594 } else if (type == L_MS_TWO_BYTES) {
3595 for (j = 0; j < wpls; j++) {
3596 sword = *(lines + j);
3597 dword = sword >> 16;
3598 SET_DATA_TWO_BYTES(lined, j, dword);
3599 }
3600 } else { /* type == L_CLIP_TO_FFFF */
3601 for (j = 0; j < wpls; j++) {
3602 sword = *(lines + j);
3603 dword = (sword >> 16) ? 0xffff : (sword & 0xffff);
3604 SET_DATA_TWO_BYTES(lined, j, dword);
3605 }
3606 }
3607 }
3608
3609 return pixd;
3610}
3611
3612
3621PIX *
3623 l_int32 type16,
3624 l_int32 type8)
3625{
3626PIX *pix1, *pixd;
3627
3628 if (!pixs || pixGetDepth(pixs) != 32)
3629 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
3630 if (type16 != L_LS_TWO_BYTES && type16 != L_MS_TWO_BYTES &&
3631 type16 != L_CLIP_TO_FFFF)
3632 return (PIX *)ERROR_PTR("invalid type16", __func__, NULL);
3633 if (type8 != L_LS_BYTE && type8 != L_MS_BYTE && type8 != L_CLIP_TO_FF)
3634 return (PIX *)ERROR_PTR("invalid type8", __func__, NULL);
3635
3636 pix1 = pixConvert32To16(pixs, type16);
3637 pixd = pixConvert16To8(pix1, type8);
3638 pixDestroy(&pix1);
3639 return pixd;
3640}
3641
3642
3643/*---------------------------------------------------------------------------*
3644 * Removal of alpha component by blending with white background *
3645 *---------------------------------------------------------------------------*/
3658PIX *
3660{
3661 if (!pixs)
3662 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3663
3664 if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4)
3665 return pixAlphaBlendUniform(pixs, 0xffffff00);
3666 else
3667 return pixClone(pixs);
3668}
3669
3670
3671/*---------------------------------------------------------------------------*
3672 * Addition of alpha component to 1 bpp *
3673 *---------------------------------------------------------------------------*/
3693PIX *
3695 PIX *pixs)
3696{
3697PIXCMAP *cmap;
3698
3699 if (!pixs || (pixGetDepth(pixs) != 1))
3700 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", __func__, NULL);
3701 if (pixd && (pixd != pixs))
3702 return (PIX *)ERROR_PTR("pixd defined but != pixs", __func__, NULL);
3703
3704 pixd = pixCopy(pixd, pixs);
3705 cmap = pixcmapCreate(1);
3706 pixSetColormap(pixd, cmap);
3707 pixcmapAddRGBA(cmap, 255, 255, 255, 0); /* 0 ==> white + transparent */
3708 pixcmapAddRGBA(cmap, 0, 0, 0, 255); /* 1 ==> black + opaque */
3709 return pixd;
3710}
3711
3712
3713/*---------------------------------------------------------------------------*
3714 * Lossless depth conversion (unpacking) *
3715 *---------------------------------------------------------------------------*/
3733PIX *
3735 l_int32 d)
3736{
3737l_int32 w, h, ds, wpls, wpld, i, j, val;
3738l_uint32 *datas, *datad, *lines, *lined;
3739PIX *pixd;
3740
3741 if (!pixs)
3742 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3743 if (pixGetColormap(pixs))
3744 return (PIX *)ERROR_PTR("pixs has colormap", __func__, NULL);
3745 if (d != 2 && d != 4 && d != 8)
3746 return (PIX *)ERROR_PTR("invalid dest depth", __func__, NULL);
3747
3748 pixGetDimensions(pixs, &w, &h, &ds);
3749 if (d < ds)
3750 return (PIX *)ERROR_PTR("depth > d", __func__, NULL);
3751 else if (d == ds)
3752 return pixCopy(NULL, pixs);
3753
3754 if ((pixd = pixCreate(w, h, d)) == NULL)
3755 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
3756 pixCopyResolution(pixd, pixs);
3757 pixCopyInputFormat(pixd, pixs);
3758
3759 /* Unpack the bits */
3760 datas = pixGetData(pixs);
3761 wpls = pixGetWpl(pixs);
3762 datad = pixGetData(pixd);
3763 wpld = pixGetWpl(pixd);
3764 for (i = 0; i < h; i++) {
3765 lines = datas + i * wpls;
3766 lined = datad + i * wpld;
3767 switch (ds)
3768 {
3769 case 1:
3770 for (j = 0; j < w; j++) {
3771 val = GET_DATA_BIT(lines, j);
3772 if (d == 8)
3773 SET_DATA_BYTE(lined, j, val);
3774 else if (d == 4)
3775 SET_DATA_QBIT(lined, j, val);
3776 else /* d == 2 */
3777 SET_DATA_DIBIT(lined, j, val);
3778 }
3779 break;
3780 case 2:
3781 for (j = 0; j < w; j++) {
3782 val = GET_DATA_DIBIT(lines, j);
3783 if (d == 8)
3784 SET_DATA_BYTE(lined, j, val);
3785 else /* d == 4 */
3786 SET_DATA_QBIT(lined, j, val);
3787 }
3788 break;
3789 case 4:
3790 for (j = 0; j < w; j++) {
3791 val = GET_DATA_DIBIT(lines, j);
3792 SET_DATA_BYTE(lined, j, val);
3793 }
3794 break;
3795 }
3796 }
3797
3798 return pixd;
3799}
3800
3801
3802/*---------------------------------------------------------------------------*
3803 * Conversion for printing in PostScript *
3804 *---------------------------------------------------------------------------*/
3822PIX *
3824{
3825l_int32 d;
3826PIX *pixd;
3827PIXCMAP *cmap;
3828
3829 if (!pixs)
3830 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3831
3832 cmap = pixGetColormap(pixs);
3833 d = pixGetDepth(pixs);
3834 switch (d)
3835 {
3836 case 1:
3837 case 32:
3838 pixd = pixClone(pixs);
3839 break;
3840 case 2:
3841 if (cmap)
3843 else
3844 pixd = pixConvert2To8(pixs, 0, 0x55, 0xaa, 0xff, FALSE);
3845 break;
3846 case 4:
3847 if (cmap)
3849 else
3850 pixd = pixConvert4To8(pixs, FALSE);
3851 break;
3852 case 8:
3854 break;
3855 case 16:
3856 pixd = pixConvert16To8(pixs, L_MS_BYTE);
3857 break;
3858 default:
3859 lept_stderr("depth not in {1, 2, 4, 8, 16, 32}");
3860 return NULL;
3861 }
3862
3863 return pixd;
3864}
3865
3866
3867/*---------------------------------------------------------------------------*
3868 * Scaling conversion to subpixel RGB *
3869 *---------------------------------------------------------------------------*/
3899PIX *
3901 l_float32 scalex,
3902 l_float32 scaley,
3903 l_int32 order)
3904{
3905l_int32 d;
3906PIX *pix1, *pixd;
3907PIXCMAP *cmap;
3908
3909 if (!pixs)
3910 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3911 d = pixGetDepth(pixs);
3912 cmap = pixGetColormap(pixs);
3913 if (d != 8 && d != 32 && !cmap)
3914 return (PIX *)ERROR_PTR("pix not 8 or 32 bpp and not cmapped",
3915 __func__, NULL);
3916 if (scalex <= 0.0 || scaley <= 0.0)
3917 return (PIX *)ERROR_PTR("scale factors must be > 0", __func__, NULL);
3918 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
3919 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
3920 return (PIX *)ERROR_PTR("invalid subpixel order", __func__, NULL);
3921 if ((pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC)) == NULL)
3922 return (PIX *)ERROR_PTR("pix1 not made", __func__, NULL);
3923
3924 d = pixGetDepth(pix1);
3925 pixd = NULL;
3926 if (d == 8)
3927 pixd = pixConvertGrayToSubpixelRGB(pix1, scalex, scaley, order);
3928 else if (d == 32)
3929 pixd = pixConvertColorToSubpixelRGB(pix1, scalex, scaley, order);
3930 else
3931 L_ERROR("invalid depth %d\n", __func__, d);
3932
3933 pixDestroy(&pix1);
3934 return pixd;
3935}
3936
3937
3967PIX *
3969 l_float32 scalex,
3970 l_float32 scaley,
3971 l_int32 order)
3972{
3973l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
3974l_uint32 *datat, *datad, *linet, *lined;
3975PIX *pix1, *pix2, *pixd;
3976PIXCMAP *cmap;
3977
3978 if (!pixs)
3979 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
3980 d = pixGetDepth(pixs);
3981 cmap = pixGetColormap(pixs);
3982 if (d != 8 && !cmap)
3983 return (PIX *)ERROR_PTR("pix not 8 bpp & not cmapped", __func__, NULL);
3984 if (scalex <= 0.0 || scaley <= 0.0)
3985 return (PIX *)ERROR_PTR("scale factors must be > 0", __func__, NULL);
3986 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
3987 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
3988 return (PIX *)ERROR_PTR("invalid subpixel order", __func__, NULL);
3989
3990 direction =
3991 (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
3992 ? L_HORIZ : L_VERT;
3994 if (direction == L_HORIZ)
3995 pix2 = pixScale(pix1, 3.0f * scalex, scaley);
3996 else /* L_VERT */
3997 pix2 = pixScale(pix1, scalex, 3.0f * scaley);
3998
3999 pixGetDimensions(pix2, &w, &h, NULL);
4000 wd = (direction == L_HORIZ) ? w / 3 : w;
4001 hd = (direction == L_VERT) ? h / 3 : h;
4002 pixd = pixCreate(wd, hd, 32);
4003 datad = pixGetData(pixd);
4004 wpld = pixGetWpl(pixd);
4005 datat = pixGetData(pix2);
4006 wplt = pixGetWpl(pix2);
4007 if (direction == L_HORIZ) {
4008 for (i = 0; i < hd; i++) {
4009 linet = datat + i * wplt;
4010 lined = datad + i * wpld;
4011 for (j = 0; j < wd; j++) {
4012 rval = GET_DATA_BYTE(linet, 3 * j);
4013 gval = GET_DATA_BYTE(linet, 3 * j + 1);
4014 bval = GET_DATA_BYTE(linet, 3 * j + 2);
4015 if (order == L_SUBPIXEL_ORDER_RGB)
4016 composeRGBPixel(rval, gval, bval, &lined[j]);
4017 else /* order BGR */
4018 composeRGBPixel(bval, gval, rval, &lined[j]);
4019 }
4020 }
4021 } else { /* L_VERT */
4022 for (i = 0; i < hd; i++) {
4023 linet = datat + 3 * i * wplt;
4024 lined = datad + i * wpld;
4025 for (j = 0; j < wd; j++) {
4026 rval = GET_DATA_BYTE(linet, j);
4027 gval = GET_DATA_BYTE(linet + wplt, j);
4028 bval = GET_DATA_BYTE(linet + 2 * wplt, j);
4029 if (order == L_SUBPIXEL_ORDER_VRGB)
4030 composeRGBPixel(rval, gval, bval, &lined[j]);
4031 else /* order VBGR */
4032 composeRGBPixel(bval, gval, rval, &lined[j]);
4033 }
4034 }
4035 }
4036
4037 pixDestroy(&pix1);
4038 pixDestroy(&pix2);
4039 return pixd;
4040}
4041
4042
4070PIX *
4072 l_float32 scalex,
4073 l_float32 scaley,
4074 l_int32 order)
4075{
4076l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
4077l_uint32 *datat, *datad, *linet, *lined;
4078PIX *pix1, *pix2, *pixd;
4079PIXCMAP *cmap;
4080
4081 if (!pixs)
4082 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
4083 d = pixGetDepth(pixs);
4084 cmap = pixGetColormap(pixs);
4085 if (d != 32 && !cmap)
4086 return (PIX *)ERROR_PTR("pix not 32 bpp & not cmapped", __func__, NULL);
4087 if (scalex <= 0.0 || scaley <= 0.0)
4088 return (PIX *)ERROR_PTR("scale factors must be > 0", __func__, NULL);
4089 if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
4090 order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
4091 return (PIX *)ERROR_PTR("invalid subpixel order", __func__, NULL);
4092
4093 direction =
4094 (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
4095 ? L_HORIZ : L_VERT;
4097 if (direction == L_HORIZ)
4098 pix2 = pixScale(pix1, 3.0f * scalex, scaley);
4099 else /* L_VERT */
4100 pix2 = pixScale(pix1, scalex, 3.0f * scaley);
4101
4102 pixGetDimensions(pix2, &w, &h, NULL);
4103 wd = (direction == L_HORIZ) ? w / 3 : w;
4104 hd = (direction == L_VERT) ? h / 3 : h;
4105 pixd = pixCreate(wd, hd, 32);
4106 pixCopyInputFormat(pixd, pixs);
4107 datad = pixGetData(pixd);
4108 wpld = pixGetWpl(pixd);
4109 datat = pixGetData(pix2);
4110 wplt = pixGetWpl(pix2);
4111 if (direction == L_HORIZ) {
4112 for (i = 0; i < hd; i++) {
4113 linet = datat + i * wplt;
4114 lined = datad + i * wpld;
4115 for (j = 0; j < wd; j++) {
4116 if (order == L_SUBPIXEL_ORDER_RGB) {
4117 extractRGBValues(linet[3 * j], &rval, NULL, NULL);
4118 extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4119 extractRGBValues(linet[3 * j + 2], NULL, NULL, &bval);
4120 } else { /* order BGR */
4121 extractRGBValues(linet[3 * j], NULL, NULL, &bval);
4122 extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4123 extractRGBValues(linet[3 * j + 2], &rval, NULL, NULL);
4124 }
4125 composeRGBPixel(rval, gval, bval, &lined[j]);
4126 }
4127 }
4128 } else { /* L_VERT */
4129 for (i = 0; i < hd; i++) {
4130 linet = datat + 3 * i * wplt;
4131 lined = datad + i * wpld;
4132 for (j = 0; j < wd; j++) {
4133 if (order == L_SUBPIXEL_ORDER_VRGB) {
4134 extractRGBValues(linet[j], &rval, NULL, NULL);
4135 extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4136 extractRGBValues((linet + 2 * wplt)[j], NULL, NULL, &bval);
4137 } else { /* order VBGR */
4138 extractRGBValues(linet[j], NULL, NULL, &bval);
4139 extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4140 extractRGBValues((linet + 2 * wplt)[j], &rval, NULL, NULL);
4141 }
4142 composeRGBPixel(rval, gval, bval, &lined[j]);
4143 }
4144 }
4145 }
4146
4147 if (pixGetSpp(pixs) == 4)
4148 pixScaleAndTransferAlpha(pixd, pixs, scalex, scaley);
4149
4150 pixDestroy(&pix1);
4151 pixDestroy(&pix2);
4152 return pixd;
4153}
4154
4155
4156/*---------------------------------------------------------------------*
4157 * Setting neutral point for min/max boost conversion to gray *
4158 *---------------------------------------------------------------------*/
4171void
4173{
4174 if (val <= 0) {
4175 L_ERROR("invalid reference value for neutral boost\n", __func__);
4176 return;
4177 }
4178 var_NEUTRAL_BOOST_VAL = val;
4179}
PIX * pixBackgroundNormSimple(PIX *pixs, PIX *pixim, PIX *pixg)
pixBackgroundNormSimple()
Definition adaptmap.c:253
#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:3560
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:3509
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:3055
PIX * pixConvertRGBToGrayMinMax(PIX *pixs, l_int32 type)
pixConvertRGBToGrayMinMax()
Definition pixconv.c:947
PIX * pixConvert8To32(PIX *pixs)
pixConvert8To32()
Definition pixconv.c:3332
PIX * pixConvertTo2(PIX *pixs)
pixConvertTo2()
Definition pixconv.c:2691
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition pixconv.c:3400
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:3124
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:2895
PIX * pixConvertLossless(PIX *pixs, l_int32 d)
pixConvertLossless()
Definition pixconv.c:3734
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:3900
PIX * pixConvertTo8Colormap(PIX *pixs, l_int32 dither)
pixConvertTo8Colormap()
Definition pixconv.c:3166
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:3299
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
Definition pixconv.c:3461
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:3199
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:3968
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition pixconv.c:3823
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:3694
PIX * pixConvert8To2(PIX *pix)
pixConvert8To2()
Definition pixconv.c:2741
PIX * pixRemoveAlpha(PIX *pixs)
pixRemoveAlpha()
Definition pixconv.c:3659
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition pixconv.c:3246
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:2952
PIX * pixConvertTo1BySampling(PIX *pixs, l_int32 factor, l_int32 threshold)
pixConvertTo1BySampling()
Definition pixconv.c:3006
PIX * pixConvertColorToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertColorToSubpixelRGB()
Definition pixconv.c:4071
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:4172
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:3622