Leptonica  1.83.1
Image processing and image analysis suite
colorspace.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 
85 #ifdef HAVE_CONFIG_H
86 #include <config_auto.h>
87 #endif /* HAVE_CONFIG_H */
88 
89 #include <string.h>
90 #include <math.h>
91 #include "allheaders.h"
92 
93 #ifndef NO_CONSOLE_IO
94 #define DEBUG_HISTO 0
95 #define SLOW_CUBE_ROOT 0
96 #endif /* ~NO_CONSOLE_IO */
97 
98  /* Functions used in xyz <--> lab conversions */
99 static l_float32 lab_forward(l_float32 v);
100 static l_float32 lab_reverse(l_float32 v);
101 
102 /*---------------------------------------------------------------------------*
103  * Colorspace conversion between RGB and HSB *
104  *---------------------------------------------------------------------------*/
141 PIX *
143  PIX *pixs)
144 {
145 l_int32 w, h, d, wpl, i, j, rval, gval, bval, hval, sval, vval;
146 l_uint32 *line, *data;
147 PIXCMAP *cmap;
148 
149  if (!pixs)
150  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
151  if (pixd && pixd != pixs)
152  return (PIX *)ERROR_PTR("pixd defined and not inplace", __func__, pixd);
153 
154  d = pixGetDepth(pixs);
155  cmap = pixGetColormap(pixs);
156  if (!cmap && d != 32)
157  return (PIX *)ERROR_PTR("not cmapped or rgb", __func__, pixd);
158 
159  if (!pixd)
160  pixd = pixCopy(NULL, pixs);
161 
162  cmap = pixGetColormap(pixd);
163  if (cmap) { /* just convert the colormap */
165  return pixd;
166  }
167 
168  /* Convert RGB image */
169  pixGetDimensions(pixd, &w, &h, NULL);
170  wpl = pixGetWpl(pixd);
171  data = pixGetData(pixd);
172  for (i = 0; i < h; i++) {
173  line = data + i * wpl;
174  for (j = 0; j < w; j++) {
175  extractRGBValues(line[j], &rval, &gval, &bval);
176  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
177  line[j] = (hval << 24) | (sval << 16) | (vval << 8);
178  }
179  }
180 
181  return pixd;
182 }
183 
184 
203 PIX *
205  PIX *pixs)
206 {
207 l_int32 w, h, d, wpl, i, j, rval, gval, bval, hval, sval, vval;
208 l_uint32 pixel;
209 l_uint32 *line, *data;
210 PIXCMAP *cmap;
211 
212  if (!pixs)
213  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
214  if (pixd && pixd != pixs)
215  return (PIX *)ERROR_PTR("pixd defined and not inplace", __func__, pixd);
216 
217  d = pixGetDepth(pixs);
218  cmap = pixGetColormap(pixs);
219  if (!cmap && d != 32)
220  return (PIX *)ERROR_PTR("not cmapped or hsv", __func__, pixd);
221 
222  if (!pixd)
223  pixd = pixCopy(NULL, pixs);
224 
225  cmap = pixGetColormap(pixd);
226  if (cmap) { /* just convert the colormap */
228  return pixd;
229  }
230 
231  /* Convert HSV image */
232  pixGetDimensions(pixd, &w, &h, NULL);
233  wpl = pixGetWpl(pixd);
234  data = pixGetData(pixd);
235  for (i = 0; i < h; i++) {
236  line = data + i * wpl;
237  for (j = 0; j < w; j++) {
238  pixel = line[j];
239  hval = pixel >> 24;
240  sval = (pixel >> 16) & 0xff;
241  vval = (pixel >> 8) & 0xff;
242  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
243  composeRGBPixel(rval, gval, bval, line + j);
244  }
245  }
246 
247  return pixd;
248 }
249 
250 
276 l_ok
277 convertRGBToHSV(l_int32 rval,
278  l_int32 gval,
279  l_int32 bval,
280  l_int32 *phval,
281  l_int32 *psval,
282  l_int32 *pvval)
283 {
284 l_int32 minrg, maxrg, min, max, delta;
285 l_float32 h;
286 
287  if (phval) *phval = 0;
288  if (psval) *psval = 0;
289  if (pvval) *pvval = 0;
290  if (!phval || !psval || !pvval)
291  return ERROR_INT("&hval, &sval, &vval not all defined", __func__, 1);
292 
293  minrg = L_MIN(rval, gval);
294  min = L_MIN(minrg, bval);
295  maxrg = L_MAX(rval, gval);
296  max = L_MAX(maxrg, bval);
297  delta = max - min;
298 
299  *pvval = max;
300  if (delta == 0) { /* gray; no chroma */
301  *phval = 0;
302  *psval = 0;
303  } else {
304  *psval = (l_int32)(255. * (l_float32)delta / (l_float32)max + 0.5);
305  if (rval == max) /* between magenta and yellow */
306  h = (l_float32)(gval - bval) / (l_float32)delta;
307  else if (gval == max) /* between yellow and cyan */
308  h = 2. + (l_float32)(bval - rval) / (l_float32)delta;
309  else /* between cyan and magenta */
310  h = 4. + (l_float32)(rval - gval) / (l_float32)delta;
311  h *= 40.0;
312  if (h < 0.0)
313  h += 240.0;
314  if (h >= 239.5)
315  h = 0.0;
316  *phval = (l_int32)(h + 0.5);
317  }
318 
319  return 0;
320 }
321 
322 
336 l_ok
337 convertHSVToRGB(l_int32 hval,
338  l_int32 sval,
339  l_int32 vval,
340  l_int32 *prval,
341  l_int32 *pgval,
342  l_int32 *pbval)
343 {
344 l_int32 i, x, y, z;
345 l_float32 h, f, s;
346 
347  if (prval) *prval = 0;
348  if (pgval) *pgval = 0;
349  if (pbval) *pbval = 0;
350  if (!prval || !pgval || !pbval)
351  return ERROR_INT("&rval, &gval, &bval not all defined", __func__, 1);
352 
353  if (sval == 0) { /* gray */
354  *prval = vval;
355  *pgval = vval;
356  *pbval = vval;
357  } else {
358  if (hval < 0 || hval > 240)
359  return ERROR_INT("invalid hval", __func__, 1);
360  if (hval == 240)
361  hval = 0;
362  h = (l_float32)hval / 40.;
363  i = (l_int32)h;
364  f = h - i;
365  s = (l_float32)sval / 255.;
366  x = (l_int32)(vval * (1. - s) + 0.5);
367  y = (l_int32)(vval * (1. - s * f) + 0.5);
368  z = (l_int32)(vval * (1. - s * (1. - f)) + 0.5);
369  switch (i)
370  {
371  case 0:
372  *prval = vval;
373  *pgval = z;
374  *pbval = x;
375  break;
376  case 1:
377  *prval = y;
378  *pgval = vval;
379  *pbval = x;
380  break;
381  case 2:
382  *prval = x;
383  *pgval = vval;
384  *pbval = z;
385  break;
386  case 3:
387  *prval = x;
388  *pgval = y;
389  *pbval = vval;
390  break;
391  case 4:
392  *prval = z;
393  *pgval = x;
394  *pbval = vval;
395  break;
396  case 5:
397  *prval = vval;
398  *pgval = x;
399  *pbval = y;
400  break;
401  default: /* none possible */
402  return 1;
403  }
404  }
405 
406  return 0;
407 }
408 
409 
423 l_ok
425 {
426 l_int32 i, ncolors, rval, gval, bval, hval, sval, vval;
427 
428  if (!cmap)
429  return ERROR_INT("cmap not defined", __func__, 1);
430 
431  ncolors = pixcmapGetCount(cmap);
432  for (i = 0; i < ncolors; i++) {
433  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
434  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
435  pixcmapResetColor(cmap, i, hval, sval, vval);
436  }
437  return 0;
438 }
439 
440 
454 l_ok
456 {
457 l_int32 i, ncolors, rval, gval, bval, hval, sval, vval;
458 
459  if (!cmap)
460  return ERROR_INT("cmap not defined", __func__, 1);
461 
462  ncolors = pixcmapGetCount(cmap);
463  for (i = 0; i < ncolors; i++) {
464  pixcmapGetColor(cmap, i, &hval, &sval, &vval);
465  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
466  pixcmapResetColor(cmap, i, rval, gval, bval);
467  }
468  return 0;
469 }
470 
471 
487 PIX *
489 {
490 l_int32 w, h, d, wplt, wpld;
491 l_int32 i, j, rval, gval, bval, hval, minrg, min, maxrg, max, delta;
492 l_float32 fh;
493 l_uint32 pixel;
494 l_uint32 *linet, *lined, *datat, *datad;
495 PIX *pixt, *pixd;
496 
497  if (!pixs)
498  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
499 
500  pixGetDimensions(pixs, &w, &h, &d);
501  if (d != 32 && !pixGetColormap(pixs))
502  return (PIX *)ERROR_PTR("not cmapped or rgb", __func__, NULL);
504 
505  /* Convert RGB image */
506  pixd = pixCreate(w, h, 8);
507  pixCopyResolution(pixd, pixs);
508  wplt = pixGetWpl(pixt);
509  datat = pixGetData(pixt);
510  wpld = pixGetWpl(pixd);
511  datad = pixGetData(pixd);
512  for (i = 0; i < h; i++) {
513  linet = datat + i * wplt;
514  lined = datad + i * wpld;
515  for (j = 0; j < w; j++) {
516  pixel = linet[j];
517  extractRGBValues(pixel, &rval, &gval, &bval);
518  minrg = L_MIN(rval, gval);
519  min = L_MIN(minrg, bval);
520  maxrg = L_MAX(rval, gval);
521  max = L_MAX(maxrg, bval);
522  delta = max - min;
523  if (delta == 0) { /* gray; no chroma */
524  hval = 0;
525  } else {
526  if (rval == max) /* between magenta and yellow */
527  fh = (l_float32)(gval - bval) / (l_float32)delta;
528  else if (gval == max) /* between yellow and cyan */
529  fh = 2. + (l_float32)(bval - rval) / (l_float32)delta;
530  else /* between cyan and magenta */
531  fh = 4. + (l_float32)(rval - gval) / (l_float32)delta;
532  fh *= 40.0;
533  if (fh < 0.0)
534  fh += 240.0;
535  hval = (l_int32)(fh + 0.5);
536  }
537  SET_DATA_BYTE(lined, j, hval);
538  }
539  }
540  pixDestroy(&pixt);
541 
542  return pixd;
543 }
544 
545 
546 
561 PIX *
563 {
564 l_int32 w, h, d, wplt, wpld;
565 l_int32 i, j, rval, gval, bval, sval, minrg, min, maxrg, max, delta;
566 l_uint32 pixel;
567 l_uint32 *linet, *lined, *datat, *datad;
568 PIX *pixt, *pixd;
569 
570  if (!pixs)
571  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
572 
573  pixGetDimensions(pixs, &w, &h, &d);
574  if (d != 32 && !pixGetColormap(pixs))
575  return (PIX *)ERROR_PTR("not cmapped or rgb", __func__, NULL);
577 
578  /* Convert RGB image */
579  pixd = pixCreate(w, h, 8);
580  pixCopyResolution(pixd, pixs);
581  wplt = pixGetWpl(pixt);
582  datat = pixGetData(pixt);
583  wpld = pixGetWpl(pixd);
584  datad = pixGetData(pixd);
585  for (i = 0; i < h; i++) {
586  linet = datat + i * wplt;
587  lined = datad + i * wpld;
588  for (j = 0; j < w; j++) {
589  pixel = linet[j];
590  extractRGBValues(pixel, &rval, &gval, &bval);
591  minrg = L_MIN(rval, gval);
592  min = L_MIN(minrg, bval);
593  maxrg = L_MAX(rval, gval);
594  max = L_MAX(maxrg, bval);
595  delta = max - min;
596  if (delta == 0) /* gray; no chroma */
597  sval = 0;
598  else
599  sval = (l_int32)(255. *
600  (l_float32)delta / (l_float32)max + 0.5);
601  SET_DATA_BYTE(lined, j, sval);
602  }
603  }
604 
605  pixDestroy(&pixt);
606  return pixd;
607 }
608 
609 
624 PIX *
626 {
627 l_int32 w, h, d, wplt, wpld;
628 l_int32 i, j, rval, gval, bval, maxrg, max;
629 l_uint32 pixel;
630 l_uint32 *linet, *lined, *datat, *datad;
631 PIX *pixt, *pixd;
632 
633  if (!pixs)
634  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
635 
636  pixGetDimensions(pixs, &w, &h, &d);
637  if (d != 32 && !pixGetColormap(pixs))
638  return (PIX *)ERROR_PTR("not cmapped or rgb", __func__, NULL);
640 
641  /* Convert RGB image */
642  pixd = pixCreate(w, h, 8);
643  pixCopyResolution(pixd, pixs);
644  wplt = pixGetWpl(pixt);
645  datat = pixGetData(pixt);
646  wpld = pixGetWpl(pixd);
647  datad = pixGetData(pixd);
648  for (i = 0; i < h; i++) {
649  linet = datat + i * wplt;
650  lined = datad + i * wpld;
651  for (j = 0; j < w; j++) {
652  pixel = linet[j];
653  extractRGBValues(pixel, &rval, &gval, &bval);
654  maxrg = L_MAX(rval, gval);
655  max = L_MAX(maxrg, bval);
656  SET_DATA_BYTE(lined, j, max);
657  }
658  }
659 
660  pixDestroy(&pixt);
661  return pixd;
662 }
663 
664 
665 /*---------------------------------------------------------------------------*
666  * Selection and display of range of colors in HSV space *
667  *---------------------------------------------------------------------------*/
691 PIX *
693  l_int32 huecenter,
694  l_int32 huehw,
695  l_int32 satcenter,
696  l_int32 sathw,
697  l_int32 regionflag)
698 {
699 l_int32 i, j, w, h, wplt, wpld, hstart, hend, sstart, send, hval, sval;
700 l_int32 *hlut, *slut;
701 l_uint32 pixel;
702 l_uint32 *datat, *datad, *linet, *lined;
703 PIX *pixt, *pixd;
704 
705  if (!pixs || pixGetDepth(pixs) != 32)
706  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
707  if (regionflag != L_INCLUDE_REGION && regionflag != L_EXCLUDE_REGION)
708  return (PIX *)ERROR_PTR("invalid regionflag", __func__, NULL);
709 
710  /* Set up LUTs for hue and saturation. These have the value 1
711  * within the specified intervals of hue and saturation. */
712  hlut = (l_int32 *)LEPT_CALLOC(240, sizeof(l_int32));
713  slut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
714  sstart = L_MAX(0, satcenter - sathw);
715  send = L_MIN(255, satcenter + sathw);
716  for (i = sstart; i <= send; i++)
717  slut[i] = 1;
718  hstart = (huecenter - huehw + 240) % 240;
719  hend = (huecenter + huehw + 240) % 240;
720  if (hstart < hend) {
721  for (i = hstart; i <= hend; i++)
722  hlut[i] = 1;
723  } else { /* wrap */
724  for (i = hstart; i < 240; i++)
725  hlut[i] = 1;
726  for (i = 0; i <= hend; i++)
727  hlut[i] = 1;
728  }
729 
730  /* Generate the mask */
731  pixt = pixConvertRGBToHSV(NULL, pixs);
732  pixGetDimensions(pixs, &w, &h, NULL);
733  pixd = pixCreate(w, h, 1);
734  if (regionflag == L_INCLUDE_REGION)
735  pixClearAll(pixd);
736  else /* L_EXCLUDE_REGION */
737  pixSetAll(pixd);
738  datat = pixGetData(pixt);
739  datad = pixGetData(pixd);
740  wplt = pixGetWpl(pixt);
741  wpld = pixGetWpl(pixd);
742  for (i = 0; i < h; i++) {
743  linet = datat + i * wplt;
744  lined = datad + i * wpld;
745  for (j = 0; j < w; j++) {
746  pixel = linet[j];
747  hval = (pixel >> L_RED_SHIFT) & 0xff;
748  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
749  if (hlut[hval] == 1 && slut[sval] == 1) {
750  if (regionflag == L_INCLUDE_REGION)
751  SET_DATA_BIT(lined, j);
752  else /* L_EXCLUDE_REGION */
753  CLEAR_DATA_BIT(lined, j);
754  }
755  }
756  }
757 
758  LEPT_FREE(hlut);
759  LEPT_FREE(slut);
760  pixDestroy(&pixt);
761  return pixd;
762 }
763 
764 
788 PIX *
790  l_int32 huecenter,
791  l_int32 huehw,
792  l_int32 valcenter,
793  l_int32 valhw,
794  l_int32 regionflag)
795 {
796 l_int32 i, j, w, h, wplt, wpld, hstart, hend, vstart, vend, hval, vval;
797 l_int32 *hlut, *vlut;
798 l_uint32 pixel;
799 l_uint32 *datat, *datad, *linet, *lined;
800 PIX *pixt, *pixd;
801 
802  if (!pixs || pixGetDepth(pixs) != 32)
803  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
804  if (regionflag != L_INCLUDE_REGION && regionflag != L_EXCLUDE_REGION)
805  return (PIX *)ERROR_PTR("invalid regionflag", __func__, NULL);
806 
807  /* Set up LUTs for hue and maximum intensity (val). These have
808  * the value 1 within the specified intervals of hue and value. */
809  hlut = (l_int32 *)LEPT_CALLOC(240, sizeof(l_int32));
810  vlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
811  vstart = L_MAX(0, valcenter - valhw);
812  vend = L_MIN(255, valcenter + valhw);
813  for (i = vstart; i <= vend; i++)
814  vlut[i] = 1;
815  hstart = (huecenter - huehw + 240) % 240;
816  hend = (huecenter + huehw + 240) % 240;
817  if (hstart < hend) {
818  for (i = hstart; i <= hend; i++)
819  hlut[i] = 1;
820  } else {
821  for (i = hstart; i < 240; i++)
822  hlut[i] = 1;
823  for (i = 0; i <= hend; i++)
824  hlut[i] = 1;
825  }
826 
827  /* Generate the mask */
828  pixt = pixConvertRGBToHSV(NULL, pixs);
829  pixGetDimensions(pixs, &w, &h, NULL);
830  pixd = pixCreate(w, h, 1);
831  if (regionflag == L_INCLUDE_REGION)
832  pixClearAll(pixd);
833  else /* L_EXCLUDE_REGION */
834  pixSetAll(pixd);
835  datat = pixGetData(pixt);
836  datad = pixGetData(pixd);
837  wplt = pixGetWpl(pixt);
838  wpld = pixGetWpl(pixd);
839  for (i = 0; i < h; i++) {
840  linet = datat + i * wplt;
841  lined = datad + i * wpld;
842  for (j = 0; j < w; j++) {
843  pixel = linet[j];
844  hval = (pixel >> L_RED_SHIFT) & 0xff;
845  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
846  if (hlut[hval] == 1 && vlut[vval] == 1) {
847  if (regionflag == L_INCLUDE_REGION)
848  SET_DATA_BIT(lined, j);
849  else /* L_EXCLUDE_REGION */
850  CLEAR_DATA_BIT(lined, j);
851  }
852  }
853  }
854 
855  LEPT_FREE(hlut);
856  LEPT_FREE(vlut);
857  pixDestroy(&pixt);
858  return pixd;
859 }
860 
861 
884 PIX *
886  l_int32 satcenter,
887  l_int32 sathw,
888  l_int32 valcenter,
889  l_int32 valhw,
890  l_int32 regionflag)
891 {
892 l_int32 i, j, w, h, wplt, wpld, sval, vval, sstart, send, vstart, vend;
893 l_int32 *slut, *vlut;
894 l_uint32 pixel;
895 l_uint32 *datat, *datad, *linet, *lined;
896 PIX *pixt, *pixd;
897 
898  if (!pixs || pixGetDepth(pixs) != 32)
899  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
900  if (regionflag != L_INCLUDE_REGION && regionflag != L_EXCLUDE_REGION)
901  return (PIX *)ERROR_PTR("invalid regionflag", __func__, NULL);
902 
903  /* Set up LUTs for saturation and max intensity (val).
904  * These have the value 1 within the specified intervals of
905  * saturation and max intensity. */
906  slut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
907  vlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
908  sstart = L_MAX(0, satcenter - sathw);
909  send = L_MIN(255, satcenter + sathw);
910  vstart = L_MAX(0, valcenter - valhw);
911  vend = L_MIN(255, valcenter + valhw);
912  for (i = sstart; i <= send; i++)
913  slut[i] = 1;
914  for (i = vstart; i <= vend; i++)
915  vlut[i] = 1;
916 
917  /* Generate the mask */
918  pixt = pixConvertRGBToHSV(NULL, pixs);
919  pixGetDimensions(pixs, &w, &h, NULL);
920  pixd = pixCreate(w, h, 1);
921  if (regionflag == L_INCLUDE_REGION)
922  pixClearAll(pixd);
923  else /* L_EXCLUDE_REGION */
924  pixSetAll(pixd);
925  datat = pixGetData(pixt);
926  datad = pixGetData(pixd);
927  wplt = pixGetWpl(pixt);
928  wpld = pixGetWpl(pixd);
929  for (i = 0; i < h; i++) {
930  linet = datat + i * wplt;
931  lined = datad + i * wpld;
932  for (j = 0; j < w; j++) {
933  pixel = linet[j];
934  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
935  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
936  if (slut[sval] == 1 && vlut[vval] == 1) {
937  if (regionflag == L_INCLUDE_REGION)
938  SET_DATA_BIT(lined, j);
939  else /* L_EXCLUDE_REGION */
940  CLEAR_DATA_BIT(lined, j);
941  }
942  }
943  }
944 
945  LEPT_FREE(slut);
946  LEPT_FREE(vlut);
947  pixDestroy(&pixt);
948  return pixd;
949 }
950 
951 
971 PIX *
973  l_int32 factor,
974  NUMA **pnahue,
975  NUMA **pnasat)
976 {
977 l_int32 i, j, w, h, wplt, hval, sval, nd;
978 l_uint32 pixel;
979 l_uint32 *datat, *linet;
980 void **lined32;
981 NUMA *nahue, *nasat;
982 PIX *pixt, *pixd;
983 
984  if (pnahue) *pnahue = NULL;
985  if (pnasat) *pnasat = NULL;
986  if (!pixs || pixGetDepth(pixs) != 32)
987  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
988 
989  if (pnahue) {
990  nahue = numaCreate(240);
991  numaSetCount(nahue, 240);
992  *pnahue = nahue;
993  }
994  if (pnasat) {
995  nasat = numaCreate(256);
996  numaSetCount(nasat, 256);
997  *pnasat = nasat;
998  }
999 
1000  if (factor <= 1)
1001  pixt = pixClone(pixs);
1002  else
1003  pixt = pixScaleBySampling(pixs, 1.0 / (l_float32)factor,
1004  1.0 / (l_float32)factor);
1005 
1006  /* Create the hue-saturation histogram */
1007  pixd = pixCreate(256, 240, 32);
1008  lined32 = pixGetLinePtrs(pixd, NULL);
1009  pixGetDimensions(pixt, &w, &h, NULL);
1010  datat = pixGetData(pixt);
1011  wplt = pixGetWpl(pixt);
1012  for (i = 0; i < h; i++) {
1013  linet = datat + i * wplt;
1014  for (j = 0; j < w; j++) {
1015  pixel = linet[j];
1016  hval = (pixel >> L_RED_SHIFT) & 0xff;
1017 
1018 #if DEBUG_HISTO
1019  if (hval > 239) {
1020  lept_stderr("hval = %d for (%d,%d)\n", hval, i, j);
1021  continue;
1022  }
1023 #endif /* DEBUG_HISTO */
1024 
1025  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
1026  if (pnahue)
1027  numaShiftValue(nahue, hval, 1.0);
1028  if (pnasat)
1029  numaShiftValue(nasat, sval, 1.0);
1030  nd = GET_DATA_FOUR_BYTES(lined32[hval], sval);
1031  SET_DATA_FOUR_BYTES(lined32[hval], sval, nd + 1);
1032  }
1033  }
1034 
1035  LEPT_FREE(lined32);
1036  pixDestroy(&pixt);
1037  return pixd;
1038 }
1039 
1040 
1060 PIX *
1062  l_int32 factor,
1063  NUMA **pnahue,
1064  NUMA **pnaval)
1065 {
1066 l_int32 i, j, w, h, wplt, hval, vval, nd;
1067 l_uint32 pixel;
1068 l_uint32 *datat, *linet;
1069 void **lined32;
1070 NUMA *nahue, *naval;
1071 PIX *pixt, *pixd;
1072 
1073  if (pnahue) *pnahue = NULL;
1074  if (pnaval) *pnaval = NULL;
1075  if (!pixs || pixGetDepth(pixs) != 32)
1076  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
1077 
1078  if (pnahue) {
1079  nahue = numaCreate(240);
1080  numaSetCount(nahue, 240);
1081  *pnahue = nahue;
1082  }
1083  if (pnaval) {
1084  naval = numaCreate(256);
1085  numaSetCount(naval, 256);
1086  *pnaval = naval;
1087  }
1088 
1089  if (factor <= 1)
1090  pixt = pixClone(pixs);
1091  else
1092  pixt = pixScaleBySampling(pixs, 1.0 / (l_float32)factor,
1093  1.0 / (l_float32)factor);
1094 
1095  /* Create the hue-value histogram */
1096  pixd = pixCreate(256, 240, 32);
1097  lined32 = pixGetLinePtrs(pixd, NULL);
1098  pixGetDimensions(pixt, &w, &h, NULL);
1099  datat = pixGetData(pixt);
1100  wplt = pixGetWpl(pixt);
1101  for (i = 0; i < h; i++) {
1102  linet = datat + i * wplt;
1103  for (j = 0; j < w; j++) {
1104  pixel = linet[j];
1105  hval = (pixel >> L_RED_SHIFT) & 0xff;
1106  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
1107  if (pnahue)
1108  numaShiftValue(nahue, hval, 1.0);
1109  if (pnaval)
1110  numaShiftValue(naval, vval, 1.0);
1111  nd = GET_DATA_FOUR_BYTES(lined32[hval], vval);
1112  SET_DATA_FOUR_BYTES(lined32[hval], vval, nd + 1);
1113  }
1114  }
1115 
1116  LEPT_FREE(lined32);
1117  pixDestroy(&pixt);
1118  return pixd;
1119 }
1120 
1121 
1141 PIX *
1143  l_int32 factor,
1144  NUMA **pnasat,
1145  NUMA **pnaval)
1146 {
1147 l_int32 i, j, w, h, wplt, sval, vval, nd;
1148 l_uint32 pixel;
1149 l_uint32 *datat, *linet;
1150 void **lined32;
1151 NUMA *nasat, *naval;
1152 PIX *pixt, *pixd;
1153 
1154  if (pnasat) *pnasat = NULL;
1155  if (pnaval) *pnaval = NULL;
1156  if (!pixs || pixGetDepth(pixs) != 32)
1157  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", __func__, NULL);
1158 
1159  if (pnasat) {
1160  nasat = numaCreate(256);
1161  numaSetCount(nasat, 256);
1162  *pnasat = nasat;
1163  }
1164  if (pnaval) {
1165  naval = numaCreate(256);
1166  numaSetCount(naval, 256);
1167  *pnaval = naval;
1168  }
1169 
1170  if (factor <= 1)
1171  pixt = pixClone(pixs);
1172  else
1173  pixt = pixScaleBySampling(pixs, 1.0 / (l_float32)factor,
1174  1.0 / (l_float32)factor);
1175 
1176  /* Create the hue-value histogram */
1177  pixd = pixCreate(256, 256, 32);
1178  lined32 = pixGetLinePtrs(pixd, NULL);
1179  pixGetDimensions(pixt, &w, &h, NULL);
1180  datat = pixGetData(pixt);
1181  wplt = pixGetWpl(pixt);
1182  for (i = 0; i < h; i++) {
1183  linet = datat + i * wplt;
1184  for (j = 0; j < w; j++) {
1185  pixel = linet[j];
1186  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
1187  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
1188  if (pnasat)
1189  numaShiftValue(nasat, sval, 1.0);
1190  if (pnaval)
1191  numaShiftValue(naval, vval, 1.0);
1192  nd = GET_DATA_FOUR_BYTES(lined32[sval], vval);
1193  SET_DATA_FOUR_BYTES(lined32[sval], vval, nd + 1);
1194  }
1195  }
1196 
1197  LEPT_FREE(lined32);
1198  pixDestroy(&pixt);
1199  return pixd;
1200 }
1201 
1202 
1230 l_ok
1232  l_int32 type,
1233  l_int32 width,
1234  l_int32 height,
1235  l_int32 npeaks,
1236  l_float32 erasefactor,
1237  PTA **ppta,
1238  NUMA **pnatot,
1239  PIXA **ppixa)
1240 {
1241 l_int32 i, xmax, ymax, ewidth, eheight;
1242 l_uint32 maxval;
1243 BOX *box;
1244 NUMA *natot;
1245 PIX *pixh, *pixw, *pix1, *pix2, *pix3;
1246 PTA *pta;
1247 
1248  if (ppixa) *ppixa = NULL;
1249  if (ppta) *ppta = NULL;
1250  if (pnatot) *pnatot = NULL;
1251  if (!pixs || pixGetDepth(pixs) != 32)
1252  return ERROR_INT("pixs undefined or not 32 bpp", __func__, 1);
1253  if (!ppta || !pnatot)
1254  return ERROR_INT("&pta and &natot not both defined", __func__, 1);
1255  if (type != L_HS_HISTO && type != L_HV_HISTO && type != L_SV_HISTO)
1256  return ERROR_INT("invalid HSV histo type", __func__, 1);
1257 
1258  if ((pta = ptaCreate(npeaks)) == NULL)
1259  return ERROR_INT("pta not made", __func__, 1);
1260  *ppta = pta;
1261  if ((natot = numaCreate(npeaks)) == NULL)
1262  return ERROR_INT("natot not made", __func__, 1);
1263  *pnatot = natot;
1264 
1265  *ppta = pta;
1266  if (type == L_SV_HISTO)
1267  pixh = pixAddMirroredBorder(pixs, width + 1, width + 1, height + 1,
1268  height + 1);
1269  else /* type == L_HS_HISTO or type == L_HV_HISTO */
1270  pixh = pixAddMixedBorder(pixs, width + 1, width + 1, height + 1,
1271  height + 1);
1272 
1273  /* Get the total count in the sliding window. If the window
1274  * fully covers the peak, this will be the integrated
1275  * volume under the peak. */
1276  pixw = pixWindowedMean(pixh, width, height, 1, 0);
1277  pixDestroy(&pixh);
1278 
1279  /* Sequentially identify and erase peaks in the histogram.
1280  * If requested for debugging, save a pixa of the sequence of
1281  * false color histograms. */
1282  if (ppixa)
1283  *ppixa = pixaCreate(0);
1284  for (i = 0; i < npeaks; i++) {
1285  pixGetMaxValueInRect(pixw, NULL, &maxval, &xmax, &ymax);
1286  if (maxval == 0) break;
1287  numaAddNumber(natot, maxval);
1288  ptaAddPt(pta, xmax, ymax);
1289  ewidth = (l_int32)(width * erasefactor);
1290  eheight = (l_int32)(height * erasefactor);
1291  box = boxCreate(xmax - ewidth, ymax - eheight, 2 * ewidth + 1,
1292  2 * eheight + 1);
1293 
1294  if (ppixa) {
1295  pix1 = pixMaxDynamicRange(pixw, L_LINEAR_SCALE);
1296  pixaAddPix(*ppixa, pix1, L_INSERT);
1297  pix2 = pixConvertGrayToFalseColor(pix1, 1.0);
1298  pixaAddPix(*ppixa, pix2, L_INSERT);
1299  pix1 = pixMaxDynamicRange(pixw, L_LOG_SCALE);
1300  pix2 = pixConvertGrayToFalseColor(pix1, 1.0);
1301  pixaAddPix(*ppixa, pix2, L_INSERT);
1302  pix3 = pixConvertTo32(pix1);
1303  pixRenderHashBoxArb(pix3, box, 6, 2, L_NEG_SLOPE_LINE,
1304  1, 255, 100, 100);
1305  pixaAddPix(*ppixa, pix3, L_INSERT);
1306  pixDestroy(&pix1);
1307  }
1308 
1309  pixClearInRect(pixw, box);
1310  boxDestroy(&box);
1311  if (type == L_HS_HISTO || type == L_HV_HISTO) {
1312  /* clear wraps at bottom and top */
1313  if (ymax - eheight < 0) { /* overlap to bottom */
1314  box = boxCreate(xmax - ewidth, 240 + ymax - eheight,
1315  2 * ewidth + 1, eheight - ymax);
1316  } else if (ymax + eheight > 239) { /* overlap to top */
1317  box = boxCreate(xmax - ewidth, 0, 2 * ewidth + 1,
1318  ymax + eheight - 239);
1319  } else {
1320  box = NULL;
1321  }
1322  if (box) {
1323  pixClearInRect(pixw, box);
1324  boxDestroy(&box);
1325  }
1326  }
1327  }
1328 
1329  pixDestroy(&pixw);
1330  return 0;
1331 }
1332 
1333 
1352 PIX *
1354  l_int32 sval,
1355  l_int32 vval,
1356  l_int32 huehw,
1357  l_int32 sathw,
1358  l_int32 nsamp,
1359  l_int32 factor)
1360 {
1361 l_int32 i, j, w, huedelta, satdelta, hue, sat, rval, gval, bval;
1362 PIX *pixt, *pixd;
1363 
1364  if (hval < 0 || hval > 240)
1365  return (PIX *)ERROR_PTR("invalid hval", __func__, NULL);
1366  if (huehw < 5 || huehw > 120)
1367  return (PIX *)ERROR_PTR("invalid huehw", __func__, NULL);
1368  if (sval - sathw < 0 || sval + sathw > 255)
1369  return (PIX *)ERROR_PTR("invalid sval/sathw", __func__, NULL);
1370  if (nsamp < 1 || factor < 3)
1371  return (PIX *)ERROR_PTR("invalid nsamp or rep. factor", __func__, NULL);
1372  if (vval < 0 || vval > 255)
1373  return (PIX *)ERROR_PTR("invalid vval", __func__, NULL);
1374 
1375  w = (2 * nsamp + 1);
1376  huedelta = (l_int32)((l_float32)huehw / (l_float32)nsamp);
1377  satdelta = (l_int32)((l_float32)sathw / (l_float32)nsamp);
1378  pixt = pixCreate(w, w, 32);
1379  for (i = 0; i < w; i++) {
1380  hue = hval + huedelta * (i - nsamp);
1381  if (hue < 0) hue += 240;
1382  if (hue >= 240) hue -= 240;
1383  for (j = 0; j < w; j++) {
1384  sat = sval + satdelta * (j - nsamp);
1385  convertHSVToRGB(hue, sat, vval, &rval, &gval, &bval);
1386  pixSetRGBPixel(pixt, j, i, rval, gval, bval);
1387  }
1388  }
1389 
1390  pixd = pixExpandReplicate(pixt, factor);
1391  pixDestroy(&pixt);
1392  return pixd;
1393 }
1394 
1395 
1396 /*---------------------------------------------------------------------------*
1397  * Colorspace conversion between RGB and YUV *
1398  *---------------------------------------------------------------------------*/
1426 PIX *
1428  PIX *pixs)
1429 {
1430 l_int32 w, h, d, wpl, i, j, rval, gval, bval, yval, uval, vval;
1431 l_uint32 *line, *data;
1432 PIXCMAP *cmap;
1433 
1434  if (!pixs)
1435  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
1436  if (pixd && pixd != pixs)
1437  return (PIX *)ERROR_PTR("pixd defined and not inplace", __func__, pixd);
1438 
1439  d = pixGetDepth(pixs);
1440  cmap = pixGetColormap(pixs);
1441  if (!cmap && d != 32)
1442  return (PIX *)ERROR_PTR("not cmapped or rgb", __func__, pixd);
1443 
1444  if (!pixd)
1445  pixd = pixCopy(NULL, pixs);
1446 
1447  cmap = pixGetColormap(pixd);
1448  if (cmap) { /* just convert the colormap */
1449  pixcmapConvertRGBToYUV(cmap);
1450  return pixd;
1451  }
1452 
1453  /* Convert RGB image */
1454  pixGetDimensions(pixd, &w, &h, NULL);
1455  wpl = pixGetWpl(pixd);
1456  data = pixGetData(pixd);
1457  for (i = 0; i < h; i++) {
1458  line = data + i * wpl;
1459  for (j = 0; j < w; j++) {
1460  extractRGBValues(line[j], &rval, &gval, &bval);
1461  convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval);
1462  line[j] = (yval << 24) | (uval << 16) | (vval << 8);
1463  }
1464  }
1465 
1466  return pixd;
1467 }
1468 
1469 
1487 PIX *
1489  PIX *pixs)
1490 {
1491 l_int32 w, h, d, wpl, i, j, rval, gval, bval, yval, uval, vval;
1492 l_uint32 pixel;
1493 l_uint32 *line, *data;
1494 PIXCMAP *cmap;
1495 
1496  if (!pixs)
1497  return (PIX *)ERROR_PTR("pixs not defined", __func__, pixd);
1498  if (pixd && pixd != pixs)
1499  return (PIX *)ERROR_PTR("pixd defined and not inplace", __func__, pixd);
1500 
1501  d = pixGetDepth(pixs);
1502  cmap = pixGetColormap(pixs);
1503  if (!cmap && d != 32)
1504  return (PIX *)ERROR_PTR("not cmapped or hsv", __func__, pixd);
1505 
1506  if (!pixd)
1507  pixd = pixCopy(NULL, pixs);
1508 
1509  cmap = pixGetColormap(pixd);
1510  if (cmap) { /* just convert the colormap */
1511  pixcmapConvertYUVToRGB(cmap);
1512  return pixd;
1513  }
1514 
1515  /* Convert YUV image */
1516  pixGetDimensions(pixd, &w, &h, NULL);
1517  wpl = pixGetWpl(pixd);
1518  data = pixGetData(pixd);
1519  for (i = 0; i < h; i++) {
1520  line = data + i * wpl;
1521  for (j = 0; j < w; j++) {
1522  pixel = line[j];
1523  yval = pixel >> 24;
1524  uval = (pixel >> 16) & 0xff;
1525  vval = (pixel >> 8) & 0xff;
1526  convertYUVToRGB(yval, uval, vval, &rval, &gval, &bval);
1527  composeRGBPixel(rval, gval, bval, line + j);
1528  }
1529  }
1530 
1531  return pixd;
1532 }
1533 
1534 
1550 l_ok
1551 convertRGBToYUV(l_int32 rval,
1552  l_int32 gval,
1553  l_int32 bval,
1554  l_int32 *pyval,
1555  l_int32 *puval,
1556  l_int32 *pvval)
1557 {
1558 l_float32 norm;
1559 
1560  if (pyval) *pyval = 0;
1561  if (puval) *puval = 0;
1562  if (pvval) *pvval = 0;
1563  if (!pyval || !puval || !pvval)
1564  return ERROR_INT("&yval, &uval, &vval not all defined", __func__, 1);
1565 
1566  norm = 1.0 / 256.;
1567  *pyval = (l_int32)(16.0 +
1568  norm * (65.738 * rval + 129.057 * gval + 25.064 * bval) + 0.5);
1569  *puval = (l_int32)(128.0 +
1570  norm * (-37.945 * rval -74.494 * gval + 112.439 * bval) + 0.5);
1571  *pvval = (l_int32)(128.0 +
1572  norm * (112.439 * rval - 94.154 * gval - 18.285 * bval) + 0.5);
1573  return 0;
1574 }
1575 
1576 
1596 l_ok
1597 convertYUVToRGB(l_int32 yval,
1598  l_int32 uval,
1599  l_int32 vval,
1600  l_int32 *prval,
1601  l_int32 *pgval,
1602  l_int32 *pbval)
1603 {
1604 l_int32 rval, gval, bval;
1605 l_float32 norm, ym, um, vm;
1606 
1607  if (prval) *prval = 0;
1608  if (pgval) *pgval = 0;
1609  if (pbval) *pbval = 0;
1610  if (!prval || !pgval || !pbval)
1611  return ERROR_INT("&rval, &gval, &bval not all defined", __func__, 1);
1612 
1613  norm = 1.0 / 256.;
1614  ym = yval - 16.0;
1615  um = uval - 128.0;
1616  vm = vval - 128.0;
1617  rval = (l_int32)(norm * (298.082 * ym + 408.583 * vm) + 0.5);
1618  gval = (l_int32)(norm * (298.082 * ym - 100.291 * um - 208.120 * vm) +
1619  0.5);
1620  bval = (l_int32)(norm * (298.082 * ym + 516.411 * um) + 0.5);
1621  *prval = L_MIN(255, L_MAX(0, rval));
1622  *pgval = L_MIN(255, L_MAX(0, gval));
1623  *pbval = L_MIN(255, L_MAX(0, bval));
1624 
1625  return 0;
1626 }
1627 
1628 
1642 l_ok
1644 {
1645 l_int32 i, ncolors, rval, gval, bval, yval, uval, vval;
1646 
1647  if (!cmap)
1648  return ERROR_INT("cmap not defined", __func__, 1);
1649 
1650  ncolors = pixcmapGetCount(cmap);
1651  for (i = 0; i < ncolors; i++) {
1652  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1653  convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval);
1654  pixcmapResetColor(cmap, i, yval, uval, vval);
1655  }
1656  return 0;
1657 }
1658 
1659 
1673 l_ok
1675 {
1676 l_int32 i, ncolors, rval, gval, bval, yval, uval, vval;
1677 
1678  if (!cmap)
1679  return ERROR_INT("cmap not defined", __func__, 1);
1680 
1681  ncolors = pixcmapGetCount(cmap);
1682  for (i = 0; i < ncolors; i++) {
1683  pixcmapGetColor(cmap, i, &yval, &uval, &vval);
1684  convertYUVToRGB(yval, uval, vval, &rval, &gval, &bval);
1685  pixcmapResetColor(cmap, i, rval, gval, bval);
1686  }
1687  return 0;
1688 }
1689 
1690 
1691 /*---------------------------------------------------------------------------*
1692  * Colorspace conversion between RGB and XYZ *
1693  *---------------------------------------------------------------------------*/
1722 FPIXA *
1724 {
1725 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
1726 l_uint32 *lines, *datas;
1727 l_float32 fxval, fyval, fzval;
1728 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
1729 FPIX *fpix;
1730 FPIXA *fpixa;
1731 
1732  if (!pixs || pixGetDepth(pixs) != 32)
1733  return (FPIXA *)ERROR_PTR("pixs undefined or not rgb", __func__, NULL);
1734 
1735  /* Convert RGB image */
1736  pixGetDimensions(pixs, &w, &h, NULL);
1737  fpixa = fpixaCreate(3);
1738  for (i = 0; i < 3; i++) {
1739  fpix = fpixCreate(w, h);
1740  fpixaAddFPix(fpixa, fpix, L_INSERT);
1741  }
1742  wpls = pixGetWpl(pixs);
1743  wpld = fpixGetWpl(fpix);
1744  datas = pixGetData(pixs);
1745  datax = fpixaGetData(fpixa, 0);
1746  datay = fpixaGetData(fpixa, 1);
1747  dataz = fpixaGetData(fpixa, 2);
1748  for (i = 0; i < h; i++) {
1749  lines = datas + i * wpls;
1750  linex = datax + i * wpld;
1751  liney = datay + i * wpld;
1752  linez = dataz + i * wpld;
1753  for (j = 0; j < w; j++) {
1754  extractRGBValues(lines[j], &rval, &gval, &bval);
1755  convertRGBToXYZ(rval, gval, bval, &fxval, &fyval, &fzval);
1756  *(linex + j) = fxval;
1757  *(liney + j) = fyval;
1758  *(linez + j) = fzval;
1759  }
1760  }
1761 
1762  return fpixa;
1763 }
1764 
1765 
1779 PIX *
1781 {
1782 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
1783 l_float32 fxval, fyval, fzval;
1784 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
1785 l_uint32 *lined, *datad;
1786 PIX *pixd;
1787 FPIX *fpix;
1788 
1789  if (!fpixa || fpixaGetCount(fpixa) != 3)
1790  return (PIX *)ERROR_PTR("fpixa undefined or invalid", __func__, NULL);
1791 
1792  /* Convert XYZ image */
1793  if (fpixaGetFPixDimensions(fpixa, 0, &w, &h))
1794  return (PIX *)ERROR_PTR("fpixa dimensions not found", __func__, NULL);
1795  pixd = pixCreate(w, h, 32);
1796  wpld = pixGetWpl(pixd);
1797  datad = pixGetData(pixd);
1798  datax = fpixaGetData(fpixa, 0);
1799  datay = fpixaGetData(fpixa, 1);
1800  dataz = fpixaGetData(fpixa, 2);
1801  fpix = fpixaGetFPix(fpixa, 0, L_CLONE);
1802  wpls = fpixGetWpl(fpix);
1803  fpixDestroy(&fpix);
1804  for (i = 0; i < h; i++) {
1805  linex = datax + i * wpls;
1806  liney = datay + i * wpls;
1807  linez = dataz + i * wpls;
1808  lined = datad + i * wpld;
1809  for (j = 0; j < w; j++) {
1810  fxval = linex[j];
1811  fyval = liney[j];
1812  fzval = linez[j];
1813  convertXYZToRGB(fxval, fyval, fzval, 0, &rval, &gval, &bval);
1814  composeRGBPixel(rval, gval, bval, lined + j);
1815  }
1816  }
1817 
1818  return pixd;
1819 }
1820 
1821 
1835 l_ok
1836 convertRGBToXYZ(l_int32 rval,
1837  l_int32 gval,
1838  l_int32 bval,
1839  l_float32 *pfxval,
1840  l_float32 *pfyval,
1841  l_float32 *pfzval)
1842 {
1843  if (pfxval) *pfxval = 0.0;
1844  if (pfyval) *pfyval = 0.0;
1845  if (pfzval) *pfzval = 0.0;
1846  if (!pfxval || !pfyval || !pfzval)
1847  return ERROR_INT("&xval, &yval, &zval not all defined", __func__, 1);
1848 
1849  *pfxval = 0.4125 * rval + 0.3576 * gval + 0.1804 * bval;
1850  *pfyval = 0.2127 * rval + 0.7152 * gval + 0.0722 * bval;
1851  *pfzval = 0.0193 * rval + 0.1192 * gval + 0.9502 * bval;
1852  return 0;
1853 }
1854 
1855 
1875 l_ok
1876 convertXYZToRGB(l_float32 fxval,
1877  l_float32 fyval,
1878  l_float32 fzval,
1879  l_int32 blackout,
1880  l_int32 *prval,
1881  l_int32 *pgval,
1882  l_int32 *pbval)
1883 {
1884 l_int32 rval, gval, bval;
1885 
1886  if (prval) *prval = 0;
1887  if (pgval) *pgval = 0;
1888  if (pbval) *pbval = 0;
1889  if (!prval || !pgval ||!pbval)
1890  return ERROR_INT("&rval, &gval, &bval not all defined", __func__, 1);
1891  *prval = *pgval = *pbval = 0;
1892 
1893  rval = (l_int32)(3.2405 * fxval - 1.5372 * fyval - 0.4985 * fzval + 0.5);
1894  gval = (l_int32)(-0.9693 * fxval + 1.8760 * fyval + 0.0416 * fzval + 0.5);
1895  bval = (l_int32)(0.0556 * fxval - 0.2040 * fyval + 1.0573 * fzval + 0.5);
1896  if (blackout == 0) { /* the usual situation; use nearest rgb color */
1897  *prval = L_MAX(0, L_MIN(rval, 255));
1898  *pgval = L_MAX(0, L_MIN(gval, 255));
1899  *pbval = L_MAX(0, L_MIN(bval, 255));
1900  } else { /* use black for out of gamut */
1901  if (rval >= 0 && rval < 256 && gval >= 0 && gval < 256 &&
1902  bval >= 0 && bval < 256) { /* in gamut */
1903  *prval = rval;
1904  *pgval = gval;
1905  *pbval = bval;
1906  }
1907  }
1908  return 0;
1909 }
1910 
1911 
1912 /*---------------------------------------------------------------------------*
1913  * Colorspace conversion between XYZ and LAB *
1914  *---------------------------------------------------------------------------*/
1934 FPIXA *
1936 {
1937 l_int32 w, h, wpl, i, j;
1938 l_float32 fxval, fyval, fzval, flval, faval, fbval;
1939 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
1940 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
1941 FPIX *fpix;
1942 FPIXA *fpixad;
1943 
1944  if (!fpixas || fpixaGetCount(fpixas) != 3)
1945  return (FPIXA *)ERROR_PTR("fpixas undefined/invalid", __func__, NULL);
1946 
1947  /* Convert XYZ image */
1948  if (fpixaGetFPixDimensions(fpixas, 0, &w, &h))
1949  return (FPIXA *)ERROR_PTR("fpixas sizes not found", __func__, NULL);
1950  fpixad = fpixaCreate(3);
1951  for (i = 0; i < 3; i++) {
1952  fpix = fpixCreate(w, h);
1953  fpixaAddFPix(fpixad, fpix, L_INSERT);
1954  }
1955  wpl = fpixGetWpl(fpix);
1956  datax = fpixaGetData(fpixas, 0);
1957  datay = fpixaGetData(fpixas, 1);
1958  dataz = fpixaGetData(fpixas, 2);
1959  datal = fpixaGetData(fpixad, 0);
1960  dataa = fpixaGetData(fpixad, 1);
1961  datab = fpixaGetData(fpixad, 2);
1962 
1963  /* Convert XYZ image */
1964  for (i = 0; i < h; i++) {
1965  linex = datax + i * wpl;
1966  liney = datay + i * wpl;
1967  linez = dataz + i * wpl;
1968  linel = datal + i * wpl;
1969  linea = dataa + i * wpl;
1970  lineb = datab + i * wpl;
1971  for (j = 0; j < w; j++) {
1972  fxval = *(linex + j);
1973  fyval = *(liney + j);
1974  fzval = *(linez + j);
1975  convertXYZToLAB(fxval, fyval, fzval, &flval, &faval, &fbval);
1976  *(linel + j) = flval;
1977  *(linea + j) = faval;
1978  *(lineb + j) = fbval;
1979  }
1980  }
1981 
1982  return fpixad;
1983 }
1984 
1985 
1998 FPIXA *
2000 {
2001 l_int32 w, h, wpl, i, j;
2002 l_float32 fxval, fyval, fzval, flval, faval, fbval;
2003 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
2004 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
2005 FPIX *fpix;
2006 FPIXA *fpixad;
2007 
2008  if (!fpixas || fpixaGetCount(fpixas) != 3)
2009  return (FPIXA *)ERROR_PTR("fpixas undefined/invalid", __func__, NULL);
2010 
2011  /* Convert LAB image */
2012  if (fpixaGetFPixDimensions(fpixas, 0, &w, &h))
2013  return (FPIXA *)ERROR_PTR("fpixas sizes not found", __func__, NULL);
2014  fpixad = fpixaCreate(3);
2015  for (i = 0; i < 3; i++) {
2016  fpix = fpixCreate(w, h);
2017  fpixaAddFPix(fpixad, fpix, L_INSERT);
2018  }
2019  wpl = fpixGetWpl(fpix);
2020  datal = fpixaGetData(fpixas, 0);
2021  dataa = fpixaGetData(fpixas, 1);
2022  datab = fpixaGetData(fpixas, 2);
2023  datax = fpixaGetData(fpixad, 0);
2024  datay = fpixaGetData(fpixad, 1);
2025  dataz = fpixaGetData(fpixad, 2);
2026 
2027  /* Convert XYZ image */
2028  for (i = 0; i < h; i++) {
2029  linel = datal + i * wpl;
2030  linea = dataa + i * wpl;
2031  lineb = datab + i * wpl;
2032  linex = datax + i * wpl;
2033  liney = datay + i * wpl;
2034  linez = dataz + i * wpl;
2035  for (j = 0; j < w; j++) {
2036  flval = *(linel + j);
2037  faval = *(linea + j);
2038  fbval = *(lineb + j);
2039  convertLABToXYZ(flval, faval, fbval, &fxval, &fyval, &fzval);
2040  *(linex + j) = fxval;
2041  *(liney + j) = fyval;
2042  *(linez + j) = fzval;
2043  }
2044  }
2045 
2046  return fpixad;
2047 }
2048 
2049 
2057 l_ok
2058 convertXYZToLAB(l_float32 xval,
2059  l_float32 yval,
2060  l_float32 zval,
2061  l_float32 *plval,
2062  l_float32 *paval,
2063  l_float32 *pbval)
2064 {
2065 l_float32 xn, yn, zn, fx, fy, fz;
2066 
2067  if (plval) *plval = 0.0;
2068  if (paval) *paval = 0.0;
2069  if (pbval) *pbval = 0.0;
2070  if (!plval || !paval || !pbval)
2071  return ERROR_INT("&lval, &aval, &bval not all defined", __func__, 1);
2072 
2073  /* First normalize to the corresponding white values */
2074  xn = 0.0041259 * xval;
2075  yn = 0.0039216 * yval;
2076  zn = 0.0036012 * zval;
2077  /* Then apply the lab_forward function */
2078  fx = lab_forward(xn);
2079  fy = lab_forward(yn);
2080  fz = lab_forward(zn);
2081  *plval = 116.0 * fy - 16.0;
2082  *paval = 500.0 * (fx - fy);
2083  *pbval = 200.0 * (fy - fz);
2084  return 0;
2085 }
2086 
2087 
2095 l_ok
2096 convertLABToXYZ(l_float32 lval,
2097  l_float32 aval,
2098  l_float32 bval,
2099  l_float32 *pxval,
2100  l_float32 *pyval,
2101  l_float32 *pzval)
2102 {
2103 l_float32 fx, fy, fz;
2104 l_float32 xw = 242.37; /* x component corresponding to rgb white */
2105 l_float32 yw = 255.0; /* y component corresponding to rgb white */
2106 l_float32 zw = 277.69; /* z component corresponding to rgb white */
2107 
2108  if (pxval) *pxval = 0.0;
2109  if (pyval) *pyval = 0.0;
2110  if (pzval) *pzval = 0.0;
2111  if (!pxval || !pyval || !pzval)
2112  return ERROR_INT("&xval, &yval, &zval not all defined", __func__, 1);
2113 
2114  fy = 0.0086207 * (16.0 + lval);
2115  fx = fy + 0.002 * aval;
2116  fz = fy - 0.005 * bval;
2117  *pxval = xw * lab_reverse(fx);
2118  *pyval = yw * lab_reverse(fy);
2119  *pzval = zw * lab_reverse(fz);
2120  return 0;
2121 }
2122 
2123 
2124 /*
2125  * See http://en.wikipedia.org/wiki/Lab_color_space for formulas.
2126  * This is the forward function: from xyz to lab. It includes a rational
2127  * function approximation over [0.008856 ... 1] to the cube root, from
2128  * "Fast Color Space Transformations Using Minimax Approximations",
2129  * M. Celebi et al, http://arxiv.org/pdf/1009.0854v1.pdf.
2130  */
2131 static l_float32
2132 lab_forward(l_float32 v)
2133 {
2134 const l_float32 f_thresh = 0.008856; /* (6/29)^3 */
2135 const l_float32 f_factor = 7.787; /* (1/3) * (29/6)^2) */
2136 const l_float32 f_offset = 0.13793; /* 4/29 */
2137 
2138  if (v > f_thresh) {
2139 #if SLOW_CUBE_ROOT
2140  return powf(v, 0.333333);
2141 #else
2142  l_float32 num, den;
2143  num = 4.37089e-04 + v * (9.52695e-02 + v * (1.25201 + v * 1.30273));
2144  den = 3.91236e-03 + v * (2.95408e-01 + v * (1.71714 + v * 6.34341e-01));
2145  return num / den;
2146 #endif
2147  } else {
2148  return f_factor * v + f_offset;
2149  }
2150 }
2151 
2152 
2153 /*
2154  * See http://en.wikipedia.org/wiki/Lab_color_space for formulas.
2155  * This is the reverse (inverse) function: from lab to xyz.
2156  */
2157 static l_float32
2158 lab_reverse(l_float32 v)
2159 {
2160 const l_float32 r_thresh = 0.20690; /* 6/29 */
2161 const l_float32 r_factor = 0.12842; /* 3 * (6/29)^2 */
2162 const l_float32 r_offset = 0.13793; /* 4/29 */
2163 
2164  if (v > r_thresh) {
2165  return v * v * v;
2166  } else {
2167  return r_factor * (v - r_offset);
2168  }
2169 }
2170 
2171 
2172 /*---------------------------------------------------------------------------*
2173  * Colorspace conversion between RGB and LAB *
2174  *---------------------------------------------------------------------------*/
2187 FPIXA *
2189 {
2190 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
2191 l_uint32 *lines, *datas;
2192 l_float32 flval, faval, fbval;
2193 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
2194 FPIX *fpix;
2195 FPIXA *fpixa;
2196 
2197  if (!pixs || pixGetDepth(pixs) != 32)
2198  return (FPIXA *)ERROR_PTR("pixs undefined or not rgb", __func__, NULL);
2199 
2200  /* Convert RGB image */
2201  pixGetDimensions(pixs, &w, &h, NULL);
2202  fpixa = fpixaCreate(3);
2203  for (i = 0; i < 3; i++) {
2204  fpix = fpixCreate(w, h);
2205  fpixaAddFPix(fpixa, fpix, L_INSERT);
2206  }
2207  wpls = pixGetWpl(pixs);
2208  wpld = fpixGetWpl(fpix);
2209  datas = pixGetData(pixs);
2210  datal = fpixaGetData(fpixa, 0);
2211  dataa = fpixaGetData(fpixa, 1);
2212  datab = fpixaGetData(fpixa, 2);
2213  for (i = 0; i < h; i++) {
2214  lines = datas + i * wpls;
2215  linel = datal + i * wpld;
2216  linea = dataa + i * wpld;
2217  lineb = datab + i * wpld;
2218  for (j = 0; j < w; j++) {
2219  extractRGBValues(lines[j], &rval, &gval, &bval);
2220  convertRGBToLAB(rval, gval, bval, &flval, &faval, &fbval);
2221  *(linel + j) = flval;
2222  *(linea + j) = faval;
2223  *(lineb + j) = fbval;
2224  }
2225  }
2226 
2227  return fpixa;
2228 }
2229 
2230 
2242 PIX *
2244 {
2245 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
2246 l_float32 flval, faval, fbval;
2247 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
2248 l_uint32 *lined, *datad;
2249 PIX *pixd;
2250 FPIX *fpix;
2251 
2252  if (!fpixa || fpixaGetCount(fpixa) != 3)
2253  return (PIX *)ERROR_PTR("fpixa undefined or invalid", __func__, NULL);
2254 
2255  /* Convert LAB image */
2256  if (fpixaGetFPixDimensions(fpixa, 0, &w, &h))
2257  return (PIX *)ERROR_PTR("fpixa dimensions not found", __func__, NULL);
2258  pixd = pixCreate(w, h, 32);
2259  wpld = pixGetWpl(pixd);
2260  datad = pixGetData(pixd);
2261  datal = fpixaGetData(fpixa, 0);
2262  dataa = fpixaGetData(fpixa, 1);
2263  datab = fpixaGetData(fpixa, 2);
2264  fpix = fpixaGetFPix(fpixa, 0, L_CLONE);
2265  wpls = fpixGetWpl(fpix);
2266  fpixDestroy(&fpix);
2267  for (i = 0; i < h; i++) {
2268  linel = datal + i * wpls;
2269  linea = dataa + i * wpls;
2270  lineb = datab + i * wpls;
2271  lined = datad + i * wpld;
2272  for (j = 0; j < w; j++) {
2273  flval = linel[j];
2274  faval = linea[j];
2275  fbval = lineb[j];
2276  convertLABToRGB(flval, faval, fbval, &rval, &gval, &bval);
2277  composeRGBPixel(rval, gval, bval, lined + j);
2278  }
2279  }
2280 
2281  return pixd;
2282 }
2283 
2284 
2298 l_ok
2299 convertRGBToLAB(l_int32 rval,
2300  l_int32 gval,
2301  l_int32 bval,
2302  l_float32 *pflval,
2303  l_float32 *pfaval,
2304  l_float32 *pfbval)
2305 {
2306 l_float32 fxval, fyval, fzval;
2307 
2308  if (pflval) *pflval = 0.0;
2309  if (pfaval) *pfaval = 0.0;
2310  if (pfbval) *pfbval = 0.0;
2311  if (!pflval || !pfaval || !pfbval)
2312  return ERROR_INT("&flval, &faval, &fbval not all defined", __func__, 1);
2313 
2314  convertRGBToXYZ(rval, gval, bval, &fxval, &fyval, &fzval);
2315  convertXYZToLAB(fxval, fyval, fzval, pflval, pfaval, pfbval);
2316  return 0;
2317 }
2318 
2319 
2333 l_ok
2334 convertLABToRGB(l_float32 flval,
2335  l_float32 faval,
2336  l_float32 fbval,
2337  l_int32 *prval,
2338  l_int32 *pgval,
2339  l_int32 *pbval)
2340 {
2341 l_float32 fxval, fyval, fzval;
2342 
2343  if (prval) *prval = 0;
2344  if (pgval) *pgval = 0;
2345  if (pbval) *pbval = 0;
2346  if (!prval || !pgval || !pbval)
2347  return ERROR_INT("&rval, &gval, &bval not all defined", __func__, 1);
2348 
2349  convertLABToXYZ(flval, faval, fbval, &fxval, &fyval, &fzval);
2350  convertXYZToRGB(fxval, fyval, fzval, 0, prval, pgval, pbval);
2351  return 0;
2352 }
2353 
2354 
2355 /*---------------------------------------------------------------------------*
2356  * Gamut display of RGB color space *
2357  *---------------------------------------------------------------------------*/
2377 PIX *
2378 pixMakeGamutRGB(l_int32 scale)
2379 {
2380 l_int32 i, j, k;
2381 l_uint32 val32;
2382 PIX *pix1, *pix2;
2383 PIXA *pixa;
2384 
2385  if (scale <= 0) scale = 8; /* default */
2386 
2387  pixa = pixaCreate(32);
2388  for (k = 0; k < 32; k++) {
2389  pix1 = pixCreate(32, 32, 32);
2390  for (i = 0; i < 32; i++) {
2391  for (j = 0; j < 32; j++) {
2392  composeRGBPixel(8 * j, 8 * i, 8 * k, &val32);
2393  pixSetPixel(pix1, j, i, val32);
2394  }
2395  }
2396  pixaAddPix(pixa, pix1, L_INSERT);
2397  }
2398  pix2 = pixaDisplayTiledInColumns(pixa, 8, scale, 5, 0);
2399  pixaDestroy(&pixa);
2400  return pix2;
2401 }
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_FOUR_BYTES(pdata, n, val)
Definition: arrayaccess.h:235
#define GET_DATA_FOUR_BYTES(pdata, n)
Definition: arrayaccess.h:231
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define CLEAR_DATA_BIT(pdata, n)
Definition: arrayaccess.h:131
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:273
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:171
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:683
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:923
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:789
PIX * fpixaConvertXYZToRGB(FPIXA *fpixa)
fpixaConvertXYZToRGB()
Definition: colorspace.c:1780
l_ok pixFindHistoPeaksHSV(PIX *pixs, l_int32 type, l_int32 width, l_int32 height, l_int32 npeaks, l_float32 erasefactor, PTA **ppta, NUMA **pnatot, PIXA **ppixa)
pixFindHistoPeaksHSV()
Definition: colorspace.c:1231
PIX * pixMakeRangeMaskHV(PIX *pixs, l_int32 huecenter, l_int32 huehw, l_int32 valcenter, l_int32 valhw, l_int32 regionflag)
pixMakeRangeMaskHV()
Definition: colorspace.c:789
l_ok convertLABToRGB(l_float32 flval, l_float32 faval, l_float32 fbval, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
convertLABToRGB()
Definition: colorspace.c:2334
PIX * pixConvertRGBToHSV(PIX *pixd, PIX *pixs)
pixConvertRGBToHSV()
Definition: colorspace.c:142
FPIXA * fpixaConvertXYZToLAB(FPIXA *fpixas)
fpixaConvertXYZToLAB()
Definition: colorspace.c:1935
l_ok convertXYZToRGB(l_float32 fxval, l_float32 fyval, l_float32 fzval, l_int32 blackout, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
convertXYZToRGB()
Definition: colorspace.c:1876
FPIXA * fpixaConvertLABToXYZ(FPIXA *fpixas)
fpixaConvertLABToXYZ()
Definition: colorspace.c:1999
FPIXA * pixConvertRGBToLAB(PIX *pixs)
pixConvertRGBToLAB()
Definition: colorspace.c:2188
PIX * pixConvertRGBToValue(PIX *pixs)
pixConvertRGBToValue()
Definition: colorspace.c:625
PIX * displayHSVColorRange(l_int32 hval, l_int32 sval, l_int32 vval, l_int32 huehw, l_int32 sathw, l_int32 nsamp, l_int32 factor)
displayHSVColorRange()
Definition: colorspace.c:1353
l_ok convertHSVToRGB(l_int32 hval, l_int32 sval, l_int32 vval, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
convertHSVToRGB()
Definition: colorspace.c:337
PIX * pixConvertRGBToHue(PIX *pixs)
pixConvertRGBToHue()
Definition: colorspace.c:488
PIX * pixMakeHistoHV(PIX *pixs, l_int32 factor, NUMA **pnahue, NUMA **pnaval)
pixMakeHistoHV()
Definition: colorspace.c:1061
l_ok convertRGBToHSV(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *phval, l_int32 *psval, l_int32 *pvval)
convertRGBToHSV()
Definition: colorspace.c:277
l_ok pixcmapConvertHSVToRGB(PIXCMAP *cmap)
pixcmapConvertHSVToRGB()
Definition: colorspace.c:455
l_ok pixcmapConvertRGBToHSV(PIXCMAP *cmap)
pixcmapConvertRGBToHSV()
Definition: colorspace.c:424
PIX * pixConvertYUVToRGB(PIX *pixd, PIX *pixs)
pixConvertYUVToRGB()
Definition: colorspace.c:1488
l_ok convertRGBToYUV(l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pyval, l_int32 *puval, l_int32 *pvval)
convertRGBToYUV()
Definition: colorspace.c:1551
PIX * pixMakeGamutRGB(l_int32 scale)
pixMakeGamutRGB()
Definition: colorspace.c:2378
PIX * fpixaConvertLABToRGB(FPIXA *fpixa)
fpixaConvertLABToRGB()
Definition: colorspace.c:2243
l_ok pixcmapConvertRGBToYUV(PIXCMAP *cmap)
pixcmapConvertRGBToYUV()
Definition: colorspace.c:1643
l_ok convertLABToXYZ(l_float32 lval, l_float32 aval, l_float32 bval, l_float32 *pxval, l_float32 *pyval, l_float32 *pzval)
convertLABToXYZ()
Definition: colorspace.c:2096
l_ok convertXYZToLAB(l_float32 xval, l_float32 yval, l_float32 zval, l_float32 *plval, l_float32 *paval, l_float32 *pbval)
convertXYZToLAB()
Definition: colorspace.c:2058
FPIXA * pixConvertRGBToXYZ(PIX *pixs)
pixConvertRGBToXYZ()
Definition: colorspace.c:1723
PIX * pixConvertHSVToRGB(PIX *pixd, PIX *pixs)
pixConvertHSVToRGB()
Definition: colorspace.c:204
PIX * pixMakeRangeMaskHS(PIX *pixs, l_int32 huecenter, l_int32 huehw, l_int32 satcenter, l_int32 sathw, l_int32 regionflag)
pixMakeRangeMaskHS()
Definition: colorspace.c:692
PIX * pixMakeRangeMaskSV(PIX *pixs, l_int32 satcenter, l_int32 sathw, l_int32 valcenter, l_int32 valhw, l_int32 regionflag)
pixMakeRangeMaskSV()
Definition: colorspace.c:885
l_ok convertRGBToLAB(l_int32 rval, l_int32 gval, l_int32 bval, l_float32 *pflval, l_float32 *pfaval, l_float32 *pfbval)
convertRGBToLAB()
Definition: colorspace.c:2299
PIX * pixConvertRGBToYUV(PIX *pixd, PIX *pixs)
pixConvertRGBToYUV()
Definition: colorspace.c:1427
PIX * pixMakeHistoHS(PIX *pixs, l_int32 factor, NUMA **pnahue, NUMA **pnasat)
pixMakeHistoHS()
Definition: colorspace.c:972
l_ok convertYUVToRGB(l_int32 yval, l_int32 uval, l_int32 vval, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
convertYUVToRGB()
Definition: colorspace.c:1597
l_ok convertRGBToXYZ(l_int32 rval, l_int32 gval, l_int32 bval, l_float32 *pfxval, l_float32 *pfyval, l_float32 *pfzval)
convertRGBToXYZ()
Definition: colorspace.c:1836
l_ok pixcmapConvertYUVToRGB(PIXCMAP *cmap)
pixcmapConvertYUVToRGB()
Definition: colorspace.c:1674
PIX * pixConvertRGBToSaturation(PIX *pixs)
pixConvertRGBToSaturation()
Definition: colorspace.c:562
PIX * pixMakeHistoSV(PIX *pixs, l_int32 factor, NUMA **pnasat, NUMA **pnaval)
pixMakeHistoSV()
Definition: colorspace.c:1142
PIX * pixWindowedMean(PIX *pixs, l_int32 wc, l_int32 hc, l_int32 hasborder, l_int32 normflag)
pixWindowedMean()
Definition: convolve.c:1055
l_ok fpixaAddFPix(FPIXA *fpixa, FPIX *fpix, l_int32 copyflag)
fpixaAddFPix()
Definition: fpix1.c:669
l_float32 * fpixaGetData(FPIXA *fpixa, l_int32 index)
fpixaGetData()
Definition: fpix1.c:855
FPIX * fpixaGetFPix(FPIXA *fpixa, l_int32 index, l_int32 accesstype)
fpixaGetFPix()
Definition: fpix1.c:796
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:357
FPIXA * fpixaCreate(l_int32 n)
fpixaCreate()
Definition: fpix1.c:556
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:280
l_int32 fpixaGetCount(FPIXA *fpixa)
fpixaGetCount()
Definition: fpix1.c:778
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:152
l_ok fpixaGetFPixDimensions(FPIXA *fpixa, l_int32 index, l_int32 *pw, l_int32 *ph)
fpixaGetFPixDimensions()
Definition: fpix1.c:823
l_ok pixRenderHashBoxArb(PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval)
pixRenderHashBoxArb()
Definition: graphics.c:1845
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
l_ok numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
Definition: numabasic.c:655
l_ok numaShiftValue(NUMA *na, l_int32 index, l_float32 diff)
numaShiftValue()
Definition: numabasic.c:773
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1844
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:263
l_ok pixClearAll(PIX *pix)
pixClearAll()
Definition: pix2.c:773
l_ok pixClearInRect(PIX *pix, BOX *box)
pixClearInRect()
Definition: pix2.c:1090
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:799
PIX * pixAddMixedBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixAddMixedBorder()
Definition: pix2.c:2205
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2728
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2793
l_ok pixSetRGBPixel(PIX *pix, l_int32 x, l_int32 y, l_int32 rval, l_int32 gval, l_int32 bval)
pixSetRGBPixel()
Definition: pix2.c:378
PIX * pixAddMirroredBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixAddMirroredBorder()
Definition: pix2.c:2100
l_ok pixGetMaxValueInRect(PIX *pixs, BOX *box, l_uint32 *pmaxval, l_int32 *pxmax, l_int32 *pymax)
pixGetMaxValueInRect()
Definition: pix4.c:2300
@ L_HS_HISTO
Definition: pix.h:983
@ L_SV_HISTO
Definition: pix.h:985
@ L_HV_HISTO
Definition: pix.h:984
@ L_NEG_SLOPE_LINE
Definition: pix.h:809
@ REMOVE_CMAP_TO_FULL_COLOR
Definition: pix.h:382
@ L_CLONE
Definition: pix.h:506
@ L_INSERT
Definition: pix.h:504
@ L_EXCLUDE_REGION
Definition: pix.h:994
@ L_INCLUDE_REGION
Definition: pix.h:993
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:493
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:404
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
PIX * pixaDisplayTiledInColumns(PIXA *pixas, l_int32 nx, l_float32 scalefactor, l_int32 spacing, l_int32 border)
pixaDisplayTiledInColumns()
Definition: pixafunc2.c:912
PIX * pixMaxDynamicRange(PIX *pixs, l_int32 type)
pixMaxDynamicRange()
Definition: pixarith.c:1225
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:324
PIX * pixConvertGrayToFalseColor(PIX *pixs, l_float32 gamma)
pixConvertGrayToFalseColor()
Definition: pixconv.c:1820
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3246
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:328
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1306
PIX * pixExpandReplicate(PIX *pixs, l_int32 factor)
pixExpandReplicate()
Definition: scale2.c:852
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306