Leptonica  1.82.0
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 
95 #ifdef HAVE_CONFIG_H
96 #include <config_auto.h>
97 #endif /* HAVE_CONFIG_H */
98 
99 #include <string.h>
100 #include "allheaders.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  PROCNAME("ptaCreate");
125 
126  if (n <= 0 || n > MaxArraySize)
127  n = InitialArraySize;
128 
129  pta = (PTA *)LEPT_CALLOC(1, sizeof(PTA));
130  pta->n = 0;
131  pta->nalloc = n;
132  ptaChangeRefcount(pta, 1); /* sets to 1 */
133  pta->x = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32));
134  pta->y = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32));
135  if (!pta->x || !pta->y) {
136  ptaDestroy(&pta);
137  return (PTA *)ERROR_PTR("x and y arrays not both made", procName, NULL);
138  }
139 
140  return pta;
141 }
142 
143 
151 PTA *
153  NUMA *nay)
154 {
155 l_int32 i, n;
156 l_float32 startx, delx, xval, yval;
157 PTA *pta;
158 
159  PROCNAME("ptaCreateFromNuma");
160 
161  if (!nay)
162  return (PTA *)ERROR_PTR("nay not defined", procName, NULL);
163  n = numaGetCount(nay);
164  if (nax && numaGetCount(nax) != n)
165  return (PTA *)ERROR_PTR("nax and nay sizes differ", procName, NULL);
166 
167  pta = ptaCreate(n);
168  numaGetParameters(nay, &startx, &delx);
169  for (i = 0; i < n; i++) {
170  if (nax)
171  numaGetFValue(nax, i, &xval);
172  else /* use implicit x values from nay */
173  xval = startx + i * delx;
174  numaGetFValue(nay, i, &yval);
175  ptaAddPt(pta, xval, yval);
176  }
177 
178  return pta;
179 }
180 
181 
194 void
196 {
197 PTA *pta;
198 
199  PROCNAME("ptaDestroy");
200 
201  if (ppta == NULL) {
202  L_WARNING("ptr address is NULL!\n", procName);
203  return;
204  }
205 
206  if ((pta = *ppta) == NULL)
207  return;
208 
209  ptaChangeRefcount(pta, -1);
210  if (ptaGetRefcount(pta) <= 0) {
211  LEPT_FREE(pta->x);
212  LEPT_FREE(pta->y);
213  LEPT_FREE(pta);
214  }
215  *ppta = NULL;
216 }
217 
218 
225 PTA *
227 {
228 l_int32 i;
229 l_float32 x, y;
230 PTA *npta;
231 
232  PROCNAME("ptaCopy");
233 
234  if (!pta)
235  return (PTA *)ERROR_PTR("pta not defined", procName, NULL);
236 
237  if ((npta = ptaCreate(pta->nalloc)) == NULL)
238  return (PTA *)ERROR_PTR("npta not made", procName, NULL);
239 
240  for (i = 0; i < pta->n; i++) {
241  ptaGetPt(pta, i, &x, &y);
242  ptaAddPt(npta, x, y);
243  }
244 
245  return npta;
246 }
247 
248 
257 PTA *
259  l_int32 istart,
260  l_int32 iend)
261 {
262 l_int32 n, i, x, y;
263 PTA *ptad;
264 
265  PROCNAME("ptaCopyRange");
266 
267  if (!ptas)
268  return (PTA *)ERROR_PTR("ptas not defined", procName, NULL);
269  n = ptaGetCount(ptas);
270  if (istart < 0)
271  istart = 0;
272  if (istart >= n)
273  return (PTA *)ERROR_PTR("istart out of bounds", procName, NULL);
274  if (iend <= 0 || iend >= n)
275  iend = n - 1;
276  if (istart > iend)
277  return (PTA *)ERROR_PTR("istart > iend; no pts", procName, NULL);
278 
279  if ((ptad = ptaCreate(iend - istart + 1)) == NULL)
280  return (PTA *)ERROR_PTR("ptad not made", procName, NULL);
281  for (i = istart; i <= iend; i++) {
282  ptaGetIPt(ptas, i, &x, &y);
283  ptaAddPt(ptad, x, y);
284  }
285 
286  return ptad;
287 }
288 
289 
296 PTA *
298 {
299  PROCNAME("ptaClone");
300 
301  if (!pta)
302  return (PTA *)ERROR_PTR("pta not defined", procName, NULL);
303 
304  ptaChangeRefcount(pta, 1);
305  return pta;
306 }
307 
308 
320 l_ok
322 {
323  PROCNAME("ptaEmpty");
324 
325  if (!pta)
326  return ERROR_INT("ptad not defined", procName, 1);
327  pta->n = 0;
328  return 0;
329 }
330 
331 
332 /*---------------------------------------------------------------------*
333  * Pta array extension *
334  *---------------------------------------------------------------------*/
342 l_ok
344  l_float32 x,
345  l_float32 y)
346 {
347 l_int32 n;
348 
349  PROCNAME("ptaAddPt");
350 
351  if (!pta)
352  return ERROR_INT("pta not defined", procName, 1);
353 
354  n = pta->n;
355  if (n >= pta->nalloc) {
356  if (ptaExtendArrays(pta))
357  return ERROR_INT("extension failed", procName, 1);
358  }
359 
360  pta->x[n] = x;
361  pta->y[n] = y;
362  pta->n++;
363  return 0;
364 }
365 
366 
379 static l_int32
381 {
382 size_t oldsize, newsize;
383 
384  PROCNAME("ptaExtendArrays");
385 
386  if (!pta)
387  return ERROR_INT("pta not defined", procName, 1);
388  if (pta->nalloc > MaxArraySize)
389  return ERROR_INT("pta at maximum size; can't extend", procName, 1);
390  oldsize = 4 * pta->nalloc;
391  if (pta->nalloc > MaxArraySize / 2) {
392  newsize = 4 * MaxArraySize;
393  pta->nalloc = MaxArraySize;
394  } else {
395  newsize = 2 * oldsize;
396  pta->nalloc *= 2;
397  }
398  if ((pta->x = (l_float32 *)reallocNew((void **)&pta->x,
399  oldsize, newsize)) == NULL)
400  return ERROR_INT("new x array not returned", procName, 1);
401  if ((pta->y = (l_float32 *)reallocNew((void **)&pta->y,
402  oldsize, newsize)) == NULL)
403  return ERROR_INT("new y array not returned", procName, 1);
404 
405  return 0;
406 }
407 
408 
409 /*---------------------------------------------------------------------*
410  * Pta insertion and removal *
411  *---------------------------------------------------------------------*/
420 l_ok
422  l_int32 index,
423  l_int32 x,
424  l_int32 y)
425 {
426 l_int32 i, n;
427 
428  PROCNAME("ptaInsertPt");
429 
430  if (!pta)
431  return ERROR_INT("pta not defined", procName, 1);
432  n = ptaGetCount(pta);
433  if (index < 0 || index > n) {
434  L_ERROR("index %d not in [0,...,%d]\n", procName, index, n);
435  return 1;
436  }
437 
438  if (n > pta->nalloc) {
439  if (ptaExtendArrays(pta))
440  return ERROR_INT("extension failed", procName, 1);
441  }
442  pta->n++;
443  for (i = n; i > index; i--) {
444  pta->x[i] = pta->x[i - 1];
445  pta->y[i] = pta->y[i - 1];
446  }
447  pta->x[index] = x;
448  pta->y[index] = y;
449  return 0;
450 }
451 
452 
467 l_ok
469  l_int32 index)
470 {
471 l_int32 i, n;
472 
473  PROCNAME("ptaRemovePt");
474 
475  if (!pta)
476  return ERROR_INT("pta not defined", procName, 1);
477  n = ptaGetCount(pta);
478  if (index < 0 || index >= n) {
479  L_ERROR("index %d not in [0,...,%d]\n", procName, index, n - 1);
480  return 1;
481  }
482 
483  /* Remove the point */
484  for (i = index + 1; i < n; i++) {
485  pta->x[i - 1] = pta->x[i];
486  pta->y[i - 1] = pta->y[i];
487  }
488  pta->n--;
489  return 0;
490 }
491 
492 
493 /*---------------------------------------------------------------------*
494  * Pta accessors *
495  *---------------------------------------------------------------------*/
496 l_int32
497 ptaGetRefcount(PTA *pta)
498 {
499  PROCNAME("ptaGetRefcount");
500 
501  if (!pta)
502  return ERROR_INT("pta not defined", procName, 1);
503  return pta->refcount;
504 }
505 
506 
507 l_int32
508 ptaChangeRefcount(PTA *pta,
509  l_int32 delta)
510 {
511  PROCNAME("ptaChangeRefcount");
512 
513  if (!pta)
514  return ERROR_INT("pta not defined", procName, 1);
515  pta->refcount += delta;
516  return 0;
517 }
518 
519 
526 l_int32
528 {
529  PROCNAME("ptaGetCount");
530 
531  if (!pta)
532  return ERROR_INT("pta not defined", procName, 0);
533 
534  return pta->n;
535 }
536 
537 
547 l_ok
549  l_int32 index,
550  l_float32 *px,
551  l_float32 *py)
552 {
553  PROCNAME("ptaGetPt");
554 
555  if (px) *px = 0;
556  if (py) *py = 0;
557  if (!pta)
558  return ERROR_INT("pta not defined", procName, 1);
559  if (index < 0 || index >= pta->n)
560  return ERROR_INT("invalid index", procName, 1);
561 
562  if (px) *px = pta->x[index];
563  if (py) *py = pta->y[index];
564  return 0;
565 }
566 
567 
577 l_ok
579  l_int32 index,
580  l_int32 *px,
581  l_int32 *py)
582 {
583  PROCNAME("ptaGetIPt");
584 
585  if (px) *px = 0;
586  if (py) *py = 0;
587  if (!pta)
588  return ERROR_INT("pta not defined", procName, 1);
589  if (index < 0 || index >= pta->n)
590  return ERROR_INT("invalid index", procName, 1);
591 
592  if (px) *px = (l_int32)(pta->x[index] + 0.5);
593  if (py) *py = (l_int32)(pta->y[index] + 0.5);
594  return 0;
595 }
596 
597 
606 l_ok
608  l_int32 index,
609  l_float32 x,
610  l_float32 y)
611 {
612  PROCNAME("ptaSetPt");
613 
614  if (!pta)
615  return ERROR_INT("pta not defined", procName, 1);
616  if (index < 0 || index >= pta->n)
617  return ERROR_INT("invalid index", procName, 1);
618 
619  pta->x[index] = x;
620  pta->y[index] = y;
621  return 0;
622 }
623 
624 
638 l_ok
640  NUMA **pnax,
641  NUMA **pnay)
642 {
643 l_int32 i, n;
644 NUMA *nax, *nay;
645 
646  PROCNAME("ptaGetArrays");
647 
648  if (!pnax && !pnay)
649  return ERROR_INT("no output requested", procName, 1);
650  if (pnax) *pnax = NULL;
651  if (pnay) *pnay = NULL;
652  if (!pta)
653  return ERROR_INT("pta not defined", procName, 1);
654  if ((n = ptaGetCount(pta)) == 0)
655  return ERROR_INT("pta is empty", procName, 1);
656 
657  if (pnax) {
658  if ((nax = numaCreate(n)) == NULL)
659  return ERROR_INT("nax not made", procName, 1);
660  *pnax = nax;
661  for (i = 0; i < n; i++)
662  nax->array[i] = pta->x[i];
663  nax->n = n;
664  }
665  if (pnay) {
666  if ((nay = numaCreate(n)) == NULL)
667  return ERROR_INT("nay not made", procName, 1);
668  *pnay = nay;
669  for (i = 0; i < n; i++)
670  nay->array[i] = pta->y[i];
671  nay->n = n;
672  }
673  return 0;
674 }
675 
676 
677 /*---------------------------------------------------------------------*
678  * Pta serialized for I/O *
679  *---------------------------------------------------------------------*/
686 PTA *
687 ptaRead(const char *filename)
688 {
689 FILE *fp;
690 PTA *pta;
691 
692  PROCNAME("ptaRead");
693 
694  if (!filename)
695  return (PTA *)ERROR_PTR("filename not defined", procName, NULL);
696 
697  if ((fp = fopenReadStream(filename)) == NULL)
698  return (PTA *)ERROR_PTR("stream not opened", procName, NULL);
699  pta = ptaReadStream(fp);
700  fclose(fp);
701  if (!pta)
702  return (PTA *)ERROR_PTR("pta not read", procName, NULL);
703  return pta;
704 }
705 
706 
719 PTA *
720 ptaReadStream(FILE *fp)
721 {
722 char typestr[128]; /* hardcoded below in fscanf */
723 l_int32 i, n, ix, iy, type, version;
724 l_float32 x, y;
725 PTA *pta;
726 
727  PROCNAME("ptaReadStream");
728 
729  if (!fp)
730  return (PTA *)ERROR_PTR("stream not defined", procName, NULL);
731 
732  if (fscanf(fp, "\n Pta Version %d\n", &version) != 1)
733  return (PTA *)ERROR_PTR("not a pta file", procName, NULL);
734  if (version != PTA_VERSION_NUMBER)
735  return (PTA *)ERROR_PTR("invalid pta version", procName, NULL);
736  if (fscanf(fp, " Number of pts = %d; format = %127s\n", &n, typestr) != 2)
737  return (PTA *)ERROR_PTR("not a pta file", procName, NULL);
738  if (n < 0)
739  return (PTA *)ERROR_PTR("num pts <= 0", procName, NULL);
740  if (n > MaxArraySize)
741  return (PTA *)ERROR_PTR("too many pts", procName, NULL);
742  if (n == 0) L_INFO("the pta is empty\n", procName);
743 
744  if (!strcmp(typestr, "float"))
745  type = 0;
746  else /* typestr is "integer" */
747  type = 1;
748  if ((pta = ptaCreate(n)) == NULL)
749  return (PTA *)ERROR_PTR("pta not made", procName, NULL);
750  for (i = 0; i < n; i++) {
751  if (type == 0) { /* data is float */
752  if (fscanf(fp, " (%f, %f)\n", &x, &y) != 2) {
753  ptaDestroy(&pta);
754  return (PTA *)ERROR_PTR("error reading floats", procName, NULL);
755  }
756  ptaAddPt(pta, x, y);
757  } else { /* data is integer */
758  if (fscanf(fp, " (%d, %d)\n", &ix, &iy) != 2) {
759  ptaDestroy(&pta);
760  return (PTA *)ERROR_PTR("error reading ints", procName, NULL);
761  }
762  ptaAddPt(pta, ix, iy);
763  }
764  }
765 
766  return pta;
767 }
768 
769 
777 PTA *
778 ptaReadMem(const l_uint8 *data,
779  size_t size)
780 {
781 FILE *fp;
782 PTA *pta;
783 
784  PROCNAME("ptaReadMem");
785 
786  if (!data)
787  return (PTA *)ERROR_PTR("data not defined", procName, NULL);
788  if ((fp = fopenReadFromMemory(data, size)) == NULL)
789  return (PTA *)ERROR_PTR("stream not opened", procName, NULL);
790 
791  pta = ptaReadStream(fp);
792  fclose(fp);
793  if (!pta) L_ERROR("pta not read\n", procName);
794  return pta;
795 }
796 
797 
815 l_ok
816 ptaWriteDebug(const char *filename,
817  PTA *pta,
818  l_int32 type)
819 {
820  PROCNAME("ptaWriteDebug");
821 
822  if (LeptDebugOK) {
823  return ptaWrite(filename, pta, type);
824  } else {
825  L_INFO("write to named temp file %s is disabled\n", procName, filename);
826  return 0;
827  }
828 }
829 
830 
839 l_ok
840 ptaWrite(const char *filename,
841  PTA *pta,
842  l_int32 type)
843 {
844 l_int32 ret;
845 FILE *fp;
846 
847  PROCNAME("ptaWrite");
848 
849  if (!filename)
850  return ERROR_INT("filename not defined", procName, 1);
851  if (!pta)
852  return ERROR_INT("pta not defined", procName, 1);
853 
854  if ((fp = fopenWriteStream(filename, "w")) == NULL)
855  return ERROR_INT("stream not opened", procName, 1);
856  ret = ptaWriteStream(fp, pta, type);
857  fclose(fp);
858  if (ret)
859  return ERROR_INT("pta not written to stream", procName, 1);
860  return 0;
861 }
862 
863 
872 l_ok
873 ptaWriteStream(FILE *fp,
874  PTA *pta,
875  l_int32 type)
876 {
877 l_int32 i, n, ix, iy;
878 l_float32 x, y;
879 
880  PROCNAME("ptaWriteStream");
881 
882  if (!fp)
883  return ERROR_INT("stream not defined", procName, 1);
884  if (!pta)
885  return ERROR_INT("pta not defined", procName, 1);
886 
887  n = ptaGetCount(pta);
888  fprintf(fp, "\n Pta Version %d\n", PTA_VERSION_NUMBER);
889  if (type == 0)
890  fprintf(fp, " Number of pts = %d; format = float\n", n);
891  else /* type == 1 */
892  fprintf(fp, " Number of pts = %d; format = integer\n", n);
893  for (i = 0; i < n; i++) {
894  if (type == 0) { /* data is float */
895  ptaGetPt(pta, i, &x, &y);
896  fprintf(fp, " (%f, %f)\n", x, y);
897  } else { /* data is integer */
898  ptaGetIPt(pta, i, &ix, &iy);
899  fprintf(fp, " (%d, %d)\n", ix, iy);
900  }
901  }
902 
903  return 0;
904 }
905 
906 
921 l_ok
922 ptaWriteMem(l_uint8 **pdata,
923  size_t *psize,
924  PTA *pta,
925  l_int32 type)
926 {
927 l_int32 ret;
928 FILE *fp;
929 
930  PROCNAME("ptaWriteMem");
931 
932  if (pdata) *pdata = NULL;
933  if (psize) *psize = 0;
934  if (!pdata)
935  return ERROR_INT("&data not defined", procName, 1);
936  if (!psize)
937  return ERROR_INT("&size not defined", procName, 1);
938  if (!pta)
939  return ERROR_INT("pta not defined", procName, 1);
940 
941 #if HAVE_FMEMOPEN
942  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
943  return ERROR_INT("stream not opened", procName, 1);
944  ret = ptaWriteStream(fp, pta, type);
945  fputc('\0', fp);
946  fclose(fp);
947  *psize = *psize - 1;
948 #else
949  L_INFO("work-around: writing to a temp file\n", procName);
950  #ifdef _WIN32
951  if ((fp = fopenWriteWinTempfile()) == NULL)
952  return ERROR_INT("tmpfile stream not opened", procName, 1);
953  #else
954  if ((fp = tmpfile()) == NULL)
955  return ERROR_INT("tmpfile stream not opened", procName, 1);
956  #endif /* _WIN32 */
957  ret = ptaWriteStream(fp, pta, type);
958  rewind(fp);
959  *pdata = l_binaryReadStream(fp, psize);
960  fclose(fp);
961 #endif /* HAVE_FMEMOPEN */
962  return ret;
963 }
964 
965 
966 /*---------------------------------------------------------------------*
967  * PTAA creation, destruction *
968  *---------------------------------------------------------------------*/
975 PTAA *
976 ptaaCreate(l_int32 n)
977 {
978 PTAA *ptaa;
979 
980  PROCNAME("ptaaCreate");
981 
982  if (n <= 0 || n > MaxPtrArraySize)
983  n = InitialArraySize;
984 
985  ptaa = (PTAA *)LEPT_CALLOC(1, sizeof(PTAA));
986  ptaa->n = 0;
987  ptaa->nalloc = n;
988  if ((ptaa->pta = (PTA **)LEPT_CALLOC(n, sizeof(PTA *))) == NULL) {
989  ptaaDestroy(&ptaa);
990  return (PTAA *)ERROR_PTR("pta ptrs not made", procName, NULL);
991  }
992  return ptaa;
993 }
994 
995 
1002 void
1004 {
1005 l_int32 i;
1006 PTAA *ptaa;
1007 
1008  PROCNAME("ptaaDestroy");
1009 
1010  if (pptaa == NULL) {
1011  L_WARNING("ptr address is NULL!\n", procName);
1012  return;
1013  }
1014 
1015  if ((ptaa = *pptaa) == NULL)
1016  return;
1017 
1018  for (i = 0; i < ptaa->n; i++)
1019  ptaDestroy(&ptaa->pta[i]);
1020  LEPT_FREE(ptaa->pta);
1021  LEPT_FREE(ptaa);
1022  *pptaa = NULL;
1023 }
1024 
1025 
1026 /*---------------------------------------------------------------------*
1027  * PTAA array extension *
1028  *---------------------------------------------------------------------*/
1037 l_ok
1039  PTA *pta,
1040  l_int32 copyflag)
1041 {
1042 l_int32 n;
1043 PTA *ptac;
1044 
1045  PROCNAME("ptaaAddPta");
1046 
1047  if (!ptaa)
1048  return ERROR_INT("ptaa not defined", procName, 1);
1049  if (!pta)
1050  return ERROR_INT("pta not defined", procName, 1);
1051 
1052  if (copyflag == L_INSERT) {
1053  ptac = pta;
1054  } else if (copyflag == L_COPY) {
1055  if ((ptac = ptaCopy(pta)) == NULL)
1056  return ERROR_INT("ptac not made", procName, 1);
1057  } else if (copyflag == L_CLONE) {
1058  if ((ptac = ptaClone(pta)) == NULL)
1059  return ERROR_INT("pta clone not made", procName, 1);
1060  } else {
1061  return ERROR_INT("invalid copyflag", procName, 1);
1062  }
1063 
1064  n = ptaaGetCount(ptaa);
1065  if (n >= ptaa->nalloc) {
1066  if (ptaaExtendArray(ptaa)) {
1067  if (copyflag != L_INSERT)
1068  ptaDestroy(&ptac);
1069  return ERROR_INT("extension failed", procName, 1);
1070  }
1071  }
1072 
1073  ptaa->pta[n] = ptac;
1074  ptaa->n++;
1075  return 0;
1076 }
1077 
1078 
1092 static l_int32
1094 {
1095 size_t oldsize, newsize;
1096 
1097  PROCNAME("ptaaExtendArray");
1098 
1099  if (!ptaa)
1100  return ERROR_INT("ptaa not defined", procName, 1);
1101  oldsize = ptaa->nalloc * sizeof(PTA *);
1102  newsize = 2 * oldsize;
1103  if (newsize > 8 * MaxPtrArraySize)
1104  return ERROR_INT("newsize > 80 MB; too large", procName, 1);
1105 
1106  if ((ptaa->pta = (PTA **)reallocNew((void **)&ptaa->pta,
1107  oldsize, newsize)) == NULL)
1108  return ERROR_INT("new ptr array not returned", procName, 1);
1109 
1110  ptaa->nalloc *= 2;
1111  return 0;
1112 }
1113 
1114 
1115 /*---------------------------------------------------------------------*
1116  * Ptaa accessors *
1117  *---------------------------------------------------------------------*/
1124 l_int32
1126 {
1127  PROCNAME("ptaaGetCount");
1128 
1129  if (!ptaa)
1130  return ERROR_INT("ptaa not defined", procName, 0);
1131 
1132  return ptaa->n;
1133 }
1134 
1135 
1144 PTA *
1146  l_int32 index,
1147  l_int32 accessflag)
1148 {
1149  PROCNAME("ptaaGetPta");
1150 
1151  if (!ptaa)
1152  return (PTA *)ERROR_PTR("ptaa not defined", procName, NULL);
1153  if (index < 0 || index >= ptaa->n)
1154  return (PTA *)ERROR_PTR("index not valid", procName, NULL);
1155 
1156  if (accessflag == L_COPY)
1157  return ptaCopy(ptaa->pta[index]);
1158  else if (accessflag == L_CLONE)
1159  return ptaClone(ptaa->pta[index]);
1160  else
1161  return (PTA *)ERROR_PTR("invalid accessflag", procName, NULL);
1162 }
1163 
1164 
1175 l_ok
1177  l_int32 ipta,
1178  l_int32 jpt,
1179  l_float32 *px,
1180  l_float32 *py)
1181 {
1182 PTA *pta;
1183 
1184  PROCNAME("ptaaGetPt");
1185 
1186  if (px) *px = 0;
1187  if (py) *py = 0;
1188  if (!ptaa)
1189  return ERROR_INT("ptaa not defined", procName, 1);
1190  if (ipta < 0 || ipta >= ptaa->n)
1191  return ERROR_INT("index ipta not valid", procName, 1);
1192 
1193  pta = ptaaGetPta(ptaa, ipta, L_CLONE);
1194  if (jpt < 0 || jpt >= pta->n) {
1195  ptaDestroy(&pta);
1196  return ERROR_INT("index jpt not valid", procName, 1);
1197  }
1198 
1199  ptaGetPt(pta, jpt, px, py);
1200  ptaDestroy(&pta);
1201  return 0;
1202 }
1203 
1204 
1205 /*---------------------------------------------------------------------*
1206  * Ptaa array modifiers *
1207  *---------------------------------------------------------------------*/
1215 l_ok
1217  PTA *pta)
1218 {
1219 l_int32 n, i;
1220 PTA *ptat;
1221 
1222  PROCNAME("ptaaInitFull");
1223 
1224  if (!ptaa)
1225  return ERROR_INT("ptaa not defined", procName, 1);
1226  if (!pta)
1227  return ERROR_INT("pta not defined", procName, 1);
1228 
1229  n = ptaa->nalloc;
1230  ptaa->n = n;
1231  for (i = 0; i < n; i++) {
1232  ptat = ptaCopy(pta);
1233  ptaaReplacePta(ptaa, i, ptat);
1234  }
1235  return 0;
1236 }
1237 
1238 
1254 l_ok
1256  l_int32 index,
1257  PTA *pta)
1258 {
1259 l_int32 n;
1260 
1261  PROCNAME("ptaaReplacePta");
1262 
1263  if (!ptaa)
1264  return ERROR_INT("ptaa not defined", procName, 1);
1265  if (!pta)
1266  return ERROR_INT("pta not defined", procName, 1);
1267  n = ptaaGetCount(ptaa);
1268  if (index < 0 || index >= n)
1269  return ERROR_INT("index not valid", procName, 1);
1270 
1271  ptaDestroy(&ptaa->pta[index]);
1272  ptaa->pta[index] = pta;
1273  return 0;
1274 }
1275 
1276 
1285 l_ok
1287  l_int32 ipta,
1288  l_float32 x,
1289  l_float32 y)
1290 {
1291 PTA *pta;
1292 
1293  PROCNAME("ptaaAddPt");
1294 
1295  if (!ptaa)
1296  return ERROR_INT("ptaa not defined", procName, 1);
1297  if (ipta < 0 || ipta >= ptaa->n)
1298  return ERROR_INT("index ipta not valid", procName, 1);
1299 
1300  pta = ptaaGetPta(ptaa, ipta, L_CLONE);
1301  ptaAddPt(pta, x, y);
1302  ptaDestroy(&pta);
1303  return 0;
1304 }
1305 
1306 
1320 l_ok
1322 {
1323 l_int32 i, n, np;
1324 PTA *pta;
1325 
1326  PROCNAME("ptaaTruncate");
1327 
1328  if (!ptaa)
1329  return ERROR_INT("ptaa not defined", procName, 1);
1330 
1331  n = ptaaGetCount(ptaa);
1332  for (i = n - 1; i >= 0; i--) {
1333  pta = ptaaGetPta(ptaa, i, L_CLONE);
1334  if (!pta) {
1335  ptaa->n--;
1336  continue;
1337  }
1338  np = ptaGetCount(pta);
1339  ptaDestroy(&pta);
1340  if (np == 0) {
1341  ptaDestroy(&ptaa->pta[i]);
1342  ptaa->n--;
1343  } else {
1344  break;
1345  }
1346  }
1347  return 0;
1348 }
1349 
1350 
1351 /*---------------------------------------------------------------------*
1352  * Ptaa serialized for I/O *
1353  *---------------------------------------------------------------------*/
1360 PTAA *
1361 ptaaRead(const char *filename)
1362 {
1363 FILE *fp;
1364 PTAA *ptaa;
1365 
1366  PROCNAME("ptaaRead");
1367 
1368  if (!filename)
1369  return (PTAA *)ERROR_PTR("filename not defined", procName, NULL);
1370 
1371  if ((fp = fopenReadStream(filename)) == NULL)
1372  return (PTAA *)ERROR_PTR("stream not opened", procName, NULL);
1373  ptaa = ptaaReadStream(fp);
1374  fclose(fp);
1375  if (!ptaa)
1376  return (PTAA *)ERROR_PTR("ptaa not read", procName, NULL);
1377  return ptaa;
1378 }
1379 
1380 
1392 PTAA *
1394 {
1395 l_int32 i, n, version;
1396 PTA *pta;
1397 PTAA *ptaa;
1398 
1399  PROCNAME("ptaaReadStream");
1400 
1401  if (!fp)
1402  return (PTAA *)ERROR_PTR("stream not defined", procName, NULL);
1403 
1404  if (fscanf(fp, "\nPtaa Version %d\n", &version) != 1)
1405  return (PTAA *)ERROR_PTR("not a ptaa file", procName, NULL);
1406  if (version != PTA_VERSION_NUMBER)
1407  return (PTAA *)ERROR_PTR("invalid ptaa version", procName, NULL);
1408  if (fscanf(fp, "Number of Pta = %d\n", &n) != 1)
1409  return (PTAA *)ERROR_PTR("not a ptaa file", procName, NULL);
1410  if (n < 0)
1411  return (PTAA *)ERROR_PTR("num pta ptrs <= 0", procName, NULL);
1412  if (n > MaxPtrArraySize)
1413  return (PTAA *)ERROR_PTR("too many pta ptrs", procName, NULL);
1414  if (n == 0) L_INFO("the ptaa is empty\n", procName);
1415 
1416  if ((ptaa = ptaaCreate(n)) == NULL)
1417  return (PTAA *)ERROR_PTR("ptaa not made", procName, NULL);
1418  for (i = 0; i < n; i++) {
1419  if ((pta = ptaReadStream(fp)) == NULL) {
1420  ptaaDestroy(&ptaa);
1421  return (PTAA *)ERROR_PTR("error reading pta", procName, NULL);
1422  }
1423  ptaaAddPta(ptaa, pta, L_INSERT);
1424  }
1425 
1426  return ptaa;
1427 }
1428 
1429 
1437 PTAA *
1438 ptaaReadMem(const l_uint8 *data,
1439  size_t size)
1440 {
1441 FILE *fp;
1442 PTAA *ptaa;
1443 
1444  PROCNAME("ptaaReadMem");
1445 
1446  if (!data)
1447  return (PTAA *)ERROR_PTR("data not defined", procName, NULL);
1448  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1449  return (PTAA *)ERROR_PTR("stream not opened", procName, NULL);
1450 
1451  ptaa = ptaaReadStream(fp);
1452  fclose(fp);
1453  if (!ptaa) L_ERROR("ptaa not read\n", procName);
1454  return ptaa;
1455 }
1456 
1457 
1475 l_ok
1476 ptaaWriteDebug(const char *filename,
1477  PTAA *ptaa,
1478  l_int32 type)
1479 {
1480  PROCNAME("ptaaWriteDebug");
1481 
1482  if (LeptDebugOK) {
1483  return ptaaWrite(filename, ptaa, type);
1484  } else {
1485  L_INFO("write to named temp file %s is disabled\n", procName, filename);
1486  return 0;
1487  }
1488 }
1489 
1490 
1499 l_ok
1500 ptaaWrite(const char *filename,
1501  PTAA *ptaa,
1502  l_int32 type)
1503 {
1504 l_int32 ret;
1505 FILE *fp;
1506 
1507  PROCNAME("ptaaWrite");
1508 
1509  if (!filename)
1510  return ERROR_INT("filename not defined", procName, 1);
1511  if (!ptaa)
1512  return ERROR_INT("ptaa not defined", procName, 1);
1513 
1514  if ((fp = fopenWriteStream(filename, "w")) == NULL)
1515  return ERROR_INT("stream not opened", procName, 1);
1516  ret = ptaaWriteStream(fp, ptaa, type);
1517  fclose(fp);
1518  if (ret)
1519  return ERROR_INT("ptaa not written to stream", procName, 1);
1520  return 0;
1521 }
1522 
1523 
1532 l_ok
1534  PTAA *ptaa,
1535  l_int32 type)
1536 {
1537 l_int32 i, n;
1538 PTA *pta;
1539 
1540  PROCNAME("ptaaWriteStream");
1541 
1542  if (!fp)
1543  return ERROR_INT("stream not defined", procName, 1);
1544  if (!ptaa)
1545  return ERROR_INT("ptaa not defined", procName, 1);
1546 
1547  n = ptaaGetCount(ptaa);
1548  fprintf(fp, "\nPtaa Version %d\n", PTA_VERSION_NUMBER);
1549  fprintf(fp, "Number of Pta = %d\n", n);
1550  for (i = 0; i < n; i++) {
1551  pta = ptaaGetPta(ptaa, i, L_CLONE);
1552  ptaWriteStream(fp, pta, type);
1553  ptaDestroy(&pta);
1554  }
1555 
1556  return 0;
1557 }
1558 
1559 
1574 l_ok
1575 ptaaWriteMem(l_uint8 **pdata,
1576  size_t *psize,
1577  PTAA *ptaa,
1578  l_int32 type)
1579 {
1580 l_int32 ret;
1581 FILE *fp;
1582 
1583  PROCNAME("ptaaWriteMem");
1584 
1585  if (pdata) *pdata = NULL;
1586  if (psize) *psize = 0;
1587  if (!pdata)
1588  return ERROR_INT("&data not defined", procName, 1);
1589  if (!psize)
1590  return ERROR_INT("&size not defined", procName, 1);
1591  if (!ptaa)
1592  return ERROR_INT("ptaa not defined", procName, 1);
1593 
1594 #if HAVE_FMEMOPEN
1595  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1596  return ERROR_INT("stream not opened", procName, 1);
1597  ret = ptaaWriteStream(fp, ptaa, type);
1598  fputc('\0', fp);
1599  fclose(fp);
1600  *psize = *psize - 1;
1601 #else
1602  L_INFO("work-around: writing to a temp file\n", procName);
1603  #ifdef _WIN32
1604  if ((fp = fopenWriteWinTempfile()) == NULL)
1605  return ERROR_INT("tmpfile stream not opened", procName, 1);
1606  #else
1607  if ((fp = tmpfile()) == NULL)
1608  return ERROR_INT("tmpfile stream not opened", procName, 1);
1609  #endif /* _WIN32 */
1610  ret = ptaaWriteStream(fp, ptaa, type);
1611  rewind(fp);
1612  *pdata = l_binaryReadStream(fp, psize);
1613  fclose(fp);
1614 #endif /* HAVE_FMEMOPEN */
1615  return ret;
1616 }
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
l_ok ptaaGetPt(PTAA *ptaa, l_int32 ipta, l_int32 jpt, l_float32 *px, l_float32 *py)
ptaaGetPt()
Definition: ptabasic.c:1176
PTA * ptaCopyRange(PTA *ptas, l_int32 istart, l_int32 iend)
ptaCopyRange()
Definition: ptabasic.c:258
l_ok ptaaAddPt(PTAA *ptaa, l_int32 ipta, l_float32 x, l_float32 y)
ptaaAddPt()
Definition: ptabasic.c:1286
l_ok ptaWriteStream(FILE *fp, PTA *pta, l_int32 type)
ptaWriteStream()
Definition: ptabasic.c:873
l_ok ptaInsertPt(PTA *pta, l_int32 index, l_int32 x, l_int32 y)
ptaInsertPt()
Definition: ptabasic.c:421
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
Definition: pix.h:713
PTA * ptaReadMem(const l_uint8 *data, size_t size)
ptaReadMem()
Definition: ptabasic.c:778
#define PTA_VERSION_NUMBER
Definition: pix.h:513
Definition: pix.h:712
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
static l_int32 ptaaExtendArray(PTAA *ptaa)
ptaaExtendArray()
Definition: ptabasic.c:1093
l_ok ptaaTruncate(PTAA *ptaa)
ptaaTruncate()
Definition: ptabasic.c:1321
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:2009
l_ok ptaGetArrays(PTA *pta, NUMA **pnax, NUMA **pnay)
ptaGetArrays()
Definition: ptabasic.c:639
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition: ptabasic.c:527
static const l_int32 InitialArraySize
Definition: ptabasic.c:104
PTA * ptaRead(const char *filename)
ptaRead()
Definition: ptabasic.c:687
PTA * ptaaGetPta(PTAA *ptaa, l_int32 index, l_int32 accessflag)
ptaaGetPta()
Definition: ptabasic.c:1145
Definition: array.h:70
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_int32 nalloc
Definition: pix.h:533
PTA * ptaClone(PTA *pta)
ptaClone()
Definition: ptabasic.c:297
l_ok ptaaWriteStream(FILE *fp, PTAA *ptaa, l_int32 type)
ptaaWriteStream()
Definition: ptabasic.c:1533
Definition: pix.h:530
void ptaaDestroy(PTAA **pptaa)
ptaaDestroy()
Definition: ptabasic.c:1003
l_float32 * array
Definition: array.h:77
l_ok ptaGetPt(PTA *pta, l_int32 index, l_float32 *px, l_float32 *py)
ptaGetPt()
Definition: ptabasic.c:548
PTA * ptaCreateFromNuma(NUMA *nax, NUMA *nay)
ptaCreateFromNuma()
Definition: ptabasic.c:152
l_ok ptaaInitFull(PTAA *ptaa, PTA *pta)
ptaaInitFull()
Definition: ptabasic.c:1216
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1302
l_ok ptaaReplacePta(PTAA *ptaa, l_int32 index, PTA *pta)
ptaaReplacePta()
Definition: ptabasic.c:1255
l_ok numaGetParameters(NUMA *na, l_float32 *pstartx, l_float32 *pdelx)
numaGetParameters()
Definition: numabasic.c:963
l_ok ptaRemovePt(PTA *pta, l_int32 index)
ptaRemovePt()
Definition: ptabasic.c:468
Definition: pix.h:711
PTA * ptaCopy(PTA *pta)
ptaCopy()
Definition: ptabasic.c:226
static l_int32 ptaExtendArrays(PTA *pta)
ptaExtendArrays()
Definition: ptabasic.c:380
l_ok ptaSetPt(PTA *pta, l_int32 index, l_float32 x, l_float32 y)
ptaSetPt()
Definition: ptabasic.c:607
l_float32 * y
Definition: pix.h:521
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:2055
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402
l_int32 ptaaGetCount(PTAA *ptaa)
ptaaGetCount()
Definition: ptabasic.c:1125
l_ok ptaEmpty(PTA *pta)
ptaEmpty()
Definition: ptabasic.c:321
l_ok ptaWrite(const char *filename, PTA *pta, l_int32 type)
ptaWrite()
Definition: ptabasic.c:840
l_int32 n
Definition: array.h:73
l_ok ptaWriteDebug(const char *filename, PTA *pta, l_int32 type)
ptaWriteDebug()
Definition: ptabasic.c:816
l_ok ptaaWriteMem(l_uint8 **pdata, size_t *psize, PTAA *ptaa, l_int32 type)
ptaaWriteMem()
Definition: ptabasic.c:1575
l_ok ptaaWrite(const char *filename, PTAA *ptaa, l_int32 type)
ptaaWrite()
Definition: ptabasic.c:1500
l_int32 nalloc
Definition: pix.h:519
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
PTAA * ptaaReadStream(FILE *fp)
ptaaReadStream()
Definition: ptabasic.c:1393
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
l_ok ptaWriteMem(l_uint8 **pdata, size_t *psize, PTA *pta, l_int32 type)
ptaWriteMem()
Definition: ptabasic.c:922
PTAA * ptaaReadMem(const l_uint8 *data, size_t size)
ptaaReadMem()
Definition: ptabasic.c:1438
PTAA * ptaaCreate(l_int32 n)
ptaaCreate()
Definition: ptabasic.c:976
l_int32 n
Definition: pix.h:518
PTA * ptaReadStream(FILE *fp)
ptaReadStream()
Definition: ptabasic.c:720
Definition: pix.h:516
l_uint32 refcount
Definition: pix.h:520
l_int32 n
Definition: pix.h:532
l_ok ptaaWriteDebug(const char *filename, PTAA *ptaa, l_int32 type)
ptaaWriteDebug()
Definition: ptabasic.c:1476
PTAA * ptaaRead(const char *filename)
ptaaRead()
Definition: ptabasic.c:1361
struct Pta ** pta
Definition: pix.h:534