Leptonica  1.77.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 
155 #include <string.h>
156 #include <math.h>
157 #include "allheaders.h"
158 
159 /* ------- Set neutral point for min/max boost conversion to gray ------ */
160  /* Call l_setNeutralBoostVal() to change this */
161 static l_int32 var_NEUTRAL_BOOST_VAL = 180;
162 
163 
164 #ifndef NO_CONSOLE_IO
165 #define DEBUG_CONVERT_TO_COLORMAP 0
166 #define DEBUG_UNROLLING 0
167 #endif /* ~NO_CONSOLE_IO */
168 
169 
170 /*-------------------------------------------------------------*
171  * Conversion from 8 bpp grayscale to 1, 2 4 and 8 bpp *
172  *-------------------------------------------------------------*/
203 PIX *
205  l_int32 d,
206  l_int32 nlevels,
207  l_int32 cmapflag)
208 {
209 PIX *pixd;
210 PIXCMAP *cmap;
211 
212  PROCNAME("pixThreshold8");
213 
214  if (!pixs)
215  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
216  if (pixGetDepth(pixs) != 8)
217  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
218  if (cmapflag && nlevels < 2)
219  return (PIX *)ERROR_PTR("nlevels must be at least 2", procName, NULL);
220 
221  switch (d) {
222  case 1:
223  pixd = pixThresholdToBinary(pixs, 128);
224  if (cmapflag) {
225  cmap = pixcmapCreateLinear(1, 2);
226  pixSetColormap(pixd, cmap);
227  }
228  break;
229  case 2:
230  pixd = pixThresholdTo2bpp(pixs, nlevels, cmapflag);
231  break;
232  case 4:
233  pixd = pixThresholdTo4bpp(pixs, nlevels, cmapflag);
234  break;
235  case 8:
236  pixd = pixThresholdOn8bpp(pixs, nlevels, cmapflag);
237  break;
238  default:
239  return (PIX *)ERROR_PTR("d must be in {1,2,4,8}", procName, NULL);
240  }
241 
242  if (!pixd)
243  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
244  pixCopyInputFormat(pixd, pixs);
245  return pixd;
246 }
247 
248 
249 /*-------------------------------------------------------------*
250  * Conversion from colormapped pix *
251  *-------------------------------------------------------------*/
271 PIX *
273  l_int32 type,
274  l_int32 ifnocmap)
275 {
276  PROCNAME("pixRemoveColormapGeneral");
277 
278  if (!pixs)
279  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
280  if (ifnocmap != L_CLONE && ifnocmap != L_COPY)
281  return (PIX *)ERROR_PTR("invalid value for ifnocmap", procName, NULL);
282 
283  if (pixGetColormap(pixs))
284  return pixRemoveColormap(pixs, type);
285 
286  if (ifnocmap == L_CLONE)
287  return pixClone(pixs);
288  else
289  return pixCopy(NULL, pixs);
290 }
291 
292 
321 PIX *
323  l_int32 type)
324 {
325 l_int32 sval, rval, gval, bval, val0, val1;
326 l_int32 i, j, k, w, h, d, wpls, wpld, ncolors, count;
327 l_int32 opaque, colorfound, blackwhite;
328 l_int32 *rmap, *gmap, *bmap, *amap;
329 l_uint32 *datas, *lines, *datad, *lined, *lut, *graymap;
330 l_uint32 sword, dword;
331 PIXCMAP *cmap;
332 PIX *pixd;
333 
334  PROCNAME("pixRemoveColormap");
335 
336  if (!pixs)
337  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
338  if ((cmap = pixGetColormap(pixs)) == NULL)
339  return pixClone(pixs);
340 
341  if (type != REMOVE_CMAP_TO_BINARY &&
342  type != REMOVE_CMAP_TO_GRAYSCALE &&
343  type != REMOVE_CMAP_TO_FULL_COLOR &&
344  type != REMOVE_CMAP_WITH_ALPHA &&
345  type != REMOVE_CMAP_BASED_ON_SRC) {
346  L_WARNING("Invalid type; converting based on src\n", procName);
348  }
349 
350  pixGetDimensions(pixs, &w, &h, &d);
351  if (d != 1 && d != 2 && d != 4 && d != 8)
352  return (PIX *)ERROR_PTR("pixs must be {1,2,4,8} bpp", procName, NULL);
353 
354  if (pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap))
355  return (PIX *)ERROR_PTR("colormap arrays not made", procName, NULL);
356 
357  if (d != 1 && type == REMOVE_CMAP_TO_BINARY) {
358  L_WARNING("not 1 bpp; can't remove cmap to binary\n", procName);
360  }
361 
362  /* Select output type depending on colormap content */
363  if (type == REMOVE_CMAP_BASED_ON_SRC) {
364  pixcmapIsOpaque(cmap, &opaque);
365  pixcmapHasColor(cmap, &colorfound);
366  pixcmapIsBlackAndWhite(cmap, &blackwhite);
367  if (!opaque) { /* save the alpha */
368  type = REMOVE_CMAP_WITH_ALPHA;
369  } else if (colorfound) {
371  } else { /* opaque and no color */
372  if (d == 1 && blackwhite) /* can binarize without loss */
373  type = REMOVE_CMAP_TO_BINARY;
374  else
376  }
377  }
378 
379  ncolors = pixcmapGetCount(cmap);
380  datas = pixGetData(pixs);
381  wpls = pixGetWpl(pixs);
382  if (type == REMOVE_CMAP_TO_BINARY) {
383  if ((pixd = pixCopy(NULL, pixs)) == NULL) {
384  L_ERROR("pixd not made\n", procName);
385  goto cleanup_arrays;
386  }
387  pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
388  val0 = rval + gval + bval;
389  pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
390  val1 = rval + gval + bval;
391  if (val0 < val1) /* photometrically inverted from standard */
392  pixInvert(pixd, pixd);
393  pixDestroyColormap(pixd);
394  } else if (type == REMOVE_CMAP_TO_GRAYSCALE) {
395  if ((pixd = pixCreate(w, h, 8)) == NULL) {
396  L_ERROR("pixd not made\n", procName);
397  goto cleanup_arrays;
398  }
399  pixCopyResolution(pixd, pixs);
400  pixCopyInputFormat(pixd, pixs);
401  datad = pixGetData(pixd);
402  wpld = pixGetWpl(pixd);
403  graymap = (l_uint32 *)LEPT_CALLOC(ncolors, sizeof(l_int32));
404  for (i = 0; i < pixcmapGetCount(cmap); i++) {
405  graymap[i] = (l_uint32)(L_RED_WEIGHT * rmap[i] +
406  L_GREEN_WEIGHT * gmap[i] +
407  L_BLUE_WEIGHT * bmap[i] + 0.5);
408  }
409  for (i = 0; i < h; i++) {
410  lines = datas + i * wpls;
411  lined = datad + i * wpld;
412  switch (d) /* depth test above; no default permitted */
413  {
414  case 8:
415  /* Unrolled 4x */
416  for (j = 0, count = 0; j + 3 < w; j += 4, count++) {
417  sword = lines[count];
418  dword = (graymap[(sword >> 24) & 0xff] << 24) |
419  (graymap[(sword >> 16) & 0xff] << 16) |
420  (graymap[(sword >> 8) & 0xff] << 8) |
421  graymap[sword & 0xff];
422  lined[count] = dword;
423  }
424  /* Cleanup partial word */
425  for (; j < w; j++) {
426  sval = GET_DATA_BYTE(lines, j);
427  gval = graymap[sval];
428  SET_DATA_BYTE(lined, j, gval);
429  }
430 #if DEBUG_UNROLLING
431 #define CHECK_VALUE(a, b, c) if (GET_DATA_BYTE(a, b) != c) { \
432  fprintf(stderr, "Error: mismatch at %d, %d vs %d\n", \
433  j, GET_DATA_BYTE(a, b), c); }
434  for (j = 0; j < w; j++) {
435  sval = GET_DATA_BYTE(lines, j);
436  gval = graymap[sval];
437  CHECK_VALUE(lined, j, gval);
438  }
439 #endif
440  break;
441  case 4:
442  /* Unrolled 8x */
443  for (j = 0, count = 0; j + 7 < w; j += 8, count++) {
444  sword = lines[count];
445  dword = (graymap[(sword >> 28) & 0xf] << 24) |
446  (graymap[(sword >> 24) & 0xf] << 16) |
447  (graymap[(sword >> 20) & 0xf] << 8) |
448  graymap[(sword >> 16) & 0xf];
449  lined[2 * count] = dword;
450  dword = (graymap[(sword >> 12) & 0xf] << 24) |
451  (graymap[(sword >> 8) & 0xf] << 16) |
452  (graymap[(sword >> 4) & 0xf] << 8) |
453  graymap[sword & 0xf];
454  lined[2 * count + 1] = dword;
455  }
456  /* Cleanup partial word */
457  for (; j < w; j++) {
458  sval = GET_DATA_QBIT(lines, j);
459  gval = graymap[sval];
460  SET_DATA_BYTE(lined, j, gval);
461  }
462 #if DEBUG_UNROLLING
463  for (j = 0; j < w; j++) {
464  sval = GET_DATA_QBIT(lines, j);
465  gval = graymap[sval];
466  CHECK_VALUE(lined, j, gval);
467  }
468 #endif
469  break;
470  case 2:
471  /* Unrolled 16x */
472  for (j = 0, count = 0; j + 15 < w; j += 16, count++) {
473  sword = lines[count];
474  dword = (graymap[(sword >> 30) & 0x3] << 24) |
475  (graymap[(sword >> 28) & 0x3] << 16) |
476  (graymap[(sword >> 26) & 0x3] << 8) |
477  graymap[(sword >> 24) & 0x3];
478  lined[4 * count] = dword;
479  dword = (graymap[(sword >> 22) & 0x3] << 24) |
480  (graymap[(sword >> 20) & 0x3] << 16) |
481  (graymap[(sword >> 18) & 0x3] << 8) |
482  graymap[(sword >> 16) & 0x3];
483  lined[4 * count + 1] = dword;
484  dword = (graymap[(sword >> 14) & 0x3] << 24) |
485  (graymap[(sword >> 12) & 0x3] << 16) |
486  (graymap[(sword >> 10) & 0x3] << 8) |
487  graymap[(sword >> 8) & 0x3];
488  lined[4 * count + 2] = dword;
489  dword = (graymap[(sword >> 6) & 0x3] << 24) |
490  (graymap[(sword >> 4) & 0x3] << 16) |
491  (graymap[(sword >> 2) & 0x3] << 8) |
492  graymap[sword & 0x3];
493  lined[4 * count + 3] = dword;
494  }
495  /* Cleanup partial word */
496  for (; j < w; j++) {
497  sval = GET_DATA_DIBIT(lines, j);
498  gval = graymap[sval];
499  SET_DATA_BYTE(lined, j, gval);
500  }
501 #if DEBUG_UNROLLING
502  for (j = 0; j < w; j++) {
503  sval = GET_DATA_DIBIT(lines, j);
504  gval = graymap[sval];
505  CHECK_VALUE(lined, j, gval);
506  }
507 #endif
508  break;
509  case 1:
510  /* Unrolled 8x */
511  for (j = 0, count = 0; j + 31 < w; j += 32, count++) {
512  sword = lines[count];
513  for (k = 0; k < 4; k++) {
514  /* The top byte is always the relevant one */
515  dword = (graymap[(sword >> 31) & 0x1] << 24) |
516  (graymap[(sword >> 30) & 0x1] << 16) |
517  (graymap[(sword >> 29) & 0x1] << 8) |
518  graymap[(sword >> 28) & 0x1];
519  lined[8 * count + 2 * k] = dword;
520  dword = (graymap[(sword >> 27) & 0x1] << 24) |
521  (graymap[(sword >> 26) & 0x1] << 16) |
522  (graymap[(sword >> 25) & 0x1] << 8) |
523  graymap[(sword >> 24) & 0x1];
524  lined[8 * count + 2 * k + 1] = dword;
525  sword <<= 8; /* Move up the next byte */
526  }
527  }
528  /* Cleanup partial word */
529  for (; j < w; j++) {
530  sval = GET_DATA_BIT(lines, j);
531  gval = graymap[sval];
532  SET_DATA_BYTE(lined, j, gval);
533  }
534 #if DEBUG_UNROLLING
535  for (j = 0; j < w; j++) {
536  sval = GET_DATA_BIT(lines, j);
537  gval = graymap[sval];
538  CHECK_VALUE(lined, j, gval);
539  }
540 #undef CHECK_VALUE
541 #endif
542  break;
543  default:
544  return NULL;
545  }
546  }
547  if (graymap)
548  LEPT_FREE(graymap);
549  } else { /* type == REMOVE_CMAP_TO_FULL_COLOR or REMOVE_CMAP_WITH_ALPHA */
550  if ((pixd = pixCreate(w, h, 32)) == NULL) {
551  L_ERROR("pixd not made\n", procName);
552  goto cleanup_arrays;
553  }
554  pixCopyInputFormat(pixd, pixs);
555  pixCopyResolution(pixd, pixs);
556  if (type == REMOVE_CMAP_WITH_ALPHA)
557  pixSetSpp(pixd, 4);
558  datad = pixGetData(pixd);
559  wpld = pixGetWpl(pixd);
560  lut = (l_uint32 *)LEPT_CALLOC(ncolors, sizeof(l_uint32));
561  for (i = 0; i < ncolors; i++) {
562  if (type == REMOVE_CMAP_TO_FULL_COLOR)
563  composeRGBPixel(rmap[i], gmap[i], bmap[i], lut + i);
564  else /* full color plus alpha */
565  composeRGBAPixel(rmap[i], gmap[i], bmap[i], amap[i], lut + i);
566  }
567 
568  for (i = 0; i < h; i++) {
569  lines = datas + i * wpls;
570  lined = datad + i * wpld;
571  for (j = 0; j < w; j++) {
572  if (d == 8)
573  sval = GET_DATA_BYTE(lines, j);
574  else if (d == 4)
575  sval = GET_DATA_QBIT(lines, j);
576  else if (d == 2)
577  sval = GET_DATA_DIBIT(lines, j);
578  else /* (d == 1) */
579  sval = GET_DATA_BIT(lines, j);
580  if (sval >= ncolors)
581  L_WARNING("pixel value out of bounds\n", procName);
582  else
583  lined[j] = lut[sval];
584  }
585  }
586  LEPT_FREE(lut);
587  }
588 
589 cleanup_arrays:
590  LEPT_FREE(rmap);
591  LEPT_FREE(gmap);
592  LEPT_FREE(bmap);
593  LEPT_FREE(amap);
594  return pixd;
595 }
596 
597 
598 /*-------------------------------------------------------------*
599  * Add colormap losslessly (8 to 8) *
600  *-------------------------------------------------------------*/
612 l_ok
614 {
615 PIXCMAP *cmap;
616 
617  PROCNAME("pixAddGrayColormap8");
618 
619  if (!pixs || pixGetDepth(pixs) != 8)
620  return ERROR_INT("pixs not defined or not 8 bpp", procName, 1);
621  if (pixGetColormap(pixs))
622  return 0;
623 
624  cmap = pixcmapCreateLinear(8, 256);
625  pixSetColormap(pixs, cmap);
626  return 0;
627 }
628 
629 
643 PIX *
645 {
646 l_int32 ncolors, w, h, i, j, wpl1, wpld, index, val;
647 l_int32 *inta, *revmap;
648 l_uint32 *data1, *datad, *line1, *lined;
649 PIX *pix1, *pixd;
650 PIXCMAP *cmap;
651 
652  PROCNAME("pixAddMinimalGrayColormap8");
653 
654  if (!pixs || pixGetDepth(pixs) != 8)
655  return (PIX *)ERROR_PTR("pixs undefined or not 8 bpp", procName, NULL);
656 
657  /* Eliminate the easy cases */
658  pixNumColors(pixs, 1, &ncolors);
659  cmap = pixGetColormap(pixs);
660  if (cmap) {
661  if (pixcmapGetCount(cmap) == ncolors) /* irreducible */
662  return pixCopy(NULL, pixs);
663  else
665  } else {
666  if (ncolors == 256) {
667  pix1 = pixCopy(NULL, pixs);
668  pixAddGrayColormap8(pix1);
669  return pix1;
670  }
671  pix1 = pixClone(pixs);
672  }
673 
674  /* Find the gray levels and make a reverse map */
675  pixGetDimensions(pix1, &w, &h, NULL);
676  data1 = pixGetData(pix1);
677  wpl1 = pixGetWpl(pix1);
678  inta = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
679  for (i = 0; i < h; i++) {
680  line1 = data1 + i * wpl1;
681  for (j = 0; j < w; j++) {
682  val = GET_DATA_BYTE(line1, j);
683  inta[val] = 1;
684  }
685  }
686  cmap = pixcmapCreate(8);
687  revmap = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
688  for (i = 0, index = 0; i < 256; i++) {
689  if (inta[i]) {
690  pixcmapAddColor(cmap, i, i, i);
691  revmap[i] = index++;
692  }
693  }
694 
695  /* Set all pixels in pixd to the colormap index */
696  pixd = pixCreateTemplate(pix1);
697  pixSetColormap(pixd, cmap);
698  pixCopyInputFormat(pixd, pixs);
699  pixCopyResolution(pixd, pixs);
700  datad = pixGetData(pixd);
701  wpld = pixGetWpl(pixd);
702  for (i = 0; i < h; i++) {
703  line1 = data1 + i * wpl1;
704  lined = datad + i * wpld;
705  for (j = 0; j < w; j++) {
706  val = GET_DATA_BYTE(line1, j);
707  SET_DATA_BYTE(lined, j, revmap[val]);
708  }
709  }
710 
711  pixDestroy(&pix1);
712  LEPT_FREE(inta);
713  LEPT_FREE(revmap);
714  return pixd;
715 }
716 
717 
718 /*-------------------------------------------------------------*
719  * Conversion from RGB color to grayscale *
720  *-------------------------------------------------------------*/
732 PIX *
734 {
735  return pixConvertRGBToGray(pixs, 0.0, 0.0, 0.0);
736 }
737 
738 
752 PIX *
754  l_float32 rwt,
755  l_float32 gwt,
756  l_float32 bwt)
757 {
758 l_int32 i, j, w, h, wpls, wpld, val;
759 l_uint32 word;
760 l_uint32 *datas, *lines, *datad, *lined;
761 l_float32 sum;
762 PIX *pixd;
763 
764  PROCNAME("pixConvertRGBToGray");
765 
766  if (!pixs)
767  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
768  if (pixGetDepth(pixs) != 32)
769  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
770  if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0)
771  return (PIX *)ERROR_PTR("weights not all >= 0.0", procName, NULL);
772 
773  /* Make sure the sum of weights is 1.0; otherwise, you can get
774  * overflow in the gray value. */
775  if (rwt == 0.0 && gwt == 0.0 && bwt == 0.0) {
776  rwt = L_RED_WEIGHT;
777  gwt = L_GREEN_WEIGHT;
778  bwt = L_BLUE_WEIGHT;
779  }
780  sum = rwt + gwt + bwt;
781  if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
782  L_WARNING("weights don't sum to 1; maintaining ratios\n", procName);
783  rwt = rwt / sum;
784  gwt = gwt / sum;
785  bwt = bwt / sum;
786  }
787 
788  pixGetDimensions(pixs, &w, &h, NULL);
789  datas = pixGetData(pixs);
790  wpls = pixGetWpl(pixs);
791  if ((pixd = pixCreate(w, h, 8)) == NULL)
792  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
793  pixCopyResolution(pixd, pixs);
794  pixCopyInputFormat(pixd, pixs);
795  datad = pixGetData(pixd);
796  wpld = pixGetWpl(pixd);
797 
798  for (i = 0; i < h; i++) {
799  lines = datas + i * wpls;
800  lined = datad + i * wpld;
801  for (j = 0; j < w; j++) {
802  word = *(lines + j);
803  val = (l_int32)(rwt * ((word >> L_RED_SHIFT) & 0xff) +
804  gwt * ((word >> L_GREEN_SHIFT) & 0xff) +
805  bwt * ((word >> L_BLUE_SHIFT) & 0xff) + 0.5);
806  SET_DATA_BYTE(lined, j, val);
807  }
808  }
809 
810  return pixd;
811 }
812 
813 
830 PIX *
832 {
833 l_int32 i, j, w, h, wpls, wpld, val;
834 l_uint32 *datas, *lines, *datad, *lined;
835 PIX *pixd;
836 
837  PROCNAME("pixConvertRGBToGrayFast");
838 
839  if (!pixs)
840  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
841  if (pixGetDepth(pixs) != 32)
842  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
843 
844  pixGetDimensions(pixs, &w, &h, NULL);
845  datas = pixGetData(pixs);
846  wpls = pixGetWpl(pixs);
847  if ((pixd = pixCreate(w, h, 8)) == NULL)
848  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
849  pixCopyResolution(pixd, pixs);
850  pixCopyInputFormat(pixd, pixs);
851  datad = pixGetData(pixd);
852  wpld = pixGetWpl(pixd);
853 
854  for (i = 0; i < h; i++) {
855  lines = datas + i * wpls;
856  lined = datad + i * wpld;
857  for (j = 0; j < w; j++, lines++) {
858  val = ((*lines) >> L_GREEN_SHIFT) & 0xff;
859  SET_DATA_BYTE(lined, j, val);
860  }
861  }
862 
863  return pixd;
864 }
865 
866 
886 PIX *
888  l_int32 type)
889 {
890 l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val, minval, maxval;
891 l_uint32 *datas, *lines, *datad, *lined;
892 PIX *pixd;
893 
894  PROCNAME("pixConvertRGBToGrayMinMax");
895 
896  if (!pixs)
897  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
898  if (pixGetDepth(pixs) != 32)
899  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
900  if (type != L_CHOOSE_MIN && type != L_CHOOSE_MAX &&
901  type != L_CHOOSE_MAXDIFF && type != L_CHOOSE_MIN_BOOST &&
902  type != L_CHOOSE_MAX_BOOST)
903  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
904 
905  pixGetDimensions(pixs, &w, &h, NULL);
906  datas = pixGetData(pixs);
907  wpls = pixGetWpl(pixs);
908  if ((pixd = pixCreate(w, h, 8)) == NULL)
909  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
910  pixCopyResolution(pixd, pixs);
911  pixCopyInputFormat(pixd, pixs);
912  datad = pixGetData(pixd);
913  wpld = pixGetWpl(pixd);
914 
915  for (i = 0; i < h; i++) {
916  lines = datas + i * wpls;
917  lined = datad + i * wpld;
918  for (j = 0; j < w; j++) {
919  extractRGBValues(lines[j], &rval, &gval, &bval);
920  if (type == L_CHOOSE_MIN || type == L_CHOOSE_MIN_BOOST) {
921  val = L_MIN(rval, gval);
922  val = L_MIN(val, bval);
923  if (type == L_CHOOSE_MIN_BOOST)
924  val = L_MIN(255, (val * val) / var_NEUTRAL_BOOST_VAL);
925  } else if (type == L_CHOOSE_MAX || type == L_CHOOSE_MAX_BOOST) {
926  val = L_MAX(rval, gval);
927  val = L_MAX(val, bval);
928  if (type == L_CHOOSE_MAX_BOOST)
929  val = L_MIN(255, (val * val) / var_NEUTRAL_BOOST_VAL);
930  } else { /* L_CHOOSE_MAXDIFF */
931  minval = L_MIN(rval, gval);
932  minval = L_MIN(minval, bval);
933  maxval = L_MAX(rval, gval);
934  maxval = L_MAX(maxval, bval);
935  val = maxval - minval;
936  }
937  SET_DATA_BYTE(lined, j, val);
938  }
939  }
940 
941  return pixd;
942 }
943 
944 
973 PIX *
975  l_int32 refval)
976 {
977 l_int32 w, h, d, i, j, wplt, wpld;
978 l_int32 rval, gval, bval, sval, minrg, maxrg, min, max, delta;
979 l_int32 fullsat, newval;
980 l_float32 *invmax, *ratio;
981 l_uint32 *linet, *lined, *datat, *datad;
982 PIX *pixt, *pixd;
983 
984  PROCNAME("pixConvertRGBToGraySatBoost");
985 
986  if (!pixs)
987  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
988  pixGetDimensions(pixs, &w, &h, &d);
989  if (d != 32 && !pixGetColormap(pixs))
990  return (PIX *)ERROR_PTR("pixs not cmapped or rgb", procName, NULL);
991  if (refval < 1 || refval > 255)
992  return (PIX *)ERROR_PTR("refval not in [1 ... 255]", procName, NULL);
993 
995  pixd = pixCreate(w, h, 8);
996  pixCopyResolution(pixd, pixs);
997  pixCopyInputFormat(pixd, pixs);
998  wplt = pixGetWpl(pixt);
999  datat = pixGetData(pixt);
1000  wpld = pixGetWpl(pixd);
1001  datad = pixGetData(pixd);
1002  invmax = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
1003  ratio = (l_float32 *)LEPT_CALLOC(256, sizeof(l_float32));
1004  for (i = 1; i < 256; i++) { /* i == 0 --> delta = sval = newval = 0 */
1005  invmax[i] = 1.0 / (l_float32)i;
1006  ratio[i] = (l_float32)i / (l_float32)refval;
1007  }
1008  for (i = 0; i < h; i++) {
1009  linet = datat + i * wplt;
1010  lined = datad + i * wpld;
1011  for (j = 0; j < w; j++) {
1012  extractRGBValues(linet[j], &rval, &gval, &bval);
1013  minrg = L_MIN(rval, gval);
1014  min = L_MIN(minrg, bval);
1015  maxrg = L_MAX(rval, gval);
1016  max = L_MAX(maxrg, bval);
1017  delta = max - min;
1018  if (delta == 0) /* gray; no chroma */
1019  sval = 0;
1020  else
1021  sval = (l_int32)(255. * (l_float32)delta * invmax[max] + 0.5);
1022 
1023  fullsat = L_MIN(255, 255 * ratio[max]);
1024  newval = (sval * fullsat + (255 - sval) * max) / 255;
1025  SET_DATA_BYTE(lined, j, newval);
1026  }
1027  }
1028 
1029  pixDestroy(&pixt);
1030  LEPT_FREE(invmax);
1031  LEPT_FREE(ratio);
1032  return pixd;
1033 }
1034 
1035 
1051 PIX *
1053  l_float32 rc,
1054  l_float32 gc,
1055  l_float32 bc)
1056 {
1057 l_int32 i, j, w, h, wpls, wpld, rval, gval, bval, val;
1058 l_uint32 *datas, *lines, *datad, *lined;
1059 PIX *pixd;
1060 
1061  PROCNAME("pixConvertRGBToGrayArb");
1062 
1063  if (!pixs)
1064  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1065  if (pixGetDepth(pixs) != 32)
1066  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1067  if (rc <= 0 && gc <= 0 && bc <= 0)
1068  return (PIX *)ERROR_PTR("all coefficients <= 0", procName, NULL);
1069 
1070  pixGetDimensions(pixs, &w, &h, NULL);
1071  datas = pixGetData(pixs);
1072  wpls = pixGetWpl(pixs);
1073  if ((pixd = pixCreate(w, h, 8)) == NULL)
1074  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1075  pixCopyResolution(pixd, pixs);
1076  pixCopyInputFormat(pixd, pixs);
1077  datad = pixGetData(pixd);
1078  wpld = pixGetWpl(pixd);
1079 
1080  for (i = 0; i < h; i++) {
1081  lines = datas + i * wpls;
1082  lined = datad + i * wpld;
1083  for (j = 0; j < w; j++) {
1084  extractRGBValues(lines[j], &rval, &gval, &bval);
1085  val = (l_int32)(rc * rval + gc * gval + bc * bval);
1086  val = L_MIN(255, L_MAX(0, val));
1087  SET_DATA_BYTE(lined, j, val);
1088  }
1089  }
1090 
1091  return pixd;
1092 }
1093 
1094 
1113 PIX *
1115  l_float32 rc,
1116  l_float32 gc,
1117  l_float32 bc,
1118  l_int32 thresh,
1119  l_int32 relation)
1120 {
1121 l_int32 threshold;
1122 PIX *pix1, *pix2;
1123 
1124  PROCNAME("pixConvertRGBToBinaryArb");
1125 
1126  if (!pixs || pixGetDepth(pixs) != 32)
1127  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1128  if (rc <= 0 && gc <= 0 && bc <= 0)
1129  return (PIX *)ERROR_PTR("all coefficients <= 0", procName, NULL);
1130  if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT &&
1131  relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE)
1132  return (PIX *)ERROR_PTR("invalid relation", procName, NULL);
1133 
1134  pix1 = pixConvertRGBToGrayArb(pixs, rc, gc, bc);
1135  threshold = (relation == L_SELECT_IF_LTE || relation == L_SELECT_IF_GT) ?
1136  thresh : thresh + 1;
1137  pix2 = pixThresholdToBinary(pix1, threshold);
1138  if (relation == L_SELECT_IF_GT || relation == L_SELECT_IF_GTE)
1139  pixInvert(pix2, pix2);
1140  pixDestroy(&pix1);
1141  return pix2;
1142 }
1143 
1144 
1145 /*---------------------------------------------------------------------------*
1146  * Conversion from grayscale to colormap *
1147  *---------------------------------------------------------------------------*/
1170 PIX *
1172 {
1173 l_int32 d;
1174 PIX *pixd;
1175 PIXCMAP *cmap;
1176 
1177  PROCNAME("pixConvertGrayToColormap");
1178 
1179  if (!pixs)
1180  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1181  d = pixGetDepth(pixs);
1182  if (d != 2 && d != 4 && d != 8)
1183  return (PIX *)ERROR_PTR("pixs not 2, 4 or 8 bpp", procName, NULL);
1184 
1185  if (pixGetColormap(pixs)) {
1186  L_INFO("pixs already has a colormap\n", procName);
1187  return pixCopy(NULL, pixs);
1188  }
1189 
1190  if (d == 8) /* lossless conversion */
1191  return pixConvertGrayToColormap8(pixs, 2);
1192 
1193  /* Build a cmap with equally spaced target values over the
1194  * full 8 bpp range. */
1195  pixd = pixCopy(NULL, pixs);
1196  cmap = pixcmapCreateLinear(d, 1 << d);
1197  pixSetColormap(pixd, cmap);
1198  pixCopyInputFormat(pixd, pixs);
1199  return pixd;
1200 }
1201 
1202 
1225 PIX *
1227  l_int32 mindepth)
1228 {
1229 l_int32 ncolors, w, h, depth, i, j, wpls, wpld;
1230 l_int32 index, num, val, newval;
1231 l_int32 array[256];
1232 l_uint32 *lines, *lined, *datas, *datad;
1233 NUMA *na;
1234 PIX *pixd;
1235 PIXCMAP *cmap;
1236 
1237  PROCNAME("pixConvertGrayToColormap8");
1238 
1239  if (!pixs)
1240  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1241  if (pixGetDepth(pixs) != 8)
1242  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1243  if (mindepth != 2 && mindepth != 4 && mindepth != 8) {
1244  L_WARNING("invalid value of mindepth; setting to 8\n", procName);
1245  mindepth = 8;
1246  }
1247 
1248  if (pixGetColormap(pixs)) {
1249  L_INFO("pixs already has a colormap\n", procName);
1250  return pixCopy(NULL, pixs);
1251  }
1252 
1253  na = pixGetGrayHistogram(pixs, 1);
1255  if (mindepth == 8 || ncolors > 16)
1256  depth = 8;
1257  else if (mindepth == 4 || ncolors > 4)
1258  depth = 4;
1259  else
1260  depth = 2;
1261 
1262  pixGetDimensions(pixs, &w, &h, NULL);
1263  pixd = pixCreate(w, h, depth);
1264  cmap = pixcmapCreate(depth);
1265  pixSetColormap(pixd, cmap);
1266  pixCopyInputFormat(pixd, pixs);
1267  pixCopyResolution(pixd, pixs);
1268 
1269  index = 0;
1270  for (i = 0; i < 256; i++) {
1271  array[i] = 0; /* only to quiet the static checker */
1272  numaGetIValue(na, i, &num);
1273  if (num > 0) {
1274  pixcmapAddColor(cmap, i, i, i);
1275  array[i] = index;
1276  index++;
1277  }
1278  }
1279 
1280  datas = pixGetData(pixs);
1281  wpls = pixGetWpl(pixs);
1282  datad = pixGetData(pixd);
1283  wpld = pixGetWpl(pixd);
1284  for (i = 0; i < h; i++) {
1285  lines = datas + i * wpls;
1286  lined = datad + i * wpld;
1287  for (j = 0; j < w; j++) {
1288  val = GET_DATA_BYTE(lines, j);
1289  newval = array[val];
1290  if (depth == 2)
1291  SET_DATA_DIBIT(lined, j, newval);
1292  else if (depth == 4)
1293  SET_DATA_QBIT(lined, j, newval);
1294  else /* depth == 8 */
1295  SET_DATA_BYTE(lined, j, newval);
1296  }
1297  }
1298 
1299  numaDestroy(&na);
1300  return pixd;
1301 }
1302 
1303 
1304 /*---------------------------------------------------------------------------*
1305  * Colorizing conversion from grayscale to color *
1306  *---------------------------------------------------------------------------*/
1322 PIX *
1324  l_uint32 color,
1325  l_int32 cmapflag)
1326 {
1327 l_int32 i, j, w, h, wplt, wpld, val8;
1328 l_uint32 *datad, *datat, *lined, *linet, *tab;
1329 PIX *pixt, *pixd;
1330 PIXCMAP *cmap;
1331 
1332  PROCNAME("pixColorizeGray");
1333 
1334  if (!pixs)
1335  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1336  if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
1337  return (PIX *)ERROR_PTR("pixs not 8 bpp or cmapped", procName, NULL);
1338 
1339  if (pixGetColormap(pixs))
1341  else
1342  pixt = pixClone(pixs);
1343 
1344  cmap = pixcmapGrayToColor(color);
1345  if (cmapflag) {
1346  pixd = pixCopy(NULL, pixt);
1347  pixSetColormap(pixd, cmap);
1348  pixDestroy(&pixt);
1349  return pixd;
1350  }
1351 
1352  /* Make an RGB pix */
1353  pixcmapToRGBTable(cmap, &tab, NULL);
1354  pixGetDimensions(pixt, &w, &h, NULL);
1355  pixd = pixCreate(w, h, 32);
1356  pixCopyResolution(pixd, pixs);
1357  pixCopyInputFormat(pixd, pixs);
1358  datad = pixGetData(pixd);
1359  wpld = pixGetWpl(pixd);
1360  datat = pixGetData(pixt);
1361  wplt = pixGetWpl(pixt);
1362  for (i = 0; i < h; i++) {
1363  lined = datad + i * wpld;
1364  linet = datat + i * wplt;
1365  for (j = 0; j < w; j++) {
1366  val8 = GET_DATA_BYTE(linet, j);
1367  lined[j] = tab[val8];
1368  }
1369  }
1370 
1371  pixDestroy(&pixt);
1372  pixcmapDestroy(&cmap);
1373  LEPT_FREE(tab);
1374  return pixd;
1375 }
1376 
1377 
1378 /*---------------------------------------------------------------------------*
1379  * Conversion from RGB color to colormap *
1380  *---------------------------------------------------------------------------*/
1411 PIX *
1413  l_int32 ditherflag)
1414 {
1415 l_int32 ncolors;
1416 NUMA *na;
1417 PIX *pixd;
1418 
1419  PROCNAME("pixConvertRGBToColormap");
1420 
1421  if (!pixs)
1422  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1423  if (pixGetDepth(pixs) != 32)
1424  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1425  if (pixGetSpp(pixs) == 4)
1426  L_WARNING("pixs has alpha; removing\n", procName);
1427 
1428  /* Get the histogram and count the number of occupied level 4
1429  * leaf octcubes. We don't yet know if this is the number of
1430  * actual colors, but if it's not, all pixels falling into
1431  * the same leaf octcube will be assigned to the color of the
1432  * first pixel that lands there. */
1433  na = pixOctcubeHistogram(pixs, 4, &ncolors);
1434 
1435  /* If there are too many occupied leaf octcubes to be
1436  * represented directly in a colormap, fall back to octree
1437  * quantization, optionally with dithering. */
1438  if (ncolors > 256) {
1439  numaDestroy(&na);
1440  if (ditherflag)
1441  L_INFO("More than 256 colors; using octree quant with dithering\n",
1442  procName);
1443  else
1444  L_INFO("More than 256 colors; using octree quant; no dithering\n",
1445  procName);
1446  return pixOctreeColorQuant(pixs, 240, ditherflag);
1447  }
1448 
1449  /* There are not more than 256 occupied leaf octcubes.
1450  * Quantize to those octcubes. */
1451  pixd = pixFewColorsOctcubeQuant2(pixs, 4, na, ncolors, NULL);
1452  pixCopyInputFormat(pixd, pixs);
1453  numaDestroy(&na);
1454  return pixd;
1455 }
1456 
1457 
1458 /*---------------------------------------------------------------------------*
1459  * Conversion from colormap to 1 bpp *
1460  *---------------------------------------------------------------------------*/
1476 PIX *
1478 {
1479 l_int32 i, j, nc, w, h, imin, imax, factor, wpl1, wpld;
1480 l_int32 index, rmin, gmin, bmin, rmax, gmax, bmax, dmin, dmax;
1481 l_float32 minfract, ifract;
1482 l_int32 *lut;
1483 l_uint32 *line1, *lined, *data1, *datad;
1484 NUMA *na1, *na2; /* histograms */
1485 PIX *pix1, *pixd;
1486 PIXCMAP *cmap;
1487 
1488  PROCNAME("pixConvertCmapTo1");
1489 
1490  if (!pixs)
1491  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1492  if ((cmap = pixGetColormap(pixs)) == NULL)
1493  return (PIX *)ERROR_PTR("no colormap", procName, NULL);
1494 
1495  /* Select target colors for the two classes. Find the
1496  * colors with smallest and largest average component values.
1497  * The smallest is class 0 and the largest is class 1. */
1498  pixcmapGetRangeValues(cmap, L_SELECT_AVERAGE, NULL, NULL, &imin, &imax);
1499  pixcmapGetColor(cmap, imin, &rmin, &gmin, &bmin);
1500  pixcmapGetColor(cmap, imax, &rmax, &gmax, &bmax);
1501  nc = pixcmapGetCount(cmap);
1502 
1503  /* Assign colors to the two classes. The histogram is
1504  * initialized to 0, so any colors not found when computing
1505  * the sampled histogram will get zero weight in minfract. */
1506  if ((lut = (l_int32 *)LEPT_CALLOC(nc, sizeof(l_int32))) == NULL)
1507  return (PIX *)ERROR_PTR("calloc fail for lut", procName, NULL);
1508  pixGetDimensions(pixs, &w, &h, NULL);
1509  factor = L_MAX(1, (l_int32)sqrt((l_float64)(w * h) / 50000. + 0.5));
1510  na1 = pixGetCmapHistogram(pixs, factor);
1511  na2 = numaNormalizeHistogram(na1, 1.0);
1512  minfract = 0.0;
1513  for (i = 0; i < nc; i++) {
1514  numaGetFValue(na2, i, &ifract);
1515  pixcmapGetDistanceToColor(cmap, i, rmin, gmin, bmin, &dmin);
1516  pixcmapGetDistanceToColor(cmap, i, rmax, gmax, bmax, &dmax);
1517  if (dmin < dmax) { /* closer to dark extreme value */
1518  lut[i] = 1; /* black pixel in 1 bpp image */
1519  minfract += ifract;
1520  }
1521  }
1522  numaDestroy(&na1);
1523  numaDestroy(&na2);
1524 
1525  /* Generate the output binarized image */
1526  pix1 = pixConvertTo8(pixs, 1);
1527  pixd = pixCreate(w, h, 1);
1528  data1 = pixGetData(pix1);
1529  datad = pixGetData(pixd);
1530  wpl1 = pixGetWpl(pix1);
1531  wpld = pixGetWpl(pixd);
1532  for (i = 0; i < h; i++) {
1533  line1 = data1 + i * wpl1;
1534  lined = datad + i * wpld;
1535  for (j = 0; j < w; j++) {
1536  index = GET_DATA_BYTE(line1, j);
1537  if (lut[index] == 1) SET_DATA_BIT(lined, j);
1538  }
1539  }
1540  pixDestroy(&pix1);
1541  LEPT_FREE(lut);
1542 
1543  /* We expect minfract (the dark colors) to be less than 0.5.
1544  * If that is not the case, invert pixd. */
1545  if (minfract > 0.5) {
1546  L_INFO("minfract = %5.3f; inverting\n", procName, minfract);
1547  pixInvert(pixd, pixd);
1548  }
1549 
1550  return pixd;
1551 }
1552 
1553 
1554 /*---------------------------------------------------------------------------*
1555  * Quantization for relatively small number of colors in source *
1556  *---------------------------------------------------------------------------*/
1587 l_ok
1589  l_int32 maxcolors,
1590  l_int32 mingraycolors,
1591  l_int32 octlevel,
1592  PIX **ppixd)
1593 {
1594 l_int32 d, ncolors, iscolor, graycolors;
1595 PIX *pixg, *pixd;
1596 
1597  PROCNAME("pixQuantizeIfFewColors");
1598 
1599  if (!ppixd)
1600  return ERROR_INT("&pixd not defined", procName, 1);
1601  *ppixd = NULL;
1602  if (!pixs)
1603  return ERROR_INT("pixs not defined", procName, 1);
1604  d = pixGetDepth(pixs);
1605  if (d != 8 && d != 32)
1606  return ERROR_INT("pixs not defined", procName, 1);
1607  if (pixGetColormap(pixs) != NULL) {
1608  *ppixd = pixClone(pixs);
1609  return 0;
1610  }
1611  if (maxcolors <= 0)
1612  maxcolors = 15; /* default */
1613  if (maxcolors > 50)
1614  L_WARNING("maxcolors > 50; very large!\n", procName);
1615  if (mingraycolors <= 0)
1616  mingraycolors = 10; /* default */
1617  if (mingraycolors > 30)
1618  L_WARNING("mingraycolors > 30; very large!\n", procName);
1619  if (octlevel != 3 && octlevel != 4) {
1620  L_WARNING("invalid octlevel; setting to 3\n", procName);
1621  octlevel = 3;
1622  }
1623 
1624  /* Test the number of colors. For color, the octcube leaves
1625  * are at level 4. */
1626  pixColorsForQuantization(pixs, 0, &ncolors, &iscolor, 0);
1627  if (ncolors > maxcolors)
1628  return ERROR_INT("too many colors", procName, 1);
1629 
1630  /* Quantize!
1631  * (1) For color:
1632  * If octlevel == 4, try to quantize to an octree where
1633  * the octcube leaves are at level 4. If that fails,
1634  * back off to level 3.
1635  * If octlevel == 3, quantize to level 3 directly.
1636  * For level 3, the quality is usually good enough and there
1637  * is negligible chance of getting more than 256 colors.
1638  * (2) For grayscale, multiply ncolors by 1.5 for extra quality,
1639  * but use at least mingraycolors and not more than 256. */
1640  if (iscolor) {
1641  pixd = pixFewColorsOctcubeQuant1(pixs, octlevel);
1642  if (!pixd) { /* backoff */
1643  pixd = pixFewColorsOctcubeQuant1(pixs, octlevel - 1);
1644  if (octlevel == 3) /* shouldn't happen */
1645  L_WARNING("quantized at level 2; low quality\n", procName);
1646  }
1647  } else { /* image is really grayscale */
1648  if (d == 32)
1649  pixg = pixConvertRGBToLuminance(pixs);
1650  else
1651  pixg = pixClone(pixs);
1652  graycolors = L_MAX(mingraycolors, (l_int32)(1.5 * ncolors));
1653  graycolors = L_MIN(graycolors, 256);
1654  if (graycolors < 16)
1655  pixd = pixThresholdTo4bpp(pixg, graycolors, 1);
1656  else
1657  pixd = pixThresholdOn8bpp(pixg, graycolors, 1);
1658  pixDestroy(&pixg);
1659  }
1660  *ppixd = pixd;
1661 
1662  if (!pixd)
1663  return ERROR_INT("pixd not made", procName, 1);
1664  pixCopyInputFormat(pixd, pixs);
1665  return 0;
1666 }
1667 
1668 
1669 
1670 /*---------------------------------------------------------------------------*
1671  * Conversion from 16 bpp to 8 bpp *
1672  *---------------------------------------------------------------------------*/
1688 PIX *
1690  l_int32 type)
1691 {
1692 l_uint16 dword;
1693 l_int32 w, h, wpls, wpld, i, j, val, use_lsb;
1694 l_uint32 sword, first, second;
1695 l_uint32 *datas, *datad, *lines, *lined;
1696 PIX *pixd;
1697 
1698  PROCNAME("pixConvert16To8");
1699 
1700  if (!pixs)
1701  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1702  if (pixGetDepth(pixs) != 16)
1703  return (PIX *)ERROR_PTR("pixs not 16 bpp", procName, NULL);
1704  if (type != L_LS_BYTE && type != L_MS_BYTE &&
1705  type != L_AUTO_BYTE && type != L_CLIP_TO_FF)
1706  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
1707 
1708  pixGetDimensions(pixs, &w, &h, NULL);
1709  if ((pixd = pixCreate(w, h, 8)) == NULL)
1710  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1711  pixCopyInputFormat(pixd, pixs);
1712  pixCopyResolution(pixd, pixs);
1713  wpls = pixGetWpl(pixs);
1714  datas = pixGetData(pixs);
1715  wpld = pixGetWpl(pixd);
1716  datad = pixGetData(pixd);
1717 
1718  if (type == L_AUTO_BYTE) {
1719  use_lsb = TRUE;
1720  for (i = 0; i < h; i++) {
1721  lines = datas + i * wpls;
1722  for (j = 0; j < wpls; j++) {
1723  val = GET_DATA_TWO_BYTES(lines, j);
1724  if (val > 255) {
1725  use_lsb = FALSE;
1726  break;
1727  }
1728  }
1729  if (!use_lsb) break;
1730  }
1731  type = (use_lsb) ? L_LS_BYTE : L_MS_BYTE;
1732  }
1733 
1734  /* Convert 2 pixels at a time */
1735  for (i = 0; i < h; i++) {
1736  lines = datas + i * wpls;
1737  lined = datad + i * wpld;
1738  if (type == L_LS_BYTE) {
1739  for (j = 0; j < wpls; j++) {
1740  sword = *(lines + j);
1741  dword = ((sword >> 8) & 0xff00) | (sword & 0xff);
1742  SET_DATA_TWO_BYTES(lined, j, dword);
1743  }
1744  } else if (type == L_MS_BYTE) {
1745  for (j = 0; j < wpls; j++) {
1746  sword = *(lines + j);
1747  dword = ((sword >> 16) & 0xff00) | ((sword >> 8) & 0xff);
1748  SET_DATA_TWO_BYTES(lined, j, dword);
1749  }
1750  } else { /* type == L_CLIP_TO_FF */
1751  for (j = 0; j < wpls; j++) {
1752  sword = *(lines + j);
1753  first = (sword >> 24) ? 255 : ((sword >> 16) & 0xff);
1754  second = ((sword >> 8) & 0xff) ? 255 : (sword & 0xff);
1755  dword = (first << 8) | second;
1756  SET_DATA_TWO_BYTES(lined, j, dword);
1757  }
1758  }
1759  }
1760 
1761  return pixd;
1762 }
1763 
1764 
1765 
1766 /*---------------------------------------------------------------------------*
1767  * Conversion from grayscale to false color
1768  *---------------------------------------------------------------------------*/
1785 PIX *
1787  l_float32 gamma)
1788 {
1789 l_int32 d, i, rval, bval, gval;
1790 l_int32 *curve;
1791 l_float32 invgamma, x;
1792 PIX *pixd;
1793 PIXCMAP *cmap;
1794 
1795  PROCNAME("pixConvertGrayToFalseColor");
1796 
1797  if (!pixs)
1798  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1799  d = pixGetDepth(pixs);
1800  if (d != 8 && d != 16)
1801  return (PIX *)ERROR_PTR("pixs not 8 or 16 bpp", procName, NULL);
1802 
1803  if (d == 16) {
1804  pixd = pixConvert16To8(pixs, L_MS_BYTE);
1805  } else { /* d == 8 */
1806  if (pixGetColormap(pixs))
1808  else
1809  pixd = pixCopy(NULL, pixs);
1810  }
1811  if (!pixd)
1812  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1813  cmap = pixcmapCreate(8);
1814  pixSetColormap(pixd, cmap);
1815  pixCopyResolution(pixd, pixs);
1816  pixCopyInputFormat(pixd, pixs);
1817 
1818  /* Generate curve for transition part of color map */
1819  curve = (l_int32 *)LEPT_CALLOC(64, sizeof(l_int32));
1820  if (gamma == 0.0) gamma = 1.0;
1821  invgamma = 1. / gamma;
1822  for (i = 0; i < 64; i++) {
1823  x = (l_float32)i / 64.;
1824  curve[i] = (l_int32)(255. * powf(x, invgamma) + 0.5);
1825  }
1826 
1827  for (i = 0; i < 256; i++) {
1828  if (i < 32) {
1829  rval = 0;
1830  gval = 0;
1831  bval = curve[i + 32];
1832  } else if (i < 96) { /* 32 - 95 */
1833  rval = 0;
1834  gval = curve[i - 32];
1835  bval = 255;
1836  } else if (i < 160) { /* 96 - 159 */
1837  rval = curve[i - 96];
1838  gval = 255;
1839  bval = curve[159 - i];
1840  } else if (i < 224) { /* 160 - 223 */
1841  rval = 255;
1842  gval = curve[223 - i];
1843  bval = 0;
1844  } else { /* 224 - 255 */
1845  rval = curve[287 - i];
1846  gval = 0;
1847  bval = 0;
1848  }
1849  pixcmapAddColor(cmap, rval, gval, bval);
1850  }
1851 
1852  LEPT_FREE(curve);
1853  return pixd;
1854 }
1855 
1856 
1857 /*---------------------------------------------------------------------------*
1858  * Unpacking conversion from 1 bpp to 2, 4, 8, 16 and 32 bpp *
1859  *---------------------------------------------------------------------------*/
1877 PIX *
1879  l_int32 depth,
1880  l_int32 invert)
1881 {
1882 PIX *pixd;
1883 
1884  PROCNAME("pixUnpackBinary");
1885 
1886  if (!pixs)
1887  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1888  if (pixGetDepth(pixs) != 1)
1889  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
1890  if (depth != 2 && depth != 4 && depth != 8 && depth != 16 && depth != 32)
1891  return (PIX *)ERROR_PTR("depth not 2, 4, 8, 16 or 32 bpp",
1892  procName, NULL);
1893 
1894  if (depth == 2) {
1895  if (invert == 0)
1896  pixd = pixConvert1To2(NULL, pixs, 0, 3);
1897  else /* invert bits */
1898  pixd = pixConvert1To2(NULL, pixs, 3, 0);
1899  } else if (depth == 4) {
1900  if (invert == 0)
1901  pixd = pixConvert1To4(NULL, pixs, 0, 15);
1902  else /* invert bits */
1903  pixd = pixConvert1To4(NULL, pixs, 15, 0);
1904  } else if (depth == 8) {
1905  if (invert == 0)
1906  pixd = pixConvert1To8(NULL, pixs, 0, 255);
1907  else /* invert bits */
1908  pixd = pixConvert1To8(NULL, pixs, 255, 0);
1909  } else if (depth == 16) {
1910  if (invert == 0)
1911  pixd = pixConvert1To16(NULL, pixs, 0, 0xffff);
1912  else /* invert bits */
1913  pixd = pixConvert1To16(NULL, pixs, 0xffff, 0);
1914  } else {
1915  if (invert == 0)
1916  pixd = pixConvert1To32(NULL, pixs, 0, 0xffffffff);
1917  else /* invert bits */
1918  pixd = pixConvert1To32(NULL, pixs, 0xffffffff, 0);
1919  }
1920 
1921  pixCopyInputFormat(pixd, pixs);
1922  return pixd;
1923 }
1924 
1925 
1942 PIX *
1944  PIX *pixs,
1945  l_uint16 val0,
1946  l_uint16 val1)
1947 {
1948 l_int32 w, h, i, j, dibit, ndibits, wpls, wpld;
1949 l_uint16 val[2];
1950 l_uint32 index;
1951 l_uint32 *tab, *datas, *datad, *lines, *lined;
1952 
1953  PROCNAME("pixConvert1To16");
1954 
1955  if (!pixs)
1956  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1957  if (pixGetDepth(pixs) != 1)
1958  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
1959 
1960  pixGetDimensions(pixs, &w, &h, NULL);
1961  if (pixd) {
1962  if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
1963  return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
1964  if (pixGetDepth(pixd) != 16)
1965  return (PIX *)ERROR_PTR("pixd not 16 bpp", procName, pixd);
1966  } else {
1967  if ((pixd = pixCreate(w, h, 16)) == NULL)
1968  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1969  }
1970  pixCopyResolution(pixd, pixs);
1971  pixCopyInputFormat(pixd, pixs);
1972 
1973  /* Use a table to convert 2 src bits at a time */
1974  tab = (l_uint32 *)LEPT_CALLOC(4, sizeof(l_uint32));
1975  val[0] = val0;
1976  val[1] = val1;
1977  for (index = 0; index < 4; index++) {
1978  tab[index] = (val[(index >> 1) & 1] << 16) | val[index & 1];
1979  }
1980 
1981  datas = pixGetData(pixs);
1982  wpls = pixGetWpl(pixs);
1983  datad = pixGetData(pixd);
1984  wpld = pixGetWpl(pixd);
1985  ndibits = (w + 1) / 2;
1986  for (i = 0; i < h; i++) {
1987  lines = datas + i * wpls;
1988  lined = datad + i * wpld;
1989  for (j = 0; j < ndibits; j++) {
1990  dibit = GET_DATA_DIBIT(lines, j);
1991  lined[j] = tab[dibit];
1992  }
1993  }
1994 
1995  LEPT_FREE(tab);
1996  return pixd;
1997 }
1998 
1999 
2016 PIX *
2018  PIX *pixs,
2019  l_uint32 val0,
2020  l_uint32 val1)
2021 {
2022 l_int32 w, h, i, j, wpls, wpld, bit;
2023 l_uint32 val[2];
2024 l_uint32 *datas, *datad, *lines, *lined;
2025 
2026  PROCNAME("pixConvert1To32");
2027 
2028  if (!pixs)
2029  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2030  if (pixGetDepth(pixs) != 1)
2031  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2032 
2033  pixGetDimensions(pixs, &w, &h, NULL);
2034  if (pixd) {
2035  if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2036  return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2037  if (pixGetDepth(pixd) != 32)
2038  return (PIX *)ERROR_PTR("pixd not 32 bpp", procName, pixd);
2039  } else {
2040  if ((pixd = pixCreate(w, h, 32)) == NULL)
2041  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2042  }
2043  pixCopyResolution(pixd, pixs);
2044  pixCopyInputFormat(pixd, pixs);
2045 
2046  val[0] = val0;
2047  val[1] = val1;
2048  datas = pixGetData(pixs);
2049  wpls = pixGetWpl(pixs);
2050  datad = pixGetData(pixd);
2051  wpld = pixGetWpl(pixd);
2052  for (i = 0; i < h; i++) {
2053  lines = datas + i * wpls;
2054  lined = datad + i * wpld;
2055  for (j = 0; j <w; j++) {
2056  bit = GET_DATA_BIT(lines, j);
2057  lined[j] = val[bit];
2058  }
2059  }
2060 
2061  return pixd;
2062 }
2063 
2064 
2065 /*---------------------------------------------------------------------------*
2066  * Conversion from 1 bpp to 2 bpp *
2067  *---------------------------------------------------------------------------*/
2079 PIX *
2081 {
2082 PIX *pixd;
2083 PIXCMAP *cmap;
2084 
2085  PROCNAME("pixConvert1To2Cmap");
2086 
2087  if (!pixs)
2088  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2089  if (pixGetDepth(pixs) != 1)
2090  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2091 
2092  if ((pixd = pixConvert1To2(NULL, pixs, 0, 1)) == NULL)
2093  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2094  cmap = pixcmapCreate(2);
2095  pixcmapAddColor(cmap, 255, 255, 255);
2096  pixcmapAddColor(cmap, 0, 0, 0);
2097  pixSetColormap(pixd, cmap);
2098  pixCopyInputFormat(pixd, pixs);
2099 
2100  return pixd;
2101 }
2102 
2103 
2122 PIX *
2124  PIX *pixs,
2125  l_int32 val0,
2126  l_int32 val1)
2127 {
2128 l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2129 l_uint8 val[2];
2130 l_uint32 index;
2131 l_uint16 *tab;
2132 l_uint32 *datas, *datad, *lines, *lined;
2133 
2134  PROCNAME("pixConvert1To2");
2135 
2136  if (!pixs)
2137  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
2138  if (pixGetDepth(pixs) != 1)
2139  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
2140 
2141  pixGetDimensions(pixs, &w, &h, NULL);
2142  if (pixd) {
2143  if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2144  return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2145  if (pixGetDepth(pixd) != 2)
2146  return (PIX *)ERROR_PTR("pixd not 2 bpp", procName, pixd);
2147  } else {
2148  if ((pixd = pixCreate(w, h, 2)) == NULL)
2149  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2150  }
2151  pixCopyResolution(pixd, pixs);
2152  pixCopyInputFormat(pixd, pixs);
2153 
2154  /* Use a table to convert 8 src bits to 16 dest bits */
2155  tab = (l_uint16 *)LEPT_CALLOC(256, sizeof(l_uint16));
2156  val[0] = val0;
2157  val[1] = val1;
2158  for (index = 0; index < 256; index++) {
2159  tab[index] = (val[(index >> 7) & 1] << 14) |
2160  (val[(index >> 6) & 1] << 12) |
2161  (val[(index >> 5) & 1] << 10) |
2162  (val[(index >> 4) & 1] << 8) |
2163  (val[(index >> 3) & 1] << 6) |
2164  (val[(index >> 2) & 1] << 4) |
2165  (val[(index >> 1) & 1] << 2) | val[index & 1];
2166  }
2167 
2168  datas = pixGetData(pixs);
2169  wpls = pixGetWpl(pixs);
2170  datad = pixGetData(pixd);
2171  wpld = pixGetWpl(pixd);
2172  nbytes = (w + 7) / 8;
2173  for (i = 0; i < h; i++) {
2174  lines = datas + i * wpls;
2175  lined = datad + i * wpld;
2176  for (j = 0; j < nbytes; j++) {
2177  byteval = GET_DATA_BYTE(lines, j);
2178  SET_DATA_TWO_BYTES(lined, j, tab[byteval]);
2179  }
2180  }
2181 
2182  LEPT_FREE(tab);
2183  return pixd;
2184 }
2185 
2186 
2187 /*---------------------------------------------------------------------------*
2188  * Conversion from 1 bpp to 4 bpp *
2189  *---------------------------------------------------------------------------*/
2201 PIX *
2203 {
2204 PIX *pixd;
2205 PIXCMAP *cmap;
2206 
2207  PROCNAME("pixConvert1To4Cmap");
2208 
2209  if (!pixs)
2210  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2211  if (pixGetDepth(pixs) != 1)
2212  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2213 
2214  if ((pixd = pixConvert1To4(NULL, pixs, 0, 1)) == NULL)
2215  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2216  cmap = pixcmapCreate(4);
2217  pixcmapAddColor(cmap, 255, 255, 255);
2218  pixcmapAddColor(cmap, 0, 0, 0);
2219  pixSetColormap(pixd, cmap);
2220  pixCopyInputFormat(pixd, pixs);
2221 
2222  return pixd;
2223 }
2224 
2225 
2244 PIX *
2246  PIX *pixs,
2247  l_int32 val0,
2248  l_int32 val1)
2249 {
2250 l_int32 w, h, i, j, byteval, nbytes, wpls, wpld;
2251 l_uint8 val[2];
2252 l_uint32 index;
2253 l_uint32 *tab, *datas, *datad, *lines, *lined;
2254 
2255  PROCNAME("pixConvert1To4");
2256 
2257  if (!pixs)
2258  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
2259  if (pixGetDepth(pixs) != 1)
2260  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
2261 
2262  pixGetDimensions(pixs, &w, &h, NULL);
2263  if (pixd) {
2264  if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2265  return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2266  if (pixGetDepth(pixd) != 4)
2267  return (PIX *)ERROR_PTR("pixd not 4 bpp", procName, pixd);
2268  } else {
2269  if ((pixd = pixCreate(w, h, 4)) == NULL)
2270  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2271  }
2272  pixCopyResolution(pixd, pixs);
2273  pixCopyInputFormat(pixd, pixs);
2274 
2275  /* Use a table to convert 8 src bits to 32 bit dest word */
2276  tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
2277  val[0] = val0;
2278  val[1] = val1;
2279  for (index = 0; index < 256; index++) {
2280  tab[index] = (val[(index >> 7) & 1] << 28) |
2281  (val[(index >> 6) & 1] << 24) |
2282  (val[(index >> 5) & 1] << 20) |
2283  (val[(index >> 4) & 1] << 16) |
2284  (val[(index >> 3) & 1] << 12) |
2285  (val[(index >> 2) & 1] << 8) |
2286  (val[(index >> 1) & 1] << 4) | val[index & 1];
2287  }
2288 
2289  datas = pixGetData(pixs);
2290  wpls = pixGetWpl(pixs);
2291  datad = pixGetData(pixd);
2292  wpld = pixGetWpl(pixd);
2293  nbytes = (w + 7) / 8;
2294  for (i = 0; i < h; i++) {
2295  lines = datas + i * wpls;
2296  lined = datad + i * wpld;
2297  for (j = 0; j < nbytes; j++) {
2298  byteval = GET_DATA_BYTE(lines, j);
2299  lined[j] = tab[byteval];
2300  }
2301  }
2302 
2303  LEPT_FREE(tab);
2304  return pixd;
2305 }
2306 
2307 
2308 /*---------------------------------------------------------------------------*
2309  * Conversion from 1, 2 and 4 bpp to 8 bpp *
2310  *---------------------------------------------------------------------------*/
2322 PIX *
2324 {
2325 PIX *pixd;
2326 PIXCMAP *cmap;
2327 
2328  PROCNAME("pixConvert1To8Cmap");
2329 
2330  if (!pixs)
2331  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2332  if (pixGetDepth(pixs) != 1)
2333  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
2334 
2335  if ((pixd = pixConvert1To8(NULL, pixs, 0, 1)) == NULL)
2336  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2337  cmap = pixcmapCreate(8);
2338  pixcmapAddColor(cmap, 255, 255, 255);
2339  pixcmapAddColor(cmap, 0, 0, 0);
2340  pixSetColormap(pixd, cmap);
2341  pixCopyInputFormat(pixd, pixs);
2342  return pixd;
2343 }
2344 
2345 
2365 PIX *
2367  PIX *pixs,
2368  l_uint8 val0,
2369  l_uint8 val1)
2370 {
2371 l_int32 w, h, i, j, qbit, nqbits, wpls, wpld;
2372 l_uint8 val[2];
2373 l_uint32 index;
2374 l_uint32 *tab, *datas, *datad, *lines, *lined;
2375 
2376  PROCNAME("pixConvert1To8");
2377 
2378  if (!pixs)
2379  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
2380  if (pixGetDepth(pixs) != 1)
2381  return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, pixd);
2382 
2383  pixGetDimensions(pixs, &w, &h, NULL);
2384  if (pixd) {
2385  if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2386  return (PIX *)ERROR_PTR("pix sizes unequal", procName, pixd);
2387  if (pixGetDepth(pixd) != 8)
2388  return (PIX *)ERROR_PTR("pixd not 8 bpp", procName, pixd);
2389  } else {
2390  if ((pixd = pixCreate(w, h, 8)) == NULL)
2391  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2392  }
2393  pixCopyResolution(pixd, pixs);
2394  pixCopyInputFormat(pixd, pixs);
2395 
2396  /* Use a table to convert 4 src bits at a time */
2397  tab = (l_uint32 *)LEPT_CALLOC(16, sizeof(l_uint32));
2398  val[0] = val0;
2399  val[1] = val1;
2400  for (index = 0; index < 16; index++) {
2401  tab[index] = ((l_uint32)val[(index >> 3) & 1] << 24) |
2402  (val[(index >> 2) & 1] << 16) |
2403  (val[(index >> 1) & 1] << 8) | val[index & 1];
2404  }
2405 
2406  datas = pixGetData(pixs);
2407  wpls = pixGetWpl(pixs);
2408  datad = pixGetData(pixd);
2409  wpld = pixGetWpl(pixd);
2410  nqbits = (w + 3) / 4;
2411  for (i = 0; i < h; i++) {
2412  lines = datas + i * wpls;
2413  lined = datad + i * wpld;
2414  for (j = 0; j < nqbits; j++) {
2415  qbit = GET_DATA_QBIT(lines, j);
2416  lined[j] = tab[qbit];
2417  }
2418  }
2419 
2420  LEPT_FREE(tab);
2421  return pixd;
2422 }
2423 
2424 
2455 PIX *
2457  l_uint8 val0,
2458  l_uint8 val1,
2459  l_uint8 val2,
2460  l_uint8 val3,
2461  l_int32 cmapflag)
2462 {
2463 l_int32 w, h, i, j, nbytes, wpls, wpld, dibit, byte;
2464 l_uint8 val[4];
2465 l_uint32 index;
2466 l_uint32 *tab, *datas, *datad, *lines, *lined;
2467 PIX *pixd;
2468 PIXCMAP *cmaps, *cmapd;
2469 
2470  PROCNAME("pixConvert2To8");
2471 
2472  if (!pixs)
2473  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2474  if (pixGetDepth(pixs) != 2)
2475  return (PIX *)ERROR_PTR("pixs not 2 bpp", procName, NULL);
2476 
2477  cmaps = pixGetColormap(pixs);
2478  if (cmaps && cmapflag == FALSE)
2480 
2481  pixGetDimensions(pixs, &w, &h, NULL);
2482  if ((pixd = pixCreate(w, h, 8)) == NULL)
2483  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2484  pixCopyResolution(pixd, pixs);
2485  pixCopyInputFormat(pixd, pixs);
2486  datas = pixGetData(pixs);
2487  wpls = pixGetWpl(pixs);
2488  datad = pixGetData(pixd);
2489  wpld = pixGetWpl(pixd);
2490 
2491  if (cmapflag == TRUE) { /* pixd will have a colormap */
2492  if (cmaps) { /* use the existing colormap from pixs */
2493  cmapd = pixcmapConvertTo8(cmaps);
2494  } else { /* make a colormap from the input values */
2495  cmapd = pixcmapCreate(8);
2496  pixcmapAddColor(cmapd, val0, val0, val0);
2497  pixcmapAddColor(cmapd, val1, val1, val1);
2498  pixcmapAddColor(cmapd, val2, val2, val2);
2499  pixcmapAddColor(cmapd, val3, val3, val3);
2500  }
2501  pixSetColormap(pixd, cmapd);
2502  for (i = 0; i < h; i++) {
2503  lines = datas + i * wpls;
2504  lined = datad + i * wpld;
2505  for (j = 0; j < w; j++) {
2506  dibit = GET_DATA_DIBIT(lines, j);
2507  SET_DATA_BYTE(lined, j, dibit);
2508  }
2509  }
2510  return pixd;
2511  }
2512 
2513  /* Last case: no colormap in either pixs or pixd.
2514  * Use input values and build a table to convert 1 src byte
2515  * (4 src pixels) at a time */
2516  tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
2517  val[0] = val0;
2518  val[1] = val1;
2519  val[2] = val2;
2520  val[3] = val3;
2521  for (index = 0; index < 256; index++) {
2522  tab[index] = (val[(index >> 6) & 3] << 24) |
2523  (val[(index >> 4) & 3] << 16) |
2524  (val[(index >> 2) & 3] << 8) | val[index & 3];
2525  }
2526 
2527  nbytes = (w + 3) / 4;
2528  for (i = 0; i < h; i++) {
2529  lines = datas + i * wpls;
2530  lined = datad + i * wpld;
2531  for (j = 0; j < nbytes; j++) {
2532  byte = GET_DATA_BYTE(lines, j);
2533  lined[j] = tab[byte];
2534  }
2535  }
2536 
2537  LEPT_FREE(tab);
2538  return pixd;
2539 }
2540 
2541 
2566 PIX *
2568  l_int32 cmapflag)
2569 {
2570 l_int32 w, h, i, j, wpls, wpld, byte, qbit;
2571 l_uint32 *datas, *datad, *lines, *lined;
2572 PIX *pixd;
2573 PIXCMAP *cmaps, *cmapd;
2574 
2575  PROCNAME("pixConvert4To8");
2576 
2577  if (!pixs)
2578  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2579  if (pixGetDepth(pixs) != 4)
2580  return (PIX *)ERROR_PTR("pixs not 4 bpp", procName, NULL);
2581 
2582  cmaps = pixGetColormap(pixs);
2583  if (cmaps && cmapflag == FALSE)
2585 
2586  pixGetDimensions(pixs, &w, &h, NULL);
2587  if ((pixd = pixCreate(w, h, 8)) == NULL)
2588  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2589  pixCopyResolution(pixd, pixs);
2590  pixCopyInputFormat(pixd, pixs);
2591  datas = pixGetData(pixs);
2592  wpls = pixGetWpl(pixs);
2593  datad = pixGetData(pixd);
2594  wpld = pixGetWpl(pixd);
2595 
2596  if (cmapflag == TRUE) { /* pixd will have a colormap */
2597  if (cmaps) { /* use the existing colormap from pixs */
2598  cmapd = pixcmapConvertTo8(cmaps);
2599  } else { /* make a colormap with a linear trc */
2600  cmapd = pixcmapCreate(8);
2601  for (i = 0; i < 16; i++)
2602  pixcmapAddColor(cmapd, 17 * i, 17 * i, 17 * i);
2603  }
2604  pixSetColormap(pixd, cmapd);
2605  for (i = 0; i < h; i++) {
2606  lines = datas + i * wpls;
2607  lined = datad + i * wpld;
2608  for (j = 0; j < w; j++) {
2609  qbit = GET_DATA_QBIT(lines, j);
2610  SET_DATA_BYTE(lined, j, qbit);
2611  }
2612  }
2613  return pixd;
2614  }
2615 
2616  /* Last case: no colormap in either pixs or pixd.
2617  * Replicate the qbit value into 8 bits. */
2618  for (i = 0; i < h; i++) {
2619  lines = datas + i * wpls;
2620  lined = datad + i * wpld;
2621  for (j = 0; j < w; j++) {
2622  qbit = GET_DATA_QBIT(lines, j);
2623  byte = (qbit << 4) | qbit;
2624  SET_DATA_BYTE(lined, j, byte);
2625  }
2626  }
2627  return pixd;
2628 }
2629 
2630 
2631 
2632 /*---------------------------------------------------------------------------*
2633  * Unpacking conversion from 8 bpp to 16 bpp *
2634  *---------------------------------------------------------------------------*/
2651 PIX *
2653  l_int32 leftshift)
2654 {
2655 l_int32 i, j, w, h, d, wplt, wpld, val;
2656 l_uint32 *datat, *datad, *linet, *lined;
2657 PIX *pixt, *pixd;
2658 
2659  PROCNAME("pixConvert8To16");
2660 
2661  if (!pixs)
2662  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2663  pixGetDimensions(pixs, &w, &h, &d);
2664  if (d != 8)
2665  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
2666  if (leftshift < 0 || leftshift > 8)
2667  return (PIX *)ERROR_PTR("leftshift not in [0 ... 8]", procName, NULL);
2668 
2669  if (pixGetColormap(pixs) != NULL)
2671  else
2672  pixt = pixClone(pixs);
2673 
2674  pixd = pixCreate(w, h, 16);
2675  pixCopyResolution(pixd, pixs);
2676  pixCopyInputFormat(pixd, pixs);
2677  datat = pixGetData(pixt);
2678  datad = pixGetData(pixd);
2679  wplt = pixGetWpl(pixt);
2680  wpld = pixGetWpl(pixd);
2681  for (i = 0; i < h; i++) {
2682  linet = datat + i * wplt;
2683  lined = datad + i * wpld;
2684  for (j = 0; j < w; j++) {
2685  val = GET_DATA_BYTE(linet, j);
2686  if (leftshift == 8)
2687  val = val | (val << leftshift);
2688  else
2689  val <<= leftshift;
2690  SET_DATA_TWO_BYTES(lined, j, val);
2691  }
2692  }
2693 
2694  pixDestroy(&pixt);
2695  return pixd;
2696 }
2697 
2698 
2699 /*---------------------------------------------------------------------------*
2700  * Top-level conversion to 2 bpp *
2701  *---------------------------------------------------------------------------*/
2717 PIX *
2719 {
2720 l_int32 d;
2721 PIX *pix1, *pix2, *pix3, *pixd;
2722 
2723  PROCNAME("pixConvertTo2");
2724 
2725  if (!pixs)
2726  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2727  d = pixGetDepth(pixs);
2728  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
2729  return (PIX *)ERROR_PTR("depth not {1,2,4,8,32}", procName, NULL);
2730 
2731  if (pixGetColormap(pixs) != NULL) {
2733  d = pixGetDepth(pix1);
2734  } else {
2735  pix1 = pixCopy(NULL, pixs);
2736  }
2737  if (d == 32)
2738  pix2 = pixConvertTo8(pix1, FALSE);
2739  else
2740  pix2 = pixClone(pix1);
2741  pixDestroy(&pix1);
2742  if (d == 1) {
2743  pixd = pixConvert1To2(NULL, pix2, 3, 0);
2744  } else if (d == 2) {
2745  pixd = pixClone(pix2);
2746  } else if (d == 4) {
2747  pix3 = pixConvert4To8(pix2, FALSE); /* unpack to 8 */
2748  pixd = pixConvert8To2(pix3);
2749  pixDestroy(&pix3);
2750  } else { /* d == 8 */
2751  pixd = pixConvert8To2(pix2);
2752  }
2753  pixDestroy(&pix2);
2754  return pixd;
2755 }
2756 
2757 
2769 PIX *
2771 {
2772 l_int32 i, j, w, h, wpls, wpld;
2773 l_uint32 word;
2774 l_uint32 *datas, *lines, *datad, *lined;
2775 PIX *pixs, *pixd;
2776 
2777  PROCNAME("pixConvert8To2");
2778 
2779  if (!pix || pixGetDepth(pix) != 8)
2780  return (PIX *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2781 
2782  if (pixGetColormap(pix) != NULL)
2784  else
2785  pixs = pixClone(pix);
2786  pixGetDimensions(pixs, &w, &h, NULL);
2787  datas = pixGetData(pixs);
2788  wpls = pixGetWpl(pixs);
2789  pixd = pixCreate(w, h, 2);
2790  datad = pixGetData(pixd);
2791  wpld = pixGetWpl(pixd);
2792  for (i = 0; i < h; i++) {
2793  lines = datas + i * wpls;
2794  lined = datad + i * wpld;
2795  for (j = 0; j < wpls; j++) { /* march through 4 pixels at a time */
2796  word = lines[j] & 0xc0c0c0c0; /* top 2 bits of each byte */
2797  word = (word >> 24) | ((word & 0xff0000) >> 18) |
2798  ((word & 0xff00) >> 12) | ((word & 0xff) >> 6);
2799  SET_DATA_BYTE(lined, j, word); /* only LS byte is filled */
2800  }
2801  }
2802  pixDestroy(&pixs);
2803  return pixd;
2804 }
2805 
2806 
2807 /*---------------------------------------------------------------------------*
2808  * Top-level conversion to 4 bpp *
2809  *---------------------------------------------------------------------------*/
2825 PIX *
2827 {
2828 l_int32 d;
2829 PIX *pix1, *pix2, *pix3, *pixd;
2830 
2831  PROCNAME("pixConvertTo4");
2832 
2833  if (!pixs)
2834  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2835  d = pixGetDepth(pixs);
2836  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
2837  return (PIX *)ERROR_PTR("depth not {1,2,4,8,32}", procName, NULL);
2838 
2839  if (pixGetColormap(pixs) != NULL) {
2841  d = pixGetDepth(pix1);
2842  } else {
2843  pix1 = pixCopy(NULL, pixs);
2844  }
2845  if (d == 32)
2846  pix2 = pixConvertTo8(pix1, FALSE);
2847  else
2848  pix2 = pixClone(pix1);
2849  pixDestroy(&pix1);
2850  if (d == 1) {
2851  pixd = pixConvert1To4(NULL, pix2, 15, 0);
2852  } else if (d == 2) {
2853  pix3 = pixConvert2To8(pix2, 0, 0x55, 0xaa, 0xff, FALSE);
2854  pixd = pixConvert8To4(pix3);
2855  pixDestroy(&pix3);
2856  } else if (d == 4) {
2857  pixd = pixClone(pix2);
2858  } else { /* d == 8 */
2859  pixd = pixConvert8To4(pix2);
2860  }
2861  pixDestroy(&pix2);
2862  return pixd;
2863 }
2864 
2865 
2877 PIX *
2879 {
2880 l_int32 i, j, w, h, wpls, wpld, val;
2881 l_uint32 *datas, *lines, *datad, *lined;
2882 PIX *pixs, *pixd;
2883 
2884  PROCNAME("pixConvert8To4");
2885 
2886  if (!pix || pixGetDepth(pix) != 8)
2887  return (PIX *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2888 
2889  if (pixGetColormap(pix) != NULL)
2891  else
2892  pixs = pixClone(pix);
2893  pixGetDimensions(pixs, &w, &h, NULL);
2894  datas = pixGetData(pixs);
2895  wpls = pixGetWpl(pixs);
2896  pixd = pixCreate(w, h, 4);
2897  datad = pixGetData(pixd);
2898  wpld = pixGetWpl(pixd);
2899  for (i = 0; i < h; i++) {
2900  lines = datas + i * wpls;
2901  lined = datad + i * wpld;
2902  for (j = 0; j < w; j++) {
2903  val = GET_DATA_BYTE(lines, j);
2904  val = val >> 4; /* take top 4 bits */
2905  SET_DATA_QBIT(lined, j, val);
2906  }
2907  }
2908  pixDestroy(&pixs);
2909  return pixd;
2910 }
2911 
2912 
2913 /*---------------------------------------------------------------------------*
2914  * Top-level conversion to 1 bpp *
2915  *---------------------------------------------------------------------------*/
2932 PIX *
2934  l_int32 threshold)
2935 {
2936 l_int32 d, color0, color1, rval, gval, bval;
2937 PIX *pixg, *pixd;
2938 PIXCMAP *cmap;
2939 
2940  PROCNAME("pixConvertTo1");
2941 
2942  if (!pixs)
2943  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2944  d = pixGetDepth(pixs);
2945  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
2946  return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,32}", procName, NULL);
2947 
2948  cmap = pixGetColormap(pixs);
2949  if (d == 1) {
2950  if (!cmap) {
2951  return pixCopy(NULL, pixs);
2952  } else { /* strip the colormap off, and invert if reasonable
2953  for standard binary photometry. */
2954  pixcmapGetColor(cmap, 0, &rval, &gval, &bval);
2955  color0 = rval + gval + bval;
2956  pixcmapGetColor(cmap, 1, &rval, &gval, &bval);
2957  color1 = rval + gval + bval;
2958  pixd = pixCopy(NULL, pixs);
2959  pixDestroyColormap(pixd);
2960  if (color1 > color0)
2961  pixInvert(pixd, pixd);
2962  return pixd;
2963  }
2964  }
2965 
2966  /* For all other depths, use 8 bpp as an intermediary */
2967  pixg = pixConvertTo8(pixs, FALSE);
2968  pixd = pixThresholdToBinary(pixg, threshold);
2969  pixDestroy(&pixg);
2970  return pixd;
2971 }
2972 
2973 
2988 PIX *
2990  l_int32 factor,
2991  l_int32 threshold)
2992 {
2993 l_float32 scalefactor;
2994 PIX *pixt, *pixd;
2995 
2996  PROCNAME("pixConvertTo1BySampling");
2997 
2998  if (!pixs)
2999  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3000  if (factor < 1)
3001  return (PIX *)ERROR_PTR("factor must be >= 1", procName, NULL);
3002 
3003  scalefactor = 1. / (l_float32)factor;
3004  pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3005  pixd = pixConvertTo1(pixt, threshold);
3006 
3007  pixDestroy(&pixt);
3008  return pixd;
3009 }
3010 
3011 
3012 /*---------------------------------------------------------------------------*
3013  * Top-level conversion to 8 bpp *
3014  *---------------------------------------------------------------------------*/
3040 PIX *
3042  l_int32 cmapflag)
3043 {
3044 l_int32 d;
3045 PIX *pixd;
3046 PIXCMAP *cmap;
3047 
3048  PROCNAME("pixConvertTo8");
3049 
3050  if (!pixs)
3051  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3052  d = pixGetDepth(pixs);
3053  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
3054  return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,32}", procName, NULL);
3055 
3056  if (d == 1) {
3057  if (cmapflag)
3058  return pixConvert1To8Cmap(pixs);
3059  else
3060  return pixConvert1To8(NULL, pixs, 255, 0);
3061  } else if (d == 2) {
3062  return pixConvert2To8(pixs, 0, 85, 170, 255, cmapflag);
3063  } else if (d == 4) {
3064  return pixConvert4To8(pixs, cmapflag);
3065  } else if (d == 8) {
3066  cmap = pixGetColormap(pixs);
3067  if ((cmap && cmapflag) || (!cmap && !cmapflag)) {
3068  return pixCopy(NULL, pixs);
3069  } else if (cmap) { /* !cmapflag */
3071  } else { /* !cmap && cmapflag; add colormap to pixd */
3072  pixd = pixCopy(NULL, pixs);
3073  pixAddGrayColormap8(pixd);
3074  return pixd;
3075  }
3076  } else if (d == 16) {
3077  pixd = pixConvert16To8(pixs, L_MS_BYTE);
3078  if (cmapflag)
3079  pixAddGrayColormap8(pixd);
3080  return pixd;
3081  } else { /* d == 32 */
3082  pixd = pixConvertRGBToLuminance(pixs);
3083  if (cmapflag)
3084  pixAddGrayColormap8(pixd);
3085  return pixd;
3086  }
3087 }
3088 
3089 
3104 PIX *
3106  l_int32 factor,
3107  l_int32 cmapflag)
3108 {
3109 l_float32 scalefactor;
3110 PIX *pixt, *pixd;
3111 
3112  PROCNAME("pixConvertTo8BySampling");
3113 
3114  if (!pixs)
3115  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3116  if (factor < 1)
3117  return (PIX *)ERROR_PTR("factor must be >= 1", procName, NULL);
3118 
3119  scalefactor = 1. / (l_float32)factor;
3120  pixt = pixScaleBySampling(pixs, scalefactor, scalefactor);
3121  pixd = pixConvertTo8(pixt, cmapflag);
3122 
3123  pixDestroy(&pixt);
3124  return pixd;
3125 }
3126 
3127 
3148 PIX *
3150  l_int32 dither)
3151 {
3152 l_int32 d;
3153 
3154  PROCNAME("pixConvertTo8Colormap");
3155 
3156  if (!pixs)
3157  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3158  d = pixGetDepth(pixs);
3159  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
3160  return (PIX *)ERROR_PTR("depth not {1,2,4,8,16,32}", procName, NULL);
3161 
3162  if (d != 32)
3163  return pixConvertTo8(pixs, 1);
3164 
3165  return pixConvertRGBToColormap(pixs, dither);
3166 }
3167 
3168 
3169 /*---------------------------------------------------------------------------*
3170  * Top-level conversion to 16 bpp *
3171  *---------------------------------------------------------------------------*/
3183 PIX *
3185 {
3186 l_int32 d;
3187 
3188  PROCNAME("pixConvertTo16");
3189 
3190  if (!pixs)
3191  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3192 
3193  d = pixGetDepth(pixs);
3194  if (d == 1)
3195  return pixConvert1To16(NULL, pixs, 0xffff, 0);
3196  else if (d == 8)
3197  return pixConvert8To16(pixs, 8);
3198  else
3199  return (PIX *)ERROR_PTR("src depth not 1 or 8 bpp", procName, NULL);
3200 }
3201 
3202 
3203 
3204 /*---------------------------------------------------------------------------*
3205  * Top-level conversion to 32 bpp *
3206  *---------------------------------------------------------------------------*/
3232 PIX *
3234 {
3235 l_int32 d;
3236 PIX *pix1, *pixd;
3237 
3238  PROCNAME("pixConvertTo32");
3239 
3240  if (!pixs)
3241  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3242 
3243  d = pixGetDepth(pixs);
3244  if (d == 1) {
3245  return pixConvert1To32(NULL, pixs, 0xffffffff, 0);
3246  } else if (d == 2) {
3247  pix1 = pixConvert2To8(pixs, 0, 85, 170, 255, TRUE);
3248  pixd = pixConvert8To32(pix1);
3249  pixDestroy(&pix1);
3250  return pixd;
3251  } else if (d == 4) {
3252  pix1 = pixConvert4To8(pixs, TRUE);
3253  pixd = pixConvert8To32(pix1);
3254  pixDestroy(&pix1);
3255  return pixd;
3256  } else if (d == 8) {
3257  return pixConvert8To32(pixs);
3258  } else if (d == 16) {
3259  pix1 = pixConvert16To8(pixs, L_MS_BYTE);
3260  pixd = pixConvert8To32(pix1);
3261  pixDestroy(&pix1);
3262  return pixd;
3263  } else if (d == 24) {
3264  return pixConvert24To32(pixs);
3265  } else if (d == 32) {
3266  return pixCopy(NULL, pixs);
3267  } else {
3268  return (PIX *)ERROR_PTR("depth not 1, 2, 4, 8, 16, 32 bpp",
3269  procName, NULL);
3270  }
3271 }
3272 
3273 
3287 PIX *
3289  l_int32 factor)
3290 {
3291 l_float32 scalefactor;
3292 PIX *pix1, *pixd;
3293 
3294  PROCNAME("pixConvertTo32BySampling");
3295 
3296  if (!pixs)
3297  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3298  if (factor < 1)
3299  return (PIX *)ERROR_PTR("factor must be >= 1", procName, NULL);
3300 
3301  scalefactor = 1. / (l_float32)factor;
3302  pix1 = pixScaleBySampling(pixs, scalefactor, scalefactor);
3303  pixd = pixConvertTo32(pix1);
3304 
3305  pixDestroy(&pix1);
3306  return pixd;
3307 }
3308 
3309 
3322 PIX *
3324 {
3325 l_int32 i, j, w, h, wpls, wpld, val;
3326 l_uint32 *datas, *datad, *lines, *lined;
3327 l_uint32 *tab;
3328 PIX *pixd;
3329 
3330  PROCNAME("pixConvert8To32");
3331 
3332  if (!pixs)
3333  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3334  if (pixGetDepth(pixs) != 8)
3335  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
3336 
3337  if (pixGetColormap(pixs))
3339 
3340  pixGetDimensions(pixs, &w, &h, NULL);
3341  datas = pixGetData(pixs);
3342  wpls = pixGetWpl(pixs);
3343  if ((pixd = pixCreate(w, h, 32)) == NULL)
3344  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3345  pixCopyResolution(pixd, pixs);
3346  pixCopyInputFormat(pixd, pixs);
3347  datad = pixGetData(pixd);
3348  wpld = pixGetWpl(pixd);
3349 
3350  /* Replication table gray --> rgb */
3351  tab = (l_uint32 *)LEPT_CALLOC(256, sizeof(l_uint32));
3352  for (i = 0; i < 256; i++)
3353  tab[i] = (i << 24) | (i << 16) | (i << 8);
3354 
3355  /* Replicate 1 --> 4 bytes (alpha byte not set) */
3356  for (i = 0; i < h; i++) {
3357  lines = datas + i * wpls;
3358  lined = datad + i * wpld;
3359  for (j = 0; j < w; j++) {
3360  val = GET_DATA_BYTE(lines, j);
3361  lined[j] = tab[val];
3362  }
3363  }
3364 
3365  LEPT_FREE(tab);
3366  return pixd;
3367 }
3368 
3369 
3370 /*---------------------------------------------------------------------------*
3371  * Top-level conversion to 8 or 32 bpp, without colormap *
3372  *---------------------------------------------------------------------------*/
3392 PIX *
3394  l_int32 copyflag,
3395  l_int32 warnflag)
3396 {
3397 l_int32 d;
3398 PIX *pixd;
3399 
3400  PROCNAME("pixConvertTo8Or32");
3401 
3402  if (!pixs)
3403  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3404  if (copyflag != L_CLONE && copyflag != L_COPY)
3405  return (PIX *)ERROR_PTR("invalid copyflag", procName, NULL);
3406 
3407  d = pixGetDepth(pixs);
3408  if (pixGetColormap(pixs)) {
3409  if (warnflag) L_WARNING("pix has colormap; removing\n", procName);
3411  } else if (d == 8 || d == 32) {
3412  if (copyflag == L_CLONE)
3413  pixd = pixClone(pixs);
3414  else /* copyflag == L_COPY */
3415  pixd = pixCopy(NULL, pixs);
3416  } else {
3417  pixd = pixConvertTo8(pixs, 0);
3418  }
3419 
3420  /* Sanity check on result */
3421  d = pixGetDepth(pixd);
3422  if (d != 8 && d != 32) {
3423  pixDestroy(&pixd);
3424  return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, NULL);
3425  }
3426 
3427  return pixd;
3428 }
3429 
3430 
3431 /*---------------------------------------------------------------------------*
3432  * Conversion between 24 bpp and 32 bpp rgb *
3433  *---------------------------------------------------------------------------*/
3455 PIX *
3457 {
3458 l_uint8 *lines;
3459 l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3460 l_uint32 pixel;
3461 l_uint32 *datas, *datad, *lined;
3462 PIX *pixd;
3463 
3464  PROCNAME("pixConvert24to32");
3465 
3466  if (!pixs)
3467  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3468  pixGetDimensions(pixs, &w, &h, &d);
3469  if (d != 24)
3470  return (PIX *)ERROR_PTR("pixs not 24 bpp", procName, NULL);
3471 
3472  pixd = pixCreateNoInit(w, h, 32);
3473  datas = pixGetData(pixs);
3474  datad = pixGetData(pixd);
3475  wpls = pixGetWpl(pixs);
3476  wpld = pixGetWpl(pixd);
3477  for (i = 0; i < h; i++) {
3478  lines = (l_uint8 *)(datas + i * wpls);
3479  lined = datad + i * wpld;
3480  for (j = 0; j < w; j++) {
3481  rval = *lines++;
3482  gval = *lines++;
3483  bval = *lines++;
3484  composeRGBPixel(rval, gval, bval, &pixel);
3485  lined[j] = pixel;
3486  }
3487  }
3488  pixCopyResolution(pixd, pixs);
3489  pixCopyInputFormat(pixd, pixs);
3490  return pixd;
3491 }
3492 
3493 
3505 PIX *
3507 {
3508 l_uint8 *rgbdata8;
3509 l_int32 w, h, d, i, j, wpls, wpld, rval, gval, bval;
3510 l_uint32 *datas, *lines, *rgbdata;
3511 PIX *pixd;
3512 
3513  PROCNAME("pixConvert32to24");
3514 
3515  if (!pixs)
3516  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3517  pixGetDimensions(pixs, &w, &h, &d);
3518  if (d != 32)
3519  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
3520 
3521  datas = pixGetData(pixs);
3522  wpls = pixGetWpl(pixs);
3523  pixd = pixCreateNoInit(w, h, 24);
3524  rgbdata = pixGetData(pixd);
3525  wpld = pixGetWpl(pixd);
3526  for (i = 0; i < h; i++) {
3527  lines = datas + i * wpls;
3528  rgbdata8 = (l_uint8 *)(rgbdata + i * wpld);
3529  for (j = 0; j < w; j++) {
3530  extractRGBValues(lines[j], &rval, &gval, &bval);
3531  *rgbdata8++ = rval;
3532  *rgbdata8++ = gval;
3533  *rgbdata8++ = bval;
3534  }
3535  }
3536  pixCopyResolution(pixd, pixs);
3537  pixCopyInputFormat(pixd, pixs);
3538  return pixd;
3539 }
3540 
3541 
3542 /*---------------------------------------------------------------------------*
3543  * Conversion between 32 bpp (1 spp) and 16 or 8 bpp *
3544  *---------------------------------------------------------------------------*/
3558 PIX *
3560  l_int32 type)
3561 {
3562 l_uint16 dword;
3563 l_int32 w, h, i, j, wpls, wpld;
3564 l_uint32 sword;
3565 l_uint32 *datas, *lines, *datad, *lined;
3566 PIX *pixd;
3567 
3568  PROCNAME("pixConvert32to16");
3569 
3570  if (!pixs || pixGetDepth(pixs) != 32)
3571  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
3572  if (type != L_LS_TWO_BYTES && type != L_MS_TWO_BYTES &&
3573  type != L_CLIP_TO_FFFF)
3574  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
3575 
3576  pixGetDimensions(pixs, &w, &h, NULL);
3577  if ((pixd = pixCreate(w, h, 16)) == NULL)
3578  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3579  pixCopyResolution(pixd, pixs);
3580  pixCopyInputFormat(pixd, pixs);
3581  wpls = pixGetWpl(pixs);
3582  datas = pixGetData(pixs);
3583  wpld = pixGetWpl(pixd);
3584  datad = pixGetData(pixd);
3585 
3586  for (i = 0; i < h; i++) {
3587  lines = datas + i * wpls;
3588  lined = datad + i * wpld;
3589  if (type == L_LS_TWO_BYTES) {
3590  for (j = 0; j < wpls; j++) {
3591  sword = *(lines + j);
3592  dword = sword & 0xffff;
3593  SET_DATA_TWO_BYTES(lined, j, dword);
3594  }
3595  } else if (type == L_MS_TWO_BYTES) {
3596  for (j = 0; j < wpls; j++) {
3597  sword = *(lines + j);
3598  dword = sword >> 16;
3599  SET_DATA_TWO_BYTES(lined, j, dword);
3600  }
3601  } else { /* type == L_CLIP_TO_FFFF */
3602  for (j = 0; j < wpls; j++) {
3603  sword = *(lines + j);
3604  dword = (sword >> 16) ? 0xffff : (sword & 0xffff);
3605  SET_DATA_TWO_BYTES(lined, j, dword);
3606  }
3607  }
3608  }
3609 
3610  return pixd;
3611 }
3612 
3613 
3622 PIX *
3624  l_int32 type16,
3625  l_int32 type8)
3626 {
3627 PIX *pix1, *pixd;
3628 
3629  PROCNAME("pixConvert32to8");
3630 
3631  if (!pixs || pixGetDepth(pixs) != 32)
3632  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
3633  if (type16 != L_LS_TWO_BYTES && type16 != L_MS_TWO_BYTES &&
3634  type16 != L_CLIP_TO_FFFF)
3635  return (PIX *)ERROR_PTR("invalid type16", procName, NULL);
3636  if (type8 != L_LS_BYTE && type8 != L_MS_BYTE && type8 != L_CLIP_TO_FF)
3637  return (PIX *)ERROR_PTR("invalid type8", procName, NULL);
3638 
3639  pix1 = pixConvert32To16(pixs, type16);
3640  pixd = pixConvert16To8(pix1, type8);
3641  pixDestroy(&pix1);
3642  return pixd;
3643 }
3644 
3645 
3646 /*---------------------------------------------------------------------------*
3647  * Removal of alpha component by blending with white background *
3648  *---------------------------------------------------------------------------*/
3661 PIX *
3663 {
3664  PROCNAME("pixRemoveAlpha");
3665 
3666  if (!pixs)
3667  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3668 
3669  if (pixGetDepth(pixs) == 32 && pixGetSpp(pixs) == 4)
3670  return pixAlphaBlendUniform(pixs, 0xffffff00);
3671  else
3672  return pixClone(pixs);
3673 }
3674 
3675 
3676 /*---------------------------------------------------------------------------*
3677  * Addition of alpha component to 1 bpp *
3678  *---------------------------------------------------------------------------*/
3698 PIX *
3700  PIX *pixs)
3701 {
3702 PIXCMAP *cmap;
3703 
3704  PROCNAME("pixAddAlphaTo1bpp");
3705 
3706  if (!pixs || (pixGetDepth(pixs) != 1))
3707  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
3708  if (pixd && (pixd != pixs))
3709  return (PIX *)ERROR_PTR("pixd defined but != pixs", procName, NULL);
3710 
3711  pixd = pixCopy(pixd, pixs);
3712  cmap = pixcmapCreate(1);
3713  pixSetColormap(pixd, cmap);
3714  pixcmapAddRGBA(cmap, 255, 255, 255, 0); /* 0 ==> white + transparent */
3715  pixcmapAddRGBA(cmap, 0, 0, 0, 255); /* 1 ==> black + opaque */
3716  return pixd;
3717 }
3718 
3719 
3720 /*---------------------------------------------------------------------------*
3721  * Lossless depth conversion (unpacking) *
3722  *---------------------------------------------------------------------------*/
3740 PIX *
3742  l_int32 d)
3743 {
3744 l_int32 w, h, ds, wpls, wpld, i, j, val;
3745 l_uint32 *datas, *datad, *lines, *lined;
3746 PIX *pixd;
3747 
3748  PROCNAME("pixConvertLossless");
3749 
3750  if (!pixs)
3751  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3752  if (pixGetColormap(pixs))
3753  return (PIX *)ERROR_PTR("pixs has colormap", procName, NULL);
3754  if (d != 2 && d != 4 && d != 8)
3755  return (PIX *)ERROR_PTR("invalid dest depth", procName, NULL);
3756 
3757  pixGetDimensions(pixs, &w, &h, &ds);
3758  if (d < ds)
3759  return (PIX *)ERROR_PTR("depth > d", procName, NULL);
3760  else if (d == ds)
3761  return pixCopy(NULL, pixs);
3762 
3763  if ((pixd = pixCreate(w, h, d)) == NULL)
3764  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3765  pixCopyResolution(pixd, pixs);
3766  pixCopyInputFormat(pixd, pixs);
3767 
3768  /* Unpack the bits */
3769  datas = pixGetData(pixs);
3770  wpls = pixGetWpl(pixs);
3771  datad = pixGetData(pixd);
3772  wpld = pixGetWpl(pixd);
3773  for (i = 0; i < h; i++) {
3774  lines = datas + i * wpls;
3775  lined = datad + i * wpld;
3776  switch (ds)
3777  {
3778  case 1:
3779  for (j = 0; j < w; j++) {
3780  val = GET_DATA_BIT(lines, j);
3781  if (d == 8)
3782  SET_DATA_BYTE(lined, j, val);
3783  else if (d == 4)
3784  SET_DATA_QBIT(lined, j, val);
3785  else /* d == 2 */
3786  SET_DATA_DIBIT(lined, j, val);
3787  }
3788  break;
3789  case 2:
3790  for (j = 0; j < w; j++) {
3791  val = GET_DATA_DIBIT(lines, j);
3792  if (d == 8)
3793  SET_DATA_BYTE(lined, j, val);
3794  else /* d == 4 */
3795  SET_DATA_QBIT(lined, j, val);
3796  }
3797  break;
3798  case 4:
3799  for (j = 0; j < w; j++) {
3800  val = GET_DATA_DIBIT(lines, j);
3801  SET_DATA_BYTE(lined, j, val);
3802  }
3803  break;
3804  }
3805  }
3806 
3807  return pixd;
3808 }
3809 
3810 
3811 /*---------------------------------------------------------------------------*
3812  * Conversion for printing in PostScript *
3813  *---------------------------------------------------------------------------*/
3831 PIX *
3833 {
3834 l_int32 d;
3835 PIX *pixd;
3836 PIXCMAP *cmap;
3837 
3838  PROCNAME("pixConvertForPSWrap");
3839 
3840  if (!pixs)
3841  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3842 
3843  cmap = pixGetColormap(pixs);
3844  d = pixGetDepth(pixs);
3845  switch (d)
3846  {
3847  case 1:
3848  case 32:
3849  pixd = pixClone(pixs);
3850  break;
3851  case 2:
3852  if (cmap)
3854  else
3855  pixd = pixConvert2To8(pixs, 0, 0x55, 0xaa, 0xff, FALSE);
3856  break;
3857  case 4:
3858  if (cmap)
3860  else
3861  pixd = pixConvert4To8(pixs, FALSE);
3862  break;
3863  case 8:
3865  break;
3866  case 16:
3867  pixd = pixConvert16To8(pixs, L_MS_BYTE);
3868  break;
3869  default:
3870  fprintf(stderr, "depth not in {1, 2, 4, 8, 16, 32}");
3871  return NULL;
3872  }
3873 
3874  return pixd;
3875 }
3876 
3877 
3878 /*---------------------------------------------------------------------------*
3879  * Scaling conversion to subpixel RGB *
3880  *---------------------------------------------------------------------------*/
3910 PIX *
3912  l_float32 scalex,
3913  l_float32 scaley,
3914  l_int32 order)
3915 {
3916 l_int32 d;
3917 PIX *pix1, *pixd;
3918 PIXCMAP *cmap;
3919 
3920  PROCNAME("pixConvertToSubpixelRGB");
3921 
3922  if (!pixs)
3923  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3924  d = pixGetDepth(pixs);
3925  cmap = pixGetColormap(pixs);
3926  if (d != 8 && d != 32 && !cmap)
3927  return (PIX *)ERROR_PTR("pix not 8 or 32 bpp and not cmapped",
3928  procName, NULL);
3929  if (scalex <= 0.0 || scaley <= 0.0)
3930  return (PIX *)ERROR_PTR("scale factors must be > 0", procName, NULL);
3931  if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
3932  order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
3933  return (PIX *)ERROR_PTR("invalid subpixel order", procName, NULL);
3934  if ((pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC)) == NULL)
3935  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
3936 
3937  d = pixGetDepth(pix1);
3938  pixd = NULL;
3939  if (d == 8)
3940  pixd = pixConvertGrayToSubpixelRGB(pix1, scalex, scaley, order);
3941  else if (d == 32)
3942  pixd = pixConvertColorToSubpixelRGB(pix1, scalex, scaley, order);
3943  else
3944  L_ERROR("invalid depth %d\n", procName, d);
3945 
3946  pixDestroy(&pix1);
3947  return pixd;
3948 }
3949 
3950 
3980 PIX *
3982  l_float32 scalex,
3983  l_float32 scaley,
3984  l_int32 order)
3985 {
3986 l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
3987 l_uint32 *datat, *datad, *linet, *lined;
3988 PIX *pix1, *pix2, *pixd;
3989 PIXCMAP *cmap;
3990 
3991  PROCNAME("pixConvertGrayToSubpixelRGB");
3992 
3993  if (!pixs)
3994  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3995  d = pixGetDepth(pixs);
3996  cmap = pixGetColormap(pixs);
3997  if (d != 8 && !cmap)
3998  return (PIX *)ERROR_PTR("pix not 8 bpp & not cmapped", procName, NULL);
3999  if (scalex <= 0.0 || scaley <= 0.0)
4000  return (PIX *)ERROR_PTR("scale factors must be > 0", procName, NULL);
4001  if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
4002  order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
4003  return (PIX *)ERROR_PTR("invalid subpixel order", procName, NULL);
4004 
4005  direction =
4006  (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
4007  ? L_HORIZ : L_VERT;
4009  if (direction == L_HORIZ)
4010  pix2 = pixScale(pix1, 3.0 * scalex, scaley);
4011  else /* L_VERT */
4012  pix2 = pixScale(pix1, scalex, 3.0 * scaley);
4013 
4014  pixGetDimensions(pix2, &w, &h, NULL);
4015  wd = (direction == L_HORIZ) ? w / 3 : w;
4016  hd = (direction == L_VERT) ? h / 3 : h;
4017  pixd = pixCreate(wd, hd, 32);
4018  datad = pixGetData(pixd);
4019  wpld = pixGetWpl(pixd);
4020  datat = pixGetData(pix2);
4021  wplt = pixGetWpl(pix2);
4022  if (direction == L_HORIZ) {
4023  for (i = 0; i < hd; i++) {
4024  linet = datat + i * wplt;
4025  lined = datad + i * wpld;
4026  for (j = 0; j < wd; j++) {
4027  rval = GET_DATA_BYTE(linet, 3 * j);
4028  gval = GET_DATA_BYTE(linet, 3 * j + 1);
4029  bval = GET_DATA_BYTE(linet, 3 * j + 2);
4030  if (order == L_SUBPIXEL_ORDER_RGB)
4031  composeRGBPixel(rval, gval, bval, &lined[j]);
4032  else /* order BGR */
4033  composeRGBPixel(bval, gval, rval, &lined[j]);
4034  }
4035  }
4036  } else { /* L_VERT */
4037  for (i = 0; i < hd; i++) {
4038  linet = datat + 3 * i * wplt;
4039  lined = datad + i * wpld;
4040  for (j = 0; j < wd; j++) {
4041  rval = GET_DATA_BYTE(linet, j);
4042  gval = GET_DATA_BYTE(linet + wplt, j);
4043  bval = GET_DATA_BYTE(linet + 2 * wplt, j);
4044  if (order == L_SUBPIXEL_ORDER_VRGB)
4045  composeRGBPixel(rval, gval, bval, &lined[j]);
4046  else /* order VBGR */
4047  composeRGBPixel(bval, gval, rval, &lined[j]);
4048  }
4049  }
4050  }
4051 
4052  pixDestroy(&pix1);
4053  pixDestroy(&pix2);
4054  return pixd;
4055 }
4056 
4057 
4085 PIX *
4087  l_float32 scalex,
4088  l_float32 scaley,
4089  l_int32 order)
4090 {
4091 l_int32 w, h, d, wd, hd, wplt, wpld, i, j, rval, gval, bval, direction;
4092 l_uint32 *datat, *datad, *linet, *lined;
4093 PIX *pix1, *pix2, *pixd;
4094 PIXCMAP *cmap;
4095 
4096  PROCNAME("pixConvertColorToSubpixelRGB");
4097 
4098  if (!pixs)
4099  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
4100  d = pixGetDepth(pixs);
4101  cmap = pixGetColormap(pixs);
4102  if (d != 32 && !cmap)
4103  return (PIX *)ERROR_PTR("pix not 32 bpp & not cmapped", procName, NULL);
4104  if (scalex <= 0.0 || scaley <= 0.0)
4105  return (PIX *)ERROR_PTR("scale factors must be > 0", procName, NULL);
4106  if (order != L_SUBPIXEL_ORDER_RGB && order != L_SUBPIXEL_ORDER_BGR &&
4107  order != L_SUBPIXEL_ORDER_VRGB && order != L_SUBPIXEL_ORDER_VBGR)
4108  return (PIX *)ERROR_PTR("invalid subpixel order", procName, NULL);
4109 
4110  direction =
4111  (order == L_SUBPIXEL_ORDER_RGB || order == L_SUBPIXEL_ORDER_BGR)
4112  ? L_HORIZ : L_VERT;
4114  if (direction == L_HORIZ)
4115  pix2 = pixScale(pix1, 3.0 * scalex, scaley);
4116  else /* L_VERT */
4117  pix2 = pixScale(pix1, scalex, 3.0 * scaley);
4118 
4119  pixGetDimensions(pix2, &w, &h, NULL);
4120  wd = (direction == L_HORIZ) ? w / 3 : w;
4121  hd = (direction == L_VERT) ? h / 3 : h;
4122  pixd = pixCreate(wd, hd, 32);
4123  pixCopyInputFormat(pixd, pixs);
4124  datad = pixGetData(pixd);
4125  wpld = pixGetWpl(pixd);
4126  datat = pixGetData(pix2);
4127  wplt = pixGetWpl(pix2);
4128  if (direction == L_HORIZ) {
4129  for (i = 0; i < hd; i++) {
4130  linet = datat + i * wplt;
4131  lined = datad + i * wpld;
4132  for (j = 0; j < wd; j++) {
4133  if (order == L_SUBPIXEL_ORDER_RGB) {
4134  extractRGBValues(linet[3 * j], &rval, NULL, NULL);
4135  extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4136  extractRGBValues(linet[3 * j + 2], NULL, NULL, &bval);
4137  } else { /* order BGR */
4138  extractRGBValues(linet[3 * j], NULL, NULL, &bval);
4139  extractRGBValues(linet[3 * j + 1], NULL, &gval, NULL);
4140  extractRGBValues(linet[3 * j + 2], &rval, NULL, NULL);
4141  }
4142  composeRGBPixel(rval, gval, bval, &lined[j]);
4143  }
4144  }
4145  } else { /* L_VERT */
4146  for (i = 0; i < hd; i++) {
4147  linet = datat + 3 * i * wplt;
4148  lined = datad + i * wpld;
4149  for (j = 0; j < wd; j++) {
4150  if (order == L_SUBPIXEL_ORDER_VRGB) {
4151  extractRGBValues(linet[j], &rval, NULL, NULL);
4152  extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4153  extractRGBValues((linet + 2 * wplt)[j], NULL, NULL, &bval);
4154  } else { /* order VBGR */
4155  extractRGBValues(linet[j], NULL, NULL, &bval);
4156  extractRGBValues((linet + wplt)[j], NULL, &gval, NULL);
4157  extractRGBValues((linet + 2 * wplt)[j], &rval, NULL, NULL);
4158  }
4159  composeRGBPixel(rval, gval, bval, &lined[j]);
4160  }
4161  }
4162  }
4163 
4164  if (pixGetSpp(pixs) == 4)
4165  pixScaleAndTransferAlpha(pixd, pixs, scalex, scaley);
4166 
4167  pixDestroy(&pix1);
4168  pixDestroy(&pix2);
4169  return pixd;
4170 }
4171 
4172 
4173 /*---------------------------------------------------------------------*
4174  * Setting neutral point for min/max boost conversion to gray *
4175  *---------------------------------------------------------------------*/
4188 void
4190 {
4191  PROCNAME("l_setNeutralBoostVal");
4192 
4193  if (val <= 0) {
4194  L_ERROR("invalid reference value for neutral boost\n", procName);
4195  return;
4196  }
4197  var_NEUTRAL_BOOST_VAL = val;
4198 }
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
pixUnpackBinary()
Definition: pixconv.c:1878
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition: pixconv.c:733
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:109
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition: pixconv.c:2933
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:692
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
PIX * pixConvertRGBToBinaryArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc, l_int32 thresh, l_int32 relation)
pixConvertRGBToBinaryArb()
Definition: pixconv.c:1114
Definition: pix.h:854
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3233
PIX * pixConvertLossless(PIX *pixs, l_int32 d)
pixConvertLossless()
Definition: pixconv.c:3741
NUMA * pixOctcubeHistogram(PIX *pixs, l_int32 level, l_int32 *pncolors)
pixOctcubeHistogram()
Definition: colorquant1.c:3735
NUMA * pixGetCmapHistogram(PIX *pixs, l_int32 factor)
pixGetCmapHistogram()
Definition: pix4.c:627
PIXCMAP * pixcmapConvertTo8(PIXCMAP *cmaps)
pixcmapConvertTo8()
Definition: colormap.c:1596
static const l_float32 L_RED_WEIGHT
Definition: pix.h:243
PIX * pixThresholdOn8bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdOn8bpp()
Definition: grayquant.c:1632
PIX * pixRemoveAlpha(PIX *pixs)
pixRemoveAlpha()
Definition: pixconv.c:3662
PIX * pixConvert1To4(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To4()
Definition: pixconv.c:2245
PIXCMAP * pixcmapGrayToColor(l_uint32 color)
pixcmapGrayToColor()
Definition: colormap.c:1472
PIX * pixConvert8To32(PIX *pixs)
pixConvert8To32()
Definition: pixconv.c:3323
size_t nbytes
Definition: pixalloc.c:120
l_ok numaGetCountRelativeToZero(NUMA *na, l_int32 type, l_int32 *pcount)
numaGetCountRelativeToZero()
Definition: numafunc1.c:1057
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
PIX * pixAddMinimalGrayColormap8(PIX *pixs)
pixAddMinimalGrayColormap8()
Definition: pixconv.c:644
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_ok pixcmapIsBlackAndWhite(PIXCMAP *cmap, l_int32 *pblackwhite)
pixcmapIsBlackAndWhite()
Definition: colormap.c:1076
void l_setNeutralBoostVal(l_int32 val)
l_setNeutralBoostVal()
Definition: pixconv.c:4189
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1395
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:265
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
PIX * pixConvertGrayToColormap8(PIX *pixs, l_int32 mindepth)
pixConvertGrayToColormap8()
Definition: pixconv.c:1226
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:443
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:204
PIX * pixRemoveColormapGeneral(PIX *pixs, l_int32 type, l_int32 ifnocmap)
pixRemoveColormapGeneral()
Definition: pixconv.c:272
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:3116
l_ok pixcmapGetRangeValues(PIXCMAP *cmap, l_int32 select, l_int32 *pminval, l_int32 *pmaxval, l_int32 *pminindex, l_int32 *pmaxindex)
pixcmapGetRangeValues()
Definition: colormap.c:1376
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
PIX * pixColorizeGray(PIX *pixs, l_uint32 color, l_int32 cmapflag)
pixColorizeGray()
Definition: pixconv.c:1323
PIXCMAP * pixcmapCreateLinear(l_int32 d, l_int32 nlevels)
pixcmapCreateLinear()
Definition: colormap.c:204
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1573
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
Definition: pix.h:853
PIX * pixConvert4To8(PIX *pixs, l_int32 cmapflag)
pixConvert4To8()
Definition: pixconv.c:2567
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:111
PIX * pixConvertRGBToGrayFast(PIX *pixs)
pixConvertRGBToGrayFast()
Definition: pixconv.c:831
PIX * pixConvert1To8Cmap(PIX *pixs)
pixConvert1To8Cmap()
Definition: pixconv.c:2323
PIX * pixConvert24To32(PIX *pixs)
pixConvert24To32()
Definition: pixconv.c:3456
l_ok pixDestroyColormap(PIX *pix)
pixDestroyColormap()
Definition: pix1.c:1594
PIX * pixAlphaBlendUniform(PIX *pixs, l_uint32 color)
pixAlphaBlendUniform()
Definition: blend.c:2004
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
Definition: array.h:59
PIX * pixConvertGrayToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertGrayToSubpixelRGB()
Definition: pixconv.c:3981
PIX * pixConvertRGBToGraySatBoost(PIX *pixs, l_int32 refval)
pixConvertRGBToGraySatBoost()
Definition: pixconv.c:974
static const l_float32 L_GREEN_WEIGHT
Definition: pix.h:244
static const l_float32 L_BLUE_WEIGHT
Definition: pix.h:245
l_ok pixcmapToArrays(PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
Definition: colormap.c:1856
PIX * pixConvert1To2Cmap(PIX *pixs)
pixConvert1To2Cmap()
Definition: pixconv.c:2080
l_int32 nlevels
Definition: pixalloc.c:121
PIX * pixConvert32To16(PIX *pixs, l_int32 type)
pixConvert32To16()
Definition: pixconv.c:3559
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:751
PIX * pixConvert1To32(PIX *pixd, PIX *pixs, l_uint32 val0, l_uint32 val1)
pixConvert1To32()
Definition: pixconv.c:2017
PIX * pixConvert1To2(PIX *pixd, PIX *pixs, l_int32 val0, l_int32 val1)
pixConvert1To2()
Definition: pixconv.c:2123
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2702
PIX * pixConvertTo8Colormap(PIX *pixs, l_int32 dither)
pixConvertTo8Colormap()
Definition: pixconv.c:3149
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
l_ok pixAddGrayColormap8(PIX *pixs)
pixAddGrayColormap8()
Definition: pixconv.c:613
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
PIX * pixConvert32To24(PIX *pixs)
pixConvert32To24()
Definition: pixconv.c:3506
PIX * pixConvertRGBToGrayMinMax(PIX *pixs, l_int32 type)
pixConvertRGBToGrayMinMax()
Definition: pixconv.c:887
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
PIX * pixConvertGrayToColormap(PIX *pixs)
pixConvertGrayToColormap()
Definition: pixconv.c:1171
PIX * pixConvertTo8BySampling(PIX *pixs, l_int32 factor, l_int32 cmapflag)
pixConvertTo8BySampling()
Definition: pixconv.c:3105
PIX * pixCreateNoInit(l_int32 width, l_int32 height, l_int32 depth)
pixCreateNoInit()
Definition: pix1.c:331
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
Definition: colormap.c:1041
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
PIX * pixConvert8To2(PIX *pix)
pixConvert8To2()
Definition: pixconv.c:2770
PIX * pixFewColorsOctcubeQuant1(PIX *pixs, l_int32 level)
pixFewColorsOctcubeQuant1()
Definition: colorquant1.c:2946
PIX * pixConvertCmapTo1(PIX *pixs)
pixConvertCmapTo1()
Definition: pixconv.c:1477
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1002
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
PIX * pixConvertTo16(PIX *pixs)
pixConvertTo16()
Definition: pixconv.c:3184
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
PIX * pixConvertRGBToGray(PIX *pixs, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGray()
Definition: pixconv.c:753
PIX * pixConvertGrayToFalseColor(PIX *pixs, l_float32 gamma)
pixConvertGrayToFalseColor()
Definition: pixconv.c:1786
PIX * pixConvertForPSWrap(PIX *pixs)
pixConvertForPSWrap()
Definition: pixconv.c:3832
PIX * pixConvert2To8(PIX *pixs, l_uint8 val0, l_uint8 val1, l_uint8 val2, l_uint8 val3, l_int32 cmapflag)
pixConvert2To8()
Definition: pixconv.c:2456
PIX * pixConvertRGBToGrayArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc)
pixConvertRGBToGrayArb()
Definition: pixconv.c:1052
PIX * pixConvertColorToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertColorToSubpixelRGB()
Definition: pixconv.c:4086
PIX * pixConvert8To4(PIX *pix)
pixConvert8To4()
Definition: pixconv.c:2878
#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:1910
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
PIX * pixThresholdTo4bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo4bpp()
Definition: grayquant.c:1515
PIX * pixConvertRGBToColormap(PIX *pixs, l_int32 ditherflag)
pixConvertRGBToColormap()
Definition: pixconv.c:1412
PIX * pixConvertTo4(PIX *pixs)
pixConvertTo4()
Definition: pixconv.c:2826
PIX * pixConvertTo2(PIX *pixs)
pixConvertTo2()
Definition: pixconv.c:2718
Definition: pix.h:718
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:635
Definition: pix.h:134
PIX * pixConvert1To4Cmap(PIX *pixs)
pixConvert1To4Cmap()
Definition: pixconv.c:2202
Definition: pix.h:719
PIX * pixThresholdTo2bpp(PIX *pixs, l_int32 nlevels, l_int32 cmapflag)
pixThresholdTo2bpp()
Definition: grayquant.c:1373
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2366
PIX * pixConvert16To8(PIX *pixs, l_int32 type)
pixConvert16To8()
Definition: pixconv.c:1689
NUMA * numaNormalizeHistogram(NUMA *nas, l_float32 tsum)
numaNormalizeHistogram()
Definition: numafunc2.c:1172
PIX * pixConvert8To16(PIX *pixs, l_int32 leftshift)
pixConvert8To16()
Definition: pixconv.c:2652
PIX * pixConvert1To16(PIX *pixd, PIX *pixs, l_uint16 val0, l_uint16 val1)
pixConvert1To16()
Definition: pixconv.c:1943
PIX * pixConvertTo1BySampling(PIX *pixs, l_int32 factor, l_int32 threshold)
pixConvertTo1BySampling()
Definition: pixconv.c:2989
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
l_ok pixcmapGetDistanceToColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pdist)
pixcmapGetDistanceToColor()
Definition: colormap.c:1320
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:341
l_ok pixScaleAndTransferAlpha(PIX *pixd, PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleAndTransferAlpha()
Definition: scale2.c:1358
PIX * pixConvertTo32BySampling(PIX *pixs, l_int32 factor)
pixConvertTo32BySampling()
Definition: pixconv.c:3288
PIX * pixScale(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScale()
Definition: scale1.c:244
#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:1588
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2737
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition: pixconv.c:3393
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
l_ok pixcmapAddRGBA(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval)
pixcmapAddRGBA()
Definition: colormap.c:379
PIX * pixConvertToSubpixelRGB(PIX *pixs, l_float32 scalex, l_float32 scaley, l_int32 order)
pixConvertToSubpixelRGB()
Definition: pixconv.c:3911
PIX * pixConvert32To8(PIX *pixs, l_int32 type16, l_int32 type8)
pixConvert32To8()
Definition: pixconv.c:3623
PIX * pixAddAlphaTo1bpp(PIX *pixd, PIX *pixs)
pixAddAlphaTo1bpp()
Definition: pixconv.c:3699