Leptonica 1.83.1
Image processing and image analysis suite
Loading...
Searching...
No Matches
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
92
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
102static const l_uint32 MaxArraySize = 100000000; /* 100 million */
103static const l_uint32 MaxPtrArraySize = 10000000; /* 10 million */
104static const l_int32 InitialArraySize = 50;
105
106 /* Static functions */
107static l_int32 ptaExtendArrays(PTA *pta);
108static l_int32 ptaaExtendArray(PTAA *ptaa);
109
110/*---------------------------------------------------------------------*
111 * Pta creation, destruction, copy, clone *
112 *---------------------------------------------------------------------*/
119PTA *
120ptaCreate(l_int32 n)
121{
122PTA *pta;
123
124 if (n <= 0 || n > MaxArraySize)
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
149PTA *
151 NUMA *nay)
152{
153l_int32 i, n;
154l_float32 startx, delx, xval, yval;
155PTA *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
190void
192{
193PTA *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
218PTA *
220{
221l_int32 i;
222l_float32 x, y;
223PTA *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
248PTA *
250 l_int32 istart,
251 l_int32 iend)
252{
253l_int32 n, i, x, y;
254PTA *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
285PTA *
287{
288 if (!pta)
289 return (PTA *)ERROR_PTR("pta not defined", __func__, NULL);
290
291 ++pta->refcount;
292 return pta;
293}
294
295
307l_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 *---------------------------------------------------------------------*/
327l_ok
329 l_float32 x,
330 l_float32 y)
331{
332l_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
362static l_int32
364{
365size_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 *---------------------------------------------------------------------*/
401l_ok
403 l_int32 index,
404 l_int32 x,
405 l_int32 y)
406{
407l_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
446l_ok
448 l_int32 index)
449{
450l_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 *---------------------------------------------------------------------*/
479l_int32
481{
482 if (!pta)
483 return ERROR_INT("pta not defined", __func__, 0);
484
485 return pta->n;
486}
487
488
498l_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
526l_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
553l_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
583l_ok
585 NUMA **pnax,
586 NUMA **pnay)
587{
588l_int32 i, n;
589NUMA *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 *---------------------------------------------------------------------*/
629PTA *
630ptaRead(const char *filename)
631{
632FILE *fp;
633PTA *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
660PTA *
662{
663char typestr[128]; /* hardcoded below in fscanf */
664l_int32 i, n, ix, iy, type, version;
665l_float32 x, y;
666PTA *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
716PTA *
717ptaReadMem(const l_uint8 *data,
718 size_t size)
719{
720FILE *fp;
721PTA *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
752l_ok
753ptaWriteDebug(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
774l_ok
775ptaWrite(const char *filename,
776 PTA *pta,
777 l_int32 type)
778{
779l_int32 ret;
780FILE *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
805l_ok
807 PTA *pta,
808 l_int32 type)
809{
810l_int32 i, n, ix, iy;
811l_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
852l_ok
853ptaWriteMem(l_uint8 **pdata,
854 size_t *psize,
855 PTA *pta,
856 l_int32 type)
857{
858l_int32 ret;
859FILE *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 *---------------------------------------------------------------------*/
904PTAA *
905ptaaCreate(l_int32 n)
906{
907PTAA *ptaa;
908
909 if (n <= 0 || n > MaxPtrArraySize)
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
929void
931{
932l_int32 i;
933PTAA *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 *---------------------------------------------------------------------*/
962l_ok
964 PTA *pta,
965 l_int32 copyflag)
966{
967l_int32 n;
968PTA *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
1015static l_int32
1017{
1018size_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 *---------------------------------------------------------------------*/
1045l_int32
1047{
1048 if (!ptaa)
1049 return ERROR_INT("ptaa not defined", __func__, 0);
1050
1051 return ptaa->n;
1052}
1053
1054
1063PTA *
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
1092l_ok
1094 l_int32 ipta,
1095 l_int32 jpt,
1096 l_float32 *px,
1097 l_float32 *py)
1098{
1099PTA *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 *---------------------------------------------------------------------*/
1130l_ok
1132 PTA *pta)
1133{
1134l_int32 n, i;
1135PTA *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
1167l_ok
1169 l_int32 index,
1170 PTA *pta)
1171{
1172l_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
1196l_ok
1198 l_int32 ipta,
1199 l_float32 x,
1200 l_float32 y)
1201{
1202PTA *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
1229l_ok
1231{
1232l_int32 i, n, np;
1233PTA *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 *---------------------------------------------------------------------*/
1267PTAA *
1268ptaaRead(const char *filename)
1269{
1270FILE *fp;
1271PTAA *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
1297PTAA *
1299{
1300l_int32 i, n, version;
1301PTA *pta;
1302PTAA *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
1340PTAA *
1341ptaaReadMem(const l_uint8 *data,
1342 size_t size)
1343{
1344FILE *fp;
1345PTAA *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
1376l_ok
1377ptaaWriteDebug(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
1398l_ok
1399ptaaWrite(const char *filename,
1400 PTAA *ptaa,
1401 l_int32 type)
1402{
1403l_int32 ret;
1404FILE *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
1429l_ok
1431 PTAA *ptaa,
1432 l_int32 type)
1433{
1434l_int32 i, n;
1435PTA *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
1469l_ok
1470ptaaWriteMem(l_uint8 **pdata,
1471 size_t *psize,
1472 PTAA *ptaa,
1473 l_int32 type)
1474{
1475l_int32 ret;
1476FILE *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}
struct Numa NUMA
Definition array.h:66
static const l_int32 InitialArraySize
Definition bbuffer.c:109
struct Pta PTA
Definition pix.h:264
struct Ptaa PTAA
Definition pix.h:267
@ L_COPY
Definition pix.h:505
@ L_CLONE
Definition pix.h:506
@ L_INSERT
Definition pix.h:504
#define PTA_VERSION_NUMBER
l_ok ptaWriteStream(FILE *fp, PTA *pta, l_int32 type)
ptaWriteStream()
Definition ptabasic.c:806
static l_int32 ptaaExtendArray(PTAA *ptaa)
ptaaExtendArray()
Definition ptabasic.c:1016
PTA * ptaCreateFromNuma(NUMA *nax, NUMA *nay)
ptaCreateFromNuma()
Definition ptabasic.c:150
l_ok ptaWriteMem(l_uint8 **pdata, size_t *psize, PTA *pta, l_int32 type)
ptaWriteMem()
Definition ptabasic.c:853
PTA * ptaRead(const char *filename)
ptaRead()
Definition ptabasic.c:630
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 * ptaCopy(PTA *pta)
ptaCopy()
Definition ptabasic.c:219
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
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition ptabasic.c:120
PTA * ptaClone(PTA *pta)
ptaClone()
Definition ptabasic.c:286
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
PTA * ptaReadStream(FILE *fp)
ptaReadStream()
Definition ptabasic.c:661
l_ok ptaaAddPta(PTAA *ptaa, PTA *pta, l_int32 copyflag)
ptaaAddPta()
Definition ptabasic.c:963
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
PTA * ptaReadMem(const l_uint8 *data, size_t size)
ptaReadMem()
Definition ptabasic.c:717
l_ok ptaaInitFull(PTAA *ptaa, PTA *pta)
ptaaInitFull()
Definition ptabasic.c:1131
PTA * ptaaGetPta(PTAA *ptaa, l_int32 index, l_int32 accessflag)
ptaaGetPta()
Definition ptabasic.c:1064
PTAA * ptaaReadMem(const l_uint8 *data, size_t size)
ptaaReadMem()
Definition ptabasic.c:1341
PTA * ptaCopyRange(PTA *ptas, l_int32 istart, l_int32 iend)
ptaCopyRange()
Definition ptabasic.c:249
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
l_int32 ptaGetCount(PTA *pta)
ptaGetCount()
Definition ptabasic.c:480
PTAA * ptaaRead(const char *filename)
ptaaRead()
Definition ptabasic.c:1268
PTAA * ptaaCreate(l_int32 n)
ptaaCreate()
Definition ptabasic.c:905
void ptaaDestroy(PTAA **pptaa)
ptaaDestroy()
Definition ptabasic.c:930
PTAA * ptaaReadStream(FILE *fp)
ptaaReadStream()
Definition ptabasic.c:1298
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition ptabasic.c:191
l_ok ptaaReplacePta(PTAA *ptaa, l_int32 index, PTA *pta)
ptaaReplacePta()
Definition ptabasic.c:1168
static l_int32 ptaExtendArrays(PTA *pta)
ptaExtendArrays()
Definition ptabasic.c:363
l_ok ptaaTruncate(PTAA *ptaa)
ptaaTruncate()
Definition ptabasic.c:1230
l_float32 * array
l_int32 n
l_atomic refcount
l_int32 nalloc
l_int32 n
l_float32 * y
struct Pta ** pta
l_int32 n
l_int32 nalloc