/*====================================================================* - Copyright (C) 2001 Leptonica. All rights reserved. - This software is distributed in the hope that it will be - useful, but with NO WARRANTY OF ANY KIND. - No author or distributor accepts responsibility to anyone for the - consequences of using this software, or for whether it serves any - particular purpose or works at all, unless he or she says so in - writing. Everyone is granted permission to copy, modify and - redistribute this source code, for commercial or non-commercial - purposes, with the following restrictions: (1) the origin of this - source code must not be misrepresented; (2) modified versions must - be plainly marked as such; and (3) this notice may not be removed - or altered from any source or modified source distribution. *====================================================================*/ /* * boxbasic.c * * Basic 'class' functions for box, boxa and boxaa, * including accessors and serialization. * * Box creation, copy, clone, destruction * BOX *boxCreate() * BOX *boxCopy() * BOX *boxClone() * void boxDestroy() * * Box accessors * l_int32 boxGetGeometry() * l_int32 boxSetGeometry() * l_int32 boxGetRefcount() * l_int32 boxChangeRefcount() * * Boxa creation, copy, destruction * BOXA *boxaCreate() * BOXA *boxaCopy() * void boxaDestroy() * * Boxa array extension * l_int32 boxaAddBox() * l_int32 boxaExtendArray() * * Boxa accessors * l_int32 boxaGetCount() * l_int32 boxaGetBox() * l_int32 boxaGetBoxGeometry() * * Boxa array modifiers * l_int32 boxaReplaceBox() * l_int32 boxaInsertBox() * l_int32 boxaRemoveBox() * * Boxaa creation, copy, destruction * BOXAA *boxaaCreate() * BOXAA *boxaaCopy() * void boxaaDestroy() * * Boxaa array extension * l_int32 boxaaAddBoxa() * l_int32 boxaaExtendArray() * * Boxaa accessors * l_int32 boxaaGetCount() * l_int32 boxaaGetBoxCount() * BOXA *boxaaGetBoxa() * * Boxa array modifiers * l_int32 boxaaReplaceBoxa() * l_int32 boxaaInsertBoxa() * l_int32 boxaaRemoveBoxa() * l_int32 boxaaAddBox() * * Boxaa serialized I/O * BOXAA *boxaaRead() * BOXAA *boxaaReadStream() * l_int32 boxaaWrite() * l_int32 boxaaWriteStream() * * Boxa serialized I/O * BOXA *boxaRead() * BOXA *boxaReadStream() * l_int32 boxaWrite() * l_int32 boxaWriteStream() * * Box print (for debug) * l_int32 boxPrintStreamInfo() * * Backward compatibility old boxaa read functions * BOXAA *boxaaReadVersion2() * BOXAA *boxaaReadStreamVersion2() */ #include #include #include #include "allheaders.h" static const l_int32 INITIAL_PTR_ARRAYSIZE = 20; /* n'import quoi */ /*---------------------------------------------------------------------* * Box creation, destruction and copy * *---------------------------------------------------------------------*/ /*! * boxCreate() * * Input: x, y, width, height * Return: box, or null on error * * Notes: * (1) This clips the box to the +quad. If no part of the * box is in the +quad, this returns NULL. */ BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h) { BOX *box; PROCNAME("boxCreate"); if (w <= 0 || h <= 0) return (BOX *)ERROR_PTR("w and h not both > 0", procName, NULL); if (x < 0) { /* take part in +quad */ w = w + x; x = 0; if (w <= 0) return (BOX *)ERROR_PTR("x < 0 and box off +quad", procName, NULL); } if (y < 0) { /* take part in +quad */ h = h + y; y = 0; if (h <= 0) return (BOX *)ERROR_PTR("y < 0 and box off +quad", procName, NULL); } if ((box = (BOX *)CALLOC(1, sizeof(BOX))) == NULL) return (BOX *)ERROR_PTR("box not made", procName, NULL); boxSetGeometry(box, x, y, w, h); box->refcount = 1; return box; } /*! * boxCopy() * * Input: box * Return: copy of box, or null on error */ BOX * boxCopy(BOX *box) { BOX *boxc; PROCNAME("boxCopy"); if (!box) return (BOX *)ERROR_PTR("box not defined", procName, NULL); boxc = boxCreate(box->x, box->y, box->w, box->h); return boxc; } /*! * boxClone() * * Input: box * Return: ptr to same box, or null on error */ BOX * boxClone(BOX *box) { PROCNAME("boxClone"); if (!box) return (BOX *)ERROR_PTR("box not defined", procName, NULL); boxChangeRefcount(box, 1); return box; } /*! * boxDestroy() * * Input: &box () * Return: void * * Notes: * (1) Decrements the ref count and, if 0, destroys the box. * (2) Always nulls the input ptr. */ void boxDestroy(BOX **pbox) { BOX *box; PROCNAME("boxDestroy"); if (pbox == NULL) { L_WARNING("ptr address is null!", procName); return; } if ((box = *pbox) == NULL) return; boxChangeRefcount(box, -1); if (boxGetRefcount(box) <= 0) FREE(box); *pbox = NULL; return; } /*---------------------------------------------------------------------* * Box accessors * *---------------------------------------------------------------------*/ /*! * boxGetGeometry() * * Input: box * &x, &y, &w, &h (; each can be null) * Return: 0 if OK, 1 on error */ l_int32 boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph) { PROCNAME("boxGetGeometry"); if (px) *px = 0; if (py) *py = 0; if (pw) *pw = 0; if (ph) *ph = 0; if (!box) return ERROR_INT("box not defined", procName, 1); if (px) *px = box->x; if (py) *py = box->y; if (pw) *pw = box->w; if (ph) *ph = box->h; return 0; } /*! * boxSetGeometry() * * Input: box * x, y, w, h (use -1 to leave unchanged) * Return: 0 if OK, 1 on error */ l_int32 boxSetGeometry(BOX *box, l_int32 x, l_int32 y, l_int32 w, l_int32 h) { PROCNAME("boxSetGeometry"); if (!box) return ERROR_INT("box not defined", procName, 1); if (x != -1) box->x = x; if (y != -1) box->y = y; if (w != -1) box->w = w; if (h != -1) box->h = h; return 0; } l_int32 boxGetRefcount(BOX *box) { PROCNAME("boxGetRefcount"); if (!box) return ERROR_INT("box not defined", procName, UNDEF); return box->refcount; } l_int32 boxChangeRefcount(BOX *box, l_int32 delta) { PROCNAME("boxChangeRefcount"); if (!box) return ERROR_INT("box not defined", procName, 1); box->refcount += delta; return 0; } /*---------------------------------------------------------------------* * Boxa creation, destruction, copy, extension * *---------------------------------------------------------------------*/ /*! * boxaCreate() * * Input: n (initial number of ptrs) * Return: boxa, or null on error */ BOXA * boxaCreate(l_int32 n) { BOXA *boxa; PROCNAME("boxaCreate"); if (n <= 0) n = INITIAL_PTR_ARRAYSIZE; if ((boxa = (BOXA *)CALLOC(1, sizeof(BOXA))) == NULL) return (BOXA *)ERROR_PTR("boxa not made", procName, NULL); boxa->n = 0; boxa->nalloc = n; boxa->refcount = 1; if ((boxa->box = (BOX **)CALLOC(n, sizeof(BOX *))) == NULL) return (BOXA *)ERROR_PTR("boxa ptrs not made", procName, NULL); return boxa; } /*! * boxaCopy() * * Input: boxa * copyflag (L_COPY, L_CLONE, L_COPY_CLONE) * Return: new boxa, or null on error * * Notes: * (1) See pix.h for description of the copyflag. * (2) The copy-clone makes a new boxa that holds clones of each box. */ BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag) { l_int32 i; BOX *boxc; BOXA *boxac; PROCNAME("boxaCopy"); if (!boxa) return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL); if (copyflag == L_CLONE) { boxa->refcount++; return boxa; } if (copyflag != L_COPY && copyflag != L_COPY_CLONE) return (BOXA *)ERROR_PTR("invalid copyflag", procName, NULL); if ((boxac = boxaCreate(boxa->nalloc)) == NULL) return (BOXA *)ERROR_PTR("boxac not made", procName, NULL); for (i = 0; i < boxa->n; i++) { if (copyflag == L_COPY) boxc = boxaGetBox(boxa, i, L_COPY); else /* copy-clone */ boxc = boxaGetBox(boxa, i, L_CLONE); boxaAddBox(boxac, boxc, L_INSERT); } return boxac; } /*! * boxaDestroy() * * Input: &boxa () * Return: void * * Note: * - Decrements the ref count and, if 0, destroys the boxa. * - Always nulls the input ptr. */ void boxaDestroy(BOXA **pboxa) { l_int32 i; BOXA *boxa; PROCNAME("boxaDestroy"); if (pboxa == NULL) { L_WARNING("ptr address is null!", procName); return; } if ((boxa = *pboxa) == NULL) return; /* Decrement the ref count. If it is 0, destroy the boxa. */ boxa->refcount--; if (boxa->refcount <= 0) { for (i = 0; i < boxa->n; i++) boxDestroy(&boxa->box[i]); FREE(boxa->box); FREE(boxa); } *pboxa = NULL; return; } /*! * boxaAddBox() * * Input: boxa * box (to be added) * copyflag (L_INSERT, L_COPY, L_CLONE) * Return: 0 if OK, 1 on error */ l_int32 boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag) { l_int32 n; BOX *boxc; PROCNAME("boxaAddBox"); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); if (!box) return ERROR_INT("box not defined", procName, 1); if (copyflag == L_INSERT) boxc = box; else if (copyflag == L_COPY) boxc = boxCopy(box); else if (copyflag == L_CLONE) boxc = boxClone(box); else return ERROR_INT("invalid copyflag", procName, 1); if (!boxc) return ERROR_INT("boxc not made", procName, 1); n = boxaGetCount(boxa); if (n >= boxa->nalloc) boxaExtendArray(boxa); boxa->box[n] = boxc; boxa->n++; return 0; } /*! * boxaExtendArray() * * Input: boxa * Return: 0 if OK; 1 on error */ l_int32 boxaExtendArray(BOXA *boxa) { PROCNAME("boxaExtendArray"); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); if ((boxa->box = (BOX **)reallocNew((void **)&boxa->box, sizeof(BOX *) * boxa->nalloc, 2 * sizeof(BOX *) * boxa->nalloc)) == NULL) return ERROR_INT("new ptr array not returned", procName, 1); boxa->nalloc = 2 * boxa->nalloc; return 0; } /*---------------------------------------------------------------------* * Boxa accessors * *---------------------------------------------------------------------*/ /*! * boxaGetCount() * * Input: boxa * Return: count, or 0 on error */ l_int32 boxaGetCount(BOXA *boxa) { PROCNAME("boxaGetCount"); if (!boxa) return ERROR_INT("boxa not defined", procName, 0); return boxa->n; } /*! * boxaGetBox() * * Input: boxa * index (to the index-th box) * accessflag (L_COPY or L_CLONE) * Return: box, or null on error */ BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag) { PROCNAME("boxaGetBox"); if (!boxa) return (BOX *)ERROR_PTR("boxa not defined", procName, NULL); if (index < 0 || index >= boxa->n) return (BOX *)ERROR_PTR("index not valid", procName, NULL); if (accessflag == L_COPY) return boxCopy(boxa->box[index]); else if (accessflag == L_CLONE) return boxClone(boxa->box[index]); else return (BOX *)ERROR_PTR("invalid accessflag", procName, NULL); } /*! * boxaGetBoxGeometry() * * Input: boxa * index (to the index-th box) * &x, &y, &w, &h (; each can be null) * Return: 0 if OK, 1 on error */ l_int32 boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph) { BOX *box; PROCNAME("boxaGetBoxGeometry"); if (px) *px = 0; if (py) *py = 0; if (pw) *pw = 0; if (ph) *ph = 0; if (!boxa) return ERROR_INT("boxa not defined", procName, 1); if (index < 0 || index >= boxa->n) return ERROR_INT("index not valid", procName, 1); if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL) return ERROR_INT("box not found!", procName, 1); boxGetGeometry(box, px, py, pw, ph); boxDestroy(&box); return 0; } /*---------------------------------------------------------------------* * Boxa array modifiers * *---------------------------------------------------------------------*/ /*! * boxaReplaceBox() * * Input: boxa * index (to the index-th box) * box (insert to replace existing one) * Return: 0 if OK, 1 on error * * Notes: * (1) In-place replacement of one box. * (2) The previous box at that location is destroyed. */ l_int32 boxaReplaceBox(BOXA *boxa, l_int32 index, BOX *box) { PROCNAME("boxaReplaceBox"); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); if (index < 0 || index >= boxa->n) return ERROR_INT("index not valid", procName, 1); if (!box) return ERROR_INT("box not defined", procName, 1); boxDestroy(&(boxa->box[index])); boxa->box[index] = box; return 0; } /*! * boxaInsertBox() * * Input: boxa * index (location in boxa to insert new value) * box (new box to be inserted) * Return: 0 if OK, 1 on error * * Notes: * (1) This shifts box[i] --> box[i + 1] for all i >= index, * and then inserts box as box[index]. * (2) To insert at the beginning of the array, set index = 0. * (3) To append to the array, it's easier to use boxaAddBox(). * (4) This should not be used repeatedly to insert into large arrays, * because the function is O(n). */ l_int32 boxaInsertBox(BOXA *boxa, l_int32 index, BOX *box) { l_int32 i, n; BOX **array; PROCNAME("boxaInsertBox"); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); n = boxaGetCount(boxa); if (index < 0 || index > n) return ERROR_INT("index not in {0...n}", procName, 1); if (!box) return ERROR_INT("box not defined", procName, 1); if (n >= boxa->nalloc) boxaExtendArray(boxa); array = boxa->box; boxa->n++; for (i = n; i > index; i--) array[i] = array[i - 1]; array[index] = box; return 0; } /*! * boxaRemoveBox() * * Input: boxa * index (of box to be removed) * Return: 0 if OK, 1 on error * * Notes: * (1) This removes box[index] and then shifts * box[i] --> box[i - 1] for all i > index. * (2) It should not be used repeatedly to remove boxes from * large arrays, because the function is O(n). */ l_int32 boxaRemoveBox(BOXA *boxa, l_int32 index) { l_int32 i, n; BOX **array; PROCNAME("boxaRemoveBox"); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); n = boxaGetCount(boxa); if (index < 0 || index >= n) return ERROR_INT("index not in {0...n - 1}", procName, 1); array = boxa->box; boxDestroy(&array[index]); for (i = index + 1; i < n; i++) array[i - 1] = array[i]; array[n - 1] = NULL; boxa->n--; return 0; } /*--------------------------------------------------------------------------* * Boxaa creation, destruction * *--------------------------------------------------------------------------*/ /*! * boxaaCreate() * * Input: size of boxa ptr array to be alloc'd (0 for default) * Return: baa, or null on error */ BOXAA * boxaaCreate(l_int32 n) { BOXAA *baa; PROCNAME("boxaaCreate"); if (n <= 0) n = INITIAL_PTR_ARRAYSIZE; if ((baa = (BOXAA *)CALLOC(1, sizeof(BOXAA))) == NULL) return (BOXAA *)ERROR_PTR("baa not made", procName, NULL); if ((baa->boxa = (BOXA **)CALLOC(n, sizeof(BOXA *))) == NULL) return (BOXAA *)ERROR_PTR("boxa ptr array not made", procName, NULL); baa->nalloc = n; baa->n = 0; return baa; } /*! * boxaaCopy() * * Input: baas (input boxaa to be copied) * copyflag (L_COPY, L_CLONE) * Return: baad (new boxaa, composed of copies or clones of the boxa * in baas), or null on error * * Notes: * (1) L_COPY makes a copy of each boxa in baas. * L_CLONE makes a clone of each boxa in baas. */ BOXAA * boxaaCopy(BOXAA *baas, l_int32 copyflag) { l_int32 i, n; BOXA *boxa; BOXAA *baad; PROCNAME("boxaaCopy"); if (!baas) return (BOXAA *)ERROR_PTR("baas not defined", procName, NULL); if (copyflag != L_COPY && copyflag != L_CLONE) return (BOXAA *)ERROR_PTR("invalid copyflag", procName, NULL); n = boxaaGetCount(baas); baad = boxaaCreate(n); for (i = 0; i < n; i++) { boxa = boxaaGetBoxa(baas, i, copyflag); boxaaAddBoxa(baad, boxa, L_INSERT); } return baad; } /*! * boxaaDestroy() * * Input: &boxaa () * Return: void */ void boxaaDestroy(BOXAA **pbaa) { l_int32 i; BOXAA *baa; PROCNAME("boxaaDestroy"); if (pbaa == NULL) { L_WARNING("ptr address is NULL!", procName); return; } if ((baa = *pbaa) == NULL) return; for (i = 0; i < baa->n; i++) boxaDestroy(&baa->boxa[i]); FREE(baa->boxa); FREE(baa); *pbaa = NULL; return; } /*--------------------------------------------------------------------------* * Add Boxa to Boxaa * *--------------------------------------------------------------------------*/ /*! * boxaaAddBoxa() * * Input: boxaa * boxa (to be added) * copyflag (L_INSERT, L_COPY, L_CLONE) * Return: 0 if OK, 1 on error */ l_int32 boxaaAddBoxa(BOXAA *baa, BOXA *ba, l_int32 copyflag) { l_int32 n; BOXA *bac; PROCNAME("boxaaAddBoxa"); if (!baa) return ERROR_INT("baa not defined", procName, 1); if (!ba) return ERROR_INT("ba not defined", procName, 1); if (copyflag != L_INSERT && copyflag != L_COPY && copyflag != L_CLONE) return ERROR_INT("invalid copyflag", procName, 1); if (copyflag == L_INSERT) bac = ba; else bac = boxaCopy(ba, copyflag); n = boxaaGetCount(baa); if (n >= baa->nalloc) boxaaExtendArray(baa); baa->boxa[n] = bac; baa->n++; return 0; } /*! * boxaaExtendArray() * * Input: boxaa * Return: 0 if OK, 1 on error */ l_int32 boxaaExtendArray(BOXAA *baa) { PROCNAME("boxaaExtendArray"); if (!baa) return ERROR_INT("baa not defined", procName, 1); if ((baa->boxa = (BOXA **)reallocNew((void **)&baa->boxa, sizeof(BOXA *) * baa->nalloc, 2 * sizeof(BOXA *) * baa->nalloc)) == NULL) return ERROR_INT("new ptr array not returned", procName, 1); baa->nalloc *= 2; return 0; } /*----------------------------------------------------------------------* * Boxaa accessors * *----------------------------------------------------------------------*/ /*! * boxaaGetCount() * * Input: boxaa * Return: count (number of boxa), or 0 if no boxa or on error */ l_int32 boxaaGetCount(BOXAA *baa) { PROCNAME("boxaaGetCount"); if (!baa) return ERROR_INT("baa not defined", procName, 0); return baa->n; } /*! * boxaaGetBoxCount() * * Input: boxaa * Return: count (number of boxes), or 0 if no boxes or on error */ l_int32 boxaaGetBoxCount(BOXAA *baa) { BOXA *boxa; l_int32 n, sum, i; PROCNAME("boxaaGetBoxCount"); if (!baa) return ERROR_INT("baa not defined", procName, 0); n = boxaaGetCount(baa); for (sum = 0, i = 0; i < n; i++) { boxa = boxaaGetBoxa(baa, i, L_CLONE); sum += boxaGetCount(boxa); boxaDestroy(&boxa); } return sum; } /*! * boxaaGetBoxa() * * Input: boxaa * index (to the index-th boxa) * accessflag (L_COPY or L_CLONE) * Return: boxa, or null on error */ BOXA * boxaaGetBoxa(BOXAA *baa, l_int32 index, l_int32 accessflag) { l_int32 n; PROCNAME("boxaaGetBoxa"); if (!baa) return (BOXA *)ERROR_PTR("baa not defined", procName, NULL); n = boxaaGetCount(baa); if (index < 0 || index >= n) return (BOXA *)ERROR_PTR("index not valid", procName, NULL); if (accessflag != L_COPY && accessflag != L_CLONE) return (BOXA *)ERROR_PTR("invalid accessflag", procName, NULL); return boxaCopy(baa->boxa[index], accessflag); } /*! * boxaaReplaceBoxa() * * Input: boxaa * index (to the index-th boxa) * boxa (insert and replace any existing one) * Return: 0 if OK, 1 on error * * Notes: * (1) Any existing boxa is destroyed, and the input one * is inserted in its place. * (2) If the index is invalid, return 1 (error) */ l_int32 boxaaReplaceBoxa(BOXAA *baa, l_int32 index, BOXA *boxa) { l_int32 n; PROCNAME("boxaaReplaceBoxa"); if (!baa) return ERROR_INT("baa not defined", procName, 1); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); n = boxaaGetCount(baa); if (index < 0 || index >= n) return ERROR_INT("index not valid", procName, 1); boxaDestroy(&baa->boxa[index]); baa->boxa[index] = boxa; return 0; } /*! * boxaaInsertBoxa() * * Input: boxaa * index (location in boxaa to insert new boxa) * boxa (new boxa to be inserted) * Return: 0 if OK, 1 on error * * Notes: * (1) This shifts boxa[i] --> boxa[i + 1] for all i >= index, * and then inserts boxa as boxa[index]. * (2) To insert at the beginning of the array, set index = 0. * (3) To append to the array, it's easier to use boxaaAddBoxa(). * (4) This should not be used repeatedly to insert into large arrays, * because the function is O(n). */ l_int32 boxaaInsertBoxa(BOXAA *baa, l_int32 index, BOXA *boxa) { l_int32 i, n; BOXA **array; PROCNAME("boxaaInsertBoxa"); if (!baa) return ERROR_INT("baa not defined", procName, 1); n = boxaaGetCount(baa); if (index < 0 || index > n) return ERROR_INT("index not in {0...n}", procName, 1); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); if (n >= baa->nalloc) boxaaExtendArray(baa); array = baa->boxa; baa->n++; for (i = n; i > index; i--) array[i] = array[i - 1]; array[index] = boxa; return 0; } /*! * boxaaRemoveBoxa() * * Input: boxaa * index (of the boxa to be removed) * Return: 0 if OK, 1 on error * * Notes: * (1) This removes boxa[index] and then shifts * boxa[i] --> boxa[i - 1] for all i > index. * (2) The removed boxaa is destroyed. * (2) This should not be used repeatedly on large arrays, * because the function is O(n). */ l_int32 boxaaRemoveBoxa(BOXAA *baa, l_int32 index) { l_int32 i, n; BOXA **array; PROCNAME("boxaaRemoveBox"); if (!baa) return ERROR_INT("baa not defined", procName, 1); n = boxaaGetCount(baa); if (index < 0 || index >= n) return ERROR_INT("index not valid", procName, 1); array = baa->boxa; boxaDestroy(&array[index]); for (i = index + 1; i < n; i++) array[i - 1] = array[i]; array[n - 1] = NULL; baa->n--; return 0; } /*! * boxaaAddBox() * * Input: boxaa * index (of boxa with boxaa) * box (to be added) * accessflag (L_INSERT, L_COPY or L_CLONE) * Return: 0 if OK, 1 on error * * Notes: * (1) Adds to an existing boxa only. */ l_int32 boxaaAddBox(BOXAA *baa, l_int32 index, BOX *box, l_int32 accessflag) { l_int32 n; BOXA *boxa; PROCNAME("boxaaAddBox"); if (!baa) return ERROR_INT("baa not defined", procName, 1); n = boxaaGetCount(baa); if (index < 0 || index >= n) return ERROR_INT("index not valid", procName, 1); if (accessflag != L_INSERT && accessflag != L_COPY && accessflag != L_CLONE) return ERROR_INT("invalid accessflag", procName, 1); boxa = boxaaGetBoxa(baa, index, L_CLONE); boxaAddBox(boxa, box, accessflag); boxaDestroy(&boxa); return 0; } /*---------------------------------------------------------------------* * Boxaa serialized I/O * *---------------------------------------------------------------------*/ /*! * boxaaRead() * * Input: filename * Return: boxaa, or null on error */ BOXAA * boxaaRead(const char *filename) { FILE *fp; BOXAA *baa; PROCNAME("boxaaRead"); if (!filename) return (BOXAA *)ERROR_PTR("filename not defined", procName, NULL); if ((fp = fopenReadStream(filename)) == NULL) return (BOXAA *)ERROR_PTR("stream not opened", procName, NULL); if ((baa = boxaaReadStream(fp)) == NULL) { fclose(fp); return (BOXAA *)ERROR_PTR("boxaa not read", procName, NULL); } fclose(fp); return baa; } /*! * boxaaReadStream() * * Input: stream * Return: boxaa, or null on error */ BOXAA * boxaaReadStream(FILE *fp) { l_int32 n, i, x, y, w, h, version; l_int32 ignore; BOXA *boxa; BOXAA *baa; PROCNAME("boxaaReadStream"); if (!fp) return (BOXAA *)ERROR_PTR("stream not defined", procName, NULL); if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1) return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL); if (version != BOXAA_VERSION_NUMBER) return (BOXAA *)ERROR_PTR("invalid boxa version", procName, NULL); if (fscanf(fp, "Number of boxa = %d\n", &n) != 1) return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL); if ((baa = boxaaCreate(n)) == NULL) return (BOXAA *)ERROR_PTR("boxaa not made", procName, NULL); for (i = 0; i < n; i++) { if (fscanf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d", &ignore, &x, &y, &w, &h) != 5) return (BOXAA *)ERROR_PTR("boxa descr not valid", procName, NULL); if ((boxa = boxaReadStream(fp)) == NULL) return (BOXAA *)ERROR_PTR("boxa not made", procName, NULL); boxaaAddBoxa(baa, boxa, L_INSERT); } return baa; } /*! * boxaaWrite() * * Input: filename * boxaa * Return: 0 if OK, 1 on error */ l_int32 boxaaWrite(const char *filename, BOXAA *baa) { FILE *fp; PROCNAME("boxaaWrite"); if (!filename) return ERROR_INT("filename not defined", procName, 1); if (!baa) return ERROR_INT("baa not defined", procName, 1); if ((fp = fopen(filename, "w")) == NULL) return ERROR_INT("stream not opened", procName, 1); if (boxaaWriteStream(fp, baa)) return ERROR_INT("baa not written to stream", procName, 1); fclose(fp); return 0; } /*! * boxaaWriteStream() * * Input: stream * boxaa * Return: 0 if OK, 1 on error */ l_int32 boxaaWriteStream(FILE *fp, BOXAA *baa) { l_int32 n, i, x, y, w, h; BOX *box; BOXA *boxa; PROCNAME("boxaaWriteStream"); if (!fp) return ERROR_INT("stream not defined", procName, 1); if (!baa) return ERROR_INT("baa not defined", procName, 1); n = boxaaGetCount(baa); fprintf(fp, "\nBoxaa Version %d\n", BOXAA_VERSION_NUMBER); fprintf(fp, "Number of boxa = %d\n", n); for (i = 0; i < n; i++) { if ((boxa = boxaaGetBoxa(baa, i, L_CLONE)) == NULL) return ERROR_INT("boxa not found", procName, 1); boxaGetExtent(boxa, NULL, NULL, &box); boxGetGeometry(box, &x, &y, &w, &h); fprintf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d", i, x, y, w, h); boxaWriteStream(fp, boxa); boxDestroy(&box); boxaDestroy(&boxa); } return 0; } /*---------------------------------------------------------------------* * Boxa serialized I/O * *---------------------------------------------------------------------*/ /*! * boxaRead() * * Input: filename * Return: boxa, or null on error */ BOXA * boxaRead(const char *filename) { FILE *fp; BOXA *boxa; PROCNAME("boxaRead"); if (!filename) return (BOXA *)ERROR_PTR("filename not defined", procName, NULL); if ((fp = fopenReadStream(filename)) == NULL) return (BOXA *)ERROR_PTR("stream not opened", procName, NULL); if ((boxa = boxaReadStream(fp)) == NULL) { fclose(fp); return (BOXA *)ERROR_PTR("boxa not read", procName, NULL); } fclose(fp); return boxa; } /*! * boxaReadStream() * * Input: stream * Return: boxa, or null on error */ BOXA * boxaReadStream(FILE *fp) { l_int32 n, i, x, y, w, h, version; l_int32 ignore; BOX *box; BOXA *boxa; PROCNAME("boxaReadStream"); if (!fp) return (BOXA *)ERROR_PTR("stream not defined", procName, NULL); if (fscanf(fp, "\nBoxa Version %d\n", &version) != 1) return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL); if (version != BOXA_VERSION_NUMBER) return (BOXA *)ERROR_PTR("invalid boxa version", procName, NULL); if (fscanf(fp, "Number of boxes = %d\n", &n) != 1) return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL); if ((boxa = boxaCreate(n)) == NULL) return (BOXA *)ERROR_PTR("boxa not made", procName, NULL); for (i = 0; i < n; i++) { if (fscanf(fp, " Box[%d]: x = %d, y = %d, w = %d, h = %d\n", &ignore, &x, &y, &w, &h) != 5) return (BOXA *)ERROR_PTR("box descr not valid", procName, NULL); if ((box = boxCreate(x, y, w, h)) == NULL) return (BOXA *)ERROR_PTR("box not made", procName, NULL); boxaAddBox(boxa, box, L_INSERT); } return boxa; } /*! * boxaWrite() * * Input: filename * boxa * Return: 0 if OK, 1 on error */ l_int32 boxaWrite(const char *filename, BOXA *boxa) { FILE *fp; PROCNAME("boxaWrite"); if (!filename) return ERROR_INT("filename not defined", procName, 1); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); if ((fp = fopen(filename, "w")) == NULL) return ERROR_INT("stream not opened", procName, 1); if (boxaWriteStream(fp, boxa)) return ERROR_INT("boxa not written to stream", procName, 1); fclose(fp); return 0; } /*! * boxaWriteStream() * * Input: stream * boxa * Return: 0 if OK, 1 on error */ l_int32 boxaWriteStream(FILE *fp, BOXA *boxa) { l_int32 n, i; BOX *box; PROCNAME("boxaWriteStream"); if (!fp) return ERROR_INT("stream not defined", procName, 1); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); n = boxaGetCount(boxa); fprintf(fp, "\nBoxa Version %d\n", BOXA_VERSION_NUMBER); fprintf(fp, "Number of boxes = %d\n", n); for (i = 0; i < n; i++) { if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL) return ERROR_INT("box not found", procName, 1); fprintf(fp, " Box[%d]: x = %d, y = %d, w = %d, h = %d\n", i, box->x, box->y, box->w, box->h); boxDestroy(&box); } return 0; } /*---------------------------------------------------------------------* * Debug printing * *---------------------------------------------------------------------*/ /*! * boxPrintStreamInfo() * * Input: stream * box * Return: 0 if OK, 1 on error * * Notes: * (1) This outputs information about the box, for debugging. * (2) Use serialization functions to write to file if you want * to read the data back. */ l_int32 boxPrintStreamInfo(FILE *fp, BOX *box) { PROCNAME("boxPrintStreamInfo"); if (!fp) return ERROR_INT("stream not defined", procName, 1); if (!box) return ERROR_INT("box not defined", procName, 1); fprintf(fp, " Box x (pixels) = %d\n", box->x); fprintf(fp, " Box y (pixels) = %d\n", box->y); fprintf(fp, " Box width (pixels) = %d\n", box->w); fprintf(fp, " Box height (pixels) = %d\n", box->h); return 0; } /*---------------------------------------------------------------------* * Version for reading v.2 boxaa; kept for backward compatibility * *---------------------------------------------------------------------*/ /*! * boxaaReadVersion2() * * Input: filename * Return: boxaa, or null on error * * Notes: * (1) These old functions only work on version 2 boxaa. * They will go to an archive directory sometime after Sept 2009. * (2) The current format uses BOXAA_VERSION_NUMBER == 3) */ BOXAA * boxaaReadVersion2(const char *filename) { FILE *fp; BOXAA *baa; PROCNAME("boxaaReadVersion2"); if (!filename) return (BOXAA *)ERROR_PTR("filename not defined", procName, NULL); if ((fp = fopenReadStream(filename)) == NULL) return (BOXAA *)ERROR_PTR("stream not opened", procName, NULL); if ((baa = boxaaReadStreamVersion2(fp)) == NULL) { fclose(fp); return (BOXAA *)ERROR_PTR("boxaa not read", procName, NULL); } fclose(fp); return baa; } /*! * boxaaReadStreamVersion2() * * Input: stream * Return: boxaa, or null on error * */ BOXAA * boxaaReadStreamVersion2(FILE *fp) { l_int32 n, i, x, y, w, h, version; l_int32 ignore; BOXA *boxa; BOXAA *baa; PROCNAME("boxaaReadStreamVersion2"); if (!fp) return (BOXAA *)ERROR_PTR("stream not defined", procName, NULL); if (fscanf(fp, "\nBoxaa Version %d\n", &version) != 1) return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL); if (version != 2) { fprintf(stderr, "This is version %d\n", version); return (BOXAA *)ERROR_PTR("Not old version 2", procName, NULL); } if (fscanf(fp, "Number of boxa = %d\n", &n) != 1) return (BOXAA *)ERROR_PTR("not a boxaa file", procName, NULL); if ((baa = boxaaCreate(n)) == NULL) return (BOXAA *)ERROR_PTR("boxaa not made", procName, NULL); for (i = 0; i < n; i++) { if (fscanf(fp, " Boxa[%d]: x = %d, y = %d, w = %d, h = %d\n", &ignore, &x, &y, &w, &h) != 5) return (BOXAA *)ERROR_PTR("boxa descr not valid", procName, NULL); if ((boxa = boxaReadStream(fp)) == NULL) return (BOXAA *)ERROR_PTR("boxa not made", procName, NULL); boxaaAddBoxa(baa, boxa, L_INSERT); } return baa; }