Leptonica 1.82.0
Image processing and image analysis suite
runlength.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
59#ifdef HAVE_CONFIG_H
60#include <config_auto.h>
61#endif /* HAVE_CONFIG_H */
62
63#include <string.h>
64#include <math.h>
65#include "allheaders.h"
66
67static PIX *pixFindMinRunsOrthogonal(PIX *pixs, l_float32 angle, l_int32 depth);
68
69/*-----------------------------------------------------------------------*
70 * Label pixels by membership in runs *
71 *-----------------------------------------------------------------------*/
101PIX *
103 l_int32 color,
104 l_int32 depth,
105 l_int32 nangles)
106{
107l_float32 angle, pi;
108PIX *pixh, *pixv, *pixt, *pixg1, *pixg2, *pixg3, *pixg4;
109
110 PROCNAME("pixStrokeWidthTransform");
111
112 if (!pixs || pixGetDepth(pixs) != 1)
113 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
114 if (depth != 8 && depth != 16)
115 return (PIX *)ERROR_PTR("depth must be 8 or 16 bpp", procName, NULL);
116 if (nangles != 2 && nangles != 4 && nangles != 6 && nangles != 8)
117 return (PIX *)ERROR_PTR("nangles not in {2,4,6,8}", procName, NULL);
118
119 /* Use fg runs for evaluation */
120 if (color == 0)
121 pixt = pixInvert(NULL, pixs);
122 else
123 pixt = pixClone(pixs);
124
125 /* Find min length at 0 and 90 degrees */
126 pixh = pixRunlengthTransform(pixt, 1, L_HORIZONTAL_RUNS, depth);
127 pixv = pixRunlengthTransform(pixt, 1, L_VERTICAL_RUNS, depth);
128 pixg1 = pixMinOrMax(NULL, pixh, pixv, L_CHOOSE_MIN);
129 pixDestroy(&pixh);
130 pixDestroy(&pixv);
131
132 pixg2 = pixg3 = pixg4 = NULL;
133 pi = 3.1415926535;
134 if (nangles == 4 || nangles == 8) {
135 /* Find min length at +45 and -45 degrees */
136 angle = pi / 4.0;
137 pixg2 = pixFindMinRunsOrthogonal(pixt, angle, depth);
138 }
139
140 if (nangles == 6) {
141 /* Find min length at +30 and -60 degrees */
142 angle = pi / 6.0;
143 pixg2 = pixFindMinRunsOrthogonal(pixt, angle, depth);
144
145 /* Find min length at +60 and -30 degrees */
146 angle = pi / 3.0;
147 pixg3 = pixFindMinRunsOrthogonal(pixt, angle, depth);
148 }
149
150 if (nangles == 8) {
151 /* Find min length at +22.5 and -67.5 degrees */
152 angle = pi / 8.0;
153 pixg3 = pixFindMinRunsOrthogonal(pixt, angle, depth);
154
155 /* Find min length at +67.5 and -22.5 degrees */
156 angle = 3.0 * pi / 8.0;
157 pixg4 = pixFindMinRunsOrthogonal(pixt, angle, depth);
158 }
159 pixDestroy(&pixt);
160
161 if (nangles > 2)
162 pixMinOrMax(pixg1, pixg1, pixg2, L_CHOOSE_MIN);
163 if (nangles > 4)
164 pixMinOrMax(pixg1, pixg1, pixg3, L_CHOOSE_MIN);
165 if (nangles > 6)
166 pixMinOrMax(pixg1, pixg1, pixg4, L_CHOOSE_MIN);
167 pixDestroy(&pixg2);
168 pixDestroy(&pixg3);
169 pixDestroy(&pixg4);
170 return pixg1;
171}
172
173
198static PIX *
200 l_float32 angle,
201 l_int32 depth)
202{
203l_int32 w, h, diag, xoff, yoff;
204PIX *pixb, *pixr, *pixh, *pixv, *pixg1, *pixg2, *pixd;
205BOX *box;
206
207 PROCNAME("pixFindMinRunsOrthogonal");
208
209 if (!pixs || pixGetDepth(pixs) != 1)
210 return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
211
212 /* Rasterop into the center of a sufficiently large image
213 * so we don't lose pixels for any rotation angle. */
214 pixGetDimensions(pixs, &w, &h, NULL);
215 diag = (l_int32)(sqrt((l_float64)(w * w + h * h)) + 2.5);
216 xoff = (diag - w) / 2;
217 yoff = (diag - h) / 2;
218 pixb = pixCreate(diag, diag, 1);
219 pixRasterop(pixb, xoff, yoff, w, h, PIX_SRC, pixs, 0, 0);
220
221 /* Rotate about the 'center', get the min of orthogonal transforms,
222 * rotate back, and crop the part corresponding to pixs. */
223 pixr = pixRotateShear(pixb, diag / 2, diag / 2, angle, L_BRING_IN_WHITE);
224 pixh = pixRunlengthTransform(pixr, 1, L_HORIZONTAL_RUNS, depth);
225 pixv = pixRunlengthTransform(pixr, 1, L_VERTICAL_RUNS, depth);
226 pixg1 = pixMinOrMax(NULL, pixh, pixv, L_CHOOSE_MIN);
227 pixg2 = pixRotateShear(pixg1, diag / 2, diag / 2, -angle, L_BRING_IN_WHITE);
228 box = boxCreate(xoff, yoff, w, h);
229 pixd = pixClipRectangle(pixg2, box, NULL);
230
231 pixDestroy(&pixb);
232 pixDestroy(&pixr);
233 pixDestroy(&pixh);
234 pixDestroy(&pixv);
235 pixDestroy(&pixg1);
236 pixDestroy(&pixg2);
237 boxDestroy(&box);
238 return pixd;
239}
240
241
264PIX *
266 l_int32 color,
267 l_int32 direction,
268 l_int32 depth)
269{
270l_int32 i, j, w, h, wpld, bufsize, maxsize, n;
271l_int32 *start, *end, *buffer;
272l_uint32 *datad, *lined;
273PIX *pixt, *pixd;
274
275 PROCNAME("pixRunlengthTransform");
276
277 if (!pixs)
278 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
279 if (pixGetDepth(pixs) != 1)
280 return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
281 if (depth != 8 && depth != 16)
282 return (PIX *)ERROR_PTR("depth must be 8 or 16 bpp", procName, NULL);
283
284 pixGetDimensions(pixs, &w, &h, NULL);
285 if (direction == L_HORIZONTAL_RUNS)
286 maxsize = 1 + w / 2;
287 else if (direction == L_VERTICAL_RUNS)
288 maxsize = 1 + h / 2;
289 else
290 return (PIX *)ERROR_PTR("invalid direction", procName, NULL);
291 bufsize = L_MAX(w, h);
292 if (bufsize > 1000000) {
293 L_ERROR("largest image dimension = %d; too big\n", procName, bufsize);
294 return NULL;
295 }
296
297 if ((pixd = pixCreate(w, h, depth)) == NULL)
298 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
299 datad = pixGetData(pixd);
300 wpld = pixGetWpl(pixd);
301
302 start = (l_int32 *)LEPT_CALLOC(maxsize, sizeof(l_int32));
303 end = (l_int32 *)LEPT_CALLOC(maxsize, sizeof(l_int32));
304 buffer = (l_int32 *)LEPT_CALLOC(bufsize, sizeof(l_int32));
305
306 /* Use fg runs for evaluation */
307 if (color == 0)
308 pixt = pixInvert(NULL, pixs);
309 else
310 pixt = pixClone(pixs);
311
312 if (direction == L_HORIZONTAL_RUNS) {
313 for (i = 0; i < h; i++) {
314 pixFindHorizontalRuns(pixt, i, start, end, &n);
315 runlengthMembershipOnLine(buffer, w, depth, start, end, n);
316 lined = datad + i * wpld;
317 if (depth == 8) {
318 for (j = 0; j < w; j++)
319 SET_DATA_BYTE(lined, j, buffer[j]);
320 } else { /* depth == 16 */
321 for (j = 0; j < w; j++)
322 SET_DATA_TWO_BYTES(lined, j, buffer[j]);
323 }
324 }
325 } else { /* L_VERTICAL_RUNS */
326 for (j = 0; j < w; j++) {
327 pixFindVerticalRuns(pixt, j, start, end, &n);
328 runlengthMembershipOnLine(buffer, h, depth, start, end, n);
329 if (depth == 8) {
330 for (i = 0; i < h; i++) {
331 lined = datad + i * wpld;
332 SET_DATA_BYTE(lined, j, buffer[i]);
333 }
334 } else { /* depth == 16 */
335 for (i = 0; i < h; i++) {
336 lined = datad + i * wpld;
337 SET_DATA_TWO_BYTES(lined, j, buffer[i]);
338 }
339 }
340 }
341 }
342
343 pixDestroy(&pixt);
344 LEPT_FREE(start);
345 LEPT_FREE(end);
346 LEPT_FREE(buffer);
347 return pixd;
348}
349
350
351/*-----------------------------------------------------------------------*
352 * Find runs along horizontal and vertical lines *
353 *-----------------------------------------------------------------------*/
374l_ok
376 l_int32 y,
377 l_int32 *xstart,
378 l_int32 *xend,
379 l_int32 *pn)
380{
381l_int32 inrun; /* boolean */
382l_int32 index, w, h, d, j, wpl, val;
383l_uint32 *line;
384
385 PROCNAME("pixFindHorizontalRuns");
386
387 if (!pn)
388 return ERROR_INT("&n not defined", procName, 1);
389 *pn = 0;
390 if (!pix)
391 return ERROR_INT("pix not defined", procName, 1);
392 pixGetDimensions(pix, &w, &h, &d);
393 if (d != 1)
394 return ERROR_INT("pix not 1 bpp", procName, 1);
395 if (y < 0 || y >= h)
396 return ERROR_INT("y not in [0 ... h - 1]", procName, 1);
397 if (!xstart)
398 return ERROR_INT("xstart not defined", procName, 1);
399 if (!xend)
400 return ERROR_INT("xend not defined", procName, 1);
401
402 wpl = pixGetWpl(pix);
403 line = pixGetData(pix) + y * wpl;
404
405 inrun = FALSE;
406 index = 0;
407 for (j = 0; j < w; j++) {
408 val = GET_DATA_BIT(line, j);
409 if (!inrun) {
410 if (val) {
411 xstart[index] = j;
412 inrun = TRUE;
413 }
414 } else {
415 if (!val) {
416 xend[index++] = j - 1;
417 inrun = FALSE;
418 }
419 }
420 }
421
422 /* Finish last run if necessary */
423 if (inrun)
424 xend[index++] = w - 1;
425
426 *pn = index;
427 return 0;
428}
429
430
451l_ok
453 l_int32 x,
454 l_int32 *ystart,
455 l_int32 *yend,
456 l_int32 *pn)
457{
458l_int32 inrun; /* boolean */
459l_int32 index, w, h, d, i, wpl, val;
460l_uint32 *data, *line;
461
462 PROCNAME("pixFindVerticalRuns");
463
464 if (!pn)
465 return ERROR_INT("&n not defined", procName, 1);
466 *pn = 0;
467 if (!pix)
468 return ERROR_INT("pix not defined", procName, 1);
469 pixGetDimensions(pix, &w, &h, &d);
470 if (d != 1)
471 return ERROR_INT("pix not 1 bpp", procName, 1);
472 if (x < 0 || x >= w)
473 return ERROR_INT("x not in [0 ... w - 1]", procName, 1);
474 if (!ystart)
475 return ERROR_INT("ystart not defined", procName, 1);
476 if (!yend)
477 return ERROR_INT("yend not defined", procName, 1);
478
479 wpl = pixGetWpl(pix);
480 data = pixGetData(pix);
481
482 inrun = FALSE;
483 index = 0;
484 for (i = 0; i < h; i++) {
485 line = data + i * wpl;
486 val = GET_DATA_BIT(line, x);
487 if (!inrun) {
488 if (val) {
489 ystart[index] = i;
490 inrun = TRUE;
491 }
492 } else {
493 if (!val) {
494 yend[index++] = i - 1;
495 inrun = FALSE;
496 }
497 }
498 }
499
500 /* Finish last run if necessary */
501 if (inrun)
502 yend[index++] = h - 1;
503
504 *pn = index;
505 return 0;
506}
507
508
509/*-----------------------------------------------------------------------*
510 * Find max runs along horizontal and vertical lines *
511 *-----------------------------------------------------------------------*/
527NUMA *
529 l_int32 direction,
530 NUMA **pnastart)
531{
532l_int32 w, h, i, start, size;
533NUMA *nasize;
534
535 PROCNAME("pixFindMaxRuns");
536
537 if (pnastart) *pnastart = NULL;
538 if (direction != L_HORIZONTAL_RUNS && direction != L_VERTICAL_RUNS)
539 return (NUMA *)ERROR_PTR("direction invalid", procName, NULL);
540 if (!pix || pixGetDepth(pix) != 1)
541 return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
542
543 pixGetDimensions(pix, &w, &h, NULL);
544 nasize = numaCreate(w);
545 if (pnastart) *pnastart = numaCreate(w);
546 if (direction == L_HORIZONTAL_RUNS) {
547 for (i = 0; i < h; i++) {
548 pixFindMaxHorizontalRunOnLine(pix, i, &start, &size);
549 numaAddNumber(nasize, size);
550 if (pnastart) numaAddNumber(*pnastart, start);
551 }
552 } else { /* vertical scans */
553 for (i = 0; i < w; i++) {
554 pixFindMaxVerticalRunOnLine(pix, i, &start, &size);
555 numaAddNumber(nasize, size);
556 if (pnastart) numaAddNumber(*pnastart, start);
557 }
558 }
559
560 return nasize;
561}
562
563
580l_ok
582 l_int32 y,
583 l_int32 *pxstart,
584 l_int32 *psize)
585{
586l_int32 inrun; /* boolean */
587l_int32 w, h, j, wpl, val, maxstart, maxsize, length, start;
588l_uint32 *line;
589
590 PROCNAME("pixFindMaxHorizontalRunOnLine");
591
592 if (pxstart) *pxstart = 0;
593 if (!psize)
594 return ERROR_INT("&size not defined", procName, 1);
595 *psize = 0;
596 if (!pix || pixGetDepth(pix) != 1)
597 return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
598 pixGetDimensions(pix, &w, &h, NULL);
599 if (y < 0 || y >= h)
600 return ERROR_INT("y not in [0 ... h - 1]", procName, 1);
601
602 wpl = pixGetWpl(pix);
603 line = pixGetData(pix) + y * wpl;
604 inrun = FALSE;
605 start = 0;
606 maxstart = 0;
607 maxsize = 0;
608 for (j = 0; j < w; j++) {
609 val = GET_DATA_BIT(line, j);
610 if (!inrun) {
611 if (val) {
612 start = j;
613 inrun = TRUE;
614 }
615 } else if (!val) { /* run just ended */
616 length = j - start;
617 if (length > maxsize) {
618 maxsize = length;
619 maxstart = start;
620 }
621 inrun = FALSE;
622 }
623 }
624
625 if (inrun) { /* a run has continued to the end of the row */
626 length = j - start;
627 if (length > maxsize) {
628 maxsize = length;
629 maxstart = start;
630 }
631 }
632 if (pxstart) *pxstart = maxstart;
633 *psize = maxsize;
634 return 0;
635}
636
637
654l_ok
656 l_int32 x,
657 l_int32 *pystart,
658 l_int32 *psize)
659{
660l_int32 inrun; /* boolean */
661l_int32 w, h, i, wpl, val, maxstart, maxsize, length, start;
662l_uint32 *data, *line;
663
664 PROCNAME("pixFindMaxVerticalRunOnLine");
665
666 if (pystart) *pystart = 0;
667 if (!psize)
668 return ERROR_INT("&size not defined", procName, 1);
669 *psize = 0;
670 if (!pix || pixGetDepth(pix) != 1)
671 return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
672 pixGetDimensions(pix, &w, &h, NULL);
673 if (x < 0 || x >= w)
674 return ERROR_INT("x not in [0 ... w - 1]", procName, 1);
675
676 wpl = pixGetWpl(pix);
677 data = pixGetData(pix);
678 inrun = FALSE;
679 start = 0;
680 maxstart = 0;
681 maxsize = 0;
682 for (i = 0; i < h; i++) {
683 line = data + i * wpl;
684 val = GET_DATA_BIT(line, x);
685 if (!inrun) {
686 if (val) {
687 start = i;
688 inrun = TRUE;
689 }
690 } else if (!val) { /* run just ended */
691 length = i - start;
692 if (length > maxsize) {
693 maxsize = length;
694 maxstart = start;
695 }
696 inrun = FALSE;
697 }
698 }
699
700 if (inrun) { /* a run has continued to the end of the column */
701 length = i - start;
702 if (length > maxsize) {
703 maxsize = length;
704 maxstart = start;
705 }
706 }
707 if (pystart) *pystart = maxstart;
708 *psize = maxsize;
709 return 0;
710}
711
712
713/*-----------------------------------------------------------------------*
714 * Compute runlength-to-membership transform on a line *
715 *-----------------------------------------------------------------------*/
735l_ok
737 l_int32 size,
738 l_int32 depth,
739 l_int32 *start,
740 l_int32 *end,
741 l_int32 n)
742{
743l_int32 i, j, first, last, diff, max;
744
745 PROCNAME("runlengthMembershipOnLine");
746
747 if (!buffer)
748 return ERROR_INT("buffer not defined", procName, 1);
749 if (!start)
750 return ERROR_INT("start not defined", procName, 1);
751 if (!end)
752 return ERROR_INT("end not defined", procName, 1);
753
754 if (depth == 8)
755 max = 0xff;
756 else /* depth == 16 */
757 max = 0xffff;
758
759 memset(buffer, 0, 4 * size);
760 for (i = 0; i < n; i++) {
761 first = start[i];
762 last = end[i];
763 diff = last - first + 1;
764 diff = L_MIN(diff, max);
765 for (j = first; j <= last; j++)
766 buffer[j] = diff;
767 }
768
769 return 0;
770}
771
772
773/*-----------------------------------------------------------------------*
774 * Make byte position LUT *
775 *-----------------------------------------------------------------------*/
791l_int32 *
792makeMSBitLocTab(l_int32 bitval)
793{
794l_int32 i, j;
795l_int32 *tab;
796l_uint8 byte, mask;
797
798 tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
799 for (i = 0; i < 256; i++) {
800 byte = (l_uint8)i;
801 if (bitval == 0)
802 byte = ~byte;
803 tab[i] = 8;
804 mask = 0x80;
805 for (j = 0; j < 8; j++) {
806 if (byte & mask) {
807 tab[i] = j;
808 break;
809 }
810 mask >>= 1;
811 }
812 }
813 return tab;
814}
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
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 * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
@ L_VERTICAL_RUNS
Definition: pix.h:1162
@ L_HORIZONTAL_RUNS
Definition: pix.h:1161
#define PIX_SRC
Definition: pix.h:330
@ L_BRING_IN_WHITE
Definition: pix.h:869
PIX * pixMinOrMax(PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 type)
pixMinOrMax()
Definition: pixarith.c:1152
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:204
PIX * pixRotateShear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShear()
Definition: rotateshear.c:208
l_ok runlengthMembershipOnLine(l_int32 *buffer, l_int32 size, l_int32 depth, l_int32 *start, l_int32 *end, l_int32 n)
runlengthMembershipOnLine()
Definition: runlength.c:736
l_ok pixFindHorizontalRuns(PIX *pix, l_int32 y, l_int32 *xstart, l_int32 *xend, l_int32 *pn)
pixFindHorizontalRuns()
Definition: runlength.c:375
NUMA * pixFindMaxRuns(PIX *pix, l_int32 direction, NUMA **pnastart)
pixFindMaxRuns()
Definition: runlength.c:528
l_ok pixFindMaxHorizontalRunOnLine(PIX *pix, l_int32 y, l_int32 *pxstart, l_int32 *psize)
pixFindMaxHorizontalRunOnLine()
Definition: runlength.c:581
PIX * pixRunlengthTransform(PIX *pixs, l_int32 color, l_int32 direction, l_int32 depth)
pixRunlengthTransform()
Definition: runlength.c:265
l_ok pixFindVerticalRuns(PIX *pix, l_int32 x, l_int32 *ystart, l_int32 *yend, l_int32 *pn)
pixFindVerticalRuns()
Definition: runlength.c:452
l_ok pixFindMaxVerticalRunOnLine(PIX *pix, l_int32 x, l_int32 *pystart, l_int32 *psize)
pixFindMaxVerticalRunOnLine()
Definition: runlength.c:655
static PIX * pixFindMinRunsOrthogonal(PIX *pixs, l_float32 angle, l_int32 depth)
pixFindMinRunsOrthogonal()
Definition: runlength.c:199
PIX * pixStrokeWidthTransform(PIX *pixs, l_int32 color, l_int32 depth, l_int32 nangles)
pixStrokeWidthTransform()
Definition: runlength.c:102
l_int32 * makeMSBitLocTab(l_int32 bitval)
makeMSBitLocTab()
Definition: runlength.c:792
Definition: pix.h:481
Definition: array.h:71
Definition: pix.h:139