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