comparison mupdf-source/thirdparty/leptonica/src/ptabasic.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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
27 /*!
28 * \file ptabasic.c
29 * <pre>
30 *
31 * Pta creation, destruction, copy, clone, empty
32 * PTA *ptaCreate()
33 * PTA *ptaCreateFromNuma()
34 * void ptaDestroy()
35 * PTA *ptaCopy()
36 * PTA *ptaCopyRange()
37 * PTA *ptaClone()
38 * l_int32 ptaEmpty()
39 *
40 * Pta array extension
41 * l_int32 ptaAddPt()
42 * static l_int32 ptaExtendArrays()
43 *
44 * Pta insertion and removal
45 * l_int32 ptaInsertPt()
46 * l_int32 ptaRemovePt()
47 *
48 * Pta accessors
49 * l_int32 ptaGetCount()
50 * l_int32 ptaGetPt()
51 * l_int32 ptaGetIPt()
52 * l_int32 ptaSetPt()
53 * l_int32 ptaGetArrays()
54 *
55 * Pta serialized for I/O
56 * PTA *ptaRead()
57 * PTA *ptaReadStream()
58 * PTA *ptaReadMem()
59 * l_int32 ptaWriteDebug()
60 * l_int32 ptaWrite()
61 * l_int32 ptaWriteStream()
62 * l_int32 ptaWriteMem()
63 *
64 * Ptaa creation, destruction
65 * PTAA *ptaaCreate()
66 * void ptaaDestroy()
67 *
68 * Ptaa array extension
69 * l_int32 ptaaAddPta()
70 * static l_int32 ptaaExtendArray()
71 *
72 * Ptaa accessors
73 * l_int32 ptaaGetCount()
74 * l_int32 ptaaGetPta()
75 * l_int32 ptaaGetPt()
76 *
77 * Ptaa array modifiers
78 * l_int32 ptaaInitFull()
79 * l_int32 ptaaReplacePta()
80 * l_int32 ptaaAddPt()
81 * l_int32 ptaaTruncate()
82 *
83 * Ptaa serialized for I/O
84 * PTAA *ptaaRead()
85 * PTAA *ptaaReadStream()
86 * PTAA *ptaaReadMem()
87 * l_int32 ptaaWrite()
88 * l_int32 ptaaWriteStream()
89 * l_int32 ptaaWriteMem()
90 * </pre>
91 */
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
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; /*!< n'importe quoi */
105
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 *---------------------------------------------------------------------*/
113 /*!
114 * \brief ptaCreate()
115 *
116 * \param[in] n initial array sizes
117 * \return pta, or NULL on error.
118 */
119 PTA *
120 ptaCreate(l_int32 n)
121 {
122 PTA *pta;
123
124 if (n <= 0 || n > (l_int32)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
142 /*!
143 * \brief ptaCreateFromNuma()
144 *
145 * \param[in] nax [optional] can be null
146 * \param[in] nay
147 * \return pta, or NULL on error.
148 */
149 PTA *
150 ptaCreateFromNuma(NUMA *nax,
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
178 /*!
179 * \brief ptaDestroy()
180 *
181 * \param[in,out] ppta will be set to null before returning
182 * \return void
183 *
184 * <pre>
185 * Notes:
186 * (1) Decrements the ref count and, if 0, destroys the pta.
187 * (2) Always nulls the input ptr.
188 * </pre>
189 */
190 void
191 ptaDestroy(PTA **ppta)
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
212 /*!
213 * \brief ptaCopy()
214 *
215 * \param[in] pta
216 * \return copy of pta, or NULL on error
217 */
218 PTA *
219 ptaCopy(PTA *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
240 /*!
241 * \brief ptaCopyRange()
242 *
243 * \param[in] ptas
244 * \param[in] istart starting index in ptas
245 * \param[in] iend ending index in ptas; use 0 to copy to end
246 * \return 0 if OK, 1 on error
247 */
248 PTA *
249 ptaCopyRange(PTA *ptas,
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
279 /*!
280 * \brief ptaClone()
281 *
282 * \param[in] pta
283 * \return ptr to same pta, or NULL on error
284 */
285 PTA *
286 ptaClone(PTA *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
296 /*!
297 * \brief ptaEmpty()
298 *
299 * \param[in] pta
300 * \return 0 if OK, 1 on error
301 *
302 * <pre>
303 * Notes:
304 * This only resets the Pta::n field, for reuse
305 * </pre>
306 */
307 l_ok
308 ptaEmpty(PTA *pta)
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 *---------------------------------------------------------------------*/
320 /*!
321 * \brief ptaAddPt()
322 *
323 * \param[in] pta
324 * \param[in] x, y
325 * \return 0 if OK, 1 on error
326 */
327 l_ok
328 ptaAddPt(PTA *pta,
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
350 /*!
351 * \brief ptaExtendArrays()
352 *
353 * \param[in] pta
354 * \return 0 if OK; 1 on error
355 *
356 * <pre>
357 * Notes:
358 * (1) Doubles the size of the array.
359 * (2) The max number of points is 100M.
360 * </pre>
361 */
362 static l_int32
363 ptaExtendArrays(PTA *pta)
364 {
365 size_t oldsize, newsize;
366
367 if (!pta)
368 return ERROR_INT("pta not defined", __func__, 1);
369 if (pta->nalloc > (l_int32)MaxArraySize) /* belt & suspenders */
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 *---------------------------------------------------------------------*/
393 /*!
394 * \brief ptaInsertPt()
395 *
396 * \param[in] pta
397 * \param[in] index at which pt is to be inserted
398 * \param[in] x, y point values
399 * \return 0 if OK; 1 on error
400 */
401 l_ok
402 ptaInsertPt(PTA *pta,
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
432 /*!
433 * \brief ptaRemovePt()
434 *
435 * \param[in] pta
436 * \param[in] index of point to be removed
437 * \return 0 if OK, 1 on error
438 *
439 * <pre>
440 * Notes:
441 * (1) This shifts pta[i] --> pta[i - 1] for all i > index.
442 * (2) It should not be used repeatedly on large arrays,
443 * because the function is O(n).
444 * </pre>
445 */
446 l_ok
447 ptaRemovePt(PTA *pta,
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 *---------------------------------------------------------------------*/
473 /*!
474 * \brief ptaGetCount()
475 *
476 * \param[in] pta
477 * \return count, or 0 if no pta
478 */
479 l_int32
480 ptaGetCount(PTA *pta)
481 {
482 if (!pta)
483 return ERROR_INT("pta not defined", __func__, 0);
484
485 return pta->n;
486 }
487
488
489 /*!
490 * \brief ptaGetPt()
491 *
492 * \param[in] pta
493 * \param[in] index into arrays
494 * \param[out] px [optional] float x value
495 * \param[out] py [optional] float y value
496 * \return 0 if OK; 1 on error
497 */
498 l_ok
499 ptaGetPt(PTA *pta,
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
517 /*!
518 * \brief ptaGetIPt()
519 *
520 * \param[in] pta
521 * \param[in] index into arrays
522 * \param[out] px [optional] integer x value
523 * \param[out] py [optional] integer y value
524 * \return 0 if OK; 1 on error
525 */
526 l_ok
527 ptaGetIPt(PTA *pta,
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
545 /*!
546 * \brief ptaSetPt()
547 *
548 * \param[in] pta
549 * \param[in] index into arrays
550 * \param[in] x, y
551 * \return 0 if OK; 1 on error
552 */
553 l_ok
554 ptaSetPt(PTA *pta,
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
570 /*!
571 * \brief ptaGetArrays()
572 *
573 * \param[in] pta
574 * \param[out] pnax [optional] numa of x array
575 * \param[out] pnay [optional] numa of y array
576 * \return 0 if OK; 1 on error or if pta is empty
577 *
578 * <pre>
579 * Notes:
580 * (1) This copies the internal arrays into new Numas.
581 * </pre>
582 */
583 l_ok
584 ptaGetArrays(PTA *pta,
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 *---------------------------------------------------------------------*/
623 /*!
624 * \brief ptaRead()
625 *
626 * \param[in] filename
627 * \return pta, or NULL on error
628 */
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_1("stream not opened",
640 filename, __func__, NULL);
641 pta = ptaReadStream(fp);
642 fclose(fp);
643 if (!pta)
644 return (PTA *)ERROR_PTR_1("pta not read", filename, __func__, NULL);
645 return pta;
646 }
647
648
649 /*!
650 * \brief ptaReadStream()
651 *
652 * \param[in] fp file stream
653 * \return pta, or NULL on error
654 *
655 * <pre>
656 * Notes:
657 * (1) It is OK for the pta to be empty (n == 0).
658 * </pre>
659
660 */
661 PTA *
662 ptaReadStream(FILE *fp)
663 {
664 char typestr[128]; /* hardcoded below in fscanf */
665 l_int32 i, n, ix, iy, type, version;
666 l_float32 x, y;
667 PTA *pta;
668
669 if (!fp)
670 return (PTA *)ERROR_PTR("stream not defined", __func__, NULL);
671
672 if (fscanf(fp, "\n Pta Version %d\n", &version) != 1)
673 return (PTA *)ERROR_PTR("not a pta file", __func__, NULL);
674 if (version != PTA_VERSION_NUMBER)
675 return (PTA *)ERROR_PTR("invalid pta version", __func__, NULL);
676 if (fscanf(fp, " Number of pts = %d; format = %127s\n", &n, typestr) != 2)
677 return (PTA *)ERROR_PTR("not a pta file", __func__, NULL);
678 if (n < 0)
679 return (PTA *)ERROR_PTR("num pts <= 0", __func__, NULL);
680 if (n > (l_int32)MaxArraySize)
681 return (PTA *)ERROR_PTR("too many pts", __func__, NULL);
682 if (n == 0) L_INFO("the pta is empty\n", __func__);
683
684 if (!strcmp(typestr, "float"))
685 type = 0;
686 else /* typestr is "integer" */
687 type = 1;
688 if ((pta = ptaCreate(n)) == NULL)
689 return (PTA *)ERROR_PTR("pta not made", __func__, NULL);
690 for (i = 0; i < n; i++) {
691 if (type == 0) { /* data is float */
692 if (fscanf(fp, " (%f, %f)\n", &x, &y) != 2) {
693 ptaDestroy(&pta);
694 return (PTA *)ERROR_PTR("error reading floats", __func__, NULL);
695 }
696 ptaAddPt(pta, x, y);
697 } else { /* data is integer */
698 if (fscanf(fp, " (%d, %d)\n", &ix, &iy) != 2) {
699 ptaDestroy(&pta);
700 return (PTA *)ERROR_PTR("error reading ints", __func__, NULL);
701 }
702 ptaAddPt(pta, ix, iy);
703 }
704 }
705
706 return pta;
707 }
708
709
710 /*!
711 * \brief ptaReadMem()
712 *
713 * \param[in] data serialization in ascii
714 * \param[in] size of data in bytes; can use strlen to get it
715 * \return pta, or NULL on error
716 */
717 PTA *
718 ptaReadMem(const l_uint8 *data,
719 size_t size)
720 {
721 FILE *fp;
722 PTA *pta;
723
724 if (!data)
725 return (PTA *)ERROR_PTR("data not defined", __func__, NULL);
726 if ((fp = fopenReadFromMemory(data, size)) == NULL)
727 return (PTA *)ERROR_PTR("stream not opened", __func__, NULL);
728
729 pta = ptaReadStream(fp);
730 fclose(fp);
731 if (!pta) L_ERROR("pta not read\n", __func__);
732 return pta;
733 }
734
735
736 /*!
737 * \brief ptaWriteDebug()
738 *
739 * \param[in] filename
740 * \param[in] pta
741 * \param[in] type 0 for float values; 1 for integer values
742 * \return 0 if OK, 1 on error
743 *
744 * <pre>
745 * Notes:
746 * (1) Debug version, intended for use in the library when writing
747 * to files in a temp directory with names that are compiled in.
748 * This is used instead of ptaWrite() for all such library calls.
749 * (2) The global variable LeptDebugOK defaults to 0, and can be set
750 * or cleared by the function setLeptDebugOK().
751 * </pre>
752 */
753 l_ok
754 ptaWriteDebug(const char *filename,
755 PTA *pta,
756 l_int32 type)
757 {
758 if (LeptDebugOK) {
759 return ptaWrite(filename, pta, type);
760 } else {
761 L_INFO("write to named temp file %s is disabled\n", __func__, filename);
762 return 0;
763 }
764 }
765
766
767 /*!
768 * \brief ptaWrite()
769 *
770 * \param[in] filename
771 * \param[in] pta
772 * \param[in] type 0 for float values; 1 for integer values
773 * \return 0 if OK, 1 on error
774 */
775 l_ok
776 ptaWrite(const char *filename,
777 PTA *pta,
778 l_int32 type)
779 {
780 l_int32 ret;
781 FILE *fp;
782
783 if (!filename)
784 return ERROR_INT("filename not defined", __func__, 1);
785 if (!pta)
786 return ERROR_INT("pta not defined", __func__, 1);
787
788 if ((fp = fopenWriteStream(filename, "w")) == NULL)
789 return ERROR_INT_1("stream not opened", filename, __func__, 1);
790 ret = ptaWriteStream(fp, pta, type);
791 fclose(fp);
792 if (ret)
793 return ERROR_INT_1("pta not written to stream", filename, __func__, 1);
794 return 0;
795 }
796
797
798 /*!
799 * \brief ptaWriteStream()
800 *
801 * \param[in] fp file stream
802 * \param[in] pta
803 * \param[in] type 0 for float values; 1 for integer values
804 * \return 0 if OK; 1 on error
805 */
806 l_ok
807 ptaWriteStream(FILE *fp,
808 PTA *pta,
809 l_int32 type)
810 {
811 l_int32 i, n, ix, iy;
812 l_float32 x, y;
813
814 if (!fp)
815 return ERROR_INT("stream not defined", __func__, 1);
816 if (!pta)
817 return ERROR_INT("pta not defined", __func__, 1);
818
819 n = ptaGetCount(pta);
820 fprintf(fp, "\n Pta Version %d\n", PTA_VERSION_NUMBER);
821 if (type == 0)
822 fprintf(fp, " Number of pts = %d; format = float\n", n);
823 else /* type == 1 */
824 fprintf(fp, " Number of pts = %d; format = integer\n", n);
825 for (i = 0; i < n; i++) {
826 if (type == 0) { /* data is float */
827 ptaGetPt(pta, i, &x, &y);
828 fprintf(fp, " (%f, %f)\n", x, y);
829 } else { /* data is integer */
830 ptaGetIPt(pta, i, &ix, &iy);
831 fprintf(fp, " (%d, %d)\n", ix, iy);
832 }
833 }
834
835 return 0;
836 }
837
838
839 /*!
840 * \brief ptaWriteMem()
841 *
842 * \param[out] pdata data of serialized pta; ascii
843 * \param[out] psize size of returned data
844 * \param[in] pta
845 * \param[in] type 0 for float values; 1 for integer values
846 * \return 0 if OK, 1 on error
847 *
848 * <pre>
849 * Notes:
850 * (1) Serializes a pta in memory and puts the result in a buffer.
851 * </pre>
852 */
853 l_ok
854 ptaWriteMem(l_uint8 **pdata,
855 size_t *psize,
856 PTA *pta,
857 l_int32 type)
858 {
859 l_int32 ret;
860 FILE *fp;
861
862 if (pdata) *pdata = NULL;
863 if (psize) *psize = 0;
864 if (!pdata)
865 return ERROR_INT("&data not defined", __func__, 1);
866 if (!psize)
867 return ERROR_INT("&size not defined", __func__, 1);
868 if (!pta)
869 return ERROR_INT("pta not defined", __func__, 1);
870
871 #if HAVE_FMEMOPEN
872 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
873 return ERROR_INT("stream not opened", __func__, 1);
874 ret = ptaWriteStream(fp, pta, type);
875 fputc('\0', fp);
876 fclose(fp);
877 if (*psize > 0) *psize = *psize - 1;
878 #else
879 L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
880 #ifdef _WIN32
881 if ((fp = fopenWriteWinTempfile()) == NULL)
882 return ERROR_INT("tmpfile stream not opened", __func__, 1);
883 #else
884 if ((fp = tmpfile()) == NULL)
885 return ERROR_INT("tmpfile stream not opened", __func__, 1);
886 #endif /* _WIN32 */
887 ret = ptaWriteStream(fp, pta, type);
888 rewind(fp);
889 *pdata = l_binaryReadStream(fp, psize);
890 fclose(fp);
891 #endif /* HAVE_FMEMOPEN */
892 return ret;
893 }
894
895
896 /*---------------------------------------------------------------------*
897 * PTAA creation, destruction *
898 *---------------------------------------------------------------------*/
899 /*!
900 * \brief ptaaCreate()
901 *
902 * \param[in] n initial number of ptrs
903 * \return ptaa, or NULL on error
904 */
905 PTAA *
906 ptaaCreate(l_int32 n)
907 {
908 PTAA *ptaa;
909
910 if (n <= 0 || n > (l_int32)MaxPtrArraySize)
911 n = InitialArraySize;
912
913 ptaa = (PTAA *)LEPT_CALLOC(1, sizeof(PTAA));
914 ptaa->n = 0;
915 ptaa->nalloc = n;
916 if ((ptaa->pta = (PTA **)LEPT_CALLOC(n, sizeof(PTA *))) == NULL) {
917 ptaaDestroy(&ptaa);
918 return (PTAA *)ERROR_PTR("pta ptrs not made", __func__, NULL);
919 }
920 return ptaa;
921 }
922
923
924 /*!
925 * \brief ptaaDestroy()
926 *
927 * \param[in,out] pptaa will be set to null before returning
928 * \return void
929 */
930 void
931 ptaaDestroy(PTAA **pptaa)
932 {
933 l_int32 i;
934 PTAA *ptaa;
935
936 if (pptaa == NULL) {
937 L_WARNING("ptr address is NULL!\n", __func__);
938 return;
939 }
940
941 if ((ptaa = *pptaa) == NULL)
942 return;
943
944 for (i = 0; i < ptaa->n; i++)
945 ptaDestroy(&ptaa->pta[i]);
946 LEPT_FREE(ptaa->pta);
947 LEPT_FREE(ptaa);
948 *pptaa = NULL;
949 }
950
951
952 /*---------------------------------------------------------------------*
953 * PTAA array extension *
954 *---------------------------------------------------------------------*/
955 /*!
956 * \brief ptaaAddPta()
957 *
958 * \param[in] ptaa
959 * \param[in] pta to be added
960 * \param[in] copyflag L_INSERT, L_COPY, L_CLONE
961 * \return 0 if OK, 1 on error
962 */
963 l_ok
964 ptaaAddPta(PTAA *ptaa,
965 PTA *pta,
966 l_int32 copyflag)
967 {
968 l_int32 n;
969 PTA *ptac;
970
971 if (!ptaa)
972 return ERROR_INT("ptaa not defined", __func__, 1);
973 if (!pta)
974 return ERROR_INT("pta not defined", __func__, 1);
975
976 if (copyflag == L_INSERT) {
977 ptac = pta;
978 } else if (copyflag == L_COPY) {
979 if ((ptac = ptaCopy(pta)) == NULL)
980 return ERROR_INT("ptac not made", __func__, 1);
981 } else if (copyflag == L_CLONE) {
982 if ((ptac = ptaClone(pta)) == NULL)
983 return ERROR_INT("pta clone not made", __func__, 1);
984 } else {
985 return ERROR_INT("invalid copyflag", __func__, 1);
986 }
987
988 n = ptaaGetCount(ptaa);
989 if (n >= ptaa->nalloc) {
990 if (ptaaExtendArray(ptaa)) {
991 if (copyflag != L_INSERT)
992 ptaDestroy(&ptac);
993 return ERROR_INT("extension failed", __func__, 1);
994 }
995 }
996
997 ptaa->pta[n] = ptac;
998 ptaa->n++;
999 return 0;
1000 }
1001
1002
1003 /*!
1004 * \brief ptaaExtendArray()
1005 *
1006 * \param[in] ptaa
1007 * \return 0 if OK, 1 on error
1008 *
1009 * <pre>
1010 * Notes:
1011 * (1) This doubles the pta ptr array size.
1012 * (2) The max number of pta ptrs is 10M.
1013 * </pre>
1014 *
1015 */
1016 static l_int32
1017 ptaaExtendArray(PTAA *ptaa)
1018 {
1019 size_t oldsize, newsize;
1020
1021 if (!ptaa)
1022 return ERROR_INT("ptaa not defined", __func__, 1);
1023 oldsize = ptaa->nalloc * sizeof(PTA *);
1024 newsize = 2 * oldsize;
1025 if (newsize > 8 * MaxPtrArraySize)
1026 return ERROR_INT("newsize > 80 MB; too large", __func__, 1);
1027
1028 if ((ptaa->pta = (PTA **)reallocNew((void **)&ptaa->pta,
1029 oldsize, newsize)) == NULL)
1030 return ERROR_INT("new ptr array not returned", __func__, 1);
1031
1032 ptaa->nalloc *= 2;
1033 return 0;
1034 }
1035
1036
1037 /*---------------------------------------------------------------------*
1038 * Ptaa accessors *
1039 *---------------------------------------------------------------------*/
1040 /*!
1041 * \brief ptaaGetCount()
1042 *
1043 * \param[in] ptaa
1044 * \return count, or 0 if no ptaa
1045 */
1046 l_int32
1047 ptaaGetCount(PTAA *ptaa)
1048 {
1049 if (!ptaa)
1050 return ERROR_INT("ptaa not defined", __func__, 0);
1051
1052 return ptaa->n;
1053 }
1054
1055
1056 /*!
1057 * \brief ptaaGetPta()
1058 *
1059 * \param[in] ptaa
1060 * \param[in] index to the i-th pta
1061 * \param[in] accessflag L_COPY or L_CLONE
1062 * \return pta, or NULL on error
1063 */
1064 PTA *
1065 ptaaGetPta(PTAA *ptaa,
1066 l_int32 index,
1067 l_int32 accessflag)
1068 {
1069 if (!ptaa)
1070 return (PTA *)ERROR_PTR("ptaa not defined", __func__, NULL);
1071 if (index < 0 || index >= ptaa->n)
1072 return (PTA *)ERROR_PTR("index not valid", __func__, NULL);
1073
1074 if (accessflag == L_COPY)
1075 return ptaCopy(ptaa->pta[index]);
1076 else if (accessflag == L_CLONE)
1077 return ptaClone(ptaa->pta[index]);
1078 else
1079 return (PTA *)ERROR_PTR("invalid accessflag", __func__, NULL);
1080 }
1081
1082
1083 /*!
1084 * \brief ptaaGetPt()
1085 *
1086 * \param[in] ptaa
1087 * \param[in] ipta to the i-th pta
1088 * \param[in] jpt index to the j-th pt in the pta
1089 * \param[out] px [optional] float x value
1090 * \param[out] py [optional] float y value
1091 * \return 0 if OK; 1 on error
1092 */
1093 l_ok
1094 ptaaGetPt(PTAA *ptaa,
1095 l_int32 ipta,
1096 l_int32 jpt,
1097 l_float32 *px,
1098 l_float32 *py)
1099 {
1100 PTA *pta;
1101
1102 if (px) *px = 0;
1103 if (py) *py = 0;
1104 if (!ptaa)
1105 return ERROR_INT("ptaa not defined", __func__, 1);
1106 if (ipta < 0 || ipta >= ptaa->n)
1107 return ERROR_INT("index ipta not valid", __func__, 1);
1108
1109 pta = ptaaGetPta(ptaa, ipta, L_CLONE);
1110 if (jpt < 0 || jpt >= pta->n) {
1111 ptaDestroy(&pta);
1112 return ERROR_INT("index jpt not valid", __func__, 1);
1113 }
1114
1115 ptaGetPt(pta, jpt, px, py);
1116 ptaDestroy(&pta);
1117 return 0;
1118 }
1119
1120
1121 /*---------------------------------------------------------------------*
1122 * Ptaa array modifiers *
1123 *---------------------------------------------------------------------*/
1124 /*!
1125 * \brief ptaaInitFull()
1126 *
1127 * \param[in] ptaa can have non-null ptrs in the ptr array
1128 * \param[in] pta to be replicated into the entire ptr array
1129 * \return 0 if OK; 1 on error
1130 */
1131 l_ok
1132 ptaaInitFull(PTAA *ptaa,
1133 PTA *pta)
1134 {
1135 l_int32 n, i;
1136 PTA *ptat;
1137
1138 if (!ptaa)
1139 return ERROR_INT("ptaa not defined", __func__, 1);
1140 if (!pta)
1141 return ERROR_INT("pta not defined", __func__, 1);
1142
1143 n = ptaa->nalloc;
1144 ptaa->n = n;
1145 for (i = 0; i < n; i++) {
1146 ptat = ptaCopy(pta);
1147 ptaaReplacePta(ptaa, i, ptat);
1148 }
1149 return 0;
1150 }
1151
1152
1153 /*!
1154 * \brief ptaaReplacePta()
1155 *
1156 * \param[in] ptaa
1157 * \param[in] index to the index-th pta
1158 * \param[in] pta insert and replace any existing one
1159 * \return 0 if OK, 1 on error
1160 *
1161 * <pre>
1162 * Notes:
1163 * (1) Any existing pta is destroyed, and the input one
1164 * is inserted in its place.
1165 * (2) If %index is invalid, return 1 (error)
1166 * </pre>
1167 */
1168 l_ok
1169 ptaaReplacePta(PTAA *ptaa,
1170 l_int32 index,
1171 PTA *pta)
1172 {
1173 l_int32 n;
1174
1175 if (!ptaa)
1176 return ERROR_INT("ptaa not defined", __func__, 1);
1177 if (!pta)
1178 return ERROR_INT("pta not defined", __func__, 1);
1179 n = ptaaGetCount(ptaa);
1180 if (index < 0 || index >= n)
1181 return ERROR_INT("index not valid", __func__, 1);
1182
1183 ptaDestroy(&ptaa->pta[index]);
1184 ptaa->pta[index] = pta;
1185 return 0;
1186 }
1187
1188
1189 /*!
1190 * \brief ptaaAddPt()
1191 *
1192 * \param[in] ptaa
1193 * \param[in] ipta to the i-th pta
1194 * \param[in] x,y point coordinates
1195 * \return 0 if OK; 1 on error
1196 */
1197 l_ok
1198 ptaaAddPt(PTAA *ptaa,
1199 l_int32 ipta,
1200 l_float32 x,
1201 l_float32 y)
1202 {
1203 PTA *pta;
1204
1205 if (!ptaa)
1206 return ERROR_INT("ptaa not defined", __func__, 1);
1207 if (ipta < 0 || ipta >= ptaa->n)
1208 return ERROR_INT("index ipta not valid", __func__, 1);
1209
1210 pta = ptaaGetPta(ptaa, ipta, L_CLONE);
1211 ptaAddPt(pta, x, y);
1212 ptaDestroy(&pta);
1213 return 0;
1214 }
1215
1216
1217 /*!
1218 * \brief ptaaTruncate()
1219 *
1220 * \param[in] ptaa
1221 * \return 0 if OK, 1 on error
1222 *
1223 * <pre>
1224 * Notes:
1225 * (1) This identifies the largest index containing a pta that
1226 * has any points within it, destroys all pta above that index,
1227 * and resets the count.
1228 * </pre>
1229 */
1230 l_ok
1231 ptaaTruncate(PTAA *ptaa)
1232 {
1233 l_int32 i, n, np;
1234 PTA *pta;
1235
1236 if (!ptaa)
1237 return ERROR_INT("ptaa not defined", __func__, 1);
1238
1239 n = ptaaGetCount(ptaa);
1240 for (i = n - 1; i >= 0; i--) {
1241 pta = ptaaGetPta(ptaa, i, L_CLONE);
1242 if (!pta) {
1243 ptaa->n--;
1244 continue;
1245 }
1246 np = ptaGetCount(pta);
1247 ptaDestroy(&pta);
1248 if (np == 0) {
1249 ptaDestroy(&ptaa->pta[i]);
1250 ptaa->n--;
1251 } else {
1252 break;
1253 }
1254 }
1255 return 0;
1256 }
1257
1258
1259 /*---------------------------------------------------------------------*
1260 * Ptaa serialized for I/O *
1261 *---------------------------------------------------------------------*/
1262 /*!
1263 * \brief ptaaRead()
1264 *
1265 * \param[in] filename
1266 * \return ptaa, or NULL on error
1267 */
1268 PTAA *
1269 ptaaRead(const char *filename)
1270 {
1271 FILE *fp;
1272 PTAA *ptaa;
1273
1274 if (!filename)
1275 return (PTAA *)ERROR_PTR("filename not defined", __func__, NULL);
1276
1277 if ((fp = fopenReadStream(filename)) == NULL)
1278 return (PTAA *)ERROR_PTR_1("stream not opened",
1279 filename, __func__, NULL);
1280 ptaa = ptaaReadStream(fp);
1281 fclose(fp);
1282 if (!ptaa)
1283 return (PTAA *)ERROR_PTR_1("ptaa not read", filename, __func__, NULL);
1284 return ptaa;
1285 }
1286
1287
1288 /*!
1289 * \brief ptaaReadStream()
1290 *
1291 * \param[in] fp file stream
1292 * \return ptaa, or NULL on error
1293 *
1294 * <pre>
1295 * Notes:
1296 * (1) It is OK for the ptaa to be empty (n == 0).
1297 * </pre>
1298 */
1299 PTAA *
1300 ptaaReadStream(FILE *fp)
1301 {
1302 l_int32 i, n, version;
1303 PTA *pta;
1304 PTAA *ptaa;
1305
1306 if (!fp)
1307 return (PTAA *)ERROR_PTR("stream not defined", __func__, NULL);
1308
1309 if (fscanf(fp, "\nPtaa Version %d\n", &version) != 1)
1310 return (PTAA *)ERROR_PTR("not a ptaa file", __func__, NULL);
1311 if (version != PTA_VERSION_NUMBER)
1312 return (PTAA *)ERROR_PTR("invalid ptaa version", __func__, NULL);
1313 if (fscanf(fp, "Number of Pta = %d\n", &n) != 1)
1314 return (PTAA *)ERROR_PTR("not a ptaa file", __func__, NULL);
1315 if (n < 0)
1316 return (PTAA *)ERROR_PTR("num pta ptrs <= 0", __func__, NULL);
1317 if (n > (l_int32)MaxPtrArraySize)
1318 return (PTAA *)ERROR_PTR("too many pta ptrs", __func__, NULL);
1319 if (n == 0) L_INFO("the ptaa is empty\n", __func__);
1320
1321 if ((ptaa = ptaaCreate(n)) == NULL)
1322 return (PTAA *)ERROR_PTR("ptaa not made", __func__, NULL);
1323 for (i = 0; i < n; i++) {
1324 if ((pta = ptaReadStream(fp)) == NULL) {
1325 ptaaDestroy(&ptaa);
1326 return (PTAA *)ERROR_PTR("error reading pta", __func__, NULL);
1327 }
1328 ptaaAddPta(ptaa, pta, L_INSERT);
1329 }
1330
1331 return ptaa;
1332 }
1333
1334
1335 /*!
1336 * \brief ptaaReadMem()
1337 *
1338 * \param[in] data serialization in ascii
1339 * \param[in] size of data in bytes; can use strlen to get it
1340 * \return ptaa, or NULL on error
1341 */
1342 PTAA *
1343 ptaaReadMem(const l_uint8 *data,
1344 size_t size)
1345 {
1346 FILE *fp;
1347 PTAA *ptaa;
1348
1349 if (!data)
1350 return (PTAA *)ERROR_PTR("data not defined", __func__, NULL);
1351 if ((fp = fopenReadFromMemory(data, size)) == NULL)
1352 return (PTAA *)ERROR_PTR("stream not opened", __func__, NULL);
1353
1354 ptaa = ptaaReadStream(fp);
1355 fclose(fp);
1356 if (!ptaa) L_ERROR("ptaa not read\n", __func__);
1357 return ptaa;
1358 }
1359
1360
1361 /*!
1362 * \brief ptaaWriteDebug()
1363 *
1364 * \param[in] filename
1365 * \param[in] ptaa
1366 * \param[in] type 0 for float values; 1 for integer values
1367 * \return 0 if OK, 1 on error
1368 *
1369 * <pre>
1370 * Notes:
1371 * (1) Debug version, intended for use in the library when writing
1372 * to files in a temp directory with names that are compiled in.
1373 * This is used instead of ptaaWrite() for all such library calls.
1374 * (2) The global variable LeptDebugOK defaults to 0, and can be set
1375 * or cleared by the function setLeptDebugOK().
1376 * </pre>
1377 */
1378 l_ok
1379 ptaaWriteDebug(const char *filename,
1380 PTAA *ptaa,
1381 l_int32 type)
1382 {
1383 if (LeptDebugOK) {
1384 return ptaaWrite(filename, ptaa, type);
1385 } else {
1386 L_INFO("write to named temp file %s is disabled\n", __func__, filename);
1387 return 0;
1388 }
1389 }
1390
1391
1392 /*!
1393 * \brief ptaaWrite()
1394 *
1395 * \param[in] filename
1396 * \param[in] ptaa
1397 * \param[in] type 0 for float values; 1 for integer values
1398 * \return 0 if OK, 1 on error
1399 */
1400 l_ok
1401 ptaaWrite(const char *filename,
1402 PTAA *ptaa,
1403 l_int32 type)
1404 {
1405 l_int32 ret;
1406 FILE *fp;
1407
1408 if (!filename)
1409 return ERROR_INT("filename not defined", __func__, 1);
1410 if (!ptaa)
1411 return ERROR_INT("ptaa not defined", __func__, 1);
1412
1413 if ((fp = fopenWriteStream(filename, "w")) == NULL)
1414 return ERROR_INT_1("stream not opened", filename, __func__, 1);
1415 ret = ptaaWriteStream(fp, ptaa, type);
1416 fclose(fp);
1417 if (ret)
1418 return ERROR_INT_1("ptaa not written to stream", filename, __func__, 1);
1419 return 0;
1420 }
1421
1422
1423 /*!
1424 * \brief ptaaWriteStream()
1425 *
1426 * \param[in] fp file stream
1427 * \param[in] ptaa
1428 * \param[in] type 0 for float values; 1 for integer values
1429 * \return 0 if OK; 1 on error
1430 */
1431 l_ok
1432 ptaaWriteStream(FILE *fp,
1433 PTAA *ptaa,
1434 l_int32 type)
1435 {
1436 l_int32 i, n;
1437 PTA *pta;
1438
1439 if (!fp)
1440 return ERROR_INT("stream not defined", __func__, 1);
1441 if (!ptaa)
1442 return ERROR_INT("ptaa not defined", __func__, 1);
1443
1444 n = ptaaGetCount(ptaa);
1445 fprintf(fp, "\nPtaa Version %d\n", PTA_VERSION_NUMBER);
1446 fprintf(fp, "Number of Pta = %d\n", n);
1447 for (i = 0; i < n; i++) {
1448 pta = ptaaGetPta(ptaa, i, L_CLONE);
1449 ptaWriteStream(fp, pta, type);
1450 ptaDestroy(&pta);
1451 }
1452
1453 return 0;
1454 }
1455
1456
1457 /*!
1458 * \brief ptaaWriteMem()
1459 *
1460 * \param[out] pdata data of serialized ptaa; ascii
1461 * \param[out] psize size of returned data
1462 * \param[in] ptaa
1463 * \param[in] type 0 for float values; 1 for integer values
1464 * \return 0 if OK, 1 on error
1465 *
1466 * <pre>
1467 * Notes:
1468 * (1) Serializes %ptaa in memory and puts the result in a buffer.
1469 * </pre>
1470 */
1471 l_ok
1472 ptaaWriteMem(l_uint8 **pdata,
1473 size_t *psize,
1474 PTAA *ptaa,
1475 l_int32 type)
1476 {
1477 l_int32 ret;
1478 FILE *fp;
1479
1480 if (pdata) *pdata = NULL;
1481 if (psize) *psize = 0;
1482 if (!pdata)
1483 return ERROR_INT("&data not defined", __func__, 1);
1484 if (!psize)
1485 return ERROR_INT("&size not defined", __func__, 1);
1486 if (!ptaa)
1487 return ERROR_INT("ptaa not defined", __func__, 1);
1488
1489 #if HAVE_FMEMOPEN
1490 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1491 return ERROR_INT("stream not opened", __func__, 1);
1492 ret = ptaaWriteStream(fp, ptaa, type);
1493 fputc('\0', fp);
1494 fclose(fp);
1495 if (*psize > 0) *psize = *psize - 1;
1496 #else
1497 L_INFO("no fmemopen API --> work-around: write to temp file\n", __func__);
1498 #ifdef _WIN32
1499 if ((fp = fopenWriteWinTempfile()) == NULL)
1500 return ERROR_INT("tmpfile stream not opened", __func__, 1);
1501 #else
1502 if ((fp = tmpfile()) == NULL)
1503 return ERROR_INT("tmpfile stream not opened", __func__, 1);
1504 #endif /* _WIN32 */
1505 ret = ptaaWriteStream(fp, ptaa, type);
1506 rewind(fp);
1507 *pdata = l_binaryReadStream(fp, psize);
1508 fclose(fp);
1509 #endif /* HAVE_FMEMOPEN */
1510 return ret;
1511 }