Leptonica 1.85.0
Image processing and image analysis suite
Loading...
Searching...
No Matches
pix4.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
85#ifdef HAVE_CONFIG_H
86#include <config_auto.h>
87#endif /* HAVE_CONFIG_H */
88
89#include <string.h>
90#include <math.h>
91#include "allheaders.h"
92
93
94/*------------------------------------------------------------------*
95 * Pixel histogram and averaging *
96 *------------------------------------------------------------------*/
114NUMA *
116 l_int32 factor)
117{
118l_int32 i, j, w, h, d, wpl, val, size, count;
119l_uint32 *data, *line;
120l_float32 *array;
121NUMA *na;
122PIX *pixg;
123
124 if (!pixs)
125 return (NUMA *)ERROR_PTR("pixs not defined", __func__, NULL);
126 d = pixGetDepth(pixs);
127 if (d > 16)
128 return (NUMA *)ERROR_PTR("depth not in {1,2,4,8,16}", __func__, NULL);
129 if (factor < 1)
130 return (NUMA *)ERROR_PTR("sampling must be >= 1", __func__, NULL);
131
132 if (pixGetColormap(pixs))
133 pixg = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
134 else
135 pixg = pixClone(pixs);
136
137 pixGetDimensions(pixg, &w, &h, &d);
138 size = 1 << d;
139 if ((na = numaCreate(size)) == NULL) {
140 pixDestroy(&pixg);
141 return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
142 }
143 numaSetCount(na, size); /* all initialized to 0.0 */
144 array = numaGetFArray(na, L_NOCOPY);
145
146 if (d == 1) { /* special case */
147 pixCountPixels(pixg, &count, NULL);
148 array[0] = w * h - count;
149 array[1] = count;
150 pixDestroy(&pixg);
151 return na;
152 }
153
154 wpl = pixGetWpl(pixg);
155 data = pixGetData(pixg);
156 for (i = 0; i < h; i += factor) {
157 line = data + i * wpl;
158 if (d == 2) {
159 for (j = 0; j < w; j += factor) {
160 val = GET_DATA_DIBIT(line, j);
161 array[val] += 1.0;
162 }
163 } else if (d == 4) {
164 for (j = 0; j < w; j += factor) {
165 val = GET_DATA_QBIT(line, j);
166 array[val] += 1.0;
167 }
168 } else if (d == 8) {
169 for (j = 0; j < w; j += factor) {
170 val = GET_DATA_BYTE(line, j);
171 array[val] += 1.0;
172 }
173 } else { /* d == 16 */
174 for (j = 0; j < w; j += factor) {
175 val = GET_DATA_TWO_BYTES(line, j);
176 array[val] += 1.0;
177 }
178 }
179 }
180
181 pixDestroy(&pixg);
182 return na;
183}
184
185
208NUMA *
210 PIX *pixm,
211 l_int32 x,
212 l_int32 y,
213 l_int32 factor)
214{
215l_int32 i, j, w, h, wm, hm, dm, wplg, wplm, val;
216l_uint32 *datag, *datam, *lineg, *linem;
217l_float32 *array;
218NUMA *na;
219PIX *pixg;
220
221 if (!pixm)
222 return pixGetGrayHistogram(pixs, factor);
223 if (!pixs)
224 return (NUMA *)ERROR_PTR("pixs not defined", __func__, NULL);
225 if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
226 return (NUMA *)ERROR_PTR("pixs neither 8 bpp nor colormapped",
227 __func__, NULL);
228 pixGetDimensions(pixm, &wm, &hm, &dm);
229 if (dm != 1)
230 return (NUMA *)ERROR_PTR("pixm not 1 bpp", __func__, NULL);
231 if (factor < 1)
232 return (NUMA *)ERROR_PTR("sampling must be >= 1", __func__, NULL);
233
234 if ((na = numaCreate(256)) == NULL)
235 return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
236 numaSetCount(na, 256); /* all initialized to 0.0 */
237 array = numaGetFArray(na, L_NOCOPY);
238
239 if (pixGetColormap(pixs))
240 pixg = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
241 else
242 pixg = pixClone(pixs);
243 pixGetDimensions(pixg, &w, &h, NULL);
244 datag = pixGetData(pixg);
245 wplg = pixGetWpl(pixg);
246 datam = pixGetData(pixm);
247 wplm = pixGetWpl(pixm);
248
249 /* Generate the histogram */
250 for (i = 0; i < hm; i += factor) {
251 if (y + i < 0 || y + i >= h) continue;
252 lineg = datag + (y + i) * wplg;
253 linem = datam + i * wplm;
254 for (j = 0; j < wm; j += factor) {
255 if (x + j < 0 || x + j >= w) continue;
256 if (GET_DATA_BIT(linem, j)) {
257 val = GET_DATA_BYTE(lineg, x + j);
258 array[val] += 1.0;
259 }
260 }
261 }
262
263 pixDestroy(&pixg);
264 return na;
265}
266
267
286NUMA *
288 BOX *box,
289 l_int32 factor)
290{
291l_int32 i, j, bx, by, bw, bh, w, h, wplg, val;
292l_uint32 *datag, *lineg;
293l_float32 *array;
294NUMA *na;
295PIX *pixg;
296
297 if (!box)
298 return pixGetGrayHistogram(pixs, factor);
299 if (!pixs)
300 return (NUMA *)ERROR_PTR("pixs not defined", __func__, NULL);
301 if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
302 return (NUMA *)ERROR_PTR("pixs neither 8 bpp nor colormapped",
303 __func__, NULL);
304 if (factor < 1)
305 return (NUMA *)ERROR_PTR("sampling must be >= 1", __func__, NULL);
306
307 if ((na = numaCreate(256)) == NULL)
308 return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
309 numaSetCount(na, 256); /* all initialized to 0.0 */
310 array = numaGetFArray(na, L_NOCOPY);
311
312 if (pixGetColormap(pixs))
313 pixg = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
314 else
315 pixg = pixClone(pixs);
316 pixGetDimensions(pixg, &w, &h, NULL);
317 datag = pixGetData(pixg);
318 wplg = pixGetWpl(pixg);
319 boxGetGeometry(box, &bx, &by, &bw, &bh);
320
321 /* Generate the histogram */
322 for (i = 0; i < bh; i += factor) {
323 if (by + i < 0 || by + i >= h) continue;
324 lineg = datag + (by + i) * wplg;
325 for (j = 0; j < bw; j += factor) {
326 if (bx + j < 0 || bx + j >= w) continue;
327 val = GET_DATA_BYTE(lineg, bx + j);
328 array[val] += 1.0;
329 }
330 }
331
332 pixDestroy(&pixg);
333 return na;
334}
335
336
352NUMAA *
354 l_int32 factor,
355 l_int32 nx,
356 l_int32 ny)
357{
358l_int32 i, n;
359NUMA *na;
360NUMAA *naa;
361PIX *pix1, *pix2;
362PIXA *pixa;
363
364 if (!pixs)
365 return (NUMAA *)ERROR_PTR("pixs not defined", __func__, NULL);
366 if (factor < 1)
367 return (NUMAA *)ERROR_PTR("sampling must be >= 1", __func__, NULL);
368 if (nx < 1 || ny < 1)
369 return (NUMAA *)ERROR_PTR("nx and ny must both be > 0", __func__, NULL);
370
371 n = nx * ny;
372 if ((naa = numaaCreate(n)) == NULL)
373 return (NUMAA *)ERROR_PTR("naa not made", __func__, NULL);
374
375 pix1 = pixConvertTo8(pixs, FALSE);
376 pixa = pixaSplitPix(pix1, nx, ny, 0, 0);
377 for (i = 0; i < n; i++) {
378 pix2 = pixaGetPix(pixa, i, L_CLONE);
379 na = pixGetGrayHistogram(pix2, factor);
380 numaaAddNuma(naa, na, L_INSERT);
381 pixDestroy(&pix2);
382 }
383
384 pixDestroy(&pix1);
385 pixaDestroy(&pixa);
386 return naa;
387}
388
389
407l_ok
409 l_int32 factor,
410 NUMA **pnar,
411 NUMA **pnag,
412 NUMA **pnab)
413{
414l_int32 i, j, w, h, d, wpl, index, rval, gval, bval;
415l_uint32 *data, *line;
416l_float32 *rarray, *garray, *barray;
417NUMA *nar, *nag, *nab;
418PIXCMAP *cmap;
419
420 if (pnar) *pnar = NULL;
421 if (pnag) *pnag = NULL;
422 if (pnab) *pnab = NULL;
423 if (!pnar || !pnag || !pnab)
424 return ERROR_INT("&nar, &nag, &nab not all defined", __func__, 1);
425 if (!pixs)
426 return ERROR_INT("pixs not defined", __func__, 1);
427 pixGetDimensions(pixs, &w, &h, &d);
428 cmap = pixGetColormap(pixs);
429 if (cmap && (d != 2 && d != 4 && d != 8))
430 return ERROR_INT("colormap and not 2, 4, or 8 bpp", __func__, 1);
431 if (!cmap && d != 32)
432 return ERROR_INT("no colormap and not rgb", __func__, 1);
433 if (factor < 1)
434 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
435
436 /* Set up the histogram arrays */
437 nar = numaCreate(256);
438 nag = numaCreate(256);
439 nab = numaCreate(256);
440 numaSetCount(nar, 256);
441 numaSetCount(nag, 256);
442 numaSetCount(nab, 256);
443 rarray = numaGetFArray(nar, L_NOCOPY);
444 garray = numaGetFArray(nag, L_NOCOPY);
445 barray = numaGetFArray(nab, L_NOCOPY);
446 *pnar = nar;
447 *pnag = nag;
448 *pnab = nab;
449
450 /* Generate the color histograms */
451 data = pixGetData(pixs);
452 wpl = pixGetWpl(pixs);
453 if (cmap) {
454 for (i = 0; i < h; i += factor) {
455 line = data + i * wpl;
456 for (j = 0; j < w; j += factor) {
457 if (d == 8)
458 index = GET_DATA_BYTE(line, j);
459 else if (d == 4)
460 index = GET_DATA_QBIT(line, j);
461 else /* 2 bpp */
462 index = GET_DATA_DIBIT(line, j);
463 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
464 rarray[rval] += 1.0;
465 garray[gval] += 1.0;
466 barray[bval] += 1.0;
467 }
468 }
469 } else { /* 32 bpp rgb */
470 for (i = 0; i < h; i += factor) {
471 line = data + i * wpl;
472 for (j = 0; j < w; j += factor) {
473 extractRGBValues(line[j], &rval, &gval, &bval);
474 rarray[rval] += 1.0;
475 garray[gval] += 1.0;
476 barray[bval] += 1.0;
477 }
478 }
479 }
480
481 return 0;
482}
483
484
507l_ok
509 PIX *pixm,
510 l_int32 x,
511 l_int32 y,
512 l_int32 factor,
513 NUMA **pnar,
514 NUMA **pnag,
515 NUMA **pnab)
516{
517l_int32 i, j, w, h, d, wm, hm, dm, wpls, wplm, index, rval, gval, bval;
518l_uint32 *datas, *datam, *lines, *linem;
519l_float32 *rarray, *garray, *barray;
520NUMA *nar, *nag, *nab;
521PIXCMAP *cmap;
522
523 if (!pixm)
524 return pixGetColorHistogram(pixs, factor, pnar, pnag, pnab);
525
526 if (pnar) *pnar = NULL;
527 if (pnag) *pnag = NULL;
528 if (pnab) *pnab = NULL;
529 if (!pnar || !pnag || !pnab)
530 return ERROR_INT("&nar, &nag, &nab not all defined", __func__, 1);
531 if (!pixs)
532 return ERROR_INT("pixs not defined", __func__, 1);
533 pixGetDimensions(pixs, &w, &h, &d);
534 cmap = pixGetColormap(pixs);
535 if (cmap && (d != 2 && d != 4 && d != 8))
536 return ERROR_INT("colormap and not 2, 4, or 8 bpp", __func__, 1);
537 if (!cmap && d != 32)
538 return ERROR_INT("no colormap and not rgb", __func__, 1);
539 pixGetDimensions(pixm, &wm, &hm, &dm);
540 if (dm != 1)
541 return ERROR_INT("pixm not 1 bpp", __func__, 1);
542 if (factor < 1)
543 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
544
545 /* Set up the histogram arrays */
546 nar = numaCreate(256);
547 nag = numaCreate(256);
548 nab = numaCreate(256);
549 numaSetCount(nar, 256);
550 numaSetCount(nag, 256);
551 numaSetCount(nab, 256);
552 rarray = numaGetFArray(nar, L_NOCOPY);
553 garray = numaGetFArray(nag, L_NOCOPY);
554 barray = numaGetFArray(nab, L_NOCOPY);
555 *pnar = nar;
556 *pnag = nag;
557 *pnab = nab;
558
559 /* Generate the color histograms */
560 datas = pixGetData(pixs);
561 wpls = pixGetWpl(pixs);
562 datam = pixGetData(pixm);
563 wplm = pixGetWpl(pixm);
564 if (cmap) {
565 for (i = 0; i < hm; i += factor) {
566 if (y + i < 0 || y + i >= h) continue;
567 lines = datas + (y + i) * wpls;
568 linem = datam + i * wplm;
569 for (j = 0; j < wm; j += factor) {
570 if (x + j < 0 || x + j >= w) continue;
571 if (GET_DATA_BIT(linem, j)) {
572 if (d == 8)
573 index = GET_DATA_BYTE(lines, x + j);
574 else if (d == 4)
575 index = GET_DATA_QBIT(lines, x + j);
576 else /* 2 bpp */
577 index = GET_DATA_DIBIT(lines, x + j);
578 pixcmapGetColor(cmap, index, &rval, &gval, &bval);
579 rarray[rval] += 1.0;
580 garray[gval] += 1.0;
581 barray[bval] += 1.0;
582 }
583 }
584 }
585 } else { /* 32 bpp rgb */
586 for (i = 0; i < hm; i += factor) {
587 if (y + i < 0 || y + i >= h) continue;
588 lines = datas + (y + i) * wpls;
589 linem = datam + i * wplm;
590 for (j = 0; j < wm; j += factor) {
591 if (x + j < 0 || x + j >= w) continue;
592 if (GET_DATA_BIT(linem, j)) {
593 extractRGBValues(lines[x + j], &rval, &gval, &bval);
594 rarray[rval] += 1.0;
595 garray[gval] += 1.0;
596 barray[bval] += 1.0;
597 }
598 }
599 }
600 }
601
602 return 0;
603}
604
605
620NUMA *
622 l_int32 factor)
623{
624l_int32 i, j, w, h, d, wpl, val, size;
625l_uint32 *data, *line;
626l_float32 *array;
627NUMA *na;
628
629 if (!pixs)
630 return (NUMA *)ERROR_PTR("pixs not defined", __func__, NULL);
631 if (pixGetColormap(pixs) == NULL)
632 return (NUMA *)ERROR_PTR("pixs not cmapped", __func__, NULL);
633 if (factor < 1)
634 return (NUMA *)ERROR_PTR("sampling must be >= 1", __func__, NULL);
635 pixGetDimensions(pixs, &w, &h, &d);
636 if (d != 2 && d != 4 && d != 8)
637 return (NUMA *)ERROR_PTR("d not 2, 4 or 8", __func__, NULL);
638
639 size = 1 << d;
640 if ((na = numaCreate(size)) == NULL)
641 return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
642 numaSetCount(na, size); /* all initialized to 0.0 */
643 array = numaGetFArray(na, L_NOCOPY);
644
645 wpl = pixGetWpl(pixs);
646 data = pixGetData(pixs);
647 for (i = 0; i < h; i += factor) {
648 line = data + i * wpl;
649 for (j = 0; j < w; j += factor) {
650 if (d == 8)
651 val = GET_DATA_BYTE(line, j);
652 else if (d == 4)
653 val = GET_DATA_QBIT(line, j);
654 else /* d == 2 */
655 val = GET_DATA_DIBIT(line, j);
656 array[val] += 1.0;
657 }
658 }
659
660 return na;
661}
662
663
683NUMA *
685 PIX *pixm,
686 l_int32 x,
687 l_int32 y,
688 l_int32 factor)
689{
690l_int32 i, j, w, h, d, wm, hm, dm, wpls, wplm, val, size;
691l_uint32 *datas, *datam, *lines, *linem;
692l_float32 *array;
693NUMA *na;
694
695 if (!pixm)
696 return pixGetCmapHistogram(pixs, factor);
697
698 if (!pixs)
699 return (NUMA *)ERROR_PTR("pixs not defined", __func__, NULL);
700 if (pixGetColormap(pixs) == NULL)
701 return (NUMA *)ERROR_PTR("pixs not cmapped", __func__, NULL);
702 pixGetDimensions(pixm, &wm, &hm, &dm);
703 if (dm != 1)
704 return (NUMA *)ERROR_PTR("pixm not 1 bpp", __func__, NULL);
705 if (factor < 1)
706 return (NUMA *)ERROR_PTR("sampling must be >= 1", __func__, NULL);
707 pixGetDimensions(pixs, &w, &h, &d);
708 if (d != 2 && d != 4 && d != 8)
709 return (NUMA *)ERROR_PTR("d not 2, 4 or 8", __func__, NULL);
710
711 size = 1 << d;
712 if ((na = numaCreate(size)) == NULL)
713 return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
714 numaSetCount(na, size); /* all initialized to 0.0 */
715 array = numaGetFArray(na, L_NOCOPY);
716
717 datas = pixGetData(pixs);
718 wpls = pixGetWpl(pixs);
719 datam = pixGetData(pixm);
720 wplm = pixGetWpl(pixm);
721
722 for (i = 0; i < hm; i += factor) {
723 if (y + i < 0 || y + i >= h) continue;
724 lines = datas + (y + i) * wpls;
725 linem = datam + i * wplm;
726 for (j = 0; j < wm; j += factor) {
727 if (x + j < 0 || x + j >= w) continue;
728 if (GET_DATA_BIT(linem, j)) {
729 if (d == 8)
730 val = GET_DATA_BYTE(lines, x + j);
731 else if (d == 4)
732 val = GET_DATA_QBIT(lines, x + j);
733 else /* d == 2 */
734 val = GET_DATA_DIBIT(lines, x + j);
735 array[val] += 1.0;
736 }
737 }
738 }
739
740 return na;
741}
742
743
761NUMA *
763 BOX *box,
764 l_int32 factor)
765{
766l_int32 i, j, bx, by, bw, bh, w, h, d, wpls, val, size;
767l_uint32 *datas, *lines;
768l_float32 *array;
769NUMA *na;
770
771 if (!box)
772 return pixGetCmapHistogram(pixs, factor);
773 if (!pixs)
774 return (NUMA *)ERROR_PTR("pixs not defined", __func__, NULL);
775 if (pixGetColormap(pixs) == NULL)
776 return (NUMA *)ERROR_PTR("pixs not cmapped", __func__, NULL);
777 if (factor < 1)
778 return (NUMA *)ERROR_PTR("sampling must be >= 1", __func__, NULL);
779 pixGetDimensions(pixs, &w, &h, &d);
780 if (d != 2 && d != 4 && d != 8)
781 return (NUMA *)ERROR_PTR("d not 2, 4 or 8", __func__, NULL);
782
783 size = 1 << d;
784 if ((na = numaCreate(size)) == NULL)
785 return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
786 numaSetCount(na, size); /* all initialized to 0.0 */
787 array = numaGetFArray(na, L_NOCOPY);
788
789 datas = pixGetData(pixs);
790 wpls = pixGetWpl(pixs);
791 boxGetGeometry(box, &bx, &by, &bw, &bh);
792
793 for (i = 0; i < bh; i += factor) {
794 if (by + i < 0 || by + i >= h) continue;
795 lines = datas + (by + i) * wpls;
796 for (j = 0; j < bw; j += factor) {
797 if (bx + j < 0 || bx + j >= w) continue;
798 if (d == 8)
799 val = GET_DATA_BYTE(lines, bx + j);
800 else if (d == 4)
801 val = GET_DATA_QBIT(lines, bx + j);
802 else /* d == 2 */
803 val = GET_DATA_DIBIT(lines, bx + j);
804 array[val] += 1.0;
805 }
806 }
807
808 return na;
809}
810
811
825l_ok
827 l_int32 *pncolors)
828{
829L_DNA *da1, *da2;
830
831 if (!pncolors)
832 return ERROR_INT("&ncolors not defined", __func__, 1);
833 *pncolors = 0;
834 if (!pixs || pixGetDepth(pixs) != 32)
835 return ERROR_INT("pixs not defined or not 32 bpp", __func__, 1);
836 da1 = pixConvertDataToDna(pixs);
837 l_dnaRemoveDupsByHmap(da1, &da2, NULL);
838 *pncolors = l_dnaGetCount(da2);
839 l_dnaDestroy(&da1);
840 l_dnaDestroy(&da2);
841 return 0;
842}
843
844
859l_ok
861 l_int32 factor,
862 l_int32 *pncolors)
863{
864L_AMAP *amap;
865
866 if (!pncolors)
867 return ERROR_INT("&ncolors not defined", __func__, 1);
868 *pncolors = 0;
869 if (!pixs || pixGetDepth(pixs) != 32)
870 return ERROR_INT("pixs not defined or not 32 bpp", __func__, 1);
871 if (factor <= 0)
872 return ERROR_INT("factor must be > 0", __func__, 1);
873 amap = pixGetColorAmapHistogram(pixs, factor);
874 *pncolors = l_amapSize(amap);
875 l_amapDestroy(&amap);
876 return 0;
877}
878
879
893L_AMAP *
895 l_int32 factor)
896{
897l_int32 i, j, w, h, wpl;
898l_uint32 *data, *line;
899L_AMAP *amap;
900RB_TYPE key, value;
901RB_TYPE *pval;
902
903 if (!pixs)
904 return (L_AMAP *)ERROR_PTR("pixs not defined", __func__, NULL);
905 if (pixGetDepth(pixs) != 32)
906 return (L_AMAP *)ERROR_PTR("pixs not 32 bpp", __func__, NULL);
907 if (factor <= 0)
908 return (L_AMAP *)ERROR_PTR("factor must be > 0", __func__, NULL);
909 pixGetDimensions(pixs, &w, &h, NULL);
910 data = pixGetData(pixs);
911 wpl = pixGetWpl(pixs);
912 amap = l_amapCreate(L_UINT_TYPE);
913 for (i = 0; i < h; i += factor) {
914 line = data + i * wpl;
915 for (j = 0; j < w; j += factor) {
916 key.utype = line[j];
917 pval = l_amapFind(amap, key);
918 if (!pval)
919 value.itype = 1;
920 else
921 value.itype = 1 + pval->itype;
922 l_amapInsert(amap, key, value);
923 }
924 }
925
926 return amap;
927}
928
929
942l_int32
944 l_uint32 val)
945{
946RB_TYPE key;
947RB_TYPE *pval;
948
949 if (!amap)
950 return ERROR_INT("amap not defined", __func__, -1);
951
952 key.utype = val;
953 pval = l_amapFind(amap, key);
954 return (pval) ? pval->itype : 0;
955}
956
957
979l_ok
981 l_int32 factor,
982 l_float32 rank,
983 l_uint32 *pvalue)
984{
985l_int32 d;
986l_float32 val, rval, gval, bval;
987PIX *pixt;
988PIXCMAP *cmap;
989
990 if (!pvalue)
991 return ERROR_INT("&value not defined", __func__, 1);
992 *pvalue = 0;
993 if (!pixs)
994 return ERROR_INT("pixs not defined", __func__, 1);
995 d = pixGetDepth(pixs);
996 cmap = pixGetColormap(pixs);
997 if (d != 8 && d != 32 && !cmap)
998 return ERROR_INT("pixs not 8 or 32 bpp, or cmapped", __func__, 1);
999 if (cmap)
1000 pixt = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC);
1001 else
1002 pixt = pixClone(pixs);
1003 d = pixGetDepth(pixt);
1004
1005 if (d == 8) {
1006 pixGetRankValueMasked(pixt, NULL, 0, 0, factor, rank, &val, NULL);
1007 *pvalue = lept_roundftoi(val);
1008 } else {
1009 pixGetRankValueMaskedRGB(pixt, NULL, 0, 0, factor, rank,
1010 &rval, &gval, &bval);
1011 composeRGBPixel(lept_roundftoi(rval), lept_roundftoi(gval),
1012 lept_roundftoi(bval), pvalue);
1013 }
1014
1015 pixDestroy(&pixt);
1016 return 0;
1017}
1018
1019
1047l_ok
1049 PIX *pixm,
1050 l_int32 x,
1051 l_int32 y,
1052 l_int32 factor,
1053 l_float32 rank,
1054 l_float32 *prval,
1055 l_float32 *pgval,
1056 l_float32 *pbval)
1057{
1058l_float32 scale;
1059PIX *pixmt, *pixt;
1060
1061 if (prval) *prval = 0.0;
1062 if (pgval) *pgval = 0.0;
1063 if (pbval) *pbval = 0.0;
1064 if (!prval && !pgval && !pbval)
1065 return ERROR_INT("no results requested", __func__, 1);
1066 if (!pixs)
1067 return ERROR_INT("pixs not defined", __func__, 1);
1068 if (pixGetDepth(pixs) != 32)
1069 return ERROR_INT("pixs not 32 bpp", __func__, 1);
1070 if (pixm && pixGetDepth(pixm) != 1)
1071 return ERROR_INT("pixm not 1 bpp", __func__, 1);
1072 if (factor < 1)
1073 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
1074 if (rank < 0.0 || rank > 1.0)
1075 return ERROR_INT("rank not in [0.0 ... 1.0]", __func__, 1);
1076
1077 pixmt = NULL;
1078 if (pixm) {
1079 scale = 1.0f / (l_float32)factor;
1080 pixmt = pixScale(pixm, scale, scale);
1081 }
1082 if (prval) {
1083 pixt = pixScaleRGBToGrayFast(pixs, factor, COLOR_RED);
1084 pixGetRankValueMasked(pixt, pixmt, x / factor, y / factor,
1085 factor, rank, prval, NULL);
1086 pixDestroy(&pixt);
1087 }
1088 if (pgval) {
1089 pixt = pixScaleRGBToGrayFast(pixs, factor, COLOR_GREEN);
1090 pixGetRankValueMasked(pixt, pixmt, x / factor, y / factor,
1091 factor, rank, pgval, NULL);
1092 pixDestroy(&pixt);
1093 }
1094 if (pbval) {
1095 pixt = pixScaleRGBToGrayFast(pixs, factor, COLOR_BLUE);
1096 pixGetRankValueMasked(pixt, pixmt, x / factor, y / factor,
1097 factor, rank, pbval, NULL);
1098 pixDestroy(&pixt);
1099 }
1100 pixDestroy(&pixmt);
1101 return 0;
1102}
1103
1104
1137l_ok
1139 PIX *pixm,
1140 l_int32 x,
1141 l_int32 y,
1142 l_int32 factor,
1143 l_float32 rank,
1144 l_float32 *pval,
1145 NUMA **pna)
1146{
1147NUMA *na;
1148
1149 if (pna) *pna = NULL;
1150 if (!pval)
1151 return ERROR_INT("&val not defined", __func__, 1);
1152 *pval = 0.0;
1153 if (!pixs)
1154 return ERROR_INT("pixs not defined", __func__, 1);
1155 if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
1156 return ERROR_INT("pixs neither 8 bpp nor colormapped", __func__, 1);
1157 if (pixm && pixGetDepth(pixm) != 1)
1158 return ERROR_INT("pixm not 1 bpp", __func__, 1);
1159 if (factor < 1)
1160 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
1161 if (rank < 0.0 || rank > 1.0)
1162 return ERROR_INT("rank not in [0.0 ... 1.0]", __func__, 1);
1163
1164 if ((na = pixGetGrayHistogramMasked(pixs, pixm, x, y, factor)) == NULL)
1165 return ERROR_INT("na not made", __func__, 1);
1166 numaHistogramGetValFromRank(na, rank, pval);
1167 if (pna)
1168 *pna = na;
1169 else
1170 numaDestroy(&na);
1171
1172 return 0;
1173}
1174
1175
1206l_ok
1208 PIX *pixm,
1209 l_int32 x,
1210 l_int32 y,
1211 l_int32 factor,
1212 l_uint32 *pval)
1213{
1214l_int32 i, j, w, h, d, wm, hm, wpl1, wplm, val, rval, gval, bval, count;
1215l_uint32 *data1, *datam, *line1, *linem;
1216l_float64 sum, rsum, gsum, bsum;
1217PIX *pix1;
1218
1219 if (!pval)
1220 return ERROR_INT("&val not defined", __func__, 1);
1221 *pval = 0;
1222 if (!pixs)
1223 return ERROR_INT("pixs not defined", __func__, 1);
1224 d = pixGetDepth(pixs);
1225 if (d != 32 && !pixGetColormap(pixs))
1226 return ERROR_INT("pixs not rgb or colormapped", __func__, 1);
1227 if (pixm && pixGetDepth(pixm) != 1)
1228 return ERROR_INT("pixm not 1 bpp", __func__, 1);
1229 if (factor < 1)
1230 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
1231
1232 if (pixGetColormap(pixs))
1233 pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC);
1234 else
1235 pix1 = pixClone(pixs);
1236 pixGetDimensions(pix1, &w, &h, &d);
1237 if (d == 1) {
1238 pixDestroy(&pix1);
1239 return ERROR_INT("pix1 is just 1 bpp", __func__, 1);
1240 }
1241 data1 = pixGetData(pix1);
1242 wpl1 = pixGetWpl(pix1);
1243
1244 sum = rsum = gsum = bsum = 0.0;
1245 count = 0;
1246 if (!pixm) {
1247 for (i = 0; i < h; i += factor) {
1248 line1 = data1 + i * wpl1;
1249 for (j = 0; j < w; j += factor) {
1250 if (d == 8) {
1251 val = GET_DATA_BYTE(line1, j);
1252 sum += val;
1253 } else { /* rgb */
1254 extractRGBValues(*(line1 + j), &rval, &gval, &bval);
1255 rsum += rval;
1256 gsum += gval;
1257 bsum += bval;
1258 }
1259 count++;
1260 }
1261 }
1262 } else { /* masked */
1263 pixGetDimensions(pixm, &wm, &hm, NULL);
1264 datam = pixGetData(pixm);
1265 wplm = pixGetWpl(pixm);
1266 for (i = 0; i < hm; i += factor) {
1267 if (y + i < 0 || y + i >= h) continue;
1268 line1 = data1 + (y + i) * wpl1;
1269 linem = datam + i * wplm;
1270 for (j = 0; j < wm; j += factor) {
1271 if (x + j < 0 || x + j >= w) continue;
1272 if (GET_DATA_BIT(linem, j)) {
1273 if (d == 8) {
1274 val = GET_DATA_BYTE(line1, x + j);
1275 sum += val;
1276 } else { /* rgb */
1277 extractRGBValues(*(line1 + x + j), &rval, &gval, &bval);
1278 rsum += rval;
1279 gsum += gval;
1280 bsum += bval;
1281 }
1282 count++;
1283 }
1284 }
1285 }
1286 }
1287
1288 pixDestroy(&pix1);
1289 if (count == 0)
1290 return ERROR_INT("no pixels sampled", __func__, 1);
1291 if (d == 8) {
1292 *pval = (l_uint32)(sum / (l_float64)count);
1293 } else { /* d == 32 */
1294 rval = (l_uint32)(rsum / (l_float64)count);
1295 gval = (l_uint32)(gsum / (l_float64)count);
1296 bval = (l_uint32)(bsum / (l_float64)count);
1297 composeRGBPixel(rval, gval, bval, pval);
1298 }
1299
1300 return 0;
1301}
1302
1303
1322l_ok
1324 l_int32 factor,
1325 l_int32 type,
1326 l_uint32 *pvalue)
1327{
1328l_int32 d;
1329l_float32 val, rval, gval, bval;
1330PIX *pixt;
1331PIXCMAP *cmap;
1332
1333 if (!pvalue)
1334 return ERROR_INT("&value not defined", __func__, 1);
1335 *pvalue = 0;
1336 if (!pixs)
1337 return ERROR_INT("pixs not defined", __func__, 1);
1338 d = pixGetDepth(pixs);
1339 cmap = pixGetColormap(pixs);
1340 if (d != 8 && d != 32 && !cmap)
1341 return ERROR_INT("pixs not 8 or 32 bpp, or cmapped", __func__, 1);
1342 if (cmap)
1343 pixt = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC);
1344 else
1345 pixt = pixClone(pixs);
1346 d = pixGetDepth(pixt);
1347
1348 if (d == 8) {
1349 pixGetAverageMasked(pixt, NULL, 0, 0, factor, type, &val);
1350 *pvalue = lept_roundftoi(val);
1351 } else {
1352 pixGetAverageMaskedRGB(pixt, NULL, 0, 0, factor, type,
1353 &rval, &gval, &bval);
1354 composeRGBPixel(lept_roundftoi(rval), lept_roundftoi(gval),
1355 lept_roundftoi(bval), pvalue);
1356 }
1357
1358 pixDestroy(&pixt);
1359 return 0;
1360}
1361
1362
1387l_ok
1389 PIX *pixm,
1390 l_int32 x,
1391 l_int32 y,
1392 l_int32 factor,
1393 l_int32 type,
1394 l_float32 *prval,
1395 l_float32 *pgval,
1396 l_float32 *pbval)
1397{
1398l_int32 empty;
1399PIX *pixt;
1400PIXCMAP *cmap;
1401
1402 if (prval) *prval = 0.0;
1403 if (pgval) *pgval = 0.0;
1404 if (pbval) *pbval = 0.0;
1405 if (!prval && !pgval && !pbval)
1406 return ERROR_INT("no values requested", __func__, 1);
1407 if (!pixs)
1408 return ERROR_INT("pixs not defined", __func__, 1);
1409 cmap = pixGetColormap(pixs);
1410 if (pixGetDepth(pixs) != 32 && !cmap)
1411 return ERROR_INT("pixs neither 32 bpp nor colormapped", __func__, 1);
1412 if (pixm && pixGetDepth(pixm) != 1)
1413 return ERROR_INT("pixm not 1 bpp", __func__, 1);
1414 if (factor < 1)
1415 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
1416 if (type != L_MEAN_ABSVAL && type != L_ROOT_MEAN_SQUARE &&
1417 type != L_STANDARD_DEVIATION && type != L_VARIANCE)
1418 return ERROR_INT("invalid measure type", __func__, 1);
1419 if (pixm) {
1420 pixZero(pixm, &empty);
1421 if (empty)
1422 return ERROR_INT("empty mask", __func__, 1);
1423 }
1424
1425 if (prval) {
1426 if (cmap)
1427 pixt = pixGetRGBComponentCmap(pixs, COLOR_RED);
1428 else
1429 pixt = pixGetRGBComponent(pixs, COLOR_RED);
1430 pixGetAverageMasked(pixt, pixm, x, y, factor, type, prval);
1431 pixDestroy(&pixt);
1432 }
1433 if (pgval) {
1434 if (cmap)
1435 pixt = pixGetRGBComponentCmap(pixs, COLOR_GREEN);
1436 else
1437 pixt = pixGetRGBComponent(pixs, COLOR_GREEN);
1438 pixGetAverageMasked(pixt, pixm, x, y, factor, type, pgval);
1439 pixDestroy(&pixt);
1440 }
1441 if (pbval) {
1442 if (cmap)
1443 pixt = pixGetRGBComponentCmap(pixs, COLOR_BLUE);
1444 else
1445 pixt = pixGetRGBComponent(pixs, COLOR_BLUE);
1446 pixGetAverageMasked(pixt, pixm, x, y, factor, type, pbval);
1447 pixDestroy(&pixt);
1448 }
1449
1450 return 0;
1451}
1452
1453
1487l_ok
1489 PIX *pixm,
1490 l_int32 x,
1491 l_int32 y,
1492 l_int32 factor,
1493 l_int32 type,
1494 l_float32 *pval)
1495{
1496l_int32 i, j, w, h, d, wm, hm, wplg, wplm, val, count, empty;
1497l_uint32 *datag, *datam, *lineg, *linem;
1498l_float64 sumave, summs, ave, meansq, var;
1499PIX *pixg;
1500
1501 if (!pval)
1502 return ERROR_INT("&val not defined", __func__, 1);
1503 *pval = 0.0;
1504 if (!pixs)
1505 return ERROR_INT("pixs not defined", __func__, 1);
1506 d = pixGetDepth(pixs);
1507 if (d != 8 && d != 16 && !pixGetColormap(pixs))
1508 return ERROR_INT("pixs not 8 or 16 bpp or colormapped", __func__, 1);
1509 if (pixm && pixGetDepth(pixm) != 1)
1510 return ERROR_INT("pixm not 1 bpp", __func__, 1);
1511 if (factor < 1)
1512 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
1513 if (type != L_MEAN_ABSVAL && type != L_ROOT_MEAN_SQUARE &&
1514 type != L_STANDARD_DEVIATION && type != L_VARIANCE)
1515 return ERROR_INT("invalid measure type", __func__, 1);
1516 if (pixm) {
1517 pixZero(pixm, &empty);
1518 if (empty)
1519 return ERROR_INT("empty mask", __func__, 1);
1520 }
1521
1522 if (pixGetColormap(pixs))
1523 pixg = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
1524 else
1525 pixg = pixClone(pixs);
1526 pixGetDimensions(pixg, &w, &h, &d);
1527 datag = pixGetData(pixg);
1528 wplg = pixGetWpl(pixg);
1529
1530 sumave = summs = 0.0;
1531 count = 0;
1532 if (!pixm) {
1533 for (i = 0; i < h; i += factor) {
1534 lineg = datag + i * wplg;
1535 for (j = 0; j < w; j += factor) {
1536 if (d == 8)
1537 val = GET_DATA_BYTE(lineg, j);
1538 else /* d == 16 */
1539 val = GET_DATA_TWO_BYTES(lineg, j);
1540 if (type != L_ROOT_MEAN_SQUARE)
1541 sumave += val;
1542 if (type != L_MEAN_ABSVAL)
1543 summs += (l_float64)(val) * val;
1544 count++;
1545 }
1546 }
1547 } else {
1548 pixGetDimensions(pixm, &wm, &hm, NULL);
1549 datam = pixGetData(pixm);
1550 wplm = pixGetWpl(pixm);
1551 for (i = 0; i < hm; i += factor) {
1552 if (y + i < 0 || y + i >= h) continue;
1553 lineg = datag + (y + i) * wplg;
1554 linem = datam + i * wplm;
1555 for (j = 0; j < wm; j += factor) {
1556 if (x + j < 0 || x + j >= w) continue;
1557 if (GET_DATA_BIT(linem, j)) {
1558 if (d == 8)
1559 val = GET_DATA_BYTE(lineg, x + j);
1560 else /* d == 16 */
1561 val = GET_DATA_TWO_BYTES(lineg, x + j);
1562 if (type != L_ROOT_MEAN_SQUARE)
1563 sumave += val;
1564 if (type != L_MEAN_ABSVAL)
1565 summs += (l_float64)(val) * val;
1566 count++;
1567 }
1568 }
1569 }
1570 }
1571
1572 pixDestroy(&pixg);
1573 if (count == 0)
1574 return ERROR_INT("no pixels sampled", __func__, 1);
1575 ave = sumave / (l_float64)count;
1576 meansq = summs / (l_float64)count;
1577 var = meansq - ave * ave;
1578 if (type == L_MEAN_ABSVAL)
1579 *pval = (l_float32)ave;
1580 else if (type == L_ROOT_MEAN_SQUARE)
1581 *pval = (l_float32)sqrt(meansq);
1582 else if (type == L_STANDARD_DEVIATION)
1583 *pval = (l_float32)sqrt(var);
1584 else /* type == L_VARIANCE */
1585 *pval = (l_float32)var;
1586
1587 return 0;
1588}
1589
1590
1609l_ok
1611 l_int32 sx,
1612 l_int32 sy,
1613 l_int32 type,
1614 PIX **ppixr,
1615 PIX **ppixg,
1616 PIX **ppixb)
1617{
1618PIX *pixt;
1619PIXCMAP *cmap;
1620
1621 if (ppixr) *ppixr = NULL;
1622 if (ppixg) *ppixg = NULL;
1623 if (ppixb) *ppixb = NULL;
1624 if (!ppixr && !ppixg && !ppixb)
1625 return ERROR_INT("no data requested", __func__, 1);
1626 if (!pixs)
1627 return ERROR_INT("pixs not defined", __func__, 1);
1628 cmap = pixGetColormap(pixs);
1629 if (pixGetDepth(pixs) != 32 && !cmap)
1630 return ERROR_INT("pixs neither 32 bpp nor colormapped", __func__, 1);
1631 if (sx < 2 || sy < 2)
1632 return ERROR_INT("sx and sy not both > 1", __func__, 1);
1633 if (type != L_MEAN_ABSVAL && type != L_ROOT_MEAN_SQUARE &&
1634 type != L_STANDARD_DEVIATION)
1635 return ERROR_INT("invalid measure type", __func__, 1);
1636
1637 if (ppixr) {
1638 if (cmap)
1639 pixt = pixGetRGBComponentCmap(pixs, COLOR_RED);
1640 else
1641 pixt = pixGetRGBComponent(pixs, COLOR_RED);
1642 *ppixr = pixGetAverageTiled(pixt, sx, sy, type);
1643 pixDestroy(&pixt);
1644 }
1645 if (ppixg) {
1646 if (cmap)
1647 pixt = pixGetRGBComponentCmap(pixs, COLOR_GREEN);
1648 else
1649 pixt = pixGetRGBComponent(pixs, COLOR_GREEN);
1650 *ppixg = pixGetAverageTiled(pixt, sx, sy, type);
1651 pixDestroy(&pixt);
1652 }
1653 if (ppixb) {
1654 if (cmap)
1655 pixt = pixGetRGBComponentCmap(pixs, COLOR_BLUE);
1656 else
1657 pixt = pixGetRGBComponent(pixs, COLOR_BLUE);
1658 *ppixb = pixGetAverageTiled(pixt, sx, sy, type);
1659 pixDestroy(&pixt);
1660 }
1661
1662 return 0;
1663}
1664
1665
1684PIX *
1686 l_int32 sx,
1687 l_int32 sy,
1688 l_int32 type)
1689{
1690l_int32 i, j, k, m, w, h, wd, hd, d, pos, wplt, wpld, valt;
1691l_uint32 *datat, *datad, *linet, *lined, *startt;
1692l_float64 sumave, summs, ave, meansq, normfact;
1693PIX *pixt, *pixd;
1694
1695 if (!pixs)
1696 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1697 pixGetDimensions(pixs, &w, &h, &d);
1698 if (d != 8 && !pixGetColormap(pixs))
1699 return (PIX *)ERROR_PTR("pixs not 8 bpp or cmapped", __func__, NULL);
1700 if (sx < 2 || sy < 2)
1701 return (PIX *)ERROR_PTR("sx and sy not both > 1", __func__, NULL);
1702 wd = w / sx;
1703 hd = h / sy;
1704 if (wd < 1 || hd < 1)
1705 return (PIX *)ERROR_PTR("wd or hd == 0", __func__, NULL);
1706 if (type != L_MEAN_ABSVAL && type != L_ROOT_MEAN_SQUARE &&
1707 type != L_STANDARD_DEVIATION)
1708 return (PIX *)ERROR_PTR("invalid measure type", __func__, NULL);
1709
1710 pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
1711 pixd = pixCreate(wd, hd, 8);
1712 datat = pixGetData(pixt);
1713 wplt = pixGetWpl(pixt);
1714 datad = pixGetData(pixd);
1715 wpld = pixGetWpl(pixd);
1716 normfact = 1. / (l_float64)(sx * sy);
1717 for (i = 0; i < hd; i++) {
1718 lined = datad + i * wpld;
1719 linet = datat + i * sy * wplt;
1720 for (j = 0; j < wd; j++) {
1721 if (type == L_MEAN_ABSVAL || type == L_STANDARD_DEVIATION) {
1722 sumave = 0.0;
1723 for (k = 0; k < sy; k++) {
1724 startt = linet + k * wplt;
1725 for (m = 0; m < sx; m++) {
1726 pos = j * sx + m;
1727 valt = GET_DATA_BYTE(startt, pos);
1728 sumave += valt;
1729 }
1730 }
1731 ave = normfact * sumave;
1732 }
1733 if (type == L_ROOT_MEAN_SQUARE || type == L_STANDARD_DEVIATION) {
1734 summs = 0.0;
1735 for (k = 0; k < sy; k++) {
1736 startt = linet + k * wplt;
1737 for (m = 0; m < sx; m++) {
1738 pos = j * sx + m;
1739 valt = GET_DATA_BYTE(startt, pos);
1740 summs += (l_float64)(valt) * valt;
1741 }
1742 }
1743 meansq = normfact * summs;
1744 }
1745 if (type == L_MEAN_ABSVAL)
1746 valt = (l_int32)(ave + 0.5);
1747 else if (type == L_ROOT_MEAN_SQUARE)
1748 valt = (l_int32)(sqrt(meansq) + 0.5);
1749 else /* type == L_STANDARD_DEVIATION */
1750 valt = (l_int32)(sqrt(meansq - ave * ave) + 0.5);
1751 SET_DATA_BYTE(lined, j, valt);
1752 }
1753 }
1754
1755 pixDestroy(&pixt);
1756 return pixd;
1757}
1758
1759
1785l_int32
1787 BOX *box,
1788 NUMA **pnamean,
1789 NUMA **pnamedian,
1790 NUMA **pnamode,
1791 NUMA **pnamodecount,
1792 NUMA **pnavar,
1793 NUMA **pnarootvar)
1794{
1795l_int32 i, j, k, w, h, val, wpls, sum, sumsq, target, max, modeval;
1796l_int32 xstart, xend, ystart, yend, bw, bh;
1797l_int32 *histo;
1798l_uint32 *lines, *datas;
1799l_float32 norm;
1800l_float32 *famean, *fameansq, *favar, *farootvar;
1801l_float32 *famedian, *famode, *famodecount;
1802
1803 if (pnamean) *pnamean = NULL;
1804 if (pnamedian) *pnamedian = NULL;
1805 if (pnamode) *pnamode = NULL;
1806 if (pnamodecount) *pnamodecount = NULL;
1807 if (pnavar) *pnavar = NULL;
1808 if (pnarootvar) *pnarootvar = NULL;
1809 if (!pixs || pixGetDepth(pixs) != 8)
1810 return ERROR_INT("pixs undefined or not 8 bpp", __func__, 1);
1811 famean = fameansq = favar = farootvar = NULL;
1812 famedian = famode = famodecount = NULL;
1813
1814 pixGetDimensions(pixs, &w, &h, NULL);
1815 if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
1816 &bw, &bh) == 1)
1817 return ERROR_INT("invalid clipping box", __func__, 1);
1818
1819 /* We need the mean for variance and root variance */
1820 datas = pixGetData(pixs);
1821 wpls = pixGetWpl(pixs);
1822 if (pnamean || pnavar || pnarootvar) {
1823 norm = 1.f / (l_float32)bw;
1824 famean = (l_float32 *)LEPT_CALLOC(bh, sizeof(l_float32));
1825 fameansq = (l_float32 *)LEPT_CALLOC(bh, sizeof(l_float32));
1826 if (pnavar || pnarootvar) {
1827 favar = (l_float32 *)LEPT_CALLOC(bh, sizeof(l_float32));
1828 if (pnarootvar)
1829 farootvar = (l_float32 *)LEPT_CALLOC(bh, sizeof(l_float32));
1830 }
1831 for (i = ystart; i < yend; i++) {
1832 sum = sumsq = 0;
1833 lines = datas + i * wpls;
1834 for (j = xstart; j < xend; j++) {
1835 val = GET_DATA_BYTE(lines, j);
1836 sum += val;
1837 sumsq += val * val;
1838 }
1839 famean[i] = norm * sum;
1840 fameansq[i] = norm * sumsq;
1841 if (pnavar || pnarootvar) {
1842 favar[i] = fameansq[i] - famean[i] * famean[i];
1843 if (pnarootvar)
1844 farootvar[i] = sqrtf(favar[i]);
1845 }
1846 }
1847 LEPT_FREE(fameansq);
1848 if (pnamean)
1849 *pnamean = numaCreateFromFArray(famean, bh, L_INSERT);
1850 else
1851 LEPT_FREE(famean);
1852 if (pnavar)
1853 *pnavar = numaCreateFromFArray(favar, bh, L_INSERT);
1854 else
1855 LEPT_FREE(favar);
1856 if (pnarootvar)
1857 *pnarootvar = numaCreateFromFArray(farootvar, bh, L_INSERT);
1858 }
1859
1860 /* We need a histogram to find the median and/or mode values */
1861 if (pnamedian || pnamode || pnamodecount) {
1862 histo = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1863 if (pnamedian) {
1864 *pnamedian = numaMakeConstant(0, bh);
1865 famedian = numaGetFArray(*pnamedian, L_NOCOPY);
1866 }
1867 if (pnamode) {
1868 *pnamode = numaMakeConstant(0, bh);
1869 famode = numaGetFArray(*pnamode, L_NOCOPY);
1870 }
1871 if (pnamodecount) {
1872 *pnamodecount = numaMakeConstant(0, bh);
1873 famodecount = numaGetFArray(*pnamodecount, L_NOCOPY);
1874 }
1875 for (i = ystart; i < yend; i++) {
1876 lines = datas + i * wpls;
1877 memset(histo, 0, 1024);
1878 for (j = xstart; j < xend; j++) {
1879 val = GET_DATA_BYTE(lines, j);
1880 histo[val]++;
1881 }
1882
1883 if (pnamedian) {
1884 sum = 0;
1885 target = (bw + 1) / 2;
1886 for (k = 0; k < 256; k++) {
1887 sum += histo[k];
1888 if (sum >= target) {
1889 famedian[i] = k;
1890 break;
1891 }
1892 }
1893 }
1894
1895 if (pnamode || pnamodecount) {
1896 max = 0;
1897 modeval = 0;
1898 for (k = 0; k < 256; k++) {
1899 if (histo[k] > max) {
1900 max = histo[k];
1901 modeval = k;
1902 }
1903 }
1904 if (pnamode)
1905 famode[i] = modeval;
1906 if (pnamodecount)
1907 famodecount[i] = max;
1908 }
1909 }
1910 LEPT_FREE(histo);
1911 }
1912
1913 return 0;
1914}
1915
1916
1943l_int32
1945 BOX *box,
1946 NUMA **pnamean,
1947 NUMA **pnamedian,
1948 NUMA **pnamode,
1949 NUMA **pnamodecount,
1950 NUMA **pnavar,
1951 NUMA **pnarootvar)
1952{
1953l_int32 i, j, k, w, h, val, wpls, sum, sumsq, target, max, modeval;
1954l_int32 xstart, xend, ystart, yend, bw, bh;
1955l_int32 *histo;
1956l_uint32 *lines, *datas;
1957l_float32 norm;
1958l_float32 *famean, *fameansq, *favar, *farootvar;
1959l_float32 *famedian, *famode, *famodecount;
1960
1961 if (pnamean) *pnamean = NULL;
1962 if (pnamedian) *pnamedian = NULL;
1963 if (pnamode) *pnamode = NULL;
1964 if (pnamodecount) *pnamodecount = NULL;
1965 if (pnavar) *pnavar = NULL;
1966 if (pnarootvar) *pnarootvar = NULL;
1967 if (!pixs || pixGetDepth(pixs) != 8)
1968 return ERROR_INT("pixs undefined or not 8 bpp", __func__, 1);
1969 famean = fameansq = favar = farootvar = NULL;
1970 famedian = famode = famodecount = NULL;
1971
1972 pixGetDimensions(pixs, &w, &h, NULL);
1973 if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
1974 &bw, &bh) == 1)
1975 return ERROR_INT("invalid clipping box", __func__, 1);
1976
1977 /* We need the mean for variance and root variance */
1978 datas = pixGetData(pixs);
1979 wpls = pixGetWpl(pixs);
1980 if (pnamean || pnavar || pnarootvar) {
1981 norm = 1.f / (l_float32)bh;
1982 famean = (l_float32 *)LEPT_CALLOC(bw, sizeof(l_float32));
1983 fameansq = (l_float32 *)LEPT_CALLOC(bw, sizeof(l_float32));
1984 if (pnavar || pnarootvar) {
1985 favar = (l_float32 *)LEPT_CALLOC(bw, sizeof(l_float32));
1986 if (pnarootvar)
1987 farootvar = (l_float32 *)LEPT_CALLOC(bw, sizeof(l_float32));
1988 }
1989 for (j = xstart; j < xend; j++) {
1990 sum = sumsq = 0;
1991 for (i = ystart, lines = datas; i < yend; lines += wpls, i++) {
1992 val = GET_DATA_BYTE(lines, j);
1993 sum += val;
1994 sumsq += val * val;
1995 }
1996 famean[j] = norm * sum;
1997 fameansq[j] = norm * sumsq;
1998 if (pnavar || pnarootvar) {
1999 favar[j] = fameansq[j] - famean[j] * famean[j];
2000 if (pnarootvar)
2001 farootvar[j] = sqrtf(favar[j]);
2002 }
2003 }
2004 LEPT_FREE(fameansq);
2005 if (pnamean)
2006 *pnamean = numaCreateFromFArray(famean, bw, L_INSERT);
2007 else
2008 LEPT_FREE(famean);
2009 if (pnavar)
2010 *pnavar = numaCreateFromFArray(favar, bw, L_INSERT);
2011 else
2012 LEPT_FREE(favar);
2013 if (pnarootvar)
2014 *pnarootvar = numaCreateFromFArray(farootvar, bw, L_INSERT);
2015 }
2016
2017 /* We need a histogram to find the median and/or mode values */
2018 if (pnamedian || pnamode || pnamodecount) {
2019 histo = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
2020 if (pnamedian) {
2021 *pnamedian = numaMakeConstant(0, bw);
2022 famedian = numaGetFArray(*pnamedian, L_NOCOPY);
2023 }
2024 if (pnamode) {
2025 *pnamode = numaMakeConstant(0, bw);
2026 famode = numaGetFArray(*pnamode, L_NOCOPY);
2027 }
2028 if (pnamodecount) {
2029 *pnamodecount = numaMakeConstant(0, bw);
2030 famodecount = numaGetFArray(*pnamodecount, L_NOCOPY);
2031 }
2032 for (j = xstart; j < xend; j++) {
2033 memset(histo, 0, 1024);
2034 for (i = ystart, lines = datas; i < yend; lines += wpls, i++) {
2035 val = GET_DATA_BYTE(lines, j);
2036 histo[val]++;
2037 }
2038
2039 if (pnamedian) {
2040 sum = 0;
2041 target = (bh + 1) / 2;
2042 for (k = 0; k < 256; k++) {
2043 sum += histo[k];
2044 if (sum >= target) {
2045 famedian[j] = k;
2046 break;
2047 }
2048 }
2049 }
2050
2051 if (pnamode || pnamodecount) {
2052 max = 0;
2053 modeval = 0;
2054 for (k = 0; k < 256; k++) {
2055 if (histo[k] > max) {
2056 max = histo[k];
2057 modeval = k;
2058 }
2059 }
2060 if (pnamode)
2061 famode[j] = modeval;
2062 if (pnamodecount)
2063 famodecount[j] = max;
2064 }
2065 }
2066 LEPT_FREE(histo);
2067 }
2068
2069 return 0;
2070}
2071
2072
2088l_ok
2090 l_int32 factor,
2091 l_int32 color,
2092 l_int32 *pminval,
2093 l_int32 *pmaxval)
2094{
2095l_int32 d;
2096PIXCMAP *cmap;
2097
2098 if (pminval) *pminval = 0;
2099 if (pmaxval) *pmaxval = 0;
2100 if (!pminval && !pmaxval)
2101 return ERROR_INT("no result requested", __func__, 1);
2102 if (!pixs)
2103 return ERROR_INT("pixs not defined", __func__, 1);
2104
2105 cmap = pixGetColormap(pixs);
2106 if (cmap)
2107 return pixcmapGetRangeValues(cmap, color, pminval, pmaxval,
2108 NULL, NULL);
2109
2110 if (factor < 1)
2111 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
2112 d = pixGetDepth(pixs);
2113 if (d != 8 && d != 32)
2114 return ERROR_INT("pixs not 8 or 32 bpp", __func__, 1);
2115
2116 if (d == 8) {
2117 pixGetExtremeValue(pixs, factor, L_SELECT_MIN,
2118 NULL, NULL, NULL, pminval);
2119 pixGetExtremeValue(pixs, factor, L_SELECT_MAX,
2120 NULL, NULL, NULL, pmaxval);
2121 } else if (color == L_SELECT_RED) {
2122 pixGetExtremeValue(pixs, factor, L_SELECT_MIN,
2123 pminval, NULL, NULL, NULL);
2124 pixGetExtremeValue(pixs, factor, L_SELECT_MAX,
2125 pmaxval, NULL, NULL, NULL);
2126 } else if (color == L_SELECT_GREEN) {
2127 pixGetExtremeValue(pixs, factor, L_SELECT_MIN,
2128 NULL, pminval, NULL, NULL);
2129 pixGetExtremeValue(pixs, factor, L_SELECT_MAX,
2130 NULL, pmaxval, NULL, NULL);
2131 } else if (color == L_SELECT_BLUE) {
2132 pixGetExtremeValue(pixs, factor, L_SELECT_MIN,
2133 NULL, NULL, pminval, NULL);
2134 pixGetExtremeValue(pixs, factor, L_SELECT_MAX,
2135 NULL, NULL, pmaxval, NULL);
2136 } else {
2137 return ERROR_INT("invalid color", __func__, 1);
2138 }
2139
2140 return 0;
2141}
2142
2143
2164l_ok
2166 l_int32 factor,
2167 l_int32 type,
2168 l_int32 *prval,
2169 l_int32 *pgval,
2170 l_int32 *pbval,
2171 l_int32 *pgrayval)
2172{
2173l_int32 i, j, w, h, d, wpl;
2174l_int32 val, extval, rval, gval, bval, extrval, extgval, extbval;
2175l_uint32 pixel;
2176l_uint32 *data, *line;
2177PIXCMAP *cmap;
2178
2179 if (prval) *prval = -1;
2180 if (pgval) *pgval = -1;
2181 if (pbval) *pbval = -1;
2182 if (pgrayval) *pgrayval = -1;
2183 if (!pixs)
2184 return ERROR_INT("pixs not defined", __func__, 1);
2185 if (type != L_SELECT_MIN && type != L_SELECT_MAX)
2186 return ERROR_INT("invalid type", __func__, 1);
2187
2188 cmap = pixGetColormap(pixs);
2189 if (cmap) {
2190 if (type == L_SELECT_MIN) {
2191 if (prval) pixcmapGetRangeValues(cmap, L_SELECT_RED, prval, NULL,
2192 NULL, NULL);
2193 if (pgval) pixcmapGetRangeValues(cmap, L_SELECT_GREEN, pgval, NULL,
2194 NULL, NULL);
2195 if (pbval) pixcmapGetRangeValues(cmap, L_SELECT_BLUE, pbval, NULL,
2196 NULL, NULL);
2197 } else { /* type == L_SELECT_MAX */
2198 if (prval) pixcmapGetRangeValues(cmap, L_SELECT_RED, NULL, prval,
2199 NULL, NULL);
2200 if (pgval) pixcmapGetRangeValues(cmap, L_SELECT_GREEN, NULL, pgval,
2201 NULL, NULL);
2202 if (pbval) pixcmapGetRangeValues(cmap, L_SELECT_BLUE, NULL, pbval,
2203 NULL, NULL);
2204 }
2205 return 0;
2206 }
2207
2208 pixGetDimensions(pixs, &w, &h, &d);
2209 if (factor < 1)
2210 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
2211 if (d != 8 && d != 32)
2212 return ERROR_INT("pixs not 8 or 32 bpp", __func__, 1);
2213 if (d == 8 && !pgrayval)
2214 return ERROR_INT("can't return result in grayval", __func__, 1);
2215 if (d == 32 && !prval && !pgval && !pbval)
2216 return ERROR_INT("can't return result in r/g/b-val", __func__, 1);
2217
2218 data = pixGetData(pixs);
2219 wpl = pixGetWpl(pixs);
2220 if (d == 8) {
2221 if (type == L_SELECT_MIN)
2222 extval = 100000;
2223 else /* get max */
2224 extval = -1;
2225
2226 for (i = 0; i < h; i += factor) {
2227 line = data + i * wpl;
2228 for (j = 0; j < w; j += factor) {
2229 val = GET_DATA_BYTE(line, j);
2230 if ((type == L_SELECT_MIN && val < extval) ||
2231 (type == L_SELECT_MAX && val > extval))
2232 extval = val;
2233 }
2234 }
2235 *pgrayval = extval;
2236 return 0;
2237 }
2238
2239 /* 32 bpp rgb */
2240 if (type == L_SELECT_MIN) {
2241 extrval = 100000;
2242 extgval = 100000;
2243 extbval = 100000;
2244 } else {
2245 extrval = -1;
2246 extgval = -1;
2247 extbval = -1;
2248 }
2249 for (i = 0; i < h; i += factor) {
2250 line = data + i * wpl;
2251 for (j = 0; j < w; j += factor) {
2252 pixel = line[j];
2253 if (prval) {
2254 rval = (pixel >> L_RED_SHIFT) & 0xff;
2255 if ((type == L_SELECT_MIN && rval < extrval) ||
2256 (type == L_SELECT_MAX && rval > extrval))
2257 extrval = rval;
2258 }
2259 if (pgval) {
2260 gval = (pixel >> L_GREEN_SHIFT) & 0xff;
2261 if ((type == L_SELECT_MIN && gval < extgval) ||
2262 (type == L_SELECT_MAX && gval > extgval))
2263 extgval = gval;
2264 }
2265 if (pbval) {
2266 bval = (pixel >> L_BLUE_SHIFT) & 0xff;
2267 if ((type == L_SELECT_MIN && bval < extbval) ||
2268 (type == L_SELECT_MAX && bval > extbval))
2269 extbval = bval;
2270 }
2271 }
2272 }
2273 if (prval) *prval = extrval;
2274 if (pgval) *pgval = extgval;
2275 if (pbval) *pbval = extbval;
2276 return 0;
2277}
2278
2279
2299l_ok
2301 BOX *box,
2302 l_uint32 *pmaxval,
2303 l_int32 *pxmax,
2304 l_int32 *pymax)
2305{
2306l_int32 i, j, w, h, d, wpl, bw, bh;
2307l_int32 xstart, ystart, xend, yend, xmax, ymax;
2308l_uint32 val, maxval;
2309l_uint32 *data, *line;
2310
2311 if (pmaxval) *pmaxval = 0;
2312 if (pxmax) *pxmax = 0;
2313 if (pymax) *pymax = 0;
2314 if (!pmaxval && !pxmax && !pymax)
2315 return ERROR_INT("no data requested", __func__, 1);
2316 if (!pixs)
2317 return ERROR_INT("pixs not defined", __func__, 1);
2318 if (pixGetColormap(pixs) != NULL)
2319 return ERROR_INT("pixs has colormap", __func__, 1);
2320 pixGetDimensions(pixs, &w, &h, &d);
2321 if (d != 8 && d != 16 && d != 32)
2322 return ERROR_INT("pixs not 8, 16 or 32 bpp", __func__, 1);
2323
2324 xstart = ystart = 0;
2325 xend = w - 1;
2326 yend = h - 1;
2327 if (box) {
2328 boxGetGeometry(box, &xstart, &ystart, &bw, &bh);
2329 xend = xstart + bw - 1;
2330 yend = ystart + bh - 1;
2331 }
2332
2333 data = pixGetData(pixs);
2334 wpl = pixGetWpl(pixs);
2335 maxval = 0;
2336 xmax = ymax = 0;
2337 for (i = ystart; i <= yend; i++) {
2338 line = data + i * wpl;
2339 for (j = xstart; j <= xend; j++) {
2340 if (d == 8)
2341 val = GET_DATA_BYTE(line, j);
2342 else if (d == 16)
2343 val = GET_DATA_TWO_BYTES(line, j);
2344 else /* d == 32 */
2345 val = line[j];
2346 if (val > maxval) {
2347 maxval = val;
2348 xmax = j;
2349 ymax = i;
2350 }
2351 }
2352 }
2353 if (maxval == 0) { /* no counts; pick the center of the rectangle */
2354 xmax = (xstart + xend) / 2;
2355 ymax = (ystart + yend) / 2;
2356 }
2357
2358 if (pmaxval) *pmaxval = maxval;
2359 if (pxmax) *pxmax = xmax;
2360 if (pymax) *pymax = ymax;
2361 return 0;
2362}
2363
2364
2372l_ok
2374 l_int32 *pmaxindex)
2375{
2376l_int32 i, j, w, h, d, wpl, val, max, maxval, empty;
2377l_uint32 *data, *line;
2378
2379 if (!pmaxindex)
2380 return ERROR_INT("&maxindex not defined", __func__, 1);
2381 *pmaxindex = 0;
2382 if (!pixs)
2383 return ERROR_INT("pixs not defined", __func__, 1);
2384 pixGetDimensions(pixs, &w, &h, &d);
2385 if (d != 1 && d != 2 && d != 4 && d != 8)
2386 return ERROR_INT("invalid pixs depth; not in (1,2,4,8}", __func__, 1);
2387
2388 wpl = pixGetWpl(pixs);
2389 data = pixGetData(pixs);
2390 max = 0;
2391 maxval = (1 << d) - 1;
2392 if (d == 1) {
2393 pixZero(pixs, &empty);
2394 if (!empty) max = 1;
2395 *pmaxindex = max;
2396 return 0;
2397 }
2398 for (i = 0; i < h; i++) {
2399 line = data + i * wpl;
2400 if (d == 2) {
2401 for (j = 0; j < w; j++) {
2402 val = GET_DATA_DIBIT(line, j);
2403 if (val > max) max = val;
2404 }
2405 } else if (d == 4) {
2406 for (j = 0; j < w; j++) {
2407 val = GET_DATA_QBIT(line, j);
2408 if (val > max) max = val;
2409 }
2410 } else if (d == 8) {
2411 for (j = 0; j < w; j++) {
2412 val = GET_DATA_BYTE(line, j);
2413 if (val > max) max = val;
2414 }
2415 }
2416 if (max == maxval) break;
2417 }
2418 *pmaxindex = max;
2419 return 0;
2420}
2421
2422
2444l_ok
2446 l_int32 nbins,
2447 l_int32 factor,
2448 l_int32 color,
2449 l_int32 *pminval,
2450 l_int32 *pmaxval,
2451 l_uint32 **pcarray,
2452 l_int32 fontsize)
2453{
2454l_int32 i, minval, maxval, rval, gval, bval;
2455l_uint32 *carray;
2456PIX *pixt;
2457
2458 if (pminval) *pminval = 0;
2459 if (pmaxval) *pmaxval = 0;
2460 if (pcarray) *pcarray = NULL;
2461 if (!pminval && !pmaxval)
2462 return ERROR_INT("no result requested", __func__, 1);
2463 if (!pixs || pixGetDepth(pixs) != 32)
2464 return ERROR_INT("pixs not defined or not 32 bpp", __func__, 1);
2465 if (factor < 1)
2466 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
2467 if (color != L_SELECT_RED && color != L_SELECT_GREEN &&
2468 color != L_SELECT_BLUE)
2469 return ERROR_INT("invalid color", __func__, 1);
2470 if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2471 return ERROR_INT("invalid fontsize", __func__, 1);
2472
2473 pixGetRankColorArray(pixs, nbins, color, factor, &carray, NULL, 0);
2474 if (!carray)
2475 return ERROR_INT("carray not made", __func__, 1);
2476
2477 if (fontsize > 0) {
2478 for (i = 0; i < nbins; i++)
2479 L_INFO("c[%d] = %x\n", __func__, i, carray[i]);
2480 pixt = pixDisplayColorArray(carray, nbins, 200, 5, fontsize);
2481 pixDisplay(pixt, 100, 100);
2482 pixDestroy(&pixt);
2483 }
2484
2485 extractRGBValues(carray[0], &rval, &gval, &bval);
2486 minval = rval;
2487 if (color == L_SELECT_GREEN)
2488 minval = gval;
2489 else if (color == L_SELECT_BLUE)
2490 minval = bval;
2491 extractRGBValues(carray[nbins - 1], &rval, &gval, &bval);
2492 maxval = rval;
2493 if (color == L_SELECT_GREEN)
2494 maxval = gval;
2495 else if (color == L_SELECT_BLUE)
2496 maxval = bval;
2497
2498 if (pminval) *pminval = minval;
2499 if (pmaxval) *pmaxval = maxval;
2500 if (pcarray)
2501 *pcarray = carray;
2502 else
2503 LEPT_FREE(carray);
2504 return 0;
2505}
2506
2507
2541l_ok
2543 l_int32 nbins,
2544 l_int32 type,
2545 l_int32 factor,
2546 l_uint32 **pcarray,
2547 PIXA *pixadb,
2548 l_int32 fontsize)
2549{
2550l_int32 ret, w, h, samplesperbin;
2551l_uint32 *array;
2552PIX *pix1, *pixc, *pixg, *pixd;
2553PIXCMAP *cmap;
2554
2555 if (!pcarray)
2556 return ERROR_INT("&carray not defined", __func__, 1);
2557 *pcarray = NULL;
2558 if (factor < 1)
2559 return ERROR_INT("sampling factor must be >= 1", __func__, 1);
2560 if (nbins < 2)
2561 return ERROR_INT("nbins must be at least 2", __func__, 1);
2562 if (!pixs)
2563 return ERROR_INT("pixs not defined", __func__, 1);
2564 cmap = pixGetColormap(pixs);
2565 if (pixGetDepth(pixs) != 32 && !cmap)
2566 return ERROR_INT("pixs neither 32 bpp nor cmapped", __func__, 1);
2567 if (type != L_SELECT_RED && type != L_SELECT_GREEN &&
2568 type != L_SELECT_BLUE && type != L_SELECT_MIN &&
2569 type != L_SELECT_MAX && type != L_SELECT_AVERAGE &&
2570 type != L_SELECT_HUE && type != L_SELECT_SATURATION)
2571 return ERROR_INT("invalid type", __func__, 1);
2572 if (pixadb) {
2573 if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2) {
2574 L_WARNING("invalid fontsize %d; setting to 6\n", __func__,
2575 fontsize);
2576 fontsize = 6;
2577 }
2578 }
2579 pixGetDimensions(pixs, &w, &h, NULL);
2580 samplesperbin = (w * h) / (factor * factor * nbins);
2581 if (samplesperbin < 10) {
2582 L_ERROR("samplesperbin = %d < 10\n", __func__, samplesperbin);
2583 return 1;
2584 }
2585
2586 /* Downscale by factor and remove colormap if it exists */
2587 pix1 = pixScaleByIntSampling(pixs, factor);
2588 if (cmap)
2589 pixc = pixRemoveColormap(pix1, REMOVE_CMAP_TO_FULL_COLOR);
2590 else
2591 pixc = pixClone(pix1);
2592 pixDestroy(&pix1);
2593
2594 /* Convert to an 8 bit version for ordering the pixels */
2595 pixg = pixConvertRGBToGrayGeneral(pixc, type, 0.0, 0.0, 0.0);
2596
2597 /* Get the average color in each bin for pixels whose grayscale
2598 * values are in the range for that bin. */
2599 pixGetBinnedColor(pixc, pixg, 1, nbins, pcarray, pixadb);
2600 ret = 0;
2601 if ((array = *pcarray) == NULL) {
2602 L_ERROR("color array not returned\n", __func__);
2603 ret = 1;
2604 }
2605 if (array && pixadb) {
2606 pixd = pixDisplayColorArray(array, nbins, 200, 5, fontsize);
2607 pixWriteDebug("/tmp/lept/regout/rankhisto.png", pixd, IFF_PNG);
2608 pixDestroy(&pixd);
2609 }
2610
2611 pixDestroy(&pixc);
2612 pixDestroy(&pixg);
2613 return ret;
2614}
2615
2616
2644l_ok
2646 PIX *pixg,
2647 l_int32 factor,
2648 l_int32 nbins,
2649 l_uint32 **pcarray,
2650 PIXA *pixadb)
2651{
2652l_int32 i, j, w, h, wpls, wplg;
2653l_int32 count, bincount, binindex, binsize, npts, avepts, ntot;
2654l_int32 rval, gval, bval, grayval, rave, gave, bave;
2655l_uint32 *datas, *datag, *lines, *lineg, *carray;
2656l_float64 val64, rsum, gsum, bsum;
2657L_DNAA *daa;
2658NUMA *naeach;
2659PIX *pix1;
2660
2661 if (!pcarray)
2662 return ERROR_INT("&carray not defined", __func__, 1);
2663 *pcarray = NULL;
2664 if (!pixs || pixGetDepth(pixs) != 32)
2665 return ERROR_INT("pixs undefined or not 32 bpp", __func__, 1);
2666 if (!pixg || pixGetDepth(pixg) != 8)
2667 return ERROR_INT("pixg undefined or not 8 bpp", __func__, 1);
2668 if (factor < 1) {
2669 L_WARNING("sampling factor less than 1; setting to 1\n", __func__);
2670 factor = 1;
2671 }
2672 if (nbins < 1 || nbins > 100)
2673 return ERROR_INT("nbins not in [1,100]", __func__, 1);
2674
2675 /* Require that each bin has at least 5 pixels. */
2676 pixGetDimensions(pixs, &w, &h, NULL);
2677 npts = (w + factor - 1) * (h + factor - 1) / (factor * factor);
2678 avepts = (npts + nbins - 1) / nbins; /* average number of pts in a bin */
2679 if (avepts < 5) {
2680 L_ERROR("avepts = %d; must be >= 5\n", __func__, avepts);
2681 return 1;
2682 }
2683
2684 /* ------------------------------------------------------------ *
2685 * Find the average color for each bin. The colors are ordered *
2686 * by the gray value in the corresponding pixel in %pixg. *
2687 * The bins have equal numbers of pixels (within 1). *
2688 * ------------------------------------------------------------ */
2689
2690 /* Generate a dnaa, where each dna has the colors corresponding
2691 * to the grayscale value given by the index of the dna in the dnaa */
2692 datas = pixGetData(pixs);
2693 wpls = pixGetWpl(pixs);
2694 datag = pixGetData(pixg);
2695 wplg = pixGetWpl(pixg);
2696 daa = l_dnaaCreateFull(256, 0);
2697 for (i = 0; i < h; i += factor) {
2698 lines = datas + i * wpls;
2699 lineg = datag + i * wplg;
2700 for (j = 0; j < w; j += factor) {
2701 grayval = GET_DATA_BYTE(lineg, j);
2702 l_dnaaAddNumber(daa, grayval, lines[j]);
2703 }
2704 }
2705
2706 if (pixadb) {
2707 NUMA *na, *nabinval, *narank;
2708 na = numaCreate(256); /* grayscale histogram */
2709 for (i = 0; i < 256; i++)
2710 numaAddNumber(na, l_dnaaGetDnaCount(daa, i));
2711
2712 /* Plot the gray bin value and the rank(gray) values */
2713 numaDiscretizeHistoInBins(na, nbins, &nabinval, &narank);
2714 pix1 = gplotSimplePix1(nabinval, "Gray value in each bin");
2715 pixaAddPix(pixadb, pix1, L_INSERT);
2716 pix1 = gplotSimplePix1(narank, "rank as function of gray value");
2717 pixaAddPix(pixadb, pix1, L_INSERT);
2718 numaDestroy(&na);
2719 numaDestroy(&nabinval);
2720 numaDestroy(&narank);
2721 }
2722
2723 /* Get the number of items in each bin */
2724 ntot = l_dnaaGetNumberCount(daa);
2725 if ((naeach = numaGetUniformBinSizes(ntot, nbins)) == NULL) {
2726 l_dnaaDestroy(&daa);
2727 return ERROR_INT("naeach not made", __func__, 1);
2728 }
2729
2730 /* Get the average color in each bin. This algorithm is
2731 * esssentially the same as in numaDiscretizeHistoInBins() */
2732 carray = (l_uint32 *)LEPT_CALLOC(nbins, sizeof(l_uint32));
2733 rsum = gsum = bsum = 0.0;
2734 bincount = 0;
2735 binindex = 0;
2736 numaGetIValue(naeach, 0, &binsize);
2737 for (i = 0; i < 256; i++) {
2738 count = l_dnaaGetDnaCount(daa, i);
2739 for (j = 0; j < count; j++) {
2740 bincount++;
2741 l_dnaaGetValue(daa, i, j, &val64);
2742 extractRGBValues((l_uint32)val64, &rval, &gval, &bval);
2743 rsum += rval;
2744 gsum += gval;
2745 bsum += bval;
2746 if (bincount == binsize) { /* add bin entry */
2747 rave = (l_int32)(rsum / binsize + 0.5);
2748 gave = (l_int32)(gsum / binsize + 0.5);
2749 bave = (l_int32)(bsum / binsize + 0.5);
2750 composeRGBPixel(rave, gave, bave, carray + binindex);
2751 rsum = gsum = bsum = 0.0;
2752 bincount = 0;
2753 binindex++;
2754 if (binindex == nbins) break;
2755 numaGetIValue(naeach, binindex, &binsize);
2756 }
2757 }
2758 if (binindex == nbins) break;
2759 }
2760 if (binindex != nbins)
2761 L_ERROR("binindex = %d != nbins = %d\n", __func__, binindex, nbins);
2762
2763 if (pixadb) {
2764 NUMA *nared, *nagreen, *nablue;
2765 nared = numaCreate(nbins);
2766 nagreen = numaCreate(nbins);
2767 nablue = numaCreate(nbins);
2768 for (i = 0; i < nbins; i++) {
2769 extractRGBValues(carray[i], &rval, &gval, &bval);
2770 numaAddNumber(nared, rval);
2771 numaAddNumber(nagreen, gval);
2772 numaAddNumber(nablue, bval);
2773 }
2774 lept_mkdir("lept/regout");
2775 pix1 = gplotSimplePix1(nared, "Average red val vs. rank bin");
2776 pixaAddPix(pixadb, pix1, L_INSERT);
2777 pix1 = gplotSimplePix1(nagreen, "Average green val vs. rank bin");
2778 pixaAddPix(pixadb, pix1, L_INSERT);
2779 pix1 = gplotSimplePix1(nablue, "Average blue val vs. rank bin");
2780 pixaAddPix(pixadb, pix1, L_INSERT);
2781 numaDestroy(&nared);
2782 numaDestroy(&nagreen);
2783 numaDestroy(&nablue);
2784 }
2785
2786 *pcarray = carray;
2787 numaDestroy(&naeach);
2788 l_dnaaDestroy(&daa);
2789 return 0;
2790}
2791
2792
2812PIX *
2813pixDisplayColorArray(l_uint32 *carray,
2814 l_int32 ncolors,
2815 l_int32 side,
2816 l_int32 ncols,
2817 l_int32 fontsize)
2818{
2819char textstr[256];
2820l_int32 i, rval, gval, bval;
2821L_BMF *bmf;
2822PIX *pix1, *pix2, *pix3, *pix4;
2823PIXA *pixa;
2824
2825 if (!carray)
2826 return (PIX *)ERROR_PTR("carray not defined", __func__, NULL);
2827 if (fontsize < 0 || fontsize > 20 || fontsize & 1 || fontsize == 2)
2828 return (PIX *)ERROR_PTR("invalid fontsize", __func__, NULL);
2829
2830 bmf = (fontsize == 0) ? NULL : bmfCreate(NULL, fontsize);
2831 pixa = pixaCreate(ncolors);
2832 for (i = 0; i < ncolors; i++) {
2833 pix1 = pixCreate(side, side, 32);
2834 pixSetAllArbitrary(pix1, carray[i]);
2835 pix2 = pixAddBorder(pix1, 2, 1);
2836 if (bmf) {
2837 extractRGBValues(carray[i], &rval, &gval, &bval);
2838 snprintf(textstr, sizeof(textstr),
2839 "%d: (%d %d %d)", i, rval, gval, bval);
2840 pix3 = pixAddSingleTextblock(pix2, bmf, textstr, 0xff000000,
2841 L_ADD_BELOW, NULL);
2842 } else {
2843 pix3 = pixClone(pix2);
2844 }
2845 pixaAddPix(pixa, pix3, L_INSERT);
2846 pixDestroy(&pix1);
2847 pixDestroy(&pix2);
2848 }
2849 pix4 = pixaDisplayTiledInColumns(pixa, ncols, 1.0, 20, 2);
2850 pixaDestroy(&pixa);
2851 bmfDestroy(&bmf);
2852 return pix4;
2853}
2854
2855
2886PIX *
2888 l_int32 direction,
2889 l_int32 size,
2890 l_int32 nbins,
2891 l_int32 type)
2892{
2893l_int32 i, j, w, h, mindim, nstrips;
2894l_uint32 *array;
2895BOXA *boxa;
2896PIX *pix1, *pix2, *pixd;
2897PIXA *pixa;
2898PIXCMAP *cmap;
2899
2900 if (!pixs)
2901 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
2902 cmap = pixGetColormap(pixs);
2903 if (pixGetDepth(pixs) != 32 && !cmap)
2904 return (PIX *)ERROR_PTR("pixs neither 32 bpp nor cmapped",
2905 __func__, NULL);
2906 if (direction != L_SCAN_HORIZONTAL && direction != L_SCAN_VERTICAL)
2907 return (PIX *)ERROR_PTR("invalid direction", __func__, NULL);
2908 if (size < 1)
2909 return (PIX *)ERROR_PTR("size < 1", __func__, NULL);
2910 if (nbins < 2)
2911 return (PIX *)ERROR_PTR("nbins must be at least 2", __func__, NULL);
2912 if (type != L_SELECT_RED && type != L_SELECT_GREEN &&
2913 type != L_SELECT_BLUE && type != L_SELECT_MIN &&
2914 type != L_SELECT_MAX && type != L_SELECT_AVERAGE &&
2915 type != L_SELECT_HUE && type != L_SELECT_SATURATION)
2916 return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
2917 pixGetDimensions(pixs, &w, &h, NULL);
2918 mindim = L_MIN(w, h);
2919 if (mindim < 20 || nbins > mindim)
2920 return (PIX *)ERROR_PTR("pix too small and/or too many bins",
2921 __func__, NULL);
2922
2923 /* Remove colormap if it exists */
2924 if (cmap)
2925 pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR);
2926 else
2927 pix1 = pixClone(pixs);
2928 pixGetDimensions(pixs, &w, &h, NULL);
2929
2930 pixd = NULL;
2931 boxa = makeMosaicStrips(w, h, direction, size);
2932 pixa = pixClipRectangles(pix1, boxa);
2933 nstrips = pixaGetCount(pixa);
2934 if (direction == L_SCAN_HORIZONTAL) {
2935 pixd = pixCreate(nstrips, nbins, 32);
2936 for (i = 0; i < nstrips; i++) {
2937 pix2 = pixaGetPix(pixa, i, L_CLONE);
2938 pixGetRankColorArray(pix2, nbins, type, 1, &array, NULL, 0);
2939 if (array) {
2940 for (j = 0; j < nbins; j++)
2941 pixSetPixel(pixd, i, j, array[j]);
2942 LEPT_FREE(array);
2943 }
2944 pixDestroy(&pix2);
2945 }
2946 } else { /* L_SCAN_VERTICAL */
2947 pixd = pixCreate(nbins, nstrips, 32);
2948 for (i = 0; i < nstrips; i++) {
2949 pix2 = pixaGetPix(pixa, i, L_CLONE);
2950 pixGetRankColorArray(pix2, nbins, type, 1, &array, NULL, 0);
2951 if (array) {
2952 for (j = 0; j < nbins; j++)
2953 pixSetPixel(pixd, j, i, array[j]);
2954 LEPT_FREE(array);
2955 }
2956 pixDestroy(&pix2);
2957 }
2958 }
2959 pixDestroy(&pix1);
2960 boxaDestroy(&boxa);
2961 pixaDestroy(&pixa);
2962 return pixd;
2963}
2964
2965
2966
2967/*-------------------------------------------------------------*
2968 * Pixelwise aligned statistics *
2969 *-------------------------------------------------------------*/
2991PIX *
2993 l_int32 type,
2994 l_int32 nbins,
2995 l_int32 thresh)
2996{
2997l_int32 j, n, w, h, d;
2998l_float32 *colvect;
2999PIX *pixt, *pixd;
3000
3001 if (!pixa)
3002 return (PIX *)ERROR_PTR("pixa not defined", __func__, NULL);
3003 if (type != L_MEAN_ABSVAL && type != L_MEDIAN_VAL &&
3004 type != L_MODE_VAL && type != L_MODE_COUNT)
3005 return (PIX *)ERROR_PTR("invalid type", __func__, NULL);
3006 n = pixaGetCount(pixa);
3007 if (n == 0)
3008 return (PIX *)ERROR_PTR("no pix in pixa", __func__, NULL);
3009 pixaGetPixDimensions(pixa, 0, &w, &h, &d);
3010 if (d != 8)
3011 return (PIX *)ERROR_PTR("pix not 8 bpp", __func__, NULL);
3012
3013 pixd = pixCreate(w, h, 8);
3014 pixt = pixCreate(n, h, 8);
3015 colvect = (l_float32 *)LEPT_CALLOC(h, sizeof(l_float32));
3016 for (j = 0; j < w; j++) {
3017 pixaExtractColumnFromEachPix(pixa, j, pixt);
3018 pixGetRowStats(pixt, type, nbins, thresh, colvect);
3019 pixSetPixelColumn(pixd, j, colvect);
3020 }
3021
3022 LEPT_FREE(colvect);
3023 pixDestroy(&pixt);
3024 return pixd;
3025}
3026
3027
3036l_ok
3038 l_int32 col,
3039 PIX *pixd)
3040{
3041l_int32 i, k, n, w, h, ht, val, wplt, wpld;
3042l_uint32 *datad, *datat;
3043PIX *pixt;
3044
3045 if (!pixa)
3046 return ERROR_INT("pixa not defined", __func__, 1);
3047 if (!pixd || pixGetDepth(pixd) != 8)
3048 return ERROR_INT("pixd not defined or not 8 bpp", __func__, 1);
3049 n = pixaGetCount(pixa);
3050 pixGetDimensions(pixd, &w, &h, NULL);
3051 if (n != w)
3052 return ERROR_INT("pix width != n", __func__, 1);
3053 pixt = pixaGetPix(pixa, 0, L_CLONE);
3054 wplt = pixGetWpl(pixt);
3055 pixGetDimensions(pixt, NULL, &ht, NULL);
3056 pixDestroy(&pixt);
3057 if (h != ht)
3058 return ERROR_INT("pixd height != column height", __func__, 1);
3059
3060 datad = pixGetData(pixd);
3061 wpld = pixGetWpl(pixd);
3062 for (k = 0; k < n; k++) {
3063 pixt = pixaGetPix(pixa, k, L_CLONE);
3064 datat = pixGetData(pixt);
3065 for (i = 0; i < h; i++) {
3066 val = GET_DATA_BYTE(datat, col);
3067 SET_DATA_BYTE(datad + i * wpld, k, val);
3068 datat += wplt;
3069 }
3070 pixDestroy(&pixt);
3071 }
3072
3073 return 0;
3074}
3075
3076
3109l_ok
3111 l_int32 type,
3112 l_int32 nbins,
3113 l_int32 thresh,
3114 l_float32 *colvect)
3115{
3116l_int32 i, j, k, w, h, val, wpls, sum, target, max, modeval;
3117l_int32 *histo, *gray2bin, *bin2gray;
3118l_uint32 *lines, *datas;
3119
3120 if (!pixs || pixGetDepth(pixs) != 8)
3121 return ERROR_INT("pixs not defined or not 8 bpp", __func__, 1);
3122 if (!colvect)
3123 return ERROR_INT("colvect not defined", __func__, 1);
3124 if (type != L_MEAN_ABSVAL && type != L_MEDIAN_VAL &&
3125 type != L_MODE_VAL && type != L_MODE_COUNT)
3126 return ERROR_INT("invalid type", __func__, 1);
3127 if (type != L_MEAN_ABSVAL && (nbins < 1 || nbins > 256))
3128 return ERROR_INT("invalid nbins", __func__, 1);
3129 pixGetDimensions(pixs, &w, &h, NULL);
3130
3131 datas = pixGetData(pixs);
3132 wpls = pixGetWpl(pixs);
3133 if (type == L_MEAN_ABSVAL) {
3134 for (i = 0; i < h; i++) {
3135 sum = 0;
3136 lines = datas + i * wpls;
3137 for (j = 0; j < w; j++)
3138 sum += GET_DATA_BYTE(lines, j);
3139 colvect[i] = (l_float32)sum / (l_float32)w;
3140 }
3141 return 0;
3142 }
3143
3144 /* We need a histogram; binwidth ~ 256 / nbins */
3145 histo = (l_int32 *)LEPT_CALLOC(nbins, sizeof(l_int32));
3146 gray2bin = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
3147 bin2gray = (l_int32 *)LEPT_CALLOC(nbins, sizeof(l_int32));
3148 for (i = 0; i < 256; i++) /* gray value --> histo bin */
3149 gray2bin[i] = (i * nbins) / 256;
3150 for (i = 0; i < nbins; i++) /* histo bin --> gray value */
3151 bin2gray[i] = (i * 256 + 128) / nbins;
3152
3153 for (i = 0; i < h; i++) {
3154 lines = datas + i * wpls;
3155 for (k = 0; k < nbins; k++)
3156 histo[k] = 0;
3157 for (j = 0; j < w; j++) {
3158 val = GET_DATA_BYTE(lines, j);
3159 histo[gray2bin[val]]++;
3160 }
3161
3162 if (type == L_MEDIAN_VAL) {
3163 sum = 0;
3164 target = (w + 1) / 2;
3165 for (k = 0; k < nbins; k++) {
3166 sum += histo[k];
3167 if (sum >= target) {
3168 colvect[i] = bin2gray[k];
3169 break;
3170 }
3171 }
3172 } else if (type == L_MODE_VAL) {
3173 max = 0;
3174 modeval = 0;
3175 for (k = 0; k < nbins; k++) {
3176 if (histo[k] > max) {
3177 max = histo[k];
3178 modeval = k;
3179 }
3180 }
3181 if (max < thresh)
3182 colvect[i] = 0;
3183 else
3184 colvect[i] = bin2gray[modeval];
3185 } else { /* type == L_MODE_COUNT */
3186 max = 0;
3187 for (k = 0; k < nbins; k++) {
3188 if (histo[k] > max)
3189 max = histo[k];
3190 }
3191 colvect[i] = max;
3192 }
3193 }
3194
3195 LEPT_FREE(histo);
3196 LEPT_FREE(gray2bin);
3197 LEPT_FREE(bin2gray);
3198 return 0;
3199}
3200
3201
3229l_ok
3231 l_int32 type,
3232 l_int32 nbins,
3233 l_int32 thresh,
3234 l_float32 *rowvect)
3235{
3236l_int32 i, j, k, w, h, val, wpls, sum, target, max, modeval;
3237l_int32 *histo, *gray2bin, *bin2gray;
3238l_uint32 *datas;
3239
3240 if (!pixs || pixGetDepth(pixs) != 8)
3241 return ERROR_INT("pixs not defined or not 8 bpp", __func__, 1);
3242 if (!rowvect)
3243 return ERROR_INT("rowvect not defined", __func__, 1);
3244 if (type != L_MEAN_ABSVAL && type != L_MEDIAN_VAL &&
3245 type != L_MODE_VAL && type != L_MODE_COUNT)
3246 return ERROR_INT("invalid type", __func__, 1);
3247 if (type != L_MEAN_ABSVAL && (nbins < 1 || nbins > 256))
3248 return ERROR_INT("invalid nbins", __func__, 1);
3249 pixGetDimensions(pixs, &w, &h, NULL);
3250
3251 datas = pixGetData(pixs);
3252 wpls = pixGetWpl(pixs);
3253 if (type == L_MEAN_ABSVAL) {
3254 for (j = 0; j < w; j++) {
3255 sum = 0;
3256 for (i = 0; i < h; i++)
3257 sum += GET_DATA_BYTE(datas + i * wpls, j);
3258 rowvect[j] = (l_float32)sum / (l_float32)h;
3259 }
3260 return 0;
3261 }
3262
3263 /* We need a histogram; binwidth ~ 256 / nbins */
3264 histo = (l_int32 *)LEPT_CALLOC(nbins, sizeof(l_int32));
3265 gray2bin = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
3266 bin2gray = (l_int32 *)LEPT_CALLOC(nbins, sizeof(l_int32));
3267 for (i = 0; i < 256; i++) /* gray value --> histo bin */
3268 gray2bin[i] = (i * nbins) / 256;
3269 for (i = 0; i < nbins; i++) /* histo bin --> gray value */
3270 bin2gray[i] = (i * 256 + 128) / nbins;
3271
3272 for (j = 0; j < w; j++) {
3273 for (i = 0; i < h; i++) {
3274 val = GET_DATA_BYTE(datas + i * wpls, j);
3275 histo[gray2bin[val]]++;
3276 }
3277
3278 if (type == L_MEDIAN_VAL) {
3279 sum = 0;
3280 target = (h + 1) / 2;
3281 for (k = 0; k < nbins; k++) {
3282 sum += histo[k];
3283 if (sum >= target) {
3284 rowvect[j] = bin2gray[k];
3285 break;
3286 }
3287 }
3288 } else if (type == L_MODE_VAL) {
3289 max = 0;
3290 modeval = 0;
3291 for (k = 0; k < nbins; k++) {
3292 if (histo[k] > max) {
3293 max = histo[k];
3294 modeval = k;
3295 }
3296 }
3297 if (max < thresh)
3298 rowvect[j] = 0;
3299 else
3300 rowvect[j] = bin2gray[modeval];
3301 } else { /* type == L_MODE_COUNT */
3302 max = 0;
3303 for (k = 0; k < nbins; k++) {
3304 if (histo[k] > max)
3305 max = histo[k];
3306 }
3307 rowvect[j] = max;
3308 }
3309 for (k = 0; k < nbins; k++)
3310 histo[k] = 0;
3311 }
3312
3313 LEPT_FREE(histo);
3314 LEPT_FREE(gray2bin);
3315 LEPT_FREE(bin2gray);
3316 return 0;
3317}
3318
3319
3328l_ok
3330 l_int32 col,
3331 l_float32 *colvect)
3332{
3333l_int32 i, w, h, wpl;
3334l_uint32 *data;
3335
3336 if (!pix || pixGetDepth(pix) != 8)
3337 return ERROR_INT("pix not defined or not 8 bpp", __func__, 1);
3338 if (!colvect)
3339 return ERROR_INT("colvect not defined", __func__, 1);
3340 pixGetDimensions(pix, &w, &h, NULL);
3341 if (col < 0 || col > w)
3342 return ERROR_INT("invalid col", __func__, 1);
3343
3344 data = pixGetData(pix);
3345 wpl = pixGetWpl(pix);
3346 for (i = 0; i < h; i++)
3347 SET_DATA_BYTE(data + i * wpl, col, (l_int32)colvect[i]);
3348
3349 return 0;
3350}
3351
3352
3353/*-------------------------------------------------------------*
3354 * Foreground/background estimation *
3355 *-------------------------------------------------------------*/
3366l_ok
3368 l_int32 factor,
3369 l_int32 thresh,
3370 l_int32 *pfgval,
3371 l_int32 *pbgval)
3372{
3373l_float32 fval;
3374PIX *pixg, *pixm;
3375
3376 if (pfgval) *pfgval = 0;
3377 if (pbgval) *pbgval = 0;
3378 if (!pfgval && !pbgval)
3379 return ERROR_INT("no data requested", __func__, 1);
3380 if (!pixs)
3381 return ERROR_INT("pixs not defined", __func__, 1);
3382
3383 /* Generate a subsampled 8 bpp version and a mask over the fg */
3384 pixg = pixConvertTo8BySampling(pixs, factor, 0);
3385 pixm = pixThresholdToBinary(pixg, thresh);
3386
3387 if (pfgval) {
3388 pixGetAverageMasked(pixg, pixm, 0, 0, 1, L_MEAN_ABSVAL, &fval);
3389 *pfgval = (l_int32)(fval + 0.5);
3390 }
3391
3392 if (pbgval) {
3393 pixInvert(pixm, pixm);
3394 pixGetAverageMasked(pixg, pixm, 0, 0, 1, L_MEAN_ABSVAL, &fval);
3395 *pbgval = (l_int32)(fval + 0.5);
3396 }
3397
3398 pixDestroy(&pixg);
3399 pixDestroy(&pixm);
3400 return 0;
3401}
3402
3403
3423l_ok
3425 l_float32 scorefract,
3426 l_int32 factor,
3427 l_int32 *pthresh,
3428 l_int32 *pfgval,
3429 l_int32 *pbgval,
3430 PIX **ppixdb)
3431{
3432char buf[256];
3433l_int32 thresh;
3434l_float32 avefg, avebg, maxnum;
3435GPLOT *gplot;
3436NUMA *na, *nascore, *nax, *nay;
3437PIX *pixg;
3438
3439 if (pthresh) *pthresh = 0;
3440 if (pfgval) *pfgval = 0;
3441 if (pbgval) *pbgval = 0;
3442 if (ppixdb) *ppixdb = NULL;
3443 if (!pthresh && !pfgval && !pbgval)
3444 return ERROR_INT("no data requested", __func__, 1);
3445 if (!pixs)
3446 return ERROR_INT("pixs not defined", __func__, 1);
3447
3448 /* Generate a subsampled 8 bpp version */
3449 pixg = pixConvertTo8BySampling(pixs, factor, 0);
3450
3451 /* Make the fg/bg estimates */
3452 na = pixGetGrayHistogram(pixg, 1);
3453 if (ppixdb) {
3454 numaSplitDistribution(na, scorefract, &thresh, &avefg, &avebg,
3455 NULL, NULL, &nascore);
3456 numaDestroy(&nascore);
3457 } else {
3458 numaSplitDistribution(na, scorefract, &thresh, &avefg, &avebg,
3459 NULL, NULL, NULL);
3460 }
3461
3462 if (pthresh) *pthresh = thresh;
3463 if (pfgval) *pfgval = (l_int32)(avefg + 0.5);
3464 if (pbgval) *pbgval = (l_int32)(avebg + 0.5);
3465
3466 if (ppixdb) {
3467 lept_mkdir("lept/redout");
3468 gplot = gplotCreate("/tmp/lept/redout/histplot", GPLOT_PNG, "Histogram",
3469 "Grayscale value", "Number of pixels");
3470 gplotAddPlot(gplot, NULL, na, GPLOT_LINES, NULL);
3471 nax = numaMakeConstant(thresh, 2);
3472 numaGetMax(na, &maxnum, NULL);
3473 nay = numaMakeConstant(0, 2);
3474 numaReplaceNumber(nay, 1, (l_int32)(0.5 * maxnum));
3475 snprintf(buf, sizeof(buf), "score fract = %3.1f", scorefract);
3476 gplotAddPlot(gplot, nax, nay, GPLOT_LINES, buf);
3477 *ppixdb = gplotMakeOutputPix(gplot);
3478 gplotDestroy(&gplot);
3479 numaDestroy(&nax);
3480 numaDestroy(&nay);
3481 }
3482
3483 pixDestroy(&pixg);
3484 numaDestroy(&na);
3485 return 0;
3486}
#define GET_DATA_QBIT(pdata, n)
#define GET_DATA_TWO_BYTES(pdata, n)
#define GET_DATA_BYTE(pdata, n)
#define GET_DATA_DIBIT(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
#define GET_DATA_BIT(pdata, n)
l_ok pixCountRGBColorsByHash(PIX *pixs, l_int32 *pncolors)
pixCountRGBColorsByHash()
Definition pix4.c:826
L_AMAP * pixGetColorAmapHistogram(PIX *pixs, l_int32 factor)
pixGetColorAmapHistogram()
Definition pix4.c:894
l_ok pixGetAverageMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_int32 type, l_float32 *pval)
pixGetAverageMasked()
Definition pix4.c:1488
l_ok pixGetColorHistogram(PIX *pixs, l_int32 factor, NUMA **pnar, NUMA **pnag, NUMA **pnab)
pixGetColorHistogram()
Definition pix4.c:408
NUMA * pixGetCmapHistogramInRect(PIX *pixs, BOX *box, l_int32 factor)
pixGetCmapHistogramInRect()
Definition pix4.c:762
l_ok pixGetRankValueMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_float32 rank, l_float32 *pval, NUMA **pna)
pixGetRankValueMasked()
Definition pix4.c:1138
l_ok pixGetBinnedComponentRange(PIX *pixs, l_int32 nbins, l_int32 factor, l_int32 color, l_int32 *pminval, l_int32 *pmaxval, l_uint32 **pcarray, l_int32 fontsize)
pixGetBinnedComponentRange()
Definition pix4.c:2445
PIX * pixRankBinByStrip(PIX *pixs, l_int32 direction, l_int32 size, l_int32 nbins, l_int32 type)
pixRankBinByStrip()
Definition pix4.c:2887
l_ok pixGetColorHistogramMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, NUMA **pnar, NUMA **pnag, NUMA **pnab)
pixGetColorHistogramMasked()
Definition pix4.c:508
l_ok pixGetMaxColorIndex(PIX *pixs, l_int32 *pmaxindex)
pixGetMaxColorIndex()
Definition pix4.c:2373
PIX * pixaGetAlignedStats(PIXA *pixa, l_int32 type, l_int32 nbins, l_int32 thresh)
pixaGetAlignedStats()
Definition pix4.c:2992
l_ok pixGetRangeValues(PIX *pixs, l_int32 factor, l_int32 color, l_int32 *pminval, l_int32 *pmaxval)
pixGetRangeValues()
Definition pix4.c:2089
l_ok pixGetRankValueMaskedRGB(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_float32 rank, l_float32 *prval, l_float32 *pgval, l_float32 *pbval)
pixGetRankValueMaskedRGB()
Definition pix4.c:1048
l_ok pixSplitDistributionFgBg(PIX *pixs, l_float32 scorefract, l_int32 factor, l_int32 *pthresh, l_int32 *pfgval, l_int32 *pbgval, PIX **ppixdb)
pixSplitDistributionFgBg()
Definition pix4.c:3424
l_ok pixGetRowStats(PIX *pixs, l_int32 type, l_int32 nbins, l_int32 thresh, l_float32 *colvect)
pixGetRowStats()
Definition pix4.c:3110
PIX * pixGetAverageTiled(PIX *pixs, l_int32 sx, l_int32 sy, l_int32 type)
pixGetAverageTiled()
Definition pix4.c:1685
l_ok pixaExtractColumnFromEachPix(PIXA *pixa, l_int32 col, PIX *pixd)
pixaExtractColumnFromEachPix()
Definition pix4.c:3037
NUMA * pixGetCmapHistogramMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor)
pixGetCmapHistogramMasked()
Definition pix4.c:684
l_ok pixGetRankColorArray(PIX *pixs, l_int32 nbins, l_int32 type, l_int32 factor, l_uint32 **pcarray, PIXA *pixadb, l_int32 fontsize)
pixGetRankColorArray()
Definition pix4.c:2542
PIX * pixDisplayColorArray(l_uint32 *carray, l_int32 ncolors, l_int32 side, l_int32 ncols, l_int32 fontsize)
pixDisplayColorArray()
Definition pix4.c:2813
NUMA * pixGetGrayHistogram(PIX *pixs, l_int32 factor)
pixGetGrayHistogram()
Definition pix4.c:115
l_ok pixGetAverageTiledRGB(PIX *pixs, l_int32 sx, l_int32 sy, l_int32 type, PIX **ppixr, PIX **ppixg, PIX **ppixb)
pixGetAverageTiledRGB()
Definition pix4.c:1610
NUMAA * pixGetGrayHistogramTiled(PIX *pixs, l_int32 factor, l_int32 nx, l_int32 ny)
pixGetGrayHistogramTiled()
Definition pix4.c:353
l_int32 pixColumnStats(PIX *pixs, BOX *box, NUMA **pnamean, NUMA **pnamedian, NUMA **pnamode, NUMA **pnamodecount, NUMA **pnavar, NUMA **pnarootvar)
pixColumnStats()
Definition pix4.c:1944
l_ok pixGetPixelStats(PIX *pixs, l_int32 factor, l_int32 type, l_uint32 *pvalue)
pixGetPixelStats()
Definition pix4.c:1323
l_ok pixCountRGBColors(PIX *pixs, l_int32 factor, l_int32 *pncolors)
pixCountRGBColors()
Definition pix4.c:860
l_ok pixGetBinnedColor(PIX *pixs, PIX *pixg, l_int32 factor, l_int32 nbins, l_uint32 **pcarray, PIXA *pixadb)
pixGetBinnedColor()
Definition pix4.c:2645
l_ok pixGetExtremeValue(PIX *pixs, l_int32 factor, l_int32 type, l_int32 *prval, l_int32 *pgval, l_int32 *pbval, l_int32 *pgrayval)
pixGetExtremeValue()
Definition pix4.c:2165
l_ok pixSetPixelColumn(PIX *pix, l_int32 col, l_float32 *colvect)
pixSetPixelColumn()
Definition pix4.c:3329
l_ok pixThresholdForFgBg(PIX *pixs, l_int32 factor, l_int32 thresh, l_int32 *pfgval, l_int32 *pbgval)
pixThresholdForFgBg()
Definition pix4.c:3367
l_ok pixGetRankValue(PIX *pixs, l_int32 factor, l_float32 rank, l_uint32 *pvalue)
pixGetRankValue()
Definition pix4.c:980
NUMA * pixGetGrayHistogramMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor)
pixGetGrayHistogramMasked()
Definition pix4.c:209
NUMA * pixGetGrayHistogramInRect(PIX *pixs, BOX *box, l_int32 factor)
pixGetGrayHistogramInRect()
Definition pix4.c:287
l_int32 pixRowStats(PIX *pixs, BOX *box, NUMA **pnamean, NUMA **pnamedian, NUMA **pnamode, NUMA **pnamodecount, NUMA **pnavar, NUMA **pnarootvar)
pixRowStats()
Definition pix4.c:1786
l_ok pixGetMaxValueInRect(PIX *pixs, BOX *box, l_uint32 *pmaxval, l_int32 *pxmax, l_int32 *pymax)
pixGetMaxValueInRect()
Definition pix4.c:2300
l_ok pixGetAverageMaskedRGB(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_int32 type, l_float32 *prval, l_float32 *pgval, l_float32 *pbval)
pixGetAverageMaskedRGB()
Definition pix4.c:1388
NUMA * pixGetCmapHistogram(PIX *pixs, l_int32 factor)
pixGetCmapHistogram()
Definition pix4.c:621
l_int32 amapGetCountForColor(L_AMAP *amap, l_uint32 val)
amapGetCountForColor()
Definition pix4.c:943
l_ok pixGetPixelAverage(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_uint32 *pval)
pixGetPixelAverage()
Definition pix4.c:1207
l_ok pixGetColumnStats(PIX *pixs, l_int32 type, l_int32 nbins, l_int32 thresh, l_float32 *rowvect)
pixGetColumnStats()
Definition pix4.c:3230
@ COLOR_BLUE
Definition pix.h:330
@ COLOR_RED
Definition pix.h:328
@ COLOR_GREEN
Definition pix.h:329
@ L_SELECT_MAX
Definition pix.h:619
@ L_SELECT_GREEN
Definition pix.h:616
@ L_SELECT_SATURATION
Definition pix.h:622
@ L_SELECT_BLUE
Definition pix.h:617
@ L_SELECT_AVERAGE
Definition pix.h:620
@ L_SELECT_MIN
Definition pix.h:618
@ L_SELECT_HUE
Definition pix.h:621
@ L_SELECT_RED
Definition pix.h:615
@ REMOVE_CMAP_TO_FULL_COLOR
Definition pix.h:382
@ REMOVE_CMAP_TO_GRAYSCALE
Definition pix.h:381
@ REMOVE_CMAP_BASED_ON_SRC
Definition pix.h:384
@ L_ADD_BELOW
Definition pix.h:1003
@ L_CLONE
Definition pix.h:506
@ L_NOCOPY
Definition pix.h:503
@ L_INSERT
Definition pix.h:504
@ L_SCAN_VERTICAL
Definition pix.h:835
@ L_SCAN_HORIZONTAL
Definition pix.h:834
@ L_MODE_VAL
Definition pix.h:763
@ L_ROOT_MEAN_SQUARE
Definition pix.h:765
@ L_MODE_COUNT
Definition pix.h:764
@ L_MEAN_ABSVAL
Definition pix.h:761
@ L_VARIANCE
Definition pix.h:767
@ L_STANDARD_DEVIATION
Definition pix.h:766
@ L_MEDIAN_VAL
Definition pix.h:762
Definition gplot.h:77
Definition bmf.h:47