main(int argc, char **argv) { char *filein, *fileout; l_int32 d; l_float32 scalex, scaley; PIX *pixs, *pixd; static char mainName[] = "scaletest1"; if (argc != 5) return ERROR_INT(" Syntax: scaletest1 filein scalex scaley fileout", mainName, 1); filein = argv[1]; scalex = atof(argv[2]); scaley = atof(argv[3]); fileout = argv[4]; if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pixs not made", mainName, 1); /* choose type of scaling operation */ #if 1 pixd = pixScale(pixs, scalex, scaley); #elif 0 pixd = pixScaleLI(pixs, scalex, scaley); #elif 0 pixd = pixScaleSmooth(pixs, scalex, scaley); #elif 0 pixd = pixScaleAreaMap(pixs, scalex, scaley); #elif 0 pixd = pixScaleBySampling(pixs, scalex, scaley); #else pixd = pixScaleToGray(pixs, scalex); #endif d = pixGetDepth(pixd); #if 1 if (d <= 8) pixWrite(fileout, pixd, IFF_PNG); else pixWrite(fileout, pixd, IFF_JFIF_JPEG); #else pixWrite(fileout, pixd, IFF_PNG); #endif pixDestroy(&pixs); pixDestroy(&pixd); return 0; }
/* * pixWriteSegmentedPageToPS() * * Input: pixs (all depths; colormap ok) * pixm (<optional> 1 bpp segmentation mask over image region) * textscale (scale of text output relative to pixs) * imagescale (scale of image output relative to pixs) * threshold (threshold for binarization; typ. 190) * 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 generates the PS string for a mixed text/image page, * and adds it to an existing file if @pageno > 1. * The PS output is determined by fitting the result to * a letter-size (8.5 x 11 inch) page. * (2) The two images (pixs and pixm) are at the same resolution * (typically 300 ppi). They are used to generate two compressed * images, pixb and pixc, that are put directly into the output * PS file. * (3) pixb is the text component. In the PostScript world, we think of * it as a mask through which we paint black. It is produced by * scaling pixs by @textscale, and thresholding to 1 bpp. * (4) pixc is the image component, which is that part of pixs under * the mask pixm. It is scaled from pixs by @imagescale. * (5) Typical values are textscale = 2.0 and imagescale = 0.5. * (6) If pixm == NULL, the page has only text. If it is all black, * the page is all image and has no text. * (7) This can be used to write a multi-page PS file, by using * sequential page numbers with the same output file. It can * also be used to write separate PS files for each page, * by using different output files with @pageno = 0 or 1. */ l_int32 pixWriteSegmentedPageToPS(PIX *pixs, PIX *pixm, l_float32 textscale, l_float32 imagescale, l_int32 threshold, l_int32 pageno, const char *fileout) { l_int32 alltext, notext, d, ret; l_uint32 val; l_float32 scaleratio; PIX *pixmi, *pixmis, *pixt, *pixg, *pixsc, *pixb, *pixc; PROCNAME("pixWriteSegmentedPageToPS"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (!fileout) return ERROR_INT("fileout not defined", procName, 1); if (imagescale <= 0.0 || textscale <= 0.0) return ERROR_INT("relative scales must be > 0.0", procName, 1); /* Analyze the page. Determine the ratio by which the * binary text mask is scaled relative to the image part. * If there is no image region (alltext == TRUE), the * text mask will be rendered directly to fit the page, * and scaleratio = 1.0. */ alltext = TRUE; notext = FALSE; scaleratio = 1.0; if (pixm) { pixZero(pixm, &alltext); /* pixm empty: all text */ if (alltext) pixm = NULL; /* treat it as not existing here */ else { pixmi = pixInvert(NULL, pixm); pixZero(pixmi, ¬ext); /* pixm full; no text */ pixDestroy(&pixmi); scaleratio = textscale / imagescale; } } if (pixGetDepth(pixs) == 1) { /* render tiff g4 */ pixb = pixClone(pixs); pixc = NULL; } else { pixt = pixConvertTo8Or32(pixs, 0, 0); /* this can be a clone of pixs */ /* Get the binary text mask. Note that pixg cannot be a * clone of pixs, because it may be altered by pixSetMasked(). */ pixb = NULL; if (notext == FALSE) { d = pixGetDepth(pixt); if (d == 8) pixg = pixCopy(NULL, pixt); else /* d == 32 */ pixg = pixConvertRGBToLuminance(pixt); if (pixm) /* clear out the image parts */ pixSetMasked(pixg, pixm, 255); if (textscale == 1.0) pixsc = pixClone(pixg); else if (textscale >= 0.7) pixsc = pixScaleGrayLI(pixg, textscale, textscale); else pixsc = pixScaleAreaMap(pixg, textscale, textscale); pixb = pixThresholdToBinary(pixsc, threshold); pixDestroy(&pixg); pixDestroy(&pixsc); } /* Get the scaled image region */ pixc = NULL; if (pixm) { if (imagescale == 1.0) pixsc = pixClone(pixt); /* can possibly be a clone of pixs */ else pixsc = pixScale(pixt, imagescale, imagescale); /* If pixm is not full, clear the pixels in pixsc * corresponding to bg in pixm, where there can be text * that is written through the mask pixb. Note that * we could skip this and use pixsc directly in * pixWriteMixedToPS(); however, clearing these * non-image regions to a white background will reduce * the size of pixc (relative to pixsc), and hence * reduce the size of the PS file that is generated. * Use a copy so that we don't accidentally alter pixs. */ if (notext == FALSE) { pixmis = pixScale(pixm, imagescale, imagescale); pixmi = pixInvert(NULL, pixmis); val = (d == 8) ? 0xff : 0xffffff00; pixc = pixCopy(NULL, pixsc); pixSetMasked(pixc, pixmi, val); /* clear non-image part */ pixDestroy(&pixmis); pixDestroy(&pixmi); } else pixc = pixClone(pixsc); pixDestroy(&pixsc); } pixDestroy(&pixt); } ret = pixWriteMixedToPS(pixb, pixc, scaleratio, pageno, fileout); pixDestroy(&pixb); pixDestroy(&pixc); return ret; }
main(int argc, char **argv) { l_int32 i; l_float32 pi, scale, angle; PIX *pixc, *pixm, *pix1, *pix2, *pix3; PIXA *pixa; PTA *pta1, *pta2, *pta3, *pta4; static char mainName[] = "smallpix_reg"; /* Make a small test image, the hard way! */ pi = 3.1415926535; pixc = pixCreate(9, 9, 32); pixm = pixCreate(9, 9, 1); pta1 = generatePtaLineFromPt(4, 4, 3.1, 0.0); pta2 = generatePtaLineFromPt(4, 4, 3.1, 0.5 * pi); pta3 = generatePtaLineFromPt(4, 4, 3.1, pi); pta4 = generatePtaLineFromPt(4, 4, 3.1, 1.5 * pi); ptaJoin(pta1, pta2, 0, 0); ptaJoin(pta1, pta3, 0, 0); ptaJoin(pta1, pta4, 0, 0); pixRenderPta(pixm, pta1, L_SET_PIXELS); pixPaintThroughMask(pixc, pixm, 0, 0, 0x00ff0000); ptaDestroy(&pta1); ptaDestroy(&pta2); ptaDestroy(&pta3); ptaDestroy(&pta4); pixDestroy(&pixm); /* Results differ for scaleSmoothLow() w/ and w/out + 0.5. * Neither is properly symmetric (with symm pattern on odd-sized * pix, because the smoothing is destroying the symmetry. */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 2); for (i = 0; i < 11; i++) { scale = 0.30 + 0.035 * (l_float32)i; pix2 = pixScaleSmooth(pix1, scale, scale); pix3 = pixExpandReplicate(pix2, 6); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 100, NULL); /* Results same for pixScaleAreaMap w/ and w/out + 0.5 */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 2); for (i = 0; i < 11; i++) { scale = 0.30 + 0.035 * (l_float32)i; pix2 = pixScaleAreaMap(pix1, scale, scale); pix3 = pixExpandReplicate(pix2, 6); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 200, NULL); /* Results better for pixScaleBySampling with + 0.5, for small, * odd-dimension pix. */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 2); for (i = 0; i < 11; i++) { scale = 0.30 + 0.035 * (l_float32)i; pix2 = pixScaleBySampling(pix1, scale, scale); pix3 = pixExpandReplicate(pix2, 6); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 300, NULL); /* Results same for pixRotateAM w/ and w/out + 0.5 */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 1); for (i = 0; i < 11; i++) { angle = 0.10 + 0.05 * (l_float32)i; pix2 = pixRotateAM(pix1, angle, L_BRING_IN_BLACK); pix3 = pixExpandReplicate(pix2, 8); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 400, NULL); /* If the size is odd, we express the center exactly, and the * results are better for pixRotateBySampling() w/out 0.5 * However, if the size is even, the center value is not * exact, and if we choose it 0.5 smaller than the actual * center, we get symmetrical results with +0.5. * So we choose not to include + 0.5. */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 1); for (i = 0; i < 11; i++) { angle = 0.10 + 0.05 * (l_float32)i; pix2 = pixRotateBySampling(pix1, 4, 4, angle, L_BRING_IN_BLACK); pix3 = pixExpandReplicate(pix2, 8); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 500, NULL); /* Results same for pixRotateAMCorner w/ and w/out + 0.5 */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 1); for (i = 0; i < 11; i++) { angle = 0.10 + 0.05 * (l_float32)i; pix2 = pixRotateAMCorner(pix1, angle, L_BRING_IN_BLACK); pix3 = pixExpandReplicate(pix2, 8); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 600, NULL); /* Results better for pixRotateAMColorFast without + 0.5 */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 1); for (i = 0; i < 11; i++) { angle = 0.10 + 0.05 * (l_float32)i; pix2 = pixRotateAMColorFast(pix1, angle, 0); pix3 = pixExpandReplicate(pix2, 8); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 700, NULL); /* Results slightly better for pixScaleColorLI() w/out + 0.5 */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 1); for (i = 0; i < 11; i++) { scale = 1.0 + 0.2 * (l_float32)i; pix2 = pixScaleColorLI(pix1, scale, scale); pix3 = pixExpandReplicate(pix2, 4); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 800, NULL); /* Results slightly better for pixScaleColorLI() w/out + 0.5 */ pixa = pixaCreate(11); pix1 = pixExpandReplicate(pixc, 1); for (i = 0; i < 11; i++) { scale = 1.0 + 0.2 * (l_float32)i; pix2 = pixScaleLI(pix1, scale, scale); pix3 = pixExpandReplicate(pix2, 4); pixSaveTiled(pix3, pixa, 1, (i == 0), 20, 32); pixDestroy(&pix2); pixDestroy(&pix3); } pixDestroy(&pix1); DisplayPix(&pixa, 100, 940, NULL); pixDestroy(&pixc); return 0; }