Leptonica  1.83.1
Image processing and image analysis suite
pixconv.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
157 #ifdef HAVE_CONFIG_H
158 #include <config_auto.h>
159 #endif /* HAVE_CONFIG_H */
160 
161 #include <string.h>
162 #include <math.h>
163 #include "allheaders.h"
164 
165 /* ------- Set neutral point for min/max boost conversion to gray ------ */
166  /* Call l_setNeutralBoostVal() to change this */
167 static 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  *-------------------------------------------------------------*/
209 PIX *
211  l_int32 d,
212  l_int32 nlevels,
213  l_int32 cmapflag)
214 {
215 PIX *pixd;
216 PIXCMAP *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  *-------------------------------------------------------------*/
275 PIX *
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 
323 PIX *
325  l_int32 type)
326 {
327 l_int32 sval, rval, gval, bval, val0, val1;
328 l_int32 i, j, k, w, h, d, wpls, wpld, ncolors, nalloc, count;
329 l_int32 opaque, colorfound, blackwhite;
330 l_int32 *rmap, *gmap, *bmap, *amap;
331 l_uint32 *datas, *lines, *datad, *lined, *lut, *graymap;
332 l_uint32 sword, dword;
333 PIXCMAP *cmap;
334 PIX *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 &&
342  type != REMOVE_CMAP_TO_FULL_COLOR &&
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 */
372  type = REMOVE_CMAP_WITH_ALPHA;
373  } else if (colorfound) {
375  } else { /* opaque and no color */
376  if (d == 1 && blackwhite) /* can binarize without loss */
377  type = REMOVE_CMAP_TO_BINARY;
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 
592 cleanup_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  *-------------------------------------------------------------*/
615 l_ok
617 {
618 PIXCMAP *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 
644 PIX *
646 {
647 l_int32 ncolors, w, h, i, j, wpl1, wpld, index, val;
648 l_int32 *inta, *revmap;
649 l_uint32 *data1, *datad, *line1, *lined;
650 PIX *pix1, *pixd;
651 PIXCMAP *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);
667  pixAddGrayColormap8(pix1);
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  *-------------------------------------------------------------*/
731 PIX *
733 {
734  return pixConvertRGBToGray(pixs, 0.0, 0.0, 0.0);
735 }
736 
737 
755 PIX *
757  l_int32 type,
758  l_float32 rwt,
759  l_float32 gwt,
760  l_float32 bwt)
761 {
762 PIX *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.34, 0.33, 0.33);
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 
814 PIX *
816  l_float32 rwt,
817  l_float32 gwt,
818  l_float32 bwt)
819 {
820 l_int32 i, j, w, h, wpls, wpld, val;
821 l_uint32 word;
822 l_uint32 *datas, *lines, *datad, *lined;
823 l_float32 sum;
824 PIX *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 
890 PIX *
892 {
893 l_int32 i, j, w, h, wpls, wpld, val;
894 l_uint32 *datas, *lines, *datad, *lined;
895 PIX *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 
946 PIX *
948  l_int32 type)
949 {
950 l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val, minval, maxval;
951 l_uint32 *datas, *lines, *datad, *lined;
952 PIX *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 
1031 PIX *
1033  l_int32 refval)
1034 {
1035 l_int32 w, h, d, i, j, wplt, wpld;
1036 l_int32 rval, gval, bval, sval, minrg, maxrg, min, max, delta;
1037 l_int32 fullsat, newval;
1038 l_float32 *invmax, *ratio;
1039 l_uint32 *linet, *lined, *datat, *datad;
1040 PIX *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.0 / (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 
1107 PIX *
1109  l_float32 rc,
1110  l_float32 gc,
1111  l_float32 bc)
1112 {
1113 l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val;
1114 l_uint32 *datas, *lines, *datad, *lined;
1115 PIX *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 
1167 PIX *
1169  l_float32 rc,
1170  l_float32 gc,
1171  l_float32 bc,
1172  l_int32 thresh,
1173  l_int32 relation)
1174 {
1175 l_int32 threshold;
1176 PIX *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  *---------------------------------------------------------------------------*/
1222 PIX *
1224 {
1225 l_int32 d;
1226 PIX *pixd;
1227 PIXCMAP *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 
1275 PIX *
1277  l_int32 mindepth)
1278 {
1279 l_int32 ncolors, w, h, depth, i, j, wpls, wpld;
1280 l_int32 index, num, val, newval;
1281 l_int32 array[256];
1282 l_uint32 *lines, *lined, *datas, *datad;
1283 NUMA *na;
1284 PIX *pixd;
1285 PIXCMAP *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);
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  *---------------------------------------------------------------------------*/
1370 PIX *
1372  l_uint32 color,
1373  l_int32 cmapflag)
1374 {
1375 l_int32 i, j, w, h, wplt, wpld, val8;
1376 l_uint32 *datad, *datat, *lined, *linet, *tab;
1377 PIX *pixt, *pixd;
1378 PIXCMAP *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  *---------------------------------------------------------------------------*/
1455 PIX *
1457  l_int32 ditherflag)
1458 {
1459 l_int32 ncolors;
1460 NUMA *na;
1461 PIX *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  *---------------------------------------------------------------------------*/
1517 PIX *
1519 {
1520 l_int32 i, j, nc, w, h, imin, imax, factor, wpl1, wpld;
1521 l_int32 index, rmin, gmin, bmin, rmax, gmax, bmax, dmin, dmax;
1522 l_float32 minfract, ifract;
1523 l_int32 *lut;
1524 l_uint32 *line1, *lined, *data1, *datad;
1525 NUMA *na1, *na2; /* histograms */
1526 PIX *pix1, *pixd;
1527 PIXCMAP *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  *---------------------------------------------------------------------------*/
1626 l_ok
1628  l_int32 maxcolors,
1629  l_int32 mingraycolors,
1630  l_int32 octlevel,
1631  PIX **ppixd)
1632 {
1633 l_int32 d, ncolors, iscolor, graycolors;
1634 PIX *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  *---------------------------------------------------------------------------*/
1725 PIX *
1727  l_int32 type)
1728 {
1729 l_uint16 dword;
1730 l_int32 w, h, wpls, wpld, i, j, val, use_lsb;
1731 l_uint32 sword, first, second;
1732 l_uint32 *datas, *datad, *lines, *lined;
1733 PIX *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  *---------------------------------------------------------------------------*/
1819 PIX *
1821  l_float32 gamma)
1822 {
1823 l_int32 d;
1824 PIX *pixd;
1825 PIXCMAP *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  *---------------------------------------------------------------------------*/
1872 PIX *
1874  l_int32 depth,
1875  l_int32 invert)
1876 {
1877 PIX *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 
1935 PIX *
1937  PIX *pixs,
1938  l_uint16 val0,
1939  l_uint16 val1)
1940 {
1941 l_int32 w, h, i, j, dibit, ndibits, wpls, wpld;
1942 l_uint16 val[2];
1943 l_uint32 index;
1944 l_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 
2007 PIX *
2009  PIX *pixs,
2010  l_uint32 val0,
2011  l_uint32 val1)
2012 {
2013 l_int32 w, h, i, j, wpls, wpld, bit;
2014 l_uint32 val[2];
2015 l_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  *---------------------------------------------------------------------------*/
2068 PIX *
2070 {
2071 PIX *pixd;
2072 PIXCMAP *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 
2109 PIX *
2111  PIX *pixs,
2112  l_int32 val0,
2113  l_int32 val1)
2114 {
2115 l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2116 l_uint8 val[2];
2117 l_uint32 index;
2118 l_uint16 *tab;
2119 l_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  *---------------------------------------------------------------------------*/
2186 PIX *
2188 {
2189 PIX *pixd;
2190 PIXCMAP *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 
2227 PIX *
2229  PIX *pixs,
2230  l_int32 val0,
2231  l_int32 val1)
2232 {
2233 l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2234 l_uint8 val[2];
2235 l_uint32 index;
2236 l_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  *---------------------------------------------------------------------------*/
2303 PIX *
2305 {
2306 PIX *pixd;
2307 PIXCMAP *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 
2344 PIX *
2346  PIX *pixs,
2347  l_uint8 val0,
2348  l_uint8 val1)
2349 {
2350 l_int32 w, h, i, j, qbit, nqbits, wpls, wpld;
2351 l_uint8 val[2];
2352 l_uint32 index;
2353 l_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 
2433 PIX *
2435  l_uint8 val0,
2436  l_uint8 val1,
2437  l_uint8 val2,
2438  l_uint8 val3,
2439  l_int32 cmapflag)
2440 {
2441 l_int32 w, h, i, j, nbytes, wpls, wpld, dibit, byte;
2442 l_uint32 val[4];
2443 l_uint32 index;
2444 l_uint32 *tab, *datas, *datad, *lines, *lined;
2445 PIX *pixd;
2446 PIXCMAP *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 
2543 PIX *
2545  l_int32 cmapflag)
2546 {
2547 l_int32 w, h, i, j, wpls, wpld, byte, qbit;
2548 l_uint32 *datas, *datad, *lines, *lined;
2549 PIX *pixd;
2550 PIXCMAP *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  *---------------------------------------------------------------------------*/
2626 PIX *
2628  l_int32 leftshift)
2629 {
2630 l_int32 i, j, w, h, d, wplt, wpld, val;
2631 l_uint32 *datat, *datad, *linet, *lined;
2632 PIX *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  *---------------------------------------------------------------------------*/
2690 PIX *
2692 {
2693 l_int32 d;
2694 PIX *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 
2740 PIX *
2742 {
2743 l_int32 i, j, w, h, wpls, wpld;
2744 l_uint32 word;
2745 l_uint32 *datas, *lines, *datad, *lined;
2746 PIX *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  *---------------------------------------------------------------------------*/
2794 PIX *
2796 {
2797 l_int32 d;
2798 PIX *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 
2844 PIX *
2846 {
2847 l_int32 i, j, w, h, wpls, wpld, val;
2848 l_uint32 *datas, *lines, *datad, *lined;
2849 PIX *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  *---------------------------------------------------------------------------*/
2894 PIX *
2896 {
2897 l_int32 d, color0, color1, rval, gval, bval;
2898 PIX *pix1, *pix2, *pixd;
2899 PIXCMAP *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 
2951 PIX *
2953  l_int32 threshold)
2954 {
2955 l_int32 d, color0, color1, rval, gval, bval;
2956 PIX *pixg, *pixd;
2957 PIXCMAP *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 
3005 PIX *
3007  l_int32 factor,
3008  l_int32 threshold)
3009 {
3010 l_float32 scalefactor;
3011 PIX *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. / (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  *---------------------------------------------------------------------------*/
3054 PIX *
3056  l_int32 cmapflag)
3057 {
3058 l_int32 d;
3059 PIX *pix1, *pixd;
3060 PIXCMAP *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 
3123 PIX *
3125  l_int32 factor,
3126  l_int32 cmapflag)
3127 {
3128 l_float32 scalefactor;
3129 PIX *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. / (l_float32)factor;
3137  pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3138  pixd = pixConvertTo8(pixt, cmapflag);
3139 
3140  pixDestroy(&pixt);
3141  return pixd;
3142 }
3143 
3144 
3165 PIX *
3167  l_int32 dither)
3168 {
3169 l_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  *---------------------------------------------------------------------------*/
3198 PIX *
3200 {
3201 l_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  *---------------------------------------------------------------------------*/
3245 PIX *
3247 {
3248 l_int32 d;
3249 PIX *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 
3298 PIX *
3300  l_int32 factor)
3301 {
3302 l_float32 scalefactor;
3303 PIX *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. / (l_float32)factor;
3311  pix1 = pixScaleBySampling(pixs, scalefactor, scalefactor);
3312  pixd = pixConvertTo32(pix1);
3313 
3314  pixDestroy(&pix1);
3315  return pixd;
3316 }
3317 
3318 
3331 PIX *
3333 {
3334 l_int32 i, j, w, h, wpls, wpld, val;
3335 l_uint32 *datas, *datad, *lines, *lined;
3336 l_uint32 *tab;
3337 PIX *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  *---------------------------------------------------------------------------*/
3399 PIX *
3401  l_int32 copyflag,
3402  l_int32 warnflag)
3403 {
3404 l_int32 d;
3405 PIX *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  *---------------------------------------------------------------------------*/
3460 PIX *
3462 {
3463 l_uint8 *lines;
3464 l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3465 l_uint32 pixel;
3466 l_uint32 *datas, *datad, *lined;
3467 PIX *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 
3508 PIX *
3510 {
3511 l_uint8 *rgbdata8;
3512 l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3513 l_uint32 *datas, *lines, *rgbdata;
3514 PIX *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  *---------------------------------------------------------------------------*/
3559 PIX *
3561  l_int32 type)
3562 {
3563 l_uint16 dword;
3564 l_int32 w, h, i, j, wpls, wpld;
3565 l_uint32 sword;
3566 l_uint32 *datas, *lines, *datad, *lined;
3567 PIX *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 
3621 PIX *
3623  l_int32 type16,
3624  l_int32 type8)
3625 {
3626 PIX *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  *---------------------------------------------------------------------------*/
3658 PIX *
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  *---------------------------------------------------------------------------*/
3693 PIX *
3695  PIX *pixs)
3696 {
3697 PIXCMAP *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  *---------------------------------------------------------------------------*/
3733 PIX *
3735  l_int32 d)
3736 {
3737 l_int32 w, h, ds, wpls, wpld, i, j, val;
3738 l_uint32 *datas, *datad, *lines, *lined;
3739 PIX *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  *---------------------------------------------------------------------------*/
3822 PIX *
3824 {
3825 l_int32 d;
3826 PIX *pixd;
3827 PIXCMAP *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  *---------------------------------------------------------------------------*/
3899 PIX *
3901  l_float32 scalex,
3902  l_float32 scaley,
3903  l_int32 order)
3904 {
3905 l_int32 d;
3906 PIX *pix1, *pixd;
3907 PIXCMAP *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 
3967 PIX *
3969  l_float32 scalex,
3970  l_float32 scaley,
3971  l_int32 order)
3972 {
3973 l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
3974 l_uint32 *datat, *datad, *linet, *lined;
3975 PIX *pix1, *pix2, *pixd;
3976 PIXCMAP *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.0 * scalex, scaley);
3996  else /* L_VERT */
3997  pix2 = pixScale(pix1, scalex, 3.0 * 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 
4070 PIX *
4072  l_float32 scalex,
4073  l_float32 scaley,
4074  l_int32 order)
4075 {
4076 l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
4077 l_uint32 *datat, *datad, *linet, *lined;
4078 PIX *pix1, *pix2, *pixd;
4079 PIXCMAP *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.0 * scalex, scaley);
4099  else /* L_VERT */
4100  pix2 = pixScale(pix1, scalex, 3.0 * 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  *---------------------------------------------------------------------*/
4171 void
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:245
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
PIX * pixAlphaBlendUniform(PIX *pixs, l_uint32 color)
pixAlphaBlendUniform()
Definition: blend.c:1998
l_ok pixColorsForQuantization(PIX *pixs, l_int32 thresh, l_int32 *pncolors, l_int32 *piscolor, l_int32 debug)
pixColorsForQuantization()
l_ok pixNumColors(PIX *pixs, l_int32 factor, l_int32 *pncolors)
pixNumColors()
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:272
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1026
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:683
l_ok pixcmapGetDistanceToColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pdist)
pixcmapGetDistanceToColor()
Definition: colormap.c:1399
PIXCMAP * pixcmapConvertTo8(PIXCMAP *cmaps)
pixcmapConvertTo8()
Definition: colormap.c:1729
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:126
l_ok pixcmapAddRGBA(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval)
pixcmapAddRGBA()
Definition: colormap.c:439
PIXCMAP * pixcmapGrayToFalseColor(l_float32 gamma)
pixcmapGrayToFalseColor()
Definition: colormap.c:1545
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:789
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
Definition: colormap.c:1063
PIXCMAP * pixcmapGrayToColor(l_uint32 color)
pixcmapGrayToColor()
Definition: colormap.c:1609
l_ok pixcmapGetRangeValues(PIXCMAP *cmap, l_int32 select, l_int32 *pminval, l_int32 *pmaxval, l_int32 *pminindex, l_int32 *pmaxindex)
pixcmapGetRangeValues()
Definition: colormap.c:1453
PIXCMAP * pixcmapCreateLinear(l_int32 d, l_int32 nlevels)
pixcmapCreateLinear()
Definition: colormap.c:215
l_ok pixcmapToArrays(const PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
Definition: colormap.c:1981
l_ok pixcmapIsBlackAndWhite(PIXCMAP *cmap, l_int32 *pblackwhite)
pixcmapIsBlackAndWhite()
Definition: colormap.c:1165
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:403
l_ok pixcmapToRGBTable(PIXCMAP *cmap, l_uint32 **ptab, l_int32 *pncolors)
pixcmapToRGBTable()
Definition: colormap.c:2032
PIX * pixFewColorsOctcubeQuant1(PIX *pixs, l_int32 level)
pixFewColorsOctcubeQuant1()
Definition: colorquant1.c:2909
NUMA * pixOctcubeHistogram(PIX *pixs, l_int32 level, l_int32 *pncolors)
pixOctcubeHistogram()
Definition: colorquant1.c:3686
PIX * pixOctreeColorQuant(PIX *pixs, l_int32 colors, l_int32 ditherflag)
pixOctreeColorQuant()
Definition: colorquant1.c:536
PIX * pixFewColorsOctcubeQuant2(PIX *pixs, l_int32 level, NUMA *na, l_int32 ncolors, l_int32 *pnerrors)
pixFewColorsOctcubeQuant2()
Definition: colorquant1.c:3077
PIX * pixConvertRGBToHue(PIX *pixs)
pixConvertRGBToHue()
Definition: colorspace.c:488
PIX * pixConvertRGBToSaturation(PIX *pixs)
pixConvertRGBToSaturation()
Definition: colorspace.c:562
PIX * pixThresholdTo2bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo2bpp()
Definition: grayquant.c:1356
PIX * pixThresholdTo4bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo4bpp()
Definition: grayquant.c:1496
PIX * pixThresholdOn8bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdOn8bpp()
Definition: grayquant.c:1611
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:443
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:687
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:720
l_ok numaGetCountRelativeToZero(NUMA *na, l_int32 type, l_int32 *pcount)
numaGetCountRelativeToZero()
Definition: numafunc1.c:1088
NUMA * numaNormalizeHistogram(NUMA *nas, l_float32 tsum)
numaNormalizeHistogram()
Definition: numafunc2.c:1147
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1582
l_ok pixDestroyColormap(PIX *pix)
pixDestroyColormap()
Definition: pix1.c:1609
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2464
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1346
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2758
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2793
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1481
NUMA * pixGetGrayHistogram(PIX *pixs, l_int32 factor)
pixGetGrayHistogram()
Definition: pix4.c:115
NUMA * pixGetCmapHistogram(PIX *pixs, l_int32 factor)
pixGetCmapHistogram()
Definition: pix4.c:621
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:1073
static const l_float32 L_GREEN_WEIGHT
Definition: pix.h:371
PIX * pixConvertRGBToGrayGeneral(PIX *pixs, l_int32 type, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGrayGeneral()
Definition: pixconv.c:756
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
pixUnpackBinary()
Definition: pixconv.c:1873
PIX * pixConvert1To8Cmap(PIX *pixs)
pixConvert1To8Cmap()
Definition: pixconv.c:2304
PIX * pixConvertColorToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertColorToSubpixelRGB()
Definition: pixconv.c:4071
PIX * pixConvert1To32(PIX *pixd, PIX *pixs, l_uint32 val0, l_uint32 val1)
pixConvert1To32()
Definition: pixconv.c:2008
PIX * pixConvertTo1Adaptive(PIX *pixs)
pixConvertTo1Adaptive()
Definition: pixconv.c:2895
PIX * pixConvert1To16(PIX *pixd, PIX *pixs, l_uint16 val0, l_uint16 val1)
pixConvert1To16()
Definition: pixconv.c:1936
PIX * pixConvertRGBToGrayMinMax(PIX *pixs, l_int32 type)
pixConvertRGBToGrayMinMax()
Definition: pixconv.c:947
l_ok pixQuantizeIfFewColors(PIX *pixs, l_int32 maxcolors, l_int32 mingraycolors, l_int32 octlevel, PIX **ppixd)
pixQuantizeIfFewColors()
Definition: pixconv.c:1627
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition: pixconv.c:3400
PIX * pixRemoveAlpha(PIX *pixs)
pixRemoveAlpha()
Definition: pixconv.c:3659
PIX * pixConvertTo1BySampling(PIX *pixs, l_int32 factor, l_int32 threshold)
pixConvertTo1BySampling()
Definition: pixconv.c:3006
PIX * pixConvertTo2(PIX *pixs)
pixConvertTo2()
Definition: pixconv.c:2691
PIX * pixConvertCmapTo1(PIX *pixs)
pixConvertCmapTo1()
Definition: pixconv.c:1518
PIX * pixConvert4To8(PIX *pixs, l_int32 cmapflag)
pixConvert4To8()
Definition: pixconv.c:2544
PIX * pixConvertRGBToGray(PIX *pixs, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGray()
Definition: pixconv.c:815
PIX * pixAddAlphaTo1bpp(PIX *pixd, PIX *pixs)
pixAddAlphaTo1bpp()
Definition: pixconv.c:3694
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 * pixConvert1To4(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To4()
Definition: pixconv.c:2228
PIX * pixConvert1To4Cmap(PIX *pixs)
pixConvert1To4Cmap()
Definition: pixconv.c:2187
PIX * pixConvert32To16(PIX *pixs, l_int32 type)
pixConvert32To16()
Definition: pixconv.c:3560
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
PIX * pixConvertRGBToColormap(PIX *pixs, l_int32 ditherflag)
pixConvertRGBToColormap()
Definition: pixconv.c:1456
l_ok pixAddGrayColormap8(PIX *pixs)
pixAddGrayColormap8()
Definition: pixconv.c:616
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition: pixconv.c:1371
PIX * pixConvertGrayToColormap8(PIX *pixs, l_int32 mindepth)
pixConvertGrayToColormap8()
Definition: pixconv.c:1276
PIX * pixConvertTo8BySampling(PIX *pixs, l_int32 factor, l_int32 cmapflag)
pixConvertTo8BySampling()
Definition: pixconv.c:3124
PIX * pixConvertTo8Colormap(PIX *pixs, l_int32 dither)
pixConvertTo8Colormap()
Definition: pixconv.c:3166
PIX * pixConvertGrayToFalseColor(PIX *pixs, l_float32 gamma)
pixConvertGrayToFalseColor()
Definition: pixconv.c:1820
PIX * pixThreshold8(PIX *pixs, l_int32 d, l_int32 nlevels, l_int32 cmapflag)
pixThreshold8()
Definition: pixconv.c:210
PIX * pixConvert8To16(PIX *pixs, l_int32 leftshift)
pixConvert8To16()
Definition: pixconv.c:2627
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition: pixconv.c:2952
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition: pixconv.c:3823
PIX * pixAddMinimalGrayColormap8(PIX *pixs)
pixAddMinimalGrayColormap8()
Definition: pixconv.c:645
PIX * pixConvert1To2Cmap(PIX *pixs)
pixConvert1To2Cmap()
Definition: pixconv.c:2069
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2345
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3055
PIX * pixConvertLossless(PIX *pixs, l_int32 d)
pixConvertLossless()
Definition: pixconv.c:3734
PIX * pixConvertTo32BySampling(PIX *pixs, l_int32 factor)
pixConvertTo32BySampling()
Definition: pixconv.c:3299
PIX * pixConvert1To2(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To2()
Definition: pixconv.c:2110
PIX * pixConvertTo4(PIX *pixs)
pixConvertTo4()
Definition: pixconv.c:2795
PIX * pixConvertTo16(PIX *pixs)
pixConvertTo16()
Definition: pixconv.c:3199
PIX * pixRemoveColormapGeneral(PIX *pixs, l_int32 type, l_int32 ifnocmap)
pixRemoveColormapGeneral()
Definition: pixconv.c:276
PIX * pixConvertRGBToGrayArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc)
pixConvertRGBToGrayArb()
Definition: pixconv.c:1108
PIX * pixConvert8To32(PIX *pixs)
pixConvert8To32()
Definition: pixconv.c:3332
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition: pixconv.c:732
PIX * pixConvertRGBToGraySatBoost(PIX *pixs, l_int32 refval)
pixConvertRGBToGraySatBoost()
Definition: pixconv.c:1032
PIX * pixConvert8To4(PIX *pix)
pixConvert8To4()
Definition: pixconv.c:2845
PIX * pixConvert8To2(PIX *pix)
pixConvert8To2()
Definition: pixconv.c:2741
PIX * pixConvertGrayToColormap(PIX *pixs)
pixConvertGrayToColormap()
Definition: pixconv.c:1223
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3246
PIX * pixConvert32To8(PIX *pixs, l_int32 type16, l_int32 type8)
pixConvert32To8()
Definition: pixconv.c:3622
PIX * pixConvertRGBToGrayFast(PIX *pixs)
pixConvertRGBToGrayFast()
Definition: pixconv.c:891
PIX * pixConvert16To8(PIX *pixs, l_int32 type)
pixConvert16To8()
Definition: pixconv.c:1726
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
Definition: pixconv.c:3461
void l_setNeutralBoostVal(l_int32 val)
l_setNeutralBoostVal()
Definition: pixconv.c:4172
PIX * pixConvertGrayToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertGrayToSubpixelRGB()
Definition: pixconv.c:3968
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 * pixConvert32To24(PIX *pixs)
pixConvert32To24()
Definition: pixconv.c:3509
PIX * pixConvertToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertToSubpixelRGB()
Definition: pixconv.c:3900
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:250
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1306
l_ok pixScaleAndTransferAlpha(PIX *pixd, PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleAndTransferAlpha()
Definition: scale2.c:1334
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306