Пример #1
0
/*
 *  pixWriteMixedToPS()
 *
 *      Input:  pixb (<optionall> 1 bpp "mask"; typically for text)
 *              pixc (<optional> 8 or 32 bpp image regions)
 *              scale (relative scale factor for rendering pixb
 *                    relative to pixc; typ. 4.0)
 *              pageno (page number in set; use 1 for new output file)
 *              fileout (output ps file)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This low level function generates the PS string for a mixed
 *          text/image page, and adds it to an existing file if
 *          %pageno > 1.
 *      (2) The two images (pixb and pixc) are typically generated at the
 *          resolution that they will be rendered in the PS file.
 *      (3) pixb is the text component.  In the PostScript world, we think of
 *          it as a mask through which we paint black.
 *      (4) pixc is the (typically halftone) image component.  It is
 *          white in the rest of the page.  To minimize the size of the
 *          PS file, it should be rendered at a resolution that is at
 *          least equal to its actual resolution.
 *      (5) %scale gives the ratio of resolution of pixb to pixc.
 *          Typical resolutions are: 600 ppi for pixb, 150 ppi for pixc;
 *          so %scale = 4.0.  If one of the images is not defined,
 *          the value of %scale is ignored.
 *      (6) We write pixc with DCT compression (jpeg).  This is followed
 *          by painting the text as black through the mask pixb.  If
 *          pixc doesn't exist (alltext), we write the text with the
 *          PS "image" operator instead of the "imagemask" operator,
 *          because ghostscript's ps2pdf is flaky when the latter is used.
 *      (7) The actual output resolution is determined by fitting the
 *          result to a letter-size (8.5 x 11 inch) page.
 */
l_int32
pixWriteMixedToPS(PIX         *pixb,
                  PIX         *pixc,
                  l_float32    scale,
                  l_int32      pageno,
                  const char  *fileout)
{
    char        *tname;
    const char  *op;
    l_int32      resb, resc, endpage, maskop, ret;

    PROCNAME("pixWriteMixedToPS");

    if (!pixb && !pixc)
        return ERROR_INT("pixb and pixc both undefined", procName, 1);
    if (!fileout)
        return ERROR_INT("fileout not defined", procName, 1);

    /* Compute the resolution that fills a letter-size page. */
    if (!pixc) {
        resb = getResLetterPage(pixGetWidth(pixb), pixGetHeight(pixb), 0);
    } else {
        resc = getResLetterPage(pixGetWidth(pixc), pixGetHeight(pixc), 0);
        if (pixb)
            resb = (l_int32)(scale * resc);
    }

    /* Write the jpeg image first */
    if (pixc) {
        tname = l_makeTempFilename(NULL);
        pixWrite(tname, pixc, IFF_JFIF_JPEG);
        endpage = (pixb) ? FALSE : TRUE;
        op = (pageno <= 1) ? "w" : "a";
        ret = convertJpegToPS(tname, fileout, op, 0, 0, resc, 1.0,
                              pageno, endpage);
        lept_rmfile(tname);
        LEPT_FREE(tname);
        if (ret)
            return ERROR_INT("jpeg data not written", procName, 1);
    }

    /* Write the binary data, either directly or, if there is
     * a jpeg image on the page, through the mask. */
    if (pixb) {
        tname = l_makeTempFilename(NULL);
        pixWrite(tname, pixb, IFF_TIFF_G4);
        op = (pageno <= 1 && !pixc) ? "w" : "a";
        maskop = (pixc) ? 1 : 0;
        ret = convertG4ToPS(tname, fileout, op, 0, 0, resb, 1.0,
                            pageno, maskop, 1);
        lept_rmfile(tname);
        LEPT_FREE(tname);
        if (ret)
            return ERROR_INT("tiff data not written", procName, 1);
    }

    return 0;
}
Пример #2
0
/*!
 * \brief   pixWriteMemGif()
 *
 * \param[out]   pdata data of gif compressed image
 * \param[out]   psize size of returned data
 * \param[in]    pix
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) See comments in pixReadMemGif()
 *      (2) For Giflib version >= 5.1, this uses the EGifOpen() buffer
 *          interface.  No temp files are required.
 * </pre>
 */
l_int32
pixWriteMemGif(l_uint8  **pdata,
               size_t    *psize,
               PIX       *pix)
{
#if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5
int           giferr;
l_int32       result;
GifFileType  *gif;
L_BBUFFER     *buffer;
#else
char         *fname;
#endif  /* 5.1 and beyond */

    PROCNAME("pixWriteMemGif");

    if (!pdata)
        return ERROR_INT("&data not defined", procName, 1 );
    *pdata = NULL;
    if (!psize)
        return ERROR_INT("&size not defined", procName, 1 );
    *psize = 0;
    if (!pix)
        return ERROR_INT("&pix not defined", procName, 1 );

#if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5
    if((buffer = bbufferCreate(NULL, 0)) == NULL) {
        return ERROR_INT("failed to create buffer", procName, 1);
    }

    if ((gif = EGifOpen((void*)buffer, gifWriteFunc, NULL)) == NULL) {
        bbufferDestroy(&buffer);
        return ERROR_INT("failed to create GIF image handle", procName, 1);
    }

    result = pixToGif(pix, gif);
    EGifCloseFile(gif, &giferr);

    if(result == 0) {
        *pdata = bbufferDestroyAndSaveData(&buffer, psize);
    } else {
        bbufferDestroy(&buffer);
    }
    return result;
#else
    L_INFO("writing to a temp file, not directly to memory\n", procName);

        /* Write to a temp file */
    fname = l_makeTempFilename(NULL);
    pixWrite(fname, pix, IFF_GIF);

        /* Read back into memory */
    *pdata = l_binaryRead(fname, psize);
    lept_rmfile(fname);
    LEPT_FREE(fname);
    return 0;
#endif
}
Пример #3
0
/*!
 * \brief   pixReadMemGif()
 *
 * \param[in]    data const; gif-encoded
 * \param[in]    size of data
 * \return  pix, or NULL on error
 *
 * <pre>
 * Notes:
 *   * For Giflib version >= 5.1, this uses the DGifOpen() buffer
 *     interface.  No temp files are required.
 *   * For Giflib version < 5.1:
 *       (1) Write the gif compressed data to file and read it back.
 *           Note: we can't use the GNU runtime extension fmemopen()
 *           because libgif doesn't have a file stream interface.
 *       (2) This should be relatively safe from a sophisticated attack,
 *           because we use mkstemp (or its Windows equivalent) to generate
 *           a filename and link the file.  It would be nice to go further
 *           and do this:
 *               l_int32 fd = mkstemp(template);
 *               FILE *fp = fdopen(fd, "w+b");
 *               fwrite(data, 1, size, fp);
 *               rewind(fp);
 *               Pix *pix = pixReadStreamGif(fp);
 *           but this can't be done with gif files becuase of the way
 *           that libgif handles the file descriptors: fp is in a
 *           bad state after writing.
 * </pre>
 */
PIX *
pixReadMemGif(const l_uint8  *cdata,
              size_t          size)
{
#if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5
GifFileType   *gif;
GifReadBuffer  buffer;
#else
char          *fname;
PIX           *pix;
#endif  /* 5.1 and beyond */

    PROCNAME("pixReadMemGif");

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

#if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5
    buffer.cdata = cdata;
    buffer.size = size;
    buffer.pos = 0;
    if ((gif = DGifOpen((void*)&buffer, gifReadFunc, NULL)) == NULL)
        return (PIX *)ERROR_PTR("could not open gif stream from memory",
                                procName, NULL);

    return gifToPix(gif);
#else
    L_INFO("using a temp file; not reading from memory\n", procName); 
        /* Write to a temp file */
    fname = l_makeTempFilename(NULL);
    l_binaryWrite(fname, "w", (l_uint8 *)cdata, size);

        /* Read back from the file */
    pix = pixRead(fname);
    lept_rmfile(fname);
    LEPT_FREE(fname);
    if (!pix) L_ERROR("pix not read\n", procName);
    return pix;
#endif  /* 5.1 and beyond */
}
Пример #4
0
int main(int    argc,
         char **argv)
{
l_int32       i, n, w, h;
BOXA         *boxa;
NUMA         *naindex, *naw, *nah, *naw_med, *nah_med;
PIX          *pixs, *pixt;
L_REGPARAMS  *rp;

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

        /* Generate arrays of word widths and heights */
    pixs = pixRead("feyn.tif");
    pixGetWordBoxesInTextlines(pixs, 1, 6, 6, 500, 50, &boxa, &naindex);
    n = boxaGetCount(boxa);
    naw = numaCreate(0);
    nah = numaCreate(0);
    for (i = 0; i < n; i++) {
        boxaGetBoxGeometry(boxa, i, NULL, NULL, &w, &h);
        numaAddNumber(naw, w);
        numaAddNumber(nah, h);
    }
    boxaDestroy(&boxa);
    numaDestroy(&naindex);

        /* Make the rank bin arrays of median values, with 10 bins */
    lept_rmfile("/tmp/lept/regout/w_10bin.png");  /* remove existing ones */
    lept_rmfile("/tmp/lept/regout/h_10bin.png");
    lept_rmfile("/tmp/lept/regout/w_30bin.png");
    lept_rmfile("/tmp/lept/regout/h_30bin.png");
    numaGetRankBinValues(naw, 10, NULL, &naw_med);
    numaGetRankBinValues(nah, 10, NULL, &nah_med);
    gplotSimple1(naw_med, GPLOT_PNG, "/tmp/lept/regout/w_10bin",
                 "width vs rank bins (10)");
    gplotSimple1(nah_med, GPLOT_PNG, "/tmp/lept/regout/h_10bin",
                 "height vs rank bins (10)");
    numaDestroy(&naw_med);
    numaDestroy(&nah_med);

        /* Make the rank bin arrays of median values, with 30 bins */
    numaGetRankBinValues(naw, 30, NULL, &naw_med);
    numaGetRankBinValues(nah, 30, NULL, &nah_med);
    gplotSimple1(naw_med, GPLOT_PNG, "/tmp/lept/regout/w_30bin",
                 "width vs rank bins (30)");
    gplotSimple1(nah_med, GPLOT_PNG, "/tmp/lept/regout/h_30bin",
                 "height vs rank bins (30)");
    numaDestroy(&naw_med);
    numaDestroy(&nah_med);

        /* Save as golden files, or check against them */
    regTestCheckFile(rp, "/tmp/lept/regout/w_10bin.png");  /* 0 */
    regTestCheckFile(rp, "/tmp/lept/regout/h_10bin.png");  /* 1 */
    regTestCheckFile(rp, "/tmp/lept/regout/w_30bin.png");  /* 2 */
    regTestCheckFile(rp, "/tmp/lept/regout/h_30bin.png");  /* 3 */

        /* Display results for debugging */
    pixt = pixRead("/tmp/lept/regout/w_10bin.png");
    pixDisplayWithTitle(pixt, 0, 0, NULL, rp->display);
    pixDestroy(&pixt);
    pixt = pixRead("/tmp/lept/regout/h_10bin.png");
    pixDisplayWithTitle(pixt, 650, 0, NULL, rp->display);
    pixDestroy(&pixt);
    pixt = pixRead("/tmp/lept/regout/w_30bin.png");
    pixDisplayWithTitle(pixt, 0, 550, NULL, rp->display);
    pixDestroy(&pixt);
    pixt = pixRead("/tmp/lept/regout/h_30bin.png");
    pixDisplayWithTitle(pixt, 650, 550, NULL, rp->display);
    pixDestroy(&pixt);

    pixDestroy(&pixs);
    numaDestroy(&naw);
    numaDestroy(&nah);
    return regTestCleanup(rp);
}
Пример #5
0
int main(int    argc,
         char **argv)
{
l_int32       i, n;
l_float32     pi, angle, val;
BOX          *box;
BOXA         *boxa, *boxa1, *boxa2;
NUMA         *na1, *na2;
PIX          *pix, *pix1, *pix2;
PIXA         *pixa1, *pixa2, *pixa3, *pixa4;
L_REGPARAMS  *rp;

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

    lept_rmfile("/tmp/regout/insert3.ba");
    lept_rmfile("/tmp/regout/insert4.ba");
    lept_rmfile("/tmp/regout/insert6.pa");
    lept_rmfile("/tmp/regout/insert7.pa");
    lept_rmfile("/tmp/regout/insert9.pa");
    lept_rmfile("/tmp/regout/insert10.pa");

    /* ----------------- Test numa operations -------------------- */
    pi = 3.1415926535;
    na1 = numaCreate(500);
    for (i = 0; i < 500; i++) {
        angle = 0.02293 * i * pi;
        val = (l_float32)sin(angle);
        numaAddNumber(na1, val);
    }
    numaWrite("/tmp/regout/insert0.na", na1);
    na2 = numaCopy(na1);
    n = numaGetCount(na2);
    for (i = 0; i < n; i++) {
        numaGetFValue(na2, i, &val);
        numaRemoveNumber(na2, i);
        numaInsertNumber(na2, i, val);
    }
    numaWrite("/tmp/regout/insert1.na", na2);
    regTestCheckFile(rp, "/tmp/regout/insert0.na");  /* 0 */
    regTestCheckFile(rp, "/tmp/regout/insert1.na");  /* 1 */
    regTestCompareFiles(rp, 0, 1);  /* 2 */
    numaDestroy(&na1);
    numaDestroy(&na2);

    /* ----------------- Test boxa operations -------------------- */
    pix1 = pixRead("feyn.tif");
    box = boxCreate(1138, 1666, 1070, 380);
    pix2 = pixClipRectangle(pix1, box, NULL);
    boxDestroy(&box);
    boxa1 = pixConnComp(pix2, NULL, 8);
    boxaWrite("/tmp/regout/insert3.ba", boxa1);
    boxa2 = boxaCopy(boxa1, L_COPY);
    n = boxaGetCount(boxa2);
    for (i = 0; i < n; i++) {
        boxaRemoveBoxAndSave(boxa2, i, &box);
        boxaInsertBox(boxa2, i, box);
    }
    boxaWrite("/tmp/regout/insert4.ba", boxa2);
    regTestCheckFile(rp, "/tmp/regout/insert3.ba");  /* 3 */
    regTestCheckFile(rp, "/tmp/regout/insert4.ba");  /* 4 */
    regTestCompareFiles(rp, 3, 4);  /* 5 */
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    boxaDestroy(&boxa1);
    boxaDestroy(&boxa2);

    /* ----------------- Test pixa operations -------------------- */
    pix1 = pixRead("feyn.tif");
    box = boxCreate(1138, 1666, 1070, 380);
    pix2 = pixClipRectangle(pix1, box, NULL);
    boxDestroy(&box);
    boxa = pixConnComp(pix2, &pixa1, 8);
    boxaDestroy(&boxa);
    pixaWrite("/tmp/regout/insert6.pa", pixa1);
    regTestCheckFile(rp, "/tmp/regout/insert6.pa");  /* 6 */
    pixDestroy(&pix1);
    pixDestroy(&pix2);

        /* Remove and insert each one */
    pixa2 = pixaCopy(pixa1, L_COPY);
    n = pixaGetCount(pixa2);
    for (i = 0; i < n; i++) {
        pixaRemovePixAndSave(pixa2, i, &pix, &box);
        pixaInsertPix(pixa2, i, pix, box);
    }
    pixaWrite("/tmp/regout/insert7.pa", pixa2);
    regTestCheckFile(rp, "/tmp/regout/insert7.pa");  /* 7 */
    regTestCompareFiles(rp, 6, 7);  /* 8 */

        /* Move the last to the beginning; do it n times */
    pixa3 = pixaCopy(pixa2, L_COPY);
    for (i = 0; i < n; i++) {
        pix = pixaGetPix(pixa3, n - 1, L_CLONE);
        box = pixaGetBox(pixa3, n - 1, L_CLONE);
        pixaInsertPix(pixa3, 0, pix, box);
        pixaRemovePix(pixa3, n);
    }
    pixaWrite("/tmp/regout/insert9.pa", pixa3);
    regTestCheckFile(rp, "/tmp/regout/insert9.pa");  /* 9 */

        /* Move the first one to the end; do it n times */
    pixa4 = pixaCopy(pixa3, L_COPY);
    for (i = 0; i < n; i++) {
        pix = pixaGetPix(pixa4, 0, L_CLONE);
        box = pixaGetBox(pixa4, 0, L_CLONE);
        pixaInsertPix(pixa4, n, pix, box);  /* make sure insert works at end */
        pixaRemovePix(pixa4, 0);
    }
    pixaWrite("/tmp/regout/insert10.pa", pixa4);
    regTestCheckFile(rp, "/tmp/regout/insert10.pa");  /* 10 */
    regTestCompareFiles(rp, 9, 10);  /* 11 */
    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    pixaDestroy(&pixa3);
    pixaDestroy(&pixa4);

    return regTestCleanup(rp);
}
Пример #6
0
/*
 *  pixaWriteCompressedToPS()
 *
 *      Input:  pixa (any set of images)
 *              fileout (output ps file)
 *              res (of input image)
 *              level (compression: 2 or 3)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This generates a PS file of multiple page images, all
 *          with bounding boxes.
 *      (2) It compresses to:
 *              cmap + level2:        jpeg
 *              cmap + level3:        flate
 *              1 bpp:                tiffg4
 *              2 or 4 bpp + level2:  jpeg
 *              2 or 4 bpp + level3:  flate
 *              8 bpp:                jpeg
 *              16 bpp:               flate
 *              32 bpp:               jpeg
 *      (3) To generate a pdf, use: ps2pdf <infile.ps> <outfile.pdf>
 */
l_int32
pixaWriteCompressedToPS(PIXA        *pixa,
                        const char  *fileout,
                        l_int32      res,
                        l_int32      level)
{
    char     *tname;
    l_int32   i, n, firstfile, index, writeout, d;
    PIX      *pix, *pixt;
    PIXCMAP  *cmap;

    PROCNAME("pixaWriteCompressedToPS");

    if (!pixa)
        return ERROR_INT("pixa not defined", procName, 1);
    if (!fileout)
        return ERROR_INT("fileout not defined", procName, 1);
    if (level != 2 && level != 3) {
        L_ERROR("only levels 2 and 3 permitted; using level 2\n", procName);
        level = 2;
    }

    n = pixaGetCount(pixa);
    firstfile = TRUE;
    index = 0;
    tname = l_makeTempFilename(NULL);
    for (i = 0; i < n; i++) {
        writeout = TRUE;
        pix = pixaGetPix(pixa, i, L_CLONE);
        d = pixGetDepth(pix);
        cmap = pixGetColormap(pix);
        if (d == 1) {
            pixWrite(tname, pix, IFF_TIFF_G4);
        } else if (cmap) {
            if (level == 2) {
                pixt = pixConvertForPSWrap(pix);
                pixWrite(tname, pixt, IFF_JFIF_JPEG);
                pixDestroy(&pixt);
            } else {  /* level == 3 */
                pixWrite(tname, pix, IFF_PNG);
            }
        } else if (d == 16) {
            if (level == 2)
                L_WARNING("d = 16; must write out flate\n", procName);
            pixWrite(tname, pix, IFF_PNG);
        } else if (d == 2 || d == 4) {
            if (level == 2) {
                pixt = pixConvertTo8(pix, 0);
                pixWrite(tname, pixt, IFF_JFIF_JPEG);
                pixDestroy(&pixt);
            } else {  /* level == 3 */
                pixWrite(tname, pix, IFF_PNG);
            }
        } else if (d == 8 || d == 32) {
            pixWrite(tname, pix, IFF_JFIF_JPEG);
        } else {  /* shouldn't happen */
            L_ERROR("invalid depth: %d\n", procName, d);
            writeout = FALSE;
        }
        pixDestroy(&pix);

        if (writeout)
            writeImageCompressedToPSFile(tname, fileout, res,
                                         &firstfile, &index);
    }

    lept_rmfile(tname);
    LEPT_FREE(tname);
    return 0;
}
Пример #7
0
/*
 *  convertToPSEmbed()
 *
 *      Input:  filein (input image file -- any format)
 *              fileout (output ps file)
 *              level (compression: 1 (uncompressed), 2 or 3)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This is a wrapper function that generates a PS file with
 *          a bounding box, from any input image file.
 *      (2) Do the best job of compression given the specified level.
 *          %level=3 does flate compression on anything that is not
 *          tiffg4 (1 bpp) or jpeg (8 bpp or rgb).
 *      (3) If %level=2 and the file is not tiffg4 or jpeg, it will
 *          first be written to file as jpeg with quality = 75.
 *          This will remove the colormap and cause some degradation
 *          in the image.
 *      (4) The bounding box is required when a program such as TeX
 *          (through epsf) places and rescales the image.  It is
 *          sized for fitting the image to an 8.5 x 11.0 inch page.
 */
l_int32
convertToPSEmbed(const char  *filein,
                 const char  *fileout,
                 l_int32      level)
{
    char    *tname;
    l_int32  d, format;
    PIX     *pix, *pixs;

    PROCNAME("convertToPSEmbed");

    if (!filein)
        return ERROR_INT("filein not defined", procName, 1);
    if (!fileout)
        return ERROR_INT("fileout not defined", procName, 1);
    if (level != 1 && level != 2 && level != 3) {
        L_ERROR("invalid level specified; using level 2\n", procName);
        level = 2;
    }

    if (level == 1) {  /* no compression */
        pixWritePSEmbed(filein, fileout);
        return 0;
    }

    /* Find the format and write out directly if in jpeg or tiff g4 */
    findFileFormat(filein, &format);
    if (format == IFF_JFIF_JPEG) {
        convertJpegToPSEmbed(filein, fileout);
        return 0;
    } else if (format == IFF_TIFF_G4) {
        convertG4ToPSEmbed(filein, fileout);
        return 0;
    } else if (format == IFF_UNKNOWN) {
        L_ERROR("format of %s not known\n", procName, filein);
        return 1;
    }

    /* If level 3, flate encode. */
    if (level == 3) {
        convertFlateToPSEmbed(filein, fileout);
        return 0;
    }

    /* OK, it's level 2, so we must convert to jpeg or tiff g4 */
    if ((pixs = pixRead(filein)) == NULL)
        return ERROR_INT("image not read from file", procName, 1);
    d = pixGetDepth(pixs);
    if ((d == 2 || d == 4) && !pixGetColormap(pixs))
        pix = pixConvertTo8(pixs, 0);
    else if (d == 16)
        pix = pixConvert16To8(pixs, 1);
    else
        pix = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC);

    d = pixGetDepth(pix);
    tname = l_makeTempFilename(NULL);
    if (d == 1) {
        pixWrite(tname, pix, IFF_TIFF_G4);
        convertG4ToPSEmbed(tname, fileout);
    } else {
        pixWrite(tname, pix, IFF_JFIF_JPEG);
        convertJpegToPSEmbed(tname, fileout);
    }

    lept_rmfile(tname);
    LEPT_FREE(tname);
    pixDestroy(&pix);
    pixDestroy(&pixs);
    return 0;
}