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 pixabasic.c
29 * <pre>
30 *
31 * Pixa creation, destruction, copying
32 * PIXA *pixaCreate()
33 * PIXA *pixaCreateFromPix()
34 * PIXA *pixaCreateFromBoxa()
35 * PIXA *pixaSplitPix()
36 * void pixaDestroy()
37 * PIXA *pixaCopy()
38 *
39 * Pixa addition
40 * l_int32 pixaAddPix()
41 * l_int32 pixaAddBox()
42 * static l_int32 pixaExtendArray()
43 * l_int32 pixaExtendArrayToSize()
44 *
45 * Pixa accessors
46 * l_int32 pixaGetCount()
47 * l_int32 pixaChangeRefcount()
48 * PIX *pixaGetPix()
49 * l_int32 pixaGetPixDimensions()
50 * BOXA *pixaGetBoxa()
51 * l_int32 pixaGetBoxaCount()
52 * BOX *pixaGetBox()
53 * l_int32 pixaGetBoxGeometry()
54 * l_int32 pixaSetBoxa()
55 * PIX **pixaGetPixArray()
56 * l_int32 pixaVerifyDepth()
57 * l_int32 pixaVerifyDimensions()
58 * l_int32 pixaIsFull()
59 * l_int32 pixaCountText()
60 * l_int32 pixaSetText()
61 * void ***pixaGetLinePtrs()
62 *
63 * Pixa output info
64 * l_int32 pixaWriteStreamInfo()
65 *
66 * Pixa array modifiers
67 * l_int32 pixaReplacePix()
68 * l_int32 pixaInsertPix()
69 * l_int32 pixaRemovePix()
70 * l_int32 pixaRemovePixAndSave()
71 * l_int32 pixaInitFull()
72 * l_int32 pixaClear()
73 *
74 * Pixa and Pixaa combination
75 * l_int32 pixaJoin()
76 * PIXA *pixaInterleave()
77 * l_int32 pixaaJoin()
78 *
79 * Pixaa creation, destruction
80 * PIXAA *pixaaCreate()
81 * PIXAA *pixaaCreateFromPixa()
82 * void pixaaDestroy()
83 *
84 * Pixaa addition
85 * l_int32 pixaaAddPixa()
86 * l_int32 pixaaExtendArray()
87 * l_int32 pixaaAddPix()
88 * l_int32 pixaaAddBox()
89 *
90 * Pixaa accessors
91 * l_int32 pixaaGetCount()
92 * PIXA *pixaaGetPixa()
93 * BOXA *pixaaGetBoxa()
94 * PIX *pixaaGetPix()
95 * l_int32 pixaaVerifyDepth()
96 * l_int32 pixaaVerifyDimensions()
97 * l_int32 pixaaIsFull()
98 *
99 * Pixaa array modifiers
100 * l_int32 pixaaInitFull()
101 * l_int32 pixaaReplacePixa()
102 * l_int32 pixaaClear()
103 * l_int32 pixaaTruncate()
104 *
105 * Pixa serialized I/O (requires png support)
106 * PIXA *pixaRead()
107 * PIXA *pixaReadStream()
108 * PIXA *pixaReadMem()
109 * l_int32 pixaWriteDebug()
110 * l_int32 pixaWrite()
111 * l_int32 pixaWriteStream()
112 * l_int32 pixaWriteMem()
113 * PIXA *pixaReadBoth()
114 *
115 * Pixaa serialized I/O (requires png support)
116 * PIXAA *pixaaReadFromFiles()
117 * PIXAA *pixaaRead()
118 * PIXAA *pixaaReadStream()
119 * PIXAA *pixaaReadMem()
120 * l_int32 pixaaWrite()
121 * l_int32 pixaaWriteStream()
122 * l_int32 pixaaWriteMem()
123 *
124 *
125 * Important note on reference counting:
126 * Reference counting for the Pixa is analogous to that for the Boxa.
127 * See pix.h for details. pixaCopy() provides three possible modes
128 * of copy. The basic rule is that however a Pixa is obtained
129 * (e.g., from pixaCreate*(), pixaCopy(), or a Pixaa accessor),
130 * it is necessary to call pixaDestroy() on it.
131 * </pre>
132 */
133
134 #ifdef HAVE_CONFIG_H
135 #include "config_auto.h"
136 #endif /* HAVE_CONFIG_H */
137
138 #include <string.h>
139 #include "allheaders.h"
140
141 static const l_int32 INITIAL_PTR_ARRAYSIZE = 20; /* n'import quoi */
142
143 /* Static functions */
144 static l_int32 pixaExtendArray(PIXA *pixa);
145
146
147 /*---------------------------------------------------------------------*
148 * Pixa creation, destruction, copy *
149 *---------------------------------------------------------------------*/
150 /*!
151 * \brief pixaCreate()
152 *
153 * \param[in] n initial number of ptrs
154 * \return pixa, or NULL on error
155 *
156 * <pre>
157 * Notes:
158 * (1) This creates an empty boxa.
159 * </pre>
160 */
161 PIXA *
pixaCreate(l_int32 n)162 pixaCreate(l_int32 n)
163 {
164 PIXA *pixa;
165
166 PROCNAME("pixaCreate");
167
168 if (n <= 0)
169 n = INITIAL_PTR_ARRAYSIZE;
170
171 pixa = (PIXA *)LEPT_CALLOC(1, sizeof(PIXA));
172 pixa->n = 0;
173 pixa->nalloc = n;
174 pixa->refcount = 1;
175 pixa->pix = (PIX **)LEPT_CALLOC(n, sizeof(PIX *));
176 pixa->boxa = boxaCreate(n);
177 if (!pixa->pix || !pixa->boxa) {
178 pixaDestroy(&pixa);
179 return (PIXA *)ERROR_PTR("pix or boxa not made", procName, NULL);
180 }
181 return pixa;
182 }
183
184
185 /*!
186 * \brief pixaCreateFromPix()
187 *
188 * \param[in] pixs with individual components on a lattice
189 * \param[in] n number of components
190 * \param[in] cellw width of each cell
191 * \param[in] cellh height of each cell
192 * \return pixa, or NULL on error
193 *
194 * <pre>
195 * Notes:
196 * (1) For bpp = 1, we truncate each retrieved pix to the ON
197 * pixels, which we assume for now start at (0,0)
198 * </pre>
199 */
200 PIXA *
pixaCreateFromPix(PIX * pixs,l_int32 n,l_int32 cellw,l_int32 cellh)201 pixaCreateFromPix(PIX *pixs,
202 l_int32 n,
203 l_int32 cellw,
204 l_int32 cellh)
205 {
206 l_int32 w, h, d, nw, nh, i, j, index;
207 PIX *pix1, *pix2;
208 PIXA *pixa;
209
210 PROCNAME("pixaCreateFromPix");
211
212 if (!pixs)
213 return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
214 if (n <= 0)
215 return (PIXA *)ERROR_PTR("n must be > 0", procName, NULL);
216
217 if ((pixa = pixaCreate(n)) == NULL)
218 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
219 pixGetDimensions(pixs, &w, &h, &d);
220 if ((pix1 = pixCreate(cellw, cellh, d)) == NULL) {
221 pixaDestroy(&pixa);
222 return (PIXA *)ERROR_PTR("pix1 not made", procName, NULL);
223 }
224
225 nw = (w + cellw - 1) / cellw;
226 nh = (h + cellh - 1) / cellh;
227 for (i = 0, index = 0; i < nh; i++) {
228 for (j = 0; j < nw && index < n; j++, index++) {
229 pixRasterop(pix1, 0, 0, cellw, cellh, PIX_SRC, pixs,
230 j * cellw, i * cellh);
231 if (d == 1 && !pixClipToForeground(pix1, &pix2, NULL))
232 pixaAddPix(pixa, pix2, L_INSERT);
233 else
234 pixaAddPix(pixa, pix1, L_COPY);
235 }
236 }
237
238 pixDestroy(&pix1);
239 return pixa;
240 }
241
242
243 /*!
244 * \brief pixaCreateFromBoxa()
245 *
246 * \param[in] pixs
247 * \param[in] boxa
248 * \param[out] pcropwarn [optional] TRUE if the boxa extent
249 * is larger than pixs.
250 * \return pixad, or NULL on error
251 *
252 * <pre>
253 * Notes:
254 * (1) This simply extracts from pixs the region corresponding to each
255 * box in the boxa.
256 * (2) The 3rd arg is optional. If the extent of the boxa exceeds the
257 * size of the pixa, so that some boxes are either clipped
258 * or entirely outside the pix, a warning is returned as TRUE.
259 * (3) pixad will have only the properly clipped elements, and
260 * the internal boxa will be correct.
261 * </pre>
262 */
263 PIXA *
pixaCreateFromBoxa(PIX * pixs,BOXA * boxa,l_int32 * pcropwarn)264 pixaCreateFromBoxa(PIX *pixs,
265 BOXA *boxa,
266 l_int32 *pcropwarn)
267 {
268 l_int32 i, n, w, h, wbox, hbox, cropwarn;
269 BOX *box, *boxc;
270 PIX *pixd;
271 PIXA *pixad;
272
273 PROCNAME("pixaCreateFromBoxa");
274
275 if (!pixs)
276 return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
277 if (!boxa)
278 return (PIXA *)ERROR_PTR("boxa not defined", procName, NULL);
279
280 n = boxaGetCount(boxa);
281 if ((pixad = pixaCreate(n)) == NULL)
282 return (PIXA *)ERROR_PTR("pixad not made", procName, NULL);
283
284 boxaGetExtent(boxa, &wbox, &hbox, NULL);
285 pixGetDimensions(pixs, &w, &h, NULL);
286 cropwarn = FALSE;
287 if (wbox > w || hbox > h)
288 cropwarn = TRUE;
289 if (pcropwarn)
290 *pcropwarn = cropwarn;
291
292 for (i = 0; i < n; i++) {
293 box = boxaGetBox(boxa, i, L_COPY);
294 if (cropwarn) { /* if box is outside pixs, pixd is NULL */
295 pixd = pixClipRectangle(pixs, box, &boxc); /* may be NULL */
296 if (pixd) {
297 pixaAddPix(pixad, pixd, L_INSERT);
298 pixaAddBox(pixad, boxc, L_INSERT);
299 }
300 boxDestroy(&box);
301 } else {
302 pixd = pixClipRectangle(pixs, box, NULL);
303 pixaAddPix(pixad, pixd, L_INSERT);
304 pixaAddBox(pixad, box, L_INSERT);
305 }
306 }
307
308 return pixad;
309 }
310
311
312 /*!
313 * \brief pixaSplitPix()
314 *
315 * \param[in] pixs with individual components on a lattice
316 * \param[in] nx number of mosaic cells horizontally
317 * \param[in] ny number of mosaic cells vertically
318 * \param[in] borderwidth of added border on all sides
319 * \param[in] bordercolor in our RGBA format: 0xrrggbbaa
320 * \return pixa, or NULL on error
321 *
322 * <pre>
323 * Notes:
324 * (1) This is a variant on pixaCreateFromPix(), where we
325 * simply divide the image up into (approximately) equal
326 * subunits. If you want the subimages to have essentially
327 * the same aspect ratio as the input pix, use nx = ny.
328 * (2) If borderwidth is 0, we ignore the input bordercolor and
329 * redefine it to white.
330 * (3) The bordercolor is always used to initialize each tiled pix,
331 * so that if the src is clipped, the unblitted part will
332 * be this color. This avoids 1 pixel wide black stripes at the
333 * left and lower edges.
334 * </pre>
335 */
336 PIXA *
pixaSplitPix(PIX * pixs,l_int32 nx,l_int32 ny,l_int32 borderwidth,l_uint32 bordercolor)337 pixaSplitPix(PIX *pixs,
338 l_int32 nx,
339 l_int32 ny,
340 l_int32 borderwidth,
341 l_uint32 bordercolor)
342 {
343 l_int32 w, h, d, cellw, cellh, i, j;
344 PIX *pix1;
345 PIXA *pixa;
346
347 PROCNAME("pixaSplitPix");
348
349 if (!pixs)
350 return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
351 if (nx <= 0 || ny <= 0)
352 return (PIXA *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
353 borderwidth = L_MAX(0, borderwidth);
354
355 if ((pixa = pixaCreate(nx * ny)) == NULL)
356 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
357 pixGetDimensions(pixs, &w, &h, &d);
358 cellw = (w + nx - 1) / nx; /* round up */
359 cellh = (h + ny - 1) / ny;
360
361 for (i = 0; i < ny; i++) {
362 for (j = 0; j < nx; j++) {
363 if ((pix1 = pixCreate(cellw + 2 * borderwidth,
364 cellh + 2 * borderwidth, d)) == NULL) {
365 pixaDestroy(&pixa);
366 return (PIXA *)ERROR_PTR("pix1 not made", procName, NULL);
367 }
368 pixCopyColormap(pix1, pixs);
369 if (borderwidth == 0) { /* initialize full image to white */
370 if (d == 1)
371 pixClearAll(pix1);
372 else
373 pixSetAll(pix1);
374 } else {
375 pixSetAllArbitrary(pix1, bordercolor);
376 }
377 pixRasterop(pix1, borderwidth, borderwidth, cellw, cellh,
378 PIX_SRC, pixs, j * cellw, i * cellh);
379 pixaAddPix(pixa, pix1, L_INSERT);
380 }
381 }
382
383 return pixa;
384 }
385
386
387 /*!
388 * \brief pixaDestroy()
389 *
390 * \param[in,out] ppixa can be nulled
391 *
392 * <pre>
393 * Notes:
394 * (1) Decrements the ref count and, if 0, destroys the pixa.
395 * (2) Always nulls the input ptr.
396 * </pre>
397 */
398 void
pixaDestroy(PIXA ** ppixa)399 pixaDestroy(PIXA **ppixa)
400 {
401 l_int32 i;
402 PIXA *pixa;
403
404 PROCNAME("pixaDestroy");
405
406 if (ppixa == NULL) {
407 L_WARNING("ptr address is NULL!\n", procName);
408 return;
409 }
410
411 if ((pixa = *ppixa) == NULL)
412 return;
413
414 /* Decrement the refcount. If it is 0, destroy the pixa. */
415 pixaChangeRefcount(pixa, -1);
416 if (pixa->refcount <= 0) {
417 for (i = 0; i < pixa->n; i++)
418 pixDestroy(&pixa->pix[i]);
419 LEPT_FREE(pixa->pix);
420 boxaDestroy(&pixa->boxa);
421 LEPT_FREE(pixa);
422 }
423
424 *ppixa = NULL;
425 return;
426 }
427
428
429 /*!
430 * \brief pixaCopy()
431 *
432 * \param[in] pixa
433 * \param[in] copyflag see pix.h for details:
434 * L_COPY makes a new pixa and copies each pix and each box;
435 * L_CLONE gives a new ref-counted handle to the input pixa;
436 * L_COPY_CLONE makes a new pixa and inserts clones of
437 * all pix and boxes
438 * \return new pixa, or NULL on error
439 */
440 PIXA *
pixaCopy(PIXA * pixa,l_int32 copyflag)441 pixaCopy(PIXA *pixa,
442 l_int32 copyflag)
443 {
444 l_int32 i, nb;
445 BOX *boxc;
446 PIX *pixc;
447 PIXA *pixac;
448
449 PROCNAME("pixaCopy");
450
451 if (!pixa)
452 return (PIXA *)ERROR_PTR("pixa not defined", procName, NULL);
453
454 if (copyflag == L_CLONE) {
455 pixaChangeRefcount(pixa, 1);
456 return pixa;
457 }
458
459 if (copyflag != L_COPY && copyflag != L_COPY_CLONE)
460 return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
461
462 if ((pixac = pixaCreate(pixa->n)) == NULL)
463 return (PIXA *)ERROR_PTR("pixac not made", procName, NULL);
464 nb = pixaGetBoxaCount(pixa);
465 for (i = 0; i < pixa->n; i++) {
466 if (copyflag == L_COPY) {
467 pixc = pixaGetPix(pixa, i, L_COPY);
468 if (i < nb) boxc = pixaGetBox(pixa, i, L_COPY);
469 } else { /* copy-clone */
470 pixc = pixaGetPix(pixa, i, L_CLONE);
471 if (i < nb) boxc = pixaGetBox(pixa, i, L_CLONE);
472 }
473 pixaAddPix(pixac, pixc, L_INSERT);
474 if (i < nb) pixaAddBox(pixac, boxc, L_INSERT);
475 }
476
477 return pixac;
478 }
479
480
481
482 /*---------------------------------------------------------------------*
483 * Pixa addition *
484 *---------------------------------------------------------------------*/
485 /*!
486 * \brief pixaAddPix()
487 *
488 * \param[in] pixa
489 * \param[in] pix to be added
490 * \param[in] copyflag L_INSERT, L_COPY, L_CLONE
491 * \return 0 if OK; 1 on error
492 */
493 l_int32
pixaAddPix(PIXA * pixa,PIX * pix,l_int32 copyflag)494 pixaAddPix(PIXA *pixa,
495 PIX *pix,
496 l_int32 copyflag)
497 {
498 l_int32 n;
499 PIX *pixc;
500
501 PROCNAME("pixaAddPix");
502
503 if (!pixa)
504 return ERROR_INT("pixa not defined", procName, 1);
505 if (!pix)
506 return ERROR_INT("pix not defined", procName, 1);
507
508 if (copyflag == L_INSERT)
509 pixc = pix;
510 else if (copyflag == L_COPY)
511 pixc = pixCopy(NULL, pix);
512 else if (copyflag == L_CLONE)
513 pixc = pixClone(pix);
514 else
515 return ERROR_INT("invalid copyflag", procName, 1);
516 if (!pixc)
517 return ERROR_INT("pixc not made", procName, 1);
518
519 n = pixaGetCount(pixa);
520 if (n >= pixa->nalloc)
521 pixaExtendArray(pixa);
522 pixa->pix[n] = pixc;
523 pixa->n++;
524
525 return 0;
526 }
527
528
529 /*!
530 * \brief pixaAddBox()
531 *
532 * \param[in] pixa
533 * \param[in] box
534 * \param[in] copyflag L_INSERT, L_COPY, L_CLONE
535 * \return 0 if OK, 1 on error
536 */
537 l_int32
pixaAddBox(PIXA * pixa,BOX * box,l_int32 copyflag)538 pixaAddBox(PIXA *pixa,
539 BOX *box,
540 l_int32 copyflag)
541 {
542 PROCNAME("pixaAddBox");
543
544 if (!pixa)
545 return ERROR_INT("pixa not defined", procName, 1);
546 if (!box)
547 return ERROR_INT("box not defined", procName, 1);
548 if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
549 return ERROR_INT("invalid copyflag", procName, 1);
550
551 boxaAddBox(pixa->boxa, box, copyflag);
552 return 0;
553 }
554
555
556 /*!
557 * \brief pixaExtendArray()
558 *
559 * \param[in] pixa
560 * \return 0 if OK; 1 on error
561 *
562 * <pre>
563 * Notes:
564 * (1) Doubles the size of the pixa and boxa ptr arrays.
565 * </pre>
566 */
567 static l_int32
pixaExtendArray(PIXA * pixa)568 pixaExtendArray(PIXA *pixa)
569 {
570 PROCNAME("pixaExtendArray");
571
572 if (!pixa)
573 return ERROR_INT("pixa not defined", procName, 1);
574
575 return pixaExtendArrayToSize(pixa, 2 * pixa->nalloc);
576 }
577
578
579 /*!
580 * \brief pixaExtendArrayToSize()
581 *
582 * \param[in] pixa
583 * \return 0 if OK; 1 on error
584 *
585 * <pre>
586 * Notes:
587 * (1) If necessary, reallocs new pixa and boxa ptrs arrays to %size.
588 * The pixa and boxa ptr arrays must always be equal in size.
589 * </pre>
590 */
591 l_int32
pixaExtendArrayToSize(PIXA * pixa,l_int32 size)592 pixaExtendArrayToSize(PIXA *pixa,
593 l_int32 size)
594 {
595 PROCNAME("pixaExtendArrayToSize");
596
597 if (!pixa)
598 return ERROR_INT("pixa not defined", procName, 1);
599
600 if (size > pixa->nalloc) {
601 if ((pixa->pix = (PIX **)reallocNew((void **)&pixa->pix,
602 sizeof(PIX *) * pixa->nalloc,
603 size * sizeof(PIX *))) == NULL)
604 return ERROR_INT("new ptr array not returned", procName, 1);
605 pixa->nalloc = size;
606 }
607 return boxaExtendArrayToSize(pixa->boxa, size);
608 }
609
610
611 /*---------------------------------------------------------------------*
612 * Pixa accessors *
613 *---------------------------------------------------------------------*/
614 /*!
615 * \brief pixaGetCount()
616 *
617 * \param[in] pixa
618 * \return count, or 0 if no pixa
619 */
620 l_int32
pixaGetCount(PIXA * pixa)621 pixaGetCount(PIXA *pixa)
622 {
623 PROCNAME("pixaGetCount");
624
625 if (!pixa)
626 return ERROR_INT("pixa not defined", procName, 0);
627
628 return pixa->n;
629 }
630
631
632 /*!
633 * \brief pixaChangeRefcount()
634 *
635 * \param[in] pixa
636 * \return 0 if OK, 1 on error
637 */
638 l_int32
pixaChangeRefcount(PIXA * pixa,l_int32 delta)639 pixaChangeRefcount(PIXA *pixa,
640 l_int32 delta)
641 {
642 PROCNAME("pixaChangeRefcount");
643
644 if (!pixa)
645 return ERROR_INT("pixa not defined", procName, 1);
646
647 pixa->refcount += delta;
648 return 0;
649 }
650
651
652 /*!
653 * \brief pixaGetPix()
654 *
655 * \param[in] pixa
656 * \param[in] index to the index-th pix
657 * \param[in] accesstype L_COPY or L_CLONE
658 * \return pix, or NULL on error
659 */
660 PIX *
pixaGetPix(PIXA * pixa,l_int32 index,l_int32 accesstype)661 pixaGetPix(PIXA *pixa,
662 l_int32 index,
663 l_int32 accesstype)
664 {
665 PIX *pix;
666
667 PROCNAME("pixaGetPix");
668
669 if (!pixa)
670 return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
671 if (index < 0 || index >= pixa->n)
672 return (PIX *)ERROR_PTR("index not valid", procName, NULL);
673 if ((pix = pixa->pix[index]) == NULL) {
674 L_ERROR("no pix at pixa[%d]\n", procName, index);
675 return (PIX *)ERROR_PTR("pix not found!", procName, NULL);
676 }
677
678 if (accesstype == L_COPY)
679 return pixCopy(NULL, pix);
680 else if (accesstype == L_CLONE)
681 return pixClone(pix);
682 else
683 return (PIX *)ERROR_PTR("invalid accesstype", procName, NULL);
684 }
685
686
687 /*!
688 * \brief pixaGetPixDimensions()
689 *
690 * \param[in] pixa
691 * \param[in] index to the index-th box
692 * \param[out] pw, ph, pd [optional] each can be null
693 * \return 0 if OK, 1 on error
694 */
695 l_int32
pixaGetPixDimensions(PIXA * pixa,l_int32 index,l_int32 * pw,l_int32 * ph,l_int32 * pd)696 pixaGetPixDimensions(PIXA *pixa,
697 l_int32 index,
698 l_int32 *pw,
699 l_int32 *ph,
700 l_int32 *pd)
701 {
702 PIX *pix;
703
704 PROCNAME("pixaGetPixDimensions");
705
706 if (pw) *pw = 0;
707 if (ph) *ph = 0;
708 if (pd) *pd = 0;
709 if (!pixa)
710 return ERROR_INT("pixa not defined", procName, 1);
711 if (index < 0 || index >= pixa->n)
712 return ERROR_INT("index not valid", procName, 1);
713
714 if ((pix = pixaGetPix(pixa, index, L_CLONE)) == NULL)
715 return ERROR_INT("pix not found!", procName, 1);
716 pixGetDimensions(pix, pw, ph, pd);
717 pixDestroy(&pix);
718 return 0;
719 }
720
721
722 /*!
723 * \brief pixaGetBoxa()
724 *
725 * \param[in] pixa
726 * \param[in] accesstype L_COPY, L_CLONE, L_COPY_CLONE
727 * \return boxa, or NULL on error
728 */
729 BOXA *
pixaGetBoxa(PIXA * pixa,l_int32 accesstype)730 pixaGetBoxa(PIXA *pixa,
731 l_int32 accesstype)
732 {
733 PROCNAME("pixaGetBoxa");
734
735 if (!pixa)
736 return (BOXA *)ERROR_PTR("pixa not defined", procName, NULL);
737 if (!pixa->boxa)
738 return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL);
739 if (accesstype != L_COPY && accesstype != L_CLONE &&
740 accesstype != L_COPY_CLONE)
741 return (BOXA *)ERROR_PTR("invalid accesstype", procName, NULL);
742
743 return boxaCopy(pixa->boxa, accesstype);
744 }
745
746
747 /*!
748 * \brief pixaGetBoxaCount()
749 *
750 * \param[in] pixa
751 * \return count, or 0 on error
752 */
753 l_int32
pixaGetBoxaCount(PIXA * pixa)754 pixaGetBoxaCount(PIXA *pixa)
755 {
756 PROCNAME("pixaGetBoxaCount");
757
758 if (!pixa)
759 return ERROR_INT("pixa not defined", procName, 0);
760
761 return boxaGetCount(pixa->boxa);
762 }
763
764
765 /*!
766 * \brief pixaGetBox()
767 *
768 * \param[in] pixa
769 * \param[in] index to the index-th pix
770 * \param[in] accesstype L_COPY or L_CLONE
771 * \return box if null, not automatically an error, or NULL on error
772 *
773 * <pre>
774 * Notes:
775 * (1) There is always a boxa with a pixa, and it is initialized so
776 * that each box ptr is NULL.
777 * (2) In general, we expect that there is either a box associated
778 * with each pix, or no boxes at all in the boxa.
779 * (3) Having no boxes is thus not an automatic error. Whether it
780 * is an actual error is determined by the calling program.
781 * If the caller expects to get a box, it is an error; see, e.g.,
782 * pixaGetBoxGeometry().
783 * </pre>
784 */
785 BOX *
pixaGetBox(PIXA * pixa,l_int32 index,l_int32 accesstype)786 pixaGetBox(PIXA *pixa,
787 l_int32 index,
788 l_int32 accesstype)
789 {
790 BOX *box;
791
792 PROCNAME("pixaGetBox");
793
794 if (!pixa)
795 return (BOX *)ERROR_PTR("pixa not defined", procName, NULL);
796 if (!pixa->boxa)
797 return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
798 if (index < 0 || index >= pixa->boxa->n)
799 return (BOX *)ERROR_PTR("index not valid", procName, NULL);
800 if (accesstype != L_COPY && accesstype != L_CLONE)
801 return (BOX *)ERROR_PTR("invalid accesstype", procName, NULL);
802
803 box = pixa->boxa->box[index];
804 if (box) {
805 if (accesstype == L_COPY)
806 return boxCopy(box);
807 else /* accesstype == L_CLONE */
808 return boxClone(box);
809 } else {
810 return NULL;
811 }
812 }
813
814
815 /*!
816 * \brief pixaGetBoxGeometry()
817 *
818 * \param[in] pixa
819 * \param[in] index to the index-th box
820 * \param[out] px, py, pw, ph [optional] each can be null
821 * \return 0 if OK, 1 on error
822 */
823 l_int32
pixaGetBoxGeometry(PIXA * pixa,l_int32 index,l_int32 * px,l_int32 * py,l_int32 * pw,l_int32 * ph)824 pixaGetBoxGeometry(PIXA *pixa,
825 l_int32 index,
826 l_int32 *px,
827 l_int32 *py,
828 l_int32 *pw,
829 l_int32 *ph)
830 {
831 BOX *box;
832
833 PROCNAME("pixaGetBoxGeometry");
834
835 if (px) *px = 0;
836 if (py) *py = 0;
837 if (pw) *pw = 0;
838 if (ph) *ph = 0;
839 if (!pixa)
840 return ERROR_INT("pixa not defined", procName, 1);
841 if (index < 0 || index >= pixa->n)
842 return ERROR_INT("index not valid", procName, 1);
843
844 if ((box = pixaGetBox(pixa, index, L_CLONE)) == NULL)
845 return ERROR_INT("box not found!", procName, 1);
846 boxGetGeometry(box, px, py, pw, ph);
847 boxDestroy(&box);
848 return 0;
849 }
850
851
852 /*!
853 * \brief pixaSetBoxa()
854 *
855 * \param[in] pixa
856 * \param[in] boxa
857 * \param[in] accesstype L_INSERT, L_COPY, L_CLONE
858 * \return 0 if OK, 1 on error
859 *
860 * <pre>
861 * Notes:
862 * (1) This destroys the existing boxa in the pixa.
863 * </pre>
864 */
865 l_int32
pixaSetBoxa(PIXA * pixa,BOXA * boxa,l_int32 accesstype)866 pixaSetBoxa(PIXA *pixa,
867 BOXA *boxa,
868 l_int32 accesstype)
869 {
870 PROCNAME("pixaSetBoxa");
871
872 if (!pixa)
873 return ERROR_INT("pixa not defined", procName, 1);
874 if (!boxa)
875 return ERROR_INT("boxa not defined", procName, 1);
876 if (accesstype != L_INSERT && accesstype != L_COPY &&
877 accesstype != L_CLONE)
878 return ERROR_INT("invalid access type", procName, 1);
879
880 boxaDestroy(&pixa->boxa);
881 if (accesstype == L_INSERT)
882 pixa->boxa = boxa;
883 else
884 pixa->boxa = boxaCopy(boxa, accesstype);
885
886 return 0;
887 }
888
889
890 /*!
891 * \brief pixaGetPixArray()
892 *
893 * \param[in] pixa
894 * \return pix array, or NULL on error
895 *
896 * <pre>
897 * Notes:
898 * (1) This returns a ptr to the actual array. The array is
899 * owned by the pixa, so it must not be destroyed.
900 * (2) The caller should always check if the return value is NULL
901 * before accessing any of the pix ptrs in this array!
902 * </pre>
903 */
904 PIX **
pixaGetPixArray(PIXA * pixa)905 pixaGetPixArray(PIXA *pixa)
906 {
907 PROCNAME("pixaGetPixArray");
908
909 if (!pixa)
910 return (PIX **)ERROR_PTR("pixa not defined", procName, NULL);
911
912 return pixa->pix;
913 }
914
915
916 /*!
917 * \brief pixaVerifyDepth()
918 *
919 * \param[in] pixa
920 * \param[out] psame 1 if depth is the same for all pix; 0 otherwise
921 * \param[out] pmaxd [optional] max depth of all pix
922 * \return 0 if OK, 1 on error
923 *
924 * <pre>
925 * Notes:
926 * (1) It is considered to be an error if there are no pix.
927 * </pre>
928 */
929 l_int32
pixaVerifyDepth(PIXA * pixa,l_int32 * psame,l_int32 * pmaxd)930 pixaVerifyDepth(PIXA *pixa,
931 l_int32 *psame,
932 l_int32 *pmaxd)
933 {
934 l_int32 i, n, d, maxd, same;
935
936 PROCNAME("pixaVerifyDepth");
937
938 if (pmaxd) *pmaxd = 0;
939 if (!psame)
940 return ERROR_INT("psame not defined", procName, 1);
941 if (!pixa)
942 return ERROR_INT("pixa not defined", procName, 1);
943 if ((n = pixaGetCount(pixa)) == 0)
944 return ERROR_INT("no pix in pixa", procName, 1);
945
946 same = 1;
947 pixaGetPixDimensions(pixa, 0, NULL, NULL, &maxd);
948 for (i = 1; i < n; i++) {
949 if (pixaGetPixDimensions(pixa, i, NULL, NULL, &d))
950 return ERROR_INT("pix depth not found", procName, 1);
951 maxd = L_MAX(maxd, d);
952 if (d != maxd)
953 same = 0;
954 }
955 *psame = same;
956 if (pmaxd) *pmaxd = maxd;
957 return 0;
958 }
959
960
961 /*!
962 * \brief pixaVerifyDimensions()
963 *
964 * \param[in] pixa
965 * \param[out] psame 1 if dimensions are the same for all pix; 0 otherwise
966 * \param[out] pmaxw [optional] max width of all pix
967 * \param[out] pmaxh [optional] max height of all pix
968 * \return 0 if OK, 1 on error
969 *
970 * <pre>
971 * Notes:
972 * (1) It is considered to be an error if there are no pix.
973 * </pre>
974 */
975 l_int32
pixaVerifyDimensions(PIXA * pixa,l_int32 * psame,l_int32 * pmaxw,l_int32 * pmaxh)976 pixaVerifyDimensions(PIXA *pixa,
977 l_int32 *psame,
978 l_int32 *pmaxw,
979 l_int32 *pmaxh)
980 {
981 l_int32 i, n, w, h, maxw, maxh, same;
982
983 PROCNAME("pixaVerifyDimensions");
984
985 if (pmaxw) *pmaxw = 0;
986 if (pmaxh) *pmaxh = 0;
987 if (!psame)
988 return ERROR_INT("psame not defined", procName, 1);
989 *psame = 0;
990 if (!pixa)
991 return ERROR_INT("pixa not defined", procName, 1);
992 if ((n = pixaGetCount(pixa)) == 0)
993 return ERROR_INT("no pix in pixa", procName, 1);
994
995 same = 1;
996 pixaGetPixDimensions(pixa, 0, &maxw, &maxh, NULL);
997 for (i = 1; i < n; i++) {
998 if (pixaGetPixDimensions(pixa, i, &w, &h, NULL))
999 return ERROR_INT("pix dimensions not found", procName, 1);
1000 maxw = L_MAX(maxw, w);
1001 maxh = L_MAX(maxh, h);
1002 if (w != maxw || h != maxh)
1003 same = 0;
1004 }
1005 *psame = same;
1006 if (pmaxw) *pmaxw = maxw;
1007 if (pmaxh) *pmaxh = maxh;
1008 return 0;
1009 }
1010
1011
1012 /*!
1013 * \brief pixaIsFull()
1014 *
1015 * \param[in] pixa
1016 * \param[out] pfullpa [optional] 1 if pixa is full
1017 * \param[out] pfullba [optional] 1 if boxa is full
1018 * \return 0 if OK, 1 on error
1019 *
1020 * <pre>
1021 * Notes:
1022 * (1) A pixa is "full" if the array of pix is fully
1023 * occupied from index 0 to index (pixa->n - 1).
1024 * </pre>
1025 */
1026 l_int32
pixaIsFull(PIXA * pixa,l_int32 * pfullpa,l_int32 * pfullba)1027 pixaIsFull(PIXA *pixa,
1028 l_int32 *pfullpa,
1029 l_int32 *pfullba)
1030 {
1031 l_int32 i, n, full;
1032 BOXA *boxa;
1033 PIX *pix;
1034
1035 PROCNAME("pixaIsFull");
1036
1037 if (pfullpa) *pfullpa = 0;
1038 if (pfullba) *pfullba = 0;
1039 if (!pixa)
1040 return ERROR_INT("pixa not defined", procName, 1);
1041
1042 n = pixaGetCount(pixa);
1043 if (pfullpa) {
1044 full = 1;
1045 for (i = 0; i < n; i++) {
1046 if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) {
1047 full = 0;
1048 break;
1049 }
1050 pixDestroy(&pix);
1051 }
1052 *pfullpa = full;
1053 }
1054 if (pfullba) {
1055 boxa = pixaGetBoxa(pixa, L_CLONE);
1056 boxaIsFull(boxa, pfullba);
1057 boxaDestroy(&boxa);
1058 }
1059 return 0;
1060 }
1061
1062
1063 /*!
1064 * \brief pixaCountText()
1065 *
1066 * \param[in] pixa
1067 * \param[out] pntext number of pix with non-empty text strings
1068 * \return 0 if OK, 1 on error.
1069 *
1070 * <pre>
1071 * Notes:
1072 * (1) All pix have non-empty text strings if the returned value %ntext
1073 * equals the pixa count.
1074 * </pre>
1075 */
1076 l_int32
pixaCountText(PIXA * pixa,l_int32 * pntext)1077 pixaCountText(PIXA *pixa,
1078 l_int32 *pntext)
1079 {
1080 char *text;
1081 l_int32 i, n;
1082 PIX *pix;
1083
1084 PROCNAME("pixaCountText");
1085
1086 if (!pntext)
1087 return ERROR_INT("&ntext not defined", procName, 1);
1088 *pntext = 0;
1089 if (!pixa)
1090 return ERROR_INT("pixa not defined", procName, 1);
1091
1092 n = pixaGetCount(pixa);
1093 for (i = 0; i < n; i++) {
1094 if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1095 continue;
1096 text = pixGetText(pix);
1097 if (text && strlen(text) > 0)
1098 (*pntext)++;
1099 pixDestroy(&pix);
1100 }
1101
1102 return 0;
1103 }
1104
1105
1106 /*!
1107 * \brief pixaSetText()
1108 *
1109 * \param[in] pixa
1110 * \param[in] sa [optional] array of text strings, to insert in each pix
1111 * \return 0 if OK, 1 on error.
1112 *
1113 * <pre>
1114 * Notes:
1115 * (1) To clear all the text fields, use sa == NULL;
1116 * (2) If sa is defined, it must be the same size as %pixa.
1117 * </pre>
1118 */
1119 l_int32
pixaSetText(PIXA * pixa,SARRAY * sa)1120 pixaSetText(PIXA *pixa,
1121 SARRAY *sa)
1122 {
1123 char *str;
1124 l_int32 i, n;
1125 PIX *pix;
1126
1127 PROCNAME("pixaSetText");
1128
1129 if (!pixa)
1130 return ERROR_INT("pixa not defined", procName, 1);
1131
1132 n = pixaGetCount(pixa);
1133 if (!sa) {
1134 for (i = 0; i < n; i++) {
1135 if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1136 continue;
1137 pixSetText(pix, NULL);
1138 pixDestroy(&pix);
1139 }
1140 return 0;
1141 }
1142
1143 if (sarrayGetCount(sa) != n)
1144 return ERROR_INT("pixa and sa sizes differ", procName, 1);
1145
1146 for (i = 0; i < n; i++) {
1147 if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
1148 continue;
1149 str = sarrayGetString(sa, i, L_NOCOPY);
1150 pixSetText(pix, str);
1151 pixDestroy(&pix);
1152 }
1153
1154 return 0;
1155 }
1156
1157
1158 /*!
1159 * \brief pixaGetLinePtrs()
1160 *
1161 * \param[in] pixa of pix that all have the same depth
1162 * \param[out] psize [optional] number of pix in the pixa
1163 * \return array of array of line ptrs, or NULL on error
1164 *
1165 * <pre>
1166 * Notes:
1167 * (1) See pixGetLinePtrs() for details.
1168 * (2) It is best if all pix in the pixa are the same size.
1169 * The size of each line ptr array is equal to the height
1170 * of the pix that it refers to.
1171 * (3) This is an array of arrays. To destroy it:
1172 * for (i = 0; i < size; i++)
1173 * LEPT_FREE(lineset[i]);
1174 * LEPT_FREE(lineset);
1175 * </pre>
1176 */
1177 void ***
pixaGetLinePtrs(PIXA * pixa,l_int32 * psize)1178 pixaGetLinePtrs(PIXA *pixa,
1179 l_int32 *psize)
1180 {
1181 l_int32 i, n, same;
1182 void **lineptrs;
1183 void ***lineset;
1184 PIX *pix;
1185
1186 PROCNAME("pixaGetLinePtrs");
1187
1188 if (psize) *psize = 0;
1189 if (!pixa)
1190 return (void ***)ERROR_PTR("pixa not defined", procName, NULL);
1191 pixaVerifyDepth(pixa, &same, NULL);
1192 if (!same)
1193 return (void ***)ERROR_PTR("pixa not all same depth", procName, NULL);
1194 n = pixaGetCount(pixa);
1195 if (psize) *psize = n;
1196 if ((lineset = (void ***)LEPT_CALLOC(n, sizeof(void **))) == NULL)
1197 return (void ***)ERROR_PTR("lineset not made", procName, NULL);
1198 for (i = 0; i < n; i++) {
1199 pix = pixaGetPix(pixa, i, L_CLONE);
1200 lineptrs = pixGetLinePtrs(pix, NULL);
1201 lineset[i] = lineptrs;
1202 pixDestroy(&pix);
1203 }
1204
1205 return lineset;
1206 }
1207
1208
1209 /*---------------------------------------------------------------------*
1210 * Pixa output info *
1211 *---------------------------------------------------------------------*/
1212 /*!
1213 * \brief pixaWriteStreamInfo()
1214 *
1215 * \param[in] fp file stream
1216 * \param[in] pixa
1217 * \return 0 if OK, 1 on error.
1218 *
1219 * <pre>
1220 * Notes:
1221 * (1) For each pix in the pixa, write out the pix dimensions, spp,
1222 * text string (if it exists), and cmap info.
1223 * </pre>
1224 */
1225 l_int32
pixaWriteStreamInfo(FILE * fp,PIXA * pixa)1226 pixaWriteStreamInfo(FILE *fp,
1227 PIXA *pixa)
1228 {
1229 char *text;
1230 l_int32 i, n, w, h, d, spp, count, hastext;
1231 PIX *pix;
1232 PIXCMAP *cmap;
1233
1234 PROCNAME("pixaWriteStreamInfo");
1235
1236 if (!fp)
1237 return ERROR_INT("stream not defined", procName, 1);
1238 if (!pixa)
1239 return ERROR_INT("pixa not defined", procName, 1);
1240
1241 n = pixaGetCount(pixa);
1242 for (i = 0; i < n; i++) {
1243 if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) {
1244 fprintf(fp, "%d: no pix at this index\n", i);
1245 continue;
1246 }
1247 pixGetDimensions(pix, &w, &h, &d);
1248 spp = pixGetSpp(pix);
1249 text = pixGetText(pix);
1250 hastext = (text && strlen(text) > 0);
1251 if ((cmap = pixGetColormap(pix)) != NULL)
1252 count = pixcmapGetCount(cmap);
1253 fprintf(fp, "Pix %d: w = %d, h = %d, d = %d, spp = %d",
1254 i, w, h, d, spp);
1255 if (cmap) fprintf(fp, ", cmap(%d colors)", count);
1256 if (hastext) fprintf(fp, ", text = %s", text);
1257 fprintf(fp, "\n");
1258 pixDestroy(&pix);
1259 }
1260
1261 return 0;
1262 }
1263
1264
1265 /*---------------------------------------------------------------------*
1266 * Pixa array modifiers *
1267 *---------------------------------------------------------------------*/
1268 /*!
1269 * \brief pixaReplacePix()
1270 *
1271 * \param[in] pixa
1272 * \param[in] index to the index-th pix
1273 * \param[in] pix insert to replace existing one
1274 * \param[in] box [optional] insert to replace existing
1275 * \return 0 if OK, 1 on error
1276 *
1277 * <pre>
1278 * Notes:
1279 * (1) In-place replacement of one pix.
1280 * (2) The previous pix at that location is destroyed.
1281 * </pre>
1282 */
1283 l_int32
pixaReplacePix(PIXA * pixa,l_int32 index,PIX * pix,BOX * box)1284 pixaReplacePix(PIXA *pixa,
1285 l_int32 index,
1286 PIX *pix,
1287 BOX *box)
1288 {
1289 BOXA *boxa;
1290
1291 PROCNAME("pixaReplacePix");
1292
1293 if (!pixa)
1294 return ERROR_INT("pixa not defined", procName, 1);
1295 if (index < 0 || index >= pixa->n)
1296 return ERROR_INT("index not valid", procName, 1);
1297 if (!pix)
1298 return ERROR_INT("pix not defined", procName, 1);
1299
1300 pixDestroy(&(pixa->pix[index]));
1301 pixa->pix[index] = pix;
1302
1303 if (box) {
1304 boxa = pixa->boxa;
1305 if (index > boxa->n)
1306 return ERROR_INT("boxa index not valid", procName, 1);
1307 boxaReplaceBox(boxa, index, box);
1308 }
1309
1310 return 0;
1311 }
1312
1313
1314 /*!
1315 * \brief pixaInsertPix()
1316 *
1317 * \param[in] pixa
1318 * \param[in] index at which pix is to be inserted
1319 * \param[in] pixs new pix to be inserted
1320 * \param[in] box [optional] new box to be inserted
1321 * \return 0 if OK, 1 on error
1322 *
1323 * <pre>
1324 * Notes:
1325 * (1) This shifts pixa[i] --> pixa[i + 1] for all i >= index,
1326 * and then inserts at pixa[index].
1327 * (2) To insert at the beginning of the array, set index = 0.
1328 * (3) It should not be used repeatedly on large arrays,
1329 * because the function is O(n).
1330 * (4) To append a pix to a pixa, it's easier to use pixaAddPix().
1331 * </pre>
1332 */
1333 l_int32
pixaInsertPix(PIXA * pixa,l_int32 index,PIX * pixs,BOX * box)1334 pixaInsertPix(PIXA *pixa,
1335 l_int32 index,
1336 PIX *pixs,
1337 BOX *box)
1338 {
1339 l_int32 i, n;
1340
1341 PROCNAME("pixaInsertPix");
1342
1343 if (!pixa)
1344 return ERROR_INT("pixa not defined", procName, 1);
1345 n = pixaGetCount(pixa);
1346 if (index < 0 || index > n)
1347 return ERROR_INT("index not in {0...n}", procName, 1);
1348 if (!pixs)
1349 return ERROR_INT("pixs not defined", procName, 1);
1350
1351 if (n >= pixa->nalloc) { /* extend both ptr arrays */
1352 pixaExtendArray(pixa);
1353 boxaExtendArray(pixa->boxa);
1354 }
1355 pixa->n++;
1356 for (i = n; i > index; i--)
1357 pixa->pix[i] = pixa->pix[i - 1];
1358 pixa->pix[index] = pixs;
1359
1360 /* Optionally, insert the box */
1361 if (box)
1362 boxaInsertBox(pixa->boxa, index, box);
1363
1364 return 0;
1365 }
1366
1367
1368 /*!
1369 * \brief pixaRemovePix()
1370 *
1371 * \param[in] pixa
1372 * \param[in] index of pix to be removed
1373 * \return 0 if OK, 1 on error
1374 *
1375 * <pre>
1376 * Notes:
1377 * (1) This shifts pixa[i] --> pixa[i - 1] for all i > index.
1378 * (2) It should not be used repeatedly on large arrays,
1379 * because the function is O(n).
1380 * (3) The corresponding box is removed as well, if it exists.
1381 * </pre>
1382 */
1383 l_int32
pixaRemovePix(PIXA * pixa,l_int32 index)1384 pixaRemovePix(PIXA *pixa,
1385 l_int32 index)
1386 {
1387 l_int32 i, n, nbox;
1388 BOXA *boxa;
1389 PIX **array;
1390
1391 PROCNAME("pixaRemovePix");
1392
1393 if (!pixa)
1394 return ERROR_INT("pixa not defined", procName, 1);
1395 n = pixaGetCount(pixa);
1396 if (index < 0 || index >= n)
1397 return ERROR_INT("index not in {0...n - 1}", procName, 1);
1398
1399 /* Remove the pix */
1400 array = pixa->pix;
1401 pixDestroy(&array[index]);
1402 for (i = index + 1; i < n; i++)
1403 array[i - 1] = array[i];
1404 array[n - 1] = NULL;
1405 pixa->n--;
1406
1407 /* Remove the box if it exists */
1408 boxa = pixa->boxa;
1409 nbox = boxaGetCount(boxa);
1410 if (index < nbox)
1411 boxaRemoveBox(boxa, index);
1412
1413 return 0;
1414 }
1415
1416
1417 /*!
1418 * \brief pixaRemovePixAndSave()
1419 *
1420 * \param[in] pixa
1421 * \param[in] index of pix to be removed
1422 * \param[out] ppix [optional] removed pix
1423 * \param[out] pbox [optional] removed box
1424 * \return 0 if OK, 1 on error
1425 *
1426 * <pre>
1427 * Notes:
1428 * (1) This shifts pixa[i] --> pixa[i - 1] for all i > index.
1429 * (2) It should not be used repeatedly on large arrays,
1430 * because the function is O(n).
1431 * (3) The corresponding box is removed as well, if it exists.
1432 * (4) The removed pix and box can either be retained or destroyed.
1433 * </pre>
1434 */
1435 l_int32
pixaRemovePixAndSave(PIXA * pixa,l_int32 index,PIX ** ppix,BOX ** pbox)1436 pixaRemovePixAndSave(PIXA *pixa,
1437 l_int32 index,
1438 PIX **ppix,
1439 BOX **pbox)
1440 {
1441 l_int32 i, n, nbox;
1442 BOXA *boxa;
1443 PIX **array;
1444
1445 PROCNAME("pixaRemovePixAndSave");
1446
1447 if (ppix) *ppix = NULL;
1448 if (pbox) *pbox = NULL;
1449 if (!pixa)
1450 return ERROR_INT("pixa not defined", procName, 1);
1451 n = pixaGetCount(pixa);
1452 if (index < 0 || index >= n)
1453 return ERROR_INT("index not in {0...n - 1}", procName, 1);
1454
1455 /* Remove the pix */
1456 array = pixa->pix;
1457 if (ppix)
1458 *ppix = pixaGetPix(pixa, index, L_CLONE);
1459 pixDestroy(&array[index]);
1460 for (i = index + 1; i < n; i++)
1461 array[i - 1] = array[i];
1462 array[n - 1] = NULL;
1463 pixa->n--;
1464
1465 /* Remove the box if it exists */
1466 boxa = pixa->boxa;
1467 nbox = boxaGetCount(boxa);
1468 if (index < nbox)
1469 boxaRemoveBoxAndSave(boxa, index, pbox);
1470
1471 return 0;
1472 }
1473
1474
1475 /*!
1476 * \brief pixaInitFull()
1477 *
1478 * \param[in] pixa typically empty
1479 * \param[in] pix [optional] to be replicated into the entire pixa ptr array
1480 * \param[in] box [optional] to be replicated into the entire boxa ptr array
1481 * \return 0 if OK, 1 on error
1482 *
1483 * <pre>
1484 * Notes:
1485 * (1) This initializes a pixa by filling up the entire pix ptr array
1486 * with copies of %pix. If %pix == NULL, we use a tiny placeholder
1487 * pix (w = h = d = 1). Any existing pix are destroyed.
1488 * It also optionally fills the boxa with copies of %box.
1489 * After this operation, the numbers of pix and (optionally)
1490 * boxes are equal to the number of allocated ptrs.
1491 * (2) Note that we use pixaReplacePix() instead of pixaInsertPix().
1492 * They both have the same effect when inserting into a NULL ptr
1493 * in the pixa ptr array:
1494 * (3) If the boxa is not initialized (i.e., filled with boxes),
1495 * later insertion of boxes will cause an error, because the
1496 * 'n' field is 0.
1497 * (4) Example usage. This function is useful to prepare for a
1498 * random insertion (or replacement) of pix into a pixa.
1499 * To randomly insert pix into a pixa, without boxes, up to
1500 * some index "max":
1501 * Pixa *pixa = pixaCreate(max);
1502 * pixaInitFull(pixa, NULL, NULL);
1503 * An existing pixa with a smaller ptr array can also be reused:
1504 * pixaExtendArrayToSize(pixa, max);
1505 * pixaInitFull(pixa, NULL, NULL);
1506 * The initialization allows the pixa to always be properly
1507 * filled, even if all pix (and boxes) are not later replaced.
1508 * </pre>
1509 */
1510 l_int32
pixaInitFull(PIXA * pixa,PIX * pix,BOX * box)1511 pixaInitFull(PIXA *pixa,
1512 PIX *pix,
1513 BOX *box)
1514 {
1515 l_int32 i, n;
1516 PIX *pix1;
1517
1518 PROCNAME("pixaInitFull");
1519
1520 if (!pixa)
1521 return ERROR_INT("pixa not defined", procName, 1);
1522
1523 n = pixa->nalloc;
1524 pixa->n = n;
1525 for (i = 0; i < n; i++) {
1526 if (pix)
1527 pix1 = pixCopy(NULL, pix);
1528 else
1529 pix1 = pixCreate(1, 1, 1);
1530 pixaReplacePix(pixa, i, pix1, NULL);
1531 }
1532 if (box)
1533 boxaInitFull(pixa->boxa, box);
1534
1535 return 0;
1536 }
1537
1538
1539 /*!
1540 * \brief pixaClear()
1541 *
1542 * \param[in] pixa
1543 * \return 0 if OK, 1 on error
1544 *
1545 * <pre>
1546 * Notes:
1547 * (1) This destroys all pix in the pixa, as well as
1548 * all boxes in the boxa. The ptrs in the pix ptr array
1549 * are all null'd. The number of allocated pix, n, is set to 0.
1550 * </pre>
1551 */
1552 l_int32
pixaClear(PIXA * pixa)1553 pixaClear(PIXA *pixa)
1554 {
1555 l_int32 i, n;
1556
1557 PROCNAME("pixaClear");
1558
1559 if (!pixa)
1560 return ERROR_INT("pixa not defined", procName, 1);
1561
1562 n = pixaGetCount(pixa);
1563 for (i = 0; i < n; i++)
1564 pixDestroy(&pixa->pix[i]);
1565 pixa->n = 0;
1566 return boxaClear(pixa->boxa);
1567 }
1568
1569
1570 /*---------------------------------------------------------------------*
1571 * Pixa and Pixaa combination *
1572 *---------------------------------------------------------------------*/
1573 /*!
1574 * \brief pixaJoin()
1575 *
1576 * \param[in] pixad dest pixa; add to this one
1577 * \param[in] pixas [optional] source pixa; add from this one
1578 * \param[in] istart starting index in pixas
1579 * \param[in] iend ending index in pixas; use -1 to cat all
1580 * \return 0 if OK, 1 on error
1581 *
1582 * <pre>
1583 * Notes:
1584 * (1) This appends a clone of each indicated pix in pixas to pixad
1585 * (2) istart < 0 is taken to mean 'read from the start' (istart = 0)
1586 * (3) iend < 0 means 'read to the end'
1587 * (4) If pixas is NULL or contains no pix, this is a no-op.
1588 * </pre>
1589 */
1590 l_int32
pixaJoin(PIXA * pixad,PIXA * pixas,l_int32 istart,l_int32 iend)1591 pixaJoin(PIXA *pixad,
1592 PIXA *pixas,
1593 l_int32 istart,
1594 l_int32 iend)
1595 {
1596 l_int32 i, n, nb;
1597 BOXA *boxas, *boxad;
1598 PIX *pix;
1599
1600 PROCNAME("pixaJoin");
1601
1602 if (!pixad)
1603 return ERROR_INT("pixad not defined", procName, 1);
1604 if (!pixas || ((n = pixaGetCount(pixas)) == 0))
1605 return 0;
1606
1607 if (istart < 0)
1608 istart = 0;
1609 if (iend < 0 || iend >= n)
1610 iend = n - 1;
1611 if (istart > iend)
1612 return ERROR_INT("istart > iend; nothing to add", procName, 1);
1613
1614 for (i = istart; i <= iend; i++) {
1615 pix = pixaGetPix(pixas, i, L_CLONE);
1616 pixaAddPix(pixad, pix, L_INSERT);
1617 }
1618
1619 boxas = pixaGetBoxa(pixas, L_CLONE);
1620 boxad = pixaGetBoxa(pixad, L_CLONE);
1621 nb = pixaGetBoxaCount(pixas);
1622 iend = L_MIN(iend, nb - 1);
1623 boxaJoin(boxad, boxas, istart, iend);
1624 boxaDestroy(&boxas); /* just the clones */
1625 boxaDestroy(&boxad);
1626 return 0;
1627 }
1628
1629
1630 /*!
1631 * \brief pixaInterleave()
1632 *
1633 * \param[in] pixa1 first src pixa
1634 * \param[in] pixa2 second src pixa
1635 * \param[in] copyflag L_CLONE, L_COPY
1636 * \return pixa interleaved from sources, or NULL on error.
1637 *
1638 * <pre>
1639 * Notes:
1640 * (1) %copyflag determines if the pix are copied or cloned.
1641 * The boxes, if they exist, are copied.
1642 * (2) If the two pixa have different sizes, a warning is issued,
1643 * and the number of pairs returned is the minimum size.
1644 * </pre>
1645 */
1646 PIXA *
pixaInterleave(PIXA * pixa1,PIXA * pixa2,l_int32 copyflag)1647 pixaInterleave(PIXA *pixa1,
1648 PIXA *pixa2,
1649 l_int32 copyflag)
1650 {
1651 l_int32 i, n1, n2, n, nb1, nb2;
1652 BOX *box;
1653 PIX *pix;
1654 PIXA *pixad;
1655
1656 PROCNAME("pixaInterleave");
1657
1658 if (!pixa1)
1659 return (PIXA *)ERROR_PTR("pixa1 not defined", procName, NULL);
1660 if (!pixa2)
1661 return (PIXA *)ERROR_PTR("pixa2 not defined", procName, NULL);
1662 if (copyflag != L_COPY && copyflag != L_CLONE)
1663 return (PIXA *)ERROR_PTR("invalid copyflag", procName, NULL);
1664 n1 = pixaGetCount(pixa1);
1665 n2 = pixaGetCount(pixa2);
1666 n = L_MIN(n1, n2);
1667 if (n == 0)
1668 return (PIXA *)ERROR_PTR("at least one input pixa is empty",
1669 procName, NULL);
1670 if (n1 != n2)
1671 L_WARNING("counts differ: %d != %d\n", procName, n1, n2);
1672
1673 pixad = pixaCreate(2 * n);
1674 nb1 = pixaGetBoxaCount(pixa1);
1675 nb2 = pixaGetBoxaCount(pixa2);
1676 for (i = 0; i < n; i++) {
1677 pix = pixaGetPix(pixa1, i, copyflag);
1678 pixaAddPix(pixad, pix, L_INSERT);
1679 if (i < nb1) {
1680 box = pixaGetBox(pixa1, i, L_COPY);
1681 pixaAddBox(pixad, box, L_INSERT);
1682 }
1683 pix = pixaGetPix(pixa2, i, copyflag);
1684 pixaAddPix(pixad, pix, L_INSERT);
1685 if (i < nb2) {
1686 box = pixaGetBox(pixa2, i, L_COPY);
1687 pixaAddBox(pixad, box, L_INSERT);
1688 }
1689 }
1690
1691 return pixad;
1692 }
1693
1694
1695 /*!
1696 * \brief pixaaJoin()
1697 *
1698 * \param[in] paad dest pixaa; add to this one
1699 * \param[in] paas [optional] source pixaa; add from this one
1700 * \param[in] istart starting index in pixaas
1701 * \param[in] iend ending index in pixaas; use -1 to cat all
1702 * \return 0 if OK, 1 on error
1703 *
1704 * <pre>
1705 * Notes:
1706 * (1) This appends a clone of each indicated pixa in paas to pixaad
1707 * (2) istart < 0 is taken to mean 'read from the start' (istart = 0)
1708 * (3) iend < 0 means 'read to the end'
1709 * </pre>
1710 */
1711 l_int32
pixaaJoin(PIXAA * paad,PIXAA * paas,l_int32 istart,l_int32 iend)1712 pixaaJoin(PIXAA *paad,
1713 PIXAA *paas,
1714 l_int32 istart,
1715 l_int32 iend)
1716 {
1717 l_int32 i, n;
1718 PIXA *pixa;
1719
1720 PROCNAME("pixaaJoin");
1721
1722 if (!paad)
1723 return ERROR_INT("pixaad not defined", procName, 1);
1724 if (!paas)
1725 return 0;
1726
1727 if (istart < 0)
1728 istart = 0;
1729 n = pixaaGetCount(paas, NULL);
1730 if (iend < 0 || iend >= n)
1731 iend = n - 1;
1732 if (istart > iend)
1733 return ERROR_INT("istart > iend; nothing to add", procName, 1);
1734
1735 for (i = istart; i <= iend; i++) {
1736 pixa = pixaaGetPixa(paas, i, L_CLONE);
1737 pixaaAddPixa(paad, pixa, L_INSERT);
1738 }
1739
1740 return 0;
1741 }
1742
1743
1744 /*---------------------------------------------------------------------*
1745 * Pixaa creation and destruction *
1746 *---------------------------------------------------------------------*/
1747 /*!
1748 * \brief pixaaCreate()
1749 *
1750 * \param[in] n initial number of pixa ptrs
1751 * \return paa, or NULL on error
1752 *
1753 * <pre>
1754 * Notes:
1755 * (1) A pixaa provides a 2-level hierarchy of images.
1756 * A common use is for segmentation masks, which are
1757 * inexpensive to store in png format.
1758 * (2) For example, suppose you want a mask for each textline
1759 * in a two-column page. The textline masks for each column
1760 * can be represented by a pixa, of which there are 2 in the pixaa.
1761 * The boxes for the textline mask components within a column
1762 * can have their origin referred to the column rather than the page.
1763 * Then the boxa field can be used to represent the two box (regions)
1764 * for the columns, and the (x,y) components of each box can
1765 * be used to get the absolute position of the textlines on
1766 * the page.
1767 * </pre>
1768 */
1769 PIXAA *
pixaaCreate(l_int32 n)1770 pixaaCreate(l_int32 n)
1771 {
1772 PIXAA *paa;
1773
1774 PROCNAME("pixaaCreate");
1775
1776 if (n <= 0)
1777 n = INITIAL_PTR_ARRAYSIZE;
1778
1779 if ((paa = (PIXAA *)LEPT_CALLOC(1, sizeof(PIXAA))) == NULL)
1780 return (PIXAA *)ERROR_PTR("paa not made", procName, NULL);
1781 paa->n = 0;
1782 paa->nalloc = n;
1783
1784 if ((paa->pixa = (PIXA **)LEPT_CALLOC(n, sizeof(PIXA *))) == NULL) {
1785 pixaaDestroy(&paa);
1786 return (PIXAA *)ERROR_PTR("pixa ptrs not made", procName, NULL);
1787 }
1788 paa->boxa = boxaCreate(n);
1789
1790 return paa;
1791 }
1792
1793
1794 /*!
1795 * \brief pixaaCreateFromPixa()
1796 *
1797 * \param[in] pixa
1798 * \param[in] n number specifying subdivision of pixa
1799 * \param[in] type L_CHOOSE_CONSECUTIVE, L_CHOOSE_SKIP_BY
1800 * \param[in] copyflag L_CLONE, L_COPY
1801 * \return paa, or NULL on error
1802 *
1803 * <pre>
1804 * Notes:
1805 * (1) This subdivides a pixa into a set of smaller pixa that
1806 * are accumulated into a pixaa.
1807 * (2) If type == L_CHOOSE_CONSECUTIVE, the first 'n' pix are
1808 * put in a pixa and added to pixaa, then the next 'n', etc.
1809 * If type == L_CHOOSE_SKIP_BY, the first pixa is made by
1810 * aggregating pix[0], pix[n], pix[2*n], etc.
1811 * (3) The copyflag specifies if each new pix is a copy or a clone.
1812 * </pre>
1813 */
1814 PIXAA *
pixaaCreateFromPixa(PIXA * pixa,l_int32 n,l_int32 type,l_int32 copyflag)1815 pixaaCreateFromPixa(PIXA *pixa,
1816 l_int32 n,
1817 l_int32 type,
1818 l_int32 copyflag)
1819 {
1820 l_int32 count, i, j, npixa;
1821 PIX *pix;
1822 PIXA *pixat;
1823 PIXAA *paa;
1824
1825 PROCNAME("pixaaCreateFromPixa");
1826
1827 if (!pixa)
1828 return (PIXAA *)ERROR_PTR("pixa not defined", procName, NULL);
1829 count = pixaGetCount(pixa);
1830 if (count == 0)
1831 return (PIXAA *)ERROR_PTR("no pix in pixa", procName, NULL);
1832 if (n <= 0)
1833 return (PIXAA *)ERROR_PTR("n must be > 0", procName, NULL);
1834 if (type != L_CHOOSE_CONSECUTIVE && type != L_CHOOSE_SKIP_BY)
1835 return (PIXAA *)ERROR_PTR("invalid type", procName, NULL);
1836 if (copyflag != L_CLONE && copyflag != L_COPY)
1837 return (PIXAA *)ERROR_PTR("invalid copyflag", procName, NULL);
1838
1839 if (type == L_CHOOSE_CONSECUTIVE)
1840 npixa = (count + n - 1) / n;
1841 else /* L_CHOOSE_SKIP_BY */
1842 npixa = L_MIN(n, count);
1843 paa = pixaaCreate(npixa);
1844 if (type == L_CHOOSE_CONSECUTIVE) {
1845 for (i = 0; i < count; i++) {
1846 if (i % n == 0)
1847 pixat = pixaCreate(n);
1848 pix = pixaGetPix(pixa, i, copyflag);
1849 pixaAddPix(pixat, pix, L_INSERT);
1850 if (i % n == n - 1)
1851 pixaaAddPixa(paa, pixat, L_INSERT);
1852 }
1853 if (i % n != 0)
1854 pixaaAddPixa(paa, pixat, L_INSERT);
1855 } else { /* L_CHOOSE_SKIP_BY */
1856 for (i = 0; i < npixa; i++) {
1857 pixat = pixaCreate(count / npixa + 1);
1858 for (j = i; j < count; j += n) {
1859 pix = pixaGetPix(pixa, j, copyflag);
1860 pixaAddPix(pixat, pix, L_INSERT);
1861 }
1862 pixaaAddPixa(paa, pixat, L_INSERT);
1863 }
1864 }
1865
1866 return paa;
1867 }
1868
1869
1870 /*!
1871 * \brief pixaaDestroy()
1872 *
1873 * \param[in,out] ppaa to be nulled
1874 * \return void
1875 */
1876 void
pixaaDestroy(PIXAA ** ppaa)1877 pixaaDestroy(PIXAA **ppaa)
1878 {
1879 l_int32 i;
1880 PIXAA *paa;
1881
1882 PROCNAME("pixaaDestroy");
1883
1884 if (ppaa == NULL) {
1885 L_WARNING("ptr address is NULL!\n", procName);
1886 return;
1887 }
1888
1889 if ((paa = *ppaa) == NULL)
1890 return;
1891
1892 for (i = 0; i < paa->n; i++)
1893 pixaDestroy(&paa->pixa[i]);
1894 LEPT_FREE(paa->pixa);
1895 boxaDestroy(&paa->boxa);
1896
1897 LEPT_FREE(paa);
1898 *ppaa = NULL;
1899
1900 return;
1901 }
1902
1903
1904 /*---------------------------------------------------------------------*
1905 * Pixaa addition *
1906 *---------------------------------------------------------------------*/
1907 /*!
1908 * \brief pixaaAddPixa()
1909 *
1910 * \param[in] paa
1911 * \param[in] pixa to be added
1912 * \param[in] copyflag:
1913 * L_INSERT inserts the pixa directly;
1914 * L_COPY makes a new pixa and copies each pix and each box;
1915 * L_CLONE gives a new handle to the input pixa;
1916 * L_COPY_CLONE makes a new pixa and inserts clones of
1917 * all pix and boxes
1918 * \return 0 if OK; 1 on error
1919 */
1920 l_int32
pixaaAddPixa(PIXAA * paa,PIXA * pixa,l_int32 copyflag)1921 pixaaAddPixa(PIXAA *paa,
1922 PIXA *pixa,
1923 l_int32 copyflag)
1924 {
1925 l_int32 n;
1926 PIXA *pixac;
1927
1928 PROCNAME("pixaaAddPixa");
1929
1930 if (!paa)
1931 return ERROR_INT("paa not defined", procName, 1);
1932 if (!pixa)
1933 return ERROR_INT("pixa not defined", procName, 1);
1934 if (copyflag != L_INSERT && copyflag != L_COPY &&
1935 copyflag != L_CLONE && copyflag != L_COPY_CLONE)
1936 return ERROR_INT("invalid copyflag", procName, 1);
1937
1938 if (copyflag == L_INSERT) {
1939 pixac = pixa;
1940 } else {
1941 if ((pixac = pixaCopy(pixa, copyflag)) == NULL)
1942 return ERROR_INT("pixac not made", procName, 1);
1943 }
1944
1945 n = pixaaGetCount(paa, NULL);
1946 if (n >= paa->nalloc)
1947 pixaaExtendArray(paa);
1948 paa->pixa[n] = pixac;
1949 paa->n++;
1950
1951 return 0;
1952 }
1953
1954
1955 /*!
1956 * \brief pixaaExtendArray()
1957 *
1958 * \param[in] paa
1959 * \return 0 if OK; 1 on error
1960 */
1961 l_int32
pixaaExtendArray(PIXAA * paa)1962 pixaaExtendArray(PIXAA *paa)
1963 {
1964 PROCNAME("pixaaExtendArray");
1965
1966 if (!paa)
1967 return ERROR_INT("paa not defined", procName, 1);
1968
1969 if ((paa->pixa = (PIXA **)reallocNew((void **)&paa->pixa,
1970 sizeof(PIXA *) * paa->nalloc,
1971 2 * sizeof(PIXA *) * paa->nalloc)) == NULL)
1972 return ERROR_INT("new ptr array not returned", procName, 1);
1973
1974 paa->nalloc = 2 * paa->nalloc;
1975 return 0;
1976 }
1977
1978
1979 /*!
1980 * \brief pixaaAddPix()
1981 *
1982 * \param[in] paa input paa
1983 * \param[in] index index of pixa in paa
1984 * \param[in] pix to be added
1985 * \param[in] box [optional] to be added
1986 * \param[in] copyflag L_INSERT, L_COPY, L_CLONE
1987 * \return 0 if OK; 1 on error
1988 */
1989 l_int32
pixaaAddPix(PIXAA * paa,l_int32 index,PIX * pix,BOX * box,l_int32 copyflag)1990 pixaaAddPix(PIXAA *paa,
1991 l_int32 index,
1992 PIX *pix,
1993 BOX *box,
1994 l_int32 copyflag)
1995 {
1996 PIXA *pixa;
1997
1998 PROCNAME("pixaaAddPix");
1999
2000 if (!paa)
2001 return ERROR_INT("paa not defined", procName, 1);
2002 if (!pix)
2003 return ERROR_INT("pix not defined", procName, 1);
2004
2005 if ((pixa = pixaaGetPixa(paa, index, L_CLONE)) == NULL)
2006 return ERROR_INT("pixa not found", procName, 1);
2007 pixaAddPix(pixa, pix, copyflag);
2008 if (box) pixaAddBox(pixa, box, copyflag);
2009 pixaDestroy(&pixa);
2010 return 0;
2011 }
2012
2013
2014 /*!
2015 * \brief pixaaAddBox()
2016 *
2017 * \param[in] paa
2018 * \param[in] box
2019 * \param[in] copyflag L_INSERT, L_COPY, L_CLONE
2020 * \return 0 if OK, 1 on error
2021 *
2022 * <pre>
2023 * Notes:
2024 * (1) The box can be used, for example, to hold the support region
2025 * of a pixa that is being added to the pixaa.
2026 * </pre>
2027 */
2028 l_int32
pixaaAddBox(PIXAA * paa,BOX * box,l_int32 copyflag)2029 pixaaAddBox(PIXAA *paa,
2030 BOX *box,
2031 l_int32 copyflag)
2032 {
2033 PROCNAME("pixaaAddBox");
2034
2035 if (!paa)
2036 return ERROR_INT("paa not defined", procName, 1);
2037 if (!box)
2038 return ERROR_INT("box not defined", procName, 1);
2039 if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE)
2040 return ERROR_INT("invalid copyflag", procName, 1);
2041
2042 boxaAddBox(paa->boxa, box, copyflag);
2043 return 0;
2044 }
2045
2046
2047
2048 /*---------------------------------------------------------------------*
2049 * Pixaa accessors *
2050 *---------------------------------------------------------------------*/
2051 /*!
2052 * \brief pixaaGetCount()
2053 *
2054 * \param[in] paa
2055 * \param[out] pna [optional] number of pix in each pixa
2056 * \return count, or 0 if no pixaa
2057 *
2058 * <pre>
2059 * Notes:
2060 * (1) If paa is empty, a returned na will also be empty.
2061 * </pre>
2062 */
2063 l_int32
pixaaGetCount(PIXAA * paa,NUMA ** pna)2064 pixaaGetCount(PIXAA *paa,
2065 NUMA **pna)
2066 {
2067 l_int32 i, n;
2068 NUMA *na;
2069 PIXA *pixa;
2070
2071 PROCNAME("pixaaGetCount");
2072
2073 if (pna) *pna = NULL;
2074 if (!paa)
2075 return ERROR_INT("paa not defined", procName, 0);
2076
2077 n = paa->n;
2078 if (pna) {
2079 if ((na = numaCreate(n)) == NULL)
2080 return ERROR_INT("na not made", procName, 0);
2081 *pna = na;
2082 for (i = 0; i < n; i++) {
2083 pixa = pixaaGetPixa(paa, i, L_CLONE);
2084 numaAddNumber(na, pixaGetCount(pixa));
2085 pixaDestroy(&pixa);
2086 }
2087 }
2088 return n;
2089 }
2090
2091
2092 /*!
2093 * \brief pixaaGetPixa()
2094 *
2095 * \param[in] paa
2096 * \param[in] index to the index-th pixa
2097 * \param[in] accesstype L_COPY, L_CLONE, L_COPY_CLONE
2098 * \return pixa, or NULL on error
2099 *
2100 * <pre>
2101 * Notes:
2102 * (1) L_COPY makes a new pixa with a copy of every pix
2103 * (2) L_CLONE just makes a new reference to the pixa,
2104 * and bumps the counter. You would use this, for example,
2105 * when you need to extract some data from a pix within a
2106 * pixa within a pixaa.
2107 * (3) L_COPY_CLONE makes a new pixa with a clone of every pix
2108 * and box
2109 * (4) In all cases, you must invoke pixaDestroy() on the returned pixa
2110 * </pre>
2111 */
2112 PIXA *
pixaaGetPixa(PIXAA * paa,l_int32 index,l_int32 accesstype)2113 pixaaGetPixa(PIXAA *paa,
2114 l_int32 index,
2115 l_int32 accesstype)
2116 {
2117 PIXA *pixa;
2118
2119 PROCNAME("pixaaGetPixa");
2120
2121 if (!paa)
2122 return (PIXA *)ERROR_PTR("paa not defined", procName, NULL);
2123 if (index < 0 || index >= paa->n)
2124 return (PIXA *)ERROR_PTR("index not valid", procName, NULL);
2125 if (accesstype != L_COPY && accesstype != L_CLONE &&
2126 accesstype != L_COPY_CLONE)
2127 return (PIXA *)ERROR_PTR("invalid accesstype", procName, NULL);
2128
2129 if ((pixa = paa->pixa[index]) == NULL) { /* shouldn't happen! */
2130 L_ERROR("missing pixa[%d]\n", procName, index);
2131 return (PIXA *)ERROR_PTR("pixa not found at index", procName, NULL);
2132 }
2133 return pixaCopy(pixa, accesstype);
2134 }
2135
2136
2137 /*!
2138 * \brief pixaaGetBoxa()
2139 *
2140 * \param[in] paa
2141 * \param[in] accesstype L_COPY, L_CLONE
2142 * \return boxa, or NULL on error
2143 *
2144 * <pre>
2145 * Notes:
2146 * (1) L_COPY returns a copy; L_CLONE returns a new reference to the boxa.
2147 * (2) In both cases, invoke boxaDestroy() on the returned boxa.
2148 * </pre>
2149 */
2150 BOXA *
pixaaGetBoxa(PIXAA * paa,l_int32 accesstype)2151 pixaaGetBoxa(PIXAA *paa,
2152 l_int32 accesstype)
2153 {
2154 PROCNAME("pixaaGetBoxa");
2155
2156 if (!paa)
2157 return (BOXA *)ERROR_PTR("paa not defined", procName, NULL);
2158 if (accesstype != L_COPY && accesstype != L_CLONE)
2159 return (BOXA *)ERROR_PTR("invalid access type", procName, NULL);
2160
2161 return boxaCopy(paa->boxa, accesstype);
2162 }
2163
2164
2165 /*!
2166 * \brief pixaaGetPix()
2167 *
2168 * \param[in] paa
2169 * \param[in] index index into the pixa array in the pixaa
2170 * \param[in] ipix index into the pix array in the pixa
2171 * \param[in] accessflag L_COPY or L_CLONE
2172 * \return pix, or NULL on error
2173 */
2174 PIX *
pixaaGetPix(PIXAA * paa,l_int32 index,l_int32 ipix,l_int32 accessflag)2175 pixaaGetPix(PIXAA *paa,
2176 l_int32 index,
2177 l_int32 ipix,
2178 l_int32 accessflag)
2179 {
2180 PIX *pix;
2181 PIXA *pixa;
2182
2183 PROCNAME("pixaaGetPix");
2184
2185 if ((pixa = pixaaGetPixa(paa, index, L_CLONE)) == NULL)
2186 return (PIX *)ERROR_PTR("pixa not retrieved", procName, NULL);
2187 if ((pix = pixaGetPix(pixa, ipix, accessflag)) == NULL)
2188 L_ERROR("pix not retrieved\n", procName);
2189 pixaDestroy(&pixa);
2190 return pix;
2191 }
2192
2193
2194 /*!
2195 * \brief pixaaVerifyDepth()
2196 *
2197 * \param[in] paa
2198 * \param[out] psame 1 if all pix have the same depth; 0 otherwise
2199 * \param[out] pmaxd [optional] max depth of all pix in pixaa
2200 * \return 0 if OK; 1 on error
2201 *
2202 * <pre>
2203 * Notes:
2204 * (1) It is considered to be an error if any pixa have no pix.
2205 * </pre>
2206 */
2207 l_int32
pixaaVerifyDepth(PIXAA * paa,l_int32 * psame,l_int32 * pmaxd)2208 pixaaVerifyDepth(PIXAA *paa,
2209 l_int32 *psame,
2210 l_int32 *pmaxd)
2211 {
2212 l_int32 i, n, d, maxd, same, samed;
2213 PIXA *pixa;
2214
2215 PROCNAME("pixaaVerifyDepth");
2216
2217 if (pmaxd) *pmaxd = 0;
2218 if (!psame)
2219 return ERROR_INT("psame not defined", procName, 1);
2220 *psame = 0;
2221 if (!paa)
2222 return ERROR_INT("paa not defined", procName, 1);
2223 if ((n = pixaaGetCount(paa, NULL)) == 0)
2224 return ERROR_INT("no pixa in paa", procName, 1);
2225
2226 pixa = pixaaGetPixa(paa, 0, L_CLONE);
2227 pixaVerifyDepth(pixa, &same, &maxd); /* init same, maxd with first pixa */
2228 pixaDestroy(&pixa);
2229 for (i = 1; i < n; i++) {
2230 pixa = pixaaGetPixa(paa, i, L_CLONE);
2231 pixaVerifyDepth(pixa, &samed, &d);
2232 pixaDestroy(&pixa);
2233 maxd = L_MAX(maxd, d);
2234 if (!samed || maxd != d)
2235 same = 0;
2236 }
2237 *psame = same;
2238 if (pmaxd) *pmaxd = maxd;
2239 return 0;
2240 }
2241
2242
2243 /*!
2244 * \brief pixaaVerifyDimensions()
2245 *
2246 * \param[in] paa
2247 * \param[out] psame 1 if all pix have the same depth; 0 otherwise
2248 * \param[out] pmaxw [optional] max width of all pix in pixaa
2249 * \param[out] pmaxh [optional] max height of all pix in pixaa
2250 * \return 0 if OK; 1 on error
2251 *
2252 * <pre>
2253 * Notes:
2254 * (1) It is considered to be an error if any pixa have no pix.
2255 * </pre>
2256 */
2257 l_int32
pixaaVerifyDimensions(PIXAA * paa,l_int32 * psame,l_int32 * pmaxw,l_int32 * pmaxh)2258 pixaaVerifyDimensions(PIXAA *paa,
2259 l_int32 *psame,
2260 l_int32 *pmaxw,
2261 l_int32 *pmaxh)
2262 {
2263 l_int32 i, n, w, h, maxw, maxh, same, same2;
2264 PIXA *pixa;
2265
2266 PROCNAME("pixaaVerifyDimensions");
2267
2268 if (pmaxw) *pmaxw = 0;
2269 if (pmaxh) *pmaxh = 0;
2270 if (!psame)
2271 return ERROR_INT("psame not defined", procName, 1);
2272 *psame = 0;
2273 if (!paa)
2274 return ERROR_INT("paa not defined", procName, 1);
2275 if ((n = pixaaGetCount(paa, NULL)) == 0)
2276 return ERROR_INT("no pixa in paa", procName, 1);
2277
2278 /* Init same; init maxw and maxh from first pixa */
2279 pixa = pixaaGetPixa(paa, 0, L_CLONE);
2280 pixaVerifyDimensions(pixa, &same, &maxw, &maxh);
2281 pixaDestroy(&pixa);
2282
2283 for (i = 1; i < n; i++) {
2284 pixa = pixaaGetPixa(paa, i, L_CLONE);
2285 pixaVerifyDimensions(pixa, &same2, &w, &h);
2286 pixaDestroy(&pixa);
2287 maxw = L_MAX(maxw, w);
2288 maxh = L_MAX(maxh, h);
2289 if (!same2 || maxw != w || maxh != h)
2290 same = 0;
2291 }
2292 *psame = same;
2293 if (pmaxw) *pmaxw = maxw;
2294 if (pmaxh) *pmaxh = maxh;
2295 return 0;
2296 }
2297
2298
2299 /*!
2300 * \brief pixaaIsFull()
2301 *
2302 * \param[in] paa
2303 * \param[out] pfull 1 if all pixa in the paa have full pix arrays
2304 * \return return 0 if OK, 1 on error
2305 *
2306 * <pre>
2307 * Notes:
2308 * (1) Does not require boxa associated with each pixa to be full.
2309 * </pre>
2310 */
2311 l_int32
pixaaIsFull(PIXAA * paa,l_int32 * pfull)2312 pixaaIsFull(PIXAA *paa,
2313 l_int32 *pfull)
2314 {
2315 l_int32 i, n, full;
2316 PIXA *pixa;
2317
2318 PROCNAME("pixaaIsFull");
2319
2320 if (!pfull)
2321 return ERROR_INT("&full not defined", procName, 0);
2322 *pfull = 0;
2323 if (!paa)
2324 return ERROR_INT("paa not defined", procName, 0);
2325
2326 n = pixaaGetCount(paa, NULL);
2327 full = 1;
2328 for (i = 0; i < n; i++) {
2329 pixa = pixaaGetPixa(paa, i, L_CLONE);
2330 pixaIsFull(pixa, &full, NULL);
2331 pixaDestroy(&pixa);
2332 if (!full) break;
2333 }
2334 *pfull = full;
2335 return 0;
2336 }
2337
2338
2339 /*---------------------------------------------------------------------*
2340 * Pixaa array modifiers *
2341 *---------------------------------------------------------------------*/
2342 /*!
2343 * \brief pixaaInitFull()
2344 *
2345 * \param[in] paa typically empty
2346 * \param[in] pixa to be replicated into the entire pixa ptr array
2347 * \return 0 if OK, 1 on error
2348 *
2349 * <pre>
2350 * Notes:
2351 * (1) This initializes a pixaa by filling up the entire pixa ptr array
2352 * with copies of %pixa. Any existing pixa are destroyed.
2353 * (2) Example usage. This function is useful to prepare for a
2354 * random insertion (or replacement) of pixa into a pixaa.
2355 * To randomly insert pixa into a pixaa, up to some index "max":
2356 * Pixaa *paa = pixaaCreate(max);
2357 * Pixa *pixa = pixaCreate(1); // if you want little memory
2358 * pixaaInitFull(paa, pixa); // copy it to entire array
2359 * pixaDestroy(&pixa); // no longer needed
2360 * The initialization allows the pixaa to always be properly filled.
2361 * </pre>
2362 */
2363 l_int32
pixaaInitFull(PIXAA * paa,PIXA * pixa)2364 pixaaInitFull(PIXAA *paa,
2365 PIXA *pixa)
2366 {
2367 l_int32 i, n;
2368 PIXA *pixat;
2369
2370 PROCNAME("pixaaInitFull");
2371
2372 if (!paa)
2373 return ERROR_INT("paa not defined", procName, 1);
2374 if (!pixa)
2375 return ERROR_INT("pixa not defined", procName, 1);
2376
2377 n = paa->nalloc;
2378 paa->n = n;
2379 for (i = 0; i < n; i++) {
2380 pixat = pixaCopy(pixa, L_COPY);
2381 pixaaReplacePixa(paa, i, pixat);
2382 }
2383
2384 return 0;
2385 }
2386
2387
2388 /*!
2389 * \brief pixaaReplacePixa()
2390 *
2391 * \param[in] paa
2392 * \param[in] index to the index-th pixa
2393 * \param[in] pixa insert to replace existing one
2394 * \return 0 if OK, 1 on error
2395 *
2396 * <pre>
2397 * Notes:
2398 * (1) This allows random insertion of a pixa into a pixaa, with
2399 * destruction of any existing pixa at that location.
2400 * The input pixa is now owned by the pixaa.
2401 * (2) No other pixa in the array are affected.
2402 * (3) The index must be within the allowed set.
2403 * </pre>
2404 */
2405 l_int32
pixaaReplacePixa(PIXAA * paa,l_int32 index,PIXA * pixa)2406 pixaaReplacePixa(PIXAA *paa,
2407 l_int32 index,
2408 PIXA *pixa)
2409 {
2410
2411 PROCNAME("pixaaReplacePixa");
2412
2413 if (!paa)
2414 return ERROR_INT("paa not defined", procName, 1);
2415 if (index < 0 || index >= paa->n)
2416 return ERROR_INT("index not valid", procName, 1);
2417 if (!pixa)
2418 return ERROR_INT("pixa not defined", procName, 1);
2419
2420 pixaDestroy(&(paa->pixa[index]));
2421 paa->pixa[index] = pixa;
2422 return 0;
2423 }
2424
2425
2426 /*!
2427 * \brief pixaaClear()
2428 *
2429 * \param[in] paa
2430 * \return 0 if OK, 1 on error
2431 *
2432 * <pre>
2433 * Notes:
2434 * (1) This destroys all pixa in the pixaa, and nulls the ptrs
2435 * in the pixa ptr array.
2436 * </pre>
2437 */
2438 l_int32
pixaaClear(PIXAA * paa)2439 pixaaClear(PIXAA *paa)
2440 {
2441 l_int32 i, n;
2442
2443 PROCNAME("pixaClear");
2444
2445 if (!paa)
2446 return ERROR_INT("paa not defined", procName, 1);
2447
2448 n = pixaaGetCount(paa, NULL);
2449 for (i = 0; i < n; i++)
2450 pixaDestroy(&paa->pixa[i]);
2451 paa->n = 0;
2452 return 0;
2453 }
2454
2455
2456 /*!
2457 * \brief pixaaTruncate()
2458 *
2459 * \param[in] paa
2460 * \return 0 if OK, 1 on error
2461 *
2462 * <pre>
2463 * Notes:
2464 * (1) This identifies the largest index containing a pixa that
2465 * has any pix within it, destroys all pixa above that index,
2466 * and resets the count.
2467 * </pre>
2468 */
2469 l_int32
pixaaTruncate(PIXAA * paa)2470 pixaaTruncate(PIXAA *paa)
2471 {
2472 l_int32 i, n, np;
2473 PIXA *pixa;
2474
2475 PROCNAME("pixaaTruncate");
2476
2477 if (!paa)
2478 return ERROR_INT("paa not defined", procName, 1);
2479
2480 n = pixaaGetCount(paa, NULL);
2481 for (i = n - 1; i >= 0; i--) {
2482 pixa = pixaaGetPixa(paa, i, L_CLONE);
2483 if (!pixa) {
2484 paa->n--;
2485 continue;
2486 }
2487 np = pixaGetCount(pixa);
2488 pixaDestroy(&pixa);
2489 if (np == 0) {
2490 pixaDestroy(&paa->pixa[i]);
2491 paa->n--;
2492 } else {
2493 break;
2494 }
2495 }
2496 return 0;
2497 }
2498
2499
2500
2501 /*---------------------------------------------------------------------*
2502 * Pixa serialized I/O *
2503 *---------------------------------------------------------------------*/
2504 /*!
2505 * \brief pixaRead()
2506 *
2507 * \param[in] filename
2508 * \return pixa, or NULL on error
2509 *
2510 * <pre>
2511 * Notes:
2512 * (1) The pix are stored in the file as png.
2513 * If the png library is not linked, this will fail.
2514 * </pre>
2515 */
2516 PIXA *
pixaRead(const char * filename)2517 pixaRead(const char *filename)
2518 {
2519 FILE *fp;
2520 PIXA *pixa;
2521
2522 PROCNAME("pixaRead");
2523
2524 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
2525 return (PIXA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2526 #endif /* !HAVE_LIBPNG */
2527
2528 if (!filename)
2529 return (PIXA *)ERROR_PTR("filename not defined", procName, NULL);
2530
2531 if ((fp = fopenReadStream(filename)) == NULL)
2532 return (PIXA *)ERROR_PTR("stream not opened", procName, NULL);
2533 pixa = pixaReadStream(fp);
2534 fclose(fp);
2535 if (!pixa)
2536 return (PIXA *)ERROR_PTR("pixa not read", procName, NULL);
2537 return pixa;
2538 }
2539
2540
2541 /*!
2542 * \brief pixaReadStream()
2543 *
2544 * \param[in] fp file stream
2545 * \return pixa, or NULL on error
2546 *
2547 * <pre>
2548 * Notes:
2549 * (1) The pix are stored in the file as png.
2550 * If the png library is not linked, this will fail.
2551 * </pre>
2552 */
2553 PIXA *
pixaReadStream(FILE * fp)2554 pixaReadStream(FILE *fp)
2555 {
2556 l_int32 n, i, xres, yres, version;
2557 l_int32 ignore;
2558 BOXA *boxa;
2559 PIX *pix;
2560 PIXA *pixa;
2561
2562 PROCNAME("pixaReadStream");
2563
2564 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
2565 return (PIXA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2566 #endif /* !HAVE_LIBPNG */
2567
2568 if (!fp)
2569 return (PIXA *)ERROR_PTR("stream not defined", procName, NULL);
2570
2571 if (fscanf(fp, "\nPixa Version %d\n", &version) != 1)
2572 return (PIXA *)ERROR_PTR("not a pixa file", procName, NULL);
2573 if (version != PIXA_VERSION_NUMBER)
2574 return (PIXA *)ERROR_PTR("invalid pixa version", procName, NULL);
2575 if (fscanf(fp, "Number of pix = %d\n", &n) != 1)
2576 return (PIXA *)ERROR_PTR("not a pixa file", procName, NULL);
2577
2578 if ((boxa = boxaReadStream(fp)) == NULL)
2579 return (PIXA *)ERROR_PTR("boxa not made", procName, NULL);
2580 if ((pixa = pixaCreate(n)) == NULL) {
2581 boxaDestroy(&boxa);
2582 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
2583 }
2584 boxaDestroy(&pixa->boxa);
2585 pixa->boxa = boxa;
2586
2587 for (i = 0; i < n; i++) {
2588 if ((fscanf(fp, " pix[%d]: xres = %d, yres = %d\n",
2589 &ignore, &xres, &yres)) != 3) {
2590 pixaDestroy(&pixa);
2591 return (PIXA *)ERROR_PTR("res reading error", procName, NULL);
2592 }
2593 if ((pix = pixReadStreamPng(fp)) == NULL) {
2594 pixaDestroy(&pixa);
2595 return (PIXA *)ERROR_PTR("pix not read", procName, NULL);
2596 }
2597 pixSetXRes(pix, xres);
2598 pixSetYRes(pix, yres);
2599 pixaAddPix(pixa, pix, L_INSERT);
2600 }
2601 return pixa;
2602 }
2603
2604
2605 /*!
2606 * \brief pixaReadMem()
2607 *
2608 * \param[in] data of serialized pixa
2609 * \param[in] size of data in bytes
2610 * \return pixa, or NULL on error
2611 */
2612 PIXA *
pixaReadMem(const l_uint8 * data,size_t size)2613 pixaReadMem(const l_uint8 *data,
2614 size_t size)
2615 {
2616 FILE *fp;
2617 PIXA *pixa;
2618
2619 PROCNAME("pixaReadMem");
2620
2621 if (!data)
2622 return (PIXA *)ERROR_PTR("data not defined", procName, NULL);
2623 if ((fp = fopenReadFromMemory(data, size)) == NULL)
2624 return (PIXA *)ERROR_PTR("stream not opened", procName, NULL);
2625
2626 pixa = pixaReadStream(fp);
2627 fclose(fp);
2628 if (!pixa) L_ERROR("pixa not read\n", procName);
2629 return pixa;
2630 }
2631
2632
2633 /*!
2634 * \brief pixaWriteDebug()
2635 *
2636 * \param[in] fname
2637 * \param[in] pixa
2638 * \return 0 if OK; 1 on error
2639 *
2640 * <pre>
2641 * Notes:
2642 * (1) Debug version, intended for use in the library when writing
2643 * to files in a temp directory with names that are compiled in.
2644 * This is used instead of pixaWrite() for all such library calls.
2645 * (2) The global variable LeptDebugOK defaults to 0, and can be set
2646 * or cleared by the function setLeptDebugOK().
2647 * </pre>
2648 */
2649 l_int32
pixaWriteDebug(const char * fname,PIXA * pixa)2650 pixaWriteDebug(const char *fname,
2651 PIXA *pixa)
2652 {
2653 PROCNAME("pixaWriteDebug");
2654
2655 if (LeptDebugOK) {
2656 return pixaWrite(fname, pixa);
2657 } else {
2658 L_INFO("write to named temp file %s is disabled\n", procName, fname);
2659 return 0;
2660 }
2661 }
2662
2663
2664 /*!
2665 * \brief pixaWrite()
2666 *
2667 * \param[in] filename
2668 * \param[in] pixa
2669 * \return 0 if OK, 1 on error
2670 *
2671 * <pre>
2672 * Notes:
2673 * (1) The pix are stored in the file as png.
2674 * If the png library is not linked, this will fail.
2675 * </pre>
2676 */
2677 l_int32
pixaWrite(const char * filename,PIXA * pixa)2678 pixaWrite(const char *filename,
2679 PIXA *pixa)
2680 {
2681 l_int32 ret;
2682 FILE *fp;
2683
2684 PROCNAME("pixaWrite");
2685
2686 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
2687 return ERROR_INT("no libpng: can't write data", procName, 1);
2688 #endif /* !HAVE_LIBPNG */
2689
2690 if (!filename)
2691 return ERROR_INT("filename not defined", procName, 1);
2692 if (!pixa)
2693 return ERROR_INT("pixa not defined", procName, 1);
2694
2695 if ((fp = fopenWriteStream(filename, "wb")) == NULL)
2696 return ERROR_INT("stream not opened", procName, 1);
2697 ret = pixaWriteStream(fp, pixa);
2698 fclose(fp);
2699 if (ret)
2700 return ERROR_INT("pixa not written to stream", procName, 1);
2701 return 0;
2702 }
2703
2704
2705 /*!
2706 * \brief pixaWriteStream()
2707 *
2708 * \param[in] fp file stream opened for "wb"
2709 * \param[in] pixa
2710 * \return 0 if OK, 1 on error
2711 *
2712 * <pre>
2713 * Notes:
2714 * (1) The pix are stored in the file as png.
2715 * If the png library is not linked, this will fail.
2716 * </pre>
2717 */
2718 l_int32
pixaWriteStream(FILE * fp,PIXA * pixa)2719 pixaWriteStream(FILE *fp,
2720 PIXA *pixa)
2721 {
2722 l_int32 n, i;
2723 PIX *pix;
2724
2725 PROCNAME("pixaWriteStream");
2726
2727 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
2728 return ERROR_INT("no libpng: can't write data", procName, 1);
2729 #endif /* !HAVE_LIBPNG */
2730
2731 if (!fp)
2732 return ERROR_INT("stream not defined", procName, 1);
2733 if (!pixa)
2734 return ERROR_INT("pixa not defined", procName, 1);
2735
2736 n = pixaGetCount(pixa);
2737 fprintf(fp, "\nPixa Version %d\n", PIXA_VERSION_NUMBER);
2738 fprintf(fp, "Number of pix = %d\n", n);
2739 boxaWriteStream(fp, pixa->boxa);
2740 for (i = 0; i < n; i++) {
2741 if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
2742 return ERROR_INT("pix not found", procName, 1);
2743 fprintf(fp, " pix[%d]: xres = %d, yres = %d\n",
2744 i, pix->xres, pix->yres);
2745 pixWriteStreamPng(fp, pix, 0.0);
2746 pixDestroy(&pix);
2747 }
2748 return 0;
2749 }
2750
2751
2752 /*!
2753 * \brief pixaWriteMem()
2754 *
2755 * \param[out] pdata data of serialized pixa
2756 * \param[out] psize size of returned data
2757 * \param[in] pixa
2758 * \return 0 if OK, 1 on error
2759 *
2760 * <pre>
2761 * Notes:
2762 * (1) Serializes a pixa in memory and puts the result in a buffer.
2763 * </pre>
2764 */
2765 l_int32
pixaWriteMem(l_uint8 ** pdata,size_t * psize,PIXA * pixa)2766 pixaWriteMem(l_uint8 **pdata,
2767 size_t *psize,
2768 PIXA *pixa)
2769 {
2770 l_int32 ret;
2771 FILE *fp;
2772
2773 PROCNAME("pixaWriteMem");
2774
2775 if (pdata) *pdata = NULL;
2776 if (psize) *psize = 0;
2777 if (!pdata)
2778 return ERROR_INT("&data not defined", procName, 1);
2779 if (!psize)
2780 return ERROR_INT("&size not defined", procName, 1);
2781 if (!pixa)
2782 return ERROR_INT("pixa not defined", procName, 1);
2783
2784 #if HAVE_FMEMOPEN
2785 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
2786 return ERROR_INT("stream not opened", procName, 1);
2787 ret = pixaWriteStream(fp, pixa);
2788 #else
2789 L_INFO("work-around: writing to a temp file\n", procName);
2790 #ifdef _WIN32
2791 if ((fp = fopenWriteWinTempfile()) == NULL)
2792 return ERROR_INT("tmpfile stream not opened", procName, 1);
2793 #else
2794 if ((fp = tmpfile()) == NULL)
2795 return ERROR_INT("tmpfile stream not opened", procName, 1);
2796 #endif /* _WIN32 */
2797 ret = pixaWriteStream(fp, pixa);
2798 rewind(fp);
2799 *pdata = l_binaryReadStream(fp, psize);
2800 #endif /* HAVE_FMEMOPEN */
2801 fclose(fp);
2802 return ret;
2803 }
2804
2805
2806 /*!
2807 * \brief pixaReadBoth()
2808 *
2809 * \param[in] filename
2810 * \return pixa, or NULL on error
2811 *
2812 * <pre>
2813 * Notes:
2814 * (1) This reads serialized files of either a pixa or a pixacomp,
2815 * and returns a pixa in memory. It requires png and jpeg libraries.
2816 * </pre>
2817 */
2818 PIXA *
pixaReadBoth(const char * filename)2819 pixaReadBoth(const char *filename)
2820 {
2821 char buf[32];
2822 char *sname;
2823 PIXA *pixa;
2824 PIXAC *pac;
2825
2826 PROCNAME("pixaReadBoth");
2827
2828 if (!filename)
2829 return (PIXA *)ERROR_PTR("filename not defined", procName, NULL);
2830
2831 l_getStructStrFromFile(filename, L_STR_NAME, &sname);
2832 if (!sname)
2833 return (PIXA *)ERROR_PTR("struct name not found", procName, NULL);
2834 snprintf(buf, sizeof(buf), "%s", sname);
2835 LEPT_FREE(sname);
2836
2837 if (strcmp(buf, "Pixacomp") == 0) {
2838 if ((pac = pixacompRead(filename)) == NULL)
2839 return (PIXA *)ERROR_PTR("pac not made", procName, NULL);
2840 pixa = pixaCreateFromPixacomp(pac, L_COPY);
2841 pixacompDestroy(&pac);
2842 } else if (strcmp(buf, "Pixa") == 0) {
2843 if ((pixa = pixaRead(filename)) == NULL)
2844 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
2845 } else {
2846 return (PIXA *)ERROR_PTR("invalid file type", procName, NULL);
2847 }
2848 return pixa;
2849 }
2850
2851
2852 /*---------------------------------------------------------------------*
2853 * Pixaa serialized I/O *
2854 *---------------------------------------------------------------------*/
2855 /*!
2856 * \brief pixaaReadFromFiles()
2857 *
2858 * \param[in] dirname directory
2859 * \param[in] substr [optional] substring filter on filenames; can be NULL
2860 * \param[in] first 0-based
2861 * \param[in] nfiles use 0 for everything from %first to the end
2862 * \return paa, or NULL on error or if no pixa files are found.
2863 *
2864 * <pre>
2865 * Notes:
2866 * (1) The files must be serialized pixa files (e.g., *.pa)
2867 * If some files cannot be read, warnings are issued.
2868 * (2) Use %substr to filter filenames in the directory. If
2869 * %substr == NULL, this takes all files.
2870 * (3) After filtering, use %first and %nfiles to select
2871 * a contiguous set of files, that have been lexically
2872 * sorted in increasing order.
2873 * </pre>
2874 */
2875 PIXAA *
pixaaReadFromFiles(const char * dirname,const char * substr,l_int32 first,l_int32 nfiles)2876 pixaaReadFromFiles(const char *dirname,
2877 const char *substr,
2878 l_int32 first,
2879 l_int32 nfiles)
2880 {
2881 char *fname;
2882 l_int32 i, n;
2883 PIXA *pixa;
2884 PIXAA *paa;
2885 SARRAY *sa;
2886
2887 PROCNAME("pixaaReadFromFiles");
2888
2889 if (!dirname)
2890 return (PIXAA *)ERROR_PTR("dirname not defined", procName, NULL);
2891
2892 sa = getSortedPathnamesInDirectory(dirname, substr, first, nfiles);
2893 if (!sa || ((n = sarrayGetCount(sa)) == 0)) {
2894 sarrayDestroy(&sa);
2895 return (PIXAA *)ERROR_PTR("no pixa files found", procName, NULL);
2896 }
2897
2898 paa = pixaaCreate(n);
2899 for (i = 0; i < n; i++) {
2900 fname = sarrayGetString(sa, i, L_NOCOPY);
2901 if ((pixa = pixaRead(fname)) == NULL) {
2902 L_ERROR("pixa not read for %d-th file", procName, i);
2903 continue;
2904 }
2905 pixaaAddPixa(paa, pixa, L_INSERT);
2906 }
2907
2908 sarrayDestroy(&sa);
2909 return paa;
2910 }
2911
2912
2913 /*!
2914 * \brief pixaaRead()
2915 *
2916 * \param[in] filename
2917 * \return paa, or NULL on error
2918 *
2919 * <pre>
2920 * Notes:
2921 * (1) The pix are stored in the file as png.
2922 * If the png library is not linked, this will fail.
2923 * </pre>
2924 */
2925 PIXAA *
pixaaRead(const char * filename)2926 pixaaRead(const char *filename)
2927 {
2928 FILE *fp;
2929 PIXAA *paa;
2930
2931 PROCNAME("pixaaRead");
2932
2933 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
2934 return (PIXAA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2935 #endif /* !HAVE_LIBPNG */
2936
2937 if (!filename)
2938 return (PIXAA *)ERROR_PTR("filename not defined", procName, NULL);
2939
2940 if ((fp = fopenReadStream(filename)) == NULL)
2941 return (PIXAA *)ERROR_PTR("stream not opened", procName, NULL);
2942 paa = pixaaReadStream(fp);
2943 fclose(fp);
2944 if (!paa)
2945 return (PIXAA *)ERROR_PTR("paa not read", procName, NULL);
2946 return paa;
2947 }
2948
2949
2950 /*!
2951 * \brief pixaaReadStream()
2952 *
2953 * \param[in] fp file stream
2954 * \return paa, or NULL on error
2955 *
2956 * <pre>
2957 * Notes:
2958 * (1) The pix are stored in the file as png.
2959 * If the png library is not linked, this will fail.
2960 * </pre>
2961 */
2962 PIXAA *
pixaaReadStream(FILE * fp)2963 pixaaReadStream(FILE *fp)
2964 {
2965 l_int32 n, i, version;
2966 l_int32 ignore;
2967 BOXA *boxa;
2968 PIXA *pixa;
2969 PIXAA *paa;
2970
2971 PROCNAME("pixaaReadStream");
2972
2973 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
2974 return (PIXAA *)ERROR_PTR("no libpng: can't read data", procName, NULL);
2975 #endif /* !HAVE_LIBPNG */
2976
2977 if (!fp)
2978 return (PIXAA *)ERROR_PTR("stream not defined", procName, NULL);
2979
2980 if (fscanf(fp, "\nPixaa Version %d\n", &version) != 1)
2981 return (PIXAA *)ERROR_PTR("not a pixaa file", procName, NULL);
2982 if (version != PIXAA_VERSION_NUMBER)
2983 return (PIXAA *)ERROR_PTR("invalid pixaa version", procName, NULL);
2984 if (fscanf(fp, "Number of pixa = %d\n", &n) != 1)
2985 return (PIXAA *)ERROR_PTR("not a pixaa file", procName, NULL);
2986
2987 if ((paa = pixaaCreate(n)) == NULL)
2988 return (PIXAA *)ERROR_PTR("paa not made", procName, NULL);
2989 if ((boxa = boxaReadStream(fp)) == NULL) {
2990 pixaaDestroy(&paa);
2991 return (PIXAA *)ERROR_PTR("boxa not made", procName, NULL);
2992 }
2993 boxaDestroy(&paa->boxa);
2994 paa->boxa = boxa;
2995
2996 for (i = 0; i < n; i++) {
2997 if ((fscanf(fp, "\n\n --------------- pixa[%d] ---------------\n",
2998 &ignore)) != 1) {
2999 pixaaDestroy(&paa);
3000 return (PIXAA *)ERROR_PTR("text reading", procName, NULL);
3001 }
3002 if ((pixa = pixaReadStream(fp)) == NULL) {
3003 pixaaDestroy(&paa);
3004 return (PIXAA *)ERROR_PTR("pixa not read", procName, NULL);
3005 }
3006 pixaaAddPixa(paa, pixa, L_INSERT);
3007 }
3008
3009 return paa;
3010 }
3011
3012
3013 /*!
3014 * \brief pixaaReadMem()
3015 *
3016 * \param[in] data of serialized pixaa
3017 * \param[in] size of data in bytes
3018 * \return paa, or NULL on error
3019 */
3020 PIXAA *
pixaaReadMem(const l_uint8 * data,size_t size)3021 pixaaReadMem(const l_uint8 *data,
3022 size_t size)
3023 {
3024 FILE *fp;
3025 PIXAA *paa;
3026
3027 PROCNAME("paaReadMem");
3028
3029 if (!data)
3030 return (PIXAA *)ERROR_PTR("data not defined", procName, NULL);
3031 if ((fp = fopenReadFromMemory(data, size)) == NULL)
3032 return (PIXAA *)ERROR_PTR("stream not opened", procName, NULL);
3033
3034 paa = pixaaReadStream(fp);
3035 fclose(fp);
3036 if (!paa) L_ERROR("paa not read\n", procName);
3037 return paa;
3038 }
3039
3040
3041 /*!
3042 * \brief pixaaWrite()
3043 *
3044 * \param[in] filename
3045 * \param[in] paa
3046 * \return 0 if OK, 1 on error
3047 *
3048 * <pre>
3049 * Notes:
3050 * (1) The pix are stored in the file as png.
3051 * If the png library is not linked, this will fail.
3052 * </pre>
3053 */
3054 l_int32
pixaaWrite(const char * filename,PIXAA * paa)3055 pixaaWrite(const char *filename,
3056 PIXAA *paa)
3057 {
3058 l_int32 ret;
3059 FILE *fp;
3060
3061 PROCNAME("pixaaWrite");
3062
3063 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
3064 return ERROR_INT("no libpng: can't read data", procName, 1);
3065 #endif /* !HAVE_LIBPNG */
3066
3067 if (!filename)
3068 return ERROR_INT("filename not defined", procName, 1);
3069 if (!paa)
3070 return ERROR_INT("paa not defined", procName, 1);
3071
3072 if ((fp = fopenWriteStream(filename, "wb")) == NULL)
3073 return ERROR_INT("stream not opened", procName, 1);
3074 ret = pixaaWriteStream(fp, paa);
3075 fclose(fp);
3076 if (ret)
3077 return ERROR_INT("paa not written to stream", procName, 1);
3078 return 0;
3079 }
3080
3081
3082 /*!
3083 * \brief pixaaWriteStream()
3084 *
3085 * \param[in] fp file stream opened for "wb"
3086 * \param[in] paa
3087 * \return 0 if OK, 1 on error
3088 *
3089 * <pre>
3090 * Notes:
3091 * (1) The pix are stored in the file as png.
3092 * If the png library is not linked, this will fail.
3093 * </pre>
3094 */
3095 l_int32
pixaaWriteStream(FILE * fp,PIXAA * paa)3096 pixaaWriteStream(FILE *fp,
3097 PIXAA *paa)
3098 {
3099 l_int32 n, i;
3100 PIXA *pixa;
3101
3102 PROCNAME("pixaaWriteStream");
3103
3104 #if !HAVE_LIBPNG /* defined in environ.h and config_auto.h */
3105 return ERROR_INT("no libpng: can't read data", procName, 1);
3106 #endif /* !HAVE_LIBPNG */
3107
3108 if (!fp)
3109 return ERROR_INT("stream not defined", procName, 1);
3110 if (!paa)
3111 return ERROR_INT("paa not defined", procName, 1);
3112
3113 n = pixaaGetCount(paa, NULL);
3114 fprintf(fp, "\nPixaa Version %d\n", PIXAA_VERSION_NUMBER);
3115 fprintf(fp, "Number of pixa = %d\n", n);
3116 boxaWriteStream(fp, paa->boxa);
3117 for (i = 0; i < n; i++) {
3118 if ((pixa = pixaaGetPixa(paa, i, L_CLONE)) == NULL)
3119 return ERROR_INT("pixa not found", procName, 1);
3120 fprintf(fp, "\n\n --------------- pixa[%d] ---------------\n", i);
3121 pixaWriteStream(fp, pixa);
3122 pixaDestroy(&pixa);
3123 }
3124 return 0;
3125 }
3126
3127
3128 /*!
3129 * \brief pixaaWriteMem()
3130 *
3131 * \param[out] pdata data of serialized pixaa
3132 * \param[out] psize size of returned data
3133 * \param[in] paa
3134 * \return 0 if OK, 1 on error
3135 *
3136 * <pre>
3137 * Notes:
3138 * (1) Serializes a pixaa in memory and puts the result in a buffer.
3139 * </pre>
3140 */
3141 l_int32
pixaaWriteMem(l_uint8 ** pdata,size_t * psize,PIXAA * paa)3142 pixaaWriteMem(l_uint8 **pdata,
3143 size_t *psize,
3144 PIXAA *paa)
3145 {
3146 l_int32 ret;
3147 FILE *fp;
3148
3149 PROCNAME("pixaaWriteMem");
3150
3151 if (pdata) *pdata = NULL;
3152 if (psize) *psize = 0;
3153 if (!pdata)
3154 return ERROR_INT("&data not defined", procName, 1);
3155 if (!psize)
3156 return ERROR_INT("&size not defined", procName, 1);
3157 if (!paa)
3158 return ERROR_INT("paa not defined", procName, 1);
3159
3160 #if HAVE_FMEMOPEN
3161 if ((fp = open_memstream((char **)pdata, psize)) == NULL)
3162 return ERROR_INT("stream not opened", procName, 1);
3163 ret = pixaaWriteStream(fp, paa);
3164 #else
3165 L_INFO("work-around: writing to a temp file\n", procName);
3166 #ifdef _WIN32
3167 if ((fp = fopenWriteWinTempfile()) == NULL)
3168 return ERROR_INT("tmpfile stream not opened", procName, 1);
3169 #else
3170 if ((fp = tmpfile()) == NULL)
3171 return ERROR_INT("tmpfile stream not opened", procName, 1);
3172 #endif /* _WIN32 */
3173 ret = pixaaWriteStream(fp, paa);
3174 rewind(fp);
3175 *pdata = l_binaryReadStream(fp, psize);
3176 #endif /* HAVE_FMEMOPEN */
3177 fclose(fp);
3178 return ret;
3179 }
3180
3181