Leptonica 1.82.0
Image processing and image analysis suite
enhance.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
118#ifdef HAVE_CONFIG_H
119#include <config_auto.h>
120#endif /* HAVE_CONFIG_H */
121
122#include <math.h>
123#include "allheaders.h"
124
125 /* Scales contrast enhancement factor to have a useful range
126 * between 0.0 and 1.0 */
127static const l_float32 EnhanceScaleFactor = 5.0;
128
129/*-------------------------------------------------------------*
130 * Gamma TRC (tone reproduction curve) mapping *
131 *-------------------------------------------------------------*/
175PIX *
177 PIX *pixs,
178 l_float32 gamma,
179 l_int32 minval,
180 l_int32 maxval)
181{
182l_int32 d;
183NUMA *nag;
184PIXCMAP *cmap;
185
186 PROCNAME("pixGammaTRC");
187
188 if (!pixs)
189 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
190 if (pixd && (pixd != pixs))
191 return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
192 if (gamma <= 0.0) {
193 L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
194 gamma = 1.0;
195 }
196 if (minval >= maxval)
197 return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
198 cmap = pixGetColormap(pixs);
199 d = pixGetDepth(pixs);
200 if (!cmap && d != 8 && d != 32)
201 return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
202
203 if (gamma == 1.0 && minval == 0 && maxval == 255) /* no-op */
204 return pixCopy(pixd, pixs);
205
206 if (!pixd) /* start with a copy if not in-place */
207 pixd = pixCopy(NULL, pixs);
208
209 if (cmap) {
210 pixcmapGammaTRC(pixGetColormap(pixd), gamma, minval, maxval);
211 return pixd;
212 }
213
214 /* pixd is 8 or 32 bpp */
215 if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
216 return (PIX *)ERROR_PTR("nag not made", procName, pixd);
217 pixTRCMap(pixd, NULL, nag);
218 numaDestroy(&nag);
219
220 return pixd;
221}
222
223
243PIX *
245 PIX *pixs,
246 PIX *pixm,
247 l_float32 gamma,
248 l_int32 minval,
249 l_int32 maxval)
250{
251l_int32 d;
252NUMA *nag;
253
254 PROCNAME("pixGammaTRCMasked");
255
256 if (!pixm)
257 return pixGammaTRC(pixd, pixs, gamma, minval, maxval);
258
259 if (!pixs)
260 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
261 if (pixGetColormap(pixs))
262 return (PIX *)ERROR_PTR("invalid: pixs has a colormap", procName, pixd);
263 if (pixd && (pixd != pixs))
264 return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
265 d = pixGetDepth(pixs);
266 if (d != 8 && d != 32)
267 return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
268 if (minval >= maxval)
269 return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
270 if (gamma <= 0.0) {
271 L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
272 gamma = 1.0;
273 }
274
275 if (gamma == 1.0 && minval == 0 && maxval == 255)
276 return pixCopy(pixd, pixs);
277
278 if (!pixd) /* start with a copy if not in-place */
279 pixd = pixCopy(NULL, pixs);
280
281 if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
282 return (PIX *)ERROR_PTR("nag not made", procName, pixd);
283 pixTRCMap(pixd, pixm, nag);
284 numaDestroy(&nag);
285
286 return pixd;
287}
288
289
307PIX *
309 PIX *pixs,
310 l_float32 gamma,
311 l_int32 minval,
312 l_int32 maxval)
313{
314NUMA *nag;
315PIX *pixalpha;
316
317 PROCNAME("pixGammaTRCWithAlpha");
318
319 if (!pixs || pixGetDepth(pixs) != 32)
320 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, pixd);
321 if (pixd && (pixd != pixs))
322 return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
323 if (gamma <= 0.0) {
324 L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
325 gamma = 1.0;
326 }
327 if (minval >= maxval)
328 return (PIX *)ERROR_PTR("minval not < maxval", procName, pixd);
329
330 if (gamma == 1.0 && minval == 0 && maxval == 255)
331 return pixCopy(pixd, pixs);
332 if (!pixd) /* start with a copy if not in-place */
333 pixd = pixCopy(NULL, pixs);
334
335 pixalpha = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL); /* save */
336 if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL)
337 return (PIX *)ERROR_PTR("nag not made", procName, pixd);
338 pixTRCMap(pixd, NULL, nag);
339 pixSetRGBComponent(pixd, pixalpha, L_ALPHA_CHANNEL); /* restore */
340 pixSetSpp(pixd, 4);
341
342 numaDestroy(&nag);
343 pixDestroy(&pixalpha);
344 return pixd;
345}
346
347
368NUMA *
369numaGammaTRC(l_float32 gamma,
370 l_int32 minval,
371 l_int32 maxval)
372{
373l_int32 i, val;
374l_float32 x, invgamma;
375NUMA *na;
376
377 PROCNAME("numaGammaTRC");
378
379 if (minval >= maxval)
380 return (NUMA *)ERROR_PTR("minval not < maxval", procName, NULL);
381 if (gamma <= 0.0) {
382 L_WARNING("gamma must be > 0.0; setting to 1.0\n", procName);
383 gamma = 1.0;
384 }
385
386 invgamma = 1. / gamma;
387 na = numaCreate(256);
388 for (i = 0; i < minval; i++)
389 numaAddNumber(na, 0);
390 for (i = minval; i <= maxval; i++) {
391 if (i < 0) continue;
392 if (i > 255) continue;
393 x = (l_float32)(i - minval) / (l_float32)(maxval - minval);
394 val = (l_int32)(255. * powf(x, invgamma) + 0.5);
395 val = L_MAX(val, 0);
396 val = L_MIN(val, 255);
397 numaAddNumber(na, val);
398 }
399 for (i = maxval + 1; i < 256; i++)
400 numaAddNumber(na, 255);
401
402 return na;
403}
404
405
406/*-------------------------------------------------------------*
407 * Contrast enhancement *
408 *-------------------------------------------------------------*/
438PIX *
440 PIX *pixs,
441 l_float32 factor)
442{
443l_int32 d;
444NUMA *nac;
445PIXCMAP *cmap;
446
447 PROCNAME("pixContrastTRC");
448
449 if (!pixs)
450 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
451 if (pixd && (pixd != pixs))
452 return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
453 if (factor < 0.0) {
454 L_WARNING("factor must be >= 0.0; using 0.0\n", procName);
455 factor = 0.0;
456 }
457 if (factor == 0.0)
458 return pixCopy(pixd, pixs);
459
460 cmap = pixGetColormap(pixs);
461 d = pixGetDepth(pixs);
462 if (!cmap && d != 8 && d != 32)
463 return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
464
465 if (!pixd) /* start with a copy if not in-place */
466 pixd = pixCopy(NULL, pixs);
467
468 if (cmap) {
469 pixcmapContrastTRC(pixGetColormap(pixd), factor);
470 return pixd;
471 }
472
473 /* pixd is 8 or 32 bpp */
474 if ((nac = numaContrastTRC(factor)) == NULL)
475 return (PIX *)ERROR_PTR("nac not made", procName, pixd);
476 pixTRCMap(pixd, NULL, nac);
477 numaDestroy(&nac);
478
479 return pixd;
480}
481
482
500PIX *
502 PIX *pixs,
503 PIX *pixm,
504 l_float32 factor)
505{
506l_int32 d;
507NUMA *nac;
508
509 PROCNAME("pixContrastTRCMasked");
510
511 if (!pixm)
512 return pixContrastTRC(pixd, pixs, factor);
513
514 if (!pixs)
515 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
516 if (pixGetColormap(pixs))
517 return (PIX *)ERROR_PTR("invalid: pixs has a colormap", procName, pixd);
518 if (pixd && (pixd != pixs))
519 return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
520 d = pixGetDepth(pixs);
521 if (d != 8 && d != 32)
522 return (PIX *)ERROR_PTR("depth not 8 or 32 bpp", procName, pixd);
523
524 if (factor < 0.0) {
525 L_WARNING("factor must be >= 0.0; using 0.0\n", procName);
526 factor = 0.0;
527 }
528 if (factor == 0.0)
529 return pixCopy(pixd, pixs);
530
531 if (!pixd) /* start with a copy if not in-place */
532 pixd = pixCopy(NULL, pixs);
533
534 if ((nac = numaContrastTRC(factor)) == NULL)
535 return (PIX *)ERROR_PTR("nac not made", procName, pixd);
536 pixTRCMap(pixd, pixm, nac);
537 numaDestroy(&nac);
538
539 return pixd;
540}
541
542
559NUMA *
560numaContrastTRC(l_float32 factor)
561{
562l_int32 i, val;
563l_float64 x, ymax, ymin, dely, scale;
564NUMA *na;
565
566 PROCNAME("numaContrastTRC");
567
568 if (factor < 0.0) {
569 L_WARNING("factor must be >= 0.0; using 0.0; no enhancement\n",
570 procName);
571 factor = 0.0;
572 }
573 if (factor == 0.0)
574 return numaMakeSequence(0, 1, 256); /* linear map */
575
576 scale = EnhanceScaleFactor;
577 ymax = atan((l_float64)(1.0 * factor * scale));
578 ymin = atan((l_float64)(-127. * factor * scale / 128.));
579 dely = ymax - ymin;
580 na = numaCreate(256);
581 for (i = 0; i < 256; i++) {
582 x = (l_float64)i;
583 val = (l_int32)((255. / dely) *
584 (-ymin + atan((l_float64)(factor * scale * (x - 127.) / 128.))) +
585 0.5);
586 numaAddNumber(na, val);
587 }
588
589 return na;
590}
591
592
593/*-------------------------------------------------------------*
594 * Histogram equalization *
595 *-------------------------------------------------------------*/
629PIX *
631 PIX *pixs,
632 l_float32 fract,
633 l_int32 factor)
634{
635l_int32 d;
636NUMA *na;
637PIX *pixt, *pix8;
638PIXCMAP *cmap;
639
640 PROCNAME("pixEqualizeTRC");
641
642 if (!pixs)
643 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
644 if (pixd && (pixd != pixs))
645 return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
646 cmap = pixGetColormap(pixs);
647 d = pixGetDepth(pixs);
648 if (d != 8 && d != 32 && !cmap)
649 return (PIX *)ERROR_PTR("pixs not 8/32 bpp or cmapped", procName, NULL);
650 if (fract < 0.0 || fract > 1.0)
651 return (PIX *)ERROR_PTR("fract not in [0.0 ... 1.0]", procName, NULL);
652 if (factor < 1)
653 return (PIX *)ERROR_PTR("sampling factor < 1", procName, NULL);
654
655 if (fract == 0.0)
656 return pixCopy(pixd, pixs);
657
658 /* If there is a colormap, remove it. */
659 if (cmap)
661 else
662 pixt = pixClone(pixs);
663
664 /* Make a copy if necessary */
665 pixd = pixCopy(pixd, pixt);
666 pixDestroy(&pixt);
667
668 d = pixGetDepth(pixd);
669 if (d == 8) {
670 na = numaEqualizeTRC(pixd, fract, factor);
671 pixTRCMap(pixd, NULL, na);
672 numaDestroy(&na);
673 } else { /* 32 bpp */
674 pix8 = pixGetRGBComponent(pixd, COLOR_RED);
675 na = numaEqualizeTRC(pix8, fract, factor);
676 pixTRCMap(pix8, NULL, na);
677 pixSetRGBComponent(pixd, pix8, COLOR_RED);
678 numaDestroy(&na);
679 pixDestroy(&pix8);
680 pix8 = pixGetRGBComponent(pixd, COLOR_GREEN);
681 na = numaEqualizeTRC(pix8, fract, factor);
682 pixTRCMap(pix8, NULL, na);
683 pixSetRGBComponent(pixd, pix8, COLOR_GREEN);
684 numaDestroy(&na);
685 pixDestroy(&pix8);
686 pix8 = pixGetRGBComponent(pixd, COLOR_BLUE);
687 na = numaEqualizeTRC(pix8, fract, factor);
688 pixTRCMap(pix8, NULL, na);
689 pixSetRGBComponent(pixd, pix8, COLOR_BLUE);
690 numaDestroy(&na);
691 pixDestroy(&pix8);
692 }
693
694 return pixd;
695}
696
697
716NUMA *
718 l_float32 fract,
719 l_int32 factor)
720{
721l_int32 iin, iout, itarg;
722l_float32 val, sum;
723NUMA *nah, *nasum, *nad;
724
725 PROCNAME("numaEqualizeTRC");
726
727 if (!pix)
728 return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
729 if (pixGetDepth(pix) != 8)
730 return (NUMA *)ERROR_PTR("pix not 8 bpp", procName, NULL);
731 if (fract < 0.0 || fract > 1.0)
732 return (NUMA *)ERROR_PTR("fract not in [0.0 ... 1.0]", procName, NULL);
733 if (factor < 1)
734 return (NUMA *)ERROR_PTR("sampling factor < 1", procName, NULL);
735
736 if (fract == 0.0)
737 L_WARNING("fract = 0.0; no equalization requested\n", procName);
738
739 if ((nah = pixGetGrayHistogram(pix, factor)) == NULL)
740 return (NUMA *)ERROR_PTR("histogram not made", procName, NULL);
741 numaGetSum(nah, &sum);
742 nasum = numaGetPartialSums(nah);
743
744 nad = numaCreate(256);
745 for (iin = 0; iin < 256; iin++) {
746 numaGetFValue(nasum, iin, &val);
747 itarg = (l_int32)(255. * val / sum + 0.5);
748 iout = iin + (l_int32)(fract * (itarg - iin));
749 iout = L_MIN(iout, 255); /* to be safe */
750 numaAddNumber(nad, iout);
751 }
752
753 numaDestroy(&nah);
754 numaDestroy(&nasum);
755 return nad;
756}
757
758
759/*-------------------------------------------------------------*
760 * Generic TRC mapping *
761 *-------------------------------------------------------------*/
783l_int32
785 PIX *pixm,
786 NUMA *na)
787{
788l_int32 w, h, d, wm, hm, wpl, wplm, i, j, sval8, dval8;
789l_uint32 sval32, dval32;
790l_uint32 *data, *datam, *line, *linem, *tab;
791
792 PROCNAME("pixTRCMap");
793
794 if (!pixs)
795 return ERROR_INT("pixs not defined", procName, 1);
796 if (pixGetColormap(pixs))
797 return ERROR_INT("pixs is colormapped", procName, 1);
798 if (!na)
799 return ERROR_INT("na not defined", procName, 1);
800 if (numaGetCount(na) != 256)
801 return ERROR_INT("na not of size 256", procName, 1);
802 pixGetDimensions(pixs, &w, &h, &d);
803 if (d != 8 && d != 32)
804 return ERROR_INT("pixs not 8 or 32 bpp", procName, 1);
805 if (pixm) {
806 if (pixGetDepth(pixm) != 1)
807 return ERROR_INT("pixm not 1 bpp", procName, 1);
808 }
809
810 tab = (l_uint32 *)numaGetIArray(na); /* get the array for efficiency */
811 wpl = pixGetWpl(pixs);
812 data = pixGetData(pixs);
813 if (!pixm) {
814 if (d == 8) {
815 for (i = 0; i < h; i++) {
816 line = data + i * wpl;
817 for (j = 0; j < w; j++) {
818 sval8 = GET_DATA_BYTE(line, j);
819 dval8 = tab[sval8];
820 SET_DATA_BYTE(line, j, dval8);
821 }
822 }
823 } else { /* d == 32 */
824 for (i = 0; i < h; i++) {
825 line = data + i * wpl;
826 for (j = 0; j < w; j++) {
827 sval32 = *(line + j);
828 dval32 =
829 tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
830 tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
831 tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
832 *(line + j) = dval32;
833 }
834 }
835 }
836 } else {
837 datam = pixGetData(pixm);
838 wplm = pixGetWpl(pixm);
839 pixGetDimensions(pixm, &wm, &hm, NULL);
840 if (d == 8) {
841 for (i = 0; i < h; i++) {
842 if (i >= hm)
843 break;
844 line = data + i * wpl;
845 linem = datam + i * wplm;
846 for (j = 0; j < w; j++) {
847 if (j >= wm)
848 break;
849 if (GET_DATA_BIT(linem, j) == 0)
850 continue;
851 sval8 = GET_DATA_BYTE(line, j);
852 dval8 = tab[sval8];
853 SET_DATA_BYTE(line, j, dval8);
854 }
855 }
856 } else { /* d == 32 */
857 for (i = 0; i < h; i++) {
858 if (i >= hm)
859 break;
860 line = data + i * wpl;
861 linem = datam + i * wplm;
862 for (j = 0; j < w; j++) {
863 if (j >= wm)
864 break;
865 if (GET_DATA_BIT(linem, j) == 0)
866 continue;
867 sval32 = *(line + j);
868 dval32 =
869 tab[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
870 tab[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
871 tab[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
872 *(line + j) = dval32;
873 }
874 }
875 }
876 }
877
878 LEPT_FREE(tab);
879 return 0;
880}
881
882
905l_int32
907 PIX *pixm,
908 NUMA *nar,
909 NUMA *nag,
910 NUMA *nab)
911{
912l_int32 w, h, wm, hm, wpl, wplm, i, j;
913l_uint32 sval32, dval32;
914l_uint32 *data, *datam, *line, *linem, *tabr, *tabg, *tabb;
915
916 PROCNAME("pixTRCMapGeneral");
917
918 if (!pixs || pixGetDepth(pixs) != 32)
919 return ERROR_INT("pixs not defined or not 32 bpp", procName, 1);
920 if (pixm && pixGetDepth(pixm) != 1)
921 return ERROR_INT("pixm defined and not 1 bpp", procName, 1);
922 if (!nar || !nag || !nab)
923 return ERROR_INT("na{r,g,b} not all defined", procName, 1);
924 if (numaGetCount(nar) != 256 || numaGetCount(nag) != 256 ||
925 numaGetCount(nab) != 256)
926 return ERROR_INT("na{r,g,b} not all of size 256", procName, 1);
927
928 /* Get the arrays for efficiency */
929 tabr = (l_uint32 *)numaGetIArray(nar);
930 tabg = (l_uint32 *)numaGetIArray(nag);
931 tabb = (l_uint32 *)numaGetIArray(nab);
932 pixGetDimensions(pixs, &w, &h, NULL);
933 wpl = pixGetWpl(pixs);
934 data = pixGetData(pixs);
935 if (!pixm) {
936 for (i = 0; i < h; i++) {
937 line = data + i * wpl;
938 for (j = 0; j < w; j++) {
939 sval32 = *(line + j);
940 dval32 =
941 tabr[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
942 tabg[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
943 tabb[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
944 *(line + j) = dval32;
945 }
946 }
947 } else {
948 datam = pixGetData(pixm);
949 wplm = pixGetWpl(pixm);
950 pixGetDimensions(pixm, &wm, &hm, NULL);
951 for (i = 0; i < h; i++) {
952 if (i >= hm)
953 break;
954 line = data + i * wpl;
955 linem = datam + i * wplm;
956 for (j = 0; j < w; j++) {
957 if (j >= wm)
958 break;
959 if (GET_DATA_BIT(linem, j) == 0)
960 continue;
961 sval32 = *(line + j);
962 dval32 =
963 tabr[(sval32 >> L_RED_SHIFT) & 0xff] << L_RED_SHIFT |
964 tabg[(sval32 >> L_GREEN_SHIFT) & 0xff] << L_GREEN_SHIFT |
965 tabb[(sval32 >> L_BLUE_SHIFT) & 0xff] << L_BLUE_SHIFT;
966 *(line + j) = dval32;
967 }
968 }
969 }
970
971 LEPT_FREE(tabr);
972 LEPT_FREE(tabg);
973 LEPT_FREE(tabb);
974 return 0;
975}
976
977
978
979/*-----------------------------------------------------------------------*
980 * Unsharp masking *
981 *-----------------------------------------------------------------------*/
1000PIX *
1002 l_int32 halfwidth,
1003 l_float32 fract)
1004{
1005l_int32 d;
1006PIX *pix1, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
1007
1008 PROCNAME("pixUnsharpMasking");
1009
1010 if (!pixs || (pixGetDepth(pixs) == 1))
1011 return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", procName, NULL);
1012 if (fract <= 0.0 || halfwidth <= 0) {
1013 L_WARNING("no sharpening requested; clone returned\n", procName);
1014 return pixClone(pixs);
1015 }
1016
1017 if (halfwidth == 1 || halfwidth == 2)
1018 return pixUnsharpMaskingFast(pixs, halfwidth, fract, L_BOTH_DIRECTIONS);
1019
1020 /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
1021 if ((pix1 = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
1022 return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1023
1024 /* Sharpen */
1025 d = pixGetDepth(pix1);
1026 if (d == 8) {
1027 pixd = pixUnsharpMaskingGray(pix1, halfwidth, fract);
1028 } else { /* d == 32 */
1029 pixr = pixGetRGBComponent(pix1, COLOR_RED);
1030 pixrs = pixUnsharpMaskingGray(pixr, halfwidth, fract);
1031 pixDestroy(&pixr);
1032 pixg = pixGetRGBComponent(pix1, COLOR_GREEN);
1033 pixgs = pixUnsharpMaskingGray(pixg, halfwidth, fract);
1034 pixDestroy(&pixg);
1035 pixb = pixGetRGBComponent(pix1, COLOR_BLUE);
1036 pixbs = pixUnsharpMaskingGray(pixb, halfwidth, fract);
1037 pixDestroy(&pixb);
1038 pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
1039 pixDestroy(&pixrs);
1040 pixDestroy(&pixgs);
1041 pixDestroy(&pixbs);
1042 if (pixGetSpp(pixs) == 4)
1044 }
1045
1046 pixDestroy(&pix1);
1047 return pixd;
1048}
1049
1050
1069PIX *
1071 l_int32 halfwidth,
1072 l_float32 fract)
1073{
1074l_int32 w, h, d;
1075PIX *pixc, *pixd;
1076PIXACC *pixacc;
1077
1078 PROCNAME("pixUnsharpMaskingGray");
1079
1080 if (!pixs)
1081 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1082 pixGetDimensions(pixs, &w, &h, &d);
1083 if (d != 8 || pixGetColormap(pixs) != NULL)
1084 return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1085 if (fract <= 0.0 || halfwidth <= 0) {
1086 L_WARNING("no sharpening requested; clone returned\n", procName);
1087 return pixClone(pixs);
1088 }
1089 if (halfwidth == 1 || halfwidth == 2)
1090 return pixUnsharpMaskingGrayFast(pixs, halfwidth, fract,
1091 L_BOTH_DIRECTIONS);
1092
1093 if ((pixc = pixBlockconvGray(pixs, NULL, halfwidth, halfwidth)) == NULL)
1094 return (PIX *)ERROR_PTR("pixc not made", procName, NULL);
1095
1096 /* Steps:
1097 * (1) edge image is pixs - pixc (this is highpass part)
1098 * (2) multiply edge image by fract
1099 * (3) add fraction of edge to pixs
1100 *
1101 * To show how this is done with both interfaces to arithmetic
1102 * on integer Pix, here is the implementation in the lower-level
1103 * function calls:
1104 * pixt = pixInitAccumulate(w, h, 0x10000000)) == NULL)
1105 * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1106 * pixAccumulate(pixt, pixc, L_ARITH_SUBTRACT);
1107 * pixMultConstAccumulate(pixt, fract, 0x10000000);
1108 * pixAccumulate(pixt, pixs, L_ARITH_ADD);
1109 * pixd = pixFinalAccumulate(pixt, 0x10000000, 8)) == NULL)
1110 * pixDestroy(&pixt);
1111 *
1112 * The code below does the same thing using the Pixacc accumulator,
1113 * hiding the details of the offset that is needed for subtraction.
1114 */
1115 pixacc = pixaccCreate(w, h, 1);
1116 pixaccAdd(pixacc, pixs);
1117 pixaccSubtract(pixacc, pixc);
1118 pixaccMultConst(pixacc, fract);
1119 pixaccAdd(pixacc, pixs);
1120 pixd = pixaccFinal(pixacc, 8);
1121 pixaccDestroy(&pixacc);
1122
1123 pixDestroy(&pixc);
1124 return pixd;
1125}
1126
1127
1166PIX *
1168 l_int32 halfwidth,
1169 l_float32 fract,
1170 l_int32 direction)
1171{
1172l_int32 d;
1173PIX *pixt, *pixd, *pixr, *pixrs, *pixg, *pixgs, *pixb, *pixbs;
1174
1175 PROCNAME("pixUnsharpMaskingFast");
1176
1177 if (!pixs || (pixGetDepth(pixs) == 1))
1178 return (PIX *)ERROR_PTR("pixs not defined or 1 bpp", procName, NULL);
1179 if (fract <= 0.0 || halfwidth <= 0) {
1180 L_WARNING("no sharpening requested; clone returned\n", procName);
1181 return pixClone(pixs);
1182 }
1183 if (halfwidth != 1 && halfwidth != 2)
1184 return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1185 if (direction != L_HORIZ && direction != L_VERT &&
1186 direction != L_BOTH_DIRECTIONS)
1187 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1188
1189 /* Remove colormap; clone if possible; result is either 8 or 32 bpp */
1190 if ((pixt = pixConvertTo8Or32(pixs, L_CLONE, 0)) == NULL)
1191 return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
1192
1193 /* Sharpen */
1194 d = pixGetDepth(pixt);
1195 if (d == 8) {
1196 pixd = pixUnsharpMaskingGrayFast(pixt, halfwidth, fract, direction);
1197 } else { /* d == 32 */
1198 pixr = pixGetRGBComponent(pixs, COLOR_RED);
1199 pixrs = pixUnsharpMaskingGrayFast(pixr, halfwidth, fract, direction);
1200 pixDestroy(&pixr);
1201 pixg = pixGetRGBComponent(pixs, COLOR_GREEN);
1202 pixgs = pixUnsharpMaskingGrayFast(pixg, halfwidth, fract, direction);
1203 pixDestroy(&pixg);
1204 pixb = pixGetRGBComponent(pixs, COLOR_BLUE);
1205 pixbs = pixUnsharpMaskingGrayFast(pixb, halfwidth, fract, direction);
1206 pixDestroy(&pixb);
1207 pixd = pixCreateRGBImage(pixrs, pixgs, pixbs);
1208 if (pixGetSpp(pixs) == 4)
1210 pixDestroy(&pixrs);
1211 pixDestroy(&pixgs);
1212 pixDestroy(&pixbs);
1213 }
1214
1215 pixDestroy(&pixt);
1216 return pixd;
1217}
1218
1219
1220
1237PIX *
1239 l_int32 halfwidth,
1240 l_float32 fract,
1241 l_int32 direction)
1242{
1243PIX *pixd;
1244
1245 PROCNAME("pixUnsharpMaskingGrayFast");
1246
1247 if (!pixs)
1248 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1249 if (pixGetDepth(pixs) != 8 || pixGetColormap(pixs) != NULL)
1250 return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1251 if (fract <= 0.0 || halfwidth <= 0) {
1252 L_WARNING("no sharpening requested; clone returned\n", procName);
1253 return pixClone(pixs);
1254 }
1255 if (halfwidth != 1 && halfwidth != 2)
1256 return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1257 if (direction != L_HORIZ && direction != L_VERT &&
1258 direction != L_BOTH_DIRECTIONS)
1259 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
1260
1261 if (direction != L_BOTH_DIRECTIONS)
1262 pixd = pixUnsharpMaskingGray1D(pixs, halfwidth, fract, direction);
1263 else /* 2D sharpening */
1264 pixd = pixUnsharpMaskingGray2D(pixs, halfwidth, fract);
1265
1266 return pixd;
1267}
1268
1269
1286PIX *
1288 l_int32 halfwidth,
1289 l_float32 fract,
1290 l_int32 direction)
1291{
1292l_int32 w, h, d, wpls, wpld, i, j, ival;
1293l_uint32 *datas, *datad;
1294l_uint32 *lines, *lines0, *lines1, *lines2, *lines3, *lines4, *lined;
1295l_float32 val, a[5];
1296PIX *pixd;
1297
1298 PROCNAME("pixUnsharpMaskingGray1D");
1299
1300 if (!pixs)
1301 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1302 pixGetDimensions(pixs, &w, &h, &d);
1303 if (d != 8 || pixGetColormap(pixs) != NULL)
1304 return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1305 if (fract <= 0.0 || halfwidth <= 0) {
1306 L_WARNING("no sharpening requested; clone returned\n", procName);
1307 return pixClone(pixs);
1308 }
1309 if (halfwidth != 1 && halfwidth != 2)
1310 return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1311
1312 /* Initialize pixd with pixels from pixs that will not be
1313 * set when computing the sharpened values. */
1314 pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1315 halfwidth, halfwidth);
1316 datas = pixGetData(pixs);
1317 datad = pixGetData(pixd);
1318 wpls = pixGetWpl(pixs);
1319 wpld = pixGetWpl(pixd);
1320
1321 if (halfwidth == 1) {
1322 a[0] = -fract / 3.0;
1323 a[1] = 1.0 + fract * 2.0 / 3.0;
1324 a[2] = a[0];
1325 } else { /* halfwidth == 2 */
1326 a[0] = -fract / 5.0;
1327 a[1] = a[0];
1328 a[2] = 1.0 + fract * 4.0 / 5.0;
1329 a[3] = a[0];
1330 a[4] = a[0];
1331 }
1332
1333 if (direction == L_HORIZ) {
1334 for (i = 0; i < h; i++) {
1335 lines = datas + i * wpls;
1336 lined = datad + i * wpld;
1337 if (halfwidth == 1) {
1338 for (j = 1; j < w - 1; j++) {
1339 val = a[0] * GET_DATA_BYTE(lines, j - 1) +
1340 a[1] * GET_DATA_BYTE(lines, j) +
1341 a[2] * GET_DATA_BYTE(lines, j + 1);
1342 ival = (l_int32)val;
1343 ival = L_MAX(0, ival);
1344 ival = L_MIN(255, ival);
1345 SET_DATA_BYTE(lined, j, ival);
1346 }
1347 } else { /* halfwidth == 2 */
1348 for (j = 2; j < w - 2; j++) {
1349 val = a[0] * GET_DATA_BYTE(lines, j - 2) +
1350 a[1] * GET_DATA_BYTE(lines, j - 1) +
1351 a[2] * GET_DATA_BYTE(lines, j) +
1352 a[3] * GET_DATA_BYTE(lines, j + 1) +
1353 a[4] * GET_DATA_BYTE(lines, j + 2);
1354 ival = (l_int32)val;
1355 ival = L_MAX(0, ival);
1356 ival = L_MIN(255, ival);
1357 SET_DATA_BYTE(lined, j, ival);
1358 }
1359 }
1360 }
1361 } else { /* direction == L_VERT */
1362 if (halfwidth == 1) {
1363 for (i = 1; i < h - 1; i++) {
1364 lines0 = datas + (i - 1) * wpls;
1365 lines1 = datas + i * wpls;
1366 lines2 = datas + (i + 1) * wpls;
1367 lined = datad + i * wpld;
1368 for (j = 0; j < w; j++) {
1369 val = a[0] * GET_DATA_BYTE(lines0, j) +
1370 a[1] * GET_DATA_BYTE(lines1, j) +
1371 a[2] * GET_DATA_BYTE(lines2, j);
1372 ival = (l_int32)val;
1373 ival = L_MAX(0, ival);
1374 ival = L_MIN(255, ival);
1375 SET_DATA_BYTE(lined, j, ival);
1376 }
1377 }
1378 } else { /* halfwidth == 2 */
1379 for (i = 2; i < h - 2; i++) {
1380 lines0 = datas + (i - 2) * wpls;
1381 lines1 = datas + (i - 1) * wpls;
1382 lines2 = datas + i * wpls;
1383 lines3 = datas + (i + 1) * wpls;
1384 lines4 = datas + (i + 2) * wpls;
1385 lined = datad + i * wpld;
1386 for (j = 0; j < w; j++) {
1387 val = a[0] * GET_DATA_BYTE(lines0, j) +
1388 a[1] * GET_DATA_BYTE(lines1, j) +
1389 a[2] * GET_DATA_BYTE(lines2, j) +
1390 a[3] * GET_DATA_BYTE(lines3, j) +
1391 a[4] * GET_DATA_BYTE(lines4, j);
1392 ival = (l_int32)val;
1393 ival = L_MAX(0, ival);
1394 ival = L_MIN(255, ival);
1395 SET_DATA_BYTE(lined, j, ival);
1396 }
1397 }
1398 }
1399 }
1400
1401 return pixd;
1402}
1403
1404
1420PIX *
1422 l_int32 halfwidth,
1423 l_float32 fract)
1424{
1425l_int32 w, h, d, wpls, wpld, wplf, i, j, ival, sval;
1426l_uint32 *datas, *datad, *lines, *lined;
1427l_float32 val, norm;
1428l_float32 *dataf, *linef, *linef0, *linef1, *linef2, *linef3, *linef4;
1429PIX *pixd;
1430FPIX *fpix;
1431
1432 PROCNAME("pixUnsharpMaskingGray2D");
1433
1434 if (!pixs)
1435 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1436 pixGetDimensions(pixs, &w, &h, &d);
1437 if (d != 8 || pixGetColormap(pixs) != NULL)
1438 return (PIX *)ERROR_PTR("pixs not 8 bpp or has cmap", procName, NULL);
1439 if (fract <= 0.0 || halfwidth <= 0) {
1440 L_WARNING("no sharpening requested; clone returned\n", procName);
1441 return pixClone(pixs);
1442 }
1443 if (halfwidth != 1 && halfwidth != 2)
1444 return (PIX *)ERROR_PTR("halfwidth must be 1 or 2", procName, NULL);
1445
1446 if ((pixd = pixCopyBorder(NULL, pixs, halfwidth, halfwidth,
1447 halfwidth, halfwidth)) == NULL)
1448 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1449 datad = pixGetData(pixd);
1450 wpld = pixGetWpl(pixd);
1451 datas = pixGetData(pixs);
1452 wpls = pixGetWpl(pixs);
1453
1454 /* Do the low pass separably. Store the result of horizontal
1455 * smoothing in an intermediate fpix. */
1456 if ((fpix = fpixCreate(w, h)) == NULL) {
1457 pixDestroy(&pixd);
1458 return (PIX *)ERROR_PTR("fpix not made", procName, NULL);
1459 }
1460 dataf = fpixGetData(fpix);
1461 wplf = fpixGetWpl(fpix);
1462 if (halfwidth == 1) {
1463 for (i = 0; i < h; i++) {
1464 lines = datas + i * wpls;
1465 linef = dataf + i * wplf;
1466 for (j = 1; j < w - 1; j++) {
1467 val = GET_DATA_BYTE(lines, j - 1) +
1468 GET_DATA_BYTE(lines, j) +
1469 GET_DATA_BYTE(lines, j + 1);
1470 linef[j] = val;
1471 }
1472 }
1473 } else {
1474 for (i = 0; i < h; i++) {
1475 lines = datas + i * wpls;
1476 linef = dataf + i * wplf;
1477 for (j = 2; j < w - 2; j++) {
1478 val = GET_DATA_BYTE(lines, j - 2) +
1479 GET_DATA_BYTE(lines, j - 1) +
1480 GET_DATA_BYTE(lines, j) +
1481 GET_DATA_BYTE(lines, j + 1) +
1482 GET_DATA_BYTE(lines, j + 2);
1483 linef[j] = val;
1484 }
1485 }
1486 }
1487
1488 /* Do vertical smoothing to finish the low-pass filter.
1489 * At each pixel, if L is the lowpass value, I is the
1490 * src pixel value and f is the fraction of highpass to
1491 * be added to I, then the highpass filter value is
1492 * H = I - L
1493 * and the new sharpened value is
1494 * N = I + f * H. */
1495 if (halfwidth == 1) {
1496 for (i = 1; i < h - 1; i++) {
1497 linef0 = dataf + (i - 1) * wplf;
1498 linef1 = dataf + i * wplf;
1499 linef2 = dataf + (i + 1) * wplf;
1500 lined = datad + i * wpld;
1501 lines = datas + i * wpls;
1502 norm = 1.0 / 9.0;
1503 for (j = 1; j < w - 1; j++) {
1504 val = norm * (linef0[j] + linef1[j] +
1505 linef2[j]); /* L: lowpass filter value */
1506 sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1507 ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1508 ival = L_MAX(0, ival);
1509 ival = L_MIN(255, ival);
1510 SET_DATA_BYTE(lined, j, ival);
1511 }
1512 }
1513 } else {
1514 for (i = 2; i < h - 2; i++) {
1515 linef0 = dataf + (i - 2) * wplf;
1516 linef1 = dataf + (i - 1) * wplf;
1517 linef2 = dataf + i * wplf;
1518 linef3 = dataf + (i + 1) * wplf;
1519 linef4 = dataf + (i + 2) * wplf;
1520 lined = datad + i * wpld;
1521 lines = datas + i * wpls;
1522 norm = 1.0 / 25.0;
1523 for (j = 2; j < w - 2; j++) {
1524 val = norm * (linef0[j] + linef1[j] + linef2[j] + linef3[j] +
1525 linef4[j]); /* L: lowpass filter value */
1526 sval = GET_DATA_BYTE(lines, j); /* I: source pixel */
1527 ival = (l_int32)(sval + fract * (sval - val) + 0.5);
1528 ival = L_MAX(0, ival);
1529 ival = L_MIN(255, ival);
1530 SET_DATA_BYTE(lined, j, ival);
1531 }
1532 }
1533 }
1534
1535 fpixDestroy(&fpix);
1536 return pixd;
1537}
1538
1539
1540/*-----------------------------------------------------------------------*
1541 * Hue and saturation modification *
1542 *-----------------------------------------------------------------------*/
1566PIX *
1568 PIX *pixs,
1569 l_float32 fract)
1570{
1571l_int32 w, h, d, i, j, wpl, delhue;
1572l_int32 rval, gval, bval, hval, sval, vval;
1573l_uint32 *data, *line;
1574
1575 PROCNAME("pixModifyHue");
1576
1577 if (!pixs)
1578 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1579 if (pixGetColormap(pixs) != NULL)
1580 return (PIX *)ERROR_PTR("pixs colormapped", procName, NULL);
1581 if (pixd && (pixd != pixs))
1582 return (PIX *)ERROR_PTR("pixd not null or pixs", procName, pixd);
1583 pixGetDimensions(pixs, &w, &h, &d);
1584 if (d != 32)
1585 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1586 if (L_ABS(fract) > 1.0)
1587 return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1588
1589 pixd = pixCopy(pixd, pixs);
1590
1591 delhue = (l_int32)(240 * fract);
1592 if (delhue == 0 || delhue == 240 || delhue == -240) {
1593 L_WARNING("no change requested in hue\n", procName);
1594 return pixd;
1595 }
1596 if (delhue < 0)
1597 delhue += 240;
1598
1599 data = pixGetData(pixd);
1600 wpl = pixGetWpl(pixd);
1601 for (i = 0; i < h; i++) {
1602 line = data + i * wpl;
1603 for (j = 0; j < w; j++) {
1604 extractRGBValues(line[j], &rval, &gval, &bval);
1605 convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1606 hval = (hval + delhue) % 240;
1607 convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1608 composeRGBPixel(rval, gval, bval, line + j);
1609 }
1610 }
1611 if (pixGetSpp(pixs) == 4)
1613
1614 return pixd;
1615}
1616
1617
1640PIX *
1642 PIX *pixs,
1643 l_float32 fract)
1644{
1645l_int32 w, h, d, i, j, wpl;
1646l_int32 rval, gval, bval, hval, sval, vval;
1647l_uint32 *data, *line;
1648
1649 PROCNAME("pixModifySaturation");
1650
1651 if (!pixs)
1652 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1653 pixGetDimensions(pixs, &w, &h, &d);
1654 if (d != 32)
1655 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1656 if (L_ABS(fract) > 1.0)
1657 return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1658
1659 pixd = pixCopy(pixd, pixs);
1660 if (fract == 0.0) {
1661 L_WARNING("no change requested in saturation\n", procName);
1662 return pixd;
1663 }
1664
1665 data = pixGetData(pixd);
1666 wpl = pixGetWpl(pixd);
1667 for (i = 0; i < h; i++) {
1668 line = data + i * wpl;
1669 for (j = 0; j < w; j++) {
1670 extractRGBValues(line[j], &rval, &gval, &bval);
1671 convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1672 if (fract < 0.0)
1673 sval = (l_int32)(sval * (1.0 + fract));
1674 else
1675 sval = (l_int32)(sval + fract * (255 - sval));
1676 convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1677 composeRGBPixel(rval, gval, bval, line + j);
1678 }
1679 }
1680 if (pixGetSpp(pixs) == 4)
1682
1683 return pixd;
1684}
1685
1686
1695l_int32
1697 l_int32 factor,
1698 l_float32 *psat)
1699{
1700l_int32 w, h, d, i, j, wpl, sum, count;
1701l_int32 rval, gval, bval, hval, sval, vval;
1702l_uint32 *data, *line;
1703
1704 PROCNAME("pixMeasureSaturation");
1705
1706 if (!psat)
1707 return ERROR_INT("pixs not defined", procName, 1);
1708 *psat = 0.0;
1709 if (!pixs)
1710 return ERROR_INT("pixs not defined", procName, 1);
1711 pixGetDimensions(pixs, &w, &h, &d);
1712 if (d != 32)
1713 return ERROR_INT("pixs not 32 bpp", procName, 1);
1714 if (factor < 1)
1715 return ERROR_INT("subsampling factor < 1", procName, 1);
1716
1717 data = pixGetData(pixs);
1718 wpl = pixGetWpl(pixs);
1719 for (i = 0, sum = 0, count = 0; i < h; i += factor) {
1720 line = data + i * wpl;
1721 for (j = 0; j < w; j += factor) {
1722 extractRGBValues(line[j], &rval, &gval, &bval);
1723 convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1724 sum += sval;
1725 count++;
1726 }
1727 }
1728
1729 if (count > 0)
1730 *psat = (l_float32)sum / (l_float32)count;
1731 return 0;
1732}
1733
1734
1757PIX *
1759 PIX *pixs,
1760 l_float32 fract)
1761{
1762l_int32 w, h, d, i, j, wpl;
1763l_int32 rval, gval, bval, hval, sval, vval;
1764l_uint32 *data, *line;
1765
1766 PROCNAME("pixModifyBrightness");
1767
1768 if (!pixs)
1769 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1770 pixGetDimensions(pixs, &w, &h, &d);
1771 if (d != 32)
1772 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1773 if (L_ABS(fract) > 1.0)
1774 return (PIX *)ERROR_PTR("fract not in [-1.0 ... 1.0]", procName, NULL);
1775
1776 pixd = pixCopy(pixd, pixs);
1777 if (fract == 0.0) {
1778 L_WARNING("no change requested in brightness\n", procName);
1779 return pixd;
1780 }
1781
1782 data = pixGetData(pixd);
1783 wpl = pixGetWpl(pixd);
1784 for (i = 0; i < h; i++) {
1785 line = data + i * wpl;
1786 for (j = 0; j < w; j++) {
1787 extractRGBValues(line[j], &rval, &gval, &bval);
1788 convertRGBToHSV(rval, gval, bval, &hval, &sval, &vval);
1789 if (fract > 0.0)
1790 vval = (l_int32)(vval + fract * (255.0 - vval));
1791 else
1792 vval = (l_int32)(vval * (1.0 + fract));
1793 convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval);
1794 composeRGBPixel(rval, gval, bval, line + j);
1795 }
1796 }
1797 if (pixGetSpp(pixs) == 4)
1799
1800 return pixd;
1801}
1802
1803
1804/*-----------------------------------------------------------------------*
1805 * Color shifting *
1806 *-----------------------------------------------------------------------*/
1838PIX *
1840 l_float32 roff,
1841 l_float32 goff,
1842 l_float32 boff,
1843 l_float32 delta,
1844 l_int32 nincr)
1845{
1846char buf[64];
1847l_int32 i, w, h;
1848l_float32 del, ratio;
1849L_BMF *bmf;
1850PIX *pix1, *pix2, *pix3;
1851PIXA *pixa;
1852
1853 PROCNAME("pixMosaicColorShiftRGB");
1854
1855 if (!pixs || pixGetDepth(pixs) != 32)
1856 return (PIX *)ERROR_PTR("pixs undefined or not rgb", procName, NULL);
1857 if (roff < -1.0 || roff > 1.0)
1858 return (PIX *)ERROR_PTR("roff not in [-1.0, 1.0]", procName, NULL);
1859 if (goff < -1.0 || goff > 1.0)
1860 return (PIX *)ERROR_PTR("goff not in [-1.0, 1.0]", procName, NULL);
1861 if (boff < -1.0 || boff > 1.0)
1862 return (PIX *)ERROR_PTR("boff not in [-1.0, 1.0]", procName, NULL);
1863 if (delta < 0.0 || delta > 0.1)
1864 return (PIX *)ERROR_PTR("delta not in [0.0, 0.1]", procName, NULL);
1865 if (delta == 0.0) delta = 0.04;
1866 if (nincr < 0 || nincr > 6)
1867 return (PIX *)ERROR_PTR("nincr not in [0, 6]", procName, NULL);
1868 if (nincr == 0) nincr = 2;
1869
1870 /* Require width and height to be >= 100, and the aspect ratio <= 5.0 */
1871 pixGetDimensions(pixs, &w, &h, NULL);
1872 if (w < 100 || h < 100)
1873 return (PIX *)ERROR_PTR("w and h not both >= 100", procName, NULL);
1874 pixMaxAspectRatio(pixs, &ratio);
1875 if (ratio < 1.0 || ratio > 5.0) {
1876 L_ERROR("invalid aspect ratio %5.1f\n", procName, ratio);
1877 return NULL;
1878 }
1879
1880 pixa = pixaCreate(3 * (2 * nincr + 1));
1881 bmf = bmfCreate(NULL, 8);
1882 pix1 = pixScaleToSize(pixs, 400, 0);
1883 for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1884 pix2 = pixColorShiftRGB(pix1, roff + del, goff, boff);
1885 snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1886 roff + del, goff, boff);
1887 pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1888 L_ADD_BELOW, 0);
1889 pixaAddPix(pixa, pix3, L_INSERT);
1890 pixDestroy(&pix2);
1891 }
1892 for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1893 pix2 = pixColorShiftRGB(pix1, roff, goff + del, boff);
1894 snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1895 roff, goff + del, boff);
1896 pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1897 L_ADD_BELOW, 0);
1898 pixaAddPix(pixa, pix3, L_INSERT);
1899 pixDestroy(&pix2);
1900 }
1901 for (i = 0, del = - nincr * delta; i < 2 * nincr + 1; i++, del += delta) {
1902 pix2 = pixColorShiftRGB(pix1, roff, goff, boff + del);
1903 snprintf(buf, sizeof(buf), "%4.2f, %4.2f, %4.2f",
1904 roff, goff, boff + del);
1905 pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000,
1906 L_ADD_BELOW, 0);
1907 pixaAddPix(pixa, pix3, L_INSERT);
1908 pixDestroy(&pix2);
1909 }
1910 pixDestroy(&pix1);
1911
1912 pix1 = pixaDisplayTiledAndScaled(pixa, 32, 300, 2 * nincr + 1, 0, 30, 2);
1913 pixaDestroy(&pixa);
1914 bmfDestroy(&bmf);
1915 return pix1;
1916}
1917
1918
1944PIX *
1946 l_float32 rfract,
1947 l_float32 gfract,
1948 l_float32 bfract)
1949{
1950l_int32 w, h, i, j, wpls, wpld, rval, gval, bval;
1951l_int32 *rlut, *glut, *blut;
1952l_uint32 *datas, *datad, *lines, *lined;
1953l_float32 fi;
1954PIX *pixd;
1955
1956 PROCNAME("pixColorShiftRGB");
1957
1958 if (!pixs)
1959 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1960 if (pixGetDepth(pixs) != 32)
1961 return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
1962 if (rfract < -1.0 || rfract > 1.0)
1963 return (PIX *)ERROR_PTR("rfract not in [-1.0, 1.0]", procName, NULL);
1964 if (gfract < -1.0 || gfract > 1.0)
1965 return (PIX *)ERROR_PTR("gfract not in [-1.0, 1.0]", procName, NULL);
1966 if (bfract < -1.0 || bfract > 1.0)
1967 return (PIX *)ERROR_PTR("bfract not in [-1.0, 1.0]", procName, NULL);
1968 if (rfract == 0.0 && gfract == 0.0 && bfract == 0.0)
1969 return pixCopy(NULL, pixs);
1970
1971 rlut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1972 glut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1973 blut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1974 for (i = 0; i < 256; i++) {
1975 fi = i;
1976 if (rfract >= 0) {
1977 rlut[i] = (l_int32)(fi + (255.0 - fi) * rfract);
1978 } else {
1979 rlut[i] = (l_int32)(fi * (1.0 + rfract));
1980 }
1981 if (gfract >= 0) {
1982 glut[i] = (l_int32)(fi + (255.0 - fi) * gfract);
1983 } else {
1984 glut[i] = (l_int32)(fi * (1.0 + gfract));
1985 }
1986 if (bfract >= 0) {
1987 blut[i] = (l_int32)(fi + (255.0 - fi) * bfract);
1988 } else {
1989 blut[i] = (l_int32)(fi * (1.0 + bfract));
1990 }
1991 }
1992
1993 pixGetDimensions(pixs, &w, &h, NULL);
1994 datas = pixGetData(pixs);
1995 wpls = pixGetWpl(pixs);
1996 pixd = pixCreate(w, h, 32);
1997 datad = pixGetData(pixd);
1998 wpld = pixGetWpl(pixd);
1999 for (i = 0; i < h; i++) {
2000 lines = datas + i * wpls;
2001 lined = datad + i * wpld;
2002 for (j = 0; j < w; j++) {
2003 extractRGBValues(lines[j], &rval, &gval, &bval);
2004 composeRGBPixel(rlut[rval], glut[gval], blut[bval], lined + j);
2005 }
2006 }
2007
2008 LEPT_FREE(rlut);
2009 LEPT_FREE(glut);
2010 LEPT_FREE(blut);
2011 return pixd;
2012}
2013
2014/*-----------------------------------------------------------------------*
2015 * Darken gray (unsaturated) pixels
2016 *-----------------------------------------------------------------------*/
2043PIX *
2045 PIX *pixs,
2046 l_int32 thresh,
2047 l_int32 satlimit)
2048{
2049l_int32 w, h, i, j, wpls, wpld;
2050l_int32 rval, gval, bval, minrg, min, maxrg, max, sat;
2051l_uint32 *datas, *datad, *lines, *lined;
2052l_float32 ratio;
2053
2054 PROCNAME("pixDarkenGray");
2055
2056 if (!pixs || pixGetDepth(pixs) != 32)
2057 return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
2058 if (thresh < 0 || thresh > 255)
2059 return (PIX *)ERROR_PTR("invalid thresh", procName, NULL);
2060 if (satlimit < 1)
2061 return (PIX *)ERROR_PTR("invalid satlimit", procName, NULL);
2062 if (pixd && (pixs != pixd))
2063 return (PIX *)ERROR_PTR("not new or in-place", procName, NULL);
2064
2065 pixGetDimensions(pixs, &w, &h, NULL);
2066 datas = pixGetData(pixs);
2067 wpls = pixGetWpl(pixs);
2068 if ((pixd = pixCopy(pixd, pixs)) == NULL)
2069 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2070 datad = pixGetData(pixd);
2071 wpld = pixGetWpl(pixd);
2072
2073 for (i = 0; i < h; i++) {
2074 lines = datas + i * wpls;
2075 lined = datad + i * wpld;
2076 for (j = 0; j < w; j++) {
2077 extractRGBValues(lines[j], &rval, &gval, &bval);
2078 minrg = L_MIN(rval, gval);
2079 min = L_MIN(minrg, bval);
2080 maxrg = L_MAX(rval, gval);
2081 max = L_MAX(maxrg, bval);
2082 sat = max - min;
2083 if (max >= thresh || sat >= satlimit)
2084 continue;
2085 ratio = (l_float32)sat / (l_float32)satlimit;
2086 composeRGBPixel((l_int32)(ratio * rval), (l_int32)(ratio * gval),
2087 (l_int32)(ratio * bval), &lined[j]);
2088 }
2089 }
2090 return pixd;
2091}
2092
2093
2094/*-----------------------------------------------------------------------*
2095 * General multiplicative constant color transform *
2096 *-----------------------------------------------------------------------*/
2115PIX *
2117 l_float32 rfact,
2118 l_float32 gfact,
2119 l_float32 bfact)
2120{
2121l_int32 i, j, w, h, d, wpls, wpld;
2122l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2123l_uint32 nval;
2124l_uint32 *datas, *datad, *lines, *lined;
2125PIX *pixd;
2126PIXCMAP *cmap;
2127
2128 PROCNAME("pixMultConstantColor");
2129
2130 if (!pixs)
2131 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2132 pixGetDimensions(pixs, &w, &h, &d);
2133 cmap = pixGetColormap(pixs);
2134 if (!cmap && d != 32)
2135 return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
2136 rfact = L_MAX(0.0, rfact);
2137 gfact = L_MAX(0.0, gfact);
2138 bfact = L_MAX(0.0, bfact);
2139
2140 if (cmap) {
2141 if ((pixd = pixCopy(NULL, pixs)) == NULL)
2142 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2143 cmap = pixGetColormap(pixd);
2144 ncolors = pixcmapGetCount(cmap);
2145 for (i = 0; i < ncolors; i++) {
2146 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2147 nrval = (l_int32)(rfact * rval);
2148 ngval = (l_int32)(gfact * gval);
2149 nbval = (l_int32)(bfact * bval);
2150 nrval = L_MIN(255, nrval);
2151 ngval = L_MIN(255, ngval);
2152 nbval = L_MIN(255, nbval);
2153 pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2154 }
2155 return pixd;
2156 }
2157
2158 if ((pixd = pixCreateTemplate(pixs)) == NULL)
2159 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2160 datas = pixGetData(pixs);
2161 datad = pixGetData(pixd);
2162 wpls = pixGetWpl(pixs);
2163 wpld = pixGetWpl(pixd);
2164 for (i = 0; i < h; i++) {
2165 lines = datas + i * wpls;
2166 lined = datad + i * wpld;
2167 for (j = 0; j < w; j++) {
2168 extractRGBValues(lines[j], &rval, &gval, &bval);
2169 nrval = (l_int32)(rfact * rval);
2170 ngval = (l_int32)(gfact * gval);
2171 nbval = (l_int32)(bfact * bval);
2172 nrval = L_MIN(255, nrval);
2173 ngval = L_MIN(255, ngval);
2174 nbval = L_MIN(255, nbval);
2175 composeRGBPixel(nrval, ngval, nbval, &nval);
2176 *(lined + j) = nval;
2177 }
2178 }
2179
2180 return pixd;
2181}
2182
2183
2217PIX *
2219 L_KERNEL *kel)
2220{
2221l_int32 i, j, index, kw, kh, w, h, d, wpls, wpld;
2222l_int32 ncolors, rval, gval, bval, nrval, ngval, nbval;
2223l_uint32 nval;
2224l_uint32 *datas, *datad, *lines, *lined;
2225l_float32 v[9]; /* use linear array for convenience */
2226PIX *pixd;
2227PIXCMAP *cmap;
2228
2229 PROCNAME("pixMultMatrixColor");
2230
2231 if (!pixs)
2232 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2233 if (!kel)
2234 return (PIX *)ERROR_PTR("kel not defined", procName, NULL);
2235 kernelGetParameters(kel, &kw, &kh, NULL, NULL);
2236 if (kw != 3 || kh != 3)
2237 return (PIX *)ERROR_PTR("matrix not 3x3", procName, NULL);
2238 pixGetDimensions(pixs, &w, &h, &d);
2239 cmap = pixGetColormap(pixs);
2240 if (!cmap && d != 32)
2241 return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
2242
2243 for (i = 0, index = 0; i < 3; i++)
2244 for (j = 0; j < 3; j++, index++)
2245 kernelGetElement(kel, i, j, v + index);
2246
2247 if (cmap) {
2248 if ((pixd = pixCopy(NULL, pixs)) == NULL)
2249 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2250 cmap = pixGetColormap(pixd);
2251 ncolors = pixcmapGetCount(cmap);
2252 for (i = 0; i < ncolors; i++) {
2253 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
2254 nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2255 ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2256 nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2257 nrval = L_MAX(0, L_MIN(255, nrval));
2258 ngval = L_MAX(0, L_MIN(255, ngval));
2259 nbval = L_MAX(0, L_MIN(255, nbval));
2260 pixcmapResetColor(cmap, i, nrval, ngval, nbval);
2261 }
2262 return pixd;
2263 }
2264
2265 if ((pixd = pixCreateTemplate(pixs)) == NULL)
2266 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2267 datas = pixGetData(pixs);
2268 datad = pixGetData(pixd);
2269 wpls = pixGetWpl(pixs);
2270 wpld = pixGetWpl(pixd);
2271 for (i = 0; i < h; i++) {
2272 lines = datas + i * wpls;
2273 lined = datad + i * wpld;
2274 for (j = 0; j < w; j++) {
2275 extractRGBValues(lines[j], &rval, &gval, &bval);
2276 nrval = (l_int32)(v[0] * rval + v[1] * gval + v[2] * bval);
2277 ngval = (l_int32)(v[3] * rval + v[4] * gval + v[5] * bval);
2278 nbval = (l_int32)(v[6] * rval + v[7] * gval + v[8] * bval);
2279 nrval = L_MAX(0, L_MIN(255, nrval));
2280 ngval = L_MAX(0, L_MIN(255, ngval));
2281 nbval = L_MAX(0, L_MIN(255, nbval));
2282 composeRGBPixel(nrval, ngval, nbval, &nval);
2283 *(lined + j) = nval;
2284 }
2285 }
2286
2287 return pixd;
2288}
2289
2290
2291/*-------------------------------------------------------------*
2292 * Half-edge by bandpass *
2293 *-------------------------------------------------------------*/
2326PIX *
2328 l_int32 sm1h,
2329 l_int32 sm1v,
2330 l_int32 sm2h,
2331 l_int32 sm2v)
2332{
2333l_int32 d;
2334PIX *pixg, *pixacc, *pixc1, *pixc2;
2335
2336 PROCNAME("pixHalfEdgeByBandpass");
2337
2338 if (!pixs)
2339 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2340 if (sm1h == sm2h && sm1v == sm2v)
2341 return (PIX *)ERROR_PTR("sm2 = sm1", procName, NULL);
2342 d = pixGetDepth(pixs);
2343 if (d != 8 && d != 32)
2344 return (PIX *)ERROR_PTR("pixs not 8 or 32 bpp", procName, NULL);
2345 if (d == 32)
2346 pixg = pixConvertRGBToLuminance(pixs);
2347 else /* d == 8 */
2348 pixg = pixClone(pixs);
2349
2350 /* Make a convolution accumulator and use it twice */
2351 if ((pixacc = pixBlockconvAccum(pixg)) == NULL) {
2352 pixDestroy(&pixg);
2353 return (PIX *)ERROR_PTR("pixacc not made", procName, NULL);
2354 }
2355 if ((pixc1 = pixBlockconvGray(pixg, pixacc, sm1h, sm1v)) == NULL) {
2356 pixDestroy(&pixg);
2357 pixDestroy(&pixacc);
2358 return (PIX *)ERROR_PTR("pixc1 not made", procName, NULL);
2359 }
2360 pixc2 = pixBlockconvGray(pixg, pixacc, sm2h, sm2v);
2361 pixDestroy(&pixg);
2362 pixDestroy(&pixacc);
2363 if (!pixc2) {
2364 pixDestroy(&pixc1);
2365 return (PIX *)ERROR_PTR("pixc2 not made", procName, NULL);
2366 }
2367
2368 /* Compute the half-edge using pixc1 - pixc2. */
2369 pixSubtractGray(pixc1, pixc1, pixc2);
2370 pixDestroy(&pixc2);
2371 return pixc1;
2372}
#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
void bmfDestroy(L_BMF **pbmf)
bmfDestroy()
Definition: bmf.c:169
L_BMF * bmfCreate(const char *dir, l_int32 fontsize)
bmfCreate()
Definition: bmf.c:117
l_ok pixcmapContrastTRC(PIXCMAP *cmap, l_float32 factor)
pixcmapContrastTRC()
Definition: colormap.c:2385
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 pixcmapGammaTRC(PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixcmapGammaTRC()
Definition: colormap.c:2330
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
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:343
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:281
PIX * pixBlockconvAccum(PIX *pixs)
pixBlockconvAccum()
Definition: convolve.c:460
PIX * pixBlockconvGray(PIX *pixs, PIX *pixacc, l_int32 wc, l_int32 hc)
pixBlockconvGray()
Definition: convolve.c:216
l_int32 pixMeasureSaturation(PIX *pixs, l_int32 factor, l_float32 *psat)
pixMeasureSaturation()
Definition: enhance.c:1696
PIX * pixDarkenGray(PIX *pixd, PIX *pixs, l_int32 thresh, l_int32 satlimit)
pixDarkenGray()
Definition: enhance.c:2044
PIX * pixContrastTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 factor)
pixContrastTRCMasked()
Definition: enhance.c:501
NUMA * numaEqualizeTRC(PIX *pix, l_float32 fract, l_int32 factor)
numaEqualizeTRC()
Definition: enhance.c:717
PIX * pixUnsharpMaskingFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingFast()
Definition: enhance.c:1167
PIX * pixModifyHue(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyHue()
Definition: enhance.c:1567
PIX * pixUnsharpMaskingGray2D(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray2D()
Definition: enhance.c:1421
PIX * pixColorShiftRGB(PIX *pixs, l_float32 rfract, l_float32 gfract, l_float32 bfract)
pixColorShiftRGB()
Definition: enhance.c:1945
PIX * pixMultConstantColor(PIX *pixs, l_float32 rfact, l_float32 gfact, l_float32 bfact)
pixMultConstantColor()
Definition: enhance.c:2116
PIX * pixMosaicColorShiftRGB(PIX *pixs, l_float32 roff, l_float32 goff, l_float32 boff, l_float32 delta, l_int32 nincr)
pixMosaicColorShiftRGB()
Definition: enhance.c:1839
l_int32 pixTRCMap(PIX *pixs, PIX *pixm, NUMA *na)
pixTRCMap()
Definition: enhance.c:784
PIX * pixGammaTRC(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRC()
Definition: enhance.c:176
NUMA * numaGammaTRC(l_float32 gamma, l_int32 minval, l_int32 maxval)
numaGammaTRC()
Definition: enhance.c:369
PIX * pixGammaTRCMasked(PIX *pixd, PIX *pixs, PIX *pixm, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCMasked()
Definition: enhance.c:244
PIX * pixHalfEdgeByBandpass(PIX *pixs, l_int32 sm1h, l_int32 sm1v, l_int32 sm2h, l_int32 sm2v)
pixHalfEdgeByBandpass()
Definition: enhance.c:2327
PIX * pixUnsharpMasking(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMasking()
Definition: enhance.c:1001
PIX * pixUnsharpMaskingGrayFast(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGrayFast()
Definition: enhance.c:1238
PIX * pixModifySaturation(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifySaturation()
Definition: enhance.c:1641
l_int32 pixTRCMapGeneral(PIX *pixs, PIX *pixm, NUMA *nar, NUMA *nag, NUMA *nab)
pixTRCMapGeneral()
Definition: enhance.c:906
PIX * pixUnsharpMaskingGray1D(PIX *pixs, l_int32 halfwidth, l_float32 fract, l_int32 direction)
pixUnsharpMaskingGray1D()
Definition: enhance.c:1287
PIX * pixMultMatrixColor(PIX *pixs, L_KERNEL *kel)
pixMultMatrixColor()
Definition: enhance.c:2218
PIX * pixGammaTRCWithAlpha(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval)
pixGammaTRCWithAlpha()
Definition: enhance.c:308
PIX * pixUnsharpMaskingGray(PIX *pixs, l_int32 halfwidth, l_float32 fract)
pixUnsharpMaskingGray()
Definition: enhance.c:1070
PIX * pixEqualizeTRC(PIX *pixd, PIX *pixs, l_float32 fract, l_int32 factor)
pixEqualizeTRC()
Definition: enhance.c:630
PIX * pixModifyBrightness(PIX *pixd, PIX *pixs, l_float32 fract)
pixModifyBrightness()
Definition: enhance.c:1758
PIX * pixContrastTRC(PIX *pixd, PIX *pixs, l_float32 factor)
pixContrastTRC()
Definition: enhance.c:439
NUMA * numaContrastTRC(l_float32 factor)
numaContrastTRC()
Definition: enhance.c:560
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:156
l_float32 * fpixGetData(FPIX *fpix)
fpixGetData()
Definition: fpix1.c:519
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:376
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:292
l_ok kernelGetParameters(L_KERNEL *kel, l_int32 *psy, l_int32 *psx, l_int32 *pcy, l_int32 *pcx)
kernelGetParameters()
Definition: kernel.c:274
l_ok kernelGetElement(L_KERNEL *kel, l_int32 row, l_int32 col, l_float32 *pval)
kernelGetElement()
Definition: kernel.c:215
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:847
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:821
NUMA * numaGetPartialSums(NUMA *na)
numaGetPartialSums()
Definition: numafunc1.c:579
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
Definition: numafunc1.c:538
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
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixMaxAspectRatio(PIX *pixs, l_float32 *pratio)
pixMaxAspectRatio()
Definition: pix1.c:2013
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
PIX * pixCopyBorder(PIX *pixd, PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixCopyBorder()
Definition: pix2.c:1769
l_ok pixCopyRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixCopyRGBComponent()
Definition: pix2.c:2690
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
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
l_ok pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 comp)
pixSetRGBComponent()
Definition: pix2.c:2538
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
pixCreateRGBImage()
Definition: pix2.c:2423
NUMA * pixGetGrayHistogram(PIX *pixs, l_int32 factor)
pixGetGrayHistogram()
Definition: pix4.c:115
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ L_ALPHA_CHANNEL
Definition: pix.h:207
@ COLOR_GREEN
Definition: pix.h:205
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:260
@ L_ADD_BELOW
Definition: pix.h:1210
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
l_ok pixaAddPix(PIXA *pixa, PIX *pix, l_int32 copyflag)
pixaAddPix()
Definition: pixabasic.c:506
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
PIXA * pixaCreate(l_int32 n)
pixaCreate()
Definition: pixabasic.c:167
PIXACC * pixaccCreate(l_int32 w, l_int32 h, l_int32 negflag)
pixaccCreate()
Definition: pixacc.c:92
l_ok pixaccSubtract(PIXACC *pixacc, PIX *pix)
pixaccSubtract()
Definition: pixacc.c:276
l_ok pixaccAdd(PIXACC *pixacc, PIX *pix)
pixaccAdd()
Definition: pixacc.c:254
void pixaccDestroy(PIXACC **ppixacc)
pixaccDestroy()
Definition: pixacc.c:162
PIX * pixaccFinal(PIXACC *pixacc, l_int32 outdepth)
pixaccFinal()
Definition: pixacc.c:193
l_ok pixaccMultConst(PIXACC *pixacc, l_float32 factor)
pixaccMultConst()
Definition: pixacc.c:298
PIX * pixaDisplayTiledAndScaled(PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border)
pixaDisplayTiledAndScaled()
Definition: pixafunc2.c:1045
PIX * pixSubtractGray(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtractGray()
Definition: pixarith.c:357
PIX * pixConvertRGBToLuminance(PIX *pixs)
pixConvertRGBToLuminance()
Definition: pixconv.c:742
PIX * pixConvertTo8Or32(PIX *pixs, l_int32 copyflag, l_int32 warnflag)
pixConvertTo8Or32()
Definition: pixconv.c:3492
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
PIX * pixScaleToSize(PIX *pixs, l_int32 wd, l_int32 hd)
pixScaleToSize()
Definition: scale1.c:323
Definition: pix.h:579
Definition: bmf.h:47
Definition: morph.h:89
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
Definition: pix.h:544
PIX * pixAddSingleTextblock(PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow)
pixAddSingleTextblock()
Definition: textops.c:120