Leptonica  1.77.0
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 
82 #include <string.h>
83 #include <math.h>
84 #include "allheaders.h"
85 
86 #ifndef NO_CONSOLE_IO
87 #define DEBUG_HISTO 0
88 #define SLOW_CUBE_ROOT 0
89 #endif /* ~NO_CONSOLE_IO */
90 
91  /* Functions used in xyz <--> lab conversions */
92 static l_float32 lab_forward(l_float32 v);
93 static l_float32 lab_reverse(l_float32 v);
94 
95 
96 /*---------------------------------------------------------------------------*
97  * Colorspace conversion between RGB and HSB *
98  *---------------------------------------------------------------------------*/
133 PIX *
135  PIX *pixs)
136 {
137 l_int32 w, h, d, wpl, i, j, rval, gval, bval, hval, sval, vval;
138 l_uint32 *line, *data;
139 PIXCMAP *cmap;
140 
141  PROCNAME("pixConvertRGBToHSV");
142 
143  if (!pixs)
144  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
145  if (pixd && pixd != pixs)
146  return (PIX *)ERROR_PTR("pixd defined and not inplace", procName, pixd);
147 
148  d = pixGetDepth(pixs);
149  cmap = pixGetColormap(pixs);
150  if (!cmap && d != 32)
151  return (PIX *)ERROR_PTR("not cmapped or rgb", procName, pixd);
152 
153  if (!pixd)
154  pixd = pixCopy(NULL, pixs);
155 
156  cmap = pixGetColormap(pixd);
157  if (cmap) { /* just convert the colormap */
159  return pixd;
160  }
161 
162  /* Convert RGB image */
163  pixGetDimensions(pixd, &w, &h, NULL);
164  wpl = pixGetWpl(pixd);
165  data = pixGetData(pixd);
166  for (i = 0; i < h; i++) {
167  line = data + i * wpl;
168  for (j = 0; j < w; j++) {
169  extractRGBValues(line[j], &rval, &gval, &bval);
170  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
171  line[j] = (hval << 24) | (sval << 16) | (vval << 8);
172  }
173  }
174 
175  return pixd;
176 }
177 
178 
197 PIX *
199  PIX *pixs)
200 {
201 l_int32 w, h, d, wpl, i, j, rval, gval, bval, hval, sval, vval;
202 l_uint32 pixel;
203 l_uint32 *line, *data;
204 PIXCMAP *cmap;
205 
206  PROCNAME("pixConvertHSVToRGB");
207 
208  if (!pixs)
209  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
210  if (pixd && pixd != pixs)
211  return (PIX *)ERROR_PTR("pixd defined and not inplace", procName, pixd);
212 
213  d = pixGetDepth(pixs);
214  cmap = pixGetColormap(pixs);
215  if (!cmap && d != 32)
216  return (PIX *)ERROR_PTR("not cmapped or hsv", procName, pixd);
217 
218  if (!pixd)
219  pixd = pixCopy(NULL, pixs);
220 
221  cmap = pixGetColormap(pixd);
222  if (cmap) { /* just convert the colormap */
224  return pixd;
225  }
226 
227  /* Convert HSV image */
228  pixGetDimensions(pixd, &w, &h, NULL);
229  wpl = pixGetWpl(pixd);
230  data = pixGetData(pixd);
231  for (i = 0; i < h; i++) {
232  line = data + i * wpl;
233  for (j = 0; j < w; j++) {
234  pixel = line[j];
235  hval = pixel >> 24;
236  sval = (pixel >> 16) & 0xff;
237  vval = (pixel >> 8) & 0xff;
238  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
239  composeRGBPixel(rval, gval, bval, line + j);
240  }
241  }
242 
243  return pixd;
244 }
245 
246 
272 l_ok
273 convertRGBToHSV(l_int32 rval,
274  l_int32 gval,
275  l_int32 bval,
276  l_int32 *phval,
277  l_int32 *psval,
278  l_int32 *pvval)
279 {
280 l_int32 minrg, maxrg, min, max, delta;
281 l_float32 h;
282 
283  PROCNAME("convertRGBToHSV");
284 
285  if (phval) *phval = 0;
286  if (psval) *psval = 0;
287  if (pvval) *pvval = 0;
288  if (!phval || !psval || !pvval)
289  return ERROR_INT("&hval, &sval, &vval not all defined", procName, 1);
290 
291  minrg = L_MIN(rval, gval);
292  min = L_MIN(minrg, bval);
293  maxrg = L_MAX(rval, gval);
294  max = L_MAX(maxrg, bval);
295  delta = max - min;
296 
297  *pvval = max;
298  if (delta == 0) { /* gray; no chroma */
299  *phval = 0;
300  *psval = 0;
301  } else {
302  *psval = (l_int32)(255. * (l_float32)delta / (l_float32)max + 0.5);
303  if (rval == max) /* between magenta and yellow */
304  h = (l_float32)(gval - bval) / (l_float32)delta;
305  else if (gval == max) /* between yellow and cyan */
306  h = 2. + (l_float32)(bval - rval) / (l_float32)delta;
307  else /* between cyan and magenta */
308  h = 4. + (l_float32)(rval - gval) / (l_float32)delta;
309  h *= 40.0;
310  if (h < 0.0)
311  h += 240.0;
312  if (h >= 239.5)
313  h = 0.0;
314  *phval = (l_int32)(h + 0.5);
315  }
316 
317  return 0;
318 }
319 
320 
334 l_ok
335 convertHSVToRGB(l_int32 hval,
336  l_int32 sval,
337  l_int32 vval,
338  l_int32 *prval,
339  l_int32 *pgval,
340  l_int32 *pbval)
341 {
342 l_int32 i, x, y, z;
343 l_float32 h, f, s;
344 
345  PROCNAME("convertHSVToRGB");
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", procName, 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", procName, 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  PROCNAME("pixcmapConvertRGBToHSV");
429 
430  if (!cmap)
431  return ERROR_INT("cmap not defined", procName, 1);
432 
433  ncolors = pixcmapGetCount(cmap);
434  for (i = 0; i < ncolors; i++) {
435  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
436  convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
437  pixcmapResetColor(cmap, i, hval, sval, vval);
438  }
439  return 0;
440 }
441 
442 
456 l_ok
458 {
459 l_int32 i, ncolors, rval, gval, bval, hval, sval, vval;
460 
461  PROCNAME("pixcmapConvertHSVToRGB");
462 
463  if (!cmap)
464  return ERROR_INT("cmap not defined", procName, 1);
465 
466  ncolors = pixcmapGetCount(cmap);
467  for (i = 0; i < ncolors; i++) {
468  pixcmapGetColor(cmap, i, &hval, &sval, &vval);
469  convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
470  pixcmapResetColor(cmap, i, rval, gval, bval);
471  }
472  return 0;
473 }
474 
475 
491 PIX *
493 {
494 l_int32 w, h, d, wplt, wpld;
495 l_int32 i, j, rval, gval, bval, hval, minrg, min, maxrg, max, delta;
496 l_float32 fh;
497 l_uint32 pixel;
498 l_uint32 *linet, *lined, *datat, *datad;
499 PIX *pixt, *pixd;
500 
501  PROCNAME("pixConvertRGBToHue");
502 
503  if (!pixs)
504  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
505 
506  pixGetDimensions(pixs, &w, &h, &d);
507  if (d != 32 && !pixGetColormap(pixs))
508  return (PIX *)ERROR_PTR("not cmapped or rgb", procName, NULL);
510 
511  /* Convert RGB image */
512  pixd = pixCreate(w, h, 8);
513  pixCopyResolution(pixd, pixs);
514  wplt = pixGetWpl(pixt);
515  datat = pixGetData(pixt);
516  wpld = pixGetWpl(pixd);
517  datad = pixGetData(pixd);
518  for (i = 0; i < h; i++) {
519  linet = datat + i * wplt;
520  lined = datad + i * wpld;
521  for (j = 0; j < w; j++) {
522  pixel = linet[j];
523  extractRGBValues(pixel, &rval, &gval, &bval);
524  minrg = L_MIN(rval, gval);
525  min = L_MIN(minrg, bval);
526  maxrg = L_MAX(rval, gval);
527  max = L_MAX(maxrg, bval);
528  delta = max - min;
529  if (delta == 0) { /* gray; no chroma */
530  hval = 0;
531  } else {
532  if (rval == max) /* between magenta and yellow */
533  fh = (l_float32)(gval - bval) / (l_float32)delta;
534  else if (gval == max) /* between yellow and cyan */
535  fh = 2. + (l_float32)(bval - rval) / (l_float32)delta;
536  else /* between cyan and magenta */
537  fh = 4. + (l_float32)(rval - gval) / (l_float32)delta;
538  fh *= 40.0;
539  if (fh < 0.0)
540  fh += 240.0;
541  hval = (l_int32)(fh + 0.5);
542  }
543  SET_DATA_BYTE(lined, j, hval);
544  }
545  }
546  pixDestroy(&pixt);
547 
548  return pixd;
549 }
550 
551 
552 
567 PIX *
569 {
570 l_int32 w, h, d, wplt, wpld;
571 l_int32 i, j, rval, gval, bval, sval, minrg, min, maxrg, max, delta;
572 l_uint32 pixel;
573 l_uint32 *linet, *lined, *datat, *datad;
574 PIX *pixt, *pixd;
575 
576  PROCNAME("pixConvertRGBToSaturation");
577 
578  if (!pixs)
579  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
580 
581  pixGetDimensions(pixs, &w, &h, &d);
582  if (d != 32 && !pixGetColormap(pixs))
583  return (PIX *)ERROR_PTR("not cmapped or rgb", procName, NULL);
585 
586  /* Convert RGB image */
587  pixd = pixCreate(w, h, 8);
588  pixCopyResolution(pixd, pixs);
589  wplt = pixGetWpl(pixt);
590  datat = pixGetData(pixt);
591  wpld = pixGetWpl(pixd);
592  datad = pixGetData(pixd);
593  for (i = 0; i < h; i++) {
594  linet = datat + i * wplt;
595  lined = datad + i * wpld;
596  for (j = 0; j < w; j++) {
597  pixel = linet[j];
598  extractRGBValues(pixel, &rval, &gval, &bval);
599  minrg = L_MIN(rval, gval);
600  min = L_MIN(minrg, bval);
601  maxrg = L_MAX(rval, gval);
602  max = L_MAX(maxrg, bval);
603  delta = max - min;
604  if (delta == 0) /* gray; no chroma */
605  sval = 0;
606  else
607  sval = (l_int32)(255. *
608  (l_float32)delta / (l_float32)max + 0.5);
609  SET_DATA_BYTE(lined, j, sval);
610  }
611  }
612 
613  pixDestroy(&pixt);
614  return pixd;
615 }
616 
617 
632 PIX *
634 {
635 l_int32 w, h, d, wplt, wpld;
636 l_int32 i, j, rval, gval, bval, maxrg, max;
637 l_uint32 pixel;
638 l_uint32 *linet, *lined, *datat, *datad;
639 PIX *pixt, *pixd;
640 
641  PROCNAME("pixConvertRGBToValue");
642 
643  if (!pixs)
644  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
645 
646  pixGetDimensions(pixs, &w, &h, &d);
647  if (d != 32 && !pixGetColormap(pixs))
648  return (PIX *)ERROR_PTR("not cmapped or rgb", procName, NULL);
650 
651  /* Convert RGB image */
652  pixd = pixCreate(w, h, 8);
653  pixCopyResolution(pixd, pixs);
654  wplt = pixGetWpl(pixt);
655  datat = pixGetData(pixt);
656  wpld = pixGetWpl(pixd);
657  datad = pixGetData(pixd);
658  for (i = 0; i < h; i++) {
659  linet = datat + i * wplt;
660  lined = datad + i * wpld;
661  for (j = 0; j < w; j++) {
662  pixel = linet[j];
663  extractRGBValues(pixel, &rval, &gval, &bval);
664  maxrg = L_MAX(rval, gval);
665  max = L_MAX(maxrg, bval);
666  SET_DATA_BYTE(lined, j, max);
667  }
668  }
669 
670  pixDestroy(&pixt);
671  return pixd;
672 }
673 
674 
675 /*---------------------------------------------------------------------------*
676  * Selection and display of range of colors in HSV space *
677  *---------------------------------------------------------------------------*/
701 PIX *
703  l_int32 huecenter,
704  l_int32 huehw,
705  l_int32 satcenter,
706  l_int32 sathw,
707  l_int32 regionflag)
708 {
709 l_int32 i, j, w, h, wplt, wpld, hstart, hend, sstart, send, hval, sval;
710 l_int32 *hlut, *slut;
711 l_uint32 pixel;
712 l_uint32 *datat, *datad, *linet, *lined;
713 PIX *pixt, *pixd;
714 
715  PROCNAME("pixMakeRangeMaskHS");
716 
717  if (!pixs || pixGetDepth(pixs) != 32)
718  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
719  if (regionflag != L_INCLUDE_REGION && regionflag != L_EXCLUDE_REGION)
720  return (PIX *)ERROR_PTR("invalid regionflag", procName, NULL);
721 
722  /* Set up LUTs for hue and saturation. These have the value 1
723  * within the specified intervals of hue and saturation. */
724  hlut = (l_int32 *)LEPT_CALLOC(240, sizeof(l_int32));
725  slut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
726  sstart = L_MAX(0, satcenter - sathw);
727  send = L_MIN(255, satcenter + sathw);
728  for (i = sstart; i <= send; i++)
729  slut[i] = 1;
730  hstart = (huecenter - huehw + 240) % 240;
731  hend = (huecenter + huehw + 240) % 240;
732  if (hstart < hend) {
733  for (i = hstart; i <= hend; i++)
734  hlut[i] = 1;
735  } else { /* wrap */
736  for (i = hstart; i < 240; i++)
737  hlut[i] = 1;
738  for (i = 0; i <= hend; i++)
739  hlut[i] = 1;
740  }
741 
742  /* Generate the mask */
743  pixt = pixConvertRGBToHSV(NULL, pixs);
744  pixGetDimensions(pixs, &w, &h, NULL);
745  pixd = pixCreateNoInit(w, h, 1);
746  if (regionflag == L_INCLUDE_REGION)
747  pixClearAll(pixd);
748  else /* L_EXCLUDE_REGION */
749  pixSetAll(pixd);
750  datat = pixGetData(pixt);
751  datad = pixGetData(pixd);
752  wplt = pixGetWpl(pixt);
753  wpld = pixGetWpl(pixd);
754  for (i = 0; i < h; i++) {
755  linet = datat + i * wplt;
756  lined = datad + i * wpld;
757  for (j = 0; j < w; j++) {
758  pixel = linet[j];
759  hval = (pixel >> L_RED_SHIFT) & 0xff;
760  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
761  if (hlut[hval] == 1 && slut[sval] == 1) {
762  if (regionflag == L_INCLUDE_REGION)
763  SET_DATA_BIT(lined, j);
764  else /* L_EXCLUDE_REGION */
765  CLEAR_DATA_BIT(lined, j);
766  }
767  }
768  }
769 
770  LEPT_FREE(hlut);
771  LEPT_FREE(slut);
772  pixDestroy(&pixt);
773  return pixd;
774 }
775 
776 
800 PIX *
802  l_int32 huecenter,
803  l_int32 huehw,
804  l_int32 valcenter,
805  l_int32 valhw,
806  l_int32 regionflag)
807 {
808 l_int32 i, j, w, h, wplt, wpld, hstart, hend, vstart, vend, hval, vval;
809 l_int32 *hlut, *vlut;
810 l_uint32 pixel;
811 l_uint32 *datat, *datad, *linet, *lined;
812 PIX *pixt, *pixd;
813 
814  PROCNAME("pixMakeRangeMaskHV");
815 
816  if (!pixs || pixGetDepth(pixs) != 32)
817  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
818  if (regionflag != L_INCLUDE_REGION && regionflag != L_EXCLUDE_REGION)
819  return (PIX *)ERROR_PTR("invalid regionflag", procName, NULL);
820 
821  /* Set up LUTs for hue and maximum intensity (val). These have
822  * the value 1 within the specified intervals of hue and value. */
823  hlut = (l_int32 *)LEPT_CALLOC(240, sizeof(l_int32));
824  vlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
825  vstart = L_MAX(0, valcenter - valhw);
826  vend = L_MIN(255, valcenter + valhw);
827  for (i = vstart; i <= vend; i++)
828  vlut[i] = 1;
829  hstart = (huecenter - huehw + 240) % 240;
830  hend = (huecenter + huehw + 240) % 240;
831  if (hstart < hend) {
832  for (i = hstart; i <= hend; i++)
833  hlut[i] = 1;
834  } else {
835  for (i = hstart; i < 240; i++)
836  hlut[i] = 1;
837  for (i = 0; i <= hend; i++)
838  hlut[i] = 1;
839  }
840 
841  /* Generate the mask */
842  pixt = pixConvertRGBToHSV(NULL, pixs);
843  pixGetDimensions(pixs, &w, &h, NULL);
844  pixd = pixCreateNoInit(w, h, 1);
845  if (regionflag == L_INCLUDE_REGION)
846  pixClearAll(pixd);
847  else /* L_EXCLUDE_REGION */
848  pixSetAll(pixd);
849  datat = pixGetData(pixt);
850  datad = pixGetData(pixd);
851  wplt = pixGetWpl(pixt);
852  wpld = pixGetWpl(pixd);
853  for (i = 0; i < h; i++) {
854  linet = datat + i * wplt;
855  lined = datad + i * wpld;
856  for (j = 0; j < w; j++) {
857  pixel = linet[j];
858  hval = (pixel >> L_RED_SHIFT) & 0xff;
859  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
860  if (hlut[hval] == 1 && vlut[vval] == 1) {
861  if (regionflag == L_INCLUDE_REGION)
862  SET_DATA_BIT(lined, j);
863  else /* L_EXCLUDE_REGION */
864  CLEAR_DATA_BIT(lined, j);
865  }
866  }
867  }
868 
869  LEPT_FREE(hlut);
870  LEPT_FREE(vlut);
871  pixDestroy(&pixt);
872  return pixd;
873 }
874 
875 
898 PIX *
900  l_int32 satcenter,
901  l_int32 sathw,
902  l_int32 valcenter,
903  l_int32 valhw,
904  l_int32 regionflag)
905 {
906 l_int32 i, j, w, h, wplt, wpld, sval, vval, sstart, send, vstart, vend;
907 l_int32 *slut, *vlut;
908 l_uint32 pixel;
909 l_uint32 *datat, *datad, *linet, *lined;
910 PIX *pixt, *pixd;
911 
912  PROCNAME("pixMakeRangeMaskSV");
913 
914  if (!pixs || pixGetDepth(pixs) != 32)
915  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
916  if (regionflag != L_INCLUDE_REGION && regionflag != L_EXCLUDE_REGION)
917  return (PIX *)ERROR_PTR("invalid regionflag", procName, NULL);
918 
919  /* Set up LUTs for saturation and max intensity (val).
920  * These have the value 1 within the specified intervals of
921  * saturation and max intensity. */
922  slut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
923  vlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
924  sstart = L_MAX(0, satcenter - sathw);
925  send = L_MIN(255, satcenter + sathw);
926  vstart = L_MAX(0, valcenter - valhw);
927  vend = L_MIN(255, valcenter + valhw);
928  for (i = sstart; i <= send; i++)
929  slut[i] = 1;
930  for (i = vstart; i <= vend; i++)
931  vlut[i] = 1;
932 
933  /* Generate the mask */
934  pixt = pixConvertRGBToHSV(NULL, pixs);
935  pixGetDimensions(pixs, &w, &h, NULL);
936  pixd = pixCreateNoInit(w, h, 1);
937  if (regionflag == L_INCLUDE_REGION)
938  pixClearAll(pixd);
939  else /* L_EXCLUDE_REGION */
940  pixSetAll(pixd);
941  datat = pixGetData(pixt);
942  datad = pixGetData(pixd);
943  wplt = pixGetWpl(pixt);
944  wpld = pixGetWpl(pixd);
945  for (i = 0; i < h; i++) {
946  linet = datat + i * wplt;
947  lined = datad + i * wpld;
948  for (j = 0; j < w; j++) {
949  pixel = linet[j];
950  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
951  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
952  if (slut[sval] == 1 && vlut[vval] == 1) {
953  if (regionflag == L_INCLUDE_REGION)
954  SET_DATA_BIT(lined, j);
955  else /* L_EXCLUDE_REGION */
956  CLEAR_DATA_BIT(lined, j);
957  }
958  }
959  }
960 
961  LEPT_FREE(slut);
962  LEPT_FREE(vlut);
963  pixDestroy(&pixt);
964  return pixd;
965 }
966 
967 
987 PIX *
989  l_int32 factor,
990  NUMA **pnahue,
991  NUMA **pnasat)
992 {
993 l_int32 i, j, w, h, wplt, hval, sval, nd;
994 l_uint32 pixel;
995 l_uint32 *datat, *linet;
996 void **lined32;
997 NUMA *nahue, *nasat;
998 PIX *pixt, *pixd;
999 
1000  PROCNAME("pixMakeHistoHS");
1001 
1002  if (pnahue) *pnahue = NULL;
1003  if (pnasat) *pnasat = NULL;
1004  if (!pixs || pixGetDepth(pixs) != 32)
1005  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1006 
1007  if (pnahue) {
1008  nahue = numaCreate(240);
1009  numaSetCount(nahue, 240);
1010  *pnahue = nahue;
1011  }
1012  if (pnasat) {
1013  nasat = numaCreate(256);
1014  numaSetCount(nasat, 256);
1015  *pnasat = nasat;
1016  }
1017 
1018  if (factor <= 1)
1019  pixt = pixClone(pixs);
1020  else
1021  pixt = pixScaleBySampling(pixs, 1.0 / (l_float32)factor,
1022  1.0 / (l_float32)factor);
1023 
1024  /* Create the hue-saturation histogram */
1025  pixd = pixCreate(256, 240, 32);
1026  lined32 = pixGetLinePtrs(pixd, NULL);
1027  pixGetDimensions(pixt, &w, &h, NULL);
1028  datat = pixGetData(pixt);
1029  wplt = pixGetWpl(pixt);
1030  for (i = 0; i < h; i++) {
1031  linet = datat + i * wplt;
1032  for (j = 0; j < w; j++) {
1033  pixel = linet[j];
1034  hval = (pixel >> L_RED_SHIFT) & 0xff;
1035 
1036 #if DEBUG_HISTO
1037  if (hval > 239) {
1038  fprintf(stderr, "hval = %d for (%d,%d)\n", hval, i, j);
1039  continue;
1040  }
1041 #endif /* DEBUG_HISTO */
1042 
1043  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
1044  if (pnahue)
1045  numaShiftValue(nahue, hval, 1.0);
1046  if (pnasat)
1047  numaShiftValue(nasat, sval, 1.0);
1048  nd = GET_DATA_FOUR_BYTES(lined32[hval], sval);
1049  SET_DATA_FOUR_BYTES(lined32[hval], sval, nd + 1);
1050  }
1051  }
1052 
1053  LEPT_FREE(lined32);
1054  pixDestroy(&pixt);
1055  return pixd;
1056 }
1057 
1058 
1078 PIX *
1080  l_int32 factor,
1081  NUMA **pnahue,
1082  NUMA **pnaval)
1083 {
1084 l_int32 i, j, w, h, wplt, hval, vval, nd;
1085 l_uint32 pixel;
1086 l_uint32 *datat, *linet;
1087 void **lined32;
1088 NUMA *nahue, *naval;
1089 PIX *pixt, *pixd;
1090 
1091  PROCNAME("pixMakeHistoHV");
1092 
1093  if (pnahue) *pnahue = NULL;
1094  if (pnaval) *pnaval = NULL;
1095  if (!pixs || pixGetDepth(pixs) != 32)
1096  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1097 
1098  if (pnahue) {
1099  nahue = numaCreate(240);
1100  numaSetCount(nahue, 240);
1101  *pnahue = nahue;
1102  }
1103  if (pnaval) {
1104  naval = numaCreate(256);
1105  numaSetCount(naval, 256);
1106  *pnaval = naval;
1107  }
1108 
1109  if (factor <= 1)
1110  pixt = pixClone(pixs);
1111  else
1112  pixt = pixScaleBySampling(pixs, 1.0 / (l_float32)factor,
1113  1.0 / (l_float32)factor);
1114 
1115  /* Create the hue-value histogram */
1116  pixd = pixCreate(256, 240, 32);
1117  lined32 = pixGetLinePtrs(pixd, NULL);
1118  pixGetDimensions(pixt, &w, &h, NULL);
1119  datat = pixGetData(pixt);
1120  wplt = pixGetWpl(pixt);
1121  for (i = 0; i < h; i++) {
1122  linet = datat + i * wplt;
1123  for (j = 0; j < w; j++) {
1124  pixel = linet[j];
1125  hval = (pixel >> L_RED_SHIFT) & 0xff;
1126  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
1127  if (pnahue)
1128  numaShiftValue(nahue, hval, 1.0);
1129  if (pnaval)
1130  numaShiftValue(naval, vval, 1.0);
1131  nd = GET_DATA_FOUR_BYTES(lined32[hval], vval);
1132  SET_DATA_FOUR_BYTES(lined32[hval], vval, nd + 1);
1133  }
1134  }
1135 
1136  LEPT_FREE(lined32);
1137  pixDestroy(&pixt);
1138  return pixd;
1139 }
1140 
1141 
1161 PIX *
1163  l_int32 factor,
1164  NUMA **pnasat,
1165  NUMA **pnaval)
1166 {
1167 l_int32 i, j, w, h, wplt, sval, vval, nd;
1168 l_uint32 pixel;
1169 l_uint32 *datat, *linet;
1170 void **lined32;
1171 NUMA *nasat, *naval;
1172 PIX *pixt, *pixd;
1173 
1174  PROCNAME("pixMakeHistoSV");
1175 
1176  if (pnasat) *pnasat = NULL;
1177  if (pnaval) *pnaval = NULL;
1178  if (!pixs || pixGetDepth(pixs) != 32)
1179  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1180 
1181  if (pnasat) {
1182  nasat = numaCreate(256);
1183  numaSetCount(nasat, 256);
1184  *pnasat = nasat;
1185  }
1186  if (pnaval) {
1187  naval = numaCreate(256);
1188  numaSetCount(naval, 256);
1189  *pnaval = naval;
1190  }
1191 
1192  if (factor <= 1)
1193  pixt = pixClone(pixs);
1194  else
1195  pixt = pixScaleBySampling(pixs, 1.0 / (l_float32)factor,
1196  1.0 / (l_float32)factor);
1197 
1198  /* Create the hue-value histogram */
1199  pixd = pixCreate(256, 256, 32);
1200  lined32 = pixGetLinePtrs(pixd, NULL);
1201  pixGetDimensions(pixt, &w, &h, NULL);
1202  datat = pixGetData(pixt);
1203  wplt = pixGetWpl(pixt);
1204  for (i = 0; i < h; i++) {
1205  linet = datat + i * wplt;
1206  for (j = 0; j < w; j++) {
1207  pixel = linet[j];
1208  sval = (pixel >> L_GREEN_SHIFT) & 0xff;
1209  vval = (pixel >> L_BLUE_SHIFT) & 0xff;
1210  if (pnasat)
1211  numaShiftValue(nasat, sval, 1.0);
1212  if (pnaval)
1213  numaShiftValue(naval, vval, 1.0);
1214  nd = GET_DATA_FOUR_BYTES(lined32[sval], vval);
1215  SET_DATA_FOUR_BYTES(lined32[sval], vval, nd + 1);
1216  }
1217  }
1218 
1219  LEPT_FREE(lined32);
1220  pixDestroy(&pixt);
1221  return pixd;
1222 }
1223 
1224 
1252 l_ok
1254  l_int32 type,
1255  l_int32 width,
1256  l_int32 height,
1257  l_int32 npeaks,
1258  l_float32 erasefactor,
1259  PTA **ppta,
1260  NUMA **pnatot,
1261  PIXA **ppixa)
1262 {
1263 l_int32 i, xmax, ymax, ewidth, eheight;
1264 l_uint32 maxval;
1265 BOX *box;
1266 NUMA *natot;
1267 PIX *pixh, *pixw, *pix1, *pix2, *pix3;
1268 PTA *pta;
1269 
1270  PROCNAME("pixFindHistoPeaksHSV");
1271 
1272  if (ppixa) *ppixa = NULL;
1273  if (ppta) *ppta = NULL;
1274  if (pnatot) *pnatot = NULL;
1275  if (!pixs || pixGetDepth(pixs) != 32)
1276  return ERROR_INT("pixs undefined or not 32 bpp", procName, 1);
1277  if (!ppta || !pnatot)
1278  return ERROR_INT("&pta and &natot not both defined", procName, 1);
1279  if (type != L_HS_HISTO && type != L_HV_HISTO && type != L_SV_HISTO)
1280  return ERROR_INT("invalid HSV histo type", procName, 1);
1281 
1282  if ((pta = ptaCreate(npeaks)) == NULL)
1283  return ERROR_INT("pta not made", procName, 1);
1284  *ppta = pta;
1285  if ((natot = numaCreate(npeaks)) == NULL)
1286  return ERROR_INT("natot not made", procName, 1);
1287  *pnatot = natot;
1288 
1289  *ppta = pta;
1290  if (type == L_SV_HISTO)
1291  pixh = pixAddMirroredBorder(pixs, width + 1, width + 1, height + 1,
1292  height + 1);
1293  else /* type == L_HS_HISTO or type == L_HV_HISTO */
1294  pixh = pixAddMixedBorder(pixs, width + 1, width + 1, height + 1,
1295  height + 1);
1296 
1297  /* Get the total count in the sliding window. If the window
1298  * fully covers the peak, this will be the integrated
1299  * volume under the peak. */
1300  pixw = pixWindowedMean(pixh, width, height, 1, 0);
1301  pixDestroy(&pixh);
1302 
1303  /* Sequentially identify and erase peaks in the histogram.
1304  * If requested for debugging, save a pixa of the sequence of
1305  * false color histograms. */
1306  if (ppixa)
1307  *ppixa = pixaCreate(0);
1308  for (i = 0; i < npeaks; i++) {
1309  pixGetMaxValueInRect(pixw, NULL, &maxval, &xmax, &ymax);
1310  if (maxval == 0) break;
1311  numaAddNumber(natot, maxval);
1312  ptaAddPt(pta, xmax, ymax);
1313  ewidth = (l_int32)(width * erasefactor);
1314  eheight = (l_int32)(height * erasefactor);
1315  box = boxCreate(xmax - ewidth, ymax - eheight, 2 * ewidth + 1,
1316  2 * eheight + 1);
1317 
1318  if (ppixa) {
1319  pix1 = pixMaxDynamicRange(pixw, L_LINEAR_SCALE);
1320  pixaAddPix(*ppixa, pix1, L_INSERT);
1321  pix2 = pixConvertGrayToFalseColor(pix1, 1.0);
1322  pixaAddPix(*ppixa, pix2, L_INSERT);
1323  pix1 = pixMaxDynamicRange(pixw, L_LOG_SCALE);
1324  pix2 = pixConvertGrayToFalseColor(pix1, 1.0);
1325  pixaAddPix(*ppixa, pix2, L_INSERT);
1326  pix3 = pixConvertTo32(pix1);
1327  pixRenderHashBoxArb(pix3, box, 6, 2, L_NEG_SLOPE_LINE,
1328  1, 255, 100, 100);
1329  pixaAddPix(*ppixa, pix3, L_INSERT);
1330  pixDestroy(&pix1);
1331  }
1332 
1333  pixClearInRect(pixw, box);
1334  boxDestroy(&box);
1335  if (type == L_HS_HISTO || type == L_HV_HISTO) {
1336  /* clear wraps at bottom and top */
1337  if (ymax - eheight < 0) { /* overlap to bottom */
1338  box = boxCreate(xmax - ewidth, 240 + ymax - eheight,
1339  2 * ewidth + 1, eheight - ymax);
1340  } else if (ymax + eheight > 239) { /* overlap to top */
1341  box = boxCreate(xmax - ewidth, 0, 2 * ewidth + 1,
1342  ymax + eheight - 239);
1343  } else {
1344  box = NULL;
1345  }
1346  if (box) {
1347  pixClearInRect(pixw, box);
1348  boxDestroy(&box);
1349  }
1350  }
1351  }
1352 
1353  pixDestroy(&pixw);
1354  return 0;
1355 }
1356 
1357 
1377 PIX *
1379  l_int32 sval,
1380  l_int32 vval,
1381  l_int32 huehw,
1382  l_int32 sathw,
1383  l_int32 nsamp,
1384  l_int32 factor)
1385 {
1386 l_int32 i, j, w, huedelta, satdelta, hue, sat, rval, gval, bval;
1387 PIX *pixt, *pixd;
1388 
1389  PROCNAME("displayHSVColorRange");
1390 
1391  if (hval < 0 || hval > 240)
1392  return (PIX *)ERROR_PTR("invalid hval", procName, NULL);
1393  if (huehw < 5 || huehw > 120)
1394  return (PIX *)ERROR_PTR("invalid huehw", procName, NULL);
1395  if (sval - sathw < 0 || sval + sathw > 255)
1396  return (PIX *)ERROR_PTR("invalid sval/sathw", procName, NULL);
1397  if (nsamp < 1 || factor < 3)
1398  return (PIX *)ERROR_PTR("invalid nsamp or rep. factor", procName, NULL);
1399  if (vval < 0 || vval > 255)
1400  return (PIX *)ERROR_PTR("invalid vval", procName, NULL);
1401 
1402  w = (2 * nsamp + 1);
1403  huedelta = (l_int32)((l_float32)huehw / (l_float32)nsamp);
1404  satdelta = (l_int32)((l_float32)sathw / (l_float32)nsamp);
1405  pixt = pixCreate(w, w, 32);
1406  for (i = 0; i < w; i++) {
1407  hue = hval + huedelta * (i - nsamp);
1408  if (hue < 0) hue += 240;
1409  if (hue >= 240) hue -= 240;
1410  for (j = 0; j < w; j++) {
1411  sat = sval + satdelta * (j - nsamp);
1412  convertHSVToRGB(hue, sat, vval, &rval, &gval, &bval);
1413  pixSetRGBPixel(pixt, j, i, rval, gval, bval);
1414  }
1415  }
1416 
1417  pixd = pixExpandReplicate(pixt, factor);
1418  pixDestroy(&pixt);
1419  return pixd;
1420 }
1421 
1422 
1423 /*---------------------------------------------------------------------------*
1424  * Colorspace conversion between RGB and YUV *
1425  *---------------------------------------------------------------------------*/
1453 PIX *
1455  PIX *pixs)
1456 {
1457 l_int32 w, h, d, wpl, i, j, rval, gval, bval, yval, uval, vval;
1458 l_uint32 *line, *data;
1459 PIXCMAP *cmap;
1460 
1461  PROCNAME("pixConvertRGBToYUV");
1462 
1463  if (!pixs)
1464  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1465  if (pixd && pixd != pixs)
1466  return (PIX *)ERROR_PTR("pixd defined and not inplace", procName, pixd);
1467 
1468  d = pixGetDepth(pixs);
1469  cmap = pixGetColormap(pixs);
1470  if (!cmap && d != 32)
1471  return (PIX *)ERROR_PTR("not cmapped or rgb", procName, pixd);
1472 
1473  if (!pixd)
1474  pixd = pixCopy(NULL, pixs);
1475 
1476  cmap = pixGetColormap(pixd);
1477  if (cmap) { /* just convert the colormap */
1478  pixcmapConvertRGBToYUV(cmap);
1479  return pixd;
1480  }
1481 
1482  /* Convert RGB image */
1483  pixGetDimensions(pixd, &w, &h, NULL);
1484  wpl = pixGetWpl(pixd);
1485  data = pixGetData(pixd);
1486  for (i = 0; i < h; i++) {
1487  line = data + i * wpl;
1488  for (j = 0; j < w; j++) {
1489  extractRGBValues(line[j], &rval, &gval, &bval);
1490  convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval);
1491  line[j] = (yval << 24) | (uval << 16) | (vval << 8);
1492  }
1493  }
1494 
1495  return pixd;
1496 }
1497 
1498 
1516 PIX *
1518  PIX *pixs)
1519 {
1520 l_int32 w, h, d, wpl, i, j, rval, gval, bval, yval, uval, vval;
1521 l_uint32 pixel;
1522 l_uint32 *line, *data;
1523 PIXCMAP *cmap;
1524 
1525  PROCNAME("pixConvertYUVToRGB");
1526 
1527  if (!pixs)
1528  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1529  if (pixd && pixd != pixs)
1530  return (PIX *)ERROR_PTR("pixd defined and not inplace", procName, pixd);
1531 
1532  d = pixGetDepth(pixs);
1533  cmap = pixGetColormap(pixs);
1534  if (!cmap && d != 32)
1535  return (PIX *)ERROR_PTR("not cmapped or hsv", procName, pixd);
1536 
1537  if (!pixd)
1538  pixd = pixCopy(NULL, pixs);
1539 
1540  cmap = pixGetColormap(pixd);
1541  if (cmap) { /* just convert the colormap */
1542  pixcmapConvertYUVToRGB(cmap);
1543  return pixd;
1544  }
1545 
1546  /* Convert YUV image */
1547  pixGetDimensions(pixd, &w, &h, NULL);
1548  wpl = pixGetWpl(pixd);
1549  data = pixGetData(pixd);
1550  for (i = 0; i < h; i++) {
1551  line = data + i * wpl;
1552  for (j = 0; j < w; j++) {
1553  pixel = line[j];
1554  yval = pixel >> 24;
1555  uval = (pixel >> 16) & 0xff;
1556  vval = (pixel >> 8) & 0xff;
1557  convertYUVToRGB(yval, uval, vval, &rval, &gval, &bval);
1558  composeRGBPixel(rval, gval, bval, line + j);
1559  }
1560  }
1561 
1562  return pixd;
1563 }
1564 
1565 
1581 l_ok
1582 convertRGBToYUV(l_int32 rval,
1583  l_int32 gval,
1584  l_int32 bval,
1585  l_int32 *pyval,
1586  l_int32 *puval,
1587  l_int32 *pvval)
1588 {
1589 l_float32 norm;
1590 
1591  PROCNAME("convertRGBToYUV");
1592 
1593  if (pyval) *pyval = 0;
1594  if (puval) *puval = 0;
1595  if (pvval) *pvval = 0;
1596  if (!pyval || !puval || !pvval)
1597  return ERROR_INT("&yval, &uval, &vval not all defined", procName, 1);
1598 
1599  norm = 1.0 / 256.;
1600  *pyval = (l_int32)(16.0 +
1601  norm * (65.738 * rval + 129.057 * gval + 25.064 * bval) + 0.5);
1602  *puval = (l_int32)(128.0 +
1603  norm * (-37.945 * rval -74.494 * gval + 112.439 * bval) + 0.5);
1604  *pvval = (l_int32)(128.0 +
1605  norm * (112.439 * rval - 94.154 * gval - 18.285 * bval) + 0.5);
1606  return 0;
1607 }
1608 
1609 
1629 l_ok
1630 convertYUVToRGB(l_int32 yval,
1631  l_int32 uval,
1632  l_int32 vval,
1633  l_int32 *prval,
1634  l_int32 *pgval,
1635  l_int32 *pbval)
1636 {
1637 l_int32 rval, gval, bval;
1638 l_float32 norm, ym, um, vm;
1639 
1640  PROCNAME("convertYUVToRGB");
1641 
1642  if (prval) *prval = 0;
1643  if (pgval) *pgval = 0;
1644  if (pbval) *pbval = 0;
1645  if (!prval || !pgval || !pbval)
1646  return ERROR_INT("&rval, &gval, &bval not all defined", procName, 1);
1647 
1648  norm = 1.0 / 256.;
1649  ym = yval - 16.0;
1650  um = uval - 128.0;
1651  vm = vval - 128.0;
1652  rval = (l_int32)(norm * (298.082 * ym + 408.583 * vm) + 0.5);
1653  gval = (l_int32)(norm * (298.082 * ym - 100.291 * um - 208.120 * vm) +
1654  0.5);
1655  bval = (l_int32)(norm * (298.082 * ym + 516.411 * um) + 0.5);
1656  *prval = L_MIN(255, L_MAX(0, rval));
1657  *pgval = L_MIN(255, L_MAX(0, gval));
1658  *pbval = L_MIN(255, L_MAX(0, bval));
1659 
1660  return 0;
1661 }
1662 
1663 
1677 l_ok
1679 {
1680 l_int32 i, ncolors, rval, gval, bval, yval, uval, vval;
1681 
1682  PROCNAME("pixcmapConvertRGBToYUV");
1683 
1684  if (!cmap)
1685  return ERROR_INT("cmap not defined", procName, 1);
1686 
1687  ncolors = pixcmapGetCount(cmap);
1688  for (i = 0; i < ncolors; i++) {
1689  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
1690  convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval);
1691  pixcmapResetColor(cmap, i, yval, uval, vval);
1692  }
1693  return 0;
1694 }
1695 
1696 
1710 l_ok
1712 {
1713 l_int32 i, ncolors, rval, gval, bval, yval, uval, vval;
1714 
1715  PROCNAME("pixcmapConvertYUVToRGB");
1716 
1717  if (!cmap)
1718  return ERROR_INT("cmap not defined", procName, 1);
1719 
1720  ncolors = pixcmapGetCount(cmap);
1721  for (i = 0; i < ncolors; i++) {
1722  pixcmapGetColor(cmap, i, &yval, &uval, &vval);
1723  convertYUVToRGB(yval, uval, vval, &rval, &gval, &bval);
1724  pixcmapResetColor(cmap, i, rval, gval, bval);
1725  }
1726  return 0;
1727 }
1728 
1729 
1730 /*---------------------------------------------------------------------------*
1731  * Colorspace conversion between RGB and XYZ *
1732  *---------------------------------------------------------------------------*/
1761 FPIXA *
1763 {
1764 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
1765 l_uint32 *lines, *datas;
1766 l_float32 fxval, fyval, fzval;
1767 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
1768 FPIX *fpix;
1769 FPIXA *fpixa;
1770 
1771  PROCNAME("pixConvertRGBToXYZ");
1772 
1773  if (!pixs || pixGetDepth(pixs) != 32)
1774  return (FPIXA *)ERROR_PTR("pixs undefined or not rgb", procName, NULL);
1775 
1776  /* Convert RGB image */
1777  pixGetDimensions(pixs, &w, &h, NULL);
1778  fpixa = fpixaCreate(3);
1779  for (i = 0; i < 3; i++) {
1780  fpix = fpixCreate(w, h);
1781  fpixaAddFPix(fpixa, fpix, L_INSERT);
1782  }
1783  wpls = pixGetWpl(pixs);
1784  wpld = fpixGetWpl(fpix);
1785  datas = pixGetData(pixs);
1786  datax = fpixaGetData(fpixa, 0);
1787  datay = fpixaGetData(fpixa, 1);
1788  dataz = fpixaGetData(fpixa, 2);
1789  for (i = 0; i < h; i++) {
1790  lines = datas + i * wpls;
1791  linex = datax + i * wpld;
1792  liney = datay + i * wpld;
1793  linez = dataz + i * wpld;
1794  for (j = 0; j < w; j++) {
1795  extractRGBValues(lines[j], &rval, &gval, &bval);
1796  convertRGBToXYZ(rval, gval, bval, &fxval, &fyval, &fzval);
1797  *(linex + j) = fxval;
1798  *(liney + j) = fyval;
1799  *(linez + j) = fzval;
1800  }
1801  }
1802 
1803  return fpixa;
1804 }
1805 
1806 
1820 PIX *
1822 {
1823 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
1824 l_float32 fxval, fyval, fzval;
1825 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
1826 l_uint32 *lined, *datad;
1827 PIX *pixd;
1828 FPIX *fpix;
1829 
1830  PROCNAME("fpixaConvertXYZToRGB");
1831 
1832  if (!fpixa || fpixaGetCount(fpixa) != 3)
1833  return (PIX *)ERROR_PTR("fpixa undefined or invalid", procName, NULL);
1834 
1835  /* Convert XYZ image */
1836  if (fpixaGetFPixDimensions(fpixa, 0, &w, &h))
1837  return (PIX *)ERROR_PTR("fpixa dimensions not found", procName, NULL);
1838  pixd = pixCreate(w, h, 32);
1839  wpld = pixGetWpl(pixd);
1840  datad = pixGetData(pixd);
1841  datax = fpixaGetData(fpixa, 0);
1842  datay = fpixaGetData(fpixa, 1);
1843  dataz = fpixaGetData(fpixa, 2);
1844  fpix = fpixaGetFPix(fpixa, 0, L_CLONE);
1845  wpls = fpixGetWpl(fpix);
1846  fpixDestroy(&fpix);
1847  for (i = 0; i < h; i++) {
1848  linex = datax + i * wpls;
1849  liney = datay + i * wpls;
1850  linez = dataz + i * wpls;
1851  lined = datad + i * wpld;
1852  for (j = 0; j < w; j++) {
1853  fxval = linex[j];
1854  fyval = liney[j];
1855  fzval = linez[j];
1856  convertXYZToRGB(fxval, fyval, fzval, 0, &rval, &gval, &bval);
1857  composeRGBPixel(rval, gval, bval, lined + j);
1858  }
1859  }
1860 
1861  return pixd;
1862 }
1863 
1864 
1878 l_ok
1879 convertRGBToXYZ(l_int32 rval,
1880  l_int32 gval,
1881  l_int32 bval,
1882  l_float32 *pfxval,
1883  l_float32 *pfyval,
1884  l_float32 *pfzval)
1885 {
1886  PROCNAME("convertRGBToXYZ");
1887 
1888  if (pfxval) *pfxval = 0.0;
1889  if (pfyval) *pfyval = 0.0;
1890  if (pfzval) *pfzval = 0.0;
1891  if (!pfxval || !pfyval || !pfzval)
1892  return ERROR_INT("&xval, &yval, &zval not all defined", procName, 1);
1893 
1894  *pfxval = 0.4125 * rval + 0.3576 * gval + 0.1804 * bval;
1895  *pfyval = 0.2127 * rval + 0.7152 * gval + 0.0722 * bval;
1896  *pfzval = 0.0193 * rval + 0.1192 * gval + 0.9502 * bval;
1897  return 0;
1898 }
1899 
1900 
1920 l_ok
1921 convertXYZToRGB(l_float32 fxval,
1922  l_float32 fyval,
1923  l_float32 fzval,
1924  l_int32 blackout,
1925  l_int32 *prval,
1926  l_int32 *pgval,
1927  l_int32 *pbval)
1928 {
1929 l_int32 rval, gval, bval;
1930 
1931  PROCNAME("convertXYZToRGB");
1932 
1933  if (prval) *prval = 0;
1934  if (pgval) *pgval = 0;
1935  if (pbval) *pbval = 0;
1936  if (!prval || !pgval ||!pbval)
1937  return ERROR_INT("&rval, &gval, &bval not all defined", procName, 1);
1938  *prval = *pgval = *pbval = 0;
1939 
1940  rval = (l_int32)(3.2405 * fxval - 1.5372 * fyval - 0.4985 * fzval + 0.5);
1941  gval = (l_int32)(-0.9693 * fxval + 1.8760 * fyval + 0.0416 * fzval + 0.5);
1942  bval = (l_int32)(0.0556 * fxval - 0.2040 * fyval + 1.0573 * fzval + 0.5);
1943  if (blackout == 0) { /* the usual situation; use nearest rgb color */
1944  *prval = L_MAX(0, L_MIN(rval, 255));
1945  *pgval = L_MAX(0, L_MIN(gval, 255));
1946  *pbval = L_MAX(0, L_MIN(bval, 255));
1947  } else { /* use black for out of gamut */
1948  if (rval >= 0 && rval < 256 && gval >= 0 && gval < 256 &&
1949  bval >= 0 && bval < 256) { /* in gamut */
1950  *prval = rval;
1951  *pgval = gval;
1952  *pbval = bval;
1953  }
1954  }
1955  return 0;
1956 }
1957 
1958 
1959 /*---------------------------------------------------------------------------*
1960  * Colorspace conversion between XYZ and LAB *
1961  *---------------------------------------------------------------------------*/
1981 FPIXA *
1983 {
1984 l_int32 w, h, wpl, i, j;
1985 l_float32 fxval, fyval, fzval, flval, faval, fbval;
1986 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
1987 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
1988 FPIX *fpix;
1989 FPIXA *fpixad;
1990 
1991  PROCNAME("fpixaConvertXYZToLAB");
1992 
1993  if (!fpixas || fpixaGetCount(fpixas) != 3)
1994  return (FPIXA *)ERROR_PTR("fpixas undefined/invalid", procName, NULL);
1995 
1996  /* Convert XYZ image */
1997  if (fpixaGetFPixDimensions(fpixas, 0, &w, &h))
1998  return (FPIXA *)ERROR_PTR("fpixas sizes not found", procName, NULL);
1999  fpixad = fpixaCreate(3);
2000  for (i = 0; i < 3; i++) {
2001  fpix = fpixCreate(w, h);
2002  fpixaAddFPix(fpixad, fpix, L_INSERT);
2003  }
2004  wpl = fpixGetWpl(fpix);
2005  datax = fpixaGetData(fpixas, 0);
2006  datay = fpixaGetData(fpixas, 1);
2007  dataz = fpixaGetData(fpixas, 2);
2008  datal = fpixaGetData(fpixad, 0);
2009  dataa = fpixaGetData(fpixad, 1);
2010  datab = fpixaGetData(fpixad, 2);
2011 
2012  /* Convert XYZ image */
2013  for (i = 0; i < h; i++) {
2014  linex = datax + i * wpl;
2015  liney = datay + i * wpl;
2016  linez = dataz + i * wpl;
2017  linel = datal + i * wpl;
2018  linea = dataa + i * wpl;
2019  lineb = datab + i * wpl;
2020  for (j = 0; j < w; j++) {
2021  fxval = *(linex + j);
2022  fyval = *(liney + j);
2023  fzval = *(linez + j);
2024  convertXYZToLAB(fxval, fyval, fzval, &flval, &faval, &fbval);
2025  *(linel + j) = flval;
2026  *(linea + j) = faval;
2027  *(lineb + j) = fbval;
2028  }
2029  }
2030 
2031  return fpixad;
2032 }
2033 
2034 
2047 FPIXA *
2049 {
2050 l_int32 w, h, wpl, i, j;
2051 l_float32 fxval, fyval, fzval, flval, faval, fbval;
2052 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
2053 l_float32 *linex, *liney, *linez, *datax, *datay, *dataz;
2054 FPIX *fpix;
2055 FPIXA *fpixad;
2056 
2057  PROCNAME("fpixaConvertLABToXYZ");
2058 
2059  if (!fpixas || fpixaGetCount(fpixas) != 3)
2060  return (FPIXA *)ERROR_PTR("fpixas undefined/invalid", procName, NULL);
2061 
2062  /* Convert LAB image */
2063  if (fpixaGetFPixDimensions(fpixas, 0, &w, &h))
2064  return (FPIXA *)ERROR_PTR("fpixas sizes not found", procName, NULL);
2065  fpixad = fpixaCreate(3);
2066  for (i = 0; i < 3; i++) {
2067  fpix = fpixCreate(w, h);
2068  fpixaAddFPix(fpixad, fpix, L_INSERT);
2069  }
2070  wpl = fpixGetWpl(fpix);
2071  datal = fpixaGetData(fpixas, 0);
2072  dataa = fpixaGetData(fpixas, 1);
2073  datab = fpixaGetData(fpixas, 2);
2074  datax = fpixaGetData(fpixad, 0);
2075  datay = fpixaGetData(fpixad, 1);
2076  dataz = fpixaGetData(fpixad, 2);
2077 
2078  /* Convert XYZ image */
2079  for (i = 0; i < h; i++) {
2080  linel = datal + i * wpl;
2081  linea = dataa + i * wpl;
2082  lineb = datab + i * wpl;
2083  linex = datax + i * wpl;
2084  liney = datay + i * wpl;
2085  linez = dataz + i * wpl;
2086  for (j = 0; j < w; j++) {
2087  flval = *(linel + j);
2088  faval = *(linea + j);
2089  fbval = *(lineb + j);
2090  convertLABToXYZ(flval, faval, fbval, &fxval, &fyval, &fzval);
2091  *(linex + j) = fxval;
2092  *(liney + j) = fyval;
2093  *(linez + j) = fzval;
2094  }
2095  }
2096 
2097  return fpixad;
2098 }
2099 
2100 
2108 l_ok
2109 convertXYZToLAB(l_float32 xval,
2110  l_float32 yval,
2111  l_float32 zval,
2112  l_float32 *plval,
2113  l_float32 *paval,
2114  l_float32 *pbval)
2115 {
2116 l_float32 xn, yn, zn, fx, fy, fz;
2117 
2118  PROCNAME("convertXYZToLAB");
2119 
2120  if (plval) *plval = 0.0;
2121  if (paval) *paval = 0.0;
2122  if (pbval) *pbval = 0.0;
2123  if (!plval || !paval || !pbval)
2124  return ERROR_INT("&lval, &aval, &bval not all defined", procName, 1);
2125 
2126  /* First normalize to the corresponding white values */
2127  xn = 0.0041259 * xval;
2128  yn = 0.0039216 * yval;
2129  zn = 0.0036012 * zval;
2130  /* Then apply the lab_forward function */
2131  fx = lab_forward(xn);
2132  fy = lab_forward(yn);
2133  fz = lab_forward(zn);
2134  *plval = 116.0 * fy - 16.0;
2135  *paval = 500.0 * (fx - fy);
2136  *pbval = 200.0 * (fy - fz);
2137  return 0;
2138 }
2139 
2140 
2148 l_ok
2149 convertLABToXYZ(l_float32 lval,
2150  l_float32 aval,
2151  l_float32 bval,
2152  l_float32 *pxval,
2153  l_float32 *pyval,
2154  l_float32 *pzval)
2155 {
2156 l_float32 fx, fy, fz;
2157 l_float32 xw = 242.37; /* x component corresponding to rgb white */
2158 l_float32 yw = 255.0; /* y component corresponding to rgb white */
2159 l_float32 zw = 277.69; /* z component corresponding to rgb white */
2160 
2161  PROCNAME("convertLABToXYZ");
2162 
2163  if (pxval) *pxval = 0.0;
2164  if (pyval) *pyval = 0.0;
2165  if (pzval) *pzval = 0.0;
2166  if (!pxval || !pyval || !pzval)
2167  return ERROR_INT("&xval, &yval, &zval not all defined", procName, 1);
2168 
2169  fy = 0.0086207 * (16.0 + lval);
2170  fx = fy + 0.002 * aval;
2171  fz = fy - 0.005 * bval;
2172  *pxval = xw * lab_reverse(fx);
2173  *pyval = yw * lab_reverse(fy);
2174  *pzval = zw * lab_reverse(fz);
2175  return 0;
2176 }
2177 
2178 
2179 /*
2180  * See http://en.wikipedia.org/wiki/Lab_color_space for formulas.
2181  * This is the forward function: from xyz to lab. It includes a rational
2182  * function approximation over [0.008856 ... 1] to the cube root, from
2183  * "Fast Color Space Transformations Using Minimax Approximations",
2184  * M. Celebi et al, http://arxiv.org/pdf/1009.0854v1.pdf.
2185  */
2186 static l_float32
2187 lab_forward(l_float32 v)
2188 {
2189 const l_float32 f_thresh = 0.008856; /* (6/29)^3 */
2190 const l_float32 f_factor = 7.787; /* (1/3) * (29/6)^2) */
2191 const l_float32 f_offset = 0.13793; /* 4/29 */
2192 
2193  if (v > f_thresh) {
2194 #if SLOW_CUBE_ROOT
2195  return powf(v, 0.333333);
2196 #else
2197  l_float32 num, den;
2198  num = 4.37089e-04 + v * (9.52695e-02 + v * (1.25201 + v * 1.30273));
2199  den = 3.91236e-03 + v * (2.95408e-01 + v * (1.71714 + v * 6.34341e-01));
2200  return num / den;
2201 #endif
2202  } else {
2203  return f_factor * v + f_offset;
2204  }
2205 }
2206 
2207 
2208 /*
2209  * See http://en.wikipedia.org/wiki/Lab_color_space for formulas.
2210  * This is the reverse (inverse) function: from lab to xyz.
2211  */
2212 static l_float32
2213 lab_reverse(l_float32 v)
2214 {
2215 const l_float32 r_thresh = 0.20690; /* 6/29 */
2216 const l_float32 r_factor = 0.12842; /* 3 * (6/29)^2 */
2217 const l_float32 r_offset = 0.13793; /* 4/29 */
2218 
2219  if (v > r_thresh) {
2220  return v * v * v;
2221  } else {
2222  return r_factor * (v - r_offset);
2223  }
2224 }
2225 
2226 
2227 /*---------------------------------------------------------------------------*
2228  * Colorspace conversion between RGB and LAB *
2229  *---------------------------------------------------------------------------*/
2242 FPIXA *
2244 {
2245 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
2246 l_uint32 *lines, *datas;
2247 l_float32 flval, faval, fbval;
2248 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
2249 FPIX *fpix;
2250 FPIXA *fpixa;
2251 
2252  PROCNAME("pixConvertRGBToLAB");
2253 
2254  if (!pixs || pixGetDepth(pixs) != 32)
2255  return (FPIXA *)ERROR_PTR("pixs undefined or not rgb", procName, NULL);
2256 
2257  /* Convert RGB image */
2258  pixGetDimensions(pixs, &w, &h, NULL);
2259  fpixa = fpixaCreate(3);
2260  for (i = 0; i < 3; i++) {
2261  fpix = fpixCreate(w, h);
2262  fpixaAddFPix(fpixa, fpix, L_INSERT);
2263  }
2264  wpls = pixGetWpl(pixs);
2265  wpld = fpixGetWpl(fpix);
2266  datas = pixGetData(pixs);
2267  datal = fpixaGetData(fpixa, 0);
2268  dataa = fpixaGetData(fpixa, 1);
2269  datab = fpixaGetData(fpixa, 2);
2270  for (i = 0; i < h; i++) {
2271  lines = datas + i * wpls;
2272  linel = datal + i * wpld;
2273  linea = dataa + i * wpld;
2274  lineb = datab + i * wpld;
2275  for (j = 0; j < w; j++) {
2276  extractRGBValues(lines[j], &rval, &gval, &bval);
2277  convertRGBToLAB(rval, gval, bval, &flval, &faval, &fbval);
2278  *(linel + j) = flval;
2279  *(linea + j) = faval;
2280  *(lineb + j) = fbval;
2281  }
2282  }
2283 
2284  return fpixa;
2285 }
2286 
2287 
2299 PIX *
2301 {
2302 l_int32 w, h, wpls, wpld, i, j, rval, gval, bval;
2303 l_float32 flval, faval, fbval;
2304 l_float32 *linel, *linea, *lineb, *datal, *dataa, *datab;
2305 l_uint32 *lined, *datad;
2306 PIX *pixd;
2307 FPIX *fpix;
2308 
2309  PROCNAME("fpixaConvertLABToRGB");
2310 
2311  if (!fpixa || fpixaGetCount(fpixa) != 3)
2312  return (PIX *)ERROR_PTR("fpixa undefined or invalid", procName, NULL);
2313 
2314  /* Convert LAB image */
2315  if (fpixaGetFPixDimensions(fpixa, 0, &w, &h))
2316  return (PIX *)ERROR_PTR("fpixa dimensions not found", procName, NULL);
2317  pixd = pixCreate(w, h, 32);
2318  wpld = pixGetWpl(pixd);
2319  datad = pixGetData(pixd);
2320  datal = fpixaGetData(fpixa, 0);
2321  dataa = fpixaGetData(fpixa, 1);
2322  datab = fpixaGetData(fpixa, 2);
2323  fpix = fpixaGetFPix(fpixa, 0, L_CLONE);
2324  wpls = fpixGetWpl(fpix);
2325  fpixDestroy(&fpix);
2326  for (i = 0; i < h; i++) {
2327  linel = datal + i * wpls;
2328  linea = dataa + i * wpls;
2329  lineb = datab + i * wpls;
2330  lined = datad + i * wpld;
2331  for (j = 0; j < w; j++) {
2332  flval = linel[j];
2333  faval = linea[j];
2334  fbval = lineb[j];
2335  convertLABToRGB(flval, faval, fbval, &rval, &gval, &bval);
2336  composeRGBPixel(rval, gval, bval, lined + j);
2337  }
2338  }
2339 
2340  return pixd;
2341 }
2342 
2343 
2357 l_ok
2358 convertRGBToLAB(l_int32 rval,
2359  l_int32 gval,
2360  l_int32 bval,
2361  l_float32 *pflval,
2362  l_float32 *pfaval,
2363  l_float32 *pfbval)
2364 {
2365 l_float32 fxval, fyval, fzval;
2366 
2367  PROCNAME("convertRGBToLAB");
2368 
2369  if (pflval) *pflval = 0.0;
2370  if (pfaval) *pfaval = 0.0;
2371  if (pfbval) *pfbval = 0.0;
2372  if (!pflval || !pfaval || !pfbval)
2373  return ERROR_INT("&flval, &faval, &fbval not all defined", procName, 1);
2374 
2375  convertRGBToXYZ(rval, gval, bval, &fxval, &fyval, &fzval);
2376  convertXYZToLAB(fxval, fyval, fzval, pflval, pfaval, pfbval);
2377  return 0;
2378 }
2379 
2380 
2394 l_ok
2395 convertLABToRGB(l_float32 flval,
2396  l_float32 faval,
2397  l_float32 fbval,
2398  l_int32 *prval,
2399  l_int32 *pgval,
2400  l_int32 *pbval)
2401 {
2402 l_float32 fxval, fyval, fzval;
2403 
2404  PROCNAME("convertLABToRGB");
2405 
2406  if (prval) *prval = 0;
2407  if (pgval) *pgval = 0;
2408  if (pbval) *pbval = 0;
2409  if (!prval || !pgval || !pbval)
2410  return ERROR_INT("&rval, &gval, &bval not all defined", procName, 1);
2411 
2412  convertLABToXYZ(flval, faval, fbval, &fxval, &fyval, &fzval);
2413  convertXYZToRGB(fxval, fyval, fzval, 0, prval, pgval, pbval);
2414  return 0;
2415 }
l_ok pixSetRGBPixel(PIX *pix, l_int32 x, l_int32 y, l_int32 rval, l_int32 gval, l_int32 bval)
pixSetRGBPixel()
Definition: pix2.c:368
PIX * pixAddMixedBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixAddMixedBorder()
Definition: pix2.c:2135
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
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:2149
Definition: pix.h:717
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:1582
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3233
PIX * pixMakeRangeMaskSV(PIX *pixs, l_int32 satcenter, l_int32 sathw, l_int32 valcenter, l_int32 valhw, l_int32 regionflag)
pixMakeRangeMaskSV()
Definition: colorspace.c:899
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:342
PIX * pixWindowedMean(PIX *pixs, l_int32 wc, l_int32 hc, l_int32 hasborder, l_int32 normflag)
pixWindowedMean()
Definition: convolve.c:1065
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
PIX * pixConvertRGBToHue(PIX *pixs)
pixConvertRGBToHue()
Definition: colorspace.c:492
l_int32 fpixaGetCount(FPIXA *fpixa)
fpixaGetCount()
Definition: fpix1.c:942
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:163
PIX * pixMaxDynamicRange(PIX *pixs, l_int32 type)
pixMaxDynamicRange()
Definition: pixarith.c:1155
PIX * pixConvertYUVToRGB(PIX *pixd, PIX *pixs)
pixConvertYUVToRGB()
Definition: colorspace.c:1517
FPIXA * fpixaConvertLABToXYZ(FPIXA *fpixas)
fpixaConvertLABToXYZ()
Definition: colorspace.c:2048
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:116
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1810
#define GET_DATA_FOUR_BYTES(pdata, n)
Definition: arrayaccess.h:231
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:741
PIX * pixAddMirroredBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixAddMirroredBorder()
Definition: pix2.c:2026
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
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:1879
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
l_ok numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
Definition: numabasic.c:658
PIX * pixScaleBySampling(PIX *pixs, l_float32 scalex, l_float32 scaley)
pixScaleBySampling()
Definition: scale1.c:1338
Definition: pix.h:597
FPIXA * fpixaCreate(l_int32 n)
fpixaCreate()
Definition: fpix1.c:714
PIX * fpixaConvertLABToRGB(FPIXA *fpixa)
fpixaConvertLABToRGB()
Definition: colorspace.c:2300
l_ok pixClearInRect(PIX *pix, BOX *box)
pixClearInRect()
Definition: pix2.c:1043
PIX * pixMakeHistoSV(PIX *pixs, l_int32 factor, NUMA **pnasat, NUMA **pnaval)
pixMakeHistoSV()
Definition: colorspace.c:1162
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:2395
l_ok fpixaGetFPixDimensions(FPIXA *fpixa, l_int32 index, l_int32 *pw, l_int32 *ph)
fpixaGetFPixDimensions()
Definition: fpix1.c:1012
#define CLEAR_DATA_BIT(pdata, n)
Definition: arrayaccess.h:131
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:503
Definition: array.h:59
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:2109
FPIXA * pixConvertRGBToXYZ(PIX *pixs)
pixConvertRGBToXYZ()
Definition: colorspace.c:1762
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:335
l_ok pixClearAll(PIX *pix)
pixClearAll()
Definition: pix2.c:712
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:751
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
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:1253
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:459
FPIXA * pixConvertRGBToLAB(PIX *pixs)
pixConvertRGBToLAB()
Definition: colorspace.c:2243
l_float32 * fpixaGetData(FPIXA *fpixa, l_int32 index)
fpixaGetData()
Definition: fpix1.c:1046
PIX * pixCreateNoInit(l_int32 width, l_int32 height, l_int32 depth)
pixCreateNoInit()
Definition: pix1.c:331
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
PIX * pixMakeRangeMaskHV(PIX *pixs, l_int32 huecenter, l_int32 huehw, l_int32 valcenter, l_int32 valhw, l_int32 regionflag)
pixMakeRangeMaskHV()
Definition: colorspace.c:801
PIX * pixMakeHistoHV(PIX *pixs, l_int32 factor, NUMA **pnahue, NUMA **pnaval)
pixMakeHistoHV()
Definition: colorspace.c:1079
PIX * pixConvertHSVToRGB(PIX *pixd, PIX *pixs)
pixConvertHSVToRGB()
Definition: colorspace.c:198
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
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:1630
PIX * pixMakeHistoHS(PIX *pixs, l_int32 factor, NUMA **pnahue, NUMA **pnasat)
pixMakeHistoHS()
Definition: colorspace.c:988
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:1378
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:273
l_ok numaShiftValue(NUMA *na, l_int32 index, l_float32 diff)
numaShiftValue()
Definition: numabasic.c:784
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:893
PIX * pixConvertRGBToYUV(PIX *pixd, PIX *pixs)
pixConvertRGBToYUV()
Definition: colorspace.c:1454
Definition: pix.h:454
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:1921
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
PIX * pixMakeRangeMaskHS(PIX *pixs, l_int32 huecenter, l_int32 huehw, l_int32 satcenter, l_int32 sathw, l_int32 regionflag)
pixMakeRangeMaskHS()
Definition: colorspace.c:702
PIX * pixConvertGrayToFalseColor(PIX *pixs, l_float32 gamma)
pixConvertGrayToFalseColor()
Definition: pixconv.c:1786
l_ok pixcmapConvertHSVToRGB(PIXCMAP *cmap)
pixcmapConvertHSVToRGB()
Definition: colorspace.c:457
#define SET_DATA_FOUR_BYTES(pdata, n, val)
Definition: arrayaccess.h:235
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:1893
PIX * pixExpandReplicate(PIX *pixs, l_int32 factor)
pixExpandReplicate()
Definition: scale2.c:867
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:153
PIX * pixConvertRGBToSaturation(PIX *pixs)
pixConvertRGBToSaturation()
Definition: colorspace.c:568
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:635
Definition: pix.h:134
Definition: pix.h:719
l_ok pixGetMaxValueInRect(PIX *pixs, BOX *box, l_uint32 *pmaxval, l_int32 *pxmax, l_int32 *pymax)
pixGetMaxValueInRect()
Definition: pix4.c:2278
l_ok pixcmapConvertRGBToYUV(PIXCMAP *cmap)
pixcmapConvertRGBToYUV()
Definition: colorspace.c:1678
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
PIX * pixConvertRGBToValue(PIX *pixs)
pixConvertRGBToValue()
Definition: colorspace.c:633
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
FPIXA * fpixaConvertXYZToLAB(FPIXA *fpixas)
fpixaConvertXYZToLAB()
Definition: colorspace.c:1982
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:2358
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
l_ok pixcmapConvertRGBToHSV(PIXCMAP *cmap)
pixcmapConvertRGBToHSV()
Definition: colorspace.c:424
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:373
Definition: pix.h:480
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2737
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
PIX * fpixaConvertXYZToRGB(FPIXA *fpixa)
fpixaConvertXYZToRGB()
Definition: colorspace.c:1821
FPIX * fpixaGetFPix(FPIXA *fpixa, l_int32 index, l_int32 accesstype)
fpixaGetFPix()
Definition: fpix1.c:983
l_ok fpixaAddFPix(FPIXA *fpixa, FPIX *fpix, l_int32 copyflag)
fpixaAddFPix()
Definition: fpix1.c:842
Definition: pix.h:517
Definition: pix.h:582
PIX * pixConvertRGBToHSV(PIX *pixd, PIX *pixs)
pixConvertRGBToHSV()
Definition: colorspace.c:134
l_ok pixcmapConvertYUVToRGB(PIXCMAP *cmap)
pixcmapConvertYUVToRGB()
Definition: colorspace.c:1711