Leptonica  1.77.0
Image processing and image analysis suite
coloring.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 
92 #include "allheaders.h"
93 
94 
95 /*---------------------------------------------------------------------*
96  * Coloring "gray" pixels *
97  *---------------------------------------------------------------------*/
125 PIX *
127  BOXA *boxa,
128  l_int32 type,
129  l_int32 thresh,
130  l_int32 rval,
131  l_int32 gval,
132  l_int32 bval)
133 {
134 l_int32 i, n, ncolors, ngray;
135 BOX *box;
136 PIX *pixd;
137 PIXCMAP *cmap;
138 
139  PROCNAME("pixColorGrayRegions");
140 
141  if (!pixs || pixGetDepth(pixs) == 1)
142  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
143  if (!boxa)
144  return (PIX *)ERROR_PTR("boxa not defined", procName, NULL);
145  if (type != L_PAINT_LIGHT && type != L_PAINT_DARK)
146  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
147 
148  /* If cmapped and there is room in an 8 bpp colormap for
149  * expansion, convert pixs to 8 bpp, and colorize. */
150  cmap = pixGetColormap(pixs);
151  if (cmap) {
152  ncolors = pixcmapGetCount(cmap);
153  pixcmapCountGrayColors(cmap, &ngray);
154  if (ncolors + ngray < 255) {
155  pixd = pixConvertTo8(pixs, 1); /* always new image */
156  pixColorGrayRegionsCmap(pixd, boxa, type, rval, gval, bval);
157  return pixd;
158  }
159  }
160 
161  /* The output will be rgb. Make sure the thresholds are valid */
162  if (type == L_PAINT_LIGHT) { /* thresh should be low */
163  if (thresh >= 255)
164  return (PIX *)ERROR_PTR("thresh must be < 255", procName, NULL);
165  if (thresh > 127)
166  L_WARNING("threshold set very high\n", procName);
167  } else { /* type == L_PAINT_DARK; thresh should be high */
168  if (thresh <= 0)
169  return (PIX *)ERROR_PTR("thresh must be > 0", procName, NULL);
170  if (thresh < 128)
171  L_WARNING("threshold set very low\n", procName);
172  }
173 
174  pixd = pixConvertTo32(pixs); /* always new image */
175  n = boxaGetCount(boxa);
176  for (i = 0; i < n; i++) {
177  box = boxaGetBox(boxa, i, L_CLONE);
178  pixColorGray(pixd, box, type, thresh, rval, gval, bval);
179  boxDestroy(&box);
180  }
181 
182  return pixd;
183 }
184 
185 
226 l_ok
228  BOX *box,
229  l_int32 type,
230  l_int32 thresh,
231  l_int32 rval,
232  l_int32 gval,
233  l_int32 bval)
234 {
235 l_int32 i, j, w, h, d, wpl, x1, x2, y1, y2, bw, bh;
236 l_int32 nrval, ngval, nbval, aveval;
237 l_float32 factor;
238 l_uint32 val32;
239 l_uint32 *line, *data;
240 PIX *pixt;
241 PIXCMAP *cmap;
242 
243  PROCNAME("pixColorGray");
244 
245  if (!pixs)
246  return ERROR_INT("pixs not defined", procName, 1);
247  if (type != L_PAINT_LIGHT && type != L_PAINT_DARK)
248  return ERROR_INT("invalid type", procName, 1);
249 
250  cmap = pixGetColormap(pixs);
251  pixGetDimensions(pixs, &w, &h, &d);
252  if (!cmap && d != 8 && d != 32)
253  return ERROR_INT("pixs not cmapped, 8 bpp or rgb", procName, 1);
254  if (cmap)
255  return pixColorGrayCmap(pixs, box, type, rval, gval, bval);
256 
257  /* rgb or 8 bpp gray image; check the thresh */
258  if (type == L_PAINT_LIGHT) { /* thresh should be low */
259  if (thresh >= 255)
260  return ERROR_INT("thresh must be < 255; else this is a no-op",
261  procName, 1);
262  if (thresh > 127)
263  L_WARNING("threshold set very high\n", procName);
264  } else { /* type == L_PAINT_DARK; thresh should be high */
265  if (thresh <= 0)
266  return ERROR_INT("thresh must be > 0; else this is a no-op",
267  procName, 1);
268  if (thresh < 128)
269  L_WARNING("threshold set very low\n", procName);
270  }
271 
272  /* In-place conversion to 32 bpp if necessary */
273  if (d == 8) {
274  pixt = pixConvertTo32(pixs);
275  pixTransferAllData(pixs, &pixt, 1, 0);
276  }
277 
278  if (!box) {
279  x1 = y1 = 0;
280  x2 = w;
281  y2 = h;
282  } else {
283  boxGetGeometry(box, &x1, &y1, &bw, &bh);
284  x2 = x1 + bw - 1;
285  y2 = y1 + bh - 1;
286  }
287 
288  data = pixGetData(pixs);
289  wpl = pixGetWpl(pixs);
290  factor = 1. / 255.;
291  for (i = y1; i <= y2; i++) {
292  if (i < 0 || i >= h)
293  continue;
294  line = data + i * wpl;
295  for (j = x1; j <= x2; j++) {
296  if (j < 0 || j >= w)
297  continue;
298  val32 = *(line + j);
299  aveval = ((val32 >> 24) + ((val32 >> 16) & 0xff) +
300  ((val32 >> 8) & 0xff)) / 3;
301  if (type == L_PAINT_LIGHT) {
302  if (aveval < thresh) /* skip sufficiently dark pixels */
303  continue;
304  nrval = (l_int32)(rval * aveval * factor);
305  ngval = (l_int32)(gval * aveval * factor);
306  nbval = (l_int32)(bval * aveval * factor);
307  } else { /* type == L_PAINT_DARK */
308  if (aveval > thresh) /* skip sufficiently light pixels */
309  continue;
310  nrval = rval + (l_int32)((255. - rval) * aveval * factor);
311  ngval = gval + (l_int32)((255. - gval) * aveval * factor);
312  nbval = bval + (l_int32)((255. - bval) * aveval * factor);
313  }
314  composeRGBPixel(nrval, ngval, nbval, &val32);
315  *(line + j) = val32;
316  }
317  }
318 
319  return 0;
320 }
321 
322 
352 PIX *
354  PIX *pixm,
355  l_int32 type,
356  l_int32 thresh,
357  l_int32 rval,
358  l_int32 gval,
359  l_int32 bval)
360 {
361 l_int32 i, j, w, h, d, wm, hm, wmin, hmin, wpl, wplm;
362 l_int32 nrval, ngval, nbval, aveval;
363 l_float32 factor;
364 l_uint32 val32;
365 l_uint32 *line, *data, *linem, *datam;
366 PIX *pixd;
367 PIXCMAP *cmap;
368 
369  PROCNAME("pixColorGrayMasked");
370 
371  if (!pixs)
372  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
373  if (!pixm || pixGetDepth(pixm) != 1)
374  return (PIX *)ERROR_PTR("pixm undefined or not 1 bpp", procName, NULL);
375  if (type != L_PAINT_LIGHT && type != L_PAINT_DARK)
376  return (PIX *)ERROR_PTR("invalid type", procName, NULL);
377 
378  cmap = pixGetColormap(pixs);
379  pixGetDimensions(pixs, &w, &h, &d);
380  if (!cmap && d != 8 && d != 32)
381  return (PIX *)ERROR_PTR("pixs not cmapped, 8 bpp gray or 32 bpp",
382  procName, NULL);
383  if (cmap) {
384  pixd = pixCopy(NULL, pixs);
385  pixColorGrayMaskedCmap(pixd, pixm, type, rval, gval, bval);
386  return pixd;
387  }
388 
389  /* rgb or 8 bpp gray image; check the thresh */
390  if (type == L_PAINT_LIGHT) { /* thresh should be low */
391  if (thresh >= 255)
392  return (PIX *)ERROR_PTR(
393  "thresh must be < 255; else this is a no-op", procName, NULL);
394  if (thresh > 127)
395  L_WARNING("threshold set very high\n", procName);
396  } else { /* type == L_PAINT_DARK; thresh should be high */
397  if (thresh <= 0)
398  return (PIX *)ERROR_PTR(
399  "thresh must be > 0; else this is a no-op", procName, NULL);
400  if (thresh < 128)
401  L_WARNING("threshold set very low\n", procName);
402  }
403 
404  pixGetDimensions(pixm, &wm, &hm, NULL);
405  if (wm != w)
406  L_WARNING("wm = %d differs from w = %d\n", procName, wm, w);
407  if (hm != h)
408  L_WARNING("hm = %d differs from h = %d\n", procName, hm, h);
409  wmin = L_MIN(w, wm);
410  hmin = L_MIN(h, hm);
411  if (d == 8)
412  pixd = pixConvertTo32(pixs);
413  else
414  pixd = pixCopy(NULL, pixs);
415 
416  data = pixGetData(pixd);
417  wpl = pixGetWpl(pixd);
418  datam = pixGetData(pixm);
419  wplm = pixGetWpl(pixm);
420  factor = 1. / 255.;
421  for (i = 0; i < hmin; i++) {
422  line = data + i * wpl;
423  linem = datam + i * wplm;
424  for (j = 0; j < wmin; j++) {
425  if (GET_DATA_BIT(linem, j) == 0)
426  continue;
427  val32 = *(line + j);
428  aveval = ((val32 >> 24) + ((val32 >> 16) & 0xff) +
429  ((val32 >> 8) & 0xff)) / 3;
430  if (type == L_PAINT_LIGHT) {
431  if (aveval < thresh) /* skip sufficiently dark pixels */
432  continue;
433  nrval = (l_int32)(rval * aveval * factor);
434  ngval = (l_int32)(gval * aveval * factor);
435  nbval = (l_int32)(bval * aveval * factor);
436  } else { /* type == L_PAINT_DARK */
437  if (aveval > thresh) /* skip sufficiently light pixels */
438  continue;
439  nrval = rval + (l_int32)((255. - rval) * aveval * factor);
440  ngval = gval + (l_int32)((255. - gval) * aveval * factor);
441  nbval = bval + (l_int32)((255. - bval) * aveval * factor);
442  }
443  composeRGBPixel(nrval, ngval, nbval, &val32);
444  *(line + j) = val32;
445  }
446  }
447 
448  return pixd;
449 }
450 
451 
452 /*------------------------------------------------------------------*
453  * Adjusting one or more colors to a target color *
454  *------------------------------------------------------------------*/
477 PIX *
479  PIX *pixs,
480  l_uint32 srcval,
481  l_uint32 dstval,
482  l_int32 diff)
483 {
484 l_int32 val, sval, dval;
485 l_int32 rval, gval, bval, rsval, gsval, bsval;
486 l_int32 i, j, w, h, d, wpl;
487 l_uint32 pixel;
488 l_uint32 *line, *data;
489 
490  PROCNAME("pixSnapColor");
491 
492  if (!pixs)
493  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
494  if (pixd && (pixd != pixs))
495  return (PIX *)ERROR_PTR("pixd not null or == pixs", procName, pixd);
496 
497  if (pixGetColormap(pixs))
498  return pixSnapColorCmap(pixd, pixs, srcval, dstval, diff);
499 
500  /* pixs does not have a colormap; it must be 8 bpp gray or
501  * 32 bpp rgb. */
502  if (pixGetDepth(pixs) < 8)
503  return (PIX *)ERROR_PTR("pixs is < 8 bpp", procName, pixd);
504 
505  /* Do the work on pixd */
506  if (!pixd)
507  pixd = pixCopy(NULL, pixs);
508 
509  pixGetDimensions(pixd, &w, &h, &d);
510  data = pixGetData(pixd);
511  wpl = pixGetWpl(pixd);
512  if (d == 8) {
513  sval = srcval & 0xff;
514  dval = dstval & 0xff;
515  for (i = 0; i < h; i++) {
516  line = data + i * wpl;
517  for (j = 0; j < w; j++) {
518  val = GET_DATA_BYTE(line, j);
519  if (L_ABS(val - sval) <= diff)
520  SET_DATA_BYTE(line, j, dval);
521  }
522  }
523  } else { /* d == 32 */
524  extractRGBValues(srcval, &rsval, &gsval, &bsval);
525  for (i = 0; i < h; i++) {
526  line = data + i * wpl;
527  for (j = 0; j < w; j++) {
528  pixel = *(line + j);
529  extractRGBValues(pixel, &rval, &gval, &bval);
530  if ((L_ABS(rval - rsval) <= diff) &&
531  (L_ABS(gval - gsval) <= diff) &&
532  (L_ABS(bval - bsval) <= diff))
533  *(line + j) = dstval; /* replace */
534  }
535  }
536  }
537 
538  return pixd;
539 }
540 
541 
564 PIX *
566  PIX *pixs,
567  l_uint32 srcval,
568  l_uint32 dstval,
569  l_int32 diff)
570 {
571 l_int32 i, ncolors, index, found;
572 l_int32 rval, gval, bval, rsval, gsval, bsval, rdval, gdval, bdval;
573 l_int32 *tab;
574 PIX *pixm;
575 PIXCMAP *cmap;
576 
577  PROCNAME("pixSnapColorCmap");
578 
579  if (!pixs)
580  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
581  if (!pixGetColormap(pixs))
582  return (PIX *)ERROR_PTR("cmap not found", procName, pixd);
583  if (pixd && (pixd != pixs))
584  return (PIX *)ERROR_PTR("pixd not null or == pixs", procName, pixd);
585 
586  if (!pixd)
587  pixd = pixCopy(NULL, pixs);
588 
589  /* If no free colors, look for one close to the target
590  * that can be commandeered. */
591  cmap = pixGetColormap(pixd);
592  ncolors = pixcmapGetCount(cmap);
593  extractRGBValues(srcval, &rsval, &gsval, &bsval);
594  extractRGBValues(dstval, &rdval, &gdval, &bdval);
595  found = FALSE;
596  if (pixcmapGetFreeCount(cmap) == 0) {
597  for (i = 0; i < ncolors; i++) {
598  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
599  if ((L_ABS(rval - rsval) <= diff) &&
600  (L_ABS(gval - gsval) <= diff) &&
601  (L_ABS(bval - bsval) <= diff)) {
602  index = i;
603  pixcmapResetColor(cmap, index, rdval, gdval, bdval);
604  found = TRUE;
605  break;
606  }
607  }
608  } else { /* just add the new color */
609  pixcmapAddColor(cmap, rdval, gdval, bdval);
610  ncolors = pixcmapGetCount(cmap);
611  index = ncolors - 1; /* index of new destination color */
612  found = TRUE;
613  }
614 
615  if (!found) {
616  L_INFO("nothing to do\n", procName);
617  return pixd;
618  }
619 
620  /* For each color in cmap that is close enough to srcval,
621  * set the tab value to 1. Then generate a 1 bpp mask with
622  * fg pixels for every pixel in pixd that is close enough
623  * to srcval (i.e., has value 1 in tab). */
624  if ((tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32))) == NULL)
625  return (PIX *)ERROR_PTR("tab not made", procName, pixd);
626  for (i = 0; i < ncolors; i++) {
627  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
628  if ((L_ABS(rval - rsval) <= diff) &&
629  (L_ABS(gval - gsval) <= diff) &&
630  (L_ABS(bval - bsval) <= diff))
631  tab[i] = 1;
632  }
633  pixm = pixMakeMaskFromLUT(pixd, tab);
634  LEPT_FREE(tab);
635 
636  /* Use the binary mask to set all selected pixels to
637  * the dest color index. */
638  pixSetMasked(pixd, pixm, dstval);
639  pixDestroy(&pixm);
640 
641  /* Remove all unused colors from the colormap. */
642  pixRemoveUnusedColors(pixd);
643 
644  return pixd;
645 }
646 
647 
648 /*---------------------------------------------------------------------*
649  * Piecewise linear color mapping based on a source/target pair *
650  *---------------------------------------------------------------------*/
680 PIX *
682  PIX *pixs,
683  l_uint32 srcval,
684  l_uint32 dstval)
685 {
686 l_int32 i, j, w, h, wpl;
687 l_int32 rval, gval, bval, rsval, gsval, bsval, rdval, gdval, bdval;
688 l_int32 *rtab, *gtab, *btab;
689 l_uint32 pixel;
690 l_uint32 *line, *data;
691 
692  PROCNAME("pixLinearMapToTargetColor");
693 
694  if (!pixs)
695  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
696  if (pixd && (pixd != pixs))
697  return (PIX *)ERROR_PTR("pixd not null or == pixs", procName, pixd);
698  if (pixGetDepth(pixs) != 32)
699  return (PIX *)ERROR_PTR("pixs is not 32 bpp", procName, pixd);
700 
701  /* Do the work on pixd */
702  if (!pixd)
703  pixd = pixCopy(NULL, pixs);
704 
705  extractRGBValues(srcval, &rsval, &gsval, &bsval);
706  extractRGBValues(dstval, &rdval, &gdval, &bdval);
707  rsval = L_MIN(254, L_MAX(1, rsval));
708  gsval = L_MIN(254, L_MAX(1, gsval));
709  bsval = L_MIN(254, L_MAX(1, bsval));
710  rtab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
711  gtab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
712  btab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
713  if (!rtab || !gtab || !btab)
714  return (PIX *)ERROR_PTR("calloc fail for tab", procName, pixd);
715  for (i = 0; i < 256; i++) {
716  if (i <= rsval)
717  rtab[i] = (i * rdval) / rsval;
718  else
719  rtab[i] = rdval + ((255 - rdval) * (i - rsval)) / (255 - rsval);
720  if (i <= gsval)
721  gtab[i] = (i * gdval) / gsval;
722  else
723  gtab[i] = gdval + ((255 - gdval) * (i - gsval)) / (255 - gsval);
724  if (i <= bsval)
725  btab[i] = (i * bdval) / bsval;
726  else
727  btab[i] = bdval + ((255 - bdval) * (i - bsval)) / (255 - bsval);
728  }
729  pixGetDimensions(pixd, &w, &h, NULL);
730  data = pixGetData(pixd);
731  wpl = pixGetWpl(pixd);
732  for (i = 0; i < h; i++) {
733  line = data + i * wpl;
734  for (j = 0; j < w; j++) {
735  pixel = line[j];
736  extractRGBValues(pixel, &rval, &gval, &bval);
737  composeRGBPixel(rtab[rval], gtab[gval], btab[bval], &pixel);
738  line[j] = pixel;
739  }
740  }
741 
742  LEPT_FREE(rtab);
743  LEPT_FREE(gtab);
744  LEPT_FREE(btab);
745  return pixd;
746 }
747 
748 
777 l_ok
779  l_uint32 srcmap,
780  l_uint32 dstmap,
781  l_uint32 *pdcolor)
782 {
783 l_int32 srval, sgval, sbval, drval, dgval, dbval;
784 l_int32 srmap, sgmap, sbmap, drmap, dgmap, dbmap;
785 
786  PROCNAME("pixelLinearMapToTargetColor");
787 
788  if (!pdcolor)
789  return ERROR_INT("&dcolor not defined", procName, 1);
790  *pdcolor = 0;
791 
792  extractRGBValues(scolor, &srval, &sgval, &sbval);
793  extractRGBValues(srcmap, &srmap, &sgmap, &sbmap);
794  extractRGBValues(dstmap, &drmap, &dgmap, &dbmap);
795  srmap = L_MIN(254, L_MAX(1, srmap));
796  sgmap = L_MIN(254, L_MAX(1, sgmap));
797  sbmap = L_MIN(254, L_MAX(1, sbmap));
798 
799  if (srval <= srmap)
800  drval = (srval * drmap) / srmap;
801  else
802  drval = drmap + ((255 - drmap) * (srval - srmap)) / (255 - srmap);
803  if (sgval <= sgmap)
804  dgval = (sgval * dgmap) / sgmap;
805  else
806  dgval = dgmap + ((255 - dgmap) * (sgval - sgmap)) / (255 - sgmap);
807  if (sbval <= sbmap)
808  dbval = (sbval * dbmap) / sbmap;
809  else
810  dbval = dbmap + ((255 - dbmap) * (sbval - sbmap)) / (255 - sbmap);
811 
812  composeRGBPixel(drval, dgval, dbval, pdcolor);
813  return 0;
814 }
815 
816 
817 /*------------------------------------------------------------------*
818  * Fractional shift of RGB towards black or white *
819  *------------------------------------------------------------------*/
862 PIX *
864  PIX *pixs,
865  l_uint32 srcval,
866  l_uint32 dstval)
867 {
868 l_int32 i, j, w, h, wpl;
869 l_int32 rval, gval, bval, rsval, gsval, bsval, rdval, gdval, bdval;
870 l_int32 *rtab, *gtab, *btab;
871 l_uint32 pixel;
872 l_uint32 *line, *data;
873 PIXCMAP *cmap;
874 
875  PROCNAME("pixShiftByComponent");
876 
877  if (!pixs)
878  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
879  if (pixd && (pixd != pixs))
880  return (PIX *)ERROR_PTR("pixd not null or == pixs", procName, pixd);
881  if (pixGetDepth(pixs) != 32 && !pixGetColormap(pixs))
882  return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, pixd);
883 
884  /* Do the work on pixd */
885  if (!pixd)
886  pixd = pixCopy(NULL, pixs);
887 
888  /* If colormapped, just modify it */
889  if ((cmap = pixGetColormap(pixd)) != NULL) {
890  pixcmapShiftByComponent(cmap, srcval, dstval);
891  return pixd;
892  }
893 
894  extractRGBValues(srcval, &rsval, &gsval, &bsval);
895  extractRGBValues(dstval, &rdval, &gdval, &bdval);
896  rtab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
897  gtab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
898  btab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
899  if (!rtab || !gtab || !btab) {
900  L_ERROR("calloc fail for tab\n", procName);
901  goto cleanup;
902  }
903  for (i = 0; i < 256; i++) {
904  if (rdval == rsval)
905  rtab[i] = i;
906  else if (rdval < rsval)
907  rtab[i] = (i * rdval) / rsval;
908  else
909  rtab[i] = 255 - (255 - rdval) * (255 - i) / (255 - rsval);
910  if (gdval == gsval)
911  gtab[i] = i;
912  else if (gdval < gsval)
913  gtab[i] = (i * gdval) / gsval;
914  else
915  gtab[i] = 255 - (255 - gdval) * (255 - i) / (255 - gsval);
916  if (bdval == bsval)
917  btab[i] = i;
918  else if (bdval < bsval)
919  btab[i] = (i * bdval) / bsval;
920  else
921  btab[i] = 255 - (255 - bdval) * (255 - i) / (255 - bsval);
922  }
923  pixGetDimensions(pixd, &w, &h, NULL);
924  data = pixGetData(pixd);
925  wpl = pixGetWpl(pixd);
926  for (i = 0; i < h; i++) {
927  line = data + i * wpl;
928  for (j = 0; j < w; j++) {
929  pixel = line[j];
930  extractRGBValues(pixel, &rval, &gval, &bval);
931  composeRGBPixel(rtab[rval], gtab[gval], btab[bval], &pixel);
932  line[j] = pixel;
933  }
934  }
935 
936 cleanup:
937  LEPT_FREE(rtab);
938  LEPT_FREE(gtab);
939  LEPT_FREE(btab);
940  return pixd;
941 }
942 
943 
963 l_ok
965  l_int32 gval,
966  l_int32 bval,
967  l_uint32 srcval,
968  l_uint32 dstval,
969  l_uint32 *ppixel)
970 {
971 l_int32 rsval, rdval, gsval, gdval, bsval, bdval, rs, gs, bs;
972 
973  PROCNAME("pixelShiftByComponent");
974 
975  if (!ppixel)
976  return ERROR_INT("&pixel defined", procName, 1);
977 
978  extractRGBValues(srcval, &rsval, &gsval, &bsval);
979  extractRGBValues(dstval, &rdval, &gdval, &bdval);
980  if (rdval == rsval)
981  rs = rval;
982  else if (rdval < rsval)
983  rs = (rval * rdval) / rsval;
984  else
985  rs = 255 - (255 - rdval) * (255 - rval) / (255 - rsval);
986  if (gdval == gsval)
987  gs = gval;
988  else if (gdval < gsval)
989  gs = (gval * gdval) / gsval;
990  else
991  gs = 255 - (255 - gdval) * (255 - gval) / (255 - gsval);
992  if (bdval == bsval)
993  bs = bval;
994  else if (bdval < bsval)
995  bs = (bval * bdval) / bsval;
996  else
997  bs = 255 - (255 - bdval) * (255 - bval) / (255 - bsval);
998  composeRGBPixel(rs, gs, bs, ppixel);
999  return 0;
1000 }
1001 
1002 
1022 l_ok
1024  l_int32 gval,
1025  l_int32 bval,
1026  l_float32 fraction,
1027  l_uint32 *ppixel)
1028 {
1029 l_int32 nrval, ngval, nbval;
1030 
1031  PROCNAME("pixelFractionalShift");
1032 
1033  if (!ppixel)
1034  return ERROR_INT("&pixel defined", procName, 1);
1035  if (fraction < -1.0 || fraction > 1.0)
1036  return ERROR_INT("fraction not in [-1 ... +1]", procName, 1);
1037 
1038  nrval = (fraction < 0) ? (l_int32)((1.0 + fraction) * rval + 0.5) :
1039  rval + (l_int32)(fraction * (255 - rval) + 0.5);
1040  ngval = (fraction < 0) ? (l_int32)((1.0 + fraction) * gval + 0.5) :
1041  gval + (l_int32)(fraction * (255 - gval) + 0.5);
1042  nbval = (fraction < 0) ? (l_int32)((1.0 + fraction) * bval + 0.5) :
1043  bval + (l_int32)(fraction * (255 - bval) + 0.5);
1044  composeRGBPixel(nrval, ngval, nbval, ppixel);
1045  return 0;
1046 }
l_ok pixcmapCountGrayColors(PIXCMAP *cmap, l_int32 *pngray)
pixcmapCountGrayColors()
Definition: colormap.c:1117
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3233
l_ok pixSetMasked(PIX *pixd, PIX *pixm, l_uint32 val)
pixSetMasked()
Definition: pix3.c:155
l_ok pixelFractionalShift(l_int32 rval, l_int32 gval, l_int32 bval, l_float32 fraction, l_uint32 *ppixel)
pixelFractionalShift()
Definition: coloring.c:1023
l_int32 n
Definition: ccbord.h:111
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3041
PIX * pixSnapColorCmap(PIX *pixd, PIX *pixs, l_uint32 srcval, l_uint32 dstval, l_int32 diff)
pixSnapColorCmap()
Definition: coloring.c:565
l_ok pixColorGray(PIX *pixs, BOX *box, l_int32 type, l_int32 thresh, l_int32 rval, l_int32 gval, l_int32 bval)
pixColorGray()
Definition: coloring.c:227
PIX * pixLinearMapToTargetColor(PIX *pixd, PIX *pixs, l_uint32 srcval, l_uint32 dstval)
pixLinearMapToTargetColor()
Definition: coloring.c:681
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
l_ok pixColorGrayCmap(PIX *pixs, BOX *box, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval)
pixColorGrayCmap()
Definition: paintcmap.c:327
Definition: pix.h:492
l_ok pixelShiftByComponent(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 srcval, l_uint32 dstval, l_uint32 *ppixel)
pixelShiftByComponent()
Definition: coloring.c:964
l_ok pixColorGrayMaskedCmap(PIX *pixs, PIX *pixm, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval)
pixColorGrayMaskedCmap()
Definition: paintcmap.c:395
PIX * pixSnapColor(PIX *pixd, PIX *pixs, l_uint32 srcval, l_uint32 dstval, l_int32 diff)
pixSnapColor()
Definition: coloring.c:478
l_ok pixColorGrayRegionsCmap(PIX *pixs, BOXA *boxa, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval)
pixColorGrayRegionsCmap()
Definition: paintcmap.c:219
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 pixelLinearMapToTargetColor(l_uint32 scolor, l_uint32 srcmap, l_uint32 dstmap, l_uint32 *pdcolor)
pixelLinearMapToTargetColor()
Definition: coloring.c:778
PIX * pixColorGrayMasked(PIX *pixs, PIX *pixm, l_int32 type, l_int32 thresh, l_int32 rval, l_int32 gval, l_int32 bval)
pixColorGrayMasked()
Definition: coloring.c:353
l_int32 h
Definition: ccbord.h:110
PIX * pixShiftByComponent(PIX *pixd, PIX *pixs, l_uint32 srcval, l_uint32 dstval)
pixShiftByComponent()
Definition: coloring.c:863
l_int32 w
Definition: ccbord.h:109
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
l_int32 pixcmapGetFreeCount(PIXCMAP *cmap)
pixcmapGetFreeCount()
Definition: colormap.c:652
l_ok pixcmapShiftByComponent(PIXCMAP *cmap, l_uint32 srcval, l_uint32 dstval)
pixcmapShiftByComponent()
Definition: colormap.c:2280
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:763
l_ok pixcmapResetColor(PIXCMAP *cmap, l_int32 index, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapResetColor()
Definition: colormap.c:893
PIX * pixColorGrayRegions(PIX *pixs, BOXA *boxa, l_int32 type, l_int32 thresh, l_int32 rval, l_int32 gval, l_int32 bval)
pixColorGrayRegions()
Definition: coloring.c:126
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
PIX * pixMakeMaskFromLUT(PIX *pixs, l_int32 *tab)
pixMakeMaskFromLUT()
Definition: pix3.c:1000
l_ok pixRemoveUnusedColors(PIX *pixs)
pixRemoveUnusedColors()
Definition: colorquant1.c:3944
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:635
Definition: pix.h:134
Definition: pix.h:719
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:718
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
l_ok pixTransferAllData(PIX *pixd, PIX **ppixs, l_int32 copytext, l_int32 copyformat)
pixTransferAllData()
Definition: pix1.c:855
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:341
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:310
Definition: pix.h:480
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2737