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 
67 static PIX *pixFindMinRunsOrthogonal(PIX *pixs, l_float32 angle, l_int32 depth);
68 
69 /*-----------------------------------------------------------------------*
70  * Label pixels by membership in runs *
71  *-----------------------------------------------------------------------*/
101 PIX *
103  l_int32 color,
104  l_int32 depth,
105  l_int32 nangles)
106 {
107 l_float32 angle, pi;
108 PIX *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 
198 static PIX *
200  l_float32 angle,
201  l_int32 depth)
202 {
203 l_int32 w, h, diag, xoff, yoff;
204 PIX *pixb, *pixr, *pixh, *pixv, *pixg1, *pixg2, *pixd;
205 BOX *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 
264 PIX *
266  l_int32 color,
267  l_int32 direction,
268  l_int32 depth)
269 {
270 l_int32 i, j, w, h, wpld, bufsize, maxsize, n;
271 l_int32 *start, *end, *buffer;
272 l_uint32 *datad, *lined;
273 PIX *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  *-----------------------------------------------------------------------*/
374 l_ok
376  l_int32 y,
377  l_int32 *xstart,
378  l_int32 *xend,
379  l_int32 *pn)
380 {
381 l_int32 inrun; /* boolean */
382 l_int32 index, w, h, d, j, wpl, val;
383 l_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 
451 l_ok
453  l_int32 x,
454  l_int32 *ystart,
455  l_int32 *yend,
456  l_int32 *pn)
457 {
458 l_int32 inrun; /* boolean */
459 l_int32 index, w, h, d, i, wpl, val;
460 l_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  *-----------------------------------------------------------------------*/
527 NUMA *
529  l_int32 direction,
530  NUMA **pnastart)
531 {
532 l_int32 w, h, i, start, size;
533 NUMA *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 
580 l_ok
582  l_int32 y,
583  l_int32 *pxstart,
584  l_int32 *psize)
585 {
586 l_int32 inrun; /* boolean */
587 l_int32 w, h, j, wpl, val, maxstart, maxsize, length, start;
588 l_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 
654 l_ok
656  l_int32 x,
657  l_int32 *pystart,
658  l_int32 *psize)
659 {
660 l_int32 inrun; /* boolean */
661 l_int32 w, h, i, wpl, val, maxstart, maxsize, length, start;
662 l_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  *-----------------------------------------------------------------------*/
735 l_ok
737  l_int32 size,
738  l_int32 depth,
739  l_int32 *start,
740  l_int32 *end,
741  l_int32 n)
742 {
743 l_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  *-----------------------------------------------------------------------*/
791 l_int32 *
792 makeMSBitLocTab(l_int32 bitval)
793 {
794 l_int32 i, j;
795 l_int32 *tab;
796 l_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 }
PIX * pixRotateShear(PIX *pixs, l_int32 xcen, l_int32 ycen, l_float32 angle, l_int32 incolor)
pixRotateShear()
Definition: rotateshear.c:208
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
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 * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixFindMaxVerticalRunOnLine(PIX *pix, l_int32 x, l_int32 *pystart, l_int32 *psize)
pixFindMaxVerticalRunOnLine()
Definition: runlength.c:655
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
l_ok pixFindHorizontalRuns(PIX *pix, l_int32 y, l_int32 *xstart, l_int32 *xend, l_int32 *pn)
pixFindHorizontalRuns()
Definition: runlength.c:375
Definition: array.h:70
l_int32 * makeMSBitLocTab(l_int32 bitval)
makeMSBitLocTab()
Definition: runlength.c:792
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
static PIX * pixFindMinRunsOrthogonal(PIX *pixs, l_float32 angle, l_int32 depth)
pixFindMinRunsOrthogonal()
Definition: runlength.c:199
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
l_ok pixFindVerticalRuns(PIX *pix, l_int32 x, l_int32 *ystart, l_int32 *yend, l_int32 *pn)
pixFindVerticalRuns()
Definition: runlength.c:452
PIX * pixRunlengthTransform(PIX *pixs, l_int32 color, l_int32 direction, l_int32 depth)
pixRunlengthTransform()
Definition: runlength.c:265
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
Definition: pix.h:138
#define PIX_SRC
Definition: pix.h:330
l_ok pixFindMaxHorizontalRunOnLine(PIX *pix, l_int32 y, l_int32 *pxstart, l_int32 *psize)
pixFindMaxHorizontalRunOnLine()
Definition: runlength.c:581
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
PIX * pixMinOrMax(PIX *pixd, PIX *pixs1, PIX *pixs2, l_int32 type)
pixMinOrMax()
Definition: pixarith.c:1152
PIX * pixStrokeWidthTransform(PIX *pixs, l_int32 color, l_int32 depth, l_int32 nangles)
pixStrokeWidthTransform()
Definition: runlength.c:102
NUMA * pixFindMaxRuns(PIX *pix, l_int32 direction, NUMA **pnastart)
pixFindMaxRuns()
Definition: runlength.c:528
Definition: pix.h:480
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
l_int32 index
Definition: regutils.h:123