示例#1
0
/*!
 *  lheapDestroy()
 *
 *      Input:  &lheap  (<to be nulled>)
 *              freeflag (TRUE to free each remaining struct in the array)
 *      Return: void
 *
 *  Notes:
 *      (1) Use freeflag == TRUE when the items in the array can be
 *          simply destroyed using free.  If those items require their
 *          own destroy function, they must be destroyed before
 *          calling this function, and then this function is called
 *          with freeflag == FALSE.
 *      (2) To destroy the lheap, we destroy the ptr array, then
 *          the lheap, and then null the contents of the input ptr.
 */
void
lheapDestroy(L_HEAP  **plh,
             l_int32   freeflag)
{
l_int32  i;
L_HEAP  *lh;

    PROCNAME("lheapDestroy");

    if (plh == NULL) {
        L_WARNING("ptr address is NULL", procName);
        return;
    }
    if ((lh = *plh) == NULL)
        return;

    if (freeflag) {  /* free each struct in the array */
        for (i = 0; i < lh->n; i++)
            FREE(lh->array[i]);
    }
    else if (lh->n > 0)  /* freeflag == FALSE but elements exist on array */
        L_WARNING_INT("memory leak of %d items in lheap!", procName, lh->n);

    if (lh->array)
        FREE(lh->array);
    FREE(lh);
    *plh = NULL;

    return;
}
示例#2
0
文件: queue.c 项目: 0xkasun/Dummy_Tes
/*!
 *  lqueueDestroy()
 *
 *      Input:  &lqueue  (<to be nulled>)
 *              freeflag (TRUE to free each remaining struct in the array)
 *      Return: void
 *
 *  Notes:
 *      (1) If freeflag is TRUE, frees each struct in the array.
 *      (2) If freeflag is FALSE but there are elements on the array,
 *          gives a warning and destroys the array.  This will
 *          cause a memory leak of all the items that were on the queue.
 *          So if the items require their own destroy function, they
 *          must be destroyed before the queue.  The same applies to the
 *          auxiliary stack, if it is used.
 *      (3) To destroy the L_Queue, we destroy the ptr array, then
 *          the lqueue, and then null the contents of the input ptr.
 */
void
lqueueDestroy(L_QUEUE  **plq,
              l_int32    freeflag)
{
void     *item;
L_QUEUE  *lq;

    PROCNAME("lqueueDestroy");

    if (plq == NULL) {
        L_WARNING("ptr address is NULL", procName);
        return;
    }
    if ((lq = *plq) == NULL)
        return;

    if (freeflag) {
        while(lq->nelem > 0) {
            item = lqueueRemove(lq);
            FREE(item);
        }
    }
    else if (lq->nelem > 0)
        L_WARNING_INT("memory leak of %d items in lqueue!",
                      procName, lq->nelem);

    if (lq->array)
        FREE(lq->array);
    if (lq->stack)
        lstackDestroy(&lq->stack, freeflag);
    FREE(lq);
    *plq = NULL;

    return;
}
示例#3
0
/*!
 *  pixaAddBorderGeneral()
 *
 *      Input:  pixad (can be null or equal to pixas)
 *              pixas (containing pix of all depths; colormap ok)
 *              left, right, top, bot  (number of pixels added)
 *              val   (value of added border pixels)
 *      Return: pixad (with border added to each pix), including on error
 *
 *  Notes:
 *      (1) For binary images:
 *             white:  val = 0
 *             black:  val = 1
 *          For grayscale images:
 *             white:  val = 2 ** d - 1
 *             black:  val = 0
 *          For rgb color images:
 *             white:  val = 0xffffff00
 *             black:  val = 0
 *          For colormapped images, use 'index' found this way:
 *             white: pixcmapGetRankIntensity(cmap, 1.0, &index);
 *             black: pixcmapGetRankIntensity(cmap, 0.0, &index);
 *      (2) For in-place replacement of each pix with a bordered version,
 *          use @pixad = @pixas.  To make a new pixa, use @pixad = NULL.
 *      (3) In both cases, the boxa has sides adjusted as if it were
 *          expanded by the border.
 */
PIXA *
pixaAddBorderGeneral(PIXA     *pixad,
                     PIXA     *pixas,
                     l_int32   left,
                     l_int32   right,
                     l_int32   top,
                     l_int32   bot,
                     l_uint32  val)
{
l_int32  i, n, nbox;
BOX     *box;
BOXA    *boxad;
PIX     *pixs, *pixd;

    PROCNAME("pixaAddBorderGeneral");

    if (!pixas)
        return (PIXA *)ERROR_PTR("pixas not defined", procName, pixad);
    if (left < 0 || right < 0 || top < 0 || bot < 0)
        return (PIXA *)ERROR_PTR("negative border added!", procName, pixad);
    if (pixad && (pixad != pixas))
        return (PIXA *)ERROR_PTR("pixad defined but != pixas", procName, pixad);

    n = pixaGetCount(pixas);
    if (!pixad)
        pixad = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pixs = pixaGetPix(pixas, i, L_CLONE);
        pixd = pixAddBorderGeneral(pixs, left, right, top, bot, val);
        if (pixad == pixas)  /* replace */
            pixaReplacePix(pixad, i, pixd, NULL);
        else
            pixaAddPix(pixad, pixd, L_INSERT);
        pixDestroy(&pixs);
    }

    nbox = pixaGetBoxaCount(pixas);
    boxad = pixaGetBoxa(pixad, L_CLONE);
    for (i = 0; i < nbox; i++) {
        if ((box = pixaGetBox(pixas, i, L_COPY)) == NULL) {
            L_WARNING_INT("box %d not found", procName, i);
            break;
        }
        boxAdjustSides(box, box, -left, right, -top, bot);
        if (pixad == pixas)  /* replace */
            boxaReplaceBox(boxad, i, box);
        else
            boxaAddBox(boxad, box, L_INSERT);
    }
    boxaDestroy(&boxad);

    return pixad;
}
示例#4
0
/*!
 *  pixColorSegmentCluster()
 *
 *      Input:  pixs  (32 bpp; 24-bit color)
 *              maxdist (max euclidean dist to existing cluster)
 *              maxcolors (max number of colors allowed in first pass)
 *      Return: pixd (8 bit with colormap), or null on error
 *
 *  Notes:
 *      (1) This is phase 1.  See description in pixColorSegment().
 *      (2) Greedy unsupervised classification.  If the limit 'maxcolors'
 *          is exceeded, the computation is repeated with a larger
 *          allowed cluster size.
 *      (3) On each successive iteration, 'maxdist' is increased by a
 *          constant factor.  See comments in pixColorSegment() for
 *          a guideline on parameter selection.
 *          Note that the diagonal of the 8-bit rgb color cube is about
 *          440, so for 'maxdist' = 440, you are guaranteed to get 1 color!
 */
PIX *
pixColorSegmentCluster(PIX       *pixs,
                       l_int32    maxdist,
                       l_int32    maxcolors)
{
l_int32    w, h, newmaxdist, ret, niters, ncolors, success;
PIX       *pixd;
PIXCMAP   *cmap;

    PROCNAME("pixColorSegmentCluster");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 32)
        return (PIX *)ERROR_PTR("must be rgb color", procName, NULL);

    w = pixGetWidth(pixs);
    h = pixGetHeight(pixs);
    if ((pixd = pixCreate(w, h, 8)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    cmap = pixcmapCreate(8);
    pixSetColormap(pixd, cmap);
    pixCopyResolution(pixd, pixs);

    newmaxdist = maxdist;
    niters = 0;
    success = TRUE;
    while (1) {
        ret = pixColorSegmentTryCluster(pixd, pixs, newmaxdist, maxcolors);
        niters++;
        if (!ret) {
            ncolors = pixcmapGetCount(cmap);
            L_INFO_INT2("Success with %d colors after %d iters", procName,
                       ncolors, niters);
            break;
        }
        if (niters == MAX_ALLOWED_ITERATIONS) {
            L_WARNING_INT("too many iters; newmaxdist = %d",
                          procName, newmaxdist);
            success = FALSE;
            break;
        }
        newmaxdist = (l_int32)(DIST_EXPAND_FACT * (l_float32)newmaxdist);
    }

    if (!success) {
        pixDestroy(&pixd);
        return (PIX *)ERROR_PTR("failure in phase 1", procName, NULL);
    }

    return pixd;
}
示例#5
0
文件: ptra.c 项目: 0xkasun/Dummy_Tes
/*!
 *  ptraDestroy()
 *
 *      Input:  &ptra (<to be nulled>)
 *              freeflag (TRUE to free each remaining item in the array)
 *              warnflag (TRUE to warn if any remaining items are not destroyed)
 *      Return: void
 *
 *  Notes:
 *      (1) If @freeflag == TRUE, frees each item in the array.
 *      (2) If @freeflag == FALSE and warnflag == TRUE, and there are
 *          items on the array, this gives a warning and destroys the array.
 *          If these items are not owned elsewhere, this will cause
 *          a memory leak of all the items that were on the array.
 *          So if the items are not owned elsewhere and require their
 *          own destroy function, they must be destroyed before the ptra.
 *      (3) If warnflag == FALSE, no warnings will be issued.  This is
 *          useful if the items are owned elsewhere, such as a
 *          PixMemoryStore().
 *      (4) To destroy the ptra, we destroy the ptr array, then
 *          the ptra, and then null the contents of the input ptr.
 */
void
ptraDestroy(L_PTRA  **ppa,
            l_int32   freeflag,
            l_int32   warnflag)
{
l_int32  i, nactual;
void    *item;
L_PTRA  *pa;

    PROCNAME("ptraDestroy");

    if (ppa == NULL) {
        L_WARNING("ptr address is NULL", procName);
        return;
    }
    if ((pa = *ppa) == NULL)
        return;

    ptraGetActualCount(pa, &nactual);
    if (nactual > 0) {
        if (freeflag) {
            for (i = 0; i <= pa->imax; i++) {
                if ((item = ptraRemove(pa, i, L_NO_COMPACTION)) != NULL)
                    FREE(item);
            }
        }
        else if (warnflag)
            L_WARNING_INT("potential memory leak of %d items in ptra",
                          procName, nactual);
    }

    FREE(pa->array);
    FREE(pa);
    *ppa = NULL;
    return;
}
示例#6
0
/*!
 *  pixaDisplayTiledInRows()
 *
 *      Input:  pixa
 *              outdepth (output depth: 1, 8 or 32 bpp)
 *              maxwidth (of output image)
 *              scalefactor (applied to every pix; use 1.0 for no scaling)
 *              background (0 for white, 1 for black; this is the color
 *                 of the spacing between the images)
 *              spacing  (between images, and on outside)
 *              border (width of black border added to each image;
 *                      use 0 for no border)
 *      Return: pixd (of tiled images), or null on error
 *
 *  Notes:
 *      (1) This saves a pixa to a single image file of width not to
 *          exceed maxwidth, with background color either white or black,
 *          and with each row tiled such that the top of each pix is
 *          aligned and separated by 'spacing' from the next one.
 *          A black border can be added to each pix.
 *      (2) All pix are converted to outdepth; existing colormaps are removed.
 *      (3) This does a reasonably spacewise-efficient job of laying
 *          out the individual pix images into a tiled composite.
 */
PIX *
pixaDisplayTiledInRows(PIXA      *pixa,
                       l_int32    outdepth,
                       l_int32    maxwidth,
                       l_float32  scalefactor,
                       l_int32    background,
                       l_int32    spacing,
                       l_int32    border)
{
l_int32  h;  /* cumulative height over all the rows */
l_int32  w;  /* cumulative height in the current row */
l_int32  bordval, wtry, wt, ht;
l_int32  irow;  /* index of current pix in current row */
l_int32  wmaxrow;  /* width of the largest row */
l_int32  maxh;  /* max height in row */
l_int32  i, j, index, n, x, y, nrows, ninrow;
NUMA    *nainrow;  /* number of pix in the row */
NUMA    *namaxh;  /* height of max pix in the row */
PIX     *pix, *pixn, *pixt, *pixd;
PIXA    *pixan;

    PROCNAME("pixaDisplayTiledInRows");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    if (outdepth != 1 && outdepth != 8 && outdepth != 32)
        return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL);
    if (border < 0)
        border = 0;
    if (scalefactor <= 0.0) scalefactor = 1.0;
    
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);

        /* Normalize depths, scale, remove colormaps; optionally add border */
    pixan = pixaCreate(n);
    bordval = (outdepth == 1) ? 1 : 0;
    for (i = 0; i < n; i++) {
        if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL)
            continue;

        if (outdepth == 1)
            pixn = pixConvertTo1(pix, 128);
        else if (outdepth == 8)
            pixn = pixConvertTo8(pix, FALSE);
        else  /* outdepth == 32 */
            pixn = pixConvertTo32(pix);
        pixDestroy(&pix);

        if (scalefactor != 1.0)
            pixt = pixScale(pixn, scalefactor, scalefactor);
        else
            pixt = pixClone(pixn);
        if (border)
            pixd = pixAddBorder(pixt, border, bordval);
        else
            pixd = pixClone(pixt);
        pixDestroy(&pixn);
        pixDestroy(&pixt);

        pixaAddPix(pixan, pixd, L_INSERT);
    }
    if (pixaGetCount(pixan) != n) {
        n = pixaGetCount(pixan);
        L_WARNING_INT("only got %d components", procName, n);
        if (n == 0) {
            pixaDestroy(&pixan);
            return (PIX *)ERROR_PTR("no components", procName, NULL);
        }
    }

        /* Compute parameters for layout */
    nainrow = numaCreate(0);
    namaxh = numaCreate(0);
    wmaxrow = 0;
    w = h = spacing;
    maxh = 0;  /* max height in row */
    for (i = 0, irow = 0; i < n; i++, irow++) {
        pixaGetPixDimensions(pixan, i, &wt, &ht, NULL);
        wtry = w + wt + spacing;
        if (wtry > maxwidth) {  /* end the current row and start next one */
            numaAddNumber(nainrow, irow); 
            numaAddNumber(namaxh, maxh); 
            wmaxrow = L_MAX(wmaxrow, w);
            h += maxh + spacing;
            irow = 0;
            w = wt + 2 * spacing;
            maxh = ht;
        } else {
            w = wtry;
            maxh = L_MAX(maxh, ht);
        }
    }

        /* Enter the parameters for the last row */
    numaAddNumber(nainrow, irow); 
    numaAddNumber(namaxh, maxh); 
    wmaxrow = L_MAX(wmaxrow, w);
    h += maxh + spacing;
            
    if ((pixd = pixCreate(wmaxrow, h, outdepth)) == NULL) {
        numaDestroy(&nainrow);
        numaDestroy(&namaxh);
        pixaDestroy(&pixan);
	return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    }

        /* Reset the background color if necessary */
    if ((background == 1 && outdepth == 1) ||
        (background == 0 && outdepth != 1))
        pixSetAll(pixd);

        /* Blit the images to the dest */
    nrows = numaGetCount(nainrow);
    y = spacing;
    for (i = 0, index = 0; i < nrows; i++) {  /* over rows */
        numaGetIValue(nainrow, i, &ninrow);
        numaGetIValue(namaxh, i, &maxh);
        x = spacing;
        for (j = 0; j < ninrow; j++, index++) {   /* over pix in row */
            pix = pixaGetPix(pixan, index, L_CLONE);
            pixGetDimensions(pix, &wt, &ht, NULL);
            pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pix, 0, 0);
            pixDestroy(&pix);
            x += wt + spacing;
        }
        y += maxh + spacing;
    }

    numaDestroy(&nainrow);
    numaDestroy(&namaxh);
    pixaDestroy(&pixan);
    return pixd;
}
示例#7
0
/*!
 *  expandBinaryPower2Low()
 */
l_int32
expandBinaryPower2Low(l_uint32  *datad,
                      l_int32    wd,
                      l_int32    hd,
                      l_int32    wpld,
                      l_uint32  *datas,
                      l_int32    ws,
                      l_int32    hs,
                      l_int32    wpls,
                      l_int32    factor)
{
l_int32    i, j, k, sdibits, sqbits, sbytes;
l_uint8    sval;
l_uint16  *tab2;
l_uint32  *tab4, *tab8;
l_uint32  *lines, *lined;

    PROCNAME("expandBinaryPower2Low");

    switch (factor)
    {
    case 2:
        if ((tab2 = makeExpandTab2x()) == NULL)
            return ERROR_INT("tab2 not made", procName, 1);
        sbytes = (ws + 7) / 8;
        for (i = 0; i < hs; i++) {
            lines = datas + i * wpls;
            lined = datad + 2 * i * wpld;
            for (j = 0; j < sbytes; j++) {
                sval = GET_DATA_BYTE(lines, j);
                SET_DATA_TWO_BYTES(lined, j, tab2[sval]);
            }
            memcpy((char *)(lined + wpld), (char *)lined, 4 * wpld);
        }
        FREE(tab2);
        break;
    case 4:
        if ((tab4 = makeExpandTab4x()) == NULL)
            return ERROR_INT("tab4 not made", procName, 1);
        sbytes = (ws + 7) / 8;
        for (i = 0; i < hs; i++) {
            lines = datas + i * wpls;
            lined = datad + 4 * i * wpld;
            for (j = 0; j < sbytes; j++) {
                sval = GET_DATA_BYTE(lines, j);
                lined[j] = tab4[sval];
            }
            for (k = 1; k < 4; k++)
                memcpy((char *)(lined + k * wpld), (char *)lined, 4 * wpld);
        }
        FREE(tab4);
        break;
    case 8:
        if ((tab8 = makeExpandTab8x()) == NULL)
            return ERROR_INT("tab8 not made", procName, 1);
        sqbits = (ws + 3) / 4;
        for (i = 0; i < hs; i++) {
            lines = datas + i * wpls;
            lined = datad + 8 * i * wpld;
            for (j = 0; j < sqbits; j++) {
                sval = GET_DATA_QBIT(lines, j);
                if (sval > 15)
                    L_WARNING_INT("sval = %d; should be < 16", procName, sval);
                lined[j] = tab8[sval];
            }
            for (k = 1; k < 8; k++)
                memcpy((char *)(lined + k * wpld), (char *)lined, 4 * wpld);
        }
        FREE(tab8);
        break;
    case 16:
        sdibits = (ws + 1) / 2;
        for (i = 0; i < hs; i++) {
            lines = datas + i * wpls;
            lined = datad + 16 * i * wpld;
            for (j = 0; j < sdibits; j++) {
                sval = GET_DATA_DIBIT(lines, j);
                lined[j] = expandtab16[sval];
            }
            for (k = 1; k < 16; k++)
                memcpy((char *)(lined + k * wpld), (char *)lined, 4 * wpld);
        }
        break;
    default:
        return ERROR_INT("expansion factor not in {2,4,8,16}", procName, 1);
    }

    return 0;
}
示例#8
0
/*!
 *  pixSauvolaBinarizeTiled()
 *
 *      Input:  pixs (8 bpp grayscale, not colormapped)
 *              whsize (window half-width for measuring local statistics)
 *              factor (factor for reducing threshold due to variance; >= 0)
 *              nx, ny (subdivision into tiles; >= 1)
 *              &pixth (<optional return> Sauvola threshold values)
 *              &pixd (<optional return> thresholded image)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The window width and height are 2 * @whsize + 1.  The minimum
 *          value for @whsize is 2; typically it is >= 7..
 *      (2) For nx == ny == 1, this defaults to pixSauvolaBinarize().
 *      (3) Why a tiled version?
 *          (a) Because the mean value accumulator is a uint32, overflow
 *              can occur for an image with more than 16M pixels.
 *          (b) The mean value accumulator array for 16M pixels is 64 MB.
 *              The mean square accumulator array for 16M pixels is 128 MB.
 *              Using tiles reduces the size of these arrays.
 *          (c) Each tile can be processed independently, in parallel,
 *              on a multicore processor.
 *      (4) The Sauvola threshold is determined from the formula:
 *              t = m * (1 - k * (1 - s / 128))
 *          See pixSauvolaBinarize() for details.
 */
l_int32
pixSauvolaBinarizeTiled(PIX       *pixs,
                        l_int32    whsize,
                        l_float32  factor,
                        l_int32    nx,
                        l_int32    ny,
                        PIX      **ppixth,
                        PIX      **ppixd)
{
l_int32     i, j, w, h, xrat, yrat;
PIX        *pixth, *pixd, *tileth, *tiled, *pixt;
PIX       **ptileth, **ptiled;
PIXTILING  *pt;

    PROCNAME("pixSauvolaBinarizeTiled");
    
    if (!ppixth && !ppixd)
        return ERROR_INT("no outputs", procName, 1);
    if (ppixth) *ppixth = NULL;
    if (ppixd) *ppixd = NULL;
    if (!pixs || pixGetDepth(pixs) != 8)
        return ERROR_INT("pixs undefined or not 8 bpp", procName, 1);
    if (pixGetColormap(pixs))
        return ERROR_INT("pixs is cmapped", procName, 1);
    pixGetDimensions(pixs, &w, &h, NULL);
    if (whsize < 2)
        return ERROR_INT("whsize must be >= 2", procName, 1);
    if (w < 2 * whsize + 3 || h < 2 * whsize + 3)
        return ERROR_INT("whsize too large for image", procName, 1);
    if (factor < 0.0)
        return ERROR_INT("factor must be >= 0", procName, 1);

    if (nx <= 1 && ny <= 1)
        return pixSauvolaBinarize(pixs, whsize, factor, 1, NULL, NULL,
                                  ppixth, ppixd);

        /* Test to see if the tiles are too small.  The required
         * condition is that the tile dimensions must be at least
         * (whsize + 2) x (whsize + 2).  */
    xrat = w / nx;
    yrat = h / ny;
    if (xrat < whsize + 2) {
        nx = w / (whsize + 2);
        L_WARNING_INT("tile width too small; nx reduced to %d", procName, nx);
    }
    if (yrat < whsize + 2) {
        ny = h / (whsize + 2);
        L_WARNING_INT("tile height too small; ny reduced to %d", procName, ny);
    }
    if (nx <= 1 && ny <= 1)
        return pixSauvolaBinarize(pixs, whsize, factor, 1, NULL, NULL,
                                  ppixth, ppixd);

        /* We can use pixtiling for painting both outputs, if requested */
    if (ppixth) {
        pixth = pixCreateNoInit(w, h, 8);
        *ppixth = pixth;
    }
    if (ppixd) {
        pixd = pixCreateNoInit(w, h, 1);
        *ppixd = pixd;
    }
    pt = pixTilingCreate(pixs, nx, ny, 0, 0, whsize + 1, whsize + 1);
    pixTilingNoStripOnPaint(pt);  /* pixSauvolaBinarize() does the stripping */

    for (i = 0; i < ny; i++) {
        for (j = 0; j < nx; j++) {
            pixt = pixTilingGetTile(pt, i, j);
            ptileth = (ppixth) ? &tileth : NULL;
            ptiled = (ppixd) ? &tiled : NULL;
            pixSauvolaBinarize(pixt, whsize, factor, 0, NULL, NULL,
                               ptileth, ptiled);
            if (ppixth) {  /* do not strip */
                pixTilingPaintTile(pixth, i, j, tileth, pt);
                pixDestroy(&tileth);
            }
            if (ppixd) {
                pixTilingPaintTile(pixd, i, j, tiled, pt);
                pixDestroy(&tiled);
            }
            pixDestroy(&pixt);
        }
    }

    pixTilingDestroy(&pt);
    return 0;
}
示例#9
0
/*!
 *  sarrayMakeInnerLoopDWACode()
 */
static SARRAY *
sarrayMakeInnerLoopDWACode(SEL     *sel,
                           l_int32  index)
{
char    *tstr, *string;
char     logicalor[] = "|";
char     logicaland[] = "&";
char     bigbuf[BUFFER_SIZE];
l_int32  i, j, optype, count, nfound, delx, dely;
SARRAY  *sa;

    PROCNAME("sarrayMakeInnerLoopDWACode");

    if (!sel)
        return (SARRAY *)ERROR_PTR("sel not defined", procName, NULL);

    if (index % 2 == 0) {
        optype = L_MORPH_DILATE;
        tstr = logicalor;
    }
    else {
        optype = L_MORPH_ERODE;
        tstr = logicaland;
    }

    count = 0;
    for (i = 0; i < sel->sy; i++) {
        for (j = 0; j < sel->sx; j++) {
            if (sel->data[i][j] == 1)
                count++;
        }
    }

    if ((sa = sarrayCreate(0)) == NULL)
        return (SARRAY *)ERROR_PTR("sa not made", procName, NULL);
    if (count == 0) {
        L_WARNING_INT("no hits in Sel %d", procName, index);
        return sa;  /* no code inside! */
    }

    nfound = 0;
    for (i = 0; i < sel->sy; i++) {
        for (j = 0; j < sel->sx; j++) {
            if (sel->data[i][j] == 1) {
                nfound++;
                if (optype == L_MORPH_DILATE) {
                    dely = sel->cy - i;
                    delx = sel->cx - j;
                }
                else if (optype == L_MORPH_ERODE) {
                    dely = i - sel->cy;
                    delx = j - sel->cx;
                }
                if ((string = makeBarrelshiftString(delx, dely)) == NULL) {
                    L_WARNING("barrel shift string not made", procName);
                    continue;
                }
                if (count == 1)  /* just one item */
                    sprintf(bigbuf, "            *dptr = %s;", string);
                else if (nfound == 1)
                    sprintf(bigbuf, "            *dptr = %s %s", string, tstr);
                else if (nfound < count)
                    sprintf(bigbuf, "                    %s %s", string, tstr);
                else  /* nfound == count */
                    sprintf(bigbuf, "                    %s;", string);
                sarrayAddString(sa, bigbuf, 1);
                FREE(string);
            }
        }
    }

    return sa;
}