Beispiel #1
0
/*!
 *  pixFHMTGen_1()
 *
 *      Input:  pixd (usual 3 choices: null, == pixs, != pixs)
 *              pixs (1 bpp)
 *              sel name
 *      Return: pixd
 *
 *  Notes:
 *      (1) This is a dwa implementation of the hit-miss transform
 *          on pixs by the sel.
 *      (2) The sel must be limited in size to not more than 31 pixels
 *          about the origin.  It must have at least one hit, and it
 *          can have any number of misses.
 *      (3) This handles all required setting of the border pixels
 *          before erosion and dilation.
 */
PIX *
pixFHMTGen_1(PIX   *pixd,
             PIX   *pixs,
             char  *selname)
{
l_int32    i, index, found, w, h, wpls, wpld;
l_uint32  *datad, *datas, *datat;
PIX       *pixt;

    PROCNAME("pixFHMTGen_1");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
    if (pixGetDepth(pixs) != 1)
        return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);

    found = FALSE;
    for (i = 0; i < NUM_SELS_GENERATED; i++) {
        if (strcmp(selname, SEL_NAMES[i]) == 0) {
            found = TRUE;
            index = i;
            break;
        }
    }
    if (found == FALSE)
        return (PIX *)ERROR_PTR("sel index not found", procName, pixd);

    if (!pixd) {
        if ((pixd = pixCreateTemplate(pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    }
    else  /* for in-place or pre-allocated */
        pixResizeImageData(pixd, pixs);
    wpls = pixGetWpl(pixs);
    wpld = pixGetWpl(pixd);

        /*  The images must be surrounded with 32 additional border
         *  pixels, that we'll read from.  We fabricate a "proper"
         *  image as the subimage within the border, having the
         *  following parameters:  */
    w = pixGetWidth(pixs) - 64;
    h = pixGetHeight(pixs) - 64;
    datas = pixGetData(pixs) + 32 * wpls + 1;
    datad = pixGetData(pixd) + 32 * wpld + 1;

    if (pixd == pixs) {  /* need temp image if in-place */
        if ((pixt = pixCopy(NULL, pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
        datat = pixGetData(pixt) + 32 * wpls + 1;
        fhmtgen_low_1(datad, w, h, wpld, datat, wpls, index);
        pixDestroy(&pixt);
    }
    else {  /* not in-place */
        fhmtgen_low_1(datad, w, h, wpld, datas, wpls, index);
    }

    return pixd;
}
/*!
 *  pixTransferAllData()
 *
 *      Input:  pixd (must be different from pixs)
 *              &pixs (will be nulled if refcount goes to 0)
 *              copytext (1 to copy the text field; 0 to skip)
 *              copyformat (1 to copy the informat field; 0 to skip)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This does a complete data transfer from pixs to pixd,
 *          followed by the destruction of pixs (refcount permitting).
 *      (2) If the refcount of pixs is 1, pixs is destroyed.  Otherwise,
 *          the data in pixs is copied (rather than transferred) to pixd.
 *      (3) This operation, like all others with a pre-existing pixd,
 *          will side-effect any existing clones of pixd.  The pixd
 *          refcount does not change.
 *      (4) When might you use this?  Suppose you have an in-place Pix
 *          function (returning void) with the typical signature:
 *              void function-inplace(PIX *pix, ...)
 *          where "..." are non-pointer input parameters, and suppose
 *          further that you sometimes want to return an arbitrary Pix
 *          in place of the input Pix.  There are two ways you can do this:
 *          (a) The straightforward way is to change the function
 *              signature to take the address of the Pix ptr:
 *                  void function-inplace(PIX **ppix, ...) {
 *                      PIX *pixt = function-makenew(*ppix);
 *                      pixDestroy(ppix);
 *                      *ppix = pixt;
 *                      return;
 *                  }
 *              Here, the input and returned pix are different, as viewed
 *              by the calling function, and the inplace function is
 *              expected to destroy the input pix to avoid a memory leak.
 *          (b) Keep the signature the same and use pixTransferAllData()
 *              to return the new Pix in the input Pix struct:
 *                  void function-inplace(PIX *pix, ...) {
 *                      PIX *pixt = function-makenew(pix);
 *                      pixTransferAllData(pix, &pixt);  // pixt is destroyed
 *                      return;
 *                  }
 *              Here, the input and returned pix are the same, as viewed
 *              by the calling function, and the inplace function must
 *              never destroy the input pix, because the calling function
 *              maintains an unchanged handle to it.
 */
l_int32
pixTransferAllData(PIX     *pixd,
                   PIX    **ppixs,
                   l_int32  copytext,
                   l_int32  copyformat)
{
l_int32  nbytes;
PIX     *pixs;

    PROCNAME("pixTransferAllData");

    if (!ppixs)
        return ERROR_INT("&pixs not defined", procName, 1);
    if ((pixs = *ppixs) == NULL)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!pixd)
        return ERROR_INT("pixd not defined", procName, 1);
    if (pixs == pixd)  /* no-op */
        return ERROR_INT("pixd == pixs", procName, 1);

    if (pixGetRefcount(pixs) == 1) {  /* transfer the data, cmap, text */
        pixFreeData(pixd);  /* dealloc any existing data */
        pixSetData(pixd, pixGetData(pixs));  /* transfer new data from pixs */
        pixs->data = NULL;  /* pixs no longer owns data */
        pixSetColormap(pixd, pixGetColormap(pixs));  /* frees old; sets new */
        pixs->colormap = NULL;  /* pixs no longer owns colormap */
        if (copytext) {
            pixSetText(pixd, pixGetText(pixs));
            pixSetText(pixs, NULL);
        }
    } else {  /* preserve pixs by making a copy of the data, cmap, text */
        pixResizeImageData(pixd, pixs);
        nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
        memcpy((char *)pixGetData(pixd), (char *)pixGetData(pixs), nbytes);
        pixCopyColormap(pixd, pixs);
        if (copytext)
            pixCopyText(pixd, pixs);
    }
  
    pixCopyResolution(pixd, pixs);
    pixCopyDimensions(pixd, pixs);
    if (copyformat)
        pixCopyInputFormat(pixd, pixs);

        /* This will destroy pixs if data was transferred;
         * otherwise, it just decrements its refcount. */
    pixDestroy(ppixs);
    return 0;
}
/*!
 *  pixCopy()
 *
 *      Input:  pixd (<optional>; can be null, or equal to pixs,
 *                    or different from pixs)
 *              pixs
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) There are three cases:
 *            (a) pixd == null  (makes a new pix; refcount = 1)
 *            (b) pixd == pixs  (no-op)
 *            (c) pixd != pixs  (data copy; no change in refcount)
 *          If the refcount of pixd > 1, case (c) will side-effect
 *          these handles.
 *      (2) The general pattern of use is:
 *             pixd = pixCopy(pixd, pixs);
 *          This will work for all three cases.
 *          For clarity when the case is known, you can use:
 *            (a) pixd = pixCopy(NULL, pixs);
 *            (c) pixCopy(pixd, pixs);
 *      (3) For case (c), we check if pixs and pixd are the same
 *          size (w,h,d).  If so, the data is copied directly.
 *          Otherwise, the data is reallocated to the correct size
 *          and the copy proceeds.  The refcount of pixd is unchanged.
 *      (4) This operation, like all others that may involve a pre-existing
 *          pixd, will side-effect any existing clones of pixd.
 */
PIX *
pixCopy(PIX  *pixd,   /* can be null */
        PIX  *pixs)
{
l_int32    bytes;
l_uint32  *datas, *datad;

    PROCNAME("pixCopy");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixs == pixd)
        return pixd;

        /* Total bytes in image data */
    bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);

        /* If we're making a new pix ... */
    if (!pixd) {
        if ((pixd = pixCreateTemplate(pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
        datas = pixGetData(pixs);
        datad = pixGetData(pixd);
        memcpy((char *)datad, (char *)datas, bytes);
        return pixd;
    }

        /* Reallocate image data if sizes are different */
    if (pixResizeImageData(pixd, pixs) == 1)
        return (PIX *)ERROR_PTR("reallocation of data failed", procName, NULL);

        /* Copy non-image data fields */
    pixCopyColormap(pixd, pixs);
    pixCopyResolution(pixd, pixs);
    pixCopyInputFormat(pixd, pixs);
    pixCopyText(pixd, pixs);

        /* Copy image data */
    datas = pixGetData(pixs);
    datad = pixGetData(pixd);
    memcpy((char*)datad, (char*)datas, bytes);
    return pixd;
}
Beispiel #4
0
/*!
 *  pixFMorphopGen_3()
 *
 *      Input:  pixd (usual 3 choices: null, == pixs, != pixs)
 *              pixs (1 bpp)
 *              operation  (L_MORPH_DILATE, L_MORPH_ERODE,
 *                          L_MORPH_OPEN, L_MORPH_CLOSE)
 *              sel name
 *      Return: pixd
 *
 *  Notes:
 *      (1) This is a dwa operation, and the Sels must be limited in
 *          size to not more than 31 pixels about the origin.
 *      (2) A border of appropriate size (32 pixels, or 64 pixels
 *          for safe closing with asymmetric b.c.) must be added before
 *          this function is called.
 *      (3) This handles all required setting of the border pixels
 *          before erosion and dilation.
 *      (4) The closing operation is safe; no pixels can be removed
 *          near the boundary.
 */
PIX *
pixFMorphopGen_3(PIX     *pixd,
                 PIX     *pixs,
                 l_int32  operation,
                 char    *selname)
{
l_int32    i, index, found, w, h, wpls, wpld, bordercolor, erodeop, borderop;
l_uint32  *datad, *datas, *datat;
PIX       *pixt;

    PROCNAME("pixFMorphopGen_3");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
    if (pixGetDepth(pixs) != 1)
        return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);

        /* Get boundary colors to use */
    bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
    if (bordercolor == 1)
        erodeop = PIX_SET;
    else
        erodeop = PIX_CLR;

    found = FALSE;
    for (i = 0; i < NUM_SELS_GENERATED; i++) {
        if (strcmp(selname, SEL_NAMES[i]) == 0) {
            found = TRUE;
            index = 2 * i;
            break;
        }
    }
    if (found == FALSE)
        return (PIX *)ERROR_PTR("sel index not found", procName, pixd);

    if (!pixd) {
        if ((pixd = pixCreateTemplate(pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    }
    else  /* for in-place or pre-allocated */
        pixResizeImageData(pixd, pixs);
    wpls = pixGetWpl(pixs);
    wpld = pixGetWpl(pixd);

        /* The images must be surrounded, in advance, with a border of
         * size 32 pixels (or 64, for closing), that we'll read from.
         * Fabricate a "proper" image as the subimage within the 32
         * pixel border, having the following parameters:  */
    w = pixGetWidth(pixs) - 64;
    h = pixGetHeight(pixs) - 64;
    datas = pixGetData(pixs) + 32 * wpls + 1;
    datad = pixGetData(pixd) + 32 * wpld + 1;

    if (operation == L_MORPH_DILATE || operation == L_MORPH_ERODE) {
        borderop = PIX_CLR;
        if (operation == L_MORPH_ERODE) {
            borderop = erodeop;
            index++;
        }
        if (pixd == pixs) {  /* in-place; generate a temp image */
            if ((pixt = pixCopy(NULL, pixs)) == NULL)
                return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
            datat = pixGetData(pixt) + 32 * wpls + 1;
            pixSetOrClearBorder(pixt, 32, 32, 32, 32, borderop);
            fmorphopgen_low_3(datad, w, h, wpld, datat, wpls, index);
            pixDestroy(&pixt);
        }
        else { /* not in-place */
            pixSetOrClearBorder(pixs, 32, 32, 32, 32, borderop);
            fmorphopgen_low_3(datad, w, h, wpld, datas, wpls, index);
        }
    }
    else {  /* opening or closing; generate a temp image */
        if ((pixt = pixCreateTemplate(pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
        datat = pixGetData(pixt) + 32 * wpls + 1;
        if (operation == L_MORPH_OPEN) {
            pixSetOrClearBorder(pixs, 32, 32, 32, 32, erodeop);
            fmorphopgen_low_3(datat, w, h, wpls, datas, wpls, index+1);
            pixSetOrClearBorder(pixt, 32, 32, 32, 32, PIX_CLR);
            fmorphopgen_low_3(datad, w, h, wpld, datat, wpls, index);
        }
        else {  /* closing */
            pixSetOrClearBorder(pixs, 32, 32, 32, 32, PIX_CLR);
            fmorphopgen_low_3(datat, w, h, wpls, datas, wpls, index);
            pixSetOrClearBorder(pixt, 32, 32, 32, 32, erodeop);
            fmorphopgen_low_3(datad, w, h, wpld, datat, wpls, index+1);
        }
        pixDestroy(&pixt);
    }

    return pixd;
}