Beispiel #1
0
/*!
 *  kernelDisplayInPix()
 *
 *      Input:  kernel
 *              size (of grid interiors; odd; either 1 or a minimum size
 *                    of 17 is enforced)
 *              gthick (grid thickness; either 0 or a minimum size of 2
 *                      is enforced)
 *      Return: pix (display of kernel), or null on error
 *
 *  Notes:
 *      (1) This gives a visual representation of a kernel.
 *      (2) There are two modes of display:
 *          (a) Grid lines of minimum width 2, surrounding regions
 *              representing kernel elements of minimum size 17,
 *              with a "plus" mark at the kernel origin, or
 *          (b) A pix without grid lines and using 1 pixel per kernel element.
 *      (3) For both cases, the kernel absolute value is displayed,
 *          normalized such that the maximum absolute value is 255.
 *      (4) Large 2D separable kernels should be used for convolution
 *          with two 1D kernels.  However, for the bilateral filter,
 *          the computation time is independent of the size of the
 *          2D content kernel.
 */
PIX *
kernelDisplayInPix(L_KERNEL     *kel,
                   l_int32       size,
                   l_int32       gthick)
{
l_int32    i, j, w, h, sx, sy, cx, cy, width, x0, y0;
l_int32    normval;
l_float32  minval, maxval, max, val, norm;
PIX       *pixd, *pixt0, *pixt1;

    PROCNAME("kernelDisplayInPix");

    if (!kel)
        return (PIX *)ERROR_PTR("kernel not defined", procName, NULL);

        /* Normalize the max value to be 255 for display */
    kernelGetParameters(kel, &sy, &sx, &cy, &cx);
    kernelGetMinMax(kel, &minval, &maxval);
    max = L_MAX(maxval, -minval);
    if (max == 0.0)
        return (PIX *)ERROR_PTR("kernel elements all 0.0", procName, NULL);
    norm = 255. / (l_float32)max;

        /* Handle the 1 element/pixel case; typically with large kernels */
    if (size == 1 && gthick == 0) {
        pixd = pixCreate(sx, sy, 8);
        for (i = 0; i < sy; i++) {
            for (j = 0; j < sx; j++) {
                kernelGetElement(kel, i, j, &val);
                normval = (l_int32)(norm * L_ABS(val));
                pixSetPixel(pixd, j, i, normval);
            }
        }
        return pixd;
    }

        /* Enforce the constraints for the grid line version */
    if (size < 17) {
        L_WARNING("size < 17; setting to 17\n", procName);
        size = 17;
    }
    if (size % 2 == 0)
        size++;
    if (gthick < 2) {
        L_WARNING("grid thickness < 2; setting to 2\n", procName);
        gthick = 2;
    }

    w = size * sx + gthick * (sx + 1);
    h = size * sy + gthick * (sy + 1);
    pixd = pixCreate(w, h, 8);

        /* Generate grid lines */
    for (i = 0; i <= sy; i++)
        pixRenderLine(pixd, 0, gthick / 2 + i * (size + gthick),
                      w - 1, gthick / 2 + i * (size + gthick),
                      gthick, L_SET_PIXELS);
    for (j = 0; j <= sx; j++)
        pixRenderLine(pixd, gthick / 2 + j * (size + gthick), 0,
                      gthick / 2 + j * (size + gthick), h - 1,
                      gthick, L_SET_PIXELS);

        /* Generate mask for each element */
    pixt0 = pixCreate(size, size, 1);
    pixSetAll(pixt0);

        /* Generate crossed lines for origin pattern */
    pixt1 = pixCreate(size, size, 1);
    width = size / 8;
    pixRenderLine(pixt1, size / 2, (l_int32)(0.12 * size),
                           size / 2, (l_int32)(0.88 * size),
                           width, L_SET_PIXELS);
    pixRenderLine(pixt1, (l_int32)(0.15 * size), size / 2,
                           (l_int32)(0.85 * size), size / 2,
                           width, L_FLIP_PIXELS);
    pixRasterop(pixt1, size / 2 - width, size / 2 - width,
                2 * width, 2 * width, PIX_NOT(PIX_DST), NULL, 0, 0);

        /* Paste the patterns in */
    y0 = gthick;
    for (i = 0; i < sy; i++) {
        x0 = gthick;
        for (j = 0; j < sx; j++) {
            kernelGetElement(kel, i, j, &val);
            normval = (l_int32)(norm * L_ABS(val));
            pixSetMaskedGeneral(pixd, pixt0, normval, x0, y0);
	    if (i == cy && j == cx)
                pixPaintThroughMask(pixd, pixt1, x0, y0, 255 - normval);
            x0 += size + gthick;
        }
        y0 += size + gthick;
    }

    pixDestroy(&pixt0);
    pixDestroy(&pixt1);
    return pixd;
}
int main(int    argc,
         char **argv)
{
l_int32       w, h, x, y, i, n;
l_float32    *vc;
PIX          *pix1, *pix2, *pix3, *pix4, *pix5;
PIXA         *pixas, *pixa;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pixas = pixaCreate(11);
    for (i = 0; i < 10; i++) {  /* this preserves any alpha */
        pix1 = pixRead(fnames[i]);
        pix2 = pixScaleBySamplingToSize(pix1, 250, 150);
        pixaAddPix(pixas, pix2, L_INSERT);
        pixDestroy(&pix1);
    }

        /* Add a transparent grid over the rgb image */
    pix1 = pixaGetPix(pixas, 8, L_COPY);
    pixGetDimensions(pix1, &w, &h, NULL);
    pix2 = pixCreate(w, h, 1);
    for (i = 0; i < 5; i++) {
        y = h * (i + 1) / 6;
        pixRenderLine(pix2, 0, y, w, y, 3, L_SET_PIXELS);
    }
    for (i = 0; i < 7; i++) {
        x = w * (i + 1) / 8;
        pixRenderLine(pix2, x, 0, x, h, 3, L_SET_PIXELS);
    }
    pix3 = pixConvertTo8(pix2, 0);  /* 1 --> 0 ==> transparent */
    pixSetRGBComponent(pix1, pix3, L_ALPHA_CHANNEL);
    pixaAddPix(pixas, pix1, L_INSERT);
    n = pixaGetCount(pixas);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

#if DO_ALL
        /* Display with and without removing alpha with white bg */
    pix1 = pixaDisplayTiledInRows(pixas, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRemoveAlpha(pix1);
        pixaAddPix(pixa, pix2, L_INSERT);
        pixDestroy(&pix1);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
         /* Setting to gray */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pixSetAllGray(pix1, 170);
        pix2 = pixRemoveAlpha(pix1);
        pixaAddPix(pixa, pix2, L_INSERT);
        pixDestroy(&pix1);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pix1, 400, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* General scaling */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixScaleToSize(pix1, 350, 650);
        pix3 = pixScaleToSize(pix2, 200, 200);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Scaling by sampling */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixScaleBySamplingToSize(pix1, 350, 650);
        pix3 = pixScaleBySamplingToSize(pix2, 200, 200);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by area mapping; no embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 0, 0);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 0, 0);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by area mapping; with embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 250, 150);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 250, 150);
        pix4 = pixRemoveBorderToSize(pix3, 250, 150);
        pix5 = pixRemoveAlpha(pix4);
        pixaAddPix(pixa, pix5, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 6 */
    pixDisplayWithTitle(pix1, 0, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by 3-shear; no embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 0, 0);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 0, 0);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 7 */
    pixDisplayWithTitle(pix1, 200, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL 
        /* Rotation by 3-shear; with embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 250, 150);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 250, 150);
        pix4 = pixRemoveBorderToSize(pix3, 250, 150);
        pix5 = pixRemoveAlpha(pix4);
        pixaAddPix(pixa, pix5, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 8 */
    pixDisplayWithTitle(pix1, 400, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by 2-shear about the center */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pixGetDimensions(pix1, &w, &h, NULL);
        pix2 = pixRotate2Shear(pix1, w / 2, h / 2, 0.25, L_BRING_IN_WHITE);
        pix3 = pixRotate2Shear(pix2, w / 2, h / 2, -0.35, L_BRING_IN_WHITE);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 9 */
    pixDisplayWithTitle(pix1, 600, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by sampling; no embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 0, 0);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 0, 0);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 10 */
    pixDisplayWithTitle(pix1, 800, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by sampling; with embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 250, 150);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 250, 150);
        pix4 = pixRemoveBorderToSize(pix3, 250, 150);
        pix5 = pixRemoveAlpha(pix4);
        pixaAddPix(pixa, pix5, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 11 */
    pixDisplayWithTitle(pix1, 1000, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by area mapping at corner */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotateAMCorner(pix1, 0.25, L_BRING_IN_WHITE);
        pix3 = pixRotateAMCorner(pix2, -0.35, L_BRING_IN_WHITE);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 12 */
    pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Affine transform by interpolation */
    pixa = pixaCreate(n);
    vc = Generate3PtTransformVector();
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixAffine(pix1, vc, L_BRING_IN_WHITE);
/*        pix2 = pixAffineSampled(pix1, vc, L_BRING_IN_WHITE); */
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 13 */
    pixDisplayWithTitle(pix1, 200, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

#if DO_ALL
        /* Projective transform by sampling */
    pixa = pixaCreate(n);
    vc = Generate4PtTransformVector(PROJECTIVE);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixProjectiveSampled(pix1, vc, L_BRING_IN_WHITE);
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 14 */
    pixDisplayWithTitle(pix1, 400, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

#if DO_ALL
        /* Projective transform by interpolation */
    pixa = pixaCreate(n);
    vc = Generate4PtTransformVector(PROJECTIVE);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixProjective(pix1, vc, L_BRING_IN_WHITE);
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 15 */
    pixDisplayWithTitle(pix1, 600, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

#if DO_ALL
        /* Bilinear transform by interpolation */
    pixa = pixaCreate(n);
    vc = Generate4PtTransformVector(BILINEAR);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixBilinear(pix1, vc, L_BRING_IN_WHITE);
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 16 */
    pixDisplayWithTitle(pix1, 800, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

    pixaDestroy(&pixas);
    return regTestCleanup(rp);
}
/*!
 *  pixaGenerateFont()
 *
 *      Input:  pix (of 95 characters in 3 rows)
 *              fontsize (4, 6, 8, ... , 20, in pts at 300 ppi)
 *              &bl1 (<return> baseline of row 1)
 *              &bl2 (<return> baseline of row 2)
 *              &bl3 (<return> baseline of row 3)
 *      Return: pixa of font bitmaps for 95 characters, or null on error
 *
 *  Notes:
 *      (1) This does all the work.  See pixaGenerateFontFromFile()
 *          for an overview.
 *      (2) The pix is for one of the 9 fonts.  @fontsize is only
 *          used here for debugging.
 */
PIXA *
pixaGenerateFont(PIX      *pixs,
                 l_int32   fontsize,
                 l_int32  *pbl0,
                 l_int32  *pbl1,
                 l_int32  *pbl2)
{
l_int32   i, j, nrows, nrowchars, nchars, h, yval;
l_int32   width, height;
l_int32   baseline[3];
l_int32  *tab = NULL;
BOX      *box, *box1, *box2;
BOXA     *boxar, *boxac, *boxacs;
PIX      *pix1, *pix2, *pixr, *pixrc, *pixc;
PIXA     *pixa;
l_int32   n, w, inrow, top;
l_int32  *ia;
NUMA     *na;

    PROCNAME("pixaGenerateFont");

    if (!pbl0 || !pbl1 || !pbl2)
        return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
    *pbl0 = *pbl1 = *pbl2 = 0;
    if (!pixs)
        return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);

        /* Locate the 3 rows of characters */
    w = pixGetWidth(pixs);
    na = pixCountPixelsByRow(pixs, NULL);
    boxar = boxaCreate(0);
    n = numaGetCount(na);
    ia = numaGetIArray(na);
    inrow = 0;
    for (i = 0; i < n; i++) {
        if (!inrow && ia[i] > 0) {
            inrow = 1;
            top = i;
        } else if (inrow && ia[i] == 0) {
            inrow = 0;
            box = boxCreate(0, top, w, i - top);
            boxaAddBox(boxar, box, L_INSERT);
        }
    }
    FREE(ia);
    numaDestroy(&na);
    nrows = boxaGetCount(boxar);
#if  DEBUG_FONT_GEN
    L_INFO("For fontsize %s, have %d rows\n", procName, fontsize, nrows);
#endif  /* DEBUG_FONT_GEN */
    if (nrows != 3) {
        L_INFO("nrows = %d; skipping fontsize %d\n", procName, nrows, fontsize);
        return (PIXA *)ERROR_PTR("3 rows not generated", procName, NULL);
    }

        /* Grab the character images and baseline data */
#if DEBUG_BASELINE
    lept_rmdir("baseline");
    lept_mkdir("baseline");
#endif  /* DEBUG_BASELINE */
    tab = makePixelSumTab8();
    pixa = pixaCreate(95);
    for (i = 0; i < nrows; i++) {
        box = boxaGetBox(boxar, i, L_CLONE);
        pixr = pixClipRectangle(pixs, box, NULL);  /* row of chars */
        pixGetTextBaseline(pixr, tab, &yval);
        baseline[i] = yval;

#if DEBUG_BASELINE
        L_INFO("Baseline info: row %d, yval = %d, h = %d\n", procName,
               i, yval, pixGetHeight(pixr));
        pix1 = pixCopy(NULL, pixr);
        pixRenderLine(pix1, 0, yval, pixGetWidth(pix1), yval, 1,
                      L_FLIP_PIXELS);
        if (i == 0 )
            pixWrite("/tmp/baseline/row0.png", pix1, IFF_PNG);
        else if (i == 1)
            pixWrite("/tmp/baseline/row1.png", pix1, IFF_PNG);
        else
            pixWrite("/tmp/baseline/row2.png", pix1, IFF_PNG);
        pixDestroy(&pix1);
#endif  /* DEBUG_BASELINE */

        boxDestroy(&box);
        pixrc = pixCloseSafeBrick(NULL, pixr, 1, 35);
        boxac = pixConnComp(pixrc, NULL, 8);
        boxacs = boxaSort(boxac, L_SORT_BY_X, L_SORT_INCREASING, NULL);
        if (i == 0) {  /* consolidate the two components of '"' */
            box1 = boxaGetBox(boxacs, 1, L_CLONE);
            box2 = boxaGetBox(boxacs, 2, L_CLONE);
            box1->w = box2->x + box2->w - box1->x;  /* increase width */
            boxDestroy(&box1);
            boxDestroy(&box2);
            boxaRemoveBox(boxacs, 2);
        }
        h = pixGetHeight(pixr);
        nrowchars = boxaGetCount(boxacs);
        for (j = 0; j < nrowchars; j++) {
            box = boxaGetBox(boxacs, j, L_COPY);
            if (box->w <= 2 && box->h == 1) {  /* skip 1x1, 2x1 components */
                boxDestroy(&box);
                continue;
            }
            box->y = 0;
            box->h = h - 1;
            pixc = pixClipRectangle(pixr, box, NULL);
            boxDestroy(&box);
            if (i == 0 && j == 0)  /* add a pix for the space; change later */
                pixaAddPix(pixa, pixc, L_COPY);
            if (i == 2 && j == 0)  /* add a pix for the '\'; change later */
                pixaAddPix(pixa, pixc, L_COPY);
            pixaAddPix(pixa, pixc, L_INSERT);
        }
        pixDestroy(&pixr);
        pixDestroy(&pixrc);
        boxaDestroy(&boxac);
        boxaDestroy(&boxacs);
    }
    FREE(tab);

    nchars = pixaGetCount(pixa);
    if (nchars != 95)
        return (PIXA *)ERROR_PTR("95 chars not generated", procName, NULL);

    *pbl0 = baseline[0];
    *pbl1 = baseline[1];
    *pbl2 = baseline[2];

        /* Fix the space character up; it should have no ON pixels,
         * and be about twice as wide as the '!' character.    */
    pix1 = pixaGetPix(pixa, 0, L_CLONE);
    width = 2 * pixGetWidth(pix1);
    height = pixGetHeight(pix1);
    pixDestroy(&pix1);
    pix1 = pixCreate(width, height, 1);
    pixaReplacePix(pixa, 0, pix1, NULL);

        /* Fix up the '\' character; use a LR flip of the '/' char */
    pix1 = pixaGetPix(pixa, 15, L_CLONE);
    pix2 = pixFlipLR(NULL, pix1);
    pixDestroy(&pix1);
    pixaReplacePix(pixa, 60, pix2, NULL);

#if DEBUG_CHARS
    pix1 = pixaDisplayTiled(pixa, 1500, 0, 10);
    pixDisplay(pix1, 100 * i, 200);
    pixDestroy(&pix1);
#endif  /* DEBUG_CHARS */

    boxaDestroy(&boxar);
    return pixa;
}
Beispiel #4
0
int main(int    argc,
         char **argv)
{
char        *filein, *fileout;
l_int32      x, y, n, i;
PIX         *pixs;
PTA         *pta;
PTAA        *ptaa, *ptaa2, *ptaa3;
static char  mainName[] = "cornertest";

    if (argc != 3)
        return ERROR_INT(" Syntax:  cornertest filein fileout", mainName, 1);

    filein = argv[1];
    fileout = argv[2];
    if ((pixs = pixRead(filein)) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);

        /* Clean noise in LR corner of witten.tif */
    pixSetPixel(pixs, 2252, 3051, 0);
    pixSetPixel(pixs, 2252, 3050, 0);
    pixSetPixel(pixs, 2251, 3050, 0);

    pta = pixFindCornerPixels(pixs);
    ptaWriteStream(stderr, pta, 1);

        /* Test pta and ptaa I/O */
#if 1
    ptaa = ptaaCreate(3);
    ptaaAddPta(ptaa, pta, L_COPY);
    ptaaAddPta(ptaa, pta, L_COPY);
    ptaaAddPta(ptaa, pta, L_COPY);
    ptaaWriteStream(stderr, ptaa, 1);
    ptaaWrite("/tmp/junkptaa", ptaa, 1);
    ptaa2 = ptaaRead("/tmp/junkptaa");
    ptaaWrite("/tmp/junkptaa2", ptaa2, 1);
    ptaaWrite("/tmp/junkptaa3", ptaa, 0);
    ptaa3 = ptaaRead("/tmp/junkptaa3");
    ptaaWrite("/tmp/junkptaa4", ptaa3, 0);
    ptaaDestroy(&ptaa);
    ptaaDestroy(&ptaa2);
    ptaaDestroy(&ptaa3);
#endif

        /* mark corner pixels */
    n = ptaGetCount(pta);
    for (i = 0; i < n; i++) {
        ptaGetIPt(pta, i, &x, &y);
        pixRenderLine(pixs, x - LINE_SIZE, y, x + LINE_SIZE, y, 5,
                      L_FLIP_PIXELS);
        pixRenderLine(pixs, x, y - LINE_SIZE, x, y + LINE_SIZE, 5,
                      L_FLIP_PIXELS);
    }

    pixWrite(fileout, pixs, IFF_PNG);

    pixDestroy(&pixs);
    ptaDestroy(&pta);
    ptaDestroy(&pta);
    return 0;
}
Beispiel #5
0
/*!
 *  pixaGenerateFont()
 *
 *      Input:  dir (directory holding image of character set)
 *              size (4, 6, 8, ... , 20, in pts at 300 ppi)
 *              &bl1 (<return> baseline of row 1)
 *              &bl2 (<return> baseline of row 2)
 *              &bl3 (<return> baseline of row 3)
 *      Return: pixa of font bitmaps for 95 characters, or null on error
 *
 *  These font generation functions use 9 sets, each with bitmaps
 *  of 94 ascii characters, all in Palatino-Roman font.
 *  Each input bitmap has 3 rows of characters.  The range of
 *  ascii values in each row is as follows:
 *    row 0:  32-57   (32 is a space)
 *    row 1:  58-91   (92, '\', is not represented in this font)
 *    row 2:  93-126 
 *  We LR flip the '/' char to generate a bitmap for the missing
 *  '\' character, so that we have representations of all 95
 *  printable chars.
 *
 *  Computation of the bitmaps and baselines for a single
 *  font takes from 40 to 200 msec on a 2 GHz processor,
 *  depending on the size.  Use pixaGetFont() to read the
 *  generated character set directly from files that were
 *  produced in prog/genfonts.c using this function.
 */
PIXA *
pixaGenerateFont(const char  *dir,
                 l_int32      size,
                 l_int32     *pbl0,
                 l_int32     *pbl1,
                 l_int32     *pbl2)
{
char     *pathname;
l_int32   fileno;
l_int32   i, j, nrows, nrowchars, nchars, h, yval;
l_int32   width, height;
l_int32   baseline[3];
l_int32  *tab;
BOX      *box, *box1, *box2;
BOXA     *boxar, *boxac, *boxacs;
PIX      *pixs, *pixt1, *pixt2, *pixt3;
PIX      *pixr, *pixrc, *pixc;
PIXA     *pixa;

    PROCNAME("pixaGenerateFont");

    if (!pbl0 || !pbl1 || !pbl2)
        return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
    *pbl0 = *pbl1 = *pbl2 = 0;

    fileno = (size / 2) - 2;
    if (fileno < 0 || fileno > NFONTS)
        return (PIXA *)ERROR_PTR("font size invalid", procName, NULL);
    tab = makePixelSumTab8();
    pathname = genPathname(dir, inputfonts[fileno]);
    if ((pixs = pixRead(pathname)) == NULL)
        return (PIXA *)ERROR_PTR("pixs not all defined", procName, NULL);
    FREE(pathname);

    pixa = pixaCreate(95);
    pixt1 = pixMorphSequence(pixs, "c1.35 + c101.1", 0);
    boxar = pixConnComp(pixt1, NULL, 8);  /* one box for each row */
    pixDestroy(&pixt1);
    nrows = boxaGetCount(boxar);
#if  DEBUG_FONT_GEN
    fprintf(stderr, "For font %s, number of rows is %d\n",
            inputfonts[fileno], nrows);
#endif  /* DEBUG_FONT_GEN */
    if (nrows != 3) {
        L_INFO_INT2("nrows = %d; skipping font %d", procName, nrows, fileno);
        return (PIXA *)ERROR_PTR("3 rows not generated", procName, NULL);
    }
    for (i = 0; i < nrows; i++) {
        box = boxaGetBox(boxar, i, L_CLONE);
        pixr = pixClipRectangle(pixs, box, NULL);  /* row of chars */
        pixGetTextBaseline(pixr, tab, &yval);
        baseline[i] = yval;

#if DEBUG_BASELINE
      { PIX *pixbl;
        fprintf(stderr, "row %d, yval = %d, h = %d\n",
                i, yval, pixGetHeight(pixr));
        pixbl = pixCopy(NULL, pixr);
        pixRenderLine(pixbl, 0, yval, pixGetWidth(pixbl), yval, 1,
                      L_FLIP_PIXELS);
        if (i == 0 )
            pixWrite("junktl0", pixbl, IFF_PNG);
        else if (i == 1)
            pixWrite("junktl1", pixbl, IFF_PNG);
        else
            pixWrite("junktl2", pixbl, IFF_PNG);
        pixDestroy(&pixbl);
      }
#endif  /* DEBUG_BASELINE */

        boxDestroy(&box);
        pixrc = pixCloseSafeBrick(NULL, pixr, 1, 35);
        boxac = pixConnComp(pixrc, NULL, 8);
        boxacs = boxaSort(boxac, L_SORT_BY_X, L_SORT_INCREASING, NULL);
        if (i == 0) {  /* consolidate the two components of '"' */
            box1 = boxaGetBox(boxacs, 1, L_CLONE);
            box2 = boxaGetBox(boxacs, 2, L_CLONE);
            box1->w = box2->x + box2->w - box1->x;  /* increase width */
            boxDestroy(&box1);
            boxDestroy(&box2);
            boxaRemoveBox(boxacs, 2);
        }
        h = pixGetHeight(pixr);
        nrowchars = boxaGetCount(boxacs);
        for (j = 0; j < nrowchars; j++) {
            box = boxaGetBox(boxacs, j, L_COPY);
            if (box->w <= 2 && box->h == 1) {  /* skip 1x1, 2x1 components */
                boxDestroy(&box);
                continue;
            }
            box->y = 0;
            box->h = h - 1;
            pixc = pixClipRectangle(pixr, box, NULL);
            boxDestroy(&box);
            if (i == 0 && j == 0)  /* add a pix for the space; change later */
                pixaAddPix(pixa, pixc, L_COPY);
            if (i == 2 && j == 0)  /* add a pix for the '\'; change later */
                pixaAddPix(pixa, pixc, L_COPY);
            pixaAddPix(pixa, pixc, L_INSERT);
        }
        pixDestroy(&pixr);
        pixDestroy(&pixrc);
        boxaDestroy(&boxac);
        boxaDestroy(&boxacs);
    }

    nchars = pixaGetCount(pixa);
    if (nchars != 95)
        return (PIXA *)ERROR_PTR("95 chars not generated", procName, NULL);

    *pbl0 = baseline[0];
    *pbl1 = baseline[1];
    *pbl2 = baseline[2];
        
        /* Fix the space character up; it should have no ON pixels,
         * and be about twice as wide as the '!' character.    */
    pixt2 = pixaGetPix(pixa, 0, L_CLONE);
    width = 2 * pixGetWidth(pixt2);
    height = pixGetHeight(pixt2);
    pixDestroy(&pixt2);
    pixt2 = pixCreate(width, height, 1);
    pixaReplacePix(pixa, 0, pixt2, NULL);

        /* Fix up the '\' character; use a LR flip of the '/' char */
    pixt2 = pixaGetPix(pixa, 15, L_CLONE);
    pixt3 = pixFlipLR(NULL, pixt2);
    pixDestroy(&pixt2);
    pixaReplacePix(pixa, 60, pixt3, NULL);
    
#if DEBUG_CHARS
  { PIX *pixd;
    pixd = pixaDisplayTiled(pixa, 1500, 0, 10);
    pixDisplay(pixd, 100 * i, 200);
    pixDestroy(&pixd);
  }
#endif  /* DEBUG_CHARS */

    pixDestroy(&pixs);
    boxaDestroy(&boxar);
    FREE(tab);

    return pixa;
}