Leptonica  1.82.0
Image processing and image analysis suite
graphics.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 
117 #ifdef HAVE_CONFIG_H
118 #include <config_auto.h>
119 #endif /* HAVE_CONFIG_H */
120 
121 #include <string.h>
122 #include <math.h>
123 #include "allheaders.h"
124 
125 /*------------------------------------------------------------------*
126  * Pta generation for arbitrary shapes built with lines *
127  *------------------------------------------------------------------*/
140 PTA *
141 generatePtaLine(l_int32 x1,
142  l_int32 y1,
143  l_int32 x2,
144  l_int32 y2)
145 {
146 l_int32 npts, diff, getyofx, sign, i, x, y;
147 l_float32 slope;
148 PTA *pta;
149 
150  PROCNAME("generatePtaLine");
151 
152  /* Generate line parameters */
153  if (x1 == x2 && y1 == y2) { /* same point */
154  getyofx = TRUE;
155  npts = 1;
156  } else if (L_ABS(x2 - x1) >= L_ABS(y2 - y1)) {
157  getyofx = TRUE;
158  npts = L_ABS(x2 - x1) + 1;
159  diff = x2 - x1;
160  sign = L_SIGN(x2 - x1);
161  slope = (l_float32)(sign * (y2 - y1)) / (l_float32)diff;
162  } else {
163  getyofx = FALSE;
164  npts = L_ABS(y2 - y1) + 1;
165  diff = y2 - y1;
166  sign = L_SIGN(y2 - y1);
167  slope = (l_float32)(sign * (x2 - x1)) / (l_float32)diff;
168  }
169 
170  if ((pta = ptaCreate(npts)) == NULL)
171  return (PTA *)ERROR_PTR("pta not made", procName, NULL);
172 
173  if (npts == 1) { /* degenerate case */
174  ptaAddPt(pta, x1, y1);
175  return pta;
176  }
177 
178  /* Generate the set of points */
179  if (getyofx) { /* y = y(x) */
180  for (i = 0; i < npts; i++) {
181  x = x1 + sign * i;
182  y = (l_int32)(y1 + (l_float32)i * slope + 0.5);
183  ptaAddPt(pta, x, y);
184  }
185  } else { /* x = x(y) */
186  for (i = 0; i < npts; i++) {
187  x = (l_int32)(x1 + (l_float32)i * slope + 0.5);
188  y = y1 + sign * i;
189  ptaAddPt(pta, x, y);
190  }
191  }
192 
193  return pta;
194 }
195 
196 
205 PTA *
207  l_int32 y1,
208  l_int32 x2,
209  l_int32 y2,
210  l_int32 width)
211 {
212 l_int32 i, x1a, x2a, y1a, y2a;
213 PTA *pta, *ptaj;
214 
215  PROCNAME("generatePtaWideLine");
216 
217  if (width < 1) {
218  L_WARNING("width < 1; setting to 1\n", procName);
219  width = 1;
220  }
221 
222  if ((ptaj = generatePtaLine(x1, y1, x2, y2)) == NULL)
223  return (PTA *)ERROR_PTR("ptaj not made", procName, NULL);
224  if (width == 1)
225  return ptaj;
226 
227  /* width > 1; estimate line direction & join */
228  if (L_ABS(x1 - x2) > L_ABS(y1 - y2)) { /* "horizontal" line */
229  for (i = 1; i < width; i++) {
230  if ((i & 1) == 1) { /* place above */
231  y1a = y1 - (i + 1) / 2;
232  y2a = y2 - (i + 1) / 2;
233  } else { /* place below */
234  y1a = y1 + (i + 1) / 2;
235  y2a = y2 + (i + 1) / 2;
236  }
237  if ((pta = generatePtaLine(x1, y1a, x2, y2a)) != NULL) {
238  ptaJoin(ptaj, pta, 0, -1);
239  ptaDestroy(&pta);
240  }
241  }
242  } else { /* "vertical" line */
243  for (i = 1; i < width; i++) {
244  if ((i & 1) == 1) { /* place to left */
245  x1a = x1 - (i + 1) / 2;
246  x2a = x2 - (i + 1) / 2;
247  } else { /* place to right */
248  x1a = x1 + (i + 1) / 2;
249  x2a = x2 + (i + 1) / 2;
250  }
251  if ((pta = generatePtaLine(x1a, y1, x2a, y2)) != NULL) {
252  ptaJoin(ptaj, pta, 0, -1);
253  ptaDestroy(&pta);
254  }
255  }
256  }
257 
258  return ptaj;
259 }
260 
261 
275 PTA *
277  l_int32 width)
278 {
279 l_int32 x, y, w, h;
280 PTA *ptad, *pta;
281 
282  PROCNAME("generatePtaBox");
283 
284  if (!box)
285  return (PTA *)ERROR_PTR("box not defined", procName, NULL);
286  if (width < 1) {
287  L_WARNING("width < 1; setting to 1\n", procName);
288  width = 1;
289  }
290 
291  /* Generate line points and add them to the pta. */
292  boxGetGeometry(box, &x, &y, &w, &h);
293  if (w == 0 || h == 0)
294  return (PTA *)ERROR_PTR("box has w = 0 or h = 0", procName, NULL);
295  ptad = ptaCreate(0);
296  if ((width & 1) == 1) { /* odd width */
297  pta = generatePtaWideLine(x - width / 2, y,
298  x + w - 1 + width / 2, y, width);
299  ptaJoin(ptad, pta, 0, -1);
300  ptaDestroy(&pta);
301  pta = generatePtaWideLine(x + w - 1, y + 1 + width / 2,
302  x + w - 1, y + h - 2 - width / 2, width);
303  ptaJoin(ptad, pta, 0, -1);
304  ptaDestroy(&pta);
305  pta = generatePtaWideLine(x + w - 1 + width / 2, y + h - 1,
306  x - width / 2, y + h - 1, width);
307  ptaJoin(ptad, pta, 0, -1);
308  ptaDestroy(&pta);
309  pta = generatePtaWideLine(x, y + h - 2 - width / 2,
310  x, y + 1 + width / 2, width);
311  ptaJoin(ptad, pta, 0, -1);
312  ptaDestroy(&pta);
313  } else { /* even width */
314  pta = generatePtaWideLine(x - width / 2, y,
315  x + w - 2 + width / 2, y, width);
316  ptaJoin(ptad, pta, 0, -1);
317  ptaDestroy(&pta);
318  pta = generatePtaWideLine(x + w - 1, y + 0 + width / 2,
319  x + w - 1, y + h - 2 - width / 2, width);
320  ptaJoin(ptad, pta, 0, -1);
321  ptaDestroy(&pta);
322  pta = generatePtaWideLine(x + w - 2 + width / 2, y + h - 1,
323  x - width / 2, y + h - 1, width);
324  ptaJoin(ptad, pta, 0, -1);
325  ptaDestroy(&pta);
326  pta = generatePtaWideLine(x, y + h - 2 - width / 2,
327  x, y + 0 + width / 2, width);
328  ptaJoin(ptad, pta, 0, -1);
329  ptaDestroy(&pta);
330  }
331 
332  return ptad;
333 }
334 
335 
352 PTA *
354  l_int32 width,
355  l_int32 removedups)
356 {
357 l_int32 i, n;
358 BOX *box;
359 PTA *ptad, *ptat, *pta;
360 
361  PROCNAME("generatePtaBoxa");
362 
363  if (!boxa)
364  return (PTA *)ERROR_PTR("boxa not defined", procName, NULL);
365  if (width < 1) {
366  L_WARNING("width < 1; setting to 1\n", procName);
367  width = 1;
368  }
369 
370  n = boxaGetCount(boxa);
371  ptat = ptaCreate(0);
372  for (i = 0; i < n; i++) {
373  box = boxaGetBox(boxa, i, L_CLONE);
374  pta = generatePtaBox(box, width);
375  ptaJoin(ptat, pta, 0, -1);
376  ptaDestroy(&pta);
377  boxDestroy(&box);
378  }
379 
380  if (removedups)
381  ptaRemoveDupsByAset(ptat, &ptad);
382  else
383  ptad = ptaClone(ptat);
384 
385  ptaDestroy(&ptat);
386  return ptad;
387 }
388 
389 
409 PTA *
411  l_int32 spacing,
412  l_int32 width,
413  l_int32 orient,
414  l_int32 outline)
415 {
416 l_int32 bx, by, bh, bw, x, y, x1, y1, x2, y2, i, n, npts;
417 PTA *ptad, *pta;
418 
419  PROCNAME("generatePtaHashBox");
420 
421  if (!box)
422  return (PTA *)ERROR_PTR("box not defined", procName, NULL);
423  if (spacing <= 1)
424  return (PTA *)ERROR_PTR("spacing not > 1", procName, NULL);
425  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
426  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
427  return (PTA *)ERROR_PTR("invalid line orientation", procName, NULL);
428  boxGetGeometry(box, &bx, &by, &bw, &bh);
429  if (bw == 0 || bh == 0)
430  return (PTA *)ERROR_PTR("box has bw = 0 or bh = 0", procName, NULL);
431  if (width < 1) {
432  L_WARNING("width < 1; setting to 1\n", procName);
433  width = 1;
434  }
435 
436  /* Generate line points and add them to the pta. */
437  ptad = ptaCreate(0);
438  if (outline) {
439  pta = generatePtaBox(box, width);
440  ptaJoin(ptad, pta, 0, -1);
441  ptaDestroy(&pta);
442  }
443  if (orient == L_HORIZONTAL_LINE) {
444  n = 1 + bh / spacing;
445  for (i = 0; i < n; i++) {
446  y = by + (i * (bh - 1)) / (n - 1);
447  pta = generatePtaWideLine(bx, y, bx + bw - 1, y, width);
448  ptaJoin(ptad, pta, 0, -1);
449  ptaDestroy(&pta);
450  }
451  } else if (orient == L_VERTICAL_LINE) {
452  n = 1 + bw / spacing;
453  for (i = 0; i < n; i++) {
454  x = bx + (i * (bw - 1)) / (n - 1);
455  pta = generatePtaWideLine(x, by, x, by + bh - 1, width);
456  ptaJoin(ptad, pta, 0, -1);
457  ptaDestroy(&pta);
458  }
459  } else if (orient == L_POS_SLOPE_LINE) {
460  n = 2 + (l_int32)((bw + bh) / (1.4 * spacing));
461  for (i = 0; i < n; i++) {
462  x = (l_int32)(bx + (i + 0.5) * 1.4 * spacing);
463  boxIntersectByLine(box, x, by - 1, 1.0, &x1, &y1, &x2, &y2, &npts);
464  if (npts == 2) {
465  pta = generatePtaWideLine(x1, y1, x2, y2, width);
466  ptaJoin(ptad, pta, 0, -1);
467  ptaDestroy(&pta);
468  }
469  }
470  } else { /* orient == L_NEG_SLOPE_LINE */
471  n = 2 + (l_int32)((bw + bh) / (1.4 * spacing));
472  for (i = 0; i < n; i++) {
473  x = (l_int32)(bx - bh + (i + 0.5) * 1.4 * spacing);
474  boxIntersectByLine(box, x, by - 1, -1.0, &x1, &y1, &x2, &y2, &npts);
475  if (npts == 2) {
476  pta = generatePtaWideLine(x1, y1, x2, y2, width);
477  ptaJoin(ptad, pta, 0, -1);
478  ptaDestroy(&pta);
479  }
480  }
481  }
482 
483  return ptad;
484 }
485 
486 
512 PTA *
514  l_int32 spacing,
515  l_int32 width,
516  l_int32 orient,
517  l_int32 outline,
518  l_int32 removedups)
519 {
520 l_int32 i, n;
521 BOX *box;
522 PTA *ptad, *ptat, *pta;
523 
524  PROCNAME("generatePtaHashBoxa");
525 
526  if (!boxa)
527  return (PTA *)ERROR_PTR("boxa not defined", procName, NULL);
528  if (spacing <= 1)
529  return (PTA *)ERROR_PTR("spacing not > 1", procName, NULL);
530  if (width < 1) {
531  L_WARNING("width < 1; setting to 1\n", procName);
532  width = 1;
533  }
534  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
535  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
536  return (PTA *)ERROR_PTR("invalid line orientation", procName, NULL);
537 
538  n = boxaGetCount(boxa);
539  ptat = ptaCreate(0);
540  for (i = 0; i < n; i++) {
541  box = boxaGetBox(boxa, i, L_CLONE);
542  pta = generatePtaHashBox(box, spacing, width, orient, outline);
543  ptaJoin(ptat, pta, 0, -1);
544  ptaDestroy(&pta);
545  boxDestroy(&box);
546  }
547 
548  if (removedups)
549  ptaRemoveDupsByAset(ptat, &ptad);
550  else
551  ptad = ptaClone(ptat);
552 
553  ptaDestroy(&ptat);
554  return ptad;
555 }
556 
557 
572 PTAA *
574 {
575 l_int32 i, n, x, y, w, h;
576 BOX *box;
577 PTA *pta;
578 PTAA *ptaa;
579 
580  PROCNAME("generatePtaaBoxa");
581 
582  if (!boxa)
583  return (PTAA *)ERROR_PTR("boxa not defined", procName, NULL);
584 
585  n = boxaGetCount(boxa);
586  ptaa = ptaaCreate(n);
587  for (i = 0; i < n; i++) {
588  box = boxaGetBox(boxa, i, L_CLONE);
589  boxGetGeometry(box, &x, &y, &w, &h);
590  pta = ptaCreate(4);
591  ptaAddPt(pta, x, y);
592  ptaAddPt(pta, x + w - 1, y);
593  ptaAddPt(pta, x + w - 1, y + h - 1);
594  ptaAddPt(pta, x, y + h - 1);
595  ptaaAddPta(ptaa, pta, L_INSERT);
596  boxDestroy(&box);
597  }
598 
599  return ptaa;
600 }
601 
602 
625 PTAA *
627  l_int32 spacing,
628  l_int32 width,
629  l_int32 orient,
630  l_int32 outline)
631 {
632 l_int32 i, n;
633 BOX *box;
634 PTA *pta;
635 PTAA *ptaa;
636 
637  PROCNAME("generatePtaaHashBoxa");
638 
639  if (!boxa)
640  return (PTAA *)ERROR_PTR("boxa not defined", procName, NULL);
641  if (spacing <= 1)
642  return (PTAA *)ERROR_PTR("spacing not > 1", procName, NULL);
643  if (width < 1) {
644  L_WARNING("width < 1; setting to 1\n", procName);
645  width = 1;
646  }
647  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
648  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
649  return (PTAA *)ERROR_PTR("invalid line orientation", procName, NULL);
650 
651  n = boxaGetCount(boxa);
652  ptaa = ptaaCreate(n);
653  for (i = 0; i < n; i++) {
654  box = boxaGetBox(boxa, i, L_CLONE);
655  pta = generatePtaHashBox(box, spacing, width, orient, outline);
656  ptaaAddPta(ptaa, pta, L_INSERT);
657  boxDestroy(&box);
658  }
659 
660  return ptaa;
661 }
662 
663 
673 PTA *
675  l_int32 width,
676  l_int32 closeflag,
677  l_int32 removedups)
678 {
679 l_int32 i, n, x1, y1, x2, y2;
680 PTA *ptad, *ptat, *pta;
681 
682  PROCNAME("generatePtaPolyline");
683 
684  if (!ptas)
685  return (PTA *)ERROR_PTR("ptas not defined", procName, NULL);
686  if (width < 1) {
687  L_WARNING("width < 1; setting to 1\n", procName);
688  width = 1;
689  }
690 
691  n = ptaGetCount(ptas);
692  ptat = ptaCreate(0);
693  if (n < 2) /* nothing to do */
694  return ptat;
695 
696  ptaGetIPt(ptas, 0, &x1, &y1);
697  for (i = 1; i < n; i++) {
698  ptaGetIPt(ptas, i, &x2, &y2);
699  pta = generatePtaWideLine(x1, y1, x2, y2, width);
700  ptaJoin(ptat, pta, 0, -1);
701  ptaDestroy(&pta);
702  x1 = x2;
703  y1 = y2;
704  }
705 
706  if (closeflag) {
707  ptaGetIPt(ptas, 0, &x2, &y2);
708  pta = generatePtaWideLine(x1, y1, x2, y2, width);
709  ptaJoin(ptat, pta, 0, -1);
710  ptaDestroy(&pta);
711  }
712 
713  if (removedups)
714  ptaRemoveDupsByAset(ptat, &ptad);
715  else
716  ptad = ptaClone(ptat);
717 
718  ptaDestroy(&ptat);
719  return ptad;
720 }
721 
722 
731 PTA *
732 generatePtaGrid(l_int32 w,
733  l_int32 h,
734  l_int32 nx,
735  l_int32 ny,
736  l_int32 width)
737 {
738 l_int32 i, j, bx, by, x1, x2, y1, y2;
739 BOX *box;
740 BOXA *boxa;
741 PTA *pta;
742 
743  PROCNAME("generatePtaGrid");
744 
745  if (nx < 1 || ny < 1)
746  return (PTA *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
747  if (w < 2 * nx || h < 2 * ny)
748  return (PTA *)ERROR_PTR("w and/or h too small", procName, NULL);
749  if (width < 1) {
750  L_WARNING("width < 1; setting to 1\n", procName);
751  width = 1;
752  }
753 
754  boxa = boxaCreate(nx * ny);
755  bx = (w + nx - 1) / nx;
756  by = (h + ny - 1) / ny;
757  for (i = 0; i < ny; i++) {
758  y1 = by * i;
759  y2 = L_MIN(y1 + by, h - 1);
760  for (j = 0; j < nx; j++) {
761  x1 = bx * j;
762  x2 = L_MIN(x1 + bx, w - 1);
763  box = boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
764  boxaAddBox(boxa, box, L_INSERT);
765  }
766  }
767 
768  pta = generatePtaBoxa(boxa, width, 1);
769  boxaDestroy(&boxa);
770  return pta;
771 }
772 
773 
789 PTA *
791 {
792 l_int32 i, n, x, y, xp, yp;
793 PTA *ptad;
794 
795  PROCNAME("convertPtaLineTo4cc");
796 
797  if (!ptas)
798  return (PTA *)ERROR_PTR("ptas not defined", procName, NULL);
799 
800  n = ptaGetCount(ptas);
801  ptad = ptaCreate(n);
802  ptaGetIPt(ptas, 0, &xp, &yp);
803  ptaAddPt(ptad, xp, yp);
804  for (i = 1; i < n; i++) {
805  ptaGetIPt(ptas, i, &x, &y);
806  if (x != xp && y != yp) /* diagonal */
807  ptaAddPt(ptad, x, yp);
808  ptaAddPt(ptad, x, y);
809  xp = x;
810  yp = y;
811  }
812 
813  return ptad;
814 }
815 
816 
832 PTA *
833 generatePtaFilledCircle(l_int32 radius)
834 {
835 l_int32 x, y;
836 l_float32 radthresh, sqdist;
837 PTA *pta;
838 
839  PROCNAME("generatePtaFilledCircle");
840 
841  if (radius < 1)
842  return (PTA *)ERROR_PTR("radius must be >= 1", procName, NULL);
843 
844  pta = ptaCreate(0);
845  radthresh = (radius + 0.5) * (radius + 0.5);
846  for (y = 0; y <= 2 * radius; y++) {
847  for (x = 0; x <= 2 * radius; x++) {
848  sqdist = (l_float32)((y - radius) * (y - radius) +
849  (x - radius) * (x - radius));
850  if (sqdist <= radthresh)
851  ptaAddPt(pta, x, y);
852  }
853  }
854 
855  return pta;
856 }
857 
858 
872 PTA *
874 {
875 l_int32 x, y;
876 PTA *pta;
877 
878  PROCNAME("generatePtaFilledSquare");
879  if (side < 1)
880  return (PTA *)ERROR_PTR("side must be > 0", procName, NULL);
881 
882  pta = ptaCreate(0);
883  for (y = 0; y < side; y++)
884  for (x = 0; x < side; x++)
885  ptaAddPt(pta, x, y);
886 
887  return pta;
888 }
889 
890 
906 PTA *
908  l_int32 y,
909  l_float64 length,
910  l_float64 radang)
911 {
912 l_int32 x2, y2; /* the point at the other end of the line */
913 
914  x2 = x + (l_int32)((length - 1.0) * cos(radang));
915  y2 = y + (l_int32)((length - 1.0) * sin(radang));
916  return generatePtaLine(x, y, x2, y2);
917 }
918 
919 
930 l_ok
931 locatePtRadially(l_int32 xr,
932  l_int32 yr,
933  l_float64 dist,
934  l_float64 radang,
935  l_float64 *px,
936  l_float64 *py)
937 {
938  PROCNAME("locatePtRadially");
939 
940  if (!px || !py)
941  return ERROR_INT("&x and &y not both defined", procName, 1);
942 
943  *px = xr + dist * cos(radang);
944  *py = yr + dist * sin(radang);
945  return 0;
946 }
947 
948 
949 /*------------------------------------------------------------------*
950  * Rendering function plots directly on images *
951  *------------------------------------------------------------------*/
972 l_ok
974  NUMA *na,
975  l_int32 plotloc,
976  l_int32 linewidth,
977  l_int32 max,
978  l_uint32 color)
979 {
980 l_int32 w, h, size, rval, gval, bval;
981 PIX *pix1;
982 PTA *pta;
983 
984  PROCNAME("pixRenderPlotFromNuma");
985 
986  if (!ppix)
987  return ERROR_INT("&pix not defined", procName, 1);
988  if (*ppix == NULL)
989  return ERROR_INT("pix not defined", procName, 1);
990 
991  pixGetDimensions(*ppix, &w, &h, NULL);
992  size = (plotloc == L_PLOT_AT_TOP || plotloc == L_PLOT_AT_MID_HORIZ ||
993  plotloc == L_PLOT_AT_BOT) ? h : w;
994  pta = makePlotPtaFromNuma(na, size, plotloc, linewidth, max);
995  if (!pta)
996  return ERROR_INT("pta not made", procName, 1);
997 
998  if (pixGetDepth(*ppix) != 32) {
999  pix1 = pixConvertTo32(*ppix);
1000  pixDestroy(ppix);
1001  *ppix = pix1;
1002  }
1003  extractRGBValues(color, &rval, &gval, &bval);
1004  pixRenderPtaArb(*ppix, pta, rval, gval, bval);
1005  ptaDestroy(&pta);
1006  return 0;
1007 }
1008 
1009 
1031 PTA *
1033  l_int32 size,
1034  l_int32 plotloc,
1035  l_int32 linewidth,
1036  l_int32 max)
1037 {
1038 l_int32 orient, refpos;
1039 
1040  PROCNAME("makePlotPtaFromNuma");
1041 
1042  if (!na)
1043  return (PTA *)ERROR_PTR("na not defined", procName, NULL);
1044  if (plotloc == L_PLOT_AT_TOP || plotloc == L_PLOT_AT_MID_HORIZ ||
1045  plotloc == L_PLOT_AT_BOT) {
1046  orient = L_HORIZONTAL_LINE;
1047  } else if (plotloc == L_PLOT_AT_LEFT || plotloc == L_PLOT_AT_MID_VERT ||
1048  plotloc == L_PLOT_AT_RIGHT) {
1049  orient = L_VERTICAL_LINE;
1050  } else {
1051  return (PTA *)ERROR_PTR("invalid plotloc", procName, NULL);
1052  }
1053 
1054  if (plotloc == L_PLOT_AT_LEFT || plotloc == L_PLOT_AT_TOP)
1055  refpos = max;
1056  else if (plotloc == L_PLOT_AT_MID_VERT || plotloc == L_PLOT_AT_MID_HORIZ)
1057  refpos = size / 2;
1058  else /* L_PLOT_AT_RIGHT || L_PLOT_AT_BOT */
1059  refpos = size - max - 1;
1060 
1061  return makePlotPtaFromNumaGen(na, orient, linewidth, refpos, max, 1);
1062 }
1063 
1064 
1088 l_ok
1090  NUMA *na,
1091  l_int32 orient,
1092  l_int32 linewidth,
1093  l_int32 refpos,
1094  l_int32 max,
1095  l_int32 drawref,
1096  l_uint32 color)
1097 {
1098 l_int32 rval, gval, bval;
1099 PIX *pix1;
1100 PTA *pta;
1101 
1102  PROCNAME("pixRenderPlotFromNumaGen");
1103 
1104  if (!ppix)
1105  return ERROR_INT("&pix not defined", procName, 1);
1106  if (*ppix == NULL)
1107  return ERROR_INT("pix not defined", procName, 1);
1108 
1109  pta = makePlotPtaFromNumaGen(na, orient, linewidth, refpos, max, drawref);
1110  if (!pta)
1111  return ERROR_INT("pta not made", procName, 1);
1112 
1113  if (pixGetDepth(*ppix) != 32) {
1114  pix1 = pixConvertTo32(*ppix);
1115  pixDestroy(ppix);
1116  *ppix = pix1;
1117  }
1118  extractRGBValues(color, &rval, &gval, &bval);
1119  pixRenderPtaArb(*ppix, pta, rval, gval, bval);
1120  ptaDestroy(&pta);
1121  return 0;
1122 }
1123 
1124 
1154 PTA *
1156  l_int32 orient,
1157  l_int32 linewidth,
1158  l_int32 refpos,
1159  l_int32 max,
1160  l_int32 drawref)
1161 {
1162 l_int32 i, n, maxw, maxh;
1163 l_float32 minval, maxval, absval, val, scale, start, del;
1164 PTA *pta1, *pta2, *ptad;
1165 
1166  PROCNAME("makePlotPtaFromNumaGen");
1167 
1168  if (!na)
1169  return (PTA *)ERROR_PTR("na not defined", procName, NULL);
1170  if (orient != L_HORIZONTAL_LINE && orient != L_VERTICAL_LINE)
1171  return (PTA *)ERROR_PTR("invalid orient", procName, NULL);
1172  if (linewidth < 1) {
1173  L_WARNING("linewidth < 1; setting to 1\n", procName);
1174  linewidth = 1;
1175  }
1176  if (linewidth > 7) {
1177  L_WARNING("linewidth > 7; setting to 7\n", procName);
1178  linewidth = 7;
1179  }
1180 
1181  numaGetMin(na, &minval, NULL);
1182  numaGetMax(na, &maxval, NULL);
1183  absval = L_MAX(L_ABS(minval), L_ABS(maxval));
1184  scale = (l_float32)max / (l_float32)absval;
1185  n = numaGetCount(na);
1186  numaGetParameters(na, &start, &del);
1187 
1188  /* Generate the plot points */
1189  pta1 = ptaCreate(n);
1190  for (i = 0; i < n; i++) {
1191  numaGetFValue(na, i, &val);
1192  if (orient == L_HORIZONTAL_LINE) {
1193  ptaAddPt(pta1, start + i * del, refpos + scale * val);
1194  maxw = (del >= 0) ? start + n * del + linewidth
1195  : start + linewidth;
1196  maxh = refpos + max + linewidth;
1197  } else { /* vertical line */
1198  ptaAddPt(pta1, refpos + scale * val, start + i * del);
1199  maxw = refpos + max + linewidth;
1200  maxh = (del >= 0) ? start + n * del + linewidth
1201  : start + linewidth;
1202  }
1203  }
1204 
1205  /* Optionally, widen the plot */
1206  if (linewidth > 1) {
1207  if (linewidth % 2 == 0) /* even linewidth; use side of a square */
1208  pta2 = generatePtaFilledSquare(linewidth);
1209  else /* odd linewidth; use radius of a circle */
1210  pta2 = generatePtaFilledCircle(linewidth / 2);
1211  ptad = ptaReplicatePattern(pta1, NULL, pta2, linewidth / 2,
1212  linewidth / 2, maxw, maxh);
1213  ptaDestroy(&pta2);
1214  } else {
1215  ptad = ptaClone(pta1);
1216  }
1217  ptaDestroy(&pta1);
1218 
1219  /* Optionally, add the reference lines */
1220  if (drawref) {
1221  if (orient == L_HORIZONTAL_LINE) {
1222  pta1 = generatePtaLine(start, refpos, start + n * del, refpos);
1223  ptaJoin(ptad, pta1, 0, -1);
1224  ptaDestroy(&pta1);
1225  pta1 = generatePtaLine(start, refpos - max,
1226  start, refpos + max);
1227  ptaJoin(ptad, pta1, 0, -1);
1228  } else { /* vertical line */
1229  pta1 = generatePtaLine(refpos, start, refpos, start + n * del);
1230  ptaJoin(ptad, pta1, 0, -1);
1231  ptaDestroy(&pta1);
1232  pta1 = generatePtaLine(refpos - max, start,
1233  refpos + max, start);
1234  ptaJoin(ptad, pta1, 0, -1);
1235  }
1236  ptaDestroy(&pta1);
1237  }
1238 
1239  return ptad;
1240 }
1241 
1242 
1243 /*------------------------------------------------------------------*
1244  * Pta generation for arbitrary shapes built with lines *
1245  *------------------------------------------------------------------*/
1266 l_ok
1268  PTA *pta,
1269  l_int32 op)
1270 {
1271 l_int32 i, n, x, y, w, h, d, maxval;
1272 
1273  PROCNAME("pixRenderPta");
1274 
1275  if (!pix)
1276  return ERROR_INT("pix not defined", procName, 1);
1277  if (pixGetColormap(pix))
1278  return ERROR_INT("pix is colormapped", procName, 1);
1279  if (!pta)
1280  return ERROR_INT("pta not defined", procName, 1);
1281  if (op != L_SET_PIXELS && op != L_CLEAR_PIXELS && op != L_FLIP_PIXELS)
1282  return ERROR_INT("invalid op", procName, 1);
1283 
1284  pixGetDimensions(pix, &w, &h, &d);
1285  maxval = 1;
1286  if (op == L_SET_PIXELS) {
1287  switch (d)
1288  {
1289  case 2:
1290  maxval = 0x3;
1291  break;
1292  case 4:
1293  maxval = 0xf;
1294  break;
1295  case 8:
1296  maxval = 0xff;
1297  break;
1298  case 16:
1299  maxval = 0xffff;
1300  break;
1301  case 32:
1302  maxval = 0xffffffff;
1303  break;
1304  }
1305  }
1306 
1307  n = ptaGetCount(pta);
1308  for (i = 0; i < n; i++) {
1309  ptaGetIPt(pta, i, &x, &y);
1310  if (x < 0 || x >= w)
1311  continue;
1312  if (y < 0 || y >= h)
1313  continue;
1314  switch (op)
1315  {
1316  case L_SET_PIXELS:
1317  pixSetPixel(pix, x, y, maxval);
1318  break;
1319  case L_CLEAR_PIXELS:
1320  pixClearPixel(pix, x, y);
1321  break;
1322  case L_FLIP_PIXELS:
1323  pixFlipPixel(pix, x, y);
1324  break;
1325  default:
1326  break;
1327  }
1328  }
1329 
1330  return 0;
1331 }
1332 
1333 
1355 l_ok
1357  PTA *pta,
1358  l_uint8 rval,
1359  l_uint8 gval,
1360  l_uint8 bval)
1361 {
1362 l_int32 i, n, x, y, w, h, d, index;
1363 l_uint8 val;
1364 l_uint32 val32;
1365 PIXCMAP *cmap;
1366 
1367  PROCNAME("pixRenderPtaArb");
1368 
1369  if (!pix)
1370  return ERROR_INT("pix not defined", procName, 1);
1371  if (!pta)
1372  return ERROR_INT("pta not defined", procName, 1);
1373  d = pixGetDepth(pix);
1374  if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
1375  return ERROR_INT("depth not in {1,2,4,8,32}", procName, 1);
1376 
1377  if (d == 1) {
1378  pixRenderPta(pix, pta, L_SET_PIXELS);
1379  return 0;
1380  }
1381 
1382  cmap = pixGetColormap(pix);
1383  pixGetDimensions(pix, &w, &h, &d);
1384  if (cmap) {
1385  pixcmapAddNearestColor(cmap, rval, gval, bval, &index);
1386  } else {
1387  if (d == 2)
1388  val = (rval + gval + bval) / (3 * 64);
1389  else if (d == 4)
1390  val = (rval + gval + bval) / (3 * 16);
1391  else if (d == 8)
1392  val = (rval + gval + bval) / 3;
1393  else /* d == 32 */
1394  composeRGBPixel(rval, gval, bval, &val32);
1395  }
1396 
1397  n = ptaGetCount(pta);
1398  for (i = 0; i < n; i++) {
1399  ptaGetIPt(pta, i, &x, &y);
1400  if (x < 0 || x >= w)
1401  continue;
1402  if (y < 0 || y >= h)
1403  continue;
1404  if (cmap)
1405  pixSetPixel(pix, x, y, index);
1406  else if (d == 32)
1407  pixSetPixel(pix, x, y, val32);
1408  else
1409  pixSetPixel(pix, x, y, val);
1410  }
1411 
1412  return 0;
1413 }
1414 
1415 
1430 l_ok
1432  PTA *pta,
1433  l_uint8 rval,
1434  l_uint8 gval,
1435  l_uint8 bval,
1436  l_float32 fract)
1437 {
1438 l_int32 i, n, x, y, w, h;
1439 l_uint8 nrval, ngval, nbval;
1440 l_uint32 val32;
1441 l_float32 frval, fgval, fbval;
1442 
1443  PROCNAME("pixRenderPtaBlend");
1444 
1445  if (!pix)
1446  return ERROR_INT("pix not defined", procName, 1);
1447  if (!pta)
1448  return ERROR_INT("pta not defined", procName, 1);
1449  if (pixGetDepth(pix) != 32)
1450  return ERROR_INT("depth not 32 bpp", procName, 1);
1451  if (fract < 0.0 || fract > 1.0) {
1452  L_WARNING("fract must be in [0.0, 1.0]; setting to 0.5\n", procName);
1453  fract = 0.5;
1454  }
1455 
1456  pixGetDimensions(pix, &w, &h, NULL);
1457  n = ptaGetCount(pta);
1458  frval = fract * rval;
1459  fgval = fract * gval;
1460  fbval = fract * bval;
1461  for (i = 0; i < n; i++) {
1462  ptaGetIPt(pta, i, &x, &y);
1463  if (x < 0 || x >= w)
1464  continue;
1465  if (y < 0 || y >= h)
1466  continue;
1467  pixGetPixel(pix, x, y, &val32);
1468  nrval = GET_DATA_BYTE(&val32, COLOR_RED);
1469  nrval = (l_uint8)((1. - fract) * nrval + frval);
1470  ngval = GET_DATA_BYTE(&val32, COLOR_GREEN);
1471  ngval = (l_uint8)((1. - fract) * ngval + fgval);
1472  nbval = GET_DATA_BYTE(&val32, COLOR_BLUE);
1473  nbval = (l_uint8)((1. - fract) * nbval + fbval);
1474  composeRGBPixel(nrval, ngval, nbval, &val32);
1475  pixSetPixel(pix, x, y, val32);
1476  }
1477 
1478  return 0;
1479 }
1480 
1481 
1482 /*------------------------------------------------------------------*
1483  * Rendering of arbitrary shapes built with lines *
1484  *------------------------------------------------------------------*/
1495 l_ok
1497  l_int32 x1,
1498  l_int32 y1,
1499  l_int32 x2,
1500  l_int32 y2,
1501  l_int32 width,
1502  l_int32 op)
1503 {
1504 PTA *pta;
1505 
1506  PROCNAME("pixRenderLine");
1507 
1508  if (!pix)
1509  return ERROR_INT("pix not defined", procName, 1);
1510  if (width < 1) {
1511  L_WARNING("width must be > 0; setting to 1\n", procName);
1512  width = 1;
1513  }
1514  if (op != L_SET_PIXELS && op != L_CLEAR_PIXELS && op != L_FLIP_PIXELS)
1515  return ERROR_INT("invalid op", procName, 1);
1516 
1517  if ((pta = generatePtaWideLine(x1, y1, x2, y2, width)) == NULL)
1518  return ERROR_INT("pta not made", procName, 1);
1519  pixRenderPta(pix, pta, op);
1520  ptaDestroy(&pta);
1521  return 0;
1522 }
1523 
1524 
1535 l_ok
1537  l_int32 x1,
1538  l_int32 y1,
1539  l_int32 x2,
1540  l_int32 y2,
1541  l_int32 width,
1542  l_uint8 rval,
1543  l_uint8 gval,
1544  l_uint8 bval)
1545 {
1546 PTA *pta;
1547 
1548  PROCNAME("pixRenderLineArb");
1549 
1550  if (!pix)
1551  return ERROR_INT("pix not defined", procName, 1);
1552  if (width < 1) {
1553  L_WARNING("width must be > 0; setting to 1\n", procName);
1554  width = 1;
1555  }
1556 
1557  if ((pta = generatePtaWideLine(x1, y1, x2, y2, width)) == NULL)
1558  return ERROR_INT("pta not made", procName, 1);
1559  pixRenderPtaArb(pix, pta, rval, gval, bval);
1560  ptaDestroy(&pta);
1561  return 0;
1562 }
1563 
1564 
1576 l_ok
1578  l_int32 x1,
1579  l_int32 y1,
1580  l_int32 x2,
1581  l_int32 y2,
1582  l_int32 width,
1583  l_uint8 rval,
1584  l_uint8 gval,
1585  l_uint8 bval,
1586  l_float32 fract)
1587 {
1588 PTA *pta;
1589 
1590  PROCNAME("pixRenderLineBlend");
1591 
1592  if (!pix)
1593  return ERROR_INT("pix not defined", procName, 1);
1594  if (width < 1) {
1595  L_WARNING("width must be > 0; setting to 1\n", procName);
1596  width = 1;
1597  }
1598 
1599  if ((pta = generatePtaWideLine(x1, y1, x2, y2, width)) == NULL)
1600  return ERROR_INT("pta not made", procName, 1);
1601  pixRenderPtaBlend(pix, pta, rval, gval, bval, fract);
1602  ptaDestroy(&pta);
1603  return 0;
1604 }
1605 
1606 
1616 l_ok
1618  BOX *box,
1619  l_int32 width,
1620  l_int32 op)
1621 {
1622 PTA *pta;
1623 
1624  PROCNAME("pixRenderBox");
1625 
1626  if (!pix)
1627  return ERROR_INT("pix not defined", procName, 1);
1628  if (!box)
1629  return ERROR_INT("box not defined", procName, 1);
1630  if (width < 1) {
1631  L_WARNING("width < 1; setting to 1\n", procName);
1632  width = 1;
1633  }
1634  if (op != L_SET_PIXELS && op != L_CLEAR_PIXELS && op != L_FLIP_PIXELS)
1635  return ERROR_INT("invalid op", procName, 1);
1636 
1637  if ((pta = generatePtaBox(box, width)) == NULL)
1638  return ERROR_INT("pta not made", procName, 1);
1639  pixRenderPta(pix, pta, op);
1640  ptaDestroy(&pta);
1641  return 0;
1642 }
1643 
1644 
1654 l_ok
1656  BOX *box,
1657  l_int32 width,
1658  l_uint8 rval,
1659  l_uint8 gval,
1660  l_uint8 bval)
1661 {
1662 PTA *pta;
1663 
1664  PROCNAME("pixRenderBoxArb");
1665 
1666  if (!pix)
1667  return ERROR_INT("pix not defined", procName, 1);
1668  if (!box)
1669  return ERROR_INT("box not defined", procName, 1);
1670  if (width < 1) {
1671  L_WARNING("width < 1; setting to 1\n", procName);
1672  width = 1;
1673  }
1674 
1675  if ((pta = generatePtaBox(box, width)) == NULL)
1676  return ERROR_INT("pta not made", procName, 1);
1677  pixRenderPtaArb(pix, pta, rval, gval, bval);
1678  ptaDestroy(&pta);
1679  return 0;
1680 }
1681 
1682 
1694 l_ok
1696  BOX *box,
1697  l_int32 width,
1698  l_uint8 rval,
1699  l_uint8 gval,
1700  l_uint8 bval,
1701  l_float32 fract)
1702 {
1703 PTA *pta;
1704 
1705  PROCNAME("pixRenderBoxBlend");
1706 
1707  if (!pix)
1708  return ERROR_INT("pix not defined", procName, 1);
1709  if (!box)
1710  return ERROR_INT("box not defined", procName, 1);
1711  if (width < 1) {
1712  L_WARNING("width < 1; setting to 1\n", procName);
1713  width = 1;
1714  }
1715 
1716  if ((pta = generatePtaBox(box, width)) == NULL)
1717  return ERROR_INT("pta not made", procName, 1);
1718  pixRenderPtaBlend(pix, pta, rval, gval, bval, fract);
1719  ptaDestroy(&pta);
1720  return 0;
1721 }
1722 
1723 
1733 l_ok
1735  BOXA *boxa,
1736  l_int32 width,
1737  l_int32 op)
1738 {
1739 PTA *pta;
1740 
1741  PROCNAME("pixRenderBoxa");
1742 
1743  if (!pix)
1744  return ERROR_INT("pix not defined", procName, 1);
1745  if (!boxa)
1746  return ERROR_INT("boxa not defined", procName, 1);
1747  if (width < 1) {
1748  L_WARNING("width < 1; setting to 1\n", procName);
1749  width = 1;
1750  }
1751  if (op != L_SET_PIXELS && op != L_CLEAR_PIXELS && op != L_FLIP_PIXELS)
1752  return ERROR_INT("invalid op", procName, 1);
1753 
1754  if ((pta = generatePtaBoxa(boxa, width, 0)) == NULL)
1755  return ERROR_INT("pta not made", procName, 1);
1756  pixRenderPta(pix, pta, op);
1757  ptaDestroy(&pta);
1758  return 0;
1759 }
1760 
1761 
1771 l_ok
1773  BOXA *boxa,
1774  l_int32 width,
1775  l_uint8 rval,
1776  l_uint8 gval,
1777  l_uint8 bval)
1778 {
1779 PTA *pta;
1780 
1781  PROCNAME("pixRenderBoxaArb");
1782 
1783  if (!pix)
1784  return ERROR_INT("pix not defined", procName, 1);
1785  if (!boxa)
1786  return ERROR_INT("boxa not defined", procName, 1);
1787  if (width < 1) {
1788  L_WARNING("width < 1; setting to 1\n", procName);
1789  width = 1;
1790  }
1791 
1792  if ((pta = generatePtaBoxa(boxa, width, 0)) == NULL)
1793  return ERROR_INT("pta not made", procName, 1);
1794  pixRenderPtaArb(pix, pta, rval, gval, bval);
1795  ptaDestroy(&pta);
1796  return 0;
1797 }
1798 
1799 
1812 l_ok
1814  BOXA *boxa,
1815  l_int32 width,
1816  l_uint8 rval,
1817  l_uint8 gval,
1818  l_uint8 bval,
1819  l_float32 fract,
1820  l_int32 removedups)
1821 {
1822 PTA *pta;
1823 
1824  PROCNAME("pixRenderBoxaBlend");
1825 
1826  if (!pix)
1827  return ERROR_INT("pix not defined", procName, 1);
1828  if (!boxa)
1829  return ERROR_INT("boxa not defined", procName, 1);
1830  if (width < 1) {
1831  L_WARNING("width < 1; setting to 1\n", procName);
1832  width = 1;
1833  }
1834 
1835  if ((pta = generatePtaBoxa(boxa, width, removedups)) == NULL)
1836  return ERROR_INT("pta not made", procName, 1);
1837  pixRenderPtaBlend(pix, pta, rval, gval, bval, fract);
1838  ptaDestroy(&pta);
1839  return 0;
1840 }
1841 
1842 
1855 l_ok
1857  BOX *box,
1858  l_int32 spacing,
1859  l_int32 width,
1860  l_int32 orient,
1861  l_int32 outline,
1862  l_int32 op)
1863 {
1864 PTA *pta;
1865 
1866  PROCNAME("pixRenderHashBox");
1867 
1868  if (!pix)
1869  return ERROR_INT("pix not defined", procName, 1);
1870  if (!box)
1871  return ERROR_INT("box not defined", procName, 1);
1872  if (spacing <= 1)
1873  return ERROR_INT("spacing not > 1", procName, 1);
1874  if (width < 1) {
1875  L_WARNING("width < 1; setting to 1\n", procName);
1876  width = 1;
1877  }
1878  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
1879  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
1880  return ERROR_INT("invalid line orientation", procName, 1);
1881  if (op != L_SET_PIXELS && op != L_CLEAR_PIXELS && op != L_FLIP_PIXELS)
1882  return ERROR_INT("invalid op", procName, 1);
1883 
1884  pta = generatePtaHashBox(box, spacing, width, orient, outline);
1885  if (!pta)
1886  return ERROR_INT("pta not made", procName, 1);
1887  pixRenderPta(pix, pta, op);
1888  ptaDestroy(&pta);
1889  return 0;
1890 }
1891 
1892 
1905 l_ok
1907  BOX *box,
1908  l_int32 spacing,
1909  l_int32 width,
1910  l_int32 orient,
1911  l_int32 outline,
1912  l_int32 rval,
1913  l_int32 gval,
1914  l_int32 bval)
1915 {
1916 PTA *pta;
1917 
1918  PROCNAME("pixRenderHashBoxArb");
1919 
1920  if (!pix)
1921  return ERROR_INT("pix not defined", procName, 1);
1922  if (!box)
1923  return ERROR_INT("box not defined", procName, 1);
1924  if (spacing <= 1)
1925  return ERROR_INT("spacing not > 1", procName, 1);
1926  if (width < 1) {
1927  L_WARNING("width < 1; setting to 1\n", procName);
1928  width = 1;
1929  }
1930  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
1931  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
1932  return ERROR_INT("invalid line orientation", procName, 1);
1933 
1934  pta = generatePtaHashBox(box, spacing, width, orient, outline);
1935  if (!pta)
1936  return ERROR_INT("pta not made", procName, 1);
1937  pixRenderPtaArb(pix, pta, rval, gval, bval);
1938  ptaDestroy(&pta);
1939  return 0;
1940 }
1941 
1942 
1957 l_ok
1959  BOX *box,
1960  l_int32 spacing,
1961  l_int32 width,
1962  l_int32 orient,
1963  l_int32 outline,
1964  l_int32 rval,
1965  l_int32 gval,
1966  l_int32 bval,
1967  l_float32 fract)
1968 {
1969 PTA *pta;
1970 
1971  PROCNAME("pixRenderHashBoxBlend");
1972 
1973  if (!pix)
1974  return ERROR_INT("pix not defined", procName, 1);
1975  if (!box)
1976  return ERROR_INT("box not defined", procName, 1);
1977  if (spacing <= 1)
1978  return ERROR_INT("spacing not > 1", procName, 1);
1979  if (width < 1) {
1980  L_WARNING("width < 1; setting to 1\n", procName);
1981  width = 1;
1982  }
1983  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
1984  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
1985  return ERROR_INT("invalid line orientation", procName, 1);
1986 
1987  pta = generatePtaHashBox(box, spacing, width, orient, outline);
1988  if (!pta)
1989  return ERROR_INT("pta not made", procName, 1);
1990  pixRenderPtaBlend(pix, pta, rval, gval, bval, fract);
1991  ptaDestroy(&pta);
1992  return 0;
1993 }
1994 
1995 
2017 l_ok
2019  PIX *pixm,
2020  l_int32 x,
2021  l_int32 y,
2022  l_int32 spacing,
2023  l_int32 width,
2024  l_int32 orient,
2025  l_int32 outline,
2026  l_int32 rval,
2027  l_int32 gval,
2028  l_int32 bval)
2029 {
2030 l_int32 w, h;
2031 BOX *box1, *box2;
2032 PIX *pix1;
2033 PTA *pta1, *pta2;
2034 
2035  PROCNAME("pixRenderHashMaskArb");
2036 
2037  if (!pix)
2038  return ERROR_INT("pix not defined", procName, 1);
2039  if (!pixm || pixGetDepth(pixm) != 1)
2040  return ERROR_INT("pixm not defined or not 1 bpp", procName, 1);
2041  if (spacing <= 1)
2042  return ERROR_INT("spacing not > 1", procName, 1);
2043  if (width < 1) {
2044  L_WARNING("width < 1; setting to 1\n", procName);
2045  width = 1;
2046  }
2047  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
2048  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
2049  return ERROR_INT("invalid line orientation", procName, 1);
2050 
2051  /* Get the points for masked hash lines */
2052  pixGetDimensions(pixm, &w, &h, NULL);
2053  box1 = boxCreate(0, 0, w, h);
2054  pta1 = generatePtaHashBox(box1, spacing, width, orient, outline);
2055  pta2 = ptaCropToMask(pta1, pixm);
2056  boxDestroy(&box1);
2057  ptaDestroy(&pta1);
2058 
2059  /* Clip out the region and apply the hash lines */
2060  box2 = boxCreate(x, y, w, h);
2061  pix1 = pixClipRectangle(pix, box2, NULL);
2062  pixRenderPtaArb(pix1, pta2, rval, gval, bval);
2063  ptaDestroy(&pta2);
2064  boxDestroy(&box2);
2065 
2066  /* Rasterop the altered rectangle back in place */
2067  pixRasterop(pix, x, y, w, h, PIX_SRC, pix1, 0, 0);
2068  pixDestroy(&pix1);
2069  return 0;
2070 }
2071 
2072 
2087 l_ok
2089  BOXA *boxa,
2090  l_int32 spacing,
2091  l_int32 width,
2092  l_int32 orient,
2093  l_int32 outline,
2094  l_int32 op)
2095  {
2096 PTA *pta;
2097 
2098  PROCNAME("pixRenderHashBoxa");
2099 
2100  if (!pix)
2101  return ERROR_INT("pix not defined", procName, 1);
2102  if (!boxa)
2103  return ERROR_INT("boxa not defined", procName, 1);
2104  if (spacing <= 1)
2105  return ERROR_INT("spacing not > 1", procName, 1);
2106  if (width < 1) {
2107  L_WARNING("width < 1; setting to 1\n", procName);
2108  width = 1;
2109  }
2110  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
2111  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
2112  return ERROR_INT("invalid line orientation", procName, 1);
2113  if (op != L_SET_PIXELS && op != L_CLEAR_PIXELS && op != L_FLIP_PIXELS)
2114  return ERROR_INT("invalid op", procName, 1);
2115 
2116  pta = generatePtaHashBoxa(boxa, spacing, width, orient, outline, 1);
2117  if (!pta)
2118  return ERROR_INT("pta not made", procName, 1);
2119  pixRenderPta(pix, pta, op);
2120  ptaDestroy(&pta);
2121  return 0;
2122 }
2123 
2124 
2139 l_ok
2141  BOXA *boxa,
2142  l_int32 spacing,
2143  l_int32 width,
2144  l_int32 orient,
2145  l_int32 outline,
2146  l_int32 rval,
2147  l_int32 gval,
2148  l_int32 bval)
2149 {
2150 PTA *pta;
2151 
2152  PROCNAME("pixRenderHashBoxArb");
2153 
2154  if (!pix)
2155  return ERROR_INT("pix not defined", procName, 1);
2156  if (!boxa)
2157  return ERROR_INT("boxa not defined", procName, 1);
2158  if (spacing <= 1)
2159  return ERROR_INT("spacing not > 1", procName, 1);
2160  if (width < 1) {
2161  L_WARNING("width < 1; setting to 1\n", procName);
2162  width = 1;
2163  }
2164  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
2165  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
2166  return ERROR_INT("invalid line orientation", procName, 1);
2167 
2168  pta = generatePtaHashBoxa(boxa, spacing, width, orient, outline, 1);
2169  if (!pta)
2170  return ERROR_INT("pta not made", procName, 1);
2171  pixRenderPtaArb(pix, pta, rval, gval, bval);
2172  ptaDestroy(&pta);
2173  return 0;
2174 }
2175 
2176 
2193 l_ok
2195  BOXA *boxa,
2196  l_int32 spacing,
2197  l_int32 width,
2198  l_int32 orient,
2199  l_int32 outline,
2200  l_int32 rval,
2201  l_int32 gval,
2202  l_int32 bval,
2203  l_float32 fract)
2204 {
2205 PTA *pta;
2206 
2207  PROCNAME("pixRenderHashBoxaBlend");
2208 
2209  if (!pix)
2210  return ERROR_INT("pix not defined", procName, 1);
2211  if (!boxa)
2212  return ERROR_INT("boxa not defined", procName, 1);
2213  if (spacing <= 1)
2214  return ERROR_INT("spacing not > 1", procName, 1);
2215  if (width < 1) {
2216  L_WARNING("width < 1; setting to 1\n", procName);
2217  width = 1;
2218  }
2219  if (orient != L_HORIZONTAL_LINE && orient != L_POS_SLOPE_LINE &&
2220  orient != L_VERTICAL_LINE && orient != L_NEG_SLOPE_LINE)
2221  return ERROR_INT("invalid line orientation", procName, 1);
2222 
2223  pta = generatePtaHashBoxa(boxa, spacing, width, orient, outline, 1);
2224  if (!pta)
2225  return ERROR_INT("pta not made", procName, 1);
2226  pixRenderPtaBlend(pix, pta, rval, gval, bval, fract);
2227  ptaDestroy(&pta);
2228  return 0;
2229 }
2230 
2231 
2247 l_ok
2249  PTA *ptas,
2250  l_int32 width,
2251  l_int32 op,
2252  l_int32 closeflag)
2253 {
2254 PTA *pta;
2255 
2256  PROCNAME("pixRenderPolyline");
2257 
2258  if (!pix)
2259  return ERROR_INT("pix not defined", procName, 1);
2260  if (!ptas)
2261  return ERROR_INT("ptas not defined", procName, 1);
2262  if (width < 1) {
2263  L_WARNING("width < 1; setting to 1\n", procName);
2264  width = 1;
2265  }
2266  if (op != L_SET_PIXELS && op != L_CLEAR_PIXELS && op != L_FLIP_PIXELS)
2267  return ERROR_INT("invalid op", procName, 1);
2268 
2269  if ((pta = generatePtaPolyline(ptas, width, closeflag, 0)) == NULL)
2270  return ERROR_INT("pta not made", procName, 1);
2271  pixRenderPta(pix, pta, op);
2272  ptaDestroy(&pta);
2273  return 0;
2274 }
2275 
2276 
2292 l_ok
2294  PTA *ptas,
2295  l_int32 width,
2296  l_uint8 rval,
2297  l_uint8 gval,
2298  l_uint8 bval,
2299  l_int32 closeflag)
2300 {
2301 PTA *pta;
2302 
2303  PROCNAME("pixRenderPolylineArb");
2304 
2305  if (!pix)
2306  return ERROR_INT("pix not defined", procName, 1);
2307  if (!ptas)
2308  return ERROR_INT("ptas not defined", procName, 1);
2309  if (width < 1) {
2310  L_WARNING("width < 1; setting to 1\n", procName);
2311  width = 1;
2312  }
2313 
2314  if ((pta = generatePtaPolyline(ptas, width, closeflag, 0)) == NULL)
2315  return ERROR_INT("pta not made", procName, 1);
2316  pixRenderPtaArb(pix, pta, rval, gval, bval);
2317  ptaDestroy(&pta);
2318  return 0;
2319 }
2320 
2321 
2335 l_ok
2337  PTA *ptas,
2338  l_int32 width,
2339  l_uint8 rval,
2340  l_uint8 gval,
2341  l_uint8 bval,
2342  l_float32 fract,
2343  l_int32 closeflag,
2344  l_int32 removedups)
2345 {
2346 PTA *pta;
2347 
2348  PROCNAME("pixRenderPolylineBlend");
2349 
2350  if (!pix)
2351  return ERROR_INT("pix not defined", procName, 1);
2352  if (!ptas)
2353  return ERROR_INT("ptas not defined", procName, 1);
2354  if (width < 1) {
2355  L_WARNING("width < 1; setting to 1\n", procName);
2356  width = 1;
2357  }
2358 
2359  if ((pta = generatePtaPolyline(ptas, width, closeflag, removedups)) == NULL)
2360  return ERROR_INT("pta not made", procName, 1);
2361  pixRenderPtaBlend(pix, pta, rval, gval, bval, fract);
2362  ptaDestroy(&pta);
2363  return 0;
2364 }
2365 
2366 
2376 l_ok
2378  l_int32 nx,
2379  l_int32 ny,
2380  l_int32 width,
2381  l_uint8 rval,
2382  l_uint8 gval,
2383  l_uint8 bval)
2384 {
2385 l_int32 w, h;
2386 PTA *pta;
2387 
2388  PROCNAME("pixRenderGridArb");
2389 
2390  if (!pix)
2391  return ERROR_INT("pix not defined", procName, 1);
2392  if (nx < 1 || ny < 1)
2393  return ERROR_INT("nx, ny must be > 0", procName, 1);
2394  if (width < 1) {
2395  L_WARNING("width < 1; setting to 1\n", procName);
2396  width = 1;
2397  }
2398 
2399  pixGetDimensions(pix, &w, &h, NULL);
2400  if ((pta = generatePtaGrid(w, h, nx, ny, width)) == NULL)
2401  return ERROR_INT("pta not made", procName, 1);
2402  pixRenderPtaArb(pix, pta, rval, gval, bval);
2403  ptaDestroy(&pta);
2404  return 0;
2405 }
2406 
2407 
2436 PIX *
2438  PTAA *ptaa,
2439  l_int32 polyflag,
2440  l_int32 width,
2441  l_int32 closeflag)
2442 {
2443 l_int32 i, n, index, rval, gval, bval;
2444 PIXCMAP *cmap;
2445 PTA *pta, *ptat;
2446 PIX *pixd;
2447 
2448  PROCNAME("pixRenderRandomCmapPtaa");
2449 
2450  if (!pix)
2451  return (PIX *)ERROR_PTR("pix not defined", procName, NULL);
2452  if (!ptaa)
2453  return (PIX *)ERROR_PTR("ptaa not defined", procName, NULL);
2454  if (polyflag != 0 && width < 1) {
2455  L_WARNING("width < 1; setting to 1\n", procName);
2456  width = 1;
2457  }
2458 
2459  pixd = pixConvertTo8(pix, FALSE);
2460  cmap = pixcmapCreateRandom(8, 1, 1);
2461  pixSetColormap(pixd, cmap);
2462 
2463  if ((n = ptaaGetCount(ptaa)) == 0)
2464  return pixd;
2465 
2466  for (i = 0; i < n; i++) {
2467  index = 1 + (i % 254);
2468  pixcmapGetColor(cmap, index, &rval, &gval, &bval);
2469  pta = ptaaGetPta(ptaa, i, L_CLONE);
2470  if (polyflag)
2471  ptat = generatePtaPolyline(pta, width, closeflag, 0);
2472  else
2473  ptat = ptaClone(pta);
2474  pixRenderPtaArb(pixd, ptat, rval, gval, bval);
2475  ptaDestroy(&pta);
2476  ptaDestroy(&ptat);
2477  }
2478 
2479  return pixd;
2480 }
2481 
2482 
2483 
2484 /*------------------------------------------------------------------*
2485  * Rendering and filling of polygons *
2486  *------------------------------------------------------------------*/
2505 PIX *
2507  l_int32 width,
2508  l_int32 *pxmin,
2509  l_int32 *pymin)
2510 {
2511 l_float32 fxmin, fxmax, fymin, fymax;
2512 PIX *pixd;
2513 PTA *pta1, *pta2;
2514 
2515  PROCNAME("pixRenderPolygon");
2516 
2517  if (pxmin) *pxmin = 0;
2518  if (pymin) *pymin = 0;
2519  if (!ptas)
2520  return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);
2521 
2522  /* Generate a 4-connected polygon line */
2523  if ((pta1 = generatePtaPolyline(ptas, width, 1, 0)) == NULL)
2524  return (PIX *)ERROR_PTR("pta1 not made", procName, NULL);
2525  if (width < 2)
2526  pta2 = convertPtaLineTo4cc(pta1);
2527  else
2528  pta2 = ptaClone(pta1);
2529 
2530  /* Render onto a minimum-sized pix */
2531  ptaGetRange(pta2, &fxmin, &fxmax, &fymin, &fymax);
2532  if (pxmin) *pxmin = (l_int32)(fxmin + 0.5);
2533  if (pymin) *pymin = (l_int32)(fymin + 0.5);
2534  pixd = pixCreate((l_int32)(fxmax + 0.5) + 1, (l_int32)(fymax + 0.5) + 1, 1);
2535  pixRenderPolyline(pixd, pta2, width, L_SET_PIXELS, 1);
2536  ptaDestroy(&pta1);
2537  ptaDestroy(&pta2);
2538  return pixd;
2539 }
2540 
2541 
2560 PIX *
2562  PTA *pta,
2563  l_int32 xmin,
2564  l_int32 ymin)
2565 {
2566 l_int32 w, h, i, n, inside, found;
2567 l_int32 *xstart, *xend;
2568 PIX *pixi, *pixd;
2569 
2570  PROCNAME("pixFillPolygon");
2571 
2572  if (!pixs || (pixGetDepth(pixs) != 1))
2573  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
2574  if (!pta)
2575  return (PIX *)ERROR_PTR("pta not defined", procName, NULL);
2576  if (ptaGetCount(pta) < 2)
2577  return (PIX *)ERROR_PTR("pta has < 2 pts", procName, NULL);
2578 
2579  pixGetDimensions(pixs, &w, &h, NULL);
2580  xstart = (l_int32 *)LEPT_CALLOC(L_MAX(1, w / 2), sizeof(l_int32));
2581  xend = (l_int32 *)LEPT_CALLOC(L_MAX(1, w / 2), sizeof(l_int32));
2582  if (!xstart || !xend) {
2583  LEPT_FREE(xstart);
2584  LEPT_FREE(xend);
2585  return (PIX *)ERROR_PTR("xstart and xend not made", procName, NULL);
2586  }
2587 
2588  /* Find a raster with 2 or more black runs. The first background
2589  * pixel after the end of the first run is likely to be inside
2590  * the polygon, and can be used as a seed pixel. */
2591  found = FALSE;
2592  for (i = ymin + 1; i < h; i++) {
2593  pixFindHorizontalRuns(pixs, i, xstart, xend, &n);
2594  if (n > 1) {
2595  ptaPtInsidePolygon(pta, xend[0] + 1, i, &inside);
2596  if (inside) {
2597  found = TRUE;
2598  break;
2599  }
2600  }
2601  }
2602  if (!found) {
2603  L_WARNING("nothing found to fill\n", procName);
2604  LEPT_FREE(xstart);
2605  LEPT_FREE(xend);
2606  return 0;
2607  }
2608 
2609  /* Place the seed pixel in the output image */
2610  pixd = pixCreateTemplate(pixs);
2611  pixSetPixel(pixd, xend[0] + 1, i, 1);
2612 
2613  /* Invert pixs to make a filling mask, and fill from the seed */
2614  pixi = pixInvert(NULL, pixs);
2615  pixSeedfillBinary(pixd, pixd, pixi, 4);
2616 
2617  /* Add the pixels of the original polygon outline */
2618  pixOr(pixd, pixd, pixs);
2619 
2620  pixDestroy(&pixi);
2621  LEPT_FREE(xstart);
2622  LEPT_FREE(xend);
2623  return pixd;
2624 }
2625 
2626 
2627 /*------------------------------------------------------------------*
2628  * Contour rendering on grayscale images *
2629  *------------------------------------------------------------------*/
2646 PIX *
2648  l_int32 startval,
2649  l_int32 incr,
2650  l_int32 outdepth)
2651 {
2652 l_int32 w, h, d, maxval, wpls, wpld, i, j, val, test;
2653 l_uint32 *datas, *datad, *lines, *lined;
2654 PIX *pixd;
2655 
2656  PROCNAME("pixRenderContours");
2657 
2658  if (!pixs)
2659  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2660  if (pixGetColormap(pixs))
2661  return (PIX *)ERROR_PTR("pixs has colormap", procName, NULL);
2662  pixGetDimensions(pixs, &w, &h, &d);
2663  if (d != 8 && d != 16)
2664  return (PIX *)ERROR_PTR("pixs not 8 or 16 bpp", procName, NULL);
2665  if (outdepth != 1 && outdepth != d) {
2666  L_WARNING("invalid outdepth; setting to 1\n", procName);
2667  outdepth = 1;
2668  }
2669  maxval = (1 << d) - 1;
2670  if (startval < 0 || startval > maxval)
2671  return (PIX *)ERROR_PTR("startval not in [0 ... maxval]",
2672  procName, NULL);
2673  if (incr < 1)
2674  return (PIX *)ERROR_PTR("incr < 1", procName, NULL);
2675 
2676  if (outdepth == d)
2677  pixd = pixCopy(NULL, pixs);
2678  else
2679  pixd = pixCreate(w, h, 1);
2680 
2681  pixCopyResolution(pixd, pixs);
2682  datad = pixGetData(pixd);
2683  wpld = pixGetWpl(pixd);
2684  datas = pixGetData(pixs);
2685  wpls = pixGetWpl(pixs);
2686 
2687  switch (d)
2688  {
2689  case 8:
2690  if (outdepth == 1) {
2691  for (i = 0; i < h; i++) {
2692  lines = datas + i * wpls;
2693  lined = datad + i * wpld;
2694  for (j = 0; j < w; j++) {
2695  val = GET_DATA_BYTE(lines, j);
2696  if (val < startval)
2697  continue;
2698  test = (val - startval) % incr;
2699  if (!test)
2700  SET_DATA_BIT(lined, j);
2701  }
2702  }
2703  } else { /* outdepth == d */
2704  for (i = 0; i < h; i++) {
2705  lines = datas + i * wpls;
2706  lined = datad + i * wpld;
2707  for (j = 0; j < w; j++) {
2708  val = GET_DATA_BYTE(lines, j);
2709  if (val < startval)
2710  continue;
2711  test = (val - startval) % incr;
2712  if (!test)
2713  SET_DATA_BYTE(lined, j, 0);
2714  }
2715  }
2716  }
2717  break;
2718 
2719  case 16:
2720  if (outdepth == 1) {
2721  for (i = 0; i < h; i++) {
2722  lines = datas + i * wpls;
2723  lined = datad + i * wpld;
2724  for (j = 0; j < w; j++) {
2725  val = GET_DATA_TWO_BYTES(lines, j);
2726  if (val < startval)
2727  continue;
2728  test = (val - startval) % incr;
2729  if (!test)
2730  SET_DATA_BIT(lined, j);
2731  }
2732  }
2733  } else { /* outdepth == d */
2734  for (i = 0; i < h; i++) {
2735  lines = datas + i * wpls;
2736  lined = datad + i * wpld;
2737  for (j = 0; j < w; j++) {
2738  val = GET_DATA_TWO_BYTES(lines, j);
2739  if (val < startval)
2740  continue;
2741  test = (val - startval) % incr;
2742  if (!test)
2743  SET_DATA_TWO_BYTES(lined, j, 0);
2744  }
2745  }
2746  }
2747  break;
2748 
2749  default:
2750  return (PIX *)ERROR_PTR("pixs not 8 or 16 bpp", procName, NULL);
2751  }
2752 
2753  return pixd;
2754 }
2755 
2756 
2772 PIX *
2774  l_int32 ncontours)
2775 {
2776 l_float32 minval, maxval, incr;
2777 
2778  PROCNAME("fpixAutoRenderContours");
2779 
2780  if (!fpix)
2781  return (PIX *)ERROR_PTR("fpix not defined", procName, NULL);
2782  if (ncontours < 2 || ncontours > 500)
2783  return (PIX *)ERROR_PTR("ncontours < 2 or > 500", procName, NULL);
2784 
2785  fpixGetMin(fpix, &minval, NULL, NULL);
2786  fpixGetMax(fpix, &maxval, NULL, NULL);
2787  if (minval == maxval)
2788  return (PIX *)ERROR_PTR("all values in fpix are equal", procName, NULL);
2789  incr = (maxval - minval) / ((l_float32)ncontours - 1);
2790  return fpixRenderContours(fpix, incr, 0.15);
2791 }
2792 
2793 
2810 PIX *
2812  l_float32 incr,
2813  l_float32 proxim)
2814 {
2815 l_int32 i, j, w, h, wpls, wpld;
2816 l_float32 val, invincr, finter, above, below, diff;
2817 l_uint32 *datad, *lined;
2818 l_float32 *datas, *lines;
2819 PIX *pixd;
2820 PIXCMAP *cmap;
2821 
2822  PROCNAME("fpixRenderContours");
2823 
2824  if (!fpixs)
2825  return (PIX *)ERROR_PTR("fpixs not defined", procName, NULL);
2826  if (incr <= 0.0)
2827  return (PIX *)ERROR_PTR("incr <= 0.0", procName, NULL);
2828  if (proxim <= 0.0)
2829  proxim = 0.15; /* default */
2830 
2831  fpixGetDimensions(fpixs, &w, &h);
2832  if ((pixd = pixCreate(w, h, 8)) == NULL)
2833  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2834  cmap = pixcmapCreate(8);
2835  pixSetColormap(pixd, cmap);
2836  pixcmapAddColor(cmap, 255, 255, 255); /* white */
2837  pixcmapAddColor(cmap, 0, 0, 0); /* black */
2838  pixcmapAddColor(cmap, 255, 0, 0); /* red */
2839 
2840  datas = fpixGetData(fpixs);
2841  wpls = fpixGetWpl(fpixs);
2842  datad = pixGetData(pixd);
2843  wpld = pixGetWpl(pixd);
2844  invincr = 1.0 / incr;
2845  for (i = 0; i < h; i++) {
2846  lines = datas + i * wpls;
2847  lined = datad + i * wpld;
2848  for (j = 0; j < w; j++) {
2849  val = lines[j];
2850  finter = invincr * val;
2851  above = finter - floorf(finter);
2852  below = ceilf(finter) - finter;
2853  diff = L_MIN(above, below);
2854  if (diff <= proxim) {
2855  if (val < 0.0)
2856  SET_DATA_BYTE(lined, j, 2);
2857  else
2858  SET_DATA_BYTE(lined, j, 1);
2859  }
2860  }
2861  }
2862 
2863  return pixd;
2864 }
2865 
2866 
2867 /*------------------------------------------------------------------*
2868  * Boundary pt generation on 1 bpp images *
2869  *------------------------------------------------------------------*/
2889 PTA *
2891  l_int32 width)
2892 {
2893 PIX *pix1;
2894 PTA *pta;
2895 
2896  PROCNAME("pixGeneratePtaBoundary");
2897 
2898  if (!pixs || pixGetDepth(pixs) != 1)
2899  return (PTA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
2900  if (width < 1) {
2901  L_WARNING("width < 1; setting to 1\n", procName);
2902  width = 1;
2903  }
2904 
2905  pix1 = pixErodeBrick(NULL, pixs, 2 * width + 1, 2 * width + 1);
2906  pixXor(pix1, pix1, pixs);
2907  pta = ptaGetPixelsFromPix(pix1, NULL);
2908  pixDestroy(&pix1);
2909  return pta;
2910 }
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
l_ok boxIntersectByLine(BOX *box, l_int32 x, l_int32 y, l_float32 slope, l_int32 *px1, l_int32 *py1, l_int32 *px2, l_int32 *py2, l_int32 *pn)
boxIntersectByLine()
Definition: boxfunc1.c:1625
PIXCMAP * pixcmapCreateRandom(l_int32 depth, l_int32 hasblack, l_int32 haswhite)
pixcmapCreateRandom()
Definition: colormap.c:172
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
l_ok pixcmapAddNearestColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 *pindex)
pixcmapAddNearestColor()
Definition: colormap.c:545
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
l_ok pixcmapAddColor(PIXCMAP *cmap, l_int32 rval, l_int32 gval, l_int32 bval)
pixcmapAddColor()
Definition: colormap.c:414
l_ok fpixGetDimensions(FPIX *fpix, l_int32 *pw, l_int32 *ph)
fpixGetDimensions()
Definition: fpix1.c:329
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:376
l_float32 * fpixGetData(FPIX *fpix)
fpixGetData()
Definition: fpix1.c:519
l_ok fpixGetMax(FPIX *fpix, l_float32 *pmaxval, l_int32 *pxmaxloc, l_int32 *pymaxloc)
fpixGetMax()
Definition: fpix2.c:748
l_ok fpixGetMin(FPIX *fpix, l_float32 *pminval, l_int32 *pxminloc, l_int32 *pyminloc)
fpixGetMin()
Definition: fpix2.c:695
l_ok pixRenderPolyline(PIX *pix, PTA *ptas, l_int32 width, l_int32 op, l_int32 closeflag)
pixRenderPolyline()
Definition: graphics.c:2248
l_ok pixRenderHashBoxaBlend(PIX *pix, BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval, l_float32 fract)
pixRenderHashBoxaBlend()
Definition: graphics.c:2194
l_ok pixRenderGridArb(PIX *pix, l_int32 nx, l_int32 ny, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderGridArb()
Definition: graphics.c:2377
l_ok pixRenderHashBoxBlend(PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval, l_float32 fract)
pixRenderHashBoxBlend()
Definition: graphics.c:1958
l_ok pixRenderHashBox(PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 op)
pixRenderHashBox()
Definition: graphics.c:1856
l_ok pixRenderPtaArb(PIX *pix, PTA *pta, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderPtaArb()
Definition: graphics.c:1356
l_ok locatePtRadially(l_int32 xr, l_int32 yr, l_float64 dist, l_float64 radang, l_float64 *px, l_float64 *py)
locatePtRadially()
Definition: graphics.c:931
l_ok pixRenderBoxBlend(PIX *pix, BOX *box, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract)
pixRenderBoxBlend()
Definition: graphics.c:1695
l_ok pixRenderPtaBlend(PIX *pix, PTA *pta, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract)
pixRenderPtaBlend()
Definition: graphics.c:1431
l_ok pixRenderLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_int32 op)
pixRenderLine()
Definition: graphics.c:1496
l_ok pixRenderHashBoxa(PIX *pix, BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 op)
pixRenderHashBoxa()
Definition: graphics.c:2088
PTA * convertPtaLineTo4cc(PTA *ptas)
convertPtaLineTo4cc()
Definition: graphics.c:790
l_ok pixRenderHashBoxaArb(PIX *pix, BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval)
pixRenderHashBoxaArb()
Definition: graphics.c:2140
PTA * generatePtaBox(BOX *box, l_int32 width)
generatePtaBox()
Definition: graphics.c:276
PIX * pixRenderRandomCmapPtaa(PIX *pix, PTAA *ptaa, l_int32 polyflag, l_int32 width, l_int32 closeflag)
pixRenderRandomCmapPtaa()
Definition: graphics.c:2437
l_ok pixRenderBox(PIX *pix, BOX *box, l_int32 width, l_int32 op)
pixRenderBox()
Definition: graphics.c:1617
l_ok pixRenderPolylineArb(PIX *pix, PTA *ptas, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_int32 closeflag)
pixRenderPolylineArb()
Definition: graphics.c:2293
PTAA * generatePtaaHashBoxa(BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline)
generatePtaaHashBoxa()
Definition: graphics.c:626
PTA * generatePtaGrid(l_int32 w, l_int32 h, l_int32 nx, l_int32 ny, l_int32 width)
generatePtaGrid()
Definition: graphics.c:732
PTA * generatePtaPolyline(PTA *ptas, l_int32 width, l_int32 closeflag, l_int32 removedups)
generatePtaPolyline()
Definition: graphics.c:674
l_ok pixRenderPolylineBlend(PIX *pix, PTA *ptas, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract, l_int32 closeflag, l_int32 removedups)
pixRenderPolylineBlend()
Definition: graphics.c:2336
l_ok pixRenderPlotFromNuma(PIX **ppix, NUMA *na, l_int32 plotloc, l_int32 linewidth, l_int32 max, l_uint32 color)
pixRenderPlotFromNuma()
Definition: graphics.c:973
PTA * pixGeneratePtaBoundary(PIX *pixs, l_int32 width)
pixGeneratePtaBoundary()
Definition: graphics.c:2890
l_ok pixRenderPlotFromNumaGen(PIX **ppix, NUMA *na, l_int32 orient, l_int32 linewidth, l_int32 refpos, l_int32 max, l_int32 drawref, l_uint32 color)
pixRenderPlotFromNumaGen()
Definition: graphics.c:1089
l_ok pixRenderHashBoxArb(PIX *pix, BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval)
pixRenderHashBoxArb()
Definition: graphics.c:1906
l_ok pixRenderHashMaskArb(PIX *pix, PIX *pixm, l_int32 x, l_int32 y, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 rval, l_int32 gval, l_int32 bval)
pixRenderHashMaskArb()
Definition: graphics.c:2018
PTA * makePlotPtaFromNuma(NUMA *na, l_int32 size, l_int32 plotloc, l_int32 linewidth, l_int32 max)
makePlotPtaFromNuma()
Definition: graphics.c:1032
l_ok pixRenderLineArb(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderLineArb()
Definition: graphics.c:1536
PTAA * generatePtaaBoxa(BOXA *boxa)
generatePtaaBoxa()
Definition: graphics.c:573
PTA * generatePtaLineFromPt(l_int32 x, l_int32 y, l_float64 length, l_float64 radang)
generatePtaLineFromPt()
Definition: graphics.c:907
PIX * pixFillPolygon(PIX *pixs, PTA *pta, l_int32 xmin, l_int32 ymin)
pixFillPolygon()
Definition: graphics.c:2561
l_ok pixRenderLineBlend(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract)
pixRenderLineBlend()
Definition: graphics.c:1577
PTA * generatePtaLine(l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2)
generatePtaLine()
Definition: graphics.c:141
PIX * fpixAutoRenderContours(FPIX *fpix, l_int32 ncontours)
fpixAutoRenderContours()
Definition: graphics.c:2773
l_ok pixRenderBoxaBlend(PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval, l_float32 fract, l_int32 removedups)
pixRenderBoxaBlend()
Definition: graphics.c:1813
PTA * generatePtaHashBox(BOX *box, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline)
generatePtaHashBox()
Definition: graphics.c:410
l_ok pixRenderBoxArb(PIX *pix, BOX *box, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxArb()
Definition: graphics.c:1655
l_ok pixRenderBoxa(PIX *pix, BOXA *boxa, l_int32 width, l_int32 op)
pixRenderBoxa()
Definition: graphics.c:1734
PIX * pixRenderPolygon(PTA *ptas, l_int32 width, l_int32 *pxmin, l_int32 *pymin)
pixRenderPolygon()
Definition: graphics.c:2506
PTA * makePlotPtaFromNumaGen(NUMA *na, l_int32 orient, l_int32 linewidth, l_int32 refpos, l_int32 max, l_int32 drawref)
makePlotPtaFromNumaGen()
Definition: graphics.c:1155
PTA * generatePtaHashBoxa(BOXA *boxa, l_int32 spacing, l_int32 width, l_int32 orient, l_int32 outline, l_int32 removedups)
generatePtaHashBoxa()
Definition: graphics.c:513
PTA * generatePtaWideLine(l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 width)
generatePtaWideLine()
Definition: graphics.c:206
l_ok pixRenderBoxaArb(PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxaArb()
Definition: graphics.c:1772
PTA * generatePtaBoxa(BOXA *boxa, l_int32 width, l_int32 removedups)
generatePtaBoxa()
Definition: graphics.c:353
l_ok pixRenderPta(PIX *pix, PTA *pta, l_int32 op)
pixRenderPta()
Definition: graphics.c:1267
PIX * pixRenderContours(PIX *pixs, l_int32 startval, l_int32 incr, l_int32 outdepth)
pixRenderContours()
Definition: graphics.c:2647
PTA * generatePtaFilledCircle(l_int32 radius)
generatePtaFilledCircle()
Definition: graphics.c:833
PIX * fpixRenderContours(FPIX *fpixs, l_float32 incr, l_float32 proxim)
fpixRenderContours()
Definition: graphics.c:2811
PTA * generatePtaFilledSquare(l_int32 side)
generatePtaFilledSquare()
Definition: graphics.c:873
PIX * pixErodeBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeBrick()
Definition: morph.c:758
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetParameters(NUMA *na, l_float32 *pstartx, l_float32 *pdelx)
numaGetParameters()
Definition: numabasic.c:963
l_ok numaGetMin(NUMA *na, l_float32 *pminval, l_int32 *piminloc)
numaGetMin()
Definition: numafunc1.c:453
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:496
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
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 * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:263
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:190
l_ok pixClearPixel(PIX *pix, l_int32 x, l_int32 y)
pixClearPixel()
Definition: pix2.c:540
l_ok pixFlipPixel(PIX *pix, l_int32 x, l_int32 y)
pixFlipPixel()
Definition: pix2.c:602
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
PIX * pixOr(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixOr()
Definition: pix3.c:1560
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1688
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ COLOR_GREEN
Definition: pix.h:205
@ L_FLIP_PIXELS
Definition: pix.h:774
@ L_SET_PIXELS
Definition: pix.h:772
@ L_CLEAR_PIXELS
Definition: pix.h:773
@ L_POS_SLOPE_LINE
Definition: pix.h:1014
@ L_HORIZONTAL_LINE
Definition: pix.h:1013
@ L_NEG_SLOPE_LINE
Definition: pix.h:1016
@ L_VERTICAL_LINE
Definition: pix.h:1015
@ L_CLONE
Definition: pix.h:713
@ L_INSERT
Definition: pix.h:711
@ L_PLOT_AT_BOT
Definition: pix.h:1226
@ L_PLOT_AT_LEFT
Definition: pix.h:1227
@ L_PLOT_AT_MID_VERT
Definition: pix.h:1228
@ L_PLOT_AT_MID_HORIZ
Definition: pix.h:1225
@ L_PLOT_AT_TOP
Definition: pix.h:1224
@ L_PLOT_AT_RIGHT
Definition: pix.h:1229
#define PIX_SRC
Definition: pix.h:330
PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag)
pixConvertTo8()
Definition: pixconv.c:3133
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
PTAA * ptaaCreate(l_int32 n)
ptaaCreate()
Definition: ptabasic.c:976
PTA * ptaaGetPta(PTAA *ptaa, l_int32 index, l_int32 accessflag)
ptaaGetPta()
Definition: ptabasic.c:1145
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
l_ok ptaaAddPta(PTAA *ptaa, PTA *pta, l_int32 copyflag)
ptaaAddPta()
Definition: ptabasic.c:1038
PTA * ptaClone(PTA *pta)
ptaClone()
Definition: ptabasic.c:297
l_int32 ptaaGetCount(PTAA *ptaa)
ptaaGetCount()
Definition: ptabasic.c:1125
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
PTA * ptaGetPixelsFromPix(PIX *pixs, BOX *box)
ptaGetPixelsFromPix()
Definition: ptafunc1.c:1970
l_int32 ptaPtInsidePolygon(PTA *pta, l_float32 x, l_float32 y, l_int32 *pinside)
ptaPtInsidePolygon()
Definition: ptafunc1.c:780
l_ok ptaJoin(PTA *ptad, PTA *ptas, l_int32 istart, l_int32 iend)
ptaJoin()
Definition: ptafunc1.c:167
l_ok ptaGetRange(PTA *pta, l_float32 *pminx, l_float32 *pmaxx, l_float32 *pminy, l_float32 *pmaxy)
ptaGetRange()
Definition: ptafunc1.c:488
PTA * ptaReplicatePattern(PTA *ptas, PIX *pixp, PTA *ptap, l_int32 cx, l_int32 cy, l_int32 w, l_int32 h)
ptaReplicatePattern()
Definition: ptafunc1.c:2620
PTA * ptaCropToMask(PTA *ptas, PIX *pixm)
ptaCropToMask()
Definition: ptafunc1.c:1039
l_ok ptaRemoveDupsByAset(PTA *ptas, PTA **pptad)
ptaRemoveDupsByAset()
Definition: ptafunc2.c:489
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
l_ok pixFindHorizontalRuns(PIX *pix, l_int32 y, l_int32 *xstart, l_int32 *xend, l_int32 *pn)
pixFindHorizontalRuns()
Definition: runlength.c:375
PIX * pixSeedfillBinary(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 connectivity)
pixSeedfillBinary()
Definition: seedfill.c:247
Definition: pix.h:481
Definition: pix.h:492
Definition: pix.h:579
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:517
Definition: pix.h:531