/* * 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) { const char tnameb[] = "/tmp/junk_pix_write_mixed.tif"; const char tnamec[] = "/tmp/junk_pix_write_mixed.jpg"; 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) { pixWrite(tnamec, pixc, IFF_JFIF_JPEG); endpage = (pixb) ? FALSE : TRUE; op = (pageno <= 1) ? "w" : "a"; ret = convertJpegToPS(tnamec, fileout, op, 0, 0, resc, 1.0, pageno, endpage); 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) { pixWrite(tnameb, pixb, IFF_TIFF_G4); op = (pageno <= 1 && !pixc) ? "w" : "a"; maskop = (pixc) ? 1 : 0; ret = convertTiffG4ToPS(tnameb, fileout, op, 0, 0, resb, 1.0, pageno, maskop, 1); if (ret) return ERROR_INT("tiff data not written", procName, 1); } return 0; }
/* * writeImageCompressedToPSFile() * * Input: filein (input image file) * fileout (output ps file) * res (output printer resolution) * &firstfile (<input and return> 1 if the first image; * 0 otherwise) * &index (<input and return> index of image in output ps file) * Return: 0 if OK, 1 on error * * Notes: * (1) This wraps a single page image in PS. * (2) The input file can be in any format. It is compressed as follows: * * if in tiffg4 --> use ccittg4 * * if in jpeg --> use dct * * all others --> use flate * (3) @index is incremented if the page is successfully written. */ l_int32 writeImageCompressedToPSFile(const char *filein, const char *fileout, l_int32 res, l_int32 *pfirstfile, l_int32 *pindex) { const char *op; l_int32 format, retval; FILE *fp; PROCNAME("writeImageCompressedToPSFile"); if (!pfirstfile || !pindex) return ERROR_INT("&firstfile and &index not defined", procName, 1); if ((fp = fopenReadStream(filein)) == NULL) return ERROR_INT("filein not found", procName, 1); findFileFormat(fp, &format); fclose(fp); if (format == IFF_UNKNOWN) { L_ERROR_STRING("Format of %s not known", procName, filein); return 1; } op = (*pfirstfile == TRUE) ? "w" : "a"; if (format == IFF_JFIF_JPEG) { retval = convertJpegToPS(filein, fileout, op, 0, 0, res, 1.0, *pindex + 1, TRUE); if (retval == 0) { *pfirstfile = FALSE; (*pindex)++; } } else if (format == IFF_TIFF_G4) { retval = convertTiffG4ToPS(filein, fileout, op, 0, 0, res, 1.0, *pindex + 1, FALSE, TRUE); if (retval == 0) { *pfirstfile = FALSE; (*pindex)++; } } else { /* all other image formats */ retval = convertFlateToPS(filein, fileout, op, 0, 0, res, 1.0, *pindex + 1, TRUE); if (retval == 0) { *pfirstfile = FALSE; (*pindex)++; } } return retval; }
main(int argc, char **argv) { l_int32 w, h, success, display; l_float32 factor, scale; BOX *box; FILE *fp, *fp1; PIX *pixs, *pixt; if (regTestSetup(argc, argv, &fp, &display, &success, NULL)) return 1; factor = 0.95; /* Uncompressed PS with scaling but centered on the page */ pixs = pixRead("feyn-fract.tif"); pixGetDimensions(pixs, &w, &h, NULL); scale = L_MIN(factor * 2550 / w, factor * 3300 / h); fp1 = fopen("/tmp/psio0.ps", "wb+"); pixWriteStreamPS(fp1, pixs, NULL, 300, scale); fclose(fp1); regTestCheckFile(fp, argv, "/tmp/psio0.ps", 0, &success); pixDestroy(&pixs); /* Uncompressed PS with scaling, with LL corner at (1500, 1500) mils */ pixs = pixRead("weasel4.11c.png"); pixGetDimensions(pixs, &w, &h, NULL); scale = L_MIN(factor * 2550 / w, factor * 3300 / h); box = boxCreate(1500, 1500, (l_int32)(1000 * scale * w / 300), (l_int32)(1000 * scale * h / 300)); fp1 = fopen("/tmp/psio1.ps", "wb+"); pixWriteStreamPS(fp1, pixs, box, 300, 1.0); fclose(fp1); regTestCheckFile(fp, argv, "/tmp/psio1.ps", 1, &success); boxDestroy(&box); pixDestroy(&pixs); /* DCT compressed PS with LL corner at (300, 1000) pixels */ pixs = pixRead("marge.jpg"); pixt = pixConvertTo32(pixs); pixWrite("/tmp/psio2.jpg", pixt, IFF_JFIF_JPEG); convertJpegToPS("/tmp/psio2.jpg", "/tmp/psio3.ps", "w", 300, 1000, 0, 4.0, 1, 1); regTestCheckFile(fp, argv, "/tmp/psio2.jpg", 2, &success); regTestCheckFile(fp, argv, "/tmp/psio3.ps", 3, &success); pixDestroy(&pixt); pixDestroy(&pixs); /* For each page, apply tiff g4 image first; then jpeg or png over it */ convertTiffG4ToPS("feyn.tif", "/tmp/psio4.ps", "w", 0, 0, 0, 1.0, 1, 1, 0); convertJpegToPS("marge.jpg", "/tmp/psio4.ps", "a", 500, 100, 300, 2.0, 1, 0); convertFlateToPS("weasel4.11c.png", "/tmp/psio4.ps", "a", 300, 400, 300, 6.0, 1, 0); convertJpegToPS("marge.jpg", "/tmp/psio4.ps", "a", 100, 800, 300, 1.5, 1, 1); convertTiffG4ToPS("feyn.tif", "/tmp/psio4.ps", "a", 0, 0, 0, 1.0, 2, 1, 0); convertJpegToPS("marge.jpg", "/tmp/psio4.ps", "a", 1000, 700, 300, 2.0, 2, 0); convertJpegToPS("marge.jpg", "/tmp/psio4.ps", "a", 100, 200, 300, 2.0, 2, 1); convertTiffG4ToPS("feyn.tif", "/tmp/psio4.ps", "a", 0, 0, 0, 1.0, 3, 1, 0); convertJpegToPS("marge.jpg", "/tmp/psio4.ps", "a", 200, 200, 300, 2.0, 3, 0); convertJpegToPS("marge.jpg", "/tmp/psio4.ps", "a", 200, 900, 300, 2.0, 3, 1); regTestCheckFile(fp, argv, "/tmp/psio4.ps", 4, &success); /* Now apply jpeg first; then paint through a g4 mask. * For gv, the first image with a b.b. determines the * window size for the canvas, so we put down the largest * image first. If we had rendered a small image first, * gv and evince will not show the entire page. However, after * conversion to pdf, everything works fine, regardless of the * order in which images are placed into the PS. That is * because the pdf interpreter is robust to bad hints, ignoring * the page hints and computing the bounding box from the * set of images rendered on the page. */ pixs = pixRead("wyom.jpg"); pixt = pixScaleToSize(pixs, 2528, 3300); pixWrite("/tmp/psio5.jpg", pixt, IFF_JFIF_JPEG); pixDestroy(&pixs); pixDestroy(&pixt); convertJpegToPS("/tmp/psio5.jpg", "/tmp/psio5.ps", "w", 0, 0, 0, 1.0, 1, 0); convertFlateToPS("weasel8.240c.png", "/tmp/psio5.ps", "a", 100, 100, 300, 5.0, 1, 0); convertFlateToPS("weasel8.149g.png", "/tmp/psio5.ps", "a", 200, 300, 300, 5.0, 1, 0); convertFlateToPS("weasel4.11c.png", "/tmp/psio5.ps", "a", 300, 500, 300, 5.0, 1, 0); convertTiffG4ToPS("feyn.tif", "/tmp/psio5.ps", "a", 0, 0, 0, 1.0, 1, 1, 1); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 500, 100, 300, 2.0, 2, 0); convertFlateToPS("weasel4.11c.png", "/tmp/psio5.ps", "a", 300, 400, 300, 6.0, 2, 0); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 100, 800, 300, 1.5, 2, 0); convertTiffG4ToPS("feyn.tif", "/tmp/psio5.ps", "a", 0, 0, 0, 1.0, 2, 1, 1); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 500, 100, 300, 2.0, 3, 0); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 100, 800, 300, 2.0, 3, 0); convertTiffG4ToPS("feyn.tif", "/tmp/psio5.ps", "a", 0, 0, 0, 1.0, 3, 1, 1); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 1000, 700, 300, 2.0, 4, 0); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 100, 200, 300, 2.0, 4, 0); convertTiffG4ToPS("feyn.tif", "/tmp/psio5.ps", "a", 0, 0, 0, 1.0, 4, 1, 1); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 200, 200, 300, 2.0, 5, 0); convertJpegToPS("marge.jpg", "/tmp/psio5.ps", "a", 200, 900, 300, 2.0, 5, 0); convertTiffG4ToPS("feyn.tif", "/tmp/psio5.ps", "a", 0, 0, 0, 1.0, 5, 1, 1); regTestCheckFile(fp, argv, "/tmp/psio5.ps", 5, &success); /* Generation using segmentation masks */ convertSegmentedPagesToPS(".", "lion-page", ".", "lion-mask", 10, 0, 100, 2.0, 0.8, 190, "/tmp/psio6.ps"); regTestCheckFile(fp, argv, "/tmp/psio6.ps", 6, &success); regTestCleanup(argc, argv, fp, success, NULL); return 0; }