Leptonica  1.77.0
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 
98 #include <string.h>
99 #include "allheaders.h"
100 
101 /*-------------------------------------------------------------*
102  * Colormap creation and addition *
103  *-------------------------------------------------------------*/
110 PIXCMAP *
111 pixcmapCreate(l_int32 depth)
112 {
113 RGBA_QUAD *cta;
114 PIXCMAP *cmap;
115 
116  PROCNAME("pixcmapCreate");
117 
118  if (depth != 1 && depth != 2 && depth !=4 && depth != 8)
119  return (PIXCMAP *)ERROR_PTR("depth not in {1,2,4,8}", procName, NULL);
120 
121  cmap = (PIXCMAP *)LEPT_CALLOC(1, sizeof(PIXCMAP));
122  cmap->depth = depth;
123  cmap->nalloc = 1 << depth;
124  cta = (RGBA_QUAD *)LEPT_CALLOC(cmap->nalloc, sizeof(RGBA_QUAD));
125  cmap->array = cta;
126  cmap->n = 0;
127  return cmap;
128 }
129 
130 
157 PIXCMAP *
158 pixcmapCreateRandom(l_int32 depth,
159  l_int32 hasblack,
160  l_int32 haswhite)
161 {
162 l_int32 ncolors, i;
163 l_int32 red[256], green[256], blue[256];
164 PIXCMAP *cmap;
165 
166  PROCNAME("pixcmapCreateRandom");
167 
168  if (depth != 2 && depth != 4 && depth != 8)
169  return (PIXCMAP *)ERROR_PTR("depth not in {2, 4, 8}", procName, NULL);
170  if (hasblack != 0) hasblack = 1;
171  if (haswhite != 0) haswhite = 1;
172 
173  cmap = pixcmapCreate(depth);
174  ncolors = 1 << depth;
175  if (hasblack) /* first color is optionally black */
176  pixcmapAddColor(cmap, 0, 0, 0);
177  for (i = hasblack; i < ncolors - haswhite; i++) {
178  red[i] = (l_uint32)rand() & 0xff;
179  green[i] = (l_uint32)rand() & 0xff;
180  blue[i] = (l_uint32)rand() & 0xff;
181  pixcmapAddColor(cmap, red[i], green[i], blue[i]);
182  }
183  if (haswhite) /* last color is optionally white */
184  pixcmapAddColor(cmap, 255, 255, 255);
185 
186  return cmap;
187 }
188 
189 
203 PIXCMAP *
205  l_int32 nlevels)
206 {
207 l_int32 maxlevels, i, val;
208 PIXCMAP *cmap;
209 
210  PROCNAME("pixcmapCreateLinear");
211 
212  if (d != 1 && d != 2 && d !=4 && d != 8)
213  return (PIXCMAP *)ERROR_PTR("d not in {1, 2, 4, 8}", procName, NULL);
214  maxlevels = 1 << d;
215  if (nlevels < 2 || nlevels > maxlevels)
216  return (PIXCMAP *)ERROR_PTR("invalid nlevels", procName, NULL);
217 
218  cmap = pixcmapCreate(d);
219  for (i = 0; i < nlevels; i++) {
220  val = (255 * i) / (nlevels - 1);
221  pixcmapAddColor(cmap, val, val, val);
222  }
223  return cmap;
224 }
225 
226 
233 PIXCMAP *
235 {
236 l_int32 nbytes, valid;
237 PIXCMAP *cmapd;
238 
239  PROCNAME("pixcmapCopy");
240 
241  if (!cmaps)
242  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
243  pixcmapIsValid(cmaps, &valid);
244  if (!valid)
245  return (PIXCMAP *)ERROR_PTR("invalid cmap", procName, NULL);
246 
247  cmapd = (PIXCMAP *)LEPT_CALLOC(1, sizeof(PIXCMAP));
248  nbytes = cmaps->nalloc * sizeof(RGBA_QUAD);
249  cmapd->array = (void *)LEPT_CALLOC(1, nbytes);
250  memcpy(cmapd->array, cmaps->array, cmaps->n * sizeof(RGBA_QUAD));
251  cmapd->n = cmaps->n;
252  cmapd->nalloc = cmaps->nalloc;
253  cmapd->depth = cmaps->depth;
254  return cmapd;
255 }
256 
257 
264 void
266 {
267 PIXCMAP *cmap;
268 
269  PROCNAME("pixcmapDestroy");
270 
271  if (pcmap == NULL) {
272  L_WARNING("ptr address is null!\n", procName);
273  return;
274  }
275 
276  if ((cmap = *pcmap) == NULL)
277  return;
278 
279  LEPT_FREE(cmap->array);
280  LEPT_FREE(cmap);
281  *pcmap = NULL;
282  return;
283 }
284 
292 l_ok
294  l_int32 *pvalid)
295 {
296 l_int32 d;
297 
298  PROCNAME("pixcmapIsValid");
299 
300  if (!pvalid)
301  return ERROR_INT("&valid not defined", procName, 1);
302  *pvalid = 0;
303  if (!cmap)
304  return ERROR_INT("cmap not defined", procName, 1);
305  if (!cmap->array)
306  return ERROR_INT("cmap array not defined", procName, 1);
307  d = cmap->depth;
308  if (d !=1 && d != 2 && d != 4 && d != 8) {
309  L_ERROR("invalid cmap depth: %d\n", procName, d);
310  return 1;
311  }
312  if (cmap->nalloc < 2 || cmap->nalloc > 256) {
313  L_ERROR("invalid cmap nalloc: %d\n", procName, cmap->nalloc);
314  return 1;
315  }
316  if (cmap->n < 0 || cmap->n > 256 || cmap->n > cmap->nalloc) {
317  L_ERROR("invalid cmap n: %d (nalloc = %d)\n", procName,
318  cmap->n, cmap->nalloc);
319  return 1;
320  }
321  *pvalid = 1;
322  return 0;
323 }
324 
325 
340 l_ok
342  l_int32 rval,
343  l_int32 gval,
344  l_int32 bval)
345 {
346 RGBA_QUAD *cta;
347 
348  PROCNAME("pixcmapAddColor");
349 
350  if (!cmap)
351  return ERROR_INT("cmap not defined", procName, 1);
352  if (cmap->n >= cmap->nalloc)
353  return ERROR_INT("no free color entries", procName, 1);
354 
355  cta = (RGBA_QUAD *)cmap->array;
356  cta[cmap->n].red = rval;
357  cta[cmap->n].green = gval;
358  cta[cmap->n].blue = bval;
359  cta[cmap->n].alpha = 255;
360  cmap->n++;
361  return 0;
362 }
363 
364 
378 l_ok
380  l_int32 rval,
381  l_int32 gval,
382  l_int32 bval,
383  l_int32 aval)
384 {
385 RGBA_QUAD *cta;
386 
387  PROCNAME("pixcmapAddRGBA");
388 
389  if (!cmap)
390  return ERROR_INT("cmap not defined", procName, 1);
391  if (cmap->n >= cmap->nalloc)
392  return ERROR_INT("no free color entries", procName, 1);
393 
394  cta = (RGBA_QUAD *)cmap->array;
395  cta[cmap->n].red = rval;
396  cta[cmap->n].green = gval;
397  cta[cmap->n].blue = bval;
398  cta[cmap->n].alpha = aval;
399  cmap->n++;
400  return 0;
401 }
402 
403 
422 l_ok
424  l_int32 rval,
425  l_int32 gval,
426  l_int32 bval,
427  l_int32 *pindex)
428 {
429  PROCNAME("pixcmapAddNewColor");
430 
431  if (!pindex)
432  return ERROR_INT("&index not defined", procName, 1);
433  *pindex = 0;
434  if (!cmap)
435  return ERROR_INT("cmap not defined", procName, 1);
436 
437  /* Check if the color is already present. */
438  if (!pixcmapGetIndex(cmap, rval, gval, bval, pindex)) /* found */
439  return 0;
440 
441  /* We need to add the color. Is there room? */
442  if (cmap->n >= cmap->nalloc) {
443  L_WARNING("no free color entries\n", procName);
444  return 2;
445  }
446 
447  /* There's room. Add it. */
448  pixcmapAddColor(cmap, rval, gval, bval);
449  *pindex = pixcmapGetCount(cmap) - 1;
450  return 0;
451 }
452 
453 
471 l_ok
473  l_int32 rval,
474  l_int32 gval,
475  l_int32 bval,
476  l_int32 *pindex)
477 {
478  PROCNAME("pixcmapAddNearestColor");
479 
480  if (!pindex)
481  return ERROR_INT("&index not defined", procName, 1);
482  *pindex = 0;
483  if (!cmap)
484  return ERROR_INT("cmap not defined", procName, 1);
485 
486  /* Check if the color is already present. */
487  if (!pixcmapGetIndex(cmap, rval, gval, bval, pindex)) /* found */
488  return 0;
489 
490  /* We need to add the color. Is there room? */
491  if (cmap->n < cmap->nalloc) {
492  pixcmapAddColor(cmap, rval, gval, bval);
493  *pindex = pixcmapGetCount(cmap) - 1;
494  return 0;
495  }
496 
497  /* There's no room. Return the index of the nearest color */
498  pixcmapGetNearestIndex(cmap, rval, gval, bval, pindex);
499  return 0;
500 }
501 
502 
518 l_ok
520  l_int32 rval,
521  l_int32 gval,
522  l_int32 bval,
523  l_int32 *pusable)
524 {
525 l_int32 index;
526 
527  PROCNAME("pixcmapUsableColor");
528 
529  if (!pusable)
530  return ERROR_INT("&usable not defined", procName, 1);
531  *pusable = 0;
532  if (!cmap)
533  return ERROR_INT("cmap not defined", procName, 1);
534 
535  /* Is there room to add it? */
536  if (cmap->n < cmap->nalloc) {
537  *pusable = 1;
538  return 0;
539  }
540 
541  /* No room; check if the color is already present. */
542  if (!pixcmapGetIndex(cmap, rval, gval, bval, &index)) /* found */
543  *pusable = 1;
544  return 0;
545 }
546 
547 
565 l_ok
567  l_int32 color,
568  l_int32 *pindex)
569 {
570 l_int32 index;
571 
572  PROCNAME("pixcmapAddBlackOrWhite");
573 
574  if (pindex) *pindex = 0;
575  if (!cmap)
576  return ERROR_INT("cmap not defined", procName, 1);
577 
578  if (color == 0) { /* black */
579  if (pixcmapGetFreeCount(cmap) > 0)
580  pixcmapAddNewColor(cmap, 0, 0, 0, &index);
581  else
582  pixcmapGetRankIntensity(cmap, 0.0, &index);
583  } else { /* white */
584  if (pixcmapGetFreeCount(cmap) > 0)
585  pixcmapAddNewColor(cmap, 255, 255, 255, &index);
586  else
587  pixcmapGetRankIntensity(cmap, 1.0, &index);
588  }
589 
590  if (pindex)
591  *pindex = index;
592  return 0;
593 }
594 
595 
604 l_ok
606  l_int32 setblack,
607  l_int32 setwhite)
608 {
609 l_int32 index;
610 
611  PROCNAME("pixcmapSetBlackAndWhite");
612 
613  if (!cmap)
614  return ERROR_INT("cmap not defined", procName, 1);
615 
616  if (setblack) {
617  pixcmapGetRankIntensity(cmap, 0.0, &index);
618  pixcmapResetColor(cmap, index, 0, 0, 0);
619  }
620  if (setwhite) {
621  pixcmapGetRankIntensity(cmap, 1.0, &index);
622  pixcmapResetColor(cmap, index, 255, 255, 255);
623  }
624  return 0;
625 }
626 
627 
634 l_int32
636 {
637  PROCNAME("pixcmapGetCount");
638 
639  if (!cmap)
640  return ERROR_INT("cmap not defined", procName, 0);
641  return cmap->n;
642 }
643 
644 
651 l_int32
653 {
654  PROCNAME("pixcmapGetFreeCount");
655 
656  if (!cmap)
657  return ERROR_INT("cmap not defined", procName, 0);
658  return (cmap->nalloc - cmap->n);
659 }
660 
661 
668 l_int32
670 {
671  PROCNAME("pixcmapGetDepth");
672 
673  if (!cmap)
674  return ERROR_INT("cmap not defined", procName, 0);
675  return cmap->depth;
676 }
677 
678 
691 l_ok
693  l_int32 *pmindepth)
694 {
695 l_int32 ncolors;
696 
697  PROCNAME("pixcmapGetMinDepth");
698 
699  if (!pmindepth)
700  return ERROR_INT("&mindepth not defined", procName, 1);
701  *pmindepth = 0;
702  if (!cmap)
703  return ERROR_INT("cmap not defined", procName, 1);
704 
705  ncolors = pixcmapGetCount(cmap);
706  if (ncolors <= 4)
707  *pmindepth = 2;
708  else if (ncolors <= 16)
709  *pmindepth = 4;
710  else /* ncolors > 16 */
711  *pmindepth = 8;
712  return 0;
713 }
714 
715 
727 l_ok
729 {
730  PROCNAME("pixcmapClear");
731 
732  if (!cmap)
733  return ERROR_INT("cmap not defined", procName, 1);
734  cmap->n = 0;
735  return 0;
736 }
737 
738 
739 /*-------------------------------------------------------------*
740  * Colormap random access *
741  *-------------------------------------------------------------*/
750 l_ok
752  l_int32 index,
753  l_int32 *prval,
754  l_int32 *pgval,
755  l_int32 *pbval)
756 {
757 RGBA_QUAD *cta;
758 
759  PROCNAME("pixcmapGetColor");
760 
761  if (!prval || !pgval || !pbval)
762  return ERROR_INT("&rval, &gval, &bval not all defined", procName, 1);
763  *prval = *pgval = *pbval = 0;
764  if (!cmap)
765  return ERROR_INT("cmap not defined", procName, 1);
766  if (index < 0 || index >= cmap->n)
767  return ERROR_INT("index out of bounds", procName, 1);
768 
769  cta = (RGBA_QUAD *)cmap->array;
770  *prval = cta[index].red;
771  *pgval = cta[index].green;
772  *pbval = cta[index].blue;
773  return 0;
774 }
775 
776 
790 l_ok
792  l_int32 index,
793  l_uint32 *pval32)
794 {
795 l_int32 rval, gval, bval;
796 
797  PROCNAME("pixcmapGetColor32");
798 
799  if (!pval32)
800  return ERROR_INT("&val32 not defined", procName, 1);
801  *pval32 = 0;
802 
803  if (pixcmapGetColor(cmap, index, &rval, &gval, &bval) != 0)
804  return ERROR_INT("rgb values not found", procName, 1);
805  composeRGBAPixel(rval, gval, bval, 255, pval32);
806  return 0;
807 }
808 
809 
818 l_ok
820  l_int32 index,
821  l_int32 *prval,
822  l_int32 *pgval,
823  l_int32 *pbval,
824  l_int32 *paval)
825 {
826 RGBA_QUAD *cta;
827 
828  PROCNAME("pixcmapGetRGBA");
829 
830  if (!prval || !pgval || !pbval || !paval)
831  return ERROR_INT("&rval, &gval, &bval, &aval not all defined",
832  procName, 1);
833  *prval = *pgval = *pbval = *paval = 0;
834  if (!cmap)
835  return ERROR_INT("cmap not defined", procName, 1);
836  if (index < 0 || index >= cmap->n)
837  return ERROR_INT("index out of bounds", procName, 1);
838 
839  cta = (RGBA_QUAD *)cmap->array;
840  *prval = cta[index].red;
841  *pgval = cta[index].green;
842  *pbval = cta[index].blue;
843  *paval = cta[index].alpha;
844  return 0;
845 }
846 
847 
856 l_ok
858  l_int32 index,
859  l_uint32 *pval32)
860 {
861 l_int32 rval, gval, bval, aval;
862 
863  PROCNAME("pixcmapGetRGBA32");
864 
865  if (!pval32)
866  return ERROR_INT("&val32 not defined", procName, 1);
867  *pval32 = 0;
868 
869  if (pixcmapGetRGBA(cmap, index, &rval, &gval, &bval, &aval) != 0)
870  return ERROR_INT("rgba values not found", procName, 1);
871  composeRGBAPixel(rval, gval, bval, aval, pval32);
872  return 0;
873 }
874 
875 
892 l_ok
894  l_int32 index,
895  l_int32 rval,
896  l_int32 gval,
897  l_int32 bval)
898 {
899 RGBA_QUAD *cta;
900 
901  PROCNAME("pixcmapResetColor");
902 
903  if (!cmap)
904  return ERROR_INT("cmap not defined", procName, 1);
905  if (index < 0 || index >= cmap->n)
906  return ERROR_INT("index out of bounds", procName, 1);
907 
908  cta = (RGBA_QUAD *)cmap->array;
909  cta[index].red = rval;
910  cta[index].green = gval;
911  cta[index].blue = bval;
912  cta[index].alpha = 255;
913  return 0;
914 }
915 
916 
933 l_ok
935  l_int32 index,
936  l_int32 aval)
937 {
938 RGBA_QUAD *cta;
939 
940  PROCNAME("pixcmapSetAlpha");
941 
942  if (!cmap)
943  return ERROR_INT("cmap not defined", procName, 1);
944  if (index < 0 || index >= cmap->n)
945  return ERROR_INT("index out of bounds", procName, 1);
946 
947  cta = (RGBA_QUAD *)cmap->array;
948  cta[index].alpha = aval;
949  return 0;
950 }
951 
952 
962 l_int32
964  l_int32 rval,
965  l_int32 gval,
966  l_int32 bval,
967  l_int32 *pindex)
968 {
969 l_int32 n, i;
970 RGBA_QUAD *cta;
971 
972  PROCNAME("pixcmapGetIndex");
973 
974  if (!pindex)
975  return ERROR_INT("&index not defined", procName, 1);
976  *pindex = 0;
977  if (!cmap)
978  return ERROR_INT("cmap not defined", procName, 1);
979  n = pixcmapGetCount(cmap);
980 
981  cta = (RGBA_QUAD *)cmap->array;
982  for (i = 0; i < n; i++) {
983  if (rval == cta[i].red &&
984  gval == cta[i].green &&
985  bval == cta[i].blue) {
986  *pindex = i;
987  return 0;
988  }
989  }
990  return 1;
991 }
992 
993 
1001 l_ok
1003  l_int32 *pcolor)
1004 {
1005 l_int32 n, i;
1006 l_int32 *rmap, *gmap, *bmap;
1007 
1008  PROCNAME("pixcmapHasColor");
1009 
1010  if (!pcolor)
1011  return ERROR_INT("&color not defined", procName, 1);
1012  *pcolor = FALSE;
1013  if (!cmap)
1014  return ERROR_INT("cmap not defined", procName, 1);
1015 
1016  if (pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL))
1017  return ERROR_INT("colormap arrays not made", procName, 1);
1018  n = pixcmapGetCount(cmap);
1019  for (i = 0; i < n; i++) {
1020  if ((rmap[i] != gmap[i]) || (rmap[i] != bmap[i])) {
1021  *pcolor = TRUE;
1022  break;
1023  }
1024  }
1025 
1026  LEPT_FREE(rmap);
1027  LEPT_FREE(gmap);
1028  LEPT_FREE(bmap);
1029  return 0;
1030 }
1031 
1032 
1040 l_ok
1042  l_int32 *popaque)
1043 {
1044 l_int32 i, n;
1045 RGBA_QUAD *cta;
1046 
1047  PROCNAME("pixcmapIsOpaque");
1048 
1049  if (!popaque)
1050  return ERROR_INT("&opaque not defined", procName, 1);
1051  *popaque = TRUE;
1052  if (!cmap)
1053  return ERROR_INT("cmap not defined", procName, 1);
1054 
1055  n = pixcmapGetCount(cmap);
1056  cta = (RGBA_QUAD *)cmap->array;
1057  for (i = 0; i < n; i++) {
1058  if (cta[i].alpha != 255) {
1059  *popaque = FALSE;
1060  break;
1061  }
1062  }
1063  return 0;
1064 }
1065 
1066 
1075 l_ok
1077  l_int32 *pblackwhite)
1078 {
1079 l_int32 val0, val1, hascolor;
1080 RGBA_QUAD *cta;
1081 
1082  PROCNAME("pixcmapIsBlackAndWhite");
1083 
1084  if (!pblackwhite)
1085  return ERROR_INT("&blackwhite not defined", procName, 1);
1086  *pblackwhite = FALSE;
1087  if (!cmap)
1088  return ERROR_INT("cmap not defined", procName, 1);
1089  if (pixcmapGetCount(cmap) != 2)
1090  return 0;
1091 
1092  pixcmapHasColor(cmap, &hascolor);
1093  if (hascolor) return 0;
1094 
1095  cta = (RGBA_QUAD *)cmap->array;
1096  val0 = cta[0].red;
1097  val1 = cta[1].red;
1098  if ((val0 == 0 && val1 == 255) || (val0 == 255 && val1 == 0))
1099  *pblackwhite = TRUE;
1100  return 0;
1101 }
1102 
1103 
1116 l_ok
1118  l_int32 *pngray)
1119 {
1120 l_int32 n, i, rval, gval, bval, count;
1121 l_int32 *array;
1122 
1123  PROCNAME("pixcmapCountGrayColors");
1124 
1125  if (!pngray)
1126  return ERROR_INT("&ngray not defined", procName, 1);
1127  *pngray = 0;
1128  if (!cmap)
1129  return ERROR_INT("cmap not defined", procName, 1);
1130 
1131  array = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1132  n = pixcmapGetCount(cmap);
1133  count = 0;
1134  for (i = 0; i < n; i++) {
1135  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1136  if ((rval == gval) && (rval == bval) && (array[rval] == 0)) {
1137  array[rval] = 1;
1138  count++;
1139  }
1140  }
1141 
1142  LEPT_FREE(array);
1143  *pngray = count;
1144  return 0;
1145 }
1146 
1147 
1157 l_ok
1159  l_float32 rankval,
1160  l_int32 *pindex)
1161 {
1162 l_int32 n, i, rval, gval, bval, rankindex;
1163 NUMA *na, *nasort;
1164 
1165  PROCNAME("pixcmapGetRankIntensity");
1166 
1167  if (!pindex)
1168  return ERROR_INT("&index not defined", procName, 1);
1169  *pindex = 0;
1170  if (!cmap)
1171  return ERROR_INT("cmap not defined", procName, 1);
1172  if (rankval < 0.0 || rankval > 1.0)
1173  return ERROR_INT("rankval not in [0.0 ... 1.0]", procName, 1);
1174 
1175  n = pixcmapGetCount(cmap);
1176  na = numaCreate(n);
1177  for (i = 0; i < n; i++) {
1178  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1179  numaAddNumber(na, rval + gval + bval);
1180  }
1181  nasort = numaGetSortIndex(na, L_SORT_INCREASING);
1182  rankindex = (l_int32)(rankval * (n - 1) + 0.5);
1183  numaGetIValue(nasort, rankindex, pindex);
1184 
1185  numaDestroy(&na);
1186  numaDestroy(&nasort);
1187  return 0;
1188 }
1189 
1190 
1208 l_ok
1210  l_int32 rval,
1211  l_int32 gval,
1212  l_int32 bval,
1213  l_int32 *pindex)
1214 {
1215 l_int32 i, n, delta, dist, mindist;
1216 RGBA_QUAD *cta;
1217 
1218  PROCNAME("pixcmapGetNearestIndex");
1219 
1220  if (!pindex)
1221  return ERROR_INT("&index not defined", procName, 1);
1222  *pindex = UNDEF;
1223  if (!cmap)
1224  return ERROR_INT("cmap not defined", procName, 1);
1225 
1226  if ((cta = (RGBA_QUAD *)cmap->array) == NULL)
1227  return ERROR_INT("cta not defined(!)", procName, 1);
1228  n = pixcmapGetCount(cmap);
1229 
1230  mindist = 3 * 255 * 255 + 1;
1231  for (i = 0; i < n; i++) {
1232  delta = cta[i].red - rval;
1233  dist = delta * delta;
1234  delta = cta[i].green - gval;
1235  dist += delta * delta;
1236  delta = cta[i].blue - bval;
1237  dist += delta * delta;
1238  if (dist < mindist) {
1239  *pindex = i;
1240  if (dist == 0)
1241  break;
1242  mindist = dist;
1243  }
1244  }
1245 
1246  return 0;
1247 }
1248 
1249 
1266 l_ok
1268  l_int32 val,
1269  l_int32 *pindex)
1270 {
1271 l_int32 i, n, dist, mindist;
1272 RGBA_QUAD *cta;
1273 
1274  PROCNAME("pixcmapGetNearestGrayIndex");
1275 
1276  if (!pindex)
1277  return ERROR_INT("&index not defined", procName, 1);
1278  *pindex = 0;
1279  if (!cmap)
1280  return ERROR_INT("cmap not defined", procName, 1);
1281  if (val < 0 || val > 255)
1282  return ERROR_INT("val not in [0 ... 255]", procName, 1);
1283 
1284  if ((cta = (RGBA_QUAD *)cmap->array) == NULL)
1285  return ERROR_INT("cta not defined(!)", procName, 1);
1286  n = pixcmapGetCount(cmap);
1287 
1288  mindist = 256;
1289  for (i = 0; i < n; i++) {
1290  dist = cta[i].green - val;
1291  dist = L_ABS(dist);
1292  if (dist < mindist) {
1293  *pindex = i;
1294  if (dist == 0)
1295  break;
1296  mindist = dist;
1297  }
1298  }
1299 
1300  return 0;
1301 }
1302 
1303 
1319 l_ok
1321  l_int32 index,
1322  l_int32 rval,
1323  l_int32 gval,
1324  l_int32 bval,
1325  l_int32 *pdist)
1326 {
1327 l_int32 n, delta, dist;
1328 RGBA_QUAD *cta;
1329 
1330  PROCNAME("pixcmapGetDistanceToColor");
1331 
1332  if (!pdist)
1333  return ERROR_INT("&dist not defined", procName, 1);
1334  *pdist = UNDEF;
1335  if (!cmap)
1336  return ERROR_INT("cmap not defined", procName, 1);
1337  n = pixcmapGetCount(cmap);
1338  if (index >= n)
1339  return ERROR_INT("invalid index", procName, 1);
1340 
1341  if ((cta = (RGBA_QUAD *)cmap->array) == NULL)
1342  return ERROR_INT("cta not defined(!)", procName, 1);
1343 
1344  delta = cta[index].red - rval;
1345  dist = delta * delta;
1346  delta = cta[index].green - gval;
1347  dist += delta * delta;
1348  delta = cta[index].blue - bval;
1349  dist += delta * delta;
1350  *pdist = dist;
1351 
1352  return 0;
1353 }
1354 
1355 
1375 l_ok
1377  l_int32 select,
1378  l_int32 *pminval,
1379  l_int32 *pmaxval,
1380  l_int32 *pminindex,
1381  l_int32 *pmaxindex)
1382 {
1383 l_int32 i, n, imin, imax, minval, maxval, rval, gval, bval, aveval;
1384 
1385  PROCNAME("pixcmapGetRangeValues");
1386 
1387  if (pminval) *pminval = UNDEF;
1388  if (pmaxval) *pmaxval = UNDEF;
1389  if (pminindex) *pminindex = UNDEF;
1390  if (pmaxindex) *pmaxindex = UNDEF;
1391  if (!pminval && !pmaxval && !pminindex && !pmaxindex)
1392  return ERROR_INT("no result requested", procName, 1);
1393  if (!cmap)
1394  return ERROR_INT("cmap not defined", procName, 1);
1395 
1396  imin = UNDEF;
1397  imax = UNDEF;
1398  minval = 100000;
1399  maxval = -1;
1400  n = pixcmapGetCount(cmap);
1401  for (i = 0; i < n; i++) {
1402  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1403  if (select == L_SELECT_RED) {
1404  if (rval < minval) {
1405  minval = rval;
1406  imin = i;
1407  }
1408  if (rval > maxval) {
1409  maxval = rval;
1410  imax = i;
1411  }
1412  } else if (select == L_SELECT_GREEN) {
1413  if (gval < minval) {
1414  minval = gval;
1415  imin = i;
1416  }
1417  if (gval > maxval) {
1418  maxval = gval;
1419  imax = i;
1420  }
1421  } else if (select == L_SELECT_BLUE) {
1422  if (bval < minval) {
1423  minval = bval;
1424  imin = i;
1425  }
1426  if (bval > maxval) {
1427  maxval = bval;
1428  imax = i;
1429  }
1430  } else if (select == L_SELECT_AVERAGE) {
1431  aveval = (rval + gval + bval) / 3;
1432  if (aveval < minval) {
1433  minval = aveval;
1434  imin = i;
1435  }
1436  if (aveval > maxval) {
1437  maxval = aveval;
1438  imax = i;
1439  }
1440  } else {
1441  return ERROR_INT("invalid selection", procName, 1);
1442  }
1443  }
1444 
1445  if (pminval) *pminval = minval;
1446  if (pmaxval) *pmaxval = maxval;
1447  if (pminindex) *pminindex = imin;
1448  if (pmaxindex) *pmaxindex = imax;
1449  return 0;
1450 }
1451 
1452 
1453 /*-------------------------------------------------------------*
1454  * Colormap conversion *
1455  *-------------------------------------------------------------*/
1471 PIXCMAP *
1472 pixcmapGrayToColor(l_uint32 color)
1473 {
1474 l_int32 i, rval, gval, bval;
1475 PIXCMAP *cmap;
1476 
1477  extractRGBValues(color, &rval, &gval, &bval);
1478  cmap = pixcmapCreate(8);
1479  for (i = 0; i < 256; i++) {
1480  pixcmapAddColor(cmap, rval + (i * (255 - rval)) / 255,
1481  gval + (i * (255 - gval)) / 255,
1482  bval + (i * (255 - bval)) / 255);
1483  }
1484 
1485  return cmap;
1486 }
1487 
1488 
1503 PIXCMAP *
1505  l_float32 rwt,
1506  l_float32 gwt,
1507  l_float32 bwt)
1508 {
1509 l_int32 i, n, rval, gval, bval, val;
1510 l_float32 sum;
1511 PIXCMAP *cmapd;
1512 
1513  PROCNAME("pixcmapColorToGray");
1514 
1515  if (!cmaps)
1516  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
1517  if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0)
1518  return (PIXCMAP *)ERROR_PTR("weights not all >= 0.0", procName, NULL);
1519 
1520  /* Make sure the sum of weights is 1.0; otherwise, you can get
1521  * overflow in the gray value. */
1522  sum = rwt + gwt + bwt;
1523  if (sum == 0.0) {
1524  L_WARNING("all weights zero; setting equal to 1/3\n", procName);
1525  rwt = gwt = bwt = 0.33333;
1526  sum = 1.0;
1527  }
1528  if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */
1529  L_WARNING("weights don't sum to 1; maintaining ratios\n", procName);
1530  rwt = rwt / sum;
1531  gwt = gwt / sum;
1532  bwt = bwt / sum;
1533  }
1534 
1535  if ((cmapd = pixcmapCopy(cmaps)) == NULL)
1536  return (PIXCMAP *)ERROR_PTR("cmapd not made", procName, NULL);
1537  n = pixcmapGetCount(cmapd);
1538  for (i = 0; i < n; i++) {
1539  pixcmapGetColor(cmapd, i, &rval, &gval, &bval);
1540  val = (l_int32)(rwt * rval + gwt * gval + bwt * bval + 0.5);
1541  pixcmapResetColor(cmapd, i, val, val, val);
1542  }
1543 
1544  return cmapd;
1545 }
1546 
1547 
1560 PIXCMAP *
1562 {
1563 l_int32 i, n, rval, gval, bval;
1564 PIXCMAP *cmapd;
1565 
1566  PROCNAME("pixcmapConvertTo4");
1567 
1568  if (!cmaps)
1569  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
1570  if (pixcmapGetDepth(cmaps) != 2)
1571  return (PIXCMAP *)ERROR_PTR("cmaps not for 2 bpp pix", procName, NULL);
1572 
1573  cmapd = pixcmapCreate(4);
1574  n = pixcmapGetCount(cmaps);
1575  for (i = 0; i < n; i++) {
1576  pixcmapGetColor(cmaps, i, &rval, &gval, &bval);
1577  pixcmapAddColor(cmapd, rval, gval, bval);
1578  }
1579  return cmapd;
1580 }
1581 
1582 
1595 PIXCMAP *
1597 {
1598 l_int32 i, n, depth, rval, gval, bval;
1599 PIXCMAP *cmapd;
1600 
1601  PROCNAME("pixcmapConvertTo8");
1602 
1603  if (!cmaps)
1604  return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL);
1605  depth = pixcmapGetDepth(cmaps);
1606  if (depth == 8) return pixcmapCopy(cmaps);
1607  if (depth != 2 && depth != 4)
1608  return (PIXCMAP *)ERROR_PTR("cmaps not 2 or 4 bpp", procName, NULL);
1609 
1610  cmapd = pixcmapCreate(8);
1611  n = pixcmapGetCount(cmaps);
1612  for (i = 0; i < n; i++) {
1613  pixcmapGetColor(cmaps, i, &rval, &gval, &bval);
1614  pixcmapAddColor(cmapd, rval, gval, bval);
1615  }
1616  return cmapd;
1617 }
1618 
1619 
1620 /*-------------------------------------------------------------*
1621  * Colormap I/O *
1622  *-------------------------------------------------------------*/
1629 PIXCMAP *
1630 pixcmapRead(const char *filename)
1631 {
1632 FILE *fp;
1633 PIXCMAP *cmap;
1634 
1635  PROCNAME("pixcmapRead");
1636 
1637  if (!filename)
1638  return (PIXCMAP *)ERROR_PTR("filename not defined", procName, NULL);
1639 
1640  if ((fp = fopenReadStream(filename)) == NULL)
1641  return (PIXCMAP *)ERROR_PTR("stream not opened", procName, NULL);
1642  cmap = pixcmapReadStream(fp);
1643  fclose(fp);
1644  if (!cmap)
1645  return (PIXCMAP *)ERROR_PTR("cmap not read", procName, NULL);
1646  return cmap;
1647 }
1648 
1649 
1656 PIXCMAP *
1658 {
1659 l_int32 rval, gval, bval, aval, ignore;
1660 l_int32 i, index, ret, depth, ncolors;
1661 PIXCMAP *cmap;
1662 
1663  PROCNAME("pixcmapReadStream");
1664 
1665  if (!fp)
1666  return (PIXCMAP *)ERROR_PTR("stream not defined", procName, NULL);
1667 
1668  ret = fscanf(fp, "\nPixcmap: depth = %d bpp; %d colors\n",
1669  &depth, &ncolors);
1670  if (ret != 2 ||
1671  (depth != 1 && depth != 2 && depth != 4 && depth != 8) ||
1672  (ncolors < 2 || ncolors > 256))
1673  return (PIXCMAP *)ERROR_PTR("invalid cmap size", procName, NULL);
1674  ignore = fscanf(fp, "Color R-val G-val B-val Alpha\n");
1675  ignore = fscanf(fp, "----------------------------------------\n");
1676 
1677  cmap = pixcmapCreate(depth);
1678  for (i = 0; i < ncolors; i++) {
1679  if (fscanf(fp, "%3d %3d %3d %3d %3d\n",
1680  &index, &rval, &gval, &bval, &aval) != 5) {
1681  pixcmapDestroy(&cmap);
1682  return (PIXCMAP *)ERROR_PTR("invalid entry", procName, NULL);
1683  }
1684  pixcmapAddRGBA(cmap, rval, gval, bval, aval);
1685  }
1686  return cmap;
1687 }
1688 
1689 
1697 PIXCMAP *
1698 pixcmapReadMem(const l_uint8 *data,
1699  size_t size)
1700 {
1701 FILE *fp;
1702 PIXCMAP *cmap;
1703 
1704  PROCNAME("pixcmapReadMem");
1705 
1706  if (!data)
1707  return (PIXCMAP *)ERROR_PTR("data not defined", procName, NULL);
1708  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1709  return (PIXCMAP *)ERROR_PTR("stream not opened", procName, NULL);
1710 
1711  cmap = pixcmapReadStream(fp);
1712  fclose(fp);
1713  if (!cmap) L_ERROR("cmap not read\n", procName);
1714  return cmap;
1715 }
1716 
1717 
1725 l_ok
1726 pixcmapWrite(const char *filename,
1727  PIXCMAP *cmap)
1728 {
1729 l_int32 ret;
1730 FILE *fp;
1731 
1732  PROCNAME("pixcmapWrite");
1733 
1734  if (!filename)
1735  return ERROR_INT("filename not defined", procName, 1);
1736  if (!cmap)
1737  return ERROR_INT("cmap not defined", procName, 1);
1738 
1739  if ((fp = fopenWriteStream(filename, "w")) == NULL)
1740  return ERROR_INT("stream not opened", procName, 1);
1741  ret = pixcmapWriteStream(fp, cmap);
1742  fclose(fp);
1743  if (ret)
1744  return ERROR_INT("cmap not written to stream", procName, 1);
1745  return 0;
1746 }
1747 
1748 
1749 
1757 l_ok
1759  PIXCMAP *cmap)
1760 {
1761 l_int32 *rmap, *gmap, *bmap, *amap;
1762 l_int32 i;
1763 
1764  PROCNAME("pixcmapWriteStream");
1765 
1766  if (!fp)
1767  return ERROR_INT("stream not defined", procName, 1);
1768  if (!cmap)
1769  return ERROR_INT("cmap not defined", procName, 1);
1770 
1771  if (pixcmapToArrays(cmap, &rmap, &gmap, &bmap, &amap))
1772  return ERROR_INT("colormap arrays not made", procName, 1);
1773 
1774  fprintf(fp, "\nPixcmap: depth = %d bpp; %d colors\n", cmap->depth, cmap->n);
1775  fprintf(fp, "Color R-val G-val B-val Alpha\n");
1776  fprintf(fp, "----------------------------------------\n");
1777  for (i = 0; i < cmap->n; i++)
1778  fprintf(fp, "%3d %3d %3d %3d %3d\n",
1779  i, rmap[i], gmap[i], bmap[i], amap[i]);
1780  fprintf(fp, "\n");
1781 
1782  LEPT_FREE(rmap);
1783  LEPT_FREE(gmap);
1784  LEPT_FREE(bmap);
1785  LEPT_FREE(amap);
1786  return 0;
1787 }
1788 
1789 
1803 l_ok
1804 pixcmapWriteMem(l_uint8 **pdata,
1805  size_t *psize,
1806  PIXCMAP *cmap)
1807 {
1808 l_int32 ret;
1809 FILE *fp;
1810 
1811  PROCNAME("pixcmapWriteMem");
1812 
1813  if (pdata) *pdata = NULL;
1814  if (psize) *psize = 0;
1815  if (!pdata)
1816  return ERROR_INT("&data not defined", procName, 1);
1817  if (!psize)
1818  return ERROR_INT("&size not defined", procName, 1);
1819  if (!cmap)
1820  return ERROR_INT("cmap not defined", procName, 1);
1821 
1822 #if HAVE_FMEMOPEN
1823  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1824  return ERROR_INT("stream not opened", procName, 1);
1825  ret = pixcmapWriteStream(fp, cmap);
1826 #else
1827  L_INFO("work-around: writing to a temp file\n", procName);
1828  #ifdef _WIN32
1829  if ((fp = fopenWriteWinTempfile()) == NULL)
1830  return ERROR_INT("tmpfile stream not opened", procName, 1);
1831  #else
1832  if ((fp = tmpfile()) == NULL)
1833  return ERROR_INT("tmpfile stream not opened", procName, 1);
1834  #endif /* _WIN32 */
1835  ret = pixcmapWriteStream(fp, cmap);
1836  rewind(fp);
1837  *pdata = l_binaryReadStream(fp, psize);
1838 #endif /* HAVE_FMEMOPEN */
1839  fclose(fp);
1840  return ret;
1841 }
1842 
1843 
1844 /*----------------------------------------------------------------------*
1845  * Extract colormap arrays and serialization *
1846  *----------------------------------------------------------------------*/
1855 l_ok
1857  l_int32 **prmap,
1858  l_int32 **pgmap,
1859  l_int32 **pbmap,
1860  l_int32 **pamap)
1861 {
1862 l_int32 *rmap, *gmap, *bmap, *amap;
1863 l_int32 i, ncolors;
1864 RGBA_QUAD *cta;
1865 
1866  PROCNAME("pixcmapToArrays");
1867 
1868  if (!prmap || !pgmap || !pbmap)
1869  return ERROR_INT("&rmap, &gmap, &bmap not all defined", procName, 1);
1870  *prmap = *pgmap = *pbmap = NULL;
1871  if (pamap) *pamap = NULL;
1872  if (!cmap)
1873  return ERROR_INT("cmap not defined", procName, 1);
1874 
1875  ncolors = pixcmapGetCount(cmap);
1876  if (((rmap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32))) == NULL) ||
1877  ((gmap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32))) == NULL) ||
1878  ((bmap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32))) == NULL))
1879  return ERROR_INT("calloc fail for *map", procName, 1);
1880  *prmap = rmap;
1881  *pgmap = gmap;
1882  *pbmap = bmap;
1883  if (pamap) {
1884  amap = (l_int32 *)LEPT_CALLOC(ncolors, sizeof(l_int32));
1885  *pamap = amap;
1886  }
1887 
1888  cta = (RGBA_QUAD *)cmap->array;
1889  for (i = 0; i < ncolors; i++) {
1890  rmap[i] = cta[i].red;
1891  gmap[i] = cta[i].green;
1892  bmap[i] = cta[i].blue;
1893  if (pamap)
1894  amap[i] = cta[i].alpha;
1895  }
1896 
1897  return 0;
1898 }
1899 
1900 
1909 l_ok
1911  l_uint32 **ptab,
1912  l_int32 *pncolors)
1913 {
1914 l_int32 i, ncolors, rval, gval, bval, aval;
1915 l_uint32 *tab;
1916 
1917  PROCNAME("pixcmapToRGBTable");
1918 
1919  if (!ptab)
1920  return ERROR_INT("&tab not defined", procName, 1);
1921  *ptab = NULL;
1922  if (!cmap)
1923  return ERROR_INT("cmap not defined", procName, 1);
1924 
1925  ncolors = pixcmapGetCount(cmap);
1926  if (pncolors)
1927  *pncolors = ncolors;
1928  if ((tab = (l_uint32 *)LEPT_CALLOC(ncolors, sizeof(l_uint32))) == NULL)
1929  return ERROR_INT("tab not made", procName, 1);
1930  *ptab = tab;
1931 
1932  for (i = 0; i < ncolors; i++) {
1933  pixcmapGetRGBA(cmap, i, &rval, &gval, &bval, &aval);
1934  composeRGBAPixel(rval, gval, bval, aval, &tab[i]);
1935  }
1936  return 0;
1937 }
1938 
1939 
1954 l_ok
1956  l_int32 cpc,
1957  l_int32 *pncolors,
1958  l_uint8 **pdata)
1959 {
1960 l_int32 i, ncolors, rval, gval, bval, aval;
1961 l_uint8 *data;
1962 
1963  PROCNAME("pixcmapSerializeToMemory");
1964 
1965  if (!pdata)
1966  return ERROR_INT("&data not defined", procName, 1);
1967  *pdata = NULL;
1968  if (!pncolors)
1969  return ERROR_INT("&ncolors not defined", procName, 1);
1970  *pncolors = 0;
1971  if (!cmap)
1972  return ERROR_INT("cmap not defined", procName, 1);
1973  if (cpc != 3 && cpc != 4)
1974  return ERROR_INT("cpc not 3 or 4", procName, 1);
1975 
1976  ncolors = pixcmapGetCount(cmap);
1977  *pncolors = ncolors;
1978  if ((data = (l_uint8 *)LEPT_CALLOC((size_t)cpc * ncolors, sizeof(l_uint8)))
1979  == NULL)
1980  return ERROR_INT("data not made", procName, 1);
1981  *pdata = data;
1982 
1983  for (i = 0; i < ncolors; i++) {
1984  pixcmapGetRGBA(cmap, i, &rval, &gval, &bval, &aval);
1985  data[cpc * i] = rval;
1986  data[cpc * i + 1] = gval;
1987  data[cpc * i + 2] = bval;
1988  if (cpc == 4)
1989  data[cpc * i + 3] = aval;
1990  }
1991  return 0;
1992 }
1993 
1994 
2003 PIXCMAP *
2005  l_int32 cpc,
2006  l_int32 ncolors)
2007 {
2008 l_int32 i, d, rval, gval, bval, aval;
2009 PIXCMAP *cmap;
2010 
2011  PROCNAME("pixcmapDeserializeFromMemory");
2012 
2013  if (!data)
2014  return (PIXCMAP *)ERROR_PTR("data not defined", procName, NULL);
2015  if (cpc != 3 && cpc != 4)
2016  return (PIXCMAP *)ERROR_PTR("cpc not 3 or 4", procName, NULL);
2017  if (ncolors == 0)
2018  return (PIXCMAP *)ERROR_PTR("no entries", procName, NULL);
2019  if (ncolors > 256)
2020  return (PIXCMAP *)ERROR_PTR("ncolors > 256", procName, NULL);
2021 
2022  if (ncolors > 16)
2023  d = 8;
2024  else if (ncolors > 4)
2025  d = 4;
2026  else if (ncolors > 2)
2027  d = 2;
2028  else
2029  d = 1;
2030  cmap = pixcmapCreate(d);
2031  for (i = 0; i < ncolors; i++) {
2032  rval = data[cpc * i];
2033  gval = data[cpc * i + 1];
2034  bval = data[cpc * i + 2];
2035  if (cpc == 4)
2036  aval = data[cpc * i + 3];
2037  else
2038  aval = 255; /* opaque */
2039  pixcmapAddRGBA(cmap, rval, gval, bval, aval);
2040  }
2041 
2042  return cmap;
2043 }
2044 
2045 
2064 char *
2065 pixcmapConvertToHex(l_uint8 *data,
2066  l_int32 ncolors)
2067 {
2068 l_int32 i, j, hexbytes;
2069 char *hexdata = NULL;
2070 char buf[4];
2071 
2072  PROCNAME("pixcmapConvertToHex");
2073 
2074  if (!data)
2075  return (char *)ERROR_PTR("data not defined", procName, NULL);
2076  if (ncolors < 1)
2077  return (char *)ERROR_PTR("no colors", procName, NULL);
2078 
2079  hexbytes = 2 + (2 * 3 + 1) * ncolors + 2;
2080  hexdata = (char *)LEPT_CALLOC(hexbytes, sizeof(char));
2081  hexdata[0] = '<';
2082  hexdata[1] = ' ';
2083 
2084  for (i = 0; i < ncolors; i++) {
2085  j = 2 + (2 * 3 + 1) * i;
2086  snprintf(buf, sizeof(buf), "%02x", data[3 * i]);
2087  hexdata[j] = buf[0];
2088  hexdata[j + 1] = buf[1];
2089  snprintf(buf, sizeof(buf), "%02x", data[3 * i + 1]);
2090  hexdata[j + 2] = buf[0];
2091  hexdata[j + 3] = buf[1];
2092  snprintf(buf, sizeof(buf), "%02x", data[3 * i + 2]);
2093  hexdata[j + 4] = buf[0];
2094  hexdata[j + 5] = buf[1];
2095  hexdata[j + 6] = ' ';
2096  }
2097  hexdata[j + 7] = '>';
2098  hexdata[j + 8] = '\0';
2099  return hexdata;
2100 }
2101 
2102 
2103 /*-------------------------------------------------------------*
2104  * Colormap transforms *
2105  *-------------------------------------------------------------*/
2122 l_ok
2124  l_float32 gamma,
2125  l_int32 minval,
2126  l_int32 maxval)
2127 {
2128 l_int32 rval, gval, bval, trval, tgval, tbval, i, ncolors;
2129 NUMA *nag;
2130 
2131  PROCNAME("pixcmapGammaTRC");
2132 
2133  if (!cmap)
2134  return ERROR_INT("cmap not defined", procName, 1);
2135  if (gamma <= 0.0) {
2136  L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
2137  gamma = 1.0;
2138  }
2139  if (minval >= maxval)
2140  return ERROR_INT("minval not < maxval", procName, 1);
2141 
2142  if (gamma == 1.0 && minval == 0 && maxval == 255) /* no-op */
2143  return 0;
2144 
2145  if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
2146  return ERROR_INT("nag not made", procName, 1);
2147 
2148  ncolors = pixcmapGetCount(cmap);
2149  for (i = 0; i < ncolors; i++) {
2150  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2151  numaGetIValue(nag, rval, &trval);
2152  numaGetIValue(nag, gval, &tgval);
2153  numaGetIValue(nag, bval, &tbval);
2154  pixcmapResetColor(cmap, i, trval, tgval, tbval);
2155  }
2156 
2157  numaDestroy(&nag);
2158  return 0;
2159 }
2160 
2161 
2177 l_ok
2179  l_float32 factor)
2180 {
2181 l_int32 i, ncolors, rval, gval, bval, trval, tgval, tbval;
2182 NUMA *nac;
2183 
2184  PROCNAME("pixcmapContrastTRC");
2185 
2186  if (!cmap)
2187  return ERROR_INT("cmap not defined", procName, 1);
2188  if (factor < 0.0) {
2189  L_WARNING("factor must be >= 0.0; setting to 0.0\n", procName);
2190  factor = 0.0;
2191  }
2192 
2193  if ((nac = numaContrastTRC(factor)) == NULL)
2194  return ERROR_INT("nac not made", procName, 1);
2195 
2196  ncolors = pixcmapGetCount(cmap);
2197  for (i = 0; i < ncolors; i++) {
2198  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2199  numaGetIValue(nac, rval, &trval);
2200  numaGetIValue(nac, gval, &tgval);
2201  numaGetIValue(nac, bval, &tbval);
2202  pixcmapResetColor(cmap, i, trval, tgval, tbval);
2203  }
2204 
2205  numaDestroy(&nac);
2206  return 0;
2207 }
2208 
2209 
2229 l_ok
2231  l_float32 fraction)
2232 {
2233 l_int32 i, ncolors, rval, gval, bval;
2234 
2235  PROCNAME("pixcmapShiftIntensity");
2236 
2237  if (!cmap)
2238  return ERROR_INT("cmap not defined", procName, 1);
2239  if (fraction < -1.0 || fraction > 1.0)
2240  return ERROR_INT("fraction not in [-1.0, 1.0]", procName, 1);
2241 
2242  ncolors = pixcmapGetCount(cmap);
2243  for (i = 0; i < ncolors; i++) {
2244  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2245  if (fraction < 0.0)
2246  pixcmapResetColor(cmap, i,
2247  (l_int32)((1.0 + fraction) * rval),
2248  (l_int32)((1.0 + fraction) * gval),
2249  (l_int32)((1.0 + fraction) * bval));
2250  else
2251  pixcmapResetColor(cmap, i,
2252  rval + (l_int32)(fraction * (255 - rval)),
2253  gval + (l_int32)(fraction * (255 - gval)),
2254  bval + (l_int32)(fraction * (255 - bval)));
2255  }
2256 
2257  return 0;
2258 }
2259 
2260 
2279 l_ok
2281  l_uint32 srcval,
2282  l_uint32 dstval)
2283 {
2284 l_int32 i, ncolors, rval, gval, bval;
2285 l_uint32 newval;
2286 
2287  PROCNAME("pixcmapShiftByComponent");
2288 
2289  if (!cmap)
2290  return ERROR_INT("cmap not defined", procName, 1);
2291 
2292  ncolors = pixcmapGetCount(cmap);
2293  for (i = 0; i < ncolors; i++) {
2294  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2295  pixelShiftByComponent(rval, gval, bval, srcval, dstval, &newval);
2296  extractRGBValues(newval, &rval, &gval, &bval);
2297  pixcmapResetColor(cmap, i, rval, gval, bval);
2298  }
2299 
2300  return 0;
2301 }
l_uint8 alpha
Definition: pix.h:174
l_ok pixcmapCountGrayColors(PIXCMAP *cmap, l_int32 *pngray)
pixcmapCountGrayColors()
Definition: colormap.c:1117
l_int32 pixcmapGetDepth(PIXCMAP *cmap)
pixcmapGetDepth()
Definition: colormap.c:669
NUMA * numaGetSortIndex(NUMA *na, l_int32 sortorder)
numaGetSortIndex()
Definition: numafunc1.c:2637
l_ok pixcmapGetMinDepth(PIXCMAP *cmap, l_int32 *pmindepth)
pixcmapGetMinDepth()
Definition: colormap.c:692
char * pixcmapConvertToHex(l_uint8 *data, l_int32 ncolors)
pixcmapConvertToHex()
Definition: colormap.c:2065
l_int32 n
Definition: pix.h:160
PIXCMAP * pixcmapReadStream(FILE *fp)
pixcmapReadStream()
Definition: colormap.c:1657
l_ok pixcmapWriteMem(l_uint8 **pdata, size_t *psize, PIXCMAP *cmap)
pixcmapWriteMem()
Definition: colormap.c:1804
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIXCMAP * pixcmapConvertTo8(PIXCMAP *cmaps)
pixcmapConvertTo8()
Definition: colormap.c:1596
l_int32 n
Definition: ccbord.h:111
NUMA * numaGammaTRC(l_float32 gamma, l_int32 minval, l_int32 maxval)
numaGammaTRC()
Definition: enhance.c:366
l_ok pixcmapGetNearestIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetNearestIndex()
Definition: colormap.c:1209
PIXCMAP * pixcmapGrayToColor(l_uint32 color)
pixcmapGrayToColor()
Definition: colormap.c:1472
PIXCMAP * pixcmapRead(const char *filename)
pixcmapRead()
Definition: colormap.c:1630
l_ok pixcmapWriteStream(FILE *fp, PIXCMAP *cmap)
pixcmapWriteStream()
Definition: colormap.c:1758
l_ok pixcmapWrite(const char *filename, PIXCMAP *cmap)
pixcmapWrite()
Definition: colormap.c:1726
l_uint8 red
Definition: pix.h:173
l_ok pixcmapSerializeToMemory(PIXCMAP *cmap, l_int32 cpc, l_int32 *pncolors, l_uint8 **pdata)
pixcmapSerializeToMemory()
Definition: colormap.c:1955
l_ok pixcmapIsBlackAndWhite(PIXCMAP *cmap, l_int32 *pblackwhite)
pixcmapIsBlackAndWhite()
Definition: colormap.c:1076
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1734
void pixcmapDestroy(PIXCMAP **pcmap)
pixcmapDestroy()
Definition: colormap.c:265
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
PIXCMAP * pixcmapReadMem(const l_uint8 *data, size_t size)
pixcmapReadMem()
Definition: colormap.c:1698
l_int32 depth
Definition: pix.h:158
PIXCMAP * pixcmapConvertTo4(PIXCMAP *cmaps)
pixcmapConvertTo4()
Definition: colormap.c:1561
l_int32 nalloc
Definition: pix.h:159
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
PIXCMAP * pixcmapCreateLinear(l_int32 d, l_int32 nlevels)
pixcmapCreateLinear()
Definition: colormap.c:204
l_ok pixcmapShiftIntensity(PIXCMAP *cmap, l_float32 fraction)
pixcmapShiftIntensity()
Definition: colormap.c:2230
l_uint8 blue
Definition: pix.h:171
l_ok pixcmapGetRGBA32(PIXCMAP *cmap, l_int32 index, l_uint32 *pval32)
pixcmapGetRGBA32()
Definition: colormap.c:857
l_ok pixelShiftByComponent(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 srcval, l_uint32 dstval, l_uint32 *ppixel)
pixelShiftByComponent()
Definition: coloring.c:964
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:111
l_ok pixcmapGetNearestGrayIndex(PIXCMAP *cmap, l_int32 val, l_int32 *pindex)
pixcmapGetNearestGrayIndex()
Definition: colormap.c:1267
l_int32 pixcmapGetIndex(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapGetIndex()
Definition: colormap.c:963
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:727
Definition: array.h:59
l_ok pixcmapToArrays(PIXCMAP *cmap, l_int32 **prmap, l_int32 **pgmap, l_int32 **pbmap, l_int32 **pamap)
pixcmapToArrays()
Definition: colormap.c:1856
PIXCMAP * pixcmapColorToGray(PIXCMAP *cmaps, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixcmapColorToGray()
Definition: colormap.c:1504
l_ok pixcmapContrastTRC(PIXCMAP *cmap, l_float32 factor)
pixcmapContrastTRC()
Definition: colormap.c:2178
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:751
l_ok pixcmapIsValid(PIXCMAP *cmap, l_int32 *pvalid)
pixcmapIsValid()
Definition: colormap.c:293
l_ok composeRGBAPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval, l_uint32 *ppixel)
composeRGBAPixel()
Definition: pix2.c:2702
l_ok pixcmapAddNewColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapAddNewColor()
Definition: colormap.c:423
FILE * fopenWriteWinTempfile()
fopenWriteWinTempfile()
Definition: utils2.c:1780
l_ok pixcmapSetBlackAndWhite(PIXCMAP *cmap, l_int32 setblack, l_int32 setwhite)
pixcmapSetBlackAndWhite()
Definition: colormap.c:605
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:2004
l_int32 pixcmapGetFreeCount(PIXCMAP *cmap)
pixcmapGetFreeCount()
Definition: colormap.c:652
l_ok pixcmapShiftByComponent(PIXCMAP *cmap, l_uint32 srcval, l_uint32 dstval)
pixcmapShiftByComponent()
Definition: colormap.c:2280
l_ok pixcmapIsOpaque(PIXCMAP *cmap, l_int32 *popaque)
pixcmapIsOpaque()
Definition: colormap.c:1041
l_ok pixcmapAddNearestColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapAddNearestColor()
Definition: colormap.c:472
l_ok pixcmapSetAlpha(PIXCMAP *cmap, l_int32 index, l_int32 aval)
pixcmapSetAlpha()
Definition: colormap.c:934
NUMA * numaContrastTRC(l_float32 factor)
numaContrastTRC()
Definition: enhance.c:557
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:893
l_ok pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
pixcmapHasColor()
Definition: colormap.c:1002
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1700
l_ok pixcmapUsableColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pusable)
pixcmapUsableColor()
Definition: colormap.c:519
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1657
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1262
l_ok pixcmapAddBlackOrWhite(PIXCMAP *cmap, l_int32 color, l_int32 *pindex)
pixcmapAddBlackOrWhite()
Definition: colormap.c:566
l_ok pixcmapGetColor32(PIXCMAP *cmap, l_int32 index, l_uint32 *pval32)
pixcmapGetColor32()
Definition: colormap.c:791
l_ok pixcmapToRGBTable(PIXCMAP *cmap, l_uint32 **ptab, l_int32 *pncolors)
pixcmapToRGBTable()
Definition: colormap.c:1910
void * array
Definition: pix.h:157
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:635
PIXCMAP * pixcmapCopy(PIXCMAP *cmaps)
pixcmapCopy()
Definition: colormap.c:234
l_ok pixcmapGetRGBA(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *paval)
pixcmapGetRGBA()
Definition: colormap.c:819
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
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2737
l_ok pixcmapGammaTRC(PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixcmapGammaTRC()
Definition: colormap.c:2123
l_ok pixcmapAddRGBA(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 aval)
pixcmapAddRGBA()
Definition: colormap.c:379
l_ok pixcmapGetRankIntensity(PIXCMAP *cmap, l_float32 rankval, l_int32 *pindex)
pixcmapGetRankIntensity()
Definition: colormap.c:1158
l_ok pixcmapClear(PIXCMAP *cmap)
pixcmapClear()
Definition: colormap.c:728
PIXCMAP * pixcmapCreateRandom(l_int32 depth, l_int32 hasblack, l_int32 haswhite)
pixcmapCreateRandom()
Definition: colormap.c:158