Leptonica  1.73
Image processing and image analysis suite
colormap.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 
97 #include <string.h>
98 #include "allheaders.h"
99 
100 /*-------------------------------------------------------------*
101  * Colormap creation and addition *
102  *-------------------------------------------------------------*/
109 PIXCMAP *
110 pixcmapCreate(l_int32 depth)
111 {
112 RGBA_QUAD *cta;
113 PIXCMAP *cmap;
114 
115  PROCNAME("pixcmapCreate");
116 
117  if (depth != 1 && depth != 2 && depth !=4 && depth != 8)
118  return (PIXCMAP *)ERROR_PTR("depth not in {1,2,4,8}", procName, NULL);
119 
120  cmap = (PIXCMAP *)LEPT_CALLOC(1, sizeof(PIXCMAP));
121  cmap->depth = depth;
122  cmap->nalloc = 1 << depth;
123  cta = (RGBA_QUAD *)LEPT_CALLOC(cmap->nalloc, sizeof(RGBA_QUAD));
124  cmap->array = cta;
125  cmap->n = 0;
126  return cmap;
127 }
128 
129 
156 PIXCMAP *
157 pixcmapCreateRandom(l_int32 depth,
158  l_int32 hasblack,
159  l_int32 haswhite)
160 {
161 l_int32 ncolors, i;
162 l_int32 red[256], green[256], blue[256];
163 PIXCMAP *cmap;
164 
165  PROCNAME("pixcmapCreateRandom");
166 
167  if (depth != 2 && depth != 4 && depth != 8)
168  return (PIXCMAP *)ERROR_PTR("depth not in {2, 4, 8}", procName, NULL);
169  if (hasblack != 0) hasblack = 1;
170  if (haswhite != 0) haswhite = 1;
171 
172  cmap = pixcmapCreate(depth);
173  ncolors = 1 << depth;
174  if (hasblack) /* first color is optionally black */
175  pixcmapAddColor(cmap, 0, 0, 0);
176  for (i = hasblack; i < ncolors - haswhite; i++) {
177  red[i] = (l_uint32)rand() & 0xff;
178  green[i] = (l_uint32)rand() & 0xff;
179  blue[i] = (l_uint32)rand() & 0xff;
180  pixcmapAddColor(cmap, red[i], green[i], blue[i]);
181  }
182  if (haswhite) /* last color is optionally white */
183  pixcmapAddColor(cmap, 255, 255, 255);
184 
185  return cmap;
186 }
187 
188 
202 PIXCMAP *
204  l_int32 nlevels)
205 {
206 l_int32 maxlevels, i, val;
207 PIXCMAP *cmap;
208 
209  PROCNAME("pixcmapCreateLinear");
210 
211  if (d != 1 && d != 2 && d !=4 && d != 8)
212  return (PIXCMAP *)ERROR_PTR("d not in {1, 2, 4, 8}", procName, NULL);
213  maxlevels = 1 << d;
214  if (nlevels < 2 || nlevels > maxlevels)
215  return (PIXCMAP *)ERROR_PTR("invalid nlevels", procName, NULL);
216 
217  cmap = pixcmapCreate(d);
218  for (i = 0; i < nlevels; i++) {
219  val = (255 * i) / (nlevels - 1);
220  pixcmapAddColor(cmap, val, val, val);
221  }
222  return cmap;
223 }
224 
225 
232 PIXCMAP *
234 {
235 l_int32 nbytes;
236 PIXCMAP *cmapd;
237 
238  PROCNAME("pixcmapCopy");
239 
240  if (!cmaps)
241  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
242  if (cmaps->nalloc > 256)
243  return (PIXCMAP *)ERROR_PTR("nalloc > 256", procName, NULL);
244 
245  cmapd = (PIXCMAP *)LEPT_CALLOC(1, sizeof(PIXCMAP));
246  nbytes = cmaps->nalloc * sizeof(RGBA_QUAD);
247  cmapd->array = (void *)LEPT_CALLOC(1, nbytes);
248  memcpy(cmapd->array, cmaps->array, nbytes);
249  cmapd->n = cmaps->n;
250  cmapd->nalloc = cmaps->nalloc;
251  cmapd->depth = cmaps->depth;
252  return cmapd;
253 }
254 
255 
262 void
264 {
265 PIXCMAP *cmap;
266 
267  PROCNAME("pixcmapDestroy");
268 
269  if (pcmap == NULL) {
270  L_WARNING("ptr address is null!\n", procName);
271  return;
272  }
273 
274  if ((cmap = *pcmap) == NULL)
275  return;
276 
277  LEPT_FREE(cmap->array);
278  LEPT_FREE(cmap);
279  *pcmap = NULL;
280  return;
281 }
282 
283 
298 l_int32
300  l_int32 rval,
301  l_int32 gval,
302  l_int32 bval)
303 {
304 RGBA_QUAD *cta;
305 
306  PROCNAME("pixcmapAddColor");
307 
308  if (!cmap)
309  return ERROR_INT("cmap not defined", procName, 1);
310  if (cmap->n >= cmap->nalloc)
311  return ERROR_INT("no free color entries", procName, 1);
312 
313  cta = (RGBA_QUAD *)cmap->array;
314  cta[cmap->n].red = rval;
315  cta[cmap->n].green = gval;
316  cta[cmap->n].blue = bval;
317  cta[cmap->n].alpha = 255;
318  cmap->n++;
319  return 0;
320 }
321 
322 
336 l_int32
338  l_int32 rval,
339  l_int32 gval,
340  l_int32 bval,
341  l_int32 aval)
342 {
343 RGBA_QUAD *cta;
344 
345  PROCNAME("pixcmapAddRGBA");
346 
347  if (!cmap)
348  return ERROR_INT("cmap not defined", procName, 1);
349  if (cmap->n >= cmap->nalloc)
350  return ERROR_INT("no free color entries", procName, 1);
351 
352  cta = (RGBA_QUAD *)cmap->array;
353  cta[cmap->n].red = rval;
354  cta[cmap->n].green = gval;
355  cta[cmap->n].blue = bval;
356  cta[cmap->n].alpha = aval;
357  cmap->n++;
358  return 0;
359 }
360 
361 
380 l_int32
382  l_int32 rval,
383  l_int32 gval,
384  l_int32 bval,
385  l_int32 *pindex)
386 {
387  PROCNAME("pixcmapAddNewColor");
388 
389  if (!pindex)
390  return ERROR_INT("&index not defined", procName, 1);
391  *pindex = 0;
392  if (!cmap)
393  return ERROR_INT("cmap not defined", procName, 1);
394 
395  /* Check if the color is already present. */
396  if (!pixcmapGetIndex(cmap, rval, gval, bval, pindex)) /* found */
397  return 0;
398 
399  /* We need to add the color. Is there room? */
400  if (cmap->n >= cmap->nalloc) {
401  L_WARNING("no free color entries\n", procName);
402  return 2;
403  }
404 
405  /* There's room. Add it. */
406  pixcmapAddColor(cmap, rval, gval, bval);
407  *pindex = pixcmapGetCount(cmap) - 1;
408  return 0;
409 }
410 
411 
429 l_int32
431  l_int32 rval,
432  l_int32 gval,
433  l_int32 bval,
434  l_int32 *pindex)
435 {
436  PROCNAME("pixcmapAddNearestColor");
437 
438  if (!pindex)
439  return ERROR_INT("&index not defined", procName, 1);
440  *pindex = 0;
441  if (!cmap)
442  return ERROR_INT("cmap not defined", procName, 1);
443 
444  /* Check if the color is already present. */
445  if (!pixcmapGetIndex(cmap, rval, gval, bval, pindex)) /* found */
446  return 0;
447 
448  /* We need to add the color. Is there room? */
449  if (cmap->n < cmap->nalloc) {
450  pixcmapAddColor(cmap, rval, gval, bval);
451  *pindex = pixcmapGetCount(cmap) - 1;
452  return 0;
453  }
454 
455  /* There's no room. Return the index of the nearest color */
456  pixcmapGetNearestIndex(cmap, rval, gval, bval, pindex);
457  return 0;
458 }
459 
460 
476 l_int32
478  l_int32 rval,
479  l_int32 gval,
480  l_int32 bval,
481  l_int32 *pusable)
482 {
483 l_int32 index;
484 
485  PROCNAME("pixcmapUsableColor");
486 
487  if (!pusable)
488  return ERROR_INT("&usable not defined", procName, 1);
489  *pusable = 0;
490  if (!cmap)
491  return ERROR_INT("cmap not defined", procName, 1);
492 
493  /* Is there room to add it? */
494  if (cmap->n < cmap->nalloc) {
495  *pusable = 1;
496  return 0;
497  }
498 
499  /* No room; check if the color is already present. */
500  if (!pixcmapGetIndex(cmap, rval, gval, bval, &index)) /* found */
501  *pusable = 1;
502  return 0;
503 }
504 
505 
523 l_int32
525  l_int32 color,
526  l_int32 *pindex)
527 {
528 l_int32 index;
529 
530  PROCNAME("pixcmapAddBlackOrWhite");
531 
532  if (pindex) *pindex = 0;
533  if (!cmap)
534  return ERROR_INT("cmap not defined", procName, 1);
535 
536  if (color == 0) { /* black */
537  if (pixcmapGetFreeCount(cmap) > 0)
538  pixcmapAddNewColor(cmap, 0, 0, 0, &index);
539  else
540  pixcmapGetRankIntensity(cmap, 0.0, &index);
541  } else { /* white */
542  if (pixcmapGetFreeCount(cmap) > 0)
543  pixcmapAddNewColor(cmap, 255, 255, 255, &index);
544  else
545  pixcmapGetRankIntensity(cmap, 1.0, &index);
546  }
547 
548  if (pindex)
549  *pindex = index;
550  return 0;
551 }
552 
553 
562 l_int32
564  l_int32 setblack,
565  l_int32 setwhite)
566 {
567 l_int32 index;
568 
569  PROCNAME("pixcmapSetBlackAndWhite");
570 
571  if (!cmap)
572  return ERROR_INT("cmap not defined", procName, 1);
573 
574  if (setblack) {
575  pixcmapGetRankIntensity(cmap, 0.0, &index);
576  pixcmapResetColor(cmap, index, 0, 0, 0);
577  }
578  if (setwhite) {
579  pixcmapGetRankIntensity(cmap, 1.0, &index);
580  pixcmapResetColor(cmap, index, 255, 255, 255);
581  }
582  return 0;
583 }
584 
585 
592 l_int32
594 {
595  PROCNAME("pixcmapGetCount");
596 
597  if (!cmap)
598  return ERROR_INT("cmap not defined", procName, 0);
599  return cmap->n;
600 }
601 
602 
609 l_int32
611 {
612  PROCNAME("pixcmapGetFreeCount");
613 
614  if (!cmap)
615  return ERROR_INT("cmap not defined", procName, 0);
616  return (cmap->nalloc - cmap->n);
617 }
618 
619 
626 l_int32
628 {
629  PROCNAME("pixcmapGetDepth");
630 
631  if (!cmap)
632  return ERROR_INT("cmap not defined", procName, 0);
633  return cmap->depth;
634 }
635 
636 
649 l_int32
651  l_int32 *pmindepth)
652 {
653 l_int32 ncolors;
654 
655  PROCNAME("pixcmapGetMinDepth");
656 
657  if (!pmindepth)
658  return ERROR_INT("&mindepth not defined", procName, 1);
659  *pmindepth = 0;
660  if (!cmap)
661  return ERROR_INT("cmap not defined", procName, 1);
662 
663  ncolors = pixcmapGetCount(cmap);
664  if (ncolors <= 4)
665  *pmindepth = 2;
666  else if (ncolors <= 16)
667  *pmindepth = 4;
668  else /* ncolors > 16 */
669  *pmindepth = 8;
670  return 0;
671 }
672 
673 
685 l_int32
687 {
688  PROCNAME("pixcmapClear");
689 
690  if (!cmap)
691  return ERROR_INT("cmap not defined", procName, 1);
692  cmap->n = 0;
693  return 0;
694 }
695 
696 
697 /*-------------------------------------------------------------*
698  * Colormap random access *
699  *-------------------------------------------------------------*/
708 l_int32
710  l_int32 index,
711  l_int32 *prval,
712  l_int32 *pgval,
713  l_int32 *pbval)
714 {
715 RGBA_QUAD *cta;
716 
717  PROCNAME("pixcmapGetColor");
718 
719  if (!prval || !pgval || !pbval)
720  return ERROR_INT("&rval, &gval, &bval not all defined", procName, 1);
721  *prval = *pgval = *pbval = 0;
722  if (!cmap)
723  return ERROR_INT("cmap not defined", procName, 1);
724  if (index < 0 || index >= cmap->n)
725  return ERROR_INT("index out of bounds", procName, 1);
726 
727  cta = (RGBA_QUAD *)cmap->array;
728  *prval = cta[index].red;
729  *pgval = cta[index].green;
730  *pbval = cta[index].blue;
731  return 0;
732 }
733 
734 
748 l_int32
750  l_int32 index,
751  l_uint32 *pval32)
752 {
753 l_int32 rval, gval, bval;
754 
755  PROCNAME("pixcmapGetColor32");
756 
757  if (!pval32)
758  return ERROR_INT("&val32 not defined", procName, 1);
759  *pval32 = 0;
760 
761  if (pixcmapGetColor(cmap, index, &rval, &gval, &bval) != 0)
762  return ERROR_INT("rgb values not found", procName, 1);
763  composeRGBAPixel(rval, gval, bval, 255, pval32);
764  return 0;
765 }
766 
767 
776 l_int32
778  l_int32 index,
779  l_int32 *prval,
780  l_int32 *pgval,
781  l_int32 *pbval,
782  l_int32 *paval)
783 {
784 RGBA_QUAD *cta;
785 
786  PROCNAME("pixcmapGetRGBA");
787 
788  if (!prval || !pgval || !pbval || !paval)
789  return ERROR_INT("&rval, &gval, &bval, &aval not all defined",
790  procName, 1);
791  *prval = *pgval = *pbval = *paval = 0;
792  if (!cmap)
793  return ERROR_INT("cmap not defined", procName, 1);
794  if (index < 0 || index >= cmap->n)
795  return ERROR_INT("index out of bounds", procName, 1);
796 
797  cta = (RGBA_QUAD *)cmap->array;
798  *prval = cta[index].red;
799  *pgval = cta[index].green;
800  *pbval = cta[index].blue;
801  *paval = cta[index].alpha;
802  return 0;
803 }
804 
805 
814 l_int32
816  l_int32 index,
817  l_uint32 *pval32)
818 {
819 l_int32 rval, gval, bval, aval;
820 
821  PROCNAME("pixcmapGetRGBA32");
822 
823  if (!pval32)
824  return ERROR_INT("&val32 not defined", procName, 1);
825  *pval32 = 0;
826 
827  if (pixcmapGetRGBA(cmap, index, &rval, &gval, &bval, &aval) != 0)
828  return ERROR_INT("rgba values not found", procName, 1);
829  composeRGBAPixel(rval, gval, bval, aval, pval32);
830  return 0;
831 }
832 
833 
850 l_int32
852  l_int32 index,
853  l_int32 rval,
854  l_int32 gval,
855  l_int32 bval)
856 {
857 RGBA_QUAD *cta;
858 
859  PROCNAME("pixcmapResetColor");
860 
861  if (!cmap)
862  return ERROR_INT("cmap not defined", procName, 1);
863  if (index < 0 || index >= cmap->n)
864  return ERROR_INT("index out of bounds", procName, 1);
865 
866  cta = (RGBA_QUAD *)cmap->array;
867  cta[index].red = rval;
868  cta[index].green = gval;
869  cta[index].blue = bval;
870  cta[index].alpha = 255;
871  return 0;
872 }
873 
874 
891 l_int32
893  l_int32 index,
894  l_int32 aval)
895 {
896 RGBA_QUAD *cta;
897 
898  PROCNAME("pixcmapSetAlpha");
899 
900  if (!cmap)
901  return ERROR_INT("cmap not defined", procName, 1);
902  if (index < 0 || index >= cmap->n)
903  return ERROR_INT("index out of bounds", procName, 1);
904 
905  cta = (RGBA_QUAD *)cmap->array;
906  cta[index].alpha = aval;
907  return 0;
908 }
909 
910 
920 l_int32
922  l_int32 rval,
923  l_int32 gval,
924  l_int32 bval,
925  l_int32 *pindex)
926 {
927 l_int32 n, i;
928 RGBA_QUAD *cta;
929 
930  PROCNAME("pixcmapGetIndex");
931 
932  if (!pindex)
933  return ERROR_INT("&index not defined", procName, 1);
934  *pindex = 0;
935  if (!cmap)
936  return ERROR_INT("cmap not defined", procName, 1);
937  n = pixcmapGetCount(cmap);
938 
939  cta = (RGBA_QUAD *)cmap->array;
940  for (i = 0; i < n; i++) {
941  if (rval == cta[i].red &&
942  gval == cta[i].green &&
943  bval == cta[i].blue) {
944  *pindex = i;
945  return 0;
946  }
947  }
948  return 1;
949 }
950 
951 
959 l_int32
961  l_int32 *pcolor)
962 {
963 l_int32 n, i;
964 l_int32 *rmap, *gmap, *bmap;
965 
966  PROCNAME("pixcmapHasColor");
967 
968  if (!pcolor)
969  return ERROR_INT("&color not defined", procName, 1);
970  *pcolor = FALSE;
971  if (!cmap)
972  return ERROR_INT("cmap not defined", procName, 1);
973 
974  if (pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL))
975  return ERROR_INT("colormap arrays not made", procName, 1);
976  n = pixcmapGetCount(cmap);
977  for (i = 0; i < n; i++) {
978  if ((rmap[i] != gmap[i]) || (rmap[i] != bmap[i])) {
979  *pcolor = TRUE;
980  break;
981  }
982  }
983 
984  LEPT_FREE(rmap);
985  LEPT_FREE(gmap);
986  LEPT_FREE(bmap);
987  return 0;
988 }
989 
990 
998 l_int32
1000  l_int32 *popaque)
1001 {
1002 l_int32 i, n;
1003 RGBA_QUAD *cta;
1004 
1005  PROCNAME("pixcmapIsOpaque");
1006 
1007  if (!popaque)
1008  return ERROR_INT("&opaque not defined", procName, 1);
1009  *popaque = TRUE;
1010  if (!cmap)
1011  return ERROR_INT("cmap not defined", procName, 1);
1012 
1013  n = pixcmapGetCount(cmap);
1014  cta = (RGBA_QUAD *)cmap->array;
1015  for (i = 0; i < n; i++) {
1016  if (cta[i].alpha != 255) {
1017  *popaque = FALSE;
1018  break;
1019  }
1020  }
1021  return 0;
1022 }
1023 
1024 
1033 l_int32
1035  l_int32 *pblackwhite)
1036 {
1037 l_int32 val0, val1, hascolor;
1038 RGBA_QUAD *cta;
1039 
1040  PROCNAME("pixcmapIsBlackAndWhite");
1041 
1042  if (!pblackwhite)
1043  return ERROR_INT("&blackwhite not defined", procName, 1);
1044  *pblackwhite = FALSE;
1045  if (!cmap)
1046  return ERROR_INT("cmap not defined", procName, 1);
1047  if (pixcmapGetCount(cmap) != 2)
1048  return 0;
1049 
1050  pixcmapHasColor(cmap, &hascolor);
1051  if (hascolor) return 0;
1052 
1053  cta = (RGBA_QUAD *)cmap->array;
1054  val0 = cta[0].red;
1055  val1 = cta[1].red;
1056  if ((val0 == 0 && val1 == 255) || (val0 == 255 && val1 == 0))
1057  *pblackwhite = TRUE;
1058  return 0;
1059 }
1060 
1061 
1074 l_int32
1076  l_int32 *pngray)
1077 {
1078 l_int32 n, i, rval, gval, bval, count;
1079 l_int32 *array;
1080 
1081  PROCNAME("pixcmapCountGrayColors");
1082 
1083  if (!pngray)
1084  return ERROR_INT("&ngray not defined", procName, 1);
1085  *pngray = 0;
1086  if (!cmap)
1087  return ERROR_INT("cmap not defined", procName, 1);
1088 
1089  array = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1090  n = pixcmapGetCount(cmap);
1091  count = 0;
1092  for (i = 0; i < n; i++) {
1093  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1094  if ((rval == gval) && (rval == bval) && (array[rval] == 0)) {
1095  array[rval] = 1;
1096  count++;
1097  }
1098  }
1099 
1100  LEPT_FREE(array);
1101  *pngray = count;
1102  return 0;
1103 }
1104 
1105 
1115 l_int32
1117  l_float32 rankval,
1118  l_int32 *pindex)
1119 {
1120 l_int32 n, i, rval, gval, bval, rankindex;
1121 NUMA *na, *nasort;
1122 
1123  PROCNAME("pixcmapGetRankIntensity");
1124 
1125  if (!pindex)
1126  return ERROR_INT("&index not defined", procName, 1);
1127  *pindex = 0;
1128  if (!cmap)
1129  return ERROR_INT("cmap not defined", procName, 1);
1130  if (rankval < 0.0 || rankval > 1.0)
1131  return ERROR_INT("rankval not in [0.0 ... 1.0]", procName, 1);
1132 
1133  n = pixcmapGetCount(cmap);
1134  na = numaCreate(n);
1135  for (i = 0; i < n; i++) {
1136  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1137  numaAddNumber(na, rval + gval + bval);
1138  }
1139  nasort = numaGetSortIndex(na, L_SORT_INCREASING);
1140  rankindex = (l_int32)(rankval * (n - 1) + 0.5);
1141  numaGetIValue(nasort, rankindex, pindex);
1142 
1143  numaDestroy(&na);
1144  numaDestroy(&nasort);
1145  return 0;
1146 }
1147 
1148 
1166 l_int32
1168  l_int32 rval,
1169  l_int32 gval,
1170  l_int32 bval,
1171  l_int32 *pindex)
1172 {
1173 l_int32 i, n, delta, dist, mindist;
1174 RGBA_QUAD *cta;
1175 
1176  PROCNAME("pixcmapGetNearestIndex");
1177 
1178  if (!pindex)
1179  return ERROR_INT("&index not defined", procName, 1);
1180  *pindex = UNDEF;
1181  if (!cmap)
1182  return ERROR_INT("cmap not defined", procName, 1);
1183 
1184  if ((cta = (RGBA_QUAD *)cmap->array) == NULL)
1185  return ERROR_INT("cta not defined(!)", procName, 1);
1186  n = pixcmapGetCount(cmap);
1187 
1188  mindist = 3 * 255 * 255 + 1;
1189  for (i = 0; i < n; i++) {
1190  delta = cta[i].red - rval;
1191  dist = delta * delta;
1192  delta = cta[i].green - gval;
1193  dist += delta * delta;
1194  delta = cta[i].blue - bval;
1195  dist += delta * delta;
1196  if (dist < mindist) {
1197  *pindex = i;
1198  if (dist == 0)
1199  break;
1200  mindist = dist;
1201  }
1202  }
1203 
1204  return 0;
1205 }
1206 
1207 
1224 l_int32
1226  l_int32 val,
1227  l_int32 *pindex)
1228 {
1229 l_int32 i, n, dist, mindist;
1230 RGBA_QUAD *cta;
1231 
1232  PROCNAME("pixcmapGetNearestGrayIndex");
1233 
1234  if (!pindex)
1235  return ERROR_INT("&index not defined", procName, 1);
1236  *pindex = 0;
1237  if (!cmap)
1238  return ERROR_INT("cmap not defined", procName, 1);
1239  if (val < 0 || val > 255)
1240  return ERROR_INT("val not in [0 ... 255]", procName, 1);
1241 
1242  if ((cta = (RGBA_QUAD *)cmap->array) == NULL)
1243  return ERROR_INT("cta not defined(!)", procName, 1);
1244  n = pixcmapGetCount(cmap);
1245 
1246  mindist = 256;
1247  for (i = 0; i < n; i++) {
1248  dist = cta[i].green - val;
1249  dist = L_ABS(dist);
1250  if (dist < mindist) {
1251  *pindex = i;
1252  if (dist == 0)
1253  break;
1254  mindist = dist;
1255  }
1256  }
1257 
1258  return 0;
1259 }
1260 
1261 
1277 l_int32
1279  l_int32 index,
1280  l_int32 rval,
1281  l_int32 gval,
1282  l_int32 bval,
1283  l_int32 *pdist)
1284 {
1285 l_int32 n, delta, dist;
1286 RGBA_QUAD *cta;
1287 
1288  PROCNAME("pixcmapGetDistanceToColor");
1289 
1290  if (!pdist)
1291  return ERROR_INT("&dist not defined", procName, 1);
1292  *pdist = UNDEF;
1293  if (!cmap)
1294  return ERROR_INT("cmap not defined", procName, 1);
1295  n = pixcmapGetCount(cmap);
1296  if (index >= n)
1297  return ERROR_INT("invalid index", procName, 1);
1298 
1299  if ((cta = (RGBA_QUAD *)cmap->array) == NULL)
1300  return ERROR_INT("cta not defined(!)", procName, 1);
1301 
1302  delta = cta[index].red - rval;
1303  dist = delta * delta;
1304  delta = cta[index].green - gval;
1305  dist += delta * delta;
1306  delta = cta[index].blue - bval;
1307  dist += delta * delta;
1308  *pdist = dist;
1309 
1310  return 0;
1311 }
1312 
1313 
1333 l_int32
1335  l_int32 select,
1336  l_int32 *pminval,
1337  l_int32 *pmaxval,
1338  l_int32 *pminindex,
1339  l_int32 *pmaxindex)
1340 {
1341 l_int32 i, n, imin, imax, minval, maxval, rval, gval, bval, aveval;
1342 
1343  PROCNAME("pixcmapGetRangeValues");
1344 
1345  if (pminval) *pminval = UNDEF;
1346  if (pmaxval) *pmaxval = UNDEF;
1347  if (pminindex) *pminindex = UNDEF;
1348  if (pmaxindex) *pmaxindex = UNDEF;
1349  if (!pminval && !pmaxval && !pminindex && !pmaxindex)
1350  return ERROR_INT("no result requested", procName, 1);
1351  if (!cmap)
1352  return ERROR_INT("cmap not defined", procName, 1);
1353 
1354  imin = UNDEF;
1355  imax = UNDEF;
1356  minval = 100000;
1357  maxval = -1;
1358  n = pixcmapGetCount(cmap);
1359  for (i = 0; i < n; i++) {
1360  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1361  if (select == L_SELECT_RED) {
1362  if (rval < minval) {
1363  minval = rval;
1364  imin = i;
1365  }
1366  if (rval > maxval) {
1367  maxval = rval;
1368  imax = i;
1369  }
1370  } else if (select == L_SELECT_GREEN) {
1371  if (gval < minval) {
1372  minval = gval;
1373  imin = i;
1374  }
1375  if (gval > maxval) {
1376  maxval = gval;
1377  imax = i;
1378  }
1379  } else if (select == L_SELECT_BLUE) {
1380  if (bval < minval) {
1381  minval = bval;
1382  imin = i;
1383  }
1384  if (bval > maxval) {
1385  maxval = bval;
1386  imax = i;
1387  }
1388  } else if (select == L_SELECT_AVERAGE) {
1389  aveval = (rval + gval + bval) / 3;
1390  if (aveval < minval) {
1391  minval = aveval;
1392  imin = i;
1393  }
1394  if (aveval > maxval) {
1395  maxval = aveval;
1396  imax = i;
1397  }
1398  } else {
1399  return ERROR_INT("invalid selection", procName, 1);
1400  }
1401  }
1402 
1403  if (pminval) *pminval = minval;
1404  if (pmaxval) *pmaxval = maxval;
1405  if (pminindex) *pminindex = imin;
1406  if (pmaxindex) *pmaxindex = imax;
1407  return 0;
1408 }
1409 
1410 
1411 /*-------------------------------------------------------------*
1412  * Colormap conversion *
1413  *-------------------------------------------------------------*/
1429 PIXCMAP *
1430 pixcmapGrayToColor(l_uint32 color)
1431 {
1432 l_int32 i, rval, gval, bval;
1433 PIXCMAP *cmap;
1434 
1435  extractRGBValues(color, &rval, &gval, &bval);
1436  cmap = pixcmapCreate(8);
1437  for (i = 0; i < 256; i++) {
1438  pixcmapAddColor(cmap, rval + (i * (255 - rval)) / 255,
1439  gval + (i * (255 - gval)) / 255,
1440  bval + (i * (255 - bval)) / 255);
1441  }
1442 
1443  return cmap;
1444 }
1445 
1446 
1461 PIXCMAP *
1463  l_float32 rwt,
1464  l_float32 gwt,
1465  l_float32 bwt)
1466 {
1467 l_int32 i, n, rval, gval, bval, val;
1468 l_float32 sum;
1469 PIXCMAP *cmapd;
1470 
1471  PROCNAME("pixcmapColorToGray");
1472 
1473  if (!cmaps)
1474  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
1475  if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0)
1476  return (PIXCMAP *)ERROR_PTR("weights not all >= 0.0", procName, NULL);
1477 
1478  /* Make sure the sum of weights is 1.0; otherwise, you can get
1479  * overflow in the gray value. */
1480  sum = rwt + gwt + bwt;
1481  if (sum == 0.0) {
1482  L_WARNING("all weights zero; setting equal to 1/3\n", procName);
1483  rwt = gwt = bwt = 0.33333;
1484  sum = 1.0;
1485  }
1486  if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
1487  L_WARNING("weights don't sum to 1; maintaining ratios\n", procName);
1488  rwt = rwt / sum;
1489  gwt = gwt / sum;
1490  bwt = bwt / sum;
1491  }
1492 
1493  cmapd = pixcmapCopy(cmaps);
1494  n = pixcmapGetCount(cmapd);
1495  for (i = 0; i < n; i++) {
1496  pixcmapGetColor(cmapd, i, &rval, &gval, &bval);
1497  val = (l_int32)(rwt * rval + gwt * gval + bwt * bval + 0.5);
1498  pixcmapResetColor(cmapd, i, val, val, val);
1499  }
1500 
1501  return cmapd;
1502 }
1503 
1504 
1517 PIXCMAP *
1519 {
1520 l_int32 i, n, rval, gval, bval;
1521 PIXCMAP *cmapd;
1522 
1523  PROCNAME("pixcmapConvertTo4");
1524 
1525  if (!cmaps)
1526  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
1527  if (pixcmapGetDepth(cmaps) != 2)
1528  return (PIXCMAP *)ERROR_PTR("cmaps not for 2 bpp pix", procName, NULL);
1529 
1530  cmapd = pixcmapCreate(4);
1531  n = pixcmapGetCount(cmaps);
1532  for (i = 0; i < n; i++) {
1533  pixcmapGetColor(cmaps, i, &rval, &gval, &bval);
1534  pixcmapAddColor(cmapd, rval, gval, bval);
1535  }
1536  return cmapd;
1537 }
1538 
1539 
1552 PIXCMAP *
1554 {
1555 l_int32 i, n, depth, rval, gval, bval;
1556 PIXCMAP *cmapd;
1557 
1558  PROCNAME("pixcmapConvertTo8");
1559 
1560  if (!cmaps)
1561  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
1562  depth = pixcmapGetDepth(cmaps);
1563  if (depth == 8) return pixcmapCopy(cmaps);
1564  if (depth != 2 && depth != 4)
1565  return (PIXCMAP *)ERROR_PTR("cmaps not 2 or 4 bpp", procName, NULL);
1566 
1567  cmapd = pixcmapCreate(8);
1568  n = pixcmapGetCount(cmaps);
1569  for (i = 0; i < n; i++) {
1570  pixcmapGetColor(cmaps, i, &rval, &gval, &bval);
1571  pixcmapAddColor(cmapd, rval, gval, bval);
1572  }
1573  return cmapd;
1574 }
1575 
1576 
1577 /*-------------------------------------------------------------*
1578  * Colormap I/O *
1579  *-------------------------------------------------------------*/
1586 PIXCMAP *
1587 pixcmapRead(const char *filename)
1588 {
1589 FILE *fp;
1590 PIXCMAP *cmap;
1591 
1592  PROCNAME("pixcmapRead");
1593 
1594  if (!filename)
1595  return (PIXCMAP *)ERROR_PTR("filename not defined", procName, NULL);
1596 
1597  if ((fp = fopenReadStream(filename)) == NULL)
1598  return (PIXCMAP *)ERROR_PTR("stream not opened", procName, NULL);
1599  cmap = pixcmapReadStream(fp);
1600  fclose(fp);
1601  if (!cmap)
1602  return (PIXCMAP *)ERROR_PTR("cmap not read", procName, NULL);
1603  return cmap;
1604 }
1605 
1606 
1613 PIXCMAP *
1615 {
1616 l_int32 rval, gval, bval, aval, ignore;
1617 l_int32 i, index, ret, depth, ncolors;
1618 PIXCMAP *cmap;
1619 
1620  PROCNAME("pixcmapReadStream");
1621 
1622  if (!fp)
1623  return (PIXCMAP *)ERROR_PTR("stream not defined", procName, NULL);
1624 
1625  ret = fscanf(fp, "\nPixcmap: depth = %d bpp; %d colors\n",
1626  &depth, &ncolors);
1627  if (ret != 2 ||
1628  (depth != 1 && depth != 2 && depth != 4 && depth != 8) ||
1629  (ncolors < 2 || ncolors > 256))
1630  return (PIXCMAP *)ERROR_PTR("invalid cmap size", procName, NULL);
1631  ignore = fscanf(fp, "Color R-val G-val B-val Alpha\n");
1632  ignore = fscanf(fp, "----------------------------------------\n");
1633 
1634  cmap = pixcmapCreate(depth);
1635  for (i = 0; i < ncolors; i++) {
1636  if (fscanf(fp, "%3d %3d %3d %3d %3d\n",
1637  &index, &rval, &gval, &bval, &aval) != 5) {
1638  pixcmapDestroy(&cmap);
1639  return (PIXCMAP *)ERROR_PTR("invalid entry", procName, NULL);
1640  }
1641  pixcmapAddRGBA(cmap, rval, gval, bval, aval);
1642  }
1643  return cmap;
1644 }
1645 
1646 
1654 PIXCMAP *
1655 pixcmapReadMem(const l_uint8 *data,
1656  size_t size)
1657 {
1658 FILE *fp;
1659 PIXCMAP *cmap;
1660 
1661  PROCNAME("pixcmapReadMem");
1662 
1663  if (!data)
1664  return (PIXCMAP *)ERROR_PTR("data not defined", procName, NULL);
1665  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1666  return (PIXCMAP *)ERROR_PTR("stream not opened", procName, NULL);
1667 
1668  cmap = pixcmapReadStream(fp);
1669  fclose(fp);
1670  if (!cmap) L_ERROR("cmap not read\n", procName);
1671  return cmap;
1672 }
1673 
1674 
1682 l_int32
1683 pixcmapWrite(const char *filename,
1684  PIXCMAP *cmap)
1685 {
1686 l_int32 ret;
1687 FILE *fp;
1688 
1689  PROCNAME("pixcmapWrite");
1690 
1691  if (!filename)
1692  return ERROR_INT("filename not defined", procName, 1);
1693  if (!cmap)
1694  return ERROR_INT("cmap not defined", procName, 1);
1695 
1696  if ((fp = fopenWriteStream(filename, "w")) == NULL)
1697  return ERROR_INT("stream not opened", procName, 1);
1698  ret = pixcmapWriteStream(fp, cmap);
1699  fclose(fp);
1700  if (ret)
1701  return ERROR_INT("cmap not written to stream", procName, 1);
1702  return 0;
1703 }
1704 
1705 
1706 
1714 l_int32
1716  PIXCMAP *cmap)
1717 {
1718 l_int32 *rmap, *gmap, *bmap, *amap;
1719 l_int32 i;
1720 
1721  PROCNAME("pixcmapWriteStream");
1722 
1723  if (!fp)
1724  return ERROR_INT("stream not defined", procName, 1);
1725  if (!cmap)
1726  return ERROR_INT("cmap not defined", procName, 1);
1727 
1728  if (pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap))
1729  return ERROR_INT("colormap arrays not made", procName, 1);
1730 
1731  fprintf(fp, "\nPixcmap: depth = %d bpp; %d colors\n", cmap->depth, cmap->n);
1732  fprintf(fp, "Color R-val G-val B-val Alpha\n");
1733  fprintf(fp, "----------------------------------------\n");
1734  for (i = 0; i < cmap->n; i++)
1735  fprintf(fp, "%3d %3d %3d %3d %3d\n",
1736  i, rmap[i], gmap[i], bmap[i], amap[i]);
1737  fprintf(fp, "\n");
1738 
1739  LEPT_FREE(rmap);
1740  LEPT_FREE(gmap);
1741  LEPT_FREE(bmap);
1742  LEPT_FREE(amap);
1743  return 0;
1744 }
1745 
1746 
1760 l_int32
1761 pixcmapWriteMem(l_uint8 **pdata,
1762  size_t *psize,
1763  PIXCMAP *cmap)
1764 {
1765 l_int32 ret;
1766 FILE *fp;
1767 
1768  PROCNAME("pixcmapWriteMem");
1769 
1770  if (pdata) *pdata = NULL;
1771  if (psize) *psize = 0;
1772  if (!pdata)
1773  return ERROR_INT("&data not defined", procName, 1);
1774  if (!psize)
1775  return ERROR_INT("&size not defined", procName, 1);
1776  if (!cmap)
1777  return ERROR_INT("cmap not defined", procName, 1);
1778 
1779 #if HAVE_FMEMOPEN
1780  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1781  return ERROR_INT("stream not opened", procName, 1);
1782  ret = pixcmapWriteStream(fp, cmap);
1783 #else
1784  L_INFO("work-around: writing to a temp file\n", procName);
1785  #ifdef _WIN32
1786  if ((fp = fopenWriteWinTempfile()) == NULL)
1787  return ERROR_INT("tmpfile stream not opened", procName, 1);
1788  #else
1789  if ((fp = tmpfile()) == NULL)
1790  return ERROR_INT("tmpfile stream not opened", procName, 1);
1791  #endif /* _WIN32 */
1792  ret = pixcmapWriteStream(fp, cmap);
1793  rewind(fp);
1794  *pdata = l_binaryReadStream(fp, psize);
1795 #endif /* HAVE_FMEMOPEN */
1796  fclose(fp);
1797  return ret;
1798 }
1799 
1800 
1801 /*----------------------------------------------------------------------*
1802  * Extract colormap arrays and serialization *
1803  *----------------------------------------------------------------------*/
1812 l_int32
1814  l_int32 **prmap,
1815  l_int32 **pgmap,
1816  l_int32 **pbmap,
1817  l_int32 **pamap)
1818 {
1819 l_int32 *rmap, *gmap, *bmap, *amap;
1820 l_int32 i, ncolors;
1821 RGBA_QUAD *cta;
1822 
1823  PROCNAME("pixcmapToArrays");
1824 
1825  if (!prmap || !pgmap || !pbmap)
1826  return ERROR_INT("&rmap, &gmap, &bmap not all defined", procName, 1);
1827  *prmap = *pgmap = *pbmap = NULL;
1828  if (pamap) *pamap = NULL;
1829  if (!cmap)
1830  return ERROR_INT("cmap not defined", procName, 1);
1831 
1832  ncolors = pixcmapGetCount(cmap);
1833  if (((rmap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32))) == NULL) ||
1834  ((gmap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32))) == NULL) ||
1835  ((bmap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32))) == NULL))
1836  return ERROR_INT("calloc fail for *map", procName, 1);
1837  *prmap = rmap;
1838  *pgmap = gmap;
1839  *pbmap = bmap;
1840  if (pamap) {
1841  amap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32));
1842  *pamap = amap;
1843  }
1844 
1845  cta = (RGBA_QUAD *)cmap->array;
1846  for (i = 0; i < ncolors; i++) {
1847  rmap[i] = cta[i].red;
1848  gmap[i] = cta[i].green;
1849  bmap[i] = cta[i].blue;
1850  if (pamap)
1851  amap[i] = cta[i].alpha;
1852  }
1853 
1854  return 0;
1855 }
1856 
1857 
1866 l_int32
1868  l_uint32 **ptab,
1869  l_int32 *pncolors)
1870 {
1871 l_int32 i, ncolors, rval, gval, bval, aval;
1872 l_uint32 *tab;
1873 
1874  PROCNAME("pixcmapToRGBTable");
1875 
1876  if (!ptab)
1877  return ERROR_INT("&tab not defined", procName, 1);
1878  *ptab = NULL;
1879  if (!cmap)
1880  return ERROR_INT("cmap not defined", procName, 1);
1881 
1882  ncolors = pixcmapGetCount(cmap);
1883  if (pncolors)
1884  *pncolors = ncolors;
1885  if ((tab = (l_uint32 *)LEPT_CALLOC(ncolors, sizeof(l_uint32))) == NULL)
1886  return ERROR_INT("tab not made", procName, 1);
1887  *ptab = tab;
1888 
1889  for (i = 0; i < ncolors; i++) {
1890  pixcmapGetRGBA(cmap, i, &rval, &gval, &bval, &aval);
1891  composeRGBAPixel(rval, gval, bval, aval, &tab[i]);
1892  }
1893  return 0;
1894 }
1895 
1896 
1911 l_int32
1913  l_int32 cpc,
1914  l_int32 *pncolors,
1915  l_uint8 **pdata)
1916 {
1917 l_int32 i, ncolors, rval, gval, bval, aval;
1918 l_uint8 *data;
1919 
1920  PROCNAME("pixcmapSerializeToMemory");
1921 
1922  if (!pdata)
1923  return ERROR_INT("&data not defined", procName, 1);
1924  *pdata = NULL;
1925  if (!pncolors)
1926  return ERROR_INT("&ncolors not defined", procName, 1);
1927  *pncolors = 0;
1928  if (!cmap)
1929  return ERROR_INT("cmap not defined", procName, 1);
1930  if (cpc != 3 && cpc != 4)
1931  return ERROR_INT("cpc not 3 or 4", procName, 1);
1932 
1933  ncolors = pixcmapGetCount(cmap);
1934  *pncolors = ncolors;
1935  if ((data = (l_uint8 *)LEPT_CALLOC(cpc * ncolors, sizeof(l_uint8))) == NULL)
1936  return ERROR_INT("data not made", procName, 1);
1937  *pdata = data;
1938 
1939  for (i = 0; i < ncolors; i++) {
1940  pixcmapGetRGBA(cmap, i, &rval, &gval, &bval, &aval);
1941  data[cpc * i] = rval;
1942  data[cpc * i + 1] = gval;
1943  data[cpc * i + 2] = bval;
1944  if (cpc == 4)
1945  data[cpc * i + 3] = aval;
1946  }
1947  return 0;
1948 }
1949 
1950 
1959 PIXCMAP *
1961  l_int32 cpc,
1962  l_int32 ncolors)
1963 {
1964 l_int32 i, d, rval, gval, bval, aval;
1965 PIXCMAP *cmap;
1966 
1967  PROCNAME("pixcmapDeserializeFromMemory");
1968 
1969  if (!data)
1970  return (PIXCMAP *)ERROR_PTR("data not defined", procName, NULL);
1971  if (cpc != 3 && cpc != 4)
1972  return (PIXCMAP *)ERROR_PTR("cpc not 3 or 4", procName, NULL);
1973  if (ncolors == 0)
1974  return (PIXCMAP *)ERROR_PTR("no entries", procName, NULL);
1975  if (ncolors > 256)
1976  return (PIXCMAP *)ERROR_PTR("ncolors > 256", procName, NULL);
1977 
1978  if (ncolors > 16)
1979  d = 8;
1980  else if (ncolors > 4)
1981  d = 4;
1982  else if (ncolors > 2)
1983  d = 2;
1984  else
1985  d = 1;
1986  cmap = pixcmapCreate(d);
1987  for (i = 0; i < ncolors; i++) {
1988  rval = data[cpc * i];
1989  gval = data[cpc * i + 1];
1990  bval = data[cpc * i + 2];
1991  if (cpc == 4)
1992  aval = data[cpc * i + 3];
1993  else
1994  aval = 255; /* opaque */
1995  pixcmapAddRGBA(cmap, rval, gval, bval, aval);
1996  }
1997 
1998  return cmap;
1999 }
2000 
2001 
2020 char *
2021 pixcmapConvertToHex(l_uint8 *data,
2022  l_int32 ncolors)
2023 {
2024 l_int32 i, j, hexbytes;
2025 char *hexdata = NULL;
2026 char buf[4];
2027 
2028  PROCNAME("pixcmapConvertToHex");
2029 
2030  if (!data)
2031  return (char *)ERROR_PTR("data not defined", procName, NULL);
2032  if (ncolors < 1)
2033  return (char *)ERROR_PTR("no colors", procName, NULL);
2034 
2035  hexbytes = 2 + (2 * 3 + 1) * ncolors + 2;
2036  hexdata = (char *)LEPT_CALLOC(hexbytes, sizeof(char));
2037  hexdata[0] = '<';
2038  hexdata[1] = ' ';
2039 
2040  for (i = 0; i < ncolors; i++) {
2041  j = 2 + (2 * 3 + 1) * i;
2042  snprintf(buf, sizeof(buf), "%02x", data[3 * i]);
2043  hexdata[j] = buf[0];
2044  hexdata[j + 1] = buf[1];
2045  snprintf(buf, sizeof(buf), "%02x", data[3 * i + 1]);
2046  hexdata[j + 2] = buf[0];
2047  hexdata[j + 3] = buf[1];
2048  snprintf(buf, sizeof(buf), "%02x", data[3 * i + 2]);
2049  hexdata[j + 4] = buf[0];
2050  hexdata[j + 5] = buf[1];
2051  hexdata[j + 6] = ' ';
2052  }
2053  hexdata[j + 7] = '>';
2054  hexdata[j + 8] = '\0';
2055  return hexdata;
2056 }
2057 
2058 
2059 /*-------------------------------------------------------------*
2060  * Colormap transforms *
2061  *-------------------------------------------------------------*/
2078 l_int32
2080  l_float32 gamma,
2081  l_int32 minval,
2082  l_int32 maxval)
2083 {
2084 l_int32 rval, gval, bval, trval, tgval, tbval, i, ncolors;
2085 NUMA *nag;
2086 
2087  PROCNAME("pixcmapGammaTRC");
2088 
2089  if (!cmap)
2090  return ERROR_INT("cmap not defined", procName, 1);
2091  if (gamma <= 0.0) {
2092  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
2093  gamma = 1.0;
2094  }
2095  if (minval >= maxval)
2096  return ERROR_INT("minval not < maxval", procName, 1);
2097 
2098  if (gamma == 1.0 && minval == 0 && maxval == 255) /* no-op */
2099  return 0;
2100 
2101  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
2102  return ERROR_INT("nag not made", procName, 1);
2103 
2104  ncolors = pixcmapGetCount(cmap);
2105  for (i = 0; i < ncolors; i++) {
2106  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2107  numaGetIValue(nag, rval, &trval);
2108  numaGetIValue(nag, gval, &tgval);
2109  numaGetIValue(nag, bval, &tbval);
2110  pixcmapResetColor(cmap, i, trval, tgval, tbval);
2111  }
2112 
2113  numaDestroy(&nag);
2114  return 0;
2115 }
2116 
2117 
2133 l_int32
2135  l_float32 factor)
2136 {
2137 l_int32 i, ncolors, rval, gval, bval, trval, tgval, tbval;
2138 NUMA *nac;
2139 
2140  PROCNAME("pixcmapContrastTRC");
2141 
2142  if (!cmap)
2143  return ERROR_INT("cmap not defined", procName, 1);
2144  if (factor < 0.0) {
2145  L_WARNING("factor must be >= 0.0; setting to 0.0\n", procName);
2146  factor = 0.0;
2147  }
2148 
2149  if ((nac = numaContrastTRC(factor)) == NULL)
2150  return ERROR_INT("nac not made", procName, 1);
2151 
2152  ncolors = pixcmapGetCount(cmap);
2153  for (i = 0; i < ncolors; i++) {
2154  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2155  numaGetIValue(nac, rval, &trval);
2156  numaGetIValue(nac, gval, &tgval);
2157  numaGetIValue(nac, bval, &tbval);
2158  pixcmapResetColor(cmap, i, trval, tgval, tbval);
2159  }
2160 
2161  numaDestroy(&nac);
2162  return 0;
2163 }
2164 
2165 
2185 l_int32
2187  l_float32 fraction)
2188 {
2189 l_int32 i, ncolors, rval, gval, bval;
2190 
2191  PROCNAME("pixcmapShiftIntensity");
2192 
2193  if (!cmap)
2194  return ERROR_INT("cmap not defined", procName, 1);
2195  if (fraction < -1.0 || fraction > 1.0)
2196  return ERROR_INT("fraction not in [-1.0, 1.0]", procName, 1);
2197 
2198  ncolors = pixcmapGetCount(cmap);
2199  for (i = 0; i < ncolors; i++) {
2200  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2201  if (fraction < 0.0)
2202  pixcmapResetColor(cmap, i,
2203  (l_int32)((1.0 + fraction) * rval),
2204  (l_int32)((1.0 + fraction) * gval),
2205  (l_int32)((1.0 + fraction) * bval));
2206  else
2207  pixcmapResetColor(cmap, i,
2208  rval + (l_int32)(fraction * (255 - rval)),
2209  gval + (l_int32)(fraction * (255 - gval)),
2210  bval + (l_int32)(fraction * (255 - bval)));
2211  }
2212 
2213  return 0;
2214 }
2215 
2216 
2235 l_int32
2237  l_uint32 srcval,
2238  l_uint32 dstval)
2239 {
2240 l_int32 i, ncolors, rval, gval, bval;
2241 l_uint32 newval;
2242 
2243  PROCNAME("pixcmapShiftByComponent");
2244 
2245  if (!cmap)
2246  return ERROR_INT("cmap not defined", procName, 1);
2247 
2248  ncolors = pixcmapGetCount(cmap);
2249  for (i = 0; i < ncolors; i++) {
2250  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2251  pixelShiftByComponent(rval, gval, bval, srcval, dstval, &newval);
2252  extractRGBValues(newval, &rval, &gval, &bval);
2253  pixcmapResetColor(cmap, i, rval, gval, bval);
2254  }
2255 
2256  return 0;
2257 }
l_int32 pixcmapIsBlackAndWhite(PIXCMAP *cmap, l_int32 *pblackwhite)
pixcmapIsBlackAndWhite()
Definition: colormap.c:1034
l_uint8 alpha
Definition: pix.h:174
l_int32 pixcmapGetNearestIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetNearestIndex()
Definition: colormap.c:1167
l_int32 pixcmapGetDepth(PIXCMAP *cmap)
pixcmapGetDepth()
Definition: colormap.c:627
l_int32 numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:472
NUMA * numaGetSortIndex(NUMA *na, l_int32 sortorder)
numaGetSortIndex()
Definition: numafunc1.c:2621
l_int32 pixelShiftByComponent(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 srcval, l_uint32 dstval, l_uint32 *ppixel)
pixelShiftByComponent()
Definition: coloring.c:964
char * pixcmapConvertToHex(l_uint8 *data, l_int32 ncolors)
pixcmapConvertToHex()
Definition: colormap.c:2021
l_int32 n
Definition: pix.h:160
PIXCMAP * pixcmapReadStream(FILE *fp)
pixcmapReadStream()
Definition: colormap.c:1614
PIXCMAP * pixcmapConvertTo8(PIXCMAP *cmaps)
pixcmapConvertTo8()
Definition: colormap.c:1553
l_int32 pixcmapSetBlackAndWhite(PIXCMAP *cmap, l_int32 setblack, l_int32 setwhite)
pixcmapSetBlackAndWhite()
Definition: colormap.c:563
l_int32 n
Definition: ccbord.h:111
NUMA * numaGammaTRC(l_float32 gamma, l_int32 minval, l_int32 maxval)
numaGammaTRC()
Definition: enhance.c:363
PIXCMAP * pixcmapGrayToColor(l_uint32 color)
pixcmapGrayToColor()
Definition: colormap.c:1430
PIXCMAP * pixcmapRead(const char *filename)
pixcmapRead()
Definition: colormap.c:1587
l_int32 pixcmapShiftByComponent(PIXCMAP *cmap, l_uint32 srcval, l_uint32 dstval)
pixcmapShiftByComponent()
Definition: colormap.c:2236
l_uint8 red
Definition: pix.h:173
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1670
l_int32 composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2690
l_int32 pixcmapAddNewColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapAddNewColor()
Definition: colormap.c:381
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:263
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:186
PIXCMAP * pixcmapReadMem(const l_uint8 *data, size_t size)
pixcmapReadMem()
Definition: colormap.c:1655
l_int32 depth
Definition: pix.h:158
PIXCMAP * pixcmapConvertTo4(PIXCMAP *cmaps)
pixcmapConvertTo4()
Definition: colormap.c:1518
l_int32 pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:709
l_int32 pixcmapToArrays(PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
Definition: colormap.c:1813
l_int32 pixcmapClear(PIXCMAP *cmap)
pixcmapClear()
Definition: colormap.c:686
l_int32 pixcmapGetRGBA32(PIXCMAP *cmap, l_int32 index, l_uint32 *pval32)
pixcmapGetRGBA32()
Definition: colormap.c:815
l_int32 nalloc
Definition: pix.h:159
l_int32 pixcmapAddBlackOrWhite(PIXCMAP *cmap, l_int32 color, l_int32 *pindex)
pixcmapAddBlackOrWhite()
Definition: colormap.c:524
PIXCMAP * pixcmapCreateLinear(l_int32 d, l_int32 nlevels)
pixcmapCreateLinear()
Definition: colormap.c:203
l_uint8 blue
Definition: pix.h:171
l_int32 pixcmapShiftIntensity(PIXCMAP *cmap, l_float32 fraction)
pixcmapShiftIntensity()
Definition: colormap.c:2186
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:110
l_int32 pixcmapGetRGBA(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *paval)
pixcmapGetRGBA()
Definition: colormap.c:777
l_int32 pixcmapGetIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetIndex()
Definition: colormap.c:921
l_int32 pixcmapWriteStream(FILE *fp, PIXCMAP *cmap)
pixcmapWriteStream()
Definition: colormap.c:1715
Definition: array.h:59
l_int32 pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
Definition: colormap.c:999
l_int32 pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:299
l_int32 pixcmapUsableColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pusable)
pixcmapUsableColor()
Definition: colormap.c:477
PIXCMAP * pixcmapColorToGray(PIXCMAP *cmaps, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixcmapColorToGray()
Definition: colormap.c:1462
FILE * fopenWriteWinTempfile()
fopenWriteWinTempfile()
Definition: utils2.c:1716
l_int32 pixcmapGetRankIntensity(PIXCMAP *cmap, l_float32 rankval, l_int32 *pindex)
pixcmapGetRankIntensity()
Definition: colormap.c:1116
l_uint8 green
Definition: pix.h:172
Definition: pix.h:169
PIXCMAP * pixcmapDeserializeFromMemory(l_uint8 *data, l_int32 cpc, l_int32 ncolors)
pixcmapDeserializeFromMemory()
Definition: colormap.c:1960
l_int32 pixcmapGetFreeCount(PIXCMAP *cmap)
pixcmapGetFreeCount()
Definition: colormap.c:610
l_int32 pixcmapGetColor32(PIXCMAP *cmap, l_int32 index, l_uint32 *pval32)
pixcmapGetColor32()
Definition: colormap.c:749
NUMA * numaContrastTRC(l_float32 factor)
numaContrastTRC()
Definition: enhance.c:554
l_int32 pixcmapGetMinDepth(PIXCMAP *cmap, l_int32 *pmindepth)
pixcmapGetMinDepth()
Definition: colormap.c:650
l_int32 pixcmapAddNearestColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapAddNearestColor()
Definition: colormap.c:430
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:359
l_int32 pixcmapGetDistanceToColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pdist)
pixcmapGetDistanceToColor()
Definition: colormap.c:1278
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1636
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1593
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1200
l_int32 pixcmapContrastTRC(PIXCMAP *cmap, l_float32 factor)
pixcmapContrastTRC()
Definition: colormap.c:2134
l_int32 pixcmapGetNearestGrayIndex(PIXCMAP *cmap, l_int32 val, l_int32 *pindex)
pixcmapGetNearestGrayIndex()
Definition: colormap.c:1225
l_int32 pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:851
l_int32 pixcmapWrite(const char *filename, PIXCMAP *cmap)
pixcmapWrite()
Definition: colormap.c:1683
void * array
Definition: pix.h:157
l_int32 pixcmapToRGBTable(PIXCMAP *cmap, l_uint32 **ptab, l_int32 *pncolors)
pixcmapToRGBTable()
Definition: colormap.c:1867
l_int32 pixcmapAddRGBA(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval)
pixcmapAddRGBA()
Definition: colormap.c:337
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:593
l_int32 pixcmapWriteMem(l_uint8 **pdata, size_t *psize, PIXCMAP *cmap)
pixcmapWriteMem()
Definition: colormap.c:1761
l_int32 pixcmapGammaTRC(PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixcmapGammaTRC()
Definition: colormap.c:2079
l_int32 numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:726
l_int32 pixcmapSerializeToMemory(PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata)
pixcmapSerializeToMemory()
Definition: colormap.c:1912
PIXCMAP * pixcmapCopy(PIXCMAP *cmaps)
pixcmapCopy()
Definition: colormap.c:233
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2725
l_int32 pixcmapGetRangeValues(PIXCMAP *cmap, l_int32 select, l_int32 *pminval, l_int32 *pmaxval, l_int32 *pminindex, l_int32 *pmaxindex)
pixcmapGetRangeValues()
Definition: colormap.c:1334
l_int32 pixcmapSetAlpha(PIXCMAP *cmap, l_int32 index, l_int32 aval)
pixcmapSetAlpha()
Definition: colormap.c:892
l_int32 pixcmapCountGrayColors(PIXCMAP *cmap, l_int32 *pngray)
pixcmapCountGrayColors()
Definition: colormap.c:1075
PIXCMAP * pixcmapCreateRandom(l_int32 depth, l_int32 hasblack, l_int32 haswhite)
pixcmapCreateRandom()
Definition: colormap.c:157
l_int32 pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:960