Leptonica  1.83.1
Image processing and image analysis suite
ptabasic.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 
93 #ifdef HAVE_CONFIG_H
94 #include <config_auto.h>
95 #endif /* HAVE_CONFIG_H */
96 
97 #include <string.h>
98 #include "allheaders.h"
99 #include "array_internal.h"
100 #include "pix_internal.h"
101 
102 static const l_uint32 MaxArraySize = 100000000; /* 100 million */
103 static const l_uint32 MaxPtrArraySize = 10000000; /* 10 million */
104 static const l_int32 InitialArraySize = 50;
106  /* Static functions */
107 static l_int32 ptaExtendArrays(PTA *pta);
108 static l_int32 ptaaExtendArray(PTAA *ptaa);
109 
110 /*---------------------------------------------------------------------*
111  * Pta creation, destruction, copy, clone *
112  *---------------------------------------------------------------------*/
119 PTA *
120 ptaCreate(l_int32 n)
121 {
122 PTA *pta;
123 
124  if (n <= 0 || n > MaxArraySize)
125  n = InitialArraySize;
126 
127  pta = (PTA *)LEPT_CALLOC(1, sizeof(PTA));
128  pta->n = 0;
129  pta->nalloc = n;
130  pta->refcount = 1;
131  pta->x = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32));
132  pta->y = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32));
133  if (!pta->x || !pta->y) {
134  ptaDestroy(&pta);
135  return (PTA *)ERROR_PTR("x and y arrays not both made", __func__, NULL);
136  }
137 
138  return pta;
139 }
140 
141 
149 PTA *
151  NUMA *nay)
152 {
153 l_int32 i, n;
154 l_float32 startx, delx, xval, yval;
155 PTA *pta;
156 
157  if (!nay)
158  return (PTA *)ERROR_PTR("nay not defined", __func__, NULL);
159  n = numaGetCount(nay);
160  if (nax && numaGetCount(nax) != n)
161  return (PTA *)ERROR_PTR("nax and nay sizes differ", __func__, NULL);
162 
163  pta = ptaCreate(n);
164  numaGetParameters(nay, &startx, &delx);
165  for (i = 0; i < n; i++) {
166  if (nax)
167  numaGetFValue(nax, i, &xval);
168  else /* use implicit x values from nay */
169  xval = startx + i * delx;
170  numaGetFValue(nay, i, &yval);
171  ptaAddPt(pta, xval, yval);
172  }
173 
174  return pta;
175 }
176 
177 
190 void
192 {
193 PTA *pta;
194 
195  if (ppta == NULL) {
196  L_WARNING("ptr address is NULL!\n", __func__);
197  return;
198  }
199 
200  if ((pta = *ppta) == NULL)
201  return;
202 
203  if (--pta->refcount == 0) {
204  LEPT_FREE(pta->x);
205  LEPT_FREE(pta->y);
206  LEPT_FREE(pta);
207  }
208  *ppta = NULL;
209 }
210 
211 
218 PTA *
220 {
221 l_int32 i;
222 l_float32 x, y;
223 PTA *npta;
224 
225  if (!pta)
226  return (PTA *)ERROR_PTR("pta not defined", __func__, NULL);
227 
228  if ((npta = ptaCreate(pta->nalloc)) == NULL)
229  return (PTA *)ERROR_PTR("npta not made", __func__, NULL);
230 
231  for (i = 0; i < pta->n; i++) {
232  ptaGetPt(pta, i, &x, &y);
233  ptaAddPt(npta, x, y);
234  }
235 
236  return npta;
237 }
238 
239 
248 PTA *
250  l_int32 istart,
251  l_int32 iend)
252 {
253 l_int32 n, i, x, y;
254 PTA *ptad;
255 
256  if (!ptas)
257  return (PTA *)ERROR_PTR("ptas not defined", __func__, NULL);
258  n = ptaGetCount(ptas);
259  if (istart < 0)
260  istart = 0;
261  if (istart >= n)
262  return (PTA *)ERROR_PTR("istart out of bounds", __func__, NULL);
263  if (iend <= 0 || iend >= n)
264  iend = n - 1;
265  if (istart > iend)
266  return (PTA *)ERROR_PTR("istart > iend; no pts", __func__, NULL);
267 
268  if ((ptad = ptaCreate(iend - istart + 1)) == NULL)
269  return (PTA *)ERROR_PTR("ptad not made", __func__, NULL);
270  for (i = istart; i <= iend; i++) {
271  ptaGetIPt(ptas, i, &x, &y);
272  ptaAddPt(ptad, x, y);
273  }
274 
275  return ptad;
276 }
277 
278 
285 PTA *
287 {
288  if (!pta)
289  return (PTA *)ERROR_PTR("pta not defined", __func__, NULL);
290 
291  ++pta->refcount;
292  return pta;
293 }
294 
295 
307 l_ok
309 {
310  if (!pta)
311  return ERROR_INT("ptad not defined", __func__, 1);
312  pta->n = 0;
313  return 0;
314 }
315 
316 
317 /*---------------------------------------------------------------------*
318  * Pta array extension *
319  *---------------------------------------------------------------------*/
327 l_ok
329  l_float32 x,
330  l_float32 y)
331 {
332 l_int32 n;
333 
334  if (!pta)
335  return ERROR_INT("pta not defined", __func__, 1);
336 
337  n = pta->n;
338  if (n >= pta->nalloc) {
339  if (ptaExtendArrays(pta))
340  return ERROR_INT("extension failed", __func__, 1);
341  }
342 
343  pta->x[n] = x;
344  pta->y[n] = y;
345  pta->n++;
346  return 0;
347 }
348 
349 
362 static l_int32
364 {
365 size_t oldsize, newsize;
366 
367  if (!pta)
368  return ERROR_INT("pta not defined", __func__, 1);
369  if (pta->nalloc > MaxArraySize)
370  return ERROR_INT("pta at maximum size; can't extend", __func__, 1);
371  oldsize = 4 * pta->nalloc;
372  if (pta->nalloc > MaxArraySize / 2) {
373  newsize = 4 * MaxArraySize;
374  pta->nalloc = MaxArraySize;
375  } else {
376  newsize = 2 * oldsize;
377  pta->nalloc *= 2;
378  }
379  if ((pta->x = (l_float32 *)reallocNew((void **)&pta->x,
380  oldsize, newsize)) == NULL)
381  return ERROR_INT("new x array not returned", __func__, 1);
382  if ((pta->y = (l_float32 *)reallocNew((void **)&pta->y,
383  oldsize, newsize)) == NULL)
384  return ERROR_INT("new y array not returned", __func__, 1);
385 
386  return 0;
387 }
388 
389 
390 /*---------------------------------------------------------------------*
391  * Pta insertion and removal *
392  *---------------------------------------------------------------------*/
401 l_ok
403  l_int32 index,
404  l_int32 x,
405  l_int32 y)
406 {
407 l_int32 i, n;
408 
409  if (!pta)
410  return ERROR_INT("pta not defined", __func__, 1);
411  n = ptaGetCount(pta);
412  if (index < 0 || index > n) {
413  L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n);
414  return 1;
415  }
416 
417  if (n > pta->nalloc) {
418  if (ptaExtendArrays(pta))
419  return ERROR_INT("extension failed", __func__, 1);
420  }
421  pta->n++;
422  for (i = n; i > index; i--) {
423  pta->x[i] = pta->x[i - 1];
424  pta->y[i] = pta->y[i - 1];
425  }
426  pta->x[index] = x;
427  pta->y[index] = y;
428  return 0;
429 }
430 
431 
446 l_ok
448  l_int32 index)
449 {
450 l_int32 i, n;
451 
452  if (!pta)
453  return ERROR_INT("pta not defined", __func__, 1);
454  n = ptaGetCount(pta);
455  if (index < 0 || index >= n) {
456  L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
457  return 1;
458  }
459 
460  /* Remove the point */
461  for (i = index + 1; i < n; i++) {
462  pta->x[i - 1] = pta->x[i];
463  pta->y[i - 1] = pta->y[i];
464  }
465  pta->n--;
466  return 0;
467 }
468 
469 
470 /*---------------------------------------------------------------------*
471  * Pta accessors *
472  *---------------------------------------------------------------------*/
479 l_int32
481 {
482  if (!pta)
483  return ERROR_INT("pta not defined", __func__, 0);
484 
485  return pta->n;
486 }
487 
488 
498 l_ok
500  l_int32 index,
501  l_float32 *px,
502  l_float32 *py)
503 {
504  if (px) *px = 0;
505  if (py) *py = 0;
506  if (!pta)
507  return ERROR_INT("pta not defined", __func__, 1);
508  if (index < 0 || index >= pta->n)
509  return ERROR_INT("invalid index", __func__, 1);
510 
511  if (px) *px = pta->x[index];
512  if (py) *py = pta->y[index];
513  return 0;
514 }
515 
516 
526 l_ok
528  l_int32 index,
529  l_int32 *px,
530  l_int32 *py)
531 {
532  if (px) *px = 0;
533  if (py) *py = 0;
534  if (!pta)
535  return ERROR_INT("pta not defined", __func__, 1);
536  if (index < 0 || index >= pta->n)
537  return ERROR_INT("invalid index", __func__, 1);
538 
539  if (px) *px = (l_int32)(pta->x[index] + 0.5);
540  if (py) *py = (l_int32)(pta->y[index] + 0.5);
541  return 0;
542 }
543 
544 
553 l_ok
555  l_int32 index,
556  l_float32 x,
557  l_float32 y)
558 {
559  if (!pta)
560  return ERROR_INT("pta not defined", __func__, 1);
561  if (index < 0 || index >= pta->n)
562  return ERROR_INT("invalid index", __func__, 1);
563 
564  pta->x[index] = x;
565  pta->y[index] = y;
566  return 0;
567 }
568 
569 
583 l_ok
585  NUMA **pnax,
586  NUMA **pnay)
587 {
588 l_int32 i, n;
589 NUMA *nax, *nay;
590 
591  if (!pnax && !pnay)
592  return ERROR_INT("no output requested", __func__, 1);
593  if (pnax) *pnax = NULL;
594  if (pnay) *pnay = NULL;
595  if (!pta)
596  return ERROR_INT("pta not defined", __func__, 1);
597  if ((n = ptaGetCount(pta)) == 0)
598  return ERROR_INT("pta is empty", __func__, 1);
599 
600  if (pnax) {
601  if ((nax = numaCreate(n)) == NULL)
602  return ERROR_INT("nax not made", __func__, 1);
603  *pnax = nax;
604  for (i = 0; i < n; i++)
605  nax->array[i] = pta->x[i];
606  nax->n = n;
607  }
608  if (pnay) {
609  if ((nay = numaCreate(n)) == NULL)
610  return ERROR_INT("nay not made", __func__, 1);
611  *pnay = nay;
612  for (i = 0; i < n; i++)
613  nay->array[i] = pta->y[i];
614  nay->n = n;
615  }
616  return 0;
617 }
618 
619 
620 /*---------------------------------------------------------------------*
621  * Pta serialized for I/O *
622  *---------------------------------------------------------------------*/
629 PTA *
630 ptaRead(const char *filename)
631 {
632 FILE *fp;
633 PTA *pta;
634 
635  if (!filename)
636  return (PTA *)ERROR_PTR("filename not defined", __func__, NULL);
637 
638  if ((fp = fopenReadStream(filename)) == NULL)
639  return (PTA *)ERROR_PTR("stream not opened", __func__, NULL);
640  pta = ptaReadStream(fp);
641  fclose(fp);
642  if (!pta)
643  return (PTA *)ERROR_PTR("pta not read", __func__, NULL);
644  return pta;
645 }
646 
647 
660 PTA *
661 ptaReadStream(FILE *fp)
662 {
663 char typestr[128]; /* hardcoded below in fscanf */
664 l_int32 i, n, ix, iy, type, version;
665 l_float32 x, y;
666 PTA *pta;
667 
668  if (!fp)
669  return (PTA *)ERROR_PTR("stream not defined", __func__, NULL);
670 
671  if (fscanf(fp, "\n Pta Version %d\n", &version) != 1)
672  return (PTA *)ERROR_PTR("not a pta file", __func__, NULL);
673  if (version != PTA_VERSION_NUMBER)
674  return (PTA *)ERROR_PTR("invalid pta version", __func__, NULL);
675  if (fscanf(fp, " Number of pts = %d; format = %127s\n", &n, typestr) != 2)
676  return (PTA *)ERROR_PTR("not a pta file", __func__, NULL);
677  if (n < 0)
678  return (PTA *)ERROR_PTR("num pts <= 0", __func__, NULL);
679  if (n > MaxArraySize)
680  return (PTA *)ERROR_PTR("too many pts", __func__, NULL);
681  if (n == 0) L_INFO("the pta is empty\n", __func__);
682 
683  if (!strcmp(typestr, "float"))
684  type = 0;
685  else /* typestr is "integer" */
686  type = 1;
687  if ((pta = ptaCreate(n)) == NULL)
688  return (PTA *)ERROR_PTR("pta not made", __func__, NULL);
689  for (i = 0; i < n; i++) {
690  if (type == 0) { /* data is float */
691  if (fscanf(fp, " (%f, %f)\n", &x, &y) != 2) {
692  ptaDestroy(&pta);
693  return (PTA *)ERROR_PTR("error reading floats", __func__, NULL);
694  }
695  ptaAddPt(pta, x, y);
696  } else { /* data is integer */
697  if (fscanf(fp, " (%d, %d)\n", &ix, &iy) != 2) {
698  ptaDestroy(&pta);
699  return (PTA *)ERROR_PTR("error reading ints", __func__, NULL);
700  }
701  ptaAddPt(pta, ix, iy);
702  }
703  }
704 
705  return pta;
706 }
707 
708 
716 PTA *
717 ptaReadMem(const l_uint8 *data,
718  size_t size)
719 {
720 FILE *fp;
721 PTA *pta;
722 
723  if (!data)
724  return (PTA *)ERROR_PTR("data not defined", __func__, NULL);
725  if ((fp = fopenReadFromMemory(data, size)) == NULL)
726  return (PTA *)ERROR_PTR("stream not opened", __func__, NULL);
727 
728  pta = ptaReadStream(fp);
729  fclose(fp);
730  if (!pta) L_ERROR("pta not read\n", __func__);
731  return pta;
732 }
733 
734 
752 l_ok
753 ptaWriteDebug(const char *filename,
754  PTA *pta,
755  l_int32 type)
756 {
757  if (LeptDebugOK) {
758  return ptaWrite(filename, pta, type);
759  } else {
760  L_INFO("write to named temp file %s is disabled\n", __func__, filename);
761  return 0;
762  }
763 }
764 
765 
774 l_ok
775 ptaWrite(const char *filename,
776  PTA *pta,
777  l_int32 type)
778 {
779 l_int32 ret;
780 FILE *fp;
781 
782  if (!filename)
783  return ERROR_INT("filename not defined", __func__, 1);
784  if (!pta)
785  return ERROR_INT("pta not defined", __func__, 1);
786 
787  if ((fp = fopenWriteStream(filename, "w")) == NULL)
788  return ERROR_INT("stream not opened", __func__, 1);
789  ret = ptaWriteStream(fp, pta, type);
790  fclose(fp);
791  if (ret)
792  return ERROR_INT("pta not written to stream", __func__, 1);
793  return 0;
794 }
795 
796 
805 l_ok
806 ptaWriteStream(FILE *fp,
807  PTA *pta,
808  l_int32 type)
809 {
810 l_int32 i, n, ix, iy;
811 l_float32 x, y;
812 
813  if (!fp)
814  return ERROR_INT("stream not defined", __func__, 1);
815  if (!pta)
816  return ERROR_INT("pta not defined", __func__, 1);
817 
818  n = ptaGetCount(pta);
819  fprintf(fp, "\n Pta Version %d\n", PTA_VERSION_NUMBER);
820  if (type == 0)
821  fprintf(fp, " Number of pts = %d; format = float\n", n);
822  else /* type == 1 */
823  fprintf(fp, " Number of pts = %d; format = integer\n", n);
824  for (i = 0; i < n; i++) {
825  if (type == 0) { /* data is float */
826  ptaGetPt(pta, i, &x, &y);
827  fprintf(fp, " (%f, %f)\n", x, y);
828  } else { /* data is integer */
829  ptaGetIPt(pta, i, &ix, &iy);
830  fprintf(fp, " (%d, %d)\n", ix, iy);
831  }
832  }
833 
834  return 0;
835 }
836 
837 
852 l_ok
853 ptaWriteMem(l_uint8 **pdata,
854  size_t *psize,
855  PTA *pta,
856  l_int32 type)
857 {
858 l_int32 ret;
859 FILE *fp;
860 
861  if (pdata) *pdata = NULL;
862  if (psize) *psize = 0;
863  if (!pdata)
864  return ERROR_INT("&data not defined", __func__, 1);
865  if (!psize)
866  return ERROR_INT("&size not defined", __func__, 1);
867  if (!pta)
868  return ERROR_INT("pta not defined", __func__, 1);
869 
870 #if HAVE_FMEMOPEN
871  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
872  return ERROR_INT("stream not opened", __func__, 1);
873  ret = ptaWriteStream(fp, pta, type);
874  fputc('\0', fp);
875  fclose(fp);
876  *psize = *psize - 1;
877 #else
878  L_INFO("work-around: writing to a temp file\n", __func__);
879  #ifdef _WIN32
880  if ((fp = fopenWriteWinTempfile()) == NULL)
881  return ERROR_INT("tmpfile stream not opened", __func__, 1);
882  #else
883  if ((fp = tmpfile()) == NULL)
884  return ERROR_INT("tmpfile stream not opened", __func__, 1);
885  #endif /* _WIN32 */
886  ret = ptaWriteStream(fp, pta, type);
887  rewind(fp);
888  *pdata = l_binaryReadStream(fp, psize);
889  fclose(fp);
890 #endif /* HAVE_FMEMOPEN */
891  return ret;
892 }
893 
894 
895 /*---------------------------------------------------------------------*
896  * PTAA creation, destruction *
897  *---------------------------------------------------------------------*/
904 PTAA *
905 ptaaCreate(l_int32 n)
906 {
907 PTAA *ptaa;
908 
909  if (n <= 0 || n > MaxPtrArraySize)
910  n = InitialArraySize;
911 
912  ptaa = (PTAA *)LEPT_CALLOC(1, sizeof(PTAA));
913  ptaa->n = 0;
914  ptaa->nalloc = n;
915  if ((ptaa->pta = (PTA **)LEPT_CALLOC(n, sizeof(PTA *))) == NULL) {
916  ptaaDestroy(&ptaa);
917  return (PTAA *)ERROR_PTR("pta ptrs not made", __func__, NULL);
918  }
919  return ptaa;
920 }
921 
922 
929 void
931 {
932 l_int32 i;
933 PTAA *ptaa;
934 
935  if (pptaa == NULL) {
936  L_WARNING("ptr address is NULL!\n", __func__);
937  return;
938  }
939 
940  if ((ptaa = *pptaa) == NULL)
941  return;
942 
943  for (i = 0; i < ptaa->n; i++)
944  ptaDestroy(&ptaa->pta[i]);
945  LEPT_FREE(ptaa->pta);
946  LEPT_FREE(ptaa);
947  *pptaa = NULL;
948 }
949 
950 
951 /*---------------------------------------------------------------------*
952  * PTAA array extension *
953  *---------------------------------------------------------------------*/
962 l_ok
964  PTA *pta,
965  l_int32 copyflag)
966 {
967 l_int32 n;
968 PTA *ptac;
969 
970  if (!ptaa)
971  return ERROR_INT("ptaa not defined", __func__, 1);
972  if (!pta)
973  return ERROR_INT("pta not defined", __func__, 1);
974 
975  if (copyflag == L_INSERT) {
976  ptac = pta;
977  } else if (copyflag == L_COPY) {
978  if ((ptac = ptaCopy(pta)) == NULL)
979  return ERROR_INT("ptac not made", __func__, 1);
980  } else if (copyflag == L_CLONE) {
981  if ((ptac = ptaClone(pta)) == NULL)
982  return ERROR_INT("pta clone not made", __func__, 1);
983  } else {
984  return ERROR_INT("invalid copyflag", __func__, 1);
985  }
986 
987  n = ptaaGetCount(ptaa);
988  if (n >= ptaa->nalloc) {
989  if (ptaaExtendArray(ptaa)) {
990  if (copyflag != L_INSERT)
991  ptaDestroy(&ptac);
992  return ERROR_INT("extension failed", __func__, 1);
993  }
994  }
995 
996  ptaa->pta[n] = ptac;
997  ptaa->n++;
998  return 0;
999 }
1000 
1001 
1015 static l_int32
1017 {
1018 size_t oldsize, newsize;
1019 
1020  if (!ptaa)
1021  return ERROR_INT("ptaa not defined", __func__, 1);
1022  oldsize = ptaa->nalloc * sizeof(PTA *);
1023  newsize = 2 * oldsize;
1024  if (newsize > 8 * MaxPtrArraySize)
1025  return ERROR_INT("newsize > 80 MB; too large", __func__, 1);
1026 
1027  if ((ptaa->pta = (PTA **)reallocNew((void **)&ptaa->pta,
1028  oldsize, newsize)) == NULL)
1029  return ERROR_INT("new ptr array not returned", __func__, 1);
1030 
1031  ptaa->nalloc *= 2;
1032  return 0;
1033 }
1034 
1035 
1036 /*---------------------------------------------------------------------*
1037  * Ptaa accessors *
1038  *---------------------------------------------------------------------*/
1045 l_int32
1047 {
1048  if (!ptaa)
1049  return ERROR_INT("ptaa not defined", __func__, 0);
1050 
1051  return ptaa->n;
1052 }
1053 
1054 
1063 PTA *
1065  l_int32 index,
1066  l_int32 accessflag)
1067 {
1068  if (!ptaa)
1069  return (PTA *)ERROR_PTR("ptaa not defined", __func__, NULL);
1070  if (index < 0 || index >= ptaa->n)
1071  return (PTA *)ERROR_PTR("index not valid", __func__, NULL);
1072 
1073  if (accessflag == L_COPY)
1074  return ptaCopy(ptaa->pta[index]);
1075  else if (accessflag == L_CLONE)
1076  return ptaClone(ptaa->pta[index]);
1077  else
1078  return (PTA *)ERROR_PTR("invalid accessflag", __func__, NULL);
1079 }
1080 
1081 
1092 l_ok
1094  l_int32 ipta,
1095  l_int32 jpt,
1096  l_float32 *px,
1097  l_float32 *py)
1098 {
1099 PTA *pta;
1100 
1101  if (px) *px = 0;
1102  if (py) *py = 0;
1103  if (!ptaa)
1104  return ERROR_INT("ptaa not defined", __func__, 1);
1105  if (ipta < 0 || ipta >= ptaa->n)
1106  return ERROR_INT("index ipta not valid", __func__, 1);
1107 
1108  pta = ptaaGetPta(ptaa, ipta, L_CLONE);
1109  if (jpt < 0 || jpt >= pta->n) {
1110  ptaDestroy(&pta);
1111  return ERROR_INT("index jpt not valid", __func__, 1);
1112  }
1113 
1114  ptaGetPt(pta, jpt, px, py);
1115  ptaDestroy(&pta);
1116  return 0;
1117 }
1118 
1119 
1120 /*---------------------------------------------------------------------*
1121  * Ptaa array modifiers *
1122  *---------------------------------------------------------------------*/
1130 l_ok
1132  PTA *pta)
1133 {
1134 l_int32 n, i;
1135 PTA *ptat;
1136 
1137  if (!ptaa)
1138  return ERROR_INT("ptaa not defined", __func__, 1);
1139  if (!pta)
1140  return ERROR_INT("pta not defined", __func__, 1);
1141 
1142  n = ptaa->nalloc;
1143  ptaa->n = n;
1144  for (i = 0; i < n; i++) {
1145  ptat = ptaCopy(pta);
1146  ptaaReplacePta(ptaa, i, ptat);
1147  }
1148  return 0;
1149 }
1150 
1151 
1167 l_ok
1169  l_int32 index,
1170  PTA *pta)
1171 {
1172 l_int32 n;
1173 
1174  if (!ptaa)
1175  return ERROR_INT("ptaa not defined", __func__, 1);
1176  if (!pta)
1177  return ERROR_INT("pta not defined", __func__, 1);
1178  n = ptaaGetCount(ptaa);
1179  if (index < 0 || index >= n)
1180  return ERROR_INT("index not valid", __func__, 1);
1181 
1182  ptaDestroy(&ptaa->pta[index]);
1183  ptaa->pta[index] = pta;
1184  return 0;
1185 }
1186 
1187 
1196 l_ok
1198  l_int32 ipta,
1199  l_float32 x,
1200  l_float32 y)
1201 {
1202 PTA *pta;
1203 
1204  if (!ptaa)
1205  return ERROR_INT("ptaa not defined", __func__, 1);
1206  if (ipta < 0 || ipta >= ptaa->n)
1207  return ERROR_INT("index ipta not valid", __func__, 1);
1208 
1209  pta = ptaaGetPta(ptaa, ipta, L_CLONE);
1210  ptaAddPt(pta, x, y);
1211  ptaDestroy(&pta);
1212  return 0;
1213 }
1214 
1215 
1229 l_ok
1231 {
1232 l_int32 i, n, np;
1233 PTA *pta;
1234 
1235  if (!ptaa)
1236  return ERROR_INT("ptaa not defined", __func__, 1);
1237 
1238  n = ptaaGetCount(ptaa);
1239  for (i = n - 1; i >= 0; i--) {
1240  pta = ptaaGetPta(ptaa, i, L_CLONE);
1241  if (!pta) {
1242  ptaa->n--;
1243  continue;
1244  }
1245  np = ptaGetCount(pta);
1246  ptaDestroy(&pta);
1247  if (np == 0) {
1248  ptaDestroy(&ptaa->pta[i]);
1249  ptaa->n--;
1250  } else {
1251  break;
1252  }
1253  }
1254  return 0;
1255 }
1256 
1257 
1258 /*---------------------------------------------------------------------*
1259  * Ptaa serialized for I/O *
1260  *---------------------------------------------------------------------*/
1267 PTAA *
1268 ptaaRead(const char *filename)
1269 {
1270 FILE *fp;
1271 PTAA *ptaa;
1272 
1273  if (!filename)
1274  return (PTAA *)ERROR_PTR("filename not defined", __func__, NULL);
1275 
1276  if ((fp = fopenReadStream(filename)) == NULL)
1277  return (PTAA *)ERROR_PTR("stream not opened", __func__, NULL);
1278  ptaa = ptaaReadStream(fp);
1279  fclose(fp);
1280  if (!ptaa)
1281  return (PTAA *)ERROR_PTR("ptaa not read", __func__, NULL);
1282  return ptaa;
1283 }
1284 
1285 
1297 PTAA *
1299 {
1300 l_int32 i, n, version;
1301 PTA *pta;
1302 PTAA *ptaa;
1303 
1304  if (!fp)
1305  return (PTAA *)ERROR_PTR("stream not defined", __func__, NULL);
1306 
1307  if (fscanf(fp, "\nPtaa Version %d\n", &version) != 1)
1308  return (PTAA *)ERROR_PTR("not a ptaa file", __func__, NULL);
1309  if (version != PTA_VERSION_NUMBER)
1310  return (PTAA *)ERROR_PTR("invalid ptaa version", __func__, NULL);
1311  if (fscanf(fp, "Number of Pta = %d\n", &n) != 1)
1312  return (PTAA *)ERROR_PTR("not a ptaa file", __func__, NULL);
1313  if (n < 0)
1314  return (PTAA *)ERROR_PTR("num pta ptrs <= 0", __func__, NULL);
1315  if (n > MaxPtrArraySize)
1316  return (PTAA *)ERROR_PTR("too many pta ptrs", __func__, NULL);
1317  if (n == 0) L_INFO("the ptaa is empty\n", __func__);
1318 
1319  if ((ptaa = ptaaCreate(n)) == NULL)
1320  return (PTAA *)ERROR_PTR("ptaa not made", __func__, NULL);
1321  for (i = 0; i < n; i++) {
1322  if ((pta = ptaReadStream(fp)) == NULL) {
1323  ptaaDestroy(&ptaa);
1324  return (PTAA *)ERROR_PTR("error reading pta", __func__, NULL);
1325  }
1326  ptaaAddPta(ptaa, pta, L_INSERT);
1327  }
1328 
1329  return ptaa;
1330 }
1331 
1332 
1340 PTAA *
1341 ptaaReadMem(const l_uint8 *data,
1342  size_t size)
1343 {
1344 FILE *fp;
1345 PTAA *ptaa;
1346 
1347  if (!data)
1348  return (PTAA *)ERROR_PTR("data not defined", __func__, NULL);
1349  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1350  return (PTAA *)ERROR_PTR("stream not opened", __func__, NULL);
1351 
1352  ptaa = ptaaReadStream(fp);
1353  fclose(fp);
1354  if (!ptaa) L_ERROR("ptaa not read\n", __func__);
1355  return ptaa;
1356 }
1357 
1358 
1376 l_ok
1377 ptaaWriteDebug(const char *filename,
1378  PTAA *ptaa,
1379  l_int32 type)
1380 {
1381  if (LeptDebugOK) {
1382  return ptaaWrite(filename, ptaa, type);
1383  } else {
1384  L_INFO("write to named temp file %s is disabled\n", __func__, filename);
1385  return 0;
1386  }
1387 }
1388 
1389 
1398 l_ok
1399 ptaaWrite(const char *filename,
1400  PTAA *ptaa,
1401  l_int32 type)
1402 {
1403 l_int32 ret;
1404 FILE *fp;
1405 
1406  if (!filename)
1407  return ERROR_INT("filename not defined", __func__, 1);
1408  if (!ptaa)
1409  return ERROR_INT("ptaa not defined", __func__, 1);
1410 
1411  if ((fp = fopenWriteStream(filename, "w")) == NULL)
1412  return ERROR_INT("stream not opened", __func__, 1);
1413  ret = ptaaWriteStream(fp, ptaa, type);
1414  fclose(fp);
1415  if (ret)
1416  return ERROR_INT("ptaa not written to stream", __func__, 1);
1417  return 0;
1418 }
1419 
1420 
1429 l_ok
1431  PTAA *ptaa,
1432  l_int32 type)
1433 {
1434 l_int32 i, n;
1435 PTA *pta;
1436 
1437  if (!fp)
1438  return ERROR_INT("stream not defined", __func__, 1);
1439  if (!ptaa)
1440  return ERROR_INT("ptaa not defined", __func__, 1);
1441 
1442  n = ptaaGetCount(ptaa);
1443  fprintf(fp, "\nPtaa Version %d\n", PTA_VERSION_NUMBER);
1444  fprintf(fp, "Number of Pta = %d\n", n);
1445  for (i = 0; i < n; i++) {
1446  pta = ptaaGetPta(ptaa, i, L_CLONE);
1447  ptaWriteStream(fp, pta, type);
1448  ptaDestroy(&pta);
1449  }
1450 
1451  return 0;
1452 }
1453 
1454 
1469 l_ok
1470 ptaaWriteMem(l_uint8 **pdata,
1471  size_t *psize,
1472  PTAA *ptaa,
1473  l_int32 type)
1474 {
1475 l_int32 ret;
1476 FILE *fp;
1477 
1478  if (pdata) *pdata = NULL;
1479  if (psize) *psize = 0;
1480  if (!pdata)
1481  return ERROR_INT("&data not defined", __func__, 1);
1482  if (!psize)
1483  return ERROR_INT("&size not defined", __func__, 1);
1484  if (!ptaa)
1485  return ERROR_INT("ptaa not defined", __func__, 1);
1486 
1487 #if HAVE_FMEMOPEN
1488  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1489  return ERROR_INT("stream not opened", __func__, 1);
1490  ret = ptaaWriteStream(fp, ptaa, type);
1491  fputc('\0', fp);
1492  fclose(fp);
1493  *psize = *psize - 1;
1494 #else
1495  L_INFO("work-around: writing to a temp file\n", __func__);
1496  #ifdef _WIN32
1497  if ((fp = fopenWriteWinTempfile()) == NULL)
1498  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1499  #else
1500  if ((fp = tmpfile()) == NULL)
1501  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1502  #endif /* _WIN32 */
1503  ret = ptaaWriteStream(fp, ptaa, type);
1504  rewind(fp);
1505  *pdata = l_binaryReadStream(fp, psize);
1506  fclose(fp);
1507 #endif /* HAVE_FMEMOPEN */
1508  return ret;
1509 }
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:687
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_ok numaGetParameters(NUMA *na, l_float32 *pstartx, l_float32 *pdelx)
numaGetParameters()
Definition: numabasic.c:882
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_INSERT
Definition: pix.h:504
#define PTA_VERSION_NUMBER
Definition: pix_internal.h:285
l_ok ptaWriteStream(FILE *fp, PTA *pta, l_int32 type)
ptaWriteStream()
Definition: ptabasic.c:806
PTA * ptaCreateFromNuma(NUMA *nax, NUMA *nay)
ptaCreateFromNuma()
Definition: ptabasic.c:150
PTA * ptaReadStream(FILE *fp)
ptaReadStream()
Definition: ptabasic.c:661
static l_int32 ptaaExtendArray(PTAA *ptaa)
ptaaExtendArray()
Definition: ptabasic.c:1016
l_ok ptaWriteMem(l_uint8 **pdata, size_t *psize, PTA *pta, l_int32 type)
ptaWriteMem()
Definition: ptabasic.c:853
PTAA * ptaaReadMem(const l_uint8 *data, size_t size)
ptaaReadMem()
Definition: ptabasic.c:1341
PTAA * ptaaCreate(l_int32 n)
ptaaCreate()
Definition: ptabasic.c:905
l_ok ptaaAddPt(PTAA *ptaa, l_int32 ipta, l_float32 x, l_float32 y)
ptaaAddPt()
Definition: ptabasic.c:1197
l_ok ptaSetPt(PTA *pta, l_int32 index, l_float32 x, l_float32 y)
ptaSetPt()
Definition: ptabasic.c:554
PTA * ptaaGetPta(PTAA *ptaa, l_int32 index, l_int32 accessflag)
ptaaGetPta()
Definition: ptabasic.c:1064
l_ok ptaEmpty(PTA *pta)
ptaEmpty()
Definition: ptabasic.c:308
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:527
l_ok ptaRemovePt(PTA *pta, l_int32 index)
ptaRemovePt()
Definition: ptabasic.c:447
l_ok ptaWriteDebug(const char *filename, PTA *pta, l_int32 type)
ptaWriteDebug()
Definition: ptabasic.c:753
l_ok ptaaWriteMem(l_uint8 **pdata, size_t *psize, PTAA *ptaa, l_int32 type)
ptaaWriteMem()
Definition: ptabasic.c:1470
l_ok ptaaAddPta(PTAA *ptaa, PTA *pta, l_int32 copyflag)
ptaaAddPta()
Definition: ptabasic.c:963
PTA * ptaClone(PTA *pta)
ptaClone()
Definition: ptabasic.c:286
l_int32 ptaaGetCount(PTAA *ptaa)
ptaaGetCount()
Definition: ptabasic.c:1046
l_ok ptaaWrite(const char *filename, PTAA *ptaa, l_int32 type)
ptaaWrite()
Definition: ptabasic.c:1399
l_ok ptaaInitFull(PTAA *ptaa, PTA *pta)
ptaaInitFull()
Definition: ptabasic.c:1131
PTA * ptaReadMem(const l_uint8 *data, size_t size)
ptaReadMem()
Definition: ptabasic.c:717
l_ok ptaaGetPt(PTAA *ptaa, l_int32 ipta, l_int32 jpt, l_float32 *px, l_float32 *py)
ptaaGetPt()
Definition: ptabasic.c:1093
l_ok ptaaWriteStream(FILE *fp, PTAA *ptaa, l_int32 type)
ptaaWriteStream()
Definition: ptabasic.c:1430
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:328
l_ok ptaaWriteDebug(const char *filename, PTAA *ptaa, l_int32 type)
ptaaWriteDebug()
Definition: ptabasic.c:1377
l_ok ptaGetArrays(PTA *pta, NUMA **pnax, NUMA **pnay)
ptaGetArrays()
Definition: ptabasic.c:584
l_ok ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:499
l_ok ptaInsertPt(PTA *pta, l_int32 index, l_int32 x, l_int32 y)
ptaInsertPt()
Definition: ptabasic.c:402
l_ok ptaWrite(const char *filename, PTA *pta, l_int32 type)
ptaWrite()
Definition: ptabasic.c:775
static const l_int32 InitialArraySize
Definition: ptabasic.c:104
PTA * ptaRead(const char *filename)
ptaRead()
Definition: ptabasic.c:630
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:480
void ptaaDestroy(PTAA **pptaa)
ptaaDestroy()
Definition: ptabasic.c:930
PTAA * ptaaReadStream(FILE *fp)
ptaaReadStream()
Definition: ptabasic.c:1298
PTAA * ptaaRead(const char *filename)
ptaaRead()
Definition: ptabasic.c:1268
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
l_ok ptaaReplacePta(PTAA *ptaa, l_int32 index, PTA *pta)
ptaaReplacePta()
Definition: ptabasic.c:1168
PTA * ptaCopyRange(PTA *ptas, l_int32 istart, l_int32 iend)
ptaCopyRange()
Definition: ptabasic.c:249
static l_int32 ptaExtendArrays(PTA *pta)
ptaExtendArrays()
Definition: ptabasic.c:363
l_ok ptaaTruncate(PTAA *ptaa)
ptaaTruncate()
Definition: ptabasic.c:1230
PTA * ptaCopy(PTA *pta)
ptaCopy()
Definition: ptabasic.c:219
l_float32 * array
l_int32 n
l_atomic refcount
Definition: pix_internal.h:292
l_int32 nalloc
Definition: pix_internal.h:291
l_int32 n
Definition: pix_internal.h:290
l_float32 * y
Definition: pix_internal.h:293
struct Pta ** pta
Definition: pix_internal.h:305
l_int32 n
Definition: pix_internal.h:303
l_int32 nalloc
Definition: pix_internal.h:304
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1358
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1937
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1905
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1262
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:1981
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1864