コード例 #1
0
    /* Reconstruction without compaction */
static PIXA *
ReconstructPixa1(L_PTRA  *papix,
                 L_PTRA  *pabox)
{
l_int32  i, imax, nactual;
BOX     *box;
PIX     *pix;
PIXA    *pixat;

    ptraGetMaxIndex(papix, &imax);
    ptraGetActualCount(papix, &nactual);
    fprintf(stderr, "Before removal:  imax = %4d, actual = %4d\n",
            imax, nactual);

    pixat = pixaCreate(imax + 1);
    for (i = 0; i <= imax; i++) {
        pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
        box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
        if (pix) pixaAddPix(pixat, pix, L_INSERT);
        if (box) pixaAddBox(pixat, box, L_INSERT);
    }

    ptraGetMaxIndex(papix, &imax);
    ptraGetActualCount(papix, &nactual);
    fprintf(stderr, "After removal:   imax = %4d, actual = %4d\n\n",
            imax, nactual);

    return pixat;
}
コード例 #2
0
    /* Reconstruction with compaction */
static PIXA *
ReconstructPixa2(L_PTRA  *papix,
                 L_PTRA  *pabox)
{
l_int32  i, imax, nactual;
BOX     *box;
PIX     *pix;
PIXA    *pixat;

    ptraGetMaxIndex(papix, &imax);
    ptraGetActualCount(papix, &nactual);
    fprintf(stderr, "Before removal:    imax = %4d, actual = %4d\n",
            imax, nactual);

        /* Remove half */
    pixat = pixaCreate(imax + 1);
    for (i = 0; i <= imax; i++) {
        if (i % 2 == 0) {
            pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
            box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
            if (pix) pixaAddPix(pixat, pix, L_INSERT);
            if (box) pixaAddBox(pixat, box, L_INSERT);
        }
    }

        /* Compact */
    ptraGetMaxIndex(papix, &imax);
    ptraGetActualCount(papix, &nactual);
    fprintf(stderr, "Before compaction: imax = %4d, actual = %4d\n",
            imax, nactual);
    ptraCompactArray(papix);
    ptraCompactArray(pabox);
    ptraGetMaxIndex(papix, &imax);
    ptraGetActualCount(papix, &nactual);
    fprintf(stderr, "After compaction:  imax = %4d, actual = %4d\n",
            imax, nactual);

        /* Remove the rest (and test compaction with removal) */
    while (1) {
        ptraGetActualCount(papix, &nactual);
        if (nactual == 0) break;

        pix = (PIX *)ptraRemove(papix, 0, L_COMPACTION);
        box = (BOX *)ptraRemove(pabox, 0, L_COMPACTION);
        pixaAddPix(pixat, pix, L_INSERT);
        pixaAddBox(pixat, box, L_INSERT);
    }

    ptraGetMaxIndex(papix, &imax);
    ptraGetActualCount(papix, &nactual);
    fprintf(stderr, "After removal:     imax = %4d, actual = %4d\n\n",
            imax, nactual);

    return pixat;
}
コード例 #3
0
ファイル: ptra.c プロジェクト: 0ximDigital/appsScanner
/*!
 *  ptraReplace()
 *
 *      Input:  ptra
 *              index (element to be replaced)
 *              item  (new generic ptr to a struct; can be null)
 *              freeflag (TRUE to free old item; FALSE to return it)
 *      Return: item  (old item, if it exists and is not freed),
 *                     or null on error
 */
void *
ptraReplace(L_PTRA  *pa,
            l_int32  index,
            void    *item,
            l_int32  freeflag)
{
l_int32  imax;
void    *olditem;

    PROCNAME("ptraReplace");

    if (!pa)
        return (void *)ERROR_PTR("pa not defined", procName, NULL);
    ptraGetMaxIndex(pa, &imax);
    if (index < 0 || index > imax)
        return (void *)ERROR_PTR("index not in [0 ... imax]", procName, NULL);

    olditem = pa->array[index];
    pa->array[index] = item;
    if (!item && olditem)
        pa->nactual--;
    else if (item && !olditem)
        pa->nactual++;

    if (freeflag == FALSE)
        return olditem;

    if (olditem)
        FREE(olditem);
    return NULL;
}
コード例 #4
0
ファイル: ptra.c プロジェクト: mehulsbhatt/MyOCRTEST
/*!
 *  ptraReverse()
 *
 *      Input:  ptra
 *      Return: 0 if OK, 1 on error
 */
l_int32
ptraReverse(L_PTRA *pa) {
    l_int32 i, imax;

    PROCNAME("ptraReverse");

    if (!pa)
        return ERROR_INT("pa not defined", procName, 1);
    ptraGetMaxIndex(pa, &imax);

    for (i = 0; i < (imax + 1) / 2; i++)
        ptraSwap(pa, i, imax - i);
    return 0;
}
コード例 #5
0
ファイル: ptra.c プロジェクト: mehulsbhatt/MyOCRTEST
/*!
 *  ptraRemoveLast()
 *
 *      Input:  ptra
 *      Return: item, or null on error or if the array is empty
 */
void *
ptraRemoveLast(L_PTRA *pa) {
    l_int32 imax;

    PROCNAME("ptraRemoveLast");

    if (!pa)
        return (void *) ERROR_PTR("pa not defined", procName, NULL);

    /* Remove the last item in the array.  No compaction is required. */
    ptraGetMaxIndex(pa, &imax);
    if (imax >= 0)
        return ptraRemove(pa, imax, L_NO_COMPACTION);
    else  /* empty */
        return NULL;
}
コード例 #6
0
ファイル: ptra.c プロジェクト: 0xkasun/Dummy_Tes
/*!
 *  ptraRemove()
 *
 *      Input:  ptra
 *              index (element to be removed)
 *              flag (L_NO_COMPACTION, L_COMPACTION)
 *      Return: item, or null on error
 *
 *  Notes:
 *      (1) If flag == L_NO_COMPACTION, this removes the item and
 *          nulls the ptr on the array.  If it takes the last item
 *          in the array, pa->n is reduced to the next item.
 *      (2) If flag == L_COMPACTION, this compacts the array for
 *          for all i >= index.  It should not be used repeatedly on
 *          large arrays, because compaction is O(n).
 *      (3) The ability to remove without automatic compaction allows
 *          removal with cost O(1).
 */
void *
ptraRemove(L_PTRA  *pa,
           l_int32  index,
           l_int32  flag)
{
l_int32  i, imax, fromend, icurrent;
void    *item;

    PROCNAME("ptraRemove");

    if (!pa)
        return (void *)ERROR_PTR("pa not defined", procName, NULL);
    ptraGetMaxIndex(pa, &imax);
    if (index < 0 || index > imax)
        return (void *)ERROR_PTR("index not in [0 ... imax]", procName, NULL);

    item = pa->array[index];
    if (item)
        pa->nactual--;
    pa->array[index] = NULL;

        /* If we took the last item, need to reduce pa->n */
    fromend = (index == imax);
    if (fromend) {
        for (i = index - 1; i >= 0; i--) {
            if (pa->array[i])
                break;
        }
        pa->imax = i;
        imax = i + 1;
    }

        /* Compact from index to the end of the array */
    if (!fromend && flag == L_COMPACTION) {
        for (icurrent = index, i = index + 1; i <= imax; i++) {
            if (pa->array[i])
                pa->array[icurrent++] = pa->array[i];
        }
        pa->imax = icurrent - 1;
    }
    return item;
}
コード例 #7
0
ファイル: ptra.c プロジェクト: mehulsbhatt/MyOCRTEST
/*!
 *  ptraAdd()
 *
 *      Input:  ptra
 *              item  (generic ptr to a struct)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This adds the element to the next location beyond imax,
 *          which is the largest occupied ptr in the array.  This is
 *          what you expect from a stack, where all ptrs up to and
 *          including imax are occupied, but here the occuption of
 *          items in the array is entirely arbitrary.
 */
l_int32
ptraAdd(L_PTRA *pa,
        void *item) {
    l_int32 imax;

    PROCNAME("ptraAdd");

    if (!pa)
        return ERROR_INT("pa not defined", procName, 1);
    if (!item)
        return ERROR_INT("item not defined", procName, 1);

    ptraGetMaxIndex(pa, &imax);
    if (imax >= pa->nalloc - 1 && ptraExtendArray(pa))
        return ERROR_INT("extension failure", procName, 1);
    pa->array[imax + 1] = (void *) item;
    pa->imax++;
    pa->nactual++;
    return 0;
}
コード例 #8
0
ファイル: ptra.c プロジェクト: mehulsbhatt/MyOCRTEST
/*!
 *  ptraJoin()
 *
 *      Input:  ptra1 (add to this one)
 *              ptra2 (appended to ptra1, and emptied of items; can be null)
 *      Return: 0 if OK, 1 on error
 */
l_int32
ptraJoin(L_PTRA *pa1,
         L_PTRA *pa2) {
    l_int32 i, imax;
    void *item;

    PROCNAME("ptraJoin");

    if (!pa1)
        return ERROR_INT("pa1 not defined", procName, 1);
    if (!pa2)
        return 0;

    ptraGetMaxIndex(pa2, &imax);
    for (i = 0; i <= imax; i++) {
        item = ptraRemove(pa2, i, L_NO_COMPACTION);
        ptraAdd(pa1, item);
    }

    return 0;
}
コード例 #9
0
ファイル: ptra1_reg.c プロジェクト: xmarston/BillRecognizer
static void
CopyPtras(L_PTRA   *papixs,
          L_PTRA   *paboxs,
          L_PTRA  **ppapixd,
          L_PTRA  **ppaboxd)
{
l_int32  i, imax;
BOX     *box;
PIX     *pix;

    ptraGetMaxIndex(papixs, &imax);
    *ppapixd = ptraCreate(imax + 1);
    *ppaboxd = ptraCreate(imax + 1);
    for (i = 0; i <= imax; i++) {
        pix = pixCopy(NULL, (PIX *)ptraGetPtrToItem(papixs, i));
        box = boxCopy((BOX *)ptraGetPtrToItem(paboxs, i));
        ptraAdd(*ppapixd, pix);
        ptraAdd(*ppaboxd, box);
    }
    return;
}
コード例 #10
0
ファイル: ptra.c プロジェクト: mehulsbhatt/MyOCRTEST
/*!
 *  ptraSwap()
 *
 *      Input:  ptra
 *              index1
 *              index2
 *      Return: 0 if OK, 1 on error
 */
l_int32
ptraSwap(L_PTRA *pa,
         l_int32 index1,
         l_int32 index2) {
    l_int32 imax;
    void *item;

    PROCNAME("ptraSwap");

    if (!pa)
        return ERROR_INT("pa not defined", procName, 1);
    if (index1 == index2)
        return 0;
    ptraGetMaxIndex(pa, &imax);
    if (index1 < 0 || index1 > imax || index2 < 0 || index2 > imax)
        return ERROR_INT("invalid index: not in [0 ... imax]", procName, 1);

    item = ptraRemove(pa, index1, L_NO_COMPACTION);
    item = ptraReplace(pa, index2, item, FALSE);
    ptraInsert(pa, index1, item, L_MIN_DOWNSHIFT);
    return 0;
}
コード例 #11
0
ファイル: ptra.c プロジェクト: mehulsbhatt/MyOCRTEST
/*!
 *  ptraCompactArray()
 *
 *      Input:  ptra
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This compacts the items on the array, filling any empty ptrs.
 *      (2) This does not change the size of the array of ptrs.
 */
l_int32
ptraCompactArray(L_PTRA *pa) {
    l_int32 i, imax, nactual, index;

    PROCNAME("ptraCompactArray");

    if (!pa)
        return ERROR_INT("pa not defined", procName, 1);
    ptraGetMaxIndex(pa, &imax);
    ptraGetActualCount(pa, &nactual);
    if (imax + 1 == nactual) return 0;

    /* Compact the array */
    for (i = 0, index = 0; i <= imax; i++) {
        if (pa->array[i])
            pa->array[index++] = pa->array[i];
    }
    pa->imax = index - 1;
    if (nactual != index)
        L_ERROR("index = %d; != nactual\n", procName, index);

    return 0;
}
コード例 #12
0
ファイル: ptra.c プロジェクト: 0ximDigital/appsScanner
/*!
 *  ptraInsert()
 *
 *      Input:  ptra
 *              index (location in ptra to insert new value)
 *              item  (generic ptr to a struct; can be null)
 *              shiftflag (L_AUTO_DOWNSHIFT, L_MIN_DOWNSHIFT, L_FULL_DOWNSHIFT)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This checks first to see if the location is valid, and
 *          then if there is presently an item there.  If there is not,
 *          it is simply inserted into that location.
 *      (2) If there is an item at the insert location, items must be
 *          moved down to make room for the insert.  In the downward
 *          shift there are three options, given by @shiftflag.
 *            - If @shiftflag == L_AUTO_DOWNSHIFT, a decision is made
 *              whether, in a cascade of items, to downshift a minimum
 *              amount or for all items above @index.  The decision is
 *              based on the expectation of finding holes (null ptrs)
 *              between @index and the bottom of the array.
 *              Assuming the holes are distributed uniformly, if 2 or more
 *              holes are expected, we do a minimum shift.
 *            - If @shiftflag == L_MIN_DOWNSHIFT, the downward shifting
 *              cascade of items progresses a minimum amount, until
 *              the first empty slot is reached.  This mode requires
 *              some computation before the actual shifting is done.
 *            - If @shiftflag == L_FULL_DOWNSHIFT, a shifting cascade is
 *              performed where pa[i] --> pa[i + 1] for all i >= index.
 *              Then, the item is inserted at pa[index].
 *      (3) If you are not using L_AUTO_DOWNSHIFT, the rule of thumb is
 *          to use L_FULL_DOWNSHIFT if the array is compacted (each
 *          element points to an item), and to use L_MIN_DOWNSHIFT
 *          if there are a significant number of null pointers.
 *          There is no penalty to using L_MIN_DOWNSHIFT for a
 *          compacted array, however, because the full shift is required
 *          and we don't do the O(n) computation to look for holes.
 *      (4) This should not be used repeatedly on large arrays,
 *          because the function is generally O(n).
 *      (5) However, it can be used repeatedly if we start with an empty
 *          ptr array and insert only once at each location.  For example,
 *          you can support an array of Numa, where at each ptr location
 *          you store either 0 or 1 Numa, and the Numa can be added
 *          randomly to the ptr array.
 */
l_int32
ptraInsert(L_PTRA  *pa,
           l_int32  index,
           void    *item,
           l_int32  shiftflag)
{
l_int32    i, ihole, imax;
l_float32  nexpected;

    PROCNAME("ptraInsert");

    if (!pa)
        return ERROR_INT("pa not defined", procName, 1);
    if (index < 0 || index > pa->nalloc)
        return ERROR_INT("index not in [0 ... nalloc]", procName, 1);
    if (shiftflag != L_AUTO_DOWNSHIFT && shiftflag != L_MIN_DOWNSHIFT &&
        shiftflag != L_FULL_DOWNSHIFT)
        return ERROR_INT("invalid shiftflag", procName, 1);

    if (item) pa->nactual++;
    if (index == pa->nalloc) {  /* can happen when index == n */
        if (ptraExtendArray(pa))
            return ERROR_INT("extension failure", procName, 1);
    }

        /* We are inserting into a hole or adding to the end of the array.
         * No existing items are moved. */
    ptraGetMaxIndex(pa, &imax);
    if (pa->array[index] == NULL) {
        pa->array[index] = item;
        if (item && index > imax)  /* new item put beyond max so far */
            pa->imax = index;
        return 0;
    }

        /* We are inserting at the location of an existing item,
         * forcing the existing item and those below to shift down.
         * First, extend the array automatically if the last element
         * (nalloc - 1) is occupied (imax).  This may not be necessary
         * in every situation, but only an anomalous sequence of insertions
         * into the array would cause extra ptr allocation.  */
    if (imax >= pa->nalloc - 1 && ptraExtendArray(pa))
        return ERROR_INT("extension failure", procName, 1);

        /* If there are no holes, do a full downshift.
         * Otherwise, if L_AUTO_DOWNSHIFT, use the expected number
         * of holes between index and n to determine the shift mode */
    if (imax + 1 == pa->nactual) {
        shiftflag = L_FULL_DOWNSHIFT;
    } else if (shiftflag == L_AUTO_DOWNSHIFT) {
        if (imax < 10) {
            shiftflag = L_FULL_DOWNSHIFT;  /* no big deal */
        } else {
            nexpected = (l_float32)(imax - pa->nactual) *
                         (l_float32)((imax - index) / imax);
            shiftflag = (nexpected > 2.0) ? L_MIN_DOWNSHIFT : L_FULL_DOWNSHIFT;
        }
    }

    if (shiftflag == L_MIN_DOWNSHIFT) {  /* run down looking for a hole */
        for (ihole = index + 1; ihole <= imax; ihole++) {
             if (pa->array[ihole] == NULL)
                 break;
        }
    } else {  /* L_FULL_DOWNSHIFT */
        ihole = imax + 1;
    }

    for (i = ihole; i > index; i--)
        pa->array[i] = pa->array[i - 1];
    pa->array[index] = (void *)item;
    if (ihole == imax + 1)  /* the last item was shifted down */
        pa->imax++;

    return 0;
}
コード例 #13
0
int main(int    argc,
         char **argv)
{
l_int32      i, n, w, h, nactual, imax;
BOX         *box;
BOXA        *boxa;
PIX         *pixs, *pixd, *pix;
PIXA        *pixas, *pixat, *pixac;
L_PTRA      *papix, *pabox, *papix2, *pabox2;
static char  mainName[] = "ptra1_reg";

    if (argc != 1)
        return ERROR_INT(" Syntax: ptra1_reg", mainName, 1);

    setLeptDebugOK(1);
    pixac = pixaCreate(0);

    if ((pixs = pixRead("lucasta.1.300.tif")) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);
    pixGetDimensions(pixs, &w, &h, NULL);
    boxa = pixConnComp(pixs, &pixas, 8);
    pixDestroy(&pixs);
    boxaDestroy(&boxa);
    n = pixaGetCount(pixas);

        /* Fill ptras with clones and reconstruct */
    fprintf(stderr, "Fill with clones and reconstruct\n");
    MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 1);

        /* Remove every other one for the first half;
         * with compaction at each removal */
    fprintf(stderr, "Remove every other in 1st half, with compaction\n");
    MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY);
    for (i = 0; i < n / 2; i++) {
        if (i % 2 == 0) {
            pix = (PIX *)ptraRemove(papix, i, L_COMPACTION);
            box = (BOX *)ptraRemove(pabox, i, L_COMPACTION);
            pixDestroy(&pix);
            boxDestroy(&box);
        }
    }
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 0);

        /* Remove every other one for the entire set,
         * but without compaction at each removal */
    fprintf(stderr,
            "Remove every other in 1st half, without & then with compaction\n");
    MakePtrasFromPixa(pixas, &papix, &pabox, L_COPY);
    for (i = 0; i < n; i++) {
        if (i % 2 == 0) {
            pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
            box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
            pixDestroy(&pix);
            boxDestroy(&box);
        }
    }
    ptraCompactArray(papix);  /* now do the compaction */
    ptraCompactArray(pabox);
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 0);

        /* Fill ptras using insert at head, and reconstruct */
    fprintf(stderr, "Insert at head and reconstruct\n");
    papix = ptraCreate(n);
    pabox = ptraCreate(n);
    for (i = 0; i < n; i++) {
        pix = pixaGetPix(pixas, i, L_CLONE);
        box = pixaGetBox(pixas, i, L_CLONE);
        ptraInsert(papix, 0, pix, L_MIN_DOWNSHIFT);
        ptraInsert(pabox, 0, box, L_FULL_DOWNSHIFT);
    }
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 1);

        /* Reverse the arrays by swapping */
    fprintf(stderr, "Reverse by swapping\n");
    MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
    for (i = 0; i < n / 2; i++) {
        ptraSwap(papix, i, n - i - 1);
        ptraSwap(pabox, i, n - i - 1);
    }
    ptraCompactArray(papix);  /* already compact; shouldn't do anything */
    ptraCompactArray(pabox);
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 0);

        /* Remove at the top of the array and push the hole to the end
         * by neighbor swapping (!).  This is O(n^2), so it's not a
         * recommended way to copy a ptra. [joke]  */
    fprintf(stderr,
            "Remove at top, pushing hole to end by swapping -- O(n^2)\n");
    MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
    papix2 = ptraCreate(0);
    pabox2 = ptraCreate(0);
    while (1) {
        ptraGetActualCount(papix, &nactual);
        if (nactual == 0) break;
        ptraGetMaxIndex(papix, &imax);
        pix = (PIX *)ptraRemove(papix, 0, L_NO_COMPACTION);
        box = (BOX *)ptraRemove(pabox, 0, L_NO_COMPACTION);
        ptraAdd(papix2, pix);
        ptraAdd(pabox2, box);
        for (i = 1; i <= imax; i++) {
           ptraSwap(papix, i - 1, i);
           ptraSwap(pabox, i - 1, i);
        }
    }
    ptraCompactArray(papix);  /* should be empty */
    ptraCompactArray(pabox);  /* ditto */
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 1);  /* nothing there */
    pixat = ReconstructPixa(papix2, pabox2, CHOOSE_RECON);
    ptraDestroy(&papix2, 0, 1);
    ptraDestroy(&pabox2, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 0);

        /* Remove and insert one position above, allowing minimum downshift.
         * If you specify L_AUTO_DOWNSHIFT, because there is only 1 hole,
         * it will do a full downshift at each insert.  This is a
         * situation where the heuristic (expected number of holes)
         * fails to do the optimal thing. */
    fprintf(stderr, "Remove and insert one position above (min downshift)\n");
    MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
    for (i = 1; i < n; i++) {
        pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
        box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
        ptraInsert(papix, i - 1, pix, L_MIN_DOWNSHIFT);
        ptraInsert(pabox, i - 1, box, L_MIN_DOWNSHIFT);
    }
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 1);

        /* Remove and insert one position above, but this time
         * forcing a full downshift at each step.  */
    fprintf(stderr, "Remove and insert one position above (full downshift)\n");
    MakePtrasFromPixa(pixas, &papix, &pabox, L_CLONE);
    for (i = 1; i < n; i++) {
        pix = (PIX *)ptraRemove(papix, i, L_NO_COMPACTION);
        box = (BOX *)ptraRemove(pabox, i, L_NO_COMPACTION);
        ptraInsert(papix, i - 1, pix, L_AUTO_DOWNSHIFT);
        ptraInsert(pabox, i - 1, box, L_AUTO_DOWNSHIFT);
    }
/*    ptraCompactArray(papix);
    ptraCompactArray(pabox); */
    pixat = ReconstructPixa(papix, pabox, CHOOSE_RECON);
    ptraDestroy(&papix, 0, 1);
    ptraDestroy(&pabox, 0, 1);
    DisplayResult(pixac, &pixat, w, h, 0);

    pixd = pixaDisplay(pixac, 0, 0);
    pixDisplay(pixd, 100, 100);
    pixWrite("/tmp/junkptra1.png", pixd, IFF_PNG);
    pixDestroy(&pixd);
    pixaDestroy(&pixac);
    pixaDestroy(&pixas);
    return 0;
}