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